• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
30# For OpenBSD, run using the following:
31#
32# scripts/release.sh 1 0 0 1 0 0 0 0 1 0 0 0 0 0 0 1 0
33#
34# For FreeBSD, run using the following:
35#
36# scripts/release.sh 1 1 0 1 0 0 0 0 1 0 1 0 1 0 0 1 1
37#
38# For Linux, run two separate ones (in different checkouts), like so:
39#
40# scripts/release.sh 1 1 1 1 0 1 0 0 1 0 1 0 1 0 0 1 1
41# cd build; ../scripts/release.sh 1 1 1 0 1 0 1 0 1 0 1 0 0 1 1 1 1
42#
43# Yes, I usually do sanitizers with Clang and Valgrind with GCC, and I also do
44# out-of-source builds with GCC.
45#
46# The reason I run history tests with GCC and not with Clang is because Clang
47# already runs slower as a result of running with sanitizers, and the history
48# tests are a little sensitive to load on a system.
49#
50# If this script fails on any platform when starting the Karatsuba test, check
51# that Python is installed, especially if the error says something like:
52# "karatsuba.py: not found".
53
54# Print the usage and exit with an error. Each parameter should be an integer.
55# Non-zero activates, and zero deactivates.
56# @param 1  A message to print.
57usage() {
58	if [ $# -eq 1 ]; then
59		printf '%s\n\n' "$1"
60	fi
61	printf 'usage: %s [run_tests] [generate_tests] [run_problematic_tests] \n' "$script"
62	printf '          [test_with_clang] [test_with_gcc] [run_sanitizers] [run_valgrind] \n'
63	printf '          [test_settings] [run_64_bit] [run_gen_script] [test_c11] \n'
64	printf '          [test_128_bit] [test_computed_goto] [test_karatsuba] [test_history] \n'
65	printf '          [test_editline] [test_readline]\n'
66	exit 1
67}
68
69# Print a header with a message. This is just to make it easy to track progress.
70# @param msg  The message to print in the header.
71header() {
72
73	_header_msg="$1"
74	shift
75
76	printf '\n'
77	printf '*******************\n'
78	printf "$_header_msg"
79	printf '\n'
80	printf '*******************\n'
81	printf '\n'
82}
83
84# Easy way to call make.
85do_make() {
86	# No reason to do 64 except to see if I actually can overload my system. :)
87	# Well, also that it might actually improve throughput as other jobs can run
88	# while some are waiting.
89	make -j64 "$@"
90}
91
92# Run configure.sh.
93# @param CFLAGS           The CFLAGS.
94# @param CC               The C compiler.
95# @param configure_flags  The flags for configure.sh itself.
96# @param GEN_HOST         The setting for GEN_HOST.
97# @param LONG_BIT         The setting for LONG_BIT.
98configure() {
99
100	_configure_CFLAGS="$1"
101	shift
102
103	_configure_CC="$1"
104	shift
105
106	_configure_configure_flags="$1"
107	shift
108
109	_configure_GEN_HOST="$1"
110	shift
111
112	_configure_LONG_BIT="$1"
113	shift
114
115	# Make sure to not generate tests if necessary.
116	if [ "$gen_tests" -eq 0 ]; then
117		_configure_configure_flags="-G $_configure_configure_flags"
118	fi
119
120	# Make sure to skip problematic tests if necessary.
121	if [ "$problematic_tests" -eq 0 ]; then
122		_configure_configure_flags="-P $_configure_configure_flags"
123	fi
124
125	# Choose the right extra flags.
126	if [ "$_configure_CC" = "clang" ]; then
127
128		_configure_CFLAGS="$clang_flags $_configure_CFLAGS"
129
130		# We need to quiet this warning from Clang because the configure.sh docs
131		# have this warning, so people should know. Also, I want this script to
132		# work.
133		if [ "$_configure_GEN_HOST" -eq 0 ]; then
134			_configure_CFLAGS="$_configure_CFLAGS -Wno-overlength-strings"
135		fi
136
137	elif [ "$_configure_CC" = "gcc" ]; then
138
139		_configure_CFLAGS="$gcc_flags $_configure_CFLAGS"
140
141		# We need to quiet this warning from GCC because the configure.sh docs
142		# have this warning, so people should know. Also, I want this script to
143		# work.
144		if [ "$_configure_GEN_HOST" -eq 0 ]; then
145			_configure_CFLAGS="$_configure_CFLAGS -Wno-overlength-strings"
146		fi
147
148	fi
149
150	# Print the header and do the job.
151	_configure_header=$(printf 'Running configure.sh %s ...' "$_configure_configure_flags")
152	_configure_header=$(printf "$_configure_header\n    CC=\"%s\"\n" "$_configure_CC")
153	_configure_header=$(printf "$_configure_header\n    CFLAGS=\"%s\"\n" "$_configure_CFLAGS")
154	_configure_header=$(printf "$_configure_header\n    LONG_BIT=%s" "$_configure_LONG_BIT")
155	_configure_header=$(printf "$_configure_header\n    GEN_HOST=%s" "$_configure_GEN_HOST")
156
157	header "$_configure_header"
158	CFLAGS="$_configure_CFLAGS" CC="$_configure_CC" GEN_HOST="$_configure_GEN_HOST" \
159		LONG_BIT="$_configure_LONG_BIT" "$real/configure.sh" $_configure_configure_flags > /dev/null
160}
161
162# Build with make. This function also captures and outputs any warnings if they
163# exists because as far as I am concerned, warnings are not acceptable for
164# release.
165# @param CFLAGS           The CFLAGS.
166# @param CC               The C compiler.
167# @param configure_flags  The flags for configure.sh itself.
168# @param GEN_HOST         The setting for GEN_HOST.
169# @param LONG_BIT         The setting for LONG_BIT.
170build() {
171
172	_build_CFLAGS="$1"
173	shift
174
175	_build_CC="$1"
176	shift
177
178	_build_configure_flags="$1"
179	shift
180
181	_build_GEN_HOST="$1"
182	shift
183
184	_build_LONG_BIT="$1"
185	shift
186
187	configure "$_build_CFLAGS" "$_build_CC" "$_build_configure_flags" "$_build_GEN_HOST" "$_build_LONG_BIT"
188
189	_build_header=$(printf 'Building...\n    CC=%s' "$_build_CC")
190	_build_header=$(printf "$_build_header\n    CFLAGS=\"%s\"" "$_build_CFLAGS")
191	_build_header=$(printf "$_build_header\n    LONG_BIT=%s" "$_build_LONG_BIT")
192	_build_header=$(printf "$_build_header\n    GEN_HOST=%s" "$_build_GEN_HOST")
193
194	header "$_build_header"
195
196	set +e
197
198	# Capture and print warnings.
199	do_make > /dev/null 2> "./.test.txt"
200	err=$?
201
202	set -e
203
204	if [ -s "./.test.txt" ]; then
205		printf '%s generated warning(s):\n' "$_build_CC"
206		printf '\n'
207		cat "./.test.txt"
208		exit 1
209	fi
210
211	if [ "$err" -ne 0 ]; then
212		exit "$err"
213	fi
214}
215
216# Run tests with make.
217runtest() {
218
219	header "Running tests"
220
221	if [ "$#" -gt 0 ]; then
222		do_make "$@"
223	else
224
225		do_make test
226
227		if [ "$test_history" -ne 0 ]; then
228			do_make test_history
229		fi
230	fi
231}
232
233# Builds and runs tests with both calculators, then bc only, then dc only. If
234# run_tests is false, then it just does the builds.
235# @param CFLAGS           The CFLAGS.
236# @param CC               The C compiler.
237# @param configure_flags  The flags for configure.sh itself.
238# @param GEN_HOST         The setting for GEN_HOST.
239# @param LONG_BIT         The setting for LONG_BIT.
240# @param run_tests        Whether to run tests or not.
241runconfigtests() {
242
243	_runconfigtests_CFLAGS="$1"
244	shift
245
246	_runconfigtests_CC="$1"
247	shift
248
249	_runconfigtests_configure_flags="$1"
250	shift
251
252	_runconfigtests_GEN_HOST="$1"
253	shift
254
255	_runconfigtests_LONG_BIT="$1"
256	shift
257
258	_runconfigtests_run_tests="$1"
259	shift
260
261	if [ "$_runconfigtests_run_tests" -ne 0 ]; then
262		_runconfigtests_header=$(printf 'Running tests with configure flags')
263	else
264		_runconfigtests_header=$(printf 'Building with configure flags')
265	fi
266
267	_runconfigtests_header=$(printf "$_runconfigtests_header \"%s\" ...\n" "$_runconfigtests_configure_flags")
268	_runconfigtests_header=$(printf "$_runconfigtests_header\n    CC=%s\n" "$_runconfigseries_CC")
269	_runconfigtests_header=$(printf "$_runconfigtests_header\n    CFLAGS=\"%s\"" "$_runconfigseries_CFLAGS")
270	_runconfigtests_header=$(printf "$_runconfigtests_header\n    LONG_BIT=%s" "$_runconfigtests_LONG_BIT")
271	_runconfigtests_header=$(printf "$_runconfigtests_header\n    GEN_HOST=%s" "$_runconfigtests_GEN_HOST")
272
273	header "$_runconfigtests_header"
274
275	build "$_runconfigtests_CFLAGS" "$_runconfigtests_CC" \
276		"$_runconfigtests_configure_flags" "$_runconfigtests_GEN_HOST" \
277		"$_runconfigtests_LONG_BIT"
278
279	if [ "$_runconfigtests_run_tests" -ne 0 ]; then
280		runtest
281	fi
282
283	do_make clean
284
285	build "$_runconfigtests_CFLAGS" "$_runconfigtests_CC" \
286		"$_runconfigtests_configure_flags -b" "$_runconfigtests_GEN_HOST" \
287		"$_runconfigtests_LONG_BIT"
288
289	if [ "$_runconfigtests_run_tests" -ne 0 ]; then
290		runtest
291	fi
292
293	do_make clean
294
295	build "$_runconfigtests_CFLAGS" "$_runconfigtests_CC" \
296		"$_runconfigtests_configure_flags -d" "$_runconfigtests_GEN_HOST" \
297		"$_runconfigtests_LONG_BIT"
298
299	if [ "$_runconfigtests_run_tests" -ne 0 ]; then
300		runtest
301	fi
302
303	do_make clean
304}
305
306# Builds and runs tests with runconfigtests(), but also does 64-bit, 32-bit, and
307# 128-bit rand, if requested. It also does it with the gen script (strgen.sh) if
308# requested. If run_tests is false, it just does the builds.
309# @param CFLAGS           The CFLAGS.
310# @param CC               The C compiler.
311# @param configure_flags  The flags for configure.sh itself.
312# @param run_tests        Whether to run tests or not.
313runconfigseries() {
314
315	_runconfigseries_CFLAGS="$1"
316	shift
317
318	_runconfigseries_CC="$1"
319	shift
320
321	_runconfigseries_configure_flags="$1"
322	shift
323
324	_runconfigseries_run_tests="$1"
325	shift
326
327	if [ "$run_64_bit" -ne 0 ]; then
328
329		if [ "$test_128_bit" -ne 0 ]; then
330			runconfigtests "$_runconfigseries_CFLAGS" "$_runconfigseries_CC" \
331				"$_runconfigseries_configure_flags" 1 64 "$_runconfigseries_run_tests"
332		fi
333
334		if [ "$run_gen_script" -ne 0 ]; then
335			runconfigtests "$_runconfigseries_CFLAGS" "$_runconfigseries_CC" \
336				"$_runconfigseries_configure_flags" 0 64 "$_runconfigseries_run_tests"
337		fi
338
339		runconfigtests "$_runconfigseries_CFLAGS -DBC_RAND_BUILTIN=0" "$_runconfigseries_CC" \
340			"$_runconfigseries_configure_flags" 1 64 "$_runconfigseries_run_tests"
341
342		# Test Editline and Readline if history is not turned off.
343		if [ "${_runconfigseries_configure_flags#*H}" = "${_runconfigseries_configure_flags}" ]; then
344
345			if [ "$test_editline" -ne 0 ]; then
346				runconfigtests "$_runconfigseries_CFLAGS -DBC_RAND_BUILTIN=0" "$_runconfigseries_CC" \
347					"$_runconfigseries_configure_flags -e" 1 64 "$_runconfigseries_run_tests"
348			fi
349
350			if [ "$test_readline" -ne 0 ]; then
351				runconfigtests "$_runconfigseries_CFLAGS -DBC_RAND_BUILTIN=0" "$_runconfigseries_CC" \
352					"$_runconfigseries_configure_flags -r" 1 64 "$_runconfigseries_run_tests"
353			fi
354
355		fi
356
357	fi
358
359	runconfigtests "$_runconfigseries_CFLAGS" "$_runconfigseries_CC" \
360		"$_runconfigseries_configure_flags" 1 32 "$_runconfigseries_run_tests"
361
362	if [ "$run_gen_script" -ne 0 ]; then
363		runconfigtests "$_runconfigseries_CFLAGS" "$_runconfigseries_CC" \
364			"$_runconfigseries_configure_flags" 0 32 "$_runconfigseries_run_tests"
365	fi
366}
367
368# Builds and runs tests with each setting combo running runconfigseries(). If
369# run_tests is false, it just does the builds.
370# @param CFLAGS           The CFLAGS.
371# @param CC               The C compiler.
372# @param configure_flags  The flags for configure.sh itself.
373# @param run_tests        Whether to run tests or not.
374runsettingsseries() {
375
376	_runsettingsseries_CFLAGS="$1"
377	shift
378
379	_runsettingsseries_CC="$1"
380	shift
381
382	_runsettingsseries_configure_flags="$1"
383	shift
384
385	_runsettingsseries_run_tests="$1"
386	shift
387
388	if [ "$test_settings" -ne 0 ]; then
389
390		while read _runsettingsseries_s; do
391			runconfigseries "$_runsettingsseries_CFLAGS" "$_runsettingsseries_CC" \
392				"$_runsettingsseries_configure_flags $_runsettingsseries_s" \
393				"$_runsettingsseries_run_tests"
394		done < "$scriptdir/release_settings.txt"
395
396	else
397		runconfigseries "$_runsettingsseries_CFLAGS" "$_runsettingsseries_CC" \
398			"$_runsettingsseries_configure_flags" "$_runsettingsseries_run_tests"
399	fi
400}
401
402# Builds and runs tests with each build type running runsettingsseries(). If
403# run_tests is false, it just does the builds.
404# @param CFLAGS           The CFLAGS.
405# @param CC               The C compiler.
406# @param configure_flags  The flags for configure.sh itself.
407# @param run_tests        Whether to run tests or not.
408runtestseries() {
409
410	_runtestseries_CFLAGS="$1"
411	shift
412
413	_runtestseries_CC="$1"
414	shift
415
416	_runtestseries_configure_flags="$1"
417	shift
418
419	_runtestseries_run_tests="$1"
420	shift
421
422	_runtestseries_flags="E H N EH EN HN EHN"
423
424	runsettingsseries "$_runtestseries_CFLAGS" "$_runtestseries_CC" \
425		"$_runtestseries_configure_flags" "$_runtestseries_run_tests"
426
427	for _runtestseries_f in $_runtestseries_flags; do
428		runsettingsseries "$_runtestseries_CFLAGS" "$_runtestseries_CC" \
429			"$_runtestseries_configure_flags -$_runtestseries_f" "$_runtestseries_run_tests"
430	done
431}
432
433# Builds and runs the tests for bcl. If run_tests is false, it just does the
434# builds.
435# @param CFLAGS           The CFLAGS.
436# @param CC               The C compiler.
437# @param configure_flags  The flags for configure.sh itself.
438# @param run_tests        Whether to run tests or not.
439runlibtests() {
440
441	_runlibtests_CFLAGS="$1"
442	shift
443
444	_runlibtests_CC="$1"
445	shift
446
447	_runlibtests_configure_flags="$1"
448	shift
449
450	_runlibtests_run_tests="$1"
451	shift
452
453	_runlibtests_configure_flags="$_runlibtests_configure_flags -a"
454
455	build "$_runlibtests_CFLAGS" "$_runlibtests_CC" "$_runlibtests_configure_flags" 1 64
456
457	if [ "$_runlibtests_run_tests" -ne 0 ]; then
458		runtest test
459	fi
460
461	build "$_runlibtests_CFLAGS" "$_runlibtests_CC" "$_runlibtests_configure_flags" 1 32
462
463	if [ "$_runlibtests_run_tests" -ne 0 ]; then
464		runtest test
465	fi
466}
467
468# Builds and runs tests under C99, then C11, if requested, using
469# runtestseries(). If run_tests is false, it just does the builds.
470# @param CFLAGS           The CFLAGS.
471# @param CC               The C compiler.
472# @param configure_flags  The flags for configure.sh itself.
473# @param run_tests        Whether to run tests or not.
474runtests() {
475
476	_runtests_CFLAGS="$1"
477	shift
478
479	_runtests_CC="$1"
480	shift
481
482	_runtests_configure_flags="$1"
483	shift
484
485	_runtests_run_tests="$1"
486	shift
487
488	runtestseries "-std=c99 $_runtests_CFLAGS" "$_runtests_CC" "$_runtests_configure_flags" "$_runtests_run_tests"
489
490	if [ "$test_c11" -ne 0 ]; then
491		runtestseries "-std=c11 $_runtests_CFLAGS" "$_runtests_CC" "$_runtests_configure_flags" "$_runtests_run_tests"
492	fi
493}
494
495# Runs the karatsuba tests.
496karatsuba() {
497
498	header "Running Karatsuba tests"
499	do_make karatsuba_test
500}
501
502# Builds and runs under valgrind. It runs both, bc only, then dc only.
503vg() {
504
505	header "Running valgrind"
506
507	if [ "$run_64_bit" -ne 0 ]; then
508		_vg_bits=64
509	else
510		_vg_bits=32
511	fi
512
513	build "$debug -std=c99" "gcc" "-O3 -gv" "1" "$_vg_bits"
514	runtest test
515
516	do_make clean_config
517
518	build "$debug -std=c99" "gcc" "-O3 -gvb" "1" "$_vg_bits"
519	runtest test
520
521	do_make clean_config
522
523	build "$debug -std=c99" "gcc" "-O3 -gvd" "1" "$_vg_bits"
524	runtest test
525
526	do_make clean_config
527
528	build "$debug -std=c99" "gcc" "-O3 -gva" "1" "$_vg_bits"
529	runtest test
530
531	do_make clean_config
532}
533
534# Builds the debug series and runs the tests if run_tests allows. If sanitizers
535# are enabled, it also does UBSan.
536# @param CC         The C compiler.
537# @param run_tests  Whether to run tests or not.
538debug() {
539
540	_debug_CC="$1"
541	shift
542
543	_debug_run_tests="$1"
544	shift
545
546
547	if [ "$_debug_CC" = "clang" -a "$run_sanitizers" -ne 0 ]; then
548		runtests "$debug -fsanitize=undefined" "$_debug_CC" "-gm" "$_debug_run_tests"
549	else
550		runtests "$debug" "$_debug_CC" "-g" "$_debug_run_tests"
551	fi
552
553	if [ "$_debug_CC" = "clang" -a "$run_sanitizers" -ne 0 ]; then
554		runlibtests "$debug -fsanitize=undefined" "$_debug_CC" "-gm" "$_debug_run_tests"
555	else
556		runlibtests "$debug" "$_debug_CC" "-g" "$_debug_run_tests"
557	fi
558}
559
560# Builds the release series and runs the test if run_tests allows.
561# @param CC         The C compiler.
562# @param run_tests  Whether to run tests or not.
563release() {
564
565	_release_CC="$1"
566	shift
567
568	_release_run_tests="$1"
569	shift
570
571	runtests "$release" "$_release_CC" "-O3" "$_release_run_tests"
572
573	runlibtests "$release" "$_release_CC" "-O3" "$_release_run_tests"
574}
575
576# Builds the release debug series and runs the test if run_tests allows. If
577# sanitizers are enabled, it also does ASan and MSan.
578# @param CC         The C compiler.
579# @param run_tests  Whether to run tests or not.
580reldebug() {
581
582	_reldebug_CC="$1"
583	shift
584
585	_reldebug_run_tests="$1"
586	shift
587
588
589	if [ "$_reldebug_CC" = "clang" -a "$run_sanitizers" -ne 0 ]; then
590		runtests "$debug -fsanitize=address" "$_reldebug_CC" "-mgO3" "$_reldebug_run_tests"
591		runtests "$debug -fsanitize=memory" "$_reldebug_CC" "-mgO3" "$_reldebug_run_tests"
592	else
593		runtests "$debug" "$_reldebug_CC" "-gO3" "$_reldebug_run_tests"
594	fi
595
596
597	if [ "$_reldebug_CC" = "clang" -a "$run_sanitizers" -ne 0 ]; then
598		runlibtests "$debug -fsanitize=address" "$_reldebug_CC" "-mgO3" "$_reldebug_run_tests"
599		runlibtests "$debug -fsanitize=memory" "$_reldebug_CC" "-mgO3" "$_reldebug_run_tests"
600	else
601		runlibtests "$debug" "$_reldebug_CC" "-gO3" "$_reldebug_run_tests"
602	fi
603}
604
605# Builds the min size release series and runs the test if run_tests allows.
606# @param CC         The C compiler.
607# @param run_tests  Whether to run tests or not.
608minsize() {
609
610	_minsize_CC="$1"
611	shift
612
613	_minsize_run_tests="$1"
614	shift
615
616	runtests "$release" "$_minsize_CC" "-Os" "$_minsize_run_tests"
617
618	runlibtests "$release" "$_minsize_CC" "-Os" "$_minsize_run_tests"
619}
620
621# Builds all sets: debug, release, release debug, and min size, and runs the
622# tests if run_tests allows.
623# @param CC         The C compiler.
624# @param run_tests  Whether to run tests or not.
625build_set() {
626
627	_build_set_CC="$1"
628	shift
629
630	_build_set_run_tests="$1"
631	shift
632
633	debug "$_build_set_CC" "$_build_set_run_tests"
634	release "$_build_set_CC" "$_build_set_run_tests"
635	reldebug "$_build_set_CC" "$_build_set_run_tests"
636	minsize "$_build_set_CC" "$_build_set_run_tests"
637}
638
639set -e
640
641script="$0"
642scriptdir=$(dirname "$script")
643
644. "$scriptdir/functions.sh"
645
646# Unset all bc and dc environment variables. This is intended to allow this
647# script to run in a clean environment.
648unset POSIXLY_CORRECT
649unset BC_BANNER
650unset BC_ENV_ARGS
651unset DC_ENV_ARGS
652unset BC_LINE_LENGTH
653unset DC_LINE_LENGTH
654unset BC_SIGINT_RESET
655unset DC_SIGINT_RESET
656unset BC_TTY_MODE
657unset DC_TTY_MODE
658unset BC_PROMPT
659unset DC_PROMPT
660unset BC_EXPR_EXIT
661unset DC_EXPR_EXIT
662unset BC_DIGIT_CLAMP
663unset DC_DIGIT_CLAMP
664
665# Set some strict warning flags. Clang's -Weverything can be way too strict, so
666# we actually have to turn off some things.
667clang_flags="-Weverything -Wno-padded"
668gcc_flags="-Wno-clobbered"
669
670# Common CFLAGS.
671cflags="-Wall -Wextra -Werror -pedantic"
672
673# Common debug and release flags.
674debug="$cflags -fno-omit-frame-pointer"
675release="$cflags -DNDEBUG"
676
677real=$(realpath "$scriptdir/../")
678
679# Whether to run tests.
680if [ "$#" -gt 0 ]; then
681	run_tests="$1"
682	shift
683	check_bool_arg "$run_tests"
684else
685	run_tests=1
686	check_bool_arg "$run_tests"
687fi
688
689# Whether to generate tests. On platforms like OpenBSD, there is no GNU bc to
690# generate tests, so this must be off.
691if [ "$#" -gt 0 ]; then
692	gen_tests="$1"
693	shift
694	check_bool_arg "$gen_tests"
695else
696	gen_tests=1
697	check_bool_arg "$gen_tests"
698fi
699
700# Whether to run problematic tests. This needs to be off on FreeBSD.
701if [ "$#" -gt 0 ]; then
702	problematic_tests="$1"
703	shift
704	check_bool_arg "$problematic_tests"
705else
706	problematic_tests=1
707	check_bool_arg "$problematic_tests"
708fi
709
710# Whether to test with clang.
711if [ "$#" -gt 0 ]; then
712	test_with_clang="$1"
713	shift
714	check_bool_arg "$test_with_clang"
715else
716	test_with_clang=1
717	check_bool_arg "$test_with_clang"
718fi
719
720# Whether to test with gcc.
721if [ "$#" -gt 0 ]; then
722	test_with_gcc="$1"
723	shift
724	check_bool_arg "$test_with_gcc"
725else
726	test_with_gcc=1
727	check_bool_arg "$test_with_clang"
728fi
729
730# Whether to test with sanitizers.
731if [ "$#" -gt 0 ]; then
732	run_sanitizers="$1"
733	check_bool_arg "$run_sanitizers"
734	shift
735else
736	run_sanitizers=1
737	check_bool_arg "$run_sanitizers"
738fi
739
740# Whether to test with valgrind.
741if [ "$#" -gt 0 ]; then
742	run_valgrind="$1"
743	shift
744	check_bool_arg "$run_valgrind"
745else
746	run_valgrind=1
747	check_bool_arg "$run_valgrind"
748fi
749
750# Whether to test all settings combos.
751if [ "$#" -gt 0 ]; then
752	test_settings="$1"
753	shift
754	check_bool_arg "$test_settings"
755else
756	test_settings=1
757	check_bool_arg "$test_settings"
758fi
759
760# Whether to test 64-bit in addition to 32-bit.
761if [ "$#" -gt 0 ]; then
762	run_64_bit="$1"
763	shift
764	check_bool_arg "$run_64_bit"
765else
766	run_64_bit=1
767	check_bool_arg "$run_64_bit"
768fi
769
770# Whether to test with strgen.sh in addition to strgen.c.
771if [ "$#" -gt 0 ]; then
772	run_gen_script="$1"
773	shift
774	check_bool_arg "$run_gen_script"
775else
776	run_gen_script=0
777	check_bool_arg "$run_gen_script"
778fi
779
780# Whether to test on C11 in addition to C99.
781if [ "$#" -gt 0 ]; then
782	test_c11="$1"
783	shift
784	check_bool_arg "$test_c11"
785else
786	test_c11=0
787	check_bool_arg "$test_c11"
788fi
789
790# Whether to test 128-bit integers in addition to no 128-bit integers.
791if [ "$#" -gt 0 ]; then
792	test_128_bit="$1"
793	shift
794	check_bool_arg "$test_128_bit"
795else
796	test_128_bit=0
797	check_bool_arg "$test_128_bit"
798fi
799
800# Whether to test with computed goto or not.
801if [ "$#" -gt 0 ]; then
802	test_computed_goto="$1"
803	shift
804	check_bool_arg "$test_computed_goto"
805else
806	test_computed_goto=0
807	check_bool_arg "$test_computed_goto"
808fi
809
810# Whether to test history or not.
811if [ "$#" -gt 0 ]; then
812	test_karatsuba="$1"
813	shift
814	check_bool_arg "$test_karatsuba"
815else
816	test_karatsuba=1
817	check_bool_arg "$test_karatsuba"
818fi
819
820# Whether to test history or not.
821if [ "$#" -gt 0 ]; then
822	test_history="$1"
823	shift
824	check_bool_arg "$test_history"
825else
826	test_history=0
827	check_bool_arg "$test_history"
828fi
829
830# Whether to test editline or not.
831if [ "$#" -gt 0 ]; then
832	test_editline="$1"
833	shift
834	check_bool_arg "$test_editline"
835else
836	test_editline=0
837	check_bool_arg "$test_editline"
838fi
839
840# Whether to test editline or not.
841if [ "$#" -gt 0 ]; then
842	test_readline="$1"
843	shift
844	check_bool_arg "$test_readline"
845else
846	test_readline=0
847	check_bool_arg "$test_readline"
848fi
849
850if [ "$run_64_bit" -ne 0 ]; then
851	bits=64
852else
853	bits=32
854fi
855
856if [ "$test_computed_goto" -eq 0 ]; then
857	clang_flags="-DBC_NO_COMPUTED_GOTO $clang_flags"
858	gcc_flags="-DBC_NO_COMPUTED_GOTO $gcc_flags"
859fi
860
861# Setup a default compiler.
862if [ "$test_with_clang" -ne 0 ]; then
863	defcc="clang"
864elif [ "$test_with_gcc" -ne 0 ]; then
865	defcc="gcc"
866else
867	defcc="c99"
868fi
869
870export ASAN_OPTIONS="abort_on_error=1,allocator_may_return_null=1:strict_string_checks=1:detect_stack_use_after_return=1:check_initialization_order=1:strict_init_order=1:detect_invalid_pointer_pairs=2"
871export UBSAN_OPTIONS="print_stack_trace=1,silence_unsigned_overflow=1"
872
873build "$debug -std=c99" "$defcc" "-g" "1" "$bits"
874
875header "Running math library under --standard"
876
877# Make sure the math library is POSIX compliant.
878printf 'quit\n' | bin/bc -ls
879
880do_make clean_tests
881
882# Run the clang build sets.
883if [ "$test_with_clang" -ne 0 ]; then
884	build_set "clang" "$run_tests"
885fi
886
887# Run the gcc build sets.
888if [ "$test_with_gcc" -ne 0 ]; then
889	build_set "gcc" "$run_tests"
890fi
891
892if [ "$run_tests" -ne 0 ]; then
893
894	build "$release" "$defcc" "-O3" "1" "$bits"
895
896	# Run karatsuba.
897	if [ "$test_karatsuba" -ne 0 ]; then
898		karatsuba
899	fi
900
901	# Valgrind.
902	if [ "$run_valgrind" -ne 0 -a "$test_with_gcc" -ne 0 ]; then
903		vg
904	fi
905
906	printf '\n'
907	printf 'Tests successful.\n'
908
909fi
910