'''Hacking on The Core''' — it's good for the soul! ** Navigation Tips ** 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 http://core.tcl.tk/tcl/artifact/8d45dfc70e9d36c1?ln=977%|%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 http://core.tcl.tk/tcl/artifact/e70f605d466cd972?ln=2113-2125%|%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 http://core.tcl.tk/tcl/artifact/423adfd5425eebe3?ln=841-852%|%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. ** Some Debugging Macros ** [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. ======c #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`. <> The Tcl Core | Debugging