Big code, little time, and you’ve work to do.
Where’s that function at? What’s in that struct?
There’s an app for that: ctags.
The short version:
- Install exuberant ctags.
ctags -R .in the project’s top-level directory to generate the tags file.
vim $filefrom within the same directory as your tags file.
vim -t $tagnameto jump straight to that tag.
CTRL-]while cursor in a tag (roughly fn/var/other name) pushes your current location then jumps to definition of the tag you were on.
CTRL-tpops back up the tag stack, so you can continue where you left off.
:help tagsfor more, but that’s about all you need.
(The astute vimmer will now note that the ^]/^t pair is the same one you use to jump around in vim help files. Handy, that.)
If you forget this, just
/HOW TO USE, and read that very brief section.
You don’t want just any ctags. You want the exuberant kind. Don’t ask why, just trust me:
brew install ctags and get yourself some exuberant ctags.
Caramel Apple Tarball
To demonstrate, nab yourself delicious Apple-flavored libc. This particular variety is the one included with 10.8.3.
tar xzf Libc-825.26.tar.gz,
cd Libc-825.26 into the resulting directory, and wow that’s a good chunk of stuff.
Now it’s time for ctags. First, we generate the tags file by walking the entire directory hierarchy we’re sitting at the root of. Don’t worry, it’s not so bad as all that, just a
-Recurse flag and a
. directory to kick things off:
1 2 3
Thassa lotta tags.
Let’s jump into the thick of it. Fire up
vim at the definition of
We find ourselves with cursor blinking right on the
p at the start of
1 2 3 4 5 6 7 8
This is where things would start to suck if we didn’t have ctags. The entire function is just a call to yet another function. The
_np non-portable suffix makes me think maybe it will be somewhere else. Maybe they exiled all the non-portable functions to a different file? Who knows. Even better: we don’t care.
RET, and hit
CTRL-] to jump right to that function:
1 2 3 4 5 6 7 8 9
Ooh, fun, we transition from an old-cond to a new-style struct. (Maybe that
_np suffix was
new pthreads this time.) What’s the difference between old and new? Let’s take a look-see and find out.
CTRL-]. Looks like the definition of
npthread_cond_t lives right below the original
pthread_cond_t struct definition, so comparing the two is easy. The new version looks to have swapped out most of the old guts:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
for free space and a different approach to getting things done:
1 2 3 4 5 6 7 8 9 10 11 12 13
There’s also LP64 support and some alignment games. Fun times.
Well, that’s enough struct-gazing, we can pop back on up to where we were with
CTRL-T and resume looking at the implementation of
pthread_cond_signal_thread_np, right where we left off.
I bet it’d be interesting to see what happens when that
thread argument is
NULL, as it is in a standard
And when might it be called with a non-
Curious and curiouser.
I leave you to it, dear reader, with exuberant ctags frolicking and wagging tail at your side.
Added 2013-07-26T15:03:08Z-0400: This post is an introductory walkthrough. Once you’ve got the hang of the basics, check out the discussion at /r/vim for further pointers.