Building Bash 1.14.7 on a modern system
In a previous revision of my Bash arrays post, I wrote:
Bash 1.x won’t compile with modern GCC, so I couldn’t verify how it behaves.
I recall spending a little time fighting with it, but apparently I
didn’t try very hard: getting Bash 1.14.7 to build on a modern box is
mostly just adjusting it to use stdarg instead of the
no-longer-implemented varargs. There’s also a little
fiddling with the pre-autoconf automatic configuration.
stdarg
Converting to stdarg is pretty simple: For each variadic
function (functions that take a variable number of arguments), follow
these steps:
- Replace
#include <varargs.h>with#include <stdarg.h> - Replace
function_name (va_alist) va_dclwithfunction_name (char *format, ...). - Removing the declaration and assignment for
formatfrom the function body. - Replace
va_start (args);withva_start (args, format);in the function bodies. - Replace
function_name ();withfunction_name (char *, ...)in header files and/or at the top of C files.
There’s one function that uses the variable name control
instead of format.
I’ve prepared a patch that does this.
Configuration
Instead of using autoconf-style tests to test for compiler and
platform features, Bash 1 used the file machines.h that had
#ifdefs and a huge database of of different operating
systems for different platforms. It’s gross. And quite likely won’t
handle your modern operating system.
I made these two small changes to machines.h to get it
to work correctly on my box:
- Replace
#if defined (i386)with#if defined (i386) || defined (__x86_64__). The purpose of this is obvious. - Add
#define USE_TERMCAP_EMULATIONto the section for Linux [sic] on i386 (# if !defined (done386) && (defined (__linux__) || defined (linux))). What this does is tell it to link against libcurses to use curses termcap emulation, instead of linking against libtermcap (which doesn’t exist on modern GNU/Linux systems).
Again, I’ve prepared a patch that does this.
Building
With those adjustments, it should build, but with quite a few
warnings. Making a couple of changes to CFLAGS should fix
that:
make CFLAGS='-O -g -Werror -Wno-int-to-pointer-cast -Wno-pointer-to-int-cast -Wno-deprecated-declarations -include stdio.h -include stdlib.h -include string.h -Dexp2=bash_exp2'
That’s a doozy! Let’s break it down:
-O -gThe default value for CFLAGS (defined incpp-Makefile)-WerrorTreat warnings as errors; force us to deal with any issues.-Wno-int-to-pointer-cast -Wno-pointer-to-int-castAllow casting between integers and pointers. Unfortunately, the way this version of Bash was designed requires this.-Wno-deprecated-declarationsThegetwdfunction inunistd.his considered deprecated (usegetcwdinstead). However, ifgetcwdis available, Bash uses it’s owngetwdwrapper aroundgetcwd(implemented ingeneral.c), and only uses the signature fromunistd.h, not the actuall implementation from libc.-include stdio.h -include stdlib.h -include string.hSeveral files are missing these header file includes. If not for-Werror, the default function signature fallbacks would work.-Dexp2=bash_exp2Avoid a conflict between the parser’sexp2helper function andmath.h’s base-2 exponential function.
Have fun, software archaeologists!