xref: /freebsd/contrib/bc/configure.sh (revision af23369a6deaaeb612ab266eb88b8bb8d560c322)
1#! /bin/sh
2#
3# SPDX-License-Identifier: BSD-2-Clause
4#
5# Copyright (c) 2018-2023 Gavin D. Howard and contributors.
6#
7# Redistribution and use in source and binary forms, with or without
8# modification, are permitted provided that the following conditions are met:
9#
10# * Redistributions of source code must retain the above copyright notice, this
11#   list of conditions and the following disclaimer.
12#
13# * Redistributions in binary form must reproduce the above copyright notice,
14#   this list of conditions and the following disclaimer in the documentation
15#   and/or other materials provided with the distribution.
16#
17# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27# POSSIBILITY OF SUCH DAMAGE.
28#
29
30script="$0"
31scriptdir=$(dirname "$script")
32script=$(basename "$script")
33
34builddir=$(pwd)
35
36. "$scriptdir/scripts/functions.sh"
37
38# Simply prints the help message and quits based on the argument.
39# @param msg  The help message to print.
40usage() {
41
42	if [ $# -gt 0 ]; then
43
44		_usage_val=1
45
46		printf '%s\n\n' "$1"
47
48	else
49		_usage_val=0
50	fi
51
52	printf 'usage:\n'
53	printf '    %s -h\n' "$script"
54	printf '    %s --help\n' "$script"
55	printf '    %s [-a|-bD|-dB|-c] [-CeEfgGHilmMNPrtTvz] [-O OPT_LEVEL] [-k KARATSUBA_LEN]\\\n' "$script"
56	printf '       [-s SETTING] [-S SETTING] [-p TYPE]\n'
57	printf '    %s \\\n' "$script"
58	printf '       [--library|--bc-only --disable-dc|--dc-only --disable-bc|--coverage]  \\\n'
59	printf '       [--force --debug --disable-extra-math --disable-generated-tests]      \\\n'
60	printf '       [--disable-history --disable-man-pages --disable-nls --disable-strip] \\\n'
61	printf '       [--enable-editline] [--enable-readline] [--enable-internal-history]   \\\n'
62	printf '       [--disable-problematic-tests] [--install-all-locales]                 \\\n'
63	printf '       [--opt=OPT_LEVEL] [--karatsuba-len=KARATSUBA_LEN]                     \\\n'
64	printf '       [--set-default-on=SETTING] [--set-default-off=SETTING]                \\\n'
65	printf '       [--predefined-build-type=TYPE]                                        \\\n'
66	printf '       [--prefix=PREFIX] [--bindir=BINDIR] [--datarootdir=DATAROOTDIR]       \\\n'
67	printf '       [--datadir=DATADIR] [--mandir=MANDIR] [--man1dir=MAN1DIR]             \\\n'
68	printf '       [--man3dir=MAN3DIR]\n'
69
70	if [ "$_usage_val" -ne 0 ]; then
71		exit
72	fi
73
74	printf '\n'
75	printf '    -a, --library\n'
76	printf '        Build the libbcl instead of the programs. This is meant to be used with\n'
77	printf '        Other software like programming languages that want to make use of the\n'
78	printf '        parsing and math capabilities. This option will install headers using\n'
79	printf '        `make install`.\n'
80	printf '    -b, --bc-only\n'
81	printf '        Build bc only. It is an error if "-d", "--dc-only", "-B", or\n'
82	printf '        "--disable-bc" are specified too.\n'
83	printf '    -B, --disable-bc\n'
84	printf '        Disable bc. It is an error if "-b", "--bc-only", "-D", or "--disable-dc"\n'
85	printf '        are specified too.\n'
86	printf '    -c, --coverage\n'
87	printf '        Generate test coverage code. Requires gcov and gcovr.\n'
88	printf '        It is an error if either "-b" ("-D") or "-d" ("-B") is specified.\n'
89	printf '        Requires a compiler that use gcc-compatible coverage options\n'
90	printf '    -C, --disable-clean\n'
91	printf '        Disable the clean that configure.sh does before configure.\n'
92	printf '    -d, --dc-only\n'
93	printf '        Build dc only. It is an error if "-b", "--bc-only", "-D", or\n'
94	printf '        "--disable-dc" are specified too.\n'
95	printf '    -D, --disable-dc\n'
96	printf '        Disable dc. It is an error if "-d", "--dc-only", "-B", or "--disable-bc"\n'
97	printf '        are specified too.\n'
98	printf '    -e, --enable-editline\n'
99	printf '        Enable the use of libedit/editline. This is meant for those users that\n'
100	printf '        want vi-like or Emacs-like behavior in history. This option is ignored\n'
101	printf '        if history is disabled. If the -r or -i options are given with this\n'
102	printf '        option, the last occurrence of all of the three is used.\n'
103	printf '    -E, --disable-extra-math\n'
104	printf '        Disable extra math. This includes: "$" operator (truncate to integer),\n'
105	printf '        "@" operator (set number of decimal places), and r(x, p) (rounding\n'
106	printf '        function). Additionally, this option disables the extra printing\n'
107	printf '        functions in the math library.\n'
108	printf '    -f, --force\n'
109	printf '        Force use of all enabled options, even if they do not work. This\n'
110	printf '        option is to allow the maintainer a way to test that certain options\n'
111	printf '        are not failing invisibly. (Development only.)\n'
112	printf '    -g, --debug\n'
113	printf '        Build in debug mode. Adds the "-g" flag, and if there are no\n'
114	printf '        other CFLAGS, and "-O" was not given, this also adds the "-O0"\n'
115	printf '        flag. If this flag is *not* given, "-DNDEBUG" is added to CPPFLAGS\n'
116	printf '        and a strip flag is added to the link stage.\n'
117	printf '    -G, --disable-generated-tests\n'
118	printf '        Disable generating tests. This is for platforms that do not have a\n'
119	printf '        GNU bc-compatible bc to generate tests.\n'
120	printf '    -h, --help\n'
121	printf '        Print this help message and exit.\n'
122	printf '    -H, --disable-history\n'
123	printf '        Disable history.\n'
124	printf '    -i, --enable-internal-history\n'
125	printf '        Enable the internal history implementation and do not depend on either\n'
126	printf '        editline or readline. This option is ignored if history is disabled.\n'
127	printf '        If this option is given along with -e and -r, the last occurrence of\n'
128	printf '        all of the three is used.\n'
129	printf '    -k KARATSUBA_LEN, --karatsuba-len KARATSUBA_LEN\n'
130	printf '        Set the karatsuba length to KARATSUBA_LEN (default is 64).\n'
131	printf '        It is an error if KARATSUBA_LEN is not a number or is less than 16.\n'
132	printf '    -l, --install-all-locales\n'
133	printf '        Installs all locales, regardless of how many are on the system. This\n'
134	printf '        option is useful for package maintainers who want to make sure that\n'
135	printf '        a package contains all of the locales that end users might need.\n'
136	printf '    -m, --enable-memcheck\n'
137	printf '        Enable memcheck mode, to ensure no memory leaks. For development only.\n'
138	printf '    -M, --disable-man-pages\n'
139	printf '        Disable installing manpages.\n'
140	printf '    -N, --disable-nls\n'
141	printf '        Disable POSIX locale (NLS) support.\n'
142	printf '        ***WARNING***: Locales ignore the prefix because they *must* be\n'
143	printf '        installed at a fixed location to work at all. If you do not want that\n'
144	printf '        to happen, you must disable locales (NLS) completely.\n'
145	printf '    -O OPT_LEVEL, --opt OPT_LEVEL\n'
146	printf '        Set the optimization level. This can also be included in the CFLAGS,\n'
147	printf '        but it is provided, so maintainers can build optimized debug builds.\n'
148	printf '        This is passed through to the compiler, so it must be supported.\n'
149	printf '    -p TYPE, --predefined-build-type=TYPE\n'
150	printf '        Sets a given predefined build type with specific defaults. This is for\n'
151	printf '        easy setting of predefined builds. For example, to get a build that\n'
152	printf '        acts like the GNU bc by default, TYPE should be "GNU" (without the\n'
153	printf '        quotes) This option *must* come before any others that might change the\n'
154	printf '        build options. Currently supported values for TYPE include: "BSD" (for\n'
155	printf '        matching the BSD bc and BSD dc), "GNU" (for matching the GNU bc and\n'
156	printf '        dc), "GDH" (for the preferred build of the author, Gavin D. Howard),\n'
157	printf '        and "DBG" (for the preferred debug build of the author). This will\n'
158	printf '        also automatically enable a release build (except for "DBG").\n'
159	printf '    -P, --disable-problematic-tests\n'
160	printf '        Disables problematic tests. These tests usually include tests that\n'
161	printf '        can cause a SIGKILL because of too much memory usage.\n'
162	printf '    -r, --enable-readline\n'
163	printf '        Enable the use of libreadline/readline. This is meant for those users\n'
164	printf '        that want vi-like or Emacs-like behavior in history. This option is\n'
165	printf '        ignored if history is disabled. If this option is given along with -e\n'
166	printf '        and -r, the last occurrence of all of the three is used.\n'
167	printf '    -s SETTING, --set-default-on SETTING\n'
168	printf '        Set the default named by SETTING to on. See below for possible values\n'
169	printf '        for SETTING. For multiple instances of the -s or -S for the the same\n'
170	printf '        setting, the last one is used.\n'
171	printf '    -S SETTING, --set-default-off SETTING\n'
172	printf '        Set the default named by SETTING to off. See below for possible values\n'
173	printf '        for SETTING. For multiple instances of the -s or -S for the the same\n'
174	printf '        setting, the last one is used.\n'
175	printf '    -t, --enable-test-timing\n'
176	printf '        Enable the timing of tests. This is for development only.\n'
177	printf '    -T, --disable-strip\n'
178	printf '        Disable stripping symbols from the compiled binary or binaries.\n'
179	printf '        Stripping symbols only happens when debug mode is off.\n'
180	printf '    -v, --enable-valgrind\n'
181	printf '        Enable a build appropriate for valgrind. For development only.\n'
182	printf '    -z, --enable-fuzz-mode\n'
183	printf '        Enable fuzzing mode. THIS IS FOR DEVELOPMENT ONLY.\n'
184	printf '    --prefix PREFIX\n'
185	printf '        The prefix to install to. Overrides "$PREFIX" if it exists.\n'
186	printf '        If PREFIX is "/usr", install path will be "/usr/bin".\n'
187	printf '        Default is "/usr/local".\n'
188	printf '        ***WARNING***: Locales ignore the prefix because they *must* be\n'
189	printf '        installed at a fixed location to work at all. If you do not want that to\n'
190	printf '        happen, you must disable locales (NLS) completely.\n'
191	printf '    --bindir BINDIR\n'
192	printf '        The directory to install binaries in. Overrides "$BINDIR" if it exists.\n'
193	printf '        Default is "$PREFIX/bin".\n'
194	printf '    --includedir INCLUDEDIR\n'
195	printf '        The directory to install headers in. Overrides "$INCLUDEDIR" if it\n'
196	printf '        exists. Default is "$PREFIX/include".\n'
197	printf '    --libdir LIBDIR\n'
198	printf '        The directory to install libraries in. Overrides "$LIBDIR" if it exists.\n'
199	printf '        Default is "$PREFIX/lib".\n'
200	printf '    --datarootdir DATAROOTDIR\n'
201	printf '        The root location for data files. Overrides "$DATAROOTDIR" if it exists.\n'
202	printf '        Default is "$PREFIX/share".\n'
203	printf '    --datadir DATADIR\n'
204	printf '        The location for data files. Overrides "$DATADIR" if it exists.\n'
205	printf '        Default is "$DATAROOTDIR".\n'
206	printf '    --mandir MANDIR\n'
207	printf '        The location to install manpages to. Overrides "$MANDIR" if it exists.\n'
208	printf '        Default is "$DATADIR/man".\n'
209	printf '    --man1dir MAN1DIR\n'
210	printf '        The location to install Section 1 manpages to. Overrides "$MAN1DIR" if\n'
211	printf '        it exists. Default is "$MANDIR/man1".\n'
212	printf '    --man3dir MAN3DIR\n'
213	printf '        The location to install Section 3 manpages to. Overrides "$MAN3DIR" if\n'
214	printf '        it exists. Default is "$MANDIR/man3".\n'
215	printf '\n'
216	printf 'In addition, the following environment variables are used:\n'
217	printf '\n'
218	printf '    CC           C compiler. Must be compatible with POSIX c99. If there is a\n'
219	printf '                 space in the basename of the compiler, the items after the\n'
220	printf '                 first space are assumed to be compiler flags, and in that case,\n'
221	printf '                 the flags are automatically moved into CFLAGS. Default is\n'
222	printf '                 "c99".\n'
223	printf '    HOSTCC       Host C compiler. Must be compatible with POSIX c99. If there is\n'
224	printf '                 a space in the basename of the compiler, the items after the\n'
225	printf '                 first space are assumed to be compiler flags, and in the case,\n'
226	printf '                 the flags are automatically moved into HOSTCFLAGS. Default is\n'
227	printf '                 "$CC".\n'
228	printf '    HOST_CC      Same as HOSTCC. If HOSTCC also exists, it is used.\n'
229	printf '    CFLAGS       C compiler flags.\n'
230	printf '    HOSTCFLAGS   CFLAGS for HOSTCC. Default is "$CFLAGS".\n'
231	printf '    HOST_CFLAGS  Same as HOST_CFLAGS. If HOST_CFLAGS also exists, it is used.\n'
232	printf '    CPPFLAGS     C preprocessor flags. Default is "".\n'
233	printf '    LDFLAGS      Linker flags. Default is "".\n'
234	printf '    PREFIX       The prefix to install to. Default is "/usr/local".\n'
235	printf '                 If PREFIX is "/usr", install path will be "/usr/bin".\n'
236	printf '                 ***WARNING***: Locales ignore the prefix because they *must* be\n'
237	printf '                 installed at a fixed location to work at all. If you do not\n'
238	printf '                 want that to happen, you must disable locales (NLS) completely.\n'
239	printf '    BINDIR       The directory to install binaries in. Default is "$PREFIX/bin".\n'
240	printf '    INCLUDEDIR   The directory to install header files in. Default is\n'
241	printf '                 "$PREFIX/include".\n'
242	printf '    LIBDIR       The directory to install libraries in. Default is\n'
243	printf '                 "$PREFIX/lib".\n'
244	printf '    DATAROOTDIR  The root location for data files. Default is "$PREFIX/share".\n'
245	printf '    DATADIR      The location for data files. Default is "$DATAROOTDIR".\n'
246	printf '    MANDIR       The location to install manpages to. Default is "$DATADIR/man".\n'
247	printf '    MAN1DIR      The location to install Section 1 manpages to. Default is\n'
248	printf '                 "$MANDIR/man1".\n'
249	printf '    MAN3DIR      The location to install Section 3 manpages to. Default is\n'
250	printf '                 "$MANDIR/man3".\n'
251	printf '    NLSPATH      The location to install locale catalogs to. Must be an absolute\n'
252	printf '                 path (or contain one). This is treated the same as the POSIX\n'
253	printf '                 definition of $NLSPATH (see POSIX environment variables for\n'
254	printf '                 more information). Default is "/usr/share/locale/%%L/%%N".\n'
255	printf '    PC_PATH      The location to install pkg-config files to. Must be an\n'
256	printf '                 path or contain one. Default is the first path given by the\n'
257	printf '                 output of `pkg-config --variable=pc_path pkg-config`.\n'
258	printf '    EXECSUFFIX   The suffix to append to the executable names, used to not\n'
259	printf '                 interfere with other installed bc executables. Default is "".\n'
260	printf '    EXECPREFIX   The prefix to append to the executable names, used to not\n'
261	printf '                 interfere with other installed bc executables. Default is "".\n'
262	printf '    DESTDIR      For package creation. Default is "". If it is empty when\n'
263	printf '                 `%s` is run, it can also be passed to `make install`\n' "$script"
264	printf '                 later as an environment variable. If both are specified,\n'
265	printf '                 the one given to `%s` takes precedence.\n' "$script"
266	printf '    LONG_BIT     The number of bits in a C `long` type. This is mostly for the\n'
267	printf '                 embedded space since this `bc` uses `long`s internally for\n'
268	printf '                 overflow checking. In C99, a `long` is required to be 32 bits.\n'
269	printf '                 For most normal desktop systems, setting this is unnecessary,\n'
270	printf '                 except that 32-bit platforms with 64-bit longs may want to set\n'
271	printf '                 it to `32`. Default is the default of `LONG_BIT` for the target\n'
272	printf '                 platform. Minimum allowed is `32`. It is a build time error if\n'
273	printf '                 the specified value of `LONG_BIT` is greater than the default\n'
274	printf '                 value of `LONG_BIT` for the target platform.\n'
275	printf '    GEN_HOST     Whether to use `gen/strgen.c`, instead of `gen/strgen.sh`, to\n'
276	printf '                 produce the C files that contain the help texts as well as the\n'
277	printf '                 math libraries. By default, `gen/strgen.c` is used, compiled by\n'
278	printf '                 "$HOSTCC" and run on the host machine. Using `gen/strgen.sh`\n'
279	printf '                 removes the need to compile and run an executable on the host\n'
280	printf '                 machine since `gen/strgen.sh` is a POSIX shell script. However,\n'
281	printf '                 `gen/lib2.bc` is over 4095 characters, the max supported length\n'
282	printf '                 of a string literal in C99, and `gen/strgen.sh` generates a\n'
283	printf '                 string literal instead of an array, as `gen/strgen.c` does. For\n'
284	printf '                 most production-ready compilers, this limit probably is not\n'
285	printf '                 enforced, but it could be. Both options are still available for\n'
286	printf '                 this reason. If you are sure your compiler does not have the\n'
287	printf '                 limit and do not want to compile and run a binary on the host\n'
288	printf '                 machine, set this variable to "0". Any other value, or a\n'
289	printf '                 non-existent value, will cause the build system to compile and\n'
290	printf '                 run `gen/strgen.c`. Default is "".\n'
291	printf '    GEN_EMU      Emulator to run string generator code under (leave empty if not\n'
292	printf '                 necessary). This is not necessary when using `gen/strgen.sh`.\n'
293	printf '                 Default is "".\n'
294	printf '\n'
295	printf 'WARNING: even though `configure.sh` supports both option types, short and\n'
296	printf 'long, it does not support handling both at the same time. Use only one type.\n'
297	printf '\n'
298	printf 'Settings\n'
299	printf '========\n'
300	printf '\n'
301	printf 'bc and dc have some settings that, while they cannot be removed by build time\n'
302	printf 'options, can have their defaults changed at build time by packagers. Users are\n'
303	printf 'also able to change each setting with environment variables.\n'
304	printf '\n'
305	printf 'The following is a table of settings, along with their default values and the\n'
306	printf 'environment variables users can use to change them. (For the defaults, non-zero\n'
307	printf 'means on, and zero means off.)\n'
308	printf '\n'
309	printf '| Setting         | Description          | Default      | Env Variable         |\n'
310	printf '| =============== | ==================== | ============ | ==================== |\n'
311	printf '| bc.banner       | Whether to display   |            0 | BC_BANNER            |\n'
312	printf '|                 | the bc version       |              |                      |\n'
313	printf '|                 | banner when in       |              |                      |\n'
314	printf '|                 | interactive mode.    |              |                      |\n'
315	printf '| --------------- | -------------------- | ------------ | -------------------- |\n'
316	printf '| bc.sigint_reset | Whether SIGINT will  |            1 | BC_SIGINT_RESET      |\n'
317	printf '|                 | reset bc, instead of |              |                      |\n'
318	printf '|                 | exiting, when in     |              |                      |\n'
319	printf '|                 | interactive mode.    |              |                      |\n'
320	printf '| --------------- | -------------------- | ------------ | -------------------- |\n'
321	printf '| dc.sigint_reset | Whether SIGINT will  |            1 | DC_SIGINT_RESET      |\n'
322	printf '|                 | reset dc, instead of |              |                      |\n'
323	printf '|                 | exiting, when in     |              |                      |\n'
324	printf '|                 | interactive mode.    |              |                      |\n'
325	printf '| --------------- | -------------------- | ------------ | -------------------- |\n'
326	printf '| bc.tty_mode     | Whether TTY mode for |            1 | BC_TTY_MODE          |\n'
327	printf '|                 | bc should be on when |              |                      |\n'
328	printf '|                 | available.           |              |                      |\n'
329	printf '| --------------- | -------------------- | ------------ | -------------------- |\n'
330	printf '| dc.tty_mode     | Whether TTY mode for |            0 | BC_TTY_MODE          |\n'
331	printf '|                 | dc should be on when |              |                      |\n'
332	printf '|                 | available.           |              |                      |\n'
333	printf '| --------------- | -------------------- | ------------ | -------------------- |\n'
334	printf '| bc.prompt       | Whether the prompt   | $BC_TTY_MODE | BC_PROMPT            |\n'
335	printf '|                 | for bc should be on  |              |                      |\n'
336	printf '|                 | in tty mode.         |              |                      |\n'
337	printf '| --------------- | -------------------- | ------------ | -------------------- |\n'
338	printf '| dc.prompt       | Whether the prompt   | $DC_TTY_MODE | DC_PROMPT            |\n'
339	printf '|                 | for dc should be on  |              |                      |\n'
340	printf '|                 | in tty mode.         |              |                      |\n'
341	printf '| --------------- | -------------------- | ------------ | -------------------- |\n'
342	printf '| bc.expr_exit    | Whether to exit bc   |            1 | BC_EXPR_EXIT         |\n'
343	printf '|                 | if an expression or  |              |                      |\n'
344	printf '|                 | expression file is   |              |                      |\n'
345	printf '|                 | given with the -e or |              |                      |\n'
346	printf '|                 | -f options.          |              |                      |\n'
347	printf '| --------------- | -------------------- | ------------ | -------------------- |\n'
348	printf '| dc.expr_exit    | Whether to exit dc   |            1 | DC_EXPR_EXIT         |\n'
349	printf '|                 | if an expression or  |              |                      |\n'
350	printf '|                 | expression file is   |              |                      |\n'
351	printf '|                 | given with the -e or |              |                      |\n'
352	printf '|                 | -f options.          |              |                      |\n'
353	printf '| --------------- | -------------------- | ------------ | -------------------- |\n'
354	printf '| bc.digit_clamp  | Whether to have bc   |            0 | BC_DIGIT_CLAMP       |\n'
355	printf '|                 | clamp digits that    |              |                      |\n'
356	printf '|                 | are greater than or  |              |                      |\n'
357	printf '|                 | equal to the current |              |                      |\n'
358	printf '|                 | ibase when parsing   |              |                      |\n'
359	printf '|                 | numbers.             |              |                      |\n'
360	printf '| --------------- | -------------------- | ------------ | -------------------- |\n'
361	printf '| dc.digit_clamp  | Whether to have dc   |            0 | DC_DIGIT_CLAMP       |\n'
362	printf '|                 | clamp digits that    |              |                      |\n'
363	printf '|                 | are greater than or  |              |                      |\n'
364	printf '|                 | equal to the current |              |                      |\n'
365	printf '|                 | ibase when parsing   |              |                      |\n'
366	printf '|                 | numbers.             |              |                      |\n'
367	printf '| --------------- | -------------------- | ------------ | -------------------- |\n'
368	printf '\n'
369	printf 'These settings are not meant to be changed on a whim. They are meant to ensure\n'
370	printf 'that this bc and dc will conform to the expectations of the user on each\n'
371	printf 'platform.\n'
372
373	exit "$_usage_val"
374}
375
376# Replaces a file extension in a filename. This is used mostly to turn filenames
377# like `src/num.c` into `src/num.o`. In other words, it helps to link targets to
378# the files they depend on.
379#
380# @param file  The filename.
381# @param ext1  The extension to replace.
382# @param ext2  The new extension.
383replace_ext() {
384
385	if [ "$#" -ne 3 ]; then
386		err_exit "Invalid number of args to $0"
387	fi
388
389	_replace_ext_file="$1"
390	_replace_ext_ext1="$2"
391	_replace_ext_ext2="$3"
392
393	_replace_ext_result="${_replace_ext_file%.$_replace_ext_ext1}.$_replace_ext_ext2"
394
395	printf '%s\n' "$_replace_ext_result"
396}
397
398# Replaces a file extension in every filename given in a list. The list is just
399# a space-separated list of words, so filenames are expected to *not* have
400# spaces in them. See the documentation for `replace_ext()`.
401#
402# @param files  The list of space-separated filenames to replace extensions for.
403# @param ext1   The extension to replace.
404# @param ext2   The new extension.
405replace_exts() {
406
407	if [ "$#" -ne 3 ]; then
408		err_exit "Invalid number of args to $0"
409	fi
410
411	_replace_exts_files="$1"
412	_replace_exts_ext1="$2"
413	_replace_exts_ext2="$3"
414
415	for _replace_exts_file in $_replace_exts_files; do
416		_replace_exts_new_name=$(replace_ext "$_replace_exts_file" "$_replace_exts_ext1" "$_replace_exts_ext2")
417		_replace_exts_result="$_replace_exts_result $_replace_exts_new_name"
418	done
419
420	printf '%s\n' "$_replace_exts_result"
421}
422
423# Finds a placeholder in @a str and replaces it. This is the workhorse of
424# configure.sh. It's what replaces placeholders in Makefile.in with the data
425# needed for the chosen build. Below, you will see a lot of calls to this
426# function.
427#
428# Note that needle can never contain an exclamation point. For more information,
429# see substring_replace() in scripts/functions.sh.
430#
431# @param str          The string to find and replace placeholders in.
432# @param needle       The placeholder name.
433# @param replacement  The string to use to replace the placeholder.
434replace() {
435
436	if [ "$#" -ne 3 ]; then
437		err_exit "Invalid number of args to $0"
438	fi
439
440	_replace_str="$1"
441	_replace_needle="$2"
442	_replace_replacement="$3"
443
444	substring_replace "$_replace_str" "%%$_replace_needle%%" "$_replace_replacement"
445}
446
447# This function finds all the source files that need to be built. If there is
448# only one argument and it is empty, then all source files are built. Otherwise,
449# the arguments are all assumed to be source files that should *not* be built.
450find_src_files() {
451
452	_find_src_files_args=""
453
454	if [ "$#" -ge 1 ] && [ "$1" != "" ]; then
455
456		while [ "$#" -ge 1 ]; do
457			_find_src_files_a="${1## }"
458			shift
459			_find_src_files_args=$(printf '%s\n%s/src/%s\n' "$_find_src_files_args" "$scriptdir" "${_find_src_files_a}")
460		done
461
462	fi
463
464	_find_src_files_files=$(find "$scriptdir/src/" -depth -name "*.c" -print | LC_ALL=C sort)
465
466	_find_src_files_result=""
467
468	for _find_src_files_f in $_find_src_files_files; do
469
470		# If this is true, the file is part of args, and therefore, unneeded.
471		if [ "${_find_src_files_args##*$_find_src_files_f}" != "${_find_src_files_args}" ]; then
472			continue
473		fi
474
475		_find_src_files_result=$(printf '%s\n%s\n' "$_find_src_files_result" "$_find_src_files_f")
476
477	done
478
479	printf '%s\n' "$_find_src_files_result"
480}
481
482# This function generates a list of files to go into the Makefile. It generates
483# the list of object files, as well as the list of test coverage files.
484#
485# @param contents  The contents of the Makefile template to put the list of
486#                  files into.
487gen_file_list() {
488
489	if [ "$#" -lt 1 ]; then
490		err_exit "Invalid number of args to $0"
491	fi
492
493	_gen_file_list_contents="$1"
494	shift
495
496	if [ "$#" -ge 1 ]; then
497		_gen_file_list_unneeded="$@"
498	else
499		_gen_file_list_unneeded=""
500	fi
501
502	_gen_file_list_needle_src="SRC"
503	_gen_file_list_needle_obj="OBJ"
504	_gen_file_list_needle_gcda="GCDA"
505	_gen_file_list_needle_gcno="GCNO"
506
507	_gen_file_list_replacement=$(find_src_files $_gen_file_list_unneeded | tr '\n' ' ')
508	_gen_file_list_contents=$(replace "$_gen_file_list_contents" \
509		"$_gen_file_list_needle_src" "$_gen_file_list_replacement")
510
511	_gen_file_list_cbases=""
512
513	for _gen_file_list_f in $_gen_file_list_replacement; do
514		_gen_file_list_b=$(basename "$_gen_file_list_f")
515		_gen_file_list_cbases="$_gen_file_list_cbases src/$_gen_file_list_b"
516	done
517
518	_gen_file_list_replacement=$(replace_exts "$_gen_file_list_cbases" "c" "o")
519	_gen_file_list_contents=$(replace "$_gen_file_list_contents" \
520		"$_gen_file_list_needle_obj" "$_gen_file_list_replacement")
521
522	_gen_file_list_replacement=$(replace_exts "$_gen_file_list_replacement" "o" "gcda")
523	_gen_file_list_contents=$(replace "$_gen_file_list_contents" \
524		"$_gen_file_list_needle_gcda" "$_gen_file_list_replacement")
525
526	_gen_file_list_replacement=$(replace_exts "$_gen_file_list_replacement" "gcda" "gcno")
527	_gen_file_list_contents=$(replace "$_gen_file_list_contents" \
528		"$_gen_file_list_needle_gcno" "$_gen_file_list_replacement")
529
530	printf '%s\n' "$_gen_file_list_contents"
531}
532
533# Generates the proper test targets for each test to have its own target. This
534# allows `make test` to run in parallel.
535#
536# @param name        Which calculator to generate tests for.
537# @param extra_math  An integer that, if non-zero, activates extra math tests.
538# @param time_tests  An integer that, if non-zero, tells the test suite to time
539#                    the execution of each test.
540gen_std_tests() {
541
542	_gen_std_tests_name="$1"
543	shift
544
545	_gen_std_tests_extra_math="$1"
546	shift
547
548	_gen_std_tests_time_tests="$1"
549	shift
550
551	_gen_std_tests_extra_required=$(cat "$scriptdir/tests/extra_required.txt")
552
553	for _gen_std_tests_t in $(cat "$scriptdir/tests/$_gen_std_tests_name/all.txt"); do
554
555		if [ "$_gen_std_tests_extra_math" -eq 0 ]; then
556
557			if [ -z "${_gen_std_tests_extra_required##*$_gen_std_tests_t*}" ]; then
558				printf 'test_%s_%s:\n\t@printf "Skipping %s %s\\n"\n\n' \
559					"$_gen_std_tests_name" "$_gen_std_tests_t" "$_gen_std_tests_name" \
560					"$_gen_std_tests_t" >> "Makefile"
561				continue
562			fi
563
564		fi
565
566		printf 'test_%s_%s:\n\t@export BC_TEST_OUTPUT_DIR="%s/tests"; sh $(TESTSDIR)/test.sh %s %s %s %s %s\n\n' \
567			"$_gen_std_tests_name" "$_gen_std_tests_t" "$builddir" "$_gen_std_tests_name" \
568			"$_gen_std_tests_t" "$generate_tests" "$time_tests" \
569			"$*" >> "Makefile"
570
571	done
572}
573
574# Generates a list of test targets that will be used as prerequisites for other
575# targets.
576#
577# @param name  The name of the calculator to generate test targets for.
578gen_std_test_targets() {
579
580	_gen_std_test_targets_name="$1"
581	shift
582
583	_gen_std_test_targets_tests=$(cat "$scriptdir/tests/${_gen_std_test_targets_name}/all.txt")
584
585	for _gen_std_test_targets_t in $_gen_std_test_targets_tests; do
586		printf ' test_%s_%s' "$_gen_std_test_targets_name" "$_gen_std_test_targets_t"
587	done
588
589	printf '\n'
590}
591
592# Generates the proper test targets for each error test to have its own target.
593# This allows `make test_bc_errors` and `make test_dc_errors` to run in
594# parallel.
595#
596# @param name  Which calculator to generate tests for.
597gen_err_tests() {
598
599	_gen_err_tests_name="$1"
600	shift
601
602	_gen_err_tests_fs=$(ls "$scriptdir/tests/$_gen_err_tests_name/errors/")
603
604	for _gen_err_tests_t in $_gen_err_tests_fs; do
605
606		printf 'test_%s_error_%s:\n\t@export BC_TEST_OUTPUT_DIR="%s/tests"; sh $(TESTSDIR)/error.sh %s %s %s %s\n\n' \
607			"$_gen_err_tests_name" "$_gen_err_tests_t" "$builddir" "$_gen_err_tests_name" \
608			"$_gen_err_tests_t" "$problematic_tests" "$*" >> "Makefile"
609
610	done
611
612}
613
614# Generates a list of error test targets that will be used as prerequisites for
615# other targets.
616#
617# @param name  The name of the calculator to generate test targets for.
618gen_err_test_targets() {
619
620	_gen_err_test_targets_name="$1"
621	shift
622
623	_gen_err_test_targets_tests=$(ls "$scriptdir/tests/$_gen_err_test_targets_name/errors/")
624
625	for _gen_err_test_targets_t in $_gen_err_test_targets_tests; do
626		printf ' test_%s_error_%s' "$_gen_err_test_targets_name" "$_gen_err_test_targets_t"
627	done
628
629	printf '\n'
630}
631
632# Generates the proper script test targets for each script test to have its own
633# target. This allows `make test` to run in parallel.
634#
635# @param name        Which calculator to generate tests for.
636# @param extra_math  An integer that, if non-zero, activates extra math tests.
637# @param generate    An integer that, if non-zero, activates generated tests.
638# @param time_tests  An integer that, if non-zero, tells the test suite to time
639#                    the execution of each test.
640gen_script_tests() {
641
642	_gen_script_tests_name="$1"
643	shift
644
645	_gen_script_tests_extra_math="$1"
646	shift
647
648	_gen_script_tests_generate="$1"
649	shift
650
651	_gen_script_tests_time="$1"
652	shift
653
654	_gen_script_tests_tests=$(cat "$scriptdir/tests/$_gen_script_tests_name/scripts/all.txt")
655
656	for _gen_script_tests_f in $_gen_script_tests_tests; do
657
658		_gen_script_tests_b=$(basename "$_gen_script_tests_f" ".${_gen_script_tests_name}")
659
660		printf 'test_%s_script_%s:\n\t@export BC_TEST_OUTPUT_DIR="%s/tests"; sh $(TESTSDIR)/script.sh %s %s %s 1 %s %s %s\n\n' \
661			"$_gen_script_tests_name" "$_gen_script_tests_b" "$builddir" "$_gen_script_tests_name" \
662			"$_gen_script_tests_f" "$_gen_script_tests_extra_math" "$_gen_script_tests_generate" \
663			"$_gen_script_tests_time" "$*" >> "Makefile"
664	done
665}
666
667set_default() {
668
669	_set_default_on="$1"
670	shift
671
672	_set_default_name="$1"
673	shift
674
675	# The reason that the variables that are being set do not have the same
676	# non-collision avoidance that the other variables do is that we *do* want
677	# the settings of these variables to leak out of the function. They adjust
678	# the settings outside of the function.
679	case "$_set_default_name" in
680
681		bc.banner) bc_default_banner="$_set_default_on" ;;
682		bc.sigint_reset) bc_default_sigint_reset="$_set_default_on" ;;
683		dc.sigint_reset) dc_default_sigint_reset="$_set_default_on" ;;
684		bc.tty_mode) bc_default_tty_mode="$_set_default_on" ;;
685		dc.tty_mode) dc_default_tty_mode="$_set_default_on" ;;
686		bc.prompt) bc_default_prompt="$_set_default_on" ;;
687		dc.prompt) dc_default_prompt="$_set_default_on" ;;
688		bc.expr_exit) bc_default_expr_exit="$_set_default_on";;
689		dc.expr_exit) dc_default_expr_exit="$_set_default_on";;
690		bc.digit_clamp) bc_default_digit_clamp="$_set_default_on";;
691		dc.digit_clamp) dc_default_digit_clamp="$_set_default_on";;
692		?) usage "Invalid setting: $_set_default_name" ;;
693
694	esac
695}
696
697predefined_build() {
698
699	_predefined_build_type="$1"
700	shift
701
702	# The reason that the variables that are being set do not have the same
703	# non-collision avoidance that the other variables do is that we *do* want
704	# the settings of these variables to leak out of the function. They adjust
705	# the settings outside of the function.
706	case "$_predefined_build_type" in
707
708		BSD)
709			bc_only=0
710			dc_only=0
711			coverage=0
712			debug=0
713			optimization="3"
714			hist=1
715			hist_impl="editline"
716			extra_math=1
717			generate_tests=$generate_tests
718			install_manpages=0
719			nls=1
720			force=0
721			strip_bin=1
722			all_locales=0
723			library=0
724			fuzz=0
725			time_tests=0
726			vg=0
727			memcheck=0
728			clean=1
729			bc_default_banner=0
730			bc_default_sigint_reset=1
731			dc_default_sigint_reset=1
732			bc_default_tty_mode=1
733			dc_default_tty_mode=0
734			bc_default_prompt=""
735			dc_default_prompt=""
736			bc_default_expr_exit=1
737			dc_default_expr_exit=1
738			bc_default_digit_clamp=0
739			dc_default_digit_clamp=0;;
740
741		GNU)
742			bc_only=0
743			dc_only=0
744			coverage=0
745			debug=0
746			optimization="3"
747			hist=1
748			hist_impl="internal"
749			extra_math=1
750			generate_tests=$generate_tests
751			install_manpages=1
752			nls=1
753			force=0
754			strip_bin=1
755			all_locales=0
756			library=0
757			fuzz=0
758			time_tests=0
759			vg=0
760			memcheck=0
761			clean=1
762			bc_default_banner=1
763			bc_default_sigint_reset=1
764			dc_default_sigint_reset=0
765			bc_default_tty_mode=1
766			dc_default_tty_mode=0
767			bc_default_prompt=""
768			dc_default_prompt=""
769			bc_default_expr_exit=1
770			dc_default_expr_exit=1
771			bc_default_digit_clamp=1
772			dc_default_digit_clamp=0;;
773
774		GDH)
775			CFLAGS="-flto -Weverything -Wno-padded -Werror -pedantic -std=c11"
776			bc_only=0
777			dc_only=0
778			coverage=0
779			debug=0
780			optimization="3"
781			hist=1
782			hist_impl="internal"
783			extra_math=1
784			generate_tests=1
785			install_manpages=1
786			nls=0
787			force=0
788			strip_bin=1
789			all_locales=0
790			library=0
791			fuzz=0
792			time_tests=0
793			vg=0
794			memcheck=0
795			clean=1
796			bc_default_banner=1
797			bc_default_sigint_reset=1
798			dc_default_sigint_reset=1
799			bc_default_tty_mode=1
800			dc_default_tty_mode=1
801			bc_default_prompt=""
802			dc_default_prompt=""
803			bc_default_expr_exit=0
804			dc_default_expr_exit=0
805			bc_default_digit_clamp=1
806			dc_default_digit_clamp=1;;
807
808		DBG)
809			CFLAGS="-Weverything -Wno-padded -Werror -pedantic -std=c11"
810			bc_only=0
811			dc_only=0
812			coverage=0
813			debug=1
814			optimization="0"
815			hist=1
816			hist_impl="internal"
817			extra_math=1
818			generate_tests=1
819			install_manpages=1
820			nls=1
821			force=0
822			strip_bin=1
823			all_locales=0
824			library=0
825			fuzz=0
826			time_tests=0
827			vg=0
828			memcheck=1
829			clean=1
830			bc_default_banner=1
831			bc_default_sigint_reset=1
832			dc_default_sigint_reset=1
833			bc_default_tty_mode=1
834			dc_default_tty_mode=1
835			bc_default_prompt=""
836			dc_default_prompt=""
837			bc_default_expr_exit=0
838			dc_default_expr_exit=0
839			bc_default_digit_clamp=1
840			dc_default_digit_clamp=1;;
841
842		?|'') usage "Invalid user build: \"$_predefined_build_type\". Accepted types are BSD, GNU, GDH, DBG.";;
843
844	esac
845}
846
847# Generates a list of script test targets that will be used as prerequisites for
848# other targets.
849#
850# @param name  The name of the calculator to generate script test targets for.
851gen_script_test_targets() {
852
853	_gen_script_test_targets_name="$1"
854	shift
855
856	_gen_script_test_targets_tests=$(cat "$scriptdir/tests/$_gen_script_test_targets_name/scripts/all.txt")
857
858	for _gen_script_test_targets_f in $_gen_script_test_targets_tests; do
859		_gen_script_test_targets_b=$(basename "$_gen_script_test_targets_f" \
860			".$_gen_script_test_targets_name")
861		printf ' test_%s_script_%s' "$_gen_script_test_targets_name" \
862			"$_gen_script_test_targets_b"
863	done
864
865	printf '\n'
866}
867
868# This is a list of defaults, but it is also the list of possible options for
869# users to change.
870#
871# The development options are: force (force options even if they fail), valgrind
872# (build in a way suitable for valgrind testing), memcheck (same as valgrind),
873# and fuzzing (build in a way suitable for fuzzing).
874bc_only=0
875dc_only=0
876coverage=0
877karatsuba_len=32
878debug=0
879hist=1
880hist_impl="internal"
881extra_math=1
882optimization=""
883generate_tests=1
884install_manpages=1
885nls=1
886force=0
887strip_bin=1
888all_locales=0
889library=0
890fuzz=0
891time_tests=0
892vg=0
893memcheck=0
894clean=1
895problematic_tests=1
896
897# The empty strings are because they depend on TTY mode. If they are directly
898# set, though, they will be integers. We test for empty strings later.
899bc_default_banner=0
900bc_default_sigint_reset=1
901dc_default_sigint_reset=1
902bc_default_tty_mode=1
903dc_default_tty_mode=0
904bc_default_prompt=""
905dc_default_prompt=""
906bc_default_expr_exit=1
907dc_default_expr_exit=1
908bc_default_digit_clamp=0
909dc_default_digit_clamp=0
910
911# getopts is a POSIX utility, but it cannot handle long options. Thus, the
912# handling of long options is done by hand, and that's the reason that short and
913# long options cannot be mixed.
914while getopts "abBcdDeEfgGhHik:lMmNO:p:PrS:s:tTvz-" opt; do
915
916	case "$opt" in
917		a) library=1 ;;
918		b) bc_only=1 ;;
919		B) dc_only=1 ;;
920		c) coverage=1 ;;
921		C) clean=0 ;;
922		d) dc_only=1 ;;
923		D) bc_only=1 ;;
924		e) hist_impl="editline" ;;
925		E) extra_math=0 ;;
926		f) force=1 ;;
927		g) debug=1 ;;
928		G) generate_tests=0 ;;
929		h) usage ;;
930		H) hist=0 ;;
931		i) hist_impl="internal" ;;
932		k) karatsuba_len="$OPTARG" ;;
933		l) all_locales=1 ;;
934		m) memcheck=1 ;;
935		M) install_manpages=0 ;;
936		N) nls=0 ;;
937		O) optimization="$OPTARG" ;;
938		p) predefined_build "$OPTARG" ;;
939		P) problematic_tests=0 ;;
940		r) hist_impl="readline" ;;
941		S) set_default 0 "$OPTARG" ;;
942		s) set_default 1 "$OPTARG" ;;
943		t) time_tests=1 ;;
944		T) strip_bin=0 ;;
945		v) vg=1 ;;
946		z) fuzz=1 ;;
947		-)
948			arg="$1"
949			arg="${arg#--}"
950			LONG_OPTARG="${arg#*=}"
951			case $arg in
952				help) usage ;;
953				library) library=1 ;;
954				bc-only) bc_only=1 ;;
955				dc-only) dc_only=1 ;;
956				coverage) coverage=1 ;;
957				debug) debug=1 ;;
958				force) force=1 ;;
959				prefix=?*) PREFIX="$LONG_OPTARG" ;;
960				prefix)
961					if [ "$#" -lt 2 ]; then
962						usage "No argument given for '--$arg' option"
963					fi
964					PREFIX="$2"
965					shift ;;
966				bindir=?*) BINDIR="$LONG_OPTARG" ;;
967				bindir)
968					if [ "$#" -lt 2 ]; then
969						usage "No argument given for '--$arg' option"
970					fi
971					BINDIR="$2"
972					shift ;;
973				includedir=?*) INCLUDEDIR="$LONG_OPTARG" ;;
974				includedir)
975					if [ "$#" -lt 2 ]; then
976						usage "No argument given for '--$arg' option"
977					fi
978					INCLUDEDIR="$2"
979					shift ;;
980				libdir=?*) LIBDIR="$LONG_OPTARG" ;;
981				libdir)
982					if [ "$#" -lt 2 ]; then
983						usage "No argument given for '--$arg' option"
984					fi
985					LIBDIR="$2"
986					shift ;;
987				datarootdir=?*) DATAROOTDIR="$LONG_OPTARG" ;;
988				datarootdir)
989					if [ "$#" -lt 2 ]; then
990						usage "No argument given for '--$arg' option"
991					fi
992					DATAROOTDIR="$2"
993					shift ;;
994				datadir=?*) DATADIR="$LONG_OPTARG" ;;
995				datadir)
996					if [ "$#" -lt 2 ]; then
997						usage "No argument given for '--$arg' option"
998					fi
999					DATADIR="$2"
1000					shift ;;
1001				mandir=?*) MANDIR="$LONG_OPTARG" ;;
1002				mandir)
1003					if [ "$#" -lt 2 ]; then
1004						usage "No argument given for '--$arg' option"
1005					fi
1006					MANDIR="$2"
1007					shift ;;
1008				man1dir=?*) MAN1DIR="$LONG_OPTARG" ;;
1009				man1dir)
1010					if [ "$#" -lt 2 ]; then
1011						usage "No argument given for '--$arg' option"
1012					fi
1013					MAN1DIR="$2"
1014					shift ;;
1015				man3dir=?*) MAN3DIR="$LONG_OPTARG" ;;
1016				man3dir)
1017					if [ "$#" -lt 2 ]; then
1018						usage "No argument given for '--$arg' option"
1019					fi
1020					MAN3DIR="$2"
1021					shift ;;
1022				karatsuba-len=?*) karatsuba_len="$LONG_OPTARG" ;;
1023				karatsuba-len)
1024					if [ "$#" -lt 2 ]; then
1025						usage "No argument given for '--$arg' option"
1026					fi
1027					karatsuba_len="$1"
1028					shift ;;
1029				opt=?*) optimization="$LONG_OPTARG" ;;
1030				opt)
1031					if [ "$#" -lt 2 ]; then
1032						usage "No argument given for '--$arg' option"
1033					fi
1034					optimization="$1"
1035					shift ;;
1036				set-default-on=?*) set_default 1 "$LONG_OPTARG" ;;
1037				set-default-on)
1038					if [ "$#" -lt 2 ]; then
1039						usage "No argument given for '--$arg' option"
1040					fi
1041					set_default 1 "$1"
1042					shift ;;
1043				set-default-off=?*) set_default 0 "$LONG_OPTARG" ;;
1044				set-default-off)
1045					if [ "$#" -lt 2 ]; then
1046						usage "No argument given for '--$arg' option"
1047					fi
1048					set_default 0 "$1"
1049					shift ;;
1050				predefined-build-type=?*) predefined_build "$LONG_OPTARG" ;;
1051				predefined-build-type)
1052					if [ "$#" -lt 2 ]; then
1053						usage "No argument given for '--$arg' option"
1054					fi
1055					predefined_build "$1"
1056					shift ;;
1057				disable-bc) dc_only=1 ;;
1058				disable-dc) bc_only=1 ;;
1059				disable-clean) clean=0 ;;
1060				disable-extra-math) extra_math=0 ;;
1061				disable-generated-tests) generate_tests=0 ;;
1062				disable-history) hist=0 ;;
1063				disable-man-pages) install_manpages=0 ;;
1064				disable-nls) nls=0 ;;
1065				disable-strip) strip_bin=0 ;;
1066				disable-problematic-tests) problematic_tests=0 ;;
1067				enable-editline) hist_impl="editline" ;;
1068				enable-readline) hist_impl="readline" ;;
1069				enable-internal-history) hist_impl="internal" ;;
1070				enable-test-timing) time_tests=1 ;;
1071				enable-valgrind) vg=1 ;;
1072				enable-fuzz-mode) fuzz=1 ;;
1073				enable-memcheck) memcheck=1 ;;
1074				install-all-locales) all_locales=1 ;;
1075				help* | bc-only* | dc-only* | coverage* | debug*)
1076					usage "No arg allowed for --$arg option" ;;
1077				disable-bc* | disable-dc* | disable-clean*)
1078					usage "No arg allowed for --$arg option" ;;
1079				disable-extra-math*)
1080					usage "No arg allowed for --$arg option" ;;
1081				disable-generated-tests* | disable-history*)
1082					usage "No arg allowed for --$arg option" ;;
1083				disable-man-pages* | disable-nls* | disable-strip*)
1084					usage "No arg allowed for --$arg option" ;;
1085				disable-problematic-tests*)
1086					usage "No arg allowed for --$arg option" ;;
1087				enable-fuzz-mode* | enable-test-timing* | enable-valgrind*)
1088					usage "No arg allowed for --$arg option" ;;
1089				enable-memcheck* | install-all-locales*)
1090					usage "No arg allowed for --$arg option" ;;
1091				enable-editline* | enable-readline*)
1092					usage "No arg allowed for --$arg option" ;;
1093				enable-internal-history*)
1094					usage "No arg allowed for --$arg option" ;;
1095				'') break ;; # "--" terminates argument processing
1096				* ) usage "Invalid option $LONG_OPTARG" ;;
1097			esac
1098			shift
1099			OPTIND=1 ;;
1100		?) usage "Invalid option: $opt" ;;
1101	esac
1102
1103done
1104
1105# Sometimes, developers don't want configure.sh to do a config clean. But
1106# sometimes they do.
1107if [ "$clean" -ne 0 ]; then
1108	if [ -f ./Makefile ]; then
1109		make clean_config > /dev/null
1110	fi
1111fi
1112
1113# It is an error to say that bc only should be built and likewise for dc.
1114if [ "$bc_only" -eq 1 ] && [ "$dc_only" -eq 1 ]; then
1115	usage "Can only specify one of -b(-D) or -d(-B)"
1116fi
1117
1118# The library is mutually exclusive to the calculators, so it's an error to
1119# give an option for either of them.
1120if [ "$library" -ne 0 ]; then
1121	if [ "$bc_only" -eq 1 ] || [ "$dc_only" -eq 1 ]; then
1122		usage "Must not specify -b(-D) or -d(-B) when building the library"
1123	fi
1124fi
1125
1126# KARATSUBA_LEN must be an integer and must be 16 or greater.
1127case $karatsuba_len in
1128	(*[!0-9]*|'') usage "KARATSUBA_LEN is not a number" ;;
1129	(*) ;;
1130esac
1131
1132if [ "$karatsuba_len" -lt 16 ]; then
1133	usage "KARATSUBA_LEN is less than 16"
1134fi
1135
1136set -e
1137
1138if [ -z "${LONG_BIT+set}" ]; then
1139	LONG_BIT_DEFINE=""
1140elif [ "$LONG_BIT" -lt 32 ]; then
1141	usage "LONG_BIT is less than 32"
1142else
1143	LONG_BIT_DEFINE="-DBC_LONG_BIT=$LONG_BIT"
1144fi
1145
1146if [ -z "$CC" ]; then
1147	CC="c99"
1148else
1149
1150	# I had users complain that, if they gave CFLAGS as part of CC, which
1151	# autotools allows in its braindead way, the build would fail with an error.
1152	# I don't like adjusting for autotools, but oh well. These lines puts the
1153	# stuff after the first space into CFLAGS.
1154	ccbase=$(basename "$CC")
1155	suffix=" *"
1156	prefix="* "
1157
1158	if [ "${ccbase%%$suffix}" != "$ccbase" ]; then
1159		ccflags="${ccbase#$prefix}"
1160		cc="${ccbase%%$suffix}"
1161		ccdir=$(dirname "$CC")
1162		if [ "$ccdir" = "." ] && [ "${CC#.}" = "$CC" ]; then
1163			ccdir=""
1164		else
1165			ccdir="$ccdir/"
1166		fi
1167		CC="${ccdir}${cc}"
1168		CFLAGS="$CFLAGS $ccflags"
1169	fi
1170fi
1171
1172if [ -z "$HOSTCC" ] && [ -z "$HOST_CC" ]; then
1173	HOSTCC="$CC"
1174elif [ -z "$HOSTCC" ]; then
1175	HOSTCC="$HOST_CC"
1176fi
1177
1178if [ "$HOSTCC" != "$CC" ]; then
1179
1180	# Like above, this splits HOSTCC and HOSTCFLAGS.
1181	ccbase=$(basename "$HOSTCC")
1182	suffix=" *"
1183	prefix="* "
1184
1185	if [ "${ccbase%%$suffix}" != "$ccbase" ]; then
1186		ccflags="${ccbase#$prefix}"
1187		cc="${ccbase%%$suffix}"
1188		ccdir=$(dirname "$HOSTCC")
1189		if [ "$ccdir" = "." ] && [ "${HOSTCC#.}" = "$HOSTCC" ]; then
1190			ccdir=""
1191		else
1192			ccdir="$ccdir/"
1193		fi
1194		HOSTCC="${ccdir}${cc}"
1195		HOSTCFLAGS="$HOSTCFLAGS $ccflags"
1196	fi
1197fi
1198
1199if [ -z "${HOSTCFLAGS+set}" ] && [ -z "${HOST_CFLAGS+set}" ]; then
1200	HOSTCFLAGS="$CFLAGS"
1201elif [ -z "${HOSTCFLAGS+set}" ]; then
1202	HOSTCFLAGS="$HOST_CFLAGS"
1203fi
1204
1205# Store these for the cross compilation detection later.
1206OLDCFLAGS="$CFLAGS"
1207OLDHOSTCFLAGS="$HOSTCFLAGS"
1208
1209link="@printf 'No link necessary\\\\n'"
1210main_exec="BC"
1211executable="BC_EXEC"
1212
1213tests="test_bc timeconst test_dc"
1214
1215bc_test="@export BC_TEST_OUTPUT_DIR=\"$builddir/tests\"; \$(TESTSDIR)/all.sh bc $extra_math 1 $generate_tests $problematic_tests $time_tests \$(BC_EXEC)"
1216bc_test_np="@export BC_TEST_OUTPUT_DIR=\"$builddir/tests\"; \$(TESTSDIR)/all.sh -n bc $extra_math 1 $generate_tests $problematic_tests $time_tests \$(BC_EXEC)"
1217dc_test="@export BC_TEST_OUTPUT_DIR=\"$builddir/tests\"; \$(TESTSDIR)/all.sh dc $extra_math 1 $generate_tests $problematic_tests $time_tests \$(DC_EXEC)"
1218dc_test_np="@export BC_TEST_OUTPUT_DIR=\"$builddir/tests\"; \$(TESTSDIR)/all.sh -n dc $extra_math 1 $generate_tests $problematic_tests $time_tests \$(DC_EXEC)"
1219
1220timeconst="@export BC_TEST_OUTPUT_DIR=\"$builddir/tests\"; \$(TESTSDIR)/bc/timeconst.sh \$(TESTSDIR)/bc/scripts/timeconst.bc \$(BC_EXEC)"
1221
1222# In order to have cleanup at exit, we need to be in
1223# debug mode, so don't run valgrind without that.
1224if [ "$vg" -ne 0 ]; then
1225	debug=1
1226	bc_test_exec='valgrind $(VALGRIND_ARGS) $(BC_EXEC)'
1227	dc_test_exec='valgrind $(VALGRIND_ARGS) $(DC_EXEC)'
1228	bcl_test_exec='valgrind $(VALGRIND_ARGS) $(BCL_TEST)'
1229else
1230	bc_test_exec='$(BC_EXEC)'
1231	dc_test_exec='$(DC_EXEC)'
1232	bcl_test_exec='$(BCL_TEST)'
1233fi
1234
1235test_bc_history_prereqs="test_bc_history_all"
1236test_dc_history_prereqs="test_dc_history_all"
1237
1238karatsuba="@printf 'karatsuba cannot be run because one of bc or dc is not built\\\\n'"
1239karatsuba_test="@printf 'karatsuba cannot be run because one of bc or dc is not built\\\\n'"
1240
1241bc_lib="\$(GEN_DIR)/lib.o"
1242bc_help="\$(GEN_DIR)/bc_help.o"
1243dc_help="\$(GEN_DIR)/dc_help.o"
1244
1245default_target_prereqs="\$(BIN) \$(OBJS)"
1246default_target_cmd="\$(CC) \$(CFLAGS) \$(OBJS) \$(LDFLAGS) -o \$(EXEC)"
1247default_target="\$(DC_EXEC)"
1248
1249second_target_prereqs=""
1250second_target_cmd="$default_target_cmd"
1251second_target="\$(BC_EXEC)"
1252
1253# This if/else if chain is for setting the defaults that change based on whether
1254# the library is being built, bc only, dc only, or both calculators.
1255if [ "$library" -ne 0 ]; then
1256
1257	extra_math=1
1258	nls=0
1259	hist=0
1260	bc=1
1261	dc=1
1262
1263	default_target_prereqs="\$(BIN) \$(OBJ)"
1264	default_target_cmd="ar -r -cu \$(LIBBC) \$(OBJ)"
1265	default_target="\$(LIBBC)"
1266	tests="test_library"
1267	test_bc_history_prereqs=" test_bc_history_skip"
1268	test_dc_history_prereqs=" test_dc_history_skip"
1269
1270	install_prereqs=" install_library"
1271	uninstall_prereqs=" uninstall_library"
1272	install_man_prereqs=" install_bcl_manpage"
1273	uninstall_man_prereqs=" uninstall_bcl_manpage"
1274
1275elif [ "$bc_only" -eq 1 ]; then
1276
1277	bc=1
1278	dc=0
1279
1280	dc_help=""
1281
1282	executables="bc"
1283
1284	dc_test="@printf 'No dc tests to run\\\\n'"
1285	dc_test_np="@printf 'No dc tests to run\\\\n'"
1286	test_dc_history_prereqs=" test_dc_history_skip"
1287
1288	install_prereqs=" install_execs"
1289	install_man_prereqs=" install_bc_manpage"
1290	uninstall_prereqs=" uninstall_bc"
1291	uninstall_man_prereqs=" uninstall_bc_manpage"
1292
1293	default_target="\$(BC_EXEC)"
1294	second_target="\$(DC_EXEC)"
1295	tests="test_bc timeconst"
1296
1297elif [ "$dc_only" -eq 1 ]; then
1298
1299	bc=0
1300	dc=1
1301
1302	bc_lib=""
1303	bc_help=""
1304
1305	executables="dc"
1306
1307	main_exec="DC"
1308	executable="DC_EXEC"
1309
1310	bc_test="@printf 'No bc tests to run\\\\n'"
1311	bc_test_np="@printf 'No bc tests to run\\\\n'"
1312	test_bc_history_prereqs=" test_bc_history_skip"
1313
1314	timeconst="@printf 'timeconst cannot be run because bc is not built\\\\n'"
1315
1316	install_prereqs=" install_execs"
1317	install_man_prereqs=" install_dc_manpage"
1318	uninstall_prereqs=" uninstall_dc"
1319	uninstall_man_prereqs=" uninstall_dc_manpage"
1320
1321	tests="test_dc"
1322
1323else
1324
1325	bc=1
1326	dc=1
1327
1328	executables="bc and dc"
1329
1330	karatsuba="@\$(KARATSUBA) 30 0 \$(BC_EXEC)"
1331	karatsuba_test="@\$(KARATSUBA) 1 100 \$(BC_EXEC)"
1332
1333	if [ "$library" -eq 0 ]; then
1334		install_prereqs=" install_execs"
1335		install_man_prereqs=" install_bc_manpage install_dc_manpage"
1336		uninstall_prereqs=" uninstall_bc uninstall_dc"
1337		uninstall_man_prereqs=" uninstall_bc_manpage uninstall_dc_manpage"
1338	else
1339		install_prereqs=" install_library install_bcl_header"
1340		install_man_prereqs=" install_bcl_manpage"
1341		uninstall_prereqs=" uninstall_library uninstall_bcl_header"
1342		uninstall_man_prereqs=" uninstall_bcl_manpage"
1343		tests="test_library"
1344	fi
1345
1346	second_target_prereqs="$default_target_prereqs"
1347	default_target_prereqs="$second_target"
1348	default_target_cmd="\$(LINK) \$(BIN) \$(EXEC_PREFIX)\$(DC)"
1349
1350fi
1351
1352# We need specific stuff for fuzzing.
1353if [ "$fuzz" -ne 0 ]; then
1354	debug=1
1355	hist=0
1356	nls=0
1357	optimization="3"
1358fi
1359
1360# This sets some necessary things for debug mode.
1361if [ "$debug" -eq 1 ]; then
1362
1363	if [ -z "$CFLAGS" ] && [ -z "$optimization" ]; then
1364		CFLAGS="-O0"
1365	fi
1366
1367	ccbase=$(basename "$CC")
1368
1369	if [ "$ccbase" = "clang" ]; then
1370		CFLAGS="-gdwarf-4 $CFLAGS"
1371	else
1372		CFLAGS="-g $CFLAGS"
1373	fi
1374
1375else
1376
1377	CPPFLAGS="-DNDEBUG $CPPFLAGS"
1378
1379	if [ "$strip_bin" -ne 0 ]; then
1380		LDFLAGS="-s $LDFLAGS"
1381	fi
1382fi
1383
1384# Set optimization CFLAGS.
1385if [ -n "$optimization" ]; then
1386	CFLAGS="-O$optimization $CFLAGS"
1387fi
1388
1389# Set test coverage defaults.
1390if [ "$coverage" -eq 1 ]; then
1391
1392	if [ "$bc_only" -eq 1 ] || [ "$dc_only" -eq 1 ]; then
1393		usage "Can only specify -c without -b or -d"
1394	fi
1395
1396	CFLAGS="-fprofile-arcs -ftest-coverage -g -O0 $CFLAGS"
1397	CPPFLAGS="-DNDEBUG $CPPFLAGS"
1398
1399	COVERAGE_OUTPUT="@gcov -pabcdf \$(GCDA) \$(BC_GCDA) \$(DC_GCDA) \$(HISTORY_GCDA) \$(RAND_GCDA)"
1400	COVERAGE_OUTPUT="$COVERAGE_OUTPUT;\$(RM) -f \$(GEN)*.gc*"
1401	COVERAGE_OUTPUT="$COVERAGE_OUTPUT;gcovr --exclude-unreachable-branches --exclude-throw-branches --html-details --output index.html"
1402	COVERAGE_PREREQS=" test coverage_output"
1403
1404else
1405	COVERAGE_OUTPUT="@printf 'Coverage not generated\\\\n'"
1406	COVERAGE_PREREQS=""
1407fi
1408
1409
1410# Set some defaults.
1411if [ -z "${DESTDIR+set}" ]; then
1412	destdir=""
1413else
1414	destdir="DESTDIR = $DESTDIR"
1415fi
1416
1417# defprefix is for a warning about locales later.
1418if [ -z "${PREFIX+set}" ]; then
1419	PREFIX="/usr/local"
1420	defprefix=1
1421else
1422	defprefix=0
1423fi
1424
1425if [ -z "${BINDIR+set}" ]; then
1426	BINDIR="$PREFIX/bin"
1427fi
1428
1429if [ -z "${INCLUDEDIR+set}" ]; then
1430	INCLUDEDIR="$PREFIX/include"
1431fi
1432
1433if [ -z "${LIBDIR+set}" ]; then
1434	LIBDIR="$PREFIX/lib"
1435fi
1436
1437if [ -z "${PC_PATH+set}" ]; then
1438
1439	set +e
1440
1441	command -v pkg-config > /dev/null
1442	err=$?
1443
1444	set -e
1445
1446	if [ "$err" -eq 0 ]; then
1447		PC_PATH=$(pkg-config --variable=pc_path pkg-config)
1448		PC_PATH="${PC_PATH%%:*}"
1449	else
1450		PC_PATH=""
1451	fi
1452
1453fi
1454
1455# Set a default for the DATAROOTDIR. This is done if either manpages will be
1456# installed, or locales are enabled because that's probably where NLSPATH
1457# points.
1458if [ "$install_manpages" -ne 0 ] || [ "$nls" -ne 0 ]; then
1459	if [ -z "${DATAROOTDIR+set}" ]; then
1460		DATAROOTDIR="$PREFIX/share"
1461	fi
1462fi
1463
1464# Set defaults for manpage environment variables.
1465if [ "$install_manpages" -ne 0 ]; then
1466
1467	if [ -z "${DATADIR+set}" ]; then
1468		DATADIR="$DATAROOTDIR"
1469	fi
1470
1471	if [ -z "${MANDIR+set}" ]; then
1472		MANDIR="$DATADIR/man"
1473	fi
1474
1475	if [ -z "${MAN1DIR+set}" ]; then
1476		MAN1DIR="$MANDIR/man1"
1477	fi
1478
1479	if [ -z "${MAN3DIR+set}" ]; then
1480		MAN3DIR="$MANDIR/man3"
1481	fi
1482
1483else
1484	install_man_prereqs=""
1485	uninstall_man_prereqs=""
1486fi
1487
1488# Here is where we test NLS (the locale system). This is done by trying to
1489# compile src/vm.c, which has the relevant code. If it fails, then it is
1490# disabled.
1491if [ "$nls" -ne 0 ]; then
1492
1493	set +e
1494
1495	printf 'Testing NLS...\n'
1496
1497	flags="-DBC_ENABLE_NLS=1 -DBC_ENABLED=$bc -DDC_ENABLED=$dc"
1498	flags="$flags -DBC_ENABLE_HISTORY=$hist -DBC_ENABLE_LIBRARY=0 -DBC_ENABLE_AFL=0"
1499	flags="$flags -DBC_ENABLE_EXTRA_MATH=$extra_math -I$scriptdir/include/"
1500	flags="$flags -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700"
1501
1502	ccbase=$(basename "$CC")
1503
1504	if [ "$ccbase" = "clang" ]; then
1505		flags="$flags -Wno-unreachable-code"
1506	fi
1507
1508	"$CC" $CPPFLAGS $CFLAGS $flags -c "$scriptdir/src/vm.c" -o "./vm.o" > /dev/null 2>&1
1509
1510	err="$?"
1511
1512	rm -rf "./vm.o"
1513
1514	# If this errors, it is probably because of building on Windows,
1515	# and NLS is not supported on Windows, so disable it.
1516	if [ "$err" -ne 0 ]; then
1517		printf 'NLS does not work.\n'
1518		if [ $force -eq 0 ]; then
1519			printf 'Disabling NLS...\n\n'
1520			nls=0
1521		else
1522			printf 'Forcing NLS...\n\n'
1523		fi
1524	else
1525		printf 'NLS works.\n\n'
1526
1527		printf 'Testing gencat...\n'
1528		gencat "./en_US.cat" "$scriptdir/locales/en_US.msg" > /dev/null 2>&1
1529
1530		err="$?"
1531
1532		rm -rf "./en_US.cat"
1533
1534		if [ "$err" -ne 0 ]; then
1535			printf 'gencat does not work.\n'
1536			if [ $force -eq 0 ]; then
1537				printf 'Disabling NLS...\n\n'
1538				nls=0
1539			else
1540				printf 'Forcing NLS...\n\n'
1541			fi
1542		else
1543
1544			printf 'gencat works.\n\n'
1545
1546			# It turns out that POSIX locales are really terrible, and running
1547			# gencat on one machine is not guaranteed to make those cat files
1548			# portable to another machine, so we had better warn the user here.
1549			if [ "$HOSTCC" != "$CC" ] || [ "$OLDHOSTCFLAGS" != "$OLDCFLAGS" ]; then
1550				printf 'Cross-compile detected.\n\n'
1551				printf 'WARNING: Catalog files generated with gencat may not be portable\n'
1552				printf '         across different architectures.\n\n'
1553			fi
1554
1555			if [ -z "$NLSPATH" ]; then
1556				NLSPATH="/usr/share/locale/%L/%N"
1557			fi
1558
1559			install_locales_prereqs=" install_locales"
1560			uninstall_locales_prereqs=" uninstall_locales"
1561
1562		fi
1563
1564	fi
1565
1566	set -e
1567
1568else
1569	install_locales_prereqs=""
1570	uninstall_locales_prereqs=""
1571	all_locales=0
1572fi
1573
1574if [ "$nls" -ne 0 ] && [ "$all_locales" -ne 0 ]; then
1575	install_locales="\$(LOCALE_INSTALL) -l \$(NLSPATH) \$(MAIN_EXEC) \$(DESTDIR)"
1576else
1577	install_locales="\$(LOCALE_INSTALL) \$(NLSPATH) \$(MAIN_EXEC) \$(DESTDIR)"
1578fi
1579
1580# Like the above tested locale support, this tests history.
1581if [ "$hist" -eq 1 ]; then
1582
1583	if [ "$hist_impl" = "editline" ]; then
1584		editline=1
1585		readline=0
1586	elif [ "$hist_impl" = "readline" ]; then
1587		editline=0
1588		readline=1
1589	else
1590		editline=0
1591		readline=0
1592	fi
1593
1594	set +e
1595
1596	printf 'Testing history...\n'
1597
1598	flags="-DBC_ENABLE_HISTORY=1 -DBC_ENABLED=$bc -DDC_ENABLED=$dc"
1599	flags="$flags -DBC_ENABLE_NLS=$nls -DBC_ENABLE_LIBRARY=0 -DBC_ENABLE_AFL=0"
1600	flags="$flags -DBC_ENABLE_EDITLINE=$editline -DBC_ENABLE_READLINE=$readline"
1601	flags="$flags -DBC_ENABLE_EXTRA_MATH=$extra_math -I$scriptdir/include/"
1602	flags="$flags -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700"
1603
1604	"$CC" $CPPFLAGS $CFLAGS $flags -c "$scriptdir/src/history.c" -o "./history.o" > /dev/null 2>&1
1605
1606	err="$?"
1607
1608	rm -rf "./history.o"
1609
1610	# If this errors, it is probably because of building on Windows,
1611	# and history is not supported on Windows, so disable it.
1612	if [ "$err" -ne 0 ]; then
1613		printf 'History does not work.\n'
1614		if [ $force -eq 0 ]; then
1615			printf 'Disabling history...\n\n'
1616			hist=0
1617		else
1618			printf 'Forcing history...\n\n'
1619		fi
1620	else
1621		printf 'History works.\n\n'
1622	fi
1623
1624	set -e
1625
1626else
1627
1628	editline=0
1629	readline=0
1630
1631fi
1632
1633# We have to disable the history tests if it is disabled or valgrind is on. Or
1634# if we are using editline or readline.
1635if [ "$hist" -eq 0 ] || [ "$vg" -ne 0 ]; then
1636	test_bc_history_prereqs=" test_bc_history_skip"
1637	test_dc_history_prereqs=" test_dc_history_skip"
1638	history_tests="@printf 'Skipping history tests...\\\\n'"
1639	CFLAGS="$CFLAGS -DBC_ENABLE_EDITLINE=0 -DBC_ENABLE_READLINE=0"
1640else
1641
1642	if [ "$editline" -eq 0 ] && [ "$readline" -eq 0 ]; then
1643		history_tests="@printf '\$(TEST_STARS)\\\\n\\\\nRunning history tests...\\\\n\\\\n'"
1644		history_tests="$history_tests \&\& \$(TESTSDIR)/history.sh bc -a \&\&"
1645		history_tests="$history_tests \$(TESTSDIR)/history.sh dc -a \&\& printf"
1646		history_tests="$history_tests '\\\\nAll history tests passed.\\\\n\\\\n\$(TEST_STARS)\\\\n'"
1647	else
1648		test_bc_history_prereqs=" test_bc_history_skip"
1649		test_dc_history_prereqs=" test_dc_history_skip"
1650		history_tests="@printf 'Skipping history tests...\\\\n'"
1651	fi
1652
1653	# We are also setting the CFLAGS and LDFLAGS here.
1654	if [ "$editline" -ne 0 ]; then
1655		LDFLAGS="$LDFLAGS -ledit"
1656		CFLAGS="$CFLAGS -DBC_ENABLE_EDITLINE=1 -DBC_ENABLE_READLINE=0"
1657	elif [ "$readline" -ne 0 ]; then
1658		LDFLAGS="$LDFLAGS -lreadline"
1659		CFLAGS="$CFLAGS -DBC_ENABLE_EDITLINE=0 -DBC_ENABLE_READLINE=1"
1660	else
1661		CFLAGS="$CFLAGS -DBC_ENABLE_EDITLINE=0 -DBC_ENABLE_READLINE=0"
1662	fi
1663
1664fi
1665
1666# Test FreeBSD. This is not in an if statement because regardless of whatever
1667# the user says, we need to know if we are on FreeBSD. If we are, we cannot set
1668# _POSIX_C_SOURCE and _XOPEN_SOURCE. The FreeBSD headers turn *off* stuff when
1669# that is done.
1670set +e
1671printf 'Testing for FreeBSD...\n'
1672
1673flags="-DBC_TEST_FREEBSD -DBC_ENABLE_AFL=0"
1674"$CC" $CPPFLAGS $CFLAGS $flags "-I$scriptdir/include" -E "$scriptdir/src/vm.c" > /dev/null 2>&1
1675
1676err="$?"
1677
1678if [ "$err" -ne 0 ]; then
1679	printf 'On FreeBSD. Not using _POSIX_C_SOURCE and _XOPEN_SOURCE.\n\n'
1680else
1681	printf 'Not on FreeBSD. Using _POSIX_C_SOURCE and _XOPEN_SOURCE.\n\n'
1682	CPPFLAGS="$CPPFLAGS -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700"
1683fi
1684
1685# Test OpenBSD. This is not in an if statement because regardless of whatever
1686# the user says, we need to know if we are on OpenBSD to activate _BSD_SOURCE.
1687# No, I cannot `#define _BSD_SOURCE` in a header because OpenBSD's patched GCC
1688# and Clang complain that that is only allowed for system headers. Sigh....So we
1689# have to check at configure time and set it on the compiler command-line. And
1690# we have to set it because we also set _POSIX_C_SOURCE, which OpenBSD headers
1691# detect, and when they detect it, they turn off _BSD_SOURCE unless it is
1692# specifically requested.
1693set +e
1694printf 'Testing for OpenBSD...\n'
1695
1696flags="-DBC_TEST_OPENBSD -DBC_ENABLE_AFL=0"
1697"$CC" $CPPFLAGS $CFLAGS $flags "-I$scriptdir/include" -E "$scriptdir/src/vm.c" > /dev/null 2>&1
1698
1699err="$?"
1700
1701if [ "$err" -ne 0 ]; then
1702
1703	printf 'On OpenBSD. Using _BSD_SOURCE.\n\n'
1704	bsd="-D_BSD_SOURCE"
1705
1706	# Readline errors on OpenBSD, for some weird reason.
1707	if [ "$readline" -ne 0 ]; then
1708		usage "Cannot use readline on OpenBSD"
1709	fi
1710
1711else
1712	printf 'Not on OpenBSD.\n\n'
1713	bsd=""
1714fi
1715
1716if [ "$library" -eq 1 ]; then
1717	bc_lib=""
1718fi
1719
1720if [ "$extra_math" -eq 1 ] && [ "$bc" -ne 0 ] && [ "$library" -eq 0 ]; then
1721	BC_LIB2_O="\$(GEN_DIR)/lib2.o"
1722else
1723	BC_LIB2_O=""
1724fi
1725
1726GEN_DIR="$scriptdir/gen"
1727
1728# These lines set the appropriate targets based on whether `gen/strgen.c` or
1729# `gen/strgen.sh` is used.
1730GEN="strgen"
1731GEN_EXEC_TARGET="\$(HOSTCC) -DBC_ENABLE_AFL=0 -I$scriptdir/include/  \$(HOSTCFLAGS) -o \$(GEN_EXEC) \$(GEN_C)"
1732CLEAN_PREREQS=" clean_gen clean_coverage"
1733
1734if [ -z "${GEN_HOST+set}" ]; then
1735	GEN_HOST=1
1736else
1737	if [ "$GEN_HOST" -eq 0 ]; then
1738		GEN="strgen.sh"
1739		GEN_EXEC_TARGET="@printf 'Do not need to build gen/strgen.c\\\\n'"
1740		CLEAN_PREREQS=" clean_coverage"
1741	fi
1742fi
1743
1744manpage_args=""
1745unneeded=""
1746headers="\$(HEADERS)"
1747
1748# This series of if statements figure out what source files are *not* needed.
1749if [ "$extra_math" -eq 0 ]; then
1750	exclude_extra_math=1
1751	manpage_args="E"
1752	unneeded="$unneeded rand.c"
1753else
1754	exclude_extra_math=0
1755	headers="$headers \$(EXTRA_MATH_HEADERS)"
1756fi
1757
1758# All of these next if statements set the build type and mark certain source
1759# files as unneeded so that they won't have targets generated for them.
1760
1761if [ "$hist" -eq 0 ]; then
1762	manpage_args="${manpage_args}H"
1763	unneeded="$unneeded history.c"
1764else
1765	headers="$headers \$(HISTORY_HEADERS)"
1766fi
1767
1768if [ "$nls" -eq 0 ]; then
1769	manpage_args="${manpage_args}N"
1770fi
1771
1772if [ "$bc" -eq 0 ]; then
1773	unneeded="$unneeded bc.c bc_lex.c bc_parse.c"
1774else
1775	headers="$headers \$(BC_HEADERS)"
1776fi
1777
1778if [ "$dc" -eq 0 ]; then
1779	unneeded="$unneeded dc.c dc_lex.c dc_parse.c"
1780else
1781	headers="$headers \$(DC_HEADERS)"
1782fi
1783
1784# This convoluted mess does pull the version out. If you change the format of
1785# include/version.h, you may have to change this line.
1786version=$(cat "$scriptdir/include/version.h" | grep "VERSION " - | awk '{ print $3 }' -)
1787
1788if [ "$library" -ne 0 ]; then
1789
1790	unneeded="$unneeded args.c opt.c read.c file.c main.c"
1791	unneeded="$unneeded lang.c lex.c parse.c program.c"
1792	unneeded="$unneeded bc.c bc_lex.c bc_parse.c"
1793	unneeded="$unneeded dc.c dc_lex.c dc_parse.c"
1794	headers="$headers \$(LIBRARY_HEADERS)"
1795
1796	if [ "$PC_PATH" != "" ]; then
1797
1798		contents=$(cat "$scriptdir/bcl.pc.in")
1799
1800		contents=$(replace "$contents" "INCLUDEDIR" "$INCLUDEDIR")
1801		contents=$(replace "$contents" "LIBDIR" "$LIBDIR")
1802		contents=$(replace "$contents" "VERSION" "$version")
1803
1804		printf '%s\n' "$contents" > "./bcl.pc"
1805
1806		pkg_config_install="\$(SAFE_INSTALL) \$(PC_INSTALL_ARGS) \"\$(BCL_PC)\" \"\$(DESTDIR)\$(PC_PATH)/\$(BCL_PC)\""
1807		pkg_config_uninstall="\$(RM) -f \"\$(DESTDIR)\$(PC_PATH)/\$(BCL_PC)\""
1808
1809	else
1810
1811		pkg_config_install=""
1812		pkg_config_uninstall=""
1813
1814	fi
1815
1816else
1817
1818	unneeded="$unneeded library.c"
1819
1820	PC_PATH=""
1821	pkg_config_install=""
1822	pkg_config_uninstall=""
1823
1824fi
1825
1826# library.c is not needed under normal circumstances.
1827if [ "$unneeded" = "" ]; then
1828	unneeded="library.c"
1829fi
1830
1831# This sets the appropriate manpage for a full build.
1832if [ "$manpage_args" = "" ]; then
1833	manpage_args="A"
1834fi
1835
1836if [ "$vg" -ne 0 ]; then
1837	memcheck=1
1838fi
1839
1840if [ "$bc_default_prompt" = "" ]; then
1841	bc_default_prompt="$bc_default_tty_mode"
1842fi
1843
1844if [ "$dc_default_prompt" = "" ]; then
1845	dc_default_prompt="$dc_default_tty_mode"
1846fi
1847
1848# Generate the test targets and prerequisites.
1849bc_tests=$(gen_std_test_targets bc)
1850bc_script_tests=$(gen_script_test_targets bc)
1851bc_err_tests=$(gen_err_test_targets bc)
1852dc_tests=$(gen_std_test_targets dc)
1853dc_script_tests=$(gen_script_test_targets dc)
1854dc_err_tests=$(gen_err_test_targets dc)
1855
1856# Print out the values; this is for debugging.
1857printf 'Version: %s\n' "$version"
1858
1859if [ "$bc" -ne 0 ]; then
1860	printf 'Building bc\n'
1861else
1862	printf 'Not building bc\n'
1863fi
1864if [ "$dc" -ne 0 ]; then
1865	printf 'Building dc\n'
1866else
1867	printf 'Not building dc\n'
1868fi
1869printf '\n'
1870printf 'BC_ENABLE_LIBRARY=%s\n\n' "$library"
1871printf 'BC_ENABLE_HISTORY=%s\n' "$hist"
1872printf 'BC_ENABLE_EXTRA_MATH=%s\n' "$extra_math"
1873printf 'BC_ENABLE_NLS=%s\n\n' "$nls"
1874printf 'BC_ENABLE_AFL=%s\n' "$fuzz"
1875printf '\n'
1876printf 'BC_NUM_KARATSUBA_LEN=%s\n' "$karatsuba_len"
1877printf '\n'
1878printf 'CC=%s\n' "$CC"
1879printf 'CFLAGS=%s\n' "$CFLAGS"
1880printf 'HOSTCC=%s\n' "$HOSTCC"
1881printf 'HOSTCFLAGS=%s\n' "$HOSTCFLAGS"
1882printf 'CPPFLAGS=%s\n' "$CPPFLAGS"
1883printf 'LDFLAGS=%s\n' "$LDFLAGS"
1884printf 'PREFIX=%s\n' "$PREFIX"
1885printf 'BINDIR=%s\n' "$BINDIR"
1886printf 'INCLUDEDIR=%s\n' "$INCLUDEDIR"
1887printf 'LIBDIR=%s\n' "$LIBDIR"
1888printf 'DATAROOTDIR=%s\n' "$DATAROOTDIR"
1889printf 'DATADIR=%s\n' "$DATADIR"
1890printf 'MANDIR=%s\n' "$MANDIR"
1891printf 'MAN1DIR=%s\n' "$MAN1DIR"
1892printf 'MAN3DIR=%s\n' "$MAN3DIR"
1893printf 'NLSPATH=%s\n' "$NLSPATH"
1894printf 'PC_PATH=%s\n' "$PC_PATH"
1895printf 'EXECSUFFIX=%s\n' "$EXECSUFFIX"
1896printf 'EXECPREFIX=%s\n' "$EXECPREFIX"
1897printf 'DESTDIR=%s\n' "$DESTDIR"
1898printf 'LONG_BIT=%s\n' "$LONG_BIT"
1899printf 'GEN_HOST=%s\n' "$GEN_HOST"
1900printf 'GEN_EMU=%s\n' "$GEN_EMU"
1901printf '\n'
1902printf 'Setting Defaults\n'
1903printf '================\n'
1904printf 'bc.banner=%s\n' "$bc_default_banner"
1905printf 'bc.sigint_reset=%s\n' "$bc_default_sigint_reset"
1906printf 'dc.sigint_reset=%s\n' "$dc_default_sigint_reset"
1907printf 'bc.tty_mode=%s\n' "$bc_default_tty_mode"
1908printf 'dc.tty_mode=%s\n' "$dc_default_tty_mode"
1909printf 'bc.prompt=%s\n' "$bc_default_prompt"
1910printf 'dc.prompt=%s\n' "$dc_default_prompt"
1911printf 'bc.expr_exit=%s\n' "$bc_default_expr_exit"
1912printf 'dc.expr_exit=%s\n' "$dc_default_expr_exit"
1913printf 'bc.digit_clamp=%s\n' "$bc_default_digit_clamp"
1914printf 'dc.digit_clamp=%s\n' "$dc_default_digit_clamp"
1915
1916# This code outputs a warning. The warning is to not surprise users when locales
1917# are installed outside of the prefix. This warning is suppressed when the
1918# default prefix is used, as well, so as not to panic users just installing by
1919# hand. I believe this will be okay because NLSPATH is usually in /usr and the
1920# default prefix is /usr/local, so they'll be close that way.
1921if [ "$nls" -ne 0 ] && [ "${NLSPATH#$PREFIX}" = "${NLSPATH}" ] && [ "$defprefix" -eq 0 ]; then
1922	printf '\n********************************************************************************\n\n'
1923	printf 'WARNING: Locales will *NOT* be installed in $PREFIX (%s).\n' "$PREFIX"
1924	printf '\n'
1925	printf '         This is because they *MUST* be installed at a fixed location to even\n'
1926	printf '         work, and that fixed location is $NLSPATH (%s).\n' "$NLSPATH"
1927	printf '\n'
1928	printf '         This location is *outside* of $PREFIX. If you do not wish to install\n'
1929	printf '         locales outside of $PREFIX, you must disable NLS with the -N or the\n'
1930	printf '         --disable-nls options.\n'
1931	printf '\n'
1932	printf '         The author apologizes for the inconvenience, but the need to install\n'
1933	printf '         the locales at a fixed location is mandated by POSIX, and it is not\n'
1934	printf '         possible for the author to change that requirement.\n'
1935	printf '\n********************************************************************************\n'
1936fi
1937
1938# This is where the real work begins. This is the point at which the Makefile.in
1939# template is edited and output to the Makefile.
1940
1941contents=$(cat "$scriptdir/Makefile.in")
1942
1943needle="WARNING"
1944replacement='*** WARNING: Autogenerated from Makefile.in. DO NOT MODIFY ***'
1945
1946contents=$(replace "$contents" "$needle" "$replacement")
1947
1948# The contents are edited to have the list of files to build.
1949contents=$(gen_file_list "$contents" $unneeded)
1950
1951SRC_TARGETS=""
1952
1953# This line and loop generates the individual targets for source files. I used
1954# to just use an implicit target, but that was found to be inadequate when I
1955# added the library.
1956src_files=$(find_src_files $unneeded)
1957
1958for f in $src_files; do
1959	o=$(replace_ext "$f" "c" "o")
1960	o=$(basename "$o")
1961	SRC_TARGETS=$(printf '%s\n\nsrc/%s: src %s %s\n\t$(CC) $(CFLAGS) -o src/%s -c %s\n' \
1962		"$SRC_TARGETS" "$o" "$headers" "$f" "$o" "$f")
1963done
1964
1965# Replace all the placeholders.
1966contents=$(replace "$contents" "ROOTDIR" "$scriptdir")
1967contents=$(replace "$contents" "BUILDDIR" "$builddir")
1968
1969contents=$(replace "$contents" "HEADERS" "$headers")
1970
1971contents=$(replace "$contents" "BC_ENABLED" "$bc")
1972contents=$(replace "$contents" "DC_ENABLED" "$dc")
1973
1974contents=$(replace "$contents" "BC_ALL_TESTS" "$bc_test")
1975contents=$(replace "$contents" "BC_ALL_TESTS_NP" "$bc_test_np")
1976contents=$(replace "$contents" "BC_TESTS" "$bc_tests")
1977contents=$(replace "$contents" "BC_SCRIPT_TESTS" "$bc_script_tests")
1978contents=$(replace "$contents" "BC_ERROR_TESTS" "$bc_err_tests")
1979contents=$(replace "$contents" "BC_TEST_EXEC" "$bc_test_exec")
1980contents=$(replace "$contents" "TIMECONST_ALL_TESTS" "$timeconst")
1981
1982contents=$(replace "$contents" "DC_ALL_TESTS" "$dc_test")
1983contents=$(replace "$contents" "DC_ALL_TESTS_NP" "$dc_test_np")
1984contents=$(replace "$contents" "DC_TESTS" "$dc_tests")
1985contents=$(replace "$contents" "DC_SCRIPT_TESTS" "$dc_script_tests")
1986contents=$(replace "$contents" "DC_ERROR_TESTS" "$dc_err_tests")
1987contents=$(replace "$contents" "DC_TEST_EXEC" "$dc_test_exec")
1988
1989contents=$(replace "$contents" "BCL_TEST_EXEC" "$bcl_test_exec")
1990
1991contents=$(replace "$contents" "BUILD_TYPE" "$manpage_args")
1992contents=$(replace "$contents" "EXCLUDE_EXTRA_MATH" "$exclude_extra_math")
1993
1994contents=$(replace "$contents" "LIBRARY" "$library")
1995contents=$(replace "$contents" "HISTORY" "$hist")
1996contents=$(replace "$contents" "EXTRA_MATH" "$extra_math")
1997contents=$(replace "$contents" "NLS" "$nls")
1998contents=$(replace "$contents" "FUZZ" "$fuzz")
1999contents=$(replace "$contents" "MEMCHECK" "$memcheck")
2000
2001contents=$(replace "$contents" "BC_LIB_O" "$bc_lib")
2002contents=$(replace "$contents" "BC_HELP_O" "$bc_help")
2003contents=$(replace "$contents" "DC_HELP_O" "$dc_help")
2004contents=$(replace "$contents" "BC_LIB2_O" "$BC_LIB2_O")
2005contents=$(replace "$contents" "KARATSUBA_LEN" "$karatsuba_len")
2006
2007contents=$(replace "$contents" "NLSPATH" "$NLSPATH")
2008contents=$(replace "$contents" "DESTDIR" "$destdir")
2009contents=$(replace "$contents" "EXECSUFFIX" "$EXECSUFFIX")
2010contents=$(replace "$contents" "EXECPREFIX" "$EXECPREFIX")
2011contents=$(replace "$contents" "BINDIR" "$BINDIR")
2012contents=$(replace "$contents" "INCLUDEDIR" "$INCLUDEDIR")
2013contents=$(replace "$contents" "LIBDIR" "$LIBDIR")
2014contents=$(replace "$contents" "MAN1DIR" "$MAN1DIR")
2015contents=$(replace "$contents" "MAN3DIR" "$MAN3DIR")
2016contents=$(replace "$contents" "CFLAGS" "$CFLAGS")
2017contents=$(replace "$contents" "HOSTCFLAGS" "$HOSTCFLAGS")
2018contents=$(replace "$contents" "CPPFLAGS" "$CPPFLAGS")
2019contents=$(replace "$contents" "LDFLAGS" "$LDFLAGS")
2020contents=$(replace "$contents" "CC" "$CC")
2021contents=$(replace "$contents" "HOSTCC" "$HOSTCC")
2022contents=$(replace "$contents" "COVERAGE_OUTPUT" "$COVERAGE_OUTPUT")
2023contents=$(replace "$contents" "COVERAGE_PREREQS" "$COVERAGE_PREREQS")
2024contents=$(replace "$contents" "INSTALL_PREREQS" "$install_prereqs")
2025contents=$(replace "$contents" "INSTALL_MAN_PREREQS" "$install_man_prereqs")
2026contents=$(replace "$contents" "INSTALL_LOCALES" "$install_locales")
2027contents=$(replace "$contents" "INSTALL_LOCALES_PREREQS" "$install_locales_prereqs")
2028contents=$(replace "$contents" "UNINSTALL_MAN_PREREQS" "$uninstall_man_prereqs")
2029contents=$(replace "$contents" "UNINSTALL_PREREQS" "$uninstall_prereqs")
2030contents=$(replace "$contents" "UNINSTALL_LOCALES_PREREQS" "$uninstall_locales_prereqs")
2031
2032contents=$(replace "$contents" "PC_PATH" "$PC_PATH")
2033contents=$(replace "$contents" "PKG_CONFIG_INSTALL" "$pkg_config_install")
2034contents=$(replace "$contents" "PKG_CONFIG_UNINSTALL" "$pkg_config_uninstall")
2035
2036contents=$(replace "$contents" "DEFAULT_TARGET" "$default_target")
2037contents=$(replace "$contents" "DEFAULT_TARGET_PREREQS" "$default_target_prereqs")
2038contents=$(replace "$contents" "DEFAULT_TARGET_CMD" "$default_target_cmd")
2039contents=$(replace "$contents" "SECOND_TARGET" "$second_target")
2040contents=$(replace "$contents" "SECOND_TARGET_PREREQS" "$second_target_prereqs")
2041contents=$(replace "$contents" "SECOND_TARGET_CMD" "$second_target_cmd")
2042
2043contents=$(replace "$contents" "ALL_PREREQ" "$ALL_PREREQ")
2044contents=$(replace "$contents" "BC_EXEC_PREREQ" "$bc_exec_prereq")
2045contents=$(replace "$contents" "BC_EXEC_CMD" "$bc_exec_cmd")
2046contents=$(replace "$contents" "DC_EXEC_PREREQ" "$dc_exec_prereq")
2047contents=$(replace "$contents" "DC_EXEC_CMD" "$dc_exec_cmd")
2048
2049contents=$(replace "$contents" "EXECUTABLES" "$executables")
2050contents=$(replace "$contents" "MAIN_EXEC" "$main_exec")
2051contents=$(replace "$contents" "EXEC" "$executable")
2052contents=$(replace "$contents" "TESTS" "$tests")
2053
2054contents=$(replace "$contents" "BC_HISTORY_TEST_PREREQS" "$test_bc_history_prereqs")
2055contents=$(replace "$contents" "DC_HISTORY_TEST_PREREQS" "$test_dc_history_prereqs")
2056contents=$(replace "$contents" "HISTORY_TESTS" "$history_tests")
2057
2058contents=$(replace "$contents" "VG_BC_TEST" "$vg_bc_test")
2059contents=$(replace "$contents" "VG_DC_TEST" "$vg_dc_test")
2060
2061contents=$(replace "$contents" "TIMECONST" "$timeconst")
2062
2063contents=$(replace "$contents" "KARATSUBA" "$karatsuba")
2064contents=$(replace "$contents" "KARATSUBA_TEST" "$karatsuba_test")
2065
2066contents=$(replace "$contents" "LONG_BIT_DEFINE" "$LONG_BIT_DEFINE")
2067
2068contents=$(replace "$contents" "GEN_DIR" "$GEN_DIR")
2069contents=$(replace "$contents" "GEN" "$GEN")
2070contents=$(replace "$contents" "GEN_EXEC_TARGET" "$GEN_EXEC_TARGET")
2071contents=$(replace "$contents" "CLEAN_PREREQS" "$CLEAN_PREREQS")
2072contents=$(replace "$contents" "GEN_EMU" "$GEN_EMU")
2073
2074contents=$(replace "$contents" "BSD" "$bsd")
2075
2076contents=$(replace "$contents" "BC_DEFAULT_BANNER" "$bc_default_banner")
2077contents=$(replace "$contents" "BC_DEFAULT_SIGINT_RESET" "$bc_default_sigint_reset")
2078contents=$(replace "$contents" "DC_DEFAULT_SIGINT_RESET" "$dc_default_sigint_reset")
2079contents=$(replace "$contents" "BC_DEFAULT_TTY_MODE" "$bc_default_tty_mode")
2080contents=$(replace "$contents" "DC_DEFAULT_TTY_MODE" "$dc_default_tty_mode")
2081contents=$(replace "$contents" "BC_DEFAULT_PROMPT" "$bc_default_prompt")
2082contents=$(replace "$contents" "DC_DEFAULT_PROMPT" "$dc_default_prompt")
2083contents=$(replace "$contents" "BC_DEFAULT_EXPR_EXIT" "$bc_default_expr_exit")
2084contents=$(replace "$contents" "DC_DEFAULT_EXPR_EXIT" "$dc_default_expr_exit")
2085contents=$(replace "$contents" "BC_DEFAULT_DIGIT_CLAMP" "$bc_default_digit_clamp")
2086contents=$(replace "$contents" "DC_DEFAULT_DIGIT_CLAMP" "$dc_default_digit_clamp")
2087
2088# Do the first print to the Makefile.
2089printf '%s\n%s\n\n' "$contents" "$SRC_TARGETS" > "Makefile"
2090
2091# Generate the individual test targets.
2092if [ "$bc" -ne 0 ]; then
2093	gen_std_tests bc "$extra_math" "$time_tests" $bc_test_exec
2094	gen_script_tests bc "$extra_math" "$generate_tests" "$time_tests" $bc_test_exec
2095	gen_err_tests bc $bc_test_exec
2096fi
2097
2098if [ "$dc" -ne 0 ]; then
2099	gen_std_tests dc "$extra_math" "$time_tests" $dc_test_exec
2100	gen_script_tests dc "$extra_math" "$generate_tests" "$time_tests" $dc_test_exec
2101	gen_err_tests dc $dc_test_exec
2102fi
2103
2104# Copy the correct manuals to the expected places.
2105mkdir -p manuals
2106cp -f "$scriptdir/manuals/bc/$manpage_args.1.md" manuals/bc.1.md
2107cp -f "$scriptdir/manuals/bc/$manpage_args.1" manuals/bc.1
2108cp -f "$scriptdir/manuals/dc/$manpage_args.1.md" manuals/dc.1.md
2109cp -f "$scriptdir/manuals/dc/$manpage_args.1" manuals/dc.1
2110
2111make clean > /dev/null
2112