summaryrefslogtreecommitdiffstats
path: root/generic/tclInterp.c
diff options
context:
space:
mode:
Diffstat (limited to 'generic/tclInterp.c')
-rw-r--r--generic/tclInterp.c1949
1 files changed, 1224 insertions, 725 deletions
diff --git a/generic/tclInterp.c b/generic/tclInterp.c
index c521435..0da5d47 100644
--- a/generic/tclInterp.c
+++ b/generic/tclInterp.c
@@ -9,8 +9,6 @@
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- * RCS: @(#) $Id: tclInterp.c,v 1.60 2005/07/17 21:17:42 dkf Exp $
*/
#include "tclInt.h"
@@ -18,11 +16,10 @@
/*
* A pointer to a string that holds an initialization script that if non-NULL
* is evaluated in Tcl_Init() prior to the built-in initialization script
- * above. This variable can be modified by the procedure below.
+ * above. This variable can be modified by the function below.
*/
-static char * tclPreInitScript = NULL;
-
+static const char *tclPreInitScript = NULL;
/* Forward declaration */
struct Target;
@@ -50,9 +47,9 @@ typedef struct Alias {
* This is used by alias deletion to remove
* the alias from the slave interpreter alias
* table. */
- struct Target *targetPtr; /* Entry for target command in master. This
- * is used in the master interpreter to map
- * back from the target command to aliases
+ struct Target *targetPtr; /* Entry for target command in master. This is
+ * used in the master interpreter to map back
+ * from the target command to aliases
* redirecting to it. */
int objc; /* Count of Tcl_Obj in the prefix of the
* target command to be invoked in the target
@@ -80,7 +77,7 @@ typedef struct Slave {
Tcl_Interp *masterInterp; /* Master interpreter for this slave. */
Tcl_HashEntry *slaveEntryPtr;
/* Hash entry in masters slave table for this
- * slave interpreter. Used to find this
+ * slave interpreter. Used to find this
* record, and used when deleting the slave
* interpreter to delete it from the master's
* table. */
@@ -156,98 +153,137 @@ typedef struct InterpInfo {
/*
* Limit callbacks handled by scripts are modelled as structures which are
- * stored in hashes indexed by a two-word key. Note that the type of the
+ * stored in hashes indexed by a two-word key. Note that the type of the
* 'type' field in the key is not int; this is to make sure that things are
* likely to work properly on 64-bit architectures.
*/
-struct ScriptLimitCallback {
- Tcl_Interp *interp;
- Tcl_Obj *scriptObj;
- int type;
- Tcl_HashEntry *entryPtr;
-};
+typedef struct ScriptLimitCallback {
+ Tcl_Interp *interp; /* The interpreter in which to execute the
+ * callback. */
+ Tcl_Obj *scriptObj; /* The script to execute to perform the
+ * user-defined part of the callback. */
+ int type; /* What kind of callback is this. */
+ Tcl_HashEntry *entryPtr; /* The entry in the hash table maintained by
+ * the target interpreter that refers to this
+ * callback record, or NULL if the entry has
+ * already been deleted from that hash
+ * table. */
+} ScriptLimitCallback;
+
+typedef struct ScriptLimitCallbackKey {
+ Tcl_Interp *interp; /* The interpreter that the limit callback was
+ * attached to. This is not the interpreter
+ * that the callback runs in! */
+ long type; /* The type of callback that this is. */
+} ScriptLimitCallbackKey;
-struct ScriptLimitCallbackKey {
- Tcl_Interp *interp;
- long type;
+/*
+ * TIP#143 limit handler internal representation.
+ */
+
+struct LimitHandler {
+ int flags; /* The state of this particular handler. */
+ Tcl_LimitHandlerProc *handlerProc;
+ /* The handler callback. */
+ ClientData clientData; /* Opaque argument to the handler callback. */
+ Tcl_LimitHandlerDeleteProc *deleteProc;
+ /* How to delete the clientData. */
+ LimitHandler *prevPtr; /* Previous item in linked list of
+ * handlers. */
+ LimitHandler *nextPtr; /* Next item in linked list of handlers. */
};
/*
- * Prototypes for local static procedures:
+ * Values for the LimitHandler flags field.
+ * LIMIT_HANDLER_ACTIVE - Whether the handler is currently being
+ * processed; handlers are never to be entered reentrantly.
+ * LIMIT_HANDLER_DELETED - Whether the handler has been deleted. This
+ * should not normally be observed because when a handler is
+ * deleted it is also spliced out of the list of handlers, but
+ * even so we will be careful.
+ */
+
+#define LIMIT_HANDLER_ACTIVE 0x01
+#define LIMIT_HANDLER_DELETED 0x02
+
+
+
+/*
+ * Prototypes for local static functions:
*/
-static int AliasCreate _ANSI_ARGS_((Tcl_Interp *interp,
+static int AliasCreate(Tcl_Interp *interp,
Tcl_Interp *slaveInterp, Tcl_Interp *masterInterp,
Tcl_Obj *namePtr, Tcl_Obj *targetPtr, int objc,
- Tcl_Obj *CONST objv[]));
-static int AliasDelete _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Interp *slaveInterp, Tcl_Obj *namePtr));
-static int AliasDescribe _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Interp *slaveInterp, Tcl_Obj *objPtr));
-static int AliasList _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Interp *slaveInterp));
-static int AliasObjCmd _ANSI_ARGS_((ClientData dummy,
+ Tcl_Obj *const objv[]);
+static int AliasDelete(Tcl_Interp *interp,
+ Tcl_Interp *slaveInterp, Tcl_Obj *namePtr);
+static int AliasDescribe(Tcl_Interp *interp,
+ Tcl_Interp *slaveInterp, Tcl_Obj *objPtr);
+static int AliasList(Tcl_Interp *interp, Tcl_Interp *slaveInterp);
+static int AliasObjCmd(ClientData dummy,
Tcl_Interp *currentInterp, int objc,
- Tcl_Obj *CONST objv[]));
-static void AliasObjCmdDeleteProc _ANSI_ARGS_((
- ClientData clientData));
-
-static Tcl_Interp * GetInterp _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Obj *pathPtr));
-static Tcl_Interp * GetInterp2 _ANSI_ARGS_((Tcl_Interp *interp, int objc,
- Tcl_Obj *CONST objv[]));
-static void InterpInfoDeleteProc _ANSI_ARGS_((
- ClientData clientData, Tcl_Interp *interp));
-static int SlaveBgerror _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Interp *slaveInterp, int objc,
- Tcl_Obj *CONST objv[]));
-static Tcl_Interp * SlaveCreate _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Obj *pathPtr, int safe));
-static int SlaveEval _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Interp *slaveInterp, int objc,
- Tcl_Obj *CONST objv[]));
-static int SlaveExpose _ANSI_ARGS_((Tcl_Interp *interp,
+ Tcl_Obj *const objv[]);
+static int AliasNRCmd(ClientData dummy,
+ Tcl_Interp *currentInterp, int objc,
+ Tcl_Obj *const objv[]);
+static void AliasObjCmdDeleteProc(ClientData clientData);
+static Tcl_Interp * GetInterp(Tcl_Interp *interp, Tcl_Obj *pathPtr);
+static Tcl_Interp * GetInterp2(Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+static void InterpInfoDeleteProc(ClientData clientData,
+ Tcl_Interp *interp);
+static int SlaveBgerror(Tcl_Interp *interp,
Tcl_Interp *slaveInterp, int objc,
- Tcl_Obj *CONST objv[]));
-static int SlaveHide _ANSI_ARGS_((Tcl_Interp *interp,
+ Tcl_Obj *const objv[]);
+static Tcl_Interp * SlaveCreate(Tcl_Interp *interp, Tcl_Obj *pathPtr,
+ int safe);
+static int SlaveDebugCmd(Tcl_Interp *interp,
+ Tcl_Interp *slaveInterp,
+ int objc, Tcl_Obj *const objv[]);
+static int SlaveEval(Tcl_Interp *interp, Tcl_Interp *slaveInterp,
+ int objc, Tcl_Obj *const objv[]);
+static int SlaveExpose(Tcl_Interp *interp,
Tcl_Interp *slaveInterp, int objc,
- Tcl_Obj *CONST objv[]));
-static int SlaveHidden _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Interp *slaveInterp));
-static int SlaveInvokeHidden _ANSI_ARGS_((Tcl_Interp *interp,
+ Tcl_Obj *const objv[]);
+static int SlaveHide(Tcl_Interp *interp, Tcl_Interp *slaveInterp,
+ int objc, Tcl_Obj *const objv[]);
+static int SlaveHidden(Tcl_Interp *interp,
+ Tcl_Interp *slaveInterp);
+static int SlaveInvokeHidden(Tcl_Interp *interp,
Tcl_Interp *slaveInterp,
- CONST char *namespaceName,
- int objc, Tcl_Obj *CONST objv[]));
-static int SlaveMarkTrusted _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Interp *slaveInterp));
-static int SlaveObjCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int objc,
- Tcl_Obj *CONST objv[]));
-static void SlaveObjCmdDeleteProc _ANSI_ARGS_((
- ClientData clientData));
-static int SlaveRecursionLimit _ANSI_ARGS_((Tcl_Interp *interp,
+ const char *namespaceName,
+ int objc, Tcl_Obj *const objv[]);
+static int SlaveMarkTrusted(Tcl_Interp *interp,
+ Tcl_Interp *slaveInterp);
+static int SlaveObjCmd(ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+static void SlaveObjCmdDeleteProc(ClientData clientData);
+static int SlaveRecursionLimit(Tcl_Interp *interp,
Tcl_Interp *slaveInterp, int objc,
- Tcl_Obj *CONST objv[]));
-static int SlaveCommandLimitCmd _ANSI_ARGS_((Tcl_Interp *interp,
+ Tcl_Obj *const objv[]);
+static int SlaveCommandLimitCmd(Tcl_Interp *interp,
Tcl_Interp *slaveInterp, int consumedObjc,
- int objc, Tcl_Obj *CONST objv[]));
-static int SlaveTimeLimitCmd _ANSI_ARGS_((Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+static int SlaveTimeLimitCmd(Tcl_Interp *interp,
Tcl_Interp *slaveInterp, int consumedObjc,
- int objc, Tcl_Obj *CONST objv[]));
-static void InheritLimitsFromMaster _ANSI_ARGS_((
- Tcl_Interp *slaveInterp,
- Tcl_Interp *masterInterp));
-static void SetScriptLimitCallback _ANSI_ARGS_((Tcl_Interp *interp,
- int type, Tcl_Interp *targetInterp,
- Tcl_Obj *scriptObj));
-static void CallScriptLimitCallback _ANSI_ARGS_((
- ClientData clientData, Tcl_Interp *interp));
-static void DeleteScriptLimitCallback _ANSI_ARGS_((
- ClientData clientData));
-static void RunLimitHandlers _ANSI_ARGS_((LimitHandler *handlerPtr,
- Tcl_Interp *interp));
-static void TimeLimitCallback _ANSI_ARGS_((ClientData clientData));
+ int objc, Tcl_Obj *const objv[]);
+static void InheritLimitsFromMaster(Tcl_Interp *slaveInterp,
+ Tcl_Interp *masterInterp);
+static void SetScriptLimitCallback(Tcl_Interp *interp, int type,
+ Tcl_Interp *targetInterp, Tcl_Obj *scriptObj);
+static void CallScriptLimitCallback(ClientData clientData,
+ Tcl_Interp *interp);
+static void DeleteScriptLimitCallback(ClientData clientData);
+static void RunLimitHandlers(LimitHandler *handlerPtr,
+ Tcl_Interp *interp);
+static void TimeLimitCallback(ClientData clientData);
+
+/* NRE enabling */
+static Tcl_NRPostProc NRPostInvokeHidden;
+static Tcl_ObjCmdProc NRInterpCmd;
+static Tcl_ObjCmdProc NRSlaveCmd;
/*
@@ -267,11 +303,11 @@ static void TimeLimitCallback _ANSI_ARGS_((ClientData clientData));
*----------------------------------------------------------------------
*/
-char *
-TclSetPreInitScript (string)
- char *string; /* Pointer to a script. */
+const char *
+TclSetPreInitScript(
+ const char *string) /* Pointer to a script. */
{
- char *prevString = tclPreInitScript;
+ const char *prevString = tclPreInitScript;
tclPreInitScript = string;
return(prevString);
}
@@ -281,7 +317,7 @@ TclSetPreInitScript (string)
*
* Tcl_Init --
*
- * This procedure is typically invoked by Tcl_AppInit procedures to find
+ * This function is typically invoked by Tcl_AppInit functions to find
* and source the "init.tcl" script, which should exist somewhere on the
* Tcl library path.
*
@@ -296,40 +332,40 @@ TclSetPreInitScript (string)
*/
int
-Tcl_Init(interp)
- Tcl_Interp *interp; /* Interpreter to initialize. */
+Tcl_Init(
+ Tcl_Interp *interp) /* Interpreter to initialize. */
{
if (tclPreInitScript != NULL) {
if (Tcl_Eval(interp, tclPreInitScript) == TCL_ERROR) {
- return (TCL_ERROR);
- };
+ return TCL_ERROR;
+ }
}
/*
* In order to find init.tcl during initialization, the following script
- * is invoked by Tcl_Init(). It looks in several different directories:
+ * is invoked by Tcl_Init(). It looks in several different directories:
*
* $tcl_library - can specify a primary location, if set, no
- * other locations will be checked. This is
- * the recommended way for a program that
- * embeds Tcl to specifically tell Tcl where to
- * find an init.tcl file.
+ * other locations will be checked. This is the
+ * recommended way for a program that embeds
+ * Tcl to specifically tell Tcl where to find
+ * an init.tcl file.
*
* $env(TCL_LIBRARY) - highest priority so user can always override
* the search path unless the application has
* specified an exact directory above
*
- * $tclDefaultLibrary - INTERNAL: This variable is set by Tcl
- * on those platforms where it can determine at
+ * $tclDefaultLibrary - INTERNAL: This variable is set by Tcl on
+ * those platforms where it can determine at
* runtime the directory where it expects the
- * init.tcl file to be. After [tclInit] reads
+ * init.tcl file to be. After [tclInit] reads
* and uses this value, it [unset]s it.
* External users of Tcl should not make use of
* the variable to customize [tclInit].
*
- * $tcl_libPath - OBSOLETE: This variable is no longer
- * set by Tcl itself, but [tclInit] examines it
- * in case some program that embeds Tcl is
+ * $tcl_libPath - OBSOLETE: This variable is no longer set by
+ * Tcl itself, but [tclInit] examines it in
+ * case some program that embeds Tcl is
* customizing [tclInit] by setting this
* variable to a list of directories in which
* to search.
@@ -343,11 +379,11 @@ Tcl_Init(interp)
* will be set as the value of tcl_library.
*
* Note that this entire search mechanism can be bypassed by defining an
- * alternate tclInit procedure before calling Tcl_Init().
+ * alternate tclInit command before calling Tcl_Init().
*/
return Tcl_Eval(interp,
-"if {[info proc tclInit]==\"\"} {\n"
+"if {[namespace which -command tclInit] eq \"\"} {\n"
" proc tclInit {} {\n"
" global tcl_libPath tcl_library env tclDefaultLibrary\n"
" rename tclInit {}\n"
@@ -417,8 +453,7 @@ Tcl_Init(interp)
* TclInterpInit --
*
* Initializes the invoking interpreter for using the master, slave and
- * safe interp facilities. This is called from inside
- * Tcl_CreateInterp().
+ * safe interp facilities. This is called from inside Tcl_CreateInterp().
*
* Results:
* Always returns TCL_OK for backwards compatibility.
@@ -431,15 +466,15 @@ Tcl_Init(interp)
*/
int
-TclInterpInit(interp)
- Tcl_Interp *interp; /* Interpreter to initialize. */
+TclInterpInit(
+ Tcl_Interp *interp) /* Interpreter to initialize. */
{
InterpInfo *interpInfoPtr;
Master *masterPtr;
Slave *slavePtr;
- interpInfoPtr = (InterpInfo *) ckalloc(sizeof(InterpInfo));
- ((Interp *) interp)->interpInfo = (ClientData) interpInfoPtr;
+ interpInfoPtr = ckalloc(sizeof(InterpInfo));
+ ((Interp *) interp)->interpInfo = interpInfoPtr;
masterPtr = &interpInfoPtr->master;
Tcl_InitHashTable(&masterPtr->slaveTable, TCL_STRING_KEYS);
@@ -452,7 +487,8 @@ TclInterpInit(interp)
slavePtr->interpCmd = NULL;
Tcl_InitHashTable(&slavePtr->aliasTable, TCL_STRING_KEYS);
- Tcl_CreateObjCommand(interp, "interp", Tcl_InterpObjCmd, NULL, NULL);
+ Tcl_NRCreateCommand(interp, "interp", Tcl_InterpObjCmd, NRInterpCmd,
+ NULL, NULL);
Tcl_CallWhenDeleted(interp, InterpInfoDeleteProc, NULL);
return TCL_OK;
@@ -463,7 +499,7 @@ TclInterpInit(interp)
*
* InterpInfoDeleteProc --
*
- * Invoked when an interpreter is being deleted. It releases all storage
+ * Invoked when an interpreter is being deleted. It releases all storage
* used by the master/slave/safe interpreter facilities.
*
* Results:
@@ -476,9 +512,9 @@ TclInterpInit(interp)
*/
static void
-InterpInfoDeleteProc(clientData, interp)
- ClientData clientData; /* Ignored. */
- Tcl_Interp *interp; /* Interp being deleted. All commands for
+InterpInfoDeleteProc(
+ ClientData clientData, /* Ignored. */
+ Tcl_Interp *interp) /* Interp being deleted. All commands for
* slave interps should already be deleted. */
{
InterpInfo *interpInfoPtr;
@@ -534,7 +570,7 @@ InterpInfoDeleteProc(clientData, interp)
}
Tcl_DeleteHashTable(&slavePtr->aliasTable);
- ckfree((char *) interpInfoPtr);
+ ckfree(interpInfoPtr);
}
/*
@@ -542,8 +578,8 @@ InterpInfoDeleteProc(clientData, interp)
*
* Tcl_InterpObjCmd --
*
- * This procedure is invoked to process the "interp" Tcl command. See
- * the user documentation for details on what it does.
+ * This function is invoked to process the "interp" Tcl command. See the
+ * user documentation for details on what it does.
*
* Results:
* A standard Tcl result.
@@ -555,27 +591,40 @@ InterpInfoDeleteProc(clientData, interp)
*/
/* ARGSUSED */
int
-Tcl_InterpObjCmd(clientData, interp, objc, objv)
- ClientData clientData; /* Unused. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+Tcl_InterpObjCmd(
+ ClientData clientData, /* Unused. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ return Tcl_NRCallObjProc(interp, NRInterpCmd, clientData, objc, objv);
+}
+
+static int
+NRInterpCmd(
+ ClientData clientData, /* Unused. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
+ Tcl_Interp *slaveInterp;
int index;
- static CONST char *options[] = {
- "alias", "aliases", "bgerror", "create",
- "delete", "eval", "exists", "expose",
- "hide", "hidden", "issafe", "invokehidden",
- "limit", "marktrusted", "recursionlimit","slaves",
- "share", "target", "transfer",
+ static const char *const options[] = {
+ "alias", "aliases", "bgerror", "cancel",
+ "create", "debug", "delete",
+ "eval", "exists", "expose",
+ "hide", "hidden", "issafe",
+ "invokehidden", "limit", "marktrusted", "recursionlimit",
+ "slaves", "share", "target", "transfer",
NULL
};
enum option {
- OPT_ALIAS, OPT_ALIASES, OPT_BGERROR, OPT_CREATE,
- OPT_DELETE, OPT_EVAL, OPT_EXISTS, OPT_EXPOSE,
- OPT_HIDE, OPT_HIDDEN, OPT_ISSAFE, OPT_INVOKEHID,
- OPT_LIMIT, OPT_MARKTRUSTED,OPT_RECLIMIT, OPT_SLAVES,
- OPT_SHARE, OPT_TARGET, OPT_TRANSFER
+ OPT_ALIAS, OPT_ALIASES, OPT_BGERROR, OPT_CANCEL,
+ OPT_CREATE, OPT_DEBUG, OPT_DELETE,
+ OPT_EVAL, OPT_EXISTS, OPT_EXPOSE,
+ OPT_HIDE, OPT_HIDDEN, OPT_ISSAFE,
+ OPT_INVOKEHID, OPT_LIMIT, OPT_MARKTRUSTED,OPT_RECLIMIT,
+ OPT_SLAVES, OPT_SHARE, OPT_TARGET, OPT_TRANSFER
};
if (objc < 2) {
@@ -588,30 +637,30 @@ Tcl_InterpObjCmd(clientData, interp, objc, objv)
}
switch ((enum option) index) {
case OPT_ALIAS: {
- Tcl_Interp *slaveInterp, *masterInterp;
+ Tcl_Interp *masterInterp;
if (objc < 4) {
aliasArgs:
Tcl_WrongNumArgs(interp, 2, objv,
- "slavePath slaveCmd ?masterPath masterCmd? ?args ..?");
+ "slavePath slaveCmd ?masterPath masterCmd? ?arg ...?");
return TCL_ERROR;
}
slaveInterp = GetInterp(interp, objv[2]);
- if (slaveInterp == (Tcl_Interp *) NULL) {
+ if (slaveInterp == NULL) {
return TCL_ERROR;
}
if (objc == 4) {
return AliasDescribe(interp, slaveInterp, objv[3]);
}
- if ((objc == 5) && (Tcl_GetString(objv[4])[0] == '\0')) {
+ if ((objc == 5) && (TclGetString(objv[4])[0] == '\0')) {
return AliasDelete(interp, slaveInterp, objv[3]);
}
if (objc > 5) {
masterInterp = GetInterp(interp, objv[4]);
- if (masterInterp == (Tcl_Interp *) NULL) {
+ if (masterInterp == NULL) {
return TCL_ERROR;
}
- if (Tcl_GetString(objv[5])[0] == '\0') {
+ if (TclGetString(objv[5])[0] == '\0') {
if (objc == 6) {
return AliasDelete(interp, slaveInterp, objv[3]);
}
@@ -622,18 +671,13 @@ Tcl_InterpObjCmd(clientData, interp, objc, objv)
}
goto aliasArgs;
}
- case OPT_ALIASES: {
- Tcl_Interp *slaveInterp;
-
+ case OPT_ALIASES:
slaveInterp = GetInterp2(interp, objc, objv);
if (slaveInterp == NULL) {
return TCL_ERROR;
}
return AliasList(interp, slaveInterp);
- }
- case OPT_BGERROR: {
- Tcl_Interp *slaveInterp;
-
+ case OPT_BGERROR:
if (objc != 3 && objc != 4) {
Tcl_WrongNumArgs(interp, 2, objv, "path ?cmdPrefix?");
return TCL_ERROR;
@@ -643,13 +687,84 @@ Tcl_InterpObjCmd(clientData, interp, objc, objv)
return TCL_ERROR;
}
return SlaveBgerror(interp, slaveInterp, objc - 3, objv + 3);
+ case OPT_CANCEL: {
+ int i, flags;
+ Tcl_Obj *resultObjPtr;
+ static const char *const cancelOptions[] = {
+ "-unwind", "--", NULL
+ };
+ enum option {
+ OPT_UNWIND, OPT_LAST
+ };
+
+ flags = 0;
+
+ for (i = 2; i < objc; i++) {
+ if (TclGetString(objv[i])[0] != '-') {
+ break;
+ }
+ if (Tcl_GetIndexFromObj(interp, objv[i], cancelOptions, "option",
+ 0, &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ switch ((enum option) index) {
+ case OPT_UNWIND:
+ /*
+ * The evaluation stack in the target interp is to be unwound.
+ */
+
+ flags |= TCL_CANCEL_UNWIND;
+ break;
+ case OPT_LAST:
+ i++;
+ goto endOfForLoop;
+ }
+ }
+
+ endOfForLoop:
+ if ((i + 2) < objc) {
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "?-unwind? ?--? ?path? ?result?");
+ return TCL_ERROR;
+ }
+
+ /*
+ * Did they specify a slave interp to cancel the script in progress
+ * in? If not, use the current interp.
+ */
+
+ if (i < objc) {
+ slaveInterp = GetInterp(interp, objv[i]);
+ if (slaveInterp == NULL) {
+ return TCL_ERROR;
+ }
+ i++;
+ } else {
+ slaveInterp = interp;
+ }
+
+ if (i < objc) {
+ resultObjPtr = objv[i];
+
+ /*
+ * Tcl_CancelEval removes this reference.
+ */
+
+ Tcl_IncrRefCount(resultObjPtr);
+ i++;
+ } else {
+ resultObjPtr = NULL;
+ }
+
+ return Tcl_CancelEval(slaveInterp, resultObjPtr, 0, flags);
}
case OPT_CREATE: {
int i, last, safe;
Tcl_Obj *slavePtr;
char buf[16 + TCL_INTEGER_SPACE];
- static CONST char *options[] = {
- "-safe", "--", NULL
+ static const char *const createOptions[] = {
+ "-safe", "--", NULL
};
enum option {
OPT_SAFE, OPT_LAST
@@ -665,8 +780,8 @@ Tcl_InterpObjCmd(clientData, interp, objc, objv)
last = 0;
for (i = 2; i < objc; i++) {
if ((last == 0) && (Tcl_GetString(objv[i])[0] == '-')) {
- if (Tcl_GetIndexFromObj(interp, objv[i], options, "option", 0,
- &index) != TCL_OK) {
+ if (Tcl_GetIndexFromObj(interp, objv[i], createOptions,
+ "option", 0, &index) != TCL_OK) {
return TCL_ERROR;
}
if (index == OPT_SAFE) {
@@ -712,10 +827,23 @@ Tcl_InterpObjCmd(clientData, interp, objc, objv)
Tcl_SetObjResult(interp, slavePtr);
return TCL_OK;
}
+ case OPT_DEBUG: /* TIP #378 */
+ /*
+ * Currently only -frame supported, otherwise ?-option ?value??
+ */
+
+ if (objc < 3 || objc > 5) {
+ Tcl_WrongNumArgs(interp, 2, objv, "path ?-frame ?bool??");
+ return TCL_ERROR;
+ }
+ slaveInterp = GetInterp(interp, objv[2]);
+ if (slaveInterp == NULL) {
+ return TCL_ERROR;
+ }
+ return SlaveDebugCmd(interp, slaveInterp, objc - 3, objv + 3);
case OPT_DELETE: {
int i;
InterpInfo *iiPtr;
- Tcl_Interp *slaveInterp;
for (i = 2; i < objc; i++) {
slaveInterp = GetInterp(interp, objv[i]);
@@ -724,6 +852,8 @@ Tcl_InterpObjCmd(clientData, interp, objc, objv)
} else if (slaveInterp == interp) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"cannot delete the current interpreter", -1));
+ Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP",
+ "DELETESELF", NULL);
return TCL_ERROR;
}
iiPtr = (InterpInfo *) ((Interp *) slaveInterp)->interpInfo;
@@ -732,9 +862,7 @@ Tcl_InterpObjCmd(clientData, interp, objc, objv)
}
return TCL_OK;
}
- case OPT_EVAL: {
- Tcl_Interp *slaveInterp;
-
+ case OPT_EVAL:
if (objc < 4) {
Tcl_WrongNumArgs(interp, 2, objv, "path arg ?arg ...?");
return TCL_ERROR;
@@ -744,12 +872,9 @@ Tcl_InterpObjCmd(clientData, interp, objc, objv)
return TCL_ERROR;
}
return SlaveEval(interp, slaveInterp, objc - 3, objv + 3);
- }
case OPT_EXISTS: {
- int exists;
- Tcl_Interp *slaveInterp;
+ int exists = 1;
- exists = 1;
slaveInterp = GetInterp2(interp, objc, objv);
if (slaveInterp == NULL) {
if (objc > 3) {
@@ -761,9 +886,7 @@ Tcl_InterpObjCmd(clientData, interp, objc, objv)
Tcl_SetObjResult(interp, Tcl_NewBooleanObj(exists));
return TCL_OK;
}
- case OPT_EXPOSE: {
- Tcl_Interp *slaveInterp;
-
+ case OPT_EXPOSE:
if ((objc < 4) || (objc > 5)) {
Tcl_WrongNumArgs(interp, 2, objv, "path hiddenCmdName ?cmdName?");
return TCL_ERROR;
@@ -773,45 +896,34 @@ Tcl_InterpObjCmd(clientData, interp, objc, objv)
return TCL_ERROR;
}
return SlaveExpose(interp, slaveInterp, objc - 3, objv + 3);
- }
- case OPT_HIDE: {
- Tcl_Interp *slaveInterp; /* A slave. */
-
+ case OPT_HIDE:
if ((objc < 4) || (objc > 5)) {
Tcl_WrongNumArgs(interp, 2, objv, "path cmdName ?hiddenCmdName?");
return TCL_ERROR;
}
slaveInterp = GetInterp(interp, objv[2]);
- if (slaveInterp == (Tcl_Interp *) NULL) {
+ if (slaveInterp == NULL) {
return TCL_ERROR;
}
return SlaveHide(interp, slaveInterp, objc - 3, objv + 3);
- }
- case OPT_HIDDEN: {
- Tcl_Interp *slaveInterp; /* A slave. */
-
+ case OPT_HIDDEN:
slaveInterp = GetInterp2(interp, objc, objv);
if (slaveInterp == NULL) {
return TCL_ERROR;
}
return SlaveHidden(interp, slaveInterp);
- }
- case OPT_ISSAFE: {
- Tcl_Interp *slaveInterp;
-
+ case OPT_ISSAFE:
slaveInterp = GetInterp2(interp, objc, objv);
if (slaveInterp == NULL) {
return TCL_ERROR;
}
Tcl_SetObjResult(interp, Tcl_NewBooleanObj(Tcl_IsSafe(slaveInterp)));
return TCL_OK;
- }
case OPT_INVOKEHID: {
- int i, index;
- CONST char *namespaceName;
- Tcl_Interp *slaveInterp;
- static CONST char *hiddenOptions[] = {
- "-global", "-namespace", "--", NULL
+ int i;
+ const char *namespaceName;
+ static const char *const hiddenOptions[] = {
+ "-global", "-namespace", "--", NULL
};
enum hiddenOption {
OPT_GLOBAL, OPT_NAMESPACE, OPT_LAST
@@ -819,7 +931,7 @@ Tcl_InterpObjCmd(clientData, interp, objc, objv)
namespaceName = NULL;
for (i = 3; i < objc; i++) {
- if (Tcl_GetString(objv[i])[0] != '-') {
+ if (TclGetString(objv[i])[0] != '-') {
break;
}
if (Tcl_GetIndexFromObj(interp, objv[i], hiddenOptions, "option",
@@ -832,7 +944,7 @@ Tcl_InterpObjCmd(clientData, interp, objc, objv)
if (++i == objc) { /* There must be more arguments. */
break;
} else {
- namespaceName = Tcl_GetString(objv[i]);
+ namespaceName = TclGetString(objv[i]);
}
} else {
i++;
@@ -845,15 +957,14 @@ Tcl_InterpObjCmd(clientData, interp, objc, objv)
return TCL_ERROR;
}
slaveInterp = GetInterp(interp, objv[2]);
- if (slaveInterp == (Tcl_Interp *) NULL) {
+ if (slaveInterp == NULL) {
return TCL_ERROR;
}
return SlaveInvokeHidden(interp, slaveInterp, namespaceName, objc - i,
objv + i);
}
case OPT_LIMIT: {
- Tcl_Interp *slaveInterp;
- static CONST char *limitTypes[] = {
+ static const char *const limitTypes[] = {
"commands", "time", NULL
};
enum LimitTypes {
@@ -862,7 +973,8 @@ Tcl_InterpObjCmd(clientData, interp, objc, objv)
int limitType;
if (objc < 4) {
- Tcl_WrongNumArgs(interp, 2, objv, "path limitType ?options?");
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "path limitType ?-option value ...?");
return TCL_ERROR;
}
slaveInterp = GetInterp(interp, objv[2]);
@@ -880,9 +992,7 @@ Tcl_InterpObjCmd(clientData, interp, objc, objv)
return SlaveTimeLimitCmd(interp, slaveInterp, 4, objc, objv);
}
}
- case OPT_MARKTRUSTED: {
- Tcl_Interp *slaveInterp;
-
+ case OPT_MARKTRUSTED:
if (objc != 3) {
Tcl_WrongNumArgs(interp, 2, objv, "path");
return TCL_ERROR;
@@ -892,10 +1002,7 @@ Tcl_InterpObjCmd(clientData, interp, objc, objv)
return TCL_ERROR;
}
return SlaveMarkTrusted(interp, slaveInterp);
- }
- case OPT_RECLIMIT: {
- Tcl_Interp *slaveInterp;
-
+ case OPT_RECLIMIT:
if (objc != 3 && objc != 4) {
Tcl_WrongNumArgs(interp, 2, objv, "path ?newlimit?");
return TCL_ERROR;
@@ -905,9 +1012,7 @@ Tcl_InterpObjCmd(clientData, interp, objc, objv)
return TCL_ERROR;
}
return SlaveRecursionLimit(interp, slaveInterp, objc - 3, objv + 3);
- }
case OPT_SLAVES: {
- Tcl_Interp *slaveInterp;
InterpInfo *iiPtr;
Tcl_Obj *resultPtr;
Tcl_HashEntry *hPtr;
@@ -929,9 +1034,9 @@ Tcl_InterpObjCmd(clientData, interp, objc, objv)
Tcl_SetObjResult(interp, resultPtr);
return TCL_OK;
}
+ case OPT_TRANSFER:
case OPT_SHARE: {
- Tcl_Interp *slaveInterp; /* A slave. */
- Tcl_Interp *masterInterp; /* Its master. */
+ Tcl_Interp *masterInterp; /* The master of the slave. */
Tcl_Channel chan;
if (objc != 5) {
@@ -942,9 +1047,9 @@ Tcl_InterpObjCmd(clientData, interp, objc, objv)
if (masterInterp == NULL) {
return TCL_ERROR;
}
- chan = Tcl_GetChannel(masterInterp, Tcl_GetString(objv[3]), NULL);
+ chan = Tcl_GetChannel(masterInterp, TclGetString(objv[3]), NULL);
if (chan == NULL) {
- TclTransferResult(masterInterp, TCL_OK, interp);
+ Tcl_TransferResult(masterInterp, TCL_OK, interp);
return TCL_ERROR;
}
slaveInterp = GetInterp(interp, objv[4]);
@@ -952,14 +1057,24 @@ Tcl_InterpObjCmd(clientData, interp, objc, objv)
return TCL_ERROR;
}
Tcl_RegisterChannel(slaveInterp, chan);
+ if (index == OPT_TRANSFER) {
+ /*
+ * When transferring, as opposed to sharing, we must unhitch the
+ * channel from the interpreter where it started.
+ */
+
+ if (Tcl_UnregisterChannel(masterInterp, chan) != TCL_OK) {
+ Tcl_TransferResult(masterInterp, TCL_OK, interp);
+ return TCL_ERROR;
+ }
+ }
return TCL_OK;
}
case OPT_TARGET: {
- Tcl_Interp *slaveInterp;
InterpInfo *iiPtr;
Tcl_HashEntry *hPtr;
Alias *aliasPtr;
- char *aliasName;
+ const char *aliasName;
if (objc != 4) {
Tcl_WrongNumArgs(interp, 2, objv, "path alias");
@@ -971,50 +1086,25 @@ Tcl_InterpObjCmd(clientData, interp, objc, objv)
return TCL_ERROR;
}
- aliasName = Tcl_GetString(objv[3]);
+ aliasName = TclGetString(objv[3]);
iiPtr = (InterpInfo *) ((Interp *) slaveInterp)->interpInfo;
hPtr = Tcl_FindHashEntry(&iiPtr->slave.aliasTable, aliasName);
if (hPtr == NULL) {
- Tcl_AppendResult(interp, "alias \"", aliasName, "\" in path \"",
- Tcl_GetString(objv[2]), "\" not found", (char *) NULL);
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "alias \"%s\" in path \"%s\" not found",
+ aliasName, Tcl_GetString(objv[2])));
+ Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ALIAS", aliasName,
+ NULL);
return TCL_ERROR;
}
- aliasPtr = (Alias *) Tcl_GetHashValue(hPtr);
+ aliasPtr = Tcl_GetHashValue(hPtr);
if (Tcl_GetInterpPath(interp, aliasPtr->targetInterp) != TCL_OK) {
- Tcl_ResetResult(interp);
- Tcl_AppendResult(interp, "target interpreter for alias \"",
- aliasName, "\" in path \"", Tcl_GetString(objv[2]),
- "\" is not my descendant", (char *) NULL);
- return TCL_ERROR;
- }
- return TCL_OK;
- }
- case OPT_TRANSFER: {
- Tcl_Interp *slaveInterp; /* A slave. */
- Tcl_Interp *masterInterp; /* Its master. */
- Tcl_Channel chan;
-
- if (objc != 5) {
- Tcl_WrongNumArgs(interp, 2, objv, "srcPath channelId destPath");
- return TCL_ERROR;
- }
- masterInterp = GetInterp(interp, objv[2]);
- if (masterInterp == NULL) {
- return TCL_ERROR;
- }
- chan = Tcl_GetChannel(masterInterp, Tcl_GetString(objv[3]), NULL);
- if (chan == NULL) {
- TclTransferResult(masterInterp, TCL_OK, interp);
- return TCL_ERROR;
- }
- slaveInterp = GetInterp(interp, objv[4]);
- if (slaveInterp == NULL) {
- return TCL_ERROR;
- }
- Tcl_RegisterChannel(slaveInterp, chan);
- if (Tcl_UnregisterChannel(masterInterp, chan) != TCL_OK) {
- TclTransferResult(masterInterp, TCL_OK, interp);
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "target interpreter for alias \"%s\" in path \"%s\" is "
+ "not my descendant", aliasName, Tcl_GetString(objv[2])));
+ Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP",
+ "TARGETSHROUDED", NULL);
return TCL_ERROR;
}
return TCL_OK;
@@ -1045,11 +1135,11 @@ Tcl_InterpObjCmd(clientData, interp, objc, objv)
*/
static Tcl_Interp *
-GetInterp2(interp, objc, objv)
- Tcl_Interp *interp; /* Default interp if no interp was specified
+GetInterp2(
+ Tcl_Interp *interp, /* Default interp if no interp was specified
* on the command line. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
if (objc == 2) {
return interp;
@@ -1078,20 +1168,20 @@ GetInterp2(interp, objc, objv)
*/
int
-Tcl_CreateAlias(slaveInterp, slaveCmd, targetInterp, targetCmd, argc, argv)
- Tcl_Interp *slaveInterp; /* Interpreter for source command. */
- CONST char *slaveCmd; /* Command to install in slave. */
- Tcl_Interp *targetInterp; /* Interpreter for target command. */
- CONST char *targetCmd; /* Name of target command. */
- int argc; /* How many additional arguments? */
- CONST char * CONST *argv; /* These are the additional args. */
+Tcl_CreateAlias(
+ Tcl_Interp *slaveInterp, /* Interpreter for source command. */
+ const char *slaveCmd, /* Command to install in slave. */
+ Tcl_Interp *targetInterp, /* Interpreter for target command. */
+ const char *targetCmd, /* Name of target command. */
+ int argc, /* How many additional arguments? */
+ const char *const *argv) /* These are the additional args. */
{
Tcl_Obj *slaveObjPtr, *targetObjPtr;
Tcl_Obj **objv;
int i;
int result;
- objv = (Tcl_Obj **) ckalloc((unsigned) sizeof(Tcl_Obj *) * argc);
+ objv = TclStackAlloc(slaveInterp, (unsigned) sizeof(Tcl_Obj *) * argc);
for (i = 0; i < argc; i++) {
objv[i] = Tcl_NewStringObj(argv[i], -1);
Tcl_IncrRefCount(objv[i]);
@@ -1109,7 +1199,7 @@ Tcl_CreateAlias(slaveInterp, slaveCmd, targetInterp, targetCmd, argc, argv)
for (i = 0; i < argc; i++) {
Tcl_DecrRefCount(objv[i]);
}
- ckfree((char *) objv);
+ TclStackFree(slaveInterp, objv);
Tcl_DecrRefCount(targetObjPtr);
Tcl_DecrRefCount(slaveObjPtr);
@@ -1133,13 +1223,13 @@ Tcl_CreateAlias(slaveInterp, slaveCmd, targetInterp, targetCmd, argc, argv)
*/
int
-Tcl_CreateAliasObj(slaveInterp, slaveCmd, targetInterp, targetCmd, objc, objv)
- Tcl_Interp *slaveInterp; /* Interpreter for source command. */
- CONST char *slaveCmd; /* Command to install in slave. */
- Tcl_Interp *targetInterp; /* Interpreter for target command. */
- CONST char *targetCmd; /* Name of target command. */
- int objc; /* How many additional arguments? */
- Tcl_Obj *CONST objv[]; /* Argument vector. */
+Tcl_CreateAliasObj(
+ Tcl_Interp *slaveInterp, /* Interpreter for source command. */
+ const char *slaveCmd, /* Command to install in slave. */
+ Tcl_Interp *targetInterp, /* Interpreter for target command. */
+ const char *targetCmd, /* Name of target command. */
+ int objc, /* How many additional arguments? */
+ Tcl_Obj *const objv[]) /* Argument vector. */
{
Tcl_Obj *slaveObjPtr, *targetObjPtr;
int result;
@@ -1175,29 +1265,29 @@ Tcl_CreateAliasObj(slaveInterp, slaveCmd, targetInterp, targetCmd, objc, objv)
*/
int
-Tcl_GetAlias(interp, aliasName, targetInterpPtr, targetNamePtr, argcPtr,
- argvPtr)
- Tcl_Interp *interp; /* Interp to start search from. */
- CONST char *aliasName; /* Name of alias to find. */
- Tcl_Interp **targetInterpPtr; /* (Return) target interpreter. */
- CONST char **targetNamePtr; /* (Return) name of target command. */
- int *argcPtr; /* (Return) count of addnl args. */
- CONST char ***argvPtr; /* (Return) additional arguments. */
+Tcl_GetAlias(
+ Tcl_Interp *interp, /* Interp to start search from. */
+ const char *aliasName, /* Name of alias to find. */
+ Tcl_Interp **targetInterpPtr,
+ /* (Return) target interpreter. */
+ const char **targetNamePtr, /* (Return) name of target command. */
+ int *argcPtr, /* (Return) count of addnl args. */
+ const char ***argvPtr) /* (Return) additional arguments. */
{
- InterpInfo *iiPtr;
+ InterpInfo *iiPtr = (InterpInfo *) ((Interp *) interp)->interpInfo;
Tcl_HashEntry *hPtr;
Alias *aliasPtr;
int i, objc;
Tcl_Obj **objv;
- iiPtr = (InterpInfo *) ((Interp *) interp)->interpInfo;
hPtr = Tcl_FindHashEntry(&iiPtr->slave.aliasTable, aliasName);
if (hPtr == NULL) {
- Tcl_AppendResult(interp, "alias \"", aliasName,
- "\" not found", (char *) NULL);
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "alias \"%s\" not found", aliasName));
+ Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ALIAS", aliasName, NULL);
return TCL_ERROR;
}
- aliasPtr = (Alias *) Tcl_GetHashValue(hPtr);
+ aliasPtr = Tcl_GetHashValue(hPtr);
objc = aliasPtr->objc;
objv = &aliasPtr->objPtr;
@@ -1205,16 +1295,16 @@ Tcl_GetAlias(interp, aliasName, targetInterpPtr, targetNamePtr, argcPtr,
*targetInterpPtr = aliasPtr->targetInterp;
}
if (targetNamePtr != NULL) {
- *targetNamePtr = Tcl_GetString(objv[0]);
+ *targetNamePtr = TclGetString(objv[0]);
}
if (argcPtr != NULL) {
*argcPtr = objc - 1;
}
if (argvPtr != NULL) {
- *argvPtr = (CONST char **)
- ckalloc((unsigned) sizeof(CONST char *) * (objc - 1));
+ *argvPtr = (const char **)
+ ckalloc(sizeof(const char *) * (objc - 1));
for (i = 1; i < objc; i++) {
- *argvPtr[i - 1] = Tcl_GetString(objv[i]);
+ (*argvPtr)[i - 1] = TclGetString(objv[i]);
}
}
return TCL_OK;
@@ -1237,42 +1327,42 @@ Tcl_GetAlias(interp, aliasName, targetInterpPtr, targetNamePtr, argcPtr,
*/
int
-Tcl_GetAliasObj(interp, aliasName, targetInterpPtr, targetNamePtr, objcPtr,
- objvPtr)
- Tcl_Interp *interp; /* Interp to start search from. */
- CONST char *aliasName; /* Name of alias to find. */
- Tcl_Interp **targetInterpPtr; /* (Return) target interpreter. */
- CONST char **targetNamePtr; /* (Return) name of target command. */
- int *objcPtr; /* (Return) count of addnl args. */
- Tcl_Obj ***objvPtr; /* (Return) additional args. */
+Tcl_GetAliasObj(
+ Tcl_Interp *interp, /* Interp to start search from. */
+ const char *aliasName, /* Name of alias to find. */
+ Tcl_Interp **targetInterpPtr,
+ /* (Return) target interpreter. */
+ const char **targetNamePtr, /* (Return) name of target command. */
+ int *objcPtr, /* (Return) count of addnl args. */
+ Tcl_Obj ***objvPtr) /* (Return) additional args. */
{
- InterpInfo *iiPtr;
+ InterpInfo *iiPtr = (InterpInfo *) ((Interp *) interp)->interpInfo;
Tcl_HashEntry *hPtr;
Alias *aliasPtr;
int objc;
Tcl_Obj **objv;
- iiPtr = (InterpInfo *) ((Interp *) interp)->interpInfo;
hPtr = Tcl_FindHashEntry(&iiPtr->slave.aliasTable, aliasName);
- if (hPtr == (Tcl_HashEntry *) NULL) {
- Tcl_AppendResult(interp, "alias \"", aliasName, "\" not found",
- (char *) NULL);
+ if (hPtr == NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "alias \"%s\" not found", aliasName));
+ Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ALIAS", aliasName, NULL);
return TCL_ERROR;
}
- aliasPtr = (Alias *) Tcl_GetHashValue(hPtr);
+ aliasPtr = Tcl_GetHashValue(hPtr);
objc = aliasPtr->objc;
objv = &aliasPtr->objPtr;
- if (targetInterpPtr != (Tcl_Interp **) NULL) {
+ if (targetInterpPtr != NULL) {
*targetInterpPtr = aliasPtr->targetInterp;
}
- if (targetNamePtr != (CONST char **) NULL) {
- *targetNamePtr = Tcl_GetString(objv[0]);
+ if (targetNamePtr != NULL) {
+ *targetNamePtr = TclGetString(objv[0]);
}
- if (objcPtr != (int *) NULL) {
+ if (objcPtr != NULL) {
*objcPtr = objc - 1;
}
- if (objvPtr != (Tcl_Obj ***) NULL) {
+ if (objvPtr != NULL) {
*objvPtr = objv + 1;
}
return TCL_OK;
@@ -1301,12 +1391,11 @@ Tcl_GetAliasObj(interp, aliasName, targetInterpPtr, targetNamePtr, objcPtr,
*/
int
-TclPreventAliasLoop(interp, cmdInterp, cmd)
- Tcl_Interp *interp; /* Interp in which to report errors. */
- Tcl_Interp *cmdInterp; /* Interp in which the command is
- * being defined. */
- Tcl_Command cmd; /* Tcl command we are attempting to
- * define. */
+TclPreventAliasLoop(
+ Tcl_Interp *interp, /* Interp in which to report errors. */
+ Tcl_Interp *cmdInterp, /* Interp in which the command is being
+ * defined. */
+ Tcl_Command cmd) /* Tcl command we are attempting to define. */
{
Command *cmdPtr = (Command *) cmd;
Alias *aliasPtr, *nextAliasPtr;
@@ -1328,7 +1417,7 @@ TclPreventAliasLoop(interp, cmdInterp, cmd)
* chain then we have a loop.
*/
- aliasPtr = (Alias *) cmdPtr->objClientData;
+ aliasPtr = cmdPtr->objClientData;
nextAliasPtr = aliasPtr;
while (1) {
Tcl_Obj *cmdNamePtr;
@@ -1344,24 +1433,26 @@ TclPreventAliasLoop(interp, cmdInterp, cmd)
* [Bug #641195]
*/
- Tcl_AppendResult(interp, "cannot define or rename alias \"",
- Tcl_GetCommandName(cmdInterp, cmd),
- "\": interpreter deleted", (char *) NULL);
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "cannot define or rename alias \"%s\": interpreter deleted",
+ Tcl_GetCommandName(cmdInterp, cmd)));
return TCL_ERROR;
}
cmdNamePtr = nextAliasPtr->objPtr;
aliasCmd = Tcl_FindCommand(nextAliasPtr->targetInterp,
- Tcl_GetString(cmdNamePtr),
+ TclGetString(cmdNamePtr),
Tcl_GetGlobalNamespace(nextAliasPtr->targetInterp),
/*flags*/ 0);
- if (aliasCmd == (Tcl_Command) NULL) {
+ if (aliasCmd == NULL) {
return TCL_OK;
}
aliasCmdPtr = (Command *) aliasCmd;
if (aliasCmdPtr == cmdPtr) {
- Tcl_AppendResult(interp, "cannot define or rename alias \"",
- Tcl_GetCommandName(cmdInterp, cmd),
- "\": would create a loop", (char *) NULL);
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "cannot define or rename alias \"%s\": would create a loop",
+ Tcl_GetCommandName(cmdInterp, cmd)));
+ Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP",
+ "ALIASLOOP", NULL);
return TCL_ERROR;
}
@@ -1374,7 +1465,7 @@ TclPreventAliasLoop(interp, cmdInterp, cmd)
if (aliasCmdPtr->objProc != AliasObjCmd) {
return TCL_OK;
}
- nextAliasPtr = (Alias *) aliasCmdPtr->objClientData;
+ nextAliasPtr = aliasCmdPtr->objClientData;
}
/* NOTREACHED */
@@ -1398,17 +1489,16 @@ TclPreventAliasLoop(interp, cmdInterp, cmd)
*/
static int
-AliasCreate(interp, slaveInterp, masterInterp, namePtr, targetNamePtr,
- objc, objv)
- Tcl_Interp *interp; /* Interp for error reporting. */
- Tcl_Interp *slaveInterp; /* Interp where alias cmd will live or from
+AliasCreate(
+ Tcl_Interp *interp, /* Interp for error reporting. */
+ Tcl_Interp *slaveInterp, /* Interp where alias cmd will live or from
* which alias will be deleted. */
- Tcl_Interp *masterInterp; /* Interp in which target command will be
+ Tcl_Interp *masterInterp, /* Interp in which target command will be
* invoked. */
- Tcl_Obj *namePtr; /* Name of alias cmd. */
- Tcl_Obj *targetNamePtr; /* Name of target cmd. */
- int objc; /* Additional arguments to store */
- Tcl_Obj *CONST objv[]; /* with alias. */
+ Tcl_Obj *namePtr, /* Name of alias cmd. */
+ Tcl_Obj *targetNamePtr, /* Name of target cmd. */
+ int objc, /* Additional arguments to store */
+ Tcl_Obj *const objv[]) /* with alias. */
{
Alias *aliasPtr;
Tcl_HashEntry *hPtr;
@@ -1416,10 +1506,9 @@ AliasCreate(interp, slaveInterp, masterInterp, namePtr, targetNamePtr,
Slave *slavePtr;
Master *masterPtr;
Tcl_Obj **prefv;
- int new, i;
+ int isNew, i;
- aliasPtr = (Alias *) ckalloc((unsigned) (sizeof(Alias)
- + objc * sizeof(Tcl_Obj *)));
+ aliasPtr = ckalloc(sizeof(Alias) + objc * sizeof(Tcl_Obj *));
aliasPtr->token = namePtr;
Tcl_IncrRefCount(aliasPtr->token);
aliasPtr->targetInterp = masterInterp;
@@ -1437,17 +1526,23 @@ AliasCreate(interp, slaveInterp, masterInterp, namePtr, targetNamePtr,
Tcl_Preserve(slaveInterp);
Tcl_Preserve(masterInterp);
+ if (slaveInterp == masterInterp) {
+ aliasPtr->slaveCmd = Tcl_NRCreateCommand(slaveInterp,
+ TclGetString(namePtr), AliasObjCmd, AliasNRCmd, aliasPtr,
+ AliasObjCmdDeleteProc);
+ } else {
aliasPtr->slaveCmd = Tcl_CreateObjCommand(slaveInterp,
- Tcl_GetString(namePtr), AliasObjCmd, (ClientData) aliasPtr,
+ TclGetString(namePtr), AliasObjCmd, aliasPtr,
AliasObjCmdDeleteProc);
+ }
if (TclPreventAliasLoop(interp, slaveInterp,
aliasPtr->slaveCmd) != TCL_OK) {
/*
- * Found an alias loop! The last call to Tcl_CreateObjCommand made
- * the alias point to itself. Delete the command and its alias
- * record. Be careful to wipe out its client data first, so the
- * command doesn't try to delete itself.
+ * Found an alias loop! The last call to Tcl_CreateObjCommand made the
+ * alias point to itself. Delete the command and its alias record. Be
+ * careful to wipe out its client data first, so the command doesn't
+ * try to delete itself.
*/
Command *cmdPtr;
@@ -1464,7 +1559,7 @@ AliasCreate(interp, slaveInterp, masterInterp, namePtr, targetNamePtr,
cmdPtr->deleteData = NULL;
Tcl_DeleteCommandFromToken(slaveInterp, aliasPtr->slaveCmd);
- ckfree((char *) aliasPtr);
+ ckfree(aliasPtr);
/*
* The result was already set by TclPreventAliasLoop.
@@ -1482,11 +1577,11 @@ AliasCreate(interp, slaveInterp, masterInterp, namePtr, targetNamePtr,
slavePtr = &((InterpInfo *) ((Interp *) slaveInterp)->interpInfo)->slave;
while (1) {
Tcl_Obj *newToken;
- char *string;
+ const char *string;
- string = Tcl_GetString(aliasPtr->token);
- hPtr = Tcl_CreateHashEntry(&slavePtr->aliasTable, string, &new);
- if (new != 0) {
+ string = TclGetString(aliasPtr->token);
+ hPtr = Tcl_CreateHashEntry(&slavePtr->aliasTable, string, &isNew);
+ if (isNew != 0) {
break;
}
@@ -1502,7 +1597,7 @@ AliasCreate(interp, slaveInterp, masterInterp, namePtr, targetNamePtr,
* on the precise definition of these tokens.
*/
- newToken = Tcl_NewStringObj("::",-1);
+ TclNewLiteralStringObj(newToken, "::");
Tcl_AppendObjToObj(newToken, aliasPtr->token);
Tcl_DecrRefCount(aliasPtr->token);
aliasPtr->token = newToken;
@@ -1510,7 +1605,7 @@ AliasCreate(interp, slaveInterp, masterInterp, namePtr, targetNamePtr,
}
aliasPtr->aliasEntryPtr = hPtr;
- Tcl_SetHashValue(hPtr, (ClientData) aliasPtr);
+ Tcl_SetHashValue(hPtr, aliasPtr);
/*
* Create the new command. We must do it after deleting any old command,
@@ -1521,11 +1616,11 @@ AliasCreate(interp, slaveInterp, masterInterp, namePtr, targetNamePtr,
* interp alias {} foo {} zop # Now recreate "foo"...
*/
- targetPtr = (Target *) ckalloc((unsigned) sizeof(Target));
+ targetPtr = ckalloc(sizeof(Target));
targetPtr->slaveCmd = aliasPtr->slaveCmd;
targetPtr->slaveInterp = slaveInterp;
- masterPtr = &((InterpInfo *) ((Interp*) masterInterp)->interpInfo)->master;
+ masterPtr = &((InterpInfo*) ((Interp*) masterInterp)->interpInfo)->master;
targetPtr->nextPtr = masterPtr->targetsPtr;
targetPtr->prevPtr = NULL;
if (masterPtr->targetsPtr != NULL) {
@@ -1558,10 +1653,10 @@ AliasCreate(interp, slaveInterp, masterInterp, namePtr, targetNamePtr,
*/
static int
-AliasDelete(interp, slaveInterp, namePtr)
- Tcl_Interp *interp; /* Interpreter for result & errors. */
- Tcl_Interp *slaveInterp; /* Interpreter containing alias. */
- Tcl_Obj *namePtr; /* Name of alias to delete. */
+AliasDelete(
+ Tcl_Interp *interp, /* Interpreter for result & errors. */
+ Tcl_Interp *slaveInterp, /* Interpreter containing alias. */
+ Tcl_Obj *namePtr) /* Name of alias to delete. */
{
Slave *slavePtr;
Alias *aliasPtr;
@@ -1574,13 +1669,15 @@ AliasDelete(interp, slaveInterp, namePtr)
*/
slavePtr = &((InterpInfo *) ((Interp *) slaveInterp)->interpInfo)->slave;
- hPtr = Tcl_FindHashEntry(&slavePtr->aliasTable, Tcl_GetString(namePtr));
+ hPtr = Tcl_FindHashEntry(&slavePtr->aliasTable, TclGetString(namePtr));
if (hPtr == NULL) {
- Tcl_AppendResult(interp, "alias \"", Tcl_GetString(namePtr),
- "\" not found", NULL);
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "alias \"%s\" not found", TclGetString(namePtr)));
+ Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ALIAS",
+ TclGetString(namePtr), NULL);
return TCL_ERROR;
}
- aliasPtr = (Alias *) Tcl_GetHashValue(hPtr);
+ aliasPtr = Tcl_GetHashValue(hPtr);
Tcl_DeleteCommandFromToken(slaveInterp, aliasPtr->slaveCmd);
return TCL_OK;
}
@@ -1604,10 +1701,10 @@ AliasDelete(interp, slaveInterp, namePtr)
*/
static int
-AliasDescribe(interp, slaveInterp, namePtr)
- Tcl_Interp *interp; /* Interpreter for result & errors. */
- Tcl_Interp *slaveInterp; /* Interpreter containing alias. */
- Tcl_Obj *namePtr; /* Name of alias to describe. */
+AliasDescribe(
+ Tcl_Interp *interp, /* Interpreter for result & errors. */
+ Tcl_Interp *slaveInterp, /* Interpreter containing alias. */
+ Tcl_Obj *namePtr) /* Name of alias to describe. */
{
Slave *slavePtr;
Tcl_HashEntry *hPtr;
@@ -1625,7 +1722,7 @@ AliasDescribe(interp, slaveInterp, namePtr)
if (hPtr == NULL) {
return TCL_OK;
}
- aliasPtr = (Alias *) Tcl_GetHashValue(hPtr);
+ aliasPtr = Tcl_GetHashValue(hPtr);
prefixPtr = Tcl_NewListObj(aliasPtr->objc, &aliasPtr->objPtr);
Tcl_SetObjResult(interp, prefixPtr);
return TCL_OK;
@@ -1648,9 +1745,9 @@ AliasDescribe(interp, slaveInterp, namePtr)
*/
static int
-AliasList(interp, slaveInterp)
- Tcl_Interp *interp; /* Interp for data return. */
- Tcl_Interp *slaveInterp; /* Interp whose aliases to compute. */
+AliasList(
+ Tcl_Interp *interp, /* Interp for data return. */
+ Tcl_Interp *slaveInterp) /* Interp whose aliases to compute. */
{
Tcl_HashEntry *entryPtr;
Tcl_HashSearch hashSearch;
@@ -1662,7 +1759,7 @@ AliasList(interp, slaveInterp)
entryPtr = Tcl_FirstHashEntry(&slavePtr->aliasTable, &hashSearch);
for ( ; entryPtr != NULL; entryPtr = Tcl_NextHashEntry(&hashSearch)) {
- aliasPtr = (Alias *) Tcl_GetHashValue(entryPtr);
+ aliasPtr = Tcl_GetHashValue(entryPtr);
Tcl_ListObjAppendElement(NULL, resultPtr, aliasPtr->token);
}
Tcl_SetObjResult(interp, resultPtr);
@@ -1674,9 +1771,9 @@ AliasList(interp, slaveInterp)
*
* AliasObjCmd --
*
- * This is the procedure that services invocations of aliases in a slave
+ * This is the function that services invocations of aliases in a slave
* interpreter. One such command exists for each alias. When invoked,
- * this procedure redirects the invocation to the target command in the
+ * this function redirects the invocation to the target command in the
* master interpreter as designated by the Alias record associated with
* this command.
*
@@ -1692,20 +1789,84 @@ AliasList(interp, slaveInterp)
*/
static int
-AliasObjCmd(clientData, interp, objc, objv)
- ClientData clientData; /* Alias record. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument vector. */
+AliasNRCmd(
+ ClientData clientData, /* Alias record. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument vector. */
+{
+ Interp *iPtr = (Interp *) interp;
+ Alias *aliasPtr = clientData;
+ int prefc, cmdc, i;
+ Tcl_Obj **prefv, **cmdv;
+ int isRootEnsemble = (iPtr->ensembleRewrite.sourceObjs == NULL);
+ Tcl_Obj *listPtr;
+ List *listRep;
+ int flags = TCL_EVAL_INVOKE;
+
+ /*
+ * Append the arguments to the command prefix and invoke the command in
+ * the target interp's global namespace.
+ */
+
+ prefc = aliasPtr->objc;
+ prefv = &aliasPtr->objPtr;
+ cmdc = prefc + objc - 1;
+
+ listPtr = Tcl_NewListObj(cmdc, NULL);
+ listRep = listPtr->internalRep.twoPtrValue.ptr1;
+ listRep->elemCount = cmdc;
+ cmdv = &listRep->elements;
+
+ prefv = &aliasPtr->objPtr;
+ memcpy(cmdv, prefv, (size_t) (prefc * sizeof(Tcl_Obj *)));
+ memcpy(cmdv+prefc, objv+1, (size_t) ((objc-1) * sizeof(Tcl_Obj *)));
+
+ for (i=0; i<cmdc; i++) {
+ Tcl_IncrRefCount(cmdv[i]);
+ }
+
+ /*
+ * Use the ensemble rewriting machinery to ensure correct error messages:
+ * only the source command should show, not the full target prefix.
+ */
+
+ if (isRootEnsemble) {
+ iPtr->ensembleRewrite.sourceObjs = objv;
+ iPtr->ensembleRewrite.numRemovedObjs = 1;
+ iPtr->ensembleRewrite.numInsertedObjs = prefc;
+ } else {
+ iPtr->ensembleRewrite.numInsertedObjs += prefc - 1;
+ }
+
+ /*
+ * We are sending a 0-refCount obj, do not need a callback: it will be
+ * cleaned up automatically. But we may need to clear the rootEnsemble
+ * stuff ...
+ */
+
+ if (isRootEnsemble) {
+ TclNRAddCallback(interp, TclClearRootEnsemble, NULL, NULL, NULL, NULL);
+ }
+ TclSkipTailcall(interp);
+ return Tcl_NREvalObj(interp, listPtr, flags);
+}
+
+static int
+AliasObjCmd(
+ ClientData clientData, /* Alias record. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument vector. */
{
#define ALIAS_CMDV_PREALLOC 10
- Tcl_Interp *targetInterp;
- Alias *aliasPtr;
+ Alias *aliasPtr = clientData;
+ Tcl_Interp *targetInterp = aliasPtr->targetInterp;
int result, prefc, cmdc, i;
Tcl_Obj **prefv, **cmdv;
Tcl_Obj *cmdArr[ALIAS_CMDV_PREALLOC];
- aliasPtr = (Alias *) clientData;
- targetInterp = aliasPtr->targetInterp;
+ Interp *tPtr = (Interp *) targetInterp;
+ int isRootEnsemble = (tPtr->ensembleRewrite.sourceObjs == NULL);
/*
* Append the arguments to the command prefix and invoke the command in
@@ -1718,34 +1879,74 @@ AliasObjCmd(clientData, interp, objc, objv)
if (cmdc <= ALIAS_CMDV_PREALLOC) {
cmdv = cmdArr;
} else {
- cmdv = (Tcl_Obj **) ckalloc((unsigned) (cmdc * sizeof(Tcl_Obj *)));
+ cmdv = TclStackAlloc(interp, cmdc * sizeof(Tcl_Obj *));
}
prefv = &aliasPtr->objPtr;
- memcpy((VOID *) cmdv, (VOID *) prefv,
- (size_t) (prefc * sizeof(Tcl_Obj *)));
- memcpy((VOID *) (cmdv+prefc), (VOID *) (objv+1),
- (size_t) ((objc-1) * sizeof(Tcl_Obj *)));
+ memcpy(cmdv, prefv, (size_t) (prefc * sizeof(Tcl_Obj *)));
+ memcpy(cmdv+prefc, objv+1, (size_t) ((objc-1) * sizeof(Tcl_Obj *)));
Tcl_ResetResult(targetInterp);
for (i=0; i<cmdc; i++) {
Tcl_IncrRefCount(cmdv[i]);
}
- if (targetInterp != interp) {
- Tcl_Preserve((ClientData) targetInterp);
- result = Tcl_EvalObjv(targetInterp, cmdc, cmdv, TCL_EVAL_INVOKE);
- TclTransferResult(targetInterp, result, interp);
- Tcl_Release((ClientData) targetInterp);
+
+ /*
+ * Use the ensemble rewriting machinery to ensure correct error messages:
+ * only the source command should show, not the full target prefix.
+ */
+
+ if (isRootEnsemble) {
+ tPtr->ensembleRewrite.sourceObjs = objv;
+ tPtr->ensembleRewrite.numRemovedObjs = 1;
+ tPtr->ensembleRewrite.numInsertedObjs = prefc;
} else {
- result = Tcl_EvalObjv(targetInterp, cmdc, cmdv, TCL_EVAL_INVOKE);
+ tPtr->ensembleRewrite.numInsertedObjs += prefc - 1;
+ }
+
+ /*
+ * Protect the target interpreter if it isn't the same as the source
+ * interpreter so that we can continue to work with it after the target
+ * command completes.
+ */
+
+ if (targetInterp != interp) {
+ Tcl_Preserve(targetInterp);
+ }
+
+ /*
+ * Execute the target command in the target interpreter.
+ */
+
+ result = Tcl_EvalObjv(targetInterp, cmdc, cmdv, TCL_EVAL_INVOKE);
+
+ /*
+ * Clean up the ensemble rewrite info if we set it in the first place.
+ */
+
+ if (isRootEnsemble) {
+ tPtr->ensembleRewrite.sourceObjs = NULL;
+ tPtr->ensembleRewrite.numRemovedObjs = 0;
+ tPtr->ensembleRewrite.numInsertedObjs = 0;
+ }
+
+ /*
+ * If it was a cross-interpreter alias, we need to transfer the result
+ * back to the source interpreter and release the lock we previously set
+ * on the target interpreter.
+ */
+
+ if (targetInterp != interp) {
+ Tcl_TransferResult(targetInterp, result, interp);
+ Tcl_Release(targetInterp);
}
+
for (i=0; i<cmdc; i++) {
Tcl_DecrRefCount(cmdv[i]);
}
-
if (cmdv != cmdArr) {
- ckfree((char *) cmdv);
+ TclStackFree(interp, cmdv);
}
return result;
#undef ALIAS_CMDV_PREALLOC
@@ -1770,16 +1971,14 @@ AliasObjCmd(clientData, interp, objc, objv)
*/
static void
-AliasObjCmdDeleteProc(clientData)
- ClientData clientData; /* The alias record for this alias. */
+AliasObjCmdDeleteProc(
+ ClientData clientData) /* The alias record for this alias. */
{
- Alias *aliasPtr;
+ Alias *aliasPtr = clientData;
Target *targetPtr;
int i;
Tcl_Obj **objv;
- aliasPtr = (Alias *) clientData;
-
Tcl_DecrRefCount(aliasPtr->token);
objv = &aliasPtr->objPtr;
for (i = 0; i < aliasPtr->objc; i++) {
@@ -1797,14 +1996,15 @@ AliasObjCmdDeleteProc(clientData)
} else {
Master *masterPtr = &((InterpInfo *) ((Interp *)
aliasPtr->targetInterp)->interpInfo)->master;
+
masterPtr->targetsPtr = targetPtr->nextPtr;
}
if (targetPtr->nextPtr != NULL) {
targetPtr->nextPtr->prevPtr = targetPtr->prevPtr;
}
- ckfree((char *) targetPtr);
- ckfree((char *) aliasPtr);
+ ckfree(targetPtr);
+ ckfree(aliasPtr);
}
/*
@@ -1831,10 +2031,10 @@ AliasObjCmdDeleteProc(clientData)
*/
Tcl_Interp *
-Tcl_CreateSlave(interp, slavePath, isSafe)
- Tcl_Interp *interp; /* Interpreter to start search at. */
- CONST char *slavePath; /* Name of slave to create. */
- int isSafe; /* Should new slave be "safe" ? */
+Tcl_CreateSlave(
+ Tcl_Interp *interp, /* Interpreter to start search at. */
+ const char *slavePath, /* Name of slave to create. */
+ int isSafe) /* Should new slave be "safe" ? */
{
Tcl_Obj *pathPtr;
Tcl_Interp *slaveInterp;
@@ -1863,9 +2063,9 @@ Tcl_CreateSlave(interp, slavePath, isSafe)
*/
Tcl_Interp *
-Tcl_GetSlave(interp, slavePath)
- Tcl_Interp *interp; /* Interpreter to start search from. */
- CONST char *slavePath; /* Path of slave to find. */
+Tcl_GetSlave(
+ Tcl_Interp *interp, /* Interpreter to start search from. */
+ const char *slavePath) /* Path of slave to find. */
{
Tcl_Obj *pathPtr;
Tcl_Interp *slaveInterp;
@@ -1894,12 +2094,12 @@ Tcl_GetSlave(interp, slavePath)
*/
Tcl_Interp *
-Tcl_GetMaster(interp)
- Tcl_Interp *interp; /* Get the master of this interpreter. */
+Tcl_GetMaster(
+ Tcl_Interp *interp) /* Get the master of this interpreter. */
{
Slave *slavePtr; /* Slave record of this interpreter. */
- if (interp == (Tcl_Interp *) NULL) {
+ if (interp == NULL) {
return NULL;
}
slavePtr = &((InterpInfo *) ((Interp *) interp)->interpInfo)->slave;
@@ -1909,6 +2109,72 @@ Tcl_GetMaster(interp)
/*
*----------------------------------------------------------------------
*
+ * TclSetSlaveCancelFlags --
+ *
+ * This function marks all slave interpreters belonging to a given
+ * interpreter as being canceled or not canceled, depending on the
+ * provided flags.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclSetSlaveCancelFlags(
+ Tcl_Interp *interp, /* Set cancel flags of this interpreter. */
+ int flags, /* Collection of OR-ed bits that control
+ * the cancellation of the script. Only
+ * TCL_CANCEL_UNWIND is currently
+ * supported. */
+ int force) /* Non-zero to ignore numLevels for the purpose
+ * of resetting the cancellation flags. */
+{
+ Master *masterPtr; /* Master record of given interpreter. */
+ Tcl_HashEntry *hPtr; /* Search element. */
+ Tcl_HashSearch hashSearch; /* Search variable. */
+ Slave *slavePtr; /* Slave record of interpreter. */
+ Interp *iPtr;
+
+ if (interp == NULL) {
+ return;
+ }
+
+ flags &= (CANCELED | TCL_CANCEL_UNWIND);
+
+ masterPtr = &((InterpInfo *) ((Interp *) interp)->interpInfo)->master;
+
+ hPtr = Tcl_FirstHashEntry(&masterPtr->slaveTable, &hashSearch);
+ for ( ; hPtr != NULL; hPtr = Tcl_NextHashEntry(&hashSearch)) {
+ slavePtr = Tcl_GetHashValue(hPtr);
+ iPtr = (Interp *) slavePtr->slaveInterp;
+
+ if (iPtr == NULL) {
+ continue;
+ }
+
+ if (flags == 0) {
+ TclResetCancellation((Tcl_Interp *) iPtr, force);
+ } else {
+ TclSetCancelFlags(iPtr, flags);
+ }
+
+ /*
+ * Now, recursively handle this for the slaves of this slave
+ * interpreter.
+ */
+
+ TclSetSlaveCancelFlags((Tcl_Interp *) iPtr, flags, force);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* Tcl_GetInterpPath --
*
* Sets the result of the asking interpreter to a proper Tcl list
@@ -1931,24 +2197,26 @@ Tcl_GetMaster(interp)
*/
int
-Tcl_GetInterpPath(askingInterp, targetInterp)
- Tcl_Interp *askingInterp; /* Interpreter to start search from. */
- Tcl_Interp *targetInterp; /* Interpreter to find. */
+Tcl_GetInterpPath(
+ Tcl_Interp *askingInterp, /* Interpreter to start search from. */
+ Tcl_Interp *targetInterp) /* Interpreter to find. */
{
InterpInfo *iiPtr;
if (targetInterp == askingInterp) {
+ Tcl_SetObjResult(askingInterp, Tcl_NewObj());
return TCL_OK;
}
if (targetInterp == NULL) {
return TCL_ERROR;
}
iiPtr = (InterpInfo *) ((Interp *) targetInterp)->interpInfo;
- if (Tcl_GetInterpPath(askingInterp, iiPtr->slave.masterInterp) != TCL_OK) {
+ if (Tcl_GetInterpPath(askingInterp, iiPtr->slave.masterInterp) != TCL_OK){
return TCL_ERROR;
}
- Tcl_AppendElement(askingInterp, Tcl_GetHashKey(&iiPtr->master.slaveTable,
- iiPtr->slave.slaveEntryPtr));
+ Tcl_ListObjAppendElement(NULL, Tcl_GetObjResult(askingInterp),
+ Tcl_NewStringObj(Tcl_GetHashKey(&iiPtr->master.slaveTable,
+ iiPtr->slave.slaveEntryPtr), -1));
return TCL_OK;
}
@@ -1970,9 +2238,9 @@ Tcl_GetInterpPath(askingInterp, targetInterp)
*/
static Tcl_Interp *
-GetInterp(interp, pathPtr)
- Tcl_Interp *interp; /* Interp. to start search from. */
- Tcl_Obj *pathPtr; /* List object containing name of interp. to
+GetInterp(
+ Tcl_Interp *interp, /* Interp. to start search from. */
+ Tcl_Obj *pathPtr) /* List object containing name of interp. to
* be found. */
{
Tcl_HashEntry *hPtr; /* Search element. */
@@ -1982,7 +2250,7 @@ GetInterp(interp, pathPtr)
Tcl_Interp *searchInterp; /* Interim storage for interp. to find. */
InterpInfo *masterInfoPtr;
- if (Tcl_ListObjGetElements(interp, pathPtr, &objc, &objv) != TCL_OK) {
+ if (TclListObjGetElements(interp, pathPtr, &objc, &objv) != TCL_OK) {
return NULL;
}
@@ -1990,20 +2258,22 @@ GetInterp(interp, pathPtr)
for (i = 0; i < objc; i++) {
masterInfoPtr = (InterpInfo *) ((Interp *) searchInterp)->interpInfo;
hPtr = Tcl_FindHashEntry(&masterInfoPtr->master.slaveTable,
- Tcl_GetString(objv[i]));
+ TclGetString(objv[i]));
if (hPtr == NULL) {
searchInterp = NULL;
break;
}
- slavePtr = (Slave *) Tcl_GetHashValue(hPtr);
+ slavePtr = Tcl_GetHashValue(hPtr);
searchInterp = slavePtr->slaveInterp;
if (searchInterp == NULL) {
break;
}
}
if (searchInterp == NULL) {
- Tcl_AppendResult(interp, "could not find interpreter \"",
- Tcl_GetString(pathPtr), "\"", (char *) NULL);
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "could not find interpreter \"%s\"", TclGetString(pathPtr)));
+ Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "INTERP",
+ TclGetString(pathPtr), NULL);
}
return searchInterp;
}
@@ -2027,24 +2297,26 @@ GetInterp(interp, pathPtr)
*/
static int
-SlaveBgerror(interp, slaveInterp, objc, objv)
- Tcl_Interp *interp; /* Interp for error return. */
- Tcl_Interp *slaveInterp; /* Interp in which limit is set/queried. */
- int objc; /* Set or Query. */
- Tcl_Obj *CONST objv[]; /* Argument strings. */
+SlaveBgerror(
+ Tcl_Interp *interp, /* Interp for error return. */
+ Tcl_Interp *slaveInterp, /* Interp in which limit is set/queried. */
+ int objc, /* Set or Query. */
+ Tcl_Obj *const objv[]) /* Argument strings. */
{
if (objc) {
int length;
- if (TCL_ERROR == Tcl_ListObjLength(NULL, objv[0], &length)
+ if (TCL_ERROR == TclListObjLength(NULL, objv[0], &length)
|| (length < 1)) {
- Tcl_AppendResult(interp, "cmdPrefix must be list of length >= 1",
- (char *) NULL);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "cmdPrefix must be list of length >= 1", -1));
+ Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP",
+ "BGERRORFORMAT", NULL);
return TCL_ERROR;
}
- TclSetBgErrorHandler(interp, objv[0]);
+ TclSetBgErrorHandler(slaveInterp, objv[0]);
}
- Tcl_SetObjResult(interp, TclGetBgErrorHandler(interp));
+ Tcl_SetObjResult(interp, TclGetBgErrorHandler(slaveInterp));
return TCL_OK;
}
@@ -2068,17 +2340,17 @@ SlaveBgerror(interp, slaveInterp, objc, objv)
*/
static Tcl_Interp *
-SlaveCreate(interp, pathPtr, safe)
- Tcl_Interp *interp; /* Interp. to start search from. */
- Tcl_Obj *pathPtr; /* Path (name) of slave to create. */
- int safe; /* Should we make it "safe"? */
+SlaveCreate(
+ Tcl_Interp *interp, /* Interp. to start search from. */
+ Tcl_Obj *pathPtr, /* Path (name) of slave to create. */
+ int safe) /* Should we make it "safe"? */
{
Tcl_Interp *masterInterp, *slaveInterp;
Slave *slavePtr;
InterpInfo *masterInfoPtr;
Tcl_HashEntry *hPtr;
- char *path;
- int new, objc;
+ const char *path;
+ int isNew, objc;
Tcl_Obj **objv;
if (Tcl_ListObjGetElements(interp, pathPtr, &objc, &objv) != TCL_OK) {
@@ -2086,7 +2358,7 @@ SlaveCreate(interp, pathPtr, safe)
}
if (objc < 2) {
masterInterp = interp;
- path = Tcl_GetString(pathPtr);
+ path = TclGetString(pathPtr);
} else {
Tcl_Obj *objPtr;
@@ -2096,17 +2368,19 @@ SlaveCreate(interp, pathPtr, safe)
if (masterInterp == NULL) {
return NULL;
}
- path = Tcl_GetString(objv[objc - 1]);
+ path = TclGetString(objv[objc - 1]);
}
if (safe == 0) {
safe = Tcl_IsSafe(masterInterp);
}
masterInfoPtr = (InterpInfo *) ((Interp *) masterInterp)->interpInfo;
- hPtr = Tcl_CreateHashEntry(&masterInfoPtr->master.slaveTable, path, &new);
- if (new == 0) {
- Tcl_AppendResult(interp, "interpreter named \"", path,
- "\" already exists, cannot create", (char *) NULL);
+ hPtr = Tcl_CreateHashEntry(&masterInfoPtr->master.slaveTable, path,
+ &isNew);
+ if (isNew == 0) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "interpreter named \"%s\" already exists, cannot create",
+ path));
return NULL;
}
@@ -2115,10 +2389,10 @@ SlaveCreate(interp, pathPtr, safe)
slavePtr->masterInterp = masterInterp;
slavePtr->slaveEntryPtr = hPtr;
slavePtr->slaveInterp = slaveInterp;
- slavePtr->interpCmd = Tcl_CreateObjCommand(masterInterp, path,
- SlaveObjCmd, (ClientData) slaveInterp, SlaveObjCmdDeleteProc);
+ slavePtr->interpCmd = Tcl_NRCreateCommand(masterInterp, path,
+ SlaveObjCmd, NRSlaveCmd, slaveInterp, SlaveObjCmdDeleteProc);
Tcl_InitHashTable(&slavePtr->aliasTable, TCL_STRING_KEYS);
- Tcl_SetHashValue(hPtr, (ClientData) slavePtr);
+ Tcl_SetHashValue(hPtr, slavePtr);
Tcl_SetVar(slaveInterp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
/*
@@ -2151,13 +2425,20 @@ SlaveCreate(interp, pathPtr, safe)
InheritLimitsFromMaster(slaveInterp, masterInterp);
+ /*
+ * The [clock] command presents a safe API, but uses unsafe features in
+ * its implementation. This means it has to be implemented in safe interps
+ * as an alias to a version in the (trusted) master.
+ */
+
if (safe) {
- Tcl_Obj* clockObj = Tcl_NewStringObj("clock", -1);
+ Tcl_Obj *clockObj;
int status;
+ TclNewLiteralStringObj(clockObj, "clock");
Tcl_IncrRefCount(clockObj);
status = AliasCreate(interp, slaveInterp, masterInterp, clockObj,
- clockObj, 0, (Tcl_Obj *CONST *) NULL);
+ clockObj, 0, NULL);
Tcl_DecrRefCount(clockObj);
if (status != TCL_OK) {
goto error2;
@@ -2166,9 +2447,9 @@ SlaveCreate(interp, pathPtr, safe)
return slaveInterp;
- error:
- TclTransferResult(slaveInterp, TCL_ERROR, interp);
- error2:
+ error:
+ Tcl_TransferResult(slaveInterp, TCL_ERROR, interp);
+ error2:
Tcl_DeleteInterp(slaveInterp);
return NULL;
@@ -2192,26 +2473,37 @@ SlaveCreate(interp, pathPtr, safe)
*/
static int
-SlaveObjCmd(clientData, interp, objc, objv)
- ClientData clientData; /* Slave interpreter. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+SlaveObjCmd(
+ ClientData clientData, /* Slave interpreter. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
- Tcl_Interp *slaveInterp;
+ return Tcl_NRCallObjProc(interp, NRSlaveCmd, clientData, objc, objv);
+}
+
+static int
+NRSlaveCmd(
+ ClientData clientData, /* Slave interpreter. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ Tcl_Interp *slaveInterp = clientData;
int index;
- static CONST char *options[] = {
- "alias", "aliases", "bgerror", "eval",
- "expose", "hide", "hidden", "issafe",
- "invokehidden", "limit", "marktrusted", "recursionlimit", NULL
+ static const char *const options[] = {
+ "alias", "aliases", "bgerror", "debug",
+ "eval", "expose", "hide", "hidden",
+ "issafe", "invokehidden", "limit", "marktrusted",
+ "recursionlimit", NULL
};
enum options {
- OPT_ALIAS, OPT_ALIASES, OPT_BGERROR, OPT_EVAL,
- OPT_EXPOSE, OPT_HIDE, OPT_HIDDEN, OPT_ISSAFE,
- OPT_INVOKEHIDDEN, OPT_LIMIT, OPT_MARKTRUSTED, OPT_RECLIMIT
+ OPT_ALIAS, OPT_ALIASES, OPT_BGERROR, OPT_DEBUG,
+ OPT_EVAL, OPT_EXPOSE, OPT_HIDE, OPT_HIDDEN,
+ OPT_ISSAFE, OPT_INVOKEHIDDEN, OPT_LIMIT, OPT_MARKTRUSTED,
+ OPT_RECLIMIT
};
- slaveInterp = (Tcl_Interp *) clientData;
if (slaveInterp == NULL) {
Tcl_Panic("SlaveObjCmd: interpreter has been deleted");
}
@@ -2231,7 +2523,7 @@ SlaveObjCmd(clientData, interp, objc, objv)
if (objc == 3) {
return AliasDescribe(interp, slaveInterp, objv[2]);
}
- if (Tcl_GetString(objv[3])[0] == '\0') {
+ if (TclGetString(objv[3])[0] == '\0') {
if (objc == 4) {
return AliasDelete(interp, slaveInterp, objv[2]);
}
@@ -2240,11 +2532,11 @@ SlaveObjCmd(clientData, interp, objc, objv)
objv[3], objc - 4, objv + 4);
}
}
- Tcl_WrongNumArgs(interp, 2, objv, "aliasName ?targetName? ?args..?");
+ Tcl_WrongNumArgs(interp, 2, objv, "aliasName ?targetName? ?arg ...?");
return TCL_ERROR;
case OPT_ALIASES:
if (objc != 2) {
- Tcl_WrongNumArgs(interp, 2, objv, (char *) NULL);
+ Tcl_WrongNumArgs(interp, 2, objv, NULL);
return TCL_ERROR;
}
return AliasList(interp, slaveInterp);
@@ -2254,6 +2546,16 @@ SlaveObjCmd(clientData, interp, objc, objv)
return TCL_ERROR;
}
return SlaveBgerror(interp, slaveInterp, objc - 2, objv + 2);
+ case OPT_DEBUG:
+ /*
+ * TIP #378
+ * Currently only -frame supported, otherwise ?-option ?value? ...?
+ */
+ if (objc > 4) {
+ Tcl_WrongNumArgs(interp, 2, objv, "?-frame ?bool??");
+ return TCL_ERROR;
+ }
+ return SlaveDebugCmd(interp, slaveInterp, objc - 2, objv + 2);
case OPT_EVAL:
if (objc < 3) {
Tcl_WrongNumArgs(interp, 2, objv, "arg ?arg ...?");
@@ -2280,17 +2582,16 @@ SlaveObjCmd(clientData, interp, objc, objv)
return SlaveHidden(interp, slaveInterp);
case OPT_ISSAFE:
if (objc != 2) {
- Tcl_WrongNumArgs(interp, 2, objv, (char *) NULL);
+ Tcl_WrongNumArgs(interp, 2, objv, NULL);
return TCL_ERROR;
}
Tcl_SetObjResult(interp, Tcl_NewBooleanObj(Tcl_IsSafe(slaveInterp)));
return TCL_OK;
case OPT_INVOKEHIDDEN: {
- int i, index;
- CONST char *namespaceName;
- static CONST char *hiddenOptions[] = {
- "-global", "-namespace", "--",
- NULL
+ int i;
+ const char *namespaceName;
+ static const char *const hiddenOptions[] = {
+ "-global", "-namespace", "--", NULL
};
enum hiddenOption {
OPT_GLOBAL, OPT_NAMESPACE, OPT_LAST
@@ -2298,7 +2599,7 @@ SlaveObjCmd(clientData, interp, objc, objv)
namespaceName = NULL;
for (i = 2; i < objc; i++) {
- if (Tcl_GetString(objv[i])[0] != '-') {
+ if (TclGetString(objv[i])[0] != '-') {
break;
}
if (Tcl_GetIndexFromObj(interp, objv[i], hiddenOptions, "option",
@@ -2311,7 +2612,7 @@ SlaveObjCmd(clientData, interp, objc, objv)
if (++i == objc) { /* There must be more arguments. */
break;
} else {
- namespaceName = Tcl_GetString(objv[i]);
+ namespaceName = TclGetString(objv[i]);
}
} else {
i++;
@@ -2327,7 +2628,7 @@ SlaveObjCmd(clientData, interp, objc, objv)
objc - i, objv + i);
}
case OPT_LIMIT: {
- static CONST char *limitTypes[] = {
+ static const char *const limitTypes[] = {
"commands", "time", NULL
};
enum LimitTypes {
@@ -2336,7 +2637,7 @@ SlaveObjCmd(clientData, interp, objc, objv)
int limitType;
if (objc < 3) {
- Tcl_WrongNumArgs(interp, 2, objv, "limitType ?options?");
+ Tcl_WrongNumArgs(interp, 2, objv, "limitType ?-option value ...?");
return TCL_ERROR;
}
if (Tcl_GetIndexFromObj(interp, objv[2], limitTypes, "limit type", 0,
@@ -2387,13 +2688,13 @@ SlaveObjCmd(clientData, interp, objc, objv)
*/
static void
-SlaveObjCmdDeleteProc(clientData)
- ClientData clientData; /* The SlaveRecord for the command. */
+SlaveObjCmdDeleteProc(
+ ClientData clientData) /* The SlaveRecord for the command. */
{
- Slave *slavePtr; /* Interim storage for Slave record. */
- Tcl_Interp *slaveInterp; /* And for a slave interp. */
+ Slave *slavePtr; /* Interim storage for Slave record. */
+ Tcl_Interp *slaveInterp = clientData;
+ /* And for a slave interp. */
- slaveInterp = (Tcl_Interp *) clientData;
slavePtr = &((InterpInfo *) ((Interp *) slaveInterp)->interpInfo)->slave;
/*
@@ -2404,7 +2705,7 @@ SlaveObjCmdDeleteProc(clientData)
/*
* Set to NULL so that when the InterpInfo is cleaned up in the slave it
- * does not try to delete the command causing all sorts of grief. See
+ * does not try to delete the command causing all sorts of grief. See
* SlaveRecordDeleteProc().
*/
@@ -2418,6 +2719,77 @@ SlaveObjCmdDeleteProc(clientData)
/*
*----------------------------------------------------------------------
*
+ * SlaveDebugCmd -- TIP #378
+ *
+ * Helper function to handle 'debug' command in a slave interpreter.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * May modify INTERP_DEBUG_FRAME flag in the slave.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+SlaveDebugCmd(
+ Tcl_Interp *interp, /* Interp for error return. */
+ Tcl_Interp *slaveInterp, /* The slave interpreter in which command
+ * will be evaluated. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ static const char *const debugTypes[] = {
+ "-frame", NULL
+ };
+ enum DebugTypes {
+ DEBUG_TYPE_FRAME
+ };
+ int debugType;
+ Interp *iPtr;
+ Tcl_Obj *resultPtr;
+
+ iPtr = (Interp *) slaveInterp;
+ if (objc == 0) {
+ resultPtr = Tcl_NewObj();
+ Tcl_ListObjAppendElement(NULL, resultPtr,
+ Tcl_NewStringObj("-frame", -1));
+ Tcl_ListObjAppendElement(NULL, resultPtr,
+ Tcl_NewBooleanObj(iPtr->flags & INTERP_DEBUG_FRAME));
+ Tcl_SetObjResult(interp, resultPtr);
+ } else {
+ if (Tcl_GetIndexFromObj(interp, objv[0], debugTypes, "debug option",
+ 0, &debugType) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (debugType == DEBUG_TYPE_FRAME) {
+ if (objc == 2) { /* set */
+ if (Tcl_GetBooleanFromObj(interp, objv[1], &debugType)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Quietly ignore attempts to disable interp debugging. This
+ * is a one-way switch as frame debug info is maintained in a
+ * stack that must be consistent once turned on.
+ */
+
+ if (debugType) {
+ iPtr->flags |= INTERP_DEBUG_FRAME;
+ }
+ }
+ Tcl_SetObjResult(interp,
+ Tcl_NewBooleanObj(iPtr->flags & INTERP_DEBUG_FRAME));
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* SlaveEval --
*
* Helper function to evaluate a command in a slave interpreter.
@@ -2432,30 +2804,49 @@ SlaveObjCmdDeleteProc(clientData)
*/
static int
-SlaveEval(interp, slaveInterp, objc, objv)
- Tcl_Interp *interp; /* Interp for error return. */
- Tcl_Interp *slaveInterp; /* The slave interpreter in which command
+SlaveEval(
+ Tcl_Interp *interp, /* Interp for error return. */
+ Tcl_Interp *slaveInterp, /* The slave interpreter in which command
* will be evaluated. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
int result;
- Tcl_Obj *objPtr;
- Tcl_Preserve((ClientData) slaveInterp);
+ /*
+ * TIP #285: If necessary, reset the cancellation flags for the slave
+ * interpreter now; otherwise, canceling a script in a master interpreter
+ * can result in a situation where a slave interpreter can no longer
+ * evaluate any scripts unless somebody calls the TclResetCancellation
+ * function for that particular Tcl_Interp.
+ */
+
+ TclSetSlaveCancelFlags(slaveInterp, 0, 0);
+
+ Tcl_Preserve(slaveInterp);
Tcl_AllowExceptions(slaveInterp);
if (objc == 1) {
- result = Tcl_EvalObjEx(slaveInterp, objv[0], 0);
+ /*
+ * TIP #280: Make actual argument location available to eval'd script.
+ */
+
+ Interp *iPtr = (Interp *) interp;
+ CmdFrame *invoker = iPtr->cmdFramePtr;
+ int word = 0;
+
+ TclArgumentGet(interp, objv[0], &invoker, &word);
+
+ result = TclEvalObjEx(slaveInterp, objv[0], 0, invoker, word);
} else {
- objPtr = Tcl_ConcatObj(objc, objv);
+ Tcl_Obj *objPtr = Tcl_ConcatObj(objc, objv);
Tcl_IncrRefCount(objPtr);
result = Tcl_EvalObjEx(slaveInterp, objPtr, 0);
Tcl_DecrRefCount(objPtr);
}
- TclTransferResult(slaveInterp, result, interp);
+ Tcl_TransferResult(slaveInterp, result, interp);
- Tcl_Release((ClientData) slaveInterp);
+ Tcl_Release(slaveInterp);
return result;
}
@@ -2477,25 +2868,27 @@ SlaveEval(interp, slaveInterp, objc, objv)
*/
static int
-SlaveExpose(interp, slaveInterp, objc, objv)
- Tcl_Interp *interp; /* Interp for error return. */
- Tcl_Interp *slaveInterp; /* Interp in which command will be exposed. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument strings. */
+SlaveExpose(
+ Tcl_Interp *interp, /* Interp for error return. */
+ Tcl_Interp *slaveInterp, /* Interp in which command will be exposed. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument strings. */
{
- char *name;
+ const char *name;
if (Tcl_IsSafe(interp)) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"permission denied: safe interpreter cannot expose commands",
-1));
+ Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP", "UNSAFE",
+ NULL);
return TCL_ERROR;
}
- name = Tcl_GetString(objv[(objc == 1) ? 0 : 1]);
- if (Tcl_ExposeCommand(slaveInterp, Tcl_GetString(objv[0]),
+ name = TclGetString(objv[(objc == 1) ? 0 : 1]);
+ if (Tcl_ExposeCommand(slaveInterp, TclGetString(objv[0]),
name) != TCL_OK) {
- TclTransferResult(slaveInterp, TCL_ERROR, interp);
+ Tcl_TransferResult(slaveInterp, TCL_ERROR, interp);
return TCL_ERROR;
}
return TCL_OK;
@@ -2519,28 +2912,31 @@ SlaveExpose(interp, slaveInterp, objc, objv)
*/
static int
-SlaveRecursionLimit(interp, slaveInterp, objc, objv)
- Tcl_Interp *interp; /* Interp for error return. */
- Tcl_Interp *slaveInterp; /* Interp in which limit is set/queried. */
- int objc; /* Set or Query. */
- Tcl_Obj *CONST objv[]; /* Argument strings. */
+SlaveRecursionLimit(
+ Tcl_Interp *interp, /* Interp for error return. */
+ Tcl_Interp *slaveInterp, /* Interp in which limit is set/queried. */
+ int objc, /* Set or Query. */
+ Tcl_Obj *const objv[]) /* Argument strings. */
{
Interp *iPtr;
int limit;
if (objc) {
if (Tcl_IsSafe(interp)) {
- Tcl_AppendResult(interp, "permission denied: ",
- "safe interpreters cannot change recursion limit",
- (char *) NULL);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj("permission denied: "
+ "safe interpreters cannot change recursion limit", -1));
+ Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP", "UNSAFE",
+ NULL);
return TCL_ERROR;
}
- if (Tcl_GetIntFromObj(interp, objv[0], &limit) == TCL_ERROR) {
+ if (TclGetIntFromObj(interp, objv[0], &limit) == TCL_ERROR) {
return TCL_ERROR;
}
if (limit <= 0) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"recursion limit must be > 0", -1));
+ Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP", "BADLIMIT",
+ NULL);
return TCL_ERROR;
}
Tcl_SetRecursionLimit(slaveInterp, limit);
@@ -2548,6 +2944,7 @@ SlaveRecursionLimit(interp, slaveInterp, objc, objv)
if (interp == slaveInterp && iPtr->numLevels > limit) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"falling back due to new recursion limit", -1));
+ Tcl_SetErrorCode(interp, "TCL", "RECURSION", NULL);
return TCL_ERROR;
}
Tcl_SetObjResult(interp, objv[0]);
@@ -2577,24 +2974,26 @@ SlaveRecursionLimit(interp, slaveInterp, objc, objv)
*/
static int
-SlaveHide(interp, slaveInterp, objc, objv)
- Tcl_Interp *interp; /* Interp for error return. */
- Tcl_Interp *slaveInterp; /* Interp in which command will be exposed. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument strings. */
+SlaveHide(
+ Tcl_Interp *interp, /* Interp for error return. */
+ Tcl_Interp *slaveInterp, /* Interp in which command will be exposed. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument strings. */
{
- char *name;
+ const char *name;
if (Tcl_IsSafe(interp)) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"permission denied: safe interpreter cannot hide commands",
-1));
+ Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP", "UNSAFE",
+ NULL);
return TCL_ERROR;
}
- name = Tcl_GetString(objv[(objc == 1) ? 0 : 1]);
- if (Tcl_HideCommand(slaveInterp, Tcl_GetString(objv[0]), name) != TCL_OK) {
- TclTransferResult(slaveInterp, TCL_ERROR, interp);
+ name = TclGetString(objv[(objc == 1) ? 0 : 1]);
+ if (Tcl_HideCommand(slaveInterp, TclGetString(objv[0]), name) != TCL_OK) {
+ Tcl_TransferResult(slaveInterp, TCL_ERROR, interp);
return TCL_ERROR;
}
return TCL_OK;
@@ -2618,9 +3017,9 @@ SlaveHide(interp, slaveInterp, objc, objv)
*/
static int
-SlaveHidden(interp, slaveInterp)
- Tcl_Interp *interp; /* Interp for data return. */
- Tcl_Interp *slaveInterp; /* Interp whose hidden commands to query. */
+SlaveHidden(
+ Tcl_Interp *interp, /* Interp for data return. */
+ Tcl_Interp *slaveInterp) /* Interp whose hidden commands to query. */
{
Tcl_Obj *listObjPtr = Tcl_NewObj(); /* Local object pointer. */
Tcl_HashTable *hTblPtr; /* For local searches. */
@@ -2628,9 +3027,9 @@ SlaveHidden(interp, slaveInterp)
Tcl_HashSearch hSearch; /* For local searches. */
hTblPtr = ((Interp *) slaveInterp)->hiddenCmdTablePtr;
- if (hTblPtr != (Tcl_HashTable *) NULL) {
+ if (hTblPtr != NULL) {
for (hPtr = Tcl_FirstHashEntry(hTblPtr, &hSearch);
- hPtr != (Tcl_HashEntry *) NULL;
+ hPtr != NULL;
hPtr = Tcl_NextHashEntry(&hSearch)) {
Tcl_ListObjAppendElement(NULL, listObjPtr,
Tcl_NewStringObj(Tcl_GetHashKey(hTblPtr, hPtr), -1));
@@ -2657,13 +3056,13 @@ SlaveHidden(interp, slaveInterp)
*/
static int
-SlaveInvokeHidden(interp, slaveInterp, namespaceName, objc, objv)
- Tcl_Interp *interp; /* Interp for error return. */
- Tcl_Interp *slaveInterp; /* The slave interpreter in which command will
+SlaveInvokeHidden(
+ Tcl_Interp *interp, /* Interp for error return. */
+ Tcl_Interp *slaveInterp, /* The slave interpreter in which command will
* be invoked. */
- CONST char *namespaceName; /* The namespace to use, if any. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+ const char *namespaceName, /* The namespace to use, if any. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
int result;
@@ -2671,31 +3070,53 @@ SlaveInvokeHidden(interp, slaveInterp, namespaceName, objc, objv)
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"not allowed to invoke hidden commands from safe interpreter",
-1));
+ Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP", "UNSAFE",
+ NULL);
return TCL_ERROR;
}
- Tcl_Preserve((ClientData) slaveInterp);
+ Tcl_Preserve(slaveInterp);
Tcl_AllowExceptions(slaveInterp);
if (namespaceName == NULL) {
- result = TclObjInvoke(slaveInterp, objc, objv, TCL_INVOKE_HIDDEN);
+ NRE_callback *rootPtr = TOP_CB(slaveInterp);
+
+ Tcl_NRAddCallback(interp, NRPostInvokeHidden, slaveInterp,
+ rootPtr, NULL, NULL);
+ return TclNRInvoke(NULL, slaveInterp, objc, objv);
} else {
Namespace *nsPtr, *dummy1, *dummy2;
- CONST char *tail;
+ const char *tail;
- result = TclGetNamespaceForQualName(slaveInterp, namespaceName,
- (Namespace *) NULL, TCL_FIND_ONLY_NS | TCL_GLOBAL_ONLY
- | TCL_LEAVE_ERR_MSG | TCL_CREATE_NS_IF_UNKNOWN, &nsPtr,
- &dummy1, &dummy2, &tail);
+ result = TclGetNamespaceForQualName(slaveInterp, namespaceName, NULL,
+ TCL_FIND_ONLY_NS | TCL_GLOBAL_ONLY | TCL_LEAVE_ERR_MSG
+ | TCL_CREATE_NS_IF_UNKNOWN, &nsPtr, &dummy1, &dummy2, &tail);
if (result == TCL_OK) {
result = TclObjInvokeNamespace(slaveInterp, objc, objv,
- (Tcl_Namespace *)nsPtr, TCL_INVOKE_HIDDEN);
+ (Tcl_Namespace *) nsPtr, TCL_INVOKE_HIDDEN);
}
}
- TclTransferResult(slaveInterp, result, interp);
+ Tcl_TransferResult(slaveInterp, result, interp);
+
+ Tcl_Release(slaveInterp);
+ return result;
+}
+
+static int
+NRPostInvokeHidden(
+ ClientData data[],
+ Tcl_Interp *interp,
+ int result)
+{
+ Tcl_Interp *slaveInterp = (Tcl_Interp *)data[0];
+ NRE_callback *rootPtr = (NRE_callback *)data[1];
- Tcl_Release((ClientData) slaveInterp);
+ if (interp != slaveInterp) {
+ result = TclNRRunCallbacks(slaveInterp, result, rootPtr);
+ Tcl_TransferResult(slaveInterp, result, interp);
+ }
+ Tcl_Release(slaveInterp);
return result;
}
@@ -2717,15 +3138,17 @@ SlaveInvokeHidden(interp, slaveInterp, namespaceName, objc, objv)
*/
static int
-SlaveMarkTrusted(interp, slaveInterp)
- Tcl_Interp *interp; /* Interp for error return. */
- Tcl_Interp *slaveInterp; /* The slave interpreter which will be marked
+SlaveMarkTrusted(
+ Tcl_Interp *interp, /* Interp for error return. */
+ Tcl_Interp *slaveInterp) /* The slave interpreter which will be marked
* trusted. */
{
if (Tcl_IsSafe(interp)) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"permission denied: safe interpreter cannot mark trusted",
-1));
+ Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP", "UNSAFE",
+ NULL);
return TCL_ERROR;
}
((Interp *) slaveInterp)->flags &= ~SAFE_INTERP;
@@ -2749,17 +3172,15 @@ SlaveMarkTrusted(interp, slaveInterp)
*/
int
-Tcl_IsSafe(interp)
- Tcl_Interp *interp; /* Is this interpreter "safe" ? */
+Tcl_IsSafe(
+ Tcl_Interp *interp) /* Is this interpreter "safe" ? */
{
- Interp *iPtr;
+ Interp *iPtr = (Interp *) interp;
- if (interp == (Tcl_Interp *) NULL) {
+ if (iPtr == NULL) {
return 0;
}
- iPtr = (Interp *) interp;
-
- return ( (iPtr->flags) & SAFE_INTERP ) ? 1 : 0 ;
+ return (iPtr->flags & SAFE_INTERP) ? 1 : 0;
}
/*
@@ -2782,14 +3203,31 @@ Tcl_IsSafe(interp)
*/
int
-Tcl_MakeSafe(interp)
- Tcl_Interp *interp; /* Interpreter to be made safe. */
+Tcl_MakeSafe(
+ Tcl_Interp *interp) /* Interpreter to be made safe. */
{
Tcl_Channel chan; /* Channel to remove from safe interpreter. */
Interp *iPtr = (Interp *) interp;
+ Tcl_Interp *master = ((InterpInfo*) iPtr->interpInfo)->slave.masterInterp;
TclHideUnsafeCommands(interp);
+ if (master != NULL) {
+ /*
+ * Alias these function implementations in the slave to those in the
+ * master; the overall implementations are safe, but they're normally
+ * defined by init.tcl which is not sourced by safe interpreters.
+ * Assume these functions all work. [Bug 2895741]
+ */
+
+ (void) Tcl_Eval(interp,
+ "namespace eval ::tcl {namespace eval mathfunc {}}");
+ (void) Tcl_CreateAlias(interp, "::tcl::mathfunc::min", master,
+ "::tcl::mathfunc::min", 0, NULL);
+ (void) Tcl_CreateAlias(interp, "::tcl::mathfunc::max", master,
+ "::tcl::mathfunc::max", 0, NULL);
+ }
+
iPtr->flags |= SAFE_INTERP;
/*
@@ -2832,15 +3270,15 @@ Tcl_MakeSafe(interp)
*/
chan = Tcl_GetStdChannel(TCL_STDIN);
- if (chan != (Tcl_Channel) NULL) {
+ if (chan != NULL) {
Tcl_UnregisterChannel(interp, chan);
}
chan = Tcl_GetStdChannel(TCL_STDOUT);
- if (chan != (Tcl_Channel) NULL) {
+ if (chan != NULL) {
Tcl_UnregisterChannel(interp, chan);
}
chan = Tcl_GetStdChannel(TCL_STDERR);
- if (chan != (Tcl_Channel) NULL) {
+ if (chan != NULL) {
Tcl_UnregisterChannel(interp, chan);
}
@@ -2862,12 +3300,15 @@ Tcl_MakeSafe(interp)
* Side effects:
* None.
*
+ * Notes:
+ * If you change this function, you MUST also update TclLimitExceeded() in
+ * tclInt.h.
*----------------------------------------------------------------------
*/
int
-Tcl_LimitExceeded(interp)
- Tcl_Interp *interp;
+Tcl_LimitExceeded(
+ Tcl_Interp *interp)
{
register Interp *iPtr = (Interp *) interp;
@@ -2889,12 +3330,16 @@ Tcl_LimitExceeded(interp)
* Side effects:
* Increments the limit granularity counter.
*
+ * Notes:
+ * If you change this function, you MUST also update TclLimitReady() in
+ * tclInt.h.
+ *
*----------------------------------------------------------------------
*/
int
-Tcl_LimitReady(interp)
- Tcl_Interp *interp;
+Tcl_LimitReady(
+ Tcl_Interp *interp)
{
register Interp *iPtr = (Interp *) interp;
@@ -2921,7 +3366,7 @@ Tcl_LimitReady(interp)
* Tcl_LimitCheck --
*
* Check all currently set limits in the interpreter (where permitted by
- * granularity). If a limit is exceeded, call its callbacks and, if the
+ * granularity). If a limit is exceeded, call its callbacks and, if the
* limit is still exceeded after the callbacks have run, make the
* interpreter generate an error that cannot be caught within the limited
* interpreter.
@@ -2939,8 +3384,8 @@ Tcl_LimitReady(interp)
*/
int
-Tcl_LimitCheck(interp)
- Tcl_Interp *interp;
+Tcl_LimitCheck(
+ Tcl_Interp *interp)
{
Interp *iPtr = (Interp *) interp;
register int ticker = iPtr->limit.granularityTicker;
@@ -2959,8 +3404,9 @@ Tcl_LimitCheck(interp)
if (iPtr->limit.cmdCount >= iPtr->cmdCount) {
iPtr->limit.exceeded &= ~TCL_LIMIT_COMMANDS;
} else if (iPtr->limit.exceeded & TCL_LIMIT_COMMANDS) {
- Tcl_ResetResult(interp);
- Tcl_AppendResult(interp, "command count limit exceeded", NULL);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "command count limit exceeded", -1));
+ Tcl_SetErrorCode(interp, "TCL", "LIMIT", "COMMANDS", NULL);
Tcl_Release(interp);
return TCL_ERROR;
}
@@ -2984,8 +3430,9 @@ Tcl_LimitCheck(interp)
iPtr->limit.time.usec >= now.usec)) {
iPtr->limit.exceeded &= ~TCL_LIMIT_TIME;
} else if (iPtr->limit.exceeded & TCL_LIMIT_TIME) {
- Tcl_ResetResult(interp);
- Tcl_AppendResult(interp, "time limit exceeded", NULL);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "time limit exceeded", -1));
+ Tcl_SetErrorCode(interp, "TCL", "LIMIT", "TIME", NULL);
Tcl_Release(interp);
return TCL_ERROR;
}
@@ -3015,9 +3462,9 @@ Tcl_LimitCheck(interp)
*/
static void
-RunLimitHandlers(handlerPtr, interp)
- LimitHandler *handlerPtr;
- Tcl_Interp *interp;
+RunLimitHandlers(
+ LimitHandler *handlerPtr,
+ Tcl_Interp *interp)
{
LimitHandler *nextPtr;
for (; handlerPtr!=NULL ; handlerPtr=nextPtr) {
@@ -3038,12 +3485,12 @@ RunLimitHandlers(handlerPtr, interp)
*/
handlerPtr->flags |= LIMIT_HANDLER_ACTIVE;
- (handlerPtr->handlerProc)(handlerPtr->clientData, interp);
+ handlerPtr->handlerProc(handlerPtr->clientData, interp);
handlerPtr->flags &= ~LIMIT_HANDLER_ACTIVE;
/*
* Rediscover this value; it might have changed during the processing
- * of a limit handler. We have to record it here because we might
+ * of a limit handler. We have to record it here because we might
* delete the structure below, and reading a value out of a deleted
* structure is unsafe (even if actually legal with some
* malloc()/free() implementations.)
@@ -3059,9 +3506,9 @@ RunLimitHandlers(handlerPtr, interp)
if (handlerPtr->flags & LIMIT_HANDLER_DELETED) {
if (handlerPtr->deleteProc != NULL) {
- (handlerPtr->deleteProc)(handlerPtr->clientData);
+ handlerPtr->deleteProc(handlerPtr->clientData);
}
- ckfree((char *) handlerPtr);
+ ckfree(handlerPtr);
}
}
}
@@ -3083,12 +3530,12 @@ RunLimitHandlers(handlerPtr, interp)
*/
void
-Tcl_LimitAddHandler(interp, type, handlerProc, clientData, deleteProc)
- Tcl_Interp *interp;
- int type;
- Tcl_LimitHandlerProc *handlerProc;
- ClientData clientData;
- Tcl_LimitHandlerDeleteProc *deleteProc;
+Tcl_LimitAddHandler(
+ Tcl_Interp *interp,
+ int type,
+ Tcl_LimitHandlerProc *handlerProc,
+ ClientData clientData,
+ Tcl_LimitHandlerDeleteProc *deleteProc)
{
Interp *iPtr = (Interp *) interp;
LimitHandler *handlerPtr;
@@ -3101,14 +3548,14 @@ Tcl_LimitAddHandler(interp, type, handlerProc, clientData, deleteProc)
deleteProc = (Tcl_LimitHandlerDeleteProc *) Tcl_Free;
}
if (deleteProc == (Tcl_LimitHandlerDeleteProc *) TCL_STATIC) {
- deleteProc = (Tcl_LimitHandlerDeleteProc *) NULL;
+ deleteProc = NULL;
}
/*
* Allocate a handler record.
*/
- handlerPtr = (LimitHandler *) ckalloc(sizeof(LimitHandler));
+ handlerPtr = ckalloc(sizeof(LimitHandler));
handlerPtr->flags = 0;
handlerPtr->handlerProc = handlerProc;
handlerPtr->clientData = clientData;
@@ -3152,7 +3599,7 @@ Tcl_LimitAddHandler(interp, type, handlerProc, clientData, deleteProc)
*
* Side effects:
* The handler is spliced out of the internal linked list for the limit,
- * and if not currently being invoked, deleted. Otherwise it is just
+ * and if not currently being invoked, deleted. Otherwise it is just
* marked for deletion and removed when the limit handler has finished
* executing.
*
@@ -3160,11 +3607,11 @@ Tcl_LimitAddHandler(interp, type, handlerProc, clientData, deleteProc)
*/
void
-Tcl_LimitRemoveHandler(interp, type, handlerProc, clientData)
- Tcl_Interp *interp;
- int type;
- Tcl_LimitHandlerProc *handlerProc;
- ClientData clientData;
+Tcl_LimitRemoveHandler(
+ Tcl_Interp *interp,
+ int type,
+ Tcl_LimitHandlerProc *handlerProc,
+ ClientData clientData)
{
Interp *iPtr = (Interp *) interp;
LimitHandler *handlerPtr;
@@ -3219,15 +3666,15 @@ Tcl_LimitRemoveHandler(interp, type, handlerProc, clientData)
/*
* If nothing is currently executing the handler, delete its client
- * data and the overall handler structure now. Otherwise it will all
+ * data and the overall handler structure now. Otherwise it will all
* go away when the handler returns.
*/
if (!(handlerPtr->flags & LIMIT_HANDLER_ACTIVE)) {
if (handlerPtr->deleteProc != NULL) {
- (handlerPtr->deleteProc)(handlerPtr->clientData);
+ handlerPtr->deleteProc(handlerPtr->clientData);
}
- ckfree((char *) handlerPtr);
+ ckfree(handlerPtr);
}
return;
}
@@ -3252,8 +3699,8 @@ Tcl_LimitRemoveHandler(interp, type, handlerProc, clientData)
*/
void
-TclLimitRemoveAllHandlers(interp)
- Tcl_Interp *interp;
+TclLimitRemoveAllHandlers(
+ Tcl_Interp *interp)
{
Interp *iPtr = (Interp *) interp;
LimitHandler *handlerPtr, *nextHandlerPtr;
@@ -3279,15 +3726,15 @@ TclLimitRemoveAllHandlers(interp)
/*
* If nothing is currently executing the handler, delete its client
- * data and the overall handler structure now. Otherwise it will all
+ * data and the overall handler structure now. Otherwise it will all
* go away when the handler returns.
*/
if (!(handlerPtr->flags & LIMIT_HANDLER_ACTIVE)) {
if (handlerPtr->deleteProc != NULL) {
- (handlerPtr->deleteProc)(handlerPtr->clientData);
+ handlerPtr->deleteProc(handlerPtr->clientData);
}
- ckfree((char *) handlerPtr);
+ ckfree(handlerPtr);
}
}
@@ -3312,15 +3759,15 @@ TclLimitRemoveAllHandlers(interp)
/*
* If nothing is currently executing the handler, delete its client
- * data and the overall handler structure now. Otherwise it will all
+ * data and the overall handler structure now. Otherwise it will all
* go away when the handler returns.
*/
if (!(handlerPtr->flags & LIMIT_HANDLER_ACTIVE)) {
if (handlerPtr->deleteProc != NULL) {
- (handlerPtr->deleteProc)(handlerPtr->clientData);
+ handlerPtr->deleteProc(handlerPtr->clientData);
}
- ckfree((char *) handlerPtr);
+ ckfree(handlerPtr);
}
}
@@ -3352,9 +3799,9 @@ TclLimitRemoveAllHandlers(interp)
*/
int
-Tcl_LimitTypeEnabled(interp, type)
- Tcl_Interp *interp;
- int type;
+Tcl_LimitTypeEnabled(
+ Tcl_Interp *interp,
+ int type)
{
Interp *iPtr = (Interp *) interp;
@@ -3379,9 +3826,9 @@ Tcl_LimitTypeEnabled(interp, type)
*/
int
-Tcl_LimitTypeExceeded(interp, type)
- Tcl_Interp *interp;
- int type;
+Tcl_LimitTypeExceeded(
+ Tcl_Interp *interp,
+ int type)
{
Interp *iPtr = (Interp *) interp;
@@ -3407,9 +3854,9 @@ Tcl_LimitTypeExceeded(interp, type)
*/
void
-Tcl_LimitTypeSet(interp, type)
- Tcl_Interp *interp;
- int type;
+Tcl_LimitTypeSet(
+ Tcl_Interp *interp,
+ int type)
{
Interp *iPtr = (Interp *) interp;
@@ -3427,7 +3874,7 @@ Tcl_LimitTypeSet(interp, type)
* None.
*
* Side effects:
- * The limit is disabled. If the limit was exceeded when this function
+ * The limit is disabled. If the limit was exceeded when this function
* was called, the limit will no longer be exceeded afterwards and the
* interpreter will be free to execute further scripts (assuming it isn't
* also deleted, of course).
@@ -3436,9 +3883,9 @@ Tcl_LimitTypeSet(interp, type)
*/
void
-Tcl_LimitTypeReset(interp, type)
- Tcl_Interp *interp;
- int type;
+Tcl_LimitTypeReset(
+ Tcl_Interp *interp,
+ int type)
{
Interp *iPtr = (Interp *) interp;
@@ -3457,7 +3904,7 @@ Tcl_LimitTypeReset(interp, type)
* None.
*
* Side effects:
- * Also resets whether the command limit was exceeded. This might permit
+ * Also resets whether the command limit was exceeded. This might permit
* a small amount of further execution in the interpreter even if the
* limit itself is theoretically exceeded.
*
@@ -3465,9 +3912,9 @@ Tcl_LimitTypeReset(interp, type)
*/
void
-Tcl_LimitSetCommands(interp, commandLimit)
- Tcl_Interp *interp;
- int commandLimit;
+Tcl_LimitSetCommands(
+ Tcl_Interp *interp,
+ int commandLimit)
{
Interp *iPtr = (Interp *) interp;
@@ -3493,8 +3940,8 @@ Tcl_LimitSetCommands(interp, commandLimit)
*/
int
-Tcl_LimitGetCommands(interp)
- Tcl_Interp *interp;
+Tcl_LimitGetCommands(
+ Tcl_Interp *interp)
{
Interp *iPtr = (Interp *) interp;
@@ -3513,7 +3960,7 @@ Tcl_LimitGetCommands(interp)
* None.
*
* Side effects:
- * Also resets whether the time limit was exceeded. This might permit a
+ * Also resets whether the time limit was exceeded. This might permit a
* small amount of further execution in the interpreter even if the limit
* itself is theoretically exceeded.
*
@@ -3521,9 +3968,9 @@ Tcl_LimitGetCommands(interp)
*/
void
-Tcl_LimitSetTime(interp, timeLimitPtr)
- Tcl_Interp *interp;
- Tcl_Time *timeLimitPtr;
+Tcl_LimitSetTime(
+ Tcl_Interp *interp,
+ Tcl_Time *timeLimitPtr)
{
Interp *iPtr = (Interp *) interp;
Tcl_Time nextMoment;
@@ -3539,8 +3986,8 @@ Tcl_LimitSetTime(interp, timeLimitPtr)
nextMoment.usec -= 1000000;
}
iPtr->limit.timeEvent = TclCreateAbsoluteTimerHandler(&nextMoment,
- TimeLimitCallback, (ClientData) interp);
- iPtr->limit.exceeded &= ~TCL_LIMIT_COMMANDS;
+ TimeLimitCallback, interp);
+ iPtr->limit.exceeded &= ~TCL_LIMIT_TIME;
}
/*
@@ -3562,18 +4009,30 @@ Tcl_LimitSetTime(interp, timeLimitPtr)
*/
static void
-TimeLimitCallback(clientData)
- ClientData clientData;
+TimeLimitCallback(
+ ClientData clientData)
{
- Tcl_Interp *interp = (Tcl_Interp *) clientData;
+ Tcl_Interp *interp = clientData;
+ Interp *iPtr = clientData;
+ int code;
+
+ Tcl_Preserve(interp);
+ iPtr->limit.timeEvent = NULL;
+
+ /*
+ * Must reset the granularity ticker here to force an immediate full
+ * check. This is OK because we're swallowing the cost in the overall cost
+ * of the event loop. [Bug 2891362]
+ */
- Tcl_Preserve((ClientData) interp);
- ((Interp *)interp)->limit.timeEvent = NULL;
- if (Tcl_LimitCheck(interp) != TCL_OK) {
+ iPtr->limit.granularityTicker = 0;
+
+ code = Tcl_LimitCheck(interp);
+ if (code != TCL_OK) {
Tcl_AddErrorInfo(interp, "\n (while waiting for event)");
- Tcl_BackgroundError(interp);
+ Tcl_BackgroundException(interp, code);
}
- Tcl_Release((ClientData) interp);
+ Tcl_Release(interp);
}
/*
@@ -3594,9 +4053,9 @@ TimeLimitCallback(clientData)
*/
void
-Tcl_LimitGetTime(interp, timeLimitPtr)
- Tcl_Interp *interp;
- Tcl_Time *timeLimitPtr;
+Tcl_LimitGetTime(
+ Tcl_Interp *interp,
+ Tcl_Time *timeLimitPtr)
{
Interp *iPtr = (Interp *) interp;
@@ -3621,10 +4080,10 @@ Tcl_LimitGetTime(interp, timeLimitPtr)
*/
void
-Tcl_LimitSetGranularity(interp, type, granularity)
- Tcl_Interp *interp;
- int type;
- int granularity;
+Tcl_LimitSetGranularity(
+ Tcl_Interp *interp,
+ int type,
+ int granularity)
{
Interp *iPtr = (Interp *) interp;
if (granularity < 1) {
@@ -3659,9 +4118,9 @@ Tcl_LimitSetGranularity(interp, type, granularity)
*/
int
-Tcl_LimitGetGranularity(interp, type)
- Tcl_Interp *interp;
- int type;
+Tcl_LimitGetGranularity(
+ Tcl_Interp *interp,
+ int type)
{
Interp *iPtr = (Interp *) interp;
@@ -3694,15 +4153,16 @@ Tcl_LimitGetGranularity(interp, type)
*/
static void
-DeleteScriptLimitCallback(clientData)
- ClientData clientData;
+DeleteScriptLimitCallback(
+ ClientData clientData)
{
- struct ScriptLimitCallback *limitCBPtr =
- (struct ScriptLimitCallback *) clientData;
+ ScriptLimitCallback *limitCBPtr = clientData;
Tcl_DecrRefCount(limitCBPtr->scriptObj);
- Tcl_DeleteHashEntry(limitCBPtr->entryPtr);
- ckfree((char *) limitCBPtr);
+ if (limitCBPtr->entryPtr != NULL) {
+ Tcl_DeleteHashEntry(limitCBPtr->entryPtr);
+ }
+ ckfree(limitCBPtr);
}
/*
@@ -3710,26 +4170,25 @@ DeleteScriptLimitCallback(clientData)
*
* CallScriptLimitCallback --
*
- * Invoke a script limit callback. Used to implement limit callbacks set
+ * Invoke a script limit callback. Used to implement limit callbacks set
* at the Tcl level on child interpreters.
*
* Results:
* None.
*
* Side effects:
- * Depends on the callback script. Errors are reported as background
+ * Depends on the callback script. Errors are reported as background
* errors.
*
*----------------------------------------------------------------------
*/
static void
-CallScriptLimitCallback(clientData, interp)
- ClientData clientData;
- Tcl_Interp *interp; /* Interpreter which failed the limit */
+CallScriptLimitCallback(
+ ClientData clientData,
+ Tcl_Interp *interp) /* Interpreter which failed the limit */
{
- struct ScriptLimitCallback *limitCBPtr =
- (struct ScriptLimitCallback *) clientData;
+ ScriptLimitCallback *limitCBPtr = clientData;
int code;
if (Tcl_InterpDeleted(limitCBPtr->interp)) {
@@ -3739,7 +4198,7 @@ CallScriptLimitCallback(clientData, interp)
code = Tcl_EvalObjEx(limitCBPtr->interp, limitCBPtr->scriptObj,
TCL_EVAL_GLOBAL);
if (code != TCL_OK && !Tcl_InterpDeleted(limitCBPtr->interp)) {
- Tcl_BackgroundError(limitCBPtr->interp);
+ Tcl_BackgroundException(limitCBPtr->interp, code);
}
Tcl_Release(limitCBPtr->interp);
}
@@ -3751,7 +4210,7 @@ CallScriptLimitCallback(clientData, interp)
*
* Install (or remove, if scriptObj is NULL) a limit callback script that
* is called when the target interpreter exceeds the type of limit
- * specified. Each interpreter may only have one callback set on another
+ * specified. Each interpreter may only have one callback set on another
* interpreter through this mechanism (though as many interpreters may be
* limited as the programmer chooses overall).
*
@@ -3766,16 +4225,16 @@ CallScriptLimitCallback(clientData, interp)
*/
static void
-SetScriptLimitCallback(interp, type, targetInterp, scriptObj)
- Tcl_Interp *interp;
- int type;
- Tcl_Interp *targetInterp;
- Tcl_Obj *scriptObj;
+SetScriptLimitCallback(
+ Tcl_Interp *interp,
+ int type,
+ Tcl_Interp *targetInterp,
+ Tcl_Obj *scriptObj)
{
- struct ScriptLimitCallback *limitCBPtr;
+ ScriptLimitCallback *limitCBPtr;
Tcl_HashEntry *hashPtr;
int isNew;
- struct ScriptLimitCallbackKey key;
+ ScriptLimitCallbackKey key;
Interp *iPtr = (Interp *) interp;
if (interp == targetInterp) {
@@ -3794,15 +4253,16 @@ SetScriptLimitCallback(interp, type, targetInterp, scriptObj)
return;
}
- hashPtr = Tcl_CreateHashEntry(&iPtr->limit.callbacks, (char *) &key,
+ hashPtr = Tcl_CreateHashEntry(&iPtr->limit.callbacks, &key,
&isNew);
if (!isNew) {
+ limitCBPtr = Tcl_GetHashValue(hashPtr);
+ limitCBPtr->entryPtr = NULL;
Tcl_LimitRemoveHandler(targetInterp, type, CallScriptLimitCallback,
- Tcl_GetHashValue(hashPtr));
+ limitCBPtr);
}
- limitCBPtr = (struct ScriptLimitCallback *)
- ckalloc(sizeof(struct ScriptLimitCallback));
+ limitCBPtr = ckalloc(sizeof(ScriptLimitCallback));
limitCBPtr->interp = interp;
limitCBPtr->scriptObj = scriptObj;
limitCBPtr->entryPtr = hashPtr;
@@ -3810,8 +4270,8 @@ SetScriptLimitCallback(interp, type, targetInterp, scriptObj)
Tcl_IncrRefCount(scriptObj);
Tcl_LimitAddHandler(targetInterp, type, CallScriptLimitCallback,
- (ClientData) limitCBPtr, DeleteScriptLimitCallback);
- Tcl_SetHashValue(hashPtr, (ClientData) limitCBPtr);
+ limitCBPtr, DeleteScriptLimitCallback);
+ Tcl_SetHashValue(hashPtr, limitCBPtr);
}
/*
@@ -3820,7 +4280,7 @@ SetScriptLimitCallback(interp, type, targetInterp, scriptObj)
* TclRemoveScriptLimitCallbacks --
*
* Remove all script-implemented limit callbacks that make calls back
- * into the given interpreter. This invoked as part of deleting an
+ * into the given interpreter. This invoked as part of deleting an
* interpreter.
*
* Results:
@@ -3833,17 +4293,17 @@ SetScriptLimitCallback(interp, type, targetInterp, scriptObj)
*/
void
-TclRemoveScriptLimitCallbacks(interp)
- Tcl_Interp *interp;
+TclRemoveScriptLimitCallbacks(
+ Tcl_Interp *interp)
{
Interp *iPtr = (Interp *) interp;
Tcl_HashEntry *hashPtr;
Tcl_HashSearch search;
- struct ScriptLimitCallbackKey *keyPtr;
+ ScriptLimitCallbackKey *keyPtr;
hashPtr = Tcl_FirstHashEntry(&iPtr->limit.callbacks, &search);
while (hashPtr != NULL) {
- keyPtr = (struct ScriptLimitCallbackKey *)
+ keyPtr = (ScriptLimitCallbackKey *)
Tcl_GetHashKey(&iPtr->limit.callbacks, hashPtr);
Tcl_LimitRemoveHandler(keyPtr->interp, keyPtr->type,
CallScriptLimitCallback, Tcl_GetHashValue(hashPtr));
@@ -3858,7 +4318,7 @@ TclRemoveScriptLimitCallbacks(interp)
* TclInitLimitSupport --
*
* Initialise all the parts of the interpreter relating to resource limit
- * management. This allows an interpreter to both have limits set upon
+ * management. This allows an interpreter to both have limits set upon
* itself and set limits upon other interpreters.
*
* Results:
@@ -3871,8 +4331,8 @@ TclRemoveScriptLimitCallbacks(interp)
*/
void
-TclInitLimitSupport(interp)
- Tcl_Interp *interp;
+TclInitLimitSupport(
+ Tcl_Interp *interp)
{
Interp *iPtr = (Interp *) interp;
@@ -3887,7 +4347,7 @@ TclInitLimitSupport(interp)
iPtr->limit.timeEvent = NULL;
iPtr->limit.timeGranularity = 10;
Tcl_InitHashTable(&iPtr->limit.callbacks,
- sizeof(struct ScriptLimitCallbackKey)/sizeof(int));
+ sizeof(ScriptLimitCallbackKey)/sizeof(int));
}
/*
@@ -3911,8 +4371,9 @@ TclInitLimitSupport(interp)
*/
static void
-InheritLimitsFromMaster(slaveInterp, masterInterp)
- Tcl_Interp *slaveInterp, *masterInterp;
+InheritLimitsFromMaster(
+ Tcl_Interp *slaveInterp,
+ Tcl_Interp *masterInterp)
{
Interp *slavePtr = (Interp *) slaveInterp;
Interp *masterPtr = (Interp *) masterInterp;
@@ -3936,7 +4397,7 @@ InheritLimitsFromMaster(slaveInterp, masterInterp)
* SlaveCommandLimitCmd --
*
* Implementation of the [interp limit $i commands] and [$i limit
- * commands] subcommands. See the interp manual page for a full
+ * commands] subcommands. See the interp manual page for a full
* description.
*
* Results:
@@ -3949,14 +4410,14 @@ InheritLimitsFromMaster(slaveInterp, masterInterp)
*/
static int
-SlaveCommandLimitCmd(interp, slaveInterp, consumedObjc, objc, objv)
- Tcl_Interp *interp; /* Current interpreter. */
- Tcl_Interp *slaveInterp; /* Interpreter being adjusted. */
- int consumedObjc; /* Number of args already parsed. */
- int objc; /* Total number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+SlaveCommandLimitCmd(
+ Tcl_Interp *interp, /* Current interpreter. */
+ Tcl_Interp *slaveInterp, /* Interpreter being adjusted. */
+ int consumedObjc, /* Number of args already parsed. */
+ int objc, /* Total number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
- static CONST char *options[] = {
+ static const char *const options[] = {
"-command", "-granularity", "-value", NULL
};
enum Options {
@@ -3964,10 +4425,24 @@ SlaveCommandLimitCmd(interp, slaveInterp, consumedObjc, objc, objv)
};
Interp *iPtr = (Interp *) interp;
int index;
- struct ScriptLimitCallbackKey key;
- struct ScriptLimitCallback *limitCBPtr;
+ ScriptLimitCallbackKey key;
+ ScriptLimitCallback *limitCBPtr;
Tcl_HashEntry *hPtr;
+ /*
+ * First, ensure that we are not reading or writing the calling
+ * interpreter's limits; it may only manipulate its children. Note that
+ * the low level API enforces this with Tcl_Panic, which we want to
+ * avoid. [Bug 3398794]
+ */
+
+ if (interp == slaveInterp) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "limits on current interpreter inaccessible", -1));
+ Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP", "SELF", NULL);
+ return TCL_ERROR;
+ }
+
if (objc == consumedObjc) {
Tcl_Obj *dictPtr;
@@ -3976,8 +4451,7 @@ SlaveCommandLimitCmd(interp, slaveInterp, consumedObjc, objc, objv)
key.type = TCL_LIMIT_COMMANDS;
hPtr = Tcl_FindHashEntry(&iPtr->limit.callbacks, (char *) &key);
if (hPtr != NULL) {
- limitCBPtr = (struct ScriptLimitCallback *)
- Tcl_GetHashValue(hPtr);
+ limitCBPtr = Tcl_GetHashValue(hPtr);
if (limitCBPtr != NULL && limitCBPtr->scriptObj != NULL) {
Tcl_DictObjPut(NULL, dictPtr, Tcl_NewStringObj(options[0], -1),
limitCBPtr->scriptObj);
@@ -4019,8 +4493,7 @@ SlaveCommandLimitCmd(interp, slaveInterp, consumedObjc, objc, objv)
key.type = TCL_LIMIT_COMMANDS;
hPtr = Tcl_FindHashEntry(&iPtr->limit.callbacks, (char *) &key);
if (hPtr != NULL) {
- limitCBPtr = (struct ScriptLimitCallback *)
- Tcl_GetHashValue(hPtr);
+ limitCBPtr = Tcl_GetHashValue(hPtr);
if (limitCBPtr != NULL && limitCBPtr->scriptObj != NULL) {
Tcl_SetObjResult(interp, limitCBPtr->scriptObj);
}
@@ -4039,8 +4512,7 @@ SlaveCommandLimitCmd(interp, slaveInterp, consumedObjc, objc, objv)
}
return TCL_OK;
} else if ((objc-consumedObjc) & 1 /* isOdd(objc-consumedObjc) */) {
- Tcl_WrongNumArgs(interp, consumedObjc, objv,
- "?-option? ?value? ?-option value ...?");
+ Tcl_WrongNumArgs(interp, consumedObjc, objv, "?-option value ...?");
return TCL_ERROR;
} else {
int i, scriptLen = 0, limitLen = 0;
@@ -4059,12 +4531,14 @@ SlaveCommandLimitCmd(interp, slaveInterp, consumedObjc, objc, objv)
break;
case OPT_GRAN:
granObj = objv[i+1];
- if (Tcl_GetIntFromObj(interp, objv[i+1], &gran) != TCL_OK) {
+ if (TclGetIntFromObj(interp, objv[i+1], &gran) != TCL_OK) {
return TCL_ERROR;
}
if (gran < 1) {
- Tcl_AppendResult(interp, "granularity must be at ",
- "least 1", NULL);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "granularity must be at least 1", -1));
+ Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP",
+ "BADVALUE", NULL);
return TCL_ERROR;
}
break;
@@ -4074,12 +4548,14 @@ SlaveCommandLimitCmd(interp, slaveInterp, consumedObjc, objc, objv)
if (limitLen == 0) {
break;
}
- if (Tcl_GetIntFromObj(interp, objv[i+1], &limit) != TCL_OK) {
+ if (TclGetIntFromObj(interp, objv[i+1], &limit) != TCL_OK) {
return TCL_ERROR;
}
if (limit < 0) {
- Tcl_AppendResult(interp, "command limit value must be at ",
- "least 0", NULL);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "command limit value must be at least 0", -1));
+ Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP",
+ "BADVALUE", NULL);
return TCL_ERROR;
}
break;
@@ -4110,7 +4586,7 @@ SlaveCommandLimitCmd(interp, slaveInterp, consumedObjc, objc, objv)
* SlaveTimeLimitCmd --
*
* Implementation of the [interp limit $i time] and [$i limit time]
- * subcommands. See the interp manual page for a full description.
+ * subcommands. See the interp manual page for a full description.
*
* Results:
* A standard Tcl result.
@@ -4122,14 +4598,14 @@ SlaveCommandLimitCmd(interp, slaveInterp, consumedObjc, objc, objv)
*/
static int
-SlaveTimeLimitCmd(interp, slaveInterp, consumedObjc, objc, objv)
- Tcl_Interp *interp; /* Current interpreter. */
- Tcl_Interp *slaveInterp; /* Interpreter being adjusted. */
- int consumedObjc; /* Number of args already parsed. */
- int objc; /* Total number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+SlaveTimeLimitCmd(
+ Tcl_Interp *interp, /* Current interpreter. */
+ Tcl_Interp *slaveInterp, /* Interpreter being adjusted. */
+ int consumedObjc, /* Number of args already parsed. */
+ int objc, /* Total number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
- static CONST char *options[] = {
+ static const char *const options[] = {
"-command", "-granularity", "-milliseconds", "-seconds", NULL
};
enum Options {
@@ -4137,10 +4613,24 @@ SlaveTimeLimitCmd(interp, slaveInterp, consumedObjc, objc, objv)
};
Interp *iPtr = (Interp *) interp;
int index;
- struct ScriptLimitCallbackKey key;
- struct ScriptLimitCallback *limitCBPtr;
+ ScriptLimitCallbackKey key;
+ ScriptLimitCallback *limitCBPtr;
Tcl_HashEntry *hPtr;
+ /*
+ * First, ensure that we are not reading or writing the calling
+ * interpreter's limits; it may only manipulate its children. Note that
+ * the low level API enforces this with Tcl_Panic, which we want to
+ * avoid. [Bug 3398794]
+ */
+
+ if (interp == slaveInterp) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "limits on current interpreter inaccessible", -1));
+ Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP", "SELF", NULL);
+ return TCL_ERROR;
+ }
+
if (objc == consumedObjc) {
Tcl_Obj *dictPtr;
@@ -4149,8 +4639,7 @@ SlaveTimeLimitCmd(interp, slaveInterp, consumedObjc, objc, objv)
key.type = TCL_LIMIT_TIME;
hPtr = Tcl_FindHashEntry(&iPtr->limit.callbacks, (char *) &key);
if (hPtr != NULL) {
- limitCBPtr = (struct ScriptLimitCallback *)
- Tcl_GetHashValue(hPtr);
+ limitCBPtr = Tcl_GetHashValue(hPtr);
if (limitCBPtr != NULL && limitCBPtr->scriptObj != NULL) {
Tcl_DictObjPut(NULL, dictPtr, Tcl_NewStringObj(options[0], -1),
limitCBPtr->scriptObj);
@@ -4198,8 +4687,7 @@ SlaveTimeLimitCmd(interp, slaveInterp, consumedObjc, objc, objv)
key.type = TCL_LIMIT_TIME;
hPtr = Tcl_FindHashEntry(&iPtr->limit.callbacks, (char *) &key);
if (hPtr != NULL) {
- limitCBPtr = (struct ScriptLimitCallback *)
- Tcl_GetHashValue(hPtr);
+ limitCBPtr = Tcl_GetHashValue(hPtr);
if (limitCBPtr != NULL && limitCBPtr->scriptObj != NULL) {
Tcl_SetObjResult(interp, limitCBPtr->scriptObj);
}
@@ -4229,8 +4717,7 @@ SlaveTimeLimitCmd(interp, slaveInterp, consumedObjc, objc, objv)
}
return TCL_OK;
} else if ((objc-consumedObjc) & 1 /* isOdd(objc-consumedObjc) */) {
- Tcl_WrongNumArgs(interp, consumedObjc, objv,
- "?-option? ?value? ?-option value ...?");
+ Tcl_WrongNumArgs(interp, consumedObjc, objv, "?-option value ...?");
return TCL_ERROR;
} else {
int i, scriptLen = 0, milliLen = 0, secLen = 0;
@@ -4253,12 +4740,14 @@ SlaveTimeLimitCmd(interp, slaveInterp, consumedObjc, objc, objv)
break;
case OPT_GRAN:
granObj = objv[i+1];
- if (Tcl_GetIntFromObj(interp, objv[i+1], &gran) != TCL_OK) {
+ if (TclGetIntFromObj(interp, objv[i+1], &gran) != TCL_OK) {
return TCL_ERROR;
}
if (gran < 1) {
- Tcl_AppendResult(interp, "granularity must be at ",
- "least 1", NULL);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "granularity must be at least 1", -1));
+ Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP",
+ "BADVALUE", NULL);
return TCL_ERROR;
}
break;
@@ -4268,15 +4757,17 @@ SlaveTimeLimitCmd(interp, slaveInterp, consumedObjc, objc, objv)
if (milliLen == 0) {
break;
}
- if (Tcl_GetIntFromObj(interp, objv[i+1], &tmp) != TCL_OK) {
+ if (TclGetIntFromObj(interp, objv[i+1], &tmp) != TCL_OK) {
return TCL_ERROR;
}
if (tmp < 0) {
- Tcl_AppendResult(interp, "milliseconds must be at least 0",
- NULL);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "milliseconds must be at least 0", -1));
+ Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP",
+ "BADVALUE", NULL);
return TCL_ERROR;
}
- limitMoment.usec = ((long)tmp)*1000;
+ limitMoment.usec = ((long) tmp)*1000;
break;
case OPT_SEC:
secObj = objv[i+1];
@@ -4284,12 +4775,14 @@ SlaveTimeLimitCmd(interp, slaveInterp, consumedObjc, objc, objv)
if (secLen == 0) {
break;
}
- if (Tcl_GetIntFromObj(interp, objv[i+1], &tmp) != TCL_OK) {
+ if (TclGetIntFromObj(interp, objv[i+1], &tmp) != TCL_OK) {
return TCL_ERROR;
}
if (tmp < 0) {
- Tcl_AppendResult(interp, "seconds must be at least 0",
- NULL);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "seconds must be at least 0", -1));
+ Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP",
+ "BADVALUE", NULL);
return TCL_ERROR;
}
limitMoment.sec = tmp;
@@ -4300,17 +4793,23 @@ SlaveTimeLimitCmd(interp, slaveInterp, consumedObjc, objc, objv)
if (milliObj != NULL) {
/*
* Setting -milliseconds but clearing -seconds, or resetting
- * -milliseconds but not resetting -seconds? Bad voodoo!
+ * -milliseconds but not resetting -seconds? Bad voodoo!
*/
if (secObj != NULL && secLen == 0 && milliLen > 0) {
- Tcl_AppendResult(interp, "may only set -milliseconds ",
- "if -seconds is not also being reset", NULL);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "may only set -milliseconds if -seconds is not "
+ "also being reset", -1));
+ Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP",
+ "BADUSAGE", NULL);
return TCL_ERROR;
}
if (milliLen == 0 && (secObj == NULL || secLen > 0)) {
- Tcl_AppendResult(interp, "may only reset -milliseconds ",
- "if -seconds is also being reset", NULL);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "may only reset -milliseconds if -seconds is "
+ "also being reset", -1));
+ Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP",
+ "BADUSAGE", NULL);
return TCL_ERROR;
}
}
@@ -4318,7 +4817,7 @@ SlaveTimeLimitCmd(interp, slaveInterp, consumedObjc, objc, objv)
if (milliLen > 0 || secLen > 0) {
/*
* Force usec to be in range [0..1000000), possibly
- * incrementing sec in the process. This makes it much easier
+ * incrementing sec in the process. This makes it much easier
* for people to write scripts that do small time increments.
*/