aboutsummaryrefslogtreecommitdiff
path: root/contrib/bc
diff options
context:
space:
mode:
authorStefan Eßer <se@FreeBSD.org>2022-03-07 22:23:56 +0000
committerStefan Eßer <se@FreeBSD.org>2022-03-07 22:26:09 +0000
commit23210c9f42af94dc6bcdae3996d8a3d010dd6bfe (patch)
tree642ba6c5d4d5e02e1fe7890192458bcc0ea9c1e2 /contrib/bc
parent9282f04ff0ee89cc4064e510f7fa505cfc890bf0 (diff)
parent3673adf1ee311d6f83176d3e43cf0efb314764e4 (diff)
downloadsrc-23210c9f42af94dc6bcdae3996d8a3d010dd6bfe.tar.gz
src-23210c9f42af94dc6bcdae3996d8a3d010dd6bfe.zip
contrib/bc: update to version 5.2.3
This version fixes a parse error when passing a file to bc using -f if that file has a multiline comment or string in it. Merge commit '3673adf1ee311d6f83176d3e43cf0efb314764e4' MFC after: 3 days
Diffstat (limited to 'contrib/bc')
-rw-r--r--contrib/bc/.gitignore12
-rw-r--r--contrib/bc/NEWS.md5
-rw-r--r--contrib/bc/benchmarks/bc/add.bc21
-rw-r--r--contrib/bc/benchmarks/bc/arrays.bc38
-rw-r--r--contrib/bc/benchmarks/bc/arrays_and_constants.bc38
-rw-r--r--contrib/bc/benchmarks/bc/bitfuncs.bc18
-rw-r--r--contrib/bc/benchmarks/bc/constants.bc41
-rw-r--r--contrib/bc/benchmarks/bc/divide.bc26
-rw-r--r--contrib/bc/benchmarks/bc/functions.bc38
-rw-r--r--contrib/bc/benchmarks/bc/irand_long.bc12
-rw-r--r--contrib/bc/benchmarks/bc/irand_short.bc9
-rw-r--r--contrib/bc/benchmarks/bc/lib.bc11
-rw-r--r--contrib/bc/benchmarks/bc/multiply.bc23
-rw-r--r--contrib/bc/benchmarks/bc/postfix_incdec.bc11
-rw-r--r--contrib/bc/benchmarks/bc/power.bc2
-rw-r--r--contrib/bc/benchmarks/bc/strings.bc40
-rw-r--r--contrib/bc/benchmarks/bc/subtract.bc22
-rw-r--r--contrib/bc/benchmarks/dc/modexp.dc42
-rw-r--r--contrib/bc/include/lang.h4
-rw-r--r--contrib/bc/include/lex.h11
-rw-r--r--contrib/bc/include/parse.h4
-rw-r--r--contrib/bc/include/status.h4
-rw-r--r--contrib/bc/include/version.h2
-rw-r--r--contrib/bc/include/vm.h9
-rw-r--r--contrib/bc/manuals/bc.1.md.in2476
-rw-r--r--contrib/bc/manuals/benchmarks.md673
-rw-r--r--contrib/bc/manuals/dc.1.md.in1452
-rw-r--r--contrib/bc/manuals/development.md5110
-rw-r--r--contrib/bc/manuals/header.txt27
-rw-r--r--contrib/bc/manuals/header_bc.txt1
-rw-r--r--contrib/bc/manuals/header_bcl.txt1
-rw-r--r--contrib/bc/manuals/header_dc.txt1
-rw-r--r--contrib/bc/manuals/release.md72
-rwxr-xr-xcontrib/bc/scripts/afl.py245
-rwxr-xr-xcontrib/bc/scripts/alloc.sh84
-rwxr-xr-xcontrib/bc/scripts/benchmark.sh159
-rw-r--r--contrib/bc/scripts/bitfuncgen.c240
-rwxr-xr-xcontrib/bc/scripts/fuzz_prep.sh81
-rwxr-xr-xcontrib/bc/scripts/manpage.sh175
-rw-r--r--contrib/bc/scripts/ministat.c675
-rwxr-xr-xcontrib/bc/scripts/package.sh248
-rwxr-xr-xcontrib/bc/scripts/radamsa.sh133
-rw-r--r--contrib/bc/scripts/radamsa.txt17
-rwxr-xr-xcontrib/bc/scripts/randmath.py421
-rwxr-xr-xcontrib/bc/scripts/release.sh810
-rw-r--r--contrib/bc/scripts/release_settings.txt16
-rwxr-xr-xcontrib/bc/scripts/test_settings.sh77
-rw-r--r--contrib/bc/scripts/test_settings.txt93
-rw-r--r--contrib/bc/src/bc_lex.c2
-rw-r--r--contrib/bc/src/dc_lex.c3
-rw-r--r--contrib/bc/src/lex.c17
-rw-r--r--contrib/bc/src/parse.c4
-rw-r--r--contrib/bc/src/program.c6
-rw-r--r--contrib/bc/src/vm.c153
-rw-r--r--contrib/bc/tests/fuzzing/bc_afl.yaml125
-rw-r--r--contrib/bc/tests/fuzzing/bc_afl_continue.yaml122
-rw-r--r--contrib/bc/tests/fuzzing/bc_inputs1/array.bc60
-rw-r--r--contrib/bc/tests/fuzzing/bc_inputs1/decimal.txt30
-rw-r--r--contrib/bc/tests/fuzzing/bc_inputs1/functions.bc7
-rw-r--r--contrib/bc/tests/fuzzing/bc_inputs1/len.bc48
-rw-r--r--contrib/bc/tests/fuzzing/bc_inputs1/lib10.txt4
-rw-r--r--contrib/bc/tests/fuzzing/bc_inputs1/lib12.txt1
-rw-r--r--contrib/bc/tests/fuzzing/bc_inputs1/lib2.txt15
-rw-r--r--contrib/bc/tests/fuzzing/bc_inputs1/lib3.txt6
-rw-r--r--contrib/bc/tests/fuzzing/bc_inputs1/lib6.txt5
-rw-r--r--contrib/bc/tests/fuzzing/bc_inputs2/bitfuncs.txt42
-rw-r--r--contrib/bc/tests/fuzzing/bc_inputs2/lib15.txt1
-rw-r--r--contrib/bc/tests/fuzzing/bc_inputs2/lib21.txt1
-rw-r--r--contrib/bc/tests/fuzzing/bc_inputs2/misc3.txt12
-rw-r--r--contrib/bc/tests/fuzzing/bc_inputs2/modulus.txt27
-rw-r--r--contrib/bc/tests/fuzzing/bc_inputs2/references.bc408
-rw-r--r--contrib/bc/tests/fuzzing/bc_inputs3/02.txt1
-rw-r--r--contrib/bc/tests/fuzzing/bc_inputs3/03.txt2
-rw-r--r--contrib/bc/tests/fuzzing/bc_inputs3/06.txt1
-rw-r--r--contrib/bc/tests/fuzzing/bc_inputs3/07.txt8
-rw-r--r--contrib/bc/tests/fuzzing/bc_inputs3/10.txt1
-rw-r--r--contrib/bc/tests/fuzzing/bc_inputs3/12.txt2
-rw-r--r--contrib/bc/tests/fuzzing/bc_inputs3/16.txt1
-rw-r--r--contrib/bc/tests/fuzzing/bc_inputs3/trunc.txt15
-rw-r--r--contrib/bc/tests/fuzzing/dc_inputs/01.txt2
-rw-r--r--contrib/bc/tests/fuzzing/dc_inputs/02.txt5
-rw-r--r--contrib/bc/tests/fuzzing/dc_inputs/03.txt2
-rw-r--r--contrib/bc/tests/fuzzing/dc_inputs/04.txt9
-rw-r--r--contrib/bc/tests/fuzzing/dc_inputs/05.txt3
-rw-r--r--contrib/bc/tests/fuzzing/dc_inputs/06.txt1
-rw-r--r--contrib/bc/tests/fuzzing/dc_inputs/07.txt3
-rw-r--r--contrib/bc/tests/fuzzing/dc_inputs/08.txt1
-rw-r--r--contrib/bc/tests/fuzzing/dc_inputs/09.txt9
-rw-r--r--contrib/bc/tests/fuzzing/dc_inputs/10.txt11
-rw-r--r--contrib/bc/tests/fuzzing/dc_inputs/11.txt4
-rw-r--r--contrib/bc/tests/fuzzing/dc_inputs/12.txt2
-rw-r--r--contrib/bc/tests/fuzzing/dc_inputs/13.txt7
-rw-r--r--contrib/bc/tests/fuzzing/dc_inputs/14.txt7
-rw-r--r--contrib/bc/tests/fuzzing/dc_inputs/15.txt11
-rw-r--r--contrib/bc/tests/fuzzing/dc_inputs/16.txt1
-rw-r--r--contrib/bc/tests/fuzzing/dc_inputs/17.txt20
-rw-r--r--contrib/bc/tests/fuzzing/dc_inputs/18.txt3
-rw-r--r--contrib/bc/tests/fuzzing/dc_inputs/20.txt3
-rw-r--r--contrib/bc/tests/fuzzing/dc_inputs/21.txt5
-rw-r--r--contrib/bc/tests/fuzzing/dc_inputs/22.txt36
-rw-r--r--contrib/bc/tests/fuzzing/dc_inputs/23.txt2
-rw-r--r--contrib/bc/tests/fuzzing/dc_inputs/24.txt1
-rw-r--r--contrib/bc/tests/fuzzing/dc_inputs/25.txt6
-rw-r--r--contrib/bc/tests/fuzzing/dc_inputs/26.txt155
-rw-r--r--contrib/bc/tests/fuzzing/dc_inputs/27.txt2
-rw-r--r--contrib/bc/tests/fuzzing/dc_inputs/28.txt1
-rw-r--r--contrib/bc/tests/fuzzing/dc_inputs/29.txt13
-rw-r--r--contrib/bc/tests/fuzzing/dc_inputs/30.txt1
-rw-r--r--contrib/bc/tests/fuzzing/dc_inputs/abs.txt7
-rw-r--r--contrib/bc/tests/fuzzing/dc_inputs/add.txt33
-rw-r--r--contrib/bc/tests/fuzzing/dc_inputs/array.dc2
-rw-r--r--contrib/bc/tests/fuzzing/dc_inputs/boolean.txt80
-rw-r--r--contrib/bc/tests/fuzzing/dc_inputs/decimal.txt41
-rw-r--r--contrib/bc/tests/fuzzing/dc_inputs/divide.txt33
-rw-r--r--contrib/bc/tests/fuzzing/dc_inputs/divmod.txt64
-rw-r--r--contrib/bc/tests/fuzzing/dc_inputs/else.dc4
-rw-r--r--contrib/bc/tests/fuzzing/dc_inputs/engineering.txt19
-rw-r--r--contrib/bc/tests/fuzzing/dc_inputs/loop.dc3
-rw-r--r--contrib/bc/tests/fuzzing/dc_inputs/misc.txt1
-rw-r--r--contrib/bc/tests/fuzzing/dc_inputs/modexp.txt103
-rw-r--r--contrib/bc/tests/fuzzing/dc_inputs/modulus.txt70
-rw-r--r--contrib/bc/tests/fuzzing/dc_inputs/multiply.txt42
-rw-r--r--contrib/bc/tests/fuzzing/dc_inputs/places.txt14
-rw-r--r--contrib/bc/tests/fuzzing/dc_inputs/power.txt36
-rw-r--r--contrib/bc/tests/fuzzing/dc_inputs/quit.dc2
-rw-r--r--contrib/bc/tests/fuzzing/dc_inputs/scientific.txt55
-rw-r--r--contrib/bc/tests/fuzzing/dc_inputs/shift.txt42
-rw-r--r--contrib/bc/tests/fuzzing/dc_inputs/sqrt.txt14
-rw-r--r--contrib/bc/tests/fuzzing/dc_inputs/stack_len.txt15
-rw-r--r--contrib/bc/tests/fuzzing/dc_inputs/stdin.txt205
-rw-r--r--contrib/bc/tests/fuzzing/dc_inputs/stream.dc2
-rw-r--r--contrib/bc/tests/fuzzing/dc_inputs/strings.txt51
-rw-r--r--contrib/bc/tests/fuzzing/dc_inputs/subtract.txt33
-rw-r--r--contrib/bc/tests/fuzzing/dc_inputs/vars.txt2
-rw-r--r--contrib/bc/tests/fuzzing/dc_inputs/weird.dc2
-rwxr-xr-xcontrib/bc/tests/other.sh50
136 files changed, 16127 insertions, 84 deletions
diff --git a/contrib/bc/.gitignore b/contrib/bc/.gitignore
index 31e43aa61efc..8d0c7d33935c 100644
--- a/contrib/bc/.gitignore
+++ b/contrib/bc/.gitignore
@@ -33,7 +33,9 @@ dc_help.c
config.mak
timeconst.bc
Makefile
+bcl.pc
+build/*
tests/fuzzing/bc_outputs1/*
tests/fuzzing/bc_outputs2/*
tests/fuzzing/bc_outputs3/*
@@ -61,7 +63,7 @@ tests/bc/scripts/strings2.txt
benchmarks/bc/*.txt
benchmarks/dc/*.txt
scripts/ministat
-scripts/bitgen
+scripts/bitfuncgen
perf.data
perf.data.old
*.gcda
@@ -76,5 +78,9 @@ cscope*.out
tags
*.vcxproj.user
-Debug/*
-Release/*
+vs/.vs/*
+vs/bin/*
+vs/lib/*
+vs/src2/*
+vs/tests/*.txt
+vs/tests/*.exe
diff --git a/contrib/bc/NEWS.md b/contrib/bc/NEWS.md
index 9a354e537d9f..0f28d552df18 100644
--- a/contrib/bc/NEWS.md
+++ b/contrib/bc/NEWS.md
@@ -1,5 +1,10 @@
# News
+## 5.2.3
+
+This is a production release that fixes one bug, a parse error when passing a
+file to `bc` using `-f` if that file had a multiline comment or string in it.
+
## 5.2.2
This is a production release that fixes one bug, a segmentation fault if
diff --git a/contrib/bc/benchmarks/bc/add.bc b/contrib/bc/benchmarks/bc/add.bc
new file mode 100644
index 000000000000..90a83e4758d9
--- /dev/null
+++ b/contrib/bc/benchmarks/bc/add.bc
@@ -0,0 +1,21 @@
+#! /usr/bin/bc -lq
+
+print "scale = 20\n"
+print "x = 1234567890 / scale\n"
+print "len = length(x) + 1 + scale\n"
+print "len *= 2\n"
+
+scale = 20
+x = 1234567890 / scale
+len = length(x) + 1 + scale
+len *= 2
+
+for (i = 0; i <= len; ++i) {
+ print "a[", i, "] = x * (10^", i, ")\n"
+}
+
+for (i = 1; i <= 10000; ++i) {
+ for (j = 0; j < len; ++j) {
+ print "v = a[", i, "] + a[", j, "]\n"
+ }
+}
diff --git a/contrib/bc/benchmarks/bc/arrays.bc b/contrib/bc/benchmarks/bc/arrays.bc
new file mode 100644
index 000000000000..cc0276d6ad20
--- /dev/null
+++ b/contrib/bc/benchmarks/bc/arrays.bc
@@ -0,0 +1,38 @@
+#! /usr/bin/bc
+#
+# 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.
+#
+
+max = 1000000
+
+for (i = 0; i < max; ++i) {
+ print "a", i, "[0] = ", i, "\n"
+}
+
+print "halt\n"
+
+halt
diff --git a/contrib/bc/benchmarks/bc/arrays_and_constants.bc b/contrib/bc/benchmarks/bc/arrays_and_constants.bc
new file mode 100644
index 000000000000..9a2172ece5be
--- /dev/null
+++ b/contrib/bc/benchmarks/bc/arrays_and_constants.bc
@@ -0,0 +1,38 @@
+#! /usr/bin/bc
+#
+# 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.
+#
+
+max = 1000000
+
+for (i = 0; i < max; ++i) {
+ print "b", i, "[100] = ", i, "\n"
+}
+
+print "halt\n"
+
+halt
diff --git a/contrib/bc/benchmarks/bc/bitfuncs.bc b/contrib/bc/benchmarks/bc/bitfuncs.bc
new file mode 100644
index 000000000000..69d357c2ce8a
--- /dev/null
+++ b/contrib/bc/benchmarks/bc/bitfuncs.bc
@@ -0,0 +1,18 @@
+#! /usr/bin/bc -lq
+
+scale = 0
+max = 10000
+
+print "scale = 0\n"
+
+for (i = 0; i < max; ++i) {
+
+ a = rand()
+ b = rand()
+
+ print "band(", a, ", ", b, ")\n"
+ print "bor(", a, ", ", b, ")\n"
+ print "bxor(", a, ", ", b, ")\n"
+ print "bshl(", a, ", ", b % 32, ")\n"
+ print "bshr(", a, ", ", b % 32, ")\n"
+}
diff --git a/contrib/bc/benchmarks/bc/constants.bc b/contrib/bc/benchmarks/bc/constants.bc
new file mode 100644
index 000000000000..1f7b92d47566
--- /dev/null
+++ b/contrib/bc/benchmarks/bc/constants.bc
@@ -0,0 +1,41 @@
+#! /usr/bin/bc
+#
+# 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.
+#
+
+max = 1000
+max2 = 1000
+
+for (i = 0; i < max; ++i) {
+
+ print "c = ", i, "\n"
+ print "e = 0.", i, "\n"
+
+ for (j = 0; j < max2; ++j) {
+ print "d = ", i, ".", j, "\n"
+ }
+}
diff --git a/contrib/bc/benchmarks/bc/divide.bc b/contrib/bc/benchmarks/bc/divide.bc
new file mode 100644
index 000000000000..227794badbcb
--- /dev/null
+++ b/contrib/bc/benchmarks/bc/divide.bc
@@ -0,0 +1,26 @@
+#! /usr/bin/bc -lq
+
+print "scale = 20\n"
+print "x = 1234567890 * 10^(-scale)\n"
+print "len = 1 + 2 * scale\n"
+print "scale += 10\n"
+
+scale = 20
+x = 1234567890 * 10^(-scale)
+len = 1 + 2 * scale
+
+scale += 10
+
+for (i = 0; i <= len; ++i) {
+ print "a[", i, "] = x * (10^", i, ")\n"
+}
+
+for (i = 1; i <= 10000; ++i) {
+ for (j = 0; j < len; ++j) {
+ print "v = a[0] / a[", j, "]\n"
+ print "v = a[", i, "] / a[", j, "]\n"
+ print "v = (a[0] * ", i, ") / a[", j, "]\n"
+ print "v = a[0] / (a[", j, "] * ", i, ")\n"
+ print "v = (a[0] * ", i, ") / (a[", j, "] * ", i, ")\n"
+ }
+}
diff --git a/contrib/bc/benchmarks/bc/functions.bc b/contrib/bc/benchmarks/bc/functions.bc
new file mode 100644
index 000000000000..7848c8df0c9f
--- /dev/null
+++ b/contrib/bc/benchmarks/bc/functions.bc
@@ -0,0 +1,38 @@
+#! /usr/bin/bc
+#
+# 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.
+#
+
+max = 1000000
+
+for (i = 0; i < max; ++i) {
+ print "define etsna", i, "(n) {\n\tn\n}\n"
+}
+
+print "halt\n"
+
+halt
diff --git a/contrib/bc/benchmarks/bc/irand_long.bc b/contrib/bc/benchmarks/bc/irand_long.bc
new file mode 100644
index 000000000000..2d2404942f83
--- /dev/null
+++ b/contrib/bc/benchmarks/bc/irand_long.bc
@@ -0,0 +1,12 @@
+#! /usr/bin/bc -lq
+
+start = 2^256
+end = start + 10000000
+
+for (i = start; i < end; ++i) {
+ print "irand(", i, ")\n"
+}
+
+print "halt\n"
+
+halt
diff --git a/contrib/bc/benchmarks/bc/irand_short.bc b/contrib/bc/benchmarks/bc/irand_short.bc
new file mode 100644
index 000000000000..a53d407879f3
--- /dev/null
+++ b/contrib/bc/benchmarks/bc/irand_short.bc
@@ -0,0 +1,9 @@
+#! /usr/bin/bc -lq
+
+for (i = 2; i < 10000000; ++i) {
+ print "irand(", i, ")\n"
+}
+
+print "halt\n"
+
+halt
diff --git a/contrib/bc/benchmarks/bc/lib.bc b/contrib/bc/benchmarks/bc/lib.bc
new file mode 100644
index 000000000000..fb7cd1b93354
--- /dev/null
+++ b/contrib/bc/benchmarks/bc/lib.bc
@@ -0,0 +1,11 @@
+#! /usr/bin/bc -lq
+
+print "for (i = 100; i < 1000; ++i) {\n"
+print " v = pi(i)\n"
+print " v = e(v)\n"
+print " v = l(v)\n"
+print "}\n"
+
+print "halt\n"
+
+halt
diff --git a/contrib/bc/benchmarks/bc/multiply.bc b/contrib/bc/benchmarks/bc/multiply.bc
new file mode 100644
index 000000000000..d4ed08e055c8
--- /dev/null
+++ b/contrib/bc/benchmarks/bc/multiply.bc
@@ -0,0 +1,23 @@
+#! /usr/bin/bc -lq
+
+print "scale = 20\n"
+print "x = 1234567890 / scale\n"
+print "len = length(x) + 1 + scale\n"
+
+scale = 20
+x = 1234567890 / scale
+len = length(x) + 1 + scale
+
+for (i = 0; i <= len; ++i) {
+ print "a[", i, "] = x * (10^", i, ")\n"
+}
+
+for (i = 1; i <= 10000; ++i) {
+ for (j = 0; j < len; ++j) {
+ print "v = a[0] * a[", j, "]\n"
+ print "v = a[", i, "] * a[", j, "]\n"
+ print "v = (a[0] * ", i, ") * a[", j, "]\n"
+ print "v = a[0] * (a[", j, "] * ", i, ")\n"
+ print "v = (a[0] * ", i, ") * (a[", j, "] * ", i, ")\n"
+ }
+}
diff --git a/contrib/bc/benchmarks/bc/postfix_incdec.bc b/contrib/bc/benchmarks/bc/postfix_incdec.bc
new file mode 100644
index 000000000000..2437f4c4c820
--- /dev/null
+++ b/contrib/bc/benchmarks/bc/postfix_incdec.bc
@@ -0,0 +1,11 @@
+#! /usr/bin/bc -lq
+
+max = 1000000
+
+for (i = 0; i < max; ++i) {
+ print "i++\ni--\n"
+}
+
+print "halt\n"
+
+halt
diff --git a/contrib/bc/benchmarks/bc/power.bc b/contrib/bc/benchmarks/bc/power.bc
new file mode 100644
index 000000000000..b067aa732d10
--- /dev/null
+++ b/contrib/bc/benchmarks/bc/power.bc
@@ -0,0 +1,2 @@
+#! /usr/bin/bc -lq
+
diff --git a/contrib/bc/benchmarks/bc/strings.bc b/contrib/bc/benchmarks/bc/strings.bc
new file mode 100644
index 000000000000..a97017ea78b4
--- /dev/null
+++ b/contrib/bc/benchmarks/bc/strings.bc
@@ -0,0 +1,40 @@
+#! /usr/bin/bc
+#
+# 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.
+#
+
+max = 1000000
+
+print "\qasotehnuasnotehustnaoheusntaoheustnaoheusntaoehunsatoheuastoehuaosnetuhaosetnuhaosentuahoesntuahoeuhstoeunhatoehusanotehusatnoheus\q\n"
+
+for (i = 0; i < max; ++i) {
+ print "\qabc", i, " = ", i, "\\n\q\n"
+}
+
+print "halt\n"
+
+halt
diff --git a/contrib/bc/benchmarks/bc/subtract.bc b/contrib/bc/benchmarks/bc/subtract.bc
new file mode 100644
index 000000000000..b88bd60e935c
--- /dev/null
+++ b/contrib/bc/benchmarks/bc/subtract.bc
@@ -0,0 +1,22 @@
+#! /usr/bin/bc -lq
+
+print "scale = 20\n"
+print "x = 1234567890 / scale\n"
+print "len = length(x) + 1 + scale\n"
+print "len *= 2\n"
+
+scale = 20
+x = 1234567890 / scale
+len = length(x) + 1 + scale
+len *= 2
+
+for (i = 0; i <= len; ++i) {
+ print "a[", i, "] = x * (10^", i, ")\n"
+}
+
+for (i = 1; i <= 10000; ++i) {
+ for (j = 0; j < len; ++j) {
+ print "v = a[", i, "] - a[", j, "]\n"
+ }
+}
+
diff --git a/contrib/bc/benchmarks/dc/modexp.dc b/contrib/bc/benchmarks/dc/modexp.dc
new file mode 100644
index 000000000000..48f304cb92da
--- /dev/null
+++ b/contrib/bc/benchmarks/dc/modexp.dc
@@ -0,0 +1,42 @@
+#! /usr/bin/dc
+#
+# 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.
+
+[ ]ss
+[|]so
+100sm 0si
+[
+ li1+si 0sj
+ [
+ lj1+sj 0sk
+ [
+ lk1+sk lin lsn ljn lsn lkn lsn lon 10P lk lm !<z
+ ]dszx
+ lj lm !<y
+ ]dsyx
+ li lm !<x
+]dsxx
diff --git a/contrib/bc/include/lang.h b/contrib/bc/include/lang.h
index 09b0d6072806..fb0c3420aa22 100644
--- a/contrib/bc/include/lang.h
+++ b/contrib/bc/include/lang.h
@@ -41,6 +41,10 @@
#include <assert.h>
#endif // BC_C11
+#if BC_C11
+#include <assert.h>
+#endif // BC_C11
+
#include <status.h>
#include <vector.h>
#include <num.h>
diff --git a/contrib/bc/include/lex.h b/contrib/bc/include/lex.h
index 0e7af1742001..129b9940618f 100644
--- a/contrib/bc/include/lex.h
+++ b/contrib/bc/include/lex.h
@@ -491,6 +491,11 @@ typedef struct BcLex {
/// if a string or comment are not properly terminated.
bool is_stdin;
+ /// If this is true, the lexer is processing expressions from the
+ /// command-line and can ask for more data if a string or comment are not
+ /// properly terminated.
+ bool is_exprs;
+
} BcLex;
/**
@@ -519,8 +524,10 @@ void bc_lex_file(BcLex *l, const char *file);
* @param l The lexer.
* @param text The text to lex.
* @param is_stdin True if the text is from stdin, false otherwise.
+ * @param is_exprs True if the text is from command-line expressions, false
+ * otherwise.
*/
-void bc_lex_text(BcLex *l, const char *text, bool is_stdin);
+void bc_lex_text(BcLex *l, const char *text, bool is_stdin, bool is_exprs);
/**
* Generic next function for the parser to call. It takes care of calling the
@@ -579,7 +586,7 @@ void bc_lex_invalidChar(BcLex *l, char c);
/**
* Reads a line from stdin and puts it into the lexer's buffer.
- * @param l The lexer.
+ * @param l The lexer.
*/
bool bc_lex_readLine(BcLex *l);
diff --git a/contrib/bc/include/parse.h b/contrib/bc/include/parse.h
index 0088c1523ec6..35ca1652fc98 100644
--- a/contrib/bc/include/parse.h
+++ b/contrib/bc/include/parse.h
@@ -263,8 +263,10 @@ void bc_parse_pushName(const BcParse* p, char *name, bool var);
* @param p The parser.
* @param text The text to lex.
* @param is_stdin True if the text is from stdin, false otherwise.
+ * @param is_exprs True if the text is from command-line expressions, false
+ * otherwise.
*/
-void bc_parse_text(BcParse *p, const char *text, bool is_stdin);
+void bc_parse_text(BcParse *p, const char *text, bool is_stdin, bool is_exprs);
// References to const 0 and 1 strings for special cases. bc and dc have
// specific instructions for 0 and 1 because they pop up so often and (in the
diff --git a/contrib/bc/include/status.h b/contrib/bc/include/status.h
index 993b5e698fb3..df084c70c1b5 100644
--- a/contrib/bc/include/status.h
+++ b/contrib/bc/include/status.h
@@ -116,7 +116,7 @@
#endif // BC_DEBUG_CODE
// We want to be able to use _Noreturn on C11 compilers.
-#if __STDC_VERSION__ >= 201100L
+#if __STDC_VERSION__ >= 201112L
#include <stdnoreturn.h>
#define BC_NORETURN _Noreturn
@@ -401,7 +401,7 @@ typedef enum BcErr {
/// Void value used in an expression error.
BC_ERR_EXEC_VOID_VAL,
- // Parse (and lex errors).
+ // Parse (and lex) errors.
/// EOF encountered when not expected error.
BC_ERR_PARSE_EOF,
diff --git a/contrib/bc/include/version.h b/contrib/bc/include/version.h
index 0c4122528e7d..a7d1640a87a2 100644
--- a/contrib/bc/include/version.h
+++ b/contrib/bc/include/version.h
@@ -37,6 +37,6 @@
#define BC_VERSION_H
/// The current version.
-#define VERSION 5.2.2
+#define VERSION 5.2.3
#endif // BC_VERSION_H
diff --git a/contrib/bc/include/vm.h b/contrib/bc/include/vm.h
index 6f69712a804b..cf7eb5238870 100644
--- a/contrib/bc/include/vm.h
+++ b/contrib/bc/include/vm.h
@@ -754,13 +754,20 @@ void* bc_vm_realloc(void *ptr, size_t n);
char* bc_vm_strdup(const char *str);
/**
- * Reads a line into BcVm's buffer field.
+ * Reads a line from stdin into BcVm's buffer field.
* @param clear True if the buffer should be cleared first, false otherwise.
* @return True if a line was read, false otherwise.
*/
bool bc_vm_readLine(bool clear);
/**
+ * Reads a line from the command-line expressions into BcVm's buffer field.
+ * @param clear True if the buffer should be cleared first, false otherwise.
+ * @return True if a line was read, false otherwise.
+ */
+bool bc_vm_readBuf(bool clear);
+
+/**
* A convenience and portability function for OpenBSD's pledge().
* @param promises The promises to pledge().
* @param execpromises The exec promises to pledge().
diff --git a/contrib/bc/manuals/bc.1.md.in b/contrib/bc/manuals/bc.1.md.in
new file mode 100644
index 000000000000..e5ca807dbe39
--- /dev/null
+++ b/contrib/bc/manuals/bc.1.md.in
@@ -0,0 +1,2476 @@
+<!---
+
+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.
+
+-->
+
+# NAME
+
+bc - arbitrary-precision decimal arithmetic language and calculator
+
+# SYNOPSIS
+
+**bc** [**-ghilPqRsvVw**] [**-\-global-stacks**] [**-\-help**] [**-\-interactive**] [**-\-mathlib**] [**-\-no-prompt**] [**-\-no-read-prompt**] [**-\-quiet**] [**-\-standard**] [**-\-warn**] [**-\-version**] [**-e** *expr*] [**-\-expression**=*expr*...] [**-f** *file*...] [**-\-file**=*file*...] [*file*...]
+
+# DESCRIPTION
+
+bc(1) is an interactive processor for a language first standardized in 1991 by
+POSIX. (The current standard is [here][1].) The language provides unlimited
+precision decimal arithmetic and is somewhat C-like, but there are differences.
+Such differences will be noted in this document.
+
+After parsing and handling options, this bc(1) reads any files given on the
+command line and executes them before reading from **stdin**.
+
+{{ A H N HN }}
+This bc(1) is a drop-in replacement for *any* bc(1), including (and
+especially) the GNU bc(1). It also has many extensions and extra features beyond
+other implementations.
+{{ end }}
+{{ E EH EN EHN }}
+This bc(1) is a drop-in replacement for *any* bc(1), including (and especially)
+the GNU bc(1).
+{{ end }}
+
+**Note**: If running this bc(1) on *any* script meant for another bc(1) gives a
+parse error, it is probably because a word this bc(1) reserves as a keyword is
+used as the name of a function, variable, or array. To fix that, use the
+command-line option **-r** *keyword*, where *keyword* is the keyword that is
+used as a name in the script. For more information, see the **OPTIONS** section.
+
+If parsing scripts meant for other bc(1) implementations still does not work,
+that is a bug and should be reported. See the **BUGS** section.
+
+# OPTIONS
+
+The following are the options that bc(1) accepts.
+
+**-g**, **-\-global-stacks**
+
+{{ A H N HN }}
+: Turns the globals **ibase**, **obase**, **scale**, and **seed** into stacks.
+
+ This has the effect that a copy of the current value of all four are pushed
+{{ end }}
+{{ E EH EN EHN }}
+: Turns the globals **ibase**, **obase**, and **scale** into stacks.
+
+ This has the effect that a copy of the current value of all three are pushed
+{{ end }}
+ onto a stack for every function call, as well as popped when every function
+ returns. This means that functions can assign to any and all of those
+ globals without worrying that the change will affect other functions.
+ Thus, a hypothetical function named **output(x,b)** that simply printed
+ **x** in base **b** could be written like this:
+
+ define void output(x, b) {
+ obase=b
+ x
+ }
+
+ instead of like this:
+
+ define void output(x, b) {
+ auto c
+ c=obase
+ obase=b
+ x
+ obase=c
+ }
+
+ This makes writing functions much easier.
+
+{{ A H N HN }}
+ (**Note**: the function **output(x,b)** exists in the extended math library.
+ See the **LIBRARY** section.)
+
+ However, since using this flag means that functions cannot set **ibase**,
+ **obase**, **scale**, or **seed** globally, functions that are made to do so
+ cannot work anymore. There are two possible use cases for that, and each has
+ a solution.
+{{ end }}
+{{ E EH EN EHN }}
+ However, since using this flag means that functions cannot set **ibase**,
+ **obase**, or **scale** globally, functions that are made to do so cannot
+ work anymore. There are two possible use cases for that, and each has a
+ solution.
+{{ end }}
+
+ First, if a function is called on startup to turn bc(1) into a number
+ converter, it is possible to replace that capability with various shell
+ aliases. Examples:
+
+ alias d2o="bc -e ibase=A -e obase=8"
+ alias h2b="bc -e ibase=G -e obase=2"
+
+{{ A H N HN }}
+ Second, if the purpose of a function is to set **ibase**, **obase**,
+ **scale**, or **seed** globally for any other purpose, it could be split
+ into one to four functions (based on how many globals it sets) and each of
+ those functions could return the desired value for a global.
+
+ For functions that set **seed**, the value assigned to **seed** is not
+ propagated to parent functions. This means that the sequence of
+ pseudo-random numbers that they see will not be the same sequence of
+ pseudo-random numbers that any parent sees. This is only the case once
+ **seed** has been set.
+
+ If a function desires to not affect the sequence of pseudo-random numbers
+ of its parents, but wants to use the same **seed**, it can use the following
+ line:
+
+ seed = seed
+{{ end }}
+{{ E EH EN EHN }}
+ Second, if the purpose of a function is to set **ibase**, **obase**, or
+ **scale** globally for any other purpose, it could be split into one to
+ three functions (based on how many globals it sets) and each of those
+ functions could return the desired value for a global.
+{{ end }}
+
+ If the behavior of this option is desired for every run of bc(1), then users
+ could make sure to define **BC_ENV_ARGS** and include this option (see the
+ **ENVIRONMENT VARIABLES** section for more details).
+
+ If **-s**, **-w**, or any equivalents are used, this option is ignored.
+
+ This is a **non-portable extension**.
+
+**-h**, **-\-help**
+
+: Prints a usage message and quits.
+
+**-i**, **-\-interactive**
+
+: Forces interactive mode. (See the **INTERACTIVE MODE** section.)
+
+ This is a **non-portable extension**.
+
+**-L**, **-\-no-line-length**
+
+: Disables line length checking and prints numbers without backslashes and
+ newlines. In other words, this option sets **BC_LINE_LENGTH** to **0** (see
+ the **ENVIRONMENT VARIABLES** section).
+
+ This is a **non-portable extension**.
+
+**-l**, **-\-mathlib**
+
+: Sets **scale** (see the **SYNTAX** section) to **20** and loads the included
+{{ A H N HN }}
+ math library and the extended math library before running any code,
+ including any expressions or files specified on the command line.
+
+ To learn what is in the libraries, see the **LIBRARY** section.
+{{ end }}
+{{ E EH EN EHN }}
+ math library before running any code, including any expressions or files
+ specified on the command line.
+
+ To learn what is in the library, see the **LIBRARY** section.
+{{ end }}
+
+**-P**, **-\-no-prompt**
+
+: Disables the prompt in TTY mode. (The prompt is only enabled in TTY mode.
+ See the **TTY MODE** section.) This is mostly for those users that do not
+ want a prompt or are not used to having them in bc(1). Most of those users
+ would want to put this option in **BC_ENV_ARGS** (see the
+ **ENVIRONMENT VARIABLES** section).
+
+ These options override the **BC_PROMPT** and **BC_TTY_MODE** environment
+ variables (see the **ENVIRONMENT VARIABLES** section).
+
+ This is a **non-portable extension**.
+
+**-R**, **-\-no-read-prompt**
+
+: Disables the read prompt in TTY mode. (The read prompt is only enabled in
+ TTY mode. See the **TTY MODE** section.) This is mostly for those users that
+ do not want a read prompt or are not used to having them in bc(1). Most of
+ those users would want to put this option in **BC_ENV_ARGS** (see the
+ **ENVIRONMENT VARIABLES** section). This option is also useful in hash bang
+ lines of bc(1) scripts that prompt for user input.
+
+ This option does not disable the regular prompt because the read prompt is
+ only used when the **read()** built-in function is called.
+
+ These options *do* override the **BC_PROMPT** and **BC_TTY_MODE**
+ environment variables (see the **ENVIRONMENT VARIABLES** section), but only
+ for the read prompt.
+
+ This is a **non-portable extension**.
+
+**-r** *keyword*, **-\-redefine**=*keyword*
+
+: Redefines *keyword* in order to allow it to be used as a function, variable,
+ or array name. This is useful when this bc(1) gives parse errors when
+ parsing scripts meant for other bc(1) implementations.
+
+ The keywords this bc(1) allows to be redefined are:
+
+ * **abs**
+ * **asciify**
+ * **continue**
+ * **divmod**
+ * **else**
+ * **halt**
+{{ A H N HN }}
+ * **irand**
+{{ end }}
+ * **last**
+ * **limits**
+ * **maxibase**
+ * **maxobase**
+{{ A H N HN }}
+ * **maxrand**
+{{ end }}
+ * **maxscale**
+ * **modexp**
+ * **print**
+{{ A H N HN }}
+ * **rand**
+{{ end }}
+ * **read**
+{{ A H N HN }}
+ * **seed**
+{{ end }}
+ * **stream**
+
+ If any of those keywords are used as a function, variable, or array name in
+ a script, use this option with the keyword as the argument. If multiple are
+ used, use this option for all of them; it can be used multiple times.
+
+ Keywords are *not* redefined when parsing the builtin math library (see the
+ **LIBRARY** section).
+
+ It is a fatal error to redefine keywords mandated by the POSIX standard. It
+ is a fatal error to attempt to redefine words that this bc(1) does not
+ reserve as keywords.
+
+**-q**, **-\-quiet**
+
+: This option is for compatibility with the [GNU bc(1)][2]; it is a no-op.
+ Without this option, GNU bc(1) prints a copyright header. This bc(1) only
+ prints the copyright header if one or more of the **-v**, **-V**, or
+ **-\-version** options are given.
+
+ This is a **non-portable extension**.
+
+**-s**, **-\-standard**
+
+: Process exactly the language defined by the [standard][1] and error if any
+ extensions are used.
+
+ This is a **non-portable extension**.
+
+**-v**, **-V**, **-\-version**
+
+: Print the version information (copyright header) and exit.
+
+ This is a **non-portable extension**.
+
+**-w**, **-\-warn**
+
+: Like **-s** and **-\-standard**, except that warnings (and not errors) are
+ printed for non-standard extensions and execution continues normally.
+
+ This is a **non-portable extension**.
+
+**-z**, **-\-leading-zeroes**
+
+: Makes bc(1) print all numbers greater than **-1** and less than **1**, and
+ not equal to **0**, with a leading zero.
+
+ This can be set for individual numbers with the **plz(x)**, plznl(x)**,
+ **pnlz(x)**, and **pnlznl(x)** functions in the extended math library (see
+ the **LIBRARY** section).
+
+ This is a **non-portable extension**.
+
+**-e** *expr*, **-\-expression**=*expr*
+
+: Evaluates *expr*. If multiple expressions are given, they are evaluated in
+ order. If files are given as well (see below), the expressions and files are
+ evaluated in the order given. This means that if a file is given before an
+ expression, the file is read in and evaluated first.
+
+ If this option is given on the command-line (i.e., not in **BC_ENV_ARGS**,
+ see the **ENVIRONMENT VARIABLES** section), then after processing all
+ expressions and files, bc(1) will exit, unless **-** (**stdin**) was given
+ as an argument at least once to **-f** or **-\-file**, whether on the
+ command-line or in **BC_ENV_ARGS**. However, if any other **-e**,
+ **-\-expression**, **-f**, or **-\-file** arguments are given after **-f-**
+ or equivalent is given, bc(1) will give a fatal error and exit.
+
+ This is a **non-portable extension**.
+
+**-f** *file*, **-\-file**=*file*
+
+: Reads in *file* and evaluates it, line by line, as though it were read
+ through **stdin**. If expressions are also given (see above), the
+ expressions are evaluated in the order given.
+
+ If this option is given on the command-line (i.e., not in **BC_ENV_ARGS**,
+ see the **ENVIRONMENT VARIABLES** section), then after processing all
+ expressions and files, bc(1) will exit, unless **-** (**stdin**) was given
+ as an argument at least once to **-f** or **-\-file**. However, if any other
+ **-e**, **-\-expression**, **-f**, or **-\-file** arguments are given after
+ **-f-** or equivalent is given, bc(1) will give a fatal error and exit.
+
+ This is a **non-portable extension**.
+
+All long options are **non-portable extensions**.
+
+# STDIN
+
+If no files or expressions are given by the **-f**, **-\-file**, **-e**, or
+**-\-expression** options, then bc(1) read from **stdin**.
+
+However, there are a few caveats to this.
+
+First, **stdin** is evaluated a line at a time. The only exception to this is if
+the parse cannot complete. That means that starting a string without ending it
+or starting a function, **if** statement, or loop without ending it will also
+cause bc(1) to not execute.
+
+Second, after an **if** statement, bc(1) doesn't know if an **else** statement
+will follow, so it will not execute until it knows there will not be an **else**
+statement.
+
+# STDOUT
+
+Any non-error output is written to **stdout**. In addition, if history (see the
+**HISTORY** section) and the prompt (see the **TTY MODE** section) are enabled,
+both are output to **stdout**.
+
+**Note**: Unlike other bc(1) implementations, this bc(1) will issue a fatal
+error (see the **EXIT STATUS** section) if it cannot write to **stdout**, so if
+**stdout** is closed, as in **bc <file> >&-**, it will quit with an error. This
+is done so that bc(1) can report problems when **stdout** is redirected to a
+file.
+
+If there are scripts that depend on the behavior of other bc(1) implementations,
+it is recommended that those scripts be changed to redirect **stdout** to
+**/dev/null**.
+
+# STDERR
+
+Any error output is written to **stderr**.
+
+**Note**: Unlike other bc(1) implementations, this bc(1) will issue a fatal
+error (see the **EXIT STATUS** section) if it cannot write to **stderr**, so if
+**stderr** is closed, as in **bc <file> 2>&-**, it will quit with an error. This
+is done so that bc(1) can exit with an error code when **stderr** is redirected
+to a file.
+
+If there are scripts that depend on the behavior of other bc(1) implementations,
+it is recommended that those scripts be changed to redirect **stderr** to
+**/dev/null**.
+
+# SYNTAX
+
+The syntax for bc(1) programs is mostly C-like, with some differences. This
+bc(1) follows the [POSIX standard][1], which is a much more thorough resource
+for the language this bc(1) accepts. This section is meant to be a summary and a
+listing of all the extensions to the standard.
+
+In the sections below, **E** means expression, **S** means statement, and **I**
+means identifier.
+
+Identifiers (**I**) start with a lowercase letter and can be followed by any
+number (up to **BC_NAME_MAX-1**) of lowercase letters (**a-z**), digits
+(**0-9**), and underscores (**\_**). The regex is **\[a-z\]\[a-z0-9\_\]\***.
+Identifiers with more than one character (letter) are a
+**non-portable extension**.
+
+**ibase** is a global variable determining how to interpret constant numbers. It
+is the "input" base, or the number base used for interpreting input numbers.
+**ibase** is initially **10**. If the **-s** (**-\-standard**) and **-w**
+(**-\-warn**) flags were not given on the command line, the max allowable value
+for **ibase** is **36**. Otherwise, it is **16**. The min allowable value for
+**ibase** is **2**. The max allowable value for **ibase** can be queried in
+bc(1) programs with the **maxibase()** built-in function.
+
+**obase** is a global variable determining how to output results. It is the
+"output" base, or the number base used for outputting numbers. **obase** is
+initially **10**. The max allowable value for **obase** is **BC_BASE_MAX** and
+can be queried in bc(1) programs with the **maxobase()** built-in function. The
+{{ A H N HN }}
+min allowable value for **obase** is **0**. If **obase** is **0**, values are
+output in scientific notation, and if **obase** is **1**, values are output in
+engineering notation. Otherwise, values are output in the specified base.
+
+Outputting in scientific and engineering notations are **non-portable
+extensions**.
+{{ end }}
+{{ E EH EN EHN }}
+min allowable value for **obase** is **2**. Values are output in the specified
+base.
+{{ end }}
+
+The *scale* of an expression is the number of digits in the result of the
+expression right of the decimal point, and **scale** is a global variable that
+sets the precision of any operations, with exceptions. **scale** is initially
+**0**. **scale** cannot be negative. The max allowable value for **scale** is
+**BC_SCALE_MAX** and can be queried in bc(1) programs with the **maxscale()**
+built-in function.
+
+bc(1) has both *global* variables and *local* variables. All *local*
+variables are local to the function; they are parameters or are introduced in
+the **auto** list of a function (see the **FUNCTIONS** section). If a variable
+is accessed which is not a parameter or in the **auto** list, it is assumed to
+be *global*. If a parent function has a *local* variable version of a variable
+that a child function considers *global*, the value of that *global* variable in
+the child function is the value of the variable in the parent function, not the
+value of the actual *global* variable.
+
+All of the above applies to arrays as well.
+
+The value of a statement that is an expression (i.e., any of the named
+expressions or operands) is printed unless the lowest precedence operator is an
+assignment operator *and* the expression is notsurrounded by parentheses.
+
+The value that is printed is also assigned to the special variable **last**. A
+single dot (**.**) may also be used as a synonym for **last**. These are
+**non-portable extensions**.
+
+Either semicolons or newlines may separate statements.
+
+## Comments
+
+There are two kinds of comments:
+
+1. Block comments are enclosed in **/\*** and **\*/**.
+2. Line comments go from **#** until, and not including, the next newline. This
+ is a **non-portable extension**.
+
+## Named Expressions
+
+The following are named expressions in bc(1):
+
+1. Variables: **I**
+2. Array Elements: **I[E]**
+3. **ibase**
+4. **obase**
+5. **scale**
+{{ A H N HN }}
+6. **seed**
+7. **last** or a single dot (**.**)
+
+Numbers 6 and 7 are **non-portable extensions**.
+
+The meaning of **seed** is dependent on the current pseudo-random number
+generator but is guaranteed to not change except for new major versions.
+
+The *scale* and sign of the value may be significant.
+
+If a previously used **seed** value is assigned to **seed** and used again, the
+pseudo-random number generator is guaranteed to produce the same sequence of
+pseudo-random numbers as it did when the **seed** value was previously used.
+
+The exact value assigned to **seed** is not guaranteed to be returned if
+**seed** is queried again immediately. However, if **seed** *does* return a
+different value, both values, when assigned to **seed**, are guaranteed to
+produce the same sequence of pseudo-random numbers. This means that certain
+values assigned to **seed** will *not* produce unique sequences of pseudo-random
+numbers. The value of **seed** will change after any use of the **rand()** and
+**irand(E)** operands (see the *Operands* subsection below), except if the
+parameter passed to **irand(E)** is **0**, **1**, or negative.
+
+There is no limit to the length (number of significant decimal digits) or
+*scale* of the value that can be assigned to **seed**.
+{{ end }}
+{{ E EH EN EHN }}
+6. **last** or a single dot (**.**)
+
+Number 6 is a **non-portable extension**.
+{{ end }}
+
+Variables and arrays do not interfere; users can have arrays named the same as
+variables. This also applies to functions (see the **FUNCTIONS** section), so a
+user can have a variable, array, and function that all have the same name, and
+they will not shadow each other, whether inside of functions or not.
+
+Named expressions are required as the operand of **increment**/**decrement**
+operators and as the left side of **assignment** operators (see the *Operators*
+subsection).
+
+## Operands
+
+The following are valid operands in bc(1):
+
+1. Numbers (see the *Numbers* subsection below).
+2. Array indices (**I[E]**).
+3. **(E)**: The value of **E** (used to change precedence).
+4. **sqrt(E)**: The square root of **E**. **E** must be non-negative.
+5. **length(E)**: The number of significant decimal digits in **E**. Returns
+ **1** for **0** with no decimal places. If given a string, the length of the
+ string is returned. Passing a string to **length(E)** is a **non-portable
+ extension**.
+6. **length(I[])**: The number of elements in the array **I**. This is a
+ **non-portable extension**.
+7. **scale(E)**: The *scale* of **E**.
+8. **abs(E)**: The absolute value of **E**. This is a **non-portable
+ extension**.
+9. **modexp(E, E, E)**: Modular exponentiation, where the first expression is
+ the base, the second is the exponent, and the third is the modulus. All
+ three values must be integers. The second argument must be non-negative. The
+ third argument must be non-zero. This is a **non-portable extension**.
+10. **divmod(E, E, I[])**: Division and modulus in one operation. This is for
+ optimization. The first expression is the dividend, and the second is the
+ divisor, which must be non-zero. The return value is the quotient, and the
+ modulus is stored in index **0** of the provided array (the last argument).
+ This is a **non-portable extension**.
+11. **asciify(E)**: If **E** is a string, returns a string that is the first
+ letter of its argument. If it is a number, calculates the number mod **256**
+ and returns that number as a one-character string. This is a **non-portable
+ extension**.
+12. **I()**, **I(E)**, **I(E, E)**, and so on, where **I** is an identifier for
+ a non-**void** function (see the *Void Functions* subsection of the
+ **FUNCTIONS** section). The **E** argument(s) may also be arrays of the form
+ **I[]**, which will automatically be turned into array references (see the
+ *Array References* subsection of the **FUNCTIONS** section) if the
+ corresponding parameter in the function definition is an array reference.
+13. **read()**: Reads a line from **stdin** and uses that as an expression. The
+ result of that expression is the result of the **read()** operand. This is a
+ **non-portable extension**.
+14. **maxibase()**: The max allowable **ibase**. This is a **non-portable
+ extension**.
+15. **maxobase()**: The max allowable **obase**. This is a **non-portable
+ extension**.
+16. **maxscale()**: The max allowable **scale**. This is a **non-portable
+ extension**.
+17. **line_length()**: The line length set with **BC_LINE_LENGTH** (see the
+ **ENVIRONMENT VARIABLES** section). This is a **non-portable extension**.
+18. **global_stacks()**: **0** if global stacks are not enabled with the **-g**
+ or **-\-global-stacks** options, non-zero otherwise. See the **OPTIONS**
+ section. This is a **non-portable extension**.
+19. **leading_zero()**: **0** if leading zeroes are not enabled with the **-z**
+ or **--leading-zeroes** options, non-zero otherwise. See the **OPTIONS**
+ section. This is a **non-portable extension**.
+{{ A H N HN }}
+20. **rand()**: A pseudo-random integer between **0** (inclusive) and
+ **BC_RAND_MAX** (inclusive). Using this operand will change the value of
+ **seed**. This is a **non-portable extension**.
+21. **irand(E)**: A pseudo-random integer between **0** (inclusive) and the
+ value of **E** (exclusive). If **E** is negative or is a non-integer
+ (**E**'s *scale* is not **0**), an error is raised, and bc(1) resets (see
+ the **RESET** section) while **seed** remains unchanged. If **E** is larger
+ than **BC_RAND_MAX**, the higher bound is honored by generating several
+ pseudo-random integers, multiplying them by appropriate powers of
+ **BC_RAND_MAX+1**, and adding them together. Thus, the size of integer that
+ can be generated with this operand is unbounded. Using this operand will
+ change the value of **seed**, unless the value of **E** is **0** or **1**.
+ In that case, **0** is returned, and **seed** is *not* changed. This is a
+ **non-portable extension**.
+22. **maxrand()**: The max integer returned by **rand()**. This is a
+ **non-portable extension**.
+
+The integers generated by **rand()** and **irand(E)** are guaranteed to be as
+unbiased as possible, subject to the limitations of the pseudo-random number
+generator.
+
+**Note**: The values returned by the pseudo-random number generator with
+**rand()** and **irand(E)** are guaranteed to *NOT* be cryptographically secure.
+This is a consequence of using a seeded pseudo-random number generator. However,
+they *are* guaranteed to be reproducible with identical **seed** values. This
+means that the pseudo-random values from bc(1) should only be used where a
+reproducible stream of pseudo-random numbers is *ESSENTIAL*. In any other case,
+use a non-seeded pseudo-random number generator.
+{{ end }}
+
+## Numbers
+
+Numbers are strings made up of digits, uppercase letters, and at most **1**
+period for a radix. Numbers can have up to **BC_NUM_MAX** digits. Uppercase
+letters are equal to **9** + their position in the alphabet (i.e., **A** equals
+**10**, or **9+1**). If a digit or letter makes no sense with the current value
+of **ibase**, they are set to the value of the highest valid digit in **ibase**.
+
+Single-character numbers (i.e., **A** alone) take the value that they would have
+if they were valid digits, regardless of the value of **ibase**. This means that
+**A** alone always equals decimal **10** and **Z** alone always equals decimal
+**35**.
+
+{{ A H N HN }}
+In addition, bc(1) accepts numbers in scientific notation. These have the form
+**\<number\>e\<integer\>**. The exponent (the portion after the **e**) must be
+an integer. An example is **1.89237e9**, which is equal to **1892370000**.
+Negative exponents are also allowed, so **4.2890e-3** is equal to **0.0042890**.
+
+Using scientific notation is an error or warning if the **-s** or **-w**,
+respectively, command-line options (or equivalents) are given.
+
+**WARNING**: Both the number and the exponent in scientific notation are
+interpreted according to the current **ibase**, but the number is still
+multiplied by **10\^exponent** regardless of the current **ibase**. For example,
+if **ibase** is **16** and bc(1) is given the number string **FFeA**, the
+resulting decimal number will be **2550000000000**, and if bc(1) is given the
+number string **10e-4**, the resulting decimal number will be **0.0016**.
+
+Accepting input as scientific notation is a **non-portable extension**.
+{{ end }}
+
+## Operators
+
+The following arithmetic and logical operators can be used. They are listed in
+order of decreasing precedence. Operators in the same group have the same
+precedence.
+
+**++** **-\-**
+
+: Type: Prefix and Postfix
+
+ Associativity: None
+
+ Description: **increment**, **decrement**
+
+**-** **!**
+
+: Type: Prefix
+
+ Associativity: None
+
+ Description: **negation**, **boolean not**
+
+{{ A H N HN }}
+**\$**
+
+: Type: Postfix
+
+ Associativity: None
+
+ Description: **truncation**
+
+**\@**
+
+: Type: Binary
+
+ Associativity: Right
+
+ Description: **set precision**
+{{ end }}
+
+**\^**
+
+: Type: Binary
+
+ Associativity: Right
+
+ Description: **power**
+
+**\*** **/** **%**
+
+: Type: Binary
+
+ Associativity: Left
+
+ Description: **multiply**, **divide**, **modulus**
+
+**+** **-**
+
+: Type: Binary
+
+ Associativity: Left
+
+ Description: **add**, **subtract**
+
+{{ A H N HN }}
+**\<\<** **\>\>**
+
+: Type: Binary
+
+ Associativity: Left
+
+ Description: **shift left**, **shift right**
+
+**=** **\<\<=** **\>\>=** **+=** **-=** **\*=** **/=** **%=** **\^=** **\@=**
+{{ end }}
+{{ E EH EN EHN }}
+**=** **+=** **-=** **\*=** **/=** **%=** **\^=**
+{{ end }}
+
+: Type: Binary
+
+ Associativity: Right
+
+ Description: **assignment**
+
+**==** **\<=** **\>=** **!=** **\<** **\>**
+
+: Type: Binary
+
+ Associativity: Left
+
+ Description: **relational**
+
+**&&**
+
+: Type: Binary
+
+ Associativity: Left
+
+ Description: **boolean and**
+
+**||**
+
+: Type: Binary
+
+ Associativity: Left
+
+ Description: **boolean or**
+
+The operators will be described in more detail below.
+
+**++** **-\-**
+
+: The prefix and postfix **increment** and **decrement** operators behave
+ exactly like they would in C. They require a named expression (see the
+ *Named Expressions* subsection) as an operand.
+
+ The prefix versions of these operators are more efficient; use them where
+ possible.
+
+**-**
+
+: The **negation** operator returns **0** if a user attempts to negate any
+ expression with the value **0**. Otherwise, a copy of the expression with
+ its sign flipped is returned.
+
+**!**
+
+: The **boolean not** operator returns **1** if the expression is **0**, or
+ **0** otherwise.
+
+ This is a **non-portable extension**.
+
+{{ A H N HN }}
+**\$**
+
+: The **truncation** operator returns a copy of the given expression with all
+ of its *scale* removed.
+
+ This is a **non-portable extension**.
+
+**\@**
+
+: The **set precision** operator takes two expressions and returns a copy of
+ the first with its *scale* equal to the value of the second expression. That
+ could either mean that the number is returned without change (if the
+ *scale* of the first expression matches the value of the second
+ expression), extended (if it is less), or truncated (if it is more).
+
+ The second expression must be an integer (no *scale*) and non-negative.
+
+ This is a **non-portable extension**.
+{{ end }}
+
+**\^**
+
+: The **power** operator (not the **exclusive or** operator, as it would be in
+ C) takes two expressions and raises the first to the power of the value of
+ the second. The *scale* of the result is equal to **scale**.
+
+ The second expression must be an integer (no *scale*), and if it is
+ negative, the first value must be non-zero.
+
+**\***
+
+: The **multiply** operator takes two expressions, multiplies them, and
+ returns the product. If **a** is the *scale* of the first expression and
+ **b** is the *scale* of the second expression, the *scale* of the result is
+ equal to **min(a+b,max(scale,a,b))** where **min()** and **max()** return
+ the obvious values.
+
+**/**
+
+: The **divide** operator takes two expressions, divides them, and returns the
+ quotient. The *scale* of the result shall be the value of **scale**.
+
+ The second expression must be non-zero.
+
+**%**
+
+: The **modulus** operator takes two expressions, **a** and **b**, and
+ evaluates them by 1) Computing **a/b** to current **scale** and 2) Using the
+ result of step 1 to calculate **a-(a/b)\*b** to *scale*
+ **max(scale+scale(b),scale(a))**.
+
+ The second expression must be non-zero.
+
+**+**
+
+: The **add** operator takes two expressions, **a** and **b**, and returns the
+ sum, with a *scale* equal to the max of the *scale*s of **a** and **b**.
+
+**-**
+
+: The **subtract** operator takes two expressions, **a** and **b**, and
+ returns the difference, with a *scale* equal to the max of the *scale*s of
+ **a** and **b**.
+
+{{ A H N HN }}
+**\<\<**
+
+: The **left shift** operator takes two expressions, **a** and **b**, and
+ returns a copy of the value of **a** with its decimal point moved **b**
+ places to the right.
+
+ The second expression must be an integer (no *scale*) and non-negative.
+
+ This is a **non-portable extension**.
+
+**\>\>**
+
+: The **right shift** operator takes two expressions, **a** and **b**, and
+ returns a copy of the value of **a** with its decimal point moved **b**
+ places to the left.
+
+ The second expression must be an integer (no *scale*) and non-negative.
+
+ This is a **non-portable extension**.
+{{ end }}
+
+{{ A H N HN }}
+**=** **\<\<=** **\>\>=** **+=** **-=** **\*=** **/=** **%=** **\^=** **\@=**
+{{ end }}
+{{ E EH EN EHN }}
+**=** **+=** **-=** **\*=** **/=** **%=** **\^=**
+{{ end }}
+
+: The **assignment** operators take two expressions, **a** and **b** where
+ **a** is a named expression (see the *Named Expressions* subsection).
+
+ For **=**, **b** is copied and the result is assigned to **a**. For all
+ others, **a** and **b** are applied as operands to the corresponding
+ arithmetic operator and the result is assigned to **a**.
+
+{{ A H N HN }}
+ The **assignment** operators that correspond to operators that are
+ extensions are themselves **non-portable extensions**.
+{{ end }}
+
+**==** **\<=** **\>=** **!=** **\<** **\>**
+
+: The **relational** operators compare two expressions, **a** and **b**, and
+ if the relation holds, according to C language semantics, the result is
+ **1**. Otherwise, it is **0**.
+
+ Note that unlike in C, these operators have a lower precedence than the
+ **assignment** operators, which means that **a=b\>c** is interpreted as
+ **(a=b)\>c**.
+
+ Also, unlike the [standard][1] requires, these operators can appear anywhere
+ any other expressions can be used. This allowance is a
+ **non-portable extension**.
+
+**&&**
+
+: The **boolean and** operator takes two expressions and returns **1** if both
+ expressions are non-zero, **0** otherwise.
+
+ This is *not* a short-circuit operator.
+
+ This is a **non-portable extension**.
+
+**||**
+
+: The **boolean or** operator takes two expressions and returns **1** if one
+ of the expressions is non-zero, **0** otherwise.
+
+ This is *not* a short-circuit operator.
+
+ This is a **non-portable extension**.
+
+## Statements
+
+The following items are statements:
+
+1. **E**
+2. **{** **S** **;** ... **;** **S** **}**
+3. **if** **(** **E** **)** **S**
+4. **if** **(** **E** **)** **S** **else** **S**
+5. **while** **(** **E** **)** **S**
+6. **for** **(** **E** **;** **E** **;** **E** **)** **S**
+7. An empty statement
+8. **break**
+9. **continue**
+10. **quit**
+11. **halt**
+12. **limits**
+13. A string of characters, enclosed in double quotes
+14. **print** **E** **,** ... **,** **E**
+15. **stream** **E** **,** ... **,** **E**
+16. **I()**, **I(E)**, **I(E, E)**, and so on, where **I** is an identifier for
+ a **void** function (see the *Void Functions* subsection of the
+ **FUNCTIONS** section). The **E** argument(s) may also be arrays of the form
+ **I[]**, which will automatically be turned into array references (see the
+ *Array References* subsection of the **FUNCTIONS** section) if the
+ corresponding parameter in the function definition is an array reference.
+
+Numbers 4, 9, 11, 12, 14, 15, and 16 are **non-portable extensions**.
+
+Also, as a **non-portable extension**, any or all of the expressions in the
+header of a for loop may be omitted. If the condition (second expression) is
+omitted, it is assumed to be a constant **1**.
+
+The **break** statement causes a loop to stop iterating and resume execution
+immediately following a loop. This is only allowed in loops.
+
+The **continue** statement causes a loop iteration to stop early and returns to
+the start of the loop, including testing the loop condition. This is only
+allowed in loops.
+
+The **if** **else** statement does the same thing as in C.
+
+The **quit** statement causes bc(1) to quit, even if it is on a branch that will
+not be executed (it is a compile-time command).
+
+The **halt** statement causes bc(1) to quit, if it is executed. (Unlike **quit**
+if it is on a branch of an **if** statement that is not executed, bc(1) does not
+quit.)
+
+The **limits** statement prints the limits that this bc(1) is subject to. This
+is like the **quit** statement in that it is a compile-time command.
+
+An expression by itself is evaluated and printed, followed by a newline.
+
+{{ A H N HN }}
+Both scientific notation and engineering notation are available for printing the
+results of expressions. Scientific notation is activated by assigning **0** to
+**obase**, and engineering notation is activated by assigning **1** to
+**obase**. To deactivate them, just assign a different value to **obase**.
+
+Scientific notation and engineering notation are disabled if bc(1) is run with
+either the **-s** or **-w** command-line options (or equivalents).
+
+Printing numbers in scientific notation and/or engineering notation is a
+**non-portable extension**.
+{{ end }}
+
+## Strings
+
+If strings appear as a statement by themselves, they are printed without a
+trailing newline.
+
+In addition to appearing as a lone statement by themselves, strings can be
+assigned to variables and array elements. They can also be passed to functions
+in variable parameters.
+
+If any statement that expects a string is given a variable that had a string
+assigned to it, the statement acts as though it had received a string.
+
+If any math operation is attempted on a string or a variable or array element
+that has been assigned a string, an error is raised, and bc(1) resets (see the
+**RESET** section).
+
+Assigning strings to variables and array elements and passing them to functions
+are **non-portable extensions**.
+
+## Print Statement
+
+The "expressions" in a **print** statement may also be strings. If they are, there
+are backslash escape sequences that are interpreted specially. What those
+sequences are, and what they cause to be printed, are shown below:
+
+**\\a**: **\\a**
+
+**\\b**: **\\b**
+
+**\\\\**: **\\**
+
+**\\e**: **\\**
+
+**\\f**: **\\f**
+
+**\\n**: **\\n**
+
+**\\q**: **"**
+
+**\\r**: **\\r**
+
+**\\t**: **\\t**
+
+Any other character following a backslash causes the backslash and character to
+be printed as-is.
+
+Any non-string expression in a print statement shall be assigned to **last**,
+like any other expression that is printed.
+
+## Stream Statement
+
+The "expressions in a **stream** statement may also be strings.
+
+If a **stream** statement is given a string, it prints the string as though the
+string had appeared as its own statement. In other words, the **stream**
+statement prints strings normally, without a newline.
+
+If a **stream** statement is given a number, a copy of it is truncated and its
+absolute value is calculated. The result is then printed as though **obase** is
+**256** and each digit is interpreted as an 8-bit ASCII character, making it a
+byte stream.
+
+## Order of Evaluation
+
+All expressions in a statment are evaluated left to right, except as necessary
+to maintain order of operations. This means, for example, assuming that **i** is
+equal to **0**, in the expression
+
+ a[i++] = i++
+
+the first (or 0th) element of **a** is set to **1**, and **i** is equal to **2**
+at the end of the expression.
+
+This includes function arguments. Thus, assuming **i** is equal to **0**, this
+means that in the expression
+
+ x(i++, i++)
+
+the first argument passed to **x()** is **0**, and the second argument is **1**,
+while **i** is equal to **2** before the function starts executing.
+
+# FUNCTIONS
+
+Function definitions are as follows:
+
+```
+define I(I,...,I){
+ auto I,...,I
+ S;...;S
+ return(E)
+}
+```
+
+Any **I** in the parameter list or **auto** list may be replaced with **I[]** to
+make a parameter or **auto** var an array, and any **I** in the parameter list
+may be replaced with **\*I[]** to make a parameter an array reference. Callers
+of functions that take array references should not put an asterisk in the call;
+they must be called with just **I[]** like normal array parameters and will be
+automatically converted into references.
+
+As a **non-portable extension**, the opening brace of a **define** statement may
+appear on the next line.
+
+As a **non-portable extension**, the return statement may also be in one of the
+following forms:
+
+1. **return**
+2. **return** **(** **)**
+3. **return** **E**
+
+The first two, or not specifying a **return** statement, is equivalent to
+**return (0)**, unless the function is a **void** function (see the *Void
+Functions* subsection below).
+
+## Void Functions
+
+Functions can also be **void** functions, defined as follows:
+
+```
+define void I(I,...,I){
+ auto I,...,I
+ S;...;S
+ return
+}
+```
+
+They can only be used as standalone expressions, where such an expression would
+be printed alone, except in a print statement.
+
+Void functions can only use the first two **return** statements listed above.
+They can also omit the return statement entirely.
+
+The word "void" is not treated as a keyword; it is still possible to have
+variables, arrays, and functions named **void**. The word "void" is only
+treated specially right after the **define** keyword.
+
+This is a **non-portable extension**.
+
+## Array References
+
+For any array in the parameter list, if the array is declared in the form
+
+```
+*I[]
+```
+
+it is a **reference**. Any changes to the array in the function are reflected,
+when the function returns, to the array that was passed in.
+
+Other than this, all function arguments are passed by value.
+
+This is a **non-portable extension**.
+
+# LIBRARY
+
+{{ A H N HN }}
+All of the functions below, including the functions in the extended math
+library (see the *Extended Library* subsection below), are available when the
+**-l** or **-\-mathlib** command-line flags are given, except that the extended
+math library is not available when the **-s** option, the **-w** option, or
+equivalents are given.
+{{ end }}
+{{ E EH EN EHN }}
+All of the functions below are available when the **-l** or **-\-mathlib**
+command-line flags are given.
+{{ end }}
+
+## Standard Library
+
+The [standard][1] defines the following functions for the math library:
+
+**s(x)**
+
+: Returns the sine of **x**, which is assumed to be in radians.
+
+ This is a transcendental function (see the *Transcendental Functions*
+ subsection below).
+
+**c(x)**
+
+: Returns the cosine of **x**, which is assumed to be in radians.
+
+ This is a transcendental function (see the *Transcendental Functions*
+ subsection below).
+
+**a(x)**
+
+: Returns the arctangent of **x**, in radians.
+
+ This is a transcendental function (see the *Transcendental Functions*
+ subsection below).
+
+**l(x)**
+
+: Returns the natural logarithm of **x**.
+
+ This is a transcendental function (see the *Transcendental Functions*
+ subsection below).
+
+**e(x)**
+
+: Returns the mathematical constant **e** raised to the power of **x**.
+
+ This is a transcendental function (see the *Transcendental Functions*
+ subsection below).
+
+**j(x, n)**
+
+: Returns the bessel integer order **n** (truncated) of **x**.
+
+ This is a transcendental function (see the *Transcendental Functions*
+ subsection below).
+
+{{ A H N HN }}
+## Extended Library
+
+The extended library is *not* loaded when the **-s**/**-\-standard** or
+**-w**/**-\-warn** options are given since they are not part of the library
+defined by the [standard][1].
+
+The extended library is a **non-portable extension**.
+
+**p(x, y)**
+
+: Calculates **x** to the power of **y**, even if **y** is not an integer, and
+ returns the result to the current **scale**.
+
+ It is an error if **y** is negative and **x** is **0**.
+
+ This is a transcendental function (see the *Transcendental Functions*
+ subsection below).
+
+**r(x, p)**
+
+: Returns **x** rounded to **p** decimal places according to the rounding mode
+ [round half away from **0**][3].
+
+**ceil(x, p)**
+
+: Returns **x** rounded to **p** decimal places according to the rounding mode
+ [round away from **0**][6].
+
+**f(x)**
+
+: Returns the factorial of the truncated absolute value of **x**.
+
+**perm(n, k)**
+
+: Returns the permutation of the truncated absolute value of **n** of the
+ truncated absolute value of **k**, if **k \<= n**. If not, it returns **0**.
+
+**comb(n, k)**
+
+: Returns the combination of the truncated absolute value of **n** of the
+ truncated absolute value of **k**, if **k \<= n**. If not, it returns **0**.
+
+**l2(x)**
+
+: Returns the logarithm base **2** of **x**.
+
+ This is a transcendental function (see the *Transcendental Functions*
+ subsection below).
+
+**l10(x)**
+
+: Returns the logarithm base **10** of **x**.
+
+ This is a transcendental function (see the *Transcendental Functions*
+ subsection below).
+
+**log(x, b)**
+
+: Returns the logarithm base **b** of **x**.
+
+ This is a transcendental function (see the *Transcendental Functions*
+ subsection below).
+
+**cbrt(x)**
+
+: Returns the cube root of **x**.
+
+**root(x, n)**
+
+: Calculates the truncated value of **n**, **r**, and returns the **r**th root
+ of **x** to the current **scale**.
+
+ If **r** is **0** or negative, this raises an error and causes bc(1) to
+ reset (see the **RESET** section). It also raises an error and causes bc(1)
+ to reset if **r** is even and **x** is negative.
+
+**gcd(a, b)**
+
+: Returns the greatest common divisor (factor) of the truncated absolute value
+ of **a** and the truncated absolute value of **b**.
+
+**lcm(a, b)**
+
+: Returns the least common multiple of the truncated absolute value of **a**
+ and the truncated absolute value of **b**.
+
+**pi(p)**
+
+: Returns **pi** to **p** decimal places.
+
+ This is a transcendental function (see the *Transcendental Functions*
+ subsection below).
+
+**t(x)**
+
+: Returns the tangent of **x**, which is assumed to be in radians.
+
+ This is a transcendental function (see the *Transcendental Functions*
+ subsection below).
+
+**a2(y, x)**
+
+: Returns the arctangent of **y/x**, in radians. If both **y** and **x** are
+ equal to **0**, it raises an error and causes bc(1) to reset (see the
+ **RESET** section). Otherwise, if **x** is greater than **0**, it returns
+ **a(y/x)**. If **x** is less than **0**, and **y** is greater than or equal
+ to **0**, it returns **a(y/x)+pi**. If **x** is less than **0**, and **y**
+ is less than **0**, it returns **a(y/x)-pi**. If **x** is equal to **0**,
+ and **y** is greater than **0**, it returns **pi/2**. If **x** is equal to
+ **0**, and **y** is less than **0**, it returns **-pi/2**.
+
+ This function is the same as the **atan2()** function in many programming
+ languages.
+
+ This is a transcendental function (see the *Transcendental Functions*
+ subsection below).
+
+**sin(x)**
+
+: Returns the sine of **x**, which is assumed to be in radians.
+
+ This is an alias of **s(x)**.
+
+ This is a transcendental function (see the *Transcendental Functions*
+ subsection below).
+
+**cos(x)**
+
+: Returns the cosine of **x**, which is assumed to be in radians.
+
+ This is an alias of **c(x)**.
+
+ This is a transcendental function (see the *Transcendental Functions*
+ subsection below).
+
+**tan(x)**
+
+: Returns the tangent of **x**, which is assumed to be in radians.
+
+ If **x** is equal to **1** or **-1**, this raises an error and causes bc(1)
+ to reset (see the **RESET** section).
+
+ This is an alias of **t(x)**.
+
+ This is a transcendental function (see the *Transcendental Functions*
+ subsection below).
+
+**atan(x)**
+
+: Returns the arctangent of **x**, in radians.
+
+ This is an alias of **a(x)**.
+
+ This is a transcendental function (see the *Transcendental Functions*
+ subsection below).
+
+**atan2(y, x)**
+
+: Returns the arctangent of **y/x**, in radians. If both **y** and **x** are
+ equal to **0**, it raises an error and causes bc(1) to reset (see the
+ **RESET** section). Otherwise, if **x** is greater than **0**, it returns
+ **a(y/x)**. If **x** is less than **0**, and **y** is greater than or equal
+ to **0**, it returns **a(y/x)+pi**. If **x** is less than **0**, and **y**
+ is less than **0**, it returns **a(y/x)-pi**. If **x** is equal to **0**,
+ and **y** is greater than **0**, it returns **pi/2**. If **x** is equal to
+ **0**, and **y** is less than **0**, it returns **-pi/2**.
+
+ This function is the same as the **atan2()** function in many programming
+ languages.
+
+ This is an alias of **a2(y, x)**.
+
+ This is a transcendental function (see the *Transcendental Functions*
+ subsection below).
+
+**r2d(x)**
+
+: Converts **x** from radians to degrees and returns the result.
+
+ This is a transcendental function (see the *Transcendental Functions*
+ subsection below).
+
+**d2r(x)**
+
+: Converts **x** from degrees to radians and returns the result.
+
+ This is a transcendental function (see the *Transcendental Functions*
+ subsection below).
+
+**frand(p)**
+
+: Generates a pseudo-random number between **0** (inclusive) and **1**
+ (exclusive) with the number of decimal digits after the decimal point equal
+ to the truncated absolute value of **p**. If **p** is not **0**, then
+ calling this function will change the value of **seed**. If **p** is **0**,
+ then **0** is returned, and **seed** is *not* changed.
+
+**ifrand(i, p)**
+
+: Generates a pseudo-random number that is between **0** (inclusive) and the
+ truncated absolute value of **i** (exclusive) with the number of decimal
+ digits after the decimal point equal to the truncated absolute value of
+ **p**. If the absolute value of **i** is greater than or equal to **2**, and
+ **p** is not **0**, then calling this function will change the value of
+ **seed**; otherwise, **0** is returned and **seed** is not changed.
+
+**srand(x)**
+
+: Returns **x** with its sign flipped with probability **0.5**. In other
+ words, it randomizes the sign of **x**.
+
+**brand()**
+
+: Returns a random boolean value (either **0** or **1**).
+
+**band(a, b)**
+
+: Takes the truncated absolute value of both **a** and **b** and calculates
+ and returns the result of the bitwise **and** operation between them.
+
+ If you want to use signed two's complement arguments, use **s2u(x)** to
+ convert.
+
+**bor(a, b)**
+
+: Takes the truncated absolute value of both **a** and **b** and calculates
+ and returns the result of the bitwise **or** operation between them.
+
+ If you want to use signed two's complement arguments, use **s2u(x)** to
+ convert.
+
+**bxor(a, b)**
+
+: Takes the truncated absolute value of both **a** and **b** and calculates
+ and returns the result of the bitwise **xor** operation between them.
+
+ If you want to use signed two's complement arguments, use **s2u(x)** to
+ convert.
+
+**bshl(a, b)**
+
+: Takes the truncated absolute value of both **a** and **b** and calculates
+ and returns the result of **a** bit-shifted left by **b** places.
+
+ If you want to use signed two's complement arguments, use **s2u(x)** to
+ convert.
+
+**bshr(a, b)**
+
+: Takes the truncated absolute value of both **a** and **b** and calculates
+ and returns the truncated result of **a** bit-shifted right by **b** places.
+
+ If you want to use signed two's complement arguments, use **s2u(x)** to
+ convert.
+
+**bnotn(x, n)**
+
+: Takes the truncated absolute value of **x** and does a bitwise not as though
+ it has the same number of bytes as the truncated absolute value of **n**.
+
+ If you want to a use signed two's complement argument, use **s2u(x)** to
+ convert.
+
+**bnot8(x)**
+
+: Does a bitwise not of the truncated absolute value of **x** as though it has
+ **8** binary digits (1 unsigned byte).
+
+ If you want to a use signed two's complement argument, use **s2u(x)** to
+ convert.
+
+**bnot16(x)**
+
+: Does a bitwise not of the truncated absolute value of **x** as though it has
+ **16** binary digits (2 unsigned bytes).
+
+ If you want to a use signed two's complement argument, use **s2u(x)** to
+ convert.
+
+**bnot32(x)**
+
+: Does a bitwise not of the truncated absolute value of **x** as though it has
+ **32** binary digits (4 unsigned bytes).
+
+ If you want to a use signed two's complement argument, use **s2u(x)** to
+ convert.
+
+**bnot64(x)**
+
+: Does a bitwise not of the truncated absolute value of **x** as though it has
+ **64** binary digits (8 unsigned bytes).
+
+ If you want to a use signed two's complement argument, use **s2u(x)** to
+ convert.
+
+**bnot(x)**
+
+: Does a bitwise not of the truncated absolute value of **x** as though it has
+ the minimum number of power of two unsigned bytes.
+
+ If you want to a use signed two's complement argument, use **s2u(x)** to
+ convert.
+
+**brevn(x, n)**
+
+: Runs a bit reversal on the truncated absolute value of **x** as though it
+ has the same number of 8-bit bytes as the truncated absolute value of **n**.
+
+ If you want to a use signed two's complement argument, use **s2u(x)** to
+ convert.
+
+**brev8(x)**
+
+: Runs a bit reversal on the truncated absolute value of **x** as though it
+ has 8 binary digits (1 unsigned byte).
+
+ If you want to a use signed two's complement argument, use **s2u(x)** to
+ convert.
+
+**brev16(x)**
+
+: Runs a bit reversal on the truncated absolute value of **x** as though it
+ has 16 binary digits (2 unsigned bytes).
+
+ If you want to a use signed two's complement argument, use **s2u(x)** to
+ convert.
+
+**brev32(x)**
+
+: Runs a bit reversal on the truncated absolute value of **x** as though it
+ has 32 binary digits (4 unsigned bytes).
+
+ If you want to a use signed two's complement argument, use **s2u(x)** to
+ convert.
+
+**brev64(x)**
+
+: Runs a bit reversal on the truncated absolute value of **x** as though it
+ has 64 binary digits (8 unsigned bytes).
+
+ If you want to a use signed two's complement argument, use **s2u(x)** to
+ convert.
+
+**brev(x)**
+
+: Runs a bit reversal on the truncated absolute value of **x** as though it
+ has the minimum number of power of two unsigned bytes.
+
+ If you want to a use signed two's complement argument, use **s2u(x)** to
+ convert.
+
+**broln(x, p, n)**
+
+: Does a left bitwise rotatation of the truncated absolute value of **x**, as
+ though it has the same number of unsigned 8-bit bytes as the truncated
+ absolute value of **n**, by the number of places equal to the truncated
+ absolute value of **p** modded by the **2** to the power of the number of
+ binary digits in **n** 8-bit bytes.
+
+ If you want to a use signed two's complement argument, use **s2u(x)** to
+ convert.
+
+**brol8(x, p)**
+
+: Does a left bitwise rotatation of the truncated absolute value of **x**, as
+ though it has **8** binary digits (**1** unsigned byte), by the number of
+ places equal to the truncated absolute value of **p** modded by **2** to the
+ power of **8**.
+
+ If you want to a use signed two's complement argument, use **s2u(x)** to
+ convert.
+
+**brol16(x, p)**
+
+: Does a left bitwise rotatation of the truncated absolute value of **x**, as
+ though it has **16** binary digits (**2** unsigned bytes), by the number of
+ places equal to the truncated absolute value of **p** modded by **2** to the
+ power of **16**.
+
+ If you want to a use signed two's complement argument, use **s2u(x)** to
+ convert.
+
+**brol32(x, p)**
+
+: Does a left bitwise rotatation of the truncated absolute value of **x**, as
+ though it has **32** binary digits (**2** unsigned bytes), by the number of
+ places equal to the truncated absolute value of **p** modded by **2** to the
+ power of **32**.
+
+ If you want to a use signed two's complement argument, use **s2u(x)** to
+ convert.
+
+**brol64(x, p)**
+
+: Does a left bitwise rotatation of the truncated absolute value of **x**, as
+ though it has **64** binary digits (**2** unsigned bytes), by the number of
+ places equal to the truncated absolute value of **p** modded by **2** to the
+ power of **64**.
+
+ If you want to a use signed two's complement argument, use **s2u(x)** to
+ convert.
+
+**brol(x, p)**
+
+: Does a left bitwise rotatation of the truncated absolute value of **x**, as
+ though it has the minimum number of power of two unsigned 8-bit bytes, by
+ the number of places equal to the truncated absolute value of **p** modded
+ by 2 to the power of the number of binary digits in the minimum number of
+ 8-bit bytes.
+
+ If you want to a use signed two's complement argument, use **s2u(x)** to
+ convert.
+
+**brorn(x, p, n)**
+
+: Does a right bitwise rotatation of the truncated absolute value of **x**, as
+ though it has the same number of unsigned 8-bit bytes as the truncated
+ absolute value of **n**, by the number of places equal to the truncated
+ absolute value of **p** modded by the **2** to the power of the number of
+ binary digits in **n** 8-bit bytes.
+
+ If you want to a use signed two's complement argument, use **s2u(x)** to
+ convert.
+
+**bror8(x, p)**
+
+: Does a right bitwise rotatation of the truncated absolute value of **x**, as
+ though it has **8** binary digits (**1** unsigned byte), by the number of
+ places equal to the truncated absolute value of **p** modded by **2** to the
+ power of **8**.
+
+ If you want to a use signed two's complement argument, use **s2u(x)** to
+ convert.
+
+**bror16(x, p)**
+
+: Does a right bitwise rotatation of the truncated absolute value of **x**, as
+ though it has **16** binary digits (**2** unsigned bytes), by the number of
+ places equal to the truncated absolute value of **p** modded by **2** to the
+ power of **16**.
+
+ If you want to a use signed two's complement argument, use **s2u(x)** to
+ convert.
+
+**bror32(x, p)**
+
+: Does a right bitwise rotatation of the truncated absolute value of **x**, as
+ though it has **32** binary digits (**2** unsigned bytes), by the number of
+ places equal to the truncated absolute value of **p** modded by **2** to the
+ power of **32**.
+
+ If you want to a use signed two's complement argument, use **s2u(x)** to
+ convert.
+
+**bror64(x, p)**
+
+: Does a right bitwise rotatation of the truncated absolute value of **x**, as
+ though it has **64** binary digits (**2** unsigned bytes), by the number of
+ places equal to the truncated absolute value of **p** modded by **2** to the
+ power of **64**.
+
+ If you want to a use signed two's complement argument, use **s2u(x)** to
+ convert.
+
+**bror(x, p)**
+
+: Does a right bitwise rotatation of the truncated absolute value of **x**, as
+ though it has the minimum number of power of two unsigned 8-bit bytes, by
+ the number of places equal to the truncated absolute value of **p** modded
+ by 2 to the power of the number of binary digits in the minimum number of
+ 8-bit bytes.
+
+ If you want to a use signed two's complement argument, use **s2u(x)** to
+ convert.
+
+**bmodn(x, n)**
+
+: Returns the modulus of the truncated absolute value of **x** by **2** to the
+ power of the multiplication of the truncated absolute value of **n** and
+ **8**.
+
+ If you want to a use signed two's complement argument, use **s2u(x)** to
+ convert.
+
+**bmod8(x, n)**
+
+: Returns the modulus of the truncated absolute value of **x** by **2** to the
+ power of **8**.
+
+ If you want to a use signed two's complement argument, use **s2u(x)** to
+ convert.
+
+**bmod16(x, n)**
+
+: Returns the modulus of the truncated absolute value of **x** by **2** to the
+ power of **16**.
+
+ If you want to a use signed two's complement argument, use **s2u(x)** to
+ convert.
+
+**bmod32(x, n)**
+
+: Returns the modulus of the truncated absolute value of **x** by **2** to the
+ power of **32**.
+
+ If you want to a use signed two's complement argument, use **s2u(x)** to
+ convert.
+
+**bmod64(x, n)**
+
+: Returns the modulus of the truncated absolute value of **x** by **2** to the
+ power of **64**.
+
+ If you want to a use signed two's complement argument, use **s2u(x)** to
+ convert.
+
+**bunrev(t)**
+
+: Assumes **t** is a bitwise-reversed number with an extra set bit one place
+ more significant than the real most significant bit (which was the least
+ significant bit in the original number). This number is reversed and
+ returned without the extra set bit.
+
+ This function is used to implement other bitwise functions; it is not meant
+ to be used by users, but it can be.
+
+**plz(x)**
+
+: If **x** is not equal to **0** and greater that **-1** and less than **1**,
+ it is printed with a leading zero, regardless of the use of the **-z**
+ option (see the **OPTIONS** section) and without a trailing newline.
+
+ Otherwise, **x** is printed normally, without a trailing newline.
+
+**plznl(x)**
+
+: If **x** is not equal to **0** and greater that **-1** and less than **1**,
+ it is printed with a leading zero, regardless of the use of the **-z**
+ option (see the **OPTIONS** section) and with a trailing newline.
+
+ Otherwise, **x** is printed normally, with a trailing newline.
+
+**pnlz(x)**
+
+: If **x** is not equal to **0** and greater that **-1** and less than **1**,
+ it is printed without a leading zero, regardless of the use of the **-z**
+ option (see the **OPTIONS** section) and without a trailing newline.
+
+ Otherwise, **x** is printed normally, without a trailing newline.
+
+**pnlznl(x)**
+
+: If **x** is not equal to **0** and greater that **-1** and less than **1**,
+ it is printed without a leading zero, regardless of the use of the **-z**
+ option (see the **OPTIONS** section) and with a trailing newline.
+
+ Otherwise, **x** is printed normally, with a trailing newline.
+
+**ubytes(x)**
+
+: Returns the numbers of unsigned integer bytes required to hold the truncated
+ absolute value of **x**.
+
+**sbytes(x)**
+
+: Returns the numbers of signed, two's-complement integer bytes required to
+ hold the truncated value of **x**.
+
+**s2u(x)**
+
+: Returns **x** if it is non-negative. If it *is* negative, then it calculates
+ what **x** would be as a 2's-complement signed integer and returns the
+ non-negative integer that would have the same representation in binary.
+
+**s2un(x,n)**
+
+: Returns **x** if it is non-negative. If it *is* negative, then it calculates
+ what **x** would be as a 2's-complement signed integer with **n** bytes and
+ returns the non-negative integer that would have the same representation in
+ binary. If **x** cannot fit into **n** 2's-complement signed bytes, it is
+ truncated to fit.
+
+**hex(x)**
+
+: Outputs the hexadecimal (base **16**) representation of **x**.
+
+ This is a **void** function (see the *Void Functions* subsection of the
+ **FUNCTIONS** section).
+
+**binary(x)**
+
+: Outputs the binary (base **2**) representation of **x**.
+
+ This is a **void** function (see the *Void Functions* subsection of the
+ **FUNCTIONS** section).
+
+**output(x, b)**
+
+: Outputs the base **b** representation of **x**.
+
+ This is a **void** function (see the *Void Functions* subsection of the
+ **FUNCTIONS** section).
+
+**uint(x)**
+
+: Outputs the representation, in binary and hexadecimal, of **x** as an
+ unsigned integer in as few power of two bytes as possible. Both outputs are
+ split into bytes separated by spaces.
+
+ If **x** is not an integer or is negative, an error message is printed
+ instead, but bc(1) is not reset (see the **RESET** section).
+
+ This is a **void** function (see the *Void Functions* subsection of the
+ **FUNCTIONS** section).
+
+**int(x)**
+
+: Outputs the representation, in binary and hexadecimal, of **x** as a signed,
+ two's-complement integer in as few power of two bytes as possible. Both
+ outputs are split into bytes separated by spaces.
+
+ If **x** is not an integer, an error message is printed instead, but bc(1)
+ is not reset (see the **RESET** section).
+
+ This is a **void** function (see the *Void Functions* subsection of the
+ **FUNCTIONS** section).
+
+**uintn(x, n)**
+
+: Outputs the representation, in binary and hexadecimal, of **x** as an
+ unsigned integer in **n** bytes. Both outputs are split into bytes separated
+ by spaces.
+
+ If **x** is not an integer, is negative, or cannot fit into **n** bytes, an
+ error message is printed instead, but bc(1) is not reset (see the **RESET**
+ section).
+
+ This is a **void** function (see the *Void Functions* subsection of the
+ **FUNCTIONS** section).
+
+**intn(x, n)**
+
+: Outputs the representation, in binary and hexadecimal, of **x** as a signed,
+ two's-complement integer in **n** bytes. Both outputs are split into bytes
+ separated by spaces.
+
+ If **x** is not an integer or cannot fit into **n** bytes, an error message
+ is printed instead, but bc(1) is not reset (see the **RESET** section).
+
+ This is a **void** function (see the *Void Functions* subsection of the
+ **FUNCTIONS** section).
+
+**uint8(x)**
+
+: Outputs the representation, in binary and hexadecimal, of **x** as an
+ unsigned integer in **1** byte. Both outputs are split into bytes separated
+ by spaces.
+
+ If **x** is not an integer, is negative, or cannot fit into **1** byte, an
+ error message is printed instead, but bc(1) is not reset (see the **RESET**
+ section).
+
+ This is a **void** function (see the *Void Functions* subsection of the
+ **FUNCTIONS** section).
+
+**int8(x)**
+
+: Outputs the representation, in binary and hexadecimal, of **x** as a signed,
+ two's-complement integer in **1** byte. Both outputs are split into bytes
+ separated by spaces.
+
+ If **x** is not an integer or cannot fit into **1** byte, an error message
+ is printed instead, but bc(1) is not reset (see the **RESET** section).
+
+ This is a **void** function (see the *Void Functions* subsection of the
+ **FUNCTIONS** section).
+
+**uint16(x)**
+
+: Outputs the representation, in binary and hexadecimal, of **x** as an
+ unsigned integer in **2** bytes. Both outputs are split into bytes separated
+ by spaces.
+
+ If **x** is not an integer, is negative, or cannot fit into **2** bytes, an
+ error message is printed instead, but bc(1) is not reset (see the **RESET**
+ section).
+
+ This is a **void** function (see the *Void Functions* subsection of the
+ **FUNCTIONS** section).
+
+**int16(x)**
+
+: Outputs the representation, in binary and hexadecimal, of **x** as a signed,
+ two's-complement integer in **2** bytes. Both outputs are split into bytes
+ separated by spaces.
+
+ If **x** is not an integer or cannot fit into **2** bytes, an error message
+ is printed instead, but bc(1) is not reset (see the **RESET** section).
+
+ This is a **void** function (see the *Void Functions* subsection of the
+ **FUNCTIONS** section).
+
+**uint32(x)**
+
+: Outputs the representation, in binary and hexadecimal, of **x** as an
+ unsigned integer in **4** bytes. Both outputs are split into bytes separated
+ by spaces.
+
+ If **x** is not an integer, is negative, or cannot fit into **4** bytes, an
+ error message is printed instead, but bc(1) is not reset (see the **RESET**
+ section).
+
+ This is a **void** function (see the *Void Functions* subsection of the
+ **FUNCTIONS** section).
+
+**int32(x)**
+
+: Outputs the representation, in binary and hexadecimal, of **x** as a signed,
+ two's-complement integer in **4** bytes. Both outputs are split into bytes
+ separated by spaces.
+
+ If **x** is not an integer or cannot fit into **4** bytes, an error message
+ is printed instead, but bc(1) is not reset (see the **RESET** section).
+
+ This is a **void** function (see the *Void Functions* subsection of the
+ **FUNCTIONS** section).
+
+**uint64(x)**
+
+: Outputs the representation, in binary and hexadecimal, of **x** as an
+ unsigned integer in **8** bytes. Both outputs are split into bytes separated
+ by spaces.
+
+ If **x** is not an integer, is negative, or cannot fit into **8** bytes, an
+ error message is printed instead, but bc(1) is not reset (see the **RESET**
+ section).
+
+ This is a **void** function (see the *Void Functions* subsection of the
+ **FUNCTIONS** section).
+
+**int64(x)**
+
+: Outputs the representation, in binary and hexadecimal, of **x** as a signed,
+ two's-complement integer in **8** bytes. Both outputs are split into bytes
+ separated by spaces.
+
+ If **x** is not an integer or cannot fit into **8** bytes, an error message
+ is printed instead, but bc(1) is not reset (see the **RESET** section).
+
+ This is a **void** function (see the *Void Functions* subsection of the
+ **FUNCTIONS** section).
+
+**hex_uint(x, n)**
+
+: Outputs the representation of the truncated absolute value of **x** as an
+ unsigned integer in hexadecimal using **n** bytes. Not all of the value will
+ be output if **n** is too small.
+
+ This is a **void** function (see the *Void Functions* subsection of the
+ **FUNCTIONS** section).
+
+**binary_uint(x, n)**
+
+: Outputs the representation of the truncated absolute value of **x** as an
+ unsigned integer in binary using **n** bytes. Not all of the value will be
+ output if **n** is too small.
+
+ This is a **void** function (see the *Void Functions* subsection of the
+ **FUNCTIONS** section).
+
+**output_uint(x, n)**
+
+: Outputs the representation of the truncated absolute value of **x** as an
+ unsigned integer in the current **obase** (see the **SYNTAX** section) using
+ **n** bytes. Not all of the value will be output if **n** is too small.
+
+ This is a **void** function (see the *Void Functions* subsection of the
+ **FUNCTIONS** section).
+
+**output_byte(x, i)**
+
+: Outputs byte **i** of the truncated absolute value of **x**, where **0** is
+ the least significant byte and **number_of_bytes - 1** is the most
+ significant byte.
+
+ This is a **void** function (see the *Void Functions* subsection of the
+ **FUNCTIONS** section).
+{{ end }}
+
+## Transcendental Functions
+
+All transcendental functions can return slightly inaccurate results (up to 1
+[ULP][4]). This is unavoidable, and [this article][5] explains why it is
+impossible and unnecessary to calculate exact results for the transcendental
+functions.
+
+Because of the possible inaccuracy, I recommend that users call those functions
+with the precision (**scale**) set to at least 1 higher than is necessary. If
+exact results are *absolutely* required, users can double the precision
+(**scale**) and then truncate.
+
+The transcendental functions in the standard math library are:
+
+* **s(x)**
+* **c(x)**
+* **a(x)**
+* **l(x)**
+* **e(x)**
+* **j(x, n)**
+
+{{ A H N HN }}
+The transcendental functions in the extended math library are:
+
+* **l2(x)**
+* **l10(x)**
+* **log(x, b)**
+* **pi(p)**
+* **t(x)**
+* **a2(y, x)**
+* **sin(x)**
+* **cos(x)**
+* **tan(x)**
+* **atan(x)**
+* **atan2(y, x)**
+* **r2d(x)**
+* **d2r(x)**
+{{ end }}
+
+# RESET
+
+When bc(1) encounters an error or a signal that it has a non-default handler
+for, it resets. This means that several things happen.
+
+First, any functions that are executing are stopped and popped off the stack.
+The behavior is not unlike that of exceptions in programming languages. Then
+the execution point is set so that any code waiting to execute (after all
+functions returned) is skipped.
+
+Thus, when bc(1) resets, it skips any remaining code waiting to be executed.
+Then, if it is interactive mode, and the error was not a fatal error (see the
+**EXIT STATUS** section), it asks for more input; otherwise, it exits with the
+appropriate return code.
+
+Note that this reset behavior is different from the GNU bc(1), which attempts to
+start executing the statement right after the one that caused an error.
+
+# PERFORMANCE
+
+Most bc(1) implementations use **char** types to calculate the value of **1**
+decimal digit at a time, but that can be slow. This bc(1) does something
+different.
+
+It uses large integers to calculate more than **1** decimal digit at a time. If
+built in a environment where **BC_LONG_BIT** (see the **LIMITS** section) is
+**64**, then each integer has **9** decimal digits. If built in an environment
+where **BC_LONG_BIT** is **32** then each integer has **4** decimal digits. This
+value (the number of decimal digits per large integer) is called
+**BC_BASE_DIGS**.
+
+The actual values of **BC_LONG_BIT** and **BC_BASE_DIGS** can be queried with
+the **limits** statement.
+
+In addition, this bc(1) uses an even larger integer for overflow checking. This
+integer type depends on the value of **BC_LONG_BIT**, but is always at least
+twice as large as the integer type used to store digits.
+
+# LIMITS
+
+The following are the limits on bc(1):
+
+**BC_LONG_BIT**
+
+: The number of bits in the **long** type in the environment where bc(1) was
+ built. This determines how many decimal digits can be stored in a single
+ large integer (see the **PERFORMANCE** section).
+
+**BC_BASE_DIGS**
+
+: The number of decimal digits per large integer (see the **PERFORMANCE**
+ section). Depends on **BC_LONG_BIT**.
+
+**BC_BASE_POW**
+
+: The max decimal number that each large integer can store (see
+ **BC_BASE_DIGS**) plus **1**. Depends on **BC_BASE_DIGS**.
+
+**BC_OVERFLOW_MAX**
+
+: The max number that the overflow type (see the **PERFORMANCE** section) can
+ hold. Depends on **BC_LONG_BIT**.
+
+**BC_BASE_MAX**
+
+: The maximum output base. Set at **BC_BASE_POW**.
+
+**BC_DIM_MAX**
+
+: The maximum size of arrays. Set at **SIZE_MAX-1**.
+
+**BC_SCALE_MAX**
+
+: The maximum **scale**. Set at **BC_OVERFLOW_MAX-1**.
+
+**BC_STRING_MAX**
+
+: The maximum length of strings. Set at **BC_OVERFLOW_MAX-1**.
+
+**BC_NAME_MAX**
+
+: The maximum length of identifiers. Set at **BC_OVERFLOW_MAX-1**.
+
+**BC_NUM_MAX**
+
+: The maximum length of a number (in decimal digits), which includes digits
+ after the decimal point. Set at **BC_OVERFLOW_MAX-1**.
+
+{{ A H N HN }}
+**BC_RAND_MAX**
+
+: The maximum integer (inclusive) returned by the **rand()** operand. Set at
+ **2\^BC_LONG_BIT-1**.
+{{ end }}
+
+Exponent
+
+: The maximum allowable exponent (positive or negative). Set at
+ **BC_OVERFLOW_MAX**.
+
+Number of vars
+
+: The maximum number of vars/arrays. Set at **SIZE_MAX-1**.
+
+The actual values can be queried with the **limits** statement.
+
+These limits are meant to be effectively non-existent; the limits are so large
+(at least on 64-bit machines) that there should not be any point at which they
+become a problem. In fact, memory should be exhausted before these limits should
+be hit.
+
+# ENVIRONMENT VARIABLES
+
+bc(1) recognizes the following environment variables:
+
+**POSIXLY_CORRECT**
+
+: If this variable exists (no matter the contents), bc(1) behaves as if
+ the **-s** option was given.
+
+**BC_ENV_ARGS**
+
+: This is another way to give command-line arguments to bc(1). They should be
+ in the same format as all other command-line arguments. These are always
+ processed first, so any files given in **BC_ENV_ARGS** will be processed
+ before arguments and files given on the command-line. This gives the user
+ the ability to set up "standard" options and files to be used at every
+ invocation. The most useful thing for such files to contain would be useful
+ functions that the user might want every time bc(1) runs.
+
+ The code that parses **BC_ENV_ARGS** will correctly handle quoted arguments,
+ but it does not understand escape sequences. For example, the string
+ **"/home/gavin/some bc file.bc"** will be correctly parsed, but the string
+ **"/home/gavin/some \"bc\" file.bc"** will include the backslashes.
+
+ The quote parsing will handle either kind of quotes, **'** or **"**. Thus,
+ if you have a file with any number of single quotes in the name, you can use
+ double quotes as the outside quotes, as in **"some 'bc' file.bc"**, and vice
+ versa if you have a file with double quotes. However, handling a file with
+ both kinds of quotes in **BC_ENV_ARGS** is not supported due to the
+ complexity of the parsing, though such files are still supported on the
+ command-line where the parsing is done by the shell.
+
+**BC_LINE_LENGTH**
+
+: If this environment variable exists and contains an integer that is greater
+ than **1** and is less than **UINT16_MAX** (**2\^16-1**), bc(1) will output
+ lines to that length, including the backslash (**\\**). The default line
+ length is **70**.
+
+ The special value of **0** will disable line length checking and print
+ numbers without regard to line length and without backslashes and newlines.
+
+**BC_BANNER**
+
+: If this environment variable exists and contains an integer, then a non-zero
+ value activates the copyright banner when bc(1) is in interactive mode,
+ while zero deactivates it.
+
+ If bc(1) is not in interactive mode (see the **INTERACTIVE MODE** section),
+ then this environment variable has no effect because bc(1) does not print
+ the banner when not in interactive mode.
+
+ This environment variable overrides the default, which can be queried with
+ the **-h** or **-\-help** options.
+
+**BC_SIGINT_RESET**
+
+: If bc(1) is not in interactive mode (see the **INTERACTIVE MODE** section),
+ then this environment variable has no effect because bc(1) exits on
+ **SIGINT** when not in interactive mode.
+
+ However, when bc(1) is in interactive mode, then if this environment
+ variable exists and contains an integer, a non-zero value makes bc(1) reset
+ on **SIGINT**, rather than exit, and zero makes bc(1) exit. If this
+ environment variable exists and is *not* an integer, then bc(1) will exit on
+ **SIGINT**.
+
+ This environment variable overrides the default, which can be queried with
+ the **-h** or **-\-help** options.
+
+**BC_TTY_MODE**
+
+: If TTY mode is *not* available (see the **TTY MODE** section), then this
+ environment variable has no effect.
+
+ However, when TTY mode is available, then if this environment variable
+ exists and contains an integer, then a non-zero value makes bc(1) use TTY
+ mode, and zero makes bc(1) not use TTY mode.
+
+ This environment variable overrides the default, which can be queried with
+ the **-h** or **-\-help** options.
+
+**BC_PROMPT**
+
+: If TTY mode is *not* available (see the **TTY MODE** section), then this
+ environment variable has no effect.
+
+ However, when TTY mode is available, then if this environment variable
+ exists and contains an integer, a non-zero value makes bc(1) use a prompt,
+ and zero or a non-integer makes bc(1) not use a prompt. If this environment
+ variable does not exist and **BC_TTY_MODE** does, then the value of the
+ **BC_TTY_MODE** environment variable is used.
+
+ This environment variable and the **BC_TTY_MODE** environment variable
+ override the default, which can be queried with the **-h** or **-\-help**
+ options.
+
+**BC_EXPR_EXIT**
+
+: If any expressions or expression files are given on the command-line with
+ **-e**, **-\-expression**, **-f**, or **-\-file**, then if this environment
+ variable exists and contains an integer, a non-zero value makes bc(1) exit
+ after executing the expressions and expression files, and a non-zero value
+ makes bc(1) not exit.
+
+ This environment variable overrides the default, which can be queried with
+ the **-h** or **-\-help** options.
+
+# EXIT STATUS
+
+bc(1) returns the following exit statuses:
+
+**0**
+
+: No error.
+
+**1**
+
+: A math error occurred. This follows standard practice of using **1** for
+ expected errors, since math errors will happen in the process of normal
+ execution.
+
+ Math errors include divide by **0**, taking the square root of a negative
+{{ A H N HN }}
+ number, using a negative number as a bound for the pseudo-random number
+ generator, attempting to convert a negative number to a hardware integer,
+ overflow when converting a number to a hardware integer, overflow when
+ calculating the size of a number, and attempting to use a non-integer where
+ an integer is required.
+
+ Converting to a hardware integer happens for the second operand of the power
+ (**\^**), places (**\@**), left shift (**\<\<**), and right shift (**\>\>**)
+ operators and their corresponding assignment operators.
+{{ end }}
+{{ E EH EN EHN }}
+ number, attempting to convert a negative number to a hardware integer,
+ overflow when converting a number to a hardware integer, overflow when
+ calculating the size of a number, and attempting to use a non-integer where
+ an integer is required.
+
+ Converting to a hardware integer happens for the second operand of the power
+ (**\^**) operator and the corresponding assignment operator.
+{{ end }}
+
+**2**
+
+: A parse error occurred.
+
+ Parse errors include unexpected **EOF**, using an invalid character, failing
+ to find the end of a string or comment, using a token where it is invalid,
+ giving an invalid expression, giving an invalid print statement, giving an
+ invalid function definition, attempting to assign to an expression that is
+ not a named expression (see the *Named Expressions* subsection of the
+ **SYNTAX** section), giving an invalid **auto** list, having a duplicate
+ **auto**/function parameter, failing to find the end of a code block,
+ attempting to return a value from a **void** function, attempting to use a
+ variable as a reference, and using any extensions when the option **-s** or
+ any equivalents were given.
+
+**3**
+
+: A runtime error occurred.
+
+ Runtime errors include assigning an invalid number to any global (**ibase**,
+ **obase**, or **scale**), giving a bad expression to a **read()** call,
+ calling **read()** inside of a **read()** call, type errors, passing the
+ wrong number of arguments to functions, attempting to call an undefined
+ function, and attempting to use a **void** function call as a value in an
+ expression.
+
+**4**
+
+: A fatal error occurred.
+
+ Fatal errors include memory allocation errors, I/O errors, failing to open
+ files, attempting to use files that do not have only ASCII characters (bc(1)
+ only accepts ASCII characters), attempting to open a directory as a file,
+ and giving invalid command-line options.
+
+The exit status **4** is special; when a fatal error occurs, bc(1) always exits
+and returns **4**, no matter what mode bc(1) is in.
+
+The other statuses will only be returned when bc(1) is not in interactive mode
+(see the **INTERACTIVE MODE** section), since bc(1) resets its state (see the
+**RESET** section) and accepts more input when one of those errors occurs in
+interactive mode. This is also the case when interactive mode is forced by the
+**-i** flag or **-\-interactive** option.
+
+These exit statuses allow bc(1) to be used in shell scripting with error
+checking, and its normal behavior can be forced by using the **-i** flag or
+**-\-interactive** option.
+
+# INTERACTIVE MODE
+
+Per the [standard][1], bc(1) has an interactive mode and a non-interactive mode.
+Interactive mode is turned on automatically when both **stdin** and **stdout**
+are hooked to a terminal, but the **-i** flag and **-\-interactive** option can
+turn it on in other situations.
+
+In interactive mode, bc(1) attempts to recover from errors (see the **RESET**
+section), and in normal execution, flushes **stdout** as soon as execution is
+done for the current input. bc(1) may also reset on **SIGINT** instead of exit,
+depending on the contents of, or default for, the **BC_SIGINT_RESET**
+environment variable (see the **ENVIRONMENT VARIABLES** section).
+
+# TTY MODE
+
+If **stdin**, **stdout**, and **stderr** are all connected to a TTY, then "TTY
+mode" is considered to be available, and thus, bc(1) can turn on TTY mode,
+subject to some settings.
+
+If there is the environment variable **BC_TTY_MODE** in the environment (see the
+**ENVIRONMENT VARIABLES** section), then if that environment variable contains a
+non-zero integer, bc(1) will turn on TTY mode when **stdin**, **stdout**, and
+**stderr** are all connected to a TTY. If the **BC_TTY_MODE** environment
+variable exists but is *not* a non-zero integer, then bc(1) will not turn TTY
+mode on.
+
+If the environment variable **BC_TTY_MODE** does *not* exist, the default
+setting is used. The default setting can be queried with the **-h** or
+**-\-help** options.
+
+TTY mode is different from interactive mode because interactive mode is required
+in the [bc(1) specification][1], and interactive mode requires only **stdin**
+and **stdout** to be connected to a terminal.
+
+{{ A E N EN }}
+## Command-Line History
+
+Command-line history is only enabled if TTY mode is, i.e., that **stdin**,
+**stdout**, and **stderr** are connected to a TTY and the **BC_TTY_MODE**
+environment variable (see the **ENVIRONMENT VARIABLES** section) and its default
+do not disable TTY mode. See the **COMMAND LINE HISTORY** section for more
+information.
+{{ end }}
+
+## Prompt
+
+If TTY mode is available, then a prompt can be enabled. Like TTY mode itself, it
+can be turned on or off with an environment variable: **BC_PROMPT** (see the
+**ENVIRONMENT VARIABLES** section).
+
+If the environment variable **BC_PROMPT** exists and is a non-zero integer, then
+the prompt is turned on when **stdin**, **stdout**, and **stderr** are connected
+to a TTY and the **-P** and **-\-no-prompt** options were not used. The read
+prompt will be turned on under the same conditions, except that the **-R** and
+**-\-no-read-prompt** options must also not be used.
+
+However, if **BC_PROMPT** does not exist, the prompt can be enabled or disabled
+with the **BC_TTY_MODE** environment variable, the **-P** and **-\-no-prompt**
+options, and the **-R** and **-\-no-read-prompt** options. See the **ENVIRONMENT
+VARIABLES** and **OPTIONS** sections for more details.
+
+# SIGNAL HANDLING
+
+Sending a **SIGINT** will cause bc(1) to do one of two things.
+
+If bc(1) is not in interactive mode (see the **INTERACTIVE MODE** section), or
+the **BC_SIGINT_RESET** environment variable (see the **ENVIRONMENT VARIABLES**
+section), or its default, is either not an integer or it is zero, bc(1) will
+exit.
+
+However, if bc(1) is in interactive mode, and the **BC_SIGINT_RESET** or its
+default is an integer and non-zero, then bc(1) will stop executing the current
+input and reset (see the **RESET** section) upon receiving a **SIGINT**.
+
+Note that "current input" can mean one of two things. If bc(1) is processing
+input from **stdin** in interactive mode, it will ask for more input. If bc(1)
+is processing input from a file in interactive mode, it will stop processing the
+file and start processing the next file, if one exists, or ask for input from
+**stdin** if no other file exists.
+
+This means that if a **SIGINT** is sent to bc(1) as it is executing a file, it
+can seem as though bc(1) did not respond to the signal since it will immediately
+start executing the next file. This is by design; most files that users execute
+when interacting with bc(1) have function definitions, which are quick to parse.
+If a file takes a long time to execute, there may be a bug in that file. The
+rest of the files could still be executed without problem, allowing the user to
+continue.
+
+**SIGTERM** and **SIGQUIT** cause bc(1) to clean up and exit, and it uses the
+{{ A E N EN }}
+default handler for all other signals. The one exception is **SIGHUP**; in that
+case, and only when bc(1) is in TTY mode (see the **TTY MODE** section), a
+**SIGHUP** will cause bc(1) to clean up and exit.
+{{ end }}
+{{ H EH HN EHN }}
+default handler for all other signals.
+{{ end }}
+
+{{ A E N EN }}
+# COMMAND LINE HISTORY
+
+bc(1) supports interactive command-line editing.
+
+If bc(1) can be in TTY mode (see the **TTY MODE** section), history can be
+enabled. This means that command-line history can only be enabled when
+**stdin**, **stdout**, and **stderr** are all connected to a TTY.
+
+Like TTY mode itself, it can be turned on or off with the environment variable
+**BC_TTY_MODE** (see the **ENVIRONMENT VARIABLES** section).
+
+If history is enabled, previous lines can be recalled and edited with the arrow
+keys.
+
+**Note**: tabs are converted to 8 spaces.
+{{ end }}
+
+{{ A E H EH }}
+# LOCALES
+
+This bc(1) ships with support for adding error messages for different locales
+and thus, supports **LC_MESSAGES**.
+{{ end }}
+
+# SEE ALSO
+
+dc(1)
+
+# STANDARDS
+
+bc(1) is compliant with the [IEEE Std 1003.1-2017 (“POSIX.1-2017”)][1]
+specification. The flags **-efghiqsvVw**, all long options, and the extensions
+noted above are extensions to that specification.
+
+Note that the specification explicitly says that bc(1) only accepts numbers that
+use a period (**.**) as a radix point, regardless of the value of
+**LC_NUMERIC**.
+
+{{ A E H EH }}
+This bc(1) supports error messages for different locales, and thus, it supports
+**LC_MESSAGES**.
+{{ end }}
+
+# BUGS
+
+None are known. Report bugs at https://git.yzena.com/gavin/bc.
+
+# AUTHORS
+
+Gavin D. Howard <gavin@yzena.com> and contributors.
+
+[1]: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html
+[2]: https://www.gnu.org/software/bc/
+[3]: https://en.wikipedia.org/wiki/Rounding#Round_half_away_from_zero
+[4]: https://en.wikipedia.org/wiki/Unit_in_the_last_place
+[5]: https://people.eecs.berkeley.edu/~wkahan/LOG10HAF.TXT
+[6]: https://en.wikipedia.org/wiki/Rounding#Rounding_away_from_zero
diff --git a/contrib/bc/manuals/benchmarks.md b/contrib/bc/manuals/benchmarks.md
new file mode 100644
index 000000000000..af0593f4e876
--- /dev/null
+++ b/contrib/bc/manuals/benchmarks.md
@@ -0,0 +1,673 @@
+# Benchmarks
+
+The results of these benchmarks suggest that building this `bc` with
+optimization at `-O3` with link-time optimization (`-flto`) will result in the
+best performance. However, using `-march=native` can result in **WORSE**
+performance.
+
+*Note*: all benchmarks were run four times, and the fastest run is the one
+shown. Also, `[bc]` means whichever `bc` was being run, and the assumed working
+directory is the root directory of this repository. Also, this `bc` was at
+version `3.0.0` while GNU `bc` was at version `1.07.1`, and all tests were
+conducted on an `x86_64` machine running Gentoo Linux with `clang` `9.0.1` as
+the compiler.
+
+## Typical Optimization Level
+
+These benchmarks were run with both `bc`'s compiled with the typical `-O2`
+optimizations and no link-time optimization.
+
+### Addition
+
+The command used was:
+
+```
+tests/script.sh bc add.bc 1 0 1 1 [bc]
+```
+
+For GNU `bc`:
+
+```
+real 2.54
+user 1.21
+sys 1.32
+```
+
+For this `bc`:
+
+```
+real 0.88
+user 0.85
+sys 0.02
+```
+
+### Subtraction
+
+The command used was:
+
+```
+tests/script.sh bc subtract.bc 1 0 1 1 [bc]
+```
+
+For GNU `bc`:
+
+```
+real 2.51
+user 1.05
+sys 1.45
+```
+
+For this `bc`:
+
+```
+real 0.91
+user 0.85
+sys 0.05
+```
+
+### Multiplication
+
+The command used was:
+
+```
+tests/script.sh bc multiply.bc 1 0 1 1 [bc]
+```
+
+For GNU `bc`:
+
+```
+real 7.15
+user 4.69
+sys 2.46
+```
+
+For this `bc`:
+
+```
+real 2.20
+user 2.10
+sys 0.09
+```
+
+### Division
+
+The command used was:
+
+```
+tests/script.sh bc divide.bc 1 0 1 1 [bc]
+```
+
+For GNU `bc`:
+
+```
+real 3.36
+user 1.87
+sys 1.48
+```
+
+For this `bc`:
+
+```
+real 1.61
+user 1.57
+sys 0.03
+```
+
+### Power
+
+The command used was:
+
+```
+printf '1234567890^100000; halt\n' | time -p [bc] -q > /dev/null
+```
+
+For GNU `bc`:
+
+```
+real 11.30
+user 11.30
+sys 0.00
+```
+
+For this `bc`:
+
+```
+real 0.73
+user 0.72
+sys 0.00
+```
+
+### Scripts
+
+[This file][1] was downloaded, saved at `../timeconst.bc` and the following
+patch was applied:
+
+```
+--- ../timeconst.bc 2018-09-28 11:32:22.808669000 -0600
++++ ../timeconst.bc 2019-06-07 07:26:36.359913078 -0600
+@@ -110,8 +110,10 @@
+
+ print "#endif /* KERNEL_TIMECONST_H */\n"
+ }
+- halt
+ }
+
+-hz = read();
+-timeconst(hz)
++for (i = 0; i <= 50000; ++i) {
++ timeconst(i)
++}
++
++halt
+```
+
+The command used was:
+
+```
+time -p [bc] ../timeconst.bc > /dev/null
+```
+
+For GNU `bc`:
+
+```
+real 16.71
+user 16.06
+sys 0.65
+```
+
+For this `bc`:
+
+```
+real 13.16
+user 13.15
+sys 0.00
+```
+
+Because this `bc` is faster when doing math, it might be a better comparison to
+run a script that is not running any math. As such, I put the following into
+`../test.bc`:
+
+```
+for (i = 0; i < 100000000; ++i) {
+ y = i
+}
+
+i
+y
+
+halt
+```
+
+The command used was:
+
+```
+time -p [bc] ../test.bc > /dev/null
+```
+
+For GNU `bc`:
+
+```
+real 16.60
+user 16.59
+sys 0.00
+```
+
+For this `bc`:
+
+```
+real 22.76
+user 22.75
+sys 0.00
+```
+
+I also put the following into `../test2.bc`:
+
+```
+i = 0
+
+while (i < 100000000) {
+ i += 1
+}
+
+i
+
+halt
+```
+
+The command used was:
+
+```
+time -p [bc] ../test2.bc > /dev/null
+```
+
+For GNU `bc`:
+
+```
+real 17.32
+user 17.30
+sys 0.00
+```
+
+For this `bc`:
+
+```
+real 16.98
+user 16.96
+sys 0.01
+```
+
+It seems that the improvements to the interpreter helped a lot in certain cases.
+
+Also, I have no idea why GNU `bc` did worse when it is technically doing less
+work.
+
+## Recommended Optimizations from `2.7.0`
+
+Note that, when running the benchmarks, the optimizations used are not the ones
+I recommended for version `2.7.0`, which are `-O3 -flto -march=native`.
+
+This `bc` separates its code into modules that, when optimized at link time,
+removes a lot of the inefficiency that comes from function overhead. This is
+most keenly felt with one function: `bc_vec_item()`, which should turn into just
+one instruction (on `x86_64`) when optimized at link time and inlined. There are
+other functions that matter as well.
+
+I also recommended `-march=native` on the grounds that newer instructions would
+increase performance on math-heavy code. We will see if that assumption was
+correct. (Spoiler: **NO**.)
+
+When compiling both `bc`'s with the optimizations I recommended for this `bc`
+for version `2.7.0`, the results are as follows.
+
+### Addition
+
+The command used was:
+
+```
+tests/script.sh bc add.bc 1 0 1 1 [bc]
+```
+
+For GNU `bc`:
+
+```
+real 2.44
+user 1.11
+sys 1.32
+```
+
+For this `bc`:
+
+```
+real 0.59
+user 0.54
+sys 0.05
+```
+
+### Subtraction
+
+The command used was:
+
+```
+tests/script.sh bc subtract.bc 1 0 1 1 [bc]
+```
+
+For GNU `bc`:
+
+```
+real 2.42
+user 1.02
+sys 1.40
+```
+
+For this `bc`:
+
+```
+real 0.64
+user 0.57
+sys 0.06
+```
+
+### Multiplication
+
+The command used was:
+
+```
+tests/script.sh bc multiply.bc 1 0 1 1 [bc]
+```
+
+For GNU `bc`:
+
+```
+real 7.01
+user 4.50
+sys 2.50
+```
+
+For this `bc`:
+
+```
+real 1.59
+user 1.53
+sys 0.05
+```
+
+### Division
+
+The command used was:
+
+```
+tests/script.sh bc divide.bc 1 0 1 1 [bc]
+```
+
+For GNU `bc`:
+
+```
+real 3.26
+user 1.82
+sys 1.44
+```
+
+For this `bc`:
+
+```
+real 1.24
+user 1.20
+sys 0.03
+```
+
+### Power
+
+The command used was:
+
+```
+printf '1234567890^100000; halt\n' | time -p [bc] -q > /dev/null
+```
+
+For GNU `bc`:
+
+```
+real 11.08
+user 11.07
+sys 0.00
+```
+
+For this `bc`:
+
+```
+real 0.71
+user 0.70
+sys 0.00
+```
+
+### Scripts
+
+The command for the `../timeconst.bc` script was:
+
+```
+time -p [bc] ../timeconst.bc > /dev/null
+```
+
+For GNU `bc`:
+
+```
+real 15.62
+user 15.08
+sys 0.53
+```
+
+For this `bc`:
+
+```
+real 10.09
+user 10.08
+sys 0.01
+```
+
+The command for the next script, the `for` loop script, was:
+
+```
+time -p [bc] ../test.bc > /dev/null
+```
+
+For GNU `bc`:
+
+```
+real 14.76
+user 14.75
+sys 0.00
+```
+
+For this `bc`:
+
+```
+real 17.95
+user 17.94
+sys 0.00
+```
+
+The command for the next script, the `while` loop script, was:
+
+```
+time -p [bc] ../test2.bc > /dev/null
+```
+
+For GNU `bc`:
+
+```
+real 14.84
+user 14.83
+sys 0.00
+```
+
+For this `bc`:
+
+```
+real 13.53
+user 13.52
+sys 0.00
+```
+
+## Link-Time Optimization Only
+
+Just for kicks, let's see if `-march=native` is even useful.
+
+The optimizations I used for both `bc`'s were `-O3 -flto`.
+
+### Addition
+
+The command used was:
+
+```
+tests/script.sh bc add.bc 1 0 1 1 [bc]
+```
+
+For GNU `bc`:
+
+```
+real 2.41
+user 1.05
+sys 1.35
+```
+
+For this `bc`:
+
+```
+real 0.58
+user 0.52
+sys 0.05
+```
+
+### Subtraction
+
+The command used was:
+
+```
+tests/script.sh bc subtract.bc 1 0 1 1 [bc]
+```
+
+For GNU `bc`:
+
+```
+real 2.39
+user 1.10
+sys 1.28
+```
+
+For this `bc`:
+
+```
+real 0.65
+user 0.57
+sys 0.07
+```
+
+### Multiplication
+
+The command used was:
+
+```
+tests/script.sh bc multiply.bc 1 0 1 1 [bc]
+```
+
+For GNU `bc`:
+
+```
+real 6.82
+user 4.30
+sys 2.51
+```
+
+For this `bc`:
+
+```
+real 1.57
+user 1.49
+sys 0.08
+```
+
+### Division
+
+The command used was:
+
+```
+tests/script.sh bc divide.bc 1 0 1 1 [bc]
+```
+
+For GNU `bc`:
+
+```
+real 3.25
+user 1.81
+sys 1.43
+```
+
+For this `bc`:
+
+```
+real 1.27
+user 1.23
+sys 0.04
+```
+
+### Power
+
+The command used was:
+
+```
+printf '1234567890^100000; halt\n' | time -p [bc] -q > /dev/null
+```
+
+For GNU `bc`:
+
+```
+real 10.50
+user 10.49
+sys 0.00
+```
+
+For this `bc`:
+
+```
+real 0.72
+user 0.71
+sys 0.00
+```
+
+### Scripts
+
+The command for the `../timeconst.bc` script was:
+
+```
+time -p [bc] ../timeconst.bc > /dev/null
+```
+
+For GNU `bc`:
+
+```
+real 15.50
+user 14.81
+sys 0.68
+```
+
+For this `bc`:
+
+```
+real 10.17
+user 10.15
+sys 0.01
+```
+
+The command for the next script, the `for` loop script, was:
+
+```
+time -p [bc] ../test.bc > /dev/null
+```
+
+For GNU `bc`:
+
+```
+real 14.99
+user 14.99
+sys 0.00
+```
+
+For this `bc`:
+
+```
+real 16.85
+user 16.84
+sys 0.00
+```
+
+The command for the next script, the `while` loop script, was:
+
+```
+time -p [bc] ../test2.bc > /dev/null
+```
+
+For GNU `bc`:
+
+```
+real 14.92
+user 14.91
+sys 0.00
+```
+
+For this `bc`:
+
+```
+real 12.75
+user 12.75
+sys 0.00
+```
+
+It turns out that `-march=native` can be a problem. As such, I have removed the
+recommendation to build with `-march=native`.
+
+## Recommended Compiler
+
+When I ran these benchmarks with my `bc` compiled under `clang` vs. `gcc`, it
+performed much better under `clang`. I recommend compiling this `bc` with
+`clang`.
+
+[1]: https://github.com/torvalds/linux/blob/master/kernel/time/timeconst.bc
diff --git a/contrib/bc/manuals/dc.1.md.in b/contrib/bc/manuals/dc.1.md.in
new file mode 100644
index 000000000000..5ca37bcc97c4
--- /dev/null
+++ b/contrib/bc/manuals/dc.1.md.in
@@ -0,0 +1,1452 @@
+<!---
+
+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.
+
+-->
+
+# Name
+
+dc - arbitrary-precision decimal reverse-Polish notation calculator
+
+# SYNOPSIS
+
+**dc** [**-hiPRvVx**] [**-\-version**] [**-\-help**] [**-\-interactive**] [**-\-no-prompt**] [**-\-no-read-prompt**] [**-\-extended-register**] [**-e** *expr*] [**-\-expression**=*expr*...] [**-f** *file*...] [**-\-file**=*file*...] [*file*...]
+
+# DESCRIPTION
+
+dc(1) is an arbitrary-precision calculator. It uses a stack (reverse Polish
+notation) to store numbers and results of computations. Arithmetic operations
+pop arguments off of the stack and push the results.
+
+If no files are given on the command-line, then dc(1) reads from **stdin** (see
+the **STDIN** section). Otherwise, those files are processed, and dc(1) will
+then exit.
+
+If a user wants to set up a standard environment, they can use **DC_ENV_ARGS**
+(see the **ENVIRONMENT VARIABLES** section). For example, if a user wants the
+**scale** always set to **10**, they can set **DC_ENV_ARGS** to **-e 10k**, and
+this dc(1) will always start with a **scale** of **10**.
+
+# OPTIONS
+
+The following are the options that dc(1) accepts.
+
+**-h**, **-\-help**
+
+: Prints a usage message and quits.
+
+**-v**, **-V**, **-\-version**
+
+: Print the version information (copyright header) and exit.
+
+**-i**, **-\-interactive**
+
+: Forces interactive mode. (See the **INTERACTIVE MODE** section.)
+
+ This is a **non-portable extension**.
+
+**-L**, **-\-no-line-length**
+
+: Disables line length checking and prints numbers without backslashes and
+ newlines. In other words, this option sets **BC_LINE_LENGTH** to **0** (see
+ the **ENVIRONMENT VARIABLES** section).
+
+ This is a **non-portable extension**.
+
+**-P**, **-\-no-prompt**
+
+: Disables the prompt in TTY mode. (The prompt is only enabled in TTY mode.
+ See the **TTY MODE** section.) This is mostly for those users that do not
+ want a prompt or are not used to having them in dc(1). Most of those users
+ would want to put this option in **DC_ENV_ARGS**.
+
+ These options override the **DC_PROMPT** and **DC_TTY_MODE** environment
+ variables (see the **ENVIRONMENT VARIABLES** section).
+
+ This is a **non-portable extension**.
+
+**-R**, **-\-no-read-prompt**
+
+: Disables the read prompt in TTY mode. (The read prompt is only enabled in
+ TTY mode. See the **TTY MODE** section.) This is mostly for those users that
+ do not want a read prompt or are not used to having them in dc(1). Most of
+ those users would want to put this option in **BC_ENV_ARGS** (see the
+ **ENVIRONMENT VARIABLES** section). This option is also useful in hash bang
+ lines of dc(1) scripts that prompt for user input.
+
+ This option does not disable the regular prompt because the read prompt is
+ only used when the **?** command is used.
+
+ These options *do* override the **DC_PROMPT** and **DC_TTY_MODE**
+ environment variables (see the **ENVIRONMENT VARIABLES** section), but only
+ for the read prompt.
+
+ This is a **non-portable extension**.
+
+**-x** **-\-extended-register**
+
+: Enables extended register mode. See the *Extended Register Mode* subsection
+ of the **REGISTERS** section for more information.
+
+ This is a **non-portable extension**.
+
+**-z**, **-\-leading-zeroes**
+
+: Makes bc(1) print all numbers greater than **-1** and less than **1**, and
+ not equal to **0**, with a leading zero.
+
+ This can be set for individual numbers with the **plz(x)**, plznl(x)**,
+ **pnlz(x)**, and **pnlznl(x)** functions in the extended math library (see
+ the **LIBRARY** section).
+
+ This is a **non-portable extension**.
+
+**-e** *expr*, **-\-expression**=*expr*
+
+: Evaluates *expr*. If multiple expressions are given, they are evaluated in
+ order. If files are given as well (see below), the expressions and files are
+ evaluated in the order given. This means that if a file is given before an
+ expression, the file is read in and evaluated first.
+
+ If this option is given on the command-line (i.e., not in **DC_ENV_ARGS**,
+ see the **ENVIRONMENT VARIABLES** section), then after processing all
+ expressions and files, dc(1) will exit, unless **-** (**stdin**) was given
+ as an argument at least once to **-f** or **-\-file**, whether on the
+ command-line or in **DC_ENV_ARGS**. However, if any other **-e**,
+ **-\-expression**, **-f**, or **-\-file** arguments are given after **-f-**
+ or equivalent is given, dc(1) will give a fatal error and exit.
+
+ This is a **non-portable extension**.
+
+**-f** *file*, **-\-file**=*file*
+
+: Reads in *file* and evaluates it, line by line, as though it were read
+ through **stdin**. If expressions are also given (see above), the
+ expressions are evaluated in the order given.
+
+ If this option is given on the command-line (i.e., not in **DC_ENV_ARGS**,
+ see the **ENVIRONMENT VARIABLES** section), then after processing all
+ expressions and files, dc(1) will exit, unless **-** (**stdin**) was given
+ as an argument at least once to **-f** or **-\-file**. However, if any other
+ **-e**, **-\-expression**, **-f**, or **-\-file** arguments are given after
+ **-f-** or equivalent is given, dc(1) will give a fatal error and exit.
+
+ This is a **non-portable extension**.
+
+All long options are **non-portable extensions**.
+
+# STDIN
+
+If no files are given on the command-line and no files or expressions are given
+by the **-f**, **-\-file**, **-e**, or **-\-expression** options, then dc(1)
+read from **stdin**.
+
+However, there is a caveat to this.
+
+First, **stdin** is evaluated a line at a time. The only exception to this is if
+a string has been finished, but not ended. This means that, except for escaped
+brackets, all brackets must be balanced before dc(1) parses and executes.
+
+# STDOUT
+
+Any non-error output is written to **stdout**. In addition, if history (see the
+**HISTORY** section) and the prompt (see the **TTY MODE** section) are enabled,
+both are output to **stdout**.
+
+**Note**: Unlike other dc(1) implementations, this dc(1) will issue a fatal
+error (see the **EXIT STATUS** section) if it cannot write to **stdout**, so if
+**stdout** is closed, as in **dc <file> >&-**, it will quit with an error. This
+is done so that dc(1) can report problems when **stdout** is redirected to a
+file.
+
+If there are scripts that depend on the behavior of other dc(1) implementations,
+it is recommended that those scripts be changed to redirect **stdout** to
+**/dev/null**.
+
+# STDERR
+
+Any error output is written to **stderr**.
+
+**Note**: Unlike other dc(1) implementations, this dc(1) will issue a fatal
+error (see the **EXIT STATUS** section) if it cannot write to **stderr**, so if
+**stderr** is closed, as in **dc <file> 2>&-**, it will quit with an error. This
+is done so that dc(1) can exit with an error code when **stderr** is redirected
+to a file.
+
+If there are scripts that depend on the behavior of other dc(1) implementations,
+it is recommended that those scripts be changed to redirect **stderr** to
+**/dev/null**.
+
+# SYNTAX
+
+Each item in the input source code, either a number (see the **NUMBERS**
+section) or a command (see the **COMMANDS** section), is processed and executed,
+in order. Input is processed immediately when entered.
+
+**ibase** is a register (see the **REGISTERS** section) that determines how to
+interpret constant numbers. It is the "input" base, or the number base used for
+interpreting input numbers. **ibase** is initially **10**. The max allowable
+value for **ibase** is **16**. The min allowable value for **ibase** is **2**.
+The max allowable value for **ibase** can be queried in dc(1) programs with the
+**T** command.
+
+**obase** is a register (see the **REGISTERS** section) that determines how to
+output results. It is the "output" base, or the number base used for outputting
+numbers. **obase** is initially **10**. The max allowable value for **obase** is
+**DC_BASE_MAX** and can be queried with the **U** command. The min allowable
+{{ A H N HN }}
+value for **obase** is **0**. If **obase** is **0**, values are output in
+scientific notation, and if **obase** is **1**, values are output in engineering
+notation. Otherwise, values are output in the specified base.
+
+Outputting in scientific and engineering notations are **non-portable
+extensions**.
+{{ end }}
+{{ E EH EN EHN }}
+value for **obase** is **2**. Values are output in the specified base.
+{{ end }}
+
+The *scale* of an expression is the number of digits in the result of the
+expression right of the decimal point, and **scale** is a register (see the
+**REGISTERS** section) that sets the precision of any operations (with
+exceptions). **scale** is initially **0**. **scale** cannot be negative. The max
+allowable value for **scale** can be queried in dc(1) programs with the **V**
+command.
+
+{{ A H N HN }}
+**seed** is a register containing the current seed for the pseudo-random number
+generator. If the current value of **seed** is queried and stored, then if it is
+assigned to **seed** later, the pseudo-random number generator is guaranteed to
+produce the same sequence of pseudo-random numbers that were generated after the
+value of **seed** was first queried.
+
+Multiple values assigned to **seed** can produce the same sequence of
+pseudo-random numbers. Likewise, when a value is assigned to **seed**, it is not
+guaranteed that querying **seed** immediately after will return the same value.
+In addition, the value of **seed** will change after any call to the **'**
+command or the **"** command that does not get receive a value of **0** or
+**1**. The maximum integer returned by the **'** command can be queried with the
+**W** command.
+
+**Note**: The values returned by the pseudo-random number generator with the
+**'** and **"** commands are guaranteed to **NOT** be cryptographically secure.
+This is a consequence of using a seeded pseudo-random number generator. However,
+they *are* guaranteed to be reproducible with identical **seed** values. This
+means that the pseudo-random values from dc(1) should only be used where a
+reproducible stream of pseudo-random numbers is *ESSENTIAL*. In any other case,
+use a non-seeded pseudo-random number generator.
+
+The pseudo-random number generator, **seed**, and all associated operations are
+**non-portable extensions**.
+{{ end }}
+
+## Comments
+
+Comments go from **#** until, and not including, the next newline. This is a
+**non-portable extension**.
+
+# NUMBERS
+
+Numbers are strings made up of digits, uppercase letters up to **F**, and at
+most **1** period for a radix. Numbers can have up to **DC_NUM_MAX** digits.
+Uppercase letters are equal to **9** + their position in the alphabet (i.e.,
+**A** equals **10**, or **9+1**). If a digit or letter makes no sense with the
+current value of **ibase**, they are set to the value of the highest valid digit
+in **ibase**.
+
+Single-character numbers (i.e., **A** alone) take the value that they would have
+if they were valid digits, regardless of the value of **ibase**. This means that
+**A** alone always equals decimal **10** and **F** alone always equals decimal
+**15**.
+
+{{ A H N HN }}
+In addition, dc(1) accepts numbers in scientific notation. These have the form
+**\<number\>e\<integer\>**. The exponent (the portion after the **e**) must be
+an integer. An example is **1.89237e9**, which is equal to **1892370000**.
+Negative exponents are also allowed, so **4.2890e_3** is equal to **0.0042890**.
+
+**WARNING**: Both the number and the exponent in scientific notation are
+interpreted according to the current **ibase**, but the number is still
+multiplied by **10\^exponent** regardless of the current **ibase**. For example,
+if **ibase** is **16** and dc(1) is given the number string **FFeA**, the
+resulting decimal number will be **2550000000000**, and if dc(1) is given the
+number string **10e_4**, the resulting decimal number will be **0.0016**.
+
+Accepting input as scientific notation is a **non-portable extension**.
+{{ end }}
+
+# COMMANDS
+
+The valid commands are listed below.
+
+## Printing
+
+These commands are used for printing.
+
+{{ A H N HN }}
+Note that both scientific notation and engineering notation are available for
+printing numbers. Scientific notation is activated by assigning **0** to
+**obase** using **0o**, and engineering notation is activated by assigning **1**
+to **obase** using **1o**. To deactivate them, just assign a different value to
+**obase**.
+
+Printing numbers in scientific notation and/or engineering notation is a
+**non-portable extension**.
+{{ end }}
+
+**p**
+
+: Prints the value on top of the stack, whether number or string, and prints a
+ newline after.
+
+ This does not alter the stack.
+
+**n**
+
+: Prints the value on top of the stack, whether number or string, and pops it
+ off of the stack.
+
+**P**
+
+: Pops a value off the stack.
+
+ If the value is a number, it is truncated and the absolute value of the
+ result is printed as though **obase** is **256** and each digit is
+ interpreted as an 8-bit ASCII character, making it a byte stream.
+
+ If the value is a string, it is printed without a trailing newline.
+
+ This is a **non-portable extension**.
+
+**f**
+
+: Prints the entire contents of the stack, in order from newest to oldest,
+ without altering anything.
+
+ Users should use this command when they get lost.
+
+## Arithmetic
+
+These are the commands used for arithmetic.
+
+**+**
+
+: The top two values are popped off the stack, added, and the result is pushed
+ onto the stack. The *scale* of the result is equal to the max *scale* of
+ both operands.
+
+**-**
+
+: The top two values are popped off the stack, subtracted, and the result is
+ pushed onto the stack. The *scale* of the result is equal to the max
+ *scale* of both operands.
+
+**\***
+
+: The top two values are popped off the stack, multiplied, and the result is
+ pushed onto the stack. If **a** is the *scale* of the first expression and
+ **b** is the *scale* of the second expression, the *scale* of the result
+ is equal to **min(a+b,max(scale,a,b))** where **min()** and **max()** return
+ the obvious values.
+
+**/**
+
+: The top two values are popped off the stack, divided, and the result is
+ pushed onto the stack. The *scale* of the result is equal to **scale**.
+
+ The first value popped off of the stack must be non-zero.
+
+**%**
+
+: The top two values are popped off the stack, remaindered, and the result is
+ pushed onto the stack.
+
+ Remaindering is equivalent to 1) Computing **a/b** to current **scale**, and
+ 2) Using the result of step 1 to calculate **a-(a/b)\*b** to *scale*
+ **max(scale+scale(b),scale(a))**.
+
+ The first value popped off of the stack must be non-zero.
+
+**~**
+
+: The top two values are popped off the stack, divided and remaindered, and
+ the results (divided first, remainder second) are pushed onto the stack.
+ This is equivalent to **x y / x y %** except that **x** and **y** are only
+ evaluated once.
+
+ The first value popped off of the stack must be non-zero.
+
+ This is a **non-portable extension**.
+
+**\^**
+
+: The top two values are popped off the stack, the second is raised to the
+ power of the first, and the result is pushed onto the stack. The *scale* of
+ the result is equal to **scale**.
+
+ The first value popped off of the stack must be an integer, and if that
+ value is negative, the second value popped off of the stack must be
+ non-zero.
+
+**v**
+
+: The top value is popped off the stack, its square root is computed, and the
+ result is pushed onto the stack. The *scale* of the result is equal to
+ **scale**.
+
+ The value popped off of the stack must be non-negative.
+
+**\_**
+
+: If this command *immediately* precedes a number (i.e., no spaces or other
+ commands), then that number is input as a negative number.
+
+ Otherwise, the top value on the stack is popped and copied, and the copy is
+ negated and pushed onto the stack. This behavior without a number is a
+ **non-portable extension**.
+
+**b**
+
+: The top value is popped off the stack, and if it is zero, it is pushed back
+ onto the stack. Otherwise, its absolute value is pushed onto the stack.
+
+ This is a **non-portable extension**.
+
+**|**
+
+: The top three values are popped off the stack, a modular exponentiation is
+ computed, and the result is pushed onto the stack.
+
+ The first value popped is used as the reduction modulus and must be an
+ integer and non-zero. The second value popped is used as the exponent and
+ must be an integer and non-negative. The third value popped is the base and
+ must be an integer.
+
+ This is a **non-portable extension**.
+
+{{ A H N HN }}
+**\$**
+
+: The top value is popped off the stack and copied, and the copy is truncated
+ and pushed onto the stack.
+
+ This is a **non-portable extension**.
+
+**\@**
+
+: The top two values are popped off the stack, and the precision of the second
+ is set to the value of the first, whether by truncation or extension.
+
+ The first value popped off of the stack must be an integer and non-negative.
+
+ This is a **non-portable extension**.
+
+**H**
+
+: The top two values are popped off the stack, and the second is shifted left
+ (radix shifted right) to the value of the first.
+
+ The first value popped off of the stack must be an integer and non-negative.
+
+ This is a **non-portable extension**.
+
+**h**
+
+: The top two values are popped off the stack, and the second is shifted right
+ (radix shifted left) to the value of the first.
+
+ The first value popped off of the stack must be an integer and non-negative.
+
+ This is a **non-portable extension**.
+{{ end }}
+
+**G**
+
+: The top two values are popped off of the stack, they are compared, and a
+ **1** is pushed if they are equal, or **0** otherwise.
+
+ This is a **non-portable extension**.
+
+**N**
+
+: The top value is popped off of the stack, and if it a **0**, a **1** is
+ pushed; otherwise, a **0** is pushed.
+
+ This is a **non-portable extension**.
+
+**(**
+
+: The top two values are popped off of the stack, they are compared, and a
+ **1** is pushed if the first is less than the second, or **0** otherwise.
+
+ This is a **non-portable extension**.
+
+**{**
+
+: The top two values are popped off of the stack, they are compared, and a
+ **1** is pushed if the first is less than or equal to the second, or **0**
+ otherwise.
+
+ This is a **non-portable extension**.
+
+**)**
+
+: The top two values are popped off of the stack, they are compared, and a
+ **1** is pushed if the first is greater than the second, or **0** otherwise.
+
+ This is a **non-portable extension**.
+
+**}**
+
+: The top two values are popped off of the stack, they are compared, and a
+ **1** is pushed if the first is greater than or equal to the second, or
+ **0** otherwise.
+
+ This is a **non-portable extension**.
+
+**M**
+
+: The top two values are popped off of the stack. If they are both non-zero, a
+ **1** is pushed onto the stack. If either of them is zero, or both of them
+ are, then a **0** is pushed onto the stack.
+
+ This is like the **&&** operator in bc(1), and it is *not* a short-circuit
+ operator.
+
+ This is a **non-portable extension**.
+
+**m**
+
+: The top two values are popped off of the stack. If at least one of them is
+ non-zero, a **1** is pushed onto the stack. If both of them are zero, then a
+ **0** is pushed onto the stack.
+
+ This is like the **||** operator in bc(1), and it is *not* a short-circuit
+ operator.
+
+ This is a **non-portable extension**.
+
+{{ A H N HN }}
+## Pseudo-Random Number Generator
+
+dc(1) has a built-in pseudo-random number generator. These commands query the
+pseudo-random number generator. (See Parameters for more information about the
+**seed** value that controls the pseudo-random number generator.)
+
+The pseudo-random number generator is guaranteed to **NOT** be
+cryptographically secure.
+
+**'**
+
+: Generates an integer between 0 and **DC_RAND_MAX**, inclusive (see the
+ **LIMITS** section).
+
+ The generated integer is made as unbiased as possible, subject to the
+ limitations of the pseudo-random number generator.
+
+ This is a **non-portable extension**.
+
+**"**
+
+: Pops a value off of the stack, which is used as an **exclusive** upper bound
+ on the integer that will be generated. If the bound is negative or is a
+ non-integer, an error is raised, and dc(1) resets (see the **RESET**
+ section) while **seed** remains unchanged. If the bound is larger than
+ **DC_RAND_MAX**, the higher bound is honored by generating several
+ pseudo-random integers, multiplying them by appropriate powers of
+ **DC_RAND_MAX+1**, and adding them together. Thus, the size of integer that
+ can be generated with this command is unbounded. Using this command will
+ change the value of **seed**, unless the operand is **0** or **1**. In that
+ case, **0** is pushed onto the stack, and **seed** is *not* changed.
+
+ The generated integer is made as unbiased as possible, subject to the
+ limitations of the pseudo-random number generator.
+
+ This is a **non-portable extension**.
+{{ end }}
+
+## Stack Control
+
+These commands control the stack.
+
+**c**
+
+: Removes all items from ("clears") the stack.
+
+**d**
+
+: Copies the item on top of the stack ("duplicates") and pushes the copy onto
+ the stack.
+
+**r**
+
+: Swaps ("reverses") the two top items on the stack.
+
+**R**
+
+: Pops ("removes") the top value from the stack.
+
+## Register Control
+
+These commands control registers (see the **REGISTERS** section).
+
+**s**_r_
+
+: Pops the value off the top of the stack and stores it into register *r*.
+
+**l**_r_
+
+: Copies the value in register *r* and pushes it onto the stack. This does not
+ alter the contents of *r*.
+
+**S**_r_
+
+: Pops the value off the top of the (main) stack and pushes it onto the stack
+ of register *r*. The previous value of the register becomes inaccessible.
+
+**L**_r_
+
+: Pops the value off the top of the stack for register *r* and push it onto
+ the main stack. The previous value in the stack for register *r*, if any, is
+ now accessible via the **l**_r_ command.
+
+## Parameters
+
+{{ A H N HN }}
+These commands control the values of **ibase**, **obase**, **scale**, and
+**seed**. Also see the **SYNTAX** section.
+{{ end }}
+{{ E EH EN EHN }}
+These commands control the values of **ibase**, **obase**, and **scale**. Also
+see the **SYNTAX** section.
+{{ end }}
+
+**i**
+
+: Pops the value off of the top of the stack and uses it to set **ibase**,
+ which must be between **2** and **16**, inclusive.
+
+ If the value on top of the stack has any *scale*, the *scale* is ignored.
+
+**o**
+
+: Pops the value off of the top of the stack and uses it to set **obase**,
+{{ A H N HN }}
+ which must be between **0** and **DC_BASE_MAX**, inclusive (see the
+ **LIMITS** section and the **NUMBERS** section).
+{{ end }}
+{{ E EH EN EHN }}
+ which must be between **2** and **DC_BASE_MAX**, inclusive (see the
+ **LIMITS** section).
+{{ end }}
+
+ If the value on top of the stack has any *scale*, the *scale* is ignored.
+
+**k**
+
+: Pops the value off of the top of the stack and uses it to set **scale**,
+ which must be non-negative.
+
+ If the value on top of the stack has any *scale*, the *scale* is ignored.
+
+{{ A H N HN }}
+**j**
+
+: Pops the value off of the top of the stack and uses it to set **seed**. The
+ meaning of **seed** is dependent on the current pseudo-random number
+ generator but is guaranteed to not change except for new major versions.
+
+ The *scale* and sign of the value may be significant.
+
+ If a previously used **seed** value is used again, the pseudo-random number
+ generator is guaranteed to produce the same sequence of pseudo-random
+ numbers as it did when the **seed** value was previously used.
+
+ The exact value assigned to **seed** is not guaranteed to be returned if the
+ **J** command is used. However, if **seed** *does* return a different value,
+ both values, when assigned to **seed**, are guaranteed to produce the same
+ sequence of pseudo-random numbers. This means that certain values assigned
+ to **seed** will not produce unique sequences of pseudo-random numbers.
+
+ There is no limit to the length (number of significant decimal digits) or
+ *scale* of the value that can be assigned to **seed**.
+
+ This is a **non-portable extension**.
+{{ end }}
+
+**I**
+
+: Pushes the current value of **ibase** onto the main stack.
+
+**O**
+
+: Pushes the current value of **obase** onto the main stack.
+
+**K**
+
+: Pushes the current value of **scale** onto the main stack.
+
+{{ A H N HN }}
+**J**
+
+: Pushes the current value of **seed** onto the main stack.
+
+ This is a **non-portable extension**.
+{{ end }}
+
+**T**
+
+: Pushes the maximum allowable value of **ibase** onto the main stack.
+
+ This is a **non-portable extension**.
+
+**U**
+
+: Pushes the maximum allowable value of **obase** onto the main stack.
+
+ This is a **non-portable extension**.
+
+**V**
+
+: Pushes the maximum allowable value of **scale** onto the main stack.
+
+ This is a **non-portable extension**.
+
+{{ A H N HN }}
+**W**
+
+: Pushes the maximum (inclusive) integer that can be generated with the **'**
+ pseudo-random number generator command.
+
+ This is a **non-portable extension**.
+{{ end }}
+
+## Strings
+
+The following commands control strings.
+
+dc(1) can work with both numbers and strings, and registers (see the
+**REGISTERS** section) can hold both strings and numbers. dc(1) always knows
+whether the contents of a register are a string or a number.
+
+While arithmetic operations have to have numbers, and will print an error if
+given a string, other commands accept strings.
+
+Strings can also be executed as macros. For example, if the string **[1pR]** is
+executed as a macro, then the code **1pR** is executed, meaning that the **1**
+will be printed with a newline after and then popped from the stack.
+
+**\[**_characters_**\]**
+
+: Makes a string containing *characters* and pushes it onto the stack.
+
+ If there are brackets (**\[** and **\]**) in the string, then they must be
+ balanced. Unbalanced brackets can be escaped using a backslash (**\\**)
+ character.
+
+ If there is a backslash character in the string, the character after it
+ (even another backslash) is put into the string verbatim, but the (first)
+ backslash is not.
+
+**a**
+
+: The value on top of the stack is popped.
+
+ If it is a number, it is truncated and its absolute value is taken. The
+ result mod **256** is calculated. If that result is **0**, push an empty
+ string; otherwise, push a one-character string where the character is the
+ result of the mod interpreted as an ASCII character.
+
+ If it is a string, then a new string is made. If the original string is
+ empty, the new string is empty. If it is not, then the first character of
+ the original string is used to create the new string as a one-character
+ string. The new string is then pushed onto the stack.
+
+ This is a **non-portable extension**.
+
+**x**
+
+: Pops a value off of the top of the stack.
+
+ If it is a number, it is pushed back onto the stack.
+
+ If it is a string, it is executed as a macro.
+
+ This behavior is the norm whenever a macro is executed, whether by this
+ command or by the conditional execution commands below.
+
+**\>**_r_
+
+: Pops two values off of the stack that must be numbers and compares them. If
+ the first value is greater than the second, then the contents of register
+ *r* are executed.
+
+ For example, **0 1>a** will execute the contents of register **a**, and
+ **1 0>a** will not.
+
+ If either or both of the values are not numbers, dc(1) will raise an error
+ and reset (see the **RESET** section).
+
+**>**_r_**e**_s_
+
+: Like the above, but will execute register *s* if the comparison fails.
+
+ If either or both of the values are not numbers, dc(1) will raise an error
+ and reset (see the **RESET** section).
+
+ This is a **non-portable extension**.
+
+**!\>**_r_
+
+: Pops two values off of the stack that must be numbers and compares them. If
+ the first value is not greater than the second (less than or equal to), then
+ the contents of register *r* are executed.
+
+ If either or both of the values are not numbers, dc(1) will raise an error
+ and reset (see the **RESET** section).
+
+**!\>**_r_**e**_s_
+
+: Like the above, but will execute register *s* if the comparison fails.
+
+ If either or both of the values are not numbers, dc(1) will raise an error
+ and reset (see the **RESET** section).
+
+ This is a **non-portable extension**.
+
+**\<**_r_
+
+: Pops two values off of the stack that must be numbers and compares them. If
+ the first value is less than the second, then the contents of register *r*
+ are executed.
+
+ If either or both of the values are not numbers, dc(1) will raise an error
+ and reset (see the **RESET** section).
+
+**\<**_r_**e**_s_
+
+: Like the above, but will execute register *s* if the comparison fails.
+
+ If either or both of the values are not numbers, dc(1) will raise an error
+ and reset (see the **RESET** section).
+
+ This is a **non-portable extension**.
+
+**!\<**_r_
+
+: Pops two values off of the stack that must be numbers and compares them. If
+ the first value is not less than the second (greater than or equal to), then
+ the contents of register *r* are executed.
+
+ If either or both of the values are not numbers, dc(1) will raise an error
+ and reset (see the **RESET** section).
+
+**!\<**_r_**e**_s_
+
+: Like the above, but will execute register *s* if the comparison fails.
+
+ If either or both of the values are not numbers, dc(1) will raise an error
+ and reset (see the **RESET** section).
+
+ This is a **non-portable extension**.
+
+**=**_r_
+
+: Pops two values off of the stack that must be numbers and compares them. If
+ the first value is equal to the second, then the contents of register *r*
+ are executed.
+
+ If either or both of the values are not numbers, dc(1) will raise an error
+ and reset (see the **RESET** section).
+
+**=**_r_**e**_s_
+
+: Like the above, but will execute register *s* if the comparison fails.
+
+ If either or both of the values are not numbers, dc(1) will raise an error
+ and reset (see the **RESET** section).
+
+ This is a **non-portable extension**.
+
+**!=**_r_
+
+: Pops two values off of the stack that must be numbers and compares them. If
+ the first value is not equal to the second, then the contents of register
+ *r* are executed.
+
+ If either or both of the values are not numbers, dc(1) will raise an error
+ and reset (see the **RESET** section).
+
+**!=**_r_**e**_s_
+
+: Like the above, but will execute register *s* if the comparison fails.
+
+ If either or both of the values are not numbers, dc(1) will raise an error
+ and reset (see the **RESET** section).
+
+ This is a **non-portable extension**.
+
+**?**
+
+: Reads a line from the **stdin** and executes it. This is to allow macros to
+ request input from users.
+
+**q**
+
+: During execution of a macro, this exits the execution of that macro and the
+ execution of the macro that executed it. If there are no macros, or only one
+ macro executing, dc(1) exits.
+
+**Q**
+
+: Pops a value from the stack which must be non-negative and is used the
+ number of macro executions to pop off of the execution stack. If the number
+ of levels to pop is greater than the number of executing macros, dc(1)
+ exits.
+
+**,**
+
+: Pushes the depth of the execution stack onto the stack. The execution stack
+ is the stack of string executions. The number that is pushed onto the stack
+ is exactly as many as is needed to make dc(1) exit with the **Q** command,
+ so the sequence **,Q** will make dc(1) exit.
+
+## Status
+
+These commands query status of the stack or its top value.
+
+**Z**
+
+: Pops a value off of the stack.
+
+ If it is a number, calculates the number of significant decimal digits it
+ has and pushes the result. It will push **1** if the argument is **0** with
+ no decimal places.
+
+ If it is a string, pushes the number of characters the string has.
+
+**X**
+
+: Pops a value off of the stack.
+
+ If it is a number, pushes the *scale* of the value onto the stack.
+
+ If it is a string, pushes **0**.
+
+**z**
+
+: Pushes the current depth of the stack (before execution of this command)
+ onto the stack.
+
+**y**_r_
+
+: Pushes the current stack depth of the register *r* onto the main stack.
+
+ Because each register has a depth of **1** (with the value **0** in the top
+ item) when dc(1) starts, dc(1) requires that each register's stack must
+ always have at least one item; dc(1) will give an error and reset otherwise
+ (see the **RESET** section). This means that this command will never push
+ **0**.
+
+ This is a **non-portable extension**.
+
+## Arrays
+
+These commands manipulate arrays.
+
+**:**_r_
+
+: Pops the top two values off of the stack. The second value will be stored in
+ the array *r* (see the **REGISTERS** section), indexed by the first value.
+
+**;**_r_
+
+: Pops the value on top of the stack and uses it as an index into the array
+ *r*. The selected value is then pushed onto the stack.
+
+**Y**_r_
+
+: Pushes the length of the array *r* onto the stack.
+
+ This is a **non-portable extension**.
+
+## Global Settings
+
+These commands retrieve global settings. These are the only commands that
+require multiple specific characters, and all of them begin with the letter
+**g**. Only the characters below are allowed after the character **g**; any
+other character produces a parse error (see the **ERRORS** section).
+
+**gl**
+
+: Pushes the line length set by **DC_LINE_LENGTH** (see the **ENVIRONMENT
+ VARIABLES** section) onto the stack.
+
+**gz**
+
+: Pushes **0** onto the stack if the leading zero setting has not been enabled
+ with the **-z** or **-\-leading-zeroes** options (see the **OPTIONS**
+ section), non-zero otherwise.
+
+# REGISTERS
+
+Registers are names that can store strings, numbers, and arrays. (Number/string
+registers do not interfere with array registers.)
+
+Each register is also its own stack, so the current register value is the top of
+the stack for the register. All registers, when first referenced, have one value
+(**0**) in their stack, and it is a runtime error to attempt to pop that item
+off of the register stack.
+
+In non-extended register mode, a register name is just the single character that
+follows any command that needs a register name. The only exceptions are: a
+newline (**'\\n'**) and a left bracket (**'['**); it is a parse error for a
+newline or a left bracket to be used as a register name.
+
+## Extended Register Mode
+
+Unlike most other dc(1) implentations, this dc(1) provides nearly unlimited
+amounts of registers, if extended register mode is enabled.
+
+If extended register mode is enabled (**-x** or **-\-extended-register**
+command-line arguments are given), then normal single character registers are
+used *unless* the character immediately following a command that needs a
+register name is a space (according to **isspace()**) and not a newline
+(**'\\n'**).
+
+In that case, the register name is found according to the regex
+**\[a-z\]\[a-z0-9\_\]\*** (like bc(1) identifiers), and it is a parse error if
+the next non-space characters do not match that regex.
+
+# RESET
+
+When dc(1) encounters an error or a signal that it has a non-default handler
+for, it resets. This means that several things happen.
+
+First, any macros that are executing are stopped and popped off the stack.
+The behavior is not unlike that of exceptions in programming languages. Then
+the execution point is set so that any code waiting to execute (after all
+macros returned) is skipped.
+
+Thus, when dc(1) resets, it skips any remaining code waiting to be executed.
+Then, if it is interactive mode, and the error was not a fatal error (see the
+**EXIT STATUS** section), it asks for more input; otherwise, it exits with the
+appropriate return code.
+
+# PERFORMANCE
+
+Most dc(1) implementations use **char** types to calculate the value of **1**
+decimal digit at a time, but that can be slow. This dc(1) does something
+different.
+
+It uses large integers to calculate more than **1** decimal digit at a time. If
+built in a environment where **DC_LONG_BIT** (see the **LIMITS** section) is
+**64**, then each integer has **9** decimal digits. If built in an environment
+where **DC_LONG_BIT** is **32** then each integer has **4** decimal digits. This
+value (the number of decimal digits per large integer) is called
+**DC_BASE_DIGS**.
+
+In addition, this dc(1) uses an even larger integer for overflow checking. This
+integer type depends on the value of **DC_LONG_BIT**, but is always at least
+twice as large as the integer type used to store digits.
+
+# LIMITS
+
+The following are the limits on dc(1):
+
+**DC_LONG_BIT**
+
+: The number of bits in the **long** type in the environment where dc(1) was
+ built. This determines how many decimal digits can be stored in a single
+ large integer (see the **PERFORMANCE** section).
+
+**DC_BASE_DIGS**
+
+: The number of decimal digits per large integer (see the **PERFORMANCE**
+ section). Depends on **DC_LONG_BIT**.
+
+**DC_BASE_POW**
+
+: The max decimal number that each large integer can store (see
+ **DC_BASE_DIGS**) plus **1**. Depends on **DC_BASE_DIGS**.
+
+**DC_OVERFLOW_MAX**
+
+: The max number that the overflow type (see the **PERFORMANCE** section) can
+ hold. Depends on **DC_LONG_BIT**.
+
+**DC_BASE_MAX**
+
+: The maximum output base. Set at **DC_BASE_POW**.
+
+**DC_DIM_MAX**
+
+: The maximum size of arrays. Set at **SIZE_MAX-1**.
+
+**DC_SCALE_MAX**
+
+: The maximum **scale**. Set at **DC_OVERFLOW_MAX-1**.
+
+**DC_STRING_MAX**
+
+: The maximum length of strings. Set at **DC_OVERFLOW_MAX-1**.
+
+**DC_NAME_MAX**
+
+: The maximum length of identifiers. Set at **DC_OVERFLOW_MAX-1**.
+
+**DC_NUM_MAX**
+
+: The maximum length of a number (in decimal digits), which includes digits
+ after the decimal point. Set at **DC_OVERFLOW_MAX-1**.
+
+{{ A H N HN }}
+**DC_RAND_MAX**
+
+: The maximum integer (inclusive) returned by the **'** command, if dc(1). Set
+ at **2\^DC_LONG_BIT-1**.
+{{ end }}
+
+Exponent
+
+: The maximum allowable exponent (positive or negative). Set at
+ **DC_OVERFLOW_MAX**.
+
+Number of vars
+
+: The maximum number of vars/arrays. Set at **SIZE_MAX-1**.
+
+These limits are meant to be effectively non-existent; the limits are so large
+(at least on 64-bit machines) that there should not be any point at which they
+become a problem. In fact, memory should be exhausted before these limits should
+be hit.
+
+# ENVIRONMENT VARIABLES
+
+dc(1) recognizes the following environment variables:
+
+**DC_ENV_ARGS**
+
+: This is another way to give command-line arguments to dc(1). They should be
+ in the same format as all other command-line arguments. These are always
+ processed first, so any files given in **DC_ENV_ARGS** will be processed
+ before arguments and files given on the command-line. This gives the user
+ the ability to set up "standard" options and files to be used at every
+ invocation. The most useful thing for such files to contain would be useful
+ functions that the user might want every time dc(1) runs. Another use would
+ be to use the **-e** option to set **scale** to a value other than **0**.
+
+ The code that parses **DC_ENV_ARGS** will correctly handle quoted arguments,
+ but it does not understand escape sequences. For example, the string
+ **"/home/gavin/some dc file.dc"** will be correctly parsed, but the string
+ **"/home/gavin/some \"dc\" file.dc"** will include the backslashes.
+
+ The quote parsing will handle either kind of quotes, **'** or **"**. Thus,
+ if you have a file with any number of single quotes in the name, you can use
+ double quotes as the outside quotes, as in **"some 'dc' file.dc"**, and vice
+ versa if you have a file with double quotes. However, handling a file with
+ both kinds of quotes in **DC_ENV_ARGS** is not supported due to the
+ complexity of the parsing, though such files are still supported on the
+ command-line where the parsing is done by the shell.
+
+**DC_LINE_LENGTH**
+
+: If this environment variable exists and contains an integer that is greater
+ than **1** and is less than **UINT16_MAX** (**2\^16-1**), dc(1) will output
+ lines to that length, including the backslash newline combo. The default
+ line length is **70**.
+
+ The special value of **0** will disable line length checking and print
+ numbers without regard to line length and without backslashes and newlines.
+
+**DC_SIGINT_RESET**
+
+: If dc(1) is not in interactive mode (see the **INTERACTIVE MODE** section),
+ then this environment variable has no effect because dc(1) exits on
+ **SIGINT** when not in interactive mode.
+
+ However, when dc(1) is in interactive mode, then if this environment
+ variable exists and contains an integer, a non-zero value makes dc(1) reset
+ on **SIGINT**, rather than exit, and zero makes dc(1) exit. If this
+ environment variable exists and is *not* an integer, then dc(1) will exit on
+ **SIGINT**.
+
+ This environment variable overrides the default, which can be queried with
+ the **-h** or **-\-help** options.
+
+**DC_TTY_MODE**
+
+: If TTY mode is *not* available (see the **TTY MODE** section), then this
+ environment variable has no effect.
+
+ However, when TTY mode is available, then if this environment variable
+ exists and contains an integer, then a non-zero value makes dc(1) use TTY
+ mode, and zero makes dc(1) not use TTY mode.
+
+ This environment variable overrides the default, which can be queried with
+ the **-h** or **-\-help** options.
+
+**DC_PROMPT**
+
+: If TTY mode is *not* available (see the **TTY MODE** section), then this
+ environment variable has no effect.
+
+ However, when TTY mode is available, then if this environment variable
+ exists and contains an integer, a non-zero value makes dc(1) use a prompt,
+ and zero or a non-integer makes dc(1) not use a prompt. If this environment
+ variable does not exist and **DC_TTY_MODE** does, then the value of the
+ **DC_TTY_MODE** environment variable is used.
+
+ This environment variable and the **DC_TTY_MODE** environment variable
+ override the default, which can be queried with the **-h** or **-\-help**
+ options.
+
+**DC_EXPR_EXIT**
+
+: If any expressions or expression files are given on the command-line with
+ **-e**, **-\-expression**, **-f**, or **-\-file**, then if this environment
+ variable exists and contains an integer, a non-zero value makes dc(1) exit
+ after executing the expressions and expression files, and a non-zero value
+ makes dc(1) not exit.
+
+ This environment variable overrides the default, which can be queried with
+ the **-h** or **-\-help** options.
+
+# EXIT STATUS
+
+dc(1) returns the following exit statuses:
+
+**0**
+
+: No error.
+
+**1**
+
+: A math error occurred. This follows standard practice of using **1** for
+ expected errors, since math errors will happen in the process of normal
+ execution.
+
+ Math errors include divide by **0**, taking the square root of a negative
+{{ A H N HN }}
+ number, using a negative number as a bound for the pseudo-random number
+ generator, attempting to convert a negative number to a hardware integer,
+ overflow when converting a number to a hardware integer, overflow when
+ calculating the size of a number, and attempting to use a non-integer where
+ an integer is required.
+
+ Converting to a hardware integer happens for the second operand of the power
+ (**\^**), places (**\@**), left shift (**H**), and right shift (**h**)
+ operators.
+{{ end }}
+{{ E EH EN EHN }}
+ number, attempting to convert a negative number to a hardware integer,
+ overflow when converting a number to a hardware integer, overflow when
+ calculating the size of a number, and attempting to use a non-integer where
+ an integer is required.
+
+ Converting to a hardware integer happens for the second operand of the power
+ (**\^**) operator.
+{{ end }}
+
+**2**
+
+: A parse error occurred.
+
+ Parse errors include unexpected **EOF**, using an invalid character, failing
+ to find the end of a string or comment, and using a token where it is
+ invalid.
+
+**3**
+
+: A runtime error occurred.
+
+ Runtime errors include assigning an invalid number to any global (**ibase**,
+ **obase**, or **scale**), giving a bad expression to a **read()** call,
+ calling **read()** inside of a **read()** call, type errors (including
+ attempting to execute a number), and attempting an operation when the stack
+ has too few elements.
+
+**4**
+
+: A fatal error occurred.
+
+ Fatal errors include memory allocation errors, I/O errors, failing to open
+ files, attempting to use files that do not have only ASCII characters (dc(1)
+ only accepts ASCII characters), attempting to open a directory as a file,
+ and giving invalid command-line options.
+
+The exit status **4** is special; when a fatal error occurs, dc(1) always exits
+and returns **4**, no matter what mode dc(1) is in.
+
+The other statuses will only be returned when dc(1) is not in interactive mode
+(see the **INTERACTIVE MODE** section), since dc(1) resets its state (see the
+**RESET** section) and accepts more input when one of those errors occurs in
+interactive mode. This is also the case when interactive mode is forced by the
+**-i** flag or **-\-interactive** option.
+
+These exit statuses allow dc(1) to be used in shell scripting with error
+checking, and its normal behavior can be forced by using the **-i** flag or
+**-\-interactive** option.
+
+# INTERACTIVE MODE
+
+Like bc(1), dc(1) has an interactive mode and a non-interactive mode.
+Interactive mode is turned on automatically when both **stdin** and **stdout**
+are hooked to a terminal, but the **-i** flag and **-\-interactive** option can
+turn it on in other situations.
+
+In interactive mode, dc(1) attempts to recover from errors (see the **RESET**
+section), and in normal execution, flushes **stdout** as soon as execution is
+done for the current input. dc(1) may also reset on **SIGINT** instead of exit,
+depending on the contents of, or default for, the **DC_SIGINT_RESET**
+environment variable (see the **ENVIRONMENT VARIABLES** section).
+
+# TTY MODE
+
+If **stdin**, **stdout**, and **stderr** are all connected to a TTY, then "TTY
+mode" is considered to be available, and thus, dc(1) can turn on TTY mode,
+subject to some settings.
+
+If there is the environment variable **DC_TTY_MODE** in the environment (see the
+**ENVIRONMENT VARIABLES** section), then if that environment variable contains a
+non-zero integer, dc(1) will turn on TTY mode when **stdin**, **stdout**, and
+**stderr** are all connected to a TTY. If the **DC_TTY_MODE** environment
+variable exists but is *not* a non-zero integer, then dc(1) will not turn TTY
+mode on.
+
+If the environment variable **DC_TTY_MODE** does *not* exist, the default
+setting is used. The default setting can be queried with the **-h** or
+**-\-help** options.
+
+TTY mode is different from interactive mode because interactive mode is required
+in the [bc(1) specification][1], and interactive mode requires only **stdin**
+and **stdout** to be connected to a terminal.
+
+{{ A E N EN }}
+## Command-Line History
+
+Command-line history is only enabled if TTY mode is, i.e., that **stdin**,
+**stdout**, and **stderr** are connected to a TTY and the **DC_TTY_MODE**
+environment variable (see the **ENVIRONMENT VARIABLES** section) and its default
+do not disable TTY mode. See the **COMMAND LINE HISTORY** section for more
+information.
+{{ end }}
+
+## Prompt
+
+If TTY mode is available, then a prompt can be enabled. Like TTY mode itself, it
+can be turned on or off with an environment variable: **DC_PROMPT** (see the
+**ENVIRONMENT VARIABLES** section).
+
+If the environment variable **DC_PROMPT** exists and is a non-zero integer, then
+the prompt is turned on when **stdin**, **stdout**, and **stderr** are connected
+to a TTY and the **-P** and **-\-no-prompt** options were not used. The read
+prompt will be turned on under the same conditions, except that the **-R** and
+**-\-no-read-prompt** options must also not be used.
+
+However, if **DC_PROMPT** does not exist, the prompt can be enabled or disabled
+with the **DC_TTY_MODE** environment variable, the **-P** and **-\-no-prompt**
+options, and the **-R** and **-\-no-read-prompt** options. See the **ENVIRONMENT
+VARIABLES** and **OPTIONS** sections for more details.
+
+# SIGNAL HANDLING
+
+Sending a **SIGINT** will cause dc(1) to do one of two things.
+
+If dc(1) is not in interactive mode (see the **INTERACTIVE MODE** section), or
+the **DC_SIGINT_RESET** environment variable (see the **ENVIRONMENT VARIABLES**
+section), or its default, is either not an integer or it is zero, dc(1) will
+exit.
+
+However, if dc(1) is in interactive mode, and the **DC_SIGINT_RESET** or its
+default is an integer and non-zero, then dc(1) will stop executing the current
+input and reset (see the **RESET** section) upon receiving a **SIGINT**.
+
+Note that "current input" can mean one of two things. If dc(1) is processing
+input from **stdin** in interactive mode, it will ask for more input. If dc(1)
+is processing input from a file in interactive mode, it will stop processing the
+file and start processing the next file, if one exists, or ask for input from
+**stdin** if no other file exists.
+
+This means that if a **SIGINT** is sent to dc(1) as it is executing a file, it
+can seem as though dc(1) did not respond to the signal since it will immediately
+start executing the next file. This is by design; most files that users execute
+when interacting with dc(1) have function definitions, which are quick to parse.
+If a file takes a long time to execute, there may be a bug in that file. The
+rest of the files could still be executed without problem, allowing the user to
+continue.
+
+**SIGTERM** and **SIGQUIT** cause dc(1) to clean up and exit, and it uses the
+{{ A E N EN }}
+default handler for all other signals. The one exception is **SIGHUP**; in that
+case, and only when dc(1) is in TTY mode (see the **TTY MODE** section), a
+**SIGHUP** will cause dc(1) to clean up and exit.
+{{ end }}
+{{ H EH HN EHN }}
+default handler for all other signals.
+{{ end }}
+
+{{ A E N EN }}
+# COMMAND LINE HISTORY
+
+dc(1) supports interactive command-line editing.
+
+If dc(1) can be in TTY mode (see the **TTY MODE** section), history can be
+enabled. This means that command-line history can only be enabled when
+**stdin**, **stdout**, and **stderr** are all connected to a TTY.
+
+Like TTY mode itself, it can be turned on or off with the environment variable
+**DC_TTY_MODE** (see the **ENVIRONMENT VARIABLES** section).
+
+**Note**: tabs are converted to 8 spaces.
+{{ end }}
+
+{{ A E H EH }}
+# LOCALES
+
+This dc(1) ships with support for adding error messages for different locales
+and thus, supports **LC_MESSAGES**.
+{{ end }}
+
+# SEE ALSO
+
+bc(1)
+
+# STANDARDS
+
+The dc(1) utility operators are compliant with the operators in the bc(1)
+[IEEE Std 1003.1-2017 (“POSIX.1-2017”)][1] specification.
+
+# BUGS
+
+None are known. Report bugs at https://git.yzena.com/gavin/bc.
+
+# AUTHOR
+
+Gavin D. Howard <gavin@yzena.com> and contributors.
+
+[1]: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html
diff --git a/contrib/bc/manuals/development.md b/contrib/bc/manuals/development.md
new file mode 100644
index 000000000000..6733d496defd
--- /dev/null
+++ b/contrib/bc/manuals/development.md
@@ -0,0 +1,5110 @@
+# Development
+
+Updated: 06 Oct 2021
+
+This document is meant for the day when I (Gavin D. Howard) get [hit by a
+bus][1]. In other words, it's meant to make the [bus factor][1] a non-issue.
+
+This document is supposed to contain all of the knowledge necessary to develop
+`bc` and `dc`.
+
+In addition, this document is meant to add to the [oral tradition of software
+engineering][118], as described by Bryan Cantrill.
+
+This document will reference other parts of the repository. That is so a lot of
+the documentation can be closest to the part of the repo where it is actually
+necessary.
+
+## What Is It?
+
+This repository contains an implementation of both [POSIX `bc`][2] and [Unix
+`dc`][3].
+
+POSIX `bc` is a standard utility required for POSIX systems. `dc` is a
+historical utility that was included in early Unix and even predates both Unix
+and C. They both are arbitrary-precision command-line calculators with their own
+programming languages. `bc`'s language looks similar to C, with infix notation
+and including functions, while `dc` uses [Reverse Polish Notation][4] and allows
+the user to execute strings as though they were functions.
+
+In addition, it is also possible to build the arbitrary-precision math as a
+library, named [`bcl`][156].
+
+**Note**: for ease, I will refer to both programs as `bc` in this document.
+However, if I say "just `bc`," I am referring to just `bc`, and if I say `dc`, I
+am referring to just `dc`.
+
+### History
+
+This project started in January 2018 when a certain individual on IRC, hearing
+that I knew how to write parsers, asked me to write a `bc` parser for his math
+library. I did so. I thought about writing my own math library, but he
+disparaged my programming skills and made me think that I couldn't do it.
+
+However, he took so long to do it that I eventually decided to give it a try and
+had a working math portion in two weeks. It taught me that I should not listen
+to such people.
+
+From that point, I decided to make it an extreme learning experience about how
+to write quality software.
+
+That individual's main goal had been to get his `bc` into [toybox][16], and I
+managed to get my own `bc` in. I also got it in [busybox][17].
+
+Eventually, in late 2018, I also decided to try my hand at implementing
+[Karatsuba multiplication][18], an algorithm that that unnamed individual
+claimed I could never implement. It took me a bit, but I did it.
+
+This project became a passion project for me, and I continued. In mid-2019,
+Stefan Eßer suggested I improve performance by putting more than 1 digit in each
+section of the numbers. After I showed immaturity because of some burnout, I
+implemented his suggestion, and the results were incredible.
+
+Since that time, I have gradually been improving the `bc` as I have learned more
+about things like fuzzing, [`scan-build`][19], [valgrind][20],
+[AddressSanitizer][21] (and the other sanitizers), and many other things.
+
+One of my happiest moments was when my `bc` was made the default in FreeBSD.
+
+But since I believe in [finishing the software I write][22], I have done less
+work on `bc` over time, though there are still times when I put a lot of effort
+in, such as now (17 June 2021), when I am attempting to convince OpenBSD to use
+my `bc`.
+
+And that is why I am writing this document: someday, someone else is going to
+want to change my code, and this document is my attempt to make it as simple as
+possible.
+
+### Values
+
+[According to Bryan Cantrill][10], all software has values. I think he's
+correct, though I [added one value for programming languages in particular][11].
+
+However, for `bc`, his original list will do:
+
+* Approachability
+* Availability
+* Compatibility
+* Composability
+* Debuggability
+* Expressiveness
+* Extensibility
+* Interoperability
+* Integrity
+* Maintainability
+* Measurability
+* Operability
+* Performance
+* Portability
+* Resiliency
+* Rigor
+* Robustness
+* Safety
+* Security
+* Simplicity
+* Stability
+* Thoroughness
+* Transparency
+* Velocity
+
+There are several values that don't apply. The reason they don't apply is
+because `bc` and `dc` are existing utilities; this is just another
+reimplementation. The designs of `bc` and `dc` are set in stone; there is
+nothing we can do to change them, so let's get rid of those values that would
+apply to their design:
+
+* Compatibility
+* Integrity
+* Maintainability
+* Measurability
+* Performance
+* Portability
+* Resiliency
+* Rigor
+* Robustness
+* Safety
+* Security
+* Simplicity
+* Stability
+* Thoroughness
+* Transparency
+
+Furthermore, some of the remaining ones don't matter to me, so let me get rid of
+those and order the rest according to my *actual* values for this project:
+
+* Robustness
+* Stability
+* Portability
+* Compatibility
+* Performance
+* Security
+* Simplicity
+
+First is **robustness**. This `bc` and `dc` should be robust, accepting any
+input, never crashing, and instead, returning an error.
+
+Closely related to that is **stability**. The execution of `bc` and `dc` should
+be deterministic and never change for the same inputs, including the
+pseudo-random number generator (for the same seed).
+
+Third is **portability**. These programs should run everywhere that POSIX
+exists, as well as Windows. This means that just about every person on the
+planet will have access to these programs.
+
+Next is **compatibility**. These programs should, as much as possible, be
+compatible with other existing implementations and standards.
+
+Then we come to **performance**. A calculator is only usable if it's fast, so
+these programs should run as fast as possible.
+
+After that is **security**. These programs should *never* be the reason a user's
+computer is compromised.
+
+And finally, **simplicity**. Where possible, the code should be simple, while
+deferring to the above values.
+
+Keep these values in mind for the rest of this document, and for exploring any
+other part of this repo.
+
+#### Portability
+
+But before I go on, I want to talk about portability in particular.
+
+Most of these principles just require good attention and care, but portability
+is different. Sometimes, it requires pulling in code from other places and
+adapting it. In other words, sometimes I need to duplicate and adapt code.
+
+This happened in a few cases:
+
+* Option parsing (see [`include/opt.h`][35]).
+* History (see [`include/history.h`][36]).
+* Pseudo-Random Number Generator (see [`include/rand.h`][37]).
+
+This was done because I decided to ensure that `bc`'s dependencies were
+basically zero. In particular, either users have a normal install of Windows or
+they have a POSIX system.
+
+A POSIX system limited me to C99, `sh`, and zero external dependencies. That
+last item is why I pull code into `bc`: if I pull it in, it's not an external
+dependency.
+
+That's why `bc` has duplicated code. Remove it, and you risk `bc` not being
+portable to some platforms.
+
+## Suggested Course
+
+I do have a suggested course for programmers to follow when trying to understand
+this codebase. The order is this:
+
+1. `bc` Spec.
+2. Manpages.
+3. Test suite.
+4. Understand the build.
+5. Algorithms manual.
+6. Code concepts.
+7. Repo structure.
+8. Headers.
+9. Source code.
+
+This order roughly follows this order:
+
+1. High-level requirements
+2. Low-level requirements
+3. High-level implementation
+4. Low-level implementation
+
+In other words, first understand what the code is *supposed* to do, then
+understand the code itself.
+
+## Useful External Tools
+
+I have a few tools external to `bc` that are useful:
+
+* A [Vim plugin with syntax files made specifically for my `bc` and `dc`][132].
+* A [repo of `bc` and `dc` scripts][133].
+* A set of `bash` aliases (see below).
+* A `.bcrc` file with items useful for my `bash` setup (see below).
+
+My `bash` aliases are these:
+
+```sh
+alias makej='make -j16'
+alias mcmake='make clean && make'
+alias mcmakej='make clean && make -j16'
+alias bcdebug='CPPFLAGS="-DBC_DEBUG_CODE=1" CFLAGS="-Weverything -Wno-padded \
+ -Wno-switch-enum -Wno-format-nonliteral -Wno-cast-align \
+ -Wno-unreachable-code-return -Wno-missing-noreturn \
+ -Wno-disabled-macro-expansion -Wno-unreachable-code -Wall -Wextra \
+ -pedantic -std=c99" ./configure.sh'
+alias bcconfig='CFLAGS="-Weverything -Wno-padded -Wno-switch-enum \
+ -Wno-format-nonliteral -Wno-cast-align -Wno-unreachable-code-return \
+ -Wno-missing-noreturn -Wno-disabled-macro-expansion -Wno-unreachable-code \
+ -Wall -Wextra -pedantic -std=c99" ./configure.sh'
+alias bcnoassert='CPPFLAGS="-DNDEBUG" CFLAGS="-Weverything -Wno-padded \
+ -Wno-switch-enum -Wno-format-nonliteral -Wno-cast-align \
+ -Wno-unreachable-code-return -Wno-missing-noreturn \
+ -Wno-disabled-macro-expansion -Wno-unreachable-code -Wall -Wextra \
+ -pedantic -std=c99" ./configure.sh'
+alias bcdebugnoassert='CPPFLAGS="-DNDEBUG -DBC_DEBUG_CODE=1" \
+ CFLAGS="-Weverything -Wno-padded -Wno-switch-enum -Wno-format-nonliteral \
+ -Wno-cast-align -Wno-unreachable-code-return -Wno-missing-noreturn \
+ -Wno-disabled-macro-expansion -Wno-unreachable-code -Wall -Wextra \
+ -pedantic -std=c99" ./configure.sh'
+alias bcunset='unset BC_LINE_LENGTH && unset BC_ENV_ARGS'
+```
+
+`makej` runs `make` with all of my cores.
+
+`mcmake` runs `make clean` before running `make`. It will take a target on the
+command-line.
+
+`mcmakej` is a combination of `makej` and `mcmake`.
+
+`bcdebug` configures `bc` for a full debug build, including `BC_DEBUG_CODE` (see
+[Debugging][134] below).
+
+`bcconfig` configures `bc` with Clang (Clang is my personal default compiler)
+using full warnings, with a few really loud and useless warnings turned off.
+
+`bcnoassert` configures `bc` to not have asserts built in.
+
+`bcdebugnoassert` is like `bcnoassert`, except it also configures `bc` for debug
+mode.
+
+`bcunset` unsets my personal `bc` environment variables, which are set to:
+
+```sh
+export BC_ENV_ARGS="-l $HOME/.bcrc"
+export BC_LINE_LENGTH="74"
+```
+
+Unsetting these environment variables are necessary for running
+[`scripts/release.sh`][83] because otherwise, it will error when attempting to
+run `bc -s` on my `$HOME/.bcrc`.
+
+Speaking of which, the contents of that file are:
+
+```bc
+define void print_time_unit(t){
+ if(t<10)print "0"
+ if(t<1&&t)print "0"
+ print t,":"
+}
+define void sec2time(t){
+ auto s,m,h,d,r
+ r=scale
+ scale=0
+ t=abs(t)
+ s=t%60
+ t-=s
+ m=t/60%60
+ t-=m
+ h=t/3600%24
+ t-=h
+ d=t/86400
+ if(d)print_time_unit(d)
+ if(h)print_time_unit(h)
+ print_time_unit(m)
+ if(s<10)print "0"
+ if(s<1&&s)print "0"
+ s
+ scale=r
+}
+define minutes(secs){
+ return secs/60;
+}
+define hours(secs){
+ return secs/3600;
+}
+define days(secs){
+ return secs/3600/24;
+}
+define years(secs){
+ return secs/3600/24/365.25;
+}
+define fbrand(b,p){
+ auto l,s,t
+ b=abs(b)$
+ if(b<2)b=2
+ s=scale
+ t=b^abs(p)$
+ l=ceil(l2(t),0)
+ if(l>scale)scale=l
+ t=irand(t)/t
+ scale=s
+ return t
+}
+define ifbrand(i,b,p){return irand(abs(i)$)+fbrand(b,p)}
+```
+
+This allows me to use `bc` as part of my `bash` prompt.
+
+## Code Style
+
+The code style for `bc` is...weird, and that comes from historical accident.
+
+In [History][23], I mentioned how I got my `bc` in [toybox][16]. Well, in order
+to do that, my `bc` originally had toybox style. Eventually, I changed to using
+tabs, and assuming they were 4 spaces wide, but other than that, I basically
+kept the same style, with some exceptions that are more or less dependent on my
+taste.
+
+The code style is as follows:
+
+* Tabs are 4 spaces.
+* Tabs are used at the beginning of lines for indent.
+* Spaces are used for alignment.
+* Lines are limited to 80 characters, period.
+* Pointer asterisk (`*`) goes with the variable (on the right), not the type,
+ unless it is for a pointer type returned from a function.
+* The opening brace is put on the same line as the header for the function,
+ loop, or `if` statement.
+* Unless the header is more than one line, in which case the opening brace is
+ put on its own line.
+* If the opening brace is put on its own line, there is no blank line after it.
+* If the opening brace is *not* put on its own line, there *is* a blank line
+ after it, *unless* the block is only one or two lines long.
+* Code lines are grouped into what I call "paragraphs." Basically, lines that
+ seem like they should go together are grouped together. This one comes down
+ to judgment.
+* Bodies of `if` statements, `else` statements, and loops that are one line
+ long are put on the same line as the statement, unless the header is more than
+ one line long, and/or, the header and body cannot fit into 80 characters with
+ a space inbetween them.
+* If single-line bodies are on a separate line from their headers, and the
+ headers are only a single line, then no braces are used.
+* However, braces are *always* used if they contain another `if` statement or
+ loop.
+* Loops with empty bodies are ended with a semicolon.
+* Expressions that return a boolean value are surrounded by paretheses.
+* Macro backslashes are aligned as far to the left as possible.
+* Binary operators have spaces on both sides.
+* If a line with binary operators overflows 80 characters, a newline is inserted
+ *after* binary operators.
+* Function modifiers and return types are on the same line as the function name.
+* With one exception, `goto`'s are only used to jump to the end of a function
+ for cleanup.
+* All structs, enums, and unions are `typedef`'ed.
+* All constant data is in one file: [`src/data.c`][131], but the corresponding
+ `extern` declarations are in the appropriate header file.
+* All local variables are declared at the beginning of the scope where they
+ appear. They may be initialized at that point, if it does not invoke UB or
+ otherwise cause bugs.
+* All precondition `assert()`'s (see [Asserts][135]) come *after* local variable
+ declarations.
+* Besides short `if` statements and loops, there should *never* be more than one
+ statement per line.
+
+### ClangFormat
+
+I attempted three times to use [ClangFormat][24] to impose a standard,
+machine-useful style on `bc`. All three failed. Otherwise, the style in this
+repo would be more consistent.
+
+## Repo Structure
+
+Functions are documented with Doxygen-style doc comments. Functions that appear
+in headers are documented in the headers, while static functions are documented
+where they are defined.
+
+### `configure`
+
+A symlink to [`configure.sh`][69].
+
+### `configure.sh`
+
+This is the script to configure `bc` and [`bcl`][156] for building.
+
+This `bc` has a custom build system. The reason for this is because of
+[*portability*][136].
+
+If `bc` used an outside build system, that build system would be an external
+dependency. Thus, I had to write a build system for `bc` that used nothing but
+C99 and POSIX utilities.
+
+One of those utilities is POSIX `sh`, which technically implements a
+Turing-complete programming language. It's a terrible one, but it works.
+
+A user that wants to build `bc` on a POSIX system (not Windows) first runs
+`configure.sh` with the options he wants. `configure.sh` uses those options and
+the `Makefile` template ([`Makefile.in`][70]) to generate an actual valid
+`Makefile`. Then `make` can do the rest.
+
+For more information about the build process, see the [Build System][142]
+section and the [build manual][14].
+
+For more information about shell scripts, see [POSIX Shell Scripts][76].
+
+`configure.sh` does the following:
+
+1. It processes command-line arguments and figure out what the user wants to
+ build.
+2. It reads in [`Makefile.in`][70].
+3. One-by-one, it replaces placeholders (in [`Makefile.in`][70]) of the form
+ `%%<placeholder_name>%%` based on the [build type][81].
+4. It appends a list of file targets based on the [build type][81].
+5. It appends the correct test targets.
+6. It copies the correct manpage and markdown manual for `bc` and `dc` into a
+ location from which they can be copied for install.
+7. It does a `make clean` to reset the build state.
+
+### `.gitattributes`
+
+A `.gitattributes` file. This is needed to preserve the `crlf` line endings in
+the Visual Studio files.
+
+### `.gitignore`
+
+The `.gitignore`
+
+### `LICENSE.md`
+
+This is the `LICENSE` file, including the licenses of various software that I
+have borrowed.
+
+### `Makefile.in`
+
+This is the `Makefile` template for [`configure.sh`][69] to use for generating a
+`Makefile`.
+
+For more information, see [`configure.sh`][69], the [Build System][142] section,
+and the [build manual][14].
+
+Because of [portability][136], the generated `Makefile.in` should be a pure
+[POSIX `make`][74]-compatible `Makefile` (minus the placeholders). Here are a
+few snares for the unwary programmer in this file:
+
+1. No extensions allowed, including and especially GNU extensions.
+2. If new headers are added, they must also be added to `Makefile.in`.
+3. Don't delete the `.POSIX:` empty target at the top; that's what tells `make`
+ implementations that pure [POSIX `make`][74] is needed.
+
+In particular, there is no way to set up variables other than the `=` operator.
+There are no conditionals, so all of the conditional stuff must be in
+[`configure.sh`][69]. This is, in fact, why [`configure.sh`][69] exists in the
+first place: [POSIX `make`][74] is barebones and only does a build with no
+configuration.
+
+### `NEWS.md`
+
+A running changelog with an entry for each version. This should be updated at
+the same time that [`include/version.h`][75] is.
+
+### `NOTICE.md`
+
+The `NOTICE` file with proper attributions.
+
+### `README.md`
+
+The `README`. Read it.
+
+### `benchmarks/`
+
+The folder containing files to generate benchmarks.
+
+Each of these files was made, at one time or another, to benchmark some
+experimental feature, so if it seems there is no rhyme or reason to these
+benchmarks, it is because there is none, besides historical accident.
+
+#### `bc/`
+
+The folder containing `bc` scripts to generate `bc` benchmarks.
+
+##### `add.bc`
+
+The file to generate the benchmark to benchmark addition in `bc`.
+
+##### `arrays_and_constants.bc`
+
+The file to generate the benchmark to benchmark `bc` using lots of array names
+and constants.
+
+##### `arrays.bc`
+
+The file to generate the benchmark to benchmark `bc` using lots of array names.
+
+##### `constants.bc`
+
+The file to generate the benchmark to benchmark `bc` using lots of constants.
+
+##### `divide.bc`
+
+The file to generate the benchmark to benchmark division in `bc`.
+
+##### `functions.bc`
+
+The file to generate the benchmark to benchmark `bc` using lots of functions.
+
+##### `irand_long.bc`
+
+The file to generate the benchmark to benchmark `bc` using lots of calls to
+`irand()` with large bounds.
+
+##### `irand_short.bc`
+
+The file to generate the benchmark to benchmark `bc` using lots of calls to
+`irand()` with small bounds.
+
+##### `lib.bc`
+
+The file to generate the benchmark to benchmark `bc` using lots of calls to
+heavy functions in `lib.bc`.
+
+##### `multiply.bc`
+
+The file to generate the benchmark to benchmark multiplication in `bc`.
+
+##### `postfix_incdec.bc`
+
+The file to generate the benchmark to benchmark `bc` using postfix increment and
+decrement operators.
+
+##### `power.bc`
+
+The file to generate the benchmark to benchmark power (exponentiation) in `bc`.
+
+##### `subtract.bc`
+
+The file to generate the benchmark to benchmark subtraction in `bc`.
+
+##### `strings.bc`
+
+The file to generate the benchmark to benchmark `bc` using lots of strings.
+
+#### `dc/`
+
+The folder containing `dc` scripts to generate `dc` benchmarks.
+
+##### `modexp.dc`
+
+The file to generate the benchmark to benchmark modular exponentiation in `dc`.
+
+### `gen/`
+
+A folder containing the files necessary to generate C strings that will be
+embedded in the executable.
+
+All of the files in this folder have license headers, but the program and script
+that can generate strings from them include code to strip the license header out
+before strings are generated.
+
+#### `bc_help.txt`
+
+A text file containing the text displayed for `bc -h` or `bc --help`.
+
+This text just contains the command-line options and a short summary of the
+differences from GNU and BSD `bc`'s. It also directs users to the manpage.
+
+The reason for this is because otherwise, the help would be far too long to be
+useful.
+
+**Warning**: The text has some `printf()` format specifiers. You need to make
+sure the format specifiers match the arguments given to `bc_file_printf()`.
+
+#### `dc_help.txt`
+
+A text file containing the text displayed for `dc -h` or `dc --help`.
+
+This text just contains the command-line options and a short summary of the
+differences from GNU and BSD `dc`'s. It also directs users to the manpage.
+
+The reason for this is because otherwise, the help would be far too long to be
+useful.
+
+**Warning**: The text has some `printf()` format specifiers. You need to make
+sure the format specifiers match the arguments given to `bc_file_printf()`.
+
+#### `lib.bc`
+
+A `bc` script containing the [standard math library][5] required by POSIX. See
+the [POSIX standard][2] for what is required.
+
+This file does not have any extraneous whitespace, except for tabs at the
+beginning of lines. That is because this data goes directly into the binary,
+and whitespace is extra bytes in the binary. Thus, not having any extra
+whitespace shrinks the resulting binary.
+
+However, tabs at the beginning of lines are kept for two reasons:
+
+1. Readability. (This file is still code.)
+2. The program and script that generate strings from this file can remove
+ tabs at the beginning of lines.
+
+For more details about the algorithms used, see the [algorithms manual][25].
+
+However, there are a few snares for unwary programmers.
+
+First, all constants must be one digit. This is because otherwise, multi-digit
+constants could be interpreted wrongly if the user uses a different `ibase`.
+This does not happen with single-digit numbers because they are guaranteed to be
+interpreted what number they would be if the `ibase` was as high as possible.
+
+This is why `A` is used in the library instead of `10`, and things like `2*9*A`
+for `180` in [`lib2.bc`][26].
+
+As an alternative, you can set `ibase` in the function, but if you do, make sure
+to set it with a single-digit number and beware the snare below...
+
+Second, `scale`, `ibase`, and `obase` must be safely restored before returning
+from any function in the library. This is because without the `-g` option,
+functions are allowed to change any of the globals.
+
+Third, all local variables in a function must be declared in an `auto` statement
+before doing anything else. This includes arrays. However, function parameters
+are considered predeclared.
+
+Fourth, and this is only a snare for `lib.bc`, not [`lib2.bc`][26], the code
+must not use *any* extensions. It has to work when users use the `-s` or `-w`
+flags.
+
+#### `lib2.bc`
+
+A `bc` script containing the [extended math library][7].
+
+Like [`lib.bc`][8], and for the same reasons, this file should have no
+extraneous whitespace, except for tabs at the beginning of lines.
+
+For more details about the algorithms used, see the [algorithms manual][25].
+
+Also, be sure to check [`lib.bc`][8] for the snares that can trip up unwary
+programmers when writing code for `lib2.bc`.
+
+#### `strgen.c`
+
+Code for the program to generate C strings from text files. This is the original
+program, although [`strgen.sh`][9] was added later.
+
+The reason I used C here is because even though I knew `sh` would be available
+(it must be available to run `configure.sh`), I didn't know how to do what I
+needed to do with POSIX utilities and `sh`.
+
+Later, [`strgen.sh`][9] was contributed by Stefan Eßer of FreeBSD, showing that
+it *could* be done with `sh` and POSIX utilities.
+
+However, `strgen.c` exists *still* exists because the versions generated by
+[`strgen.sh`][9] may technically hit an environmental limit. (See the [draft C99
+standard][12], page 21.) This is because [`strgen.sh`][9] generates string
+literals, and in C99, string literals can be limited to 4095 characters, and
+`gen/lib2.bc` is above that.
+
+Fortunately, the limit for "objects," which include `char` arrays, is much
+bigger: 65535 bytes, so that's what `strgen.c` generates.
+
+However, the existence of `strgen.c` does come with a cost: the build needs C99
+compiler that targets the host machine. For more information, see the ["Cross
+Compiling" section][13] of the [build manual][14].
+
+Read the comments in `strgen.c` for more detail about it, the arguments it
+takes, and how it works.
+
+#### `strgen.sh`
+
+An `sh` script that will generate C strings that uses only POSIX utilities. This
+exists for those situations where a host C99 compiler is not available, and the
+environment limits mentioned above in [`strgen.c`][15] don't matter.
+
+`strgen.sh` takes the same arguments as [`strgen.c`][15], and the arguments mean
+the exact same things, so see the comments in [`strgen.c`][15] for more detail
+about that, and see the comments in `strgen.sh` for more details about it and
+how it works.
+
+For more information about shell scripts, see [POSIX Shell Scripts][76].
+
+### `include/`
+
+A folder containing the headers.
+
+The headers are not included among the source code because I like it better that
+way. Also there were folders within `src/` at one point, and I did not want to
+see `#include "../some_header.h"` or things like that.
+
+So all headers are here, even though only one ([`bcl.h`][30]) is meant for end
+users (to be installed in `INCLUDEDIR`).
+
+#### `args.h`
+
+This file is the API for processing command-line arguments.
+
+#### `bc.h`
+
+This header is the API for `bc`-only items. This includes the `bc_main()`
+function and the `bc`-specific lexing and parsing items.
+
+The `bc` parser is perhaps the most sensitive part of the entire codebase. See
+the documentation in `bc.h` for more information.
+
+The code associated with this header is in [`src/bc.c`][40],
+[`src/bc_lex.c`][41], and [`src/bc_parse.c`][42].
+
+#### `bcl.h`
+
+This header is the API for the [`bcl`][156] library.
+
+This header is meant for distribution to end users and contains the API that end
+users of [`bcl`][156] can use in their own software.
+
+This header, because it's the public header, is also the root header. That means
+that it has platform-specific fixes for Windows. (If the fixes were not in this
+header, the build would fail on Windows.)
+
+The code associated with this header is in [`src/library.c`][43].
+
+#### `dc.h`
+
+This header is the API for `dc`-only items. This includes the `dc_main()`
+function and the `dc`-specific lexing and parsing items.
+
+The code associated with this header is in [`src/dc.c`][44],
+[`src/dc_lex.c`][45], and [`src/dc_parse.c`][46].
+
+#### `file.h`
+
+This header is for `bc`'s internal buffered I/O API.
+
+For more information about `bc`'s error handling and custom buffered I/O, see
+[Error Handling][97] and [Custom I/O][114], along with [`status.h`][176] and the
+notes about version [`3.0.0`][32] in the [`NEWS`][32].
+
+The code associated with this header is in [`src/file.c`][47].
+
+#### `history.h`
+
+This header is for `bc`'s implementation of command-line editing/history, which
+is based on a [UTF-8-aware fork][28] of [`linenoise`][29].
+
+For more information, see the [Command-Line History][189] section.
+
+The code associated with this header is in [`src/history.c`][48].
+
+#### `lang.h`
+
+This header defines the data structures and bytecode used for actual execution
+of `bc` and `dc` code.
+
+Yes, it's misnamed; that's an accident of history where the first things I put
+into it all seemed related to the `bc` language.
+
+The code associated with this header is in [`src/lang.c`][49].
+
+#### `lex.h`
+
+This header defines the common items that both programs need for lexing.
+
+The code associated with this header is in [`src/lex.c`][50],
+[`src/bc_lex.c`][41], and [`src/dc_lex.c`][45].
+
+#### `library.h`
+
+This header defines the things needed for [`bcl`][156] that users should *not*
+have access to. In other words, [`bcl.h`][30] is the *public* header for the
+library, and this header is the *private* header for the library.
+
+The code associated with this header is in [`src/library.c`][43].
+
+#### `num.h`
+
+This header is the API for numbers and math.
+
+The code associated with this header is in [`src/num.c`][39].
+
+#### `opt.h`
+
+This header is the API for parsing command-line arguments.
+
+It's different from [`args.h`][31] in that [`args.h`][31] is for the main code
+to process the command-line arguments into global data *after* they have already
+been parsed by `opt.h` into proper tokens. In other words, `opt.h` actually
+parses the command-line arguments, and [`args.h`][31] turns that parsed data
+into flags (bits), strings, and expressions that will be used later.
+
+Why are they separate? Because originally, `bc` used `getopt_long()` for
+parsing, so [`args.h`][31] was the only one that existed. After it was
+discovered that `getopt_long()` has different behavior on different platforms, I
+adapted a [public-domain option parsing library][34] to do the job instead. And
+in doing so, I gave it its own header.
+
+They could probably be combined, but I don't really care enough at this point.
+
+The code associated with this header is in [`src/opt.c`][51].
+
+#### `parse.h`
+
+This header defines the common items that both programs need for parsing.
+
+Note that the parsers don't produce abstract syntax trees (AST's) or any
+intermediate representations. They produce bytecode directly. In other words,
+they don't have special data structures except what they need to do their job.
+
+The code associated with this header is in [`src/parse.c`][50],
+[`src/bc_lex.c`][42], and [`src/dc_lex.c`][46].
+
+#### `program.h`
+
+This header defines the items needed to manage the data structures in
+[`lang.h`][38] as well as any helper functions needed to generate bytecode or
+execute it.
+
+The code associated with this header is in [`src/program.c`][53].
+
+#### `rand.h`
+
+This header defines the API for the [pseudo-random number generator
+(PRNG)][179].
+
+The PRNG only generates fixed-size integers. The magic of generating random
+numbers of arbitrary size is actually given to the code that does math
+([`src/num.c`][39]).
+
+The code associated with this header is in [`src/rand.c`][54].
+
+#### `read.h`
+
+This header defines the API for reading from files and `stdin`.
+
+Thus, [`file.h`][55] is really for buffered *output*, while this file is for
+*input*. There is no buffering needed for `bc`'s inputs.
+
+The code associated with this header is in [`src/read.c`][56].
+
+#### `status.h`
+
+This header has several things:
+
+* A list of possible errors that internal `bc` code can use.
+* Compiler-specific fixes.
+* Platform-specific fixes.
+* Macros for `bc`'s [error handling][97].
+
+There is no code associated with this header.
+
+#### `vector.h`
+
+This header defines the API for the vectors (resizable arrays) that are used for
+data structures.
+
+Vectors are what do the heavy lifting in almost all of `bc`'s data structures.
+Even the maps of identifiers and arrays use vectors.
+
+#### `version.h`
+
+This header defines the version of `bc`.
+
+There is no code associated with this header.
+
+#### `vm.h`
+
+This header defines the API for setting up and running `bc` and `dc`.
+
+It is so named because I think of it as the "virtual machine" of `bc`, though
+that is probably not true as [`program.h`][57] is probably the "virtual machine"
+API. Thus, the name is more historical accident.
+
+The code associated with this header is in [`src/vm.c`][58].
+
+### `locales/`
+
+This folder contains a bunch of `.msg` files and soft links to the real `.msg`
+files. This is how locale support is implemented in `bc`.
+
+The files are in the format required by the [`gencat`][59] POSIX utility. They
+all have the same messages, in the same order, with the same numbering, under
+the same groups. This is because the locale system expects those messages in
+that order.
+
+The softlinks exist because for many locales, they would contain the exact same
+information. To prevent duplication, they are simply linked to a master copy.
+
+The naming format for all files is:
+
+```
+<language_code>_<country_code>.<encoding>.msg
+```
+
+This naming format must be followed for all locale files.
+
+### `manuals/`
+
+This folder contains the documentation for `bc`, `dc`, and [`bcl`][156], along
+with a few other manuals.
+
+#### `algorithms.md`
+
+This file explains the mathematical algorithms that are used.
+
+The hope is that this file will guide people in understanding how the math code
+works.
+
+#### `bc.1.md.in`
+
+This file is a template for the markdown version of the `bc` manual and
+manpages.
+
+For more information about how the manpages and markdown manuals are generated,
+and for why, see [`scripts/manpage.sh`][60] and [Manuals][86].
+
+#### `bcl.3`
+
+This is the manpage for the [`bcl`][156] library. It is generated from
+[`bcl.3.md`][61] using [`scripts/manpage.sh`][60].
+
+For the reason why I check generated data into the repo, see
+[`scripts/manpage.sh`][60] and [Manuals][86].
+
+#### `bcl.3.md`
+
+This is the markdown manual for the [`bcl`][156] library. It is the source for the
+generated [`bcl.3`][62] file.
+
+#### `benchmarks.md`
+
+This is a document that compares this `bc` to GNU `bc` in various benchmarks. It
+was last updated when version [`3.0.0`][32] was released.
+
+It has very little documentation value, other than showing what compiler options
+are useful for performance.
+
+#### `build.md`
+
+This is the [build manual][14].
+
+This `bc` has a custom build system. The reason for this is because of
+[*portability*][136].
+
+If `bc` used an outside build system, that build system would be an external
+dependency. Thus, I had to write a build system for `bc` that used nothing but
+C99 and POSIX utilities, including barebones [POSIX `make`][74].
+
+for more information about the build system, see the [build system][142]
+section, the [build manual][14], [`configure.sh`][69], and [`Makefile.in`][70].
+
+#### `dc.1.md.in`
+
+This file is a template for the markdown version of the `dc` manual and
+manpages.
+
+For more information about how the manpages and markdown manuals are generated,
+and for why, see [`scripts/manpage.sh`][60] and [Manuals][86].
+
+#### `development.md`
+
+The file you are reading right now.
+
+#### `header_bcl.txt`
+
+Used by [`scripts/manpage.sh`][60] to give the [`bcl.3`][62] manpage a proper
+header.
+
+For more information about generating manuals, see [`scripts/manpage.sh`][60]
+and [Manuals][86].
+
+#### `header_bc.txt`
+
+Used by [`scripts/manpage.sh`][60] to give the [generated `bc` manpages][79] a
+proper header.
+
+For more information about generating manuals, see [`scripts/manpage.sh`][60]
+and [Manuals][86].
+
+#### `header_dc.txt`
+
+Used by [`scripts/manpage.sh`][60] to give the [generated `dc` manpages][80] a
+proper header.
+
+For more information about generating manuals, see [`scripts/manpage.sh`][60]
+and [Manuals][86].
+
+#### `header.txt`
+
+Used by [`scripts/manpage.sh`][60] to give all generated manpages a license
+header.
+
+For more information about generating manuals, see [`scripts/manpage.sh`][60]
+and [Manuals][86].
+
+#### `release.md`
+
+A checklist that I try to somewhat follow when making a release.
+
+#### `bc/`
+
+A folder containing the `bc` manuals.
+
+Each `bc` manual corresponds to a [build type][81]. See that link for more
+details.
+
+For each manual, there are two copies: the markdown version generated from the
+template, and the manpage generated from the markdown version.
+
+#### `dc/`
+
+A folder containing the `dc` manuals.
+
+Each `dc` manual corresponds to a [build type][81]. See that link for more
+details.
+
+For each manual, there are two copies: the markdown version generated from the
+template, and the manpage generated from the markdown version.
+
+### `scripts/`
+
+This folder contains helper scripts. Most of them are written in pure [POSIX
+`sh`][72], but one ([`karatsuba.py`][78]) is written in Python 3.
+
+For more information about the shell scripts, see [POSIX Shell Scripts][76].
+
+#### `afl.py`
+
+This script is meant to be used as part of the fuzzing workflow.
+
+It does one of two things: checks for valid crashes, or runs `bc` and or `dc`
+under all of the paths found by [AFL++][125].
+
+See [Fuzzing][82] for more information about fuzzing, including this script.
+
+#### `alloc.sh`
+
+This script is a quick and dirty script to test whether or not the garbage
+collection mechanism of the [`BcNum` caching][96] works. It has been little-used
+because it tests something that is not important to correctness.
+
+#### `benchmark.sh`
+
+A script making it easy to run benchmarks and to run the executable produced by
+[`ministat.c`][223] on them.
+
+For more information, see the [Benchmarks][144] section.
+
+#### `bitfuncgen.c`
+
+A source file for an executable to generate tests for `bc`'s bitwise functions
+in [`gen/lib2.bc`][26]. The executable is `scripts/bitfuncgen`, and it is built
+with `make bitfuncgen`. It produces the test on `stdout` and the expected
+results on `stderr`. This means that to generat tests, use the following
+invokation:
+
+```
+scripts/bitfuncgen > tests/bc/bitfuncs.txt 2> tests/bc/bitfuncs_results.txt
+```
+
+It calls `abort()` if it runs into an error.
+
+#### `exec-install.sh`
+
+This script is the magic behind making sure `dc` is installed properly if it's
+a symlink to `bc`. It checks to see if it is a link, and if so, it just creates
+a new symlink in the install directory. Of course, it also installs `bc` itself,
+or `dc` when it's alone.
+
+#### `functions.sh`
+
+This file is a bunch of common functions for most of the POSIX shell scripts. It
+is not supposed to be run; instead, it is *sourced* by other POSIX shell
+scripts, like so:
+
+```
+. "$scriptdir/functions.sh"
+```
+
+or the equivalent, depending on where the sourcing script is.
+
+For more information about the shell scripts, see [POSIX Shell Scripts][76].
+
+#### `fuzz_prep.sh`
+
+Fuzzing is a regular activity when I am preparing for a release.
+
+This script handles all the options and such for building a fuzzable binary.
+Instead of having to remember a bunch of options, I just put them in this script
+and run the script when I want to fuzz.
+
+For more information about fuzzing, see [Fuzzing][82].
+
+#### `karatsuba.py`
+
+This script has at least one of two major differences from most of the other
+scripts:
+
+* It's written in Python 3.
+* It's meant for software packagers.
+
+For example, [`scripts/afl.py`][94] and [`scripts/randmath.py`][95] are both in
+Python 3, but they are not meant for the end user or software packagers and are
+not included in source distributions. But this script is.
+
+This script breaks my rule of only POSIX utilities necessary for package
+maintainers, but there's a very good reason for that: it's only meant to be run
+*once* when the package is created for the first time, and maybe not even then.
+
+You see, this script does two things: it tests the Karatsuba implementation at
+various settings for `KARATSUBA_LEN`, and it figures out what the optimal
+`KARATSUBA_LEN` is for the machine that it is running on.
+
+Package maintainers can use this script, when creating a package for this `bc`,
+to figure out what is optimal for their users. Then they don't have to run it
+ever again. So this script only has to run on the packagers machine.
+
+I tried to write the script in `sh`, by the way, and I finally accepted the
+tradeoff of using Python 3 when it became too hard.
+
+However, I also mentioned that it's for testing Karatsuba with various settings
+of `KARATSUBA_LEN`. Package maintainers will want to run the [test suite][124],
+right?
+
+Yes, but this script is not part of the [test suite][124]; it's used for testing
+in the [`scripts/release.sh`][83] script, which is maintainer use only.
+
+However, there is one snare with `karatsuba.py`: I didn't want the user to have
+to install any Python libraries to run it. Keep that in mind if you change it.
+
+#### `link.sh`
+
+This script is the magic behind making `dc` a symlink of `bc` when both
+calculators are built.
+
+#### `locale_install.sh`
+
+This script does what its name says: it installs locales.
+
+It turns out that this is complicated.
+
+There is a magic environment variable, `$NLSPATH`, that tells you how and where
+you are supposed to install locales.
+
+Yes, *how*. And where.
+
+But now is not the place to rant about `$NLSPATH`. For more information on
+locales and `$NLSPATH`, see [Locales][85].
+
+#### `locale_uninstall.sh`
+
+This script does what its name says: it uninstalls locales.
+
+This is far less complicated than installing locales. I basically generate a
+wildcard path and then list all paths that fit that wildcard. Then I delete each
+one of those paths. Easy.
+
+For more information on locales, see [Locales][85].
+
+#### `manpage.sh`
+
+This script is the one that generates markdown manuals from a template and a
+manpage from a markdown manual.
+
+For more information about generating manuals, see [Manuals][86].
+
+#### `ministat.c`
+
+This is a file copied [from FreeBSD][221] that calculates the standard
+statistical numbers, such as mean, average, and median, based on numbers
+obtained from a file.
+
+For more information, see the [FreeBSD ministat(1) manpage][222].
+
+This file allows `bc` to build the `scripts/ministat` executable using the
+command `make ministat`, and this executable helps programmers evaluate the
+results of [benchmarks][144] more accurately.
+
+#### `package.sh`
+
+This script is what helps `bc` maintainers cut a release. It does the following:
+
+1. Creates the appropriate `git` tag.
+2. Pushes the `git` tag.
+3. Copies the repo to a temp directory.
+4. Removes files that should not be included in source distributions.
+5. Creates the tarballs.
+6. Signs the tarballs.
+7. Zips and signs the Windows executables if they exist.
+8. Calculates and outputs SHA512 and SHA256 sums for all of the files,
+ including the signatures.
+
+This script is for `bc` maintainers to use when cutting a release. It is not
+meant for outside use. This means that some non-POSIX utilities can be used,
+such as `git` and `gpg`.
+
+In addition, before using this script, it expects that the folders that Windows
+generated when building `bc`, `dc`, and [`bcl`][156], are in the parent
+directory of the repo, exactly as Windows generated them. If they are not there,
+then it will not zip and sign, nor calculate sums of, the Windows executables.
+
+Because this script creates a tag and pushes it, it should *only* be run *ONCE*
+per release.
+
+#### `radamsa.sh`
+
+A script to test `bc`'s command-line expression parsing code, which, while
+simple, strives to handle as much as possible.
+
+What this script does is it uses the test cases in [`radamsa.txt`][98] an input
+to the [Radamsa fuzzer][99].
+
+For more information, see the [Radamsa][128] section.
+
+#### `radamsa.txt`
+
+Initial test cases for the [`radamsa.sh`][100] script.
+
+#### `randmath.py`
+
+This script generates random math problems and checks that `bc`'s and `dc`'s
+output matches the GNU `bc` and `dc`. (For this reason, it is necessary to have
+GNU `bc` and `dc` installed before using this script.)
+
+One snare: be sure that this script is using the GNU `bc` and `dc`, not a
+previously-installed version of this `bc` and `dc`.
+
+If you want to check for memory issues or failing asserts, you can build the
+`bc` using `./scripts/fuzz_prep.sh -a`, and then run it under this script. Any
+errors or crashes should be caught by the script and given to the user as part
+of the "checklist" (see below).
+
+The basic idea behind this script is that it generates as many math problems as
+it can, biasing towards situations that may be likely to have bugs, and testing
+each math problem against GNU `bc` or `dc`.
+
+If GNU `bc` or `dc` fails, it just continues. If this `bc` or `dc` fails, it
+stores that problem. If the output mismatches, it also stores the problem.
+
+Then, when the user sends a `SIGINT`, the script stops testing and goes into
+report mode. One-by-one, it will go through the "checklist," the list of failed
+problems, and present each problem to the user, as well as whether this `bc` or
+`dc` crashed, and its output versus GNU. Then the user can decide to add them as
+test cases, which it does automatically to the appropriate test file.
+
+#### `release_settings.txt`
+
+A text file of settings combinations that [`release.sh`][83] uses to ensure that
+`bc` and `dc` build and work with various default settings. [`release.sh`][83]
+simply reads it line by line and uses each line for one build.
+
+#### `release.sh`
+
+This script is for `bc` maintainers only. It runs `bc`, `dc`, and [`bcl`][156]
+through a gauntlet that is mostly meant to be used in preparation for a release.
+
+It does the following:
+
+1. Builds every [build type][81], with every setting combo in
+ [`release_settings.txt`][93] with both calculators, `bc` alone, and `dc`
+ alone.
+2. Builds every [build type][81], with every setting combo in
+ [`release_settings.txt`][93] with both calculators, `bc` alone, and `dc`
+ alone for 32-bit.
+3. Does #1 and #2 for Debug, Release, Release with Debug Info, and Min Size
+ Release builds.
+4. Runs the [test suite][124] on every build, if desired.
+5. Runs the [test suite][124] under [ASan, UBSan, and MSan][21] for every build
+ type/setting combo.
+6. Runs [`scripts/karatsuba.py`][78] in test mode.
+7. Runs the [test suite][124] for both calculators, `bc` alone, and `dc` alone
+ under [valgrind][20] and errors if there are any memory bugs or memory
+ leaks.
+
+#### `safe-install.sh`
+
+A script copied from [musl][101] to atomically install files.
+
+#### `test_settings.sh`
+
+A quick and dirty script to help automate rebuilding while manually testing the
+various default settings.
+
+This script uses [`test_settings.txt`][103] to generate the various settings
+combos.
+
+For more information about settings, see [Settings][102] in the [build
+manual][14].
+
+#### `test_settings.txt`
+
+A list of the various settings combos to be used by [`test_settings.sh`][104].
+
+### `src/`
+
+This folder is, obviously, where the actual heart and soul of `bc`, the source
+code, is.
+
+All of the source files are in one folder; this simplifies the build system
+immensely.
+
+There are separate files for `bc` and `dc` specific code ([`bc.c`][40],
+[`bc_lex.c`][41], [`bc_parse.c`][42], [`dc.c`][44], [`dc_lex.c`][45], and
+[`dc_parse.c`][46]) where possible because it is cleaner to exclude an entire
+source file from a build than to have `#if`/`#endif` preprocessor guards.
+
+That said, it was easier in many cases to use preprocessor macros where both
+calculators used much of the same code and data structures, so there is a
+liberal sprinkling of them through the code.
+
+#### `args.c`
+
+Code for processing command-line arguments.
+
+The header for this file is [`include/args.h`][31].
+
+#### `bc.c`
+
+The code for the `bc` main function `bc_main()`.
+
+The header for this file is [`include/bc.h`][106].
+
+#### `bc_lex.c`
+
+The code for lexing that only `bc` needs.
+
+The headers for this file are [`include/lex.h`][180] and [`include/bc.h`][106].
+
+#### `bc_parse.c`
+
+The code for parsing that only `bc` needs. This code is the most complex and
+subtle in the entire codebase.
+
+The headers for this file are [`include/parse.h`][181] and
+[`include/bc.h`][106].
+
+#### `data.c`
+
+Due to [historical accident][23] because of a desire to get my `bc` into
+[toybox][16], all of the constant data that `bc` needs is all in one file. This
+is that file.
+
+There is no code in this file, but a lot of the const data has a heavy influence
+on code, including the order of data in arrays because that order has to
+correspond to the order of other things elsewhere in the codebase. If you change
+the order of something in this file, run `make test`, and get errors, you
+changed something that depends on the order that you messed up.
+
+Almost all headers have `extern` references to items in this file.
+
+#### `dc.c`
+
+The code for the `dc` main function `dc_main()`.
+
+The header for this file is [`include/dc.h`][182].
+
+#### `dc_lex.c`
+
+The code for lexing that only `dc` needs.
+
+The headers for this file are [`include/lex.h`][180] and [`include/dc.h`][182].
+
+#### `dc_parse.c`
+
+The code for parsing that only `dc` needs.
+
+The headers for this file are [`include/parse.h`][181] and
+[`include/bc.h`][182].
+
+#### `file.c`
+
+The code for `bc`'s implementation of buffered I/O. For more information about
+why I implemented my own buffered I/O, see [`include/file.h`][55], [Error
+Handling][97], and [Custom I/O][114], along with [`status.h`][176] and the notes
+about version [`3.0.0`][32] in the [`NEWS`][32].
+
+The header for this file is [`include/file.h`][55].
+
+#### `history.c`
+
+The code for `bc`'s implementation of command-line editing/history, which is
+based on a [UTF-8-aware fork][28] of [`linenoise`][29].
+
+For more information, see the [Command-Line History][189] section.
+
+The header for this file is [`include/history.h`][36].
+
+#### `lang.c`
+
+The data structures used for actual execution of `bc` and `dc` code.
+
+While execution is done in [`src/program.c`][53], this file defines functions
+for initializing, copying, and freeing the data structures, which is somewhat
+orthogonal to actual execution.
+
+Yes, it's misnamed; that's an accident of history where the first things I put
+into it all seemed related to the `bc` language.
+
+The header for this file is [`include/lang.h`][38].
+
+#### `lex.c`
+
+The code for the common things that both programs need for lexing.
+
+The header for this file is [`include/lex.h`][180].
+
+#### `library.c`
+
+The code to implement the public API of the `bcl` library.
+
+The code in this file does a lot to ensure that clients do not have to worry
+about internal `bc` details, especially error handling with `setjmp()` and
+`longjmp()`. That and encapsulating the handling of numbers are the bulk of what
+the code in this file actually does because most of the library is still
+implemented in [`src/num.c`][39].
+
+The headers for this file are [`include/bcl.h`][30] and
+[`include/library.h`][183].
+
+#### `main.c`
+
+The entry point for both programs; this is the `main()` function.
+
+This file has no headers associated with it.
+
+#### `num.c`
+
+The code for all of the arbitrary-precision [numbers][177] and [math][178] in
+`bc`.
+
+The header for this file is [`include/num.h`][184].
+
+#### `opt.c`
+
+The code for parsing command-line options.
+
+The header for this file is [`include/opt.h`][35].
+
+#### `parse.c`
+
+The code for the common items that both programs need for parsing.
+
+The header for this file is [`include/parse.h`][181].
+
+#### `program.c`
+
+The code for the actual execution engine for `bc` and `dc` code.
+
+The header for this file is [`include/program.h`][57].
+
+#### `rand.c`
+
+The code for the [pseudo-random number generator (PRNG)][179] and the special
+stack handling it needs.
+
+The PRNG only generates fixed-size integers. The magic of generating random
+numbers of arbitrary size is actually given to the code that does math
+([`src/num.c`][39]).
+
+The header for this file is [`include/rand.h`][37].
+
+#### `read.c`
+
+The code for reading from files and `stdin`.
+
+The header for this file is [`include/read.h`][185].
+
+#### `vector.c`
+
+The code for [vectors][111], [maps][186], and [slab vectors][187], along with
+slabs.
+
+The header for this file is [`include/vector.h`][174].
+
+#### `vm.c`
+
+The code for setting up and running `bc` and `dc`.
+
+It is so named because I think of it as the "virtual machine" of `bc`, though
+that is probably not true as [`program.h`][57] is probably the "virtual machine"
+code. Thus, the name is more historical accident.
+
+The header for this file is [`include/vm.h`][27].
+
+### `tests/`
+
+This directory contains the entire [test suite][124] and its infrastructure.
+
+#### `all.sh`
+
+A convenience script for the `make run_all_tests` target (see the [Group
+Tests][141] section for more information).
+
+#### `all.txt`
+
+The file with the names of the calculators. This is to make it easier for the
+test scripts to know where the standard and other test directories are.
+
+#### `bcl.c`
+
+The test for the [`bcl`][156] API. For more information, see the [`bcl`
+Test][157] section.
+
+#### `error.sh`
+
+The script to run the file-based error tests in `tests/<calculator>/errors/` for
+each calculator. For more information, see the [Error Tests][151] section.
+
+This is a separate script so that each error file can be run separately and in
+parallel.
+
+#### `errors.sh`
+
+The script to run the line-based error tests in `tests/<calculator>/errors.txt`
+for each calculator. For more information, see the [Error Tests][151] section.
+
+#### `extra_required.txt`
+
+The file with the list of tests which both calculators have that need the [Extra
+Math build option][188]. This exists to make it easy for test scripts to skip
+those tests when the [Extra Math build option][188] is disabled.
+
+#### `history.py`
+
+The file with all of the history tests. For more information, see the [History
+Tests][155] section.
+
+#### `history.sh`
+
+The script to integrate [`history.py`][139] into the build system in a portable
+way, and to skip it if necessary.
+
+This script also re-runs the test three times if it fails. This is because
+`pexpect` can be flaky at times.
+
+#### `other.sh`
+
+The script to run the "other" (miscellaneous) tests for each calculator. For
+more information, see the [Other Tests][154] section.
+
+#### `read.sh`
+
+The script to run the read tests for each calculator. For more information, see
+the [`read()` Tests][153] section.
+
+#### `script.sed`
+
+The `sed` script to edit the output of GNU `bc` when generating script tests.
+For more information, see the [Script Tests][150] section.
+
+#### `script.sh`
+
+The script for running one script test. For more information, see the [Script
+Tests][150] section.
+
+#### `scripts.sh`
+
+The script to help the `make run_all_tests` (see the [Group Tests][141] section)
+run all of the script tests.
+
+#### `stdin.sh`
+
+The script to run the `stdin` tests for each calculator. For more information,
+see the [`stdin` Tests][152] section.
+
+#### `test.sh`
+
+The script to run one standard test. For more information, see the [Standard
+Tests][149] section.
+
+#### `bc/`
+
+The standard tests directory for `bc`. For more information, see the [Standard
+Tests][149] section.
+
+##### `all.txt`
+
+The file to tell the build system and `make run_all_tests` (see the [Group
+Tests][141] section) what standard tests to run for `bc`, as well as in what
+order.
+
+This file just lists the test names, one per line.
+
+##### `errors.txt`
+
+The initial error test file for `bc`. This file has one test per line. See the
+[Error Tests][151] section for more information.
+
+##### `posix_errors.txt`
+
+The file of tests for POSIX compatibility for `bc`. This file has one test per
+line. For more information, see the [Error Tests][151] section.
+
+##### `timeconst.sh`
+
+The script to run the `bc` tests that use the [Linux `timeconst.bc` script][6].
+For more information, see the [Linux `timeconst.bc` Script][191]section.
+
+##### `errors/`
+
+The directory with error tests for `bc`, most discovered by AFL++ (see the
+[Fuzzing][82] section). There is one test per file. For more information, see
+the [Error Tests][151] section.
+
+##### `scripts/`
+
+The script tests directory for `bc`. For more information, see the [Script
+Tests][150] section.
+
+###### `all.txt`
+
+A file to tell the build system and `make run_all_tests` (see the [Group
+Tests][141] section) what script tests to run for `bc`, as well as in what
+order.
+
+This file just lists the test names, one per line.
+
+#### `dc/`
+
+The standard tests directory for `dc`. For more information, see the [Standard
+Tests][149] section.
+
+##### `all.txt`
+
+The file to tell the build system and `make run_all_tests` (see the [Group
+Tests][141] section) what standard tests to run for `dc`, as well as in what
+order.
+
+This file just lists the test names, one per line.
+
+##### `errors.txt`
+
+The initial error test file for `dc`. This file has one test per line. See the
+[Error Tests][151] section for more information.
+
+##### `read_errors.txt`
+
+The file of tests errors with the `?` command (`read()` in `bc`). This file has
+one test per line. See the [Error Tests][151] section for more information.
+
+##### `errors/`
+
+The directory with error tests for `dc`, most discovered by AFL++ (see the
+[Fuzzing][82] section). There is one test per file. For more information, see
+the [Error Tests][151] section.
+
+##### `scripts/`
+
+The script tests directory for `dc`. For more information, see the [Script
+Tests][150] section.
+
+###### `all.txt`
+
+The file to tell the build system and `make run_all_tests` (see the [Group
+Tests][141] section) what script tests to run for `dc`, as well as in what
+order.
+
+This file just lists the test names, one per line.
+
+#### `fuzzing/`
+
+The directory containing the fuzzing infrastructure. For more information, see
+the [Fuzzing][82] section.
+
+##### `bc_afl_continue.yaml`
+
+The [`tmuxp`][123] config (for use with [`tmux`][122]) for easily restarting a
+fuzz run. For more information, see the [Convenience][130] subsection of the
+[Fuzzing][82] section.
+
+##### `bc_afl.yaml`
+
+The [`tmuxp`][123] config (for use with [`tmux`][122]) for easily starting a
+fuzz run. For more information, see the [Convenience][130] subsection of the
+[Fuzzing][82] section.
+
+Be aware that this will delete all previous unsaved fuzzing tests in the output
+directories.
+
+##### `bc_inputs1/`
+
+The fuzzing input directory for the first third of inputs for `bc`. For more
+information, see the [Corpuses][192] subsection of the [Fuzzing][82] section.
+
+##### `bc_inputs2/`
+
+The fuzzing input directory for the second third of inputs for `bc`. For more
+information, see the [Corpuses][192] subsection of the [Fuzzing][82] section.
+
+##### `bc_inputs3/`
+
+The fuzzing input directory for the third third of inputs for `bc`. For more
+information, see the [Corpuses][192] subsection of the [Fuzzing][82] section.
+
+##### `dc_inputs/`
+
+The fuzzing input directory for the inputs for `dc`. For more information, see
+the [Corpuses][192] subsection of the [Fuzzing][82] section.
+
+### `vs/`
+
+The directory containing all of the materials needed to build `bc`, `dc`, and
+`bcl` on Windows.
+
+#### `bcl.sln`
+
+A Visual Studio solution file for [`bcl`][156]. This, along with
+[`bcl.vcxproj`][63] and [`bcl.vcxproj.filters`][64] is what makes it possible to
+build [`bcl`][156] on Windows.
+
+#### `bcl.vcxproj`
+
+A Visual Studio project file for [`bcl`][156]. This, along with [`bcl.sln`][65]
+and [`bcl.vcxproj.filters`][64] is what makes it possible to build [`bcl`][156]
+on Windows.
+
+#### `bcl.vcxproj.filters`
+
+A Visual Studio filters file for [`bcl`][156]. This, along with [`bcl.sln`][65]
+and [`bcl.vcxproj`][63] is what makes it possible to build [`bcl`][156] on
+Windows.
+
+#### `bc.sln`
+
+A Visual Studio solution file for `bc`. This, along with [`bc.vcxproj`][66]
+and [`bc.vcxproj.filters`][67] is what makes it possible to build `bc` on
+Windows.
+
+#### `bc.vcxproj`
+
+A Visual Studio project file for `bc`. This, along with [`bc.sln`][68] and
+[`bc.vcxproj.filters`][67] is what makes it possible to build `bc` on Windows.
+
+#### `bc.vcxproj.filters`
+
+A Visual Studio filters file for `bc`. This, along with [`bc.sln`][68] and
+[`bc.vcxproj`][66] is what makes it possible to build `bc` on Windows.
+
+#### `tests/`
+
+A directory of files to run tests on Windows.
+
+##### `tests_bc.bat`
+
+A file to run basic `bc` tests on Windows. It expects that it will be run from
+the directory containing it, and it also expects a `bc.exe` in the same
+directory.
+
+##### `tests_dc.bat`
+
+A file to run basic `dc` tests on Windows. It expects that it will be run from
+the directory containing it, and it also expects a `bc.exe` in the same
+directory.
+
+## Build System
+
+The build system is described in detail in the [build manual][14], so
+maintainers should start there. This section, however, describes some parts of
+the build system that only maintainers will care about.
+
+### Clean Targets
+
+`bc` has a default `make clean` target that cleans up the build files. However,
+because `bc`'s build system can generate many different types of files, there
+are other clean targets that may be useful:
+
+* `make clean_gen` cleans the `gen/strgen` executable generated from
+ [`gen/strgen.c`][15]. It has no prerequisites.
+* `make clean` cleans object files, `*.cat` files (see the [Locales][85]
+ section), executables, and files generated from text files in [`gen/`][145],
+ including `gen/strgen` if it was built. So this has a prerequisite on
+ `make clean_gen` in normal use.
+* `make clean_benchmarks` cleans [benchmarks][144], including the `ministat`
+ executable. It has no prerequisites.
+* `make clean_config` cleans the generated `Makefile` and the manuals that
+ [`configure.sh`][69] copied in preparation for install. It also depends on
+ `make clean` and `make clean_benchmarks`, so it cleans those items too. This
+ is the target that [`configure.sh`][69] uses before it does its work.
+* `make clean_coverage` cleans the generated coverage files for the [test
+ suite][124]'s [code coverage][146] capabilities. It has no prerequisites. This
+ is useful if the code coverage tools are giving errors.
+* `make clean_tests` cleans *everything*. It has prerequisites on all previous
+ clean targets, but it also cleans all of the [generated tests][143].
+
+When adding more generated files, you may need to add them to one of these
+targets and/or add a target for them especially.
+
+### Preprocessor Macros
+
+`bc` and `dc` use *a lot* of preprocessor macros to ensure that each build type:
+
+* builds,
+* works under the [test suite][124], and
+* excludes as much code as possible from all builds.
+
+This section will explain the preprocessor style of `bc` and `dc`, as well as
+provide an explanation of the macros used.
+
+#### Style
+
+The style of macro use in `bc` is pretty straightforward: I avoid depending on
+macro definitions and instead, I set defaults if the macro is not defined and
+then test the value if the macro with a plain `#if`.
+
+(Some examples of setting defaults are in [`include/status.h`][176], just above
+the definition of the `BcStatus` enum.)
+
+In other words, I use `#if` instead of `#ifndef` or `#ifdef`, where possible.
+
+There are a couple of cases where I went with standard stuff instead. For
+example, to test whether I am in debug mode or not, I still use the standard
+`#ifndef NDEBUG`.
+
+#### Standard Macros
+
+`BC_ENABLED`
+
+: This macro expands to `1` if `bc` is enabled, `0` if disabled.
+
+`DC_ENABLED`
+
+: This macro expands to `1` if `dc` is enabled, `0` if disabled.
+
+`BUILD_TYPE`
+
+: The macro expands to the build type, which is one of: `A`, `E`, `H`, `N`,
+ `EH`, `EN`, `HN`, `EHN`. This build type is used in the help text to direct
+ the user to the correct markdown manual in the `git.yzena.com` website.
+
+`EXECPREFIX`
+
+: This macro expands to the prefix on the executable name. This is used to
+ allow `bc` and `dc` to skip the prefix when finding out which calculator is
+ executing.
+
+`BC_NUM_KARATSUBA_LEN`
+
+: This macro expands to an integer, which is the length of numbers below which
+ the Karatsuba multiplication algorithm switches to brute-force
+ multiplication.
+
+`BC_ENABLE_EXTRA_MATH`
+
+: This macro expands to `1` if the [Extra Math build option][188] is enabled,
+ `0` if disabled.
+
+`BC_ENABLE_HISTORY`
+
+: This macro expands to `1` if the [History build option][193] is enabled, `0`
+ if disabled.
+
+`BC_ENABLE_NLS`
+
+: This macro expands to `1` if the [NLS build option][193] (for locales) is
+ enabled, `0` if disabled.
+
+`BC_ENABLE_LIBRARY`
+
+: This macro expands to `1` if the [`bcl` library][156] is enabled, `0` if
+ disabled. If this is enabled, building the calculators themselves is
+ disabled, but both `BC_ENABLED` and `DC_ENABLED` must be non-zero.
+
+`BC_ENABLE_MEMCHECK`
+
+: This macro expands to `1` if `bc` has been built for use with Valgrind's
+ [Memcheck][194], `0` otherwise. This ensures that fatal errors still free
+ all of their memory when exiting. `bc` does not do that normally because
+ what's the point?
+
+`BC_ENABLE_AFL`
+
+: This macro expands to `1` if `bc` has been built for fuzzing with
+ [AFL++][125], `0` otherwise. See the [Fuzzing][82] section for more
+ information.
+
+`BC_DEFAULT_BANNER`
+
+: This macro expands to the default value for displaying the `bc` banner.
+
+`BC_DEFAULT_SIGINT_RESET`
+
+: The macro expands to the default value for whether or not `bc` should reset
+ on `SIGINT` or quit.
+
+`BC_DEFAULT_TTY_MODE`
+
+: The macro expands to the default value for whether or not `bc` should use
+ TTY mode when it available.
+
+`BC_DEFAULT_PROMPT`
+
+: This macro expands to the default value for whether or not `bc` should use a
+ prompt when TTY mode is available.
+
+`DC_DEFAULT_SIGINT_RESET`
+
+: The macro expands to the default value for whether or not `dc` should reset
+ on `SIGINT` or quit.
+
+`DC_DEFAULT_TTY_MODE`
+
+: The macro expands to the default value for whether or not `dc` should use
+ TTY mode when it available.
+
+`DC_DEFAULT_PROMPT`
+
+: This macro expands to the default value for whether or not `dc` should use a
+ prompt when TTY mode is available.
+
+`BC_DEBUG_CODE`
+
+: If this macro expands to a non-zero integer, then `bc` is built with *a lot*
+ of extra debugging code. This is never set by the build system and must be
+ set by the programmer manually. This should never be set in builds given to
+ end users. For more information, see the [Debugging][134] section.
+
+## Test Suite
+
+While the source code may be the heart and soul of `bc`, the test suite is the
+arms and legs: it gives `bc` the power to do anything it needs to do.
+
+The test suite is what allowed `bc` to climb to such high heights of quality.
+This even goes for fuzzing because fuzzing depends on the test suite for its
+input corpuses. (See the [Fuzzing][82] section.)
+
+Understanding how the test suite works should be, I think, the first thing that
+maintainers learn after learning what `bc` and `dc` should do. This is because
+the test suite, properly used, gives confidence that changes have not caused
+bugs or regressions.
+
+That is why I spent the time to make the test suite as easy to use and as fast
+as possible.
+
+To use the test suite (assuming `bc` and/or `dc` are already built), run the
+following command:
+
+```
+make test
+```
+
+That's it. That's all.
+
+It will return an error code if the test suite failed. It will also print out
+information about the failure.
+
+If you want the test suite to go fast, then run the following command:
+
+```
+make -j<cores> test
+```
+
+Where `<cores>` is the number of cores that your computer has. Of course, this
+requires a `make` implementation that supports that option, but most do. (And I
+will use this convention throughout the rest of this section.)
+
+I have even tried as much as possible, to put longer-running tests near the
+beginning of the run so that the entire suite runs as fast as possible.
+
+However, if you want to be sure which test is failing, then running a bare
+`make test` is a great way to do that.
+
+But enough about how you have no excuses to use the test suite as much as
+possible; let's talk about how it works and what you *can* do with it.
+
+### Standard Tests
+
+The heavy lifting of testing the math in `bc`, as well as basic scripting, is
+done by the "standard tests" for each calculator.
+
+These tests use the files in the [`tests/bc/`][161] and [`tests/dc/`][162]
+directories (except for [`tests/bc/all.txt`][163], [`tests/bc/errors.txt`][164],
+[`tests/bc/posix_errors.txt`][165], [`tests/bc/timeconst.sh`][166],
+[`tests/dc/all.txt`][167], [`tests/dc/errors.txt`][168], and
+[`tests/dc/read_errors.txt`][175]), which are called the "standard test
+directories."
+
+For every test, there is the test file and the results file. The test files have
+names of the form `<test>.txt`, where `<test>` is the name of the test, and the
+results files have names of the form `<test>_results.txt`.
+
+If the test file exists but the results file does not, the results for that test
+are generated by a GNU-compatible `bc` or `dc`. See the [Generated Tests][143]
+section.
+
+The `all.txt` file in each standard tests directory is what tells the test suite
+and [build system][142] what tests there are, and the tests are either run in
+that order, or in the case of parallel `make`, that is the order that the
+targets are listed as prerequisites of `make test`.
+
+If the test exists in the `all.txt` file but does not *actually* exist, the test
+and its results are generated by a GNU-compatible `bc` or `dc`. See the
+[Generated Tests][143] section.
+
+To add a non-generated standard test, do the following:
+
+* Add the test file (`<test>.txt` in the standard tests directory).
+* Add the results file (`<test>_results.txt` in the standard tests directory).
+ You can skip this step if just the results file needs to be generated. See the
+ [Generated Tests][147] section for more information.
+* Add the name of the test to the `all.txt` file in the standard tests
+ directory, putting it in the order it should be in. If possible, I would put
+ longer tests near the beginning because they will start running earlier with
+ parallel `make`. I always keep `decimal` first, though, as a smoke test.
+
+If you need to add a generated standard test, see the [Generated Tests][147]
+section for how to do that.
+
+Some standard tests need to be skipped in certain cases. That is handled by the
+[build system][142]. See the [Integration with the Build System][147] section
+for more details.
+
+In addition to all of the above, the standard test directory is not only the
+directory for the standard tests of each calculator, it is also the parent
+directory of all other test directories for each calculator.
+
+#### `bc` Standard Tests
+
+The list of current (17 July 2021) standard tests for `bc` is below:
+
+decimal
+
+: Tests decimal parsing and printing.
+
+print
+
+: Tests printing in every base from decimal. This is near the top for
+ performance of parallel testing.
+
+parse
+
+: Tests parsing in any base and outputting in decimal. This is near the top
+ for performance of parallel testing.
+
+lib2
+
+: Tests the extended math library. This is near the top for performance of
+ parallel testing.
+
+print2
+
+: Tests printing at the extreme values of `obase`.
+
+length
+
+: Tests the `length()` builtin function.
+
+scale
+
+: Tests the `scale()` builtin function.
+
+shift
+
+: Tests the left (`<<`) and right (`>>`) shift operators.
+
+add
+
+: Tests addition.
+
+subtract
+
+: Tests subtraction.
+
+multiply
+
+: Tests multiplication.
+
+divide
+
+: Tests division.
+
+modulus
+
+: Tests modulus.
+
+power
+
+: Tests power (exponentiation).
+
+sqrt
+
+: Tests the `sqrt()` (square root) builtin function.
+
+trunc
+
+: Tests the truncation (`$`) operator.
+
+places
+
+: Tests the places (`@`) operator.
+
+vars
+
+: Tests some usage of variables. This one came from [AFL++][125] I think.
+
+boolean
+
+: Tests boolean operators.
+
+comp
+
+: Tests comparison operators.
+
+abs
+
+: Tests the `abs()` builtin function.
+
+assignments
+
+: Tests assignment operators, including increment/decrement operators.
+
+functions
+
+: Tests functions, specifically function parameters being replaced before they
+ themselves are used. See the comment in `bc_program_call()` about the last
+ condition.
+
+scientific
+
+: Tests scientific notation.
+
+engineering
+
+: Tests engineering notation.
+
+globals
+
+: Tests that assigning to globals affects callers.
+
+strings
+
+: Tests strings.
+
+strings2
+
+: Tests string allocation in slabs, to ensure slabs work.
+
+letters
+
+: Tests single and double letter numbers to ensure they behave differently.
+ Single-letter numbers always be set to the same value, regardless of
+ `ibase`.
+
+exponent
+
+: Tests the `e()` function in the math library.
+
+log
+
+: Tests the `l()` function in the math library.
+
+pi
+
+: Tests that `bc` produces the right value of pi for numbers with varying
+ `scale` values.
+
+arctangent
+
+: Tests the `a()` function in the math library.
+
+sine
+
+: Tests the `s()` function in the math library.
+
+cosine
+
+: Tests the `c()` function in the math library.
+
+bessel
+
+: Tests the `j()` function in the math library.
+
+arrays
+
+: Test arrays.
+
+misc
+
+: Miscellaneous tests. I named it this because at the time, I struggled to
+ classify them, but it's really testing multi-line numbers.
+
+misc1
+
+: A miscellaneous test found by [AFL++][125].
+
+misc2
+
+: A miscellaneous test found by [AFL++][125].
+
+misc3
+
+: A miscellaneous test found by [AFL++][125].
+
+misc4
+
+: A miscellaneous test found by [AFL++][125].
+
+misc5
+
+: A miscellaneous test found by [AFL++][125].
+
+misc6
+
+: A miscellaneous test found by [AFL++][125].
+
+misc7
+
+: A miscellaneous test found by [AFL++][125].
+
+void
+
+: Tests void functions.
+
+rand
+
+: Tests the pseudo-random number generator and its special stack handling.
+
+recursive_arrays
+
+: Tested the slab vector undo ability in used in `bc_parse_name()` when it
+ existed. Now used as a stress test.
+
+divmod
+
+: Tests divmod.
+
+modexp
+
+: Tests modular exponentiation.
+
+bitfuncs
+
+: Tests the bitwise functions, `band()`, `bor()`, `bxor()`, `blshift()` and
+ `brshift()` in [`gen/lib2.bc`][26].
+
+leadingzero
+
+: Tests the leading zero functionality and the `plz*()` and `pnlz*()`
+ functions in [`gen/lib2.bc`][26].
+
+#### `dc` Standard Tests
+
+The list of current (17 July 2021) standard tests for `dc` is below:
+
+decimal
+
+: Tests decimal parsing and printing.
+
+length
+
+: Tests the `length()` builtin function, including for strings and arrays.
+
+stack_len
+
+: Tests taking the length of the results stack.
+
+stack_len
+
+: Tests taking the length of the execution stack.
+
+add
+
+: Tests addition.
+
+subtract
+
+: Tests subtraction.
+
+multiply
+
+: Tests multiplication.
+
+divide
+
+: Tests division.
+
+modulus
+
+: Tests modulus.
+
+divmod
+
+: Tests divmod.
+
+power
+
+: Tests power (exponentiation).
+
+sqrt
+
+: Tests the `sqrt()` (square root) builtin function.
+
+modexp
+
+: Tests modular exponentiation.
+
+boolean
+
+: Tests boolean operators.
+
+negate
+
+: Tests negation as a command and as part of numbers.
+
+trunc
+
+: Tests the truncation (`$`) operator.
+
+places
+
+: Tests the places (`@`) operator.
+
+shift
+
+: Tests the left (`<<`) and right (`>>`) shift operators.
+
+abs
+
+: Tests the `abs()` builtin function.
+
+scientific
+
+: Tests scientific notation.
+
+engineering
+
+: Tests engineering notation.
+
+vars
+
+: Tests some usage of variables. This one came from [AFL++][125] I think.
+
+misc
+
+: Miscellaneous tests. I named it this because at the time, I struggled to
+ classify them.
+
+strings
+
+: Tests strings.
+
+rand
+
+: Tests the pseudo-random number generator and its special stack handling.
+
+exec_stack
+
+: Tests the execution stack depth command.
+
+### Script Tests
+
+The heavy lifting of testing the scripting of `bc` is done by the "script tests"
+for each calculator.
+
+These tests use the files in the [`tests/bc/scripts/`][169] and
+[`tests/dc/scripts/`][170] directories (except for
+[`tests/bc/scripts/all.txt`][171] and [`tests/dc/scripts/all.txt`][172]), which
+are called the "script test directories."
+
+To add a script test, do the following:
+
+* Add the test file (`<test>.bc` or `<test>.dc` in the script tests directory).
+* Add the results file (`<test>.txt` in the script tests directory). You can
+ skip this step if just the results file needs to be generated. See the
+ [Generated Tests][147] section for more information.
+* Add the name of the test to the `all.txt` file in the script tests directory,
+ putting it in the order it should be in. If possible, I would put longer tests
+ near the beginning because they will start running earlier with parallel
+ `make`.
+
+Some script tests need to be skipped in certain cases. That is handled by the
+[build system][142]. See the [Integration with the Build System][147] section
+for more details.
+
+Another unique thing about the script tests, at least for `bc`: they test the
+`-g` and `--global-stacks` flags. This means that all of the script tests for
+`bc` are written assuming the `-g` flag was given on the command-line
+
+There is one extra piece of script tests: [`tests/script.sed`][190]. This `sed`
+script is used to remove an incompatibility with GNU `bc`.
+
+If there is only one more character to print at the end of `BC_LINE_LENGTH`, GNU
+`bc` still prints a backslash+newline+digit combo. OpenBSD doesn't, which is
+correct according to my reading of the `bc` spec, so my `bc` doesn't as well.
+
+The `sed` script edits numbers that end with just one digit on a line by itself
+to put it on the same line as others.
+
+#### `bc` Script Tests
+
+The list of current (17 July 2021) script tests for `bc` is below:
+
+print.bc
+
+: Tests printing even harder than the print standard test.
+
+multiply.bc
+
+: Tests multiplication even harder than the multiply standard test.
+
+divide.bc
+
+: Tests division even harder than the divide standard test.
+
+subtract.bc
+
+: Tests subtraction even harder than the subtract standard test.
+
+add.bc
+
+: Tests addition even harder than the add standard test.
+
+parse.bc
+
+: Tests parsing even harder than the parse standard test.
+
+array.bc
+
+: Tests arrays even harder than the arrays standard test.
+
+atan.bc
+
+: Tests arctangent even harder than the arctangent standard test.
+
+bessel.bc
+
+: Tests bessel even harder than the bessel standard test.
+
+functions.bc
+
+: Tests functions even harder than the functions standard test.
+
+globals.bc
+
+: Tests global stacks directly.
+
+len.bc
+
+: Tests the `length()` builtin on arrays.
+
+rand.bc
+
+: Tests the random number generator in the presence of global stacks.
+
+references.bc
+
+: Tests functions with array reference parameters.
+
+screen.bc
+
+: A random script provided by an early user that he used to calculate the size
+ of computer screens
+
+strings2.bc
+
+: Tests escaping in strings.
+
+ifs.bc
+
+: Tests proper ending of `if` statements without `else` statements.
+
+ifs2.bc
+
+: More tests proper ending of `if` statements without `else` statements.
+
+#### `dc` Script Tests
+
+The list of current (17 July 2021) script tests for `dc` is below:
+
+prime.dc
+
+: Tests scripting by generating the first 100,000 primes.
+
+asciify.dc
+
+: Tests the asciify command.
+
+stream.dc
+
+: Tests the stream command.
+
+array.dc
+
+: Tests arrays.
+
+else.dc
+
+: Tests else clauses on conditional execution commands.
+
+factorial.dc
+
+: Tests scripting with factorial.
+
+loop.dc
+
+: Tests scripting by implementing loops.
+
+quit.dc
+
+: Tests the quit command in the presence of tail calls.
+
+weird.dc
+
+: A miscellaneous test.
+
+### Error Tests
+
+One of the most useful parts of the `bc` test suite, in my opinion, is the heavy
+testing of error conditions.
+
+Just about every error condition I can think of is tested, along with many
+machine-generated (by [AFL++][125]) ones.
+
+However, because the error tests will often return error codes, they require
+different infrastructure from the rest of the test suite, which assumes that
+the calculator under test will return successfully. A lot of that infrastructure
+is in the [`scripts/functions.sh`][105] script, but it basically allows the
+calculator to exit with an error code and then tests that there *was* an error
+code.
+
+Besides returning error codes, error tests also ensure that there is output from
+`stderr`. This is to make sure that an error message is always printed.
+
+The error tests for each calculator are spread through two directories, due to
+historical accident. These two directories are the standard test directory (see
+the [Standard Tests][149] section) and the `errors/` directory directly
+underneath the standard tests directory.
+
+This split is convenient, however, because the tests in each directory are
+treated differently.
+
+The error tests in the standard test directory, which include `errors.txt` for
+both calculators, `posix_errors.txt` for `bc`, and `read_errors.txt` for `dc`,
+are run by [`tests/errors.sh`][226]. It reads them line-by-line and shoves the
+data through `stdin`. Each line is considered a separate test. For this reason,
+there can't be any blank lines in the error files in the standard tests
+directory because a blank line causes a successful exit.
+
+On the other hand, the tests in the `errors/` directory below the standard tests
+directory are run by [`tests/error.sh`][227] and are considered to be one test
+per file. As such, they are used differently. They are shoved into the
+calculator through `stdin`, but they are also executed by passing them on the
+command-line.
+
+To add an error test, first figure out which kind you want.
+
+Is it a simple one-liner, and you don't care if it's tested through a file?
+
+Then put it in one of the error files in the standard test directory. I would
+only put POSIX errors in the `posix_errors.txt` file for `bc`, and only `read()`
+errors in the `read_errors.txt` file for `dc`; all others I would put in the
+respective `errors.txt` file.
+
+On the other hand, if you care if the error is run as a file on the
+command-line, or the error requires multiple lines to reproduce, then put the
+test in the respective `errors/` directory and run the [`configure.sh`][69]
+script again.
+
+After that, you are done; the test suite will automatically pick up the new
+test, and you don't have to tell the test suite the expected results.
+
+### `stdin` Tests
+
+The `stdin` tests specifically test the lexing and parsing of multi-line
+comments and strings. This is important because when reading from `stdin`, the
+calculators can only read one line at a time, so partial parses are possible.
+
+To add `stdin` tests, just add the tests to the `stdin.txt` file in the
+respective standard tests directory, and add the expected results in the
+`stdin_results.txt` in the respective standard tests directory.
+
+### `read()` Tests
+
+The `read()` tests are meant to test the `read()` builtin function, to ensure
+that the parsing and execution is correct.
+
+Each line is one test, as that is the nature of using the `read()` function, so
+to add a test, just add it as another line in the `read.txt` file in the
+respective standard tests directory, and add its result to the
+`read_results.txt` file in the respective standard tests directory.
+
+### Other Tests
+
+The "other" tests are just random tests that I could not easily classify under
+other types of tests. They usually include things like command-line parsing and
+environment variable testing.
+
+To add an other test, it requires adding the programming for it to
+[`tests/other.sh`][195] because all of the tests are written specifically in
+that script. It would be best to use the infrastructure in
+[`scripts/functions.sh`][105].
+
+### Linux `timeconst.bc` Script
+
+One special script that `bc`'s test suite will use is the [Linux `timeconst.bc`
+script][6].
+
+I made the test suite able to use this script because the reason the
+[toybox][16] maintainer wanted my `bc` is because of this script, and I wanted
+to be sure that it would run correctly on the script.
+
+However, it is not part of the distribution, nor is it part of the repository.
+The reason for this is because [`timeconst.bc`][6] is under the GPL, while this
+repo is under a BSD license.
+
+If you want `bc` to run tests on [`timeconst.bc`][6], download it and place it
+at `tests/bc/scripts/timeconst.bc`. If it is there, the test suite will
+automatically run its tests; otherwise, it will skip it.
+
+### History Tests
+
+There are automatic tests for history; however, they have dependencies: Python 3
+and [`pexpect`][137].
+
+As a result, because I need the [test suite to be portable][138], like the rest
+of `bc`, the history tests are carefully guarded with things to ensure that they
+are skipped, rather than failing if Python and [`pexpect`][137] are not
+installed. For this reason, there is a `sh` script, [`tests/history.sh`][140]
+that runs the actual script, [`tests/history.py`][139].
+
+I have added as many tests as I could to cover as many lines and branches as
+possible. I guess I could have done more, but doing so would have required a lot
+of time.
+
+I have tried to make it as easy as possible to run the history tests. They will
+run automatically if you use the `make test_history` command, and they will also
+use parallel execution with `make -j<cores> test_history`.
+
+However, the history tests are meant only to be run by maintainers of `bc`; they
+are *not* meant to be run by users and packagers. The reason for this is that
+they only seem to work reliably on Linux; `pexpect` seems to have issues on
+other platforms, especially timeout issues.
+
+Thus, they are excluded from running with `make test` and [`tests/all.sh`][225].
+However, they can be run from the [`scripts/release.sh`][83] script.
+
+All of the tests are contained in [`tests/history.py`][139]. The reason for this
+is because they are in Python, and I don't have an easy way of including Python
+(or at the very least, I am not familiar enough with Python to do that). So they
+are all in the same file to make it easier on me.
+
+Each test is one function in the script. They all take the same number and type
+of arguments:
+
+1. `exe`: the executable to run.
+2. `args`: the arguments to pass to the executable.
+3. `env`: the environment.
+
+Each function creates a child process with `pexpect.spawn` and then tests with
+that child. Then the function returns the child to the caller, who closes it
+and checks its error code against its expected error code.
+
+Yes, the error code is not a success all the time. This is because of the UTF-8
+tests; `bc` gives a fatal error on any non-ASCII data because ASCII is all `bc`
+is required to handle, per the [standard][2].
+
+So in [`tests/history.py`][139], there are four main arrays:
+
+* `bc` test functions,
+* `bc` expected error codes.
+* `dc` test functions.
+* `dc` expected error codes.
+
+[`tests/history.py`][139] takes an index as an argument; that index is what test
+it should run. That index is used to index into the proper test and error code
+array.
+
+If you need to add more history tests, you need to do the following:
+
+1. Add the function for that test to [`tests/history.py`][139].
+2. Add the function to the proper array of tests.
+3. Add the expected error code to the proper array of error codes.
+4. Add a target for the test to [`Makefile.in`][70].
+5. Add that target as a prerequisite to either `test_bc_history` or
+ `test_dc_history`.
+
+You do not need to do anything to add the test to `history_all_tests` (see
+[Group Tests][141] below) because the scripts will automatically run all of the
+tests properly.
+
+### Generated Tests
+
+Some tests are *large*, and as such, it is impractical to check them into `git`.
+Instead, the tests depend on the existence of a GNU-compatible `bc` in the
+`PATH`, which is then used to generate the tests.
+
+If [`configure.sh`][69] was run with the `-G` argument, which disables generated
+tests, then `make test` and friends will automatically skip generated tests.
+This is useful to do on platforms that are not guaranteed to have a
+GNU-compatible `bc` installed.
+
+However, adding a generated test is a complicated because you have to figure out
+*where* you want to put the file to generate the test.
+
+For example, `bc`'s test suite will automatically use a GNU-compatible `bc` to
+generate a `<test>_results.txt` file in the [standard tests][149] directory
+(either `tests/bc/` or `tests/dc/`) if none exists for the `<test>` test. If no
+`<test>.txt` file exists in the [standard tests][149] directory, then `bc`'s
+test suite will look for a `<test>.bc` or `<test>.dc` file in the [script
+tests][150] directory (either `tests/bc/scripts` or `tests/dc/scripts`), and if
+that exists, it will use that script to generate the `<test>.txt` file in the
+[standard tests][149] directory after which it will generate the
+`<test>_results.txt` file in the [standard tests][149] directory.
+
+So you can choose to either:
+
+* Have a test in the [standard tests][149] directory without a corresponding
+ `*_results.txt` file, or
+* Have a script in the [script tests][150] directory to generate the
+ corresponding file in the standard test directory before generating the
+ corresponding `*_results.txt` file.
+
+Adding a script has a double benefit: the script itself can be used as a test.
+However, script test results can also be generated.
+
+If `bc` is asked to run a script test, then if the script does not exist, `bc`'s
+test suite returns an error. If it *does* exist, but no corresponding
+`<test>.txt` file exists in the [script tests][150] directory, then a
+GNU-compatible `bc` is used to generate the `<test>.txt` results file.
+
+If generated tests are disabled through [`configure.sh`][69], then these tests
+are not generated if they do not exist. However, if they *do* exist, then they
+are run. This can happen if a `make clean_tests` was not run between a build
+that generated tests and a build that will not.
+
+### Group Tests
+
+While the test suite has a lot of targets in order to get parallel execution,
+there are five targets that allow you to run each section, or all, of the test
+suite as one unit:
+
+* `bc_all_tests` (`bc` tests)
+* `timeconst_all_tests` ([Linux `timeconst.bc` script][6] tests)
+* `dc_all_tests` (`dc` tests)
+* `history_all_tests` (history tests)
+* `run_all_tests` (combination of the previous four)
+
+In addition, there are more fine-grained targets available:
+
+* `test_bc` runs all `bc` tests (except history tests).
+* `test_dc` runs all `dc` tests (except history tests).
+* `test_bc_tests` runs all `bc` [standard tests][149].
+* `test_dc_tests` runs all `dc` [standard tests][149].
+* `test_bc_scripts` runs all `bc` [script tests][150].
+* `test_dc_scripts` runs all `dc` [script tests][150].
+* `test_bc_stdin` runs the `bc` [`stdin` tests][152].
+* `test_dc_stdin` runs the `dc` [`stdin` tests][152].
+* `test_bc_read` runs the `bc` [`read()` tests][153].
+* `test_dc_read` runs the `dc` [`read()` tests][153].
+* `test_bc_errors` runs the `bc` [error tests][151].
+* `test_dc_errors` runs the `dc` [error tests][151].
+* `test_bc_other` runs the `bc` [other tests][151].
+* `test_dc_other` runs the `dc` [other tests][151].
+* `timeconst` runs the tests for the [Linux `timeconst.bc` script][6].
+* `test_history` runs all history tests.
+* `test_bc_history` runs all `bc` history tests.
+* `test_dc_history` runs all `dc` history tests.
+
+All of the above tests are parallelizable.
+
+### Individual Tests
+
+In addition to all of the above, individual test targets are available. These
+are mostly useful for attempting to fix a singular test failure.
+
+These tests are:
+
+* `test_bc_<test>`, where `<test>` is the name of a `bc` [standard test][149].
+ The name is the name of the test file without the `.txt` extension. It is the
+ name printed by the test suite when running the test.
+* `test_dc_<test>`, where `<test>` is the name of a `dc` [standard test][149].
+ The name is the name of the test file without the `.txt` extension. It is the
+ name printed by the test suite when running the test.
+* `test_bc_script_<test>`, where `<test>` is the name of a `bc` [script
+ test][150]. The name of the test is the name of the script without the `.bc`
+ extension.
+* `test_dc_script_<test>`, where `<test>` is the name of a `dc` [script
+ test][150]. The name of the test is the name of the script without the `.dc`
+ extension.
+* `test_bc_history<idx>` runs the `bc` history test with index `<idx>`.
+* `test_dc_history<idx>` runs the `dc` history test with index `<idx>`.
+
+### [`bcl`][156] Test
+
+When [`bcl`][156] is built, the [build system][142] automatically ensures that
+`make test` runs the [`bcl`][156] test instead of the `bc` and `dc` tests.
+
+There is only one test, and it is built from [`tests/bcl.c`][158].
+
+The reason the test is in C is because [`bcl`][156] is a C library; I did not
+want to have to write C code *and* POSIX `sh` scripts to run it.
+
+The reason there is only one test is because most of the code for the library is
+tested by virtue of testing `bc` and `dc`; the test needs to only ensure that
+the library bindings and plumbing do not interfere with the underlying code.
+
+However, just because there is only one test does not mean that it doesn't test
+more than one thing. The code actually handles a series of tests, along with
+error checking to ensure that nothing went wrong.
+
+To add a [`bcl`][156] test, just figure out what test you want, figure out where
+in the [`tests/bcl.c`][158] would be best to put it, and put it there. Do as
+much error checking as possible, and use the `err(BclError)` function. Ensure
+that all memory is freed because that test is run through [Valgrind][159] and
+[AddressSanitizer][160].
+
+### Integration with the Build System
+
+If it was not obvious by now, the test suite is heavily integrated into the
+[build system][142], but the integration goes further than just making the test
+suite easy to run from `make` and generating individual and group tests.
+
+The big problem the test suite has is that some `bc` code, stuff that is
+important to test, is only in *some* builds. This includes all of the extra math
+extensions, for example.
+
+So the test suite needs to have some way of turning off the tests that depend on
+certain [build types][81] when those [build types][81] are not used.
+
+This is the reason the is tightly integrated with the [build system][142]: the
+[build system][142] knows what [build type][81] was used and can tell the test
+suite to turn off the tests that do not apply.
+
+It does this with arguments to the test scripts that are either a `1` or a `0`,
+depending on whether tests of that type should be enabled or not. These
+arguments are why I suggest, in the [Test Scripts][148] section, to always use a
+`make` target to run the test suite or any individual test. I have added a lot
+of targets to make this easy and as fast as possible.
+
+In addition to all of that, the build system is responsible for selecting the
+`bc`/`dc` tests or the [`bcl` test][157].
+
+### Output Directories
+
+During any run of the test suite, the test suite outputs the results of running
+various tests to files. These files are usually output to `tests/bc_outputs/`
+and `tests/dc_outputs/`.
+
+However, in some cases, it may be necessary to output test results to a
+different directory. If that is the case, set the environment variable
+`BC_TEST_OUTPUT_DIR` to the name of the directory.
+
+If that is done, then test results will be written to
+`$BC_TEST_OUTPUT_DIR/bc_outputs/` and `$BC_TEST_OUTPUT_DIR/dc_outputs/`.
+
+### Test Suite Portability
+
+The test suite is meant to be run by users and packagers as part of their
+install process.
+
+This puts some constraints on the test suite, but the biggest is that the test
+suite must be as [portable as `bc` itself][136].
+
+This means that the test suite must be implemented in pure POSIX `make`, `sh`,
+and C99.
+
+#### Test Scripts
+
+To accomplish the portability, the test suite is run by a bunch of `sh` scripts
+that have the constraints laid out in [POSIX Shell Scripts][76].
+
+However, that means they have some quirks, made worse by the fact that there are
+[generated tests][143] and [tests that need to be skipped, but only
+sometimes][147].
+
+This means that a lot of the scripts take an awkward number and type of
+arguments. Some arguments are strings, but most are integers, like
+[`scripts/release.sh`][83].
+
+It is for this reason that I do not suggest running the test scripts directly.
+Instead, always use an appropriate `make` target, which already knows the
+correct arguments for the test because of the [integration with the build
+system][147].
+
+### Test Coverage
+
+In order to get test coverage information, you need `gcc`, `gcov`, and `gcovr`.
+
+If you have them, run the following commands:
+
+```
+CC=gcc ./configure -gO3 -c
+make -j<cores>
+make coverage
+```
+
+Note that `make coverage` does not have a `-j<cores>` part; it cannot be run in
+parallel. If you try, you will get errors. And note that `CC=gcc` is used.
+
+After running those commands, you can open your web browser and open the
+`index.html` file in the root directory of the repo. From there, you can explore
+all of the coverage results.
+
+If you see lines or branches that you think you could hit with a manual
+execution, do such manual execution, and then run the following command:
+
+```
+make coverage_output
+```
+
+and the coverage output will be updated.
+
+If you want to rerun `make coverage`, you must do a `make clean` and build
+first, like this:
+
+```
+make clean
+make -j<cores>
+make coverage
+```
+
+Otherwise, you will get errors.
+
+If you want to run tests in parallel, you can do this:
+
+```
+make -j<cores>
+make -j<cores> test
+make coverage_output
+```
+
+and that will generate coverage output correctly.
+
+### [AddressSanitizer][21] and Friends
+
+To run the test suite under [AddressSanitizer][21] or any of its friends, use
+the following commands:
+
+```
+CFLAGS="-fsanitize=<sanitizer> ./configure -gO3 -m
+make -j<cores>
+make -j<cores> test
+```
+
+where `<sanitizer>` is the correct name of the desired sanitizer. There is one
+exception to the above: `UndefinedBehaviorSanitizer` should be run on a build
+that has zero optimization, so for `UBSan`, use the following commands:
+
+```
+CFLAGS="-fsanitize=undefined" ./configure -gO0 -m
+make -j<cores>
+make -j<cores> test
+```
+
+### [Valgrind][20]
+
+To run the test suite under [Valgrind][20], run the following commands:
+
+```
+./configure -gO3 -v
+make -j<cores>
+make -j<cores> test
+```
+
+It really is that easy. I have directly added infrastructure to the build system
+and the test suite to ensure that if [Valgrind][20] detects any memory errors or
+any memory leaks at all, it will tell the test suite infrastructure to report an
+error and exit accordingly.
+
+## POSIX Shell Scripts
+
+There is a lot of shell scripts in this repository, and every single one of them
+is written in pure [POSIX `sh`][72].
+
+The reason that they are written in [POSIX `sh`][72] is for *portability*: POSIX
+systems are only guaranteed to have a barebones implementation of `sh`
+available.
+
+There are *many* snares for unwary programmers attempting to modify
+[`configure.sh`][69], any of the scripts in this directory, [`strgen.sh`][9], or
+any of the scripts in [`tests/`][77]. Here are some of them:
+
+1. No `bash`-isms.
+2. Only POSIX standard utilities are allowed.
+3. Only command-line options defined in the POSIX standard for POSIX utilities
+ are allowed.
+4. Only the standardized behavior of POSIX utilities is allowed.
+5. Functions return data by *printing* it. Using `return` sets their exit code.
+
+In other words, the script must only use what is standardized in the [`sh`][72]
+and [Shell Command Language][73] standards in POSIX. This is *hard*. It precludes
+things like `local` and the `[[ ]]` notation.
+
+These are *enormous* restrictions and must be tested properly. I put out at
+least one release with a change to `configure.sh` that wasn't portable. That was
+an embarrassing mistake.
+
+The lack of `local`, by the way, is why variables in functions are named with
+the form:
+
+```
+_<function_name>_<var_name>
+```
+
+This is done to prevent any clashes of variable names with already existing
+names. And this applies to *all* shell scripts. However, there are a few times
+when that naming convention is *not* used; all of them are because those
+functions are required to change variables in the global scope.
+
+### Maintainer-Only Scripts
+
+If a script is meant to be used for maintainers (of `bc`, not package
+maintainers), then rules 2, 3, and 4 don't need to be followed as much because
+it is assumed that maintainers will be able to install whatever tools are
+necessary to do the job.
+
+## Manuals
+
+The manuals for `bc` and `dc` are all generated, and the manpages for `bc`,
+`dc`, and `bcl` are also generated.
+
+Why?
+
+I don't like the format of manpages, and I am not confident in my ability to
+write them. Also, they are not easy to read on the web.
+
+So that explains why `bcl`'s manpage is generated from its markdown version. But
+why are the markdown versions of the `bc` and `dc` generated?
+
+Because the content of the manuals needs to change based on the [build
+type][81]. For example, if `bc` was built with no history support, it should not
+have the **COMMAND LINE HISTORY** section in its manual. If it did, that would
+just confuse users.
+
+So the markdown manuals for `bc` and `dc` are generated from templates
+([`manuals/bc.1.md.in`][89] and [`manuals/dc.1.md.in`][90]). And from there,
+the manpages are generated from the generated manuals.
+
+The generated manpage for `bcl` ([`manuals/bcl.3`][62]) is checked into version
+control, and the generated markdown manuals and manpages for `bc`
+([`manuals/bc`][79]) and `dc` ([`manuals/dc`][80]) are as well.
+
+This is because generating the manuals and manpages requires a heavy dependency
+that only maintainers should care about: [Pandoc][92]. Because users [should not
+have to install *any* dependencies][136], the files are generated, checked into
+version control, and included in distribution tarballs.
+
+If you run [`configure.sh`][69], you have an easy way of generating the markdown
+manuals and manpages: just run `make manpages`. This target calls
+[`scripts/manpage.sh`][60] appropriately for `bc`, `dc`, and `bcl`.
+
+For more on how generating manuals and manpages works, see
+[`scripts/manpage.sh`][60].
+
+## Locales
+
+The locale system of `bc` is enormously complex, but that's because
+POSIX-compatible locales are terrible.
+
+How are they terrible?
+
+First, `gencat` does not work for generating cross-compilation. In other words,
+it does not generate machine-portable files. There's nothing I can do about
+this except for warn users.
+
+Second, the format of `.msg` files is...interesting. Thank goodness it is text
+because otherwise, it would be impossible to get them right.
+
+Third, `.msg` files are not used. In other words, `gencat` exists. Why?
+
+Fourth, `$NLSPATH` is an awful way to set where and *how* to install locales.
+
+Yes, where and *how*.
+
+Obviously, from it's name, it's a path, and that's the where. The *how* is more
+complicated.
+
+It's actually *not* a path, but a path template. It's a format string, and it
+can have a few format specifiers. For more information on that, see [this
+link][84]. But in essence, those format specifiers configure how each locale is
+supposed to be installed.
+
+With all those problems, why use POSIX locales? Portability, as always. I can't
+assume that `gettext` will be available, but I *can* pretty well assume that
+POSIX locales will be available.
+
+The locale system of `bc` includes all files under [`locales/`][85],
+[`scripts/locale_install.sh`][87], [`scripts/locale_uninstall.sh`][88],
+[`scripts/functions.sh`][105], the `bc_err_*` constants in [`src/data.c`][131],
+and the parts of the build system needed to activate it. There is also code in
+[`src/vm.c`][58] (in `bc_vm_gettext()`) for loading the current locale.
+
+If the order of error messages and/or categories are changed, the order of
+errors must be changed in the enum, the default error messages and categories in
+[`src/data.c`][131], and all of the messages and categories in the `.msg` files
+under [`locales/`][85].
+
+## Static Analysis
+
+I do *some* static analysis on `bc`.
+
+I used to use [Coverity][196], but I stopped using it when it started giving me
+too many false positives and also because it had a vulnerability.
+
+However, I still use the [Clang Static Analyzer][197] through
+[`scan-build`][19]. I only use it in debug mode because I have to add some
+special code to make it not complain about things that are definitely not a
+problem.
+
+The most frequent example of false positives is where a local is passed to a
+function to be initialized. [`scan-build`][19] misses that fact, so I
+pre-initialize such locals to prevent the warnings.
+
+To run `scan-build`, do the following:
+
+```
+make clean
+scan-build make
+```
+
+`scan-build` will print its warnings to `stdout`.
+
+## Fuzzing
+
+The quality of this `bc` is directly related to the amount of fuzzing I did. As
+such, I spent a lot of work making the fuzzing convenient and fast, though I do
+admit that it took me a long time to admit that it did need to be faster.
+
+First, there were several things which make fuzzing fast:
+
+* Using [AFL++][125]'s deferred initialization.
+* Splitting `bc`'s corpuses.
+* Parallel fuzzing.
+
+Second, there are several things which make fuzzing convenient:
+
+* Preprepared input corpuses.
+* [`scripts/fuzz_prep.sh`][119].
+* `tmux` and `tmuxp` configs.
+* [`scripts/afl.py`][94].
+
+### Fuzzing Performance
+
+Fuzzing with [AFL++][125] can be ***SLOW***. Spending the time to make it as
+fast as possible is well worth the time.
+
+However, there is a caveat to the above: it is easy to make [AFL++][125] crash,
+be unstable, or be unable to find "paths" (see [AFL++ Quickstart][129]) if the
+performance enhancements are done poorly.
+
+To stop [AFL++][125] from crashing on test cases, and to be stable, these are
+the requirements:
+
+* The state at startup must be *exactly* the same.
+* The virtual memory setup at startup must be *exactly* the same.
+
+The first isn't too hard; it's the second that is difficult.
+
+`bc` allocates a lot of memory at start. ("A lot" is relative; it's far less
+than most programs.) After going through an execution run, however, some of that
+memory, while it could be cleared and reset, is in different places because of
+vectors. Since vectors reallocate, their allocations are not guaranteed to be in
+the same place.
+
+So to make all three work, I had to set up the deferred initialization and
+persistent mode *before* any memory was allocated (except for `vm.jmp_bufs`,
+which is probably what caused the stability to drop below 100%). However, using
+deferred alone let me put the [AFL++][125] initialization further back. This
+works because [AFL++][125] sets up a `fork()` server that `fork()`'s `bc` right
+at that call. Thus, every run has the exact same virtual memory setup, and each
+run can skip all of the setup code.
+
+I tested `bc` using [AFL++][125]'s deferred initialization, plus persistent
+mode, plus shared memory fuzzing. In order to do it safely, with stability above
+99%, all of that was actually *slower* than using just deferred initialization
+with the initialization *right before* `stdin` was read. And as a bonus, the
+stability in that situation is 100%.
+
+As a result, my [AFL++][125] setup only uses deferred initialization. That's the
+`__AFL_INIT()` call.
+
+(Note: there is one more big item that must be done in order to have 100%
+stability: the pseudo-random number generator *must* start with *exactly* the
+same seed for every run. This is set up with the `tmux` and `tmuxp` configs that
+I talk about below in [Convenience][130]. This seed is set before the
+`__AFL_INIT()` call, so setting it has no runtime cost for each run, but without
+it, stability would be abysmal.)
+
+On top of that, while `dc` is plenty fast under fuzzing (because of a faster
+parser and less test cases), `bc` can be slow. So I have split the `bc` input
+corpus into three parts, and I set fuzzers to run on each individually. This
+means that they will duplicate work, but they will also find more stuff.
+
+On top of all of that, each input corpus (the three `bc` corpuses and the one
+`dc` corpus) is set to run with 4 fuzzers. That works out perfectly for two
+reasons: first, my machine has 16 cores, and second, the [AFL++][125] docs
+recommend 4 parallel fuzzers, at least, to run different "power schedules."
+
+### Convenience
+
+The preprepared input corpuses are contained in the
+`tests/fuzzing/bc_inputs{1,2,3}/`, and `tests/fuzzing/dc_inputs` directories.
+There are three `bc` directories and only one `dc` directory because `bc`'s
+input corpuses are about three times as large, and `bc` is a larger program;
+it's going to need much more fuzzing.
+
+(They do share code though, so fuzzing all of them still tests a lot of the same
+math code.)
+
+The next feature of convenience is the [`scripts/fuzz_prep.sh`][119] script. It
+assumes the existence of `afl-clang-lto` in the `$PATH`, but if that exists, it
+automatically configures and builds `bc` with a fuzz-ideal build.
+
+A fuzz-ideal build has several things:
+
+* `afl-clang-lto` as the compiler. (See [AFL++ Quickstart][129].)
+* Debug mode, to crash as easily as possible.
+* Full optimization (including [Link-Time Optimization][126]), for performance.
+* [AFL++][125]'s deferred initialization (see [Fuzzing Performance][127] above).
+* And `AFL_HARDEN=1` during the build to harden the build. See the [AFL++][125]
+ documentation for more information.
+
+There is one big thing that a fuzz-ideal build does *not* have: it does not use
+[AFL++][125]'s `libdislocator.so`. This is because `libdislocator.so` crashes if
+it fails to allocate memory. I do not want to consider those as crashes because
+my `bc` does, in fact, handle them gracefully by exiting with a set error code.
+So `libdislocator.so` is not an option.
+
+However, to add to [`scripts/fuzz_prep.sh`][119] making a fuzz-ideal build, in
+`tests/fuzzing/`, there are two `yaml` files: [`tests/fuzzing/bc_afl.yaml`][120]
+and [`tests/fuzzing/bc_afl_continue.yaml`][121]. These files are meant to be
+used with [`tmux`][122] and [`tmuxp`][123]. While other programmers will have to
+adjust the `start_directory` item, once it is adjusted, then using this command:
+
+```
+tmuxp load tests/fuzzing/bc_afl.yaml
+```
+
+will start fuzzing.
+
+In other words, to start fuzzing, the sequence is:
+
+```
+./scripts/fuzz_prep.sh
+tmuxp load tests/fuzzing/bc_afl.yaml
+```
+
+Doing that will load, in `tmux`, 16 separate instances of [AFL++][125], 12 on
+`bc` and 4 on `dc`. The outputs will be put into the
+`tests/fuzzing/bc_outputs{1,2,3}/` and `tests/fuzzing/dc_outputs/` directories.
+
+(Note that loading that config will also delete all unsaved [AFL++][125] output
+from the output directories.)
+
+Sometimes, [AFL++][125] will report crashes when there are none. When crashes
+are reported, I always run the following command:
+
+```
+./scripts/afl.py <dir>
+```
+
+where `dir` is one of `bc1`, `bc2`, `bc3`, or `dc`, depending on which of the
+16 instances reported the crash. If it was one of the first four (`bc11` through
+`bc14`), I use `bc1`. If it was one of the second four (`bc21` through `bc24`, I
+use `bc2`. If it was one of the third four (`bc31` through `bc34`, I use `bc3`.
+And if it was `dc`, I use `dc`.
+
+The [`scripts/afl.py`][94] script will report whether [AFL++][125] correctly
+reported a crash or not. If so, it will copy the crashing test case to
+`.test.txt` and tell you whether it was from running it as a file or through
+`stdin`.
+
+From there, I personally always investigate the crash and fix it. Then, when the
+crash is fixed, I either move `.test.txt` to `tests/{bc,dc}/errors/<idx>.txt` as
+an error test (if it produces an error) or I create a new
+`tests/{bc,dc}/misc<idx>.txt` test for it and a corresponding results file. (See
+[Test Suite][124] for more information about the test suite.) In either case,
+`<idx>` is the next number for a file in that particular place. For example, if
+the last file in `tests/{bc,dc}/errors/` is `tests/{bc,dc}/errors/18.txt`, I
+move `.test.txt` to `tests/bc/error/19.txt`.
+
+Then I immediately run [`scripts/afl.py`][94] again to find the next crash
+because often, [AFL++][125] found multiple test cases that trigger the same
+crash. If it finds another, I repeat the process until it is happy.
+
+Once it *is* happy, I do the same `fuzz_prep.sh`, `tmuxp load` sequence and
+restart fuzzing. Why do I restart instead of continuing? Because with the
+changes, the test outputs could be stale and invalid.
+
+However, there *is* a case where I continue: if [`scripts/afl.py`][94] finds
+that every crash reported by [AFL++][125] is invalid. If that's the case, I can
+just continue with the command:
+
+```
+tmuxp load tests/fuzzing/bc_afl_continue.yaml
+```
+
+(Note: I admit that I usually run [`scripts/afl.py`][94] while the fuzzer is
+still running, so often, I don't find a need to continue since there was no
+stop. However, the capability is there, if needed.)
+
+In addition, my fuzzing setup, including the `tmux` and `tmuxp` configs,
+automatically set up [AFL++][125] power schedules (see [Fuzzing
+Performance][127] above). They also set up the parallel fuzzing such that there
+is one fuzzer in each group of 4 that does deterministic fuzzing. It's always
+the first one in each group.
+
+For more information about deterministic fuzzing, see the [AFL++][125]
+documentation.
+
+### Corpuses
+
+I occasionally add to the input corpuses. These files come from new files in the
+[Test Suite][124]. In fact, I use soft links when the files are the same.
+
+However, when I add new files to an input corpus, I sometimes reduce the size of
+the file by removing some redundancies.
+
+And then, when adding to the `bc` corpuses, I try to add them evenly so that
+each corpus will take about the same amount of time to get to a finished state.
+
+### [AFL++][125] Quickstart
+
+The way [AFL++][125] works is complicated.
+
+First, it is the one to invoke the compiler. It leverages the compiler to add
+code to the binary to help it know when certain branches are taken.
+
+Then, when fuzzing, it uses that branch information to generate information
+about the "path" that was taken through the binary.
+
+I don't know what AFL++ counts as a new path, but each new path is added to an
+output corpus, and it is later used as a springboard to find new paths.
+
+This is what makes AFL++ so effective: it's not just blindly thrashing a binary;
+it adapts to the binary by leveraging information about paths.
+
+### Fuzzing Runs
+
+For doing a fuzzing run, I expect about a week or two where my computer is
+basically unusable, except for text editing and light web browsing.
+
+Yes, it can take two weeks for me to do a full fuzzing run, and that does *not*
+include the time needed to find and fix crashes; it only counts the time on the
+*last* run, the one that does not find any crashes. This means that the entire
+process can take a month or more.
+
+What I use as an indicator that the fuzzing run is good enough is when the
+number of "Pending" paths (see [AFL++ Quickstart][129] above) for all fuzzer
+instances, except maybe the deterministic instances, is below 50. And even then,
+I try to let deterministic instances get that far as well.
+
+You can see how many pending paths are left in the "path geometry" section of
+the [AFL++][125] dashboard.
+
+Also, to make [AFL++][125] quit, you need to send it a `SIGINT`, either with
+`Ctrl+c` or some other method. It will not quit until you tell it to.
+
+### Radamsa
+
+I rarely use [Radamsa][99] instead of [AFL++][125]. In fact, it's only happened
+once.
+
+The reason I use [Radamsa][99] instead of [AFL++][125] is because it is easier
+to use with varying command-line arguments, which was needed for testing `bc`'s
+command-line expression parsing code, and [AFL++][125] is best when testing
+input from `stdin`.
+
+[`scripts/radamsa.sh`][100] does also do fuzzing on the [AFL++][125] inputs, but
+it's not as effective at that, so I don't really use it for that either.
+
+[`scripts/radamsa.sh`][100] and [Radamsa][99] were only really used once; I have
+not had to touch the command-line expression parsing code since.
+
+### [AddressSanitizer][21] with Fuzzing
+
+One advantage of using [AFL++][125] is that it saves every test case that
+generated a new path (see [AFL++ Quickstart][129] above), and it doesn't delete
+them when the user makes it quit.
+
+Keeping them around is not a good idea, for several reasons:
+
+* They are frequently large.
+* There are a lot of them.
+* They go stale; after `bc` is changed, the generated paths may not be valid
+ anymore.
+
+However, before they are deleted, they can definitely be leveraged for even
+*more* bug squashing by running *all* of the paths through a build of `bc` with
+[AddressSanitizer][21].
+
+This can easily be done with these four commands:
+
+```
+./scripts/fuzz_prep.sh -a
+./scripts/afl.py --asan bc1
+./scripts/afl.py --asan bc2
+./scripts/afl.py --asan bc3
+./scripts/afl.py --asan dc
+```
+
+(By the way, the last four commands could be run in separate terminals to do the
+processing in parallel.)
+
+These commands build an [ASan][21]-enabled build of `bc` and `dc` and then they
+run `bc` and `dc` on all of the found crashes and path output corpuses. This is
+to check that no path or crash has found any memory errors, including memory
+leaks.
+
+Because the output corpuses can contain test cases that generate infinite loops
+in `bc` or `dc`, [`scripts/afl.py`][94] has a timeout of 8 seconds, which is far
+greater than the timeout that [AFL++][125] uses and should be enough to catch
+any crash.
+
+If [AFL++][125] fails to find crashes *and* [ASan][21] fails to find memory
+errors on the outputs of [AFL++][125], that is an excellent indicator of very
+few bugs in `bc`, and a release can be made with confidence.
+
+## Code Concepts
+
+This section is about concepts that, if understood, will make it easier to
+understand the code as it is written.
+
+The concepts in this section are not found in a single source file, but they are
+littered throughout the code. That's why I am writing them all down in a single
+place.
+
+### POSIX Mode
+
+POSIX mode is `bc`-only.
+
+In fact, POSIX mode is two different modes: Standard Mode and Warning Mode.
+These modes are designed to help users write POSIX-compatible `bc` scripts.
+
+#### Standard Mode
+
+Standard Mode is activated with the `-s` or `--standard` flags.
+
+In this mode, `bc` will error if any constructs are used that are not strictly
+compatible with the [POSIX `bc` specification][2].
+
+#### Warning Mode
+
+Warning Mode is activated with the `-w` or `--warn` flags.
+
+In this mode, `bc` will issue warnings, but continue, if any constructs are used
+that are not strictly compatible with the [POSIX `bc` specification][2].
+
+### Memory Management
+
+The memory management in `bc` is simple: everything is owned by one thing.
+
+If something is in a vector, it is owned by that vector.
+
+If something is contained in a struct, it is owned by that struct with one
+exception: structs can be given pointers to other things, but only if those
+other things will outlast the struct itself.
+
+As an example, the `BcParse` struct has a pointer to the one `BcProgram` in
+`bc`. This is okay because the program is initialized first and deallocated
+last.
+
+In other words, it's simple: if a field in a struct is a pointer, then unless
+that pointer is directly allocated by the struct (like the vector array or the
+number limb array), that struct does not own the item at that pointer.
+Otherwise, the struct *does* own the item.
+
+### [Async-Signal-Safe][115] Signal Handling
+
+`bc` is not the typical Unix utility. Most Unix utilities are I/O bound, but
+`bc` is, by and large, CPU-bound. This has several consequences, but the biggest
+is that there is no easy way to allow signals to interrupt it.
+
+This consequence is not obvious, but it comes from the fact that a lot of I/O
+operations can be interrupted and return [`EINTR`][198]. This makes such I/O
+calls natural places for allowing signals to interrupt execution, even when the
+signal comes during execution, and not interrupting I/O calls. The way this is
+done is setting a flag in the signal handler, which is checked around the time
+of the I/O call, when it is convenient.
+
+Alternatively, I/O bound programs can use the [self-pipe trick][199].
+
+Neither of these are possible in `bc` because the execution of math code can
+take a long time. If a signal arrives during this long execution time, setting a
+flag like an I/O bound application and waiting until the next I/O call could
+take seconds, minutes, hours, or even days. (Last I checked, my `bc` takes a
+week to calculate a million digits of pi, and it's not slow as far as `bc`
+implementations go.)
+
+Thus, using just the technique of setting the flag just will not work for an
+interactive calculator.
+
+Well, it can, but it requires a lot of code and massive inefficiencies. I know
+this because that was the original implementation.
+
+The original implementation set a flag and just exit the signal handler. Then,
+on just about every loop header, I have a check for the signal flag. These
+checks happened on every iteration of every loop. It was a massive waste because
+it was polling, and [polling is evil][200].
+
+So for version [3.0.0][32], I expended a lot of effort to change the
+implementation.
+
+In the new system, code *outside* the signal handler sets a flag (`vm.sig_lock`)
+to tell the signal handler whether it can use `longjmp()` to stop the current
+execution. If so, it does. If not, it sets a flag, which then is used by the
+code outside the signal handler that set the `vm.sig_lock` flag. When that code
+unsets `vm.sig_lock`, it checks to see if a signal happened, and if so, that
+code executes the `longjmp()` and stops the current execution.
+
+Other than that, the rest of the interrupt-based implementation is best
+described in the [Error Handling][97].
+
+However, there are rules for signal handlers that I must lay out.
+
+First, signal handlers can only call [async-signal-safe][115] functions.
+
+Second, any field set or read by both the signal handler and normal code must be
+a `volatile sig_atomic_t`.
+
+Third, when setting such fields, they must be set to constants and no math can
+be done on them. This restriction and the above restriction exist in order to
+ensure that the setting of the fields is always atomic with respect to signals.
+
+These rules exist for *any* code using Unix signal handlers, not just `bc`.
+
+#### Vectors and Numbers
+
+Vectors and numbers needed special consideration with the interrupt-based signal
+handling.
+
+When vectors and numbers are about to allocate, or *reallocate* their arrays,
+they need to lock signals to ensure that they do not call `malloc()` and friends
+and get interrupted by a signal because, as you will see in the [Error
+Handling][97] section, `longjmp()` cannot be used in a signal handler if it may
+be able to interrupt a non-[async-signal-safe][115] function like `malloc()` and
+friends.
+
+### Asserts
+
+If you asked me what procedure is used the most in `bc`, I would reply without
+hesitation, "`assert()`."
+
+I use `assert()` everywhere. In fact, it is what made [fuzzing][82] with
+[AFL++][125] so effective. [AFL++][125] is incredibly good at finding crashes,
+and a failing `assert()` counts as one.
+
+So while a lot of bad bugs might have corrupted data and *not* caused crashes,
+because I put in so many `assert()`'s, they were *turned into* crashing bugs,
+and [AFL++][125] found them.
+
+By far, the most bugs it found this way was in the `bc` parser. (See the [`bc`
+Parsing][110] for more information.) And even though I was careful to put
+`assert()`'s everywhere, most parser bugs manifested during execution of
+bytecode because the virtual machine assumes the bytecode is valid.
+
+Sidenote: one of those bugs caused an infinite recursion when running the sine
+(`s()`) function in the math library, so yes, parser bugs can be *very* weird.
+
+Anyway, the way I did `assert()`'s was like this: whenever I realized that I
+had put assumptions into the code, I would put an `assert()` there to test it
+**and** to *document* it.
+
+Yes, documentation. In fact, by far the best documentation of the code in `bc`
+is actually the `assert()`'s. The only time I would not put an `assert()` to
+test an assumption is if that assumption was already tested by an `assert()`
+earlier.
+
+As an example, if a function calls another function and passes a pointer that
+the caller previously `assert()`'ed was *not* `NULL`, then the callee does not
+have to `assert()` it too, unless *also* called by another function that does
+not `assert()` that.
+
+At first glance, it may seem like putting asserts for pointers being non-`NULL`
+everywhere would actually be good, but unfortunately, not for fuzzing. Each
+`assert()` is a branch, and [AFL++][125] rates its own effectiveness based on
+how many branches it covers. If there are too many `assert()`'s, it may think
+that it is not being effective and that more fuzzing is needed.
+
+This means that `assert()`'s show up most often in two places: function
+preconditions and function postconditions.
+
+Function preconditions are `assert()`'s that test conditions relating to the
+arguments a function was given. They appear at the top of the function, usually
+before anything else (except maybe initializing a local variable).
+
+Function postconditions are `assert()`'s that test the return values or other
+conditions when a function exits. These are at the bottom of a function or just
+before a `return` statement.
+
+The other `assert()`'s cover various miscellaneous assumptions.
+
+If you change the code, I ***HIGHLY*** suggest that you use `assert()`'s to
+document your assumptions. And don't remove them when [AFL++][125] gleefully
+crashes `bc` and `dc` over and over again.
+
+### Vectors
+
+In `bc`, vectors mean resizable arrays, and they are the most fundamental piece
+of code in the entire codebase.
+
+I had previously written a [vector implementation][112], which I used to guide
+my decisions, but I wrote a new one so that `bc` would not have a dependency. I
+also didn't make it as sophisticated; the one in `bc` is very simple.
+
+Vectors store some information about the type that they hold:
+
+* The size (as returned by `sizeof`).
+* An enum designating the destructor.
+
+If the destructor is `BC_DTOR_NONE`, it is counted as the type not having a
+destructor.
+
+But by storing the size, the vector can then allocate `size * cap` bytes, where
+`cap` is the capacity. Then, when growing the vector, the `cap` is doubled again
+and again until it is bigger than the requested size.
+
+But to store items, or to push items, or even to return items, the vector has to
+figure out where they are, since to it, the array just looks like an array of
+bytes.
+
+It does this by calculating a pointer to the underlying type with
+`v + (i * size)`, where `v` is the array of bytes, `i` is the index of the
+desired element, and `size` is the size of the underlying type.
+
+Doing that, vectors can avoid undefined behavior (because `char` pointers can
+be cast to any other pointer type), while calculating the exact position of
+every element.
+
+Because it can do that, it can figure out where to push new elements by
+calculating `v + (len * size)`, where `len` is the number of items actually in
+the vector.
+
+By the way, `len` is different from `cap`. While `cap` is the amount of storage
+*available*, `len` is the number of actual elements in the vector at the present
+point in time.
+
+Growing the vector happens when `len` is equal to `cap` *before* pushing new
+items, not after.
+
+To add a destructor, you need to add an enum item to `BcDtorType` in
+[`include/vector.h`][174] and add the actual destructor in the same place as the
+enum item in the `bc_vec_dtors[]` array in [`src/data.c`][131].
+
+#### Pointer Invalidation
+
+There is one big danger with the vectors as currently implemented: pointer
+invalidation.
+
+If a piece of code receives a pointer from a vector, then adds an item to the
+vector before they finish using the pointer, that code must then update the
+pointer from the vector again.
+
+This is because any pointer inside the vector is calculated based off of the
+array in the vector, and when the vector grows, it can `realloc()` the array,
+which may move it in memory. If that is done, any pointer returned by
+`bc_vec_item()`, `bc_vec_top()` and `bc_vec_item_rev()` will be invalid.
+
+This fact was the single most common cause of crashes in the early days of this
+`bc`; wherever I have put a comment about pointers becoming invalidated and
+updating them with another call to `bc_vec_item()` and friends, *do **NOT**
+remove that code!*
+
+#### Maps
+
+Maps in `bc` are...not.
+
+They are really a combination of two vectors. Those combinations are easily
+recognized in the source because one vector is named `<name>s` (plural), and the
+other is named `<name>_map`.
+
+There are currently three, all in `BcProgram`:
+
+* `fns` and `fn_map` (`bc` functions).
+* `vars` and `var_map` (variables).
+* `arrs` and `arr_map` (arrays).
+
+They work like this: the `<name>_map` vector holds `BcId`'s, which just holds a
+string and an index. The string is the name of the item, and the index is the
+index of that item in the `<name>s` vector.
+
+Obviously, I could have just done a linear search for items in the `<name>s`
+vector, but that would be slow with a lot of functions/variables/arrays.
+Instead, I ensure that whenever an item is inserted into the `<name>_map`
+vector, the item is inserted in sorted order. This means that the `<name>_map`
+is always sorted (by the names of the items).
+
+So when looking up an item in the "map", what is really done is this:
+
+1. A binary search is carried out on the names in the `<name>_map` vector.
+2. When one is found, it returns the index in the `<name>_map` vector where the
+ item was found.
+3. This index is then used to retrieve the `BcId`.
+4. The index from the `BcId` is then used to index into the `<name>s` vector,
+ which returns the *actual* desired item.
+
+Why were the `<name>s` and `<name>_map` vectors not combined for ease? The
+answer is that sometime, when attempting to insert into the "map", code might
+find that something is already there. For example, a function with that name may
+already exist, or the variable might already exist.
+
+If the insert fails, then the name already exists, and the inserting code can
+forego creating a new item to put into the vector. However, if there is no item,
+the inserting code must create a new item and insert it.
+
+If the two vectors were combined together, it would not be possible to separate
+the steps such that creating a new item could be avoided if it already exists.
+
+#### Slabs and Slab Vectors
+
+`bc` allocates *a lot* of small strings, and small allocations are the toughest
+for general-purpose allocators to handle efficiently.
+
+Because of that reason, I decided to create a system for allocating small
+strings using something that I call a "slab vector" after [slab
+allocators][201].
+
+These vectors allocate what I call "slabs," which are just an allocation of a
+single page with a length to tell the slab how much of the slab is used.
+
+The vector itself holds slabs, and when the slab vector is asked to allocate a
+string, it attempts to in the last slab. If that slab cannot do so, it allocates
+a new slab and allocates from that.
+
+There is one exception: if a string is going to be bigger than 128 bytes, then
+the string is directly allocated, and a slab is created with that pointer and a
+length of `SIZE_MAX`, which tells the slab vector that it is a direct
+allocation. Then, the last slab is pushed into the next spot and the new special
+slab is put into the vacated spot. This ensures that a non-special slab is
+always last.
+
+### Command-Line History
+
+When I first wrote `bc`, I immediately started using it in order to eat my own
+dog food.
+
+It sucked, and the biggest reason why was because of the lack of command-line
+history.
+
+At first, I just dealt with it, not knowing how command-line history might be
+implemented.
+
+Eventually, I caved and attempted to adapt [`linenoise-mob`][28], which I had
+known about for some time.
+
+It turned out to be easier than I thought; the hardest part was the tedious
+renaming of everything to fit the `bc` naming scheme.
+
+Understanding command-line history in `bc` is really about understanding VT-100
+escape codes, so I would start there.
+
+Now, the history implementation of `bc` has been adapted far beyond that initial
+adaptation to make the command-line history implementation perfect for `bc`
+alone, including integrating it into `bc`'s [Custom I/O][114] and making sure
+that it does not disturb output that did not end with a newline.
+
+On top of that, at one point, I attempted to get history to work on Windows. It
+barely worked after a lot of work and a lot of portability code, but even with
+all of that, it does not have at least one feature: multi-line pasting from the
+clipboard.
+
+### Error Handling
+
+The error handling on `bc` got an overhaul for version [`3.0.0`][32], and it
+became one of the things that taught me the most about C in particular and
+programming in general.
+
+Before then, error handling was manual. Almost all functions returned a
+`BcStatus` indicating if an error had occurred. This led to a proliferation of
+lines like:
+
+```
+if (BC_ERR(s)) return s;
+```
+
+In fact, a quick and dirty count of such lines in version `2.7.2` (the last
+version before [`3.0.0`][32]) turned up 252 occurrences of that sort of line.
+
+And that didn't even guarantee that return values were checked *everywhere*.
+
+But before I can continue, let me back up a bit.
+
+From the beginning, I decided that I would not do what GNU `bc` does on errors;
+it tries to find a point at which it can recover. Instead, I decided that I
+would have `bc` reset to a clean slate, which I believed, would reduce the
+number of bugs where an unclean state caused errors with continuing execution.
+
+So from the beginning, errors would essentially unwind the stack until they got
+to a safe place from which to clean the slate, reset, and ask for more input.
+
+Well, if that weren't enough, `bc` also has to handle [POSIX signals][113]. As
+such, it had a signal handler that set a flag. But it could not safely interrupt
+execution, so that's all it could do.
+
+In order to actually respond to the signal, I had to litter checks for the flag
+*everywhere* in the code. And I mean *everywhere*. They had to be checked on
+every iteration of *every* loop. They had to be checked going into and out of
+certain functions.
+
+It was a mess.
+
+But fortunately for me, signals did the same thing that errors did: they unwound
+the stack to the *same* place.
+
+Do you see where I am going with this?
+
+It turns out that what I needed was a [async-signal-safe][115] form of what
+programmers call "exceptions" in other languages.
+
+I knew that [`setjmp()`][116] and [`longjmp()`][117] are used in C to implement
+exceptions, so I thought I would learn how to use them. How hard could it be?
+
+Quite hard, it turns out, especially in the presence of signals. And that's
+because there are a few big snares:
+
+1. The value of any local variables are not guaranteed to be preserved after a
+ `longjmp()` back into a function.
+2. While `longjmp()` is required to be [async-signal-safe][115], if it is
+ invoked by a signal handler that interrupted a non-[async-signal-safe][115]
+ function, then the behavior is undefined.
+3. Any mutation that is not guaranteed to be atomic with respect to signals may
+ be incomplete when a signal arrives.
+
+Oh boy.
+
+For number 1, the answer to this is to hide data that must stay changed behind
+pointers. Only the *pointers* are considered local, so as long as I didn't do
+any modifying pointer arithmetic, pointers and their data would be safe. For
+cases where I have local data that must change and stay changed, I needed to
+*undo* the `setjmp()`, do the change, and the *redo* the `setjmp()`.
+
+For number 2 and number 3, `bc` needs some way to tell the signal handler that
+it cannot do a `longjmp()`. This is done by "locking" signals with a `volatile
+sig_atomic_t`. (For more information, see the [Async-Signal-Safe Signal
+Handling][173] section.) For every function that calls a function that is not
+async-signal-safe, they first need to use `BC_SIG_LOCK` to lock signals, and
+afterward, use `BC_SIG_UNLOCK` to unlock signals.
+
+Code also need to do this for all global, non-atomic mutation, which means that
+modifying any part of the `BcVm` global struct.
+
+`BC_SIG_UNLOCK` has another requirement: it must check for signals or errors and
+jump if necessary.
+
+On top of all of that, *all* functions with cleanup needed to be able to run
+their cleanup. This meant that `longjmp()` could not just jump to the finish; it
+had to start what I call a "jump series," using a stack of `jmp_buf`'s
+(`jmp_bufs` in `BcVm`). Each `longjmp()` uses the top of the `jmp_bufs` stack to
+execute its jump. Then, if the cleanup code was executed because of a jump, the
+cleanup code was responsible for continuing the jump series by popping the
+previous item off the stack and using the new top of the stack for a jump.
+
+In this way, C++-style exceptions were implemented in pure C. Not fun, but it
+works. However, the order of operations matters, especially in the macros that
+help implement the error handling.
+
+For example, in `BC_UNSETJMP`, signals are unlocked before checking for signals.
+If a signal comes between, that's fine; it will still cause a jump to the right
+place. However, disabling the lock after could mean that a signal could come
+*after* checking for signals, but before signals were unlocked, causing the
+handling of the signal to be delayed.
+
+#### Custom I/O
+
+Why did I implement my own buffered I/O for `bc`? Because I use `setjmp()` and
+`longjmp()` for error handling (see the [Error Handling][97] section), and the
+buffered I/O in `libc` does not interact well with the use of those procedures;
+all of the buffered I/O API is basically non-[async-signal-safe][115].
+
+Implementing custom buffered I/O had other benefits. First, it allowed me to
+tightly integrate history with the I/O code. Second, it allowed me to make
+changes to history in order to make it adapt to user prompts.
+
+### Lexing
+
+To simplify parsing, both calculators use lexers to turn the text into a more
+easily-parsable form.
+
+While some tokens are only one character long, others require many tokens, and
+some of those need to store all of the text corresponding to the token for use
+by the parsers. Tokens that need to store their corresponding text include, but
+are not limited to:
+
+* Strings.
+* Numbers.
+* Identifiers.
+
+For this purpose, the lexer has a [vector][111] named `str` to store the data
+for tokens. This data is overwritten if another token is lexed that needs to
+store data, so the parsers need to copy the data before calling the lexer again.
+
+Both lexers do some of the same things:
+
+* Lex identifiers into tokens, storing the identifier in `str`.
+* Lex number strings into tokens, storing the string in `str`.
+* Lex whitespace.
+* Lex comments.
+
+Other than that, and some common plumbing, the lexers have separate code.
+
+#### `dc` Lexing
+
+The `dc` lexer is remarkably simple; in fact, besides [`src/main.c`][205],
+[`src/bc.c`][40], and [`src/dc.c`][44], which just contain one function each,
+the only file smaller than [`src/dc_lex.c`][45] is [`src/args.c`][206], which
+just processes command-line arguments after they are parsed by
+[`src/opt.c`][51].
+
+For most characters, the `dc` lexer is able to convert directly from the
+character to its corresponding token. This happens using `dc_lex_tokens[]` in
+[`src/data.c`][131].
+
+`dc`'s lexer also has to lex the register name after lexing tokens for commands
+that need registers.
+
+And finally, `dc`'s lexer needs to parse `dc` strings, which is the only part of
+the `dc` lexer that is more complex than the `bc` lexer. This is because `dc`
+strings need to have a balanced number of brackets.
+
+#### `bc` Lexing
+
+The `bc` lexer is fairly simple. It does the following things:
+
+* Lexes `bc` strings.
+* Lexes `bc` identifiers. This is necessary because this is how `bc` keywords
+ are lexed. After ensuring that an identifier is not a keyword, the `bc` lexer
+ allows the common identifier function to take over.
+* Turns characters and groups of characters into `bc` operator tokens.
+
+### Parsing
+
+The difference between parsing `bc` and `dc` code is...vast. The `dc` parser is
+simple, while the `bc` parser is the most complex piece of code in the entire
+codebase.
+
+However, they both do some of the same things.
+
+First, the parsers do *not* use [abstract syntax trees][207]; instead, they
+directly generate the bytecode that will be executed by the `BcProgram` code.
+Even in the case of `bc`, this heavily simplifies the parsing because the
+[Shunting-Yard Algorithm][109] is designed to generate [Reverse Polish
+Notation][108], which is basically directly executable.
+
+Second, any extra data that the `BcProgram` needs for execution is stored into
+functions (see the [Functions][208] section). These include constants and
+strings.
+
+#### `dc` Parsing
+
+The parser for `dc`, like its lexer, is remarkably simple. In fact, the easiness
+of lexing and parsing [Reverse Polish notation][108] is probably why it was used
+for `dc` when it was first created at Bell Labs.
+
+For most tokens, the `dc` parser is able to convert directly from the token
+to its corresponding instruction. This happens using `dc_parse_insts[]` in
+[`src/data.c`][131].
+
+`dc`'s parser also has to parse the register name for commands that need
+registers. This is the most complex part of the `dc` parser; each different
+register command needs to be parsed differently because most of them require two
+or more instructions to execute properly.
+
+For example, storing in a register requires a swap instruction and an assignment
+instruction.
+
+Another example are conditional execution instructions; they need to produce the
+instruction for the condition, and then they must parse a possible "else" part,
+which might not exist.
+
+##### Existing Commands
+
+`dc` is based on commands, which are usually one letter. The following table is
+a table of which ASCII characters are already used:
+
+| Characters | Used? | For... |
+|------------|-------|--------------------------------------------|
+| Space | x | Separator |
+| `!` | x | Conditional Execution of Registers |
+| `"` | x | Bounded Rand Operator |
+| `#` | x | Comments |
+| `$` | x | Truncation |
+| `%` | x | Modulus |
+| `&` | | |
+| `'` | x | Rand Operator |
+| `(` | x | Greater Than Operator |
+| `)` | x | Less Than Operator |
+| `*` | x | Multiplication |
+| `+` | x | Addition |
+| `,` | x | Depth of Execution Stack |
+| `-` | x | Subtraction |
+| `.` | x | Numbers |
+| `/` | x | Division |
+| `0-9` | x | Numbers |
+| `:` | x | Store into Array |
+| `;` | x | Load from Array |
+| `<` | x | Conditional Execution of Registers |
+| `=` | x | Conditional Execution of Registers |
+| `>` | x | Conditional Execution of Registers |
+| `?` | x | Ask for User Input |
+| `@` | x | Places Operator |
+| `A-F` | x | Numbers |
+| `G` | x | Equal Operator |
+| `H` | x | Shift Left |
+| `I` | x | Push `ibase` onto Stack |
+| `J` | x | Push `seed` onto Stack |
+| `K` | x | Push `scale` onto Stack |
+| `L` | x | Pop off of Register |
+| `M` | x | Boolean And Operator |
+| `N` | x | Boolean Not Operator |
+| `O` | x | Push `obase` onto Stack |
+| `P` | x | Byte Stream Printing |
+| `Q` | x | Quit Some Number of Macros |
+| `R` | x | Pop Top of Stack |
+| `S` | x | Push onto Register |
+| `T` | x | Push Max `ibase` onto Stack |
+| `U` | x | Push Max `obase` onto Stack |
+| `V` | x | Push Max `scale` onto Stack |
+| `W` | x | Push Max of `'` Operator |
+| `X` | x | Scale of a Number |
+| `Y` | x | Length of Array |
+| `Z` | x | Number of Significant Digits |
+| `[` | x | Strings |
+| `\\` | x | Escaping Brackets in Strings |
+| `]` | x | Strings |
+| `^` | x | Power |
+| `_` | x | Negative Numbers and Negation |
+| Backtick | | |
+| `a` | x | Asciify |
+| `b` | x | Absolute Value |
+| `c` | x | Clear Stack |
+| `d` | x | Duplication of Top of Stack |
+| `e` | x | Else in Conditional Execution of Registers |
+| `f` | x | Printing the Stack |
+| `g` | x | Global Settings |
+| `h` | x | Shift Right |
+| `i` | x | Set `ibase` |
+| `j` | x | Set `seed` |
+| `k` | x | Set `scale` |
+| `l` | x | Load from Register |
+| `m` | x | Boolean Or Operator |
+| `n` | x | Print and Pop |
+| `o` | x | Set `obase` |
+| `p` | x | Print with Newline |
+| `q` | x | Quit Two Macros |
+| `r` | x | Swap Top Two Items |
+| `s` | x | Store into Register |
+| `t` | | |
+| `u` | | |
+| `v` | x | Square Root |
+| `w` | | |
+| `x` | x | Execute String |
+| `y` | x | Current Depth of a Register |
+| `z` | x | Current Depth of Stack |
+| `{` | x | Greater Than or Equal Operator |
+| `\|` | x | Moduler Exponentiation |
+| `}` | x | Less Than or Equal Operator |
+| `~` | x | Division and Modulus Combined |
+
+#### `bc` Parsing
+
+`bc`'s parser is, by far, the most sensitive piece of code in this software, and
+there is a very big reason for that: `bc`'s standard is awful and defined a very
+poor language.
+
+The standard says that either semicolons or newlines can end statements. Trying
+to parse the end of a statement when it can either be a newline or a semicolon
+is subtle. Doing it in the presence of control flow constructs that do not have
+to use braces is even harder.
+
+And then comes the biggest complication of all: `bc` has to assume that it is
+*always* at a REPL (Read-Eval-Print Loop). `bc` is, first and foremost, an
+*interactive* utility.
+
+##### Flags
+
+All of this means that `bc` has to be able to partially parse something, store
+enough data to recreate that state later, and return, making sure to not
+execute anything in the meantime.
+
+*That* is what the flags in [`include/bc.h`][106] are: they are the state that
+`bc` is saving for itself.
+
+It saves them in a stack, by the way, because it's possible to nest
+structures, just like any other programming language. Thus, not only does it
+have to store state, it needs to do it arbitrarily, and still be able to
+come back to it.
+
+So `bc` stores its parser state with flags in a stack. Careful setting of these
+flags, along with properly using them and maintaining the flag stack, are what
+make `bc` parsing work, but it's complicated. In fact, as I mentioned, the `bc`
+parser is the single most subtle, fickle, and sensitive piece of code in the
+entire codebase. Only one thing came close once: square root, and that was only
+sensitive because I wrote it wrong. This parser is pretty good, and it is
+*still* sensitive. And flags are the reason why.
+
+For more information about what individual flags there are, see the comments in
+[`include/bc.h`][106].
+
+##### Labels
+
+`bc`'s language is Turing-complete. That means that code needs the ability to
+jump around, specifically to implement control flow like `if` statements and
+loops.
+
+`bc` handles this while parsing with what I called "labels."
+
+Labels are markers in the bytecode. They are stored in functions alongside the
+bytecode, and they are just indices into the bytecode.
+
+When the `bc` parser creates a label, it pushes an index onto the labels array,
+and the index of the label in that array is the index that will be inserted into
+the bytecode.
+
+Then, when a jump happens, the index pulled out of the bytecode is used to index
+the labels array, and the label (index) at the index is then used to set the
+instruction pointer.
+
+##### Cond Labels
+
+"Cond" labels are so-called because they are used by conditionals.
+
+The key to them is that they come *before* the code that uses them. In other
+words, when jumping to a condition, code is jumping *backwards*.
+
+This means that when a cond label is created, the value that should go there is
+well-known. Cond labels are easy.
+
+However, they are still stored on a stack so that the parser knows what cond
+label to use.
+
+##### Exit Labels
+
+Exit labels are not so easy.
+
+"Exit" labels are so-called because they are used by code "exiting" out of `if`
+statements or loops.
+
+The key to them is that they come *after* the code that uses them. In other
+words, when jumping to an exit, code is jumping *forwards*.
+
+But this means that when an exit label is created, the value that should go
+there is *not* known. The code that needs it must be parsed and generated first.
+
+That means that exit labels are created with the index of `SIZE_MAX`, which is
+then specifically checked for with an assert in `bc_program_exec()` before using
+those indices.
+
+There should ***NEVER*** be a case when an exit label is not filled in properly
+if the parser has no bugs. This is because every `if` statement, every loop,
+must have an exit, so the exit must be set. If not, there is a bug.
+
+Exit labels are also stored on a stack so that the parser knows what exit label
+to use.
+
+##### Expression Parsing
+
+`bc` has expressions like you might expect in a typical programming language.
+This means [infix notation][107].
+
+One thing about infix notation is that you can't just generate code straight
+from it like you can with [Reverse Polish notation][108]. It requires more work
+to shape it into a form that works for execution on a stack machine.
+
+That extra work is called the [Shunting-Yard algorithm][109], and the form it
+translates infix notation into is...[Reverse Polish notation][108].
+
+In order to understand the rest of this section, you must understand the
+[Shunting-Yard algorithm][109]. Go do that before you read on.
+
+###### Operator Stack
+
+In `bc`, the [Shunting-Yard algorithm][109] is implemented with bytecode as the
+output and an explicit operator stack (the `ops` field in `BcParse`) as the
+operator stack. It stores tokens from `BcLex`.
+
+However, there is one **HUGE** hangup: multiple expressions can stack. This
+means that multiple expressions can be parsed at one time (think an array element
+expression in the middle of a larger expression). Because of that, we need to
+keep track of where the previous expression ended. That's what `start` parameter
+to `bc_parse_operator()` is.
+
+Parsing multiple expressions on one operator stack only works because
+expressions can only *stack*; this means that, if an expression begins before
+another ends, it must *also* end before that other expression ends. This
+property ensures that operators will never interfere with each other on the
+operator stack.
+
+###### Recursion
+
+Because expressions can stack, parsing expressions actually requires recursion.
+Well, it doesn't *require* it, but the code is much more readable that way.
+
+This recursion is indirect; the functions that `bc_parse_expr_err()` (the actual
+expression parsing function) calls can, in turn, call it.
+
+###### Expression Flags
+
+There is one more big thing: not all expressions in `bc` are equal.
+
+Some expressions have requirements that others don't have. For example, only
+array arguments can be arrays (which are technically not expressions, but are
+treated as such for parsing), and some operators (in POSIX) are not allowed in
+certain places.
+
+For this reason, functions that are part of the expression parsing
+infrastructure in `bc`'s parser usually take a `flags` argument. This is meant
+to be passed to children, and somewhere, they will be checked to ensure that the
+resulting expression meets its requirements.
+
+There are also places where the flags are changed. This is because the
+requirements change.
+
+Maintaining the integrity of the requirements flag set is an important part of
+the `bc` parser. However, they do not have to be stored on a stack because their
+stack is implicit from the recursion that expression parsing uses.
+
+### Functions
+
+Functions, in `bc`, are data structures that contain the bytecode and data
+produced by the parsers. Functions are what the `BcProgram` program executes.
+
+#### Main and Read Functions
+
+There are two functions that always exist, which I call the "main" and "read"
+functions.
+
+The "main" function is the function in which any code and data outside other
+functions is put. Basically, it is the function where the scripting code ends
+up.
+
+The "read" function is the function that is reset and parsed every time a call
+to the `read()` builtin function happens.
+
+#### `dc` Strings
+
+In `dc`, strings can be executed, and since there are no actual "functions" in
+`dc`, strings are handled as functions. In fact, they are effectively translated
+into functions by parsing.
+
+##### Tail Calls
+
+Since strings in `dc` are functions, and the fact that `dc` has no native loops,
+such loops are implemented in `dc` code using strings with conditional execution
+commands at the end of strings.
+
+When such conditional execution, or even unconditional execution, commands are
+the very last commands in a string, then `dc` can perform a [tail call][202].
+
+This is done by recording the fact that a tail call happened, done by
+incrementing an integer on a stack. When a string is executed *without* a tail
+call, a new entry is pushed onto the stack with the integer `1`.
+
+When a string finally quits that followed tail calls, its stack entry is popped,
+eliminating all of those tail calls.
+
+Why perform tail calls? Because otherwise, `dc` would be subject to the same
+thing that plagues [functional programming languages][203]: stack overflow. In
+`dc`'s case, that would manifest itself as a growing [heap][204], because the
+execution stack is stored on the heap, until a fatal allocation failure would
+occur.
+
+#### Execution
+
+Execution is handled by an interpreter implemented using `BcProgram` and code
+in [`src/program.c`][53].
+
+The interpreter is a mix between a [stack machine][210] and a [register
+machine][211]. It is a stack machine in that operations happen on a stack I call
+the "results stack," but it is a register machine in that items on the stack can
+be stored to and loaded from "registers" (`dc` terminology), variables (`bc`
+terminology), and arrays.
+
+##### Stacks
+
+There are two stacks in the interpreter:
+
+* The "results" stack (as mentioned above).
+* The "execution" stack.
+
+The results stack (the `results` field of the `BcProgram` struct) is the stack
+where the results of computations are stored. It is what makes the interpreter
+part [stack machine][210]. It is filled with `BcResult`'s.
+
+The execution stack (the `stack` field of the `BcProgram` struct) is the stack
+that tracks the current execution state of the interpreter. It is the presence
+of this separate stack that allows the interpreter to implement the machine as a
+loop, rather than recursively. It is filled with `BcInstPtr`'s, which are the
+"instruction pointers."
+
+These instruction pointers have three fields, all integers:
+
+* `func`, the index of the function that is currently executing.
+* `idx`, the index of the next bytecode instruction to execute in the function's
+ bytecode array.
+* `len`, which is the length of the results stack when the function started
+ executing. This is not used by `dc`, but it used by `bc` because functions
+ in `bc` should never affect the results stack of their callers.
+
+With these three fields, and always executing using the instruction pointer at
+the top of the execution stack, the interpreter can always keep track of its
+execution.
+
+When a function or a string starts executing, a new `BcInstPtr` is pushed onto
+the execution stack for it. This includes if a function was called recursively.
+And then, when the function or string returns, its `BcInstPtr` is popped off of
+the execution stack.
+
+##### Bytecode
+
+Execution of functions are done through bytecode produced directly by the
+parsers (see the [Parsing][209]). This bytecode is stored in the `code`
+[vector][111] of the `BcFunc` struct.
+
+This is a vector for two reasons:
+
+* It makes it easier to add bytecode to the vector in the parsers.
+* `bc` allows users to redefine functions.
+
+The reason I can use bytecode is because there are less than 256 instructions,
+so an `unsigned char` can store all the bytecodes.
+
+###### Bytecode Indices
+
+There is one other factor to bytecode: there are instructions that need to
+reference strings, constants, variables, or arrays. Bytecode need some way to
+reference those things.
+
+Fortunately, all of those things can be referenced in the same way: with indices
+because all of the items are in vectors.
+
+So `bc` has a way of encoding an index into bytecode. It does this by, after
+pushing the instruction that references anything, pushing a byte set to the
+length of the index in bytes, then the bytes of the index are pushed in
+little-endian order.
+
+Then, when the interpreter encounters an instruction that needs one or more
+items, it decodes the index or indices there and updates the `idx` field of the
+current `BcInstPtr` to point to the byte after the index or indices.
+
+One more thing: the encoder of the indices only pushes as many bytes as
+necessary to encode the index. It stops pushing when the index has no more bytes
+with any 1 bits.
+
+##### Variables
+
+In `bc`, the vector of variables, `vars` in `BcProgram`, is not a vector of
+numbers; it is a vector of vector of numbers. The first vector is the vector of
+variables, the second is the variable stack, and the last level is the actual
+number.
+
+This is because both `bc` and `dc` need variables to be stacks.
+
+For `dc`, registers are *defined* to be stacks.
+
+For `bc`, variables as stacks is how function arguments/parameters and function
+`auto` variables are implemented.
+
+When a function is called, and a value needs to be used as a function argument,
+a copy of the value is pushed onto the stack corresponding to the variable with
+the same name as the function's parameter. For `auto` variables, a new number
+set to zero is pushed onto each stack corresponding to the `auto` variables.
+(Zero is used because the [`bc` spec][2] requires that `auto` variables are set
+to zero.)
+
+It is in this way that the old value of the variable, which may not even be
+related to the function parameter or `auto` variable, is preserved while the
+variable is used as a function parameter or `auto` variable.
+
+When the function returns, of course, the stacks of the variables for the
+parameters and `auto`'s will have their top item popped, restoring the old value
+as it was before the function call.
+
+##### Arrays
+
+Like variables, arrays are also implemented as stacks. However, because they are
+arrays, there is yet another level; the `arrs` field in `BcProgram` is a vector
+of vectors of vectors of numbers. The first of the two levels is the vector of
+arrays, the second the stack of for each array, the third the actual array, and
+last the numbers in the array.
+
+`dc` has no need of this extra stack, but `bc` does because arrays can be
+function parameters themselves.
+
+When arrays are used for function arguments, they are copied with a deep copy;
+each item of the source vector is copied. This is because in `bc`, according to
+the [`bc` spec][2], all function arguments are passed by value.
+
+However, array references are possible (see below).
+
+When arrays are used as `auto`'s, a new vector is pushed with one element; if
+more elements are needed, the array is grown automatically, and new elements are
+given the value of zero.
+
+In fact, if *any* array is accessed and does not have an element at that index,
+the array is automaticall grown to that size, and all new elements are given the
+value zero. This behavior is guaranteed by the [`bc` spec][2].
+
+###### Array References
+
+Array references had to be implemented as vectors themselves because they must
+be pushed on the vectors stacks, which, as seen above, expect vectors
+themselves.
+
+So thus, references are implemented as vectors on the vector stacks. These
+vectors are not vectors of vectors themselves; they are vectors of bytes; in
+fact, the fact that they are byte vectors and not vector vectors is how a
+reference vector is detected.
+
+These reference vectors always have the same two things pushed: a byte encoding
+(the same way bytecode indices are) of the referenced vector's index in the
+`arrs` vector, and a byte encoding of the referenced vectors index in the vector
+stack.
+
+If an item in a referenced vector is needed, then the reference is dereferenced,
+and the item is returned.
+
+If a reference vector is passed to a function that does *not* expect a
+reference, the vector is dereferenced and a deep copy is done, in the same way
+as vectors are copied for normal array function parameters.
+
+### Callbacks
+
+There are many places in `bc` and `dc` where function pointers are used:
+
+* To implement destructors in vectors. (See the [Vectors][111] section.)
+* To select the correct lex and parse functions for `bc` and `dc`.
+* To select the correct function to execute unary operators.
+* To select the correct function to execute binary operators.
+* To calculate the correct number size for binary operators.
+* To print a "digit" of a number.
+* To seed the pseudo-random number generator.
+
+And there might be more.
+
+In every case, they are used for reducing the amount of code. Instead of
+`if`/`else` chains, such as:
+
+```
+if (BC_IS_BC) {
+ bc_parse_parse(vm.parse);
+}
+else {
+ dc_parse_parse(vm.parse);
+}
+```
+
+The best example of this is `bc_num_binary()`. It is called by every binary
+operator. It figures out if it needs to allocate space for a new `BcNum`. If so,
+it allocates the space and then calls the function pointer to the *true*
+operation.
+
+Doing it like that shrunk the code *immensely*. First, instead of every single
+binary operator duplicating the allocation code, it only exists in one place.
+Second, `bc_num_binary()` itself does not have a massive `if`/`else` chain or a
+`switch` statement.
+
+But perhaps the most important use was for destructors in vectors.
+
+Most of the data structures in `bc` are stored in vectors. If I hadn't made
+destructors available for vectors, then ensuring that `bc` had no memory leaks
+would have been nigh impossible. As it is, I check `bc` for memory leaks every
+release when I change the code, and I have not released `bc` after version
+`1.0.0` with any memory leaks, as far as I can remember anyway.
+
+### Numbers
+
+In order to do arbitrary-precision math, as `bc` must do, there must be some way
+of representing arbitrary-precision numbers. `BcNum` in [`include/num.h`][184]
+is `bc`'s way of doing that.
+
+(Note: the word ["limb"][214] is used below; it has a specific meaning when
+applied to arbitrary-precision numbers. It means one piece of the number. It can
+have a single digit, which is what GNU `bc` does, or it can have multiple, which
+is what this `bc` does.)
+
+This struct needs to store several things:
+
+* The array of limbs of the number. This is the `num` field.
+* The location of the decimal point. This is the `rdx` (short for [radix][215])
+ field.
+* The number of limbs the number has. This is the `len` field.
+* Whether the number is negative or not. This is the least significant bit of
+ the `rdx` field. More on that later.
+
+In addition, `bc`'s number stores the capacity of the limb array; this is the
+`cap` field.
+
+If the number needs to grow, and the capacity of the number is big enough, the
+number is not reallocated; the number of limbs is just added to.
+
+There is one additional wrinkle: to make the usual operations (binary operators)
+fast, the decimal point is *not* allowed to be in the middle of a limb; it must
+always be between limbs, after all limbs (integer), or before all limbs (real
+between -1 and 1).
+
+The reason for this is because addition, subtraction, multiplication, and
+division expect digits to be lined up on the decimal point. By requiring that it
+be between limbs, no extra alignment is needed, and those operations can proceed
+without extra overhead.
+
+This does make some operations, most notably extending, truncating, and
+shifting, more expensive, but the overhead is constant, and these operations are
+usually cheap compared to the binary operators anyway.
+
+This also requires something else: `bc` numbers need to know *exactly* how many
+decimal places they have after the decimal point. If the decimal point must be
+inbetween limbs, the last decimal place could be in the middle of a limb. The
+amount of decimal places in a number is carefully tracked and stored in the
+`scale` field, and this number must always coincide with the `rdx` field by the
+following formula:
+
+```
+scale + (BC_BASE_DIGS - 1) / BC_BASE_DIGS == rdx >> 1
+```
+
+(`BC_BASE_DIGS` is the number of decimal digits stored in one limb. It is 9 on
+64-bit systems and 4 on other systems.)
+
+Yes, `rdx` is shifted; that is because the negative bit is stored in the least
+significant bit of the `rdx` field, and the actual radix (amount of limbs after
+the decimal/radix point) is stored in the rest of the bits. This is safe because
+`BC_BASE_DIGS` is always at least 4, which means `rdx` will always need at least
+2 bits less than `scale`.
+
+In addition to `rdx` always matching `scale`, another invariant is that `rdx`
+must always be less than or equal to `len`. (Because `scale` may be greater than
+`rdx`, `scale` does not have to be less than or equal to `len`.)
+
+Another invariant is that `len` must always be less than or equal to `cap`, for
+obvious reasons.
+
+The last thing programmers need to know is that the limb array is stored in
+little-endian order. This means that the last decimal places are in the limb
+stored at index 0, and the most significant digits are stored at index `len-1`.
+
+This is done to make the most important operations fast. Addition and
+subtraction are done from least significant to most significant limbs, which
+means they can speed through memory in the way most computers are best at.
+Multiplication does the same, sort of, and with division, it matters less.
+Comparison does need to go backwards, but that's after exhausting all other
+alternatives, including for example, checking the length of the integer portion
+of each limb array.
+
+Finally, here are some possible special situations with numbers and what they
+mean:
+
+* `len == 0`: the number equals 0.
+* `len == 0 && scale != 0`: the number equals 0, but it has a `scale` value.
+ This is the only case where `scale` does not have to coincide with `rdx`
+ This can happen with division, for example, that sets a specific `scale` for
+ the result value but may produce 0.
+* `(rdx >> 1) < len`: the number is greater than or equal to 1, or less than or
+ equal to -1.
+* `(rdx >> 1) == len`: the number is greater than -1 and less than 1, not
+ including 0, although this will be true for 0 as well. However, 0 is always
+ assumed to be represented by `len == 0`.
+* `(rdx >> 1) == 0`: the number is an integer. In this case, `scale` must also
+ equal 0.
+
+#### Math Style
+
+When I wrote the math for `bc`, I adopted a certain style that, if known, will
+make it easier to understand the code. The style follows these rules:
+
+* `BcNum` arguments always come before arguments of other types.
+* Among the `BcNum` arguments, the operands always come first, and the `BcNum`
+ where the result(s) will be stored come last.
+* Error checking is placed first in the function.
+* Easy cases are placed next.
+* Preparation, such as allocating temporaries, comes next.
+* The actual math.
+* Cleanup and ensuring invariants.
+
+While these rules are not hard and fast, using them as a guide will probably
+help.
+
+### Strings as Numbers
+
+Strings can be assigned to variables. This is a problem because the vectors for
+variable stacks expect `BcNum` structs only.
+
+While I could have made a union, I decided that the complexity of adding an
+entirely new type, with destructor and everything, was not worth it. Instead, I
+took advantage of the fact that `free()`, when passed a `NULL` pointer, will do
+nothing.
+
+Using that, I made it so `BcNum`'s could store strings instead. This is marked
+by the `BcNum` having a `NULL` limb array (`num`) and a `cap` of 0 (which should
+*never* happen with a real number, though the other fields could be 0).
+
+The `BcNum` stores the function that stores the string in the `rdx` field, and
+it stores the index of the string in the `scale` field. This is used to actually
+load the string if necessary.
+
+Note that historically, string information was stored in the `loc` field of
+the `d` union in a `BcResult`. This was changed recently to standardize; now,
+all string information are stored in the `n` field of the `d` union regardless.
+This means that all string information is stored in `BcNum`'s. This removes
+extra cases.
+
+Also, if a temp is made with a string, then the result type should still be
+`BC_RESULT_STR`, not `BC_RESULT_TEMP`. This is to make it easier to do type
+checks.
+
+### Pseudo-Random Number Generator
+
+In order to understand this section, I suggest you read the information in the
+manpages about the pseudo-random number generator (PRNG) first; that will help
+you understand the guarantees it has, which is important because this section
+delves into implementation details.
+
+First, the PRNG I use is seeded; this is because most OS's have an excellent
+cryptographically secure PRNG available via command-line, usually
+`/dev/urandom`, but the only *seeded* PRNG available is usually `bash`'s
+`$RANDOM`, which is essentially a wrapper around C's `rand()`.
+
+`rand()` is...bad. It is only guaranteed to return 15 bits of random data.
+Obviously, getting good random data out of that would be hard with that alone,
+but implementations also seem to be poor.
+
+On top of that, `bc` is an arbitrary-precision calculator; if I made it able to
+generate random numbers, I could make it generate random numbers of any size,
+and since it would be seeded, results would be reproducible, when wanted.
+
+So to get that, I needed a seeded PRNG with good characteristics. After scouring
+the Internet, I decided on the [PCG PRNG][215], mostly because of [this blog
+post][216]. Part of the reason was the behavior of the xoroshiro128+ author, who
+hates on PCG and its author, but also because PCG seemed to do better when
+tested by independent parties.
+
+After that decision, I faced a challenge: PCG requires 255 bits of seed: 128 for
+the actual seed, and 127 for the "increment." (Melissa O'Neill, the PCG author,
+likens the increment to selecting a codebook.)
+
+I could, of course, put the entire 255 bits into one massive arbitrary-precision
+number; `bc` is good at that, after all. But that didn't sit right with me
+because it would mean any seed selected by users would have the real portion
+ignored, which is stupid in a program like `bc`.
+
+Instead, I decided to make the integer portion the increment (clamped down to
+size), and the real portion the seed.
+
+In most cases, this would be a bad idea because you cannot, in general, know how
+many decimal places you need to represent any number with `n` real digits in
+base `b` in another base. However, there is an easy to how many decimal digits
+after the decimal point it takes to represent reals of base 2 in base 10: the
+power of two.
+
+It turns out that, for base 2 represented in base 10, the power of 2 is
+*exactly* how many digits are necessary to represent *any* number `n/2^p`, where
+`p` is the power of 2. This is because at every halving, the number of decimal
+places increases by 1:
+
+```
+0.5
+0.25
+0.125
+0.0625
+0.03125
+0.015625
+...
+```
+
+So the algorithm to convert all 255 bits of the seed is as follows:
+
+1. Convert the increment to a `BcNum`.
+2. Convert the seed to a `BcNum`.
+3. Divide the seed by `2^128` with a `scale` of 128. (For 32-bit systems,
+ substitute 64 bits for 128.)
+4. Add the two numbers together.
+
+Likewise, the algorithm to convert from a user-supplied number to a seed is:
+
+1. Truncate a copy of the number.
+2. Subtract the result from #1 from the original number. This gives the real
+ portion of the number.
+3. Clamp the result of #1 to 127 (or 63) bits. This is the increment.
+4. Multiply the result of #2 by `2^128`.
+5. Truncate the result of #4. This is the seed.
+
+#### Generating Arbitrary-Precision Numbers
+
+I wrote a function (`bc_rand_bounded()`) that will return unbiased results with
+any bound below the max that PCG can generate.
+
+To generate an integer of arbitrary size using a bound, `bc` simply uses
+`bc_rand_bounded()` to generate numbers with a bound `10^BC_BASE_DIGS` for as
+many limbs as needed to satisfy the bigger bound.
+
+To generate numbers with arbitrary precision after the decimal point, `bc`
+merely generates an arbitrary precision integer with the bound `10^p`, where `p`
+is the desired number of decimal places, then divides in by `10^p` with a
+`scale` of `p`.
+
+## Debug Code
+
+Besides building `bc` in debug mode with the `-g` flag to [`configure.sh`][69],
+programmers can also add `-DBC_DEBUG_CODE=1` to the `CFLAGS`. This will enable
+the inclusion of *a lot* of extra code to assist with debugging.
+
+For more information, see all of the code guarded by `#if BC_DEBUG_CODE` in the
+[`include/`][212] directory and in the [`src/`][213] directory.
+
+Yes, all of the code is guarded by `#if` preprocessor statements; this is
+because the code should *never* be in a release build, and by making programmers
+add this manually (not even an option to [`configure.sh`][69]), it is easier to
+ensure that never happens.
+
+However, that said, the extra debug code is useful; that was why I kept it in.
+
+## Performance
+
+While I have put in a lot of effort to make `bc` as fast as possible, there
+might be some things you can do to speed it up without changing the code.
+
+First, you can probably use [profile-guided optimization][217] to optimize even
+better, using the test suite to profile.
+
+Second, I included macros that might help branch placement and prediction:
+
+* `BC_ERR(e)`
+* `BC_UNLIKELY(e)`
+* `BC_NO_ERR(e)`
+* `BC_LIKELY(e)`
+
+`BC_ERR` is the same as `BC_UNLIKELY`, and `BC_NO_ERR` is the same as
+`BC_LIKELY`; I just added them to also document branches that lead to error
+conditions or *away* from error conditions.
+
+Anyway, if `BC_LIKELY` and `BC_UNLIKELY` are not defined during compilation,
+they expand to nothing but the argument they were given.
+
+They can, however, be defined to `__builtin_expect((e), 1)` and
+`__builtin_expect((e), 0)`, respectively, on GCC and Clang for better branch
+prediction and placement. (For more information about `__builtin_expect()` see
+the [GCC documentation][218].)
+
+There might be other compilers that can take advantage of that, but I don't know
+anything about that.
+
+Also, as stated in the [build manual][219], link-time optimization is excellent
+at optimizing this `bc`. Use it.
+
+### Benchmarks
+
+To help programmers improve performance, I have built and assembled
+infrastructure to make benchmarking easy.
+
+First, in order to easily run benchmarks, I created
+[`scripts/benchmark.sh`][220].
+
+Second, I copied and adapted [`ministat.c`][223] [from FreeBSD][221], to make it
+easier to judge whether the results are significant or not.
+
+Third, I made the `make` clean target `make clean_benchmarks`, to clean
+`scripts/ministat` and the generated benchmark files.
+
+Fourth, I made it so [`scripts/benchmark.sh`][220] outputs the timing and memory
+data in a format that is easy for `scripts/ministat` to digest.
+
+To add a benchmark, add a script in the right directory to generate the
+benchmark. Yes, generate.
+
+All of the benchmarks are generated first, from `.bc` and `.dc` files in the
+[`benchmarks/bc/`][91] and [`benchmarks/dc/`][224]. This is so that massive
+amounts of data can be generated and then pushed through the calculators.
+
+If you need to benchmark `bc` or `dc` with simple loops, have the generator
+files simply print the loop code.
+
+### Caching of Numbers
+
+In order to provide some performance boost, `bc` tries to reuse old `BcNum`'s
+that have the default capacity (`BC_NUM_DEF_SIZE`).
+
+It does this by allowing `bc_num_free()` to put the limb array onto a
+statically-allocated stack (it's just a global array with a set size). Then,
+when a `BcNum` with the default capacity is needed, `bc_num_init()` asks if any
+are available. If the answer is yes, the one on top of the stack is returned.
+Otherwise, `NULL` is returned, and `bc_num_free()` knows it needs to `malloc()`
+a new limb array.
+
+When the stack is filled, any numbers that `bc` attempts to put on it are just
+freed.
+
+This setup saved a few percent in my testing for version [3.0.0][32], which is
+when I added it.
+
+## `bcl`
+
+At the request of one of my biggest users, I spent the time to make a build mode
+where the number and math code of `bc` could be wrapped into a library, which I
+called `bcl`.
+
+This mode is exclusive; `bc` and `dc` themselves are *not* built when building
+`bcl`.
+
+The only things in the `bc` math code that is not included is:
+
+* Printing newlines (clients do not care about `bc`'s line lenth restriction).
+* `dc`'s stream print.
+
+Even the [pseudo-random number generator][179] is included, with extra support
+for generating real numbers with it. (In `bc`, such support is in
+[`lib2.bc`][26].)
+
+### Signal Handling
+
+Like signal handling in `bc` proper (see the [Async-Signal-Safe Signal
+Handling][173] section), `bcl` has the infrastructure for signal handling.
+
+This infrastructure is different, however, as `bcl` assumes that clients will
+implement their own signal handling.
+
+So instead of doing signal handling on its own, `bcl` provides the capability to
+interrupt executions and return to the clients almost immediately. Like in `bc`,
+this is done with `setjmp()` and `longjmp()`, although the jump series is
+stopped before returning normally to client code.
+
+### Contexts
+
+Contexts were an idea by the same user that requested `bcl`. They are meant to
+make it so multiple clients in one program can keep their data separate from
+each other.
+
+### Numbers
+
+Numbers in `bcl` are literally indices into an encapsulated array of numbers,
+hidden in the context. These indices are then passed to clients to refer to
+numbers later.
+
+### Operand Consumption
+
+Most math functions in `bcl` "consume" their operand arguments; the arguments
+are freed, whether or not an error is returned.
+
+This is to make it easy to implement math code, like this:
+
+```
+n = bcl_add(bcl_mul(a, b), bcl_div(c, d));
+```
+
+If numbers need to be preserved, they can be with `bcl_dup()`:
+
+```
+n = bcl_add(bcl_mul(bcl_dup(a), bc_dup(b)), bcl_div(bcl_dup(c), bcl_dup(d)));
+```
+
+### Errors
+
+Errors can be encoded in the indices representing numbers, and where necessary,
+clients are responsible for checking those errors.
+
+The encoding of errors is this: if an error happens, the value `0-error` is
+returned. To decode, do the exact same thing. Thus, any index above
+`0-num_errors` is an error.
+
+If an index that represents an error is passed to a math function, that function
+propagates the error to its result and does not perform the math operation.
+
+All of this is to, once again, make it easy to implement the math code as above.
+
+However, where possible, errors are returned directly.
+
+[1]: https://en.wikipedia.org/wiki/Bus_factor
+[2]: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html#top
+[3]: https://en.wikipedia.org/wiki/Dc_(Unix)
+[4]: https://en.wikipedia.org/wiki/Reverse_Polish_notation
+[5]: ./bc/A.1.md#standard-library
+[6]: https://github.com/torvalds/linux/blob/master/kernel/time/timeconst.bc
+[7]: ./bc/A.1.md#extended-library
+[8]: #libbc-2
+[9]: #strgensh
+[10]: https://vimeo.com/230142234
+[11]: https://gavinhoward.com/2019/12/values-for-yao/
+[12]: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf
+[13]: ./build.md#cross-compiling
+[14]: ./build.md
+[15]: #strgenc
+[16]: http://landley.net/toybox/about.html
+[17]: https://www.busybox.net/
+[18]: https://en.wikipedia.org/wiki/Karatsuba_algorithm
+[19]: https://clang-analyzer.llvm.org/scan-build.html
+[20]: https://www.valgrind.org/
+[21]: https://clang.llvm.org/docs/AddressSanitizer.html
+[22]: https://gavinhoward.com/2019/11/finishing-software/
+[23]: #history
+[24]: https://clang.llvm.org/docs/ClangFormat.html
+[25]: ./algorithms.md
+[26]: #lib2bc
+[27]: #vmh
+[28]: https://github.com/rain-1/linenoise-mob
+[29]: https://github.com/antirez/linenoise
+[30]: #bclh
+[31]: #argsh
+[32]: ../NEWS.md#3-0-0
+[33]: ../NEWS.md
+[34]: https://github.com/skeeto/optparse
+[35]: #opth
+[36]: #historyh
+[37]: #randh
+[38]: #langh
+[39]: #numc
+[40]: #bcc
+[41]: #bc_lexc
+[42]: #bc_parsec
+[43]: #libraryc
+[44]: #dcc
+[45]: #dc_lexc
+[46]: #dc_parsec
+[47]: #filec
+[48]: #historyc
+[49]: #langc
+[50]: #lexc
+[51]: #optc
+[52]: #parsec
+[53]: #programc
+[54]: #randc
+[55]: #fileh
+[56]: #readc
+[57]: #programh
+[58]: #vmc
+[59]: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/gencat.html#top
+[60]: #manpagesh
+[61]: #bcl3md
+[62]: #bcl3
+[63]: #bclvcxproj
+[64]: #bclvcxprojfilters
+[65]: #bclsln
+[66]: #bcvcxproj
+[67]: #bcvcxprojfilters
+[68]: #bcsln
+[69]: #configuresh
+[70]: #makefilein
+[71]: #functionsh
+[72]: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/sh.html#top
+[73]: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18
+[74]: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/make.html#top
+[75]: #versionh
+[76]: ##posix-shell-scripts
+[77]: #tests
+[78]: #karatsubapy
+[79]: #bc-1
+[80]: #dc-1
+[81]: ./build.md#build-type
+[82]: #fuzzing-1
+[83]: #releasesh
+[84]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html#tag_08_02
+[85]: #locales-1
+[86]: #manuals-1
+[87]: #locale_installsh
+[88]: #locale_uninstallsh
+[89]: #bc1mdin
+[90]: #dc1mdin
+[91]: #bc
+[92]: https://pandoc.org/
+[93]: #release_settingstxt
+[94]: #aflpy
+[95]: #randmathpy
+[96]: #caching-of-numbers
+[97]: #error-handling
+[98]: #radamsatxt
+[99]: https://gitlab.com/akihe/radamsa
+[100]: #radamsash
+[101]: https://musl.libc.org/
+[102]: ./build.md#settings
+[103]: #test_settingstxt
+[104]: #test_settingssh
+[105]: #functionssh
+[106]: #bch
+[107]: https://en.wikipedia.org/wiki/Infix_notation
+[108]: https://en.wikipedia.org/wiki/Reverse_Polish_notation
+[109]: https://en.wikipedia.org/wiki/Shunting-yard_algorithm
+[110]: #bc-parsing
+[111]: #vectors
+[112]: https://git.yzena.com/Yzena/Yc/src/branch/master/include/yc/vector.h
+[113]: https://en.wikipedia.org/wiki/Signal_(IPC)
+[114]: #custom-io
+[115]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_04_03_03
+[116]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/setjmp.html
+[117]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/longjmp.html
+[118]: https://www.youtube.com/watch?v=4PaWFYm0kEw
+[119]: #fuzz_prepsh
+[120]: #bc_aflyaml
+[121]: #bc_afl_continueyaml
+[122]: https://github.com/tmux/tmux
+[123]: https://tmuxp.git-pull.com/
+[124]: #test-suite
+[125]: https://aflplus.plus/
+[126]: #link-time-optimization
+[127]: #fuzzing-performance
+[128]: #radamsa
+[129]: #afl-quickstart
+[130]: #convenience
+[131]: #datac
+[132]: https://git.yzena.com/gavin/vim-bc
+[133]: https://git.yzena.com/gavin/bc_libs
+[134]: #debugging
+[135]: #asserts
+[136]: #portability
+[137]: https://pexpect.readthedocs.io/en/stable/
+[138]: #test-suite-portability
+[139]: #historypy
+[140]: #historysh
+[141]: #group-tests
+[142]: #build-system
+[143]: #generated-tests
+[144]: #benchmarks-1
+[145]: #gen
+[146]: #test-coverage
+[147]: #integration-with-the-build-system
+[148]: #test-scripts
+[149]: #standard-tests
+[150]: #script-tests
+[151]: #error-tests
+[152]: #stdin-tests
+[153]: #read-tests
+[154]: #other-tests
+[155]: #history-tests
+[156]: #bcl
+[157]: #bcl-test
+[158]: #bclc
+[159]: #valgrind
+[160]: #addresssanitizer-and-friends
+[161]: #bc-2
+[162]: #dc-2
+[163]: #alltxt-1
+[164]: #errorstxt
+[165]: #posix_errorstxt
+[166]: #timeconstsh
+[167]: #alltxt-3
+[168]: #errorstxt-1
+[169]: #scripts-1
+[170]: #scripts-2
+[171]: #alltxt-2
+[172]: #alltxt-4
+[173]: #async-signal-safe-signal-handling
+[174]: #vectorh
+[175]: #read_errorstxt
+[176]: #statush
+[177]: #numbers
+[178]: #math-style
+[179]: #pseudo-random-number-generator
+[180]: #lexh
+[181]: #parseh
+[182]: #dch
+[183]: #libraryh
+[184]: #numh
+[185]: #readh
+[186]: #maps
+[187]: #slabs-and-slab-vectors
+[188]: ./build.md#extra-math
+[189]: #command-line-history
+[190]: #scriptsed
+[191]: #linux-timeconstbc-script
+[192]: #corpuses
+[193]: ./build.md#history
+[194]: https://www.valgrind.org/docs/manual/mc-manual.html
+[195]: #othersh
+[196]: https://scan.coverity.com/
+[197]: https://clang-analyzer.llvm.org/
+[198]: https://unix.stackexchange.com/questions/253349/eintr-is-there-a-rationale-behind-it
+[199]: https://cr.yp.to/docs/selfpipe.html
+[200]: https://skarnet.org/cgi-bin/archive.cgi?2:mss:1607:201701:dfblejammjllfkggpcph
+[201]: https://slembcke.github.io/2020/10/12/CustomAllocators.html#1-slab-allocator
+[202]: https://en.wikipedia.org/wiki/Tail_call
+[203]: https://en.wikipedia.org/wiki/Functional_programming_language
+[204]: https://en.wikipedia.org/wiki/C_dynamic_memory_allocation
+[205]: #mainc
+[206]: #argc
+[207]: https://en.wikipedia.org/wiki/Abstract_syntax_tree
+[208]: #functions
+[209]: #parsing
+[210]: https://en.wikipedia.org/wiki/Stack_machine
+[211]: https://en.wikipedia.org/wiki/Register_machine
+[212]: #include
+[213]: #src
+[214]: https://gmplib.org/manual/Nomenclature-and-Types
+[215]: https://en.wikipedia.org/wiki/Radix_point
+[216]: #main-and-read-functions
+[215]: https://www.pcg-random.org/
+[216]: https://lemire.me/blog/2017/08/22/testing-non-cryptographic-random-number-generators-my-results/
+[217]: https://en.wikipedia.org/wiki/Profile-guided_optimization
+[218]: https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html#index-_005f_005fbuiltin_005fexpect
+[219]: ./build.md#optimization
+[220]: #benchmarksh
+[221]: https://cgit.freebsd.org/src/tree/usr.bin/ministat/ministat.c
+[222]: https://www.freebsd.org/cgi/man.cgi?query=ministat&apropos=0&sektion=0&manpath=FreeBSD+13.0-RELEASE+and+Ports&arch=default&format=html
+[223]: #ministatc
+[224]: #dc
+[225]: #allsh
+[226]: #errorssh
+[227]: #errorsh
diff --git a/contrib/bc/manuals/header.txt b/contrib/bc/manuals/header.txt
new file mode 100644
index 000000000000..d805e14ad691
--- /dev/null
+++ b/contrib/bc/manuals/header.txt
@@ -0,0 +1,27 @@
+.\"
+.\" 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.
+.\"
diff --git a/contrib/bc/manuals/header_bc.txt b/contrib/bc/manuals/header_bc.txt
new file mode 100644
index 000000000000..fc2e6bdcb9c5
--- /dev/null
+++ b/contrib/bc/manuals/header_bc.txt
@@ -0,0 +1 @@
+.TH "BC" "1" "June 2021" "Gavin D. Howard" "General Commands Manual"
diff --git a/contrib/bc/manuals/header_bcl.txt b/contrib/bc/manuals/header_bcl.txt
new file mode 100644
index 000000000000..4b1c6974f3df
--- /dev/null
+++ b/contrib/bc/manuals/header_bcl.txt
@@ -0,0 +1 @@
+.TH "BCL" "3" "June 2021" "Gavin D. Howard" "Libraries Manual"
diff --git a/contrib/bc/manuals/header_dc.txt b/contrib/bc/manuals/header_dc.txt
new file mode 100644
index 000000000000..aad9e7cea50a
--- /dev/null
+++ b/contrib/bc/manuals/header_dc.txt
@@ -0,0 +1 @@
+.TH "DC" "1" "June 2021" "Gavin D. Howard" "General Commands Manual"
diff --git a/contrib/bc/manuals/release.md b/contrib/bc/manuals/release.md
new file mode 100644
index 000000000000..aa2de7ca9acb
--- /dev/null
+++ b/contrib/bc/manuals/release.md
@@ -0,0 +1,72 @@
+# Release Checklist
+
+This is the checklist for cutting a release.
+
+For a lot of these steps, they are only needed if the code that would be
+affected was changed. For example, I don't need to run the `scripts/randmath.py`
+test if I did not change any of the math code.
+
+1. Update the README.
+2. Update the manuals.
+3. Test history manually.
+4. Test with POSIX test suite.
+5. Run the `scripts/randmath.py` script an excessive amount and add failing
+ tests to test suite.
+ * debug
+ * release
+ * minrelease
+6. Fuzz with AFL.
+ * reldebug
+7. Fix AFL crashes.
+8. Find ASan crashes on AFL test cases.
+9. Fix ASan crashes.
+10. Build on Windows, no errors or warnings.
+ * Debug/`x64`.
+ * Debug/`x86`.
+ * Release{MD,MT}/`x64`.
+ * Release{MD,MT}/`x86`.
+11. Run and pass the `scripts/release.sh` script on my own machine.
+12. Run and pass the `scripts/release.sh` script, without generated tests and
+ sanitizers, on FreeBSD.
+13. Run and pass the `scripts/release.sh` script, without generated tests,
+ sanitizers, and 64-bit, on an ARM server.
+14. Run and pass the release script, with no generated tests, no clang, no
+ sanitizers, and no valgrind, on NetBSD.
+15. Run and pass the release script, with no generated tests, no sanitizers, and
+ no valgrind, on OpenBSD.
+16. Run `scan-build make`.
+17. Repeat steps 3-16 again and repeat until nothing is found.
+18. Update the benchmarks.
+19. Update the version and `NEWS.md` and commit.
+20. Boot into Windows.
+21. Build all release versions of everything.
+ * Release/`x64` for `bc`.
+ * Release/`x64` for `dc`.
+ * Release{MD,MT}/`x64` for `bcl`.
+ * Release/`x86` for `bc`.
+ * Release/`x86` for `dc`.
+ * Release{MD,MT}/`x86` for `bcl`.
+22. Put the builds where Linux can access them.
+23. Boot back into Linux.
+24. Run `make clean_tests`.
+25. Run the `scripts/package.sh` script.
+26. Upload the custom tarball and Windows builds to Yzena Gitea.
+27. Add output from `scripts/package.sh` to Yzena Gitea release notes.
+28. Edit Yzena Gitea release notes for the changelog.
+29. Upload the custom tarball to GitHub.
+30. Add output from `scripts/package.sh` to GitHub release notes.
+31. Edit GitHub release notes for the changelog.
+32. Notify the following:
+ * FreeBSD
+ * Adelie Linux
+ * Ataraxia Linux
+ * Sabotage
+ * xstatic
+ * OpenBSD
+ * NetBSD
+33. Submit new packages for the following:
+ * Alpine Linux
+ * Void Linux
+ * Gentoo Linux
+ * Linux from Scratch
+ * Arch Linux
diff --git a/contrib/bc/scripts/afl.py b/contrib/bc/scripts/afl.py
new file mode 100755
index 000000000000..c4312ce84f83
--- /dev/null
+++ b/contrib/bc/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/contrib/bc/scripts/alloc.sh b/contrib/bc/scripts/alloc.sh
new file mode 100755
index 000000000000..c5c46febe0b3
--- /dev/null
+++ b/contrib/bc/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/contrib/bc/scripts/benchmark.sh b/contrib/bc/scripts/benchmark.sh
new file mode 100755
index 000000000000..35f92452ce78
--- /dev/null
+++ b/contrib/bc/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/contrib/bc/scripts/bitfuncgen.c b/contrib/bc/scripts/bitfuncgen.c
new file mode 100644
index 000000000000..8fae531b9286
--- /dev/null
+++ b/contrib/bc/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/contrib/bc/scripts/fuzz_prep.sh b/contrib/bc/scripts/fuzz_prep.sh
new file mode 100755
index 000000000000..0441f94e340c
--- /dev/null
+++ b/contrib/bc/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/contrib/bc/scripts/manpage.sh b/contrib/bc/scripts/manpage.sh
new file mode 100755
index 000000000000..c1429a6ed51f
--- /dev/null
+++ b/contrib/bc/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/contrib/bc/scripts/ministat.c b/contrib/bc/scripts/ministat.c
new file mode 100644
index 000000000000..e5b7cd47b3e4
--- /dev/null
+++ b/contrib/bc/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/contrib/bc/scripts/package.sh b/contrib/bc/scripts/package.sh
new file mode 100755
index 000000000000..34692f7ab20a
--- /dev/null
+++ b/contrib/bc/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/contrib/bc/scripts/radamsa.sh b/contrib/bc/scripts/radamsa.sh
new file mode 100755
index 000000000000..c92923ddadc4
--- /dev/null
+++ b/contrib/bc/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/contrib/bc/scripts/radamsa.txt b/contrib/bc/scripts/radamsa.txt
new file mode 100644
index 000000000000..4bf28907bead
--- /dev/null
+++ b/contrib/bc/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/contrib/bc/scripts/randmath.py b/contrib/bc/scripts/randmath.py
new file mode 100755
index 000000000000..896f0e46c97f
--- /dev/null
+++ b/contrib/bc/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/contrib/bc/scripts/release.sh b/contrib/bc/scripts/release.sh
new file mode 100755
index 000000000000..12097b1cc8b9
--- /dev/null
+++ b/contrib/bc/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/contrib/bc/scripts/release_settings.txt b/contrib/bc/scripts/release_settings.txt
new file mode 100644
index 000000000000..1cf572347241
--- /dev/null
+++ b/contrib/bc/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/contrib/bc/scripts/test_settings.sh b/contrib/bc/scripts/test_settings.sh
new file mode 100755
index 000000000000..563dbf0e58f3
--- /dev/null
+++ b/contrib/bc/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/contrib/bc/scripts/test_settings.txt b/contrib/bc/scripts/test_settings.txt
new file mode 100644
index 000000000000..e6dd8ac92929
--- /dev/null
+++ b/contrib/bc/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
diff --git a/contrib/bc/src/bc_lex.c b/contrib/bc/src/bc_lex.c
index bd03d169ee06..4ab17c824b71 100644
--- a/contrib/bc/src/bc_lex.c
+++ b/contrib/bc/src/bc_lex.c
@@ -117,7 +117,7 @@ static void bc_lex_string(BcLex *l) {
// is '\q', which makes this loop simpler.
for (i = l->i; (c = buf[i]) && c != '"'; ++i) nlines += (c == '\n');
- if (BC_ERR(c == '\0') && !vm.eof && l->is_stdin)
+ if (BC_ERR(c == '\0') && !vm.eof && (l->is_stdin || l->is_exprs))
got_more = bc_lex_readLine(l);
} while (got_more && c != '"');
diff --git a/contrib/bc/src/dc_lex.c b/contrib/bc/src/dc_lex.c
index 576d50943f25..7f2f5dedc484 100644
--- a/contrib/bc/src/dc_lex.c
+++ b/contrib/bc/src/dc_lex.c
@@ -130,7 +130,8 @@ static void dc_lex_string(BcLex *l) {
}
if (BC_ERR(c == '\0' && depth)) {
- if (!vm.eof && l->is_stdin) got_more = bc_lex_readLine(l);
+ if (!vm.eof && (l->is_stdin || l->is_exprs))
+ got_more = bc_lex_readLine(l);
if (got_more) bc_vec_popAll(&l->str);
}
diff --git a/contrib/bc/src/lex.c b/contrib/bc/src/lex.c
index 51e9f31bfa11..3b84734efc55 100644
--- a/contrib/bc/src/lex.c
+++ b/contrib/bc/src/lex.c
@@ -82,8 +82,9 @@ void bc_lex_comment(BcLex *l) {
// If this is true, we need to request more data.
if (BC_ERR(!c || buf[i + 1] == '\0')) {
- // Read more.
- if (!vm.eof && l->is_stdin) got_more = bc_lex_readLine(l);
+ // Read more, if possible.
+ if (!vm.eof && (l->is_stdin || l->is_exprs))
+ got_more = bc_lex_readLine(l);
break;
}
@@ -302,7 +303,12 @@ bool bc_lex_readLine(BcLex *l) {
// bc_vm_readLine() needs them to be unlocked.
BC_SIG_UNLOCK;
- good = bc_vm_readLine(false);
+ // Make sure we read from the appropriate place.
+ if (l->is_stdin) good = bc_vm_readLine(false);
+ else {
+ assert(l->is_exprs);
+ good = bc_vm_readBuf(false);
+ }
BC_SIG_LOCK;
@@ -311,7 +317,7 @@ bool bc_lex_readLine(BcLex *l) {
return good;
}
-void bc_lex_text(BcLex *l, const char *text, bool is_stdin) {
+void bc_lex_text(BcLex *l, const char *text, bool is_stdin, bool is_exprs) {
BC_SIG_ASSERT_LOCKED;
@@ -321,6 +327,9 @@ void bc_lex_text(BcLex *l, const char *text, bool is_stdin) {
l->i = 0;
l->t = l->last = BC_LEX_INVALID;
l->is_stdin = is_stdin;
+ l->is_exprs = is_exprs;
+
+ assert(!l->is_stdin || !l->is_exprs);
bc_lex_next(l);
}
diff --git a/contrib/bc/src/parse.c b/contrib/bc/src/parse.c
index 7fdfa31df4ac..ba139f61ba46 100644
--- a/contrib/bc/src/parse.c
+++ b/contrib/bc/src/parse.c
@@ -150,13 +150,13 @@ void bc_parse_number(BcParse *p) {
#endif // BC_ENABLE_EXTRA_MATH
}
-void bc_parse_text(BcParse *p, const char *text, bool is_stdin) {
+void bc_parse_text(BcParse *p, const char *text, bool is_stdin, bool is_exprs) {
BC_SIG_LOCK;
// Make sure the pointer isn't invalidated.
p->func = bc_vec_item(&p->prog->fns, p->fidx);
- bc_lex_text(&p->l, text, is_stdin);
+ bc_lex_text(&p->l, text, is_stdin, is_exprs);
BC_SIG_UNLOCK;
}
diff --git a/contrib/bc/src/program.c b/contrib/bc/src/program.c
index 8ec1a011a26d..7c38ef547a82 100644
--- a/contrib/bc/src/program.c
+++ b/contrib/bc/src/program.c
@@ -710,8 +710,8 @@ static void bc_program_read(BcProgram *p) {
// We should *not* have run into EOF.
if (s == BC_STATUS_EOF) bc_err(BC_ERR_EXEC_READ_EXPR);
- // Parse *one* expression.
- bc_parse_text(&vm.read_prs, vm.read_buf.v, false);
+ // Parse *one* expression, so is_stdin should be false.
+ bc_parse_text(&vm.read_prs, vm.read_buf.v, false, false);
BC_SIG_LOCK;
vm.expr(&vm.read_prs, BC_PARSE_NOREAD | BC_PARSE_NEEDVAL);
BC_SIG_UNLOCK;
@@ -2331,7 +2331,7 @@ static void bc_program_execStr(BcProgram *p, const char *restrict code,
BC_SIG_UNLOCK;
// Parse.
- bc_parse_text(&vm.read_prs, str, false);
+ bc_parse_text(&vm.read_prs, str, false, false);
BC_SIG_LOCK;
vm.expr(&vm.read_prs, BC_PARSE_NOCALL);
diff --git a/contrib/bc/src/vm.c b/contrib/bc/src/vm.c
index ef2257644f52..da8f0e1f4416 100644
--- a/contrib/bc/src/vm.c
+++ b/contrib/bc/src/vm.c
@@ -822,11 +822,13 @@ static void bc_vm_clean(void) {
* Process a bunch of text.
* @param text The text to process.
* @param is_stdin True if the text came from stdin, false otherwise.
+ * @param is_exprs True if the text is from command-line expressions, false
+ * otherwise.
*/
-static void bc_vm_process(const char *text, bool is_stdin) {
+static void bc_vm_process(const char *text, bool is_stdin, bool is_exprs) {
// Set up the parser.
- bc_parse_text(&vm.prs, text, is_stdin);
+ bc_parse_text(&vm.prs, text, is_stdin, is_exprs);
do {
@@ -844,7 +846,7 @@ static void bc_vm_process(const char *text, bool is_stdin) {
BC_SIG_UNLOCK;
// Execute if possible.
- if(BC_IS_DC || !BC_PARSE_NO_EXEC(&vm.prs)) bc_program_exec(&vm.prog);
+ if (BC_IS_DC || !BC_PARSE_NO_EXEC(&vm.prs)) bc_program_exec(&vm.prog);
assert(BC_IS_DC || vm.prog.results.len == 0);
@@ -893,7 +895,7 @@ static void bc_vm_file(const char *file) {
BC_SIG_UNLOCK;
// Process it.
- bc_vm_process(data, false);
+ bc_vm_process(data, false, false);
#if BC_ENABLED
// Make sure to end any open if statements.
@@ -957,12 +959,14 @@ static void bc_vm_stdin(void) {
// Set up the lexer.
bc_lex_file(&vm.prs.l, bc_program_stdin_name);
- // These are global so that the dc lexer can access them, but they are tied
- // to this function, really. Well, this and bc_vm_readLine(). These are the
- // reason that we have vm.is_stdin to tell the dc lexer if we are reading
- // from stdin. Well, both lexers care. And the reason they care is so that
- // if a comment or a string goes across multiple lines, the lexer can
- // request more data from stdin until the comment or string is ended.
+ // These are global so that the lexers can access them, but they are
+ // allocated and freed in this function because they should only be used for
+ // stdin and expressions (they are used in bc_vm_exprs() as well). So they
+ // are tied to this function, really. Well, this and bc_vm_readLine(). These
+ // are the reasons that we have vm.is_stdin to tell the lexers if we are
+ // reading from stdin. Well, both lexers care. And the reason they care is
+ // so that if a comment or a string goes across multiple lines, the lexer
+ // can request more data from stdin until the comment or string is ended.
BC_SIG_LOCK;
bc_vec_init(&vm.buffer, sizeof(uchar), BC_DTOR_NONE);
bc_vec_init(&vm.line_buf, sizeof(uchar), BC_DTOR_NONE);
@@ -986,7 +990,7 @@ restart:
if (!clear) continue;
// Process the data.
- bc_vm_process(vm.buffer.v, true);
+ bc_vm_process(vm.buffer.v, true, false);
if (vm.eof) break;
else {
@@ -1002,6 +1006,7 @@ restart:
#endif // BC_ENABLED
err:
+
BC_SIG_MAYLOCK;
// Cleanup.
@@ -1026,7 +1031,8 @@ err:
}
#ifndef NDEBUG
- // Since these are tied to this function, free them here.
+ // Since these are tied to this function, free them here. We only free in
+ // debug mode because stdin is always the last thing read.
bc_vec_free(&vm.line_buf);
bc_vec_free(&vm.buffer);
#endif // NDEBUG
@@ -1034,6 +1040,75 @@ err:
BC_LONGJMP_CONT;
}
+bool bc_vm_readBuf(bool clear) {
+
+ size_t len = vm.exprs.len - 1;
+ bool more;
+
+ BC_SIG_ASSERT_NOT_LOCKED;
+
+ // Clear the buffer if desired.
+ if (clear) bc_vec_empty(&vm.buffer);
+
+ // We want to pop the nul byte off because that's what bc_read_buf()
+ // expects.
+ bc_vec_pop(&vm.buffer);
+
+ // Read one line of expressions.
+ more = bc_read_buf(&vm.buffer, vm.exprs.v, &len);
+ bc_vec_pushByte(&vm.buffer, '\0');
+
+ return more;
+}
+
+static void bc_vm_exprs(void) {
+
+ bool clear = true;
+
+ // Prepare the lexer.
+ bc_lex_file(&vm.prs.l, bc_program_exprs_name);
+
+ // We initialize this so that the lexer can access it in the case that it
+ // needs more data for expressions, such as for a multiline string or
+ // comment. See the comment on the allocation of vm.buffer above in
+ // bc_vm_stdin() for more information.
+ BC_SIG_LOCK;
+ bc_vec_init(&vm.buffer, sizeof(uchar), BC_DTOR_NONE);
+ BC_SETJMP_LOCKED(err);
+ BC_SIG_UNLOCK;
+
+ while (bc_vm_readBuf(clear)) {
+
+ size_t len = vm.buffer.len - 1;
+ const char *str = vm.buffer.v;
+
+ // We don't want to clear the buffer when the line ends with a backslash
+ // because a backslash newline is special in bc.
+ clear = (len < 2 || str[len - 2] != '\\' || str[len - 1] != '\n');
+ if (!clear) continue;
+
+ // Process the data.
+ bc_vm_process(vm.buffer.v, false, true);
+ }
+
+ // If we were not supposed to clear, then we should process everything. This
+ // makes sure that errors get reported.
+ if (!clear) bc_vm_process(vm.buffer.v, false, true);
+
+err:
+
+ BC_SIG_MAYLOCK;
+
+ // Cleanup.
+ bc_vm_clean();
+
+ // Since this is tied to this function, free it here. We always free it here
+ // because bc_vm_stdin() may or may not use it later.
+ bc_vec_free(&vm.buffer);
+
+ BC_LONGJMP_CONT;
+}
+
#if BC_ENABLED
/**
@@ -1044,7 +1119,7 @@ err:
static void bc_vm_load(const char *name, const char *text) {
bc_lex_file(&vm.prs.l, name);
- bc_parse_text(&vm.prs, text, false);
+ bc_parse_text(&vm.prs, text, false, false);
BC_SIG_LOCK;
@@ -1134,7 +1209,6 @@ static void bc_vm_exec(void) {
size_t i;
bool has_file = false;
- BcVec buf;
#if BC_ENABLED
// Load the math libraries.
@@ -1161,43 +1235,8 @@ static void bc_vm_exec(void) {
// If there are expressions to execute...
if (vm.exprs.len) {
- size_t len = vm.exprs.len - 1;
- bool more;
-
- BC_SIG_LOCK;
-
- // Create this as a buffer for reading into.
- bc_vec_init(&buf, sizeof(uchar), BC_DTOR_NONE);
-
-#ifndef NDEBUG
- BC_SETJMP_LOCKED(err);
-#endif // NDEBUG
-
- BC_SIG_UNLOCK;
-
- // Prepare the lexer.
- bc_lex_file(&vm.prs.l, bc_program_exprs_name);
-
- // Process the expressions one at a time.
- do {
-
- more = bc_read_buf(&buf, vm.exprs.v, &len);
- bc_vec_pushByte(&buf, '\0');
- bc_vm_process(buf.v, false);
-
- bc_vec_popAll(&buf);
-
- } while (more);
-
- BC_SIG_LOCK;
-
- bc_vec_free(&buf);
-
-#ifndef NDEBUG
- BC_UNSETJMP;
-#endif // NDEBUG
-
- BC_SIG_UNLOCK;
+ // Process the expressions.
+ bc_vm_exprs();
// Sometimes, executing expressions means we need to quit.
if (!vm.no_exprs && vm.exit_exprs && BC_EXPR_EXIT) return;
@@ -1239,18 +1278,6 @@ static void bc_vm_exec(void) {
// Execute from stdin. bc always does.
if (BC_IS_BC || !has_file) bc_vm_stdin();
-
-// These are all protected by ifndef NDEBUG because if these are needed, bc is
-// going to exit anyway, and I see no reason to include this code in a release
-// build when the OS is going to free all of the resources anyway.
-#ifndef NDEBUG
- return;
-
-err:
- BC_SIG_MAYLOCK;
- bc_vec_free(&buf);
- BC_LONGJMP_CONT;
-#endif // NDEBUG
}
void bc_vm_boot(int argc, char *argv[]) {
diff --git a/contrib/bc/tests/fuzzing/bc_afl.yaml b/contrib/bc/tests/fuzzing/bc_afl.yaml
new file mode 100644
index 000000000000..7d13bff95824
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/bc_afl.yaml
@@ -0,0 +1,125 @@
+session_name: bc_afl
+
+windows:
+ - window_name: control
+ layout: even-horizontal
+ panes:
+ - shell_command:
+ - echo core | doas tee /proc/sys/kernel/core_pattern
+ - echo performance | doas tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
+ - rm -rf tests/fuzzing/bc_outputs1/
+ - rm -rf tests/fuzzing/bc_outputs2/
+ - rm -rf tests/fuzzing/bc_outputs3/
+ - rm -rf tests/fuzzing/dc_outputs/
+ - window_name: bc11
+ layout: even-horizontal
+ panes:
+ - shell_command:
+ - export AFL_AUTORESUME=1
+ - sleep 15
+ - afl-fuzz -i tests/fuzzing/bc_inputs1 -o tests/fuzzing/bc_outputs1 -p exploit -D -M bc11 bin/bc -lq -e "seed = 1280937142.20981723890730892738902938071028973408912703984712093" -f-
+ - window_name: bc12
+ layout: even-horizontal
+ panes:
+ - shell_command:
+ - export AFL_AUTORESUME=1
+ - sleep 16
+ - afl-fuzz -i tests/fuzzing/bc_inputs1 -o tests/fuzzing/bc_outputs1 -p coe -S bc12 bin/bc -lq -e "seed = 1280937142.20981723890730892738902938071028973408912703984712093" -f-
+ - window_name: bc13
+ layout: even-horizontal
+ panes:
+ - shell_command:
+ - export AFL_AUTORESUME=1
+ - sleep 17
+ - afl-fuzz -i tests/fuzzing/bc_inputs1 -o tests/fuzzing/bc_outputs1 -p fast -S bc13 bin/bc -lq -e "seed = 1280937142.20981723890730892738902938071028973408912703984712093" -f-
+ - window_name: bc14
+ layout: even-horizontal
+ panes:
+ - shell_command:
+ - export AFL_AUTORESUME=1
+ - sleep 18
+ - afl-fuzz -i tests/fuzzing/bc_inputs1 -o tests/fuzzing/bc_outputs1 -p explore -S bc14 bin/bc -lq -e "seed = 1280937142.20981723890730892738902938071028973408912703984712093" -f-
+ - window_name: bc21
+ layout: even-horizontal
+ panes:
+ - shell_command:
+ - export AFL_AUTORESUME=1
+ - sleep 19
+ - afl-fuzz -i tests/fuzzing/bc_inputs2 -o tests/fuzzing/bc_outputs2 -p exploit -D -M bc21 bin/bc -lq -e "seed = 1280937142.20981723890730892738902938071028973408912703984712093" -f-
+ - window_name: bc22
+ layout: even-horizontal
+ panes:
+ - shell_command:
+ - export AFL_AUTORESUME=1
+ - sleep 20
+ - afl-fuzz -i tests/fuzzing/bc_inputs2 -o tests/fuzzing/bc_outputs2 -p coe -S bc22 bin/bc -lq -e "seed = 1280937142.20981723890730892738902938071028973408912703984712093" -f-
+ - window_name: bc23
+ layout: even-horizontal
+ panes:
+ - shell_command:
+ - export AFL_AUTORESUME=1
+ - sleep 21
+ - afl-fuzz -i tests/fuzzing/bc_inputs2 -o tests/fuzzing/bc_outputs2 -p fast -S bc23 bin/bc -lq -e "seed = 1280937142.20981723890730892738902938071028973408912703984712093" -f-
+ - window_name: bc24
+ layout: even-horizontal
+ panes:
+ - shell_command:
+ - export AFL_AUTORESUME=1
+ - sleep 22
+ - afl-fuzz -i tests/fuzzing/bc_inputs2 -o tests/fuzzing/bc_outputs2 -p explore -S bc24 bin/bc -lq -e "seed = 1280937142.20981723890730892738902938071028973408912703984712093" -f-
+ - window_name: bc31
+ layout: even-horizontal
+ panes:
+ - shell_command:
+ - export AFL_AUTORESUME=1
+ - sleep 23
+ - afl-fuzz -i tests/fuzzing/bc_inputs3 -o tests/fuzzing/bc_outputs3 -p exploit -D -M bc31 bin/bc -lq -e "seed = 1280937142.20981723890730892738902938071028973408912703984712093" -f-
+ - window_name: bc32
+ layout: even-horizontal
+ panes:
+ - shell_command:
+ - export AFL_AUTORESUME=1
+ - sleep 24
+ - afl-fuzz -i tests/fuzzing/bc_inputs3 -o tests/fuzzing/bc_outputs3 -p coe -S bc32 bin/bc -lq -e "seed = 1280937142.20981723890730892738902938071028973408912703984712093" -f-
+ - window_name: bc33
+ layout: even-horizontal
+ panes:
+ - shell_command:
+ - export AFL_AUTORESUME=1
+ - sleep 25
+ - afl-fuzz -i tests/fuzzing/bc_inputs3 -o tests/fuzzing/bc_outputs3 -p fast -S bc33 bin/bc -lq -e "seed = 1280937142.20981723890730892738902938071028973408912703984712093" -f-
+ - window_name: bc34
+ layout: even-horizontal
+ panes:
+ - shell_command:
+ - export AFL_AUTORESUME=1
+ - sleep 26
+ - afl-fuzz -i tests/fuzzing/bc_inputs3 -o tests/fuzzing/bc_outputs3 -p explore -S bc34 bin/bc -lq -e "seed = 1280937142.20981723890730892738902938071028973408912703984712093" -f-
+ - window_name: dc11
+ layout: even-horizontal
+ panes:
+ - shell_command:
+ - export AFL_AUTORESUME=1
+ - sleep 27
+ - afl-fuzz -i tests/fuzzing/dc_inputs -o tests/fuzzing/dc_outputs -p exploit -D -M dc11 bin/dc -x -e "1280937142.20981723890730892738902938071028973408912703984712093j" -f-
+ - window_name: dc12
+ layout: even-horizontal
+ panes:
+ - shell_command:
+ - export AFL_AUTORESUME=1
+ - sleep 28
+ - afl-fuzz -i tests/fuzzing/dc_inputs -o tests/fuzzing/dc_outputs -p coe -S dc12 bin/dc -x -e "1280937142.20981723890730892738902938071028973408912703984712093j" -f-
+ - window_name: dc13
+ layout: even-horizontal
+ panes:
+ - shell_command:
+ - export AFL_AUTORESUME=1
+ - sleep 29
+ - afl-fuzz -i tests/fuzzing/dc_inputs -o tests/fuzzing/dc_outputs -p fast -S dc13 bin/dc -x -e "1280937142.20981723890730892738902938071028973408912703984712093j" -f-
+ - window_name: dc14
+ layout: even-horizontal
+ panes:
+ - shell_command:
+ - export AFL_AUTORESUME=1
+ - sleep 30
+ - afl-fuzz -i tests/fuzzing/dc_inputs -o tests/fuzzing/dc_outputs -p explore -S dc14 bin/dc -x -e "1280937142.20981723890730892738902938071028973408912703984712093j" -f-
diff --git a/contrib/bc/tests/fuzzing/bc_afl_continue.yaml b/contrib/bc/tests/fuzzing/bc_afl_continue.yaml
new file mode 100644
index 000000000000..486984bdaef5
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/bc_afl_continue.yaml
@@ -0,0 +1,122 @@
+session_name: bc_afl_continue
+start_directory: ./
+
+windows:
+ - window_name: control
+ layout: even-horizontal
+ panes:
+ - shell_command:
+ - echo core | doas tee /proc/sys/kernel/core_pattern
+ - echo performance | doas tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
+ - window_name: bc11
+ layout: even-horizontal
+ panes:
+ - shell_command:
+ - export AFL_AUTORESUME=1
+ - sleep 4
+ - afl-fuzz -i- -o tests/fuzzing/bc_outputs1 -p exploit -D -M bc11 bin/bc -lq -e "seed = 1280937142.20981723890730892738902938071028973408912703984712093" -f-
+ - window_name: bc12
+ layout: even-horizontal
+ panes:
+ - shell_command:
+ - export AFL_AUTORESUME=1
+ - sleep 5
+ - afl-fuzz -i- -o tests/fuzzing/bc_outputs1 -p coe -S bc12 bin/bc -lq -e "seed = 1280937142.20981723890730892738902938071028973408912703984712093" -f-
+ - window_name: bc13
+ layout: even-horizontal
+ panes:
+ - shell_command:
+ - export AFL_AUTORESUME=1
+ - sleep 6
+ - afl-fuzz -i- -o tests/fuzzing/bc_outputs1 -p fast -S bc13 bin/bc -lq -e "seed = 1280937142.20981723890730892738902938071028973408912703984712093" -f-
+ - window_name: bc14
+ layout: even-horizontal
+ panes:
+ - shell_command:
+ - export AFL_AUTORESUME=1
+ - sleep 7
+ - afl-fuzz -i- -o tests/fuzzing/bc_outputs1 -p explore -S bc14 bin/bc -lq -e "seed = 1280937142.20981723890730892738902938071028973408912703984712093" -f-
+ - window_name: bc21
+ layout: even-horizontal
+ panes:
+ - shell_command:
+ - export AFL_AUTORESUME=1
+ - sleep 8
+ - afl-fuzz -i- -o tests/fuzzing/bc_outputs2 -p exploit -D -M bc21 bin/bc -lq -e "seed = 1280937142.20981723890730892738902938071028973408912703984712093" -f-
+ - window_name: bc22
+ layout: even-horizontal
+ panes:
+ - shell_command:
+ - export AFL_AUTORESUME=1
+ - sleep 9
+ - afl-fuzz -i- -o tests/fuzzing/bc_outputs2 -p coe -S bc22 bin/bc -lq -e "seed = 1280937142.20981723890730892738902938071028973408912703984712093" -f-
+ - window_name: bc23
+ layout: even-horizontal
+ panes:
+ - shell_command:
+ - export AFL_AUTORESUME=1
+ - sleep 10
+ - afl-fuzz -i- -o tests/fuzzing/bc_outputs2 -p fast -S bc23 bin/bc -lq -e "seed = 1280937142.20981723890730892738902938071028973408912703984712093" -f-
+ - window_name: bc24
+ layout: even-horizontal
+ panes:
+ - shell_command:
+ - export AFL_AUTORESUME=1
+ - sleep 11
+ - afl-fuzz -i- -o tests/fuzzing/bc_outputs2 -p explore -S bc24 bin/bc -lq -e "seed = 1280937142.20981723890730892738902938071028973408912703984712093" -f-
+ - window_name: bc31
+ layout: even-horizontal
+ panes:
+ - shell_command:
+ - export AFL_AUTORESUME=1
+ - sleep 12
+ - afl-fuzz -i- -o tests/fuzzing/bc_outputs3 -p exploit -D -M bc31 bin/bc -lq -e "seed = 1280937142.20981723890730892738902938071028973408912703984712093" -f-
+ - window_name: bc32
+ layout: even-horizontal
+ panes:
+ - shell_command:
+ - export AFL_AUTORESUME=1
+ - sleep 13
+ - afl-fuzz -i- -o tests/fuzzing/bc_outputs3 -p coe -S bc32 bin/bc -lq -e "seed = 1280937142.20981723890730892738902938071028973408912703984712093" -f-
+ - window_name: bc33
+ layout: even-horizontal
+ panes:
+ - shell_command:
+ - export AFL_AUTORESUME=1
+ - sleep 14
+ - afl-fuzz -i- -o tests/fuzzing/bc_outputs3 -p fast -S bc33 bin/bc -lq -e "seed = 1280937142.20981723890730892738902938071028973408912703984712093" -f-
+ - window_name: bc34
+ layout: even-horizontal
+ panes:
+ - shell_command:
+ - export AFL_AUTORESUME=1
+ - sleep 15
+ - afl-fuzz -i- -o tests/fuzzing/bc_outputs3 -p explore -S bc34 bin/bc -lq -e "seed = 1280937142.20981723890730892738902938071028973408912703984712093" -f-
+ - window_name: dc11
+ layout: even-horizontal
+ panes:
+ - shell_command:
+ - export AFL_AUTORESUME=1
+ - sleep 16
+ - afl-fuzz -i- -o tests/fuzzing/dc_outputs -p exploit -D -M dc11 bin/dc -x -e "1280937142.20981723890730892738902938071028973408912703984712093j" -f-
+ - window_name: dc12
+ layout: even-horizontal
+ panes:
+ - shell_command:
+ - export AFL_AUTORESUME=1
+ - sleep 17
+ - afl-fuzz -i- -o tests/fuzzing/dc_outputs -p coe -S dc12 bin/dc -x -e "1280937142.20981723890730892738902938071028973408912703984712093j" -f-
+ - window_name: dc13
+ layout: even-horizontal
+ panes:
+ - shell_command:
+ - export AFL_AUTORESUME=1
+ - sleep 18
+ - afl-fuzz -i- -o tests/fuzzing/dc_outputs -p fast -S dc13 bin/dc -x -e "1280937142.20981723890730892738902938071028973408912703984712093j" -f-
+ - window_name: dc14
+ layout: even-horizontal
+ panes:
+ - shell_command:
+ - export AFL_AUTORESUME=1
+ - sleep 19
+ - afl-fuzz -i- -o tests/fuzzing/dc_outputs -p explore -S dc14 bin/dc -x -e "1280937142.20981723890730892738902938071028973408912703984712093j" -f-
diff --git a/contrib/bc/tests/fuzzing/bc_inputs1/array.bc b/contrib/bc/tests/fuzzing/bc_inputs1/array.bc
new file mode 100644
index 000000000000..dac232804914
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/bc_inputs1/array.bc
@@ -0,0 +1,60 @@
+#! /usr/bin/bc -q
+
+define z(a[]) {
+ for (i = 0; i < l; ++i) {
+ a[i]
+ }
+}
+
+define x(a[]) {
+
+ # Test for separate vars and arrays.
+ auto a
+
+ for (a = 0; a < l; ++a) {
+ a[a] = -a
+ }
+
+ z(a[])
+}
+
+define g(x[], y[]) {
+ return x[0] - y[0]
+}
+
+define h(y[], x[]) {
+ return g(x[], y[])
+}
+
+define m(*x[], *y[]) {
+ return x[0] / y[0]
+}
+
+define n(*y[], *x[]) {
+ return m(x[], y[])
+}
+
+for (i = 0; i < 101; ++i) {
+ a[i] = i
+}
+
+a[104] = 204
+
+l = length(a[])
+
+for (i = 0; i <= l; ++i) {
+ a[i]
+}
+
+z(a[])
+x(a[])
+z(a[])
+l
+
+x[0] = 5
+y[0] = 4
+
+h(x[], y[])
+n(x[], y[])
+
+halt
diff --git a/contrib/bc/tests/fuzzing/bc_inputs1/decimal.txt b/contrib/bc/tests/fuzzing/bc_inputs1/decimal.txt
new file mode 100644
index 000000000000..b79da99e3dd2
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/bc_inputs1/decimal.txt
@@ -0,0 +1,30 @@
+0
+0.0
+000000000000000000000000.00000000000000000000000
+000000000000000000000000000135482346782356
+000000000000000000000000002
+1
+1023468723275435238491972521917846
+4343472432431705867392073517038270398027352709027389273920739037937960379637893607893607893670530278200795207952702873892786172916728961783907893607418973587857386079679267926737520730925372983782793652793
+-1
+-18586
+-31378682943772818461924738352952347258
+-823945628745673589495067238723986520375698237620834674509627345273096287563846592384526349872634895763257893467523987578690283762897568459072348758071071087813501875908127359018715023841710239872301387278
+.123521346523546
+0.1245923756273856
+-.1024678456387
+-0.8735863475634587
+4.0
+-6.0
+234237468293576.000000000000000000000000000000
+23987623568943567.00000000000000000005677834650000000000000
+23856934568940675.000000000000000435676782300000000000000456784
+77567648698496.000000000000000000587674750000000000458563800000000000000
+2348672354968723.2374823546000000000003256987394502346892435623870000000034578
+-2354768.000000000000000000000000000000000000
+-96739874567.000000000347683456
+-3764568345.000000000004573845000000347683460
+-356784356.934568495770004586495678300000000
+74325437345273852773827101738273127312738521733017537073520735207307570358738257390761276072160719802671980267018728630178.7082681027680521760217867841276127681270867827821768173178207830710978017738178678012767377058785378278207385237085237803278203782037237582795870
+-756752732785273851273728537852738257837283678965738527385272983678372867327835672967385278372637862738627836279863782673862783670.71738178361738718367186378610738617836781603760178367018603760178107735278372832783728367826738627836278378260736270367362073867097307925
+9812734012837410982345719208345712908357412903587192048571920458712.23957182459817249058172945781
diff --git a/contrib/bc/tests/fuzzing/bc_inputs1/functions.bc b/contrib/bc/tests/fuzzing/bc_inputs1/functions.bc
new file mode 100644
index 000000000000..80d6d1623d8d
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/bc_inputs1/functions.bc
@@ -0,0 +1,7 @@
+e(0.5)
+
+define e(x) {
+ return x
+}
+
+e(0.5)
diff --git a/contrib/bc/tests/fuzzing/bc_inputs1/len.bc b/contrib/bc/tests/fuzzing/bc_inputs1/len.bc
new file mode 100644
index 000000000000..ec931f2386a5
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/bc_inputs1/len.bc
@@ -0,0 +1,48 @@
+define fast_gcd(a, b) {
+
+ if (a == b) return a;
+ if (a > b) return fast_gcd(a - b, b)
+
+ return fast_gcd(a, b - a);
+}
+
+define void r_reduce(*r[]) {
+
+ auto g,s;
+
+ if (length(r[]) != 2) sqrt(-1);
+ if (scale(r[0])) 2^r[0];
+ if (scale(r[1])) 2^r[1];
+
+ if (r[0] >= 0 && r[1] >= 0) g = fast_gcd(r[0], r[1]);
+ else g = gcd(r[0], r[1]);
+
+ s = scale;
+ scale = 0;
+
+ r[0] /= g;
+ r[1] /= g;
+
+ scale = s;
+}
+
+define void r_init(*r[], a, b) {
+ r[0] = a;
+ r[1] = b;
+ r_reduce(r[]);
+}
+
+define void r_initi(*r[], i, a, b) {
+
+ length(r[]);
+
+ r[0] = i * b + a;
+ r[1] = b;
+
+ length(r[]);
+
+ r_reduce(r[]);
+}
+
+length(a[])
+r_initi(a[], 5, 63, 94);
diff --git a/contrib/bc/tests/fuzzing/bc_inputs1/lib10.txt b/contrib/bc/tests/fuzzing/bc_inputs1/lib10.txt
new file mode 100644
index 000000000000..7aa3fda19cc7
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/bc_inputs1/lib10.txt
@@ -0,0 +1,4 @@
+l10(0)
+l10(99)
+l10(100)
+l10(-100)
diff --git a/contrib/bc/tests/fuzzing/bc_inputs1/lib12.txt b/contrib/bc/tests/fuzzing/bc_inputs1/lib12.txt
new file mode 100644
index 000000000000..7d70e1ccdd5e
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/bc_inputs1/lib12.txt
@@ -0,0 +1 @@
+uint(0)
diff --git a/contrib/bc/tests/fuzzing/bc_inputs1/lib2.txt b/contrib/bc/tests/fuzzing/bc_inputs1/lib2.txt
new file mode 100644
index 000000000000..f345bd1669cb
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/bc_inputs1/lib2.txt
@@ -0,0 +1,15 @@
+r(0, 0)
+r(0, 1)
+r(0, 100)
+r(1, 0)
+r(1, 3)
+r(1.4, 0)
+r(1.5, 0)
+r(34.45, 2)
+r(64.1223, 4)
+r(-1, 0)
+r(-1, 3)
+r(-1.4, 0)
+r(-1.5, 0)
+r(-34.45, 2)
+r(-64.1223, 4)
diff --git a/contrib/bc/tests/fuzzing/bc_inputs1/lib3.txt b/contrib/bc/tests/fuzzing/bc_inputs1/lib3.txt
new file mode 100644
index 000000000000..1da42385ea44
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/bc_inputs1/lib3.txt
@@ -0,0 +1,6 @@
+f(0)
+f(1)
+f(2)
+f(3)
+f(4)
+f(5)
diff --git a/contrib/bc/tests/fuzzing/bc_inputs1/lib6.txt b/contrib/bc/tests/fuzzing/bc_inputs1/lib6.txt
new file mode 100644
index 000000000000..260e159f9fb6
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/bc_inputs1/lib6.txt
@@ -0,0 +1,5 @@
+pi(5)
+p=pi(scale)
+r2d(-p)
+d2r(180)
+d2r(-180)
diff --git a/contrib/bc/tests/fuzzing/bc_inputs2/bitfuncs.txt b/contrib/bc/tests/fuzzing/bc_inputs2/bitfuncs.txt
new file mode 100644
index 000000000000..e0703a715c08
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/bc_inputs2/bitfuncs.txt
@@ -0,0 +1,42 @@
+band(13946233938940740889, 12028823668264674112)
+bor(13946233938940740889, 12028823668264674112)
+bxor(13946233938940740889, 12028823668264674112)
+bshl(2366588185, 0)
+bshr(2366588185, 0)
+bshl(347743040, 25)
+bshr(347743040, 25)
+bnot8(13946233938940740889)
+bnot8(25)
+bnot16(13946233938940740889)
+bnot16(17689)
+bnot32(13946233938940740889)
+bnot32(2366588185)
+bnot64(13946233938940740889)
+brev8(13946233938940740889)
+brev8(25)
+brev16(13946233938940740889)
+brev16(17689)
+brev32(13946233938940740889)
+brev32(2366588185)
+brev64(13946233938940740889)
+brol8(13946233938940740889, 12028823668264674112)
+brol8(25, 64)
+brol16(13946233938940740889, 12028823668264674112)
+brol16(17689, 9024)
+brol32(13946233938940740889, 12028823668264674112)
+brol32(2366588185, 347743040)
+brol64(13946233938940740889, 12028823668264674112)
+bror8(13946233938940740889, 12028823668264674112)
+bror8(25, 64)
+bror16(13946233938940740889, 12028823668264674112)
+bror16(17689, 9024)
+bror32(13946233938940740889, 12028823668264674112)
+bror32(2366588185, 347743040)
+bror64(13946233938940740889, 12028823668264674112)
+bmod8(13946233938940740889)
+bmod8(25)
+bmod16(13946233938940740889)
+bmod16(17689)
+bmod32(13946233938940740889)
+bmod32(2366588185)
+bmod64(13946233938940740889)
diff --git a/contrib/bc/tests/fuzzing/bc_inputs2/lib15.txt b/contrib/bc/tests/fuzzing/bc_inputs2/lib15.txt
new file mode 100644
index 000000000000..13be33145ba3
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/bc_inputs2/lib15.txt
@@ -0,0 +1 @@
+uint(1)
diff --git a/contrib/bc/tests/fuzzing/bc_inputs2/lib21.txt b/contrib/bc/tests/fuzzing/bc_inputs2/lib21.txt
new file mode 100644
index 000000000000..82693695945d
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/bc_inputs2/lib21.txt
@@ -0,0 +1 @@
+int(1)
diff --git a/contrib/bc/tests/fuzzing/bc_inputs2/misc3.txt b/contrib/bc/tests/fuzzing/bc_inputs2/misc3.txt
new file mode 100644
index 000000000000..7aad374c4ef6
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/bc_inputs2/misc3.txt
@@ -0,0 +1,12 @@
+for (i = 0; i < A; ++i)
+{print "n"
+if(1)if(1){3
+}
+if(0)if(1){3
+}
+else 4
+if(0){if(1){3
+}}
+else 5
+{i}
+}
diff --git a/contrib/bc/tests/fuzzing/bc_inputs2/modulus.txt b/contrib/bc/tests/fuzzing/bc_inputs2/modulus.txt
new file mode 100644
index 000000000000..049cd7dbd73c
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/bc_inputs2/modulus.txt
@@ -0,0 +1,27 @@
+1 % 1
+2 % 1
+16 % 4
+17 % 4
+3496723859067234 % 298375462837546928347623059375486
+-1 % 1
+-2 % 1
+-1274852934765 % 2387628935486273546
+1 % -1
+2 % -1
+2 % -3
+16 % 5
+89237423 % -237856923854
+-1 % -1
+-2 % -1
+-2 % -2
+-2 % -3
+-13 % -7
+-14 % -7
+-15 % -7
+-127849612 % -23712347682193
+scale = 0
+1 % 1
+2 % 1
+scale = 0; -899510228 % -2448300078.40314
+scale = 0; -7424863 % -207.2609738667
+scale = 0; 3769798918 % 0.6
diff --git a/contrib/bc/tests/fuzzing/bc_inputs2/references.bc b/contrib/bc/tests/fuzzing/bc_inputs2/references.bc
new file mode 100644
index 000000000000..8188f17aa017
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/bc_inputs2/references.bc
@@ -0,0 +1,408 @@
+#! /usr/bin/bc -q
+
+define printarray(a[], len) {
+
+ auto i
+
+ for (i = 0; i < len; ++i) {
+ a[i]
+ }
+}
+
+define a2(a[], len) {
+
+ auto i
+
+ for (i = 0; i < len; ++i) {
+ a[i] = a[i] * a[i]
+ }
+
+ printarray(a[], len)
+}
+
+define a4(a__[], len) {
+
+ auto i
+
+ for (i = 0; i < len; ++i) {
+ a__[i] = a__[i] * a__[i]
+ }
+
+ printarray(a__[], len)
+}
+
+define a6(*a__[], len) {
+
+ auto i
+
+ for (i = 0; i < len; ++i) {
+ a__[i] = a__[i] * a__[i]
+ }
+
+ printarray(a__[], len)
+}
+
+define a1(*a[], len) {
+
+ auto i
+
+ for (i = 0; i < len; ++i) {
+ a[i] = i
+ }
+
+ a2(a[], len)
+
+ printarray(a[], len)
+}
+
+define a3(*a__[], len) {
+
+ auto i
+
+ for (i = 0; i < len; ++i) {
+ a__[i] = i
+ }
+
+ a4(a__[], len)
+
+ printarray(a__[], len)
+}
+
+define a5(*a__[], len) {
+
+ auto i
+
+ for (i = 0; i < len; ++i) {
+ a__[i] = i
+ }
+
+ a2(a__[], len)
+
+ printarray(a__[], len)
+}
+
+define a7(*a__[], len) {
+
+ auto i
+
+ for (i = 0; i < len; ++i) {
+ a__[i] = i
+ }
+
+ a6(a__[], len)
+
+ printarray(a__[], len)
+}
+
+len = 16
+
+a1(a[], len)
+printarray(a[], len)
+a3(a[], len)
+printarray(a[], len)
+a5(a[], len)
+printarray(a[], len)
+a7(a[], len)
+printarray(a[], len)
+
+a1(b[], len)
+printarray(b[], len)
+a3(b[], len)
+printarray(b[], len)
+a5(b[], len)
+printarray(b[], len)
+a7(b[], len)
+printarray(b[], len)
+
+a1[0] = 0
+a2[0] = 0
+a3[0] = 0
+a4[0] = 0
+a5[0] = 0
+a6[0] = 0
+a7[0] = 0
+a8[0] = 0
+a9[0] = 0
+a10[0] = 0
+a11[0] = 0
+a12[0] = 0
+a13[0] = 0
+a14[0] = 0
+a15[0] = 0
+a16[0] = 0
+a17[0] = 0
+a18[0] = 0
+a19[0] = 0
+a20[0] = 0
+a21[0] = 0
+a22[0] = 0
+a23[0] = 0
+a24[0] = 0
+a25[0] = 0
+a26[0] = 0
+a27[0] = 0
+a28[0] = 0
+a29[0] = 0
+a30[0] = 0
+a31[0] = 0
+a32[0] = 0
+a33[0] = 0
+a34[0] = 0
+a35[0] = 0
+a36[0] = 0
+a37[0] = 0
+a38[0] = 0
+a39[0] = 0
+a40[0] = 0
+a41[0] = 0
+a42[0] = 0
+a43[0] = 0
+a44[0] = 0
+a45[0] = 0
+a46[0] = 0
+a47[0] = 0
+a48[0] = 0
+a49[0] = 0
+a50[0] = 0
+a51[0] = 0
+a52[0] = 0
+a53[0] = 0
+a54[0] = 0
+a55[0] = 0
+a56[0] = 0
+a57[0] = 0
+a58[0] = 0
+a59[0] = 0
+a60[0] = 0
+a61[0] = 0
+a62[0] = 0
+a63[0] = 0
+a64[0] = 0
+a65[0] = 0
+a66[0] = 0
+a67[0] = 0
+a68[0] = 0
+a69[0] = 0
+a70[0] = 0
+a71[0] = 0
+a72[0] = 0
+a73[0] = 0
+a74[0] = 0
+a75[0] = 0
+a76[0] = 0
+a77[0] = 0
+a78[0] = 0
+a79[0] = 0
+a80[0] = 0
+a81[0] = 0
+a82[0] = 0
+a83[0] = 0
+a84[0] = 0
+a85[0] = 0
+a86[0] = 0
+a87[0] = 0
+a88[0] = 0
+a89[0] = 0
+a90[0] = 0
+a91[0] = 0
+a92[0] = 0
+a93[0] = 0
+a94[0] = 0
+a95[0] = 0
+a96[0] = 0
+a97[0] = 0
+a98[0] = 0
+a99[0] = 0
+a100[0] = 0
+a101[0] = 0
+a102[0] = 0
+a103[0] = 0
+a104[0] = 0
+a105[0] = 0
+a106[0] = 0
+a107[0] = 0
+a108[0] = 0
+a109[0] = 0
+a110[0] = 0
+a111[0] = 0
+a112[0] = 0
+a113[0] = 0
+a114[0] = 0
+a115[0] = 0
+a116[0] = 0
+a117[0] = 0
+a118[0] = 0
+a119[0] = 0
+a120[0] = 0
+a121[0] = 0
+a122[0] = 0
+a123[0] = 0
+a124[0] = 0
+a125[0] = 0
+a126[0] = 0
+a127[0] = 0
+a128[0] = 0
+a129[0] = 0
+a130[0] = 0
+a131[0] = 0
+a132[0] = 0
+a133[0] = 0
+a134[0] = 0
+a135[0] = 0
+a136[0] = 0
+a137[0] = 0
+a138[0] = 0
+a139[0] = 0
+a140[0] = 0
+a141[0] = 0
+a142[0] = 0
+a143[0] = 0
+a144[0] = 0
+a145[0] = 0
+a146[0] = 0
+a147[0] = 0
+a148[0] = 0
+a149[0] = 0
+a150[0] = 0
+a151[0] = 0
+a152[0] = 0
+a153[0] = 0
+a154[0] = 0
+a155[0] = 0
+a156[0] = 0
+a157[0] = 0
+a158[0] = 0
+a159[0] = 0
+a160[0] = 0
+a161[0] = 0
+a162[0] = 0
+a163[0] = 0
+a164[0] = 0
+a165[0] = 0
+a166[0] = 0
+a167[0] = 0
+a168[0] = 0
+a169[0] = 0
+a170[0] = 0
+a171[0] = 0
+a172[0] = 0
+a173[0] = 0
+a174[0] = 0
+a175[0] = 0
+a176[0] = 0
+a177[0] = 0
+a178[0] = 0
+a179[0] = 0
+a180[0] = 0
+a181[0] = 0
+a182[0] = 0
+a183[0] = 0
+a184[0] = 0
+a185[0] = 0
+a186[0] = 0
+a187[0] = 0
+a188[0] = 0
+a189[0] = 0
+a190[0] = 0
+a191[0] = 0
+a192[0] = 0
+a193[0] = 0
+a194[0] = 0
+a195[0] = 0
+a196[0] = 0
+a197[0] = 0
+a198[0] = 0
+a199[0] = 0
+a200[0] = 0
+a201[0] = 0
+a202[0] = 0
+a203[0] = 0
+a204[0] = 0
+a205[0] = 0
+a206[0] = 0
+a207[0] = 0
+a208[0] = 0
+a209[0] = 0
+a210[0] = 0
+a211[0] = 0
+a212[0] = 0
+a213[0] = 0
+a214[0] = 0
+a215[0] = 0
+a216[0] = 0
+a217[0] = 0
+a218[0] = 0
+a219[0] = 0
+a220[0] = 0
+a221[0] = 0
+a222[0] = 0
+a223[0] = 0
+a224[0] = 0
+a225[0] = 0
+a226[0] = 0
+a227[0] = 0
+a228[0] = 0
+a229[0] = 0
+a230[0] = 0
+a231[0] = 0
+a232[0] = 0
+a233[0] = 0
+a234[0] = 0
+a235[0] = 0
+a236[0] = 0
+a237[0] = 0
+a238[0] = 0
+a239[0] = 0
+a240[0] = 0
+a241[0] = 0
+a242[0] = 0
+a243[0] = 0
+a244[0] = 0
+a245[0] = 0
+a246[0] = 0
+a247[0] = 0
+a248[0] = 0
+a249[0] = 0
+a250[0] = 0
+a251[0] = 0
+a252[0] = 0
+a253[0] = 0
+a254[0] = 0
+a255[0] = 0
+a256[0] = 0
+
+a1(a253[], len)
+printarray(a253[], len)
+a3(a253[], len)
+printarray(a253[], len)
+a5(a253[], len)
+printarray(a253[], len)
+a7(a253[], len)
+printarray(a253[], len)
+
+a1(a254[], len)
+printarray(a254[], len)
+a3(a254[], len)
+printarray(a254[], len)
+a5(a254[], len)
+printarray(a254[], len)
+a7(a254[], len)
+printarray(a254[], len)
+
+a1(a255[], len)
+printarray(a255[], len)
+a3(a255[], len)
+printarray(a255[], len)
+a5(a255[], len)
+printarray(a255[], len)
+a7(a255[], len)
+printarray(a255[], len)
+
+a1(a256[], len)
+printarray(a256[], len)
+a3(a256[], len)
+printarray(a256[], len)
+a5(a256[], len)
+printarray(a256[], len)
+a7(a256[], len)
+printarray(a256[], len)
diff --git a/contrib/bc/tests/fuzzing/bc_inputs3/02.txt b/contrib/bc/tests/fuzzing/bc_inputs3/02.txt
new file mode 100644
index 000000000000..8cf0f3e6fec1
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/bc_inputs3/02.txt
@@ -0,0 +1 @@
+obase^= 20-f-b-4^-f-4-4^-f-4^-d
diff --git a/contrib/bc/tests/fuzzing/bc_inputs3/03.txt b/contrib/bc/tests/fuzzing/bc_inputs3/03.txt
new file mode 100644
index 000000000000..00e645cea896
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/bc_inputs3/03.txt
@@ -0,0 +1,2 @@
+for (i = 0; ; )
+for (i = 0; ;(p(s(ssqrtt()-p())))000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000#000
diff --git a/contrib/bc/tests/fuzzing/bc_inputs3/06.txt b/contrib/bc/tests/fuzzing/bc_inputs3/06.txt
new file mode 100644
index 000000000000..29fe6be37021
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/bc_inputs3/06.txt
@@ -0,0 +1 @@
+while (i == 0) {
diff --git a/contrib/bc/tests/fuzzing/bc_inputs3/07.txt b/contrib/bc/tests/fuzzing/bc_inputs3/07.txt
new file mode 100644
index 000000000000..e899d8547868
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/bc_inputs3/07.txt
@@ -0,0 +1,8 @@
+for(q=F;i<=020; ++i) #00
+{print "0"
+if(6)if(6){3
+ }
+{pr0n}
+"" }
+{pr0n}
+{print "" ""
diff --git a/contrib/bc/tests/fuzzing/bc_inputs3/10.txt b/contrib/bc/tests/fuzzing/bc_inputs3/10.txt
new file mode 100644
index 000000000000..23fb8689f598
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/bc_inputs3/10.txt
@@ -0,0 +1 @@
+d000$++
diff --git a/contrib/bc/tests/fuzzing/bc_inputs3/12.txt b/contrib/bc/tests/fuzzing/bc_inputs3/12.txt
new file mode 100644
index 000000000000..143bb71deeda
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/bc_inputs3/12.txt
@@ -0,0 +1,2 @@
+for (v ;!j -90-90; ++i)
+a= ibase ++;0
diff --git a/contrib/bc/tests/fuzzing/bc_inputs3/16.txt b/contrib/bc/tests/fuzzing/bc_inputs3/16.txt
new file mode 100644
index 000000000000..977569bda330
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/bc_inputs3/16.txt
@@ -0,0 +1 @@
+"0 \ No newline at end of file
diff --git a/contrib/bc/tests/fuzzing/bc_inputs3/trunc.txt b/contrib/bc/tests/fuzzing/bc_inputs3/trunc.txt
new file mode 100644
index 000000000000..364bb224a2e3
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/bc_inputs3/trunc.txt
@@ -0,0 +1,15 @@
+0$
+1$
+2$
+0.8249167203486$
+1.28937150237$
+2.0$
+28937.92837605126$
+2890.000000000$
+-1$
+-1.128973$
+-9812387.28910273$
+x = 83.298
+x$
+x = -1893.19
+(x)$
diff --git a/contrib/bc/tests/fuzzing/dc_inputs/01.txt b/contrib/bc/tests/fuzzing/dc_inputs/01.txt
new file mode 100644
index 000000000000..9622de95a241
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/dc_inputs/01.txt
@@ -0,0 +1,2 @@
+[[000000000
+00000]
diff --git a/contrib/bc/tests/fuzzing/dc_inputs/02.txt b/contrib/bc/tests/fuzzing/dc_inputs/02.txt
new file mode 100644
index 000000000000..79565935cf23
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/dc_inputs/02.txt
@@ -0,0 +1,5 @@
+0 R
+2 1
+1 0+pRpp
+30.x
+[00000000]ip1+pR
diff --git a/contrib/bc/tests/fuzzing/dc_inputs/03.txt b/contrib/bc/tests/fuzzing/dc_inputs/03.txt
new file mode 100644
index 000000000000..ecede2e05629
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/dc_inputs/03.txt
@@ -0,0 +1,2 @@
+0 lip1-si0l0+200sx_9lq+pR 30.x
+[li100L0dp1+s+sX10lM<0]sL0sJlLx
diff --git a/contrib/bc/tests/fuzzing/dc_inputs/04.txt b/contrib/bc/tests/fuzzing/dc_inputs/04.txt
new file mode 100644
index 000000000000..209f50c16d52
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/dc_inputs/04.txt
@@ -0,0 +1,9 @@
+zp100000000.000004p1+pR
+0 1 1+kpR
+1 1+pR
+1 0IpR
+2 9+iR
+037 483+pR
+999 999+pR
+237467456283846vpR
+.0000000ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddsdddddddddddddddddddddddddddddddddddddddddddddddddddddsdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd/ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddfddddddddddddddddddddddddddddddddddddddddddddddddddddddcdddddddddddd9000000000000000000
diff --git a/contrib/bc/tests/fuzzing/dc_inputs/05.txt b/contrib/bc/tests/fuzzing/dc_inputs/05.txt
new file mode 100644
index 000000000000..bf2ca982ed2b
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/dc_inputs/05.txt
@@ -0,0 +1,3 @@
+04000000000000300sx_9000.00000syzpRlxlq+pR
+30.x
+[li1000000sxL0LLLL900000.00000sLLL]sL0s0lLx
diff --git a/contrib/bc/tests/fuzzing/dc_inputs/06.txt b/contrib/bc/tests/fuzzing/dc_inputs/06.txt
new file mode 100644
index 000000000000..eff417eb55b4
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/dc_inputs/06.txt
@@ -0,0 +1 @@
+00Q;pd60 p d9S06+00I;pd60Q2 0^pR
diff --git a/contrib/bc/tests/fuzzing/dc_inputs/07.txt b/contrib/bc/tests/fuzzing/dc_inputs/07.txt
new file mode 100644
index 000000000000..8a09152faf58
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/dc_inputs/07.txt
@@ -0,0 +1,3 @@
+1 0 1|dR
+1 [li0L]SL10sildR
+1 [li0L]sL10|Lx
diff --git a/contrib/bc/tests/fuzzing/dc_inputs/08.txt b/contrib/bc/tests/fuzzing/dc_inputs/08.txt
new file mode 100644
index 000000000000..156de2f536b6
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/dc_inputs/08.txt
@@ -0,0 +1 @@
+0 2+p[lip1-si0li!=0^di>0]S098sil0x
diff --git a/contrib/bc/tests/fuzzing/dc_inputs/09.txt b/contrib/bc/tests/fuzzing/dc_inputs/09.txt
new file mode 100644
index 000000000000..ffc3a08908d4
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/dc_inputs/09.txt
@@ -0,0 +1,9 @@
+#00000
+0sm[Nx]0s0[]0s0x[]zs0x[]0s0[]zs0c
+0s0[Nx]0s0[]zs0x[]zs0x[Nx]0s0[]zs0#000000000
+0s0[Nx]0s_[]zs0x[li]zs^x[l0000000]0sm[]zs0x[liNx]zs0x[li;0lilix]
+x[liN]zsWx[liN]zs0x[li;0lilix]
+x[liNzs0x#000000000
+*sm[Nx]0sm[]zs0x[li]zs0x[Nx]0sm[]zsdc
+0sm[Nx]0sm[]zs0x[li]zs0x[Nx]0sm[]x]zsxx#000000000
+*s0[Nx]0sm[]0s00[00]zs0x[Nx]0sm[]z0dc
diff --git a/contrib/bc/tests/fuzzing/dc_inputs/10.txt b/contrib/bc/tests/fuzzing/dc_inputs/10.txt
new file mode 100644
index 000000000000..0fade4bb899f
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/dc_inputs/10.txt
@@ -0,0 +1,11 @@
+#0000
+0sm[Nx]0sm[]0s0x[li]0s0x[Nfvfff[]0sm[]zs0x[li]zs0x[Nx]0sm[]zs0c
+0sm[Nx]0sm[]x[li]zs0x[Nx]0sm[]zs0c
+0sm[Nx]0sm[]zs0x[li]zs0x[Nx]0sm[]zs0c
+0sm[Nx]0sm[]zs0x[li]zs0x[Nx]0sm[]zs0#000000000
+0sm[Nx]0s0[]zs0x[li]zs0x[0000000000]0sm[]zs0x[liNx]zs0x[li;0l0l0x]
+x[liNx]zs0x#000000000
+0sm[Nx]0sm[]zs0x[li]zs0x[000]0sm[]x[li]zs0x[Nx]0sm[]zs0c
+0sm[Nx]0sm[]zs0x[li]zs0x[Nx]0sm[]zs0#0000
+0sm[Nx]0sm[]zs0x[li]zs0x[Nx]0sm[]zs0#000000000
+0sm[Nx]0s_@]zs0x[li]s^x[0000000000]0s0[]zsW[0000]zsxx[000000000]
diff --git a/contrib/bc/tests/fuzzing/dc_inputs/11.txt b/contrib/bc/tests/fuzzing/dc_inputs/11.txt
new file mode 100644
index 000000000000..73bbc7d88f1c
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/dc_inputs/11.txt
@@ -0,0 +1,4 @@
+#00000000
+[[00000]aa]sM[lip1-si0li>0eM]s010sil0x
+[[0000]00]sM[]s010sil0x
+[R]sM[lip=000]s0;0
diff --git a/contrib/bc/tests/fuzzing/dc_inputs/12.txt b/contrib/bc/tests/fuzzing/dc_inputs/12.txt
new file mode 100644
index 000000000000..aff25e7381cd
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/dc_inputs/12.txt
@@ -0,0 +1,2 @@
+1;09R0si[lii000000000000000000000000000000000000000000]li1000 2346dvdddd;ddddddddddddd?-sdddddddddd0+dd0 1+pR
+0dvdddd;ddSddddddddddd 0si[lid1+sil0sili10li?-s0]dsxx[00000000]li1000 2000dvddddddddddddddddddddddddd0 0+ddd 1+pR
diff --git a/contrib/bc/tests/fuzzing/dc_inputs/13.txt b/contrib/bc/tests/fuzzing/dc_inputs/13.txt
new file mode 100644
index 000000000000..e6af9463e38c
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/dc_inputs/13.txt
@@ -0,0 +1,7 @@
+zp10[00000000\00]pppppppppppppppR
+_1 _1(pR
+_1 _2(pR
+2 1{pR
+_1 1{pR 990+pR
+2000000 300000300000000+pR
+2070000000aaaaaaaaaaaaaaxaaaaaaaaaaaaR
diff --git a/contrib/bc/tests/fuzzing/dc_inputs/14.txt b/contrib/bc/tests/fuzzing/dc_inputs/14.txt
new file mode 100644
index 000000000000..741f3bfd7704
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/dc_inputs/14.txt
@@ -0,0 +1,7 @@
+0bpR
+1bpR
+.200000bpR
+100000.0000600bpR
+_10bpR
+_.1000000bpR
+_30000.00bpR: \ No newline at end of file
diff --git a/contrib/bc/tests/fuzzing/dc_inputs/15.txt b/contrib/bc/tests/fuzzing/dc_inputs/15.txt
new file mode 100644
index 000000000000..828e8204a2aa
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/dc_inputs/15.txt
@@ -0,0 +1,11 @@
+0bpax1bpR
+1bpR
+.30b900pR
+_10bp/90
+_30_.1/10bp30_.1/90
+_300.1/90/90
+_30_.1/90
+_30000.1/90
+90
+_30000.1/90
+70.000 70u
diff --git a/contrib/bc/tests/fuzzing/dc_inputs/16.txt b/contrib/bc/tests/fuzzing/dc_inputs/16.txt
new file mode 100644
index 000000000000..b021dd66d7ff
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/dc_inputs/16.txt
@@ -0,0 +1 @@
+0 0;^dddddRps0R@s016dddRRd^2ddRZ(b-P;;$p;;;;;;9;;;;;;$ppppppppppppp30
diff --git a/contrib/bc/tests/fuzzing/dc_inputs/17.txt b/contrib/bc/tests/fuzzing/dc_inputs/17.txt
new file mode 100644
index 000000000000..fb46510fc3e3
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/dc_inputs/17.txt
@@ -0,0 +1,20 @@
+0 1(pR
+1;;;;;pR
+1
+0 18d[0000000
+000000000000000000000000000000]sM[liv1-si0li!<0pR
+_1 0{pR
+_1 _1{pR
+_1 f0070000000000.0000000000000_10000000000006.00000000000005~pRpR
+_23745860900000.070000000000000 _0.20542357869124050~pRpR
+_3000000000000000.0000000700000006002 _7000000000000005000000000.000F000000000000003~pRpR20000000 300000000003.00000000000000030~pRpR
+_30000000000000000000000000
+1 0.001.00000000030
+1 0.000000000000000000000000000000000000000000000000000000000000000000002x30000000000000000000000000000000000000$80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000<0800000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000.000F000000000000003~pRpR20000000 300000000003.00000000000000030~pRpR
+_30000000000000.00000000000
+1 0.070.70000000000
+1 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000$80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000<080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000S8800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000Z800000000000
+_10pR
+=390NpR
+_2000
+40000 5000C 2i>0eM]s01@sil0x
diff --git a/contrib/bc/tests/fuzzing/dc_inputs/18.txt b/contrib/bc/tests/fuzzing/dc_inputs/18.txt
new file mode 100644
index 000000000000..ed2659d097c2
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/dc_inputs/18.txt
@@ -0,0 +1,3 @@
+1oVVf[li;WORli1S0Zli1;rORli1dH|2li@d-NliO+rK28729@9547628O745/pR
+_29307546189299999999999999999999999999999999999995 0.00000000000000000000000000009999999999999999999+99$9999999999.999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999995 0.0000000000000000000000000000000000R0000000000000000000000000000000000000+0000000000000000-0000000000000000000005+pR
+99999999999999999999999999999999999999999999999999999999999.999999999999999999999.99999999999999999999999999999999999999999900000000000000000000000R0000000000000000000000000000000000000+0000000000000000-0000000000000000000005+pR999999999999999999999999999999999999999999 0.00000000000000000000000000000000000000000000000000000000000C0020P00000000000000000000000000000000000007fli1+7fli1+si;d7dli1+si;0=Rls1d:0li +i100>x]dsxx[0000000]dsxx[p000]l010000000 00000000000pR
diff --git a/contrib/bc/tests/fuzzing/dc_inputs/20.txt b/contrib/bc/tests/fuzzing/dc_inputs/20.txt
new file mode 100644
index 000000000000..aa7752a85c67
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/dc_inputs/20.txt
@@ -0,0 +1,3 @@
+#0000
+I20PPrP PPPP PPs0daP1:0pR
+ PPP1d:0pRR
diff --git a/contrib/bc/tests/fuzzing/dc_inputs/21.txt b/contrib/bc/tests/fuzzing/dc_inputs/21.txt
new file mode 100644
index 000000000000..01707d8256b6
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/dc_inputs/21.txt
@@ -0,0 +1,5 @@
+0bpR
+1bpR
+.200000bpR
+100000.0000600bpR
+S09bpR
diff --git a/contrib/bc/tests/fuzzing/dc_inputs/22.txt b/contrib/bc/tests/fuzzing/dc_inputs/22.txt
new file mode 100644
index 000000000000..898184649926
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/dc_inputs/22.txt
@@ -0,0 +1,36 @@
+[0000000000000]ZpR
+[He00
+[0000000\00000000]00
+[0000000\00000000]000
+[0000000\00000000]00
+[0000]
+00000]
+[28pR]
+[27pR]
+[26pR]
+[25pR]
+[24pR]
+[23pR]
+[22pR]
+[21pR]
+[20pR]
+[19pR]
+[18pR]
+[17pR]
+[16pR]
+[15pR]
+[14pR]
+[13pR]
+[12pR]
+[11pR]
+[10pR]
+[9pR]
+[8pR]
+[7pR]
+[6pR]
+[5pR]
+[4pR]
+[3pR]
+[2pR]
+[1pR]
+[xz0<x]dsxx
diff --git a/contrib/bc/tests/fuzzing/dc_inputs/23.txt b/contrib/bc/tests/fuzzing/dc_inputs/23.txt
new file mode 100644
index 000000000000..1897dfbbb0aa
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/dc_inputs/23.txt
@@ -0,0 +1,2 @@
+#00000000
+[[0000 ]00]SM[l0p1-s00l0`000]s010sil0x
diff --git a/contrib/bc/tests/fuzzing/dc_inputs/24.txt b/contrib/bc/tests/fuzzing/dc_inputs/24.txt
new file mode 100644
index 000000000000..fb9b04f7f5b8
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/dc_inputs/24.txt
@@ -0,0 +1 @@
+ [] 0:xX:0 0:0X:0n/dc.000C00}pR
diff --git a/contrib/bc/tests/fuzzing/dc_inputs/25.txt b/contrib/bc/tests/fuzzing/dc_inputs/25.txt
new file mode 100644
index 000000000000..d48a9b2e83fd
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/dc_inputs/25.txt
@@ -0,0 +1,6 @@
+#00000000
+0s0[l0d:0l01;0d:0l01;0pRl01+s0l010>x]dsxx0sx0s0
+1 2
+s0[l0d:0l01;0d:0l01;0pRl01+s0l010>x]dsxx0sx0s0
+1 2
+
diff --git a/contrib/bc/tests/fuzzing/dc_inputs/26.txt b/contrib/bc/tests/fuzzing/dc_inputs/26.txt
new file mode 100644
index 000000000000..731d3969ac3b
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/dc_inputs/26.txt
@@ -0,0 +1,155 @@
+0bpR
+1bp0
+.20bpR
+100000.0000005bpR
+_10bpR
+_.1000[l0;0;rpRl01+s0l010>x]dsxx0sx0s0
+1 2+p+p
+3+p
+4+p
+5+p
+6+p
+7+p
+8+p
+9+p
+10+p
+11+p
+12+p
+13+p
+14+p
+15+p
+16+p
+17+p
+18+p
+19+p
+20+p
+21+0+p
+71+o
+70+p
+70+p
+70+p
+70+p
+22+p
+20+p
+20+p
+20+p
+20+p
+20+p
+20+p
+20+p
+30+p
+30+p
+30+p
+30+p
+30+p
+30+p
+30+p
+30+p
+30+p
+30+p
+40+1+p
+40+p
+40+p
+40+p
+40+p
+40+p
+40+p
+40+p
+40+p
+50+p
+50+p
+50+p
+50+p
+50+p
+50+p
+50+p
+50+p
+50+p
+50+p
+60+p
+60+p
+60bpR
+1bp0
+.20bpR
+100000.0070000bpR
+_10bpR
+_.1000[l0;0;rpRl01+s0l010>x]dsxx0sx0s0
+1 2+p+p
+3+p
+4+p
+5+p
+6+p
+7+p
+8+p
+9+p
+10+p
+11+p
+12+p
+13+p
+14+p
+15+p
+16+p
+17+p
+18+p
+19+p
+20+p
+21+0+p
+71+o
+70+p
+70+p
+70+p
+70+p
+22+p
+20+p
+20+p
+20+p
+20+p
+20+p
+20+p
+20+p
+30+p
+30+p
+30+p
+30+p
+30+p
+30+p
+30+p
+30+p
+30+p
+30+p
+40+1+p
+40+p
+40+p
+40+p
+40+p
+40+p
+40+p
+40+p
+40+p
+50+p
+50+p
+50+p
+50+p
+50+p
+50+p
+50+p
+50+p
+50+p
+50+p
+60+p
+60+p
+60+p
+60+p
+60+p
+60+p
+60+p
+60
+70+p
+70+p
+70+p
+70+p
+70+p
+70+p
+70+p
+80+p
+
diff --git a/contrib/bc/tests/fuzzing/dc_inputs/27.txt b/contrib/bc/tests/fuzzing/dc_inputs/27.txt
new file mode 100644
index 000000000000..69745b952afc
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/dc_inputs/27.txt
@@ -0,0 +1,2 @@
+"0000000\
+
diff --git a/contrib/bc/tests/fuzzing/dc_inputs/28.txt b/contrib/bc/tests/fuzzing/dc_inputs/28.txt
new file mode 100644
index 000000000000..fe81732b3e38
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/dc_inputs/28.txt
@@ -0,0 +1 @@
+10 4%0:i[000] 1:b 0;0 p 1;b0:b [000] 1:b 0;b p 1;b~b 0;b p 0;b~~~0k
diff --git a/contrib/bc/tests/fuzzing/dc_inputs/29.txt b/contrib/bc/tests/fuzzing/dc_inputs/29.txt
new file mode 100644
index 000000000000..886eb8ee0a8e
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/dc_inputs/29.txt
@@ -0,0 +1,13 @@
+10 4%0:b [200] 1:b 0;b 1;b X
+ 2000 1%p0
+3460:b [200] 1:b 0;b p bp0
+.2 1%pR
+6 4%pR
+10 4%0:b [200] 1:b 0;b p 1;b X
+ 20000 1%pR
+b 0;b p 0;b2
+1bpb [200] 1:u 0;b p 1;b X
+ 2
+[000] 0:b [200] 0:b 0;b p S0b p
+[s0]XpR
+
diff --git a/contrib/bc/tests/fuzzing/dc_inputs/30.txt b/contrib/bc/tests/fuzzing/dc_inputs/30.txt
new file mode 100644
index 000000000000..e072e71617d8
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/dc_inputs/30.txt
@@ -0,0 +1 @@
+0;0[]0:b;bs0l0x;0
diff --git a/contrib/bc/tests/fuzzing/dc_inputs/abs.txt b/contrib/bc/tests/fuzzing/dc_inputs/abs.txt
new file mode 100644
index 000000000000..9907dfc6679d
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/dc_inputs/abs.txt
@@ -0,0 +1,7 @@
+0bpR
+1bpR
+.218933bpR
+138963.9873645bpR
+_19bpR
+_.1298376bpR
+_3892173.289375bpR
diff --git a/contrib/bc/tests/fuzzing/dc_inputs/add.txt b/contrib/bc/tests/fuzzing/dc_inputs/add.txt
new file mode 100644
index 000000000000..42da2f1f309c
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/dc_inputs/add.txt
@@ -0,0 +1,33 @@
+0 0+pR
+0 0 0++pR
+0 1+pR
+0 1 1++pR
+1 1+pR
+1 0+pR
+2 5+pR
+237 483+pR
+999 999+pR
+2374623 324869356734856+pR
+2378639084586723980562 23468729367839+pR
+37298367203972395108367910823465293084561329084561390845613409516734503870691837451 785621394067928346918023476190834672198467134908618723249671349062187346898241093486139046139084613490817356023871869102746182749061872609129847+pR
+1.1 0+pR
+0 1.1+pR
+457283.731284923576 37842934672834.3874629385672354+pR
+1.0 0.1+pR
+3746289134067138046 0.138375863945672398456712389456273486293+pR
+_1 _1+pR
+_4 _15+pR
+_1346782 _1287904651762468913476+pR
+99999999999999999999999999999999999999999999999999999999999.999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001+pR
+99999999999999999999999999999999999999999999999999999999999.999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999995 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005+pR
+99999999999999999999999999999999999999999999999999999999999.999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001+pR
+99999999999999999999999999999999999999999999999999999999999.999999999999999999999999999999999999999999999999999999999899999999999999999999999999999999999999999999999999999999999999 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001+pR
+99999999999999999999999999999999999989999999999999999999999.999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001+pR
+_1889985797 2012747315+pR
+0 _14338.391079082+pR
+_2422297 1.3134942556+pR
+_1289374 1289374.2893417 0.238971 28937.28971+++pR
+1289374 1289374.2893417 _0.238971 28937.28971+++pR
+1289374 1289374.2893417 0.238971 _28937.28971+++pR
+1289374 1289374.2893417 _0.238971 _28937.28971+++pR
+1289374 _1289374.2893417 _0.238971 _28937.28971+++pR
diff --git a/contrib/bc/tests/fuzzing/dc_inputs/array.dc b/contrib/bc/tests/fuzzing/dc_inputs/array.dc
new file mode 100644
index 000000000000..970f29a68768
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/dc_inputs/array.dc
@@ -0,0 +1,2 @@
+#! /usr/bin/dc
+0si[lid:rli1+sili100>x]dsxx[li;rpRli1-sili100!>x]li1+[li;rpRli1+sili100>x]
diff --git a/contrib/bc/tests/fuzzing/dc_inputs/boolean.txt b/contrib/bc/tests/fuzzing/dc_inputs/boolean.txt
new file mode 100644
index 000000000000..815100f0d085
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/dc_inputs/boolean.txt
@@ -0,0 +1,80 @@
+0 1(pR
+1 1(pR
+2 1(pR
+_1 1(pR
+_1 0(pR
+_1 _1(pR
+_1 _2(pR
+0 1{pR
+1 1{pR
+2 1{pR
+_1 1{pR
+_1 0{pR
+_1 _1{pR
+_1 _2{pR
+0 1)pR
+1 1)pR
+2 1)pR
+_1 1)pR
+_1 0)pR
+_1 _1)pR
+_1 _2)pR
+0 1}pR
+1 1}pR
+2 1}pR
+_1 1}pR
+_1 0}pR
+_1 _1}pR
+_1 _2}pR
+0 0GpR
+0 1GpR
+1 0GpR
+_1 _1GpR
+0 _1GpR
+_1 0GpR
+1 1GpR
+238 2GpR
+0NpR
+1NpR
+_1NpR
+2398NpR
+_2983.2389NpR
+0 0MpR
+1 0MpR
+0 1MpR
+1 1MpR
+128973240 0MpR
+0 2893712MpR
+1982 28937MpR
+_2938 0MpR
+0 _1023.298037MpR
+0.283917 0MpR
+2389 _1208.28937MpR
+0 289.289372MpR
+_298.29387 0MpR
+_2983.28973 82937MpR
+0 _2938.320837MpR
+_2089.2308 0MpR
+_0.2893 _2938.28973MpR
+0.00000 1892MpR
+1289.023 .0000MpR
+0 0mpR
+1 0mpR
+0 1mpR
+1 1mpR
+128973240 0mpR
+0 2893712mpR
+1982 28937mpR
+_2938 0mpR
+0 _1023.298037mpR
+0.283917 0mpR
+2389 _1208.28937mpR
+0 289.289372mpR
+_298.29387 0mpR
+_2983.28973 82937mpR
+0 _2938.320837mpR
+_2089.2308 0mpR
+_0.2893 _2938.28973mpR
+0.00000 1892mpR
+1289.023 .0000mpR
+0.0000 .00000mpR
diff --git a/contrib/bc/tests/fuzzing/dc_inputs/decimal.txt b/contrib/bc/tests/fuzzing/dc_inputs/decimal.txt
new file mode 100644
index 000000000000..fdc628c857e0
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/dc_inputs/decimal.txt
@@ -0,0 +1,41 @@
+0pR
+0.0pR
+.0000pR
+000000000000000000000000.00000000000000000000000pR
+000000000000000000000000000135482346782356pR
+000000000000000000000000002pR
+1pR
+11pR
+123pR
+7505pR
+1023468723275435238491972521917846pR
+4343472432431705867392073517038270398027352709027389273920739037937960379637893607893607893670530278200795207952702873892786172916728961783907893607418973587857386079679267926737520730925372983782793652793pR
+_1pR
+_203pR
+_57pR
+_18586pR
+_31378682943772818461924738352952347258pR
+_823945628745673589495067238723986520375698237620834674509627345273096287563846592384526349872634895763257893467523987578690283762897568459072348758071071087813501875908127359018715023841710239872301387278pR
+.123521346523546pR
+0.1245923756273856pR
+_.1024678456387pR
+_0.8735863475634587pR
+4.0pR
+_6.0pR
+234237468293576.000000000000000000000000000000pR
+23987623568943567.00000000000000000005677834650000000000000pR
+23856934568940675.000000000000000435676782300000000000000456784pR
+77567648698496.000000000000000000587674750000000000458563800000000000000pR
+2348672354968723.2374823546000000000003256987394502346892435623870000000034578pR
+_2354768.000000000000000000000000000000000000pR
+_96739874567.000000000347683456pR
+_3764568345.000000000004573845000000347683460pR
+_356784356.934568495770004586495678300000000pR
+74325437345273852773827101738273127312738521733017537073520735207307570358738257390761276072160719802671980267018728630178.7082681027680521760217867841276127681270867827821768173178207830710978017738178678012767377058785378278207385237085237803278203782037237582795870pR
+_756752732785273851273728537852738257837283678965738527385272983678372867327835672967385278372637862738627836279863782673862783670.71738178361738718367186378610738617836781603760178367018603760178107735278372832783728367826738627836278378260736270367362073867097307925pR
+9812734012837410982345719208345712908357412903587192048571920458712.23957182459817249058172945781pR
+2893.982.28937pRpR
+198273\
+.192837pR
+1892.238907\
+.3982739pRpR
diff --git a/contrib/bc/tests/fuzzing/dc_inputs/divide.txt b/contrib/bc/tests/fuzzing/dc_inputs/divide.txt
new file mode 100644
index 000000000000..38b874e9f175
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/dc_inputs/divide.txt
@@ -0,0 +1,33 @@
+20k
+0 1/pR
+0 321566/pR
+0 0.3984567238456/pR
+1 1/pR
+1 1287469297356/pR
+1 0.2395672438567234/pR
+1 237586239856.0293596728392360/pR
+1249687284356 3027949207835207/pR
+378617298617396719 35748521/pR
+9348576237845624358 0.9857829375461/pR
+35768293846193284 2374568947.045762839567823/pR
+_78987234567812345 876542837618936/pR
+_356789237555535468 0.3375273860984786903/pR
+_5203475364850390 435742903748307.70869378534043296404530458/pR
+_0.37861723347576903 7385770896/pR
+_0.399454682043962 0.34824389304/pR
+_0.6920414523873204 356489645223.76076045304879030/pR
+_35872917389671.7573280963748 73924708/pR
+_78375896314.4836709876983 0.78356798637817/pR
+_2374123896417.143789621437581 347821469423789.1473856783960/pR
+_896729350238549726 _34976289345762/pR
+_2374568293458762348596 _0.8792370647234987679/pR
+_237584692306721845726038 _21783910782374529637.978102738746189024761/pR
+_0.23457980123576298375682 _1375486293874612/pR
+_0.173897061862478951264 _0.8179327486017634987516298745/pR
+_0.9186739823576829347586 _0.235678293458756239846/pR
+_0.9375896183746982374568 _13784962873546.0928729395476283745/pR
+_2930754618923467.12323745862937465 _734869238465/pR
+_23745861923467.874675129834675 _0.23542357869124756/pR
+_3878923750692883.7238596702834756902 _7384192674957215364986723.9738461923487621983/pR
+1 0.00000000000000000000000000000000000000000002346728372937352457354204563027/pR
+239854711289345712 2891374 182 .2893 ///pR
diff --git a/contrib/bc/tests/fuzzing/dc_inputs/divmod.txt b/contrib/bc/tests/fuzzing/dc_inputs/divmod.txt
new file mode 100644
index 000000000000..1633203ff99f
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/dc_inputs/divmod.txt
@@ -0,0 +1,64 @@
+20k
+0 1~pRpR
+0 321566~pRpR
+0 0.3984567238456~pRpR
+1 1~pRpR
+1 1287469297356~pRpR
+1 0.2395672438567234~pRpR
+1 237586239856.0293596728392360~pRpR
+1249687284356 3027949207835207~pRpR
+378617298617396719 35748521~pRpR
+9348576237845624358 0.9857829375461~pRpR
+35768293846193284 2374568947.045762839567823~pRpR
+_78987234567812345 876542837618936~pRpR
+_356789237555535468 0.3375273860984786903~pRpR
+_5203475364850390 435742903748307.70869378534043296404530458~pRpR
+_0.37861723347576903 7385770896~pRpR
+_0.399454682043962 0.34824389304~pRpR
+_0.6920414523873204 356489645223.76076045304879030~pRpR
+_35872917389671.7573280963748 73924708~pRpR
+_78375896314.4836709876983 0.78356798637817~pRpR
+_2374123896417.143789621437581 347821469423789.1473856783960~pRpR
+_896729350238549726 _34976289345762~pRpR
+_2374568293458762348596 _0.8792370647234987679~pRpR
+_237584692306721845726038 _21783910782374529637.978102738746189024761~pRpR
+_0.23457980123576298375682 _1375486293874612~pRpR
+_0.173897061862478951264 _0.8179327486017634987516298745~pRpR
+_0.9186739823576829347586 _0.235678293458756239846~pRpR
+_0.9375896183746982374568 _13784962873546.0928729395476283745~pRpR
+_2930754618923467.12323745862937465 _734869238465~pRpR
+_23745861923467.874675129834675 _0.23542357869124756~pRpR
+_3878923750692883.7238596702834756902 _7384192674957215364986723.9738461923487621983~pRpR
+1 0.00000000000000000000000000000000000000000002346728372937352457354204563027~pRpR
+0k
+0 1~pRpR
+0 321566~pRpR
+0 0.3984567238456~pRpR
+1 1~pRpR
+1 1287469297356~pRpR
+1 0.2395672438567234~pRpR
+1 237586239856.0293596728392360~pRpR
+1249687284356 3027949207835207~pRpR
+378617298617396719 35748521~pRpR
+9348576237845624358 0.9857829375461~pRpR
+35768293846193284 2374568947.045762839567823~pRpR
+_78987234567812345 876542837618936~pRpR
+_356789237555535468 0.3375273860984786903~pRpR
+_5203475364850390 435742903748307.70869378534043296404530458~pRpR
+_0.37861723347576903 7385770896~pRpR
+_0.399454682043962 0.34824389304~pRpR
+_0.6920414523873204 356489645223.76076045304879030~pRpR
+_35872917389671.7573280963748 73924708~pRpR
+_78375896314.4836709876983 0.78356798637817~pRpR
+_2374123896417.143789621437581 347821469423789.1473856783960~pRpR
+_896729350238549726 _34976289345762~pRpR
+_2374568293458762348596 _0.8792370647234987679~pRpR
+_237584692306721845726038 _21783910782374529637.978102738746189024761~pRpR
+_0.23457980123576298375682 _1375486293874612~pRpR
+_0.173897061862478951264 _0.8179327486017634987516298745~pRpR
+_0.9186739823576829347586 _0.235678293458756239846~pRpR
+_0.9375896183746982374568 _13784962873546.0928729395476283745~pRpR
+_2930754618923467.12323745862937465 _734869238465~pRpR
+_23745861923467.874675129834675 _0.23542357869124756~pRpR
+_3878923750692883.7238596702834756902 _7384192674957215364986723.9738461923487621983~pRpR
+1 0.00000000000000000000000000000000000000000002346728372937352457354204563027~pRpR
diff --git a/contrib/bc/tests/fuzzing/dc_inputs/else.dc b/contrib/bc/tests/fuzzing/dc_inputs/else.dc
new file mode 100644
index 000000000000..84deb8754e9f
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/dc_inputs/else.dc
@@ -0,0 +1,4 @@
+#! /usr/bin/dc
+[[Done!]pR]sM[lip1-si0li>LeM]sL10silLx
+[[Done!]pR]sM[lip1-si0li!<LeM]sL10silLx
+[[Done!]pR]sM[lip1-si0li!=LeM]sL10silLx
diff --git a/contrib/bc/tests/fuzzing/dc_inputs/engineering.txt b/contrib/bc/tests/fuzzing/dc_inputs/engineering.txt
new file mode 100644
index 000000000000..90a35052b3cb
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/dc_inputs/engineering.txt
@@ -0,0 +1,19 @@
+1o
+0pR
+1pR
+_34pR
+298pR
+_8933pR
+29488pR
+_148232pR
+8927559pR
+.2pR
+_.02pR
+.002pR
+_.0003pR
+.0000209310pR
+_.00000289362pR
+.000000859289pR
+_.02983672pR
+.20201296pR
+_.8907210897000000000000000000pR
diff --git a/contrib/bc/tests/fuzzing/dc_inputs/loop.dc b/contrib/bc/tests/fuzzing/dc_inputs/loop.dc
new file mode 100644
index 000000000000..26cec23818df
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/dc_inputs/loop.dc
@@ -0,0 +1,3 @@
+#! /usr/bin/dc
+[lip1-si0li>L]sL10silLx
+[lip1+si10li<L]sL0silLx
diff --git a/contrib/bc/tests/fuzzing/dc_inputs/misc.txt b/contrib/bc/tests/fuzzing/dc_inputs/misc.txt
new file mode 100644
index 000000000000..222a3ad265d2
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/dc_inputs/misc.txt
@@ -0,0 +1 @@
+zp198202389.289374pzp[Hello, World!]pzpzpfrfczpfR
diff --git a/contrib/bc/tests/fuzzing/dc_inputs/modexp.txt b/contrib/bc/tests/fuzzing/dc_inputs/modexp.txt
new file mode 100644
index 000000000000..a6afb998558e
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/dc_inputs/modexp.txt
@@ -0,0 +1,103 @@
+0 0 1|pR
+1 0 1|pR
+1 0 2|pR
+0 10 1|pR
+1 293 1|pR
+1 2789365 2|pR
+100 8 7|pR
+10922384 15031007 201|pR
+3346529 189 254|pR
+4113416930 197 14|pR
+7709 5887 111|pR
+5487406 3252 128|pR
+2080527 2279453822 219|pR
+48895 50678 232|pR
+1535808383 2902995144 18|pR
+8437837 2882198 69|pR
+35363 25806 2|pR
+3221177403 1560419989 189|pR
+227 42775 163|pR
+2811398069 37500 173|pR
+15046850 3859895697 195|pR
+15770756 3621999893 119|pR
+6937927 3719297189 183|pR
+12573 43819 209|pR
+42098463 7584603 136|pR
+8656683 1328292415 226|pR
+209 81 157|pR
+141 13317429 26|pR
+809485795 60745 101|pR
+4882 1388217898 38|pR
+750704 78 119|pR
+668879580 2888860497 179|pR
+1152725844 15295742 154|pR
+16160694 8981529 154|pR
+216 102 3|pR
+3691227289 5344109 232|pR
+2195559299 61 222|pR
+2478990626 13007440 30|pR
+45083 44 117|pR
+224 55824 53|pR
+1372700133 89 94|pR
+205 10422 48|pR
+11887 12 73|pR
+5955 24353 114|pR
+1201697310 789722419 6|pR
+56577 231 229|pR
+96 38841 189|pR
+6529661 5636520 209|pR
+11005 15955685 27|pR
+9709 231 132|pR
+59790 1034579699 166|pR
+47892 14536879 79|pR
+48 208 21|pR
+33036 3877 65|pR
+164 6527085 249|pR
+12146850 224 37|pR
+218 16425679 62|pR
+51 27641 95|pR
+3076735605 49154 32|pR
+515652717 4117874315 143|pR
+300672671 720768884 110|pR
+9422066 206 5|pR
+43 97 13|pR
+545174510 65319 126|pR
+3317462730 704990271 51|pR
+47316 23231 202|pR
+7236571 4379567 106|pR
+2584584521 2459274189 29|pR
+61562 5035178 178|pR
+65302 112 151|pR
+63040 2168854052 213|pR
+9039611 2370306559 62|pR
+16414384 1020652061 83|pR
+7491 3853569905 172|pR
+1180322494 46670 84|pR
+3823343557 3865107254 127|pR
+6240872 55335 39|pR
+2281401897 1098411 251|pR
+61 2949190429 231|pR
+8981024 162 43|pR
+1 3568883218 212|pR
+4217100969 3471787779 8|pR
+3232237 13 243|pR
+29280 3972452706 100|pR
+13077 6431923 216|pR
+104 3098510775 140|pR
+9503298 174 242|pR
+3424695712 12184 23|pR
+184 15066347 151|pR
+2935856 14003205 184|pR
+1386637762 2128151420 71|pR
+154 11960656 12|pR
+743976432 4004778779 136|pR
+3909160595 3575680922 21|pR
+26133 3580 147|pR
+409154 170 68|pR
+149 55629 40|pR
+5753 13776176 32|pR
+3831447473 658273178 98|pR
+1527252003 2300622 207|pR
+3363824553 8244645 215|pR
+20 145 101|pR
+4005077294 2196555621 94|pR
diff --git a/contrib/bc/tests/fuzzing/dc_inputs/modulus.txt b/contrib/bc/tests/fuzzing/dc_inputs/modulus.txt
new file mode 100644
index 000000000000..613944b2001a
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/dc_inputs/modulus.txt
@@ -0,0 +1,70 @@
+20k
+1 1%pR
+2 1%pR
+16 4%pR
+15 4%pR
+17 4%pR
+2389473 5%pR
+39240687239 1%pR
+346728934 23958%pR
+3496723859067234 298375462837546928347623059375486%pR
+_1 1%pR
+_2 1%pR
+_47589634875689345 37869235%pR
+_1274852934765 2387628935486273546%pR
+_6324758963 237854962%pR
+1 _1%pR
+2 _1%pR
+2 _2%pR
+2 _3%pR
+16 5%pR
+15 5%pR
+14 5%pR
+89237423 _237856923854%pR
+123647238946 _12467%pR
+_1 _1%pR
+_2 _1%pR
+_2 _2%pR
+_2 _3%pR
+_13 _7%pR
+_14 _7%pR
+_15 _7%pR
+_12784956 _32746%pR
+_127849612 _23712347682193%pR
+0k
+1 1%pR
+2 1%pR
+16 4%pR
+15 4%pR
+17 4%pR
+2389473 5%pR
+39240687239 1%pR
+346728934 23958%pR
+3496723859067234 298375462837546928347623059375486%pR
+_1 1%pR
+_2 1%pR
+_47589634875689345 37869235%pR
+_1274852934765 2387628935486273546%pR
+_6324758963 237854962%pR
+1 _1%pR
+2 _1%pR
+2 _2%pR
+2 _3%pR
+16 5%pR
+15 5%pR
+14 5%pR
+89237423 _237856923854%pR
+123647238946 _12467%pR
+_1 _1%pR
+_2 _1%pR
+_2 _2%pR
+_2 _3%pR
+_13 _7%pR
+_14 _7%pR
+_15 _7%pR
+_12784956 _32746%pR
+_127849612 _23712347682193%pR
+_3191280681 641165986%pR
+0k _899510228 _2448300078.40314%pR
+0k _7424863 _207.2609738667%pR
+0k 3769798918 0.6%pR
diff --git a/contrib/bc/tests/fuzzing/dc_inputs/multiply.txt b/contrib/bc/tests/fuzzing/dc_inputs/multiply.txt
new file mode 100644
index 000000000000..1f9041d06ea7
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/dc_inputs/multiply.txt
@@ -0,0 +1,42 @@
+0 0*pR
+0.000 0*pR
+1 0*pR
+0 1*pR
+0 2498752389672835476*pR
+873246913745129084576134 0*pR
+1 472638590273489273456*pR
+12374861230476103672835496 1*pR
+1 1*pR
+2 1*pR
+1 2*pR
+2 2*pR
+3 14*pR
+17 8*pR
+1892467513846753 1872439821374591038746*pR
+328962735862.2973546835638947635 1728465791348762356*pR
+38745962374538.387427384672934867234 0.1932476528394672837568923754*pR
+9878894576289457634856.2738627161689017387608947567654 37842939768237596237854203.29874372139852739126739621793162*pR
+_1 1*pR
+_1 2*pR
+78893457 _34876238956*pR
+235678324957634 _0.2349578349672389576*pR
+_12849567821934 12738462937681*pR
+1274861293467.927843682937462 _28935678239*pR
+2936077239872.12937462836 _0.012842357682435762*pR
+2387692387566.2378569237546 _272189345628.123875629835876*pR
+0.012348629356782835962 _23487692356*pR
+0.4768349567348675934 _0.23756834576934857638495*pR
+0.98748395367485962735486 _4675839462354867.376834956738456*pR
+_321784627934586 _235762378596*pR
+_32578623567892356 _0.32567384579638456*pR
+_35768232346876 _2348672935602387620.28375682349576237856*pR
+_0.2356728394765234 _238759624356978*pR
+_0.2345768212346780 _0.235768124697074385948943532045*pR
+_0.370873860736785306278630 _7835678398607.7086378076867096270*pR
+_78365713707.7089637863786730 _738580798679306780*pR
+_73867038956790490258249 _0.7379862716391723672803679*pR
+_378621971598721837710387 _98465373878350798.09743896037963078560*pR
+37164201 2931559660*pR
+679468076118972457796560530571.46287161642138401685 93762.2836*pR
+.000000000000000000000000001 .0000000000000000000000001*pR
+239 289 _98 .8937 _.1893 28937*****pR
diff --git a/contrib/bc/tests/fuzzing/dc_inputs/places.txt b/contrib/bc/tests/fuzzing/dc_inputs/places.txt
new file mode 100644
index 000000000000..308ff1373d64
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/dc_inputs/places.txt
@@ -0,0 +1,14 @@
+0 0@pR
+1 0@pR
+2 0@pR
+0.0023896 0@pR
+1.298346 0@pR
+2.00000000 0@pR
+0.0023896 3@pR
+1.298346 4@pR
+2.00000000 5@pR
+289 3@pR
+18.34 6@pR
+_183.1 0@pR
+_23.238 8@pR
+_343.23 2@pR
diff --git a/contrib/bc/tests/fuzzing/dc_inputs/power.txt b/contrib/bc/tests/fuzzing/dc_inputs/power.txt
new file mode 100644
index 000000000000..955e42557a15
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/dc_inputs/power.txt
@@ -0,0 +1,36 @@
+20k
+0 0^pR
+0 1^pR
+0 1894^pR
+1 0^pR
+39746823 0^pR
+0.238672983047682 0^pR
+18394762374689237468.97354862973846 0^pR
+1 1^pR
+2 1^pR
+18927361346 1^pR
+0.23523785962738592635777 1^pR
+328956734869213746.89782398457234 1^pR
+8937 8^pR
+93762.2836 3^pR
+1 _1^pR
+2 _1^pR
+10 _1^pR
+683734768 _1^pR
+38579623756.897937568235 _1^pR
+1 _32467^pR
+2 _53^pR
+_1 1^pR
+_1 2^pR
+_2 1^pR
+_2 2^pR
+_237 294^pR
+_3746 28^pR
+_0.3548 35^pR
+_1 _1^pR
+_1 _2^pR
+_2 _1^pR
+_2 _2^pR
+_86 _7^pR
+0 _251^pR
+_0.2959371298 27^pR
diff --git a/contrib/bc/tests/fuzzing/dc_inputs/quit.dc b/contrib/bc/tests/fuzzing/dc_inputs/quit.dc
new file mode 100644
index 000000000000..81e6289af25b
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/dc_inputs/quit.dc
@@ -0,0 +1,2 @@
+1se [li p 1+si le li !=lem]sl [lk p 1+sk le lk !=o]so [0sk lox leQ 0sk lox le 3*1+Q 0sk lox]sm [0si llx le 1+se 10 le !=n]dsnx
+1si [li p 1+si 10 li !=set]ss [1000Q]st lsx
diff --git a/contrib/bc/tests/fuzzing/dc_inputs/scientific.txt b/contrib/bc/tests/fuzzing/dc_inputs/scientific.txt
new file mode 100644
index 000000000000..240473b0bbca
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/dc_inputs/scientific.txt
@@ -0,0 +1,55 @@
+0e0pR
+0e1pR
+0e5pR
+0e_2pR
+0e_100pR
+1e0pR
+_1e1pR
+1e9pR
+_1e21pR
+1e_1pR
+_1e_2pR
+1e_5pR
+4.92837e5pR
+_3.28971028e20pR
+6.2e3pR
+_8.289371e2pR
+5.9817280937e8pR
+_3.28977e_1pR
+8.8927891e_20pR
+_7.98239e_4pR
+4.4892e_4pR
+_18937e0pR
+198273e10pR
+_18927e_4pR
+28937e_5pR
+_891072e_7pR
+.28972e0pR
+_.891273e_1pR
+.8928397e1pR
+_.0002983172e5pR
+.00022e3pR
+_.00022e4pR
+.0000328937e8pR
+82938.29873e8.82\
+937pRpR
+2893e2\
+.389pRpR
+0o
+0pR
+1pR
+10pR
+_289pR
+2894pR
+_89434pR
+894370pR
+_1239839pR
+28931708pR
+_8052098.8029731809pR
+.1pR
+_.01pR
+.001pR
+_.00038pR
+.0000483pR
+_.0002894378190pR
+.2893712083pR
diff --git a/contrib/bc/tests/fuzzing/dc_inputs/shift.txt b/contrib/bc/tests/fuzzing/dc_inputs/shift.txt
new file mode 100644
index 000000000000..628b0a5bf6fe
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/dc_inputs/shift.txt
@@ -0,0 +1,42 @@
+0 0HpR
+1 0HpR
+2 0HpR
+0.0023896 0HpR
+1.298346 0HpR
+2.00000000 0HpR
+0.0023896 3HpR
+1.298346 4HpR
+2.00000000 5HpR
+89136.892348976 7HpR
+1892634051829351283289298 24HpR
+0 0hpR
+1 0hpR
+2 0hpR
+0.0023896 0hpR
+1.298346 0hpR
+2.00000000 0hpR
+0.0023896 3hpR
+1.298346 4hpR
+2.00000000 5hpR
+89136.892348976 7hpR
+1892634051829351283289298 24hpR
+_1 0HpR
+_2 0HpR
+_0.0023896 0HpR
+_1.298346 0HpR
+_2.00000000 0HpR
+_0.0023896 3HpR
+_1.298346 4HpR
+_2.00000000 5HpR
+_89136.892348976 7HpR
+_1892634051829351283289298 24HpR
+_1 0hpR
+_2 0hpR
+_0.0023896 0hpR
+_1.298346 0hpR
+_2.00000000 0hpR
+_0.0023896 3hpR
+_1.298346 4hpR
+_2.00000000 5hpR
+_89136.892348976 7hpR
+_1892634051829351283289298 24hpR
diff --git a/contrib/bc/tests/fuzzing/dc_inputs/sqrt.txt b/contrib/bc/tests/fuzzing/dc_inputs/sqrt.txt
new file mode 100644
index 000000000000..7c13fdd0bb5d
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/dc_inputs/sqrt.txt
@@ -0,0 +1,14 @@
+20k
+0vpR
+2vpR
+4vpR
+9vpR
+16vpR
+25vpR
+121vpR
+48765vpR
+9287356207356vpR
+0.189274385967238956872354vpR
+12389467137496823.134567829387456283946vpR
+.0000000000000000000000000000123vpR
+1vpR
diff --git a/contrib/bc/tests/fuzzing/dc_inputs/stack_len.txt b/contrib/bc/tests/fuzzing/dc_inputs/stack_len.txt
new file mode 100644
index 000000000000..1b367f3affa8
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/dc_inputs/stack_len.txt
@@ -0,0 +1,15 @@
+zp
+zp
+zp
+zp
+sa
+yap
+Sa
+yap
+Sa
+yapR
+La
+yapR
+La
+yap
+zp
diff --git a/contrib/bc/tests/fuzzing/dc_inputs/stdin.txt b/contrib/bc/tests/fuzzing/dc_inputs/stdin.txt
new file mode 100644
index 000000000000..7bf8316b99af
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/dc_inputs/stdin.txt
@@ -0,0 +1,205 @@
+0si[lid:rli1+sili10>x]dsxxli1-si[li;rpRli1-sili0!>x]dsxxli1+si[li;rpRli1+sili10>x]dsxx0sx0si
+1 2+p
+[foo]
+0
+1+p
+2+p
+3+p
+4+p
+5+p
+6+p
+7+p
+8+p
+9+p
+10+p
+11+p
+12+p
+13+p
+14+p
+15+p
+16+p
+17+p
+18+p
+19+p
+20+p
+21+p
+22+p
+23+p
+24+p
+25+p
+26+p
+27+p
+28+p
+29+p
+30+p
+31+p
+32+p
+33+p
+34+p
+35+p
+36+p
+37+p
+38+p
+39+p
+40+p
+41+p
+42+p
+43+p
+44+p
+45+p
+46+p
+47+p
+48+p
+49+p
+50+p
+51+p
+52+p
+53+p
+54+p
+55+p
+56+p
+57+p
+58+p
+59+p
+60+p
+61+p
+62+p
+63+p
+64+p
+65+p
+66+p
+67+p
+68+p
+69+p
+70+p
+71+p
+72+p
+73+p
+74+p
+75+p
+76+p
+77+p
+78+p
+79+p
+80+p
+81+p
+82+p
+83+p
+84+p
+85+p
+86+p
+87+p
+88+p
+89+p
+90+p
+91+p
+92+p
+93+p
+94+p
+95+p
+96+p
+97+p
+98+p
+99+p
+100+p
+101+p
+102+p
+103+p
+104+p
+105+p
+106+p
+107+p
+108+p
+109+p
+110+p
+111+p
+112+p
+113+p
+114+p
+115+p
+116+p
+117+p
+118+p
+119+p
+120+p
+121+p
+122+p
+123+p
+124+p
+125+p
+126+p
+127+p
+128+p
+129+p
+130+p
+131+p
+132+p
+133+p
+134+p
+135+p
+136+p
+137+p
+138+p
+139+p
+140+p
+141+p
+142+p
+143+p
+144+p
+145+p
+146+p
+147+p
+148+p
+149+p
+150+p
+151+p
+152+p
+153+p
+154+p
+155+p
+156+p
+157+p
+158+p
+159+p
+160+p
+161+p
+162+p
+163+p
+164+p
+165+p
+166+p
+167+p
+168+p
+169+p
+170+p
+171+p
+172+p
+173+p
+174+p
+175+p
+176+p
+177+p
+178+p
+179+p
+180+p
+181+p
+182+p
+183+p
+184+p
+185+p
+186+p
+187+p
+188+p
+189+p
+190+p
+191+p
+192+p
+193+p
+194+p
+195+p
+196+p
+197+p
+198+p
+199+p
+200+p
+p
diff --git a/contrib/bc/tests/fuzzing/dc_inputs/stream.dc b/contrib/bc/tests/fuzzing/dc_inputs/stream.dc
new file mode 100644
index 000000000000..5c61e7c931f9
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/dc_inputs/stream.dc
@@ -0,0 +1,2 @@
+#! /usr/bin/dc
+0si[liPlid1+sili4096>x]ddsxPx
diff --git a/contrib/bc/tests/fuzzing/dc_inputs/strings.txt b/contrib/bc/tests/fuzzing/dc_inputs/strings.txt
new file mode 100644
index 000000000000..460976abbd9e
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/dc_inputs/strings.txt
@@ -0,0 +1,51 @@
+[Hello, World!]ZpR
+[Hello, World!]pR
+[Hello, \[ World!]ZpR
+[Hello, \[ World!]pR
+[Hello, \] World!]ZpR
+[Hello, \] World!]pR
+[30pR]
+[29pR]
+[28pR]
+[27pR]
+[26pR]
+[25pR]
+[24pR]
+[23pR]
+[22pR]
+[21pR]
+[20pR]
+[19pR]
+[18pR]
+[17pR]
+[16pR]
+[15pR]
+[14pR]
+[13pR]
+[12pR]
+[11pR]
+[10pR]
+[9pR]
+[8pR]
+[7pR]
+[6pR]
+[5pR]
+[4pR]
+[3pR]
+[2pR]
+[1pR]
+[xz0<x]dsxx
+[\\]pR
+[\[\]]pR
+1xpR
+[1st] 0:b [2nd] 1:b 0;b p 1;b p
+[string]XpR
+[3 4^pR]silix
+[[[q 1 3+pR]x]x]x4 5^pR
+4xpR
+5 112ax 90ax 112ax 82ax
+[\q] pR
+[q\\] pR
+[\\] pR
+92 a pR
+[[10pR]si]x [[lix]x]x
diff --git a/contrib/bc/tests/fuzzing/dc_inputs/subtract.txt b/contrib/bc/tests/fuzzing/dc_inputs/subtract.txt
new file mode 100644
index 000000000000..2cb4104fb717
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/dc_inputs/subtract.txt
@@ -0,0 +1,33 @@
+0 0-pR
+0 1-pR
+1 0-pR
+1 1-pR
+5 2-pR
+2 9-pR
+321974 12845976238457-pR
+2874519803456710938465 384723854-pR
+10000000000000000000000000000000000000000 999999999999999999999999999999999999999-pR
+10000000000000000000000000000000000000000 9999999999999999999999999999999999999999-pR
+10000000000000000000000000000000000000000 999999999999999999999999999999999999999.99999999999999999999999999999999999-pR
+10000000000000000000000000000000000000000 9999999999999999999999999999999999999999.9999999999999999999999999999999999-pR
+10000000000000000000000000000000000000000 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000001-pR
+10000000000000000000000000000000000000001 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000001-pR
+10000000000000000000000000000000000000000.0000000001 0.0000000000000000000000000000000000000000000000000000000000000000000000000001-pR
+_2 6-pR
+_23784692345 182934721309467230894628735496027345-pR
+_224352354962873059862 _1245723576829456278354960278345-pR
+_3468273598 _12354243-pR
+_0.92345768293 _2354768923-pR
+_712384634.123476823 _24768293376-pR
+_1879234638 _0.917234869234-pR
+_0.9172438692134 _0.971284967124-pR
+_0.1283475123465 _0.937462346-pR
+_124765829346.2837468293562 _0.923467829346-pR
+_12476829385769 _1928476259034.8378629356-pR
+_0.38476284395876345 _94875394587623.2357869324857-pR
+_4674596708467.34754789403674343567 _48672394852354698.237548629345-pR
+979519669 3018100865-pR
+929002449 3280677283-pR
+0 _525898-pR
+3 _3-pR
+2 _1 2893714 _2189367411289 _.8921374 3.9201384----pR
diff --git a/contrib/bc/tests/fuzzing/dc_inputs/vars.txt b/contrib/bc/tests/fuzzing/dc_inputs/vars.txt
new file mode 100644
index 000000000000..bbe73b47d81f
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/dc_inputs/vars.txt
@@ -0,0 +1,2 @@
+298734.8921702348sx_928374892.28937syzpRlxly+pR
+298734.8921702348S xotj _928374892.28937S yotp zpRl xotj l yotp-pRzpR L xotj L yotp-pR
diff --git a/contrib/bc/tests/fuzzing/dc_inputs/weird.dc b/contrib/bc/tests/fuzzing/dc_inputs/weird.dc
new file mode 100644
index 000000000000..391ec05d6282
--- /dev/null
+++ b/contrib/bc/tests/fuzzing/dc_inputs/weird.dc
@@ -0,0 +1,2 @@
+#! /usr/bin/dc
+zp198202389.289374pzp[He World!]SzpzXfrfxzpfR
diff --git a/contrib/bc/tests/other.sh b/contrib/bc/tests/other.sh
index bd0014641846..64ba877a20c0 100755
--- a/contrib/bc/tests/other.sh
+++ b/contrib/bc/tests/other.sh
@@ -152,16 +152,19 @@ if [ "$d" = "bc" ]; then
printf '5\n0\n' > "$redefine_res"
"$exe" "$@" --redefine=print -e 'define print(x) { x }' -e 'print(5)' > "$redefine_out"
+ err="$?"
checktest "$d" "$err" "keyword redefinition" "$redefine_res" "$redefine_out"
"$exe" "$@" -r "abs" -r "else" -e 'abs = 5;else = 0' -e 'abs;else' > "$redefine_out"
+ err="$?"
checktest "$d" "$err" "keyword redefinition" "$redefine_res" "$redefine_out"
if [ "$extra_math" -ne 0 ]; then
"$exe" "$@" -lr abs -e "perm(5, 1)" -e "0" > "$redefine_out"
+ err="$?"
checktest "$d" "$err" "keyword not redefined in builtin library" "$redefine_res" "$redefine_out"
@@ -178,6 +181,53 @@ if [ "$d" = "bc" ]; then
checkerrtest "$d" "$err" "Keyword redefinition error without BC_REDEFINE_KEYWORDS" "$redefine_out" "$d"
printf 'pass\n'
+ printf 'Running multiline comment expression file test...'
+
+ multiline_expr_res=""
+ multiline_expr_out="$outputdir/bc_outputs/multiline_expr_results.txt"
+
+ # tests/bc/misc1.txt happens to have a multiline comment in it.
+ "$exe" "$@" -f "$testdir/bc/misc1.txt" > "$multiline_expr_out"
+ err="$?"
+
+ checktest "$d" "$err" "multiline comment in expression file" "$testdir/bc/misc1_results.txt" \
+ "$multiline_expr_out"
+
+ printf 'pass\n'
+ printf 'Running multiline comment expression file error test...'
+
+ "$exe" "$@" -f "$testdir/bc/errors/05.txt" 2> "$multiline_expr_out"
+ err="$?"
+
+ checkerrtest "$d" "$err" "multiline comment in expression file error" \
+ "$multiline_expr_out" "$d"
+
+ printf 'pass\n'
+ printf 'Running multiline string expression file test...'
+
+ # tests/bc/strings.txt happens to have a multiline string in it.
+ "$exe" "$@" -f "$testdir/bc/strings.txt" > "$multiline_expr_out"
+ err="$?"
+
+ checktest "$d" "$err" "multiline string in expression file" "$testdir/bc/strings_results.txt" \
+ "$multiline_expr_out"
+
+ printf 'pass\n'
+ printf 'Running multiline string expression file error test...'
+
+ "$exe" "$@" -f "$testdir/bc/errors/16.txt" 2> "$multiline_expr_out"
+ err="$?"
+
+ checkerrtest "$d" "$err" "multiline string in expression file with backslash error" \
+ "$multiline_expr_out" "$d"
+
+ "$exe" "$@" -f "$testdir/bc/errors/04.txt" 2> "$multiline_expr_out"
+ err="$?"
+
+ checkerrtest "$d" "$err" "multiline string in expression file error" \
+ "$multiline_expr_out" "$d"
+
+ printf 'pass\n'
else