summaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'scripts')
-rwxr-xr-xscripts/afl.py245
-rwxr-xr-xscripts/alloc.sh84
-rwxr-xr-xscripts/benchmark.sh159
-rw-r--r--scripts/bitfuncgen.c240
-rwxr-xr-xscripts/fuzz_prep.sh81
-rwxr-xr-xscripts/manpage.sh175
-rw-r--r--scripts/ministat.c675
-rwxr-xr-xscripts/package.sh248
-rwxr-xr-xscripts/radamsa.sh133
-rw-r--r--scripts/radamsa.txt17
-rwxr-xr-xscripts/randmath.py421
-rwxr-xr-xscripts/release.sh810
-rw-r--r--scripts/release_settings.txt16
-rwxr-xr-xscripts/test_settings.sh77
-rw-r--r--scripts/test_settings.txt93
15 files changed, 3474 insertions, 0 deletions
diff --git a/scripts/afl.py b/scripts/afl.py
new file mode 100755
index 000000000000..c4312ce84f83
--- /dev/null
+++ b/scripts/afl.py
@@ -0,0 +1,245 @@
+#! /usr/bin/python3 -B
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (c) 2018-2021 Gavin D. Howard and contributors.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# * Redistributions of source code must retain the above copyright notice, this
+# list of conditions and the following disclaimer.
+#
+# * Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+
+import os
+import sys
+import shutil
+import subprocess
+
+
+# Print the usage and exit with an error.
+def usage():
+ print("usage: {} [--asan] dir [results_dir [exe options...]]".format(script))
+ print(" The valid values for dir are: 'bc1', 'bc2', 'bc3', and 'dc'.")
+ sys.exit(1)
+
+
+# Check for a crash.
+# @param exebase The calculator that crashed.
+# @param out The file to copy the crash file to.
+# @param error The error code (negative).
+# @param file The crash file.
+# @param type The type of run that caused the crash. This is just a string
+# that would make sense to the user.
+# @param test The contents of the crash file, or which line caused the crash
+# for a run through stdin.
+def check_crash(exebase, out, error, file, type, test):
+ if error < 0:
+ print("\n{} crashed ({}) on {}:\n".format(exebase, -error, type))
+ print(" {}".format(test))
+ print("\nCopying to \"{}\"".format(out))
+ shutil.copy2(file, out)
+ print("\nexiting...")
+ sys.exit(error)
+
+
+# Runs a test. This function is used to ensure that if a test times out, it is
+# discarded. Otherwise, some tests result in incredibly long runtimes. We need
+# to ignore those.
+#
+# @param cmd The command to run.
+# @param exebase The calculator to test.
+# @param tout The timeout to use.
+# @param indata The data to push through stdin for the test.
+# @param out The file to copy the test file to if it causes a crash.
+# @param file The test file.
+# @param type The type of test. This is just a string that would make sense
+# to the user.
+# @param test The test. It could be an entire file, or just one line.
+# @param environ The environment to run the command under.
+def run_test(cmd, exebase, tout, indata, out, file, type, test, environ=None):
+ try:
+ p = subprocess.run(cmd, timeout=tout, input=indata, stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE, env=environ)
+ check_crash(exebase, out, p.returncode, file, type, test)
+ except subprocess.TimeoutExpired:
+ print("\n {} timed out. Continuing...\n".format(exebase))
+
+
+# Creates and runs a test. This basically just takes a file, runs it through the
+# appropriate calculator as a whole file, then runs it through the calculator
+# using stdin.
+# @param file The file to test.
+# @param tout The timeout to use.
+# @param environ The environment to run under.
+def create_test(file, tout, environ=None):
+
+ print(" {}".format(file))
+
+ base = os.path.basename(file)
+
+ if base == "README.txt":
+ return
+
+ with open(file, "rb") as f:
+ lines = f.readlines()
+
+ print(" Running whole file...")
+
+ run_test(exe + [ file ], exebase, tout, halt.encode(), out, file, "file", file, environ)
+
+ print(" Running file through stdin...")
+
+ with open(file, "rb") as f:
+ content = f.read()
+
+ run_test(exe, exebase, tout, content, out, file,
+ "running {} through stdin".format(file), file, environ)
+
+
+# Get the children of a directory.
+# @param dir The directory to get the children of.
+# @param get_files True if files should be gotten, false if directories should
+# be gotten.
+def get_children(dir, get_files):
+ dirs = []
+ with os.scandir(dir) as it:
+ for entry in it:
+ if not entry.name.startswith('.') and \
+ ((entry.is_dir() and not get_files) or \
+ (entry.is_file() and get_files)):
+ dirs.append(entry.name)
+ dirs.sort()
+ return dirs
+
+
+# Returns the correct executable name for the directory under test.
+# @param d The directory under test.
+def exe_name(d):
+ return "bc" if d == "bc1" or d == "bc2" or d == "bc3" else "dc"
+
+
+# Housekeeping.
+script = sys.argv[0]
+scriptdir = os.path.dirname(script)
+
+# Must run this script alone.
+if __name__ != "__main__":
+ usage()
+
+timeout = 2.5
+
+if len(sys.argv) < 2:
+ usage()
+
+idx = 1
+
+exedir = sys.argv[idx]
+
+asan = (exedir == "--asan")
+
+# We could possibly run under ASan. See later for what that means.
+if asan:
+ idx += 1
+ if len(sys.argv) < idx + 1:
+ usage()
+ exedir = sys.argv[idx]
+
+print("exedir: {}".format(exedir))
+
+# Grab the correct directory of AFL++ results.
+if len(sys.argv) >= idx + 2:
+ resultsdir = sys.argv[idx + 1]
+else:
+ if exedir == "bc1":
+ resultsdir = scriptdir + "/../tests/fuzzing/bc_outputs1"
+ elif exedir == "bc2":
+ resultsdir = scriptdir + "/../tests/fuzzing/bc_outputs2"
+ elif exedir == "bc3":
+ resultsdir = scriptdir + "/../tests/fuzzing/bc_outputs3"
+ elif exedir == "dc":
+ resultsdir = scriptdir + "/../tests/fuzzing/dc_outputs"
+ else:
+ raise ValueError("exedir must be either bc1, bc2, bc3, or dc");
+
+print("resultsdir: {}".format(resultsdir))
+
+# More command-line processing.
+if len(sys.argv) >= idx + 3:
+ exe = sys.argv[idx + 2]
+else:
+ exe = scriptdir + "/../bin/" + exe_name(exedir)
+
+exebase = os.path.basename(exe)
+
+
+# Use the correct options.
+if exebase == "bc":
+ halt = "halt\n"
+ options = "-lq"
+ seed = ["-e", "seed = 1280937142.20981723890730892738902938071028973408912703984712093", "-f-" ]
+else:
+ halt = "q\n"
+ options = "-x"
+ seed = ["-e", "1280937142.20981723890730892738902938071028973408912703984712093j", "-f-" ]
+
+# More command-line processing.
+if len(sys.argv) >= idx + 4:
+ exe = [ exe, sys.argv[idx + 3:], options ] + seed
+else:
+ exe = [ exe, options ] + seed
+for i in range(4, len(sys.argv)):
+ exe.append(sys.argv[i])
+
+out = scriptdir + "/../.test.txt"
+
+print(os.path.realpath(os.getcwd()))
+
+dirs = get_children(resultsdir, False)
+
+# Set the correct ASAN_OPTIONS.
+if asan:
+ env = os.environ.copy()
+ env['ASAN_OPTIONS'] = 'abort_on_error=1:allocator_may_return_null=1'
+
+for d in dirs:
+
+ d = resultsdir + "/" + d
+
+ print(d)
+
+ # Check the crash files.
+ files = get_children(d + "/crashes/", True)
+
+ for file in files:
+ file = d + "/crashes/" + file
+ create_test(file, timeout)
+
+ # If we are running under ASan, we want to check all files. Otherwise, skip.
+ if not asan:
+ continue
+
+ # Check all of the test cases found by AFL++.
+ files = get_children(d + "/queue/", True)
+
+ for file in files:
+ file = d + "/queue/" + file
+ create_test(file, timeout * 2, env)
+
+print("Done")
diff --git a/scripts/alloc.sh b/scripts/alloc.sh
new file mode 100755
index 000000000000..c5c46febe0b3
--- /dev/null
+++ b/scripts/alloc.sh
@@ -0,0 +1,84 @@
+#!/bin/sh
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (c) 2018-2021 Gavin D. Howard and contributors.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# * Redistributions of source code must retain the above copyright notice, this
+# list of conditions and the following disclaimer.
+#
+# * Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+
+# This script is only really useful for running on Linux. It tests the code to
+# free temps in order to make an allocation work. In order to see it work, I
+# suggest adding code after the following line in src/vm.c:
+#
+# if (BC_ERR(ptr == NULL)) bc_vm_fatalError(BC_ERR_FATAL_ALLOC_ERR);
+#
+# The code you should add is the following:
+#
+# bc_file_printf(&vm.ferr, "If you see this, the code worked.\n");
+# bc_file_flush(&vm.ferr, bc_flush_none);
+#
+# If you do not see the that message printed, the code did not work. Or, in the
+# case of some allocators, like jemalloc, the allocator just isn't great with
+# turning a bunch of small allocations into a bigger allocation,
+
+script="$0"
+scriptdir=$(dirname "$script")
+
+export LANG=C
+
+virtlimit=1000000
+
+ulimit -v $virtlimit
+
+# This script is designed to allocate lots of memory with a lot of caching of
+# numbers (the function f() specifically). Then, it's designed allocate one
+# large number and grow it until allocation failure (the function g()).
+"$scriptdir/../bin/bc" <<*EOF
+
+define f(i, n) {
+ if (n == 0) return i;
+ return f(i + 1, n - 1)
+}
+
+define g(n) {
+ t = (10^9)^(2^24)
+ while (n) {
+ n *= t
+ print "success\n"
+ }
+}
+
+iterations=2000000
+
+for (l=0; l < 100; l++) {
+ iterations
+ j = f(0, iterations$)
+ iterations += 100000
+ print "here\n"
+ n=10^235929600
+ g(n)
+ print "success\n"
+ n=0
+}
+*EOF
diff --git a/scripts/benchmark.sh b/scripts/benchmark.sh
new file mode 100755
index 000000000000..35f92452ce78
--- /dev/null
+++ b/scripts/benchmark.sh
@@ -0,0 +1,159 @@
+#! /bin/sh
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (c) 2018-2021 Gavin D. Howard and contributors.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# * Redistributions of source code must retain the above copyright notice, this
+# list of conditions and the following disclaimer.
+#
+# * Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+
+# This script depends on the GNU time utility, but I am okay with that because
+# this script is only for maintainers.
+
+# Just print the usage and exit with an error.
+usage() {
+ printf 'usage: %s [-n<runs>] [-p<pause>] dir benchmark...\n' "$0" 1>&2
+ printf ' -n runs is how many runs to run the benchmark, default 10.\n'
+ printf ' -p pause is how many seconds to pause before running the benchmarks.\n'
+ printf '\n'
+ printf 'The fields are put in this order:\n'
+ printf '1. Elapsed Time\n'
+ printf '2. System Time\n'
+ printf '3. User Time\n'
+ printf '4. Max RSS\n'
+ printf '5. Average RSS\n'
+ printf '6. Average Total Memory Use\n'
+ printf '7. Average Unshared Data\n'
+ printf '8. Average Unshared Stack\n'
+ printf '9. Average Shared Text\n'
+ printf '10. Major Page Faults\n'
+ printf '11. Minor Page Faults\n'
+ printf '12. Swaps\n'
+ printf '13. Involuntary Context Switches\n'
+ printf '14. Voluntary Context Switches\n'
+ printf '15. Inputs\n'
+ printf '16. Outputs\n'
+ printf '17. Signals Delivered\n'
+ exit 1
+}
+
+script="$0"
+scriptdir=$(dirname "$script")
+
+runs=10
+pause=0
+
+# Process command-line arguments.
+while getopts "n:p:" opt; do
+
+ case "$opt" in
+ n) runs="$OPTARG" ;;
+ p) pause="$OPTARG" ;;
+ ?) usage "Invalid option: $opt" ;;
+ esac
+
+done
+
+while [ "$#" -gt 0 ] && [ "$OPTIND" -gt 1 ]; do
+
+ OPTIND=$(bin/bc -e "$OPTIND - 1")
+ shift
+
+done
+
+if [ "$#" -lt 2 ]; then
+ usage
+fi
+
+cd "$scriptdir/.."
+
+d="$1"
+shift
+
+benchmarks=""
+
+# Create the list of benchmarks from the arguments.
+while [ "$#" -gt 0 ]; do
+
+ if [ "$benchmarks" = "" ]; then
+ benchmarks="$1"
+ else
+ benchmarks="$benchmarks $1"
+ fi
+
+ shift
+done
+
+files=""
+
+# Create the list of files from the benchmarks.
+for b in $benchmarks; do
+
+ f=$(printf "benchmarks/%s/%s.txt" "$d" "$b")
+
+ if [ "$files" = "" ]; then
+ files="$f"
+ else
+ files="$files $f"
+ fi
+
+done
+
+if [ "$d" = "bc" ]; then
+ opts="-lq"
+ halt="halt"
+else
+ opts="-x"
+ halt="q"
+fi
+
+# Generate all of the benchmarks.
+for b in $benchmarks; do
+
+ if [ ! -f "./benchmarks/$d/$b.txt" ]; then
+ printf 'Benchmarking generation of benchmarks/%s/%s.txt...\n' "$d" "$b" >&2
+ printf '%s\n' "$halt" | /usr/bin/time -v bin/$d $opts "./benchmarks/$d/$b.$d" \
+ > "./benchmarks/$d/$b.txt"
+ fi
+done
+
+# We use this format to make things easier to use with ministat.
+format="%e %S %U %M %t %K %D %p %X %F %R %W %c %w %I %O %k"
+
+printf 'Benchmarking %s...\n' "$files" >&2
+
+if [ "$pause" -gt 0 ]; then
+ sleep "$pause"
+fi
+
+i=0
+
+# Run the benchmarks as many times as told to.
+while [ "$i" -lt "$runs" ]; do
+
+ printf '%s\n' "$halt" | /usr/bin/time -f "$format" bin/$d $opts $files 2>&1 > /dev/null
+
+ # Might as well use the existing bc.
+ i=$(printf '%s + 1\n' "$i" | bin/bc)
+
+done
diff --git a/scripts/bitfuncgen.c b/scripts/bitfuncgen.c
new file mode 100644
index 000000000000..8fae531b9286
--- /dev/null
+++ b/scripts/bitfuncgen.c
@@ -0,0 +1,240 @@
+/*
+ * *****************************************************************************
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2018-2021 Gavin D. Howard and contributors.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * *****************************************************************************
+ *
+ * A generator for bitwise operations test.
+ *
+ */
+
+#include <assert.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <limits.h>
+
+#define NTESTS (100)
+
+/**
+ * Abort with an error message.
+ * @param msg The error message.
+ */
+void err(const char *msg) {
+ fprintf(stderr, "%s\n", msg);
+ abort();
+}
+
+uint64_t rev(uint64_t a, size_t bits) {
+
+ size_t i;
+ uint64_t res = 0;
+
+ for (i = 0; i < bits; ++i) {
+ res <<= 1;
+ res |= a & 1;
+ a >>= 1;
+ }
+
+ return res;
+}
+
+uint64_t mod(uint64_t a, size_t bits) {
+
+ uint64_t mod;
+
+ if (bits < 64) mod = (uint64_t) ((1ULL << bits) - 1);
+ else mod = UINT64_MAX;
+
+ return a & mod;
+}
+
+uint64_t rol(uint64_t a, uint64_t p, size_t bits) {
+
+ uint64_t res;
+
+ assert(bits <= 64);
+
+ p %= bits;
+
+ if (!p) return a;
+
+ res = (a << p) | (a >> (bits - p));
+
+ return mod(res, bits);
+}
+
+uint64_t ror(uint64_t a, uint64_t p, size_t bits) {
+
+ uint64_t res;
+
+ assert(bits <= 64);
+
+ p %= bits;
+
+ if (!p) return a;
+
+ res = (a << (bits - p)) | (a >> p);
+
+ return mod(res, bits);
+}
+
+int main(void) {
+
+ uint64_t a = 0, b = 0, t;
+ size_t i;
+
+ // We attempt to open this or /dev/random to get random data.
+ int fd = open("/dev/urandom", O_RDONLY);
+
+ if (fd < 0) {
+
+ fd = open("/dev/random", O_RDONLY);
+
+ if (fd < 0) err("cannot open a random number generator");
+ }
+
+ // Generate NTESTS tests.
+ for (i = 0; i < NTESTS; ++i) {
+
+ ssize_t nread;
+
+ // Generate random data for the first operand.
+ nread = read(fd, (char*) &a, sizeof(uint64_t));
+ if (nread != sizeof(uint64_t)) err("I/O error");
+
+ // Generate random data for the second operand.
+ nread = read(fd, (char*) &b, sizeof(uint64_t));
+ if (nread != sizeof(uint64_t)) err("I/O error");
+
+ // Output the tests to stdout.
+ printf("band(%lu, %lu)\n", a, b);
+ printf("bor(%lu, %lu)\n", a, b);
+ printf("bxor(%lu, %lu)\n", a, b);
+ printf("bshl(%lu, %lu)\n", mod(a, 32), mod(b, 5));
+ printf("bshr(%lu, %lu)\n", mod(a, 32), mod(b, 5));
+ printf("bshl(%lu, %lu)\n", mod(b, 32), mod(a, 5));
+ printf("bshr(%lu, %lu)\n", mod(b, 32), mod(a, 5));
+ printf("bnot8(%lu)\nbnot8(%lu)\n", a, mod(a, 8));
+ printf("bnot16(%lu)\nbnot16(%lu)\n", a, mod(a, 16));
+ printf("bnot32(%lu)\nbnot32(%lu)\n", a, mod(a, 32));
+ printf("bnot64(%lu)\n", a);
+ printf("brev8(%lu)\nbrev8(%lu)\n", a, mod(a, 8));
+ printf("brev16(%lu)\nbrev16(%lu)\n", a, mod(a, 16));
+ printf("brev32(%lu)\nbrev32(%lu)\n", a, mod(a, 32));
+ printf("brev64(%lu)\n", a);
+ printf("brol8(%lu, %lu)\n", a, b);
+ printf("brol8(%lu, %lu)\n", mod(a, 8), b);
+ printf("brol8(%lu, %lu)\n", a, mod(b, 8));
+ printf("brol8(%lu, %lu)\n", mod(a, 8), mod(b, 8));
+ printf("brol16(%lu, %lu)\n", a, b);
+ printf("brol16(%lu, %lu)\n", mod(a, 16), b);
+ printf("brol16(%lu, %lu)\n", a, mod(b, 16));
+ printf("brol16(%lu, %lu)\n", mod(a, 16), mod(b, 16));
+ printf("brol32(%lu, %lu)\n", a, b);
+ printf("brol32(%lu, %lu)\n", mod(a, 32), b);
+ printf("brol32(%lu, %lu)\n", a, mod(b, 32));
+ printf("brol32(%lu, %lu)\n", mod(a, 32), mod(b, 32));
+ printf("brol64(%lu, %lu)\n", a, b);
+ printf("bror8(%lu, %lu)\n", a, b);
+ printf("bror8(%lu, %lu)\n", mod(a, 8), b);
+ printf("bror8(%lu, %lu)\n", a, mod(b, 8));
+ printf("bror8(%lu, %lu)\n", mod(a, 8), mod(b, 8));
+ printf("bror16(%lu, %lu)\n", a, b);
+ printf("bror16(%lu, %lu)\n", mod(a, 16), b);
+ printf("bror16(%lu, %lu)\n", a, mod(b, 16));
+ printf("bror16(%lu, %lu)\n", mod(a, 16), mod(b, 16));
+ printf("bror32(%lu, %lu)\n", a, b);
+ printf("bror32(%lu, %lu)\n", mod(a, 32), b);
+ printf("bror32(%lu, %lu)\n", a, mod(b, 32));
+ printf("bror32(%lu, %lu)\n", mod(a, 32), mod(b, 32));
+ printf("bror64(%lu, %lu)\n", a, b);
+ printf("bmod8(%lu)\nbmod8(%lu)\n", a, mod(a, 8));
+ printf("bmod16(%lu)\nbmod16(%lu)\n", a, mod(a, 16));
+ printf("bmod32(%lu)\nbmod32(%lu)\n", a, mod(a, 32));
+ printf("bmod64(%lu)\n", a);
+
+ // Output the results to stderr.
+ fprintf(stderr, "%lu\n", a & b);
+ fprintf(stderr, "%lu\n", a | b);
+ fprintf(stderr, "%lu\n", a ^ b);
+ fprintf(stderr, "%lu\n", mod(a, 32) << mod(b, 5));
+ fprintf(stderr, "%lu\n", mod(a, 32) >> mod(b, 5));
+ fprintf(stderr, "%lu\n", mod(b, 32) << mod(a, 5));
+ fprintf(stderr, "%lu\n", mod(b, 32) >> mod(a, 5));
+ t = mod(~a, 8);
+ fprintf(stderr, "%lu\n%lu\n", t, t);
+ t = mod(~a, 16);
+ fprintf(stderr, "%lu\n%lu\n", t, t);
+ t = mod(~a, 32);
+ fprintf(stderr, "%lu\n%lu\n", t, t);
+ fprintf(stderr, "%lu\n", ~a);
+ t = rev(a, 8);
+ fprintf(stderr, "%lu\n%lu\n", t, t);
+ t = rev(a, 16);
+ fprintf(stderr, "%lu\n%lu\n", t, t);
+ t = rev(a, 32);
+ fprintf(stderr, "%lu\n%lu\n", t, t);
+ t = rev(a, 64);
+ fprintf(stderr, "%lu\n", t);
+ fprintf(stderr, "%lu\n", rol(mod(a, 8), mod(b, 8), 8));
+ fprintf(stderr, "%lu\n", rol(mod(a, 8), mod(b, 8), 8));
+ fprintf(stderr, "%lu\n", rol(mod(a, 8), mod(b, 8), 8));
+ fprintf(stderr, "%lu\n", rol(mod(a, 8), mod(b, 8), 8));
+ fprintf(stderr, "%lu\n", rol(mod(a, 16), mod(b, 16), 16));
+ fprintf(stderr, "%lu\n", rol(mod(a, 16), mod(b, 16), 16));
+ fprintf(stderr, "%lu\n", rol(mod(a, 16), mod(b, 16), 16));
+ fprintf(stderr, "%lu\n", rol(mod(a, 16), mod(b, 16), 16));
+ fprintf(stderr, "%lu\n", rol(mod(a, 32), mod(b, 32), 32));
+ fprintf(stderr, "%lu\n", rol(mod(a, 32), mod(b, 32), 32));
+ fprintf(stderr, "%lu\n", rol(mod(a, 32), mod(b, 32), 32));
+ fprintf(stderr, "%lu\n", rol(mod(a, 32), mod(b, 32), 32));
+ fprintf(stderr, "%lu\n", rol(a, b, 64));
+ fprintf(stderr, "%lu\n", ror(mod(a, 8), mod(b, 8), 8));
+ fprintf(stderr, "%lu\n", ror(mod(a, 8), mod(b, 8), 8));
+ fprintf(stderr, "%lu\n", ror(mod(a, 8), mod(b, 8), 8));
+ fprintf(stderr, "%lu\n", ror(mod(a, 8), mod(b, 8), 8));
+ fprintf(stderr, "%lu\n", ror(mod(a, 16), mod(b, 16), 16));
+ fprintf(stderr, "%lu\n", ror(mod(a, 16), mod(b, 16), 16));
+ fprintf(stderr, "%lu\n", ror(mod(a, 16), mod(b, 16), 16));
+ fprintf(stderr, "%lu\n", ror(mod(a, 16), mod(b, 16), 16));
+ fprintf(stderr, "%lu\n", ror(mod(a, 32), mod(b, 32), 32));
+ fprintf(stderr, "%lu\n", ror(mod(a, 32), mod(b, 32), 32));
+ fprintf(stderr, "%lu\n", ror(mod(a, 32), mod(b, 32), 32));
+ fprintf(stderr, "%lu\n", ror(mod(a, 32), mod(b, 32), 32));
+ fprintf(stderr, "%lu\n", ror(a, b, 64));
+ fprintf(stderr, "%lu\n%lu\n", mod(a, 8), mod(a, 8));
+ fprintf(stderr, "%lu\n%lu\n", mod(a, 16), mod(a, 16));
+ fprintf(stderr, "%lu\n%lu\n", mod(a, 32), mod(a, 32));
+ fprintf(stderr, "%lu\n", a);
+ }
+
+ return 0;
+}
diff --git a/scripts/fuzz_prep.sh b/scripts/fuzz_prep.sh
new file mode 100755
index 000000000000..0441f94e340c
--- /dev/null
+++ b/scripts/fuzz_prep.sh
@@ -0,0 +1,81 @@
+#! /bin/sh
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (c) 2018-2021 Gavin D. Howard and contributors.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# * Redistributions of source code must retain the above copyright notice, this
+# list of conditions and the following disclaimer.
+#
+# * Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+
+# Just print the usage and exit with an error.
+usage() {
+ printf 'usage: %s [-a] [afl_compiler]\n' "$0" 1>&2
+ printf '\n'
+ printf ' If -a is given, then an ASan ready build is created.\n'
+ printf ' Otherwise, a normal fuzz build is created.\n'
+ printf ' The ASan-ready build is for running under\n'
+ printf ' `tests/afl.py --asan`, which checks that there were no\n'
+ printf ' memory errors in any path found by the fuzzer.\n'
+ printf ' It might also be useful to run scripts/randmath.py on an\n'
+ printf ' ASan-ready binary.\n'
+ exit 1
+}
+
+script="$0"
+scriptdir=$(dirname "$script")
+
+asan=0
+
+# Process command-line arguments.
+while getopts "a" opt; do
+
+ case "$opt" in
+ a) asan=1 ; shift ;;
+ ?) usage "Invalid option: $opt" ;;
+ esac
+
+done
+
+if [ $# -lt 1 ]; then
+ CC=afl-clang-lto
+else
+ CC="$1"
+fi
+
+# We want this for extra sensitive crashing
+AFL_HARDEN=1
+
+cd "$scriptdir/.."
+
+set -e
+
+if [ "$asan" -ne 0 ]; then
+ CFLAGS="-flto -fsanitize=address"
+else
+ CFLAGS="-flto"
+fi
+
+# We want a debug build because asserts are counted as crashes too.
+CC="$CC" CFLAGS="$CFLAGS" ./configure.sh -gO3 -z
+
+make -j16
diff --git a/scripts/manpage.sh b/scripts/manpage.sh
new file mode 100755
index 000000000000..c1429a6ed51f
--- /dev/null
+++ b/scripts/manpage.sh
@@ -0,0 +1,175 @@
+#! /bin/sh
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (c) 2018-2021 Gavin D. Howard and contributors.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# * Redistributions of source code must retain the above copyright notice, this
+# list of conditions and the following disclaimer.
+#
+# * Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+
+# Print the usage and exit with an error.
+usage() {
+ printf "usage: %s manpage\n" "$0" 1>&2
+ exit 1
+}
+
+# Generate a manpage and print it to a file.
+# @param md The markdown manual to generate a manpage for.
+# @param out The file to print the manpage to.
+gen_manpage() {
+
+ _gen_manpage_md="$1"
+ shift
+
+ _gen_manpage_out="$1"
+ shift
+
+ cat "$manualsdir/header.txt" > "$_gen_manpage_out"
+ cat "$manualsdir/header_${manpage}.txt" >> "$_gen_manpage_out"
+
+ pandoc -f commonmark_x -t man "$_gen_manpage_md" >> "$_gen_manpage_out"
+}
+
+# Generate a manual from a template and print it to a file before generating
+# its manpage.
+# param args The type of markdown manual to generate. This is a string that
+# corresponds to build type (see the Build Type section of the
+# manuals/build.md manual).
+gen_manual() {
+
+ _gen_manual_args="$1"
+ shift
+
+ # Set up some local variables. $manualsdir and $manpage from from the
+ # variables outside the function.
+ _gen_manual_status="$ALL"
+ _gen_manual_out="$manualsdir/$manpage/$_gen_manual_args.1"
+ _gen_manual_md="$manualsdir/$manpage/$_gen_manual_args.1.md"
+ _gen_manual_temp="$manualsdir/temp.1.md"
+
+ # We need to set IFS, so we store it here for restoration later.
+ _gen_manual_ifs="$IFS"
+
+ # Remove the files that will be generated.
+ rm -rf "$_gen_manual_out" "$_gen_manual_md"
+
+ # Here is the magic. This loop reads the template line-by-line, and based on
+ # _gen_manual_status, either prints it to the markdown manual or not.
+ #
+ # Here is how the template is set up: it is a normal markdown file except
+ # that there are sections surrounded tags that look like this:
+ #
+ # {{ <build_type_list> }}
+ # ...
+ # {{ end }}
+ #
+ # Those tags mean that whatever build types are found in the
+ # <build_type_list> get to keep that section. Otherwise, skip.
+ #
+ # Obviously, the tag itself and its end are not printed to the markdown
+ # manual.
+ while IFS= read -r line; do
+
+ # If we have found an end, reset the status.
+ if [ "$line" = "{{ end }}" ]; then
+
+ # Some error checking. This helps when editing the templates.
+ if [ "$_gen_manual_status" -eq "$ALL" ]; then
+ err_exit "{{ end }} tag without corresponding start tag" 2
+ fi
+
+ _gen_manual_status="$ALL"
+
+ # We have found a tag that allows our build type to use it.
+ elif [ "${line#\{\{* $_gen_manual_args *\}\}}" != "$line" ]; then
+
+ # More error checking. We don't want tags nested.
+ if [ "$_gen_manual_status" -ne "$ALL" ]; then
+ err_exit "start tag nested in start tag" 3
+ fi
+
+ _gen_manual_status="$NOSKIP"
+
+ # We have found a tag that is *not* allowed for our build type.
+ elif [ "${line#\{\{*\}\}}" != "$line" ]; then
+
+ if [ "$_gen_manual_status" -ne "$ALL" ]; then
+ err_exit "start tag nested in start tag" 3
+ fi
+
+ _gen_manual_status="$SKIP"
+
+ # This is for normal lines. If we are not skipping, print.
+ else
+ if [ "$_gen_manual_status" -ne "$SKIP" ]; then
+ printf '%s\n' "$line" >> "$_gen_manual_temp"
+ fi
+ fi
+
+ done < "$manualsdir/${manpage}.1.md.in"
+
+ # Remove multiple blank lines.
+ uniq "$_gen_manual_temp" "$_gen_manual_md"
+
+ # Remove the temp file.
+ rm -rf "$_gen_manual_temp"
+
+ # Reset IFS.
+ IFS="$_gen_manual_ifs"
+
+ # Generate the manpage.
+ gen_manpage "$_gen_manual_md" "$_gen_manual_out"
+}
+
+set -e
+
+script="$0"
+scriptdir=$(dirname "$script")
+manualsdir="$scriptdir/../manuals"
+
+. "$scriptdir/functions.sh"
+
+# Constants for use later. If the set of build types is changed, $ARGS must be
+# updated.
+ARGS="A E H N EH EN HN EHN"
+ALL=0
+NOSKIP=1
+SKIP=2
+
+# Process command-line arguments.
+test "$#" -eq 1 || usage
+
+manpage="$1"
+shift
+
+if [ "$manpage" != "bcl" ]; then
+
+ # Generate a manual and manpage for each build type.
+ for a in $ARGS; do
+ gen_manual "$a"
+ done
+
+else
+ # For bcl, just generate the manpage.
+ gen_manpage "$manualsdir/${manpage}.3.md" "$manualsdir/${manpage}.3"
+fi
diff --git a/scripts/ministat.c b/scripts/ministat.c
new file mode 100644
index 000000000000..e5b7cd47b3e4
--- /dev/null
+++ b/scripts/ministat.c
@@ -0,0 +1,675 @@
+/*-
+ * SPDX-License-Identifier: Beerware
+ *
+ * ----------------------------------------------------------------------------
+ * "THE BEER-WARE LICENSE" (Revision 42):
+ * <phk@FreeBSD.ORG> wrote this file. As long as you retain this notice you
+ * can do whatever you want with this stuff. If we meet some day, and you think
+ * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
+ * ----------------------------------------------------------------------------
+ *
+ */
+
+#ifdef __GNU_LIBRARY__
+#include <sys/cdefs.h>
+#endif // __GNU_LIBRARY__
+
+#include <sys/ioctl.h>
+
+#ifdef __GNU_LIBRARY__
+#include <sys/queue.h>
+#endif // __GNU_LIBRARY__
+
+#include <assert.h>
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define NSTUDENT 100
+#define NCONF 6
+static double const studentpct[] = { 80, 90, 95, 98, 99, 99.5 };
+static double const student[NSTUDENT + 1][NCONF] = {
+/* inf */ { 1.282, 1.645, 1.960, 2.326, 2.576, 3.090 },
+/* 1. */ { 3.078, 6.314, 12.706, 31.821, 63.657, 318.313 },
+/* 2. */ { 1.886, 2.920, 4.303, 6.965, 9.925, 22.327 },
+/* 3. */ { 1.638, 2.353, 3.182, 4.541, 5.841, 10.215 },
+/* 4. */ { 1.533, 2.132, 2.776, 3.747, 4.604, 7.173 },
+/* 5. */ { 1.476, 2.015, 2.571, 3.365, 4.032, 5.893 },
+/* 6. */ { 1.440, 1.943, 2.447, 3.143, 3.707, 5.208 },
+/* 7. */ { 1.415, 1.895, 2.365, 2.998, 3.499, 4.782 },
+/* 8. */ { 1.397, 1.860, 2.306, 2.896, 3.355, 4.499 },
+/* 9. */ { 1.383, 1.833, 2.262, 2.821, 3.250, 4.296 },
+/* 10. */ { 1.372, 1.812, 2.228, 2.764, 3.169, 4.143 },
+/* 11. */ { 1.363, 1.796, 2.201, 2.718, 3.106, 4.024 },
+/* 12. */ { 1.356, 1.782, 2.179, 2.681, 3.055, 3.929 },
+/* 13. */ { 1.350, 1.771, 2.160, 2.650, 3.012, 3.852 },
+/* 14. */ { 1.345, 1.761, 2.145, 2.624, 2.977, 3.787 },
+/* 15. */ { 1.341, 1.753, 2.131, 2.602, 2.947, 3.733 },
+/* 16. */ { 1.337, 1.746, 2.120, 2.583, 2.921, 3.686 },
+/* 17. */ { 1.333, 1.740, 2.110, 2.567, 2.898, 3.646 },
+/* 18. */ { 1.330, 1.734, 2.101, 2.552, 2.878, 3.610 },
+/* 19. */ { 1.328, 1.729, 2.093, 2.539, 2.861, 3.579 },
+/* 20. */ { 1.325, 1.725, 2.086, 2.528, 2.845, 3.552 },
+/* 21. */ { 1.323, 1.721, 2.080, 2.518, 2.831, 3.527 },
+/* 22. */ { 1.321, 1.717, 2.074, 2.508, 2.819, 3.505 },
+/* 23. */ { 1.319, 1.714, 2.069, 2.500, 2.807, 3.485 },
+/* 24. */ { 1.318, 1.711, 2.064, 2.492, 2.797, 3.467 },
+/* 25. */ { 1.316, 1.708, 2.060, 2.485, 2.787, 3.450 },
+/* 26. */ { 1.315, 1.706, 2.056, 2.479, 2.779, 3.435 },
+/* 27. */ { 1.314, 1.703, 2.052, 2.473, 2.771, 3.421 },
+/* 28. */ { 1.313, 1.701, 2.048, 2.467, 2.763, 3.408 },
+/* 29. */ { 1.311, 1.699, 2.045, 2.462, 2.756, 3.396 },
+/* 30. */ { 1.310, 1.697, 2.042, 2.457, 2.750, 3.385 },
+/* 31. */ { 1.309, 1.696, 2.040, 2.453, 2.744, 3.375 },
+/* 32. */ { 1.309, 1.694, 2.037, 2.449, 2.738, 3.365 },
+/* 33. */ { 1.308, 1.692, 2.035, 2.445, 2.733, 3.356 },
+/* 34. */ { 1.307, 1.691, 2.032, 2.441, 2.728, 3.348 },
+/* 35. */ { 1.306, 1.690, 2.030, 2.438, 2.724, 3.340 },
+/* 36. */ { 1.306, 1.688, 2.028, 2.434, 2.719, 3.333 },
+/* 37. */ { 1.305, 1.687, 2.026, 2.431, 2.715, 3.326 },
+/* 38. */ { 1.304, 1.686, 2.024, 2.429, 2.712, 3.319 },
+/* 39. */ { 1.304, 1.685, 2.023, 2.426, 2.708, 3.313 },
+/* 40. */ { 1.303, 1.684, 2.021, 2.423, 2.704, 3.307 },
+/* 41. */ { 1.303, 1.683, 2.020, 2.421, 2.701, 3.301 },
+/* 42. */ { 1.302, 1.682, 2.018, 2.418, 2.698, 3.296 },
+/* 43. */ { 1.302, 1.681, 2.017, 2.416, 2.695, 3.291 },
+/* 44. */ { 1.301, 1.680, 2.015, 2.414, 2.692, 3.286 },
+/* 45. */ { 1.301, 1.679, 2.014, 2.412, 2.690, 3.281 },
+/* 46. */ { 1.300, 1.679, 2.013, 2.410, 2.687, 3.277 },
+/* 47. */ { 1.300, 1.678, 2.012, 2.408, 2.685, 3.273 },
+/* 48. */ { 1.299, 1.677, 2.011, 2.407, 2.682, 3.269 },
+/* 49. */ { 1.299, 1.677, 2.010, 2.405, 2.680, 3.265 },
+/* 50. */ { 1.299, 1.676, 2.009, 2.403, 2.678, 3.261 },
+/* 51. */ { 1.298, 1.675, 2.008, 2.402, 2.676, 3.258 },
+/* 52. */ { 1.298, 1.675, 2.007, 2.400, 2.674, 3.255 },
+/* 53. */ { 1.298, 1.674, 2.006, 2.399, 2.672, 3.251 },
+/* 54. */ { 1.297, 1.674, 2.005, 2.397, 2.670, 3.248 },
+/* 55. */ { 1.297, 1.673, 2.004, 2.396, 2.668, 3.245 },
+/* 56. */ { 1.297, 1.673, 2.003, 2.395, 2.667, 3.242 },
+/* 57. */ { 1.297, 1.672, 2.002, 2.394, 2.665, 3.239 },
+/* 58. */ { 1.296, 1.672, 2.002, 2.392, 2.663, 3.237 },
+/* 59. */ { 1.296, 1.671, 2.001, 2.391, 2.662, 3.234 },
+/* 60. */ { 1.296, 1.671, 2.000, 2.390, 2.660, 3.232 },
+/* 61. */ { 1.296, 1.670, 2.000, 2.389, 2.659, 3.229 },
+/* 62. */ { 1.295, 1.670, 1.999, 2.388, 2.657, 3.227 },
+/* 63. */ { 1.295, 1.669, 1.998, 2.387, 2.656, 3.225 },
+/* 64. */ { 1.295, 1.669, 1.998, 2.386, 2.655, 3.223 },
+/* 65. */ { 1.295, 1.669, 1.997, 2.385, 2.654, 3.220 },
+/* 66. */ { 1.295, 1.668, 1.997, 2.384, 2.652, 3.218 },
+/* 67. */ { 1.294, 1.668, 1.996, 2.383, 2.651, 3.216 },
+/* 68. */ { 1.294, 1.668, 1.995, 2.382, 2.650, 3.214 },
+/* 69. */ { 1.294, 1.667, 1.995, 2.382, 2.649, 3.213 },
+/* 70. */ { 1.294, 1.667, 1.994, 2.381, 2.648, 3.211 },
+/* 71. */ { 1.294, 1.667, 1.994, 2.380, 2.647, 3.209 },
+/* 72. */ { 1.293, 1.666, 1.993, 2.379, 2.646, 3.207 },
+/* 73. */ { 1.293, 1.666, 1.993, 2.379, 2.645, 3.206 },
+/* 74. */ { 1.293, 1.666, 1.993, 2.378, 2.644, 3.204 },
+/* 75. */ { 1.293, 1.665, 1.992, 2.377, 2.643, 3.202 },
+/* 76. */ { 1.293, 1.665, 1.992, 2.376, 2.642, 3.201 },
+/* 77. */ { 1.293, 1.665, 1.991, 2.376, 2.641, 3.199 },
+/* 78. */ { 1.292, 1.665, 1.991, 2.375, 2.640, 3.198 },
+/* 79. */ { 1.292, 1.664, 1.990, 2.374, 2.640, 3.197 },
+/* 80. */ { 1.292, 1.664, 1.990, 2.374, 2.639, 3.195 },
+/* 81. */ { 1.292, 1.664, 1.990, 2.373, 2.638, 3.194 },
+/* 82. */ { 1.292, 1.664, 1.989, 2.373, 2.637, 3.193 },
+/* 83. */ { 1.292, 1.663, 1.989, 2.372, 2.636, 3.191 },
+/* 84. */ { 1.292, 1.663, 1.989, 2.372, 2.636, 3.190 },
+/* 85. */ { 1.292, 1.663, 1.988, 2.371, 2.635, 3.189 },
+/* 86. */ { 1.291, 1.663, 1.988, 2.370, 2.634, 3.188 },
+/* 87. */ { 1.291, 1.663, 1.988, 2.370, 2.634, 3.187 },
+/* 88. */ { 1.291, 1.662, 1.987, 2.369, 2.633, 3.185 },
+/* 89. */ { 1.291, 1.662, 1.987, 2.369, 2.632, 3.184 },
+/* 90. */ { 1.291, 1.662, 1.987, 2.368, 2.632, 3.183 },
+/* 91. */ { 1.291, 1.662, 1.986, 2.368, 2.631, 3.182 },
+/* 92. */ { 1.291, 1.662, 1.986, 2.368, 2.630, 3.181 },
+/* 93. */ { 1.291, 1.661, 1.986, 2.367, 2.630, 3.180 },
+/* 94. */ { 1.291, 1.661, 1.986, 2.367, 2.629, 3.179 },
+/* 95. */ { 1.291, 1.661, 1.985, 2.366, 2.629, 3.178 },
+/* 96. */ { 1.290, 1.661, 1.985, 2.366, 2.628, 3.177 },
+/* 97. */ { 1.290, 1.661, 1.985, 2.365, 2.627, 3.176 },
+/* 98. */ { 1.290, 1.661, 1.984, 2.365, 2.627, 3.175 },
+/* 99. */ { 1.290, 1.660, 1.984, 2.365, 2.626, 3.175 },
+/* 100. */ { 1.290, 1.660, 1.984, 2.364, 2.626, 3.174 }
+};
+
+#define MAX_DS 8
+static char symbol[MAX_DS] = { ' ', 'x', '+', '*', '%', '#', '@', 'O' };
+
+struct dataset {
+ char *name;
+ double *points;
+ size_t lpoints;
+ double sy, syy;
+ size_t n;
+};
+
+static struct dataset *
+NewSet(void)
+{
+ struct dataset *ds;
+
+ ds = calloc(1, sizeof *ds);
+ assert(ds != NULL);
+ ds->lpoints = 100000;
+ ds->points = calloc(sizeof *ds->points, ds->lpoints);
+ assert(ds->points != NULL);
+ ds->syy = NAN;
+ return(ds);
+}
+
+static void
+AddPoint(struct dataset *ds, double a)
+{
+ double *dp;
+
+ if (ds->n >= ds->lpoints) {
+ dp = ds->points;
+ ds->lpoints *= 4;
+ ds->points = calloc(sizeof *ds->points, ds->lpoints);
+ assert(ds->points != NULL);
+ memcpy(ds->points, dp, sizeof *dp * ds->n);
+ free(dp);
+ }
+ ds->points[ds->n++] = a;
+ ds->sy += a;
+}
+
+static double
+Min(const struct dataset *ds)
+{
+
+ return (ds->points[0]);
+}
+
+static double
+Max(const struct dataset *ds)
+{
+
+ return (ds->points[ds->n -1]);
+}
+
+static double
+Avg(const struct dataset *ds)
+{
+
+ return(ds->sy / ds->n);
+}
+
+static double
+Median(const struct dataset *ds)
+{
+ const size_t m = ds->n / 2;
+
+ if ((ds->n % 2) == 0)
+ return ((ds->points[m] + (ds->points[m - 1])) / 2);
+ return (ds->points[m]);
+}
+
+static double
+Var(struct dataset *ds)
+{
+ size_t z;
+ const double a = Avg(ds);
+
+ if (isnan(ds->syy)) {
+ ds->syy = 0.0;
+ for (z = 0; z < ds->n; z++)
+ ds->syy += (ds->points[z] - a) * (ds->points[z] - a);
+ }
+
+ return (ds->syy / (ds->n - 1.0));
+}
+
+static double
+Stddev(struct dataset *ds)
+{
+
+ return sqrt(Var(ds));
+}
+
+static void
+VitalsHead(void)
+{
+
+ printf(" N Min Max Median Avg Stddev\n");
+}
+
+static void
+Vitals(struct dataset *ds, int flag)
+{
+
+ printf("%c %3zu %13.8g %13.8g %13.8g %13.8g %13.8g", symbol[flag],
+ ds->n, Min(ds), Max(ds), Median(ds), Avg(ds), Stddev(ds));
+ printf("\n");
+}
+
+static void
+Relative(struct dataset *ds, struct dataset *rs, int confidx)
+{
+ double spool, s, d, e, t;
+ double re;
+ size_t z;
+
+ z = ds->n + rs->n - 2;
+ if (z > NSTUDENT)
+ t = student[0][confidx];
+ else
+ t = student[z][confidx];
+ spool = (ds->n - 1) * Var(ds) + (rs->n - 1) * Var(rs);
+ spool /= ds->n + rs->n - 2;
+ spool = sqrt(spool);
+ s = spool * sqrt(1.0 / ds->n + 1.0 / rs->n);
+ d = Avg(ds) - Avg(rs);
+ e = t * s;
+
+ re = (ds->n - 1) * Var(ds) + (rs->n - 1) * Var(rs) *
+ (Avg(ds) * Avg(ds)) / (Avg(rs) * Avg(rs));
+ re *= (ds->n + rs->n) / (ds->n * rs->n * (ds->n + rs->n - 2.0));
+ re = t * sqrt(re);
+
+ if (fabs(d) > e) {
+ printf("Difference at %.1f%% confidence\n", studentpct[confidx]);
+ printf(" %g +/- %g\n", d, e);
+ printf(" %g%% +/- %g%%\n", d * 100 / Avg(rs), re * 100 / Avg(rs));
+ printf(" (Student's t, pooled s = %g)\n", spool);
+ } else {
+ printf("No difference proven at %.1f%% confidence\n",
+ studentpct[confidx]);
+ }
+}
+
+struct plot {
+ double min;
+ double max;
+ double span;
+ int width;
+
+ double x0, dx;
+ size_t height;
+ char *data;
+ char **bar;
+ int separate_bars;
+ int num_datasets;
+};
+
+static struct plot plot;
+
+static void
+SetupPlot(int width, int separate, int num_datasets)
+{
+ struct plot *pl;
+
+ pl = &plot;
+ pl->width = width;
+ pl->height = 0;
+ pl->data = NULL;
+ pl->bar = NULL;
+ pl->separate_bars = separate;
+ pl->num_datasets = num_datasets;
+ pl->min = 999e99;
+ pl->max = -999e99;
+}
+
+static void
+AdjPlot(double a)
+{
+ struct plot *pl;
+
+ pl = &plot;
+ if (a < pl->min)
+ pl->min = a;
+ if (a > pl->max)
+ pl->max = a;
+ pl->span = pl->max - pl->min;
+ pl->dx = pl->span / (pl->width - 1.0);
+ pl->x0 = pl->min - .5 * pl->dx;
+}
+
+static void
+DimPlot(struct dataset *ds)
+{
+ AdjPlot(Min(ds));
+ AdjPlot(Max(ds));
+ AdjPlot(Avg(ds) - Stddev(ds));
+ AdjPlot(Avg(ds) + Stddev(ds));
+}
+
+static void
+PlotSet(struct dataset *ds, int val)
+{
+ struct plot *pl;
+ int i, x;
+ size_t m, j, z;
+ size_t n;
+ int bar;
+ double av, sd;
+
+ pl = &plot;
+ if (pl->span == 0)
+ return;
+
+ if (pl->separate_bars)
+ bar = val-1;
+ else
+ bar = 0;
+
+ if (pl->bar == NULL) {
+ pl->bar = calloc(sizeof(char *), pl->num_datasets);
+ assert(pl->bar != NULL);
+ }
+
+ if (pl->bar[bar] == NULL) {
+ pl->bar[bar] = malloc(pl->width);
+ assert(pl->bar[bar] != NULL);
+ memset(pl->bar[bar], 0, pl->width);
+ }
+
+ m = 1;
+ i = -1;
+ j = 0;
+ /* Set m to max(j) + 1, to allocate required memory */
+ for (n = 0; n < ds->n; n++) {
+ x = (ds->points[n] - pl->x0) / pl->dx;
+ if (x == i) {
+ j++;
+ if (j > m)
+ m = j;
+ } else {
+ j = 1;
+ i = x;
+ }
+ }
+ m += 1;
+ if (m > pl->height) {
+ pl->data = realloc(pl->data, pl->width * m);
+ assert(pl->data != NULL);
+ memset(pl->data + pl->height * pl->width, 0,
+ (m - pl->height) * pl->width);
+ }
+ pl->height = m;
+ i = -1;
+ for (n = 0; n < ds->n; n++) {
+ x = (ds->points[n] - pl->x0) / pl->dx;
+ if (x == i) {
+ j++;
+ } else {
+ j = 1;
+ i = x;
+ }
+ pl->data[j * pl->width + x] |= val;
+ }
+ av = Avg(ds);
+ sd = Stddev(ds);
+ if (!isnan(sd)) {
+ x = ((av - sd) - pl->x0) / pl->dx;
+ m = ((av + sd) - pl->x0) / pl->dx;
+ pl->bar[bar][m] = '|';
+ pl->bar[bar][x] = '|';
+ for (z = x + 1; z < m; z++)
+ if (pl->bar[bar][z] == 0)
+ pl->bar[bar][z] = '_';
+ }
+ x = (Median(ds) - pl->x0) / pl->dx;
+ pl->bar[bar][x] = 'M';
+ x = (av - pl->x0) / pl->dx;
+ pl->bar[bar][x] = 'A';
+}
+
+static void
+DumpPlot(void)
+{
+ struct plot *pl;
+ int i, j, k;
+ size_t z;
+
+ pl = &plot;
+ if (pl->span == 0) {
+ printf("[no plot, span is zero width]\n");
+ return;
+ }
+
+ putchar('+');
+ for (i = 0; i < pl->width; i++)
+ putchar('-');
+ putchar('+');
+ putchar('\n');
+ for (z = 1; z < pl->height; z++) {
+ putchar('|');
+ for (j = 0; j < pl->width; j++) {
+ k = pl->data[(pl->height - z) * pl->width + j];
+ if (k >= 0 && k < MAX_DS)
+ putchar(symbol[k]);
+ else
+ printf("[%02x]", k);
+ }
+ putchar('|');
+ putchar('\n');
+ }
+ for (i = 0; i < pl->num_datasets; i++) {
+ if (pl->bar[i] == NULL)
+ continue;
+ putchar('|');
+ for (j = 0; j < pl->width; j++) {
+ k = pl->bar[i][j];
+ if (k == 0)
+ k = ' ';
+ putchar(k);
+ }
+ putchar('|');
+ putchar('\n');
+ }
+ putchar('+');
+ for (i = 0; i < pl->width; i++)
+ putchar('-');
+ putchar('+');
+ putchar('\n');
+}
+
+static int
+dbl_cmp(const void *a, const void *b)
+{
+ const double *aa = a;
+ const double *bb = b;
+
+ if (*aa < *bb)
+ return (-1);
+ else if (*aa > *bb)
+ return (1);
+ else
+ return (0);
+}
+
+static struct dataset *
+ReadSet(FILE *f, const char *n, int column, const char *delim)
+{
+ char buf[BUFSIZ], *p, *t;
+ struct dataset *s;
+ double d;
+ int line;
+ int i;
+
+ s = NewSet();
+ s->name = strdup(n);
+ assert(s->name != NULL);
+ line = 0;
+ while (fgets(buf, sizeof buf, f) != NULL) {
+ line++;
+
+ i = strlen(buf);
+ while (i > 0 && isspace(buf[i - 1]))
+ buf[--i] = '\0';
+ for (i = 1, t = strtok(buf, delim);
+ t != NULL && *t != '#';
+ i++, t = strtok(NULL, delim)) {
+ if (i == column)
+ break;
+ }
+ if (t == NULL || *t == '#')
+ continue;
+
+ d = strtod(t, &p);
+ if (p != NULL && *p != '\0')
+ errx(2, "Invalid data on line %d in %s", line, n);
+ if (*buf != '\0')
+ AddPoint(s, d);
+ }
+ if (s->n < 3) {
+ fprintf(stderr,
+ "Dataset %s must contain at least 3 data points\n", n);
+ exit (2);
+ }
+ qsort(s->points, s->n, sizeof *s->points, dbl_cmp);
+ return (s);
+}
+
+static void
+usage(char const *whine)
+{
+ int i;
+
+ fprintf(stderr, "%s\n", whine);
+ fprintf(stderr,
+ "Usage: ministat [-C column] [-c confidence] [-d delimiter(s)] [-Ans] [-w width] [file [file ...]]\n");
+ fprintf(stderr, "\tconfidence = {");
+ for (i = 0; i < NCONF; i++) {
+ fprintf(stderr, "%s%g%%",
+ i ? ", " : "",
+ studentpct[i]);
+ }
+ fprintf(stderr, "}\n");
+ fprintf(stderr, "\t-A : print statistics only. suppress the graph.\n");
+ fprintf(stderr, "\t-C : column number to extract (starts and defaults to 1)\n");
+ fprintf(stderr, "\t-d : delimiter(s) string, default to \" \\t\"\n");
+ fprintf(stderr, "\t-n : print summary statistics only, no graph/test\n");
+ fprintf(stderr, "\t-s : print avg/median/stddev bars on separate lines\n");
+ fprintf(stderr, "\t-w : width of graph/test output (default 74 or terminal width)\n");
+ exit (2);
+}
+
+int
+main(int argc, char **argv)
+{
+ const char *setfilenames[MAX_DS - 1];
+ struct dataset *ds[MAX_DS - 1];
+ FILE *setfiles[MAX_DS - 1];
+ int nds;
+ double a;
+ const char *delim = " \t";
+ char *p;
+ int c, i, ci;
+ int column = 1;
+ int flag_s = 0;
+ int flag_n = 0;
+ int termwidth = 74;
+ int suppress_plot = 0;
+
+ if (isatty(STDOUT_FILENO)) {
+ struct winsize wsz;
+
+ if ((p = getenv("COLUMNS")) != NULL && *p != '\0')
+ termwidth = atoi(p);
+ else if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &wsz) != -1 &&
+ wsz.ws_col > 0)
+ termwidth = wsz.ws_col - 2;
+ }
+
+ ci = -1;
+ while ((c = getopt(argc, argv, "AC:c:d:snw:")) != -1)
+ switch (c) {
+ case 'A':
+ suppress_plot = 1;
+ break;
+ case 'C':
+ column = strtol(optarg, &p, 10);
+ if (p != NULL && *p != '\0')
+ usage("Invalid column number.");
+ if (column <= 0)
+ usage("Column number should be positive.");
+ break;
+ case 'c':
+ a = strtod(optarg, &p);
+ if (p != NULL && *p != '\0')
+ usage("Not a floating point number");
+ for (i = 0; i < NCONF; i++)
+ if (a == studentpct[i])
+ ci = i;
+ if (ci == -1)
+ usage("No support for confidence level");
+ break;
+ case 'd':
+ if (*optarg == '\0')
+ usage("Can't use empty delimiter string");
+ delim = optarg;
+ break;
+ case 'n':
+ flag_n = 1;
+ break;
+ case 's':
+ flag_s = 1;
+ break;
+ case 'w':
+ termwidth = strtol(optarg, &p, 10);
+ if (p != NULL && *p != '\0')
+ usage("Invalid width, not a number.");
+ if (termwidth < 0)
+ usage("Unable to move beyond left margin.");
+ break;
+ default:
+ usage("Unknown option");
+ break;
+ }
+ if (ci == -1)
+ ci = 2;
+ argc -= optind;
+ argv += optind;
+
+ if (argc == 0) {
+ setfilenames[0] = "<stdin>";
+ setfiles[0] = stdin;
+ nds = 1;
+ } else {
+ if (argc > (MAX_DS - 1))
+ usage("Too many datasets.");
+ nds = argc;
+ for (i = 0; i < nds; i++) {
+ setfilenames[i] = argv[i];
+ if (!strcmp(argv[i], "-"))
+ setfiles[0] = stdin;
+ else
+ setfiles[i] = fopen(argv[i], "r");
+ if (setfiles[i] == NULL)
+ err(2, "Cannot open %s", argv[i]);
+ }
+ }
+
+ for (i = 0; i < nds; i++) {
+ ds[i] = ReadSet(setfiles[i], setfilenames[i], column, delim);
+ if (setfiles[i] != stdin)
+ fclose(setfiles[i]);
+ }
+
+ for (i = 0; i < nds; i++)
+ printf("%c %s\n", symbol[i+1], ds[i]->name);
+
+ if (!flag_n && !suppress_plot) {
+ SetupPlot(termwidth, flag_s, nds);
+ for (i = 0; i < nds; i++)
+ DimPlot(ds[i]);
+ for (i = 0; i < nds; i++)
+ PlotSet(ds[i], i + 1);
+ DumpPlot();
+ }
+ VitalsHead();
+ Vitals(ds[0], 1);
+ for (i = 1; i < nds; i++) {
+ Vitals(ds[i], i + 1);
+ if (!flag_n)
+ Relative(ds[i], ds[0], ci);
+ }
+ exit(0);
+}
diff --git a/scripts/package.sh b/scripts/package.sh
new file mode 100755
index 000000000000..34692f7ab20a
--- /dev/null
+++ b/scripts/package.sh
@@ -0,0 +1,248 @@
+#!/bin/sh
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (c) 2018-2021 Gavin D. Howard and contributors.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# * Redistributions of source code must retain the above copyright notice, this
+# list of conditions and the following disclaimer.
+#
+# * Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+
+# This script requires some non-POSIX utilities, but that's okay because it's
+# really for maintainer use only.
+#
+# The non-POSIX utilities include:
+#
+# * git
+# * stat
+# * tar
+# * xz
+# * sha512sum
+# * sha256sum
+# * gpg
+# * zip
+# * unzip
+
+shasum() {
+
+ f="$1"
+ shift
+
+ # All this fancy stuff takes the sha512 and sha256 sums and signs it. The
+ # output after this point is what I usually copy into the release notes.
+ # (See manuals/release.md for more information.)
+ printf '$ sha512sum %s\n' "$f"
+ sha512sum "$f"
+ printf '\n'
+ printf '$ sha256sum %s\n' "$f"
+ sha256sum "$f"
+ printf '\n'
+ printf "$ stat -c '%%s %%n'\n" "$f"
+ stat -c '%s %n' "$f"
+
+ if [ -f "$f.sig" ]; then
+ rm -f "$f.sig"
+ fi
+
+ gpg --detach-sig -o "$f.sig" "$f" 2> /dev/null
+
+ printf '\n'
+ printf '$ sha512sum %s.sig\n' "$f"
+ sha512sum "$f.sig"
+ printf '\n'
+ printf '$ sha256sum %s.sig\n' "$f"
+ sha256sum "$f.sig"
+ printf '\n'
+ printf "$ stat -c '%%s %%n'\n" "$f.sig"
+ stat -c '%s %n' "$f.sig"
+}
+
+script="$0"
+scriptdir=$(dirname "$script")
+
+repo="$scriptdir/.."
+proj="bc"
+
+cd "$repo"
+
+if [ ! -f "../vs.zip" ]; then
+ printf 'Must have Windows builds!\n'
+ exit 1
+fi
+
+# We want the absolute path for later.
+repo=$(pwd)
+
+# This convoluted mess does pull the version out. If you change the format of
+# include/version.h, you may have to change this line.
+version=$(cat include/version.h | grep "VERSION " - | awk '{ print $3 }' -)
+
+tag_msg="Version $version"
+projver="${proj}-${version}"
+
+tempdir="/tmp/${projver}"
+rm -rf $tempdir
+mkdir -p $tempdir
+
+make clean_tests > /dev/null 2> /dev/null
+
+# Delete the tag and recreate it. This is the part of the script that makes it
+# so you cannot run it twice on the same version, unless you know what you are
+# doing. In fact, you cannot run it again if users have already started to use
+# the old version of the tag.
+if git rev-parse "$version" > /dev/null 2>&1; then
+ git push --delete origin "$version" > /dev/null 2> /dev/null
+ git tag --delete "$version" > /dev/null 2> /dev/null
+fi
+
+git push > /dev/null 2> /dev/null
+git tg "$version" -m "$tag_msg" > /dev/null 2> /dev/null
+git push --tags > /dev/null 2> /dev/null
+
+# This line grabs the names of all of the files in .gitignore that still exist.
+ignores=$(git check-ignore * **/*)
+
+cp -r ./* "$tempdir"
+
+cd $tempdir
+
+# Delete all the ignored files.
+for i in $ignores; do
+ rm -rf "./$i"
+done
+
+# This is a list of files that end users (including *software packagers* and
+# *distro maintainers*!) do not care about. In particular, they *do* care about
+# the testing infrastructure for the regular test suite because distro
+# maintainers probably want to ensure the test suite runs. However, they
+# probably don't care about fuzzing or other randomized testing. Also, I
+# technically can't distribute tests/bc/scripts/timeconst.bc because it's from
+# the Linux kernel, which is GPL.
+extras=$(cat <<*EOF
+.git/
+.gitignore
+.gitattributes
+benchmarks/
+manuals/bc.1.md.in
+manuals/dc.1.md.in
+manuals/benchmarks.md
+manuals/development.md
+manuals/header_bcl.txt
+manuals/header_bc.txt
+manuals/header_dc.txt
+manuals/header.txt
+manuals/release.md
+scripts/afl.py
+scripts/alloc.sh
+scripts/benchmark.sh
+scripts/bitfuncgen.c
+scripts/fuzz_prep.sh
+scripts/manpage.sh
+scripts/ministat.c
+scripts/package.sh
+scripts/radamsa.sh
+scripts/radamsa.txt
+scripts/randmath.py
+scripts/release_settings.txt
+scripts/release.sh
+scripts/test_settings.sh
+scripts/test_settings.txt
+tests/bc_outputs/
+tests/dc_outputs/
+tests/fuzzing/
+tests/bc/scripts/timeconst.bc
+*EOF
+)
+
+for i in $extras; do
+ rm -rf "./$i"
+done
+
+cd ..
+
+parent="$repo/.."
+
+# Cleanup old stuff.
+if [ -f "$projver.tar.xz" ]; then
+ rm -rf "$projver.tar.xz"
+fi
+
+if [ -f "$projver.tar.xz.sig" ]; then
+ rm -rf "$projver.tar.xz.sig"
+fi
+
+# Tar and compress and move into the parent directory of the repo.
+tar cf "$projver.tar" "$projver/"
+xz -z -v -9 -e "$projver.tar" > /dev/null 2> /dev/null
+mv "$projver.tar.xz" "$parent"
+
+cd "$parent"
+
+# Clean up old Windows stuff.
+if [ -d windows ]; then
+ rm -rf windows
+fi
+
+if [ -f windows.zip ]; then
+ rm -rf $projver-windows.zip
+fi
+
+# Prepare Windows stuff.
+unzip vs.zip > /dev/null
+mv vs windows
+
+# Remove unneeded Windows stuff.
+rm -rf windows/*.vcxproj.user
+rm -rf windows/src2
+rm -rf windows/tests
+rm -rf windows/*.sln
+rm -rf windows/*.vcxproj
+rm -rf windows/*.vcxproj.filters
+
+rm -rf windows/bin/{Win32,x64}/{Debug,Release}/*.obj
+rm -rf windows/bin/{Win32,x64}/{Debug,Release}/*.iobj
+rm -rf windows/bin/{Win32,x64}/{Debug,Release}/bc.exe.recipe
+rm -rf windows/bin/{Win32,x64}/{Debug,Release}/bc.ilk
+rm -rf windows/bin/{Win32,x64}/{Debug,Release}/bc.log
+rm -rf windows/bin/{Win32,x64}/{Debug,Release}/bc.tlog
+rm -rf windows/bin/{Win32,x64}/{Debug,Release}/bc.pdb
+rm -rf windows/bin/{Win32,x64}/{Debug,Release}/bc.ipdb
+rm -rf windows/bin/{Win32,x64}/{Debug,Release}/bc.vcxproj.FileListAbsolute.txt
+rm -rf windows/bin/{Win32,x64}/{Debug,Release}/strgen.exe
+rm -rf windows/bin/{Win32,x64}/{Debug,Release}/vc142.idb
+rm -rf windows/bin/{Win32,x64}/{Debug,Release}/vc142.pdb
+
+rm -rf windows/lib/{Win32,x64}/{Debug,ReleaseMD,ReleaseMT}/*.obj
+rm -rf windows/lib/{Win32,x64}/{Debug,ReleaseMD,ReleaseMT}/bcl.lib.recipe
+rm -rf windows/lib/{Win32,x64}/{Debug,ReleaseMD,ReleaseMT}/bcl.log
+rm -rf windows/lib/{Win32,x64}/{Debug,ReleaseMD,ReleaseMT}/bcl.tlog
+rm -rf windows/lib/{Win32,x64}/{Debug,ReleaseMD,ReleaseMT}/bcl.idb
+rm -rf windows/lib/{Win32,x64}/{Debug,ReleaseMD,ReleaseMT}/bcl.pdb
+rm -rf windows/lib/{Win32,x64}/{Debug,ReleaseMD,ReleaseMT}/bcl.vcxproj.FileListAbsolute.txt
+
+# Zip the Windows stuff.
+zip -r $projver-windows.zip windows > /dev/null
+
+printf '\n'
+shasum "$projver.tar.xz"
+printf '\n'
+shasum "$projver-windows.zip"
diff --git a/scripts/radamsa.sh b/scripts/radamsa.sh
new file mode 100755
index 000000000000..c92923ddadc4
--- /dev/null
+++ b/scripts/radamsa.sh
@@ -0,0 +1,133 @@
+#! /bin/sh
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (c) 2018-2021 Gavin D. Howard and contributors.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# * Redistributions of source code must retain the above copyright notice, this
+# list of conditions and the following disclaimer.
+#
+# * Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+
+# This script uses some non-POSIX behavior, but since it's meant for bc
+# maintainers only, I can accept that.
+
+# Get an entry from the file. If an argument exists, it is an index. Get that
+# line. Otherwise, get a random line.
+getentry() {
+
+ # Figure out if we get a specific or random line.
+ if [ $# -gt 0 ]; then
+ entnum="$1"
+ else
+ entnum=0
+ fi
+
+ # Get data from stdin and figure out how many lines there are.
+ e=$(cat -)
+ num=$(printf '%s\n' "$e" | wc -l)
+
+ # Figure out what line we are going to get. Uses bc's own PRNG.
+ if [ "$entnum" -eq 0 ]; then
+ rand=$(printf 'irand(%s) + 1\n' "$num" | "$bcdir/bc")
+ else
+ rand="$entnum"
+ fi
+
+ # Get the line.
+ ent=$(printf '%s\n' "$e" | tail -n +$rand | head -n 1)
+
+ printf '%s\n' "$ent"
+}
+
+script="$0"
+dir=$(dirname "$script")
+
+. "$dir/functions.sh"
+
+# Command-line processing.
+if [ "$#" -lt 1 ]; then
+ printf 'usage: %s dir\n' "$0"
+ exit 1
+fi
+
+d="$1"
+shift
+
+bcdir="$dir/../bin"
+
+# Figure out the correct input directory.
+if [ "$d" = "bc" ]; then
+ inputs="$dir/../tests/fuzzing/bc_inputs1"
+ opts="-lq"
+elif [ "$d" = "dc" ]; then
+ inputs="$dir/../test/fuzzing/dc_inputs"
+ opts="-x"
+else
+ err_exit "wrong type of executable" 1
+fi
+
+export ASAN_OPTIONS="abort_on_error=1:allocator_may_return_null=1"
+
+entries=$(cat "$dir/radamsa.txt")
+
+IFS=$'\n'
+
+go=1
+
+# Infinite loop.
+while [ "$go" -ne 0 ]; do
+
+ # If we are running bc, fuzz command-line arguments in BC_ENV_ARGS.
+ if [ "$d" = "bc" ]; then
+
+ entry=$(cat -- "$dir/radamsa.txt" | getentry)
+ items=$(printf '%s\n' "$entry" | radamsa -n 10)
+
+ printf '%s\n' "$items"
+
+ for i in `seq 1 10`; do
+
+ item=$(printf '%s\n' "$items" | getentry "$i")
+
+ export BC_ENV_ARGS="$item"
+ echo 'halt' | "$bcdir/$d"
+ err=$?
+
+ checkcrash "$d" "$err" "radamsa env args: \"$item\""
+ done
+
+ fi
+
+ f=$(ls "$inputs" | getentry)
+ l=$(cat "$inputs/$f" | wc -l)
+ ll=$(printf '%s^2\n' "$l" | bc)
+
+ # Fuzz on the AFL++ inputs.
+ for i in $(seq 1 2); do
+ data=$(cat "$inputs/$f" | radamsa -n 1)
+ printf '%s\n' "$data" > "$dir/../.log_${d}_test.txt"
+ printf '%s\n' "$data" | timeout -s SIGTERM 5 "$bcdir/$d" "$opts" > /dev/null
+ err=$?
+ checkcrash "$d" "$err" "radamsa stdin"
+ done
+
+done
diff --git a/scripts/radamsa.txt b/scripts/radamsa.txt
new file mode 100644
index 000000000000..4bf28907bead
--- /dev/null
+++ b/scripts/radamsa.txt
@@ -0,0 +1,17 @@
+-lq '/home/gavin/.bcrc'
+-lq "/home/gavin/.bcrc"
+-lqg '/home/gavin/bc stuff.bc'
+-lqg "/home/gavin/bc stuff.bc"
+-lqg '/home/gavin/"bc" stuff.bc'
+-lqg "/home/gavin/'bc' stuff.bc"
+-lqg '/home/gavin/bc stuff.bc
+-lqg "/home/gavin/bc stuff.bc
+-lqg '/home/gavin/"bc" stuff.bc
+-lqg "/home/gavin/'bc' stuff.bc
+--mathlib --expand
+--file="/home/gavin/.bcrc"
+--file=/home/gavin/.bcrc
+--file="/home/gavin/bc stuff.bc"
+--file
+--expression "4+4"
+-e "irand(128)" -f /home/gavin/.bcrc
diff --git a/scripts/randmath.py b/scripts/randmath.py
new file mode 100755
index 000000000000..896f0e46c97f
--- /dev/null
+++ b/scripts/randmath.py
@@ -0,0 +1,421 @@
+#! /usr/bin/python3 -B
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (c) 2018-2021 Gavin D. Howard and contributors.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# * Redistributions of source code must retain the above copyright notice, this
+# list of conditions and the following disclaimer.
+#
+# * Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+
+import os, errno
+import random
+import sys
+import subprocess
+
+# I want line length to *not* affect differences between the two, so I set it
+# as high as possible.
+env = {
+ "BC_LINE_LENGTH": "65535",
+ "DC_LINE_LENGTH": "65535"
+}
+
+
+# Generate a random integer between 0 and 2^limit.
+# @param limit The power of two for the upper limit.
+def gen(limit=4):
+ return random.randint(0, 2 ** (8 * limit))
+
+
+# Returns a random boolean for whether a number should be negative or not.
+def negative():
+ return random.randint(0, 1) == 1
+
+
+# Returns a random boolean for whether a number should be 0 or not. I decided to
+# have it be 0 every 2^4 times since sometimes it is used to make a number less
+# than 1.
+def zero():
+ return random.randint(0, 2 ** (4) - 1) == 0
+
+
+# Generate a real portion of a number.
+def gen_real():
+
+ # Figure out if we should have a real portion. If so generate it.
+ if negative():
+ n = str(gen(25))
+ length = gen(7 / 8)
+ if len(n) < length:
+ n = ("0" * (length - len(n))) + n
+ else:
+ n = "0"
+
+ return n
+
+
+# Generates a number (as a string) based on the parameters.
+# @param op The operation under test.
+# @param neg Whether the number can be negative.
+# @param real Whether the number can be a non-integer.
+# @param z Whether the number can be zero.
+# @param limit The power of 2 upper limit for the number.
+def num(op, neg, real, z, limit=4):
+
+ # Handle zero first.
+ if z:
+ z = zero()
+ else:
+ z = False
+
+ if z:
+ # Generate a real portion maybe
+ if real:
+ n = gen_real()
+ if n != "0":
+ return "0." + n
+ return "0"
+
+ # Figure out if we should be negative.
+ if neg:
+ neg = negative()
+
+ # Generate the integer portion.
+ g = gen(limit)
+
+ # Figure out if we should have a real number. negative() is used to give a
+ # 50/50 chance of getting a negative number.
+ if real:
+ n = gen_real()
+ else:
+ n = "0"
+
+ # Generate the string.
+ g = str(g)
+ if n != "0":
+ g = g + "." + n
+
+ # Make sure to use the right negative sign.
+ if neg and g != "0":
+ if op != modexp:
+ g = "-" + g
+ else:
+ g = "_" + g
+
+ return g
+
+
+# Add a failed test to the list.
+# @param test The test that failed.
+# @param op The operation for the test.
+def add(test, op):
+ tests.append(test)
+ gen_ops.append(op)
+
+
+# Compare the output between the two.
+# @param exe The executable under test.
+# @param options The command-line options.
+# @param p The object returned from subprocess.run() for the calculator
+# under test.
+# @param test The test.
+# @param halt The halt string for the calculator under test.
+# @param expected The expected result.
+# @param op The operation under test.
+# @param do_add If true, add a failing test to the list, otherwise, don't.
+def compare(exe, options, p, test, halt, expected, op, do_add=True):
+
+ # Check for error from the calculator under test.
+ if p.returncode != 0:
+
+ print(" {} returned an error ({})".format(exe, p.returncode))
+
+ if do_add:
+ print(" adding to checklist...")
+ add(test, op)
+
+ return
+
+ actual = p.stdout.decode()
+
+ # Check for a difference in output.
+ if actual != expected:
+
+ if op >= exponent:
+
+ # This is here because GNU bc, like mine can be flaky on the
+ # functions in the math library. This is basically testing if adding
+ # 10 to the scale works to make them match. If so, the difference is
+ # only because of that.
+ indata = "scale += 10; {}; {}".format(test, halt)
+ args = [ exe, options ]
+ p2 = subprocess.run(args, input=indata.encode(), stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env)
+ expected = p2.stdout[:-10].decode()
+
+ if actual == expected:
+ print(" failed because of bug in other {}".format(exe))
+ print(" continuing...")
+ return
+
+ # Do the correct output for the situation.
+ if do_add:
+ print(" failed; adding to checklist...")
+ add(test, op)
+ else:
+ print(" failed {}".format(test))
+ print(" expected:")
+ print(" {}".format(expected))
+ print(" actual:")
+ print(" {}".format(actual))
+
+
+# Generates a test for op. I made sure that there was no clashing between
+# calculators. Each calculator is responsible for certain ops.
+# @param op The operation to test.
+def gen_test(op):
+
+ # First, figure out how big the scale should be.
+ scale = num(op, False, False, True, 5 / 8)
+
+ # Do the right thing for each op. Generate the test based on the format
+ # string and the constraints of each op. For example, some ops can't accept
+ # 0 in some arguments, and some must have integers in some arguments.
+ if op < div:
+ s = fmts[op].format(scale, num(op, True, True, True), num(op, True, True, True))
+ elif op == div or op == mod:
+ s = fmts[op].format(scale, num(op, True, True, True), num(op, True, True, False))
+ elif op == power:
+ s = fmts[op].format(scale, num(op, True, True, True, 7 / 8), num(op, True, False, True, 6 / 8))
+ elif op == modexp:
+ s = fmts[op].format(scale, num(op, True, False, True), num(op, True, False, True),
+ num(op, True, False, False))
+ elif op == sqrt:
+ s = "1"
+ while s == "1":
+ s = num(op, False, True, True, 1)
+ s = fmts[op].format(scale, s)
+ else:
+
+ if op == exponent:
+ first = num(op, True, True, True, 6 / 8)
+ elif op == bessel:
+ first = num(op, False, True, True, 6 / 8)
+ else:
+ first = num(op, True, True, True)
+
+ if op != bessel:
+ s = fmts[op].format(scale, first)
+ else:
+ s = fmts[op].format(scale, first, 6 / 8)
+
+ return s
+
+
+# Runs a test with number t.
+# @param t The number of the test.
+def run_test(t):
+
+ # Randomly select the operation.
+ op = random.randrange(bessel + 1)
+
+ # Select the right calculator.
+ if op != modexp:
+ exe = "bc"
+ halt = "halt"
+ options = "-lq"
+ else:
+ exe = "dc"
+ halt = "q"
+ options = ""
+
+ # Generate the test.
+ test = gen_test(op)
+
+ # These don't work very well for some reason.
+ if "c(0)" in test or "scale = 4; j(4" in test:
+ return
+
+ # Make sure the calculator will halt.
+ bcexe = exedir + "/" + exe
+ indata = test + "\n" + halt
+
+ print("Test {}: {}".format(t, test))
+
+ # Only bc has options.
+ if exe == "bc":
+ args = [ exe, options ]
+ else:
+ args = [ exe ]
+
+ # Run the GNU bc.
+ p = subprocess.run(args, input=indata.encode(), stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env)
+
+ output1 = p.stdout.decode()
+
+ # Error checking for GNU.
+ if p.returncode != 0 or output1 == "":
+ print(" other {} returned an error ({}); continuing...".format(exe, p.returncode))
+ return
+
+ if output1 == "\n":
+ print(" other {} has a bug; continuing...".format(exe))
+ return
+
+ # Don't know why GNU has this problem...
+ if output1 == "-0\n":
+ output1 = "0\n"
+ elif output1 == "-0":
+ output1 = "0"
+
+ args = [ bcexe, options ]
+
+ # Run this bc/dc and compare.
+ p = subprocess.run(args, input=indata.encode(), stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env)
+ compare(exe, options, p, test, halt, output1, op)
+
+
+# This script must be run by itself.
+if __name__ != "__main__":
+ sys.exit(1)
+
+script = sys.argv[0]
+testdir = os.path.dirname(script)
+
+exedir = testdir + "/../bin"
+
+# The following are tables used to generate numbers.
+
+# The operations to test.
+ops = [ '+', '-', '*', '/', '%', '^', '|' ]
+
+# The functions that can be tested.
+funcs = [ "sqrt", "e", "l", "a", "s", "c", "j" ]
+
+# The files (corresponding to the operations with the functions appended) to add
+# tests to if they fail.
+files = [ "add", "subtract", "multiply", "divide", "modulus", "power", "modexp",
+ "sqrt", "exponent", "log", "arctangent", "sine", "cosine", "bessel" ]
+
+# The format strings corresponding to each operation and then each function.
+fmts = [ "scale = {}; {} + {}", "scale = {}; {} - {}", "scale = {}; {} * {}",
+ "scale = {}; {} / {}", "scale = {}; {} % {}", "scale = {}; {} ^ {}",
+ "{}k {} {} {}|pR", "scale = {}; sqrt({})", "scale = {}; e({})",
+ "scale = {}; l({})", "scale = {}; a({})", "scale = {}; s({})",
+ "scale = {}; c({})", "scale = {}; j({}, {})" ]
+
+# Constants to make some code easier later.
+div = 3
+mod = 4
+power = 5
+modexp = 6
+sqrt = 7
+exponent = 8
+bessel = 13
+
+gen_ops = []
+tests = []
+
+# Infinite loop until the user sends SIGINT.
+try:
+ i = 0
+ while True:
+ run_test(i)
+ i = i + 1
+except KeyboardInterrupt:
+ pass
+
+# This is where we start processing the checklist of possible failures. Why only
+# possible failures? Because some operations, specifically the functions in the
+# math library, are not guaranteed to be exactly correct. Because of that, we
+# need to present every failed test to the user for a final check before we
+# add them as test cases.
+
+# No items, just exit.
+if len(tests) == 0:
+ print("\nNo items in checklist.")
+ print("Exiting")
+ sys.exit(0)
+
+print("\nGoing through the checklist...\n")
+
+# Just do some error checking. If this fails here, it's a bug in this script.
+if len(tests) != len(gen_ops):
+ print("Corrupted checklist!")
+ print("Exiting...")
+ sys.exit(1)
+
+# Go through each item in the checklist.
+for i in range(0, len(tests)):
+
+ # Yes, there's some code duplication. Sue me.
+
+ print("\n{}".format(tests[i]))
+
+ op = int(gen_ops[i])
+
+ if op != modexp:
+ exe = "bc"
+ halt = "halt"
+ options = "-lq"
+ else:
+ exe = "dc"
+ halt = "q"
+ options = ""
+
+ # We want to run the test again to show the user the difference.
+ indata = tests[i] + "\n" + halt
+
+ args = [ exe, options ]
+
+ p = subprocess.run(args, input=indata.encode(), stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env)
+
+ expected = p.stdout.decode()
+
+ bcexe = exedir + "/" + exe
+ args = [ bcexe, options ]
+
+ p = subprocess.run(args, input=indata.encode(), stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env)
+
+ compare(exe, options, p, tests[i], halt, expected, op, False)
+
+ # Ask the user to make a decision on the failed test.
+ answer = input("\nAdd test ({}/{}) to test suite? [y/N]: ".format(i + 1, len(tests)))
+
+ # Quick and dirty answer parsing.
+ if 'Y' in answer or 'y' in answer:
+
+ print("Yes")
+
+ name = testdir + "/" + exe + "/" + files[op]
+
+ # Write the test to the test file and the expected result to the
+ # results file.
+ with open(name + ".txt", "a") as f:
+ f.write(tests[i] + "\n")
+
+ with open(name + "_results.txt", "a") as f:
+ f.write(expected)
+
+ else:
+ print("No")
+
+print("Done!")
diff --git a/scripts/release.sh b/scripts/release.sh
new file mode 100755
index 000000000000..12097b1cc8b9
--- /dev/null
+++ b/scripts/release.sh
@@ -0,0 +1,810 @@
+#! /bin/sh
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (c) 2018-2021 Gavin D. Howard and contributors.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# * Redistributions of source code must retain the above copyright notice, this
+# list of conditions and the following disclaimer.
+#
+# * Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+
+# For OpenBSD, run using the following:
+#
+# scripts/release.sh 1 0 1 0 0 0 0 1 0 0 0 0 0 0
+#
+# For FreeBSD, run using the following:
+#
+# scripts/release.sh 1 0 1 0 0 0 0 1 0 1 0 0 0 0
+#
+# There is one problem with running this script on FreeBSD: it takes overcommit
+# to the extreme. This means that some tests that try to create allocation
+# failures instead make bc and dc crash. So running this script on FreeBSD does
+# not work right now.
+#
+# For Linux, run two separate ones (in different checkouts), like so:
+#
+# scripts/release.sh 1 1 1 0 1 0 0 1 0 1 0 1 0 0
+# cd build; ../scripts/release.sh 1 1 0 1 0 1 0 1 0 1 0 0 1 1
+#
+# Yes, I usually do sanitizers with Clang and Valgrind with GCC, and I also do
+# out-of-source builds with GCC.
+#
+# To run sanitizers or Valgrind with generated tests, use the following:
+#
+# scripts/release.sh 1 1 1 0 1 0 0 1 0 1 0 1 0 0
+# cd build; ../scripts/release.sh 1 1 0 1 0 1 0 1 0 1 0 0 1 1
+#
+# The reason I run history tests with GCC and not with Clang is because Clang
+# already runs slower as a result of running with sanitizers, and the history
+# tests are a little sensitive to load on a system.
+#
+# If this script fails on any platform when starting the Karatsuba test, check
+# that Python is installed, especially if the error says something like:
+# "karatsuba.py: not found".
+
+# Print the usage and exit with an error. Each parameter should be an integer.
+# Non-zero activates, and zero deactivates.
+usage() {
+ printf 'usage: %s [run_tests] [generate_tests] [test_with_clang] [test_with_gcc] \n' "$script"
+ printf ' [run_sanitizers] [run_valgrind] [test_settings] [run_64_bit] \n'
+ printf ' [run_gen_script] [test_c11] [test_128_bit] [test_computed_goto]\n'
+ printf ' [test_karatsuba] [test_history]\n'
+ exit 1
+}
+
+# Print a header with a message. This is just to make it easy to track progress.
+# @param msg The message to print in the header.
+header() {
+
+ _header_msg="$1"
+ shift
+
+ printf '\n'
+ printf '*******************\n'
+ printf "$_header_msg"
+ printf '\n'
+ printf '*******************\n'
+ printf '\n'
+}
+
+# Easy way to call make.
+do_make() {
+ # No reason to do 64 except to see if I actually can overload my system. :)
+ # Well, also that it might actually improve throughput as other jobs can run
+ # while some are waiting.
+ make -j64 "$@"
+}
+
+# Run configure.sh.
+# @param CFLAGS The CFLAGS.
+# @param CC The C compiler.
+# @param configure_flags The flags for configure.sh itself.
+# @param GEN_HOST The setting for GEN_HOST.
+# @param LONG_BIT The setting for LONG_BIT.
+configure() {
+
+ _configure_CFLAGS="$1"
+ shift
+
+ _configure_CC="$1"
+ shift
+
+ _configure_configure_flags="$1"
+ shift
+
+ _configure_GEN_HOST="$1"
+ shift
+
+ _configure_LONG_BIT="$1"
+ shift
+
+ # Make sure to not generate tests if necessary.
+ if [ "$gen_tests" -eq 0 ]; then
+ _configure_configure_flags="-G $_configure_configure_flags"
+ fi
+
+ # Choose the right extra flags.
+ if [ "$_configure_CC" = "clang" ]; then
+ _configure_CFLAGS="$clang_flags $_configure_CFLAGS"
+ elif [ "$_configure_CC" = "gcc" ]; then
+ _configure_CFLAGS="$gcc_flags $_configure_CFLAGS"
+ fi
+
+ # Print the header and do the job.
+ _configure_header=$(printf 'Running configure.sh %s ...' "$_configure_configure_flags")
+ _configure_header=$(printf "$_configure_header\n CC=\"%s\"\n" "$_configure_CC")
+ _configure_header=$(printf "$_configure_header\n CFLAGS=\"%s\"\n" "$_configure_CFLAGS")
+ _configure_header=$(printf "$_configure_header\n LONG_BIT=%s" "$_configure_LONG_BIT")
+ _configure_header=$(printf "$_configure_header\n GEN_HOST=%s" "$_configure_GEN_HOST")
+
+ header "$_configure_header"
+ CFLAGS="$_configure_CFLAGS" CC="$_configure_CC" GEN_HOST="$_configure_GEN_HOST" \
+ LONG_BIT="$_configure_LONG_BIT" "$real/configure.sh" $_configure_configure_flags > /dev/null
+}
+
+# Build with make. This function also captures and outputs any warnings if they
+# exists because as far as I am concerned, warnings are not acceptable for
+# release.
+# @param CFLAGS The CFLAGS.
+# @param CC The C compiler.
+# @param configure_flags The flags for configure.sh itself.
+# @param GEN_HOST The setting for GEN_HOST.
+# @param LONG_BIT The setting for LONG_BIT.
+build() {
+
+ _build_CFLAGS="$1"
+ shift
+
+ _build_CC="$1"
+ shift
+
+ _build_configure_flags="$1"
+ shift
+
+ _build_GEN_HOST="$1"
+ shift
+
+ _build_LONG_BIT="$1"
+ shift
+
+ configure "$_build_CFLAGS" "$_build_CC" "$_build_configure_flags" "$_build_GEN_HOST" "$_build_LONG_BIT"
+
+ _build_header=$(printf 'Building...\n CC=%s' "$_build_CC")
+ _build_header=$(printf "$_build_header\n CFLAGS=\"%s\"" "$_build_CFLAGS")
+ _build_header=$(printf "$_build_header\n LONG_BIT=%s" "$_build_LONG_BIT")
+ _build_header=$(printf "$_build_header\n GEN_HOST=%s" "$_build_GEN_HOST")
+
+ header "$_build_header"
+
+ # Capture and print warnings.
+ do_make > /dev/null 2> "./.test.txt"
+
+ if [ -s "./.test.txt" ]; then
+ printf '%s generated warning(s):\n' "$_build_CC"
+ printf '\n'
+ cat "./.test.txt"
+ exit 1
+ fi
+}
+
+# Run tests with make.
+runtest() {
+
+ header "Running tests"
+
+ if [ "$#" -gt 0 ]; then
+ do_make "$@"
+ else
+
+ do_make test
+
+ if [ "$test_history" -ne 0 ]; then
+ do_make test_history
+ fi
+ fi
+}
+
+# Builds and runs tests with both calculators, then bc only, then dc only. If
+# run_tests is false, then it just does the builds.
+# @param CFLAGS The CFLAGS.
+# @param CC The C compiler.
+# @param configure_flags The flags for configure.sh itself.
+# @param GEN_HOST The setting for GEN_HOST.
+# @param LONG_BIT The setting for LONG_BIT.
+# @param run_tests Whether to run tests or not.
+runconfigtests() {
+
+ _runconfigtests_CFLAGS="$1"
+ shift
+
+ _runconfigtests_CC="$1"
+ shift
+
+ _runconfigtests_configure_flags="$1"
+ shift
+
+ _runconfigtests_GEN_HOST="$1"
+ shift
+
+ _runconfigtests_LONG_BIT="$1"
+ shift
+
+ _runconfigtests_run_tests="$1"
+ shift
+
+ if [ "$_runconfigtests_run_tests" -ne 0 ]; then
+ _runconfigtests_header=$(printf 'Running tests with configure flags')
+ else
+ _runconfigtests_header=$(printf 'Building with configure flags')
+ fi
+
+ _runconfigtests_header=$(printf "$_runconfigtests_header \"%s\" ...\n" "$_runconfigtests_configure_flags")
+ _runconfigtests_header=$(printf "$_runconfigtests_header\n CC=%s\n" "$_runconfigseries_CC")
+ _runconfigtests_header=$(printf "$_runconfigtests_header\n CFLAGS=\"%s\"" "$_runconfigseries_CFLAGS")
+ _runconfigtests_header=$(printf "$_runconfigtests_header\n LONG_BIT=%s" "$_runconfigtests_LONG_BIT")
+ _runconfigtests_header=$(printf "$_runconfigtests_header\n GEN_HOST=%s" "$_runconfigtests_GEN_HOST")
+
+ header "$_runconfigtests_header"
+
+ build "$_runconfigtests_CFLAGS" "$_runconfigtests_CC" \
+ "$_runconfigtests_configure_flags" "$_runconfigtests_GEN_HOST" \
+ "$_runconfigtests_LONG_BIT"
+
+ if [ "$_runconfigtests_run_tests" -ne 0 ]; then
+ runtest
+ fi
+
+ do_make clean
+
+ build "$_runconfigtests_CFLAGS" "$_runconfigtests_CC" \
+ "$_runconfigtests_configure_flags -b" "$_runconfigtests_GEN_HOST" \
+ "$_runconfigtests_LONG_BIT"
+
+ if [ "$_runconfigtests_run_tests" -ne 0 ]; then
+ runtest
+ fi
+
+ do_make clean
+
+ build "$_runconfigtests_CFLAGS" "$_runconfigtests_CC" \
+ "$_runconfigtests_configure_flags -d" "$_runconfigtests_GEN_HOST" \
+ "$_runconfigtests_LONG_BIT"
+
+ if [ "$_runconfigtests_run_tests" -ne 0 ]; then
+ runtest
+ fi
+
+ do_make clean
+}
+
+# Builds and runs tests with runconfigtests(), but also does 64-bit, 32-bit, and
+# 128-bit rand, if requested. It also does it with the gen script (strgen.sh) if
+# requested. If run_tests is false, it just does the builds.
+# @param CFLAGS The CFLAGS.
+# @param CC The C compiler.
+# @param configure_flags The flags for configure.sh itself.
+# @param run_tests Whether to run tests or not.
+runconfigseries() {
+
+ _runconfigseries_CFLAGS="$1"
+ shift
+
+ _runconfigseries_CC="$1"
+ shift
+
+ _runconfigseries_configure_flags="$1"
+ shift
+
+ _runconfigseries_run_tests="$1"
+ shift
+
+ if [ "$run_64_bit" -ne 0 ]; then
+
+ if [ "$test_128_bit" -ne 0 ]; then
+ runconfigtests "$_runconfigseries_CFLAGS" "$_runconfigseries_CC" \
+ "$_runconfigseries_configure_flags" 1 64 "$_runconfigseries_run_tests"
+ fi
+
+ if [ "$run_gen_script" -ne 0 ]; then
+ runconfigtests "$_runconfigseries_CFLAGS" "$_runconfigseries_CC" \
+ "$_runconfigseries_configure_flags" 0 64 "$_runconfigseries_run_tests"
+ fi
+
+ runconfigtests "$_runconfigseries_CFLAGS -DBC_RAND_BUILTIN=0" "$_runconfigseries_CC" \
+ "$_runconfigseries_configure_flags" 1 64 "$_runconfigseries_run_tests"
+
+ fi
+
+ runconfigtests "$_runconfigseries_CFLAGS" "$_runconfigseries_CC" \
+ "$_runconfigseries_configure_flags" 1 32 "$_runconfigseries_run_tests"
+
+ if [ "$run_gen_script" -ne 0 ]; then
+ runconfigtests "$_runconfigseries_CFLAGS" "$_runconfigseries_CC" \
+ "$_runconfigseries_configure_flags" 0 32 "$_runconfigseries_run_tests"
+ fi
+}
+
+# Builds and runs tests with each setting combo running runconfigseries(). If
+# run_tests is false, it just does the builds.
+# @param CFLAGS The CFLAGS.
+# @param CC The C compiler.
+# @param configure_flags The flags for configure.sh itself.
+# @param run_tests Whether to run tests or not.
+runsettingsseries() {
+
+ _runsettingsseries_CFLAGS="$1"
+ shift
+
+ _runsettingsseries_CC="$1"
+ shift
+
+ _runsettingsseries_configure_flags="$1"
+ shift
+
+ _runsettingsseries_run_tests="$1"
+ shift
+
+ if [ "$test_settings" -ne 0 ]; then
+
+ while read _runsettingsseries_s; do
+ runconfigseries "$_runsettingsseries_CFLAGS" "$_runsettingsseries_CC" \
+ "$_runsettingsseries_configure_flags $_runsettingsseries_s" \
+ "$_runsettingsseries_run_tests"
+ done < "$scriptdir/release_settings.txt"
+
+ else
+ runconfigseries "$_runsettingsseries_CFLAGS" "$_runsettingsseries_CC" \
+ "$_runsettingsseries_configure_flags" "$_runsettingsseries_run_tests"
+ fi
+}
+
+# Builds and runs tests with each build type running runsettingsseries(). If
+# run_tests is false, it just does the builds.
+# @param CFLAGS The CFLAGS.
+# @param CC The C compiler.
+# @param configure_flags The flags for configure.sh itself.
+# @param run_tests Whether to run tests or not.
+runtestseries() {
+
+ _runtestseries_CFLAGS="$1"
+ shift
+
+ _runtestseries_CC="$1"
+ shift
+
+ _runtestseries_configure_flags="$1"
+ shift
+
+ _runtestseries_run_tests="$1"
+ shift
+
+ _runtestseries_flags="E H N EH EN HN EHN"
+
+ runsettingsseries "$_runtestseries_CFLAGS" "$_runtestseries_CC" \
+ "$_runtestseries_configure_flags" "$_runtestseries_run_tests"
+
+ for _runtestseries_f in $_runtestseries_flags; do
+ runsettingsseries "$_runtestseries_CFLAGS" "$_runtestseries_CC" \
+ "$_runtestseries_configure_flags -$_runtestseries_f" "$_runtestseries_run_tests"
+ done
+}
+
+# Builds and runs the tests for bcl. If run_tests is false, it just does the
+# builds.
+# @param CFLAGS The CFLAGS.
+# @param CC The C compiler.
+# @param configure_flags The flags for configure.sh itself.
+# @param run_tests Whether to run tests or not.
+runlibtests() {
+
+ _runlibtests_CFLAGS="$1"
+ shift
+
+ _runlibtests_CC="$1"
+ shift
+
+ _runlibtests_configure_flags="$1"
+ shift
+
+ _runlibtests_run_tests="$1"
+ shift
+
+ _runlibtests_configure_flags="$_runlibtests_configure_flags -a"
+
+ build "$_runlibtests_CFLAGS" "$_runlibtests_CC" "$_runlibtests_configure_flags" 1 64
+
+ if [ "$_runlibtests_run_tests" -ne 0 ]; then
+ runtest test
+ fi
+
+ build "$_runlibtests_CFLAGS" "$_runlibtests_CC" "$_runlibtests_configure_flags" 1 32
+
+ if [ "$_runlibtests_run_tests" -ne 0 ]; then
+ runtest test
+ fi
+}
+
+# Builds and runs tests under C99, then C11, if requested, using
+# runtestseries(). If run_tests is false, it just does the builds.
+# @param CFLAGS The CFLAGS.
+# @param CC The C compiler.
+# @param configure_flags The flags for configure.sh itself.
+# @param run_tests Whether to run tests or not.
+runtests() {
+
+ _runtests_CFLAGS="$1"
+ shift
+
+ _runtests_CC="$1"
+ shift
+
+ _runtests_configure_flags="$1"
+ shift
+
+ _runtests_run_tests="$1"
+ shift
+
+ runtestseries "-std=c99 $_runtests_CFLAGS" "$_runtests_CC" "$_runtests_configure_flags" "$_runtests_run_tests"
+
+ if [ "$test_c11" -ne 0 ]; then
+ runtestseries "-std=c11 $_runtests_CFLAGS" "$_runtests_CC" "$_runtests_configure_flags" "$_runtests_run_tests"
+ fi
+}
+
+# Runs the karatsuba tests.
+karatsuba() {
+
+ header "Running Karatsuba tests"
+ do_make karatsuba_test
+}
+
+# Builds and runs under valgrind. It runs both, bc only, then dc only.
+vg() {
+
+ header "Running valgrind"
+
+ if [ "$run_64_bit" -ne 0 ]; then
+ _vg_bits=64
+ else
+ _vg_bits=32
+ fi
+
+ build "$debug -std=c99" "gcc" "-O3 -gv" "1" "$_vg_bits"
+ runtest test
+
+ do_make clean_config
+
+ build "$debug -std=c99" "gcc" "-O3 -gvb" "1" "$_vg_bits"
+ runtest test
+
+ do_make clean_config
+
+ build "$debug -std=c99" "gcc" "-O3 -gvd" "1" "$_vg_bits"
+ runtest test
+
+ do_make clean_config
+
+ build "$debug -std=c99" "gcc" "-O3 -gva" "1" "$_vg_bits"
+ runtest test
+
+ do_make clean_config
+}
+
+# Builds the debug series and runs the tests if run_tests allows. If sanitizers
+# are enabled, it also does UBSan.
+# @param CC The C compiler.
+# @param run_tests Whether to run tests or not.
+debug() {
+
+ _debug_CC="$1"
+ shift
+
+ _debug_run_tests="$1"
+ shift
+
+
+ if [ "$_debug_CC" = "clang" -a "$run_sanitizers" -ne 0 ]; then
+ runtests "$debug -fsanitize=undefined" "$_debug_CC" "-gm" "$_debug_run_tests"
+ else
+ runtests "$debug" "$_debug_CC" "-g" "$_debug_run_tests"
+ fi
+
+
+ if [ "$_debug_CC" = "clang" -a "$run_sanitizers" -ne 0 ]; then
+ runlibtests "$debug -fsanitize=undefined" "$_debug_CC" "-gm" "$_debug_run_tests"
+ else
+ runlibtests "$debug" "$_debug_CC" "-g" "$_debug_run_tests"
+ fi
+}
+
+# Builds the release series and runs the test if run_tests allows.
+# @param CC The C compiler.
+# @param run_tests Whether to run tests or not.
+release() {
+
+ _release_CC="$1"
+ shift
+
+ _release_run_tests="$1"
+ shift
+
+ runtests "$release" "$_release_CC" "-O3" "$_release_run_tests"
+
+ runlibtests "$release" "$_release_CC" "-O3" "$_release_run_tests"
+}
+
+# Builds the release debug series and runs the test if run_tests allows. If
+# sanitizers are enabled, it also does ASan and MSan.
+# @param CC The C compiler.
+# @param run_tests Whether to run tests or not.
+reldebug() {
+
+ _reldebug_CC="$1"
+ shift
+
+ _reldebug_run_tests="$1"
+ shift
+
+
+ if [ "$_reldebug_CC" = "clang" -a "$run_sanitizers" -ne 0 ]; then
+ runtests "$debug -fsanitize=address" "$_reldebug_CC" "-mgO3" "$_reldebug_run_tests"
+ runtests "$debug -fsanitize=memory" "$_reldebug_CC" "-mgO3" "$_reldebug_run_tests"
+ else
+ runtests "$debug" "$_reldebug_CC" "-gO3" "$_reldebug_run_tests"
+ fi
+
+
+ if [ "$_reldebug_CC" = "clang" -a "$run_sanitizers" -ne 0 ]; then
+ runlibtests "$debug -fsanitize=address" "$_reldebug_CC" "-mgO3" "$_reldebug_run_tests"
+ runlibtests "$debug -fsanitize=memory" "$_reldebug_CC" "-mgO3" "$_reldebug_run_tests"
+ else
+ runlibtests "$debug" "$_reldebug_CC" "-gO3" "$_reldebug_run_tests"
+ fi
+}
+
+# Builds the min size release series and runs the test if run_tests allows.
+# @param CC The C compiler.
+# @param run_tests Whether to run tests or not.
+minsize() {
+
+ _minsize_CC="$1"
+ shift
+
+ _minsize_run_tests="$1"
+ shift
+
+ runtests "$release" "$_minsize_CC" "-Os" "$_minsize_run_tests"
+
+ runlibtests "$release" "$_minsize_CC" "-Os" "$_minsize_run_tests"
+}
+
+# Builds all sets: debug, release, release debug, and min size, and runs the
+# tests if run_tests allows.
+# @param CC The C compiler.
+# @param run_tests Whether to run tests or not.
+build_set() {
+
+ _build_set_CC="$1"
+ shift
+
+ _build_set_run_tests="$1"
+ shift
+
+ debug "$_build_set_CC" "$_build_set_run_tests"
+ release "$_build_set_CC" "$_build_set_run_tests"
+ reldebug "$_build_set_CC" "$_build_set_run_tests"
+ minsize "$_build_set_CC" "$_build_set_run_tests"
+}
+
+# Set some strict warning flags. Clang's -Weverything can be way too strict, so
+# we actually have to turn off some things.
+clang_flags="-Weverything -Wno-padded -Wno-switch-enum -Wno-format-nonliteral"
+clang_flags="$clang_flags -Wno-cast-align -Wno-missing-noreturn -Wno-disabled-macro-expansion"
+clang_flags="$clang_flags -Wno-unreachable-code -Wno-unreachable-code-return"
+clang_flags="$clang_flags -Wno-implicit-fallthrough -Wno-unused-macros -Wno-gnu-label-as-value"
+# -Wno-undef is here because Clang seems to think BC_C11 is undefined, when it's defined.
+clang_flags="$clang_flags -Wno-undef"
+gcc_flags="-Wno-maybe-uninitialized -Wno-clobbered"
+
+# Common CFLAGS.
+cflags="-Wall -Wextra -Werror -pedantic -Wno-conditional-uninitialized"
+
+# Common debug and release flags.
+debug="$cflags -fno-omit-frame-pointer"
+release="$cflags -DNDEBUG"
+
+set -e
+
+script="$0"
+scriptdir=$(dirname "$script")
+
+real=$(realpath "$scriptdir/../")
+
+# Whether to run tests.
+if [ "$#" -gt 0 ]; then
+ run_tests="$1"
+ shift
+else
+ run_tests=1
+fi
+
+# Whether to generate tests. On platforms like OpenBSD, there is no GNU bc to
+# generate tests, so this must be off.
+if [ "$#" -gt 0 ]; then
+ gen_tests="$1"
+ shift
+else
+ gen_tests=1
+fi
+
+# Whether to test with clang.
+if [ "$#" -gt 0 ]; then
+ test_with_clang="$1"
+ shift
+else
+ test_with_clang=1
+fi
+
+# Whether to test with gcc.
+if [ "$#" -gt 0 ]; then
+ test_with_gcc="$1"
+ shift
+else
+ test_with_gcc=1
+fi
+
+# Whether to test with sanitizers.
+if [ "$#" -gt 0 ]; then
+ run_sanitizers="$1"
+ shift
+else
+ run_sanitizers=1
+fi
+
+# Whether to test with valgrind.
+if [ "$#" -gt 0 ]; then
+ run_valgrind="$1"
+ shift
+else
+ run_valgrind=1
+fi
+
+# Whether to test all settings combos.
+if [ "$#" -gt 0 ]; then
+ test_settings="$1"
+ shift
+else
+ test_settings=1
+fi
+
+# Whether to test 64-bit in addition to 32-bit.
+if [ "$#" -gt 0 ]; then
+ run_64_bit="$1"
+ shift
+else
+ run_64_bit=1
+fi
+
+# Whether to test with strgen.sh in addition to strgen.c.
+if [ "$#" -gt 0 ]; then
+ run_gen_script="$1"
+ shift
+else
+ run_gen_script=0
+fi
+
+# Whether to test on C11 in addition to C99.
+if [ "$#" -gt 0 ]; then
+ test_c11="$1"
+ shift
+else
+ test_c11=0
+fi
+
+# Whether to test 128-bit integers in addition to no 128-bit integers.
+if [ "$#" -gt 0 ]; then
+ test_128_bit="$1"
+ shift
+else
+ test_128_bit=0
+fi
+
+# Whether to test with computed goto or not.
+if [ "$#" -gt 0 ]; then
+ test_computed_goto="$1"
+ shift
+else
+ test_computed_goto=0
+fi
+
+# Whether to test history or not.
+if [ "$#" -gt 0 ]; then
+ test_karatsuba="$1"
+ shift
+else
+ test_karatsuba=1
+fi
+
+# Whether to test history or not.
+if [ "$#" -gt 0 ]; then
+ test_history="$1"
+ shift
+else
+ test_history=0
+fi
+
+if [ "$run_64_bit" -ne 0 ]; then
+ bits=64
+else
+ bits=32
+fi
+
+if [ "$test_computed_goto" -eq 0 ]; then
+ clang_flags="-DBC_NO_COMPUTED_GOTO $clang_flags"
+ gcc_flags="-DBC_NO_COMPUTED_GOTO $gcc_flags"
+fi
+
+# Setup a default compiler.
+if [ "$test_with_clang" -ne 0 ]; then
+ defcc="clang"
+elif [ "$test_with_gcc" -ne 0 ]; then
+ defcc="gcc"
+else
+ defcc="c99"
+fi
+
+export 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"
+export UBSAN_OPTIONS="print_stack_trace=1,silence_unsigned_overflow=1"
+
+build "$debug -std=c99" "$defcc" "-g" "1" "$bits"
+
+header "Running math library under --standard"
+
+# Make sure the math library is POSIX compliant.
+printf 'quit\n' | bin/bc -ls
+
+do_make clean_tests
+
+# Run the clang build sets.
+if [ "$test_with_clang" -ne 0 ]; then
+ build_set "clang" "$run_tests"
+fi
+
+# Run the gcc build sets.
+if [ "$test_with_gcc" -ne 0 ]; then
+ build_set "gcc" "$run_tests"
+fi
+
+if [ "$run_tests" -ne 0 ]; then
+
+ build "$release" "$defcc" "-O3" "1" "$bits"
+
+ # Run karatsuba.
+ if [ "$test_karatsuba" -ne 0 ]; then
+ karatsuba
+ fi
+
+ # Valgrind.
+ if [ "$run_valgrind" -ne 0 -a "$test_with_gcc" -ne 0 ]; then
+ vg
+ fi
+
+ printf '\n'
+ printf 'Tests successful.\n'
+
+ # I just assume that I am going to be fuzzing when I am done.
+ header "Building for AFL++..."
+
+ "$scriptdir/fuzz_prep.sh"
+
+ printf '\n'
+ printf 'Ready for scripts/randmath.py and for fuzzing.\n'
+ printf '\n'
+ printf 'Run scripts/randmath.py if you changed any math code.\n'
+ printf '\n'
+ printf 'Then if there are no problems, run the fuzzer.\n'
+ printf '\n'
+ printf 'Then run `scripts/fuzz_prep.sh -a`.\n'
+ printf '\n'
+ printf 'Then run `scripts/afl.py --asan`.\n'
+
+fi
diff --git a/scripts/release_settings.txt b/scripts/release_settings.txt
new file mode 100644
index 000000000000..1cf572347241
--- /dev/null
+++ b/scripts/release_settings.txt
@@ -0,0 +1,16 @@
+-sbc.sigint_reset -sdc.sigint_reset -sbc.tty_mode -sdc.tty_mode -sbc.history -sdc.history -sbc.prompt -sdc.prompt
+-Sbc.sigint_reset -Sdc.sigint_reset -sbc.tty_mode -sdc.tty_mode -sbc.history -sdc.history -sbc.prompt -sdc.prompt
+-sbc.sigint_reset -sdc.sigint_reset -Sbc.tty_mode -Sdc.tty_mode -sbc.history -sdc.history -sbc.prompt -sdc.prompt
+-sbc.sigint_reset -sdc.sigint_reset -sbc.tty_mode -sdc.tty_mode -Sbc.history -Sdc.history -sbc.prompt -sdc.prompt
+-sbc.sigint_reset -sdc.sigint_reset -sbc.tty_mode -sdc.tty_mode -sbc.history -sdc.history -Sbc.prompt -Sdc.prompt
+-Sbc.sigint_reset -Sdc.sigint_reset -Sbc.tty_mode -Sdc.tty_mode -sbc.history -sdc.history -sbc.prompt -sdc.prompt
+-Sbc.sigint_reset -Sdc.sigint_reset -sbc.tty_mode -sdc.tty_mode -Sbc.history -Sdc.history -sbc.prompt -sdc.prompt
+-Sbc.sigint_reset -Sdc.sigint_reset -sbc.tty_mode -sdc.tty_mode -sbc.history -sdc.history -Sbc.prompt -Sdc.prompt
+-sbc.sigint_reset -sdc.sigint_reset -Sbc.tty_mode -Sdc.tty_mode -Sbc.history -Sdc.history -sbc.prompt -sdc.prompt
+-sbc.sigint_reset -sdc.sigint_reset -Sbc.tty_mode -Sdc.tty_mode -sbc.history -sdc.history -Sbc.prompt -Sdc.prompt
+-sbc.sigint_reset -sdc.sigint_reset -sbc.tty_mode -sdc.tty_mode -Sbc.history -Sdc.history -Sbc.prompt -Sdc.prompt
+-Sbc.sigint_reset -Sdc.sigint_reset -Sbc.tty_mode -Sdc.tty_mode -Sbc.history -Sdc.history -sbc.prompt -sdc.prompt
+-Sbc.sigint_reset -Sdc.sigint_reset -Sbc.tty_mode -Sdc.tty_mode -sbc.history -sdc.history -Sbc.prompt -Sdc.prompt
+-Sbc.sigint_reset -Sdc.sigint_reset -sbc.tty_mode -sdc.tty_mode -Sbc.history -Sdc.history -Sbc.prompt -Sdc.prompt
+-sbc.sigint_reset -sdc.sigint_reset -Sbc.tty_mode -Sdc.tty_mode -Sbc.history -Sdc.history -Sbc.prompt -Sdc.prompt
+-Sbc.sigint_reset -Sdc.sigint_reset -Sbc.tty_mode -Sdc.tty_mode -Sbc.history -Sdc.history -Sbc.prompt -Sdc.prompt
diff --git a/scripts/test_settings.sh b/scripts/test_settings.sh
new file mode 100755
index 000000000000..563dbf0e58f3
--- /dev/null
+++ b/scripts/test_settings.sh
@@ -0,0 +1,77 @@
+#! /bin/sh
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (c) 2018-2021 Gavin D. Howard and contributors.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# * Redistributions of source code must retain the above copyright notice, this
+# list of conditions and the following disclaimer.
+#
+# * Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+
+# This script's argument is a number, which is the index of the setting set
+# that is under test. This script is for maintainers only.
+#
+# The procedure is this: run the script with:
+#
+# ./scripts/test_settings.sh 1
+#
+# Then run bc and dc to ensure their stuff is correct. Then run this script
+# again with:
+#
+# ./scripts/test_settings.sh 2
+#
+# And repeat. You can also test various environment variable sets with them.
+
+# Print the usage and exit with an error.
+usage() {
+ printf 'usage: %s index\n' "$0" 1>&2
+ exit 1
+}
+
+script="$0"
+scriptdir=$(dirname "$script")
+
+cd "$scriptdir/.."
+
+test "$#" -eq 1 || usage
+
+target="$1"
+shift
+
+line=0
+
+# This loop just loops until it gets to the right line. Quick and dirty.
+while read s; do
+
+ line=$(printf '%s + 1\n' "$line" | bc)
+
+ if [ "$line" -eq "$target" ]; then
+
+ # Configure, build, and exit.
+ ./configure.sh -O3 $s
+
+ make -j16 > /dev/null
+
+ exit
+ fi
+
+done < "$scriptdir/test_settings.txt"
diff --git a/scripts/test_settings.txt b/scripts/test_settings.txt
new file mode 100644
index 000000000000..e6dd8ac92929
--- /dev/null
+++ b/scripts/test_settings.txt
@@ -0,0 +1,93 @@
+-sbc.sigint_reset -sdc.sigint_reset -sbc.tty_mode -sdc.tty_mode -sbc.history -sdc.history -sbc.prompt -sdc.prompt
+-Sbc.sigint_reset -sdc.sigint_reset -sbc.tty_mode -sdc.tty_mode -sbc.history -sdc.history -sbc.prompt -sdc.prompt
+-sbc.sigint_reset -Sdc.sigint_reset -sbc.tty_mode -sdc.tty_mode -sbc.history -sdc.history -sbc.prompt -sdc.prompt
+-sbc.sigint_reset -sdc.sigint_reset -Sbc.tty_mode -sdc.tty_mode -sbc.history -sdc.history -sbc.prompt -sdc.prompt
+-sbc.sigint_reset -sdc.sigint_reset -sbc.tty_mode -Sdc.tty_mode -sbc.history -sdc.history -sbc.prompt -sdc.prompt
+-sbc.sigint_reset -sdc.sigint_reset -sbc.tty_mode -sdc.tty_mode -Sbc.history -sdc.history -sbc.prompt -sdc.prompt
+-sbc.sigint_reset -sdc.sigint_reset -sbc.tty_mode -sdc.tty_mode -sbc.history -Sdc.history -sbc.prompt -sdc.prompt
+-sbc.sigint_reset -sdc.sigint_reset -sbc.tty_mode -sdc.tty_mode -sbc.history -sdc.history -Sbc.prompt -sdc.prompt
+-sbc.sigint_reset -sdc.sigint_reset -sbc.tty_mode -sdc.tty_mode -sbc.history -sdc.history -sbc.prompt -Sdc.prompt
+-Sbc.sigint_reset -Sdc.sigint_reset -sbc.tty_mode -sdc.tty_mode -sbc.history -sdc.history -sbc.prompt -sdc.prompt
+-Sbc.sigint_reset -sdc.sigint_reset -Sbc.tty_mode -sdc.tty_mode -sbc.history -sdc.history -sbc.prompt -sdc.prompt
+-Sbc.sigint_reset -sdc.sigint_reset -sbc.tty_mode -Sdc.tty_mode -sbc.history -sdc.history -sbc.prompt -sdc.prompt
+-Sbc.sigint_reset -sdc.sigint_reset -sbc.tty_mode -sdc.tty_mode -Sbc.history -sdc.history -sbc.prompt -sdc.prompt
+-Sbc.sigint_reset -sdc.sigint_reset -sbc.tty_mode -sdc.tty_mode -sbc.history -Sdc.history -sbc.prompt -sdc.prompt
+-Sbc.sigint_reset -sdc.sigint_reset -sbc.tty_mode -sdc.tty_mode -sbc.history -sdc.history -Sbc.prompt -sdc.prompt
+-Sbc.sigint_reset -sdc.sigint_reset -sbc.tty_mode -sdc.tty_mode -sbc.history -sdc.history -sbc.prompt -Sdc.prompt
+-sbc.sigint_reset -Sdc.sigint_reset -Sbc.tty_mode -sdc.tty_mode -sbc.history -sdc.history -sbc.prompt -sdc.prompt
+-sbc.sigint_reset -Sdc.sigint_reset -sbc.tty_mode -Sdc.tty_mode -sbc.history -sdc.history -sbc.prompt -sdc.prompt
+-sbc.sigint_reset -Sdc.sigint_reset -sbc.tty_mode -sdc.tty_mode -Sbc.history -sdc.history -sbc.prompt -sdc.prompt
+-sbc.sigint_reset -Sdc.sigint_reset -sbc.tty_mode -sdc.tty_mode -sbc.history -Sdc.history -sbc.prompt -sdc.prompt
+-sbc.sigint_reset -Sdc.sigint_reset -sbc.tty_mode -sdc.tty_mode -sbc.history -sdc.history -Sbc.prompt -sdc.prompt
+-sbc.sigint_reset -Sdc.sigint_reset -sbc.tty_mode -sdc.tty_mode -sbc.history -sdc.history -sbc.prompt -Sdc.prompt
+-sbc.sigint_reset -sdc.sigint_reset -Sbc.tty_mode -Sdc.tty_mode -sbc.history -sdc.history -sbc.prompt -sdc.prompt
+-sbc.sigint_reset -sdc.sigint_reset -Sbc.tty_mode -sdc.tty_mode -Sbc.history -sdc.history -sbc.prompt -sdc.prompt
+-sbc.sigint_reset -sdc.sigint_reset -Sbc.tty_mode -sdc.tty_mode -sbc.history -Sdc.history -sbc.prompt -sdc.prompt
+-sbc.sigint_reset -sdc.sigint_reset -Sbc.tty_mode -sdc.tty_mode -sbc.history -sdc.history -Sbc.prompt -sdc.prompt
+-sbc.sigint_reset -sdc.sigint_reset -Sbc.tty_mode -sdc.tty_mode -sbc.history -sdc.history -sbc.prompt -Sdc.prompt
+-sbc.sigint_reset -sdc.sigint_reset -sbc.tty_mode -Sdc.tty_mode -Sbc.history -sdc.history -sbc.prompt -sdc.prompt
+-sbc.sigint_reset -sdc.sigint_reset -sbc.tty_mode -Sdc.tty_mode -sbc.history -Sdc.history -sbc.prompt -sdc.prompt
+-sbc.sigint_reset -sdc.sigint_reset -sbc.tty_mode -Sdc.tty_mode -sbc.history -sdc.history -Sbc.prompt -sdc.prompt
+-sbc.sigint_reset -sdc.sigint_reset -sbc.tty_mode -Sdc.tty_mode -sbc.history -sdc.history -sbc.prompt -Sdc.prompt
+-sbc.sigint_reset -sdc.sigint_reset -sbc.tty_mode -sdc.tty_mode -Sbc.history -Sdc.history -sbc.prompt -sdc.prompt
+-sbc.sigint_reset -sdc.sigint_reset -sbc.tty_mode -sdc.tty_mode -Sbc.history -sdc.history -Sbc.prompt -sdc.prompt
+-sbc.sigint_reset -sdc.sigint_reset -sbc.tty_mode -sdc.tty_mode -Sbc.history -sdc.history -sbc.prompt -Sdc.prompt
+-sbc.sigint_reset -sdc.sigint_reset -sbc.tty_mode -sdc.tty_mode -sbc.history -Sdc.history -Sbc.prompt -sdc.prompt
+-sbc.sigint_reset -sdc.sigint_reset -sbc.tty_mode -sdc.tty_mode -sbc.history -Sdc.history -sbc.prompt -Sdc.prompt
+-sbc.sigint_reset -sdc.sigint_reset -sbc.tty_mode -sdc.tty_mode -sbc.history -sdc.history -Sbc.prompt -Sdc.prompt
+-Sbc.sigint_reset -Sdc.sigint_reset -Sbc.tty_mode -sdc.tty_mode -sbc.history -sdc.history -sbc.prompt -sdc.prompt
+-Sbc.sigint_reset -Sdc.sigint_reset -sbc.tty_mode -Sdc.tty_mode -sbc.history -sdc.history -sbc.prompt -sdc.prompt
+-Sbc.sigint_reset -Sdc.sigint_reset -sbc.tty_mode -sdc.tty_mode -Sbc.history -sdc.history -sbc.prompt -sdc.prompt
+-Sbc.sigint_reset -Sdc.sigint_reset -sbc.tty_mode -sdc.tty_mode -sbc.history -Sdc.history -sbc.prompt -sdc.prompt
+-Sbc.sigint_reset -Sdc.sigint_reset -sbc.tty_mode -sdc.tty_mode -sbc.history -sdc.history -Sbc.prompt -sdc.prompt
+-Sbc.sigint_reset -Sdc.sigint_reset -sbc.tty_mode -sdc.tty_mode -sbc.history -sdc.history -sbc.prompt -Sdc.prompt
+-sbc.sigint_reset -Sdc.sigint_reset -Sbc.tty_mode -Sdc.tty_mode -sbc.history -sdc.history -sbc.prompt -sdc.prompt
+-sbc.sigint_reset -Sdc.sigint_reset -Sbc.tty_mode -sdc.tty_mode -Sbc.history -sdc.history -sbc.prompt -sdc.prompt
+-sbc.sigint_reset -Sdc.sigint_reset -Sbc.tty_mode -sdc.tty_mode -sbc.history -Sdc.history -sbc.prompt -sdc.prompt
+-sbc.sigint_reset -Sdc.sigint_reset -Sbc.tty_mode -sdc.tty_mode -sbc.history -sdc.history -Sbc.prompt -sdc.prompt
+-sbc.sigint_reset -Sdc.sigint_reset -Sbc.tty_mode -sdc.tty_mode -sbc.history -sdc.history -sbc.prompt -Sdc.prompt
+-sbc.sigint_reset -sdc.sigint_reset -Sbc.tty_mode -Sdc.tty_mode -Sbc.history -sdc.history -sbc.prompt -sdc.prompt
+-sbc.sigint_reset -sdc.sigint_reset -Sbc.tty_mode -Sdc.tty_mode -sbc.history -Sdc.history -sbc.prompt -sdc.prompt
+-sbc.sigint_reset -sdc.sigint_reset -Sbc.tty_mode -Sdc.tty_mode -sbc.history -sdc.history -Sbc.prompt -sdc.prompt
+-sbc.sigint_reset -sdc.sigint_reset -Sbc.tty_mode -Sdc.tty_mode -sbc.history -sdc.history -sbc.prompt -Sdc.prompt
+-sbc.sigint_reset -sdc.sigint_reset -sbc.tty_mode -Sdc.tty_mode -Sbc.history -Sdc.history -sbc.prompt -sdc.prompt
+-sbc.sigint_reset -sdc.sigint_reset -sbc.tty_mode -Sdc.tty_mode -Sbc.history -sdc.history -Sbc.prompt -sdc.prompt
+-sbc.sigint_reset -sdc.sigint_reset -sbc.tty_mode -Sdc.tty_mode -Sbc.history -sdc.history -sbc.prompt -Sdc.prompt
+-sbc.sigint_reset -sdc.sigint_reset -sbc.tty_mode -sdc.tty_mode -Sbc.history -Sdc.history -Sbc.prompt -sdc.prompt
+-sbc.sigint_reset -sdc.sigint_reset -sbc.tty_mode -sdc.tty_mode -Sbc.history -Sdc.history -sbc.prompt -Sdc.prompt
+-sbc.sigint_reset -sdc.sigint_reset -sbc.tty_mode -sdc.tty_mode -sbc.history -Sdc.history -Sbc.prompt -Sdc.prompt
+-Sbc.sigint_reset -Sdc.sigint_reset -Sbc.tty_mode -Sdc.tty_mode -sbc.history -sdc.history -sbc.prompt -sdc.prompt
+-Sbc.sigint_reset -Sdc.sigint_reset -Sbc.tty_mode -sdc.tty_mode -Sbc.history -sdc.history -sbc.prompt -sdc.prompt
+-Sbc.sigint_reset -Sdc.sigint_reset -Sbc.tty_mode -sdc.tty_mode -sbc.history -Sdc.history -sbc.prompt -sdc.prompt
+-Sbc.sigint_reset -Sdc.sigint_reset -Sbc.tty_mode -sdc.tty_mode -sbc.history -sdc.history -Sbc.prompt -sdc.prompt
+-Sbc.sigint_reset -Sdc.sigint_reset -Sbc.tty_mode -sdc.tty_mode -sbc.history -sdc.history -sbc.prompt -Sdc.prompt
+-sbc.sigint_reset -Sdc.sigint_reset -Sbc.tty_mode -Sdc.tty_mode -Sbc.history -sdc.history -sbc.prompt -sdc.prompt
+-sbc.sigint_reset -Sdc.sigint_reset -Sbc.tty_mode -Sdc.tty_mode -sbc.history -Sdc.history -sbc.prompt -sdc.prompt
+-sbc.sigint_reset -Sdc.sigint_reset -Sbc.tty_mode -Sdc.tty_mode -sbc.history -sdc.history -Sbc.prompt -sdc.prompt
+-sbc.sigint_reset -Sdc.sigint_reset -Sbc.tty_mode -Sdc.tty_mode -sbc.history -sdc.history -sbc.prompt -Sdc.prompt
+-sbc.sigint_reset -sdc.sigint_reset -Sbc.tty_mode -Sdc.tty_mode -Sbc.history -Sdc.history -sbc.prompt -sdc.prompt
+-sbc.sigint_reset -sdc.sigint_reset -Sbc.tty_mode -Sdc.tty_mode -Sbc.history -sdc.history -Sbc.prompt -sdc.prompt
+-sbc.sigint_reset -sdc.sigint_reset -Sbc.tty_mode -Sdc.tty_mode -Sbc.history -sdc.history -sbc.prompt -Sdc.prompt
+-sbc.sigint_reset -sdc.sigint_reset -sbc.tty_mode -Sdc.tty_mode -Sbc.history -Sdc.history -Sbc.prompt -sdc.prompt
+-sbc.sigint_reset -sdc.sigint_reset -sbc.tty_mode -Sdc.tty_mode -Sbc.history -Sdc.history -sbc.prompt -Sdc.prompt
+-sbc.sigint_reset -sdc.sigint_reset -sbc.tty_mode -sdc.tty_mode -Sbc.history -Sdc.history -Sbc.prompt -Sdc.prompt
+-Sbc.sigint_reset -Sdc.sigint_reset -Sbc.tty_mode -Sdc.tty_mode -Sbc.history -sdc.history -sbc.prompt -sdc.prompt
+-Sbc.sigint_reset -Sdc.sigint_reset -Sbc.tty_mode -Sdc.tty_mode -sbc.history -Sdc.history -sbc.prompt -sdc.prompt
+-Sbc.sigint_reset -Sdc.sigint_reset -Sbc.tty_mode -Sdc.tty_mode -sbc.history -sdc.history -Sbc.prompt -sdc.prompt
+-Sbc.sigint_reset -Sdc.sigint_reset -Sbc.tty_mode -Sdc.tty_mode -sbc.history -sdc.history -sbc.prompt -Sdc.prompt
+-sbc.sigint_reset -Sdc.sigint_reset -Sbc.tty_mode -Sdc.tty_mode -Sbc.history -Sdc.history -sbc.prompt -sdc.prompt
+-sbc.sigint_reset -Sdc.sigint_reset -Sbc.tty_mode -Sdc.tty_mode -Sbc.history -sdc.history -Sbc.prompt -sdc.prompt
+-sbc.sigint_reset -Sdc.sigint_reset -Sbc.tty_mode -Sdc.tty_mode -Sbc.history -sdc.history -sbc.prompt -Sdc.prompt
+-sbc.sigint_reset -sdc.sigint_reset -Sbc.tty_mode -Sdc.tty_mode -Sbc.history -Sdc.history -Sbc.prompt -sdc.prompt
+-sbc.sigint_reset -sdc.sigint_reset -Sbc.tty_mode -Sdc.tty_mode -Sbc.history -Sdc.history -sbc.prompt -Sdc.prompt
+-sbc.sigint_reset -sdc.sigint_reset -sbc.tty_mode -Sdc.tty_mode -Sbc.history -Sdc.history -Sbc.prompt -Sdc.prompt
+-Sbc.sigint_reset -Sdc.sigint_reset -Sbc.tty_mode -Sdc.tty_mode -Sbc.history -Sdc.history -sbc.prompt -sdc.prompt
+-Sbc.sigint_reset -Sdc.sigint_reset -Sbc.tty_mode -Sdc.tty_mode -Sbc.history -sdc.history -Sbc.prompt -sdc.prompt
+-Sbc.sigint_reset -Sdc.sigint_reset -Sbc.tty_mode -Sdc.tty_mode -Sbc.history -sdc.history -sbc.prompt -Sdc.prompt
+-sbc.sigint_reset -Sdc.sigint_reset -Sbc.tty_mode -Sdc.tty_mode -Sbc.history -Sdc.history -Sbc.prompt -sdc.prompt
+-sbc.sigint_reset -Sdc.sigint_reset -Sbc.tty_mode -Sdc.tty_mode -Sbc.history -Sdc.history -sbc.prompt -Sdc.prompt
+-sbc.sigint_reset -sdc.sigint_reset -Sbc.tty_mode -Sdc.tty_mode -Sbc.history -Sdc.history -Sbc.prompt -Sdc.prompt
+-Sbc.sigint_reset -Sdc.sigint_reset -Sbc.tty_mode -Sdc.tty_mode -Sbc.history -Sdc.history -Sbc.prompt -sdc.prompt
+-Sbc.sigint_reset -Sdc.sigint_reset -Sbc.tty_mode -Sdc.tty_mode -Sbc.history -Sdc.history -sbc.prompt -Sdc.prompt
+-sbc.sigint_reset -Sdc.sigint_reset -Sbc.tty_mode -Sdc.tty_mode -Sbc.history -Sdc.history -Sbc.prompt -Sdc.prompt
+-Sbc.sigint_reset -Sdc.sigint_reset -Sbc.tty_mode -Sdc.tty_mode -Sbc.history -Sdc.history -Sbc.prompt -Sdc.prompt