From c02fbeff112e0172d0ad12bf7709099784305396 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Wed, 18 Mar 2015 20:41:52 -0400 Subject: Hey, I built Bash 1.14 on a modern box! --- public/bash-1.14.7-gcc4-stdarg.patch | 284 +++++++++++++++++++++++++++++++ public/bash-1.14.7-machines-config.patch | 21 +++ public/bash-arrays.md | 9 +- public/build-bash-1.md | 87 ++++++++++ 4 files changed, 397 insertions(+), 4 deletions(-) create mode 100644 public/bash-1.14.7-gcc4-stdarg.patch create mode 100644 public/bash-1.14.7-machines-config.patch create mode 100644 public/build-bash-1.md diff --git a/public/bash-1.14.7-gcc4-stdarg.patch b/public/bash-1.14.7-gcc4-stdarg.patch new file mode 100644 index 0000000..28d7c07 --- /dev/null +++ b/public/bash-1.14.7-gcc4-stdarg.patch @@ -0,0 +1,284 @@ +diff -ru bash-1.14.7/builtins/common.c bash-1.14.7.new2/builtins/common.c +--- bash-1.14.7/builtins/common.c 1995-01-30 13:02:37.000000000 -0500 ++++ bash-1.14.7.new2/builtins/common.c 2015-03-17 02:38:18.479744668 -0400 +@@ -20,7 +20,7 @@ + #include + #include "../posixstat.h" + #if defined (HAVE_VFPRINTF) +-#include ++#include + #endif /* VFPRINTF */ + + #if defined (HAVE_STRING_H) +@@ -114,17 +114,14 @@ + shell. */ + #if defined (HAVE_VFPRINTF) + void +-builtin_error (va_alist) +- va_dcl ++builtin_error (char *format, ...) + { +- char *format; + va_list args; + + if (this_command_name && *this_command_name) + fprintf (stderr, "%s: ", this_command_name); + +- va_start (args); +- format = va_arg (args, char *); ++ va_start (args, format); + vfprintf (stderr, format, args); + va_end (args); + fprintf (stderr, "\n"); +diff -ru bash-1.14.7/builtins/common.h bash-1.14.7.new2/builtins/common.h +--- bash-1.14.7/builtins/common.h 1994-04-18 19:39:46.000000000 -0500 ++++ bash-1.14.7.new2/builtins/common.h 2015-03-17 02:38:18.479744668 -0400 +@@ -23,7 +23,7 @@ + + #define ISOPTION(s, c) (s[0] == '-' && !s[2] && s[1] == c) + +-extern void builtin_error (); ++extern void builtin_error (char *, ...); + extern void bad_option (); + + extern int get_numeric_arg (); +diff -ru bash-1.14.7/error.c bash-1.14.7.new2/error.c +--- bash-1.14.7/error.c 1994-12-05 13:39:31.000000000 -0500 ++++ bash-1.14.7.new2/error.c 2015-03-17 02:38:18.479744668 -0400 +@@ -22,7 +22,7 @@ + #include + + #if defined (HAVE_VFPRINTF) +-#include ++#include + #endif + + #include +@@ -121,18 +121,15 @@ + #else /* We have VARARGS support, so use it. */ + + void +-programming_error (va_alist) +- va_dcl ++programming_error (char *format, ...) + { + va_list args; +- char *format; + + #if defined (JOB_CONTROL) + give_terminal_to (shell_pgrp); + #endif /* JOB_CONTROL */ + +- va_start (args); +- format = va_arg (args, char *); ++ va_start (args, format); + vfprintf (stderr, format, args); + fprintf (stderr, "\n"); + va_end (args); +@@ -144,15 +141,12 @@ + } + + void +-report_error (va_alist) +- va_dcl ++report_error (char *format, ...) + { + va_list args; +- char *format; + + fprintf (stderr, "%s: ", get_name_for_error ()); +- va_start (args); +- format = va_arg (args, char *); ++ va_start (args, format); + vfprintf (stderr, format, args); + fprintf (stderr, "\n"); + +@@ -162,15 +156,12 @@ + } + + void +-fatal_error (va_alist) +- va_dcl ++fatal_error (char *format, ...) + { + va_list args; +- char *format; + + fprintf (stderr, "%s: ", get_name_for_error ()); +- va_start (args); +- format = va_arg (args, char *); ++ va_start (args, format); + vfprintf (stderr, format, args); + fprintf (stderr, "\n"); + +@@ -179,30 +170,24 @@ + } + + void +-internal_error (va_alist) +- va_dcl ++internal_error (char *format, ...) + { + va_list args; +- char *format; + + fprintf (stderr, "%s: ", get_name_for_error ()); +- va_start (args); +- format = va_arg (args, char *); ++ va_start (args, format); + vfprintf (stderr, format, args); + fprintf (stderr, "\n"); + + va_end (args); + } + +-itrace (va_alist) +- va_dcl ++itrace (char *format, ...) + { + va_list args; +- char *format; + + fprintf(stderr, "TRACE: pid %d: ", getpid()); +- va_start (args); +- format = va_arg (args, char *); ++ va_start (args, format); + vfprintf (stderr, format, args); + fprintf (stderr, "\n"); + +@@ -214,11 +199,9 @@ + #if 0 + /* A trace function for silent debugging -- doesn't require a control + terminal. */ +-trace (va_alist) +- va_dcl ++trace (char *format, ...) + { + va_list args; +- char *format; + static FILE *tracefp = (FILE *)NULL; + + if (tracefp == NULL) +@@ -231,8 +214,7 @@ + + fprintf(tracefp, "TRACE: pid %d: ", getpid()); + +- va_start (args); +- format = va_arg (args, char *); ++ va_start (args, format); + vfprintf (tracefp, format, args); + fprintf (tracefp, "\n"); + +diff -ru bash-1.14.7/error.h bash-1.14.7.new2/error.h +--- bash-1.14.7/error.h 1994-01-26 14:31:10.000000000 -0500 ++++ bash-1.14.7.new2/error.h 2015-03-17 02:38:18.479744668 -0400 +@@ -25,10 +25,10 @@ + extern void file_error (); + + /* Report a programmer's error, and abort. Pass REASON, and ARG1 ... ARG5. */ +-extern void programming_error (); ++extern void programming_error (char *, ...); + + /* General error reporting. Pass FORMAT and ARG1 ... ARG5. */ +-extern void report_error (); ++extern void report_error (char *, ...); + + /* Report an unrecoverable error and exit. Pass FORMAT and ARG1 ... ARG5. */ +-extern void fatal_error (); ++extern void fatal_error (char *, ...); +diff -ru bash-1.14.7/lib/readline/display.c bash-1.14.7.new2/lib/readline/display.c +--- bash-1.14.7/lib/readline/display.c 1995-05-01 09:18:02.000000000 -0500 ++++ bash-1.14.7.new2/lib/readline/display.c 2015-03-17 02:46:02.243878132 -0400 +@@ -1020,14 +1020,11 @@ + mini-modeline. */ + + #if defined (HAVE_VARARGS_H) +-rl_message (va_alist) +- va_dcl ++rl_message (char *format, ...) + { +- char *format; + va_list args; + +- va_start (args); +- format = va_arg (args, char *); ++ va_start (args, format); + vsprintf (msg_buf, format, args); + va_end (args); + +diff -ru bash-1.14.7/lib/readline/readline.h bash-1.14.7.new2/lib/readline/readline.h +--- bash-1.14.7/lib/readline/readline.h 1994-07-26 14:35:40.000000000 -0500 ++++ bash-1.14.7.new2/lib/readline/readline.h 2015-03-17 02:46:34.466572077 -0400 +@@ -271,7 +271,7 @@ + + /* Functions in display.c */ + extern void rl_redisplay (); +-extern int rl_message (), rl_clear_message (); ++extern int rl_message (char *, ...), rl_clear_message (); + extern int rl_reset_line_state (); + extern int rl_character_len (); + extern int rl_show_char (); +diff -ru bash-1.14.7/lib/readline/rldefs.h bash-1.14.7.new2/lib/readline/rldefs.h +--- bash-1.14.7/lib/readline/rldefs.h 1995-02-25 18:55:43.000000000 -0500 ++++ bash-1.14.7.new2/lib/readline/rldefs.h 2015-03-17 02:45:26.611251831 -0400 +@@ -150,7 +150,7 @@ + #endif /* !strchr && !__STDC__ */ + + #if defined (HAVE_VARARGS_H) +-# include ++# include + #endif /* HAVE_VARARGS_H */ + + /* This is needed to include support for TIOCGWINSZ and window resizing. */ +--- bash-1.14.7/print_cmd.c 1995-01-30 12:45:09.000000000 -0500 ++++ bash-1.14.7.new2/print_cmd.c 2015-03-17 02:44:02.712916475 -0400 +@@ -20,7 +20,7 @@ + #include + + #if defined (HAVE_VARARGS_H) +-# include ++# include + #endif + + #if defined (HAVE_STRING_H) +@@ -41,7 +41,7 @@ + static int indentation = 0; + static int indentation_amount = 4; + +-static void cprintf (), newline (), indent (), the_printed_command_resize (); ++static void cprintf (char *, ...), newline (), indent (), the_printed_command_resize (); + static void semicolon (); + + static void make_command_string_internal (); +@@ -730,16 +730,14 @@ + + /* How to make the string. */ + static void +-cprintf (va_alist) +- va_dcl ++cprintf (char *control, ...) + { + register char *s; +- char *control, char_arg[2], *argp; ++ char char_arg[2], *argp; + int digit_arg, arg_len, c; + va_list args; + +- va_start (args); +- control = va_arg (args, char *); ++ va_start (args, control); + + arg_len = strlen (control); + the_printed_command_resize (arg_len + 1); +diff -ru bash-1.14.7/shell.c bash-1.14.7.new2/shell.c +--- bash-1.14.7/shell.c 1995-04-06 15:45:00.000000000 -0500 ++++ bash-1.14.7.new2/shell.c 2015-03-17 02:38:18.483077935 -0400 +@@ -43,7 +43,7 @@ + #include "bashansi.h" + + #if defined (HAVE_VARARGS_H) +-#include ++#include + #endif + + #include "shell.h" diff --git a/public/bash-1.14.7-machines-config.patch b/public/bash-1.14.7-machines-config.patch new file mode 100644 index 0000000..3773ba7 --- /dev/null +++ b/public/bash-1.14.7-machines-config.patch @@ -0,0 +1,21 @@ +diff -ru bash-1.14.7/machines.h bash-1.14.7.new2/machines.h +--- bash-1.14.7/machines.h 1995-12-18 14:13:22.000000000 -0500 ++++ bash-1.14.7.new2/machines.h 2015-03-17 02:50:38.618813331 -0400 +@@ -584,7 +584,7 @@ + /* */ + /* **************************************************************** */ + +-#if defined (i386) ++#if defined (i386) || defined (__x86_64__) + + /* Sequent Symmetry running Dynix/ptx 2.x */ + # if !defined (done386) && defined (_SEQUENT_) +@@ -891,6 +891,7 @@ + # define HAVE_SYS_SIGLIST + # define HAVE_VFPRINTF + # define HAVE_VARARGS_H ++# define USE_TERMCAP_EMULATION + # define SEARCH_LIB_NEEDS_SPACE + # if defined (__GNUC__) + # define HAVE_FIXED_INCLUDES +diff -ru bash-1.14.7/print_cmd.c bash-1.14.7.new2/print_cmd.c diff --git a/public/bash-arrays.md b/public/bash-arrays.md index cbbd4c4..23d90bb 100644 --- a/public/bash-arrays.md +++ b/public/bash-arrays.md @@ -407,8 +407,8 @@ for the arguments array, which is; though getting subset arrays from `$@` and `$*` is not (tip: use `set --` to re-purpose the arguments array). Writing for various versions of Bash, though, is pretty do-able. -Everything here works all the way back in bash-2.0 (1996), with the -following exceptions: +Everything here works all the way back in bash-2.0 (December 1996), +with the following exceptions: * The `+=` operator wasn't added until Bash 3.1. @@ -430,5 +430,6 @@ following exceptions: * In Bash 4.1 and higher, it works in the way described in the main part of this document. -Bash 1.x won't compile with modern GCC, so I couldn't verify how it -behaves. +Now, Bash 1.x doesn't have arrays at all. `$@` and `$*` work, but +using `:` to select a range of elements from them doesn't. Good thing +most boxes have been updated since 1996! diff --git a/public/build-bash-1.md b/public/build-bash-1.md new file mode 100644 index 0000000..e70a36b --- /dev/null +++ b/public/build-bash-1.md @@ -0,0 +1,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 ` with `#include ` +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 use 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 actually 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! -- cgit v1.2.3