Tcl_CreateTrace(3tcl)
π Tcl_CreateTrace π β from the Tcl Library Procedures, bestie
okay so you wanna spy on your interpreter?? like watch every command as it runs?? that's literally what this page is about, and yes it's giving main character energy. this is the 3tcl manual, and we're doing it together π«Ά
β¨ NAME β¨
Tcl_CreateTrace, Tcl_CreateObjTrace, Tcl_CreateObjTrace2, Tcl_DeleteTrace β arrange for command execution to be traced π
like... set up a lil observer that watches commands do their thing. and then also take it back down when you're done. periodt.
πΈ SYNOPSIS πΈ
#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)
see how there's three ways to make a trace and only one to delete it?? iconic honestly. the create ones all hand you back a Tcl_Trace token, and that token is your ticket to deleting later π
π ARGUMENTS π
Tcl_Interp *interp(in) β the interpreter that's holding the command you wanna trace (or un-trace, bestie). it's the whole vibe container. πTcl_Size level(in) β how deep down the rabbit hole we're watching, fr. only commands at or below this nesting level get traced... unless you pass0. let's break it down:1means top-level commands only2means top-level commands or the ones invoked as an immediate consequence of executing top-level commands (think: procedure bodies, bracketed commands, etc.) and so on, deeper and deeper0means commands at any level get traced. no cap. every single one. π
int flags(in) β flags that govern how the trace actually executes. the details are below, keep scrolling boo. β¨Tcl_CmdObjTraceProc *objProc(in) β the procedure that gets called for each command that's executed. calling-sequence deets are below, don't worry. π¦Tcl_CmdObjTraceProc2 *objProc2(in) β same deal, the procedure that gets called for each command that's executed. calling-sequence deets are below too. πΈTcl_CmdTraceProc *proc(in) β yep, also the procedure that gets called for each command that's executed. details on the calling sequence below. πvoid *clientData(in) β some arbitrary one-word value that you get to pass along toobjProc,objProc2orproc. it's your lil carry-on bag, put whatever you want in it. πTcl_CmdObjTraceDeleteProc *deleteProc(in) β the procedure that gets called when the trace is deleted. calling-sequence deets below. and ngl, aNULLpointer is totally permissible here β if you passNULL, you just get no callback when the trace gets deleted. no drama. πTcl_Trace trace(in) β the token for the trace you wanna remove. this is the return value from a previous call toTcl_CreateTrace. keep it safe, it's your receipt π§Ύ
β¨ DESCRIPTION β¨
okay so bestie, let's get into the actual β¨magicβ¨. Tcl_CreateObjTrace sets up command tracing for you. Once you call it, objProc gets invoked before the Tcl interpreter calls any command procedure while it's evaluating commands in interp. The thing that comes back from Tcl_CreateObjTrace is a token for the trace β hold onto it, because you hand it to Tcl_DeleteTrace when you wanna remove the trace. And yes, you can have many traces going at the same time on the same interpreter, no cap. π
objProc should have arguments and a result that match the 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 should match the type 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[]);
The clientData and interp parameters are straight-up copies of the corresponding arguments you gave to Tcl_CreateTrace. clientData usually points at some application-specific data structure that describes what to do when objProc fires. π
The level parameter tells you the nesting level of the command β it's 1 for top-level commands passed to Tcl_Eval by the application, 2 for the next-level commands passed to Tcl_Eval as part of parsing or interpreting level-1 commands, and so on and so on, you get the vibe.
The command parameter points to a string holding the text of the command, before any argument substitution happens.
The commandToken parameter is a Tcl command token that identifies the command about to be invoked. You can pass that token to Tcl_GetCommandName, Tcl_GetCommandInfoFromToken, or Tcl_SetCommandInfoFromToken to mess with the definition of the command.
And the objc and objv parameters designate the final parameter count and parameter vector that's gonna be passed to the command β and they've already had all the substitutions 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), then the Tcl interpreter will invoke the command. Any other return code gets treated as if the command itself returned that status, and the command is not invoked. π
bestie, listen. TheobjProccallback must NOT modifyobjvin any way. fr fr, don't touch it.
Tracing only happens for commands at a nesting level less than or equal to the level parameter. So like, the level parameter to objProc will always be less than or equal to the level parameter you passed to Tcl_CreateTrace. periodt. β¨
okay so this next part is important, don't skip it π. 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, so that those commands 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 gets improved significantly. (And this functionality is genuinely desirable, for example, when you're using Tcl_CreateObjTrace to implement an execution time profiler. iconic.) π
Calls to objProc are 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 occurs before tracing of the commands containing the substitutions. Makes sense, right?
If there's a syntax error in a command, or if there's no command procedure associated with a command name, then no tracing will occur for that command. And if a string you pass to Tcl_Eval contains multiple commands (bracketed, or on different lines) then you'll get multiple calls to objProc β one for each command. πΈ
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 use that trace token again. Throw it away, bestie, it's gone. π
When Tcl_DeleteTrace is called, the interpreter invokes the deleteProc that you 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 that was originally passed to Tcl_CreateObjTrace. π«Ά
the old-school one π
Tcl_CreateTrace is an alternative interface for command tracing β not recommended for new applications, ngl. It's there 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 a result that match 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; and 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.
bestie,procmust NOT modify thecommandorargvstrings. π
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 the command. π
π 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 is from the Tcl evaluation stack. You should not call Tcl_DecrRefCount on any of those values unless you call Tcl_IncrRefCount on them first. that's the rule bestie, no exceptions π
π SEE ALSO π
π KEYWORDS π
- command
- create
- delete
- interpreter
- trace
okay that's the whole page, you're officially a tracing expert now, go be the main character of your own interpreter β¨ππ
this was the Tcl version of the Tcl_CreateTrace(3tcl) manpage β that's the one and only Tcl, dated with the page's own footer date. slay, bye bestie ππ¦
π¦ where this page comes from
- debian trixie: tcl9.0-doc 9.0.1+dfsg-2
- ubuntu questing: tcl9.0-doc 9.0.2+dfsg-1
- ubuntu resolute: tcl9.0-doc 9.0.3+dfsg-1
- ubuntu stonking: tcl9.0-doc 9.0.4+dfsg-1
- 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