1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
|
Building Bash 1.14.7 on a modern system
=======================================
---
date: "2015-03-18"
---
In a previous revision of my [Bash arrays post](./bash-arrays.html), 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:
1. Replace `#include <varargs.h>` with `#include <stdarg.h>`
2. Replace `function_name (va_alist) va_dcl` with
`function_name (char *format, ...)`.
3. Removing the declaration and assignment for `format` from the
function body.
4. Replace `va_start (args);` with `va_start (args, format);` in the
function bodies.
5. Replace `function_name ();` with `function_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](./bash-1.14.7-gcc4-stdarg.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:
1. Replace `#if defined (i386)` with
`#if defined (i386) || defined (__x86_64__)`. The purpose of this
is obvious.
2. Add `#define USE_TERMCAP_EMULATION` to 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](./bash-1.14.7-machines-config.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 -g` The default value for CFLAGS (defined in `cpp-Makefile`)
- `-Werror` Treat warnings as errors; force us to deal with any issues.
- `-Wno-int-to-pointer-cast -Wno-pointer-to-int-cast` Allow casting
between integers and pointers. Unfortunately, the way this version
of Bash was designed requires this.
- `-Wno-deprecated-declarations` The `getwd` function in `unistd.h` is
considered deprecated (use `getcwd` instead). However, if `getcwd`
is available, Bash uses it's own `getwd` wrapper around `getcwd`
(implemented in `general.c`), and only uses the signature from
`unistd.h`, not the actuall implementation from libc.
- `-include stdio.h -include stdlib.h -include string.h` Several files
are missing these header file includes. If not for `-Werror`, the
default function signature fallbacks would work.
- `-Dexp2=bash_exp2` Avoid a conflict between the parser's `exp2`
helper function and `math.h`'s base-2 exponential function.
Have fun, software archaeologists!
|