summaryrefslogtreecommitdiffstats
path: root/generic/tclParse.c
diff options
context:
space:
mode:
authorstanton <stanton>1998-12-02 01:46:06 (GMT)
committerstanton <stanton>1998-12-02 01:46:06 (GMT)
commitdfc1f4c5ee46a899d3a2fb497635ecc525d30e30 (patch)
treeb1df10563bcf30f4212c9444394fe8421d01aa20 /generic/tclParse.c
parentd96f4346b5866249776d62e8c6f6af5d2f5d6e25 (diff)
downloadtcl-dfc1f4c5ee46a899d3a2fb497635ecc525d30e30.zip
tcl-dfc1f4c5ee46a899d3a2fb497635ecc525d30e30.tar.gz
tcl-dfc1f4c5ee46a899d3a2fb497635ecc525d30e30.tar.bz2
* generic/tclTest.c (TestevalobjvObjCmd): Updated for EvalObjv
change. * tests/parse.test: Updated tests for EvalObjv change. * generic/tclParse.c (EvalObjv, Tcl_EvalObjv): Changed Tcl_EvalObjv interface to remove string and length arguments, preserved original interface as EvalObjv for internal use. * generic/tcl.h: Changed Tcl_EvalObjv interface to remove string and length arguments. * doc/Eval.3: Updated documentation for Tcl_EvalObjv to remove string and length arguments.
Diffstat (limited to 'generic/tclParse.c')
-rw-r--r--generic/tclParse.c134
1 files changed, 115 insertions, 19 deletions
diff --git a/generic/tclParse.c b/generic/tclParse.c
index f7eff3a..7e8f9f4 100644
--- a/generic/tclParse.c
+++ b/generic/tclParse.c
@@ -13,7 +13,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.1.2.4 1998/11/11 04:54:18 stanton Exp $
+ * RCS: @(#) $Id: tclParse.c,v 1.1.2.5 1998/12/02 01:46:07 stanton Exp $
*/
#include "tclInt.h"
@@ -178,6 +178,9 @@ static int CommandComplete _ANSI_ARGS_((char *script,
int length));
static int ParseTokens _ANSI_ARGS_((char *src, int mask,
Tcl_Parse *parsePtr));
+static int EvalObjv _ANSI_ARGS_((Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[], char *command, int length,
+ int flags));
/*
*----------------------------------------------------------------------
@@ -734,7 +737,7 @@ TclExpandTokenArray(parsePtr)
/*
*----------------------------------------------------------------------
*
- * Tcl_EvalObjv --
+ * EvalObjv --
*
* This procedure evaluates a Tcl command that has already been
* parsed into words, with one Tcl_Obj holding each word.
@@ -751,8 +754,8 @@ TclExpandTokenArray(parsePtr)
*----------------------------------------------------------------------
*/
-int
-Tcl_EvalObjv(interp, objc, objv, command, length, flags)
+static int
+EvalObjv(interp, objc, objv, command, length, flags)
Tcl_Interp *interp; /* Interpreter in which to evaluate the
* command. Also used for error
* reporting. */
@@ -848,7 +851,7 @@ Tcl_EvalObjv(interp, objc, objv, command, length, flags)
(char *) NULL);
code = TCL_ERROR;
} else {
- code = Tcl_EvalObjv(interp, objc+1, newObjv, command, length, 0);
+ code = EvalObjv(interp, objc+1, newObjv, command, length, 0);
}
Tcl_DecrRefCount(newObjv[0]);
ckfree((char *) newObjv);
@@ -859,6 +862,9 @@ Tcl_EvalObjv(interp, objc, objv, command, length, flags)
* Call trace procedures if needed.
*/
+ argv = NULL;
+ commandCopy = command;
+
for (tracePtr = iPtr->tracePtr; tracePtr != NULL; tracePtr = nextPtr) {
nextPtr = tracePtr->nextPtr;
if (iPtr->numLevels > tracePtr->level) {
@@ -867,25 +873,32 @@ Tcl_EvalObjv(interp, objc, objv, command, length, flags)
/*
* This is a bit messy because we have to emulate the old trace
- * interface, which uses strings for everything. This can lose
- * information if some of the words contain null characters.
+ * interface, which uses strings for everything.
*/
- argv = (char **) ckalloc((unsigned) (objc + 1) * sizeof(char *));
- for (i = 0; i < objc; i++) {
- argv[i] = Tcl_GetString(objv[i]);
- }
- argv[objc] = 0;
- if (length < 0) {
- length = strlen(command);
+ if (argv == NULL) {
+ argv = (char **) ckalloc((unsigned) (objc + 1) * sizeof(char *));
+ for (i = 0; i < objc; i++) {
+ argv[i] = Tcl_GetString(objv[i]);
+ }
+ argv[objc] = 0;
+
+ if (length < 0) {
+ length = strlen(command);
+ } else if (length < strlen(command)) {
+ commandCopy = (char *) ckalloc((unsigned) (length + 1));
+ strncpy(commandCopy, command, (size_t) length);
+ commandCopy[length] = 0;
+ }
}
- commandCopy = (char *) ckalloc((unsigned) (length + 1));
- strncpy(commandCopy, command, (size_t) length);
- commandCopy[length] = 0;
(*tracePtr->proc)(tracePtr->clientData, interp, iPtr->numLevels,
commandCopy, cmdPtr->proc, cmdPtr->clientData,
objc, argv);
+ }
+ if (argv != NULL) {
ckfree((char *) argv);
+ }
+ if (commandCopy != command) {
ckfree((char *) commandCopy);
}
@@ -923,6 +936,89 @@ Tcl_EvalObjv(interp, objc, objv, command, length, flags)
/*
*----------------------------------------------------------------------
*
+ * Tcl_EvalObjv --
+ *
+ * This procedure evaluates a Tcl command that has already been
+ * parsed into words, with one Tcl_Obj holding each word.
+ *
+ * Results:
+ * The return value is a standard Tcl completion code such as
+ * TCL_OK or TCL_ERROR. A result or error message is left in
+ * interp's result.
+ *
+ * Side effects:
+ * Depends on the command.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_EvalObjv(interp, objc, objv, flags)
+ Tcl_Interp *interp; /* Interpreter in which to evaluate the
+ * command. Also used for error
+ * reporting. */
+ int objc; /* Number of words in command. */
+ Tcl_Obj *CONST objv[]; /* An array of pointers to objects that are
+ * the words that make up the command. */
+ int flags; /* Collection of OR-ed bits that control
+ * the evaluation of the script. Only
+ * TCL_EVAL_GLOBAL is currently
+ * supported. */
+{
+ Interp *iPtr = (Interp *)interp;
+ Trace *tracePtr;
+ Tcl_DString cmdBuf;
+ char cmdString[] = "";
+ int cmdLen = 0;
+ int code = TCL_OK;
+
+ for (tracePtr = iPtr->tracePtr; tracePtr; tracePtr = tracePtr->nextPtr) {
+ /*
+ * EvalObjv will increment numLevels so use "<" rather than "<="
+ */
+ if (iPtr->numLevels < tracePtr->level) {
+ int i;
+ /*
+ * The command will be needed for an execution trace or stack trace
+ * generate a command string.
+ */
+ cmdtraced:
+ Tcl_DStringInit(&cmdBuf);
+ for (i = 0; i < objc; i++) {
+ Tcl_DStringAppendElement(&cmdBuf, Tcl_GetString(objv[i]));
+ }
+ cmdString = Tcl_DStringValue(&cmdBuf);
+ cmdLen = Tcl_DStringLength(&cmdBuf);
+ break;
+ }
+ }
+
+ /*
+ * Execute the command if we have not done so already
+ */
+ switch (code) {
+ case TCL_OK:
+ code = EvalObjv(interp, objc, objv, cmdString, cmdLen, flags);
+ if (code == TCL_ERROR && cmdLen == 0)
+ goto cmdtraced;
+ break;
+ case TCL_ERROR:
+ Tcl_LogCommandInfo(interp, cmdString, cmdString, cmdLen);
+ break;
+ default:
+ /*NOTREACHED*/
+ break;
+ }
+
+ if (cmdLen != 0) {
+ Tcl_DStringFree(&cmdBuf);
+ }
+ return code;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* Tcl_LogCommandInfo --
*
* This procedure is invoked after an error occurs in an interpreter.
@@ -1174,7 +1270,7 @@ Tcl_EvalTokens(interp, tokenPtr, count)
*
* This procedure evaluates a Tcl script without using the compiler
* or byte-code interpreter. It just parses the script, creates
- * values for each word of each command, then calls Tcl_EvalObjv
+ * values for each word of each command, then calls EvalObjv
* to execute each command.
*
* Results:
@@ -1276,7 +1372,7 @@ Tcl_Eval2(interp, script, numBytes, flags)
* Execute the command and free the objects for its words.
*/
- code = Tcl_EvalObjv(interp, objectsUsed, objv, p, bytesLeft, 0);
+ code = EvalObjv(interp, objectsUsed, objv, p, bytesLeft, 0);
if (code != TCL_OK) {
goto error;
}