3 # SPDX-License-Identifier: BSD-2-Clause
5 # Copyright (c) 2018-2021 Gavin D. Howard and contributors.
7 # Redistribution and use in source and binary forms, with or without
8 # modification, are permitted provided that the following conditions are met:
10 # * Redistributions of source code must retain the above copyright notice, this
11 # list of conditions and the following disclaimer.
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.
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.
31 scriptdir=$(dirname "$script")
32 script=$(basename "$script")
36 . "$scriptdir/scripts/functions.sh"
38 # Simply prints the help message and quits based on the argument.
39 # @param msg The help message to print.
53 printf ' %s -h\n' "$script"
54 printf ' %s --help\n' "$script"
55 printf ' %s [-a|-bD|-dB|-c] [-CEfgGHlmMNtTvz] [-O OPT_LEVEL] [-k KARATSUBA_LEN]\\\n' "$script"
56 printf ' [-s SETTING] [-S SETTING]\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 ' [--install-all-locales] [--opt=OPT_LEVEL] \\\n'
62 printf ' [--karatsuba-len=KARATSUBA_LEN] \\\n'
63 printf ' [--set-default-on=SETTING] [--set-default-off=SETTING] \\\n'
64 printf ' [--prefix=PREFIX] [--bindir=BINDIR] [--datarootdir=DATAROOTDIR] \\\n'
65 printf ' [--datadir=DATADIR] [--mandir=MANDIR] [--man1dir=MAN1DIR] \\\n'
67 printf ' -a, --library\n'
68 printf ' Build the libbcl instead of the programs. This is meant to be used with\n'
69 printf ' Other software like programming languages that want to make use of the\n'
70 printf ' parsing and math capabilities. This option will install headers using\n'
71 printf ' `make install`.\n'
72 printf ' -b, --bc-only\n'
73 printf ' Build bc only. It is an error if "-d", "--dc-only", "-B", or\n'
74 printf ' "--disable-bc" are specified too.\n'
75 printf ' -B, --disable-bc\n'
76 printf ' Disable bc. It is an error if "-b", "--bc-only", "-D", or "--disable-dc"\n'
77 printf ' are specified too.\n'
78 printf ' -c, --coverage\n'
79 printf ' Generate test coverage code. Requires gcov and gcovr.\n'
80 printf ' It is an error if either "-b" ("-D") or "-d" ("-B") is specified.\n'
81 printf ' Requires a compiler that use gcc-compatible coverage options\n'
82 printf ' -C, --disable-clean\n'
83 printf ' Disable the clean that configure.sh does before configure.\n'
84 printf ' -d, --dc-only\n'
85 printf ' Build dc only. It is an error if "-b", "--bc-only", "-D", or\n'
86 printf ' "--disable-dc" are specified too.\n'
87 printf ' -D, --disable-dc\n'
88 printf ' Disable dc. It is an error if "-d", "--dc-only", "-B", or "--disable-bc"\n'
89 printf ' are specified too.\n'
90 printf ' -E, --disable-extra-math\n'
91 printf ' Disable extra math. This includes: "$" operator (truncate to integer),\n'
92 printf ' "@" operator (set number of decimal places), and r(x, p) (rounding\n'
93 printf ' function). Additionally, this option disables the extra printing\n'
94 printf ' functions in the math library.\n'
95 printf ' -f, --force\n'
96 printf ' Force use of all enabled options, even if they do not work. This\n'
97 printf ' option is to allow the maintainer a way to test that certain options\n'
98 printf ' are not failing invisibly. (Development only.)\n'
99 printf ' -g, --debug\n'
100 printf ' Build in debug mode. Adds the "-g" flag, and if there are no\n'
101 printf ' other CFLAGS, and "-O" was not given, this also adds the "-O0"\n'
102 printf ' flag. If this flag is *not* given, "-DNDEBUG" is added to CPPFLAGS\n'
103 printf ' and a strip flag is added to the link stage.\n'
104 printf ' -G, --disable-generated-tests\n'
105 printf ' Disable generating tests. This is for platforms that do not have a\n'
106 printf ' GNU bc-compatible bc to generate tests.\n'
107 printf ' -h, --help\n'
108 printf ' Print this help message and exit.\n'
109 printf ' -H, --disable-history\n'
110 printf ' Disable history.\n'
111 printf ' -k KARATSUBA_LEN, --karatsuba-len KARATSUBA_LEN\n'
112 printf ' Set the karatsuba length to KARATSUBA_LEN (default is 64).\n'
113 printf ' It is an error if KARATSUBA_LEN is not a number or is less than 16.\n'
114 printf ' -l, --install-all-locales\n'
115 printf ' Installs all locales, regardless of how many are on the system. This\n'
116 printf ' option is useful for package maintainers who want to make sure that\n'
117 printf ' a package contains all of the locales that end users might need.\n'
118 printf ' -m, --enable-memcheck\n'
119 printf ' Enable memcheck mode, to ensure no memory leaks. For development only.\n'
120 printf ' -M, --disable-man-pages\n'
121 printf ' Disable installing manpages.\n'
122 printf ' -N, --disable-nls\n'
123 printf ' Disable POSIX locale (NLS) support.\n'
124 printf ' -O OPT_LEVEL, --opt OPT_LEVEL\n'
125 printf ' Set the optimization level. This can also be included in the CFLAGS,\n'
126 printf ' but it is provided, so maintainers can build optimized debug builds.\n'
127 printf ' This is passed through to the compiler, so it must be supported.\n'
128 printf ' -s SETTING, --set-default-on SETTING\n'
129 printf ' Set the default named by SETTING to on. See below for possible values\n'
130 printf ' for SETTING. For multiple instances of the -s or -S for the the same\n'
131 printf ' setting, the last one is used.\n'
132 printf ' -S SETTING, --set-default-off SETTING\n'
133 printf ' Set the default named by SETTING to off. See below for possible values\n'
134 printf ' for SETTING. For multiple instances of the -s or -S for the the same\n'
135 printf ' setting, the last one is used.\n'
136 printf ' -t, --enable-test-timing\n'
137 printf ' Enable the timing of tests. This is for development only.\n'
138 printf ' -T, --disable-strip\n'
139 printf ' Disable stripping symbols from the compiled binary or binaries.\n'
140 printf ' Stripping symbols only happens when debug mode is off.\n'
141 printf ' -v, --enable-valgrind\n'
142 printf ' Enable a build appropriate for valgrind. For development only.\n'
143 printf ' -z, --enable-fuzz-mode\n'
144 printf ' Enable fuzzing mode. THIS IS FOR DEVELOPMENT ONLY.\n'
145 printf ' --prefix PREFIX\n'
146 printf ' The prefix to install to. Overrides "$PREFIX" if it exists.\n'
147 printf ' If PREFIX is "/usr", install path will be "/usr/bin".\n'
148 printf ' Default is "/usr/local".\n'
149 printf ' --bindir BINDIR\n'
150 printf ' The directory to install binaries in. Overrides "$BINDIR" if it exists.\n'
151 printf ' Default is "$PREFIX/bin".\n'
152 printf ' --includedir INCLUDEDIR\n'
153 printf ' The directory to install headers in. Overrides "$INCLUDEDIR" if it\n'
154 printf ' exists. Default is "$PREFIX/include".\n'
155 printf ' --libdir LIBDIR\n'
156 printf ' The directory to install libraries in. Overrides "$LIBDIR" if it exists.\n'
157 printf ' Default is "$PREFIX/lib".\n'
158 printf ' --datarootdir DATAROOTDIR\n'
159 printf ' The root location for data files. Overrides "$DATAROOTDIR" if it exists.\n'
160 printf ' Default is "$PREFIX/share".\n'
161 printf ' --datadir DATADIR\n'
162 printf ' The location for data files. Overrides "$DATADIR" if it exists.\n'
163 printf ' Default is "$DATAROOTDIR".\n'
164 printf ' --mandir MANDIR\n'
165 printf ' The location to install manpages to. Overrides "$MANDIR" if it exists.\n'
166 printf ' Default is "$DATADIR/man".\n'
167 printf ' --man1dir MAN1DIR\n'
168 printf ' The location to install Section 1 manpages to. Overrides "$MAN1DIR" if\n'
169 printf ' it exists. Default is "$MANDIR/man1".\n'
170 printf ' --man3dir MAN3DIR\n'
171 printf ' The location to install Section 3 manpages to. Overrides "$MAN3DIR" if\n'
172 printf ' it exists. Default is "$MANDIR/man3".\n'
174 printf 'In addition, the following environment variables are used:\n'
176 printf ' CC C compiler. Must be compatible with POSIX c99. If there is a\n'
177 printf ' space in the basename of the compiler, the items after the\n'
178 printf ' first space are assumed to be compiler flags, and in that case,\n'
179 printf ' the flags are automatically moved into CFLAGS. Default is\n'
181 printf ' HOSTCC Host C compiler. Must be compatible with POSIX c99. If there is\n'
182 printf ' a space in the basename of the compiler, the items after the\n'
183 printf ' first space are assumed to be compiler flags, and in the case,\n'
184 printf ' the flags are automatically moved into HOSTCFLAGS. Default is\n'
186 printf ' HOST_CC Same as HOSTCC. If HOSTCC also exists, it is used.\n'
187 printf ' CFLAGS C compiler flags.\n'
188 printf ' HOSTCFLAGS CFLAGS for HOSTCC. Default is "$CFLAGS".\n'
189 printf ' HOST_CFLAGS Same as HOST_CFLAGS. If HOST_CFLAGS also exists, it is used.\n'
190 printf ' CPPFLAGS C preprocessor flags. Default is "".\n'
191 printf ' LDFLAGS Linker flags. Default is "".\n'
192 printf ' PREFIX The prefix to install to. Default is "/usr/local".\n'
193 printf ' If PREFIX is "/usr", install path will be "/usr/bin".\n'
194 printf ' BINDIR The directory to install binaries in. Default is "$PREFIX/bin".\n'
195 printf ' INCLUDEDIR The directory to install header files in. Default is\n'
196 printf ' "$PREFIX/include".\n'
197 printf ' LIBDIR The directory to install libraries in. Default is\n'
198 printf ' "$PREFIX/lib".\n'
199 printf ' DATAROOTDIR The root location for data files. Default is "$PREFIX/share".\n'
200 printf ' DATADIR The location for data files. Default is "$DATAROOTDIR".\n'
201 printf ' MANDIR The location to install manpages to. Default is "$DATADIR/man".\n'
202 printf ' MAN1DIR The location to install Section 1 manpages to. Default is\n'
203 printf ' "$MANDIR/man1".\n'
204 printf ' MAN3DIR The location to install Section 3 manpages to. Default is\n'
205 printf ' "$MANDIR/man3".\n'
206 printf ' NLSPATH The location to install locale catalogs to. Must be an absolute\n'
207 printf ' path (or contain one). This is treated the same as the POSIX\n'
208 printf ' definition of $NLSPATH (see POSIX environment variables for\n'
209 printf ' more information). Default is "/usr/share/locale/%%L/%%N".\n'
210 printf ' PC_PATH The location to install pkg-config files to. Must be an\n'
211 printf ' path or contain one. Default is the first path given by the\n'
212 printf ' output of `pkg-config --variable=pc_path pkg-config`.\n'
213 printf ' EXECSUFFIX The suffix to append to the executable names, used to not\n'
214 printf ' interfere with other installed bc executables. Default is "".\n'
215 printf ' EXECPREFIX The prefix to append to the executable names, used to not\n'
216 printf ' interfere with other installed bc executables. Default is "".\n'
217 printf ' DESTDIR For package creation. Default is "". If it is empty when\n'
218 printf ' `%s` is run, it can also be passed to `make install`\n' "$script"
219 printf ' later as an environment variable. If both are specified,\n'
220 printf ' the one given to `%s` takes precedence.\n' "$script"
221 printf ' LONG_BIT The number of bits in a C `long` type. This is mostly for the\n'
222 printf ' embedded space since this `bc` uses `long`s internally for\n'
223 printf ' overflow checking. In C99, a `long` is required to be 32 bits.\n'
224 printf ' For most normal desktop systems, setting this is unnecessary,\n'
225 printf ' except that 32-bit platforms with 64-bit longs may want to set\n'
226 printf ' it to `32`. Default is the default of `LONG_BIT` for the target\n'
227 printf ' platform. Minimum allowed is `32`. It is a build time error if\n'
228 printf ' the specified value of `LONG_BIT` is greater than the default\n'
229 printf ' value of `LONG_BIT` for the target platform.\n'
230 printf ' GEN_HOST Whether to use `gen/strgen.c`, instead of `gen/strgen.sh`, to\n'
231 printf ' produce the C files that contain the help texts as well as the\n'
232 printf ' math libraries. By default, `gen/strgen.c` is used, compiled by\n'
233 printf ' "$HOSTCC" and run on the host machine. Using `gen/strgen.sh`\n'
234 printf ' removes the need to compile and run an executable on the host\n'
235 printf ' machine since `gen/strgen.sh` is a POSIX shell script. However,\n'
236 printf ' `gen/lib2.bc` is perilously close to 4095 characters, the max\n'
237 printf ' supported length of a string literal in C99 (and it could be\n'
238 printf ' added to in the future), and `gen/strgen.sh` generates a string\n'
239 printf ' literal instead of an array, as `gen/strgen.c` does. For most\n'
240 printf ' production-ready compilers, this limit probably is not\n'
241 printf ' enforced, but it could be. Both options are still available for\n'
242 printf ' this reason. If you are sure your compiler does not have the\n'
243 printf ' limit and do not want to compile and run a binary on the host\n'
244 printf ' machine, set this variable to "0". Any other value, or a\n'
245 printf ' non-existent value, will cause the build system to compile and\n'
246 printf ' run `gen/strgen.c`. Default is "".\n'
247 printf ' GEN_EMU Emulator to run string generator code under (leave empty if not\n'
248 printf ' necessary). This is not necessary when using `gen/strgen.sh`.\n'
249 printf ' Default is "".\n'
251 printf 'WARNING: even though `configure.sh` supports both option types, short and\n'
252 printf 'long, it does not support handling both at the same time. Use only one type.\n'
257 printf 'bc and dc have some settings that, while they cannot be removed by build time\n'
258 printf 'options, can have their defaults changed at build time by packagers. Users are\n'
259 printf 'also able to change each setting with environment variables.\n'
261 printf 'The following is a table of settings, along with their default values and the\n'
262 printf 'environment variables users can use to change them. (For the defaults, non-zero\n'
263 printf 'means on, and zero means off.)\n'
265 printf '| Setting | Description | Default | Env Variable |\n'
266 printf '| =============== | ==================== | ============ | ==================== |\n'
267 printf '| bc.banner | Whether to display | 0 | BC_BANNER |\n'
268 printf '| | the bc version | | |\n'
269 printf '| | banner when in | | |\n'
270 printf '| | interactive mode. | | |\n'
271 printf '| --------------- | -------------------- | ------------ | -------------------- |\n'
272 printf '| bc.sigint_reset | Whether SIGINT will | 1 | BC_SIGINT_RESET |\n'
273 printf '| | reset bc, instead of | | |\n'
274 printf '| | exiting, when in | | |\n'
275 printf '| | interactive mode. | | |\n'
276 printf '| --------------- | -------------------- | ------------ | -------------------- |\n'
277 printf '| dc.sigint_reset | Whether SIGINT will | 1 | DC_SIGINT_RESET |\n'
278 printf '| | reset dc, instead of | | |\n'
279 printf '| | exiting, when in | | |\n'
280 printf '| | interactive mode. | | |\n'
281 printf '| --------------- | -------------------- | ------------ | -------------------- |\n'
282 printf '| bc.tty_mode | Whether TTY mode for | 1 | BC_TTY_MODE |\n'
283 printf '| | bc should be on when | | |\n'
284 printf '| | available. | | |\n'
285 printf '| --------------- | -------------------- | ------------ | -------------------- |\n'
286 printf '| dc.tty_mode | Whether TTY mode for | 0 | BC_TTY_MODE |\n'
287 printf '| | dc should be on when | | |\n'
288 printf '| | available. | | |\n'
289 printf '| --------------- | -------------------- | ------------ | -------------------- |\n'
290 printf '| bc.prompt | Whether the prompt | $BC_TTY_MODE | BC_PROMPT |\n'
291 printf '| | for bc should be on | | |\n'
292 printf '| | in tty mode. | | |\n'
293 printf '| --------------- | -------------------- | ------------ | -------------------- |\n'
294 printf '| dc.prompt | Whether the prompt | $DC_TTY_MODE | DC_PROMPT |\n'
295 printf '| | for dc should be on | | |\n'
296 printf '| | in tty mode. | | |\n'
297 printf '| --------------- | -------------------- | ------------ | -------------------- |\n'
298 printf '| bc.expr_exit | Whether to exit bc | 1 | BC_EXPR_EXIT |\n'
299 printf '| | if an expression or | | |\n'
300 printf '| | expression file is | | |\n'
301 printf '| | given with the -e or | | |\n'
302 printf '| | -f options. | | |\n'
303 printf '| --------------- | -------------------- | ------------ | -------------------- |\n'
304 printf '| dc.expr_exit | Whether to exit dc | 1 | DC_EXPR_EXIT |\n'
305 printf '| | if an expression or | | |\n'
306 printf '| | expression file is | | |\n'
307 printf '| | given with the -e or | | |\n'
308 printf '| | -f options. | | |\n'
309 printf '| --------------- | -------------------- | ------------ | -------------------- |\n'
311 printf 'These settings are not meant to be changed on a whim. They are meant to ensure\n'
312 printf 'that this bc and dc will conform to the expectations of the user on each\n'
318 # Replaces a file extension in a filename. This is used mostly to turn filenames
319 # like `src/num.c` into `src/num.o`. In other words, it helps to link targets to
320 # the files they depend on.
322 # @param file The filename.
323 # @param ext1 The extension to replace.
324 # @param ext2 The new extension.
327 if [ "$#" -ne 3 ]; then
328 err_exit "Invalid number of args to $0"
331 _replace_ext_file="$1"
332 _replace_ext_ext1="$2"
333 _replace_ext_ext2="$3"
335 _replace_ext_result="${_replace_ext_file%.$_replace_ext_ext1}.$_replace_ext_ext2"
337 printf '%s\n' "$_replace_ext_result"
340 # Replaces a file extension in every filename given in a list. The list is just
341 # a space-separated list of words, so filenames are expected to *not* have
342 # spaces in them. See the documentation for `replace_ext()`.
344 # @param files The list of space-separated filenames to replace extensions for.
345 # @param ext1 The extension to replace.
346 # @param ext2 The new extension.
349 if [ "$#" -ne 3 ]; then
350 err_exit "Invalid number of args to $0"
353 _replace_exts_files="$1"
354 _replace_exts_ext1="$2"
355 _replace_exts_ext2="$3"
357 for _replace_exts_file in $_replace_exts_files; do
358 _replace_exts_new_name=$(replace_ext "$_replace_exts_file" "$_replace_exts_ext1" "$_replace_exts_ext2")
359 _replace_exts_result="$_replace_exts_result $_replace_exts_new_name"
362 printf '%s\n' "$_replace_exts_result"
365 # Finds a placeholder in @a str and replaces it. This is the workhorse of
366 # configure.sh. It's what replaces placeholders in Makefile.in with the data
367 # needed for the chosen build. Below, you will see a lot of calls to this
370 # Note that needle can never contain an exclamation point. For more information,
371 # see substring_replace() in scripts/functions.sh.
373 # @param str The string to find and replace placeholders in.
374 # @param needle The placeholder name.
375 # @param replacement The string to use to replace the placeholder.
378 if [ "$#" -ne 3 ]; then
379 err_exit "Invalid number of args to $0"
384 _replace_replacement="$3"
386 substring_replace "$_replace_str" "%%$_replace_needle%%" "$_replace_replacement"
389 # This function finds all the source files that need to be built. If there is
390 # only one argument and it is empty, then all source files are built. Otherwise,
391 # the arguments are all assumed to be source files that should *not* be built.
394 _find_src_files_args=""
396 if [ "$#" -ge 1 ] && [ "$1" != "" ]; then
398 while [ "$#" -ge 1 ]; do
399 _find_src_files_a="${1## }"
401 _find_src_files_args=$(printf '%s\n%s/src/%s\n' "$_find_src_files_args" "$scriptdir" "${_find_src_files_a}")
406 _find_src_files_files=$(find "$scriptdir/src/" -depth -name "*.c" -print)
408 _find_src_files_result=""
410 for _find_src_files_f in $_find_src_files_files; do
412 # If this is true, the file is part of args, and therefore, unneeded.
413 if [ "${_find_src_files_args##*$_find_src_files_f}" != "${_find_src_files_args}" ]; then
417 _find_src_files_result=$(printf '%s\n%s\n' "$_find_src_files_result" "$_find_src_files_f")
421 printf '%s\n' "$_find_src_files_result"
424 # This function generates a list of files to go into the Makefile. It generates
425 # the list of object files, as well as the list of test coverage files.
427 # @param contents The contents of the Makefile template to put the list of
431 if [ "$#" -lt 1 ]; then
432 err_exit "Invalid number of args to $0"
435 _gen_file_list_contents="$1"
438 if [ "$#" -ge 1 ]; then
439 _gen_file_list_unneeded="$@"
441 _gen_file_list_unneeded=""
444 _gen_file_list_needle_src="SRC"
445 _gen_file_list_needle_obj="OBJ"
446 _gen_file_list_needle_gcda="GCDA"
447 _gen_file_list_needle_gcno="GCNO"
449 _gen_file_list_replacement=$(find_src_files $_gen_file_list_unneeded | tr '\n' ' ')
450 _gen_file_list_contents=$(replace "$_gen_file_list_contents" \
451 "$_gen_file_list_needle_src" "$_gen_file_list_replacement")
453 _gen_file_list_cbases=""
455 for _gen_file_list_f in $_gen_file_list_replacement; do
456 _gen_file_list_b=$(basename "$_gen_file_list_f")
457 _gen_file_list_cbases="$_gen_file_list_cbases src/$_gen_file_list_b"
460 _gen_file_list_replacement=$(replace_exts "$_gen_file_list_cbases" "c" "o")
461 _gen_file_list_contents=$(replace "$_gen_file_list_contents" \
462 "$_gen_file_list_needle_obj" "$_gen_file_list_replacement")
464 _gen_file_list_replacement=$(replace_exts "$_gen_file_list_replacement" "o" "gcda")
465 _gen_file_list_contents=$(replace "$_gen_file_list_contents" \
466 "$_gen_file_list_needle_gcda" "$_gen_file_list_replacement")
468 _gen_file_list_replacement=$(replace_exts "$_gen_file_list_replacement" "gcda" "gcno")
469 _gen_file_list_contents=$(replace "$_gen_file_list_contents" \
470 "$_gen_file_list_needle_gcno" "$_gen_file_list_replacement")
472 printf '%s\n' "$_gen_file_list_contents"
475 # Generates the proper test targets for each test to have its own target. This
476 # allows `make test` to run in parallel.
478 # @param name Which calculator to generate tests for.
479 # @param extra_math An integer that, if non-zero, activates extra math tests.
480 # @param time_tests An integer that, if non-zero, tells the test suite to time
481 # the execution of each test.
484 _gen_std_tests_name="$1"
487 _gen_std_tests_extra_math="$1"
490 _gen_std_tests_time_tests="$1"
493 _gen_std_tests_extra_required=$(cat "$scriptdir/tests/extra_required.txt")
495 for _gen_std_tests_t in $(cat "$scriptdir/tests/$_gen_std_tests_name/all.txt"); do
497 if [ "$_gen_std_tests_extra_math" -eq 0 ]; then
499 if [ -z "${_gen_std_tests_extra_required##*$_gen_std_tests_t*}" ]; then
500 printf 'test_%s_%s:\n\t@printf "Skipping %s %s\\n"\n\n' \
501 "$_gen_std_tests_name" "$_gen_std_tests_t" "$_gen_std_tests_name" \
502 "$_gen_std_tests_t" >> "Makefile"
508 printf 'test_%s_%s:\n\t@export BC_TEST_OUTPUT_DIR="%s/tests"; sh \$(TESTSDIR)/test.sh %s %s %s %s %s\n\n' \
509 "$_gen_std_tests_name" "$_gen_std_tests_t" "$builddir" "$_gen_std_tests_name" \
510 "$_gen_std_tests_t" "$generate_tests" "$time_tests" \
516 # Generates a list of test targets that will be used as prerequisites for other
519 # @param name The name of the calculator to generate test targets for.
520 gen_std_test_targets() {
522 _gen_std_test_targets_name="$1"
525 _gen_std_test_targets_tests=$(cat "$scriptdir/tests/${_gen_std_test_targets_name}/all.txt")
527 for _gen_std_test_targets_t in $_gen_std_test_targets_tests; do
528 printf ' test_%s_%s' "$_gen_std_test_targets_name" "$_gen_std_test_targets_t"
534 # Generates the proper test targets for each error test to have its own target.
535 # This allows `make test_bc_errors` and `make test_dc_errors` to run in
538 # @param name Which calculator to generate tests for.
541 _gen_err_tests_name="$1"
544 _gen_err_tests_fs=$(ls "$scriptdir/tests/$_gen_err_tests_name/errors/")
546 for _gen_err_tests_t in $_gen_err_tests_fs; do
548 printf 'test_%s_error_%s:\n\t@export BC_TEST_OUTPUT_DIR="%s/tests"; sh \$(TESTSDIR)/error.sh %s %s %s\n\n' \
549 "$_gen_err_tests_name" "$_gen_err_tests_t" "$builddir" "$_gen_err_tests_name" \
550 "$_gen_err_tests_t" "$*" >> "Makefile"
556 # Generates a list of error test targets that will be used as prerequisites for
559 # @param name The name of the calculator to generate test targets for.
560 gen_err_test_targets() {
562 _gen_err_test_targets_name="$1"
565 _gen_err_test_targets_tests=$(ls "$scriptdir/tests/$_gen_err_test_targets_name/errors/")
567 for _gen_err_test_targets_t in $_gen_err_test_targets_tests; do
568 printf ' test_%s_error_%s' "$_gen_err_test_targets_name" "$_gen_err_test_targets_t"
574 # Generates the proper script test targets for each script test to have its own
575 # target. This allows `make test` to run in parallel.
577 # @param name Which calculator to generate tests for.
578 # @param extra_math An integer that, if non-zero, activates extra math tests.
579 # @param generate An integer that, if non-zero, activates generated tests.
580 # @param time_tests An integer that, if non-zero, tells the test suite to time
581 # the execution of each test.
584 _gen_script_tests_name="$1"
587 _gen_script_tests_extra_math="$1"
590 _gen_script_tests_generate="$1"
593 _gen_script_tests_time="$1"
596 _gen_script_tests_tests=$(cat "$scriptdir/tests/$_gen_script_tests_name/scripts/all.txt")
598 for _gen_script_tests_f in $_gen_script_tests_tests; do
600 _gen_script_tests_b=$(basename "$_gen_script_tests_f" ".${_gen_script_tests_name}")
602 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' \
603 "$_gen_script_tests_name" "$_gen_script_tests_b" "$builddir" "$_gen_script_tests_name" \
604 "$_gen_script_tests_f" "$_gen_script_tests_extra_math" "$_gen_script_tests_generate" \
605 "$_gen_script_tests_time" "$*" >> "Makefile"
614 _set_default_name="$1"
617 # The reason that the variables that are being set do not have the same
618 # non-collision avoidance that the other variables do is that we *do* want
619 # the settings of these variables to leak out of the function. They adjust
620 # the settings outside of the function.
621 case "$_set_default_name" in
623 bc.banner) bc_default_banner="$_set_default_on" ;;
624 bc.sigint_reset) bc_default_sigint_reset="$_set_default_on" ;;
625 dc.sigint_reset) dc_default_sigint_reset="$_set_default_on" ;;
626 bc.tty_mode) bc_default_tty_mode="$_set_default_on" ;;
627 dc.tty_mode) dc_default_tty_mode="$_set_default_on" ;;
628 bc.prompt) bc_default_prompt="$_set_default_on" ;;
629 dc.prompt) dc_default_prompt="$_set_default_on" ;;
630 bc.expr_exit) bc_default_expr_exit="$_set_default_on";;
631 dc.expr_exit) dc_default_expr_exit="$_set_default_on";;
632 ?) usage "Invalid setting: $_set_default_name" ;;
637 # Generates a list of script test targets that will be used as prerequisites for
640 # @param name The name of the calculator to generate script test targets for.
641 gen_script_test_targets() {
643 _gen_script_test_targets_name="$1"
646 _gen_script_test_targets_tests=$(cat "$scriptdir/tests/$_gen_script_test_targets_name/scripts/all.txt")
648 for _gen_script_test_targets_f in $_gen_script_test_targets_tests; do
649 _gen_script_test_targets_b=$(basename "$_gen_script_test_targets_f" \
650 ".$_gen_script_test_targets_name")
651 printf ' test_%s_script_%s' "$_gen_script_test_targets_name" \
652 "$_gen_script_test_targets_b"
658 # This is a list of defaults, but it is also the list of possible options for
661 # The development options are: force (force options even if they fail), valgrind
662 # (build in a way suitable for valgrind testing), memcheck (same as valgrind),
663 # and fuzzing (build in a way suitable for fuzzing).
685 # The empty strings are because they depend on TTY mode. If they are directly
686 # set, though, they will be integers. We test for empty strings later.
688 bc_default_sigint_reset=1
689 dc_default_sigint_reset=1
690 bc_default_tty_mode=1
691 dc_default_tty_mode=0
694 bc_default_expr_exit=1
695 dc_default_expr_exit=1
697 # getopts is a POSIX utility, but it cannot handle long options. Thus, the
698 # handling of long options is done by hand, and that's the reason that short and
699 # long options cannot be mixed.
700 while getopts "abBcdDEfgGhHk:lMmNO:S:s:tTvz-" opt; do
713 G) generate_tests=0 ;;
716 k) karatsuba_len="$OPTARG" ;;
719 M) install_manpages=0 ;;
721 O) optimization="$OPTARG" ;;
722 S) set_default 0 "$OPTARG" ;;
723 s) set_default 1 "$OPTARG" ;;
731 LONG_OPTARG="${arg#*=}"
734 library) library=1 ;;
735 bc-only) bc_only=1 ;;
736 dc-only) dc_only=1 ;;
737 coverage) coverage=1 ;;
740 prefix=?*) PREFIX="$LONG_OPTARG" ;;
742 if [ "$#" -lt 2 ]; then
743 usage "No argument given for '--$arg' option"
747 bindir=?*) BINDIR="$LONG_OPTARG" ;;
749 if [ "$#" -lt 2 ]; then
750 usage "No argument given for '--$arg' option"
754 includedir=?*) INCLUDEDIR="$LONG_OPTARG" ;;
756 if [ "$#" -lt 2 ]; then
757 usage "No argument given for '--$arg' option"
761 libdir=?*) LIBDIR="$LONG_OPTARG" ;;
763 if [ "$#" -lt 2 ]; then
764 usage "No argument given for '--$arg' option"
768 datarootdir=?*) DATAROOTDIR="$LONG_OPTARG" ;;
770 if [ "$#" -lt 2 ]; then
771 usage "No argument given for '--$arg' option"
775 datadir=?*) DATADIR="$LONG_OPTARG" ;;
777 if [ "$#" -lt 2 ]; then
778 usage "No argument given for '--$arg' option"
782 mandir=?*) MANDIR="$LONG_OPTARG" ;;
784 if [ "$#" -lt 2 ]; then
785 usage "No argument given for '--$arg' option"
789 man1dir=?*) MAN1DIR="$LONG_OPTARG" ;;
791 if [ "$#" -lt 2 ]; then
792 usage "No argument given for '--$arg' option"
796 man3dir=?*) MAN3DIR="$LONG_OPTARG" ;;
798 if [ "$#" -lt 2 ]; then
799 usage "No argument given for '--$arg' option"
803 localedir=?*) LOCALEDIR="$LONG_OPTARG" ;;
805 if [ "$#" -lt 2 ]; then
806 usage "No argument given for '--$arg' option"
810 karatsuba-len=?*) karatsuba_len="$LONG_OPTARG" ;;
812 if [ "$#" -lt 2 ]; then
813 usage "No argument given for '--$arg' option"
817 opt=?*) optimization="$LONG_OPTARG" ;;
819 if [ "$#" -lt 2 ]; then
820 usage "No argument given for '--$arg' option"
824 set-default-on=?*) set_default 1 "$LONG_OPTARG" ;;
826 if [ "$#" -lt 2 ]; then
827 usage "No argument given for '--$arg' option"
831 set-default-off=?*) set_default 0 "$LONG_OPTARG" ;;
833 if [ "$#" -lt 2 ]; then
834 usage "No argument given for '--$arg' option"
838 disable-bc) dc_only=1 ;;
839 disable-dc) bc_only=1 ;;
840 disable-clean) clean=0 ;;
841 disable-extra-math) extra_math=0 ;;
842 disable-generated-tests) generate_tests=0 ;;
843 disable-history) hist=0 ;;
844 disable-man-pages) install_manpages=0 ;;
845 disable-nls) nls=0 ;;
846 disable-strip) strip_bin=0 ;;
847 enable-test-timing) time_tests=1 ;;
848 enable-valgrind) vg=1 ;;
849 enable-fuzz-mode) fuzz=1 ;;
850 enable-memcheck) memcheck=1 ;;
851 install-all-locales) all_locales=1 ;;
852 help* | bc-only* | dc-only* | coverage* | debug*)
853 usage "No arg allowed for --$arg option" ;;
854 disable-bc* | disable-dc* | disable-clean*)
855 usage "No arg allowed for --$arg option" ;;
857 usage "No arg allowed for --$arg option" ;;
858 disable-generated-tests* | disable-history*)
859 usage "No arg allowed for --$arg option" ;;
860 disable-man-pages* | disable-nls* | disable-strip*)
861 usage "No arg allowed for --$arg option" ;;
862 enable-fuzz-mode* | enable-test-timing* | enable-valgrind*)
863 usage "No arg allowed for --$arg option" ;;
864 enable-memcheck* | install-all-locales*)
865 usage "No arg allowed for --$arg option" ;;
866 '') break ;; # "--" terminates argument processing
867 * ) usage "Invalid option $LONG_OPTARG" ;;
871 ?) usage "Invalid option: $opt" ;;
876 # Sometimes, developers don't want configure.sh to do a config clean. But
878 if [ "$clean" -ne 0 ]; then
879 if [ -f ./Makefile ]; then
880 make clean_config > /dev/null
884 # It is an error to say that bc only should be built and likewise for dc.
885 if [ "$bc_only" -eq 1 ] && [ "$dc_only" -eq 1 ]; then
886 usage "Can only specify one of -b(-D) or -d(-B)"
889 # The library is mutually exclusive to the calculators, so it's an error to
890 # give an option for either of them.
891 if [ "$library" -ne 0 ]; then
892 if [ "$bc_only" -eq 1 ] || [ "$dc_only" -eq 1 ]; then
893 usage "Must not specify -b(-D) or -d(-B) when building the library"
897 # KARATSUBA_LEN must be an integer and must be 16 or greater.
898 case $karatsuba_len in
899 (*[!0-9]*|'') usage "KARATSUBA_LEN is not a number" ;;
903 if [ "$karatsuba_len" -lt 16 ]; then
904 usage "KARATSUBA_LEN is less than 16"
909 if [ -z "${LONG_BIT+set}" ]; then
911 elif [ "$LONG_BIT" -lt 32 ]; then
912 usage "LONG_BIT is less than 32"
914 LONG_BIT_DEFINE="-DBC_LONG_BIT=\$(BC_LONG_BIT)"
917 if [ -z "$CC" ]; then
921 # I had users complain that, if they gave CFLAGS as part of CC, which
922 # autotools allows in its braindead way, the build would fail with an error.
923 # I don't like adjusting for autotools, but oh well. These lines puts the
924 # stuff after the first space into CFLAGS.
925 ccbase=$(basename "$CC")
929 if [ "${ccbase%%$suffix}" != "$ccbase" ]; then
930 ccflags="${ccbase#$prefix}"
931 cc="${ccbase%%$suffix}"
932 ccdir=$(dirname "$CC")
933 if [ "$ccdir" = "." ] && [ "${CC#.}" = "$CC" ]; then
939 CFLAGS="$CFLAGS $ccflags"
943 if [ -z "$HOSTCC" ] && [ -z "$HOST_CC" ]; then
945 elif [ -z "$HOSTCC" ]; then
949 if [ "$HOSTCC" != "$CC" ]; then
951 # Like above, this splits HOSTCC and HOSTCFLAGS.
952 ccbase=$(basename "$HOSTCC")
956 if [ "${ccbase%%$suffix}" != "$ccbase" ]; then
957 ccflags="${ccbase#$prefix}"
958 cc="${ccbase%%$suffix}"
959 ccdir=$(dirname "$HOSTCC")
960 if [ "$ccdir" = "." ] && [ "${HOSTCC#.}" = "$HOSTCC" ]; then
965 HOSTCC="${ccdir}${cc}"
966 HOSTCFLAGS="$HOSTCFLAGS $ccflags"
970 if [ -z "${HOSTCFLAGS+set}" ] && [ -z "${HOST_CFLAGS+set}" ]; then
972 elif [ -z "${HOSTCFLAGS+set}" ]; then
973 HOSTCFLAGS="$HOST_CFLAGS"
976 # Store these for the cross compilation detection later.
978 OLDHOSTCFLAGS="$HOSTCFLAGS"
980 link="@printf 'No link necessary\\\\n'"
984 tests="test_bc timeconst test_dc"
986 bc_test="@export BC_TEST_OUTPUT_DIR=\"$builddir/tests\"; \$(TESTSDIR)/all.sh bc $extra_math 1 $generate_tests $time_tests \$(BC_EXEC)"
987 bc_test_np="@export BC_TEST_OUTPUT_DIR=\"$builddir/tests\"; \$(TESTSDIR)/all.sh -n bc $extra_math 1 $generate_tests $time_tests \$(BC_EXEC)"
988 dc_test="@export BC_TEST_OUTPUT_DIR=\"$builddir/tests\"; \$(TESTSDIR)/all.sh dc $extra_math 1 $generate_tests $time_tests \$(DC_EXEC)"
989 dc_test_np="@export BC_TEST_OUTPUT_DIR=\"$builddir/tests\"; \$(TESTSDIR)/all.sh -n dc $extra_math 1 $generate_tests $time_tests \$(DC_EXEC)"
991 timeconst="@export BC_TEST_OUTPUT_DIR=\"$builddir/tests\"; \$(TESTSDIR)/bc/timeconst.sh \$(TESTSDIR)/bc/scripts/timeconst.bc \$(BC_EXEC)"
993 # In order to have cleanup at exit, we need to be in
994 # debug mode, so don't run valgrind without that.
995 if [ "$vg" -ne 0 ]; then
997 bc_test_exec='valgrind $(VALGRIND_ARGS) $(BC_EXEC)'
998 dc_test_exec='valgrind $(VALGRIND_ARGS) $(DC_EXEC)'
1000 bc_test_exec='$(BC_EXEC)'
1001 dc_test_exec='$(DC_EXEC)'
1004 test_bc_history_prereqs="test_bc_history_all"
1005 test_dc_history_prereqs="test_dc_history_all"
1007 karatsuba="@printf 'karatsuba cannot be run because one of bc or dc is not built\\\\n'"
1008 karatsuba_test="@printf 'karatsuba cannot be run because one of bc or dc is not built\\\\n'"
1010 bc_lib="\$(GEN_DIR)/lib.o"
1011 bc_help="\$(GEN_DIR)/bc_help.o"
1012 dc_help="\$(GEN_DIR)/dc_help.o"
1014 default_target_prereqs="\$(BIN) \$(OBJS)"
1015 default_target_cmd="\$(CC) \$(CFLAGS) \$(OBJS) \$(LDFLAGS) -o \$(EXEC)"
1016 default_target="\$(DC_EXEC)"
1018 second_target_prereqs=""
1019 second_target_cmd="$default_target_cmd"
1020 second_target="\$(BC_EXEC)"
1022 # This if/else if chain is for setting the defaults that change based on whether
1023 # the library is being built, bc only, dc only, or both calculators.
1024 if [ "$library" -ne 0 ]; then
1032 default_target_prereqs="\$(BIN) \$(OBJ)"
1033 default_target_cmd="ar -r -cu \$(LIBBC) \$(OBJ)"
1034 default_target="\$(LIBBC)"
1035 tests="test_library"
1036 test_bc_history_prereqs=" test_bc_history_skip"
1037 test_dc_history_prereqs=" test_dc_history_skip"
1039 install_prereqs=" install_library"
1040 uninstall_prereqs=" uninstall_library"
1041 install_man_prereqs=" install_bcl_manpage"
1042 uninstall_man_prereqs=" uninstall_bcl_manpage"
1044 elif [ "$bc_only" -eq 1 ]; then
1053 dc_test="@printf 'No dc tests to run\\\\n'"
1054 dc_test_np="@printf 'No dc tests to run\\\\n'"
1055 test_dc_history_prereqs=" test_dc_history_skip"
1057 install_prereqs=" install_execs"
1058 install_man_prereqs=" install_bc_manpage"
1059 uninstall_prereqs=" uninstall_bc"
1060 uninstall_man_prereqs=" uninstall_bc_manpage"
1062 default_target="\$(BC_EXEC)"
1063 second_target="\$(DC_EXEC)"
1064 tests="test_bc timeconst"
1066 elif [ "$dc_only" -eq 1 ]; then
1077 executable="DC_EXEC"
1079 bc_test="@printf 'No bc tests to run\\\\n'"
1080 bc_test_np="@printf 'No bc tests to run\\\\n'"
1081 test_bc_history_prereqs=" test_bc_history_skip"
1083 timeconst="@printf 'timeconst cannot be run because bc is not built\\\\n'"
1085 install_prereqs=" install_execs"
1086 install_man_prereqs=" install_dc_manpage"
1087 uninstall_prereqs=" uninstall_dc"
1088 uninstall_man_prereqs=" uninstall_dc_manpage"
1097 executables="bc and dc"
1099 karatsuba="@\$(KARATSUBA) 30 0 \$(BC_EXEC)"
1100 karatsuba_test="@\$(KARATSUBA) 1 100 \$(BC_EXEC)"
1102 if [ "$library" -eq 0 ]; then
1103 install_prereqs=" install_execs"
1104 install_man_prereqs=" install_bc_manpage install_dc_manpage"
1105 uninstall_prereqs=" uninstall_bc uninstall_dc"
1106 uninstall_man_prereqs=" uninstall_bc_manpage uninstall_dc_manpage"
1108 install_prereqs=" install_library install_bcl_header"
1109 install_man_prereqs=" install_bcl_manpage"
1110 uninstall_prereqs=" uninstall_library uninstall_bcl_header"
1111 uninstall_man_prereqs=" uninstall_bcl_manpage"
1112 tests="test_library"
1115 second_target_prereqs="$default_target_prereqs"
1116 default_target_prereqs="$second_target"
1117 default_target_cmd="\$(LINK) \$(BIN) \$(EXEC_PREFIX)\$(DC)"
1121 # We need specific stuff for fuzzing.
1122 if [ "$fuzz" -ne 0 ]; then
1129 # This sets some necessary things for debug mode.
1130 if [ "$debug" -eq 1 ]; then
1132 if [ -z "$CFLAGS" ] && [ -z "$optimization" ]; then
1140 CPPFLAGS="-DNDEBUG $CPPFLAGS"
1142 if [ "$strip_bin" -ne 0 ]; then
1143 LDFLAGS="-s $LDFLAGS"
1147 # Set optimization CFLAGS.
1148 if [ -n "$optimization" ]; then
1149 CFLAGS="-O$optimization $CFLAGS"
1152 # Set test coverage defaults.
1153 if [ "$coverage" -eq 1 ]; then
1155 if [ "$bc_only" -eq 1 ] || [ "$dc_only" -eq 1 ]; then
1156 usage "Can only specify -c without -b or -d"
1159 CFLAGS="-fprofile-arcs -ftest-coverage -g -O0 $CFLAGS"
1160 CPPFLAGS="-DNDEBUG $CPPFLAGS"
1162 COVERAGE_OUTPUT="@gcov -pabcdf \$(GCDA) \$(BC_GCDA) \$(DC_GCDA) \$(HISTORY_GCDA) \$(RAND_GCDA)"
1163 COVERAGE_OUTPUT="$COVERAGE_OUTPUT;\$(RM) -f \$(GEN)*.gc*"
1164 COVERAGE_OUTPUT="$COVERAGE_OUTPUT;gcovr --exclude-unreachable-branches --exclude-throw-branches --html-details --output index.html"
1165 COVERAGE_PREREQS=" test coverage_output"
1168 COVERAGE_OUTPUT="@printf 'Coverage not generated\\\\n'"
1173 # Set some defaults.
1174 if [ -z "${DESTDIR+set}" ]; then
1177 destdir="DESTDIR = $DESTDIR"
1180 if [ -z "${PREFIX+set}" ]; then
1184 if [ -z "${BINDIR+set}" ]; then
1185 BINDIR="$PREFIX/bin"
1188 if [ -z "${INCLUDEDIR+set}" ]; then
1189 INCLUDEDIR="$PREFIX/include"
1192 if [ -z "${LIBDIR+set}" ]; then
1193 LIBDIR="$PREFIX/lib"
1196 if [ -z "${PC_PATH+set}" ]; then
1200 command -v pkg-config > /dev/null
1205 if [ "$err" -eq 0 ]; then
1206 PC_PATH=$(pkg-config --variable=pc_path pkg-config)
1207 PC_PATH="${PC_PATH%%:*}"
1214 # Set a default for the DATAROOTDIR. This is done if either manpages will be
1215 # installed, or locales are enabled because that's probably where NLS_PATH
1217 if [ "$install_manpages" -ne 0 ] || [ "$nls" -ne 0 ]; then
1218 if [ -z "${DATAROOTDIR+set}" ]; then
1219 DATAROOTDIR="$PREFIX/share"
1223 # Set defaults for manpage environment variables.
1224 if [ "$install_manpages" -ne 0 ]; then
1226 if [ -z "${DATADIR+set}" ]; then
1227 DATADIR="$DATAROOTDIR"
1230 if [ -z "${MANDIR+set}" ]; then
1231 MANDIR="$DATADIR/man"
1234 if [ -z "${MAN1DIR+set}" ]; then
1235 MAN1DIR="$MANDIR/man1"
1238 if [ -z "${MAN3DIR+set}" ]; then
1239 MAN3DIR="$MANDIR/man3"
1243 install_man_prereqs=""
1244 uninstall_man_prereqs=""
1247 # Here is where we test NLS (the locale system). This is done by trying to
1248 # compile src/vm.c, which has the relevant code. If it fails, then it is
1250 if [ "$nls" -ne 0 ]; then
1254 printf 'Testing NLS...\n'
1256 flags="-DBC_ENABLE_NLS=1 -DBC_ENABLED=$bc -DDC_ENABLED=$dc"
1257 flags="$flags -DBC_ENABLE_HISTORY=$hist -DBC_ENABLE_LIBRARY=0 -DBC_ENABLE_AFL=0"
1258 flags="$flags -DBC_ENABLE_EXTRA_MATH=$extra_math -I$scriptdir/include/"
1259 flags="$flags -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700"
1261 "$CC" $CPPFLAGS $CFLAGS $flags -c "$scriptdir/src/vm.c" -o "./vm.o" > /dev/null 2>&1
1267 # If this errors, it is probably because of building on Windows,
1268 # and NLS is not supported on Windows, so disable it.
1269 if [ "$err" -ne 0 ]; then
1270 printf 'NLS does not work.\n'
1271 if [ $force -eq 0 ]; then
1272 printf 'Disabling NLS...\n\n'
1275 printf 'Forcing NLS...\n\n'
1278 printf 'NLS works.\n\n'
1280 printf 'Testing gencat...\n'
1281 gencat "./en_US.cat" "$scriptdir/locales/en_US.msg" > /dev/null 2>&1
1285 rm -rf "./en_US.cat"
1287 if [ "$err" -ne 0 ]; then
1288 printf 'gencat does not work.\n'
1289 if [ $force -eq 0 ]; then
1290 printf 'Disabling NLS...\n\n'
1293 printf 'Forcing NLS...\n\n'
1297 printf 'gencat works.\n\n'
1299 # It turns out that POSIX locales are really terrible, and running
1300 # gencat on one machine is not guaranteed to make those cat files
1301 # portable to another machine, so we had better warn the user here.
1302 if [ "$HOSTCC" != "$CC" ] || [ "$OLDHOSTCFLAGS" != "$OLDCFLAGS" ]; then
1303 printf 'Cross-compile detected.\n\n'
1304 printf 'WARNING: Catalog files generated with gencat may not be portable\n'
1305 printf ' across different architectures.\n\n'
1308 if [ -z "$NLSPATH" ]; then
1309 NLSPATH="/usr/share/locale/%L/%N"
1312 install_locales_prereqs=" install_locales"
1313 uninstall_locales_prereqs=" uninstall_locales"
1322 install_locales_prereqs=""
1323 uninstall_locales_prereqs=""
1327 if [ "$nls" -ne 0 ] && [ "$all_locales" -ne 0 ]; then
1328 install_locales="\$(LOCALE_INSTALL) -l \$(NLSPATH) \$(MAIN_EXEC) \$(DESTDIR)"
1330 install_locales="\$(LOCALE_INSTALL) \$(NLSPATH) \$(MAIN_EXEC) \$(DESTDIR)"
1333 # Like the above tested locale support, this tests history.
1334 if [ "$hist" -eq 1 ]; then
1338 printf 'Testing history...\n'
1340 flags="-DBC_ENABLE_HISTORY=1 -DBC_ENABLED=$bc -DDC_ENABLED=$dc"
1341 flags="$flags -DBC_ENABLE_NLS=$nls -DBC_ENABLE_LIBRARY=0 -DBC_ENABLE_AFL=0"
1342 flags="$flags -DBC_ENABLE_EXTRA_MATH=$extra_math -I$scriptdir/include/"
1343 flags="$flags -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700"
1345 "$CC" $CPPFLAGS $CFLAGS $flags -c "$scriptdir/src/history.c" -o "./history.o" > /dev/null 2>&1
1349 rm -rf "./history.o"
1351 # If this errors, it is probably because of building on Windows,
1352 # and history is not supported on Windows, so disable it.
1353 if [ "$err" -ne 0 ]; then
1354 printf 'History does not work.\n'
1355 if [ $force -eq 0 ]; then
1356 printf 'Disabling history...\n\n'
1359 printf 'Forcing history...\n\n'
1362 printf 'History works.\n\n'
1369 # We have to disable the history tests if it is disabled or valgrind is on.
1370 if [ "$hist" -eq 0 ] || [ "$vg" -ne 0 ]; then
1371 test_bc_history_prereqs=" test_bc_history_skip"
1372 test_dc_history_prereqs=" test_dc_history_skip"
1373 history_tests="@printf 'Skipping history tests...\\\\n'"
1375 history_tests="@printf '\$(TEST_STARS)\\\\n\\\\nRunning history tests...\\\\n\\\\n' \&\& \$(TESTSDIR)/history.sh bc -a \&\& \$(TESTSDIR)/history.sh dc -a \&\& printf '\\\\nAll history tests passed.\\\\n\\\\n\$(TEST_STARS)\\\\n'"
1378 # Test OpenBSD. This is not in an if statement because regardless of whatever
1379 # the user says, we need to know if we are on OpenBSD to activate _BSD_SOURCE.
1380 # No, I cannot `#define _BSD_SOURCE` in a header because OpenBSD's patched GCC
1381 # and Clang complain that that is only allowed for system headers. Sigh....So we
1382 # have to check at configure time and set it on the compiler command-line. And
1383 # we have to set it because we also set _POSIX_C_SOURCE, which OpenBSD headers
1384 # detect, and when they detect it, they turn off _BSD_SOURCE unless it is
1385 # specifically requested.
1387 printf 'Testing for OpenBSD...\n'
1389 flags="-DBC_TEST_OPENBSD -DBC_ENABLE_AFL=0"
1390 "$CC" $CPPFLAGS $CFLAGS $flags "-I$scriptdir/include" -E "$scriptdir/include/status.h" > /dev/null 2>&1
1394 if [ "$err" -ne 0 ]; then
1395 printf 'On OpenBSD. Using _BSD_SOURCE.\n\n'
1398 printf 'Not on OpenBSD.\n\n'
1402 if [ "$library" -eq 1 ]; then
1406 if [ "$extra_math" -eq 1 ] && [ "$bc" -ne 0 ] && [ "$library" -eq 0 ]; then
1407 BC_LIB2_O="\$(GEN_DIR)/lib2.o"
1412 # These lines set the appropriate targets based on whether `gen/strgen.c` or
1413 # `gen/strgen.sh` is used.
1415 GEN_EXEC_TARGET="\$(HOSTCC) \$(HOSTCFLAGS) -o \$(GEN_EXEC) \$(GEN_C)"
1416 CLEAN_PREREQS=" clean_gen clean_coverage"
1418 if [ -z "${GEN_HOST+set}" ]; then
1421 if [ "$GEN_HOST" -eq 0 ]; then
1423 GEN_EXEC_TARGET="@printf 'Do not need to build gen/strgen.c\\\\n'"
1424 CLEAN_PREREQS=" clean_coverage"
1430 headers="\$(HEADERS)"
1432 # This series of if statements figure out what source files are *not* needed.
1433 if [ "$extra_math" -eq 0 ]; then
1435 unneeded="$unneeded rand.c"
1437 headers="$headers \$(EXTRA_MATH_HEADERS)"
1440 # All of these next if statements set the build type and mark certain source
1441 # files as unneeded so that they won't have targets generated for them.
1443 if [ "$hist" -eq 0 ]; then
1444 manpage_args="${manpage_args}H"
1445 unneeded="$unneeded history.c"
1447 headers="$headers \$(HISTORY_HEADERS)"
1450 if [ "$nls" -eq 0 ]; then
1451 manpage_args="${manpage_args}N"
1454 if [ "$bc" -eq 0 ]; then
1455 unneeded="$unneeded bc.c bc_lex.c bc_parse.c"
1457 headers="$headers \$(BC_HEADERS)"
1460 if [ "$dc" -eq 0 ]; then
1461 unneeded="$unneeded dc.c dc_lex.c dc_parse.c"
1463 headers="$headers \$(DC_HEADERS)"
1466 # This convoluted mess does pull the version out. If you change the format of
1467 # include/version.h, you may have to change this line.
1468 version=$(cat "$scriptdir/include/version.h" | grep "VERSION " - | awk '{ print $3 }' -)
1470 if [ "$library" -ne 0 ]; then
1472 unneeded="$unneeded args.c opt.c read.c file.c main.c"
1473 unneeded="$unneeded lang.c lex.c parse.c program.c"
1474 unneeded="$unneeded bc.c bc_lex.c bc_parse.c"
1475 unneeded="$unneeded dc.c dc_lex.c dc_parse.c"
1476 headers="$headers \$(LIBRARY_HEADERS)"
1478 if [ "$PC_PATH" != "" ]; then
1480 contents=$(cat "$scriptdir/bcl.pc.in")
1482 contents=$(replace "$contents" "INCLUDEDIR" "$INCLUDEDIR")
1483 contents=$(replace "$contents" "LIBDIR" "$LIBDIR")
1484 contents=$(replace "$contents" "VERSION" "$version")
1486 printf '%s\n' "$contents" > "./bcl.pc"
1488 pkg_config_install="\$(SAFE_INSTALL) \$(PC_INSTALL_ARGS) \"\$(BCL_PC)\" \"\$(DESTDIR)\$(PC_PATH)/\$(BCL_PC)\""
1489 pkg_config_uninstall="\$(RM) -f \"\$(DESTDIR)\$(PC_PATH)/\$(BCL_PC)\""
1493 pkg_config_install=""
1494 pkg_config_uninstall=""
1500 unneeded="$unneeded library.c"
1503 pkg_config_install=""
1504 pkg_config_uninstall=""
1508 # library.c is not needed under normal circumstances.
1509 if [ "$unneeded" = "" ]; then
1510 unneeded="library.c"
1513 # This sets the appropriate manpage for a full build.
1514 if [ "$manpage_args" = "" ]; then
1518 if [ "$vg" -ne 0 ]; then
1522 if [ "$bc_default_prompt" = "" ]; then
1523 bc_default_prompt="$bc_default_tty_mode"
1526 if [ "$dc_default_prompt" = "" ]; then
1527 dc_default_prompt="$dc_default_tty_mode"
1530 # Generate the test targets and prerequisites.
1531 bc_tests=$(gen_std_test_targets bc)
1532 bc_script_tests=$(gen_script_test_targets bc)
1533 bc_err_tests=$(gen_err_test_targets bc)
1534 dc_tests=$(gen_std_test_targets dc)
1535 dc_script_tests=$(gen_script_test_targets dc)
1536 dc_err_tests=$(gen_err_test_targets dc)
1538 # Print out the values; this is for debugging.
1539 printf 'Version: %s\n' "$version"
1541 if [ "$bc" -ne 0 ]; then
1542 printf 'Building bc\n'
1544 printf 'Not building bc\n'
1546 if [ "$dc" -ne 0 ]; then
1547 printf 'Building dc\n'
1549 printf 'Not building dc\n'
1552 printf 'BC_ENABLE_LIBRARY=%s\n\n' "$library"
1553 printf 'BC_ENABLE_HISTORY=%s\n' "$hist"
1554 printf 'BC_ENABLE_EXTRA_MATH=%s\n' "$extra_math"
1555 printf 'BC_ENABLE_NLS=%s\n' "$nls"
1556 printf 'BC_ENABLE_AFL=%s\n' "$fuzz"
1558 printf 'BC_NUM_KARATSUBA_LEN=%s\n' "$karatsuba_len"
1560 printf 'CC=%s\n' "$CC"
1561 printf 'CFLAGS=%s\n' "$CFLAGS"
1562 printf 'HOSTCC=%s\n' "$HOSTCC"
1563 printf 'HOSTCFLAGS=%s\n' "$HOSTCFLAGS"
1564 printf 'CPPFLAGS=%s\n' "$CPPFLAGS"
1565 printf 'LDFLAGS=%s\n' "$LDFLAGS"
1566 printf 'PREFIX=%s\n' "$PREFIX"
1567 printf 'BINDIR=%s\n' "$BINDIR"
1568 printf 'INCLUDEDIR=%s\n' "$INCLUDEDIR"
1569 printf 'LIBDIR=%s\n' "$LIBDIR"
1570 printf 'DATAROOTDIR=%s\n' "$DATAROOTDIR"
1571 printf 'DATADIR=%s\n' "$DATADIR"
1572 printf 'MANDIR=%s\n' "$MANDIR"
1573 printf 'MAN1DIR=%s\n' "$MAN1DIR"
1574 printf 'MAN3DIR=%s\n' "$MAN3DIR"
1575 printf 'NLSPATH=%s\n' "$NLSPATH"
1576 printf 'PC_PATH=%s\n' "$PC_PATH"
1577 printf 'EXECSUFFIX=%s\n' "$EXECSUFFIX"
1578 printf 'EXECPREFIX=%s\n' "$EXECPREFIX"
1579 printf 'DESTDIR=%s\n' "$DESTDIR"
1580 printf 'LONG_BIT=%s\n' "$LONG_BIT"
1581 printf 'GEN_HOST=%s\n' "$GEN_HOST"
1582 printf 'GEN_EMU=%s\n' "$GEN_EMU"
1584 printf 'Setting Defaults\n'
1585 printf '================\n'
1586 printf 'bc.banner=%s\n' "$bc_default_banner"
1587 printf 'bc.sigint_reset=%s\n' "$bc_default_sigint_reset"
1588 printf 'dc.sigint_reset=%s\n' "$dc_default_sigint_reset"
1589 printf 'bc.tty_mode=%s\n' "$bc_default_tty_mode"
1590 printf 'dc.tty_mode=%s\n' "$dc_default_tty_mode"
1591 printf 'bc.prompt=%s\n' "$bc_default_prompt"
1592 printf 'dc.prompt=%s\n' "$dc_default_prompt"
1593 printf 'bc.expr_exit=%s\n' "$bc_default_expr_exit"
1594 printf 'dc.expr_exit=%s\n' "$dc_default_expr_exit"
1596 # This is where the real work begins. This is the point at which the Makefile.in
1597 # template is edited and output to the Makefile.
1599 contents=$(cat "$scriptdir/Makefile.in")
1602 replacement='*** WARNING: Autogenerated from Makefile.in. DO NOT MODIFY ***'
1604 contents=$(replace "$contents" "$needle" "$replacement")
1606 # The contents are edited to have the list of files to build.
1607 contents=$(gen_file_list "$contents" $unneeded)
1611 # This line and loop generates the individual targets for source files. I used
1612 # to just use an implicit target, but that was found to be inadequate when I
1613 # added the library.
1614 src_files=$(find_src_files $unneeded)
1616 for f in $src_files; do
1617 o=$(replace_ext "$f" "c" "o")
1619 SRC_TARGETS=$(printf '%s\n\nsrc/%s: src %s %s\n\t$(CC) $(CFLAGS) -o src/%s -c %s\n' \
1620 "$SRC_TARGETS" "$o" "$headers" "$f" "$o" "$f")
1623 # Replace all the placeholders.
1624 contents=$(replace "$contents" "ROOTDIR" "$scriptdir")
1625 contents=$(replace "$contents" "BUILDDIR" "$builddir")
1627 contents=$(replace "$contents" "HEADERS" "$headers")
1629 contents=$(replace "$contents" "BC_ENABLED" "$bc")
1630 contents=$(replace "$contents" "DC_ENABLED" "$dc")
1632 contents=$(replace "$contents" "BC_ALL_TESTS" "$bc_test")
1633 contents=$(replace "$contents" "BC_ALL_TESTS_NP" "$bc_test_np")
1634 contents=$(replace "$contents" "BC_TESTS" "$bc_tests")
1635 contents=$(replace "$contents" "BC_SCRIPT_TESTS" "$bc_script_tests")
1636 contents=$(replace "$contents" "BC_ERROR_TESTS" "$bc_err_tests")
1637 contents=$(replace "$contents" "BC_TEST_EXEC" "$bc_test_exec")
1638 contents=$(replace "$contents" "TIMECONST_ALL_TESTS" "$timeconst")
1640 contents=$(replace "$contents" "DC_ALL_TESTS" "$dc_test")
1641 contents=$(replace "$contents" "DC_ALL_TESTS_NP" "$dc_test_np")
1642 contents=$(replace "$contents" "DC_TESTS" "$dc_tests")
1643 contents=$(replace "$contents" "DC_SCRIPT_TESTS" "$dc_script_tests")
1644 contents=$(replace "$contents" "DC_ERROR_TESTS" "$dc_err_tests")
1645 contents=$(replace "$contents" "DC_TEST_EXEC" "$dc_test_exec")
1647 contents=$(replace "$contents" "BUILD_TYPE" "$manpage_args")
1649 contents=$(replace "$contents" "LIBRARY" "$library")
1650 contents=$(replace "$contents" "HISTORY" "$hist")
1651 contents=$(replace "$contents" "EXTRA_MATH" "$extra_math")
1652 contents=$(replace "$contents" "NLS" "$nls")
1653 contents=$(replace "$contents" "FUZZ" "$fuzz")
1654 contents=$(replace "$contents" "MEMCHECK" "$memcheck")
1656 contents=$(replace "$contents" "BC_LIB_O" "$bc_lib")
1657 contents=$(replace "$contents" "BC_HELP_O" "$bc_help")
1658 contents=$(replace "$contents" "DC_HELP_O" "$dc_help")
1659 contents=$(replace "$contents" "BC_LIB2_O" "$BC_LIB2_O")
1660 contents=$(replace "$contents" "KARATSUBA_LEN" "$karatsuba_len")
1662 contents=$(replace "$contents" "NLSPATH" "$NLSPATH")
1663 contents=$(replace "$contents" "DESTDIR" "$destdir")
1664 contents=$(replace "$contents" "EXECSUFFIX" "$EXECSUFFIX")
1665 contents=$(replace "$contents" "EXECPREFIX" "$EXECPREFIX")
1666 contents=$(replace "$contents" "BINDIR" "$BINDIR")
1667 contents=$(replace "$contents" "INCLUDEDIR" "$INCLUDEDIR")
1668 contents=$(replace "$contents" "LIBDIR" "$LIBDIR")
1669 contents=$(replace "$contents" "MAN1DIR" "$MAN1DIR")
1670 contents=$(replace "$contents" "MAN3DIR" "$MAN3DIR")
1671 contents=$(replace "$contents" "CFLAGS" "$CFLAGS")
1672 contents=$(replace "$contents" "HOSTCFLAGS" "$HOSTCFLAGS")
1673 contents=$(replace "$contents" "CPPFLAGS" "$CPPFLAGS")
1674 contents=$(replace "$contents" "LDFLAGS" "$LDFLAGS")
1675 contents=$(replace "$contents" "CC" "$CC")
1676 contents=$(replace "$contents" "HOSTCC" "$HOSTCC")
1677 contents=$(replace "$contents" "COVERAGE_OUTPUT" "$COVERAGE_OUTPUT")
1678 contents=$(replace "$contents" "COVERAGE_PREREQS" "$COVERAGE_PREREQS")
1679 contents=$(replace "$contents" "INSTALL_PREREQS" "$install_prereqs")
1680 contents=$(replace "$contents" "INSTALL_MAN_PREREQS" "$install_man_prereqs")
1681 contents=$(replace "$contents" "INSTALL_LOCALES" "$install_locales")
1682 contents=$(replace "$contents" "INSTALL_LOCALES_PREREQS" "$install_locales_prereqs")
1683 contents=$(replace "$contents" "UNINSTALL_MAN_PREREQS" "$uninstall_man_prereqs")
1684 contents=$(replace "$contents" "UNINSTALL_PREREQS" "$uninstall_prereqs")
1685 contents=$(replace "$contents" "UNINSTALL_LOCALES_PREREQS" "$uninstall_locales_prereqs")
1687 contents=$(replace "$contents" "PC_PATH" "$PC_PATH")
1688 contents=$(replace "$contents" "PKG_CONFIG_INSTALL" "$pkg_config_install")
1689 contents=$(replace "$contents" "PKG_CONFIG_UNINSTALL" "$pkg_config_uninstall")
1691 contents=$(replace "$contents" "DEFAULT_TARGET" "$default_target")
1692 contents=$(replace "$contents" "DEFAULT_TARGET_PREREQS" "$default_target_prereqs")
1693 contents=$(replace "$contents" "DEFAULT_TARGET_CMD" "$default_target_cmd")
1694 contents=$(replace "$contents" "SECOND_TARGET" "$second_target")
1695 contents=$(replace "$contents" "SECOND_TARGET_PREREQS" "$second_target_prereqs")
1696 contents=$(replace "$contents" "SECOND_TARGET_CMD" "$second_target_cmd")
1698 contents=$(replace "$contents" "ALL_PREREQ" "$ALL_PREREQ")
1699 contents=$(replace "$contents" "BC_EXEC_PREREQ" "$bc_exec_prereq")
1700 contents=$(replace "$contents" "BC_EXEC_CMD" "$bc_exec_cmd")
1701 contents=$(replace "$contents" "DC_EXEC_PREREQ" "$dc_exec_prereq")
1702 contents=$(replace "$contents" "DC_EXEC_CMD" "$dc_exec_cmd")
1704 contents=$(replace "$contents" "EXECUTABLES" "$executables")
1705 contents=$(replace "$contents" "MAIN_EXEC" "$main_exec")
1706 contents=$(replace "$contents" "EXEC" "$executable")
1707 contents=$(replace "$contents" "TESTS" "$tests")
1709 contents=$(replace "$contents" "BC_HISTORY_TEST_PREREQS" "$test_bc_history_prereqs")
1710 contents=$(replace "$contents" "DC_HISTORY_TEST_PREREQS" "$test_dc_history_prereqs")
1711 contents=$(replace "$contents" "HISTORY_TESTS" "$history_tests")
1713 contents=$(replace "$contents" "VG_BC_TEST" "$vg_bc_test")
1714 contents=$(replace "$contents" "VG_DC_TEST" "$vg_dc_test")
1716 contents=$(replace "$contents" "TIMECONST" "$timeconst")
1718 contents=$(replace "$contents" "KARATSUBA" "$karatsuba")
1719 contents=$(replace "$contents" "KARATSUBA_TEST" "$karatsuba_test")
1721 contents=$(replace "$contents" "LONG_BIT" "$LONG_BIT")
1722 contents=$(replace "$contents" "LONG_BIT_DEFINE" "$LONG_BIT_DEFINE")
1724 contents=$(replace "$contents" "GEN" "$GEN")
1725 contents=$(replace "$contents" "GEN_EXEC_TARGET" "$GEN_EXEC_TARGET")
1726 contents=$(replace "$contents" "CLEAN_PREREQS" "$CLEAN_PREREQS")
1727 contents=$(replace "$contents" "GEN_EMU" "$GEN_EMU")
1729 contents=$(replace "$contents" "BSD" "$bsd")
1731 contents=$(replace "$contents" "BC_DEFAULT_BANNER" "$bc_default_banner")
1732 contents=$(replace "$contents" "BC_DEFAULT_SIGINT_RESET" "$bc_default_sigint_reset")
1733 contents=$(replace "$contents" "DC_DEFAULT_SIGINT_RESET" "$dc_default_sigint_reset")
1734 contents=$(replace "$contents" "BC_DEFAULT_TTY_MODE" "$bc_default_tty_mode")
1735 contents=$(replace "$contents" "DC_DEFAULT_TTY_MODE" "$dc_default_tty_mode")
1736 contents=$(replace "$contents" "BC_DEFAULT_PROMPT" "$bc_default_prompt")
1737 contents=$(replace "$contents" "DC_DEFAULT_PROMPT" "$dc_default_prompt")
1738 contents=$(replace "$contents" "BC_DEFAULT_EXPR_EXIT" "$bc_default_expr_exit")
1739 contents=$(replace "$contents" "DC_DEFAULT_EXPR_EXIT" "$dc_default_expr_exit")
1741 # Do the first print to the Makefile.
1742 printf '%s\n%s\n\n' "$contents" "$SRC_TARGETS" > "Makefile"
1744 # Generate the individual test targets.
1745 if [ "$bc" -ne 0 ]; then
1746 gen_std_tests bc "$extra_math" "$time_tests" $bc_test_exec
1747 gen_script_tests bc "$extra_math" "$generate_tests" "$time_tests" $bc_test_exec
1748 gen_err_tests bc $bc_test_exec
1751 if [ "$dc" -ne 0 ]; then
1752 gen_std_tests dc "$extra_math" "$time_tests" $dc_test_exec
1753 gen_script_tests dc "$extra_math" "$generate_tests" "$time_tests" $dc_test_exec
1754 gen_err_tests dc $dc_test_exec
1757 # Copy the correct manuals to the expected places.
1759 cp -f "$scriptdir/manuals/bc/$manpage_args.1.md" manuals/bc.1.md
1760 cp -f "$scriptdir/manuals/bc/$manpage_args.1" manuals/bc.1
1761 cp -f "$scriptdir/manuals/dc/$manpage_args.1.md" manuals/dc.1.md
1762 cp -f "$scriptdir/manuals/dc/$manpage_args.1" manuals/dc.1
1764 make clean > /dev/null