Tcl_NRCallObjProc calls nreProc using a new trampoline.
Tcl_NRCreateCommand, an alternative to Tcl_CreateObjCommand, resolves cmdName, which may contain namespace qualifiers, relative to the current namespace, creates a command by that name, and returns a token for the command which may be used in subsequent calls to Tcl_GetCommandName. Except for a few cases noted below any existing command by the same name is first deleted. If interp is in the process of being deleted Tcl_NRCreateCommand does not create any command, does not delete any command, and returns NULL.
Tcl_NREvalObj pushes a function that is like Tcl_EvalObjEx but consumes no space on the C stack.
Tcl_NREvalObjv pushes a function that is like Tcl_EvalObjv but consumes no space on the C stack.
Tcl_NRCmdSwap is like Tcl_NREvalObjv, but uses cmd, a token previously returned by Tcl_CreateObjCommand or Tcl_GetCommandFromObj, instead of resolving the first word of objv.
Tcl_NRExprObj pushes a function that evaluates objPtr as an expression in the same manner as Tcl_ExprObj but without consuming space on the C stack.
All of the functions return TCL_OK if the evaluation of the script, command, or expression has been scheduled successfully. Otherwise (for example if the command name cannot be resolved), they return TCL_ERROR and store a message as the interpreter's result.
Tcl_NRAddCallback pushes postProcPtr. The signature for Tcl_NRPostProc is:
typedef int
Tcl_NRPostProc(
ClientData data[],
Tcl_Interp *interp,
int result);
data is a pointer to an array containing data0 through data3. result is the value returned by the previous function implementing part the routine.
int
TheCmdOldObjProc(
ClientData clientData,
Tcl_Interp *interp,
int objc,
Tcl_Obj *const objv[])
{
int result;
Tcl_Obj *objPtr;
... preparation ...
result = Tcl_EvalObjEx(interp, objPtr, 0);
... postprocessing ...
return result;
}
Tcl_CreateObjCommand(interp, "theCommand",
TheCmdOldObjProc, clientData, TheCmdDeleteProc);
To avoid consuming space on the C stack, TheCmdOldObjProc is renamed to TheCmdNRObjProc and the postprocessing step is split into a separate function, TheCmdPostProc, which is pushed onto the function stack. Tcl_EvalObjEx is replaced with Tcl_NREvalObj, which uses a trampoline instead of consuming space on the C stack. A new version of TheCmdOldObjProc is just a a wrapper that uses Tcl_NRCallObjProc to call TheCmdNRObjProc:
int
TheCmdOldObjProc(
ClientData clientData,
Tcl_Interp *interp,
int objc,
Tcl_Obj *const objv[])
{
return Tcl_NRCallObjProc(interp, TheCmdNRObjProc,
clientData, objc, objv);
}
int
TheCmdNRObjProc
ClientData clientData,
Tcl_Interp *interp,
int objc,
Tcl_Obj *const objv[])
{
Tcl_Obj *objPtr;
... preparation ...
Tcl_NRAddCallback(interp, TheCmdPostProc,
data0, data1, data2, data3);
/* data0 .. data3 are up to four one-word items to
* pass to the postprocessing procedure */
return Tcl_NREvalObj(interp, objPtr, 0);
}
int
TheCmdNRPostProc(
ClientData data[],
Tcl_Interp *interp,
int result)
{
/* data[0] .. data[3] are the four words of data
* passed to Tcl_NRAddCallback */
... postprocessing ...
return result;
}
Any function comprising a routine can push other functions, making it possible implement looping and sequencing constructs using the function stack.
The objPtr argument to Tcl_NREvalObj and Tcl_NRExprObj should have a reference count of at least 1, and may have additional references taken to it during execution.
The resultObj argument to Tcl_NRExprObj should be an unshared object.
Use Tcl_NRAddCallback to schedule any required final decrementing of the reference counts of arguments to any of the other functions on this page, as with any other post-processing step in the non-recursive execution engine.
The