Hacking on the C code of giflib after an absence of nearly two decades has been an interesting experience, a little like doing an archeological dig. And not one that could readily be had elsewhere; nowhere other than under Unix is code that old still genuinely useful under any but carefully sandboxed conditions. Our reward for getting enough things about API design right the first time, one might rightly say. But what’s most interesting is what has changed, and giflib provides almost ideal conditions for noticing the changes in practice that have become second nature to me while that code has stood still.
I mean, this is code so ancient and unchanged that it still had a macro to hide the difference between C compilers that have void pointers and those that don’t – it wasn’t assuming even C89, let alone C99. I only resolved the uses of that to “void *” last night, and I’ve left the definition in the header just in case.
But the largest single executable-code change I found myself making was introducing C99 bools where the code had simulated them with old-style TRUE and FALSE macros. Only internally, I might add – there are a couple of pseudo-bools in the externally visible API that I haven’t touched so as not to risk breaking source compatibility. That and counting on stdint.h to supply uint32_t were two of the big three; I’ll get to the third in a bit.
The fact that editing in now-standard typedefs was the largest change in executable code is a testament to the remarkable stability of C, I think. I can barely think of any other language in which bringing code across an eighteen-year gap would be anywhere near that easy, and you would not want to use any of the handful of partial exceptions for systems programming on a modern machine.
Something else I noticed is that there was no point at which I looked at my old code (or code from Gershon Elber, the original author of the DOS version) and had a “What the fsck were you thinking?” moment. Which is good: I guess I was already a pretty good programmer 20 years ago, and the proof is that this code ended up deployed everywhere that displays pixels, including the phone on your hip, without my ever hearing barely a bug report. On the other hand, it’s a little disconcerting to think that I might not have learned anything about practical C in two decades…
There were some moments of pure amusement in the quest as well, such as my rediscovery of gif2epsn – a utility for dumping GIFs to Epson dot-matrix printers, actually using the individual print head wires as scanning pixels. Just what the world needs in 2012. I removed it; it’s still in the repo history in the unlikely event that anyone ever cares about that code again.
In general a lot of what I’m going to be doing for the upcoming 4.2 release is removing stuff. Back then, it made sense for giflib to carry a fairly elaborate set of image viewing, image capturing, and image format conversion tools, because relatively few other codebases spoke GIF. Of course that’s all changed now, with multiformat viewers and editors the norm. I’m probably going to throw out several more utilities because it doesn’t make any sense to compete with the likes of ImageMagick and the GIMP in that space. In a sense, giflib is a victim of its own success at making its format ubiquitous.
I’ve saved what I think is the most interesting change for last. When I’m not looking at code this old I tend to forget what a thicket of #ifdefs we had to manage back in the day. Cross-platform portability was hard, and it made our code ugly. Just the huge numbers of conditional includes of header files was bad enough; we used to be nibbled to death by a thousand little ducks like the stdargs.h/varargs.h skew. It’s easy to forget how much cleaner and lighter C code is in the era of full POSIX conformance (well, everywhere except the toxic hell-swamp that is Windows, anyway) and C99 required headers – that is, until you go looking at code as ancient as giflib and it all comes flooding back.
I had almost forgotten how liberating it felt four or five years back when I made a policy decision about GPSD. Yes, we’re going to assume full POSIX/C99/SuSv2 and if that chaps your ass you can damn well fix your broken toolchain! The giflib code is much older and more encrusted. Well, it was until about 48 hours ago. I ripped all that gunge out. The code almost doesn’t need autotools now, and if I chisel a little harder and drop the X viewer and Utah Raster Toolkit support it won’t need autotools at all.
That is, in itself, interesting news. The autotools suite began life because the combinatorial explosion of feature tests and #ifdefs back in the day was too difficult to manage by hand. Over the years autoconf and friends got hairier and hairier (to the point where I got utterly fed up with it), but at the same time increasingly good standards conformance in C and Unix implementations attacked the problem from the other end. So, during the last couple of days, I’ve found that the sort of platform #ifdefs that used to be autotools’s raison-d’etre can all be yanked out – what’s left is feature switches, and only two of those.
That whole standardization thing…actually worked. Though because it snuck up on us by stages, old farts like me have half- to three-quarters forgotten the problems it was solving, and younger programmers barely ever saw those problems to begin with. This is called “progress”.