Version 4 of Hacking on The Core

Updated 2016-07-19 09:19:05 by pooryorick

Hacking on The Core — it's good for the soul!

See Also

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

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.

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.

#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.