Hacking on The Core provides information about the development of
Tcl itself.
See Also edit
- Tcl/Tk Engineering Manual
- A manual for the development of C code for Tcl/Tk.
- Re: PATCH kill access_ok() call from copy_siginfo_to_user() that we might as well avoid., Linus Torvalds, 2014-02-28
- In which Linus encourages painting the bikeshed.
Navigation Tips edit
Here's a dirty way to hunt down where a command (
file size) is implemented.
- file size is part of an ensemble, so the command will be registered somewhere with the name "size" .. let's start with grep '"size"' */*.[ch]
- searching for that string (including quotes!) leads quickly to generic/tclCmdAH.c: FileAttrSizeCmd looks like what we need!
- we can navigate quickly to the declaration site of functions by looking for the function name at the beginning of a line: grep ^FileAttrSizeCmd */*
- FileAttrSizeCmd is defined in the same file, and calls GetStatBuf, which calls its statProc argument, which is initialised with a pointer to Tcl_FSStat in tclIOUtil.c
So far, so simple .. but at this point it looks a bit hairy, and
ctags has stopped helping. Fortunately, there are naming conventions to help here:
A function like
Tcl_FSStat whose sole job is to dispatch through a struct to an implementation function also needs a
typedef to exist somewhere, defining the signature of the function it's calling. In this case, we can infer a type signature for
fsPtr->statProc, but we never see what it is called. We *could* look at the declaration of
Tcl_Filesystem, find its
statProc field and look for other things declared with that name ...
but there's a
shortcut: the typedef for
Tcl_FSStat is
Tcl_FSStatProc, and we are looking for something declared a
Tcl_FSStatProc. So search for it ..
at the beginning of a line:
grep ^Tcl_FSStatProc */*.c generic/tclIOUtil.c:132:Tcl_FSStatProc TclpObjStat;
Tclp indicates a private, platform-specific function, which will be declared for example in
unix/tclUnixFile.c, and calls a trivial wrapper for
stat(2). Simple!
This pattern of a wrapper function named
Tcl_Foo calling its implementation through a pointer typed
Tcl_FooProc is quite common across the Tcl core, so it's a useful shortcut to remember.
DKF: Commands are
mostly implemented in
tclCmd??.c. The bytecoded versions are compiled in
tclCompCmds.c or
tclCompCmds??.c (mostly by command name, but just search; the names are usually "obvious" and consistent). The bytecode engine is entirely in
tclExecute.c (and is not an easy place to start). Some commands are elsewhere (
tclVar.c for variable/stack-frame commands,
tclProc.c for
proc,
tclIOCmd.c for a bunch of ones to do with I/O,
tclNamesp.c for virtually everything to do with namespaces, etc.) The quickest way to find where a command is is usually to look at the mapping table in
tclBasic.c and search for the function name; grepping gets you to the right spot rapidly, especially since function definitions are the only places where function names appear at the start of the line in code following Tcl's Engineering Manual. Not everything is in that table (most ensembles aren't in 8.6) but they're still a minority of top-level commands.
Some Debugging Macros edit
PYK 2015-04-25: I'm still learning the ropes of
C, but I'll throw these here anyway. They came in handy recently to debug an I/O/
thread issue.
#define tdebug(statement) \
fprintf(stderr, "%p: %s\n", Tcl_GetCurrentThread(), (statement))
#define tcdebug(statePtr, statement) \
fprintf(stderr, "%p: chan %s: %s\n", Tcl_GetCurrentThread(), (statePtr)->channelName, (statement))
AMG: Minor, minor style tweaks, though the macros look good and useful for situations where you can't use the Tcl I/O or command return mechanisms. The
do ... while (0) trick is not necessary when the macro is just a single function call. Arguments to be expanded almost always should be surrounded by parentheses, and you do this, but you had
(statePtr->channelName) rather than
(statePtr)->channelName.
DKF: The
do...while(0) trick is usually entirely unnecessary with Tcl's style... but it is recommended anyway. But it's not so important for debugging things.
I tend to use
// style comments when I'm putting in things that are not meant to hit production, since Tcl
never uses them and that makes it easy to audit for stuff that I need to remove before committing.
Reference Counts edit
PYK 2018-03-13: Watch the
refCount member of
Tcl_Obj and
Object to get a play-by-play account of who is hanging onto and letting go of an object. When a segmentation fault occurs in a Tcl compiled with memory debugging, the structure the
refCount belongs to will often be filled with the "deallocated memory" pattern
0x6161616...., which indicates that the structure was freed and someone subsequently attempted to access it.