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