Tcl_CreateTrace(3)
okay so welcome to the Tcl_CreateTrace(3) page from the Tcl Library Procedures, bestie! π This one is literally about arranging for command execution to be traced, and it's giving main character energy. β¨
β¨ NAME β¨
The icons of this page are Tcl_CreateTrace, Tcl_CreateObjTrace, Tcl_CreateObjTrace2, and Tcl_DeleteTrace β together they arrange for command execution to be traced. periodt. π
πΈ SYNOPSIS πΈ
First, pull in the header like so, no cap:
#include <tcl.h>
Tcl_Trace
Tcl_CreateTrace(interp, level, proc, clientData)
Tcl_Trace
Tcl_CreateObjTrace(interp, level, flags, objProc, clientData, deleteProc)
Tcl_Trace
Tcl_CreateObjTrace2(interp, level, flags, objProc2, clientData, deleteProc)
Tcl_DeleteTrace(interp, trace)
π ARGUMENTS π
Here's the whole cast, no skips, fr fr:
Tcl_Interp *interp(in) β the interpreter that's holding the command you want to trace or untrace. It's literally the context, bestie.Tcl_Size level(in) β only commands at or below this nesting level will be traced unless0is specified.1means top-level commands only,2means top-level commands or those that are invoked as immediate consequences of executing top-level commands (procedure bodies, bracketed commands, etc.) and so on. A value of0means that commands at any level are traced. So0is the "trace everything" vibe. π₯int flags(in) β flags governing the trace execution. See below for details. The deets are coming, iykyk.Tcl_CmdObjTraceProc *objProc(in) β procedure to call for each command that is executed. See below for details of the calling sequence. Callback tea below. π«ΆTcl_CmdObjTraceProc2 *objProc2(in) β procedure to call for each command that is executed. See below for details of the calling sequence. Same energy, different name.Tcl_CmdTraceProc *proc(in) β procedure to call for each command that is executed. See below for details on the calling sequence.void *clientData(in) β arbitrary one-word value to pass toobjProc,objProc2orproc. It's your little carry-on for the callback. πTcl_CmdObjTraceDeleteProc *deleteProc(in) β procedure to call when the trace is deleted. See below for details of the calling sequence. ANULLpointer is permissible and results in no callback when the trace is deleted. SoNULLis valid, no cap. πTcl_Trace trace(in) β token for trace to be removed (return value from previous call toTcl_CreateTrace). Basically the receipt you got earlier. π§Ύ
π« DESCRIPTION π«
Okay bestie, so Tcl_CreateObjTrace is the whole setup for command tracing. The second you call it, objProc gets invoked before the Tcl interpreter calls any command procedure while it's evaluating commands in interp. And what does it hand back? A token for the trace, bestie β which you can pass straight to Tcl_DeleteTrace to yeet the trace away. And yes, you can have many traces active at once on the same interpreter. The more the merrier, honestly. π
objProc needs to have arguments and a result that match this type, Tcl_CmdObjTraceProc:
typedef int Tcl_CmdObjTraceProc(
void * clientData,
Tcl_Interp* interp,
int level,
const char *command,
Tcl_Command commandToken,
int objc,
Tcl_Obj *const objv[]);
And objProc2 has to match this type instead, Tcl_CmdObjTraceProc2:
typedef int Tcl_CmdObjTraceProc2(
void * clientData,
Tcl_Interp* interp,
Tcl_Size level,
const char *command,
Tcl_Command commandToken,
Tcl_Size objc,
Tcl_Obj *const objv[]);
Now let's vibe-check the parameters one by one, no skipping β¨
clientDataandinterpβ these are copies of the corresponding arguments you gave toTcl_CreateTrace.clientDatatypically points at some application-specific data structure that says what to do whenobjProcfires.levelβ the nesting level of the command. It's1for top-level commands passed toTcl_Evalby the application,2for the next-level commands passed toTcl_Evalas part of parsing or interpreting level-1 commands, and so on forever.commandβ points to a string containing the text of the command, before any argument substitution happens.commandTokenβ a Tcl command token that identifies the command about to be invoked. You can pass that token toTcl_GetCommandName,Tcl_GetCommandInfoFromToken, orTcl_SetCommandInfoFromTokento mess with the definition of the command. πobjcandobjvβ the final parameter count and parameter vector that will be passed to the command, with all substitutions already performed.
The objProc callback is expected to return a standard Tcl status return code. If that code is TCL_OK (the normal case, the everyday slay), the Tcl interpreter will invoke the command. Any other return code is treated as if the command itself returned that status, and the command is not invoked. So like, no command for you. π
β οΈ TheobjProccallback must not modifyobjvin any way. Not even a little. Hands off.
Tracing only happens for commands at a nesting level less than or equal to the level parameter β meaning the level parameter passed to objProc will always be less than or equal to the level parameter you gave to Tcl_CreateTrace.
Now the part nobody loves but everybody needs: performance. Tracing has a significant effect on runtime performance, because it makes the bytecode compiler refrain from generating in-line code for Tcl commands like if and while, all so they can be traced. If you don't actually need traces on the built-in commands, you can set the flags parameter to the constant value TCL_ALLOW_INLINE_COMPILATION. In that case, traces on built-in commands may or may not result in trace callbacks, depending on the state of the interpreter β but run-time performance will improve significantly. (This functionality is desirable, for example, when you're using Tcl_CreateObjTrace to implement an execution time profiler. Bestie said optimization π«Ά)
Calls to objProc get made by the Tcl parser immediately before it calls the command procedure for the command (cmdProc). This happens after argument parsing and substitution, so tracing for substituted commands happens before the tracing of the commands containing those substitutions. If there's a syntax error in a command, or if there's no command procedure associated with a command name, then no tracing occurs for that command. And if a string passed to Tcl_Eval contains multiple commands (bracketed, or on different lines), then multiple calls to objProc will happen β one for each command. One per. Fr fr. β¨
Tcl_DeleteTrace removes a trace, so no future calls get made to the procedure associated with that trace. And after Tcl_DeleteTrace returns, the caller should never again use the trace token. It's giving expired. π
When Tcl_DeleteTrace is called, the interpreter invokes the deleteProc that was passed as a parameter to Tcl_CreateObjTrace. That deleteProc must match the type Tcl_CmdObjTraceDeleteProc:
typedef void Tcl_CmdObjTraceDeleteProc(
void * clientData);
The clientData parameter will be the same as the clientData parameter originally passed to Tcl_CreateObjTrace.
Tcl_CreateTrace is an alternative interface for command tracing, and ngl it is not recommended for new applications. It exists for backward compatibility with code that was developed for older versions of the Tcl interpreter. It's similar to Tcl_CreateObjTrace, except that its proc parameter should have arguments and result matching the type Tcl_CmdTraceProc:
typedef void Tcl_CmdTraceProc(
void *clientData,
Tcl_Interp *interp,
int level,
char *command,
Tcl_CmdProc *cmdProc,
void *cmdClientData,
int argc,
const char *argv[]);
The parameters to the proc callback are similar to those of the objProc callback above. The commandToken is replaced with cmdProc, a pointer to the (string-based) command procedure that will be invoked; plus cmdClientData, the client data that will be passed to the procedure. The objc parameter is replaced with an argv parameter, which gives the arguments to the command as character strings. And proc must not modify the command or argv strings. π
βοΈ
If a trace created with Tcl_CreateTrace is in effect, inline compilation of Tcl commands such as if and while is always disabled. There is no notification when a trace created with Tcl_CreateTrace is deleted. There is no way to be notified when the trace created by Tcl_CreateTrace is deleted. And there is no way for the proc associated with a call to Tcl_CreateTrace to abort execution of a command. Like, zero. Nothing. Sorry bestie. π
π¦ REFERENCE COUNT MANAGEMENT π¦
When the proc passed to Tcl_CreateObjTrace is called, the values in its objv argument will have a reference count of at least 1, and that guaranteed reference comes from the Tcl evaluation stack. So do not call Tcl_DecrRefCount on any of those values unless you call Tcl_IncrRefCount on them first. Balance the books, queen. π
πΈ SEE ALSO πΈ
π KEYWORDS π
command, create, delete, interpreter, trace
And that's the whole page, bestie! This one comes to you from the Tcl manual β Tcl_CreateTrace(3) β so go forth, trace responsibly, and remember: don't touch objv. Mwah. πβ¨π
π¦ where this page comes from
- alpine 3.23: tcl9-doc 9.0.3-r0 Β· TCL
- alpine 3.24: tcl9-doc 9.0.3-r2 Β· TCL
- fedora 43: tcl-doc 1:9.0.2-1.fc43 Β· TCL AND GPL-3.0-or-later WITH Bison-exception-2.2 AND BSD-3-Clause
- fedora 44: tcl-doc 1:9.0.2-1.fc44 Β· TCL AND GPL-3.0-or-later WITH Bison-exception-2.2 AND BSD-3-Clause
- nixos 26.05: tcl 9.0.3
- nixpkgs unstable: tcl 9.1.0
- Copyright (c) 1989-1993 The Regents of the University of California
- Copyright (c) 1994-1996 Sun Microsystems, Inc
- Copyright (c) 2002 Kevin B. Kenny <kennykb@acm.org>. All rights reserved
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms