NAME¶
Tcl_NRCreateCommand, Tcl_NRCallObjProc, Tcl_NREvalObj, Tcl_NREvalObjv,
Tcl_NRCmdSwap, Tcl_NRExprObj, Tcl_NRAddCallback - Non-Recursive (stackless)
evaluation of Tcl scripts.
SYNOPSIS¶
#include <tcl.h>
Tcl_Command
Tcl_NRCreateCommand(interp, cmdName, proc, nreProc, clientData,
deleteProc)
int
Tcl_NRCallObjProc(interp, nreProc, clientData, objc, objv)
int
Tcl_NREvalObj(interp, objPtr, flags)
int
Tcl_NREvalObjv(interp, objc, objv, flags)
int
Tcl_NRCmdSwap(interp, cmd, objc, objv, flags)
int
Tcl_NRExprObj(interp, objPtr, resultPtr)
void
Tcl_NRAddCallback(interp, postProcPtr, data0, data1, data2, data3)
ARGUMENTS¶
- Tcl_Interp *interp (in)
- Interpreter in which to create or evaluate a command.
- char *cmdName (in)
- Name of a new command to create.
- Tcl_ObjCmdProc *proc (in)
- Implementation of a command that will be called whenever cmdName is
invoked as a command in the unoptimized way.
- Tcl_ObjCmdProc *nreProc (in)
- Implementation of a command that will be called whenever cmdName is
invoked and requested to conserve the C stack.
- ClientData clientData (in)
- Arbitrary one-word value that will be passed to proc,
nreProc, deleteProc and objProc.
- Tcl_CmdDeleteProc *deleteProc (in/out)
- Procedure to call before cmdName is deleted from the interpreter.
This procedure allows for command-specific cleanup. If deleteProc
is NULL, then no procedure is called before the command is
deleted.
- int objc (in)
- Count of parameters provided to the implementation of a command.
- Tcl_Obj **objv (in)
- Pointer to an array of Tcl values. Each value holds the value of a single
word in the command to execute.
- Tcl_Obj *objPtr (in)
- Pointer to a Tcl_Obj whose value is a script or expression to
execute.
- int flags (in)
- ORed combination of flag bits that specify additional options.
TCL_EVAL_GLOBAL is the only flag that is currently supported.
- Tcl_Command cmd (in)
- Token for a command that is to be used instead of the currently executing
command.
- Tcl_Obj *resultPtr (out)
- Pointer to an unshared Tcl_Obj where the result of expression evaluation
is written.
- Tcl_NRPostProc *postProcPtr (in)
- Pointer to a function that will be invoked when the command currently
executing in the interpreter designated by interp completes.
- ClientData data0 (in)
- ClientData data1 (in)
- ClientData data2 (in)
- ClientData data3 (in)
- data0 through data3 are four one-word values that will be
passed to the function designated by postProcPtr when it is
invoked.
DESCRIPTION¶
This series of C functions provides an interface whereby commands that are
implemented in C can be evaluated, and invoke Tcl commands scripts and
scripts, without consuming space on the C stack. The non-recursive evaluation
is done by installing a
trampoline, a small piece of code that invokes
a command or script, and then executes a series of callbacks when the command
or script returns.
The
Tcl_NRCreateCommand function creates a Tcl command in the interpreter
designated by
interp that is prepared to handle nonrecursive evaluation
with a trampoline. The
cmdName argument gives the name of the new
command. If
cmdName contains any namespace qualifiers, then the new
command is added to the specified namespace; otherwise, it is added to the
global namespace.
proc gives the procedure that will be called when the
interpreter wishes to evaluate the command in an unoptimized manner, and
nreProc is the procedure that will be called when the interpreter
wishes to evaluate the command using a trampoline.
deleteProc is a
function that will be called before the command is deleted from the
interpreter. When any of the three functions is invoked, it is passed the
clientData parameter.
Tcl_NRCreateCommand deletes any existing command
name already
associated with the interpreter (however see below for an exception where the
existing command is not deleted). It returns a token that may be used to refer
to the command in subsequent calls to
Tcl_GetCommandName. If
Tcl_NRCreateCommand is called for an interpreter that is in the process
of being deleted, then it does not create a new command, does not delete any
existing command of the same name, and returns NULL.
The
proc and
nreProc function are expected to conform to all the
rules set forth for the
proc argument to
Tcl_CreateObjCommand(3tcl) (
q.v.).
When a command that is written to cope with evaluation via trampoline is invoked
without a trampoline on the stack, it will usually respond to the invocation
by creating a trampoline and calling the trampoline-enabled implementation of
the same command. This call is done by means of
Tcl_NRCallObjProc. In
the call to
Tcl_NRCallObjProc, the
interp,
clientData,
objc and
objv parameters should be the same ones that were
passed to
proc. The
nreProc parameter should designate the
trampoline-enabled implementation of the command.
Tcl_NREvalObj arranges for the script contained in
objPtr to be
evaluated in the interpreter designated by
interp after the current
command (which must be trampoline-enabled) returns. It is the method by which
a command may invoke a script without consuming space on the C stack.
Similarly,
Tcl_NREvalObjv arranges to invoke a single Tcl command whose
words have already been separated and substituted. The
objc and
objv parameters give the words of the command to be evaluated when
execution reaches the trampoline.
Tcl_NRCmdSwap allows for trampoline evaluation of a command whose
resolution is already known. The
cmd parameter gives a
Tcl_Command token (returned from
Tcl_CreateObjCommand or
Tcl_GetCommandFromObj) identifying the command to be invoked in the
trampoline; this command must match the word in
objv[0]. The remaining
arguments are as for
Tcl_NREvalObjv.
Tcl_NREvalObj,
Tcl_NREvalObjv and
Tcl_NRCmdSwap all accept
a
flags parameter, which is an OR-ed-together set of bits to control
evaluation. At the present time, the only supported flag available to callers
is
TCL_EVAL_GLOBAL. If the
TCL_EVAL_GLOBAL flag is set, the
script or command is evaluated in the global namespace. If it is not set, it
is evaluated in the current namespace.
Tcl_NRExprObj arranges for the expression contained in
objPtr to
be evaluated in the interpreter designated by
interp after the current
command (which must be trampoline-enabled) returns. It is the method by which
a command may evaluate a Tcl expression without consuming space on the C
stack. The argument
resultPtr is a pointer to an unshared Tcl_Obj where
the result of expression evaluation is to be written. If expression evaluation
returns any code other than TCL_OK, the
resultPtr value is left
untouched.
All of the routines return
TCL_OK if command or expression invocation has
been scheduled successfully. If for any reason the scheduling cannot be
completed (for example, if the interpreter is unable to find the requested
command), they return
TCL_ERROR with an appropriate message left in the
interpreter's result.
Tcl_NRAddCallback arranges to have a C function called when the current
trampoline-enabled command in the Tcl interpreter designated by
interp
returns. The
postProcPtr argument is a pointer to the callback
function, which must have arguments and return value consistent with the
Tcl_NRPostProc data type:
typedef int
Tcl_NRPostProc(
ClientData data[],
Tcl_Interp *interp,
int result);
When the trampoline invokes the callback function, the
data parameter
will point to an array containing the four one-word quantities that were
passed to
Tcl_NRAddCallback in the
data0 through
data3
parameters. The Tcl interpreter will be designated by the
interp
parameter, and the
result parameter will contain the result (
TCL_OK,
TCL_ERROR,
TCL_RETURN,
TCL_BREAK or
TCL_CONTINUE) that was returned by the command evaluation. The callback
function is expected, in turn, either to return a
result to control
further evaluation.
Multiple
Tcl_NRAddCallback invocations may request multiple callbacks,
which may be to the same or different callback functions. If multiple
callbacks are requested, they are executed in last-in, first-out order, that
is, the most recently requested callback is executed first.
EXAMPLE¶
The usual pattern for Tcl commands that invoke other Tcl commands is something
like:
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 enable a command like this one for trampoline-based evaluation, it must be
split into three pieces:
- •
- A non-trampoline implementation, TheCmdNewObjProc, which will
simply create a trampoline and invoke the trampoline-based
implementation.
- •
- A trampoline-enabled implementation, TheCmdNRObjProc. This function
will perform the initialization, request that the trampoline call the
postprocessing routine after command evaluation, and finally, request that
the trampoline call the inner command.
- •
- A postprocessing routine, TheCmdPostProc. This function will
perform the postprocessing formerly done after the return from the inner
command in TheCmdObjProc.
The non-trampoline implementation is simple and stylized, containing a single
statement:
int
TheCmdNewObjProc(
ClientData clientData,
Tcl_Interp *interp,
int objc,
Tcl_Obj *const objv[])
{
return Tcl_NRCallObjProc(interp, TheCmdNRObjProc,
clientData, objc, objv);
}
The trampoline-enabled implementation requests postprocessing, and returns to
the trampoline requesting command evaluation.
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);
}
The postprocessing procedure does whatever the original command did upon return
from the inner evaluation.
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;
}
If
theCommand is a command that results in multiple commands or scripts
being evaluated, its postprocessing routine may schedule additional
postprocessing and then request another command evaluation by means of
Tcl_NREvalObj or one of the other evaluation routines. Looping and
sequencing constructs may be implemented in this way.
Finally, to install a trampoline-enabled command in the interpreter,
Tcl_NRCreateCommand is used in place of
Tcl_CreateObjCommand. It
accepts two command procedures instead of one. The first is for use when no
trampoline is yet on the stack, and the second is for use when there is
already a trampoline in place.
Tcl_NRCreateCommand(interp, "theCommand",
TheCmdNewObjProc, TheCmdNRObjProc, clientData,
TheCmdDeleteProc);
SEE ALSO¶
Tcl_CreateCommand(3tcl), Tcl_CreateObjCommand(3tcl), Tcl_EvalObjEx(3tcl),
Tcl_GetCommandFromObj(3tcl), Tcl_ExprObj(3tcl)
KEYWORDS¶
stackless, nonrecursive, execute, command, global, value, result, script
COPYRIGHT¶
Copyright (c) 2008 by Kevin B. Kenny