summaryrefslogtreecommitdiffstats
path: root/generic/tclBasic.c
diff options
context:
space:
mode:
Diffstat (limited to 'generic/tclBasic.c')
-rw-r--r--generic/tclBasic.c770
1 files changed, 382 insertions, 388 deletions
diff --git a/generic/tclBasic.c b/generic/tclBasic.c
index 273afea..c1bee01 100644
--- a/generic/tclBasic.c
+++ b/generic/tclBasic.c
@@ -16,7 +16,7 @@
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclBasic.c,v 1.310 2008/07/14 08:22:13 dkf Exp $
+ * RCS: @(#) $Id: tclBasic.c,v 1.311 2008/07/14 14:15:10 dkf Exp $
*/
#include "tclInt.h"
@@ -106,36 +106,28 @@ static int DTraceObjCmd(ClientData dummy, Tcl_Interp *interp, int objc,
MODULE_SCOPE const TclStubs * const tclConstStubsPtr;
-
/*
* Block for Tcl_EvalObjv helpers
*/
-static void TEOV_SwitchVarFrame(Tcl_Interp *interp);
-
-static void TEOV_PushExceptionHandlers(Tcl_Interp *interp, int objc,
- Tcl_Obj *const objv[], int flags);
-
-static inline Command *
- TEOV_LookupCmdFromObj(Tcl_Interp *interp, Tcl_Obj *namePtr,
- Namespace *lookupNsPtr);
-
-static int TEOV_NotFound(Tcl_Interp *interp, int objc,
- Tcl_Obj *const objv[], Namespace *lookupNsPtr);
-
-static int TEOV_RunEnterTraces(Tcl_Interp *interp, Command **cmdPtrPtr,
- int objc, Tcl_Obj *const objv[], Namespace *lookupNsPtr);
-
-static TclNR_PostProc TEOV_RestoreVarFrame;
-static TclNR_PostProc TEOV_RunLeaveTraces;
-static TclNR_PostProc TEOV_Exception;
-static TclNR_PostProc TEOV_Error;
-static TclNR_PostProc TEOEx_ListCallback;
-static TclNR_PostProc TEOEx_ByteCodeCallback;
-
-static int NRPostProcess(Tcl_Interp *interp, int result, int objc,
- Tcl_Obj *const objv[]);
-
+static void TEOV_SwitchVarFrame(Tcl_Interp *interp);
+static void TEOV_PushExceptionHandlers(Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[], int flags);
+static inline Command * TEOV_LookupCmdFromObj(Tcl_Interp *interp,
+ Tcl_Obj *namePtr, Namespace *lookupNsPtr);
+static int TEOV_NotFound(Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[], Namespace *lookupNsPtr);
+static int TEOV_RunEnterTraces(Tcl_Interp *interp,
+ Command **cmdPtrPtr, int objc,
+ Tcl_Obj *const objv[], Namespace *lookupNsPtr);
+static int NRPostProcess(Tcl_Interp *interp, int result,
+ int objc, Tcl_Obj *const objv[]);
+static TclNR_PostProc TEOV_RestoreVarFrame;
+static TclNR_PostProc TEOV_RunLeaveTraces;
+static TclNR_PostProc TEOV_Exception;
+static TclNR_PostProc TEOV_Error;
+static TclNR_PostProc TEOEx_ListCallback;
+static TclNR_PostProc TEOEx_ByteCodeCallback;
/*
* The following structure define the commands in the Tcl core.
@@ -254,7 +246,7 @@ static const CmdInfo builtInCmds[] = {
typedef struct {
const char *name; /* Name of the function. The full name is
- * "::tcl::mathfunc::<name>". */
+ * "::tcl::mathfunc::<name>". */
Tcl_ObjCmdProc *objCmdProc; /* Function that evaluates the function */
ClientData clientData; /* Client data for the function */
} BuiltinFuncDef;
@@ -356,17 +348,17 @@ static const OpCmdInfo mathOpCmds[] = {
{ NULL, NULL, NULL,
{0}, NULL}
};
-
/*
- * This is the script cancellation struct and hash table. The hash table
- * is used to keep track of the information necessary to process script
+ * This is the script cancellation struct and hash table. The hash table is
+ * used to keep track of the information necessary to process script
* cancellation requests, including the original interp, asynchronous handler
* tokens (created by Tcl_AsyncCreate), and the clientData and flags arguments
- * passed to Tcl_CancelEval on a per-interp basis. The cancelLock mutex is
- * used for protecting calls to Tcl_CancelEval as well as protecting access
- * to the hash table below.
+ * passed to Tcl_CancelEval on a per-interp basis. The cancelLock mutex is
+ * used for protecting calls to Tcl_CancelEval as well as protecting access to
+ * the hash table below.
*/
+
typedef struct {
Tcl_Interp *interp; /* Interp this struct belongs to */
Tcl_AsyncHandler async; /* Async handler token for script
@@ -3081,22 +3073,24 @@ CancelEvalProc(clientData, interp, code)
if (iPtr != NULL) {
/*
* Setting this flag will cause the script in progress to be
- * canceled as soon as possible. The core honors this flag
- * at all the necessary places to ensure script cancellation
- * is responsive. Extensions can check for this flag by
- * calling Tcl_Canceled and checking if TCL_ERROR is returned
- * or they can choose to ignore the script cancellation
- * flag and the associated functionality altogether.
+ * canceled as soon as possible. The core honors this flag at all
+ * the necessary places to ensure script cancellation is
+ * responsive. Extensions can check for this flag by calling
+ * Tcl_Canceled and checking if TCL_ERROR is returned or they can
+ * choose to ignore the script cancellation flag and the
+ * associated functionality altogether.
*/
+
iPtr->flags |= CANCELED;
/*
- * Currently, we only care about the TCL_CANCEL_UNWIND flag
- * from Tcl_CancelEval. We do not want to simply combine all
- * the flags from original Tcl_CancelEval call with the interp
- * flags here just in case the caller passed flags that might
- * cause behaviour unrelated to script cancellation.
+ * Currently, we only care about the TCL_CANCEL_UNWIND flag from
+ * Tcl_CancelEval. We do not want to simply combine all the flags
+ * from original Tcl_CancelEval call with the interp flags here
+ * just in case the caller passed flags that might cause behaviour
+ * unrelated to script cancellation.
*/
+
if (cancelInfo->flags & TCL_CANCEL_UNWIND) {
iPtr->flags |= TCL_CANCEL_UNWIND;
}
@@ -3145,18 +3139,18 @@ GetCommandSource(
objPtr = Tcl_NewListObj(objc, objv);
if (lookup && cfPtr) {
switch (cfPtr->type) {
- case TCL_LOCATION_EVAL:
- case TCL_LOCATION_SOURCE:
- command = cfPtr->cmd.str.cmd;
- numChars = cfPtr->cmd.str.len;
- break;
- case TCL_LOCATION_BC:
- case TCL_LOCATION_PREBC:
- command = TclGetSrcInfoForCmd(iPtr, &numChars);
- break;
- case TCL_LOCATION_EVAL_LIST:
- /* Got it already */
- break;
+ case TCL_LOCATION_EVAL:
+ case TCL_LOCATION_SOURCE:
+ command = cfPtr->cmd.str.cmd;
+ numChars = cfPtr->cmd.str.len;
+ break;
+ case TCL_LOCATION_BC:
+ case TCL_LOCATION_PREBC:
+ command = TclGetSrcInfoForCmd(iPtr, &numChars);
+ break;
+ case TCL_LOCATION_EVAL_LIST:
+ /* Got it already */
+ break;
}
if (command) {
obj2Ptr = Tcl_NewStringObj(command, numChars);
@@ -3620,7 +3614,7 @@ TclInterpReady(
if (TCL_OK != Tcl_Canceled(interp, TCL_LEAVE_ERR_MSG)) {
return TCL_ERROR;
}
-
+
/*
* Check depth of nested calls to Tcl_Eval: if this gets too large, it's
* probably because of an infinite loop somewhere.
@@ -3655,19 +3649,19 @@ TclInterpReady(
int
TclResetCancellation(
- Tcl_Interp *interp, int force)
+ Tcl_Interp *interp,
+ int force)
{
register Interp *iPtr = (Interp *) interp;
- if (iPtr != NULL) {
- if (force || (iPtr->numLevels == 0)) {
- iPtr->flags &= (~(CANCELED | TCL_CANCEL_UNWIND));
- }
-
- return TCL_OK;
- } else {
+ if (iPtr == NULL) {
return TCL_ERROR;
}
+
+ if (force || (iPtr->numLevels == 0)) {
+ iPtr->flags &= (~(CANCELED | TCL_CANCEL_UNWIND));
+ }
+ return TCL_OK;
}
/*
@@ -3676,18 +3670,18 @@ TclResetCancellation(
* Tcl_Canceled --
*
* Check if the script in progress has been canceled, i.e.,
- * Tcl_CancelEval was called for this interpreter or any of its
- * master interpreters.
+ * Tcl_CancelEval was called for this interpreter or any of its master
+ * interpreters.
*
* Results:
* The return value is TCL_OK if the script evaluation has not been
* canceled, TCL_ERROR otherwise.
*
- * If "flags" contains TCL_LEAVE_ERR_MSG, an error message is returned
- * in the interpreter's result object. Otherwise, the interpreter's
- * result object is left unchanged. If "flags" contains
- * TCL_CANCEL_UNWIND, TCL_ERROR will only be returned if the script
- * evaluation is being completely unwound.
+ * If "flags" contains TCL_LEAVE_ERR_MSG, an error message is returned in
+ * the interpreter's result object. Otherwise, the interpreter's result
+ * object is left unchanged. If "flags" contains TCL_CANCEL_UNWIND,
+ * TCL_ERROR will only be returned if the script evaluation is being
+ * completely unwound.
*
* Side effects:
* The CANCELED flag for the interp will be reset if it is set.
@@ -3705,19 +3699,20 @@ Tcl_Canceled(
int length;
/*
- * Traverse up the to the top-level interp, checking for the
- * CANCELED flag along the way. If any of the intervening
- * interps have the CANCELED flag set, the current script in
- * progress is considered to be canceled and we stop checking.
- * Otherwise, if any interp has the DELETED flag set we stop
- * checking.
+ * Traverse up the to the top-level interp, checking for the CANCELED flag
+ * along the way. If any of the intervening interps have the CANCELED flag
+ * set, the current script in progress is considered to be canceled and we
+ * stop checking. Otherwise, if any interp has the DELETED flag set we
+ * stop checking.
*/
+
for (; iPtr != NULL; iPtr = (Interp *) Tcl_GetMaster((Tcl_Interp *)iPtr)) {
/*
* Has the current script in progress for this interpreter been
- * canceled or is the stack being unwound due to the previous
- * script cancellation?
+ * canceled or is the stack being unwound due to the previous script
+ * cancellation?
*/
+
if ((iPtr->flags & CANCELED) || (iPtr->flags & TCL_CANCEL_UNWIND)) {
/*
* The CANCELED flag is a one-shot flag that is reset immediately
@@ -3726,26 +3721,33 @@ Tcl_Canceled(
* been canceled thereby allowing the evaluation stack for the
* interp to be fully unwound.
*/
+
iPtr->flags &= ~CANCELED;
/*
- * The CANCELED flag was detected and reset; however, if the caller
- * specified the TCL_CANCEL_UNWIND flag, we only return TCL_ERROR
- * (indicating that the script in progress has been canceled) if the
- * evaluation stack for the interp is being fully unwound.
+ * The CANCELED flag was detected and reset; however, if the
+ * caller specified the TCL_CANCEL_UNWIND flag, we only return
+ * TCL_ERROR (indicating that the script in progress has been
+ * canceled) if the evaluation stack for the interp is being fully
+ * unwound.
*/
- if (!(flags & TCL_CANCEL_UNWIND) || (iPtr->flags & TCL_CANCEL_UNWIND)) {
+
+ if (!(flags & TCL_CANCEL_UNWIND)
+ || (iPtr->flags & TCL_CANCEL_UNWIND)) {
/*
- * If the TCL_LEAVE_ERR_MSG flags bit is set, place an error in the
- * interp's result; otherwise, we leave it alone.
+ * If the TCL_LEAVE_ERR_MSG flags bit is set, place an error
+ * in the interp's result; otherwise, we leave it alone.
*/
+
if (flags & TCL_LEAVE_ERR_MSG) {
/*
- * Setup errorCode variables so that we can differentiate between
- * being canceled and unwound.
+ * Setup errorCode variables so that we can differentiate
+ * between being canceled and unwound.
*/
+
if (iPtr->asyncCancelMsg != NULL) {
- message = Tcl_GetStringFromObj(iPtr->asyncCancelMsg, &length);
+ message = Tcl_GetStringFromObj(iPtr->asyncCancelMsg,
+ &length);
} else {
length = 0;
}
@@ -3768,22 +3770,24 @@ Tcl_Canceled(
}
/*
- * Return TCL_ERROR to the caller (not necessarily just the Tcl core
- * itself) that indicates further processing of the script or command
- * in progress should halt gracefully and as soon as possible.
+ * Return TCL_ERROR to the caller (not necessarily just the
+ * Tcl core itself) that indicates further processing of the
+ * script or command in progress should halt gracefully and as
+ * soon as possible.
*/
+
return TCL_ERROR;
}
} else {
/*
- * FIXME: If this interpreter is being deleted we cannot continue to
- * traverse up the interp chain due to an issue with
+ * FIXME: If this interpreter is being deleted we cannot continue
+ * to traverse up the interp chain due to an issue with
* Tcl_GetMaster (really the slave interp bookkeeping) that
- * causes us to run off into a freed interp struct. Ideally,
- * this check would not be necessary because Tcl_GetMaster
- * would return NULL instead of a pointer to invalid (freed)
- * memory.
+ * causes us to run off into a freed interp struct. Ideally, this
+ * check would not be necessary because Tcl_GetMaster would
+ * return NULL instead of a pointer to invalid (freed) memory.
*/
+
if (iPtr->flags & DELETED) {
break;
}
@@ -3798,18 +3802,18 @@ Tcl_Canceled(
*
* Tcl_CancelEval --
*
- * This function schedules the cancellation of the current script in
- * the given interpreter.
+ * This function schedules the cancellation of the current script in the
+ * given interpreter.
*
* Results:
* The return value is a standard Tcl completion code such as TCL_OK or
- * TCL_ERROR. Since the interp may belong to a different thread, no
- * error message can be left in the interp's result.
+ * TCL_ERROR. Since the interp may belong to a different thread, no error
+ * message can be left in the interp's result.
*
* Side effects:
- * The script in progress in the specified interpreter will be
- * canceled with TCL_ERROR after asynchronous handlers are invoked at
- * the next Tcl_Canceled check.
+ * The script in progress in the specified interpreter will be canceled
+ * with TCL_ERROR after asynchronous handlers are invoked at the next
+ * Tcl_Canceled check.
*
*----------------------------------------------------------------------
*/
@@ -3818,8 +3822,8 @@ int
Tcl_CancelEval(
Tcl_Interp *interp, /* Interpreter in which to cancel the
* script. */
- Tcl_Obj *resultObjPtr, /* The script cancellation error message
- * or NULL for a default error message. */
+ Tcl_Obj *resultObjPtr, /* The script cancellation error message or
+ * NULL for a default error message. */
ClientData clientData, /* Passed to CancelEvalProc. */
int flags) /* Collection of OR-ed bits that control
* the cancellation of the script. Only
@@ -3828,64 +3832,66 @@ Tcl_CancelEval(
{
Tcl_HashEntry *hPtr;
CancelInfo *cancelInfo;
- int code;
+ int code = TCL_ERROR;
const char *result;
Tcl_MutexLock(&cancelLock);
- if (cancelTableInitialized == 1) {
- if (interp != NULL) {
- hPtr = Tcl_FindHashEntry(&cancelTable, (char *) interp);
-
- if (hPtr != NULL) {
- cancelInfo = (CancelInfo *) Tcl_GetHashValue(hPtr);
+ if (cancelTableInitialized != 1) {
+ /*
+ * No CancelInfo hash table (Tcl_CreateInterp has never been called?)
+ */
- if (cancelInfo != NULL) {
- /*
- * Populate information needed by the interpreter thread
- * to fulfill the cancellation request. Currently,
- * clientData is ignored. If the TCL_CANCEL_UNWIND flags
- * bit is set, the script in progress is not allowed to
- * catch the script cancellation because the evaluation
- * stack for the interp is completely unwound.
- */
- if (resultObjPtr != NULL) {
- result = Tcl_GetStringFromObj(resultObjPtr, &cancelInfo->length);
- cancelInfo->result = ckrealloc(cancelInfo->result,
- cancelInfo->length);
- memcpy((void *) cancelInfo->result, (void *) result,
- (size_t) cancelInfo->length);
- Tcl_DecrRefCount(resultObjPtr); /* discard their result object. */
- } else {
- cancelInfo->result = NULL;
- cancelInfo->length = 0;
- }
+ goto done;
+ }
+ if (interp != NULL) {
+ /*
+ * A valid interp must be supplied.
+ */
- cancelInfo->clientData = clientData;
- cancelInfo->flags = flags;
+ goto done;
+ }
+ hPtr = Tcl_FindHashEntry(&cancelTable, (char *) interp);
+ if (hPtr == NULL) {
+ /*
+ * No CancelInfo for this interp.
+ */
- Tcl_AsyncMark(cancelInfo->async);
- code = TCL_OK;
- } else {
- /* the CancelInfo for this interp is invalid */
- code = TCL_ERROR;
- }
- } else {
- /* no CancelInfo for this interp */
- code = TCL_ERROR;
- }
- } else {
- /* a valid interp must be supplied */
- code = TCL_ERROR;
- }
- } else {
+ goto done;
+ }
+ cancelInfo = Tcl_GetHashValue(hPtr);
+ if (cancelInfo == NULL) {
/*
- * No CancelInfo hash table (Tcl_CreateInterp
- * has never been called?)
+ * The CancelInfo for this interp is invalid.
*/
- code = TCL_ERROR;
+ goto done;
}
- Tcl_MutexUnlock(&cancelLock);
+ /*
+ * Populate information needed by the interpreter thread to fulfill the
+ * cancellation request. Currently, clientData is ignored. If the
+ * TCL_CANCEL_UNWIND flags bit is set, the script in progress is not
+ * allowed to catch the script cancellation because the evaluation stack
+ * for the interp is completely unwound.
+ */
+
+ if (resultObjPtr != NULL) {
+ result = Tcl_GetStringFromObj(resultObjPtr, &cancelInfo->length);
+ cancelInfo->result = ckrealloc(cancelInfo->result,
+ cancelInfo->length);
+ memcpy((void *) cancelInfo->result, (void *) result,
+ (size_t) cancelInfo->length);
+ Tcl_DecrRefCount(resultObjPtr); /* Discard their result object. */
+ } else {
+ cancelInfo->result = NULL;
+ cancelInfo->length = 0;
+ }
+ cancelInfo->clientData = clientData;
+ cancelInfo->flags = flags;
+ Tcl_AsyncMark(cancelInfo->async);
+ code = TCL_OK;
+
+ done:
+ Tcl_MutexUnlock(&cancelLock);
return code;
}
@@ -3923,10 +3929,8 @@ Tcl_EvalObjv(
Interp *iPtr = (Interp *) interp;
int result;
Namespace *lookupNsPtr;
-
TEOV_record *rootPtr = TOP_RECORD(iPtr);
TEOV_record *recordPtr;
-
Tcl_ObjCmdProc *objProc;
ClientData objClientData;
int tebcCall = TEBC_CALL(iPtr);
@@ -3984,7 +3988,6 @@ Tcl_EvalObjv(
iPtr->ensembleRewrite.sourceObjs = NULL;
}
-
/*
* Lookup the command
*/
@@ -4050,9 +4053,8 @@ Tcl_EvalObjv(
* into the TODO list, set the params as needed and restart at
* the top.
*
- * Note that I removed the DTRACE thing: I have not really thought
- * about where it really belongs, and do not really know what it does
- * either.
+ * Note that I removed the DTRACE thing: I have not really thought about
+ * where it really belongs, and do not really know what it does either.
*/
iPtr->cmdCount++;
@@ -4071,7 +4073,7 @@ Tcl_EvalObjv(
COMPLETE_RECORD(recordPtr);
cmdPtr->refCount++;
- objProcReentryPoint:
+ objProcReentryPoint:
/*
* If this is an NR-enabled command, find the real objProc.
*/
@@ -4090,124 +4092,122 @@ Tcl_EvalObjv(
*/
switch(recordPtr->type) {
- case TCL_NR_NO_TYPE: {
- break;
- }
- case TCL_NR_BC_TYPE: {
- tcl_nr_bc_type:
- if (USE_NR_TEBC && tebcCall) {
- /*
- * We were called by TEBC, and we need a bytecode to be
- * executed: just ask our caller to do that.
- * TEBC_CALL(iPtr) = TEBC_DO_EXEC = 0 is not really needed, as
- * it is already 0==TEBC_DO_EXEC
- */
-
- TEBC_CALL(iPtr) = TEBC_DO_EXEC;
- TEBC_DATA(iPtr) = recordPtr->data.codePtr;
- return TCL_OK;
- }
-
+ case TCL_NR_NO_TYPE:
+ break;
+ case TCL_NR_BC_TYPE:
+ tcl_nr_bc_type:
+ if (USE_NR_TEBC && tebcCall) {
/*
- * No TEBC atop - we'll just have to instantiate a new one and
- * do the callback on return.
+ * We were called by TEBC, and we need a bytecode to be executed:
+ * just ask our caller to do that.
+ * TEBC_CALL(iPtr) = TEBC_DO_EXEC = 0 is not really needed, as it
+ * is already 0==TEBC_DO_EXEC
*/
- result = TclExecuteByteCode(interp, recordPtr->data.codePtr);
- goto done;
+ TEBC_CALL(iPtr) = TEBC_DO_EXEC;
+ TEBC_DATA(iPtr) = recordPtr->data.codePtr;
+ return TCL_OK;
}
- case TCL_NR_TAILCALL_TYPE: {
- /*
- * Got to save this record, free the stack (ie, perform all
- * pending callbacks) and restore the record.
- */
- Tcl_Obj *tailObjPtr = recordPtr->data.obj.objPtr;
+ /*
+ * No TEBC atop - we'll just have to instantiate a new one and do the
+ * callback on return.
+ */
- result = TclEvalObjv_NR2(interp, result, rootPtr);
+ result = TclExecuteByteCode(interp, recordPtr->data.codePtr);
+ goto done;
+ case TCL_NR_TAILCALL_TYPE: {
+ /*
+ * Got to save this record, free the stack (i.e., perform all pending
+ * callbacks) and restore the record.
+ */
- if (result != TCL_OK) {
- goto done;
- }
- if (USE_NR_TEBC && tebcCall) {
- /*
- * We were called by TEBC, and we need it to drop a frame: let
- * him know.
- */
+ Tcl_Obj *tailObjPtr = recordPtr->data.obj.objPtr;
- TEBC_CALL(iPtr) = TEBC_DO_TAILCALL;
- TEBC_DATA(iPtr) = tailObjPtr;
- return TCL_OK;
- }
+ result = TclEvalObjv_NR2(interp, result, rootPtr);
+ if (result != TCL_OK) {
+ goto done;
+ }
+ if (USE_NR_TEBC && tebcCall) {
/*
- * ONLY supported if called from TEBC. Could do an 'uplevel 1'?
- * Run from here (as hinted below)? Mmhhh ... FIXME. Maybe
- * tailcalls SHOULD actually be bytecompiled (we know how to more
- * or less fake it when falling off TEBC)?
+ * We were called by TEBC, and we need it to drop a frame: let him
+ * know.
*/
- Tcl_Panic("tailcall called from a non-compiled command?");
- /* FALL THROUGH */
+ TEBC_CALL(iPtr) = TEBC_DO_TAILCALL;
+ TEBC_DATA(iPtr) = tailObjPtr;
+ return TCL_OK;
}
- case TCL_NR_CMD_TYPE: {
- /*
- * We got an unshared canonical list to eval , do it from here.
- */
- Tcl_Obj *objPtr = recordPtr->data.obj.objPtr;
- Tcl_Obj **elemPtr;
+ /*
+ * ONLY supported if called from TEBC. Could do an 'uplevel 1'? Run
+ * from here (as hinted below)? Mmhhh ... FIXME. Maybe tailcalls
+ * SHOULD actually be bytecompiled (we know how to more or less fake
+ * it when falling off TEBC)?
+ */
- flags = recordPtr->data.obj.flags;
- Tcl_ListObjGetElements(NULL, objPtr, &objc, &elemPtr);
- objv = elemPtr;
- if (objc == 0) {
- goto done;
- }
+ Tcl_Panic("tailcall called from a non-compiled command?");
+ /* FALL THROUGH */
+ }
+ case TCL_NR_CMD_TYPE: {
+ /*
+ * We got an unshared canonical list to eval , do it from here.
+ */
+
+ Tcl_Obj *objPtr = recordPtr->data.obj.objPtr;
+ Tcl_Obj **elemPtr;
+
+ flags = recordPtr->data.obj.flags;
+ Tcl_ListObjGetElements(NULL, objPtr, &objc, &elemPtr);
+ objv = elemPtr;
+ if (objc != 0) {
goto restartAtTop;
}
- case TCL_NR_SCRIPT_TYPE: {
- Tcl_Obj *objPtr = recordPtr->data.obj.objPtr;
-
- flags = recordPtr->data.obj.flags;
- if (USE_NR_TEBC && tebcCall) {
- result = TclNREvalObjEx(interp, objPtr, flags, NULL, 0);
- if (result == TCL_OK) {
- switch (recordPtr->type) {
- case TCL_NR_BC_TYPE:
- goto tcl_nr_bc_type;
- case TCL_NR_NO_TYPE:
- goto done;
- default:
- Tcl_Panic("TEOEx called from TEOV returns unexpected record type");
- }
+ goto done;
+ }
+ case TCL_NR_SCRIPT_TYPE: {
+ Tcl_Obj *objPtr = recordPtr->data.obj.objPtr;
+
+ flags = recordPtr->data.obj.flags;
+ if (USE_NR_TEBC && tebcCall) {
+ result = TclNREvalObjEx(interp, objPtr, flags, NULL, 0);
+ if (result == TCL_OK) {
+ switch (recordPtr->type) {
+ case TCL_NR_BC_TYPE:
+ goto tcl_nr_bc_type;
+ case TCL_NR_NO_TYPE:
+ goto done;
+ default:
+ Tcl_Panic("TEOEx called from TEOV returns unexpected record type");
}
- goto done;
- } else {
- result = TclEvalObjEx(interp, objPtr, flags, NULL, 0);
- goto done;
}
+ } else {
+ result = TclEvalObjEx(interp, objPtr, flags, NULL, 0);
}
- case TCL_NR_OBJPROC_TYPE: {
- /* This is a rewrite like ns-import does, without a new
- * cmdPtr or new reentrant call. FIXME: add the possibility of a
- * new callback (TclNR_ObjProc has that), and maybe also edition
- * of objc/objv? */
-
- objProc = recordPtr->data.objProc.objProc;
- objClientData = recordPtr->data.objProc.clientData;
- recordPtr->type = TCL_NR_NO_TYPE;
- goto objProcReentryPoint;
- }
- default: {
- Tcl_Panic("TEOV: unknown NR-request type %i!", recordPtr->type);
- }
+ goto done;
}
- done:
+ case TCL_NR_OBJPROC_TYPE:
+ /*
+ * This is a rewrite like ns-import does, without a new cmdPtr or new
+ * reentrant call. FIXME: add the possibility of a new callback
+ * (TclNR_ObjProc has that), and maybe also edition of objc/objv?
+ */
+
+ objProc = recordPtr->data.objProc.objProc;
+ objClientData = recordPtr->data.objProc.clientData;
+ recordPtr->type = TCL_NR_NO_TYPE;
+ goto objProcReentryPoint;
+ default:
+ Tcl_Panic("TEOV: unknown NR-request type %i!", recordPtr->type);
+ }
+
+ done:
return TclEvalObjv_NR2(interp, result, rootPtr);
}
-int TclEvalObjv_NR2(
+int
+TclEvalObjv_NR2(
Tcl_Interp *interp,
int result,
struct TEOV_record *rootPtr)
@@ -4268,11 +4268,9 @@ int TclEvalObjv_NR2(
if (TclAsyncReady(iPtr)) {
result = Tcl_AsyncInvoke(interp, result);
}
-
if (result == TCL_OK) {
result = Tcl_Canceled(interp, TCL_LEAVE_ERR_MSG);
}
-
if (result == TCL_OK && TclLimitReady(iPtr->limit)) {
result = Tcl_LimitCheck(interp);
}
@@ -4304,9 +4302,9 @@ TEOV_PushExceptionHandlers(
Interp *iPtr = (Interp *) interp;
/*
- * If any error processing is necessary, push the appropriate
- * records. Note that we have to push them in the inverse order: first
- * the one that has to run last.
+ * If any error processing is necessary, push the appropriate records.
+ * Note that we have to push them in the inverse order: first the one that
+ * has to run last.
*/
if (!(flags & TCL_EVAL_INVOKE)) {
@@ -4314,8 +4312,8 @@ TEOV_PushExceptionHandlers(
* Error messages
*/
- TclNR_AddCallback(interp, TEOV_Error, INT2PTR(objc), (ClientData) objv,
- NULL, NULL);
+ TclNR_AddCallback(interp, TEOV_Error, INT2PTR(objc),
+ (ClientData) objv, NULL,NULL);
}
if (iPtr->numLevels == 1) {
@@ -4334,11 +4332,12 @@ TEOV_SwitchVarFrame(
Interp *iPtr = (Interp *) interp;
/*
- * Change the varFrame to be the rootVarFrame, and push a record
- * to restore things at the end.
+ * Change the varFrame to be the rootVarFrame, and push a record to
+ * restore things at the end.
*/
- TclNR_AddCallback(interp, TEOV_RestoreVarFrame, iPtr->varFramePtr, NULL, NULL, NULL);
+ TclNR_AddCallback(interp, TEOV_RestoreVarFrame, iPtr->varFramePtr, NULL,
+ NULL, NULL);
iPtr->varFramePtr = iPtr->rootFramePtr;
}
@@ -4415,10 +4414,9 @@ TEOV_NotFound(
int i;
CallFrame *varFramePtr = iPtr->varFramePtr;
int result = TCL_OK;
- Namespace *currNsPtr = NULL; /* Used to check for and invoke any
- * registered unknown command handler
- * for the current namespace (TIP
- * 181). */
+ Namespace *currNsPtr = NULL;/* Used to check for and invoke any registered
+ * unknown command handler for the current
+ * namespace (TIP 181). */
int newObjc, handlerObjc;
Tcl_Obj **handlerObjv;
Namespace *savedNsPtr = NULL;
@@ -4432,8 +4430,8 @@ TEOV_NotFound(
}
/*
- * Check to see if the resolution namespace has lost its unknown
- * handler. If so, reset it to "::unknown".
+ * Check to see if the resolution namespace has lost its unknown handler.
+ * If so, reset it to "::unknown".
*/
if (currNsPtr->unknownHandlerPtr == NULL) {
@@ -4454,10 +4452,9 @@ TEOV_NotFound(
(int) sizeof(Tcl_Obj *) * newObjc);
/*
- * Copy command prefix from unknown handler and add on the real
- * command's full argument list. Note that we only use memcpy() once
- * because we have to increment the reference count of all the handler
- * arguments anyway.
+ * Copy command prefix from unknown handler and add on the real command's
+ * full argument list. Note that we only use memcpy() once because we have
+ * to increment the reference count of all the handler arguments anyway.
*/
for (i = 0; i < handlerObjc; ++i) {
@@ -4467,13 +4464,13 @@ TEOV_NotFound(
memcpy(newObjv+handlerObjc, objv, sizeof(Tcl_Obj *) * (unsigned)objc);
/*
- * Look up and invoke the handler (by recursive call to this
- * function). If there is no handler at all, instead of doing the
- * recursive call we just generate a generic error message; it would
- * be an infinite-recursion nightmare otherwise.
+ * Look up and invoke the handler (by recursive call to this function). If
+ * there is no handler at all, instead of doing the recursive call we just
+ * generate a generic error message; it would be an infinite-recursion
+ * nightmare otherwise.
*
- * In this case we worry a bit less about recursion for now, and call
- * the "blocking" interface.
+ * In this case we worry a bit less about recursion for now, and call the
+ * "blocking" interface.
*/
cmdPtr = TEOV_LookupCmdFromObj(interp, newObjv[0], lookupNsPtr);
@@ -4493,8 +4490,7 @@ TEOV_NotFound(
}
/*
- * Release any resources we locked and allocated during the handler
- * call.
+ * Release any resources we locked and allocated during the handler call.
*/
for (i = 0; i < handlerObjc; ++i) {
@@ -4525,10 +4521,10 @@ TEOV_RunEnterTraces(
command = Tcl_GetStringFromObj(commandPtr, &length);
/*
- * Call trace functions
+ * Call trace functions.
* Execute any command or execution traces. Note that we bump up the
- * command's reference count for the duration of the calling of the
- * traces so that the structure doesn't go away underneath our feet.
+ * command's reference count for the duration of the calling of the traces
+ * so that the structure doesn't go away underneath our feet.
*/
cmdPtr->refCount++;
@@ -4544,9 +4540,9 @@ TEOV_RunEnterTraces(
TclCleanupCommandMacro(cmdPtr);
/*
- * If the traces modified/deleted the command or any existing traces,
- * they will update the command's epoch. We need to lookup again, but do
- * not run enter traces on the newly found cmdPtr.
+ * If the traces modified/deleted the command or any existing traces, they
+ * will update the command's epoch. We need to lookup again, but do not
+ * run enter traces on the newly found cmdPtr.
*/
if (cmdEpoch != newEpoch) {
@@ -4556,8 +4552,7 @@ TEOV_RunEnterTraces(
if (cmdPtr) {
/*
- * Command was found: push a record to schedule
- * the leave traces.
+ * Command was found: push a record to schedule the leave traces.
*/
TclNR_AddCallback(interp, TEOV_RunLeaveTraces, INT2PTR(traceCode),
@@ -4601,18 +4596,17 @@ TEOV_RunLeaveTraces(
Tcl_DecrRefCount(commandPtr);
/*
- * As cmdPtr is set, TclEvalObjv_NR2 is about to reduce the
- * numlevels. Prevent that by resetting the cmdPtr field and dealing right
- * here with cmdPtr->refCount.
+ * As cmdPtr is set, TclEvalObjv_NR2 is about to reduce the numlevels.
+ * Prevent that by resetting the cmdPtr field and dealing right here with
+ * cmdPtr->refCount.
*/
TclCleanupCommandMacro(cmdPtr);
if (traceCode != TCL_OK) {
return traceCode;
- } else {
- return result;
}
+ return result;
}
static inline Command *
@@ -5348,34 +5342,32 @@ TclNREvalObjEx(
Tcl_IncrRefCount(objPtr);
/*
- * Pure List Optimization (no string representation). In this case, we
- * can safely use Tcl_EvalObjv instead and get an appreciable
- * improvement in execution speed. This is because it allows us to
- * avoid a setFromAny step that would just pack everything into a
- * string and back out again.
+ * Pure List Optimization (no string representation). In this case, we can
+ * safely use Tcl_EvalObjv instead and get an appreciable improvement in
+ * execution speed. This is because it allows us to avoid a setFromAny
+ * step that would just pack everything into a string and back out again.
*
* This restriction has been relaxed a bit by storing in lists whether
- * they are "canonical" or not (a canonical list being one that is
- * either pure or that has its string rep derived by
- * UpdateStringOfList from the internal rep).
+ * they are "canonical" or not (a canonical list being one that is either
+ * pure or that has its string rep derived by UpdateStringOfList from the
+ * internal rep).
*/
if (objPtr->typePtr == &tclListType) { /* is a list... */
List *listRepPtr = objPtr->internalRep.twoPtrValue.ptr1;
- if (objPtr->bytes == NULL || /* ...without a string rep */
- listRepPtr->canonicalFlag) {/* ...or that is canonical */
+ if (objPtr->bytes == NULL || /* ...without a string rep */
+ listRepPtr->canonicalFlag) { /* ...or that is canonical */
/*
- * TIP #280 Structures for tracking lines. As we know that
- * this is dynamic execution we ignore the invoker, even if
- * known.
+ * TIP #280 Structures for tracking lines. As we know that this is
+ * dynamic execution we ignore the invoker, even if known.
*/
int line, i;
char *w;
Tcl_Obj **elements, *copyPtr = TclListObjCopy(NULL, objPtr);
CmdFrame *eoFramePtr = (CmdFrame *)
- TclStackAlloc(interp, sizeof(CmdFrame));
+ TclStackAlloc(interp, sizeof(CmdFrame));
eoFramePtr->type = TCL_LOCATION_EVAL_LIST;
eoFramePtr->level = (iPtr->cmdFramePtr == NULL?
@@ -5420,9 +5412,9 @@ TclNREvalObjEx(
*/
ByteCode *newCodePtr;
- CallFrame *savedVarFramePtr = NULL;
- /* Saves old copy of iPtr->varFramePtr in
- * case TCL_EVAL_GLOBAL was set. */
+ CallFrame *savedVarFramePtr = NULL; /* Saves old copy of
+ * iPtr->varFramePtr in case
+ * TCL_EVAL_GLOBAL was set. */
if (flags & TCL_EVAL_GLOBAL) {
savedVarFramePtr = iPtr->varFramePtr;
@@ -5435,26 +5427,24 @@ TclNREvalObjEx(
if (newCodePtr) {
TEOV_record *recordPtr = TOP_RECORD(interp);
- recordPtr->type = TCL_NR_BC_TYPE;
+ recordPtr->type = TCL_NR_BC_TYPE;
recordPtr->data.codePtr = newCodePtr;
return TCL_OK;
- } else {
- return TCL_ERROR;
}
+ return TCL_ERROR;
}
/*
- * We're not supposed to use the compiler or byte-code interpreter.
- * Let Tcl_EvalEx evaluate the command directly (and probably more
- * slowly).
+ * We're not supposed to use the compiler or byte-code interpreter. Let
+ * Tcl_EvalEx evaluate the command directly (and probably more slowly).
*
- * TIP #280. Propagate context as much as we can. Especially if the
- * script to evaluate is a single literal it makes sense to look if
- * our context is one with absolute line numbers we can then track
- * into the literal itself too.
+ * TIP #280. Propagate context as much as we can. Especially if the script
+ * to evaluate is a single literal it makes sense to look if our context
+ * is one with absolute line numbers we can then track into the literal
+ * itself too.
*
- * See also tclCompile.c, TclInitCompileEnv, for the equivalent code
- * in the bytecode compiler.
+ * See also tclCompile.c, TclInitCompileEnv, for the equivalent code in
+ * the bytecode compiler.
*/
if (invoker == NULL) {
@@ -5467,21 +5457,20 @@ TclNREvalObjEx(
} else {
/*
* We have an invoker, describing the command asking for the
- * evaluation of a subordinate script. This script may originate
- * in a literal word, or from a variable, etc. Using the line
- * array we now check if we have good line information for the
- * relevant word. The type of context is relevant as well. In a
- * non-'source' context we don't have to try tracking lines.
+ * evaluation of a subordinate script. This script may originate in a
+ * literal word, or from a variable, etc. Using the line array we now
+ * check if we have good line information for the relevant word. The
+ * type of context is relevant as well. In a non-'source' context we
+ * don't have to try tracking lines.
*
- * First see if the word exists and is a literal. If not we go
- * through the easy dynamic branch. No need to perform more
- * complex invokations.
+ * First see if the word exists and is a literal. If not we go through
+ * the easy dynamic branch. No need to perform more complex
+ * invokations.
*/
if ((invoker->nline <= word) || (invoker->line[word] < 0)) {
/*
- * Dynamic script, or dynamic context, force our own
- * context.
+ * Dynamic script, or dynamic context, force our own context.
*/
script = Tcl_GetStringFromObj(objPtr, &numSrcBytes);
@@ -5494,7 +5483,7 @@ TclNREvalObjEx(
int pc = 0;
CmdFrame *ctxPtr = (CmdFrame *)
- TclStackAlloc(interp, sizeof(CmdFrame));
+ TclStackAlloc(interp, sizeof(CmdFrame));
*ctxPtr = *invoker;
if (invoker->type == TCL_LOCATION_BC) {
@@ -5570,7 +5559,9 @@ TEOEx_ByteCodeCallback(
}
iPtr->evalFlags = 0;
- /* Restore the callFrame if this was a TCL_EVAL_GLOBAL */
+ /*
+ * Restore the callFrame if this was a TCL_EVAL_GLOBAL.
+ */
if (savedVarFramePtr) {
iPtr->varFramePtr = savedVarFramePtr;
@@ -5591,7 +5582,10 @@ TEOEx_ListCallback(
CmdFrame *eoFramePtr = data[1];
Tcl_Obj *copyPtr = data[2];
- /* Remove the cmdFrame if it was added */
+ /*
+ * Remove the cmdFrame if it was added.
+ */
+
Tcl_DecrRefCount(copyPtr);
iPtr->cmdFramePtr = iPtr->cmdFramePtr->nextPtr;
ckfree((char *) eoFramePtr->line);
@@ -7415,39 +7409,38 @@ NRPostProcess(
if ((result == TCL_OK) && VALID_NEW_REQUEST(recordPtr)) {
switch(recordPtr->type) {
- case TCL_NR_BC_TYPE: {
- result = TclExecuteByteCode(interp, recordPtr->data.codePtr);
- break;
- }
- case TCL_NR_CMD_TYPE: {
- Tcl_Obj *objPtr = recordPtr->data.obj.objPtr;
- int flags = recordPtr->data.obj.flags;
- Tcl_Obj **objv;
- int objc;
-
- Tcl_ListObjGetElements(NULL, objPtr, &objc, &objv);
- result = Tcl_EvalObjv(interp, objc, objv, flags);
- break;
- }
- case TCL_NR_SCRIPT_TYPE: {
- Tcl_Obj *objPtr = recordPtr->data.obj.objPtr;
- int flags = recordPtr->data.obj.flags;
+ case TCL_NR_BC_TYPE:
+ result = TclExecuteByteCode(interp, recordPtr->data.codePtr);
+ break;
+ case TCL_NR_CMD_TYPE: {
+ Tcl_Obj *objPtr = recordPtr->data.obj.objPtr;
+ int flags = recordPtr->data.obj.flags;
+ Tcl_Obj **objv;
+ int objc;
- result = TclEvalObjEx(interp, objPtr, flags, NULL, 0);
- break;
- }
- case TCL_NR_OBJPROC_TYPE: {
- Tcl_ObjCmdProc *objProc = recordPtr->data.objProc.objProc;
- ClientData clientData = recordPtr->data.objProc.clientData;
+ Tcl_ListObjGetElements(NULL, objPtr, &objc, &objv);
+ result = Tcl_EvalObjv(interp, objc, objv, flags);
+ break;
+ }
+ case TCL_NR_SCRIPT_TYPE: {
+ Tcl_Obj *objPtr = recordPtr->data.obj.objPtr;
+ int flags = recordPtr->data.obj.flags;
- if (!objc) {
- Tcl_Panic("NRPostProcess: something is very wrong!");
- }
- result = (*objProc)(clientData, interp, objc, objv);
- break;
+ result = TclEvalObjEx(interp, objPtr, flags, NULL, 0);
+ break;
+ }
+ case TCL_NR_OBJPROC_TYPE: {
+ Tcl_ObjCmdProc *objProc = recordPtr->data.objProc.objProc;
+ ClientData clientData = recordPtr->data.objProc.clientData;
+
+ if (!objc) {
+ Tcl_Panic("NRPostProcess: something is very wrong!");
}
- default:
- Tcl_Panic("NRPostProcess: invalid record type");
+ result = (*objProc)(clientData, interp, objc, objv);
+ break;
+ }
+ default:
+ Tcl_Panic("NRPostProcess: invalid record type");
}
}
@@ -7492,7 +7485,8 @@ TclNR_CreateCommand(
* specified namespace; otherwise it is put in
* the global namespace. */
Tcl_ObjCmdProc *proc, /* Object-based function to associate with
- * name, provides direct access for direct calls */
+ * name, provides direct access for direct
+ * calls. */
Tcl_ObjCmdProc *nreProc, /* Object-based function to associate with
* name, provides NR implementation */
ClientData clientData, /* Arbitrary value to pass to object
@@ -7504,8 +7498,8 @@ TclNR_CreateCommand(
Command *cmdPtr;
- cmdPtr = (Command *) Tcl_CreateObjCommand(interp, cmdName, proc, clientData,
- deleteProc);
+ cmdPtr = (Command *) Tcl_CreateObjCommand(interp, cmdName, proc,
+ clientData, deleteProc);
cmdPtr->nreProc = nreProc;
return (Tcl_Command) cmdPtr;
}
@@ -7515,7 +7509,6 @@ TclNR_CreateCommand(
*
*/
-
/*
* TclNREvalCmd should only be called as an optimisation: when objPtr is known
* to be a canonical list that is not (and will not!) be shared
@@ -7523,8 +7516,8 @@ TclNR_CreateCommand(
int
TclNREvalCmd(
- Tcl_Interp * interp,
- Tcl_Obj * objPtr,
+ Tcl_Interp *interp,
+ Tcl_Obj *objPtr,
int flags)
{
TEOV_record *recordPtr = TOP_RECORD(interp);
@@ -7559,8 +7552,8 @@ TclNR_EvalObjv(
int
TclNR_EvalObj(
- Tcl_Interp * interp,
- Tcl_Obj * objPtr,
+ Tcl_Interp *interp,
+ Tcl_Obj *objPtr,
int flags)
{
TEOV_record *recordPtr = TOP_RECORD(interp);
@@ -7592,7 +7585,7 @@ TclNR_EvalObj(
int
TclNR_ObjProc(
- Tcl_Interp * interp,
+ Tcl_Interp *interp,
Tcl_ObjCmdProc *objProc,
ClientData clientData)
{
@@ -7631,9 +7624,9 @@ TclNR_ObjProc(
int
TclTailcallObjCmd(
ClientData clientData,
- Tcl_Interp * interp,
+ Tcl_Interp *interp,
int objc,
- Tcl_Obj *const objv[] )
+ Tcl_Obj *const objv[])
{
Interp *iPtr = (Interp *) interp;
TEOV_record *recordPtr = TOP_RECORD(interp);
@@ -7645,8 +7638,9 @@ TclTailcallObjCmd(
*/
if (!iPtr->varFramePtr->isProcCallFrame) {
- Tcl_SetResult(interp, "tailcall can only be called from a proc or lambda", TCL_STATIC);
- return TCL_ERROR;
+ Tcl_SetResult(interp,
+ "tailcall can only be called from a proc or lambda", TCL_STATIC);
+ return TCL_ERROR;
}
listPtr = Tcl_NewListObj(objc-1, objv+1);
@@ -7655,7 +7649,8 @@ TclTailcallObjCmd(
return TCL_OK;
}
-void TclNR_AddCallback(
+void
+TclNR_AddCallback(
Tcl_Interp *interp,
TclNR_PostProc *postProcPtr,
ClientData data0,
@@ -7694,15 +7689,14 @@ TclNRPushRecord(
}
void
-TclNRPopAndFreeRecord (
- Tcl_Interp * interp)
+TclNRPopAndFreeRecord(
+ Tcl_Interp *interp)
{
TEOV_record *recordPtr;
POP_RECORD(interp, recordPtr);
FREE_RECORD(interp, recordPtr);
}
-
/*
* Local Variables: