VerySillyMUD: Compilation
Series [ VerySillyMUD ]
This post is part of my “VerySillyMUD” series, chronicling an attempt to refactor an old MUD into working condition [ 1 ].
The first goal is just to get the thing to compile. The source code is early 1990s C, and I have this C compiler on my computer at home:
The compiler doesn’t quite like the source code here; it generates 21
warnings and 20 errors on the first file when we run make
! I
haven’t included the full output here for readability’s sake, but you
can peruse the
full gist
if you like. Our goal here is to get compilation to succeed while
making only minor edits that we think are safe and do not change
intended functionality.
The first error is here:
The error in question points out a conflict between the prototype
included here and the system-level include file string.h
. A
quick grep of the source code shows that strdup()
is not
implemented in the source code here, so this should just be a matter
of removing the prototypes where we find them in the source code and
instead just including them via the system level library, as seen in
this commit.
The next error/warning is:
If we look at the source code in question, we see:
This could either be a mistake in the function definition (i.e. it
should return void
instead of int
) or this is an
oversight and the function ought to be returning some kind of status
code as an integer. A quick grep shows this is actually only called
from one place (elsewhere in comm.c
) where the return value
is not captured or inspected. Therefore we can take care of this in
the short term by correcting the function declaration, as captured in
this commit
What’s next?
Ok, from looking at the error message, the compiler seems to be
confusing a locally-defined log()
function that outputs some
kind of logging message with the one from the math.h
library
for computing logarithms. The easiest way to fix this is to rename the
local function for clarity to something like log_msg()
, as
captured in
this commit.
Ah, rats, now we see that this
function didn’t actually have a prototype anywhere, or at least not in
enough places:
Adding the prototype
to the protos.h
include file seems to fix that up. Now, I
just noticed at this point the compilation of comm.c
still
generates 25 warnings but only 2 errors! It turns out the very first
fix we did for strdup
cleaned most of them up. As I am
running out of time for this session, let’s press on to try to clean
up the last two errors and at least get one file compiling. I’m
generally a proponent of the “treat compiler warnings as errors” rule
of thumb, but I think we’re not quite ready to add that rule. I’d
really like to get to the point where we can get some unit tests in
place before doing too many more modifications. The first remaining
error is:
Hmm, this is a new one for me. The bind()
function connects a
socket to a particular address so that we can start accepting
connections from clients there. The system library’s bind()
on Mac OS X only takes 3 arguments, as does
Linux’s. A
look at the source code shows there’s an extra 0
argument
being passed. Maybe this was for an older version of bind? According
to running man 2 bind
on my Mac OS X computer, in the HISTORY
section it says “The bind() function call appeared in 4.2BSD.”
It turns out if we actually look at the
man page for bind()
from 4.2BSD
it also
only takes 3 arguments! What the heck? Without really knowing what the
compilation target was for the codebase, it’s hard to say what to do
here. I’m going to assume one of the compilation targets had a
bind()
call that maybe took some optional flags as a fourth
argument, but the source code didn’t opt into any of them (hence the
zero). According to
this,
extra arguments to functions were probably
safely ignored, so I think we can just
get rid of the extra argument here
and see if that
works. It’ll certainly clean up the error at least. Ok, the last
error, then is:
I think this dates me as a C programmer, because I thought that was
still a valid way to #ifdef
-out a section of code. I’ll just
comment the code out instead.
Update: when
I mentioned this on Twitter, Steve Vinoski pointed out:
@jon_moore don't see how that would have ever worked, do you mean "#if 0"?
— Steve Vinoski (@stevevinoski) October
4, 2015
This was interesting because Steve was right in that I had forgotten
the idiom I was used to (#if 0
). But it was also interesting
that this code, which apparently worked at one point, used this
incorrect idiom (#ifdef 0
). A little experiment shows that
this is not valid in
C89
(”ANSI C”):
If I attempt to compile this using C89 compatibility, I get:
So this was written for a compiler with non-ANSI C support. It doesn’t
even appear to be valid
K&R C,
according to the list of gcc
incompatibilities between it and ANSI C
(the version of gcc
I have installed is based on the
clang
compiler,
which doesn’t support the -traditional
flag, and I’m not
motivated to go install an older version to try it out). There are
hints in the source code that this was targeted towards Sun computers;
perhaps their early-1990s-vintage proprietary system C compilers
accepted this syntax. Anyway, it’s an easy enough fix, so let’s not
dwell further on it.
(Partial) success! At this point, the make
run actually
builds 10 object files (including comm.o
) before erroring out
(full gist.
Next time
out we’ll continue fixing compilation errors in the hopes of
getting at least a clean compilation run.
[ 1 ] SillyMUD was a derivative of DikuMUD, which was originally created by Sebastian Hammer, Michael Seifert, Hans Henrik Stærfeldt, Tom Madsen, and Katja Nyboe.