aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Eßer <se@FreeBSD.org>2022-08-30 18:35:22 +0000
committerStefan Eßer <se@FreeBSD.org>2022-08-30 18:37:36 +0000
commit161a37cc712bae177402d7143cb21b7d085c69c7 (patch)
tree8eabf221dc1a31abf6f88dd6fcdb0b4e2a78fc82
parent1576f66712876ee8b0fcc8b35fb062e1813b4fc0 (diff)
vendor/bc: import version 6.0.2verndor/bc/6.0.2vendor/bc/6.0.2
Changes relative to the previous version in FreeBSD: - Fix error message on certain syntax errors. - Add digit clamping (build option and run-time option) - Make -l options no longer overridee scale value set with -S
-rw-r--r--.clang-format152
-rw-r--r--.clang-tidy43
-rw-r--r--.gitignore86
-rw-r--r--Makefile.in20
-rw-r--r--NEWS.md48
-rwxr-xr-xconfigure.sh326
-rw-r--r--gen/bc_help.txt38
-rw-r--r--gen/dc_help.txt36
-rw-r--r--gen/lib.bc1
-rw-r--r--gen/strgen.c4
-rwxr-xr-xgen/strgen.sh2
-rw-r--r--include/args.h31
-rw-r--r--include/bcl.h55
-rw-r--r--include/file.h18
-rw-r--r--include/history.h28
-rw-r--r--include/lang.h12
-rw-r--r--include/lex.h7
-rw-r--r--include/library.h136
-rw-r--r--include/num.h12
-rw-r--r--include/program.h50
-rw-r--r--include/status.h417
-rw-r--r--include/vector.h30
-rw-r--r--include/version.h2
-rw-r--r--include/vm.h237
-rw-r--r--manuals/algorithms.md2
-rw-r--r--manuals/bc/A.1385
-rw-r--r--manuals/bc/A.1.md312
-rw-r--r--manuals/bc/E.1352
-rw-r--r--manuals/bc/E.1.md296
-rw-r--r--manuals/bc/EH.1352
-rw-r--r--manuals/bc/EH.1.md296
-rw-r--r--manuals/bc/EHN.1352
-rw-r--r--manuals/bc/EHN.1.md296
-rw-r--r--manuals/bc/EN.1352
-rw-r--r--manuals/bc/EN.1.md296
-rw-r--r--manuals/bc/H.1385
-rw-r--r--manuals/bc/H.1.md312
-rw-r--r--manuals/bc/HN.1385
-rw-r--r--manuals/bc/HN.1.md312
-rw-r--r--manuals/bc/N.1385
-rw-r--r--manuals/bc/N.1.md312
-rw-r--r--manuals/bcl.3195
-rw-r--r--manuals/bcl.3.md159
-rw-r--r--manuals/build.md114
-rw-r--r--manuals/dc/A.1278
-rw-r--r--manuals/dc/A.1.md222
-rw-r--r--manuals/dc/E.1270
-rw-r--r--manuals/dc/E.1.md224
-rw-r--r--manuals/dc/EH.1270
-rw-r--r--manuals/dc/EH.1.md224
-rw-r--r--manuals/dc/EHN.1270
-rw-r--r--manuals/dc/EHN.1.md224
-rw-r--r--manuals/dc/EN.1270
-rw-r--r--manuals/dc/EN.1.md224
-rw-r--r--manuals/dc/H.1278
-rw-r--r--manuals/dc/H.1.md222
-rw-r--r--manuals/dc/HN.1278
-rw-r--r--manuals/dc/HN.1.md222
-rw-r--r--manuals/dc/N.1278
-rw-r--r--manuals/dc/N.1.md222
-rwxr-xr-xscripts/format.sh2
-rw-r--r--src/args.c106
-rw-r--r--src/bc.c14
-rw-r--r--src/bc_lex.c6
-rw-r--r--src/bc_parse.c147
-rw-r--r--src/data.c2
-rw-r--r--src/dc.c14
-rw-r--r--src/dc_lex.c4
-rw-r--r--src/dc_parse.c111
-rw-r--r--src/file.c165
-rw-r--r--src/history.c79
-rw-r--r--src/lex.c10
-rw-r--r--src/library.c553
-rw-r--r--src/main.c20
-rw-r--r--src/num.c531
-rw-r--r--src/opt.c6
-rw-r--r--src/parse.c6
-rw-r--r--src/program.c278
-rw-r--r--src/read.c34
-rw-r--r--src/vector.c35
-rw-r--r--src/vm.c682
-rwxr-xr-xtests/all.sh13
-rw-r--r--tests/bc/errors/33.txt2
-rw-r--r--tests/bcl.c5
-rw-r--r--tests/dc/scripts/all.txt1
-rw-r--r--tests/dc/scripts/no_clamp.dc29
-rw-r--r--tests/dc/scripts/no_clamp.txt29
-rwxr-xr-xtests/error.sh46
-rwxr-xr-xtests/other.sh49
-rwxr-xr-xtests/script.sh8
-rwxr-xr-xtests/test.sh8
-rw-r--r--vs/bc.vcxproj16
92 files changed, 9341 insertions, 5287 deletions
diff --git a/.clang-format b/.clang-format
deleted file mode 100644
index 845db62a72e6..000000000000
--- a/.clang-format
+++ /dev/null
@@ -1,152 +0,0 @@
----
-Language: Cpp
-# BasedOnStyle: LLVM
-AccessModifierOffset: 1
-AlignAfterOpenBracket: Align
-AlignConsecutiveAssignments: false
-AlignConsecutiveBitFields: true
-AlignConsecutiveDeclarations: false
-AlignConsecutiveMacros: false
-AlignEscapedNewlines: Left
-AlignOperands: Align
-AlignTrailingComments: true
-AllowAllArgumentsOnNextLine: false
-AllowAllConstructorInitializersOnNextLine: true
-AllowAllParametersOfDeclarationOnNextLine: false
-AllowShortBlocksOnASingleLine: Never
-AllowShortCaseLabelsOnASingleLine: false
-AllowShortEnumsOnASingleLine: false
-AllowShortFunctionsOnASingleLine: None
-AllowShortIfStatementsOnASingleLine: AllIfsAndElse
-AllowShortLambdasOnASingleLine: Empty
-AllowShortLoopsOnASingleLine: false
-AlwaysBreakAfterReturnType: All
-AlwaysBreakBeforeMultilineStrings: false
-AlwaysBreakTemplateDeclarations: true
-#AttributeMacros: []
-BinPackArguments: true
-BinPackParameters: true
-#BitFieldColonSpacing: Both
-BreakBeforeBraces: Custom
-BraceWrapping:
- AfterCaseLabel: true
- AfterClass: true
- AfterControlStatement: true
- AfterEnum: true
- AfterFunction: true
- AfterNamespace: true
- AfterObjCDeclaration: true
- AfterStruct: true
- AfterUnion: true
- AfterExternBlock: true
- BeforeCatch: true
- BeforeElse: true
- BeforeLambdaBody: false
- BeforeWhile: true
- IndentBraces: false
- SplitEmptyFunction: false
- SplitEmptyRecord: false
- SplitEmptyNamespace: false
-BreakAfterJavaFieldAnnotations: true
-BreakBeforeBinaryOperators: None
-#BreakBeforeConceptDeclarations: true
-BreakBeforeInheritanceComma: false
-BreakBeforeTernaryOperators: false
-BreakConstructorInitializers: AfterColon
-BreakInheritanceList: AfterColon
-BreakStringLiterals: false
-ColumnLimit: 80
-CommentPragmas: '^ IWYU pragma:'
-CompactNamespaces: false
-ConstructorInitializerAllOnOneLineOrOnePerLine: false
-ConstructorInitializerIndentWidth: 4
-ContinuationIndentWidth: 4
-Cpp11BracedListStyle: false
-DeriveLineEnding: false
-DerivePointerAlignment: false
-DisableFormat: false
-ExperimentalAutoDetectBinPacking: false
-FixNamespaceComments: true
-ForEachMacros:
- - foreach
- - Q_FOREACH
- - BOOST_FOREACH
-IncludeBlocks: Regroup
-IncludeCategories:
- - Regex: '^<(sys|arpa|net|netinet)/.*\.h>'
- Priority: 2
- - Regex: '^<(args|bc|bcl|dc|file|history|lang|lex|library|num|opt|parse|program|rand|read|status|vector|version|vm)\.h>'
- Priority: 3
- - Regex: '^<.*\.h>'
- Priority: 0
- - Regex: '^<.*>'
- Priority: 1
-IncludeIsMainRegex: '(Test)?$'
-IncludeIsMainSourceRegex: ''
-IndentCaseLabels: true
-IndentExternBlock: NoIndent
-IndentGotoLabels: false
-IndentPPDirectives: None
-#IndentPragmas: false
-#IndentRequires: true
-IndentWidth: 4
-IndentWrappedFunctionNames: false
-InsertTrailingCommas: None
-JavaImportGroups: []
-JavaScriptQuotes: Double
-JavaScriptWrapImports: true
-KeepEmptyLinesAtTheStartOfBlocks: false
-Language: Cpp
-MacroBlockBegin: ''
-MacroBlockEnd: ''
-MaxEmptyLinesToKeep: 1
-NamespaceIndentation: None
-NamespaceMacros: []
-ObjCBinPackProtocolList: Always
-ObjCBlockIndentWidth: 4
-ObjCBreakBeforeNestedBlockParam: true
-ObjCSpaceAfterProperty: true
-ObjCSpaceBeforeProtocolList: true
-PenaltyBreakAssignment: 1000
-PenaltyBreakBeforeFirstCallParameter: 429496720
-PenaltyBreakComment: 300
-PenaltyBreakFirstLessLess: 42949672
-PenaltyBreakString: 10000
-PenaltyBreakTemplateDeclaration: 10
-PenaltyExcessCharacter: 42949672
-PenaltyIndentedWhitespace: 1
-PenaltyReturnTypeOnItsOwnLine: 60
-PointerAlignment: Left
-#RawStringFormats:
-# This is used to get spaces around a bitwise and operator.
-ReferenceAlignment: Middle
-ReflowComments: true
-SortIncludes: false
-SortUsingDeclarations: true
-SpaceAfterCStyleCast: true
-SpaceAfterLogicalNot: false
-SpaceAfterTemplateKeyword: true
-#SpaceAroundPointerQualifiers: Default
-SpaceBeforeAssignmentOperators: true
-SpaceBeforeCpp11BracedList: true
-SpaceBeforeCtorInitializerColon: true
-SpaceBeforeInheritanceColon: true
-SpaceBeforeParens: ControlStatements
-SpaceBeforeRangeBasedForLoopColon: true
-SpaceBeforeSquareBrackets: false
-SpaceInEmptyBlock: false
-SpaceInEmptyParentheses: false
-SpacesBeforeTrailingComments: 1
-SpacesInAngles: false
-SpacesInContainerLiterals: true
-SpacesInCStyleCastParentheses: false
-SpacesInConditionalStatement: false
-SpacesInParentheses: false
-SpacesInSquareBrackets: false
-Standard: Latest
-TabWidth: 4
-TypenameMacros: []
-UseCRLF: false
-UseTab: ForIndentation
-WhitespaceSensitiveMacros: []
-...
diff --git a/.clang-tidy b/.clang-tidy
deleted file mode 100644
index 04e13de763a2..000000000000
--- a/.clang-tidy
+++ /dev/null
@@ -1,43 +0,0 @@
-Checks: 'clang-diagnostic-*,clang-analyzer-*'
-WarningsAsErrors: 'clang-diagnostic-*,clang-analyzer-*'
-HeaderFilterRegex: ''
-AnalyzeTemporaryDtors: false
-FormatStyle: file
-CheckOptions:
- - key: llvm-else-after-return.WarnOnConditionVariables
- value: 'false'
- - key: modernize-loop-convert.MinConfidence
- value: reasonable
- - key: modernize-replace-auto-ptr.IncludeStyle
- value: llvm
- - key: cert-str34-c.DiagnoseSignedUnsignedCharComparisons
- value: 'false'
- - key: google-readability-namespace-comments.ShortNamespaceLines
- value: '10'
- - key: cert-oop54-cpp.WarnOnlyIfThisHasSuspiciousField
- value: 'false'
- - key: cppcoreguidelines-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic
- value: 'true'
- - key: cert-dcl16-c.NewSuffixes
- value: 'L;LL;LU;LLU'
- - key: google-readability-braces-around-statements.ShortStatementLines
- value: '1'
- - key: modernize-pass-by-value.IncludeStyle
- value: llvm
- - key: google-readability-namespace-comments.SpacesBeforeComments
- value: '2'
- - key: modernize-loop-convert.MaxCopySize
- value: '16'
- - key: cppcoreguidelines-explicit-virtual-functions.IgnoreDestructors
- value: 'true'
- - key: modernize-use-nullptr.NullMacros
- value: 'NULL'
- - key: llvm-qualified-auto.AddConstToQualified
- value: 'false'
- - key: modernize-loop-convert.NamingStyle
- value: CamelCase
- - key: llvm-else-after-return.WarnOnUnfixable
- value: 'false'
- - key: google-readability-function-size.StatementThreshold
- value: '800'
-...
diff --git a/.gitignore b/.gitignore
deleted file mode 100644
index 8d0c7d33935c..000000000000
--- a/.gitignore
+++ /dev/null
@@ -1,86 +0,0 @@
-*.config
-*.creator
-*.files
-*.includes
-*.creator.user*
-*.cflags
-*.cxxflags
-bin/*bc
-bin/*bc.exe
-bin/*dc
-bin/*dc.exe
-bin/bcl
-bc.old
-*.o
-*.a
-.log_*.txt
-.test.txt
-.math.txt
-.results.txt
-.ops.txt
-manuals/bc.1
-manuals/bc.1.ronn
-manuals/bc.1.md
-manuals/dc.1
-manuals/dc.1.ronn
-manuals/dc.1.md
-gen/strgen
-lib.c
-lib2.c
-lib3.c
-bc_help.c
-dc_help.c
-config.mak
-timeconst.bc
-Makefile
-bcl.pc
-
-build/*
-tests/fuzzing/bc_outputs1/*
-tests/fuzzing/bc_outputs2/*
-tests/fuzzing/bc_outputs3/*
-tests/fuzzing/dc_outputs/*
-tests/bc_outputs/*
-tests/dc_outputs/*
-
-.gdb_history
-
-# Ignore the generated test files
-parse.txt
-parse_results.txt
-print.txt
-print_results.txt
-bessel.txt
-bessel_results.txt
-prime.txt
-strings2.txt
-strings2_results.txt
-tests/bc/scripts/add.txt
-tests/bc/scripts/divide.txt
-tests/bc/scripts/multiply.txt
-tests/bc/scripts/subtract.txt
-tests/bc/scripts/strings2.txt
-benchmarks/bc/*.txt
-benchmarks/dc/*.txt
-scripts/ministat
-scripts/bitfuncgen
-perf.data
-perf.data.old
-*.gcda
-*.gcno
-*.gcov
-*.html
-*.profraw
-
-core.*
-
-cscope*.out
-tags
-
-*.vcxproj.user
-vs/.vs/*
-vs/bin/*
-vs/lib/*
-vs/src2/*
-vs/tests/*.txt
-vs/tests/*.exe
diff --git a/Makefile.in b/Makefile.in
index 041b9b014cfd..eb607dca0a1f 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -55,7 +55,7 @@ HISTORY_HEADERS = $(INCDIR)/history.h
EXTRA_MATH_HEADERS = $(INCDIR)/rand.h
LIBRARY_HEADERS = $(INCDIR)/bcl.h $(INCDIR)/library.h
-GEN_DIR = gen
+GEN_DIR = %%GEN_DIR%%
GEN = %%GEN%%
GEN_EXEC = $(GEN_DIR)/$(GEN)
GEN_C = $(GENDIR)/$(GEN).c
@@ -146,7 +146,6 @@ BC_ENABLE_HISTORY = %%HISTORY%%
BC_ENABLE_EXTRA_MATH_NAME = BC_ENABLE_EXTRA_MATH
BC_ENABLE_EXTRA_MATH = %%EXTRA_MATH%%
BC_ENABLE_NLS = %%NLS%%
-BC_LONG_BIT = %%LONG_BIT%%
BC_EXCLUDE_EXTRA_MATH = %%EXCLUDE_EXTRA_MATH%%
BC_ENABLE_AFL = %%FUZZ%%
@@ -161,6 +160,8 @@ BC_DEFAULT_PROMPT = %%BC_DEFAULT_PROMPT%%
DC_DEFAULT_PROMPT = %%DC_DEFAULT_PROMPT%%
BC_DEFAULT_EXPR_EXIT = %%BC_DEFAULT_EXPR_EXIT%%
DC_DEFAULT_EXPR_EXIT = %%DC_DEFAULT_EXPR_EXIT%%
+BC_DEFAULT_DIGIT_CLAMP = %%BC_DEFAULT_DIGIT_CLAMP%%
+DC_DEFAULT_DIGIT_CLAMP = %%DC_DEFAULT_DIGIT_CLAMP%%
RM = rm
MKDIR = mkdir
@@ -192,12 +193,14 @@ BC_DEFS1 = -DBC_DEFAULT_SIGINT_RESET=$(BC_DEFAULT_SIGINT_RESET)
BC_DEFS2 = -DBC_DEFAULT_TTY_MODE=$(BC_DEFAULT_TTY_MODE)
BC_DEFS3 = -DBC_DEFAULT_PROMPT=$(BC_DEFAULT_PROMPT)
BC_DEFS4 = -DBC_DEFAULT_EXPR_EXIT=$(BC_DEFAULT_EXPR_EXIT)
-BC_DEFS = $(BC_DEFS0) $(BC_DEFS1) $(BC_DEFS2) $(BC_DEFS3) $(BC_DEFS4)
+BC_DEFS5 = -DBC_DEFAULT_DIGIT_CLAMP=$(BC_DEFAULT_DIGIT_CLAMP)
+BC_DEFS = $(BC_DEFS0) $(BC_DEFS1) $(BC_DEFS2) $(BC_DEFS3) $(BC_DEFS4) $(BC_DEFS5)
DC_DEFS1 = -DDC_DEFAULT_SIGINT_RESET=$(DC_DEFAULT_SIGINT_RESET)
DC_DEFS2 = -DDC_DEFAULT_TTY_MODE=$(DC_DEFAULT_TTY_MODE)
DC_DEFS3 = -DDC_DEFAULT_PROMPT=$(DC_DEFAULT_PROMPT)
DC_DEFS4 = -DDC_DEFAULT_EXPR_EXIT=$(DC_DEFAULT_EXPR_EXIT)
-DC_DEFS = $(DC_DEFS1) $(DC_DEFS2) $(DC_DEFS3) $(DC_DEFS4)
+DC_DEFS5 = -DDC_DEFAULT_DIGIT_CLAMP=$(DC_DEFAULT_DIGIT_CLAMP)
+DC_DEFS = $(DC_DEFS1) $(DC_DEFS2) $(DC_DEFS3) $(DC_DEFS4) $(DC_DEFS5)
CPPFLAGS1 = -D$(BC_ENABLED_NAME)=$(BC_ENABLED) -D$(DC_ENABLED_NAME)=$(DC_ENABLED)
CPPFLAGS2 = $(CPPFLAGS1) -I$(INCDIR)/ -DBUILD_TYPE=$(BC_BUILD_TYPE) %%LONG_BIT_DEFINE%%
@@ -299,11 +302,6 @@ help:
@printf ' time_test_dc runs the dc test suite, displaying times for some things\n'
@printf ' timeconst runs the test on the Linux timeconst.bc script,\n'
@printf ' if it exists and bc has been built\n'
- @printf ' valgrind runs the test suite through valgrind\n'
- @printf ' valgrind_bc runs the bc test suite, if bc has been built,\n'
- @printf ' through valgrind\n'
- @printf ' valgrind_dc runs the dc test suite, if dc has been built,\n'
- @printf ' through valgrind\n'
run_all_tests: bc_all_tests timeconst_all_tests dc_all_tests
@@ -502,10 +500,10 @@ test_history_header:
@printf '$(TEST_STARS)\n\nRunning history tests...\n\n'
library_test: $(LIBBC)
- $(CC) $(CFLAGS) $(BCL_TEST_C) $(LIBBC) -o $(BCL_TEST)
+ $(CC) $(CFLAGS) -lpthread $(BCL_TEST_C) $(LIBBC) -o $(BCL_TEST)
test_library: library_test
- $(BCL_TEST)
+ %%BCL_TEST_EXEC%%
karatsuba:
%%KARATSUBA%%
diff --git a/NEWS.md b/NEWS.md
index 543507c717df..5ba1020f85c4 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -1,5 +1,53 @@
# News
+## 6.0.2
+
+This is a production release that fixes two bugs:
+
+* The `-l` option overrode the `-S` option.
+* A double-free and crash when sending a `SIGINT` while executing expressions
+ given on the command-line.
+
+## 6.0.1
+
+This is a production release that fixes memory bugs and memory leaks in `bcl`.
+
+Users that do not use `bcl` (use only `bc` and/or `dc`) do ***NOT*** need to
+upgrade.
+
+These happened because I was unaware that the `bcl` test was not hooked into the
+Valgrind test infrastructure. Then, when I ran the release script, which tests
+everything under Valgrind (or so I thought), it caught nothing, and I thought it
+was safe.
+
+But it was not.
+
+Nevertheless, I have now run it under Valgrind and fixed all of the memory bugs
+(caused by not using `memset()` where I should have but previously didn't have
+to) and memory leaks.
+
+## 6.0.0
+
+This is a production release that fixes an oversight in the `bc` parser (that
+sometimes caused the wrong error message) and adds a feature for compatibility
+with the BSD `bc` and `dc`: turning off digit clamping when parsing numbers.
+
+The default for clamping can be set during the build (see the [build
+manual][13]), it can be set with the `BC_DIGIT_CLAMP` and `DC_DIGIT_CLAMP`
+environment variables, and it can be set with the `-c` and `-C` command-line
+options.
+
+Turning off clamping was also added to the `bcl` library.
+
+In addition, signal handling was removed from the `bcl` library in order to add
+the capability for multi-threading. This required a major version bump. I
+apologize to all library users (I don't know of any), but signals and threads do
+not play well together.
+
+To help with building, a convenience option (`-p`) to `configure.sh` was added
+to build a `bc` and `dc` that is by default compatible with either the BSD `bc`
+and `dc` or the GNU `bc` and `dc`.
+
## 5.3.3
This is a production release that fixes a build problem in the FreeBSD base
diff --git a/configure.sh b/configure.sh
index 5dc4853fbb47..e82c21817a6c 100755
--- a/configure.sh
+++ b/configure.sh
@@ -43,7 +43,7 @@ usage() {
_usage_val=1
- printf "%s\n\n" "$1"
+ printf '%s\n\n' "$1"
else
_usage_val=0
@@ -52,18 +52,25 @@ usage() {
printf 'usage:\n'
printf ' %s -h\n' "$script"
printf ' %s --help\n' "$script"
- printf ' %s [-a|-bD|-dB|-c] [-CeEfgGHlmMNrtTvz] [-O OPT_LEVEL] [-k KARATSUBA_LEN]\\\n' "$script"
- printf ' [-s SETTING] [-S SETTING]\n'
+ printf ' %s [-a|-bD|-dB|-c] [-CeEfgGHilmMNPrtTvz] [-O OPT_LEVEL] [-k KARATSUBA_LEN]\\\n' "$script"
+ printf ' [-s SETTING] [-S SETTING] [-p TYPE]\n'
printf ' %s \\\n' "$script"
printf ' [--library|--bc-only --disable-dc|--dc-only --disable-bc|--coverage] \\\n'
printf ' [--force --debug --disable-extra-math --disable-generated-tests] \\\n'
printf ' [--disable-history --disable-man-pages --disable-nls --disable-strip] \\\n'
- printf ' [--enable-editline] [--enable-readline] \\\n'
- printf ' [--install-all-locales] [--opt=OPT_LEVEL] \\\n'
- printf ' [--karatsuba-len=KARATSUBA_LEN] \\\n'
+ printf ' [--enable-editline] [--enable-readline] [--enable-internal-history] \\\n'
+ printf ' [--disable-problematic-tests] [--install-all-locales] \\\n'
+ printf ' [--opt=OPT_LEVEL] [--karatsuba-len=KARATSUBA_LEN] \\\n'
printf ' [--set-default-on=SETTING] [--set-default-off=SETTING] \\\n'
+ printf ' [--predefined-build-type=TYPE] \\\n'
printf ' [--prefix=PREFIX] [--bindir=BINDIR] [--datarootdir=DATAROOTDIR] \\\n'
printf ' [--datadir=DATADIR] [--mandir=MANDIR] [--man1dir=MAN1DIR] \\\n'
+ printf ' [--man3dir=MAN3DIR]\n'
+
+ if [ "$_usage_val" -ne 0 ]; then
+ exit
+ fi
+
printf '\n'
printf ' -a, --library\n'
printf ' Build the libbcl instead of the programs. This is meant to be used with\n'
@@ -90,9 +97,9 @@ usage() {
printf ' are specified too.\n'
printf ' -e, --enable-editline\n'
printf ' Enable the use of libedit/editline. This is meant for those users that\n'
- printf ' want vi-like or Emacs-like behavior in history.This option is ignored if\n'
- printf ' history is disabled. It is an error if this option is enabled when the\n'
- printf ' -r/--enable-readline option is enabled.\n'
+ printf ' want vi-like or Emacs-like behavior in history. This option is ignored\n'
+ printf ' if history is disabled. If the -r or -i options are given with this\n'
+ printf ' option, the last occurrence of all of the three is used.\n'
printf ' -E, --disable-extra-math\n'
printf ' Disable extra math. This includes: "$" operator (truncate to integer),\n'
printf ' "@" operator (set number of decimal places), and r(x, p) (rounding\n'
@@ -114,6 +121,11 @@ usage() {
printf ' Print this help message and exit.\n'
printf ' -H, --disable-history\n'
printf ' Disable history.\n'
+ printf ' -i, --enable-internal-history\n'
+ printf ' Enable the internal history implementation and do not depend on either\n'
+ printf ' editline or readline. This option is ignored if history is disabled.\n'
+ printf ' If this option is given along with -e and -r, the last occurrence of\n'
+ printf ' all of the three is used.\n'
printf ' -k KARATSUBA_LEN, --karatsuba-len KARATSUBA_LEN\n'
printf ' Set the karatsuba length to KARATSUBA_LEN (default is 64).\n'
printf ' It is an error if KARATSUBA_LEN is not a number or is less than 16.\n'
@@ -127,15 +139,30 @@ usage() {
printf ' Disable installing manpages.\n'
printf ' -N, --disable-nls\n'
printf ' Disable POSIX locale (NLS) support.\n'
+ printf ' ***WARNING***: Locales ignore the prefix because they *must* be\n'
+ printf ' installed at a fixed location to work at all. If you do not want that\n'
+ printf ' to happen, you must disable locales (NLS) completely.\n'
printf ' -O OPT_LEVEL, --opt OPT_LEVEL\n'
printf ' Set the optimization level. This can also be included in the CFLAGS,\n'
printf ' but it is provided, so maintainers can build optimized debug builds.\n'
printf ' This is passed through to the compiler, so it must be supported.\n'
+ printf ' -p TYPE, --predefined-build-type=TYPE\n'
+ printf ' Sets a given predefined build type with specific defaults. This is for\n'
+ printf ' easy setting of predefined builds. For example, to get a build that\n'
+ printf ' acts like the GNU bc by default, TYPE should be "GNU" (without the\n'
+ printf ' quotes) This option *must* come before any others that might change the\n'
+ printf ' build options. Currently supported values for TYPE include: "BSD" (for\n'
+ printf ' matching the BSD bc and BSD dc), "GNU" (for matching the GNU bc and\n'
+ printf ' dc), and "GDH" (for the preferred build of the author, Gavin D. Howard).\n'
+ printf ' This will also automatically enable a release build.\n'
+ printf ' -P, --disable-problematic-tests\n'
+ printf ' Disables problematic tests. These tests usually include tests that\n'
+ printf ' can cause a SIGKILL because of too much memory usage.\n'
printf ' -r, --enable-readline\n'
printf ' Enable the use of libreadline/readline. This is meant for those users\n'
- printf ' that want vi-like or Emacs-like behavior in history.This option is\n'
- printf ' ignored if history is disabled. It is an error if this option is\n'
- printf ' enabled when the -e/--enable-editline option is enabled.\n'
+ printf ' that want vi-like or Emacs-like behavior in history. This option is\n'
+ printf ' ignored if history is disabled. If this option is given along with -e\n'
+ printf ' and -r, the last occurrence of all of the three is used.\n'
printf ' -s SETTING, --set-default-on SETTING\n'
printf ' Set the default named by SETTING to on. See below for possible values\n'
printf ' for SETTING. For multiple instances of the -s or -S for the the same\n'
@@ -157,6 +184,9 @@ usage() {
printf ' The prefix to install to. Overrides "$PREFIX" if it exists.\n'
printf ' If PREFIX is "/usr", install path will be "/usr/bin".\n'
printf ' Default is "/usr/local".\n'
+ printf ' ***WARNING***: Locales ignore the prefix because they *must* be\n'
+ printf ' installed at a fixed location to work at all. If you do not want that to\n'
+ printf ' happen, you must disable locales (NLS) completely.\n'
printf ' --bindir BINDIR\n'
printf ' The directory to install binaries in. Overrides "$BINDIR" if it exists.\n'
printf ' Default is "$PREFIX/bin".\n'
@@ -202,6 +232,9 @@ usage() {
printf ' LDFLAGS Linker flags. Default is "".\n'
printf ' PREFIX The prefix to install to. Default is "/usr/local".\n'
printf ' If PREFIX is "/usr", install path will be "/usr/bin".\n'
+ printf ' ***WARNING***: Locales ignore the prefix because they *must* be\n'
+ printf ' installed at a fixed location to work at all. If you do not\n'
+ printf ' want that to happen, you must disable locales (NLS) completely.\n'
printf ' BINDIR The directory to install binaries in. Default is "$PREFIX/bin".\n'
printf ' INCLUDEDIR The directory to install header files in. Default is\n'
printf ' "$PREFIX/include".\n'
@@ -317,6 +350,20 @@ usage() {
printf '| | given with the -e or | | |\n'
printf '| | -f options. | | |\n'
printf '| --------------- | -------------------- | ------------ | -------------------- |\n'
+ printf '| bc.digit_clamp | Whether to have bc | 0 | BC_DIGIT_CLAMP |\n'
+ printf '| | clamp digits that | | |\n'
+ printf '| | are greater than or | | |\n'
+ printf '| | equal to the current | | |\n'
+ printf '| | ibase when parsing | | |\n'
+ printf '| | numbers. | | |\n'
+ printf '| --------------- | -------------------- | ------------ | -------------------- |\n'
+ printf '| dc.digit_clamp | Whether to have dc | 0 | DC_DIGIT_CLAMP |\n'
+ printf '| | clamp digits that | | |\n'
+ printf '| | are greater than or | | |\n'
+ printf '| | equal to the current | | |\n'
+ printf '| | ibase when parsing | | |\n'
+ printf '| | numbers. | | |\n'
+ printf '| --------------- | -------------------- | ------------ | -------------------- |\n'
printf '\n'
printf 'These settings are not meant to be changed on a whim. They are meant to ensure\n'
printf 'that this bc and dc will conform to the expectations of the user on each\n'
@@ -413,7 +460,7 @@ find_src_files() {
fi
- _find_src_files_files=$(find "$scriptdir/src/" -depth -name "*.c" -print)
+ _find_src_files_files=$(find "$scriptdir/src/" -depth -name "*.c" -print | LC_ALL=C sort)
_find_src_files_result=""
@@ -515,7 +562,7 @@ gen_std_tests() {
fi
- printf 'test_%s_%s:\n\t@export BC_TEST_OUTPUT_DIR="%s/tests"; sh \$(TESTSDIR)/test.sh %s %s %s %s %s\n\n' \
+ printf 'test_%s_%s:\n\t@export BC_TEST_OUTPUT_DIR="%s/tests"; sh $(TESTSDIR)/test.sh %s %s %s %s %s\n\n' \
"$_gen_std_tests_name" "$_gen_std_tests_t" "$builddir" "$_gen_std_tests_name" \
"$_gen_std_tests_t" "$generate_tests" "$time_tests" \
"$*" >> "Makefile"
@@ -555,9 +602,9 @@ gen_err_tests() {
for _gen_err_tests_t in $_gen_err_tests_fs; do
- printf 'test_%s_error_%s:\n\t@export BC_TEST_OUTPUT_DIR="%s/tests"; sh \$(TESTSDIR)/error.sh %s %s %s\n\n' \
+ printf 'test_%s_error_%s:\n\t@export BC_TEST_OUTPUT_DIR="%s/tests"; sh $(TESTSDIR)/error.sh %s %s %s %s\n\n' \
"$_gen_err_tests_name" "$_gen_err_tests_t" "$builddir" "$_gen_err_tests_name" \
- "$_gen_err_tests_t" "$*" >> "Makefile"
+ "$_gen_err_tests_t" "$problematic_tests" "$*" >> "Makefile"
done
@@ -609,7 +656,7 @@ gen_script_tests() {
_gen_script_tests_b=$(basename "$_gen_script_tests_f" ".${_gen_script_tests_name}")
- printf 'test_%s_script_%s:\n\t@export BC_TEST_OUTPUT_DIR="%s/tests"; sh \$(TESTSDIR)/script.sh %s %s %s 1 %s %s %s\n\n' \
+ printf 'test_%s_script_%s:\n\t@export BC_TEST_OUTPUT_DIR="%s/tests"; sh $(TESTSDIR)/script.sh %s %s %s 1 %s %s %s\n\n' \
"$_gen_script_tests_name" "$_gen_script_tests_b" "$builddir" "$_gen_script_tests_name" \
"$_gen_script_tests_f" "$_gen_script_tests_extra_math" "$_gen_script_tests_generate" \
"$_gen_script_tests_time" "$*" >> "Makefile"
@@ -639,11 +686,129 @@ set_default() {
dc.prompt) dc_default_prompt="$_set_default_on" ;;
bc.expr_exit) bc_default_expr_exit="$_set_default_on";;
dc.expr_exit) dc_default_expr_exit="$_set_default_on";;
+ bc.digit_clamp) bc_default_digit_clamp="$_set_default_on";;
+ dc.digit_clamp) dc_default_digit_clamp="$_set_default_on";;
?) usage "Invalid setting: $_set_default_name" ;;
esac
}
+predefined_build() {
+
+ _predefined_build_type="$1"
+ shift
+
+ # The reason that the variables that are being set do not have the same
+ # non-collision avoidance that the other variables do is that we *do* want
+ # the settings of these variables to leak out of the function. They adjust
+ # the settings outside of the function.
+ case "$_predefined_build_type" in
+
+ BSD)
+ bc_only=0
+ dc_only=0
+ coverage=0
+ debug=0
+ optimization="3"
+ hist=1
+ hist_impl="editline"
+ extra_math=1
+ generate_tests=0
+ install_manpages=0
+ nls=1
+ force=0
+ strip_bin=1
+ all_locales=0
+ library=0
+ fuzz=0
+ time_tests=0
+ vg=0
+ memcheck=0
+ clean=1
+ bc_default_banner=0
+ bc_default_sigint_reset=1
+ dc_default_sigint_reset=1
+ bc_default_tty_mode=1
+ dc_default_tty_mode=0
+ bc_default_prompt=""
+ dc_default_prompt=""
+ bc_default_expr_exit=1
+ dc_default_expr_exit=1
+ bc_default_digit_clamp=0
+ dc_default_digit_clamp=0;;
+
+ GNU)
+ bc_only=0
+ dc_only=0
+ coverage=0
+ debug=0
+ optimization="3"
+ hist=1
+ hist_impl="internal"
+ extra_math=1
+ generate_tests=1
+ install_manpages=1
+ nls=1
+ force=0
+ strip_bin=1
+ all_locales=0
+ library=0
+ fuzz=0
+ time_tests=0
+ vg=0
+ memcheck=0
+ clean=1
+ bc_default_banner=1
+ bc_default_sigint_reset=1
+ dc_default_sigint_reset=0
+ bc_default_tty_mode=1
+ dc_default_tty_mode=0
+ bc_default_prompt=""
+ dc_default_prompt=""
+ bc_default_expr_exit=1
+ dc_default_expr_exit=1
+ bc_default_digit_clamp=1
+ dc_default_digit_clamp=0;;
+
+ GDH)
+ CFLAGS="-flto -Weverything -Wno-padded -Wno-gnu-label-as-value -Werror -pedantic -std=c11"
+ bc_only=0
+ dc_only=0
+ coverage=0
+ debug=0
+ optimization="3"
+ hist=1
+ hist_impl="internal"
+ extra_math=1
+ generate_tests=1
+ install_manpages=1
+ nls=0
+ force=0
+ strip_bin=1
+ all_locales=0
+ library=0
+ fuzz=0
+ time_tests=0
+ vg=0
+ memcheck=0
+ clean=1
+ bc_default_banner=1
+ bc_default_sigint_reset=1
+ dc_default_sigint_reset=1
+ bc_default_tty_mode=1
+ dc_default_tty_mode=1
+ bc_default_prompt=""
+ dc_default_prompt=""
+ bc_default_expr_exit=0
+ dc_default_expr_exit=0
+ bc_default_digit_clamp=1
+ dc_default_digit_clamp=1;;
+
+ ?|'') usage "Invalid user build: \"$_predefined_build_type\". Accepted types are BSD, GNU, and GDH.";;
+
+ esac
+}
+
# Generates a list of script test targets that will be used as prerequisites for
# other targets.
#
@@ -677,8 +842,7 @@ coverage=0
karatsuba_len=32
debug=0
hist=1
-editline=0
-readline=0
+hist_impl="internal"
extra_math=1
optimization=""
generate_tests=1
@@ -693,6 +857,7 @@ time_tests=0
vg=0
memcheck=0
clean=1
+problematic_tests=1
# The empty strings are because they depend on TTY mode. If they are directly
# set, though, they will be integers. We test for empty strings later.
@@ -705,11 +870,13 @@ bc_default_prompt=""
dc_default_prompt=""
bc_default_expr_exit=1
dc_default_expr_exit=1
+bc_default_digit_clamp=0
+dc_default_digit_clamp=0
# getopts is a POSIX utility, but it cannot handle long options. Thus, the
# handling of long options is done by hand, and that's the reason that short and
# long options cannot be mixed.
-while getopts "abBcdDeEfgGhHk:lMmNO:rS:s:tTvz-" opt; do
+while getopts "abBcdDeEfgGhHik:lMmNO:p:PrS:s:tTvz-" opt; do
case "$opt" in
a) library=1 ;;
@@ -719,20 +886,23 @@ while getopts "abBcdDeEfgGhHk:lMmNO:rS:s:tTvz-" opt; do
C) clean=0 ;;
d) dc_only=1 ;;
D) bc_only=1 ;;
- e) editline=1 ;;
+ e) hist_impl="editline" ;;
E) extra_math=0 ;;
f) force=1 ;;
g) debug=1 ;;
G) generate_tests=0 ;;
h) usage ;;
H) hist=0 ;;
+ i) hist_impl="internal" ;;
k) karatsuba_len="$OPTARG" ;;
l) all_locales=1 ;;
m) memcheck=1 ;;
M) install_manpages=0 ;;
N) nls=0 ;;
O) optimization="$OPTARG" ;;
- r) readline=1 ;;
+ p) predefined_build "$OPTARG" ;;
+ P) problematic_tests=0 ;;
+ r) hist_impl="readline" ;;
S) set_default 0 "$OPTARG" ;;
s) set_default 1 "$OPTARG" ;;
t) time_tests=1 ;;
@@ -849,6 +1019,13 @@ while getopts "abBcdDeEfgGhHk:lMmNO:rS:s:tTvz-" opt; do
fi
set_default 0 "$1"
shift ;;
+ predefined-build-type=?*) predefined_build "$LONG_OPTARG" ;;
+ predefined-build-type)
+ if [ "$#" -lt 2 ]; then
+ usage "No argument given for '--$arg' option"
+ fi
+ predefined_build "$1"
+ shift ;;
disable-bc) dc_only=1 ;;
disable-dc) bc_only=1 ;;
disable-clean) clean=0 ;;
@@ -858,8 +1035,10 @@ while getopts "abBcdDeEfgGhHk:lMmNO:rS:s:tTvz-" opt; do
disable-man-pages) install_manpages=0 ;;
disable-nls) nls=0 ;;
disable-strip) strip_bin=0 ;;
- enable-editline) editline=1 ;;
- enable-readline) readline=1 ;;
+ disable-problematic-tests) problematic_tests=0 ;;
+ enable-editline) hist_impl="editline" ;;
+ enable-readline) hist_impl="readline" ;;
+ enable-internal-history) hist_impl="internal" ;;
enable-test-timing) time_tests=1 ;;
enable-valgrind) vg=1 ;;
enable-fuzz-mode) fuzz=1 ;;
@@ -875,12 +1054,16 @@ while getopts "abBcdDeEfgGhHk:lMmNO:rS:s:tTvz-" opt; do
usage "No arg allowed for --$arg option" ;;
disable-man-pages* | disable-nls* | disable-strip*)
usage "No arg allowed for --$arg option" ;;
+ disable-problematic-tests*)
+ usage "No arg allowed for --$arg option" ;;
enable-fuzz-mode* | enable-test-timing* | enable-valgrind*)
usage "No arg allowed for --$arg option" ;;
enable-memcheck* | install-all-locales*)
usage "No arg allowed for --$arg option" ;;
enable-editline* | enable-readline*)
usage "No arg allowed for --$arg option" ;;
+ enable-internal-history*)
+ usage "No arg allowed for --$arg option" ;;
'') break ;; # "--" terminates argument processing
* ) usage "Invalid option $LONG_OPTARG" ;;
esac
@@ -929,7 +1112,7 @@ if [ -z "${LONG_BIT+set}" ]; then
elif [ "$LONG_BIT" -lt 32 ]; then
usage "LONG_BIT is less than 32"
else
- LONG_BIT_DEFINE="-DBC_LONG_BIT=\$(BC_LONG_BIT)"
+ LONG_BIT_DEFINE="-DBC_LONG_BIT=$LONG_BIT"
fi
if [ -z "$CC" ]; then
@@ -1001,10 +1184,10 @@ executable="BC_EXEC"
tests="test_bc timeconst test_dc"
-bc_test="@export BC_TEST_OUTPUT_DIR=\"$builddir/tests\"; \$(TESTSDIR)/all.sh bc $extra_math 1 $generate_tests $time_tests \$(BC_EXEC)"
-bc_test_np="@export BC_TEST_OUTPUT_DIR=\"$builddir/tests\"; \$(TESTSDIR)/all.sh -n bc $extra_math 1 $generate_tests $time_tests \$(BC_EXEC)"
-dc_test="@export BC_TEST_OUTPUT_DIR=\"$builddir/tests\"; \$(TESTSDIR)/all.sh dc $extra_math 1 $generate_tests $time_tests \$(DC_EXEC)"
-dc_test_np="@export BC_TEST_OUTPUT_DIR=\"$builddir/tests\"; \$(TESTSDIR)/all.sh -n dc $extra_math 1 $generate_tests $time_tests \$(DC_EXEC)"
+bc_test="@export BC_TEST_OUTPUT_DIR=\"$builddir/tests\"; \$(TESTSDIR)/all.sh bc $extra_math 1 $generate_tests $problematic_tests $time_tests \$(BC_EXEC)"
+bc_test_np="@export BC_TEST_OUTPUT_DIR=\"$builddir/tests\"; \$(TESTSDIR)/all.sh -n bc $extra_math 1 $generate_tests $problematic_tests $time_tests \$(BC_EXEC)"
+dc_test="@export BC_TEST_OUTPUT_DIR=\"$builddir/tests\"; \$(TESTSDIR)/all.sh dc $extra_math 1 $generate_tests $problematic_tests $time_tests \$(DC_EXEC)"
+dc_test_np="@export BC_TEST_OUTPUT_DIR=\"$builddir/tests\"; \$(TESTSDIR)/all.sh -n dc $extra_math 1 $generate_tests $problematic_tests $time_tests \$(DC_EXEC)"
timeconst="@export BC_TEST_OUTPUT_DIR=\"$builddir/tests\"; \$(TESTSDIR)/bc/timeconst.sh \$(TESTSDIR)/bc/scripts/timeconst.bc \$(BC_EXEC)"
@@ -1014,9 +1197,11 @@ if [ "$vg" -ne 0 ]; then
debug=1
bc_test_exec='valgrind $(VALGRIND_ARGS) $(BC_EXEC)'
dc_test_exec='valgrind $(VALGRIND_ARGS) $(DC_EXEC)'
+ bcl_test_exec='valgrind $(VALGRIND_ARGS) $(BCL_TEST)'
else
bc_test_exec='$(BC_EXEC)'
dc_test_exec='$(DC_EXEC)'
+ bcl_test_exec='$(BCL_TEST)'
fi
test_bc_history_prereqs="test_bc_history_all"
@@ -1151,7 +1336,13 @@ if [ "$debug" -eq 1 ]; then
CFLAGS="-O0"
fi
- CFLAGS="-g $CFLAGS"
+ ccbase=$(basename "$CC")
+
+ if [ "$ccbase" = "clang" ]; then
+ CFLAGS="-gdwarf-4 $CFLAGS"
+ else
+ CFLAGS="-g $CFLAGS"
+ fi
else
@@ -1195,8 +1386,12 @@ else
destdir="DESTDIR = $DESTDIR"
fi
+# defprefix is for a warning about locales later.
if [ -z "${PREFIX+set}" ]; then
PREFIX="/usr/local"
+ defprefix=1
+else
+ defprefix=0
fi
if [ -z "${BINDIR+set}" ]; then
@@ -1230,7 +1425,7 @@ if [ -z "${PC_PATH+set}" ]; then
fi
# Set a default for the DATAROOTDIR. This is done if either manpages will be
-# installed, or locales are enabled because that's probably where NLS_PATH
+# installed, or locales are enabled because that's probably where NLSPATH
# points.
if [ "$install_manpages" -ne 0 ] || [ "$nls" -ne 0 ]; then
if [ -z "${DATAROOTDIR+set}" ]; then
@@ -1276,6 +1471,12 @@ if [ "$nls" -ne 0 ]; then
flags="$flags -DBC_ENABLE_EXTRA_MATH=$extra_math -I$scriptdir/include/"
flags="$flags -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700"
+ ccbase=$(basename "$CC")
+
+ if [ "$ccbase" = "clang" ]; then
+ flags="$flags -Wno-unreachable-code"
+ fi
+
"$CC" $CPPFLAGS $CFLAGS $flags -c "$scriptdir/src/vm.c" -o "./vm.o" > /dev/null 2>&1
err="$?"
@@ -1351,8 +1552,15 @@ fi
# Like the above tested locale support, this tests history.
if [ "$hist" -eq 1 ]; then
- if [ "$editline" -ne 0 ] && [ "$readline" -ne 0 ]; then
- usage "Must only enable one of readline or editline"
+ if [ "$hist_impl" = "editline" ]; then
+ editline=1
+ readline=0
+ elif [ "$hist_impl" = "readline" ]; then
+ editline=0
+ readline=1
+ else
+ editline=0
+ readline=0
fi
set +e
@@ -1387,6 +1595,11 @@ if [ "$hist" -eq 1 ]; then
set -e
+else
+
+ editline=0
+ readline=0
+
fi
# We have to disable the history tests if it is disabled or valgrind is on. Or
@@ -1430,7 +1643,7 @@ set +e
printf 'Testing for FreeBSD...\n'
flags="-DBC_TEST_FREEBSD -DBC_ENABLE_AFL=0"
-"$CC" $CPPFLAGS $CFLAGS $flags "-I$scriptdir/include" -E "$scriptdir/include/status.h" > /dev/null 2>&1
+"$CC" $CPPFLAGS $CFLAGS $flags "-I$scriptdir/include" -E "$scriptdir/src/vm.c" > /dev/null 2>&1
err="$?"
@@ -1453,13 +1666,20 @@ set +e
printf 'Testing for OpenBSD...\n'
flags="-DBC_TEST_OPENBSD -DBC_ENABLE_AFL=0"
-"$CC" $CPPFLAGS $CFLAGS $flags "-I$scriptdir/include" -E "$scriptdir/include/status.h" > /dev/null 2>&1
+"$CC" $CPPFLAGS $CFLAGS $flags "-I$scriptdir/include" -E "$scriptdir/src/vm.c" > /dev/null 2>&1
err="$?"
if [ "$err" -ne 0 ]; then
+
printf 'On OpenBSD. Using _BSD_SOURCE.\n\n'
bsd="-D_BSD_SOURCE"
+
+ # Readline errors on OpenBSD, for some weird reason.
+ if [ "$readline" -ne 0 ]; then
+ usage "Cannot use readline on OpenBSD"
+ fi
+
else
printf 'Not on OpenBSD.\n\n'
bsd=""
@@ -1475,10 +1695,12 @@ else
BC_LIB2_O=""
fi
+GEN_DIR="$scriptdir/gen"
+
# These lines set the appropriate targets based on whether `gen/strgen.c` or
# `gen/strgen.sh` is used.
GEN="strgen"
-GEN_EXEC_TARGET="\$(HOSTCC) \$(HOSTCFLAGS) -o \$(GEN_EXEC) \$(GEN_C)"
+GEN_EXEC_TARGET="\$(HOSTCC) -DBC_ENABLE_AFL=0 -I$scriptdir/include/ \$(HOSTCFLAGS) -o \$(GEN_EXEC) \$(GEN_C)"
CLEAN_PREREQS=" clean_gen clean_coverage"
if [ -z "${GEN_HOST+set}" ]; then
@@ -1620,7 +1842,7 @@ printf '\n'
printf 'BC_ENABLE_LIBRARY=%s\n\n' "$library"
printf 'BC_ENABLE_HISTORY=%s\n' "$hist"
printf 'BC_ENABLE_EXTRA_MATH=%s\n' "$extra_math"
-printf 'BC_ENABLE_NLS=%s\n' "$nls"
+printf 'BC_ENABLE_NLS=%s\n\n' "$nls"
printf 'BC_ENABLE_AFL=%s\n' "$fuzz"
printf '\n'
printf 'BC_NUM_KARATSUBA_LEN=%s\n' "$karatsuba_len"
@@ -1660,6 +1882,30 @@ printf 'bc.prompt=%s\n' "$bc_default_prompt"
printf 'dc.prompt=%s\n' "$dc_default_prompt"
printf 'bc.expr_exit=%s\n' "$bc_default_expr_exit"
printf 'dc.expr_exit=%s\n' "$dc_default_expr_exit"
+printf 'bc.digit_clamp=%s\n' "$bc_default_digit_clamp"
+printf 'dc.digit_clamp=%s\n' "$dc_default_digit_clamp"
+
+# This code outputs a warning. The warning is to not surprise users when locales
+# are installed outside of the prefix. This warning is suppressed when the
+# default prefix is used, as well, so as not to panic users just installing by
+# hand. I believe this will be okay because NLSPATH is usually in /usr and the
+# default prefix is /usr/local, so they'll be close that way.
+if [ "$nls" -ne 0 ] && [ "${NLSPATH#$PREFIX}" = "${NLSPATH}" ] && [ "$defprefix" -eq 0 ]; then
+ printf '\n********************************************************************************\n\n'
+ printf 'WARNING: Locales will *NOT* be installed in $PREFIX (%s).\n' "$PREFIX"
+ printf '\n'
+ printf ' This is because they *MUST* be installed at a fixed location to even\n'
+ printf ' work, and that fixed location is $NLSPATH (%s).\n' "$NLSPATH"
+ printf '\n'
+ printf ' This location is *outside* of $PREFIX. If you do not wish to install\n'
+ printf ' locales outside of $PREFIX, you must disable NLS with the -N or the\n'
+ printf ' --disable-nls options.\n'
+ printf '\n'
+ printf ' The author apologizes for the inconvenience, but the need to install\n'
+ printf ' the locales at a fixed location is mandated by POSIX, and it is not\n'
+ printf ' possible for the author to change that requirement.\n'
+ printf '\n********************************************************************************\n'
+fi
# This is where the real work begins. This is the point at which the Makefile.in
# template is edited and output to the Makefile.
@@ -1712,6 +1958,8 @@ contents=$(replace "$contents" "DC_SCRIPT_TESTS" "$dc_script_tests")
contents=$(replace "$contents" "DC_ERROR_TESTS" "$dc_err_tests")
contents=$(replace "$contents" "DC_TEST_EXEC" "$dc_test_exec")
+contents=$(replace "$contents" "BCL_TEST_EXEC" "$bcl_test_exec")
+
contents=$(replace "$contents" "BUILD_TYPE" "$manpage_args")
contents=$(replace "$contents" "EXCLUDE_EXTRA_MATH" "$exclude_extra_math")
@@ -1787,9 +2035,9 @@ contents=$(replace "$contents" "TIMECONST" "$timeconst")
contents=$(replace "$contents" "KARATSUBA" "$karatsuba")
contents=$(replace "$contents" "KARATSUBA_TEST" "$karatsuba_test")
-contents=$(replace "$contents" "LONG_BIT" "$LONG_BIT")
contents=$(replace "$contents" "LONG_BIT_DEFINE" "$LONG_BIT_DEFINE")
+contents=$(replace "$contents" "GEN_DIR" "$GEN_DIR")
contents=$(replace "$contents" "GEN" "$GEN")
contents=$(replace "$contents" "GEN_EXEC_TARGET" "$GEN_EXEC_TARGET")
contents=$(replace "$contents" "CLEAN_PREREQS" "$CLEAN_PREREQS")
@@ -1806,6 +2054,8 @@ contents=$(replace "$contents" "BC_DEFAULT_PROMPT" "$bc_default_prompt")
contents=$(replace "$contents" "DC_DEFAULT_PROMPT" "$dc_default_prompt")
contents=$(replace "$contents" "BC_DEFAULT_EXPR_EXIT" "$bc_default_expr_exit")
contents=$(replace "$contents" "DC_DEFAULT_EXPR_EXIT" "$dc_default_expr_exit")
+contents=$(replace "$contents" "BC_DEFAULT_DIGIT_CLAMP" "$bc_default_digit_clamp")
+contents=$(replace "$contents" "DC_DEFAULT_DIGIT_CLAMP" "$dc_default_digit_clamp")
# Do the first print to the Makefile.
printf '%s\n%s\n\n' "$contents" "$SRC_TARGETS" > "Makefile"
diff --git a/gen/bc_help.txt b/gen/bc_help.txt
index 7189d5bae723..db34e6daef95 100644
--- a/gen/bc_help.txt
+++ b/gen/bc_help.txt
@@ -62,6 +62,29 @@ This bc has three differences to the GNU bc:
This bc also implements the dot (.) extension of the BSD bc.
Options:
+
+ -C --no-digit-clamp
+
+ Disables clamping of digits that are larger than or equal to the current
+ ibase when parsing numbers.
+
+ This means that the value added to a number from a digit is always that
+ digit's value multiplied by the value of ibase raised to the power of the
+ digit's position, which starts from 0 at the least significant digit.
+
+ If multiple of this option and the -c option are given, the last is used.
+
+ -c --digit-clamp
+
+ Enables clamping of digits that are larger than or equal to the current
+ ibase when parsing numbers.
+
+ This means that digits that the value added to a number from a digit that
+ is greater than or equal to the ibase is the value of ibase minus 1 all
+ multiplied by the value of ibase raised to the power of the digit's
+ position, which starts from 0 at the least significant digit.
+
+ If multiple of this option and the -C option are given, the last is used.
{{ A H N HN }}
-E seed --seed=seed
@@ -189,6 +212,8 @@ Environment variables:
If an integer and non-zero, display the copyright banner in interactive
mode.
+ If zero, disable the banner.
+
Overrides the default, which is %s print the banner.
BC_SIGINT_RESET
@@ -196,18 +221,24 @@ Environment variables:
If an integer and non-zero, reset on SIGINT, rather than exit, when in
interactive mode.
+ If zero, do not reset on SIGINT in all cases, but exit instead.
+
Overrides the default, which is %s.
BC_TTY_MODE
If an integer and non-zero, enable TTY mode when it is available.
+ If zero, disable TTY mode in all cases.
+
Overrides the default, which is TTY mode %s.
BC_PROMPT
If an integer and non-zero, enable prompt when TTY mode is possible.
+ If zero, disable prompt in all cases.
+
Overrides the default, which is prompt %s.
BC_EXPR_EXIT
@@ -216,3 +247,10 @@ Environment variables:
given on the command-line, and does not exit when an integer and zero.
Overrides the default, which is %s.
+
+ BC_DIGIT_CLAMP
+
+ If an integer and non-zero, clamp digits larger than or equal to the
+ current ibase when parsing numbers.
+
+ Overrides the default, which is %s.
diff --git a/gen/dc_help.txt b/gen/dc_help.txt
index 05a9a68fafc1..633ddf71f226 100644
--- a/gen/dc_help.txt
+++ b/gen/dc_help.txt
@@ -71,6 +71,29 @@ This dc has a few differences from the two above:
that requires a register name is taken as the register name.
Options:
+
+ -C --no-digit-clamp
+
+ Disables clamping of digits that are larger than or equal to the current
+ ibase when parsing numbers.
+
+ This means that the value added to a number from a digit is always that
+ digit's value multiplied by the value of ibase raised to the power of the
+ digit's position, which starts from 0 at the least significant digit.
+
+ If multiple of this option and the -c option are given, the last is used.
+
+ -c --digit-clamp
+
+ Enables clamping of digits that are larger than or equal to the current
+ ibase when parsing numbers.
+
+ This means that digits that the value added to a number from a digit that
+ is greater than or equal to the ibase is the value of ibase minus 1 all
+ multiplied by the value of ibase raised to the power of the digit's
+ position, which starts from 0 at the least significant digit.
+
+ If multiple of this option and the -C option are given, the last is used.
{{ A H N HN }}
-E seed --seed=seed
@@ -155,18 +178,24 @@ Environment variables:
If an integer and non-zero, reset on SIGINT, rather than exit, when in
interactive mode.
+ If zero, do not reset on SIGINT in all cases, but exit instead.
+
Overrides the default, which is %s.
DC_TTY_MODE
If an integer and non-zero, enable TTY mode when it is available.
+ If zero, disable TTY mode in all cases.
+
Overrides the default, which is TTY mode %s.
DC_PROMPT
If an integer and non-zero, enable prompt when TTY mode is possible.
+ If zero, disable prompt in all cases.
+
Overrides the default, which is prompt %s.
DC_EXPR_EXIT
@@ -175,3 +204,10 @@ Environment variables:
given on the command-line, and does not exit when an integer and zero.
Overrides the default, which is %s.
+
+ DC_DIGIT_CLAMP
+
+ If an integer and non-zero, clamp digits larger than or equal to the
+ current ibase when parsing numbers.
+
+ Overrides the default, which is %s.
diff --git a/gen/lib.bc b/gen/lib.bc
index c0cd7f7dc8d4..8e6118e80608 100644
--- a/gen/lib.bc
+++ b/gen/lib.bc
@@ -33,7 +33,6 @@
*
*/
-scale=2*A
define e(x){
auto b,s,n,r,d,i,p,f,v
b=ibase
diff --git a/gen/strgen.c b/gen/strgen.c
index f4d01ca1391e..5bc29333ceca 100644
--- a/gen/strgen.c
+++ b/gen/strgen.c
@@ -54,9 +54,7 @@
#endif // _WIN32
// This pulls in cross-platform stuff.
-#include "../include/bcl.h"
-
-#define BC_ERR(v) (v)
+#include <status.h>
// clang-format off
diff --git a/gen/strgen.sh b/gen/strgen.sh
index ca67fda3ae71..005395aa2a6b 100755
--- a/gen/strgen.sh
+++ b/gen/strgen.sh
@@ -52,7 +52,7 @@ label="$5"
define="$6"
remove_tabs="$7"
-tmpinput=$(mktemp -t "${input##*/}")
+tmpinput=$(mktemp -t "${input##*/}_XXXXXX")
if [ "$exclude" -ne 0 ]; then
filter_text "$input" "$tmpinput" "E"
diff --git a/include/args.h b/include/args.h
index cf6bcbef621c..515e53b1e891 100644
--- a/include/args.h
+++ b/include/args.h
@@ -46,10 +46,37 @@
* @param argv The array of arguments.
* @param exit_exprs True if bc/dc should exit when there are expressions,
* false otherwise.
- * @param scale The current scale.
+ * @param scale A pointer to return the scale that the arguments set, if
+ * any.
+ * @param ibase A pointer to return the ibase that the arguments set, if
+ * any.
+ * @param obase A pointer to return the obase that the arguments set, if
+ * any.
*/
void
-bc_args(int argc, char* argv[], bool exit_exprs, BcBigDig scale);
+bc_args(int argc, char* argv[], bool exit_exprs, BcBigDig* scale,
+ BcBigDig* ibase, BcBigDig* obase);
+
+#if BC_ENABLED
+
+#if DC_ENABLED
+
+/// Returns true if the banner should be quieted.
+#define BC_ARGS_SHOULD_BE_QUIET (BC_IS_DC || vm->exprs.len > 1)
+
+#else // DC_ENABLED
+
+/// Returns true if the banner should be quieted.
+#define BC_ARGS_SHOULD_BE_QUIET (vm->exprs.len > 1)
+
+#endif // DC_ENABLED
+
+#else // BC_ENABLED
+
+/// Returns true if the banner should be quieted.
+#define BC_ARGS_SHOULD_BE_QUIET (BC_IS_DC)
+
+#endif // BC_ENABLED
// A reference to the list of long options.
extern const BcOptLong bc_args_lopt[];
diff --git a/include/bcl.h b/include/bcl.h
index 54be3239d241..0a6f43700797 100644
--- a/include/bcl.h
+++ b/include/bcl.h
@@ -36,6 +36,11 @@
#ifndef BC_BCL_H
#define BC_BCL_H
+#include <stdbool.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <stdint.h>
+
#ifdef _WIN32
#include <Windows.h>
#include <BaseTsd.h>
@@ -43,44 +48,8 @@
#include <io.h>
#endif // _WIN32
-#include <stdbool.h>
-#include <stdlib.h>
-#include <limits.h>
-#include <stdint.h>
-#include <sys/types.h>
-
-// Windows has deprecated isatty() and the rest of these. Or doesn't have them.
-// So these are just fixes for Windows.
#ifdef _WIN32
-
-// This one is special. Windows did not like me defining an
-// inline function that was not given a definition in a header
-// file. This suppresses that by making inline functions non-inline.
-#define inline
-
-#define restrict __restrict
-#define strdup _strdup
-#define write(f, b, s) _write((f), (b), (unsigned int) (s))
-#define read(f, b, s) _read((f), (b), (unsigned int) (s))
-#define close _close
-#define open(f, n, m) \
- _sopen_s((f), (n), (m) | _O_BINARY, _SH_DENYNO, _S_IREAD | _S_IWRITE)
-#define sigjmp_buf jmp_buf
-#define sigsetjmp(j, s) setjmp(j)
-#define siglongjmp longjmp
-#define isatty _isatty
-#define STDIN_FILENO _fileno(stdin)
-#define STDOUT_FILENO _fileno(stdout)
-#define STDERR_FILENO _fileno(stderr)
#define ssize_t SSIZE_T
-#define S_ISDIR(m) ((m) & (_S_IFDIR))
-#define O_RDONLY _O_RDONLY
-#define stat _stat
-#define fstat _fstat
-#define BC_FILE_SEP '\\'
-
-#else // _WIN32
-#define BC_FILE_SEP '/'
#endif // _WIN32
#define BCL_SEED_ULONGS (4)
@@ -161,11 +130,11 @@ struct BclCtxt;
typedef struct BclCtxt* BclContext;
-void
-bcl_handleSignal(void);
+BclError
+bcl_start(void);
-bool
-bcl_running(void);
+void
+bcl_end(void);
BclError
bcl_init(void);
@@ -185,6 +154,12 @@ bcl_leadingZeroes(void);
void
bcl_setLeadingZeroes(bool leadingZeroes);
+bool
+bcl_digitClamp(void);
+
+void
+bcl_setDigitClamp(bool digitClamp);
+
void
bcl_gc(void);
diff --git a/include/file.h b/include/file.h
index 30a0d9011c00..d6b7c4e56f85 100644
--- a/include/file.h
+++ b/include/file.h
@@ -98,16 +98,24 @@ typedef enum BcFlushType
} BcFlushType;
+// These are here to satisfy a clang warning about recursive macros.
+
+#define bc_file_putchar(f, t, c) bc_file_putchar_impl(f, t, c)
+#define bc_file_flushErr(f, t) bc_file_flushErr_impl(f, t)
+#define bc_file_flush(f, t) bc_file_flush_impl(f, t)
+#define bc_file_write(f, t, b, n) bc_file_write_impl(f, t, b, n)
+#define bc_file_puts(f, t, s) bc_file_puts_impl(f, t, s)
+
#else // BC_ENABLE_HISTORY && !BC_ENABLE_LINE_LIB
// These make sure that the BcFlushType parameter disappears if history is not
// used, editline is used, or readline is used.
-#define bc_file_putchar(f, t, c) bc_file_putchar(f, c)
-#define bc_file_flushErr(f, t) bc_file_flushErr(f)
-#define bc_file_flush(f, t) bc_file_flush(f)
-#define bc_file_write(f, t, b, n) bc_file_write(f, b, n)
-#define bc_file_puts(f, t, s) bc_file_puts(f, s)
+#define bc_file_putchar(f, t, c) bc_file_putchar_impl(f, c)
+#define bc_file_flushErr(f, t) bc_file_flushErr_impl(f)
+#define bc_file_flush(f, t) bc_file_flush_impl(f)
+#define bc_file_write(f, t, b, n) bc_file_write_impl(f, b, n)
+#define bc_file_puts(f, t, s) bc_file_puts_impl(f, s)
#endif // BC_ENABLE_HISTORY && !BC_ENABLE_LINE_LIB
diff --git a/include/history.h b/include/history.h
index 1e9962ded1eb..495b315cc311 100644
--- a/include/history.h
+++ b/include/history.h
@@ -79,27 +79,10 @@
#ifndef BC_HISTORY_H
#define BC_HISTORY_H
-#ifndef BC_ENABLE_HISTORY
-#define BC_ENABLE_HISTORY (1)
-#endif // BC_ENABLE_HISTORY
-
-#ifndef BC_ENABLE_EDITLINE
-#define BC_ENABLE_EDITLINE (0)
-#endif // BC_ENABLE_EDITLINE
-
-#ifndef BC_ENABLE_READLINE
-#define BC_ENABLE_READLINE (0)
-#endif // BC_ENABLE_READLINE
-
-#if BC_ENABLE_EDITLINE && BC_ENABLE_READLINE
-#error Must enable only one of editline or readline, not both.
-#endif // BC_ENABLE_EDITLINE && BC_ENABLE_READLINE
-
-#if BC_ENABLE_EDITLINE || BC_ENABLE_READLINE
-#define BC_ENABLE_LINE_LIB (1)
-#else // BC_ENABLE_EDITLINE || BC_ENABLE_READLINE
-#define BC_ENABLE_LINE_LIB (0)
-#endif // BC_ENABLE_EDITLINE || BC_ENABLE_READLINE
+// These must come before the #if BC_ENABLE_LINE_LIB below because status.h
+// defines it.
+#include <status.h>
+#include <vector.h>
#if BC_ENABLE_LINE_LIB
@@ -107,9 +90,6 @@
#include <setjmp.h>
#include <signal.h>
-#include <status.h>
-#include <vector.h>
-
extern sigjmp_buf bc_history_jmpbuf;
extern volatile sig_atomic_t bc_history_inlinelib;
diff --git a/include/lang.h b/include/lang.h
index 6b8ebabf6a95..f7356c412396 100644
--- a/include/lang.h
+++ b/include/lang.h
@@ -38,19 +38,19 @@
#include <stdbool.h>
-#if BC_C11
-#include <assert.h>
-#endif // BC_C11
-
+// These have to come first to silence a warning on BC_C11 below.
#include <status.h>
#include <vector.h>
#include <num.h>
+#if BC_C11
+#include <assert.h>
+#endif // BC_C11
+
/// The instructions for bytecode.
typedef enum BcInst
{
#if BC_ENABLED
-
/// Postfix increment and decrement. Prefix are translated into
/// BC_INST_ONE with either BC_INST_ASSIGN_PLUS or BC_INST_ASSIGN_MINUS.
BC_INST_INC = 0,
@@ -62,6 +62,7 @@ typedef enum BcInst
/// Boolean not.
BC_INST_BOOL_NOT,
+
#if BC_ENABLE_EXTRA_MATH
/// Truncation operator.
BC_INST_TRUNC,
@@ -76,7 +77,6 @@ typedef enum BcInst
BC_INST_MINUS,
#if BC_ENABLE_EXTRA_MATH
-
/// Places operator.
BC_INST_PLACES,
diff --git a/include/lex.h b/include/lex.h
index 20be6efa9cde..4f08b45d623f 100644
--- a/include/lex.h
+++ b/include/lex.h
@@ -136,6 +136,7 @@ typedef enum BcLexType
BC_LEX_OP_MINUS,
#if BC_ENABLE_EXTRA_MATH
+
/// Places (truncate or extend) operator.
BC_LEX_OP_PLACES,
@@ -144,6 +145,7 @@ typedef enum BcLexType
/// Right (decimal) shift operator.
BC_LEX_OP_RSHIFT,
+
#endif // BC_ENABLE_EXTRA_MATH
/// Equal operator.
@@ -171,6 +173,7 @@ typedef enum BcLexType
BC_LEX_OP_BOOL_AND,
#if BC_ENABLED
+
/// Power assignment operator.
BC_LEX_OP_ASSIGN_POWER,
@@ -353,8 +356,10 @@ typedef enum BcLexType
BC_LEX_KW_MAXSCALE,
#if BC_ENABLE_EXTRA_MATH
+
/// bc maxrand keyword.
BC_LEX_KW_MAXRAND,
+
#endif // BC_ENABLE_EXTRA_MATH
/// bc line_length keyword.
@@ -418,8 +423,10 @@ typedef enum BcLexType
BC_LEX_STORE_SCALE,
#if BC_ENABLE_EXTRA_MATH
+
/// Store seed command.
BC_LEX_STORE_SEED,
+
#endif // BC_ENABLE_EXTRA_MATH
/// Load variable onto stack command.
diff --git a/include/library.h b/include/library.h
index 63d24ee5f7a9..94c62923062a 100644
--- a/include/library.h
+++ b/include/library.h
@@ -39,91 +39,42 @@
#include <bcl.h>
#include <num.h>
+#include <vm.h>
/**
- * A header for functions that need to lock and setjmp(). It also sets the
- * variable that tells bcl that it is running.
- * @param l The label to jump to on error.
+ * A header that sets a jump.
+ * @param vm The thread data.
+ * @param l The label to jump to on error.
*/
-#define BC_FUNC_HEADER_LOCK(l) \
- do \
- { \
- BC_SIG_LOCK; \
- BC_SETJMP_LOCKED(l); \
- vm.err = BCL_ERROR_NONE; \
- vm.running = 1; \
- } \
+#define BC_FUNC_HEADER(vm, l) \
+ do \
+ { \
+ BC_SETJMP(vm, l); \
+ vm->err = BCL_ERROR_NONE; \
+ } \
while (0)
/**
- * A footer to unlock and stop the jumping if an error happened. It also sets
- * the variable that tells bcl that it is running.
- * @param e The error variable to set.
+ * A footer for functions that do not return an error code.
*/
-#define BC_FUNC_FOOTER_UNLOCK(e) \
- do \
- { \
- BC_SIG_ASSERT_LOCKED; \
- e = vm.err; \
- vm.running = 0; \
- BC_UNSETJMP; \
- BC_LONGJMP_STOP; \
- vm.sig_lock = 0; \
- } \
+#define BC_FUNC_FOOTER_NO_ERR(vm) \
+ do \
+ { \
+ BC_UNSETJMP(vm); \
+ } \
while (0)
/**
- * A header that sets a jump and sets running.
- * @param l The label to jump to on error.
+ * A footer for functions that *do* return an error code.
+ * @param vm The thread data.
+ * @param e The error variable to set.
*/
-#define BC_FUNC_HEADER(l) \
- do \
- { \
- BC_SETJMP(l); \
- vm.err = BCL_ERROR_NONE; \
- vm.running = 1; \
- } \
- while (0)
-
-/**
- * A header that assumes that signals are already locked. It sets a jump and
- * running.
- * @param l The label to jump to on error.
- */
-#define BC_FUNC_HEADER_INIT(l) \
- do \
- { \
- BC_SETJMP_LOCKED(l); \
- vm.err = BCL_ERROR_NONE; \
- vm.running = 1; \
- } \
- while (0)
-
-/**
- * A footer for functions that do not return an error code. It clears running
- * and unlocks the signals. It also stops the jumping.
- */
-#define BC_FUNC_FOOTER_NO_ERR \
- do \
- { \
- vm.running = 0; \
- BC_UNSETJMP; \
- BC_LONGJMP_STOP; \
- vm.sig_lock = 0; \
- } \
- while (0)
-
-/**
- * A footer for functions that *do* return an error code. It clears running and
- * unlocks the signals. It also stops the jumping.
- * @param e The error variable to set.
- */
-#define BC_FUNC_FOOTER(e) \
- do \
- { \
- e = vm.err; \
- BC_FUNC_FOOTER_NO_ERR; \
- } \
+#define BC_FUNC_FOOTER(vm, e) \
+ do \
+ { \
+ e = vm->err; \
+ BC_FUNC_FOOTER_NO_ERR(vm); \
+ } \
while (0)
/**
@@ -151,10 +102,10 @@
* is bad.
* @param c The context.
*/
-#define BC_CHECK_CTXT(c) \
+#define BC_CHECK_CTXT(vm, c) \
do \
{ \
- c = bcl_context(); \
+ c = bcl_contextHelper(vm); \
if (BC_ERR(c == NULL)) \
{ \
BclNumber n_num; \
@@ -168,10 +119,10 @@
* A header to check the context and return an error directly if it is bad.
* @param c The context.
*/
-#define BC_CHECK_CTXT_ERR(c) \
+#define BC_CHECK_CTXT_ERR(vm, c) \
do \
{ \
- c = bcl_context(); \
+ c = bcl_contextHelper(vm); \
if (BC_ERR(c == NULL)) \
{ \
return BCL_ERROR_INVALID_CONTEXT; \
@@ -183,12 +134,12 @@
* A header to check the context and abort if it is bad.
* @param c The context.
*/
-#define BC_CHECK_CTXT_ASSERT(c) \
- do \
- { \
- c = bcl_context(); \
- assert(c != NULL); \
- } \
+#define BC_CHECK_CTXT_ASSERT(vm, c) \
+ do \
+ { \
+ c = bcl_contextHelper(vm); \
+ assert(c != NULL); \
+ } \
while (0)
/**
@@ -272,4 +223,21 @@ typedef struct BclCtxt
} BclCtxt;
+/**
+ * Returns the @a BcVm for the current thread.
+ * @return The vm for the current thread.
+ */
+BcVm*
+bcl_getspecific(void);
+
+#ifndef _WIN32
+
+typedef pthread_key_t BclTls;
+
+#else // _WIN32
+
+typedef DWORD BclTls;
+
+#endif // _WIN32
+
#endif // LIBBC_PRIVATE_H
diff --git a/include/num.h b/include/num.h
index 4a4dc5bc54fa..835dd8e97478 100644
--- a/include/num.h
+++ b/include/num.h
@@ -47,10 +47,6 @@
#include <vector.h>
#include <bcl.h>
-#ifndef BC_ENABLE_EXTRA_MATH
-#define BC_ENABLE_EXTRA_MATH (1)
-#endif // BC_ENABLE_EXTRA_MATH
-
/// Everything in bc is base 10..
#define BC_BASE (10)
@@ -829,6 +825,14 @@ bc_num_parse(BcNum* restrict n, const char* restrict val, BcBigDig base);
void
bc_num_print(BcNum* restrict n, BcBigDig base, bool newline);
+/**
+ * Invert @a into @a b at the current scale.
+ * @param a The number to invert.
+ * @param b The return parameter. This must be preallocated.
+ * @param scale The current scale.
+ */
+#define bc_num_inv(a, b, scale) bc_num_div(&vm->one, (a), (b), (scale))
+
#if !BC_ENABLE_LIBRARY
/**
diff --git a/include/program.h b/include/program.h
index 1a87aa612c90..3eaf568d66ac 100644
--- a/include/program.h
+++ b/include/program.h
@@ -69,8 +69,10 @@ typedef struct BcProgram
/// The array of globals values.
BcBigDig globals[BC_PROG_GLOBALS_LEN];
+#if BC_ENABLED
/// The array of globals stacks.
BcVec globals_v[BC_PROG_GLOBALS_LEN];
+#endif // BC_ENABLED
#if BC_ENABLE_EXTRA_MATH
@@ -122,6 +124,10 @@ typedef struct BcProgram
/// A BcNum that has the proper base for asciify.
BcNum strmb;
+ // A BcNum to run asciify. This is to prevent GCC longjmp() clobbering
+ // warnings.
+ BcNum asciify;
+
#if BC_ENABLED
/// The last printed value for bc.
@@ -206,16 +212,36 @@ typedef struct BcProgram
/// This define disappears the parameter last because for dc only, last is
/// always true.
-#define bc_program_copyToVar(p, name, t, last) bc_program_copyToVar(p, name, t)
+#define bc_program_copyToVar(p, name, t, last) \
+ bc_program_copyToVar_impl(p, name, t)
+
+/// Returns true if the calculator should pop after printing.
+#define BC_PROGRAM_POP(pop) (pop)
+
+#else // !BC_ENABLED
+
+// This is here to quiet a compiler warning.
+#define bc_program_copyToVar(p, name, t, last) \
+ bc_program_copyToVar_impl(p, name, t, last)
+
+/// Returns true if the calculator should pop after printing.
+#define BC_PROGRAM_POP(pop) (BC_IS_BC || (pop))
#endif // !BC_ENABLED
+// This is here to satisfy a clang warning about recursive macros.
+#define bc_program_pushVar(p, code, bgn, pop, copy) \
+ bc_program_pushVar_impl(p, code, bgn, pop, copy)
+
#else // DC_ENABLED
-/// This define disappears pop and copy because for bc, 'pop' and 'copy' are
-/// always false.
+// This define disappears pop and copy because for bc, 'pop' and 'copy' are
+// always false.
#define bc_program_pushVar(p, code, bgn, pop, copy) \
- bc_program_pushVar(p, code, bgn)
+ bc_program_pushVar_impl(p, code, bgn)
+
+/// Returns true if the calculator should pop after printing.
+#define BC_PROGRAM_POP(pop) (BC_IS_BC)
// In debug mode, we want bc to check the stack, but otherwise, we don't because
// the bc language implicitly mandates that the stack should always have enough
@@ -438,14 +464,14 @@ extern const char bc_program_esc_seqs[];
#if BC_DEBUG_CODE
// clang-format off
-#define BC_PROG_JUMP(inst, code, ip) \
- do \
- { \
- inst = (uchar) (code)[(ip)->idx++]; \
- bc_file_printf(&vm.ferr, "inst: %s\n", bc_inst_names[inst]); \
- bc_file_flush(&vm.ferr, bc_flush_none); \
- goto *bc_program_inst_lbls[inst]; \
- } \
+#define BC_PROG_JUMP(inst, code, ip) \
+ do \
+ { \
+ inst = (uchar) (code)[(ip)->idx++]; \
+ bc_file_printf(&vm->ferr, "inst: %s\n", bc_inst_names[inst]); \
+ bc_file_flush(&vm->ferr, bc_flush_none); \
+ goto *bc_program_inst_lbls[inst]; \
+ } \
while (0)
// clang-format on
diff --git a/include/status.h b/include/status.h
index d038944d40c9..f478beb1a2d5 100644
--- a/include/status.h
+++ b/include/status.h
@@ -36,7 +36,15 @@
#ifndef BC_STATUS_H
#define BC_STATUS_H
+#ifdef _WIN32
+#include <Windows.h>
+#include <BaseTsd.h>
+#include <stdio.h>
+#include <io.h>
+#endif // _WIN32
+
#include <stdint.h>
+#include <sys/types.h>
// This is used by configure.sh to test for OpenBSD.
#ifdef BC_TEST_OPENBSD
@@ -52,6 +60,39 @@
#endif // __FreeBSD__
#endif // BC_TEST_FREEBSD
+// Windows has deprecated isatty() and the rest of these. Or doesn't have them.
+// So these are just fixes for Windows.
+#ifdef _WIN32
+
+// This one is special. Windows did not like me defining an
+// inline function that was not given a definition in a header
+// file. This suppresses that by making inline functions non-inline.
+#define inline
+
+#define restrict __restrict
+#define strdup _strdup
+#define write(f, b, s) _write((f), (b), (unsigned int) (s))
+#define read(f, b, s) _read((f), (b), (unsigned int) (s))
+#define close _close
+#define open(f, n, m) \
+ _sopen_s((f), (n), (m) | _O_BINARY, _SH_DENYNO, _S_IREAD | _S_IWRITE)
+#define sigjmp_buf jmp_buf
+#define sigsetjmp(j, s) setjmp(j)
+#define siglongjmp longjmp
+#define isatty _isatty
+#define STDIN_FILENO _fileno(stdin)
+#define STDOUT_FILENO _fileno(stdout)
+#define STDERR_FILENO _fileno(stderr)
+#define S_ISDIR(m) ((m) & (_S_IFDIR))
+#define O_RDONLY _O_RDONLY
+#define stat _stat
+#define fstat _fstat
+#define BC_FILE_SEP '\\'
+
+#else // _WIN32
+#define BC_FILE_SEP '/'
+#endif // _WIN32
+
#ifndef BC_ENABLED
#define BC_ENABLED (1)
#endif // BC_ENABLED
@@ -60,10 +101,46 @@
#define DC_ENABLED (1)
#endif // DC_ENABLED
+#ifndef BC_ENABLE_EXTRA_MATH
+#define BC_ENABLE_EXTRA_MATH (1)
+#endif // BC_ENABLE_EXTRA_MATH
+
#ifndef BC_ENABLE_LIBRARY
#define BC_ENABLE_LIBRARY (0)
#endif // BC_ENABLE_LIBRARY
+#ifndef BC_ENABLE_HISTORY
+#define BC_ENABLE_HISTORY (1)
+#endif // BC_ENABLE_HISTORY
+
+#ifndef BC_ENABLE_EDITLINE
+#define BC_ENABLE_EDITLINE (0)
+#endif // BC_ENABLE_EDITLINE
+
+#ifndef BC_ENABLE_READLINE
+#define BC_ENABLE_READLINE (0)
+#endif // BC_ENABLE_READLINE
+
+#ifndef BC_ENABLE_NLS
+#define BC_ENABLE_NLS (0)
+#endif // BC_ENABLE_NLS
+
+#ifdef __OpenBSD__
+#if BC_ENABLE_READLINE
+#error Cannot use readline on OpenBSD
+#endif // BC_ENABLE_READLINE
+#endif // __OpenBSD__
+
+#if BC_ENABLE_EDITLINE && BC_ENABLE_READLINE
+#error Must enable only one of editline or readline, not both.
+#endif // BC_ENABLE_EDITLINE && BC_ENABLE_READLINE
+
+#if BC_ENABLE_EDITLINE || BC_ENABLE_READLINE
+#define BC_ENABLE_LINE_LIB (1)
+#else // BC_ENABLE_EDITLINE || BC_ENABLE_READLINE
+#define BC_ENABLE_LINE_LIB (0)
+#endif // BC_ENABLE_EDITLINE || BC_ENABLE_READLINE
+
// This is error checking for fuzz builds.
#if BC_ENABLE_AFL
#ifndef __AFL_HAVE_MANUAL_CONTROL
@@ -122,6 +199,18 @@
#define BC_DEBUG_CODE (0)
#endif // BC_DEBUG_CODE
+#if defined(__clang__)
+#define BC_CLANG (1)
+#else // defined(__clang__)
+#define BC_CLANG (0)
+#endif // defined(__clang__)
+
+#if defined(__GNUC__) && !BC_CLANG
+#define BC_GCC (1)
+#else // defined(__GNUC__) && !BC_CLANG
+#define BC_GCC (0)
+#endif // defined(__GNUC__) && !BC_CLANG
+
// We want to be able to use _Noreturn on C11 compilers.
#if __STDC_VERSION__ >= 201112L
@@ -131,7 +220,19 @@
#else // __STDC_VERSION__
+#if BC_CLANG
+#if __has_attribute(noreturn)
+#define BC_NORETURN __attribute((noreturn))
+#else // __has_attribute(noreturn)
#define BC_NORETURN
+#endif // __has_attribute(noreturn)
+
+#else // BC_CLANG
+
+#define BC_NORETURN
+
+#endif // BC_CLANG
+
#define BC_MUST_RETURN
#define BC_C11 (0)
@@ -143,7 +244,7 @@
// GCC and Clang complain if fallthroughs are not marked with their special
// attribute. Jerks. This creates a define for marking the fallthroughs that is
// nothing on other compilers.
-#if defined(__clang__) || defined(__GNUC__)
+#if BC_CLANG || BC_GCC
#if defined(__has_attribute)
@@ -153,28 +254,28 @@
#define BC_FALLTHROUGH
#endif // __has_attribute(fallthrough)
-#ifdef __GNUC__
+#if BC_GCC
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
#undef BC_HAS_UNREACHABLE
#define BC_HAS_UNREACHABLE (1)
#endif // __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
-#else // __GNUC__
+#else // BC_GCC
#if __clang_major__ >= 4
#undef BC_HAS_UNREACHABLE
#define BC_HAS_UNREACHABLE (1)
#endif // __clang_major__ >= 4
-#endif // __GNUC__
+#endif // BC_GCC
#else // defined(__has_attribute)
#define BC_FALLTHROUGH
#endif // defined(__has_attribute)
-#else // defined(__clang__) || defined(__GNUC__)
+#else // BC_CLANG || BC_GCC
#define BC_FALLTHROUGH
-#endif // defined(__clang__) || defined(__GNUC__)
+#endif // BC_CLANG || BC_GCC
#if BC_HAS_UNREACHABLE
@@ -194,7 +295,7 @@
#endif // BC_HAS_UNREACHABLE
-#ifdef __GNUC__
+#if BC_GCC
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
@@ -203,9 +304,9 @@
#endif // __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
-#endif // __GNUC__
+#endif // BC_GCC
-#ifdef __clang__
+#if BC_CLANG
#if __clang_major__ >= 4
@@ -214,7 +315,7 @@
#endif // __clang_major__ >= 4
-#endif // __GNUC__
+#endif // BC_CLANG
#ifdef BC_NO_COMPUTED_GOTO
@@ -223,12 +324,12 @@
#endif // BC_NO_COMPUTED_GOTO
-#ifdef __GNUC__
+#if BC_GCC
#ifdef __OpenBSD__
// The OpenBSD GCC doesn't like inline.
#define inline
#endif // __OpenBSD__
-#endif // __GNUC__
+#endif // BC_GCC
// Workarounds for AIX's POSIX incompatibility.
#ifndef SIZE_MAX
@@ -279,6 +380,10 @@
#define BC_DEFAULT_EXPR_EXIT (1)
#endif // BC_DEFAULT_EXPR_EXIT
+#ifndef BC_DEFAULT_DIGIT_CLAMP
+#define BC_DEFAULT_DIGIT_CLAMP (0)
+#endif // BC_DEFAULT_DIGIT_CLAMP
+
// All of these set defaults for settings.
#ifndef DC_DEFAULT_SIGINT_RESET
#define DC_DEFAULT_SIGINT_RESET (1)
@@ -300,6 +405,10 @@
#define DC_DEFAULT_EXPR_EXIT (1)
#endif // DC_DEFAULT_EXPR_EXIT
+#ifndef DC_DEFAULT_DIGIT_CLAMP
+#define DC_DEFAULT_DIGIT_CLAMP (0)
+#endif // DC_DEFAULT_DIGIT_CLAMP
+
/// Statuses, which mark either which category of error happened, or some other
/// status that matters.
typedef enum BcStatus
@@ -558,13 +667,15 @@ typedef enum BcErr
#define BC_JMP bc_vm_jmp()
#endif // BC_DEBUG_CODE
+#if !BC_ENABLE_LIBRARY
+
/// Returns true if an exception is in flight, false otherwise.
-#define BC_SIG_EXC \
- BC_UNLIKELY(vm.status != (sig_atomic_t) BC_STATUS_SUCCESS || vm.sig)
+#define BC_SIG_EXC(vm) \
+ BC_UNLIKELY(vm->status != (sig_atomic_t) BC_STATUS_SUCCESS || vm->sig)
/// Returns true if there is *no* exception in flight, false otherwise.
-#define BC_NO_SIG_EXC \
- BC_LIKELY(vm.status == (sig_atomic_t) BC_STATUS_SUCCESS && !vm.sig)
+#define BC_NO_SIG_EXC(vm) \
+ BC_LIKELY(vm->status == (sig_atomic_t) BC_STATUS_SUCCESS && !vm->sig)
#ifndef NDEBUG
@@ -572,22 +683,22 @@ typedef enum BcErr
/// bc, and they *must* have signals locked. Other functions are expected to
/// *not* have signals locked, for reasons. So this is a pre-built assert
/// (no-op in non-debug mode) that check that signals are locked.
-#define BC_SIG_ASSERT_LOCKED \
- do \
- { \
- assert(vm.sig_lock); \
- } \
+#define BC_SIG_ASSERT_LOCKED \
+ do \
+ { \
+ assert(vm->sig_lock); \
+ } \
while (0)
/// Assert that signals are unlocked. There are non-async-signal-safe functions
/// in bc, and they *must* have signals locked. Other functions are expected to
/// *not* have signals locked, for reasons. So this is a pre-built assert
/// (no-op in non-debug mode) that check that signals are unlocked.
-#define BC_SIG_ASSERT_NOT_LOCKED \
- do \
- { \
- assert(vm.sig_lock == 0); \
- } \
+#define BC_SIG_ASSERT_NOT_LOCKED \
+ do \
+ { \
+ assert(vm->sig_lock == 0); \
+ } \
while (0)
#else // NDEBUG
@@ -611,7 +722,7 @@ typedef enum BcErr
do \
{ \
BC_SIG_ASSERT_NOT_LOCKED; \
- vm.sig_lock = 1; \
+ vm->sig_lock = 1; \
} \
while (0)
@@ -620,8 +731,8 @@ typedef enum BcErr
do \
{ \
BC_SIG_ASSERT_LOCKED; \
- vm.sig_lock = 0; \
- if (vm.sig) BC_JMP; \
+ vm->sig_lock = 0; \
+ if (vm->sig) BC_JMP; \
} \
while (0)
@@ -629,21 +740,21 @@ typedef enum BcErr
/// used after labels that longjmp() goes to after the jump because the cleanup
/// code must have signals locked, and BC_LONGJMP_CONT will unlock signals if it
/// doesn't jump.
-#define BC_SIG_MAYLOCK \
- do \
- { \
- vm.sig_lock = 1; \
- } \
+#define BC_SIG_MAYLOCK \
+ do \
+ { \
+ vm->sig_lock = 1; \
+ } \
while (0)
/// Unlocks signals, regardless of if they were already unlocked. If a signal
/// happened, then this will cause a jump.
-#define BC_SIG_MAYUNLOCK \
- do \
- { \
- vm.sig_lock = 0; \
- if (vm.sig) BC_JMP; \
- } \
+#define BC_SIG_MAYUNLOCK \
+ do \
+ { \
+ vm->sig_lock = 0; \
+ if (vm->sig) BC_JMP; \
+ } \
while (0)
/*
@@ -654,8 +765,8 @@ typedef enum BcErr
#define BC_SIG_TRYLOCK(v) \
do \
{ \
- v = vm.sig_lock; \
- vm.sig_lock = 1; \
+ v = vm->sig_lock; \
+ vm->sig_lock = 1; \
} \
while (0)
@@ -663,38 +774,23 @@ typedef enum BcErr
* initiates an exception/jump.
* @param v The old lock state.
*/
-#define BC_SIG_TRYUNLOCK(v) \
- do \
- { \
- vm.sig_lock = (v); \
- if (!(v) && vm.sig) BC_JMP; \
- } \
+#define BC_SIG_TRYUNLOCK(v) \
+ do \
+ { \
+ vm->sig_lock = (v); \
+ if (!(v) && vm->sig) BC_JMP; \
+ } \
while (0)
-/**
- * Sets a jump, and sets it up as well so that if a longjmp() happens, bc will
- * immediately goto a label where some cleanup code is. This one assumes that
- * signals are not locked and will lock them, set the jump, and unlock them.
- * Setting the jump also includes pushing the jmp_buf onto the jmp_buf stack.
- * This grows the jmp_bufs vector first to prevent a fatal error from happening
- * after the setjmp(). This is done because BC_SETJMP(l) is assumed to be used
- * *before* the actual initialization calls that need the setjmp().
- * param l The label to jump to on a longjmp().
- */
-#define BC_SETJMP(l) \
- do \
- { \
- sigjmp_buf sjb; \
- BC_SIG_LOCK; \
- bc_vec_grow(&vm.jmp_bufs, 1); \
- if (sigsetjmp(sjb, 0)) \
- { \
- assert(BC_SIG_EXC); \
- goto l; \
- } \
- bc_vec_push(&vm.jmp_bufs, &sjb); \
- BC_SIG_UNLOCK; \
- } \
+/// Stops a stack unwinding. Technically, a stack unwinding needs to be done
+/// manually, but it will always be done unless certain flags are cleared. This
+/// clears the flags.
+#define BC_LONGJMP_STOP \
+ do \
+ { \
+ vm->sig_pop = 0; \
+ vm->sig = 0; \
+ } \
while (0)
/**
@@ -704,59 +800,108 @@ typedef enum BcErr
* the initializations that need the setjmp().
* param l The label to jump to on a longjmp().
*/
-#define BC_SETJMP_LOCKED(l) \
- do \
- { \
- sigjmp_buf sjb; \
- BC_SIG_ASSERT_LOCKED; \
- if (sigsetjmp(sjb, 0)) \
- { \
- assert(BC_SIG_EXC); \
- goto l; \
- } \
- bc_vec_push(&vm.jmp_bufs, &sjb); \
- } \
+#define BC_SETJMP_LOCKED(vm, l) \
+ do \
+ { \
+ sigjmp_buf sjb; \
+ BC_SIG_ASSERT_LOCKED; \
+ if (sigsetjmp(sjb, 0)) \
+ { \
+ assert(BC_SIG_EXC(vm)); \
+ goto l; \
+ } \
+ bc_vec_push(&vm->jmp_bufs, &sjb); \
+ } \
while (0)
/// Used after cleanup labels set by BC_SETJMP and BC_SETJMP_LOCKED to jump to
/// the next place. This is what continues the stack unwinding. This basically
/// copies BC_SIG_UNLOCK into itself, but that is because its condition for
/// jumping is BC_SIG_EXC, not just that a signal happened.
-#define BC_LONGJMP_CONT \
- do \
- { \
- BC_SIG_ASSERT_LOCKED; \
- if (!vm.sig_pop) bc_vec_pop(&vm.jmp_bufs); \
- vm.sig_lock = 0; \
- if (BC_SIG_EXC) BC_JMP; \
- } \
+#define BC_LONGJMP_CONT(vm) \
+ do \
+ { \
+ BC_SIG_ASSERT_LOCKED; \
+ if (!vm->sig_pop) bc_vec_pop(&vm->jmp_bufs); \
+ vm->sig_lock = 0; \
+ if (BC_SIG_EXC(vm)) BC_JMP; \
+ } \
+ while (0)
+
+#else // !BC_ENABLE_LIBRARY
+
+#define BC_SIG_LOCK
+#define BC_SIG_UNLOCK
+#define BC_SIG_MAYLOCK
+#define BC_SIG_TRYLOCK(lock)
+#define BC_SIG_TRYUNLOCK(lock)
+#define BC_SIG_ASSERT_LOCKED
+
+/// Returns true if an exception is in flight, false otherwise.
+#define BC_SIG_EXC(vm) \
+ BC_UNLIKELY(vm->status != (sig_atomic_t) BC_STATUS_SUCCESS)
+
+/// Returns true if there is *no* exception in flight, false otherwise.
+#define BC_NO_SIG_EXC(vm) \
+ BC_LIKELY(vm->status == (sig_atomic_t) BC_STATUS_SUCCESS)
+
+/// Used after cleanup labels set by BC_SETJMP and BC_SETJMP_LOCKED to jump to
+/// the next place. This is what continues the stack unwinding. This basically
+/// copies BC_SIG_UNLOCK into itself, but that is because its condition for
+/// jumping is BC_SIG_EXC, not just that a signal happened.
+#define BC_LONGJMP_CONT(vm) \
+ do \
+ { \
+ bc_vec_pop(&vm->jmp_bufs); \
+ if (BC_SIG_EXC(vm)) BC_JMP; \
+ } \
+ while (0)
+
+#endif // !BC_ENABLE_LIBRARY
+
+/**
+ * Sets a jump, and sets it up as well so that if a longjmp() happens, bc will
+ * immediately goto a label where some cleanup code is. This one assumes that
+ * signals are not locked and will lock them, set the jump, and unlock them.
+ * Setting the jump also includes pushing the jmp_buf onto the jmp_buf stack.
+ * This grows the jmp_bufs vector first to prevent a fatal error from happening
+ * after the setjmp(). This is done because BC_SETJMP(l) is assumed to be used
+ * *before* the actual initialization calls that need the setjmp().
+ * param l The label to jump to on a longjmp().
+ */
+#define BC_SETJMP(vm, l) \
+ do \
+ { \
+ sigjmp_buf sjb; \
+ BC_SIG_LOCK; \
+ bc_vec_grow(&vm->jmp_bufs, 1); \
+ if (sigsetjmp(sjb, 0)) \
+ { \
+ assert(BC_SIG_EXC(vm)); \
+ goto l; \
+ } \
+ bc_vec_push(&vm->jmp_bufs, &sjb); \
+ BC_SIG_UNLOCK; \
+ } \
while (0)
/// Unsets a jump. It always assumes signals are locked. This basically just
/// pops a jmp_buf off of the stack of jmp_bufs, and since the jump mechanism
/// always jumps to the location at the top of the stack, this effectively
/// undoes a setjmp().
-#define BC_UNSETJMP \
- do \
- { \
- BC_SIG_ASSERT_LOCKED; \
- bc_vec_pop(&vm.jmp_bufs); \
- } \
+#define BC_UNSETJMP(vm) \
+ do \
+ { \
+ BC_SIG_ASSERT_LOCKED; \
+ bc_vec_pop(&vm->jmp_bufs); \
+ } \
while (0)
-/// Stops a stack unwinding. Technically, a stack unwinding needs to be done
-/// manually, but it will always be done unless certain flags are cleared. This
-/// clears the flags.
-#define BC_LONGJMP_STOP \
- do \
- { \
- vm.sig_pop = 0; \
- vm.sig = 0; \
- } \
- while (0)
+#if BC_ENABLE_LIBRARY
+
+#define BC_SETJMP_LOCKED(vm, l) BC_SETJMP(vm, l)
// Various convenience macros for calling the bc's error handling routine.
-#if BC_ENABLE_LIBRARY
/**
* Call bc's error handling routine.
@@ -780,6 +925,8 @@ typedef enum BcErr
#else // BC_ENABLE_LIBRARY
+// Various convenience macros for calling the bc's error handling routine.
+
/**
* Call bc's error handling routine.
* @param e The error.
@@ -813,34 +960,34 @@ typedef enum BcErr
// Convenience macros that can be placed at the beginning and exits of functions
// for easy marking of where functions are entered and exited.
#if BC_DEBUG_CODE
-#define BC_FUNC_ENTER \
- do \
- { \
- size_t bc_func_enter_i; \
- for (bc_func_enter_i = 0; bc_func_enter_i < vm.func_depth; \
- ++bc_func_enter_i) \
- { \
- bc_file_puts(&vm.ferr, bc_flush_none, " "); \
- } \
- vm.func_depth += 1; \
- bc_file_printf(&vm.ferr, "Entering %s\n", __func__); \
- bc_file_flush(&vm.ferr, bc_flush_none); \
- } \
+#define BC_FUNC_ENTER \
+ do \
+ { \
+ size_t bc_func_enter_i; \
+ for (bc_func_enter_i = 0; bc_func_enter_i < vm->func_depth; \
+ ++bc_func_enter_i) \
+ { \
+ bc_file_puts(&vm->ferr, bc_flush_none, " "); \
+ } \
+ vm->func_depth += 1; \
+ bc_file_printf(&vm->ferr, "Entering %s\n", __func__); \
+ bc_file_flush(&vm->ferr, bc_flush_none); \
+ } \
while (0);
-#define BC_FUNC_EXIT \
- do \
- { \
- size_t bc_func_enter_i; \
- vm.func_depth -= 1; \
- for (bc_func_enter_i = 0; bc_func_enter_i < vm.func_depth; \
- ++bc_func_enter_i) \
- { \
- bc_file_puts(&vm.ferr, bc_flush_none, " "); \
- } \
- bc_file_printf(&vm.ferr, "Leaving %s\n", __func__); \
- bc_file_flush(&vm.ferr, bc_flush_none); \
- } \
+#define BC_FUNC_EXIT \
+ do \
+ { \
+ size_t bc_func_enter_i; \
+ vm->func_depth -= 1; \
+ for (bc_func_enter_i = 0; bc_func_enter_i < vm->func_depth; \
+ ++bc_func_enter_i) \
+ { \
+ bc_file_puts(&vm->ferr, bc_flush_none, " "); \
+ } \
+ bc_file_printf(&vm->ferr, "Leaving %s\n", __func__); \
+ bc_file_flush(&vm->ferr, bc_flush_none); \
+ } \
while (0);
#else // BC_DEBUG_CODE
#define BC_FUNC_ENTER
diff --git a/include/vector.h b/include/vector.h
index 43158ef4ba63..539b8a1ac292 100644
--- a/include/vector.h
+++ b/include/vector.h
@@ -427,17 +427,6 @@ bc_slabvec_init(BcVec* restrict v);
char*
bc_slabvec_strdup(BcVec* restrict v, const char* str);
-#if BC_ENABLED
-
-/**
- * Undoes the last allocation on the slab vector. This allows bc to have a
- * heap-based stacks for strings. This is used by the bc parser.
- */
-void
-bc_slabvec_undo(BcVec* restrict v, size_t len);
-
-#endif // BC_ENABLED
-
/**
* Clears a slab vector. This deallocates all but the first slab and clears the
* first slab.
@@ -460,6 +449,25 @@ bc_slabvec_print(BcVec* v, const char* func);
/// A convenience macro for freeing a vector of slabs.
#define bc_slabvec_free bc_vec_free
+#if BC_ENABLED
+#if DC_ENABLED
+
+/// Returns the set of slabs for the maps and the current calculator.
+#define BC_VEC_MAP_SLABS (BC_IS_DC ? &vm->main_slabs : &vm->other_slabs)
+
+#else // DC_ENABLED
+
+/// Returns the set of slabs for the maps and the current calculator.
+#define BC_VEC_MAP_SLABS (&vm->other_slabs)
+
+#endif // DC_ENABLED
+#else // BC_ENABLED
+
+/// Returns the set of slabs for the maps and the current calculator.
+#define BC_VEC_MAP_SLABS (&vm->main_slabs)
+
+#endif // BC_ENABLED
+
#ifndef _WIN32
/**
diff --git a/include/version.h b/include/version.h
index 4400e4f59ccd..74b1dc72bd0c 100644
--- a/include/version.h
+++ b/include/version.h
@@ -37,6 +37,6 @@
#define BC_VERSION_H
/// The current version.
-#define VERSION 5.3.3
+#define VERSION 6.0.2
#endif // BC_VERSION_H
diff --git a/include/vm.h b/include/vm.h
index dd4577489467..c800e476e228 100644
--- a/include/vm.h
+++ b/include/vm.h
@@ -78,10 +78,6 @@
#endif
// Set defaults.
-//
-#ifndef BC_ENABLE_NLS
-#define BC_ENABLE_NLS (0)
-#endif // BC_ENABLE_NLS
#ifndef MAINEXEC
#define MAINEXEC bc
@@ -179,52 +175,58 @@
/// The flag for exiting with expressions.
#define BC_FLAG_EXPR_EXIT (UINTMAX_C(1) << 13)
+/// The flag for digit clamping.
+#define BC_FLAG_DIGIT_CLAMP (UINTMAX_C(1) << 14)
+
/// A convenience macro for getting the TTYIN flag.
-#define BC_TTYIN (vm.flags & BC_FLAG_TTYIN)
+#define BC_TTYIN (vm->flags & BC_FLAG_TTYIN)
/// A convenience macro for getting the TTY flag.
-#define BC_TTY (vm.flags & BC_FLAG_TTY)
+#define BC_TTY (vm->flags & BC_FLAG_TTY)
/// A convenience macro for getting the SIGINT flag.
-#define BC_SIGINT (vm.flags & BC_FLAG_SIGINT)
+#define BC_SIGINT (vm->flags & BC_FLAG_SIGINT)
#if BC_ENABLED
/// A convenience macro for getting the POSIX error flag.
-#define BC_S (vm.flags & BC_FLAG_S)
+#define BC_S (vm->flags & BC_FLAG_S)
/// A convenience macro for getting the POSIX warning flag.
-#define BC_W (vm.flags & BC_FLAG_W)
+#define BC_W (vm->flags & BC_FLAG_W)
/// A convenience macro for getting the math library flag.
-#define BC_L (vm.flags & BC_FLAG_L)
+#define BC_L (vm->flags & BC_FLAG_L)
/// A convenience macro for getting the global stacks flag.
-#define BC_G (vm.flags & BC_FLAG_G)
+#define BC_G (vm->flags & BC_FLAG_G)
#endif // BC_ENABLED
#if DC_ENABLED
/// A convenience macro for getting the extended register flag.
-#define DC_X (vm.flags & DC_FLAG_X)
+#define DC_X (vm->flags & DC_FLAG_X)
#endif // DC_ENABLED
/// A convenience macro for getting the interactive flag.
-#define BC_I (vm.flags & BC_FLAG_I)
+#define BC_I (vm->flags & BC_FLAG_I)
/// A convenience macro for getting the prompt flag.
-#define BC_P (vm.flags & BC_FLAG_P)
+#define BC_P (vm->flags & BC_FLAG_P)
/// A convenience macro for getting the read prompt flag.
-#define BC_R (vm.flags & BC_FLAG_R)
+#define BC_R (vm->flags & BC_FLAG_R)
/// A convenience macro for getting the leading zero flag.
-#define BC_Z (vm.flags & BC_FLAG_Z)
+#define BC_Z (vm->flags & BC_FLAG_Z)
/// A convenience macro for getting the expression exit flag.
-#define BC_EXPR_EXIT (vm.flags & BC_FLAG_EXPR_EXIT)
+#define BC_EXPR_EXIT (vm->flags & BC_FLAG_EXPR_EXIT)
+
+/// A convenience macro for getting the digit clamp flag.
+#define BC_DIGIT_CLAMP (vm->flags & BC_FLAG_DIGIT_CLAMP)
#if BC_ENABLED
@@ -234,10 +236,57 @@
#if DC_ENABLED
/// Returns true if bc is running.
-#define BC_IS_BC (vm.name[0] != 'd')
+#define BC_IS_BC (vm->name[0] != 'd')
/// Returns true if dc is running.
-#define BC_IS_DC (vm.name[0] == 'd')
+#define BC_IS_DC (vm->name[0] == 'd')
+
+/// Returns the correct read prompt.
+#define BC_VM_READ_PROMPT (BC_IS_BC ? "read> " : "?> ")
+
+/// Returns the string for the line length environment variable.
+#define BC_VM_LINE_LENGTH_STR (BC_IS_BC ? "BC_LINE_LENGTH" : "DC_LINE_LENGTH")
+
+/// Returns the string for the environment args environment variable.
+#define BC_VM_ENV_ARGS_STR (BC_IS_BC ? "BC_ENV_ARGS" : "DC_ENV_ARGS")
+
+/// Returns the string for the expression exit environment variable.
+#define BC_VM_EXPR_EXIT_STR (BC_IS_BC ? "BC_EXPR_EXIT" : "DC_EXPR_EXIT")
+
+/// Returns the default for the expression exit environment variable.
+#define BC_VM_EXPR_EXIT_DEF \
+ (BC_IS_BC ? BC_DEFAULT_EXPR_EXIT : DC_DEFAULT_EXPR_EXIT)
+
+/// Returns the string for the digit clamp environment variable.
+#define BC_VM_DIGIT_CLAMP_STR (BC_IS_BC ? "BC_DIGIT_CLAMP" : "DC_DIGIT_CLAMP")
+
+/// Returns the default for the digit clamp environment variable.
+#define BC_VM_DIGIT_CLAMP_DEF \
+ (BC_IS_BC ? BC_DEFAULT_DIGIT_CLAMP : DC_DEFAULT_DIGIT_CLAMP)
+
+/// Returns the string for the TTY mode environment variable.
+#define BC_VM_TTY_MODE_STR (BC_IS_BC ? "BC_TTY_MODE" : "DC_TTY_MODE")
+
+/// Returns the default for the TTY mode environment variable.
+#define BC_VM_TTY_MODE_DEF \
+ (BC_IS_BC ? BC_DEFAULT_TTY_MODE : DC_DEFAULT_TTY_MODE)
+
+/// Returns the string for the prompt environment variable.
+#define BC_VM_PROMPT_STR (BC_IS_BC ? "BC_PROMPT" : "DC_PROMPT")
+
+/// Returns the default for the prompt environment variable.
+#define BC_VM_PROMPT_DEF (BC_IS_BC ? BC_DEFAULT_PROMPT : DC_DEFAULT_PROMPT)
+
+/// Returns the string for the SIGINT reset environment variable.
+#define BC_VM_SIGINT_RESET_STR \
+ (BC_IS_BC ? "BC_SIGINT_RESET" : "DC_SIGINT_RESET")
+
+/// Returns the string for the SIGINT reset environment variable.
+#define BC_VM_SIGINT_RESET_DEF \
+ (BC_IS_BC ? BC_DEFAULT_SIGINT_RESET : DC_DEFAULT_SIGINT_RESET)
+
+/// Returns true if the calculator should run stdin.
+#define BC_VM_RUN_STDIN(has_file) (BC_IS_BC || !(has_file))
#else // DC_ENABLED
@@ -247,6 +296,48 @@
/// Returns true if dc is running.
#define BC_IS_DC (0)
+/// Returns the correct read prompt.
+#define BC_VM_READ_PROMPT ("read> ")
+
+/// Returns the string for the line length environment variable.
+#define BC_VM_LINE_LENGTH_STR ("BC_LINE_LENGTH")
+
+/// Returns the string for the environment args environment variable.
+#define BC_VM_ENV_ARGS_STR ("BC_ENV_ARGS")
+
+/// Returns the string for the expression exit environment variable.
+#define BC_VM_EXPR_EXIT_STR ("BC_EXPR_EXIT")
+
+/// Returns the default for the expression exit environment variable.
+#define BC_VM_EXPR_EXIT_DEF (BC_DEFAULT_EXPR_EXIT)
+
+/// Returns the string for the digit clamp environment variable.
+#define BC_VM_DIGIT_CLAMP_STR ("BC_DIGIT_CLAMP")
+
+/// Returns the default for the digit clamp environment variable.
+#define BC_VM_DIGIT_CLAMP_DEF (BC_DEFAULT_DIGIT_CLAMP)
+
+/// Returns the string for the TTY mode environment variable.
+#define BC_VM_TTY_MODE_STR ("BC_TTY_MODE")
+
+/// Returns the default for the TTY mode environment variable.
+#define BC_VM_TTY_MODE_DEF (BC_DEFAULT_TTY_MODE)
+
+/// Returns the string for the prompt environment variable.
+#define BC_VM_PROMPT_STR ("BC_PROMPT")
+
+/// Returns the default for the SIGINT reset environment variable.
+#define BC_VM_PROMPT_DEF (BC_DEFAULT_PROMPT)
+
+/// Returns the string for the SIGINT reset environment variable.
+#define BC_VM_SIGINT_RESET_STR ("BC_SIGINT_RESET")
+
+/// Returns the string for the SIGINT reset environment variable.
+#define BC_VM_SIGINT_RESET_DEF (BC_DEFAULT_SIGINT_RESET)
+
+/// Returns true if the calculator should run stdin.
+#define BC_VM_RUN_STDIN(has_file) (BC_IS_BC)
+
#endif // DC_ENABLED
#else // BC_ENABLED
@@ -260,6 +351,48 @@
/// Returns true if dc is running.
#define BC_IS_DC (1)
+/// Returns the correct read prompt.
+#define BC_VM_READ_PROMPT ("?> ")
+
+/// Returns the string for the line length environment variable.
+#define BC_VM_LINE_LENGTH_STR ("DC_LINE_LENGTH")
+
+/// Returns the string for the environment args environment variable.
+#define BC_VM_ENV_ARGS_STR ("DC_ENV_ARGS")
+
+/// Returns the string for the expression exit environment variable.
+#define BC_VM_EXPR_EXIT_STR ("DC_EXPR_EXIT")
+
+/// Returns the default for the expression exit environment variable.
+#define BC_VM_EXPR_EXIT_DEF (DC_DEFAULT_EXPR_EXIT)
+
+/// Returns the string for the digit clamp environment variable.
+#define BC_VM_DIGIT_CLAMP_STR ("DC_DIGIT_CLAMP")
+
+/// Returns the default for the digit clamp environment variable.
+#define BC_VM_DIGIT_CLAMP_DEF (DC_DEFAULT_DIGIT_CLAMP)
+
+/// Returns the string for the TTY mode environment variable.
+#define BC_VM_TTY_MODE_STR ("DC_TTY_MODE")
+
+/// Returns the default for the TTY mode environment variable.
+#define BC_VM_TTY_MODE_DEF (DC_DEFAULT_TTY_MODE)
+
+/// Returns the string for the prompt environment variable.
+#define BC_VM_PROMPT_STR ("DC_PROMPT")
+
+/// Returns the default for the SIGINT reset environment variable.
+#define BC_VM_PROMPT_DEF (DC_DEFAULT_PROMPT)
+
+/// Returns the string for the SIGINT reset environment variable.
+#define BC_VM_SIGINT_RESET_STR ("DC_SIGINT_RESET")
+
+/// Returns the string for the SIGINT reset environment variable.
+#define BC_VM_SIGINT_RESET_DEF (DC_DEFAULT_SIGINT_RESET)
+
+/// Returns true if the calculator should run stdin.
+#define BC_VM_RUN_STDIN(has_file) (!(has_file))
+
#endif // BC_ENABLED
/// A convenience macro for checking if the prompt is enabled.
@@ -267,7 +400,9 @@
#else // !BC_ENABLE_LIBRARY
-#define BC_Z (vm.leading_zeroes)
+#define BC_Z (vm->leading_zeroes)
+
+#define BC_DIGIT_CLAMP (vm->digit_clamp)
#endif // !BC_ENABLE_LIBRARY
@@ -437,18 +572,14 @@ typedef struct BcVm
/// Whether or not to print leading zeros.
bool leading_zeroes;
+ /// Whether or not to clamp digits that are greater than or equal to the
+ /// current ibase.
+ bool digit_clamp;
+
/// The number of "references," or times that the library was initialized.
unsigned int refs;
- /// Non-zero if bcl is running. This is volatile sig_atomic_t because it is
- /// also used in the signal handler. See the development manual
- /// (manuals/development.md#async-signal-safe-signal-handling) for more
- /// information.
- volatile sig_atomic_t running;
-
-#endif // BC_ENABLE_LIBRARY
-
-#if !BC_ENABLE_LIBRARY
+#else // BC_ENABLE_LIBRARY
/// A pointer to the filename of the current file. This is not owned by the
/// BcVm struct.
@@ -457,8 +588,6 @@ typedef struct BcVm
/// The message printed when SIGINT happens.
const char* sigmsg;
-#endif // !BC_ENABLE_LIBRARY
-
/// Non-zero when signals are "locked." This is volatile sig_atomic_t
/// because it is also used in the signal handler. See the development
/// manual (manuals/development.md#async-signal-safe-signal-handling) for
@@ -472,8 +601,6 @@ typedef struct BcVm
/// information.
volatile sig_atomic_t sig;
-#if !BC_ENABLE_LIBRARY
-
/// The length of sigmsg.
uchar siglen;
@@ -504,6 +631,10 @@ typedef struct BcVm
/// True if bc is currently reading from stdin.
bool is_stdin;
+ /// True if bc should clear its buffers. This is BcVm to fill a hole and
+ /// also to avoid clobber warnings from GCC.
+ bool clear;
+
#if BC_ENABLED
/// True if keywords should not be redefined. This is only true for the
@@ -512,13 +643,6 @@ typedef struct BcVm
#endif // BC_ENABLED
-#endif // !BC_ENABLE_LIBRARY
-
- /// An array of maxes for the globals.
- BcBigDig maxes[BC_PROG_GLOBALS_LEN + BC_ENABLE_EXTRA_MATH];
-
-#if !BC_ENABLE_LIBRARY
-
/// A vector of filenames to process.
BcVec files;
@@ -562,7 +686,10 @@ typedef struct BcVm
const char* locale;
#endif // BC_ENABLE_NLS
-#endif // !BC_ENABLE_LIBRARY
+#endif // BC_ENABLE_LIBRARY
+
+ /// An array of maxes for the globals.
+ BcBigDig maxes[BC_PROG_GLOBALS_LEN + BC_ENABLE_EXTRA_MATH];
/// The last base used to parse.
BcBigDig last_base;
@@ -652,6 +779,8 @@ typedef struct BcVm
#endif // BC_ENABLED
#endif // !BC_ENABLE_LIBRARY
+ BcDig* temps_buf[BC_VM_MAX_TEMPS];
+
#if BC_DEBUG_CODE
/// The depth for BC_FUNC_ENTER and BC_FUNC_EXIT.
@@ -697,13 +826,21 @@ void
bc_vm_addTemp(BcDig* num);
/**
- * Dish out a temp, or NULL if there are none.
+ * Return the temp on the top of the temp stack, or NULL if there are none.
* @return A temp, or NULL if none exist.
*/
BcDig*
bc_vm_takeTemp(void);
/**
+ * Gets the top temp of the temp stack. This is separate from bc_vm_takeTemp()
+ * to quiet a GCC warning about longjmp() clobbering in bc_num_init().
+ * @return A temp, or NULL if none exist.
+ */
+BcDig*
+bc_vm_getTemp(void);
+
+/**
* Frees all temporaries.
*/
void
@@ -715,7 +852,12 @@ bc_vm_freeTemps(void);
* Erases the flush argument if history does not exist because it does not
* matter if history does not exist.
*/
-#define bc_vm_putchar(c, t) bc_vm_putchar(c)
+#define bc_vm_putchar(c, t) bc_vm_putchar_impl(c)
+
+#else // !BC_ENABLE_HISTORY || BC_ENABLE_LINE_LIB
+
+// This is here to satisfy a clang warning about recursive macros.
+#define bc_vm_putchar(c, t) bc_vm_putchar_impl(c, t)
#endif // !BC_ENABLE_HISTORY || BC_ENABLE_LINE_LIB
@@ -921,10 +1063,17 @@ extern const char bc_pledge_end_history[];
/// A reference to the end pledge() promises when *not* using history.
extern const char bc_pledge_end[];
+#if !BC_ENABLE_LIBRARY
+
/// A reference to the global data.
-extern BcVm vm;
+extern BcVm* vm;
+
+/// The global data.
+extern BcVm vm_data;
/// A reference to the global output buffers.
extern char output_bufs[BC_VM_BUF_SIZE];
+#endif // !BC_ENABLE_LIBRARY
+
#endif // BC_VM_H
diff --git a/manuals/algorithms.md b/manuals/algorithms.md
index ef6b6d99a657..4d7a0edc54c4 100644
--- a/manuals/algorithms.md
+++ b/manuals/algorithms.md
@@ -178,7 +178,7 @@ to calculate the bessel when `x < 0`, It has a complexity of `O(n^3)`.
their calculations with the precision (`scale`) set to at least 1 greater than
is needed.
-### Modular Exponentiation (`dc` Only)
+### Modular Exponentiation
This `dc` uses the [Memory-efficient method][8] to compute modular
exponentiation. The complexity is `O(e*n^2)`, which may initially seem
diff --git a/manuals/bc/A.1 b/manuals/bc/A.1
index f19ed3c9ac78..9e612f680132 100644
--- a/manuals/bc/A.1
+++ b/manuals/bc/A.1
@@ -25,7 +25,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.TH "BC" "1" "June 2022" "Gavin D. Howard" "General Commands Manual"
+.TH "BC" "1" "August 2022" "Gavin D. Howard" "General Commands Manual"
.nh
.ad l
.SH NAME
@@ -33,24 +33,25 @@
bc - arbitrary-precision decimal arithmetic language and calculator
.SH SYNOPSIS
.PP
-\f[B]bc\f[R] [\f[B]-ghilPqRsvVw\f[R]] [\f[B]--global-stacks\f[R]]
+\f[B]bc\f[R] [\f[B]-cCghilPqRsvVw\f[R]] [\f[B]--digit-clamp\f[R]]
+[\f[B]--no-digit-clamp\f[R]] [\f[B]--global-stacks\f[R]]
[\f[B]--help\f[R]] [\f[B]--interactive\f[R]] [\f[B]--mathlib\f[R]]
[\f[B]--no-prompt\f[R]] [\f[B]--no-read-prompt\f[R]] [\f[B]--quiet\f[R]]
[\f[B]--standard\f[R]] [\f[B]--warn\f[R]] [\f[B]--version\f[R]]
[\f[B]-e\f[R] \f[I]expr\f[R]]
-[\f[B]--expression\f[R]=\f[I]expr\f[R]\&...] [\f[B]-f\f[R]
-\f[I]file\f[R]\&...] [\f[B]--file\f[R]=\f[I]file\f[R]\&...]
-[\f[I]file\f[R]\&...] [\f[B]-I\f[R] \f[I]ibase\f[R]]
-[\f[B]--ibase\f[R]=\f[I]ibase\f[R]] [\f[B]-O\f[R] \f[I]obase\f[R]]
-[\f[B]--obase\f[R]=\f[I]obase\f[R]] [\f[B]-S\f[R] \f[I]scale\f[R]]
-[\f[B]--scale\f[R]=\f[I]scale\f[R]] [\f[B]-E\f[R] \f[I]seed\f[R]]
-[\f[B]--seed\f[R]=\f[I]seed\f[R]]
+[\f[B]--expression\f[R]=\f[I]expr\f[R]\&...]
+[\f[B]-f\f[R] \f[I]file\f[R]\&...]
+[\f[B]--file\f[R]=\f[I]file\f[R]\&...]
+[\f[I]file\f[R]\&...]
+[\f[B]-I\f[R] \f[I]ibase\f[R]] [\f[B]--ibase\f[R]=\f[I]ibase\f[R]]
+[\f[B]-O\f[R] \f[I]obase\f[R]] [\f[B]--obase\f[R]=\f[I]obase\f[R]]
+[\f[B]-S\f[R] \f[I]scale\f[R]] [\f[B]--scale\f[R]=\f[I]scale\f[R]]
+[\f[B]-E\f[R] \f[I]seed\f[R]] [\f[B]--seed\f[R]=\f[I]seed\f[R]]
.SH DESCRIPTION
.PP
bc(1) is an interactive processor for a language first standardized in
1991 by POSIX.
-(The current standard is at
-https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html .)
+(See the \f[B]STANDARDS\f[R] section.)
The language provides unlimited precision decimal arithmetic and is
somewhat C-like, but there are differences.
Such differences will be noted in this document.
@@ -79,6 +80,102 @@ See the \f[B]BUGS\f[R] section.
.PP
The following are the options that bc(1) accepts.
.TP
+\f[B]-C\f[R], \f[B]--no-digit-clamp\f[R]
+Disables clamping of digits greater than or equal to the current
+\f[B]ibase\f[R] when parsing numbers.
+.RS
+.PP
+This means that the value added to a number from a digit is always that
+digit\[cq]s value multiplied by the value of ibase raised to the power
+of the digit\[cq]s position, which starts from 0 at the least
+significant digit.
+.PP
+If this and/or the \f[B]-c\f[R] or \f[B]--digit-clamp\f[R] options are
+given multiple times, the last one given is used.
+.PP
+This option overrides the \f[B]BC_DIGIT_CLAMP\f[R] environment variable
+(see the \f[B]ENVIRONMENT VARIABLES\f[R] section) and the default, which
+can be queried with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
+\f[B]-c\f[R], \f[B]--digit-clamp\f[R]
+Enables clamping of digits greater than or equal to the current
+\f[B]ibase\f[R] when parsing numbers.
+.RS
+.PP
+This means that digits that the value added to a number from a digit
+that is greater than or equal to the ibase is the value of ibase minus 1
+all multiplied by the value of ibase raised to the power of the
+digit\[cq]s position, which starts from 0 at the least significant
+digit.
+.PP
+If this and/or the \f[B]-C\f[R] or \f[B]--no-digit-clamp\f[R] options
+are given multiple times, the last one given is used.
+.PP
+This option overrides the \f[B]BC_DIGIT_CLAMP\f[R] environment variable
+(see the \f[B]ENVIRONMENT VARIABLES\f[R] section) and the default, which
+can be queried with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
+\f[B]-E\f[R] \f[I]seed\f[R], \f[B]--seed\f[R]=\f[I]seed\f[R]
+Sets the builtin variable \f[B]seed\f[R] to the value \f[I]seed\f[R]
+assuming that \f[I]seed\f[R] is in base 10.
+It is a fatal error if \f[I]seed\f[R] is not a valid number.
+.RS
+.PP
+If multiple instances of this option are given, the last is used.
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
+\f[B]-e\f[R] \f[I]expr\f[R], \f[B]--expression\f[R]=\f[I]expr\f[R]
+Evaluates \f[I]expr\f[R].
+If multiple expressions are given, they are evaluated in order.
+If files are given as well (see the \f[B]-f\f[R] and \f[B]--file\f[R]
+options), 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.
+.RS
+.PP
+If this option is given on the command-line (i.e., not in
+\f[B]BC_ENV_ARGS\f[R], see the \f[B]ENVIRONMENT VARIABLES\f[R] section),
+then after processing all expressions and files, bc(1) will exit, unless
+\f[B]-\f[R] (\f[B]stdin\f[R]) was given as an argument at least once to
+\f[B]-f\f[R] or \f[B]--file\f[R], whether on the command-line or in
+\f[B]BC_ENV_ARGS\f[R].
+However, if any other \f[B]-e\f[R], \f[B]--expression\f[R],
+\f[B]-f\f[R], or \f[B]--file\f[R] arguments are given after
+\f[B]-f-\f[R] or equivalent is given, bc(1) will give a fatal error and
+exit.
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
+\f[B]-f\f[R] \f[I]file\f[R], \f[B]--file\f[R]=\f[I]file\f[R]
+Reads in \f[I]file\f[R] and evaluates it, line by line, as though it
+were read through \f[B]stdin\f[R].
+If expressions are also given (see the \f[B]-e\f[R] and
+\f[B]--expression\f[R] options), the expressions are evaluated in the
+order given.
+.RS
+.PP
+If this option is given on the command-line (i.e., not in
+\f[B]BC_ENV_ARGS\f[R], see the \f[B]ENVIRONMENT VARIABLES\f[R] section),
+then after processing all expressions and files, bc(1) will exit, unless
+\f[B]-\f[R] (\f[B]stdin\f[R]) was given as an argument at least once to
+\f[B]-f\f[R] or \f[B]--file\f[R].
+However, if any other \f[B]-e\f[R], \f[B]--expression\f[R],
+\f[B]-f\f[R], or \f[B]--file\f[R] arguments are given after
+\f[B]-f-\f[R] or equivalent is given, bc(1) will give a fatal error and
+exit.
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
\f[B]-g\f[R], \f[B]--global-stacks\f[R]
Turns the globals \f[B]ibase\f[R], \f[B]obase\f[R], \f[B]scale\f[R], and
\f[B]seed\f[R] into stacks.
@@ -172,7 +269,18 @@ This is a \f[B]non-portable extension\f[R].
.RE
.TP
\f[B]-h\f[R], \f[B]--help\f[R]
-Prints a usage message and quits.
+Prints a usage message and exits.
+.TP
+\f[B]-I\f[R] \f[I]ibase\f[R], \f[B]--ibase\f[R]=\f[I]ibase\f[R]
+Sets the builtin variable \f[B]ibase\f[R] to the value \f[I]ibase\f[R]
+assuming that \f[I]ibase\f[R] is in base 10.
+It is a fatal error if \f[I]ibase\f[R] is not a valid number.
+.RS
+.PP
+If multiple instances of this option are given, the last is used.
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
.TP
\f[B]-i\f[R], \f[B]--interactive\f[R]
Forces interactive mode.
@@ -202,11 +310,23 @@ command line.
To learn what is in the libraries, see the \f[B]LIBRARY\f[R] section.
.RE
.TP
+\f[B]-O\f[R] \f[I]obase\f[R], \f[B]--obase\f[R]=\f[I]obase\f[R]
+Sets the builtin variable \f[B]obase\f[R] to the value \f[I]obase\f[R]
+assuming that \f[I]obase\f[R] is in base 10.
+It is a fatal error if \f[I]obase\f[R] is not a valid number.
+.RS
+.PP
+If multiple instances of this option are given, the last is used.
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
\f[B]-P\f[R], \f[B]--no-prompt\f[R]
Disables the prompt in TTY mode.
(The prompt is only enabled in TTY mode.
-See the \f[B]TTY MODE\f[R] section.) This is mostly for those users that
-do not want a prompt or are not used to having them in bc(1).
+See the \f[B]TTY MODE\f[R] 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
\f[B]BC_ENV_ARGS\f[R] (see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
.RS
@@ -217,11 +337,28 @@ environment variables (see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
This is a \f[B]non-portable extension\f[R].
.RE
.TP
+\f[B]-q\f[R], \f[B]--quiet\f[R]
+This option is for compatibility with the GNU bc(1)
+(https://www.gnu.org/software/bc/); 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
+\f[B]-v\f[R], \f[B]-V\f[R], or \f[B]--version\f[R] options are given
+unless the \f[B]BC_BANNER\f[R] environment variable is set and contains
+a non-zero integer or if this bc(1) was built with the header displayed
+by default.
+If \f[I]any\f[R] of that is the case, then this option \f[I]does\f[R]
+prevent bc(1) from printing the header.
+.RS
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
\f[B]-R\f[R], \f[B]--no-read-prompt\f[R]
Disables the read prompt in TTY mode.
(The read prompt is only enabled in TTY mode.
-See the \f[B]TTY MODE\f[R] section.) This is mostly for those users that
-do not want a read prompt or are not used to having them in bc(1).
+See the \f[B]TTY MODE\f[R] 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
\f[B]BC_ENV_ARGS\f[R] (see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
This option is also useful in hash bang lines of bc(1) scripts that
@@ -294,38 +431,32 @@ Keywords are \f[I]not\f[R] redefined when parsing the builtin math
library (see the \f[B]LIBRARY\f[R] section).
.PP
It is a fatal error to redefine keywords mandated by the POSIX standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html).
+(see the \f[B]STANDARDS\f[R] section).
It is a fatal error to attempt to redefine words that this bc(1) does
not reserve as keywords.
.RE
.TP
-\f[B]-q\f[R], \f[B]--quiet\f[R]
-This option is for compatibility with the GNU bc(1)
-(https://www.gnu.org/software/bc/); 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
-\f[B]-v\f[R], \f[B]-V\f[R], or \f[B]--version\f[R] options are given
-unless the \f[B]BC_BANNER\f[R] environment variable is set and contains
-a non-zero integer or if this bc(1) was built with the header displayed
-by default.
-If \f[I]any\f[R] of that is the case, then this option \f[I]does\f[R]
-prevent bc(1) from printing the header.
+\f[B]-S\f[R] \f[I]scale\f[R], \f[B]--scale\f[R]=\f[I]scale\f[R]
+Sets the builtin variable \f[B]scale\f[R] to the value \f[I]scale\f[R]
+assuming that \f[I]scale\f[R] is in base 10.
+It is a fatal error if \f[I]scale\f[R] is not a valid number.
.RS
.PP
+If multiple instances of this option are given, the last is used.
+.PP
This is a \f[B]non-portable extension\f[R].
.RE
.TP
\f[B]-s\f[R], \f[B]--standard\f[R]
-Process exactly the language defined by the standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html) and
-error if any extensions are used.
+Process exactly the language defined by the standard (see the
+\f[B]STANDARDS\f[R] section) and error if any extensions are used.
.RS
.PP
This is a \f[B]non-portable extension\f[R].
.RE
.TP
\f[B]-v\f[R], \f[B]-V\f[R], \f[B]--version\f[R]
-Print the version information (copyright header) and exit.
+Print the version information (copyright header) and exits.
.RS
.PP
This is a \f[B]non-portable extension\f[R].
@@ -351,93 +482,6 @@ extended math library (see the \f[B]LIBRARY\f[R] section).
.PP
This is a \f[B]non-portable extension\f[R].
.RE
-.TP
-\f[B]-e\f[R] \f[I]expr\f[R], \f[B]--expression\f[R]=\f[I]expr\f[R]
-Evaluates \f[I]expr\f[R].
-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.
-.RS
-.PP
-If this option is given on the command-line (i.e., not in
-\f[B]BC_ENV_ARGS\f[R], see the \f[B]ENVIRONMENT VARIABLES\f[R] section),
-then after processing all expressions and files, bc(1) will exit, unless
-\f[B]-\f[R] (\f[B]stdin\f[R]) was given as an argument at least once to
-\f[B]-f\f[R] or \f[B]--file\f[R], whether on the command-line or in
-\f[B]BC_ENV_ARGS\f[R].
-However, if any other \f[B]-e\f[R], \f[B]--expression\f[R],
-\f[B]-f\f[R], or \f[B]--file\f[R] arguments are given after
-\f[B]-f-\f[R] or equivalent is given, bc(1) will give a fatal error and
-exit.
-.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
-.TP
-\f[B]-f\f[R] \f[I]file\f[R], \f[B]--file\f[R]=\f[I]file\f[R]
-Reads in \f[I]file\f[R] and evaluates it, line by line, as though it
-were read through \f[B]stdin\f[R].
-If expressions are also given (see above), the expressions are evaluated
-in the order given.
-.RS
-.PP
-If this option is given on the command-line (i.e., not in
-\f[B]BC_ENV_ARGS\f[R], see the \f[B]ENVIRONMENT VARIABLES\f[R] section),
-then after processing all expressions and files, bc(1) will exit, unless
-\f[B]-\f[R] (\f[B]stdin\f[R]) was given as an argument at least once to
-\f[B]-f\f[R] or \f[B]--file\f[R].
-However, if any other \f[B]-e\f[R], \f[B]--expression\f[R],
-\f[B]-f\f[R], or \f[B]--file\f[R] arguments are given after
-\f[B]-f-\f[R] or equivalent is given, bc(1) will give a fatal error and
-exit.
-.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
-.TP
-\f[B]-I\f[R] \f[I]ibase\f[R], \f[B]--ibase\f[R]=\f[I]ibase\f[R]
-Sets the builtin variable \f[B]ibase\f[R] to the value \f[I]ibase\f[R]
-assuming that \f[I]ibase\f[R] is in base 10.
-It is a fatal error if \f[I]ibase\f[R] is not a valid number.
-.RS
-.PP
-If multiple instances of this option are given, the last is used.
-.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
-.TP
-\f[B]-O\f[R] \f[I]obase\f[R], \f[B]--obase\f[R]=\f[I]obase\f[R]
-Sets the builtin variable \f[B]obase\f[R] to the value \f[I]obase\f[R]
-assuming that \f[I]obase\f[R] is in base 10.
-It is a fatal error if \f[I]obase\f[R] is not a valid number.
-.RS
-.PP
-If multiple instances of this option are given, the last is used.
-.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
-.TP
-\f[B]-S\f[R] \f[I]scale\f[R], \f[B]--scale\f[R]=\f[I]scale\f[R]
-Sets the builtin variable \f[B]scale\f[R] to the value \f[I]scale\f[R]
-assuming that \f[I]scale\f[R] is in base 10.
-It is a fatal error if \f[I]scale\f[R] is not a valid number.
-.RS
-.PP
-If multiple instances of this option are given, the last is used.
-.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
-.TP
-\f[B]-E\f[R] \f[I]seed\f[R], \f[B]--seed\f[R]=\f[I]seed\f[R]
-Sets the builtin variable \f[B]seed\f[R] to the value \f[I]seed\f[R]
-assuming that \f[I]seed\f[R] is in base 10.
-It is a fatal error if \f[I]seed\f[R] is not a valid number.
-.RS
-.PP
-If multiple instances of this option are given, the last is used.
-.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
.PP
All long options are \f[B]non-portable extensions\f[R].
.SH STDIN
@@ -491,10 +535,9 @@ redirect \f[B]stderr\f[R] to \f[B]/dev/null\f[R].
.SH SYNTAX
.PP
The syntax for bc(1) programs is mostly C-like, with some differences.
-This bc(1) follows the POSIX standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html),
-which is a much more thorough resource for the language this bc(1)
-accepts.
+This bc(1) follows the POSIX standard (see the \f[B]STANDARDS\f[R]
+section), 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.
.PP
@@ -776,17 +819,49 @@ In any other case, use a non-seeded pseudo-random number generator.
Numbers are strings made up of digits, uppercase letters, and at most
\f[B]1\f[R] period for a radix.
Numbers can have up to \f[B]BC_NUM_MAX\f[R] digits.
-Uppercase letters are equal to \f[B]9\f[R] + their position in the
-alphabet (i.e., \f[B]A\f[R] equals \f[B]10\f[R], or \f[B]9+1\f[R]).
-If a digit or letter makes no sense with the current value of
-\f[B]ibase\f[R], they are set to the value of the highest valid digit in
-\f[B]ibase\f[R].
+Uppercase letters are equal to \f[B]9\f[R] plus their position in the
+alphabet, starting from \f[B]1\f[R] (i.e., \f[B]A\f[R] equals
+\f[B]10\f[R], or \f[B]9+1\f[R]).
.PP
-Single-character numbers (i.e., \f[B]A\f[R] alone) take the value that
-they would have if they were valid digits, regardless of the value of
-\f[B]ibase\f[R].
+If a digit or letter makes no sense with the current value of
+\f[B]ibase\f[R] (i.e., they are greater than or equal to the current
+value of \f[B]ibase\f[R]), then the behavior depends on the existence of
+the \f[B]-c\f[R]/\f[B]--digit-clamp\f[R] or
+\f[B]-C\f[R]/\f[B]--no-digit-clamp\f[R] options (see the
+\f[B]OPTIONS\f[R] section), the existence and setting of the
+\f[B]BC_DIGIT_CLAMP\f[R] environment variable (see the \f[B]ENVIRONMENT
+VARIABLES\f[R] section), or the default, which can be queried with the
+\f[B]-h\f[R]/\f[B]--help\f[R] option.
+.PP
+If clamping is off, then digits or letters that are greater than or
+equal to the current value of \f[B]ibase\f[R] are not changed.
+Instead, their given value is multiplied by the appropriate power of
+\f[B]ibase\f[R] and added into the number.
+This means that, with an \f[B]ibase\f[R] of \f[B]3\f[R], the number
+\f[B]AB\f[R] is equal to \f[B]3\[ha]1*A+3\[ha]0*B\f[R], which is
+\f[B]3\f[R] times \f[B]10\f[R] plus \f[B]11\f[R], or \f[B]41\f[R].
+.PP
+If clamping is on, then digits or letters that are greater than or equal
+to the current value of \f[B]ibase\f[R] are set to the value of the
+highest valid digit in \f[B]ibase\f[R] before being multiplied by the
+appropriate power of \f[B]ibase\f[R] and added into the number.
+This means that, with an \f[B]ibase\f[R] of \f[B]3\f[R], the number
+\f[B]AB\f[R] is equal to \f[B]3\[ha]1*2+3\[ha]0*2\f[R], which is
+\f[B]3\f[R] times \f[B]2\f[R] plus \f[B]2\f[R], or \f[B]8\f[R].
+.PP
+There is one exception to clamping: single-character numbers (i.e.,
+\f[B]A\f[R] alone).
+Such numbers are never clamped and always take the value they would have
+in the highest possible \f[B]ibase\f[R].
This means that \f[B]A\f[R] alone always equals decimal \f[B]10\f[R] and
\f[B]Z\f[R] alone always equals decimal \f[B]35\f[R].
+This behavior is mandated by the standard (see the STANDARDS section)
+and is meant to provide an easy way to set the current \f[B]ibase\f[R]
+(with the \f[B]i\f[R] command) regardless of the current value of
+\f[B]ibase\f[R].
+.PP
+If clamping is on, and the clamped value of a character is needed, use a
+leading zero, i.e., for \f[B]A\f[R], use \f[B]0A\f[R].
.PP
In addition, bc(1) accepts numbers in scientific notation.
These have the form \f[B]<number>e<integer>\f[R].
@@ -1076,8 +1151,7 @@ Note that unlike in C, these operators have a lower precedence than the
\f[B]assignment\f[R] operators, which means that \f[B]a=b>c\f[R] is
interpreted as \f[B](a=b)>c\f[R].
.PP
-Also, unlike the standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html)
+Also, unlike the standard (see the \f[B]STANDARDS\f[R] section)
requires, these operators can appear anywhere any other expressions can
be used.
This allowance is a \f[B]non-portable extension\f[R].
@@ -1109,8 +1183,8 @@ The following items are statements:
.IP " 1." 4
\f[B]E\f[R]
.IP " 2." 4
-\f[B]{\f[R] \f[B]S\f[R] \f[B];\f[R] \&... \f[B];\f[R] \f[B]S\f[R]
-\f[B]}\f[R]
+\f[B]{\f[R] \f[B]S\f[R] \f[B];\f[R] \&...
+\f[B];\f[R] \f[B]S\f[R] \f[B]}\f[R]
.IP " 3." 4
\f[B]if\f[R] \f[B](\f[R] \f[B]E\f[R] \f[B])\f[R] \f[B]S\f[R]
.IP " 4." 4
@@ -1136,9 +1210,11 @@ An empty statement
.IP "13." 4
A string of characters, enclosed in double quotes
.IP "14." 4
-\f[B]print\f[R] \f[B]E\f[R] \f[B],\f[R] \&... \f[B],\f[R] \f[B]E\f[R]
+\f[B]print\f[R] \f[B]E\f[R] \f[B],\f[R] \&...
+\f[B],\f[R] \f[B]E\f[R]
.IP "15." 4
-\f[B]stream\f[R] \f[B]E\f[R] \f[B],\f[R] \&... \f[B],\f[R] \f[B]E\f[R]
+\f[B]stream\f[R] \f[B]E\f[R] \f[B],\f[R] \&...
+\f[B],\f[R] \f[B]E\f[R]
.IP "16." 4
\f[B]I()\f[R], \f[B]I(E)\f[R], \f[B]I(E, E)\f[R], and so on, where
\f[B]I\f[R] is an identifier for a \f[B]void\f[R] function (see the
@@ -1384,9 +1460,8 @@ when the \f[B]-s\f[R] option, the \f[B]-w\f[R] option, or equivalents
are given.
.SS Standard Library
.PP
-The standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html)
-defines the following functions for the math library:
+The standard (see the \f[B]STANDARDS\f[R] section) defines the following
+functions for the math library:
.TP
\f[B]s(x)\f[R]
Returns the sine of \f[B]x\f[R], which is assumed to be in radians.
@@ -1441,8 +1516,7 @@ Functions\f[R] subsection below).
The extended library is \f[I]not\f[R] loaded when the
\f[B]-s\f[R]/\f[B]--standard\f[R] or \f[B]-w\f[R]/\f[B]--warn\f[R]
options are given since they are not part of the library defined by the
-standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html).
+standard (see the \f[B]STANDARDS\f[R] section).
.PP
The extended library is a \f[B]non-portable extension\f[R].
.TP
@@ -2501,7 +2575,8 @@ at which they become a problem.
In fact, memory should be exhausted before these limits should be hit.
.SH ENVIRONMENT VARIABLES
.PP
-bc(1) recognizes the following environment variables:
+As \f[B]non-portable extensions\f[R], bc(1) recognizes the following
+environment variables:
.TP
\f[B]POSIXLY_CORRECT\f[R]
If this variable exists (no matter the contents), bc(1) behaves as if
@@ -2621,6 +2696,22 @@ expressions and expression files, and a zero value makes bc(1) not exit.
This environment variable overrides the default, which can be queried
with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
.RE
+.TP
+\f[B]BC_DIGIT_CLAMP\f[R]
+When parsing numbers and if this environment variable exists and
+contains an integer, a non-zero value makes bc(1) clamp digits that are
+greater than or equal to the current \f[B]ibase\f[R] so that all such
+digits are considered equal to the \f[B]ibase\f[R] minus 1, and a zero
+value disables such clamping so that those digits are always equal to
+their value, which is multiplied by the power of the \f[B]ibase\f[R].
+.RS
+.PP
+This never applies to single-digit numbers, as per the standard (see the
+\f[B]STANDARDS\f[R] section).
+.PP
+This environment variable overrides the default, which can be queried
+with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
+.RE
.SH EXIT STATUS
.PP
bc(1) returns the following exit statuses:
@@ -2702,9 +2793,8 @@ checking, and its normal behavior can be forced by using the
\f[B]-i\f[R] flag or \f[B]--interactive\f[R] option.
.SH INTERACTIVE MODE
.PP
-Per the standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html),
-bc(1) has an interactive mode and a non-interactive mode.
+Per the standard (see the \f[B]STANDARDS\f[R] section), bc(1) has an
+interactive mode and a non-interactive mode.
Interactive mode is turned on automatically when both \f[B]stdin\f[R]
and \f[B]stdout\f[R] are hooked to a terminal, but the \f[B]-i\f[R] flag
and \f[B]--interactive\f[R] option can turn it on in other situations.
@@ -2736,8 +2826,7 @@ The default setting can be queried with the \f[B]-h\f[R] or
\f[B]--help\f[R] options.
.PP
TTY mode is different from interactive mode because interactive mode is
-required in the bc(1) standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html),
+required in the bc(1) standard (see the \f[B]STANDARDS\f[R] section),
and interactive mode requires only \f[B]stdin\f[R] and \f[B]stdout\f[R]
to be connected to a terminal.
.SS Command-Line History
diff --git a/manuals/bc/A.1.md b/manuals/bc/A.1.md
index 6061260ee087..f4d0ad892a2b 100644
--- a/manuals/bc/A.1.md
+++ b/manuals/bc/A.1.md
@@ -34,15 +34,14 @@ 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*...] [**-I** *ibase*] [**-\-ibase**=*ibase*] [**-O** *obase*] [**-\-obase**=*obase*] [**-S** *scale*] [**-\-scale**=*scale*] [**-E** *seed*] [**-\-seed**=*seed*]
+**bc** [**-cCghilPqRsvVw**] [**-\-digit-clamp**] [**-\-no-digit-clamp**] [**-\-global-stacks**] [**-\-help**] [**-\-interactive**] [**-\-mathlib**] [**-\-no-prompt**] [**-\-no-read-prompt**] [**-\-quiet**] [**-\-standard**] [**-\-warn**] [**-\-version**] [**-e** *expr*] [**-\-expression**=*expr*...] [**-f** *file*...] [**-\-file**=*file*...] [*file*...] [**-I** *ibase*] [**-\-ibase**=*ibase*] [**-O** *obase*] [**-\-obase**=*obase*] [**-S** *scale*] [**-\-scale**=*scale*] [**-E** *seed*] [**-\-seed**=*seed*]
# DESCRIPTION
bc(1) is an interactive processor for a language first standardized in 1991 by
-POSIX. (The current standard is at
-https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html .) The
-language provides unlimited precision decimal arithmetic and is somewhat C-like,
-but there are differences. Such differences will be noted in this document.
+POSIX. (See the **STANDARDS** section.) 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**.
@@ -64,6 +63,86 @@ that is a bug and should be reported. See the **BUGS** section.
The following are the options that bc(1) accepts.
+**-C**, **-\-no-digit-clamp**
+
+: Disables clamping of digits greater than or equal to the current **ibase**
+ when parsing numbers.
+
+ This means that the value added to a number from a digit is always that
+ digit's value multiplied by the value of ibase raised to the power of the
+ digit's position, which starts from 0 at the least significant digit.
+
+ If this and/or the **-c** or **-\-digit-clamp** options are given multiple
+ times, the last one given is used.
+
+ This option overrides the **BC_DIGIT_CLAMP** environment variable (see the
+ **ENVIRONMENT VARIABLES** section) and the default, which can be queried
+ with the **-h** or **-\-help** options.
+
+ This is a **non-portable extension**.
+
+**-c**, **-\-digit-clamp**
+
+: Enables clamping of digits greater than or equal to the current **ibase**
+ when parsing numbers.
+
+ This means that digits that the value added to a number from a digit that is
+ greater than or equal to the ibase is the value of ibase minus 1 all
+ multiplied by the value of ibase raised to the power of the digit's
+ position, which starts from 0 at the least significant digit.
+
+ If this and/or the **-C** or **-\-no-digit-clamp** options are given
+ multiple times, the last one given is used.
+
+ This option overrides the **BC_DIGIT_CLAMP** environment variable (see the
+ **ENVIRONMENT VARIABLES** section) and the default, which can be queried
+ with the **-h** or **-\-help** options.
+
+ This is a **non-portable extension**.
+
+**-E** *seed*, **-\-seed**=*seed*
+
+: Sets the builtin variable **seed** to the value *seed* assuming that *seed*
+ is in base 10. It is a fatal error if *seed* is not a valid number.
+
+ If multiple instances of this option are given, the last is used.
+
+ 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 the **-f** and **-\-file** options),
+ 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 the **-e** and
+ **-\-expression** options), 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**.
+
**-g**, **-\-global-stacks**
: Turns the globals **ibase**, **obase**, **scale**, and **seed** into stacks.
@@ -134,7 +213,16 @@ The following are the options that bc(1) accepts.
**-h**, **-\-help**
-: Prints a usage message and quits.
+: Prints a usage message and exits.
+
+**-I** *ibase*, **-\-ibase**=*ibase*
+
+: Sets the builtin variable **ibase** to the value *ibase* assuming that
+ *ibase* is in base 10. It is a fatal error if *ibase* is not a valid number.
+
+ If multiple instances of this option are given, the last is used.
+
+ This is a **non-portable extension**.
**-i**, **-\-interactive**
@@ -158,6 +246,15 @@ The following are the options that bc(1) accepts.
To learn what is in the libraries, see the **LIBRARY** section.
+**-O** *obase*, **-\-obase**=*obase*
+
+: Sets the builtin variable **obase** to the value *obase* assuming that
+ *obase* is in base 10. It is a fatal error if *obase* is not a valid number.
+
+ If multiple instances of this option are given, the last is used.
+
+ This is a **non-portable extension**.
+
**-P**, **-\-no-prompt**
: Disables the prompt in TTY mode. (The prompt is only enabled in TTY mode.
@@ -171,6 +268,19 @@ The following are the options that bc(1) accepts.
This is a **non-portable extension**.
+**-q**, **-\-quiet**
+
+: This option is for compatibility with the GNU bc(1)
+ (https://www.gnu.org/software/bc/); 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
+ unless the **BC_BANNER** environment variable is set and contains a non-zero
+ integer or if this bc(1) was built with the header displayed by default. If
+ *any* of that is the case, then this option *does* prevent bc(1) from
+ printing the header.
+
+ This is a **non-portable extension**.
+
**-R**, **-\-no-read-prompt**
: Disables the read prompt in TTY mode. (The read prompt is only enabled in
@@ -224,35 +334,29 @@ The following are the options that bc(1) accepts.
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
- (https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html). It is
- a fatal error to attempt to redefine words that this bc(1) does not reserve
- as keywords.
+ It is a fatal error to redefine keywords mandated by the POSIX standard (see
+ the **STANDARDS** section). It is a fatal error to attempt to redefine words
+ that this bc(1) does not reserve as keywords.
-**-q**, **-\-quiet**
+**-S** *scale*, **-\-scale**=*scale*
-: This option is for compatibility with the GNU bc(1)
- (https://www.gnu.org/software/bc/); 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
- unless the **BC_BANNER** environment variable is set and contains a non-zero
- integer or if this bc(1) was built with the header displayed by default. If
- *any* of that is the case, then this option *does* prevent bc(1) from
- printing the header.
+: Sets the builtin variable **scale** to the value *scale* assuming that
+ *scale* is in base 10. It is a fatal error if *scale* is not a valid number.
+
+ If multiple instances of this option are given, the last is used.
This is a **non-portable extension**.
**-s**, **-\-standard**
-: Process exactly the language defined by the standard
- (https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html) and
- error if any extensions are used.
+: Process exactly the language defined by the standard (see the **STANDARDS**
+ section) and error if any extensions are used.
This is a **non-portable extension**.
**-v**, **-V**, **-\-version**
-: Print the version information (copyright header) and exit.
+: Print the version information (copyright header) and exits.
This is a **non-portable extension**.
@@ -274,74 +378,6 @@ The following are the options that bc(1) accepts.
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**.
-
-**-I** *ibase*, **-\-ibase**=*ibase*
-
-: Sets the builtin variable **ibase** to the value *ibase* assuming that
- *ibase* is in base 10. It is a fatal error if *ibase* is not a valid number.
-
- If multiple instances of this option are given, the last is used.
-
- This is a **non-portable extension**.
-
-**-O** *obase*, **-\-obase**=*obase*
-
-: Sets the builtin variable **obase** to the value *obase* assuming that
- *obase* is in base 10. It is a fatal error if *obase* is not a valid number.
-
- If multiple instances of this option are given, the last is used.
-
- This is a **non-portable extension**.
-
-**-S** *scale*, **-\-scale**=*scale*
-
-: Sets the builtin variable **scale** to the value *scale* assuming that
- *scale* is in base 10. It is a fatal error if *scale* is not a valid number.
-
- If multiple instances of this option are given, the last is used.
-
- This is a **non-portable extension**.
-
-**-E** *seed*, **-\-seed**=*seed*
-
-: Sets the builtin variable **seed** to the value *seed* assuming that *seed*
- is in base 10. It is a fatal error if *seed* is not a valid number.
-
- If multiple instances of this option are given, the last is used.
-
- This is a **non-portable extension**.
-
All long options are **non-portable extensions**.
# STDIN
@@ -393,8 +429,7 @@ it is recommended that those scripts be changed to redirect **stderr** to
# SYNTAX
The syntax for bc(1) programs is mostly C-like, with some differences. This
-bc(1) follows the POSIX standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html), which is a
+bc(1) follows the POSIX standard (see the **STANDARDS** section), 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.
@@ -592,14 +627,40 @@ use a non-seeded pseudo-random number generator.
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**.
+letters are equal to **9** plus their position in the alphabet, starting from
+**1** (i.e., **A** equals **10**, or **9+1**).
+
+If a digit or letter makes no sense with the current value of **ibase** (i.e.,
+they are greater than or equal to the current value of **ibase**), then the
+behavior depends on the existence of the **-c**/**-\-digit-clamp** or
+**-C**/**-\-no-digit-clamp** options (see the **OPTIONS** section), the
+existence and setting of the **BC_DIGIT_CLAMP** environment variable (see the
+**ENVIRONMENT VARIABLES** section), or the default, which can be queried with
+the **-h**/**-\-help** option.
+
+If clamping is off, then digits or letters that are greater than or equal to the
+current value of **ibase** are not changed. Instead, their given value is
+multiplied by the appropriate power of **ibase** and added into the number. This
+means that, with an **ibase** of **3**, the number **AB** is equal to
+**3\^1\*A+3\^0\*B**, which is **3** times **10** plus **11**, or **41**.
+
+If clamping is on, then digits or letters that are greater than or equal to the
+current value of **ibase** are set to the value of the highest valid digit in
+**ibase** before being multiplied by the appropriate power of **ibase** and
+added into the number. This means that, with an **ibase** of **3**, the number
+**AB** is equal to **3\^1\*2+3\^0\*2**, which is **3** times **2** plus **2**,
+or **8**.
+
+There is one exception to clamping: single-character numbers (i.e., **A**
+alone). Such numbers are never clamped and always take the value they would have
+in the highest possible **ibase**. This means that **A** alone always equals
+decimal **10** and **Z** alone always equals decimal **35**. This behavior is
+mandated by the standard (see the STANDARDS section) and is meant to provide an
+easy way to set the current **ibase** (with the **i** command) regardless of the
+current value of **ibase**.
+
+If clamping is on, and the clamped value of a character is needed, use a leading
+zero, i.e., for **A**, use **0A**.
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
@@ -849,10 +910,9 @@ The operators will be described in more detail below.
**assignment** operators, which means that **a=b\>c** is interpreted as
**(a=b)\>c**.
- Also, unlike the standard
- (https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html)
- requires, these operators can appear anywhere any other expressions can be
- used. This allowance is a **non-portable extension**.
+ Also, unlike the standard (see the **STANDARDS** section) requires, these
+ operators can appear anywhere any other expressions can be used. This
+ allowance is a **non-portable extension**.
**&&**
@@ -1099,9 +1159,8 @@ equivalents are given.
## Standard Library
-The standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html) defines the
-following functions for the math library:
+The standard (see the **STANDARDS** section) defines the following functions for
+the math library:
**s(x)**
@@ -1149,8 +1208,7 @@ following functions for the math 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
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html).
+defined by the standard (see the **STANDARDS** section).
The extended library is a **non-portable extension**.
@@ -2085,7 +2143,8 @@ be hit.
# ENVIRONMENT VARIABLES
-bc(1) recognizes the following environment variables:
+As **non-portable extensions**, bc(1) recognizes the following environment
+variables:
**POSIXLY_CORRECT**
@@ -2191,6 +2250,21 @@ bc(1) recognizes the following environment variables:
This environment variable overrides the default, which can be queried with
the **-h** or **-\-help** options.
+**BC_DIGIT_CLAMP**
+
+: When parsing numbers and if this environment variable exists and contains an
+ integer, a non-zero value makes bc(1) clamp digits that are greater than or
+ equal to the current **ibase** so that all such digits are considered equal
+ to the **ibase** minus 1, and a zero value disables such clamping so that
+ those digits are always equal to their value, which is multiplied by the
+ power of the **ibase**.
+
+ This never applies to single-digit numbers, as per the standard (see the
+ **STANDARDS** section).
+
+ 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:
@@ -2266,12 +2340,10 @@ checking, and its normal behavior can be forced by using the **-i** flag or
# INTERACTIVE MODE
-Per the standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html), 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.
+Per the standard (see the **STANDARDS** section), 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
@@ -2297,10 +2369,8 @@ 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) standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html), and
-interactive mode requires only **stdin** and **stdout** to be connected to a
-terminal.
+in the bc(1) standard (see the **STANDARDS** section), and interactive mode
+requires only **stdin** and **stdout** to be connected to a terminal.
## Command-Line History
diff --git a/manuals/bc/E.1 b/manuals/bc/E.1
index d57b8b50c4af..d5e81268f801 100644
--- a/manuals/bc/E.1
+++ b/manuals/bc/E.1
@@ -25,7 +25,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.TH "BC" "1" "June 2022" "Gavin D. Howard" "General Commands Manual"
+.TH "BC" "1" "August 2022" "Gavin D. Howard" "General Commands Manual"
.nh
.ad l
.SH NAME
@@ -33,20 +33,21 @@
bc - arbitrary-precision decimal arithmetic language and calculator
.SH SYNOPSIS
.PP
-\f[B]bc\f[R] [\f[B]-ghilPqRsvVw\f[R]] [\f[B]--global-stacks\f[R]]
+\f[B]bc\f[R] [\f[B]-cCghilPqRsvVw\f[R]] [\f[B]--digit-clamp\f[R]]
+[\f[B]--no-digit-clamp\f[R]] [\f[B]--global-stacks\f[R]]
[\f[B]--help\f[R]] [\f[B]--interactive\f[R]] [\f[B]--mathlib\f[R]]
[\f[B]--no-prompt\f[R]] [\f[B]--no-read-prompt\f[R]] [\f[B]--quiet\f[R]]
[\f[B]--standard\f[R]] [\f[B]--warn\f[R]] [\f[B]--version\f[R]]
[\f[B]-e\f[R] \f[I]expr\f[R]]
-[\f[B]--expression\f[R]=\f[I]expr\f[R]\&...] [\f[B]-f\f[R]
-\f[I]file\f[R]\&...] [\f[B]--file\f[R]=\f[I]file\f[R]\&...]
+[\f[B]--expression\f[R]=\f[I]expr\f[R]\&...]
+[\f[B]-f\f[R] \f[I]file\f[R]\&...]
+[\f[B]--file\f[R]=\f[I]file\f[R]\&...]
[\f[I]file\f[R]\&...]
.SH DESCRIPTION
.PP
bc(1) is an interactive processor for a language first standardized in
1991 by POSIX.
-(The current standard is at
-https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html .)
+(See the \f[B]STANDARDS\f[R] section.)
The language provides unlimited precision decimal arithmetic and is
somewhat C-like, but there are differences.
Such differences will be noted in this document.
@@ -56,6 +57,8 @@ the command line and executes them before reading from \f[B]stdin\f[R].
.PP
This bc(1) is a drop-in replacement for \f[I]any\f[R] bc(1), including
(and especially) the GNU bc(1).
+It also has many extensions and extra features beyond other
+implementations.
.PP
\f[B]Note\f[R]: If running this bc(1) on \f[I]any\f[R] script meant for
another bc(1) gives a parse error, it is probably because a word this
@@ -73,6 +76,91 @@ See the \f[B]BUGS\f[R] section.
.PP
The following are the options that bc(1) accepts.
.TP
+\f[B]-C\f[R], \f[B]--no-digit-clamp\f[R]
+Disables clamping of digits greater than or equal to the current
+\f[B]ibase\f[R] when parsing numbers.
+.RS
+.PP
+This means that the value added to a number from a digit is always that
+digit\[cq]s value multiplied by the value of ibase raised to the power
+of the digit\[cq]s position, which starts from 0 at the least
+significant digit.
+.PP
+If this and/or the \f[B]-c\f[R] or \f[B]--digit-clamp\f[R] options are
+given multiple times, the last one given is used.
+.PP
+This option overrides the \f[B]BC_DIGIT_CLAMP\f[R] environment variable
+(see the \f[B]ENVIRONMENT VARIABLES\f[R] section) and the default, which
+can be queried with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
+\f[B]-c\f[R], \f[B]--digit-clamp\f[R]
+Enables clamping of digits greater than or equal to the current
+\f[B]ibase\f[R] when parsing numbers.
+.RS
+.PP
+This means that digits that the value added to a number from a digit
+that is greater than or equal to the ibase is the value of ibase minus 1
+all multiplied by the value of ibase raised to the power of the
+digit\[cq]s position, which starts from 0 at the least significant
+digit.
+.PP
+If this and/or the \f[B]-C\f[R] or \f[B]--no-digit-clamp\f[R] options
+are given multiple times, the last one given is used.
+.PP
+This option overrides the \f[B]BC_DIGIT_CLAMP\f[R] environment variable
+(see the \f[B]ENVIRONMENT VARIABLES\f[R] section) and the default, which
+can be queried with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
+\f[B]-e\f[R] \f[I]expr\f[R], \f[B]--expression\f[R]=\f[I]expr\f[R]
+Evaluates \f[I]expr\f[R].
+If multiple expressions are given, they are evaluated in order.
+If files are given as well (see the \f[B]-f\f[R] and \f[B]--file\f[R]
+options), 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.
+.RS
+.PP
+If this option is given on the command-line (i.e., not in
+\f[B]BC_ENV_ARGS\f[R], see the \f[B]ENVIRONMENT VARIABLES\f[R] section),
+then after processing all expressions and files, bc(1) will exit, unless
+\f[B]-\f[R] (\f[B]stdin\f[R]) was given as an argument at least once to
+\f[B]-f\f[R] or \f[B]--file\f[R], whether on the command-line or in
+\f[B]BC_ENV_ARGS\f[R].
+However, if any other \f[B]-e\f[R], \f[B]--expression\f[R],
+\f[B]-f\f[R], or \f[B]--file\f[R] arguments are given after
+\f[B]-f-\f[R] or equivalent is given, bc(1) will give a fatal error and
+exit.
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
+\f[B]-f\f[R] \f[I]file\f[R], \f[B]--file\f[R]=\f[I]file\f[R]
+Reads in \f[I]file\f[R] and evaluates it, line by line, as though it
+were read through \f[B]stdin\f[R].
+If expressions are also given (see the \f[B]-e\f[R] and
+\f[B]--expression\f[R] options), the expressions are evaluated in the
+order given.
+.RS
+.PP
+If this option is given on the command-line (i.e., not in
+\f[B]BC_ENV_ARGS\f[R], see the \f[B]ENVIRONMENT VARIABLES\f[R] section),
+then after processing all expressions and files, bc(1) will exit, unless
+\f[B]-\f[R] (\f[B]stdin\f[R]) was given as an argument at least once to
+\f[B]-f\f[R] or \f[B]--file\f[R].
+However, if any other \f[B]-e\f[R], \f[B]--expression\f[R],
+\f[B]-f\f[R], or \f[B]--file\f[R] arguments are given after
+\f[B]-f-\f[R] or equivalent is given, bc(1) will give a fatal error and
+exit.
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
\f[B]-g\f[R], \f[B]--global-stacks\f[R]
Turns the globals \f[B]ibase\f[R], \f[B]obase\f[R], and \f[B]scale\f[R]
into stacks.
@@ -146,7 +234,18 @@ This is a \f[B]non-portable extension\f[R].
.RE
.TP
\f[B]-h\f[R], \f[B]--help\f[R]
-Prints a usage message and quits.
+Prints a usage message and exits.
+.TP
+\f[B]-I\f[R] \f[I]ibase\f[R], \f[B]--ibase\f[R]=\f[I]ibase\f[R]
+Sets the builtin variable \f[B]ibase\f[R] to the value \f[I]ibase\f[R]
+assuming that \f[I]ibase\f[R] is in base 10.
+It is a fatal error if \f[I]ibase\f[R] is not a valid number.
+.RS
+.PP
+If multiple instances of this option are given, the last is used.
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
.TP
\f[B]-i\f[R], \f[B]--interactive\f[R]
Forces interactive mode.
@@ -175,11 +274,23 @@ any expressions or files specified on the command line.
To learn what is in the library, see the \f[B]LIBRARY\f[R] section.
.RE
.TP
+\f[B]-O\f[R] \f[I]obase\f[R], \f[B]--obase\f[R]=\f[I]obase\f[R]
+Sets the builtin variable \f[B]obase\f[R] to the value \f[I]obase\f[R]
+assuming that \f[I]obase\f[R] is in base 10.
+It is a fatal error if \f[I]obase\f[R] is not a valid number.
+.RS
+.PP
+If multiple instances of this option are given, the last is used.
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
\f[B]-P\f[R], \f[B]--no-prompt\f[R]
Disables the prompt in TTY mode.
(The prompt is only enabled in TTY mode.
-See the \f[B]TTY MODE\f[R] section.) This is mostly for those users that
-do not want a prompt or are not used to having them in bc(1).
+See the \f[B]TTY MODE\f[R] 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
\f[B]BC_ENV_ARGS\f[R] (see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
.RS
@@ -190,11 +301,28 @@ environment variables (see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
This is a \f[B]non-portable extension\f[R].
.RE
.TP
+\f[B]-q\f[R], \f[B]--quiet\f[R]
+This option is for compatibility with the GNU bc(1)
+(https://www.gnu.org/software/bc/); 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
+\f[B]-v\f[R], \f[B]-V\f[R], or \f[B]--version\f[R] options are given
+unless the \f[B]BC_BANNER\f[R] environment variable is set and contains
+a non-zero integer or if this bc(1) was built with the header displayed
+by default.
+If \f[I]any\f[R] of that is the case, then this option \f[I]does\f[R]
+prevent bc(1) from printing the header.
+.RS
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
\f[B]-R\f[R], \f[B]--no-read-prompt\f[R]
Disables the read prompt in TTY mode.
(The read prompt is only enabled in TTY mode.
-See the \f[B]TTY MODE\f[R] section.) This is mostly for those users that
-do not want a read prompt or are not used to having them in bc(1).
+See the \f[B]TTY MODE\f[R] 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
\f[B]BC_ENV_ARGS\f[R] (see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
This option is also useful in hash bang lines of bc(1) scripts that
@@ -259,38 +387,32 @@ Keywords are \f[I]not\f[R] redefined when parsing the builtin math
library (see the \f[B]LIBRARY\f[R] section).
.PP
It is a fatal error to redefine keywords mandated by the POSIX standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html).
+(see the \f[B]STANDARDS\f[R] section).
It is a fatal error to attempt to redefine words that this bc(1) does
not reserve as keywords.
.RE
.TP
-\f[B]-q\f[R], \f[B]--quiet\f[R]
-This option is for compatibility with the GNU bc(1)
-(https://www.gnu.org/software/bc/); 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
-\f[B]-v\f[R], \f[B]-V\f[R], or \f[B]--version\f[R] options are given
-unless the \f[B]BC_BANNER\f[R] environment variable is set and contains
-a non-zero integer or if this bc(1) was built with the header displayed
-by default.
-If \f[I]any\f[R] of that is the case, then this option \f[I]does\f[R]
-prevent bc(1) from printing the header.
+\f[B]-S\f[R] \f[I]scale\f[R], \f[B]--scale\f[R]=\f[I]scale\f[R]
+Sets the builtin variable \f[B]scale\f[R] to the value \f[I]scale\f[R]
+assuming that \f[I]scale\f[R] is in base 10.
+It is a fatal error if \f[I]scale\f[R] is not a valid number.
.RS
.PP
+If multiple instances of this option are given, the last is used.
+.PP
This is a \f[B]non-portable extension\f[R].
.RE
.TP
\f[B]-s\f[R], \f[B]--standard\f[R]
-Process exactly the language defined by the standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html) and
-error if any extensions are used.
+Process exactly the language defined by the standard (see the
+\f[B]STANDARDS\f[R] section) and error if any extensions are used.
.RS
.PP
This is a \f[B]non-portable extension\f[R].
.RE
.TP
\f[B]-v\f[R], \f[B]-V\f[R], \f[B]--version\f[R]
-Print the version information (copyright header) and exit.
+Print the version information (copyright header) and exits.
.RS
.PP
This is a \f[B]non-portable extension\f[R].
@@ -316,82 +438,6 @@ extended math library (see the \f[B]LIBRARY\f[R] section).
.PP
This is a \f[B]non-portable extension\f[R].
.RE
-.TP
-\f[B]-e\f[R] \f[I]expr\f[R], \f[B]--expression\f[R]=\f[I]expr\f[R]
-Evaluates \f[I]expr\f[R].
-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.
-.RS
-.PP
-If this option is given on the command-line (i.e., not in
-\f[B]BC_ENV_ARGS\f[R], see the \f[B]ENVIRONMENT VARIABLES\f[R] section),
-then after processing all expressions and files, bc(1) will exit, unless
-\f[B]-\f[R] (\f[B]stdin\f[R]) was given as an argument at least once to
-\f[B]-f\f[R] or \f[B]--file\f[R], whether on the command-line or in
-\f[B]BC_ENV_ARGS\f[R].
-However, if any other \f[B]-e\f[R], \f[B]--expression\f[R],
-\f[B]-f\f[R], or \f[B]--file\f[R] arguments are given after
-\f[B]-f-\f[R] or equivalent is given, bc(1) will give a fatal error and
-exit.
-.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
-.TP
-\f[B]-f\f[R] \f[I]file\f[R], \f[B]--file\f[R]=\f[I]file\f[R]
-Reads in \f[I]file\f[R] and evaluates it, line by line, as though it
-were read through \f[B]stdin\f[R].
-If expressions are also given (see above), the expressions are evaluated
-in the order given.
-.RS
-.PP
-If this option is given on the command-line (i.e., not in
-\f[B]BC_ENV_ARGS\f[R], see the \f[B]ENVIRONMENT VARIABLES\f[R] section),
-then after processing all expressions and files, bc(1) will exit, unless
-\f[B]-\f[R] (\f[B]stdin\f[R]) was given as an argument at least once to
-\f[B]-f\f[R] or \f[B]--file\f[R].
-However, if any other \f[B]-e\f[R], \f[B]--expression\f[R],
-\f[B]-f\f[R], or \f[B]--file\f[R] arguments are given after
-\f[B]-f-\f[R] or equivalent is given, bc(1) will give a fatal error and
-exit.
-.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
-.TP
-\f[B]-I\f[R] \f[I]ibase\f[R], \f[B]--ibase\f[R]=\f[I]ibase\f[R]
-Sets the builtin variable \f[B]ibase\f[R] to the value \f[I]ibase\f[R]
-assuming that \f[I]ibase\f[R] is in base 10.
-It is a fatal error if \f[I]ibase\f[R] is not a valid number.
-.RS
-.PP
-If multiple instances of this option are given, the last is used.
-.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
-.TP
-\f[B]-O\f[R] \f[I]obase\f[R], \f[B]--obase\f[R]=\f[I]obase\f[R]
-Sets the builtin variable \f[B]obase\f[R] to the value \f[I]obase\f[R]
-assuming that \f[I]obase\f[R] is in base 10.
-It is a fatal error if \f[I]obase\f[R] is not a valid number.
-.RS
-.PP
-If multiple instances of this option are given, the last is used.
-.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
-.TP
-\f[B]-S\f[R] \f[I]scale\f[R], \f[B]--scale\f[R]=\f[I]scale\f[R]
-Sets the builtin variable \f[B]scale\f[R] to the value \f[I]scale\f[R]
-assuming that \f[I]scale\f[R] is in base 10.
-It is a fatal error if \f[I]scale\f[R] is not a valid number.
-.RS
-.PP
-If multiple instances of this option are given, the last is used.
-.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
.PP
All long options are \f[B]non-portable extensions\f[R].
.SH STDIN
@@ -445,10 +491,9 @@ redirect \f[B]stderr\f[R] to \f[B]/dev/null\f[R].
.SH SYNTAX
.PP
The syntax for bc(1) programs is mostly C-like, with some differences.
-This bc(1) follows the POSIX standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html),
-which is a much more thorough resource for the language this bc(1)
-accepts.
+This bc(1) follows the POSIX standard (see the \f[B]STANDARDS\f[R]
+section), 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.
.PP
@@ -655,17 +700,49 @@ This is a \f[B]non-portable extension\f[R].
Numbers are strings made up of digits, uppercase letters, and at most
\f[B]1\f[R] period for a radix.
Numbers can have up to \f[B]BC_NUM_MAX\f[R] digits.
-Uppercase letters are equal to \f[B]9\f[R] + their position in the
-alphabet (i.e., \f[B]A\f[R] equals \f[B]10\f[R], or \f[B]9+1\f[R]).
-If a digit or letter makes no sense with the current value of
-\f[B]ibase\f[R], they are set to the value of the highest valid digit in
-\f[B]ibase\f[R].
+Uppercase letters are equal to \f[B]9\f[R] plus their position in the
+alphabet, starting from \f[B]1\f[R] (i.e., \f[B]A\f[R] equals
+\f[B]10\f[R], or \f[B]9+1\f[R]).
.PP
-Single-character numbers (i.e., \f[B]A\f[R] alone) take the value that
-they would have if they were valid digits, regardless of the value of
-\f[B]ibase\f[R].
+If a digit or letter makes no sense with the current value of
+\f[B]ibase\f[R] (i.e., they are greater than or equal to the current
+value of \f[B]ibase\f[R]), then the behavior depends on the existence of
+the \f[B]-c\f[R]/\f[B]--digit-clamp\f[R] or
+\f[B]-C\f[R]/\f[B]--no-digit-clamp\f[R] options (see the
+\f[B]OPTIONS\f[R] section), the existence and setting of the
+\f[B]BC_DIGIT_CLAMP\f[R] environment variable (see the \f[B]ENVIRONMENT
+VARIABLES\f[R] section), or the default, which can be queried with the
+\f[B]-h\f[R]/\f[B]--help\f[R] option.
+.PP
+If clamping is off, then digits or letters that are greater than or
+equal to the current value of \f[B]ibase\f[R] are not changed.
+Instead, their given value is multiplied by the appropriate power of
+\f[B]ibase\f[R] and added into the number.
+This means that, with an \f[B]ibase\f[R] of \f[B]3\f[R], the number
+\f[B]AB\f[R] is equal to \f[B]3\[ha]1*A+3\[ha]0*B\f[R], which is
+\f[B]3\f[R] times \f[B]10\f[R] plus \f[B]11\f[R], or \f[B]41\f[R].
+.PP
+If clamping is on, then digits or letters that are greater than or equal
+to the current value of \f[B]ibase\f[R] are set to the value of the
+highest valid digit in \f[B]ibase\f[R] before being multiplied by the
+appropriate power of \f[B]ibase\f[R] and added into the number.
+This means that, with an \f[B]ibase\f[R] of \f[B]3\f[R], the number
+\f[B]AB\f[R] is equal to \f[B]3\[ha]1*2+3\[ha]0*2\f[R], which is
+\f[B]3\f[R] times \f[B]2\f[R] plus \f[B]2\f[R], or \f[B]8\f[R].
+.PP
+There is one exception to clamping: single-character numbers (i.e.,
+\f[B]A\f[R] alone).
+Such numbers are never clamped and always take the value they would have
+in the highest possible \f[B]ibase\f[R].
This means that \f[B]A\f[R] alone always equals decimal \f[B]10\f[R] and
\f[B]Z\f[R] alone always equals decimal \f[B]35\f[R].
+This behavior is mandated by the standard (see the STANDARDS section)
+and is meant to provide an easy way to set the current \f[B]ibase\f[R]
+(with the \f[B]i\f[R] command) regardless of the current value of
+\f[B]ibase\f[R].
+.PP
+If clamping is on, and the clamped value of a character is needed, use a
+leading zero, i.e., for \f[B]A\f[R], use \f[B]0A\f[R].
.SS Operators
.PP
The following arithmetic and logical operators can be used.
@@ -853,8 +930,7 @@ Note that unlike in C, these operators have a lower precedence than the
\f[B]assignment\f[R] operators, which means that \f[B]a=b>c\f[R] is
interpreted as \f[B](a=b)>c\f[R].
.PP
-Also, unlike the standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html)
+Also, unlike the standard (see the \f[B]STANDARDS\f[R] section)
requires, these operators can appear anywhere any other expressions can
be used.
This allowance is a \f[B]non-portable extension\f[R].
@@ -886,8 +962,8 @@ The following items are statements:
.IP " 1." 4
\f[B]E\f[R]
.IP " 2." 4
-\f[B]{\f[R] \f[B]S\f[R] \f[B];\f[R] \&... \f[B];\f[R] \f[B]S\f[R]
-\f[B]}\f[R]
+\f[B]{\f[R] \f[B]S\f[R] \f[B];\f[R] \&...
+\f[B];\f[R] \f[B]S\f[R] \f[B]}\f[R]
.IP " 3." 4
\f[B]if\f[R] \f[B](\f[R] \f[B]E\f[R] \f[B])\f[R] \f[B]S\f[R]
.IP " 4." 4
@@ -913,9 +989,11 @@ An empty statement
.IP "13." 4
A string of characters, enclosed in double quotes
.IP "14." 4
-\f[B]print\f[R] \f[B]E\f[R] \f[B],\f[R] \&... \f[B],\f[R] \f[B]E\f[R]
+\f[B]print\f[R] \f[B]E\f[R] \f[B],\f[R] \&...
+\f[B],\f[R] \f[B]E\f[R]
.IP "15." 4
-\f[B]stream\f[R] \f[B]E\f[R] \f[B],\f[R] \&... \f[B],\f[R] \f[B]E\f[R]
+\f[B]stream\f[R] \f[B]E\f[R] \f[B],\f[R] \&...
+\f[B],\f[R] \f[B]E\f[R]
.IP "16." 4
\f[B]I()\f[R], \f[B]I(E)\f[R], \f[B]I(E, E)\f[R], and so on, where
\f[B]I\f[R] is an identifier for a \f[B]void\f[R] function (see the
@@ -1143,9 +1221,8 @@ All of the functions below are available when the \f[B]-l\f[R] or
\f[B]--mathlib\f[R] command-line flags are given.
.SS Standard Library
.PP
-The standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html)
-defines the following functions for the math library:
+The standard (see the \f[B]STANDARDS\f[R] section) defines the following
+functions for the math library:
.TP
\f[B]s(x)\f[R]
Returns the sine of \f[B]x\f[R], which is assumed to be in radians.
@@ -1333,7 +1410,8 @@ at which they become a problem.
In fact, memory should be exhausted before these limits should be hit.
.SH ENVIRONMENT VARIABLES
.PP
-bc(1) recognizes the following environment variables:
+As \f[B]non-portable extensions\f[R], bc(1) recognizes the following
+environment variables:
.TP
\f[B]POSIXLY_CORRECT\f[R]
If this variable exists (no matter the contents), bc(1) behaves as if
@@ -1453,6 +1531,22 @@ expressions and expression files, and a zero value makes bc(1) not exit.
This environment variable overrides the default, which can be queried
with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
.RE
+.TP
+\f[B]BC_DIGIT_CLAMP\f[R]
+When parsing numbers and if this environment variable exists and
+contains an integer, a non-zero value makes bc(1) clamp digits that are
+greater than or equal to the current \f[B]ibase\f[R] so that all such
+digits are considered equal to the \f[B]ibase\f[R] minus 1, and a zero
+value disables such clamping so that those digits are always equal to
+their value, which is multiplied by the power of the \f[B]ibase\f[R].
+.RS
+.PP
+This never applies to single-digit numbers, as per the standard (see the
+\f[B]STANDARDS\f[R] section).
+.PP
+This environment variable overrides the default, which can be queried
+with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
+.RE
.SH EXIT STATUS
.PP
bc(1) returns the following exit statuses:
@@ -1532,9 +1626,8 @@ checking, and its normal behavior can be forced by using the
\f[B]-i\f[R] flag or \f[B]--interactive\f[R] option.
.SH INTERACTIVE MODE
.PP
-Per the standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html),
-bc(1) has an interactive mode and a non-interactive mode.
+Per the standard (see the \f[B]STANDARDS\f[R] section), bc(1) has an
+interactive mode and a non-interactive mode.
Interactive mode is turned on automatically when both \f[B]stdin\f[R]
and \f[B]stdout\f[R] are hooked to a terminal, but the \f[B]-i\f[R] flag
and \f[B]--interactive\f[R] option can turn it on in other situations.
@@ -1566,8 +1659,7 @@ The default setting can be queried with the \f[B]-h\f[R] or
\f[B]--help\f[R] options.
.PP
TTY mode is different from interactive mode because interactive mode is
-required in the bc(1) standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html),
+required in the bc(1) standard (see the \f[B]STANDARDS\f[R] section),
and interactive mode requires only \f[B]stdin\f[R] and \f[B]stdout\f[R]
to be connected to a terminal.
.SS Command-Line History
diff --git a/manuals/bc/E.1.md b/manuals/bc/E.1.md
index 6c562cf69d24..85db83b1d2d8 100644
--- a/manuals/bc/E.1.md
+++ b/manuals/bc/E.1.md
@@ -34,21 +34,21 @@ 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*...]
+**bc** [**-cCghilPqRsvVw**] [**-\-digit-clamp**] [**-\-no-digit-clamp**] [**-\-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 at
-https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html .) The
-language provides unlimited precision decimal arithmetic and is somewhat C-like,
-but there are differences. Such differences will be noted in this document.
+POSIX. (See the **STANDARDS** section.) 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**.
-This bc(1) is a drop-in replacement for *any* bc(1), including (and especially)
-the GNU bc(1).
+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.
**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
@@ -63,6 +63,77 @@ that is a bug and should be reported. See the **BUGS** section.
The following are the options that bc(1) accepts.
+**-C**, **-\-no-digit-clamp**
+
+: Disables clamping of digits greater than or equal to the current **ibase**
+ when parsing numbers.
+
+ This means that the value added to a number from a digit is always that
+ digit's value multiplied by the value of ibase raised to the power of the
+ digit's position, which starts from 0 at the least significant digit.
+
+ If this and/or the **-c** or **-\-digit-clamp** options are given multiple
+ times, the last one given is used.
+
+ This option overrides the **BC_DIGIT_CLAMP** environment variable (see the
+ **ENVIRONMENT VARIABLES** section) and the default, which can be queried
+ with the **-h** or **-\-help** options.
+
+ This is a **non-portable extension**.
+
+**-c**, **-\-digit-clamp**
+
+: Enables clamping of digits greater than or equal to the current **ibase**
+ when parsing numbers.
+
+ This means that digits that the value added to a number from a digit that is
+ greater than or equal to the ibase is the value of ibase minus 1 all
+ multiplied by the value of ibase raised to the power of the digit's
+ position, which starts from 0 at the least significant digit.
+
+ If this and/or the **-C** or **-\-no-digit-clamp** options are given
+ multiple times, the last one given is used.
+
+ This option overrides the **BC_DIGIT_CLAMP** environment variable (see the
+ **ENVIRONMENT VARIABLES** section) and the default, which can be queried
+ with the **-h** or **-\-help** options.
+
+ 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 the **-f** and **-\-file** options),
+ 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 the **-e** and
+ **-\-expression** options), 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**.
+
**-g**, **-\-global-stacks**
: Turns the globals **ibase**, **obase**, and **scale** into stacks.
@@ -118,7 +189,16 @@ The following are the options that bc(1) accepts.
**-h**, **-\-help**
-: Prints a usage message and quits.
+: Prints a usage message and exits.
+
+**-I** *ibase*, **-\-ibase**=*ibase*
+
+: Sets the builtin variable **ibase** to the value *ibase* assuming that
+ *ibase* is in base 10. It is a fatal error if *ibase* is not a valid number.
+
+ If multiple instances of this option are given, the last is used.
+
+ This is a **non-portable extension**.
**-i**, **-\-interactive**
@@ -142,6 +222,15 @@ The following are the options that bc(1) accepts.
To learn what is in the library, see the **LIBRARY** section.
+**-O** *obase*, **-\-obase**=*obase*
+
+: Sets the builtin variable **obase** to the value *obase* assuming that
+ *obase* is in base 10. It is a fatal error if *obase* is not a valid number.
+
+ If multiple instances of this option are given, the last is used.
+
+ This is a **non-portable extension**.
+
**-P**, **-\-no-prompt**
: Disables the prompt in TTY mode. (The prompt is only enabled in TTY mode.
@@ -155,6 +244,19 @@ The following are the options that bc(1) accepts.
This is a **non-portable extension**.
+**-q**, **-\-quiet**
+
+: This option is for compatibility with the GNU bc(1)
+ (https://www.gnu.org/software/bc/); 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
+ unless the **BC_BANNER** environment variable is set and contains a non-zero
+ integer or if this bc(1) was built with the header displayed by default. If
+ *any* of that is the case, then this option *does* prevent bc(1) from
+ printing the header.
+
+ This is a **non-portable extension**.
+
**-R**, **-\-no-read-prompt**
: Disables the read prompt in TTY mode. (The read prompt is only enabled in
@@ -204,35 +306,29 @@ The following are the options that bc(1) accepts.
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
- (https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html). It is
- a fatal error to attempt to redefine words that this bc(1) does not reserve
- as keywords.
+ It is a fatal error to redefine keywords mandated by the POSIX standard (see
+ the **STANDARDS** section). It is a fatal error to attempt to redefine words
+ that this bc(1) does not reserve as keywords.
-**-q**, **-\-quiet**
+**-S** *scale*, **-\-scale**=*scale*
-: This option is for compatibility with the GNU bc(1)
- (https://www.gnu.org/software/bc/); 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
- unless the **BC_BANNER** environment variable is set and contains a non-zero
- integer or if this bc(1) was built with the header displayed by default. If
- *any* of that is the case, then this option *does* prevent bc(1) from
- printing the header.
+: Sets the builtin variable **scale** to the value *scale* assuming that
+ *scale* is in base 10. It is a fatal error if *scale* is not a valid number.
+
+ If multiple instances of this option are given, the last is used.
This is a **non-portable extension**.
**-s**, **-\-standard**
-: Process exactly the language defined by the standard
- (https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html) and
- error if any extensions are used.
+: Process exactly the language defined by the standard (see the **STANDARDS**
+ section) and error if any extensions are used.
This is a **non-portable extension**.
**-v**, **-V**, **-\-version**
-: Print the version information (copyright header) and exit.
+: Print the version information (copyright header) and exits.
This is a **non-portable extension**.
@@ -254,65 +350,6 @@ The following are the options that bc(1) accepts.
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**.
-
-**-I** *ibase*, **-\-ibase**=*ibase*
-
-: Sets the builtin variable **ibase** to the value *ibase* assuming that
- *ibase* is in base 10. It is a fatal error if *ibase* is not a valid number.
-
- If multiple instances of this option are given, the last is used.
-
- This is a **non-portable extension**.
-
-**-O** *obase*, **-\-obase**=*obase*
-
-: Sets the builtin variable **obase** to the value *obase* assuming that
- *obase* is in base 10. It is a fatal error if *obase* is not a valid number.
-
- If multiple instances of this option are given, the last is used.
-
- This is a **non-portable extension**.
-
-**-S** *scale*, **-\-scale**=*scale*
-
-: Sets the builtin variable **scale** to the value *scale* assuming that
- *scale* is in base 10. It is a fatal error if *scale* is not a valid number.
-
- If multiple instances of this option are given, the last is used.
-
- This is a **non-portable extension**.
-
All long options are **non-portable extensions**.
# STDIN
@@ -364,8 +401,7 @@ it is recommended that those scripts be changed to redirect **stderr** to
# SYNTAX
The syntax for bc(1) programs is mostly C-like, with some differences. This
-bc(1) follows the POSIX standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html), which is a
+bc(1) follows the POSIX standard (see the **STANDARDS** section), 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.
@@ -509,14 +545,40 @@ The following are valid operands in bc(1):
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**.
+letters are equal to **9** plus their position in the alphabet, starting from
+**1** (i.e., **A** equals **10**, or **9+1**).
+
+If a digit or letter makes no sense with the current value of **ibase** (i.e.,
+they are greater than or equal to the current value of **ibase**), then the
+behavior depends on the existence of the **-c**/**-\-digit-clamp** or
+**-C**/**-\-no-digit-clamp** options (see the **OPTIONS** section), the
+existence and setting of the **BC_DIGIT_CLAMP** environment variable (see the
+**ENVIRONMENT VARIABLES** section), or the default, which can be queried with
+the **-h**/**-\-help** option.
+
+If clamping is off, then digits or letters that are greater than or equal to the
+current value of **ibase** are not changed. Instead, their given value is
+multiplied by the appropriate power of **ibase** and added into the number. This
+means that, with an **ibase** of **3**, the number **AB** is equal to
+**3\^1\*A+3\^0\*B**, which is **3** times **10** plus **11**, or **41**.
+
+If clamping is on, then digits or letters that are greater than or equal to the
+current value of **ibase** are set to the value of the highest valid digit in
+**ibase** before being multiplied by the appropriate power of **ibase** and
+added into the number. This means that, with an **ibase** of **3**, the number
+**AB** is equal to **3\^1\*2+3\^0\*2**, which is **3** times **2** plus **2**,
+or **8**.
+
+There is one exception to clamping: single-character numbers (i.e., **A**
+alone). Such numbers are never clamped and always take the value they would have
+in the highest possible **ibase**. This means that **A** alone always equals
+decimal **10** and **Z** alone always equals decimal **35**. This behavior is
+mandated by the standard (see the STANDARDS section) and is meant to provide an
+easy way to set the current **ibase** (with the **i** command) regardless of the
+current value of **ibase**.
+
+If clamping is on, and the clamped value of a character is needed, use a leading
+zero, i.e., for **A**, use **0A**.
## Operators
@@ -683,10 +745,9 @@ The operators will be described in more detail below.
**assignment** operators, which means that **a=b\>c** is interpreted as
**(a=b)\>c**.
- Also, unlike the standard
- (https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html)
- requires, these operators can appear anywhere any other expressions can be
- used. This allowance is a **non-portable extension**.
+ Also, unlike the standard (see the **STANDARDS** section) requires, these
+ operators can appear anywhere any other expressions can be used. This
+ allowance is a **non-portable extension**.
**&&**
@@ -919,9 +980,8 @@ command-line flags are given.
## Standard Library
-The standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html) defines the
-following functions for the math library:
+The standard (see the **STANDARDS** section) defines the following functions for
+the math library:
**s(x)**
@@ -1093,7 +1153,8 @@ be hit.
# ENVIRONMENT VARIABLES
-bc(1) recognizes the following environment variables:
+As **non-portable extensions**, bc(1) recognizes the following environment
+variables:
**POSIXLY_CORRECT**
@@ -1199,6 +1260,21 @@ bc(1) recognizes the following environment variables:
This environment variable overrides the default, which can be queried with
the **-h** or **-\-help** options.
+**BC_DIGIT_CLAMP**
+
+: When parsing numbers and if this environment variable exists and contains an
+ integer, a non-zero value makes bc(1) clamp digits that are greater than or
+ equal to the current **ibase** so that all such digits are considered equal
+ to the **ibase** minus 1, and a zero value disables such clamping so that
+ those digits are always equal to their value, which is multiplied by the
+ power of the **ibase**.
+
+ This never applies to single-digit numbers, as per the standard (see the
+ **STANDARDS** section).
+
+ 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:
@@ -1272,12 +1348,10 @@ checking, and its normal behavior can be forced by using the **-i** flag or
# INTERACTIVE MODE
-Per the standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html), 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.
+Per the standard (see the **STANDARDS** section), 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
@@ -1303,10 +1377,8 @@ 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) standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html), and
-interactive mode requires only **stdin** and **stdout** to be connected to a
-terminal.
+in the bc(1) standard (see the **STANDARDS** section), and interactive mode
+requires only **stdin** and **stdout** to be connected to a terminal.
## Command-Line History
diff --git a/manuals/bc/EH.1 b/manuals/bc/EH.1
index 95b94ae90e8e..f0f2b1274dad 100644
--- a/manuals/bc/EH.1
+++ b/manuals/bc/EH.1
@@ -25,7 +25,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.TH "BC" "1" "June 2022" "Gavin D. Howard" "General Commands Manual"
+.TH "BC" "1" "August 2022" "Gavin D. Howard" "General Commands Manual"
.nh
.ad l
.SH NAME
@@ -33,20 +33,21 @@
bc - arbitrary-precision decimal arithmetic language and calculator
.SH SYNOPSIS
.PP
-\f[B]bc\f[R] [\f[B]-ghilPqRsvVw\f[R]] [\f[B]--global-stacks\f[R]]
+\f[B]bc\f[R] [\f[B]-cCghilPqRsvVw\f[R]] [\f[B]--digit-clamp\f[R]]
+[\f[B]--no-digit-clamp\f[R]] [\f[B]--global-stacks\f[R]]
[\f[B]--help\f[R]] [\f[B]--interactive\f[R]] [\f[B]--mathlib\f[R]]
[\f[B]--no-prompt\f[R]] [\f[B]--no-read-prompt\f[R]] [\f[B]--quiet\f[R]]
[\f[B]--standard\f[R]] [\f[B]--warn\f[R]] [\f[B]--version\f[R]]
[\f[B]-e\f[R] \f[I]expr\f[R]]
-[\f[B]--expression\f[R]=\f[I]expr\f[R]\&...] [\f[B]-f\f[R]
-\f[I]file\f[R]\&...] [\f[B]--file\f[R]=\f[I]file\f[R]\&...]
+[\f[B]--expression\f[R]=\f[I]expr\f[R]\&...]
+[\f[B]-f\f[R] \f[I]file\f[R]\&...]
+[\f[B]--file\f[R]=\f[I]file\f[R]\&...]
[\f[I]file\f[R]\&...]
.SH DESCRIPTION
.PP
bc(1) is an interactive processor for a language first standardized in
1991 by POSIX.
-(The current standard is at
-https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html .)
+(See the \f[B]STANDARDS\f[R] section.)
The language provides unlimited precision decimal arithmetic and is
somewhat C-like, but there are differences.
Such differences will be noted in this document.
@@ -56,6 +57,8 @@ the command line and executes them before reading from \f[B]stdin\f[R].
.PP
This bc(1) is a drop-in replacement for \f[I]any\f[R] bc(1), including
(and especially) the GNU bc(1).
+It also has many extensions and extra features beyond other
+implementations.
.PP
\f[B]Note\f[R]: If running this bc(1) on \f[I]any\f[R] script meant for
another bc(1) gives a parse error, it is probably because a word this
@@ -73,6 +76,91 @@ See the \f[B]BUGS\f[R] section.
.PP
The following are the options that bc(1) accepts.
.TP
+\f[B]-C\f[R], \f[B]--no-digit-clamp\f[R]
+Disables clamping of digits greater than or equal to the current
+\f[B]ibase\f[R] when parsing numbers.
+.RS
+.PP
+This means that the value added to a number from a digit is always that
+digit\[cq]s value multiplied by the value of ibase raised to the power
+of the digit\[cq]s position, which starts from 0 at the least
+significant digit.
+.PP
+If this and/or the \f[B]-c\f[R] or \f[B]--digit-clamp\f[R] options are
+given multiple times, the last one given is used.
+.PP
+This option overrides the \f[B]BC_DIGIT_CLAMP\f[R] environment variable
+(see the \f[B]ENVIRONMENT VARIABLES\f[R] section) and the default, which
+can be queried with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
+\f[B]-c\f[R], \f[B]--digit-clamp\f[R]
+Enables clamping of digits greater than or equal to the current
+\f[B]ibase\f[R] when parsing numbers.
+.RS
+.PP
+This means that digits that the value added to a number from a digit
+that is greater than or equal to the ibase is the value of ibase minus 1
+all multiplied by the value of ibase raised to the power of the
+digit\[cq]s position, which starts from 0 at the least significant
+digit.
+.PP
+If this and/or the \f[B]-C\f[R] or \f[B]--no-digit-clamp\f[R] options
+are given multiple times, the last one given is used.
+.PP
+This option overrides the \f[B]BC_DIGIT_CLAMP\f[R] environment variable
+(see the \f[B]ENVIRONMENT VARIABLES\f[R] section) and the default, which
+can be queried with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
+\f[B]-e\f[R] \f[I]expr\f[R], \f[B]--expression\f[R]=\f[I]expr\f[R]
+Evaluates \f[I]expr\f[R].
+If multiple expressions are given, they are evaluated in order.
+If files are given as well (see the \f[B]-f\f[R] and \f[B]--file\f[R]
+options), 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.
+.RS
+.PP
+If this option is given on the command-line (i.e., not in
+\f[B]BC_ENV_ARGS\f[R], see the \f[B]ENVIRONMENT VARIABLES\f[R] section),
+then after processing all expressions and files, bc(1) will exit, unless
+\f[B]-\f[R] (\f[B]stdin\f[R]) was given as an argument at least once to
+\f[B]-f\f[R] or \f[B]--file\f[R], whether on the command-line or in
+\f[B]BC_ENV_ARGS\f[R].
+However, if any other \f[B]-e\f[R], \f[B]--expression\f[R],
+\f[B]-f\f[R], or \f[B]--file\f[R] arguments are given after
+\f[B]-f-\f[R] or equivalent is given, bc(1) will give a fatal error and
+exit.
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
+\f[B]-f\f[R] \f[I]file\f[R], \f[B]--file\f[R]=\f[I]file\f[R]
+Reads in \f[I]file\f[R] and evaluates it, line by line, as though it
+were read through \f[B]stdin\f[R].
+If expressions are also given (see the \f[B]-e\f[R] and
+\f[B]--expression\f[R] options), the expressions are evaluated in the
+order given.
+.RS
+.PP
+If this option is given on the command-line (i.e., not in
+\f[B]BC_ENV_ARGS\f[R], see the \f[B]ENVIRONMENT VARIABLES\f[R] section),
+then after processing all expressions and files, bc(1) will exit, unless
+\f[B]-\f[R] (\f[B]stdin\f[R]) was given as an argument at least once to
+\f[B]-f\f[R] or \f[B]--file\f[R].
+However, if any other \f[B]-e\f[R], \f[B]--expression\f[R],
+\f[B]-f\f[R], or \f[B]--file\f[R] arguments are given after
+\f[B]-f-\f[R] or equivalent is given, bc(1) will give a fatal error and
+exit.
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
\f[B]-g\f[R], \f[B]--global-stacks\f[R]
Turns the globals \f[B]ibase\f[R], \f[B]obase\f[R], and \f[B]scale\f[R]
into stacks.
@@ -146,7 +234,18 @@ This is a \f[B]non-portable extension\f[R].
.RE
.TP
\f[B]-h\f[R], \f[B]--help\f[R]
-Prints a usage message and quits.
+Prints a usage message and exits.
+.TP
+\f[B]-I\f[R] \f[I]ibase\f[R], \f[B]--ibase\f[R]=\f[I]ibase\f[R]
+Sets the builtin variable \f[B]ibase\f[R] to the value \f[I]ibase\f[R]
+assuming that \f[I]ibase\f[R] is in base 10.
+It is a fatal error if \f[I]ibase\f[R] is not a valid number.
+.RS
+.PP
+If multiple instances of this option are given, the last is used.
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
.TP
\f[B]-i\f[R], \f[B]--interactive\f[R]
Forces interactive mode.
@@ -175,11 +274,23 @@ any expressions or files specified on the command line.
To learn what is in the library, see the \f[B]LIBRARY\f[R] section.
.RE
.TP
+\f[B]-O\f[R] \f[I]obase\f[R], \f[B]--obase\f[R]=\f[I]obase\f[R]
+Sets the builtin variable \f[B]obase\f[R] to the value \f[I]obase\f[R]
+assuming that \f[I]obase\f[R] is in base 10.
+It is a fatal error if \f[I]obase\f[R] is not a valid number.
+.RS
+.PP
+If multiple instances of this option are given, the last is used.
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
\f[B]-P\f[R], \f[B]--no-prompt\f[R]
Disables the prompt in TTY mode.
(The prompt is only enabled in TTY mode.
-See the \f[B]TTY MODE\f[R] section.) This is mostly for those users that
-do not want a prompt or are not used to having them in bc(1).
+See the \f[B]TTY MODE\f[R] 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
\f[B]BC_ENV_ARGS\f[R] (see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
.RS
@@ -190,11 +301,28 @@ environment variables (see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
This is a \f[B]non-portable extension\f[R].
.RE
.TP
+\f[B]-q\f[R], \f[B]--quiet\f[R]
+This option is for compatibility with the GNU bc(1)
+(https://www.gnu.org/software/bc/); 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
+\f[B]-v\f[R], \f[B]-V\f[R], or \f[B]--version\f[R] options are given
+unless the \f[B]BC_BANNER\f[R] environment variable is set and contains
+a non-zero integer or if this bc(1) was built with the header displayed
+by default.
+If \f[I]any\f[R] of that is the case, then this option \f[I]does\f[R]
+prevent bc(1) from printing the header.
+.RS
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
\f[B]-R\f[R], \f[B]--no-read-prompt\f[R]
Disables the read prompt in TTY mode.
(The read prompt is only enabled in TTY mode.
-See the \f[B]TTY MODE\f[R] section.) This is mostly for those users that
-do not want a read prompt or are not used to having them in bc(1).
+See the \f[B]TTY MODE\f[R] 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
\f[B]BC_ENV_ARGS\f[R] (see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
This option is also useful in hash bang lines of bc(1) scripts that
@@ -259,38 +387,32 @@ Keywords are \f[I]not\f[R] redefined when parsing the builtin math
library (see the \f[B]LIBRARY\f[R] section).
.PP
It is a fatal error to redefine keywords mandated by the POSIX standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html).
+(see the \f[B]STANDARDS\f[R] section).
It is a fatal error to attempt to redefine words that this bc(1) does
not reserve as keywords.
.RE
.TP
-\f[B]-q\f[R], \f[B]--quiet\f[R]
-This option is for compatibility with the GNU bc(1)
-(https://www.gnu.org/software/bc/); 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
-\f[B]-v\f[R], \f[B]-V\f[R], or \f[B]--version\f[R] options are given
-unless the \f[B]BC_BANNER\f[R] environment variable is set and contains
-a non-zero integer or if this bc(1) was built with the header displayed
-by default.
-If \f[I]any\f[R] of that is the case, then this option \f[I]does\f[R]
-prevent bc(1) from printing the header.
+\f[B]-S\f[R] \f[I]scale\f[R], \f[B]--scale\f[R]=\f[I]scale\f[R]
+Sets the builtin variable \f[B]scale\f[R] to the value \f[I]scale\f[R]
+assuming that \f[I]scale\f[R] is in base 10.
+It is a fatal error if \f[I]scale\f[R] is not a valid number.
.RS
.PP
+If multiple instances of this option are given, the last is used.
+.PP
This is a \f[B]non-portable extension\f[R].
.RE
.TP
\f[B]-s\f[R], \f[B]--standard\f[R]
-Process exactly the language defined by the standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html) and
-error if any extensions are used.
+Process exactly the language defined by the standard (see the
+\f[B]STANDARDS\f[R] section) and error if any extensions are used.
.RS
.PP
This is a \f[B]non-portable extension\f[R].
.RE
.TP
\f[B]-v\f[R], \f[B]-V\f[R], \f[B]--version\f[R]
-Print the version information (copyright header) and exit.
+Print the version information (copyright header) and exits.
.RS
.PP
This is a \f[B]non-portable extension\f[R].
@@ -316,82 +438,6 @@ extended math library (see the \f[B]LIBRARY\f[R] section).
.PP
This is a \f[B]non-portable extension\f[R].
.RE
-.TP
-\f[B]-e\f[R] \f[I]expr\f[R], \f[B]--expression\f[R]=\f[I]expr\f[R]
-Evaluates \f[I]expr\f[R].
-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.
-.RS
-.PP
-If this option is given on the command-line (i.e., not in
-\f[B]BC_ENV_ARGS\f[R], see the \f[B]ENVIRONMENT VARIABLES\f[R] section),
-then after processing all expressions and files, bc(1) will exit, unless
-\f[B]-\f[R] (\f[B]stdin\f[R]) was given as an argument at least once to
-\f[B]-f\f[R] or \f[B]--file\f[R], whether on the command-line or in
-\f[B]BC_ENV_ARGS\f[R].
-However, if any other \f[B]-e\f[R], \f[B]--expression\f[R],
-\f[B]-f\f[R], or \f[B]--file\f[R] arguments are given after
-\f[B]-f-\f[R] or equivalent is given, bc(1) will give a fatal error and
-exit.
-.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
-.TP
-\f[B]-f\f[R] \f[I]file\f[R], \f[B]--file\f[R]=\f[I]file\f[R]
-Reads in \f[I]file\f[R] and evaluates it, line by line, as though it
-were read through \f[B]stdin\f[R].
-If expressions are also given (see above), the expressions are evaluated
-in the order given.
-.RS
-.PP
-If this option is given on the command-line (i.e., not in
-\f[B]BC_ENV_ARGS\f[R], see the \f[B]ENVIRONMENT VARIABLES\f[R] section),
-then after processing all expressions and files, bc(1) will exit, unless
-\f[B]-\f[R] (\f[B]stdin\f[R]) was given as an argument at least once to
-\f[B]-f\f[R] or \f[B]--file\f[R].
-However, if any other \f[B]-e\f[R], \f[B]--expression\f[R],
-\f[B]-f\f[R], or \f[B]--file\f[R] arguments are given after
-\f[B]-f-\f[R] or equivalent is given, bc(1) will give a fatal error and
-exit.
-.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
-.TP
-\f[B]-I\f[R] \f[I]ibase\f[R], \f[B]--ibase\f[R]=\f[I]ibase\f[R]
-Sets the builtin variable \f[B]ibase\f[R] to the value \f[I]ibase\f[R]
-assuming that \f[I]ibase\f[R] is in base 10.
-It is a fatal error if \f[I]ibase\f[R] is not a valid number.
-.RS
-.PP
-If multiple instances of this option are given, the last is used.
-.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
-.TP
-\f[B]-O\f[R] \f[I]obase\f[R], \f[B]--obase\f[R]=\f[I]obase\f[R]
-Sets the builtin variable \f[B]obase\f[R] to the value \f[I]obase\f[R]
-assuming that \f[I]obase\f[R] is in base 10.
-It is a fatal error if \f[I]obase\f[R] is not a valid number.
-.RS
-.PP
-If multiple instances of this option are given, the last is used.
-.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
-.TP
-\f[B]-S\f[R] \f[I]scale\f[R], \f[B]--scale\f[R]=\f[I]scale\f[R]
-Sets the builtin variable \f[B]scale\f[R] to the value \f[I]scale\f[R]
-assuming that \f[I]scale\f[R] is in base 10.
-It is a fatal error if \f[I]scale\f[R] is not a valid number.
-.RS
-.PP
-If multiple instances of this option are given, the last is used.
-.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
.PP
All long options are \f[B]non-portable extensions\f[R].
.SH STDIN
@@ -445,10 +491,9 @@ redirect \f[B]stderr\f[R] to \f[B]/dev/null\f[R].
.SH SYNTAX
.PP
The syntax for bc(1) programs is mostly C-like, with some differences.
-This bc(1) follows the POSIX standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html),
-which is a much more thorough resource for the language this bc(1)
-accepts.
+This bc(1) follows the POSIX standard (see the \f[B]STANDARDS\f[R]
+section), 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.
.PP
@@ -655,17 +700,49 @@ This is a \f[B]non-portable extension\f[R].
Numbers are strings made up of digits, uppercase letters, and at most
\f[B]1\f[R] period for a radix.
Numbers can have up to \f[B]BC_NUM_MAX\f[R] digits.
-Uppercase letters are equal to \f[B]9\f[R] + their position in the
-alphabet (i.e., \f[B]A\f[R] equals \f[B]10\f[R], or \f[B]9+1\f[R]).
-If a digit or letter makes no sense with the current value of
-\f[B]ibase\f[R], they are set to the value of the highest valid digit in
-\f[B]ibase\f[R].
+Uppercase letters are equal to \f[B]9\f[R] plus their position in the
+alphabet, starting from \f[B]1\f[R] (i.e., \f[B]A\f[R] equals
+\f[B]10\f[R], or \f[B]9+1\f[R]).
.PP
-Single-character numbers (i.e., \f[B]A\f[R] alone) take the value that
-they would have if they were valid digits, regardless of the value of
-\f[B]ibase\f[R].
+If a digit or letter makes no sense with the current value of
+\f[B]ibase\f[R] (i.e., they are greater than or equal to the current
+value of \f[B]ibase\f[R]), then the behavior depends on the existence of
+the \f[B]-c\f[R]/\f[B]--digit-clamp\f[R] or
+\f[B]-C\f[R]/\f[B]--no-digit-clamp\f[R] options (see the
+\f[B]OPTIONS\f[R] section), the existence and setting of the
+\f[B]BC_DIGIT_CLAMP\f[R] environment variable (see the \f[B]ENVIRONMENT
+VARIABLES\f[R] section), or the default, which can be queried with the
+\f[B]-h\f[R]/\f[B]--help\f[R] option.
+.PP
+If clamping is off, then digits or letters that are greater than or
+equal to the current value of \f[B]ibase\f[R] are not changed.
+Instead, their given value is multiplied by the appropriate power of
+\f[B]ibase\f[R] and added into the number.
+This means that, with an \f[B]ibase\f[R] of \f[B]3\f[R], the number
+\f[B]AB\f[R] is equal to \f[B]3\[ha]1*A+3\[ha]0*B\f[R], which is
+\f[B]3\f[R] times \f[B]10\f[R] plus \f[B]11\f[R], or \f[B]41\f[R].
+.PP
+If clamping is on, then digits or letters that are greater than or equal
+to the current value of \f[B]ibase\f[R] are set to the value of the
+highest valid digit in \f[B]ibase\f[R] before being multiplied by the
+appropriate power of \f[B]ibase\f[R] and added into the number.
+This means that, with an \f[B]ibase\f[R] of \f[B]3\f[R], the number
+\f[B]AB\f[R] is equal to \f[B]3\[ha]1*2+3\[ha]0*2\f[R], which is
+\f[B]3\f[R] times \f[B]2\f[R] plus \f[B]2\f[R], or \f[B]8\f[R].
+.PP
+There is one exception to clamping: single-character numbers (i.e.,
+\f[B]A\f[R] alone).
+Such numbers are never clamped and always take the value they would have
+in the highest possible \f[B]ibase\f[R].
This means that \f[B]A\f[R] alone always equals decimal \f[B]10\f[R] and
\f[B]Z\f[R] alone always equals decimal \f[B]35\f[R].
+This behavior is mandated by the standard (see the STANDARDS section)
+and is meant to provide an easy way to set the current \f[B]ibase\f[R]
+(with the \f[B]i\f[R] command) regardless of the current value of
+\f[B]ibase\f[R].
+.PP
+If clamping is on, and the clamped value of a character is needed, use a
+leading zero, i.e., for \f[B]A\f[R], use \f[B]0A\f[R].
.SS Operators
.PP
The following arithmetic and logical operators can be used.
@@ -853,8 +930,7 @@ Note that unlike in C, these operators have a lower precedence than the
\f[B]assignment\f[R] operators, which means that \f[B]a=b>c\f[R] is
interpreted as \f[B](a=b)>c\f[R].
.PP
-Also, unlike the standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html)
+Also, unlike the standard (see the \f[B]STANDARDS\f[R] section)
requires, these operators can appear anywhere any other expressions can
be used.
This allowance is a \f[B]non-portable extension\f[R].
@@ -886,8 +962,8 @@ The following items are statements:
.IP " 1." 4
\f[B]E\f[R]
.IP " 2." 4
-\f[B]{\f[R] \f[B]S\f[R] \f[B];\f[R] \&... \f[B];\f[R] \f[B]S\f[R]
-\f[B]}\f[R]
+\f[B]{\f[R] \f[B]S\f[R] \f[B];\f[R] \&...
+\f[B];\f[R] \f[B]S\f[R] \f[B]}\f[R]
.IP " 3." 4
\f[B]if\f[R] \f[B](\f[R] \f[B]E\f[R] \f[B])\f[R] \f[B]S\f[R]
.IP " 4." 4
@@ -913,9 +989,11 @@ An empty statement
.IP "13." 4
A string of characters, enclosed in double quotes
.IP "14." 4
-\f[B]print\f[R] \f[B]E\f[R] \f[B],\f[R] \&... \f[B],\f[R] \f[B]E\f[R]
+\f[B]print\f[R] \f[B]E\f[R] \f[B],\f[R] \&...
+\f[B],\f[R] \f[B]E\f[R]
.IP "15." 4
-\f[B]stream\f[R] \f[B]E\f[R] \f[B],\f[R] \&... \f[B],\f[R] \f[B]E\f[R]
+\f[B]stream\f[R] \f[B]E\f[R] \f[B],\f[R] \&...
+\f[B],\f[R] \f[B]E\f[R]
.IP "16." 4
\f[B]I()\f[R], \f[B]I(E)\f[R], \f[B]I(E, E)\f[R], and so on, where
\f[B]I\f[R] is an identifier for a \f[B]void\f[R] function (see the
@@ -1143,9 +1221,8 @@ All of the functions below are available when the \f[B]-l\f[R] or
\f[B]--mathlib\f[R] command-line flags are given.
.SS Standard Library
.PP
-The standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html)
-defines the following functions for the math library:
+The standard (see the \f[B]STANDARDS\f[R] section) defines the following
+functions for the math library:
.TP
\f[B]s(x)\f[R]
Returns the sine of \f[B]x\f[R], which is assumed to be in radians.
@@ -1333,7 +1410,8 @@ at which they become a problem.
In fact, memory should be exhausted before these limits should be hit.
.SH ENVIRONMENT VARIABLES
.PP
-bc(1) recognizes the following environment variables:
+As \f[B]non-portable extensions\f[R], bc(1) recognizes the following
+environment variables:
.TP
\f[B]POSIXLY_CORRECT\f[R]
If this variable exists (no matter the contents), bc(1) behaves as if
@@ -1453,6 +1531,22 @@ expressions and expression files, and a zero value makes bc(1) not exit.
This environment variable overrides the default, which can be queried
with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
.RE
+.TP
+\f[B]BC_DIGIT_CLAMP\f[R]
+When parsing numbers and if this environment variable exists and
+contains an integer, a non-zero value makes bc(1) clamp digits that are
+greater than or equal to the current \f[B]ibase\f[R] so that all such
+digits are considered equal to the \f[B]ibase\f[R] minus 1, and a zero
+value disables such clamping so that those digits are always equal to
+their value, which is multiplied by the power of the \f[B]ibase\f[R].
+.RS
+.PP
+This never applies to single-digit numbers, as per the standard (see the
+\f[B]STANDARDS\f[R] section).
+.PP
+This environment variable overrides the default, which can be queried
+with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
+.RE
.SH EXIT STATUS
.PP
bc(1) returns the following exit statuses:
@@ -1532,9 +1626,8 @@ checking, and its normal behavior can be forced by using the
\f[B]-i\f[R] flag or \f[B]--interactive\f[R] option.
.SH INTERACTIVE MODE
.PP
-Per the standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html),
-bc(1) has an interactive mode and a non-interactive mode.
+Per the standard (see the \f[B]STANDARDS\f[R] section), bc(1) has an
+interactive mode and a non-interactive mode.
Interactive mode is turned on automatically when both \f[B]stdin\f[R]
and \f[B]stdout\f[R] are hooked to a terminal, but the \f[B]-i\f[R] flag
and \f[B]--interactive\f[R] option can turn it on in other situations.
@@ -1566,8 +1659,7 @@ The default setting can be queried with the \f[B]-h\f[R] or
\f[B]--help\f[R] options.
.PP
TTY mode is different from interactive mode because interactive mode is
-required in the bc(1) standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html),
+required in the bc(1) standard (see the \f[B]STANDARDS\f[R] section),
and interactive mode requires only \f[B]stdin\f[R] and \f[B]stdout\f[R]
to be connected to a terminal.
.SS Prompt
diff --git a/manuals/bc/EH.1.md b/manuals/bc/EH.1.md
index 82c3d6c36159..18c77d569d39 100644
--- a/manuals/bc/EH.1.md
+++ b/manuals/bc/EH.1.md
@@ -34,21 +34,21 @@ 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*...]
+**bc** [**-cCghilPqRsvVw**] [**-\-digit-clamp**] [**-\-no-digit-clamp**] [**-\-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 at
-https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html .) The
-language provides unlimited precision decimal arithmetic and is somewhat C-like,
-but there are differences. Such differences will be noted in this document.
+POSIX. (See the **STANDARDS** section.) 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**.
-This bc(1) is a drop-in replacement for *any* bc(1), including (and especially)
-the GNU bc(1).
+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.
**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
@@ -63,6 +63,77 @@ that is a bug and should be reported. See the **BUGS** section.
The following are the options that bc(1) accepts.
+**-C**, **-\-no-digit-clamp**
+
+: Disables clamping of digits greater than or equal to the current **ibase**
+ when parsing numbers.
+
+ This means that the value added to a number from a digit is always that
+ digit's value multiplied by the value of ibase raised to the power of the
+ digit's position, which starts from 0 at the least significant digit.
+
+ If this and/or the **-c** or **-\-digit-clamp** options are given multiple
+ times, the last one given is used.
+
+ This option overrides the **BC_DIGIT_CLAMP** environment variable (see the
+ **ENVIRONMENT VARIABLES** section) and the default, which can be queried
+ with the **-h** or **-\-help** options.
+
+ This is a **non-portable extension**.
+
+**-c**, **-\-digit-clamp**
+
+: Enables clamping of digits greater than or equal to the current **ibase**
+ when parsing numbers.
+
+ This means that digits that the value added to a number from a digit that is
+ greater than or equal to the ibase is the value of ibase minus 1 all
+ multiplied by the value of ibase raised to the power of the digit's
+ position, which starts from 0 at the least significant digit.
+
+ If this and/or the **-C** or **-\-no-digit-clamp** options are given
+ multiple times, the last one given is used.
+
+ This option overrides the **BC_DIGIT_CLAMP** environment variable (see the
+ **ENVIRONMENT VARIABLES** section) and the default, which can be queried
+ with the **-h** or **-\-help** options.
+
+ 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 the **-f** and **-\-file** options),
+ 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 the **-e** and
+ **-\-expression** options), 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**.
+
**-g**, **-\-global-stacks**
: Turns the globals **ibase**, **obase**, and **scale** into stacks.
@@ -118,7 +189,16 @@ The following are the options that bc(1) accepts.
**-h**, **-\-help**
-: Prints a usage message and quits.
+: Prints a usage message and exits.
+
+**-I** *ibase*, **-\-ibase**=*ibase*
+
+: Sets the builtin variable **ibase** to the value *ibase* assuming that
+ *ibase* is in base 10. It is a fatal error if *ibase* is not a valid number.
+
+ If multiple instances of this option are given, the last is used.
+
+ This is a **non-portable extension**.
**-i**, **-\-interactive**
@@ -142,6 +222,15 @@ The following are the options that bc(1) accepts.
To learn what is in the library, see the **LIBRARY** section.
+**-O** *obase*, **-\-obase**=*obase*
+
+: Sets the builtin variable **obase** to the value *obase* assuming that
+ *obase* is in base 10. It is a fatal error if *obase* is not a valid number.
+
+ If multiple instances of this option are given, the last is used.
+
+ This is a **non-portable extension**.
+
**-P**, **-\-no-prompt**
: Disables the prompt in TTY mode. (The prompt is only enabled in TTY mode.
@@ -155,6 +244,19 @@ The following are the options that bc(1) accepts.
This is a **non-portable extension**.
+**-q**, **-\-quiet**
+
+: This option is for compatibility with the GNU bc(1)
+ (https://www.gnu.org/software/bc/); 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
+ unless the **BC_BANNER** environment variable is set and contains a non-zero
+ integer or if this bc(1) was built with the header displayed by default. If
+ *any* of that is the case, then this option *does* prevent bc(1) from
+ printing the header.
+
+ This is a **non-portable extension**.
+
**-R**, **-\-no-read-prompt**
: Disables the read prompt in TTY mode. (The read prompt is only enabled in
@@ -204,35 +306,29 @@ The following are the options that bc(1) accepts.
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
- (https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html). It is
- a fatal error to attempt to redefine words that this bc(1) does not reserve
- as keywords.
+ It is a fatal error to redefine keywords mandated by the POSIX standard (see
+ the **STANDARDS** section). It is a fatal error to attempt to redefine words
+ that this bc(1) does not reserve as keywords.
-**-q**, **-\-quiet**
+**-S** *scale*, **-\-scale**=*scale*
-: This option is for compatibility with the GNU bc(1)
- (https://www.gnu.org/software/bc/); 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
- unless the **BC_BANNER** environment variable is set and contains a non-zero
- integer or if this bc(1) was built with the header displayed by default. If
- *any* of that is the case, then this option *does* prevent bc(1) from
- printing the header.
+: Sets the builtin variable **scale** to the value *scale* assuming that
+ *scale* is in base 10. It is a fatal error if *scale* is not a valid number.
+
+ If multiple instances of this option are given, the last is used.
This is a **non-portable extension**.
**-s**, **-\-standard**
-: Process exactly the language defined by the standard
- (https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html) and
- error if any extensions are used.
+: Process exactly the language defined by the standard (see the **STANDARDS**
+ section) and error if any extensions are used.
This is a **non-portable extension**.
**-v**, **-V**, **-\-version**
-: Print the version information (copyright header) and exit.
+: Print the version information (copyright header) and exits.
This is a **non-portable extension**.
@@ -254,65 +350,6 @@ The following are the options that bc(1) accepts.
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**.
-
-**-I** *ibase*, **-\-ibase**=*ibase*
-
-: Sets the builtin variable **ibase** to the value *ibase* assuming that
- *ibase* is in base 10. It is a fatal error if *ibase* is not a valid number.
-
- If multiple instances of this option are given, the last is used.
-
- This is a **non-portable extension**.
-
-**-O** *obase*, **-\-obase**=*obase*
-
-: Sets the builtin variable **obase** to the value *obase* assuming that
- *obase* is in base 10. It is a fatal error if *obase* is not a valid number.
-
- If multiple instances of this option are given, the last is used.
-
- This is a **non-portable extension**.
-
-**-S** *scale*, **-\-scale**=*scale*
-
-: Sets the builtin variable **scale** to the value *scale* assuming that
- *scale* is in base 10. It is a fatal error if *scale* is not a valid number.
-
- If multiple instances of this option are given, the last is used.
-
- This is a **non-portable extension**.
-
All long options are **non-portable extensions**.
# STDIN
@@ -364,8 +401,7 @@ it is recommended that those scripts be changed to redirect **stderr** to
# SYNTAX
The syntax for bc(1) programs is mostly C-like, with some differences. This
-bc(1) follows the POSIX standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html), which is a
+bc(1) follows the POSIX standard (see the **STANDARDS** section), 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.
@@ -509,14 +545,40 @@ The following are valid operands in bc(1):
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**.
+letters are equal to **9** plus their position in the alphabet, starting from
+**1** (i.e., **A** equals **10**, or **9+1**).
+
+If a digit or letter makes no sense with the current value of **ibase** (i.e.,
+they are greater than or equal to the current value of **ibase**), then the
+behavior depends on the existence of the **-c**/**-\-digit-clamp** or
+**-C**/**-\-no-digit-clamp** options (see the **OPTIONS** section), the
+existence and setting of the **BC_DIGIT_CLAMP** environment variable (see the
+**ENVIRONMENT VARIABLES** section), or the default, which can be queried with
+the **-h**/**-\-help** option.
+
+If clamping is off, then digits or letters that are greater than or equal to the
+current value of **ibase** are not changed. Instead, their given value is
+multiplied by the appropriate power of **ibase** and added into the number. This
+means that, with an **ibase** of **3**, the number **AB** is equal to
+**3\^1\*A+3\^0\*B**, which is **3** times **10** plus **11**, or **41**.
+
+If clamping is on, then digits or letters that are greater than or equal to the
+current value of **ibase** are set to the value of the highest valid digit in
+**ibase** before being multiplied by the appropriate power of **ibase** and
+added into the number. This means that, with an **ibase** of **3**, the number
+**AB** is equal to **3\^1\*2+3\^0\*2**, which is **3** times **2** plus **2**,
+or **8**.
+
+There is one exception to clamping: single-character numbers (i.e., **A**
+alone). Such numbers are never clamped and always take the value they would have
+in the highest possible **ibase**. This means that **A** alone always equals
+decimal **10** and **Z** alone always equals decimal **35**. This behavior is
+mandated by the standard (see the STANDARDS section) and is meant to provide an
+easy way to set the current **ibase** (with the **i** command) regardless of the
+current value of **ibase**.
+
+If clamping is on, and the clamped value of a character is needed, use a leading
+zero, i.e., for **A**, use **0A**.
## Operators
@@ -683,10 +745,9 @@ The operators will be described in more detail below.
**assignment** operators, which means that **a=b\>c** is interpreted as
**(a=b)\>c**.
- Also, unlike the standard
- (https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html)
- requires, these operators can appear anywhere any other expressions can be
- used. This allowance is a **non-portable extension**.
+ Also, unlike the standard (see the **STANDARDS** section) requires, these
+ operators can appear anywhere any other expressions can be used. This
+ allowance is a **non-portable extension**.
**&&**
@@ -919,9 +980,8 @@ command-line flags are given.
## Standard Library
-The standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html) defines the
-following functions for the math library:
+The standard (see the **STANDARDS** section) defines the following functions for
+the math library:
**s(x)**
@@ -1093,7 +1153,8 @@ be hit.
# ENVIRONMENT VARIABLES
-bc(1) recognizes the following environment variables:
+As **non-portable extensions**, bc(1) recognizes the following environment
+variables:
**POSIXLY_CORRECT**
@@ -1199,6 +1260,21 @@ bc(1) recognizes the following environment variables:
This environment variable overrides the default, which can be queried with
the **-h** or **-\-help** options.
+**BC_DIGIT_CLAMP**
+
+: When parsing numbers and if this environment variable exists and contains an
+ integer, a non-zero value makes bc(1) clamp digits that are greater than or
+ equal to the current **ibase** so that all such digits are considered equal
+ to the **ibase** minus 1, and a zero value disables such clamping so that
+ those digits are always equal to their value, which is multiplied by the
+ power of the **ibase**.
+
+ This never applies to single-digit numbers, as per the standard (see the
+ **STANDARDS** section).
+
+ 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:
@@ -1272,12 +1348,10 @@ checking, and its normal behavior can be forced by using the **-i** flag or
# INTERACTIVE MODE
-Per the standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html), 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.
+Per the standard (see the **STANDARDS** section), 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
@@ -1303,10 +1377,8 @@ 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) standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html), and
-interactive mode requires only **stdin** and **stdout** to be connected to a
-terminal.
+in the bc(1) standard (see the **STANDARDS** section), and interactive mode
+requires only **stdin** and **stdout** to be connected to a terminal.
## Prompt
diff --git a/manuals/bc/EHN.1 b/manuals/bc/EHN.1
index ca88115a5864..03887eb6ebe4 100644
--- a/manuals/bc/EHN.1
+++ b/manuals/bc/EHN.1
@@ -25,7 +25,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.TH "BC" "1" "June 2022" "Gavin D. Howard" "General Commands Manual"
+.TH "BC" "1" "August 2022" "Gavin D. Howard" "General Commands Manual"
.nh
.ad l
.SH NAME
@@ -33,20 +33,21 @@
bc - arbitrary-precision decimal arithmetic language and calculator
.SH SYNOPSIS
.PP
-\f[B]bc\f[R] [\f[B]-ghilPqRsvVw\f[R]] [\f[B]--global-stacks\f[R]]
+\f[B]bc\f[R] [\f[B]-cCghilPqRsvVw\f[R]] [\f[B]--digit-clamp\f[R]]
+[\f[B]--no-digit-clamp\f[R]] [\f[B]--global-stacks\f[R]]
[\f[B]--help\f[R]] [\f[B]--interactive\f[R]] [\f[B]--mathlib\f[R]]
[\f[B]--no-prompt\f[R]] [\f[B]--no-read-prompt\f[R]] [\f[B]--quiet\f[R]]
[\f[B]--standard\f[R]] [\f[B]--warn\f[R]] [\f[B]--version\f[R]]
[\f[B]-e\f[R] \f[I]expr\f[R]]
-[\f[B]--expression\f[R]=\f[I]expr\f[R]\&...] [\f[B]-f\f[R]
-\f[I]file\f[R]\&...] [\f[B]--file\f[R]=\f[I]file\f[R]\&...]
+[\f[B]--expression\f[R]=\f[I]expr\f[R]\&...]
+[\f[B]-f\f[R] \f[I]file\f[R]\&...]
+[\f[B]--file\f[R]=\f[I]file\f[R]\&...]
[\f[I]file\f[R]\&...]
.SH DESCRIPTION
.PP
bc(1) is an interactive processor for a language first standardized in
1991 by POSIX.
-(The current standard is at
-https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html .)
+(See the \f[B]STANDARDS\f[R] section.)
The language provides unlimited precision decimal arithmetic and is
somewhat C-like, but there are differences.
Such differences will be noted in this document.
@@ -56,6 +57,8 @@ the command line and executes them before reading from \f[B]stdin\f[R].
.PP
This bc(1) is a drop-in replacement for \f[I]any\f[R] bc(1), including
(and especially) the GNU bc(1).
+It also has many extensions and extra features beyond other
+implementations.
.PP
\f[B]Note\f[R]: If running this bc(1) on \f[I]any\f[R] script meant for
another bc(1) gives a parse error, it is probably because a word this
@@ -73,6 +76,91 @@ See the \f[B]BUGS\f[R] section.
.PP
The following are the options that bc(1) accepts.
.TP
+\f[B]-C\f[R], \f[B]--no-digit-clamp\f[R]
+Disables clamping of digits greater than or equal to the current
+\f[B]ibase\f[R] when parsing numbers.
+.RS
+.PP
+This means that the value added to a number from a digit is always that
+digit\[cq]s value multiplied by the value of ibase raised to the power
+of the digit\[cq]s position, which starts from 0 at the least
+significant digit.
+.PP
+If this and/or the \f[B]-c\f[R] or \f[B]--digit-clamp\f[R] options are
+given multiple times, the last one given is used.
+.PP
+This option overrides the \f[B]BC_DIGIT_CLAMP\f[R] environment variable
+(see the \f[B]ENVIRONMENT VARIABLES\f[R] section) and the default, which
+can be queried with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
+\f[B]-c\f[R], \f[B]--digit-clamp\f[R]
+Enables clamping of digits greater than or equal to the current
+\f[B]ibase\f[R] when parsing numbers.
+.RS
+.PP
+This means that digits that the value added to a number from a digit
+that is greater than or equal to the ibase is the value of ibase minus 1
+all multiplied by the value of ibase raised to the power of the
+digit\[cq]s position, which starts from 0 at the least significant
+digit.
+.PP
+If this and/or the \f[B]-C\f[R] or \f[B]--no-digit-clamp\f[R] options
+are given multiple times, the last one given is used.
+.PP
+This option overrides the \f[B]BC_DIGIT_CLAMP\f[R] environment variable
+(see the \f[B]ENVIRONMENT VARIABLES\f[R] section) and the default, which
+can be queried with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
+\f[B]-e\f[R] \f[I]expr\f[R], \f[B]--expression\f[R]=\f[I]expr\f[R]
+Evaluates \f[I]expr\f[R].
+If multiple expressions are given, they are evaluated in order.
+If files are given as well (see the \f[B]-f\f[R] and \f[B]--file\f[R]
+options), 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.
+.RS
+.PP
+If this option is given on the command-line (i.e., not in
+\f[B]BC_ENV_ARGS\f[R], see the \f[B]ENVIRONMENT VARIABLES\f[R] section),
+then after processing all expressions and files, bc(1) will exit, unless
+\f[B]-\f[R] (\f[B]stdin\f[R]) was given as an argument at least once to
+\f[B]-f\f[R] or \f[B]--file\f[R], whether on the command-line or in
+\f[B]BC_ENV_ARGS\f[R].
+However, if any other \f[B]-e\f[R], \f[B]--expression\f[R],
+\f[B]-f\f[R], or \f[B]--file\f[R] arguments are given after
+\f[B]-f-\f[R] or equivalent is given, bc(1) will give a fatal error and
+exit.
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
+\f[B]-f\f[R] \f[I]file\f[R], \f[B]--file\f[R]=\f[I]file\f[R]
+Reads in \f[I]file\f[R] and evaluates it, line by line, as though it
+were read through \f[B]stdin\f[R].
+If expressions are also given (see the \f[B]-e\f[R] and
+\f[B]--expression\f[R] options), the expressions are evaluated in the
+order given.
+.RS
+.PP
+If this option is given on the command-line (i.e., not in
+\f[B]BC_ENV_ARGS\f[R], see the \f[B]ENVIRONMENT VARIABLES\f[R] section),
+then after processing all expressions and files, bc(1) will exit, unless
+\f[B]-\f[R] (\f[B]stdin\f[R]) was given as an argument at least once to
+\f[B]-f\f[R] or \f[B]--file\f[R].
+However, if any other \f[B]-e\f[R], \f[B]--expression\f[R],
+\f[B]-f\f[R], or \f[B]--file\f[R] arguments are given after
+\f[B]-f-\f[R] or equivalent is given, bc(1) will give a fatal error and
+exit.
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
\f[B]-g\f[R], \f[B]--global-stacks\f[R]
Turns the globals \f[B]ibase\f[R], \f[B]obase\f[R], and \f[B]scale\f[R]
into stacks.
@@ -146,7 +234,18 @@ This is a \f[B]non-portable extension\f[R].
.RE
.TP
\f[B]-h\f[R], \f[B]--help\f[R]
-Prints a usage message and quits.
+Prints a usage message and exits.
+.TP
+\f[B]-I\f[R] \f[I]ibase\f[R], \f[B]--ibase\f[R]=\f[I]ibase\f[R]
+Sets the builtin variable \f[B]ibase\f[R] to the value \f[I]ibase\f[R]
+assuming that \f[I]ibase\f[R] is in base 10.
+It is a fatal error if \f[I]ibase\f[R] is not a valid number.
+.RS
+.PP
+If multiple instances of this option are given, the last is used.
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
.TP
\f[B]-i\f[R], \f[B]--interactive\f[R]
Forces interactive mode.
@@ -175,11 +274,23 @@ any expressions or files specified on the command line.
To learn what is in the library, see the \f[B]LIBRARY\f[R] section.
.RE
.TP
+\f[B]-O\f[R] \f[I]obase\f[R], \f[B]--obase\f[R]=\f[I]obase\f[R]
+Sets the builtin variable \f[B]obase\f[R] to the value \f[I]obase\f[R]
+assuming that \f[I]obase\f[R] is in base 10.
+It is a fatal error if \f[I]obase\f[R] is not a valid number.
+.RS
+.PP
+If multiple instances of this option are given, the last is used.
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
\f[B]-P\f[R], \f[B]--no-prompt\f[R]
Disables the prompt in TTY mode.
(The prompt is only enabled in TTY mode.
-See the \f[B]TTY MODE\f[R] section.) This is mostly for those users that
-do not want a prompt or are not used to having them in bc(1).
+See the \f[B]TTY MODE\f[R] 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
\f[B]BC_ENV_ARGS\f[R] (see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
.RS
@@ -190,11 +301,28 @@ environment variables (see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
This is a \f[B]non-portable extension\f[R].
.RE
.TP
+\f[B]-q\f[R], \f[B]--quiet\f[R]
+This option is for compatibility with the GNU bc(1)
+(https://www.gnu.org/software/bc/); 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
+\f[B]-v\f[R], \f[B]-V\f[R], or \f[B]--version\f[R] options are given
+unless the \f[B]BC_BANNER\f[R] environment variable is set and contains
+a non-zero integer or if this bc(1) was built with the header displayed
+by default.
+If \f[I]any\f[R] of that is the case, then this option \f[I]does\f[R]
+prevent bc(1) from printing the header.
+.RS
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
\f[B]-R\f[R], \f[B]--no-read-prompt\f[R]
Disables the read prompt in TTY mode.
(The read prompt is only enabled in TTY mode.
-See the \f[B]TTY MODE\f[R] section.) This is mostly for those users that
-do not want a read prompt or are not used to having them in bc(1).
+See the \f[B]TTY MODE\f[R] 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
\f[B]BC_ENV_ARGS\f[R] (see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
This option is also useful in hash bang lines of bc(1) scripts that
@@ -259,38 +387,32 @@ Keywords are \f[I]not\f[R] redefined when parsing the builtin math
library (see the \f[B]LIBRARY\f[R] section).
.PP
It is a fatal error to redefine keywords mandated by the POSIX standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html).
+(see the \f[B]STANDARDS\f[R] section).
It is a fatal error to attempt to redefine words that this bc(1) does
not reserve as keywords.
.RE
.TP
-\f[B]-q\f[R], \f[B]--quiet\f[R]
-This option is for compatibility with the GNU bc(1)
-(https://www.gnu.org/software/bc/); 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
-\f[B]-v\f[R], \f[B]-V\f[R], or \f[B]--version\f[R] options are given
-unless the \f[B]BC_BANNER\f[R] environment variable is set and contains
-a non-zero integer or if this bc(1) was built with the header displayed
-by default.
-If \f[I]any\f[R] of that is the case, then this option \f[I]does\f[R]
-prevent bc(1) from printing the header.
+\f[B]-S\f[R] \f[I]scale\f[R], \f[B]--scale\f[R]=\f[I]scale\f[R]
+Sets the builtin variable \f[B]scale\f[R] to the value \f[I]scale\f[R]
+assuming that \f[I]scale\f[R] is in base 10.
+It is a fatal error if \f[I]scale\f[R] is not a valid number.
.RS
.PP
+If multiple instances of this option are given, the last is used.
+.PP
This is a \f[B]non-portable extension\f[R].
.RE
.TP
\f[B]-s\f[R], \f[B]--standard\f[R]
-Process exactly the language defined by the standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html) and
-error if any extensions are used.
+Process exactly the language defined by the standard (see the
+\f[B]STANDARDS\f[R] section) and error if any extensions are used.
.RS
.PP
This is a \f[B]non-portable extension\f[R].
.RE
.TP
\f[B]-v\f[R], \f[B]-V\f[R], \f[B]--version\f[R]
-Print the version information (copyright header) and exit.
+Print the version information (copyright header) and exits.
.RS
.PP
This is a \f[B]non-portable extension\f[R].
@@ -316,82 +438,6 @@ extended math library (see the \f[B]LIBRARY\f[R] section).
.PP
This is a \f[B]non-portable extension\f[R].
.RE
-.TP
-\f[B]-e\f[R] \f[I]expr\f[R], \f[B]--expression\f[R]=\f[I]expr\f[R]
-Evaluates \f[I]expr\f[R].
-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.
-.RS
-.PP
-If this option is given on the command-line (i.e., not in
-\f[B]BC_ENV_ARGS\f[R], see the \f[B]ENVIRONMENT VARIABLES\f[R] section),
-then after processing all expressions and files, bc(1) will exit, unless
-\f[B]-\f[R] (\f[B]stdin\f[R]) was given as an argument at least once to
-\f[B]-f\f[R] or \f[B]--file\f[R], whether on the command-line or in
-\f[B]BC_ENV_ARGS\f[R].
-However, if any other \f[B]-e\f[R], \f[B]--expression\f[R],
-\f[B]-f\f[R], or \f[B]--file\f[R] arguments are given after
-\f[B]-f-\f[R] or equivalent is given, bc(1) will give a fatal error and
-exit.
-.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
-.TP
-\f[B]-f\f[R] \f[I]file\f[R], \f[B]--file\f[R]=\f[I]file\f[R]
-Reads in \f[I]file\f[R] and evaluates it, line by line, as though it
-were read through \f[B]stdin\f[R].
-If expressions are also given (see above), the expressions are evaluated
-in the order given.
-.RS
-.PP
-If this option is given on the command-line (i.e., not in
-\f[B]BC_ENV_ARGS\f[R], see the \f[B]ENVIRONMENT VARIABLES\f[R] section),
-then after processing all expressions and files, bc(1) will exit, unless
-\f[B]-\f[R] (\f[B]stdin\f[R]) was given as an argument at least once to
-\f[B]-f\f[R] or \f[B]--file\f[R].
-However, if any other \f[B]-e\f[R], \f[B]--expression\f[R],
-\f[B]-f\f[R], or \f[B]--file\f[R] arguments are given after
-\f[B]-f-\f[R] or equivalent is given, bc(1) will give a fatal error and
-exit.
-.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
-.TP
-\f[B]-I\f[R] \f[I]ibase\f[R], \f[B]--ibase\f[R]=\f[I]ibase\f[R]
-Sets the builtin variable \f[B]ibase\f[R] to the value \f[I]ibase\f[R]
-assuming that \f[I]ibase\f[R] is in base 10.
-It is a fatal error if \f[I]ibase\f[R] is not a valid number.
-.RS
-.PP
-If multiple instances of this option are given, the last is used.
-.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
-.TP
-\f[B]-O\f[R] \f[I]obase\f[R], \f[B]--obase\f[R]=\f[I]obase\f[R]
-Sets the builtin variable \f[B]obase\f[R] to the value \f[I]obase\f[R]
-assuming that \f[I]obase\f[R] is in base 10.
-It is a fatal error if \f[I]obase\f[R] is not a valid number.
-.RS
-.PP
-If multiple instances of this option are given, the last is used.
-.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
-.TP
-\f[B]-S\f[R] \f[I]scale\f[R], \f[B]--scale\f[R]=\f[I]scale\f[R]
-Sets the builtin variable \f[B]scale\f[R] to the value \f[I]scale\f[R]
-assuming that \f[I]scale\f[R] is in base 10.
-It is a fatal error if \f[I]scale\f[R] is not a valid number.
-.RS
-.PP
-If multiple instances of this option are given, the last is used.
-.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
.PP
All long options are \f[B]non-portable extensions\f[R].
.SH STDIN
@@ -445,10 +491,9 @@ redirect \f[B]stderr\f[R] to \f[B]/dev/null\f[R].
.SH SYNTAX
.PP
The syntax for bc(1) programs is mostly C-like, with some differences.
-This bc(1) follows the POSIX standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html),
-which is a much more thorough resource for the language this bc(1)
-accepts.
+This bc(1) follows the POSIX standard (see the \f[B]STANDARDS\f[R]
+section), 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.
.PP
@@ -655,17 +700,49 @@ This is a \f[B]non-portable extension\f[R].
Numbers are strings made up of digits, uppercase letters, and at most
\f[B]1\f[R] period for a radix.
Numbers can have up to \f[B]BC_NUM_MAX\f[R] digits.
-Uppercase letters are equal to \f[B]9\f[R] + their position in the
-alphabet (i.e., \f[B]A\f[R] equals \f[B]10\f[R], or \f[B]9+1\f[R]).
-If a digit or letter makes no sense with the current value of
-\f[B]ibase\f[R], they are set to the value of the highest valid digit in
-\f[B]ibase\f[R].
+Uppercase letters are equal to \f[B]9\f[R] plus their position in the
+alphabet, starting from \f[B]1\f[R] (i.e., \f[B]A\f[R] equals
+\f[B]10\f[R], or \f[B]9+1\f[R]).
.PP
-Single-character numbers (i.e., \f[B]A\f[R] alone) take the value that
-they would have if they were valid digits, regardless of the value of
-\f[B]ibase\f[R].
+If a digit or letter makes no sense with the current value of
+\f[B]ibase\f[R] (i.e., they are greater than or equal to the current
+value of \f[B]ibase\f[R]), then the behavior depends on the existence of
+the \f[B]-c\f[R]/\f[B]--digit-clamp\f[R] or
+\f[B]-C\f[R]/\f[B]--no-digit-clamp\f[R] options (see the
+\f[B]OPTIONS\f[R] section), the existence and setting of the
+\f[B]BC_DIGIT_CLAMP\f[R] environment variable (see the \f[B]ENVIRONMENT
+VARIABLES\f[R] section), or the default, which can be queried with the
+\f[B]-h\f[R]/\f[B]--help\f[R] option.
+.PP
+If clamping is off, then digits or letters that are greater than or
+equal to the current value of \f[B]ibase\f[R] are not changed.
+Instead, their given value is multiplied by the appropriate power of
+\f[B]ibase\f[R] and added into the number.
+This means that, with an \f[B]ibase\f[R] of \f[B]3\f[R], the number
+\f[B]AB\f[R] is equal to \f[B]3\[ha]1*A+3\[ha]0*B\f[R], which is
+\f[B]3\f[R] times \f[B]10\f[R] plus \f[B]11\f[R], or \f[B]41\f[R].
+.PP
+If clamping is on, then digits or letters that are greater than or equal
+to the current value of \f[B]ibase\f[R] are set to the value of the
+highest valid digit in \f[B]ibase\f[R] before being multiplied by the
+appropriate power of \f[B]ibase\f[R] and added into the number.
+This means that, with an \f[B]ibase\f[R] of \f[B]3\f[R], the number
+\f[B]AB\f[R] is equal to \f[B]3\[ha]1*2+3\[ha]0*2\f[R], which is
+\f[B]3\f[R] times \f[B]2\f[R] plus \f[B]2\f[R], or \f[B]8\f[R].
+.PP
+There is one exception to clamping: single-character numbers (i.e.,
+\f[B]A\f[R] alone).
+Such numbers are never clamped and always take the value they would have
+in the highest possible \f[B]ibase\f[R].
This means that \f[B]A\f[R] alone always equals decimal \f[B]10\f[R] and
\f[B]Z\f[R] alone always equals decimal \f[B]35\f[R].
+This behavior is mandated by the standard (see the STANDARDS section)
+and is meant to provide an easy way to set the current \f[B]ibase\f[R]
+(with the \f[B]i\f[R] command) regardless of the current value of
+\f[B]ibase\f[R].
+.PP
+If clamping is on, and the clamped value of a character is needed, use a
+leading zero, i.e., for \f[B]A\f[R], use \f[B]0A\f[R].
.SS Operators
.PP
The following arithmetic and logical operators can be used.
@@ -853,8 +930,7 @@ Note that unlike in C, these operators have a lower precedence than the
\f[B]assignment\f[R] operators, which means that \f[B]a=b>c\f[R] is
interpreted as \f[B](a=b)>c\f[R].
.PP
-Also, unlike the standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html)
+Also, unlike the standard (see the \f[B]STANDARDS\f[R] section)
requires, these operators can appear anywhere any other expressions can
be used.
This allowance is a \f[B]non-portable extension\f[R].
@@ -886,8 +962,8 @@ The following items are statements:
.IP " 1." 4
\f[B]E\f[R]
.IP " 2." 4
-\f[B]{\f[R] \f[B]S\f[R] \f[B];\f[R] \&... \f[B];\f[R] \f[B]S\f[R]
-\f[B]}\f[R]
+\f[B]{\f[R] \f[B]S\f[R] \f[B];\f[R] \&...
+\f[B];\f[R] \f[B]S\f[R] \f[B]}\f[R]
.IP " 3." 4
\f[B]if\f[R] \f[B](\f[R] \f[B]E\f[R] \f[B])\f[R] \f[B]S\f[R]
.IP " 4." 4
@@ -913,9 +989,11 @@ An empty statement
.IP "13." 4
A string of characters, enclosed in double quotes
.IP "14." 4
-\f[B]print\f[R] \f[B]E\f[R] \f[B],\f[R] \&... \f[B],\f[R] \f[B]E\f[R]
+\f[B]print\f[R] \f[B]E\f[R] \f[B],\f[R] \&...
+\f[B],\f[R] \f[B]E\f[R]
.IP "15." 4
-\f[B]stream\f[R] \f[B]E\f[R] \f[B],\f[R] \&... \f[B],\f[R] \f[B]E\f[R]
+\f[B]stream\f[R] \f[B]E\f[R] \f[B],\f[R] \&...
+\f[B],\f[R] \f[B]E\f[R]
.IP "16." 4
\f[B]I()\f[R], \f[B]I(E)\f[R], \f[B]I(E, E)\f[R], and so on, where
\f[B]I\f[R] is an identifier for a \f[B]void\f[R] function (see the
@@ -1143,9 +1221,8 @@ All of the functions below are available when the \f[B]-l\f[R] or
\f[B]--mathlib\f[R] command-line flags are given.
.SS Standard Library
.PP
-The standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html)
-defines the following functions for the math library:
+The standard (see the \f[B]STANDARDS\f[R] section) defines the following
+functions for the math library:
.TP
\f[B]s(x)\f[R]
Returns the sine of \f[B]x\f[R], which is assumed to be in radians.
@@ -1333,7 +1410,8 @@ at which they become a problem.
In fact, memory should be exhausted before these limits should be hit.
.SH ENVIRONMENT VARIABLES
.PP
-bc(1) recognizes the following environment variables:
+As \f[B]non-portable extensions\f[R], bc(1) recognizes the following
+environment variables:
.TP
\f[B]POSIXLY_CORRECT\f[R]
If this variable exists (no matter the contents), bc(1) behaves as if
@@ -1453,6 +1531,22 @@ expressions and expression files, and a zero value makes bc(1) not exit.
This environment variable overrides the default, which can be queried
with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
.RE
+.TP
+\f[B]BC_DIGIT_CLAMP\f[R]
+When parsing numbers and if this environment variable exists and
+contains an integer, a non-zero value makes bc(1) clamp digits that are
+greater than or equal to the current \f[B]ibase\f[R] so that all such
+digits are considered equal to the \f[B]ibase\f[R] minus 1, and a zero
+value disables such clamping so that those digits are always equal to
+their value, which is multiplied by the power of the \f[B]ibase\f[R].
+.RS
+.PP
+This never applies to single-digit numbers, as per the standard (see the
+\f[B]STANDARDS\f[R] section).
+.PP
+This environment variable overrides the default, which can be queried
+with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
+.RE
.SH EXIT STATUS
.PP
bc(1) returns the following exit statuses:
@@ -1532,9 +1626,8 @@ checking, and its normal behavior can be forced by using the
\f[B]-i\f[R] flag or \f[B]--interactive\f[R] option.
.SH INTERACTIVE MODE
.PP
-Per the standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html),
-bc(1) has an interactive mode and a non-interactive mode.
+Per the standard (see the \f[B]STANDARDS\f[R] section), bc(1) has an
+interactive mode and a non-interactive mode.
Interactive mode is turned on automatically when both \f[B]stdin\f[R]
and \f[B]stdout\f[R] are hooked to a terminal, but the \f[B]-i\f[R] flag
and \f[B]--interactive\f[R] option can turn it on in other situations.
@@ -1566,8 +1659,7 @@ The default setting can be queried with the \f[B]-h\f[R] or
\f[B]--help\f[R] options.
.PP
TTY mode is different from interactive mode because interactive mode is
-required in the bc(1) standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html),
+required in the bc(1) standard (see the \f[B]STANDARDS\f[R] section),
and interactive mode requires only \f[B]stdin\f[R] and \f[B]stdout\f[R]
to be connected to a terminal.
.SS Prompt
diff --git a/manuals/bc/EHN.1.md b/manuals/bc/EHN.1.md
index d3873ba6ac97..769ec4a18f64 100644
--- a/manuals/bc/EHN.1.md
+++ b/manuals/bc/EHN.1.md
@@ -34,21 +34,21 @@ 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*...]
+**bc** [**-cCghilPqRsvVw**] [**-\-digit-clamp**] [**-\-no-digit-clamp**] [**-\-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 at
-https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html .) The
-language provides unlimited precision decimal arithmetic and is somewhat C-like,
-but there are differences. Such differences will be noted in this document.
+POSIX. (See the **STANDARDS** section.) 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**.
-This bc(1) is a drop-in replacement for *any* bc(1), including (and especially)
-the GNU bc(1).
+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.
**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
@@ -63,6 +63,77 @@ that is a bug and should be reported. See the **BUGS** section.
The following are the options that bc(1) accepts.
+**-C**, **-\-no-digit-clamp**
+
+: Disables clamping of digits greater than or equal to the current **ibase**
+ when parsing numbers.
+
+ This means that the value added to a number from a digit is always that
+ digit's value multiplied by the value of ibase raised to the power of the
+ digit's position, which starts from 0 at the least significant digit.
+
+ If this and/or the **-c** or **-\-digit-clamp** options are given multiple
+ times, the last one given is used.
+
+ This option overrides the **BC_DIGIT_CLAMP** environment variable (see the
+ **ENVIRONMENT VARIABLES** section) and the default, which can be queried
+ with the **-h** or **-\-help** options.
+
+ This is a **non-portable extension**.
+
+**-c**, **-\-digit-clamp**
+
+: Enables clamping of digits greater than or equal to the current **ibase**
+ when parsing numbers.
+
+ This means that digits that the value added to a number from a digit that is
+ greater than or equal to the ibase is the value of ibase minus 1 all
+ multiplied by the value of ibase raised to the power of the digit's
+ position, which starts from 0 at the least significant digit.
+
+ If this and/or the **-C** or **-\-no-digit-clamp** options are given
+ multiple times, the last one given is used.
+
+ This option overrides the **BC_DIGIT_CLAMP** environment variable (see the
+ **ENVIRONMENT VARIABLES** section) and the default, which can be queried
+ with the **-h** or **-\-help** options.
+
+ 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 the **-f** and **-\-file** options),
+ 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 the **-e** and
+ **-\-expression** options), 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**.
+
**-g**, **-\-global-stacks**
: Turns the globals **ibase**, **obase**, and **scale** into stacks.
@@ -118,7 +189,16 @@ The following are the options that bc(1) accepts.
**-h**, **-\-help**
-: Prints a usage message and quits.
+: Prints a usage message and exits.
+
+**-I** *ibase*, **-\-ibase**=*ibase*
+
+: Sets the builtin variable **ibase** to the value *ibase* assuming that
+ *ibase* is in base 10. It is a fatal error if *ibase* is not a valid number.
+
+ If multiple instances of this option are given, the last is used.
+
+ This is a **non-portable extension**.
**-i**, **-\-interactive**
@@ -142,6 +222,15 @@ The following are the options that bc(1) accepts.
To learn what is in the library, see the **LIBRARY** section.
+**-O** *obase*, **-\-obase**=*obase*
+
+: Sets the builtin variable **obase** to the value *obase* assuming that
+ *obase* is in base 10. It is a fatal error if *obase* is not a valid number.
+
+ If multiple instances of this option are given, the last is used.
+
+ This is a **non-portable extension**.
+
**-P**, **-\-no-prompt**
: Disables the prompt in TTY mode. (The prompt is only enabled in TTY mode.
@@ -155,6 +244,19 @@ The following are the options that bc(1) accepts.
This is a **non-portable extension**.
+**-q**, **-\-quiet**
+
+: This option is for compatibility with the GNU bc(1)
+ (https://www.gnu.org/software/bc/); 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
+ unless the **BC_BANNER** environment variable is set and contains a non-zero
+ integer or if this bc(1) was built with the header displayed by default. If
+ *any* of that is the case, then this option *does* prevent bc(1) from
+ printing the header.
+
+ This is a **non-portable extension**.
+
**-R**, **-\-no-read-prompt**
: Disables the read prompt in TTY mode. (The read prompt is only enabled in
@@ -204,35 +306,29 @@ The following are the options that bc(1) accepts.
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
- (https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html). It is
- a fatal error to attempt to redefine words that this bc(1) does not reserve
- as keywords.
+ It is a fatal error to redefine keywords mandated by the POSIX standard (see
+ the **STANDARDS** section). It is a fatal error to attempt to redefine words
+ that this bc(1) does not reserve as keywords.
-**-q**, **-\-quiet**
+**-S** *scale*, **-\-scale**=*scale*
-: This option is for compatibility with the GNU bc(1)
- (https://www.gnu.org/software/bc/); 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
- unless the **BC_BANNER** environment variable is set and contains a non-zero
- integer or if this bc(1) was built with the header displayed by default. If
- *any* of that is the case, then this option *does* prevent bc(1) from
- printing the header.
+: Sets the builtin variable **scale** to the value *scale* assuming that
+ *scale* is in base 10. It is a fatal error if *scale* is not a valid number.
+
+ If multiple instances of this option are given, the last is used.
This is a **non-portable extension**.
**-s**, **-\-standard**
-: Process exactly the language defined by the standard
- (https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html) and
- error if any extensions are used.
+: Process exactly the language defined by the standard (see the **STANDARDS**
+ section) and error if any extensions are used.
This is a **non-portable extension**.
**-v**, **-V**, **-\-version**
-: Print the version information (copyright header) and exit.
+: Print the version information (copyright header) and exits.
This is a **non-portable extension**.
@@ -254,65 +350,6 @@ The following are the options that bc(1) accepts.
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**.
-
-**-I** *ibase*, **-\-ibase**=*ibase*
-
-: Sets the builtin variable **ibase** to the value *ibase* assuming that
- *ibase* is in base 10. It is a fatal error if *ibase* is not a valid number.
-
- If multiple instances of this option are given, the last is used.
-
- This is a **non-portable extension**.
-
-**-O** *obase*, **-\-obase**=*obase*
-
-: Sets the builtin variable **obase** to the value *obase* assuming that
- *obase* is in base 10. It is a fatal error if *obase* is not a valid number.
-
- If multiple instances of this option are given, the last is used.
-
- This is a **non-portable extension**.
-
-**-S** *scale*, **-\-scale**=*scale*
-
-: Sets the builtin variable **scale** to the value *scale* assuming that
- *scale* is in base 10. It is a fatal error if *scale* is not a valid number.
-
- If multiple instances of this option are given, the last is used.
-
- This is a **non-portable extension**.
-
All long options are **non-portable extensions**.
# STDIN
@@ -364,8 +401,7 @@ it is recommended that those scripts be changed to redirect **stderr** to
# SYNTAX
The syntax for bc(1) programs is mostly C-like, with some differences. This
-bc(1) follows the POSIX standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html), which is a
+bc(1) follows the POSIX standard (see the **STANDARDS** section), 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.
@@ -509,14 +545,40 @@ The following are valid operands in bc(1):
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**.
+letters are equal to **9** plus their position in the alphabet, starting from
+**1** (i.e., **A** equals **10**, or **9+1**).
+
+If a digit or letter makes no sense with the current value of **ibase** (i.e.,
+they are greater than or equal to the current value of **ibase**), then the
+behavior depends on the existence of the **-c**/**-\-digit-clamp** or
+**-C**/**-\-no-digit-clamp** options (see the **OPTIONS** section), the
+existence and setting of the **BC_DIGIT_CLAMP** environment variable (see the
+**ENVIRONMENT VARIABLES** section), or the default, which can be queried with
+the **-h**/**-\-help** option.
+
+If clamping is off, then digits or letters that are greater than or equal to the
+current value of **ibase** are not changed. Instead, their given value is
+multiplied by the appropriate power of **ibase** and added into the number. This
+means that, with an **ibase** of **3**, the number **AB** is equal to
+**3\^1\*A+3\^0\*B**, which is **3** times **10** plus **11**, or **41**.
+
+If clamping is on, then digits or letters that are greater than or equal to the
+current value of **ibase** are set to the value of the highest valid digit in
+**ibase** before being multiplied by the appropriate power of **ibase** and
+added into the number. This means that, with an **ibase** of **3**, the number
+**AB** is equal to **3\^1\*2+3\^0\*2**, which is **3** times **2** plus **2**,
+or **8**.
+
+There is one exception to clamping: single-character numbers (i.e., **A**
+alone). Such numbers are never clamped and always take the value they would have
+in the highest possible **ibase**. This means that **A** alone always equals
+decimal **10** and **Z** alone always equals decimal **35**. This behavior is
+mandated by the standard (see the STANDARDS section) and is meant to provide an
+easy way to set the current **ibase** (with the **i** command) regardless of the
+current value of **ibase**.
+
+If clamping is on, and the clamped value of a character is needed, use a leading
+zero, i.e., for **A**, use **0A**.
## Operators
@@ -683,10 +745,9 @@ The operators will be described in more detail below.
**assignment** operators, which means that **a=b\>c** is interpreted as
**(a=b)\>c**.
- Also, unlike the standard
- (https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html)
- requires, these operators can appear anywhere any other expressions can be
- used. This allowance is a **non-portable extension**.
+ Also, unlike the standard (see the **STANDARDS** section) requires, these
+ operators can appear anywhere any other expressions can be used. This
+ allowance is a **non-portable extension**.
**&&**
@@ -919,9 +980,8 @@ command-line flags are given.
## Standard Library
-The standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html) defines the
-following functions for the math library:
+The standard (see the **STANDARDS** section) defines the following functions for
+the math library:
**s(x)**
@@ -1093,7 +1153,8 @@ be hit.
# ENVIRONMENT VARIABLES
-bc(1) recognizes the following environment variables:
+As **non-portable extensions**, bc(1) recognizes the following environment
+variables:
**POSIXLY_CORRECT**
@@ -1199,6 +1260,21 @@ bc(1) recognizes the following environment variables:
This environment variable overrides the default, which can be queried with
the **-h** or **-\-help** options.
+**BC_DIGIT_CLAMP**
+
+: When parsing numbers and if this environment variable exists and contains an
+ integer, a non-zero value makes bc(1) clamp digits that are greater than or
+ equal to the current **ibase** so that all such digits are considered equal
+ to the **ibase** minus 1, and a zero value disables such clamping so that
+ those digits are always equal to their value, which is multiplied by the
+ power of the **ibase**.
+
+ This never applies to single-digit numbers, as per the standard (see the
+ **STANDARDS** section).
+
+ 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:
@@ -1272,12 +1348,10 @@ checking, and its normal behavior can be forced by using the **-i** flag or
# INTERACTIVE MODE
-Per the standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html), 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.
+Per the standard (see the **STANDARDS** section), 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
@@ -1303,10 +1377,8 @@ 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) standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html), and
-interactive mode requires only **stdin** and **stdout** to be connected to a
-terminal.
+in the bc(1) standard (see the **STANDARDS** section), and interactive mode
+requires only **stdin** and **stdout** to be connected to a terminal.
## Prompt
diff --git a/manuals/bc/EN.1 b/manuals/bc/EN.1
index 1f1e60aad093..082afe7d8fe6 100644
--- a/manuals/bc/EN.1
+++ b/manuals/bc/EN.1
@@ -25,7 +25,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.TH "BC" "1" "June 2022" "Gavin D. Howard" "General Commands Manual"
+.TH "BC" "1" "August 2022" "Gavin D. Howard" "General Commands Manual"
.nh
.ad l
.SH NAME
@@ -33,20 +33,21 @@
bc - arbitrary-precision decimal arithmetic language and calculator
.SH SYNOPSIS
.PP
-\f[B]bc\f[R] [\f[B]-ghilPqRsvVw\f[R]] [\f[B]--global-stacks\f[R]]
+\f[B]bc\f[R] [\f[B]-cCghilPqRsvVw\f[R]] [\f[B]--digit-clamp\f[R]]
+[\f[B]--no-digit-clamp\f[R]] [\f[B]--global-stacks\f[R]]
[\f[B]--help\f[R]] [\f[B]--interactive\f[R]] [\f[B]--mathlib\f[R]]
[\f[B]--no-prompt\f[R]] [\f[B]--no-read-prompt\f[R]] [\f[B]--quiet\f[R]]
[\f[B]--standard\f[R]] [\f[B]--warn\f[R]] [\f[B]--version\f[R]]
[\f[B]-e\f[R] \f[I]expr\f[R]]
-[\f[B]--expression\f[R]=\f[I]expr\f[R]\&...] [\f[B]-f\f[R]
-\f[I]file\f[R]\&...] [\f[B]--file\f[R]=\f[I]file\f[R]\&...]
+[\f[B]--expression\f[R]=\f[I]expr\f[R]\&...]
+[\f[B]-f\f[R] \f[I]file\f[R]\&...]
+[\f[B]--file\f[R]=\f[I]file\f[R]\&...]
[\f[I]file\f[R]\&...]
.SH DESCRIPTION
.PP
bc(1) is an interactive processor for a language first standardized in
1991 by POSIX.
-(The current standard is at
-https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html .)
+(See the \f[B]STANDARDS\f[R] section.)
The language provides unlimited precision decimal arithmetic and is
somewhat C-like, but there are differences.
Such differences will be noted in this document.
@@ -56,6 +57,8 @@ the command line and executes them before reading from \f[B]stdin\f[R].
.PP
This bc(1) is a drop-in replacement for \f[I]any\f[R] bc(1), including
(and especially) the GNU bc(1).
+It also has many extensions and extra features beyond other
+implementations.
.PP
\f[B]Note\f[R]: If running this bc(1) on \f[I]any\f[R] script meant for
another bc(1) gives a parse error, it is probably because a word this
@@ -73,6 +76,91 @@ See the \f[B]BUGS\f[R] section.
.PP
The following are the options that bc(1) accepts.
.TP
+\f[B]-C\f[R], \f[B]--no-digit-clamp\f[R]
+Disables clamping of digits greater than or equal to the current
+\f[B]ibase\f[R] when parsing numbers.
+.RS
+.PP
+This means that the value added to a number from a digit is always that
+digit\[cq]s value multiplied by the value of ibase raised to the power
+of the digit\[cq]s position, which starts from 0 at the least
+significant digit.
+.PP
+If this and/or the \f[B]-c\f[R] or \f[B]--digit-clamp\f[R] options are
+given multiple times, the last one given is used.
+.PP
+This option overrides the \f[B]BC_DIGIT_CLAMP\f[R] environment variable
+(see the \f[B]ENVIRONMENT VARIABLES\f[R] section) and the default, which
+can be queried with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
+\f[B]-c\f[R], \f[B]--digit-clamp\f[R]
+Enables clamping of digits greater than or equal to the current
+\f[B]ibase\f[R] when parsing numbers.
+.RS
+.PP
+This means that digits that the value added to a number from a digit
+that is greater than or equal to the ibase is the value of ibase minus 1
+all multiplied by the value of ibase raised to the power of the
+digit\[cq]s position, which starts from 0 at the least significant
+digit.
+.PP
+If this and/or the \f[B]-C\f[R] or \f[B]--no-digit-clamp\f[R] options
+are given multiple times, the last one given is used.
+.PP
+This option overrides the \f[B]BC_DIGIT_CLAMP\f[R] environment variable
+(see the \f[B]ENVIRONMENT VARIABLES\f[R] section) and the default, which
+can be queried with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
+\f[B]-e\f[R] \f[I]expr\f[R], \f[B]--expression\f[R]=\f[I]expr\f[R]
+Evaluates \f[I]expr\f[R].
+If multiple expressions are given, they are evaluated in order.
+If files are given as well (see the \f[B]-f\f[R] and \f[B]--file\f[R]
+options), 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.
+.RS
+.PP
+If this option is given on the command-line (i.e., not in
+\f[B]BC_ENV_ARGS\f[R], see the \f[B]ENVIRONMENT VARIABLES\f[R] section),
+then after processing all expressions and files, bc(1) will exit, unless
+\f[B]-\f[R] (\f[B]stdin\f[R]) was given as an argument at least once to
+\f[B]-f\f[R] or \f[B]--file\f[R], whether on the command-line or in
+\f[B]BC_ENV_ARGS\f[R].
+However, if any other \f[B]-e\f[R], \f[B]--expression\f[R],
+\f[B]-f\f[R], or \f[B]--file\f[R] arguments are given after
+\f[B]-f-\f[R] or equivalent is given, bc(1) will give a fatal error and
+exit.
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
+\f[B]-f\f[R] \f[I]file\f[R], \f[B]--file\f[R]=\f[I]file\f[R]
+Reads in \f[I]file\f[R] and evaluates it, line by line, as though it
+were read through \f[B]stdin\f[R].
+If expressions are also given (see the \f[B]-e\f[R] and
+\f[B]--expression\f[R] options), the expressions are evaluated in the
+order given.
+.RS
+.PP
+If this option is given on the command-line (i.e., not in
+\f[B]BC_ENV_ARGS\f[R], see the \f[B]ENVIRONMENT VARIABLES\f[R] section),
+then after processing all expressions and files, bc(1) will exit, unless
+\f[B]-\f[R] (\f[B]stdin\f[R]) was given as an argument at least once to
+\f[B]-f\f[R] or \f[B]--file\f[R].
+However, if any other \f[B]-e\f[R], \f[B]--expression\f[R],
+\f[B]-f\f[R], or \f[B]--file\f[R] arguments are given after
+\f[B]-f-\f[R] or equivalent is given, bc(1) will give a fatal error and
+exit.
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
\f[B]-g\f[R], \f[B]--global-stacks\f[R]
Turns the globals \f[B]ibase\f[R], \f[B]obase\f[R], and \f[B]scale\f[R]
into stacks.
@@ -146,7 +234,18 @@ This is a \f[B]non-portable extension\f[R].
.RE
.TP
\f[B]-h\f[R], \f[B]--help\f[R]
-Prints a usage message and quits.
+Prints a usage message and exits.
+.TP
+\f[B]-I\f[R] \f[I]ibase\f[R], \f[B]--ibase\f[R]=\f[I]ibase\f[R]
+Sets the builtin variable \f[B]ibase\f[R] to the value \f[I]ibase\f[R]
+assuming that \f[I]ibase\f[R] is in base 10.
+It is a fatal error if \f[I]ibase\f[R] is not a valid number.
+.RS
+.PP
+If multiple instances of this option are given, the last is used.
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
.TP
\f[B]-i\f[R], \f[B]--interactive\f[R]
Forces interactive mode.
@@ -175,11 +274,23 @@ any expressions or files specified on the command line.
To learn what is in the library, see the \f[B]LIBRARY\f[R] section.
.RE
.TP
+\f[B]-O\f[R] \f[I]obase\f[R], \f[B]--obase\f[R]=\f[I]obase\f[R]
+Sets the builtin variable \f[B]obase\f[R] to the value \f[I]obase\f[R]
+assuming that \f[I]obase\f[R] is in base 10.
+It is a fatal error if \f[I]obase\f[R] is not a valid number.
+.RS
+.PP
+If multiple instances of this option are given, the last is used.
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
\f[B]-P\f[R], \f[B]--no-prompt\f[R]
Disables the prompt in TTY mode.
(The prompt is only enabled in TTY mode.
-See the \f[B]TTY MODE\f[R] section.) This is mostly for those users that
-do not want a prompt or are not used to having them in bc(1).
+See the \f[B]TTY MODE\f[R] 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
\f[B]BC_ENV_ARGS\f[R] (see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
.RS
@@ -190,11 +301,28 @@ environment variables (see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
This is a \f[B]non-portable extension\f[R].
.RE
.TP
+\f[B]-q\f[R], \f[B]--quiet\f[R]
+This option is for compatibility with the GNU bc(1)
+(https://www.gnu.org/software/bc/); 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
+\f[B]-v\f[R], \f[B]-V\f[R], or \f[B]--version\f[R] options are given
+unless the \f[B]BC_BANNER\f[R] environment variable is set and contains
+a non-zero integer or if this bc(1) was built with the header displayed
+by default.
+If \f[I]any\f[R] of that is the case, then this option \f[I]does\f[R]
+prevent bc(1) from printing the header.
+.RS
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
\f[B]-R\f[R], \f[B]--no-read-prompt\f[R]
Disables the read prompt in TTY mode.
(The read prompt is only enabled in TTY mode.
-See the \f[B]TTY MODE\f[R] section.) This is mostly for those users that
-do not want a read prompt or are not used to having them in bc(1).
+See the \f[B]TTY MODE\f[R] 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
\f[B]BC_ENV_ARGS\f[R] (see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
This option is also useful in hash bang lines of bc(1) scripts that
@@ -259,38 +387,32 @@ Keywords are \f[I]not\f[R] redefined when parsing the builtin math
library (see the \f[B]LIBRARY\f[R] section).
.PP
It is a fatal error to redefine keywords mandated by the POSIX standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html).
+(see the \f[B]STANDARDS\f[R] section).
It is a fatal error to attempt to redefine words that this bc(1) does
not reserve as keywords.
.RE
.TP
-\f[B]-q\f[R], \f[B]--quiet\f[R]
-This option is for compatibility with the GNU bc(1)
-(https://www.gnu.org/software/bc/); 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
-\f[B]-v\f[R], \f[B]-V\f[R], or \f[B]--version\f[R] options are given
-unless the \f[B]BC_BANNER\f[R] environment variable is set and contains
-a non-zero integer or if this bc(1) was built with the header displayed
-by default.
-If \f[I]any\f[R] of that is the case, then this option \f[I]does\f[R]
-prevent bc(1) from printing the header.
+\f[B]-S\f[R] \f[I]scale\f[R], \f[B]--scale\f[R]=\f[I]scale\f[R]
+Sets the builtin variable \f[B]scale\f[R] to the value \f[I]scale\f[R]
+assuming that \f[I]scale\f[R] is in base 10.
+It is a fatal error if \f[I]scale\f[R] is not a valid number.
.RS
.PP
+If multiple instances of this option are given, the last is used.
+.PP
This is a \f[B]non-portable extension\f[R].
.RE
.TP
\f[B]-s\f[R], \f[B]--standard\f[R]
-Process exactly the language defined by the standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html) and
-error if any extensions are used.
+Process exactly the language defined by the standard (see the
+\f[B]STANDARDS\f[R] section) and error if any extensions are used.
.RS
.PP
This is a \f[B]non-portable extension\f[R].
.RE
.TP
\f[B]-v\f[R], \f[B]-V\f[R], \f[B]--version\f[R]
-Print the version information (copyright header) and exit.
+Print the version information (copyright header) and exits.
.RS
.PP
This is a \f[B]non-portable extension\f[R].
@@ -316,82 +438,6 @@ extended math library (see the \f[B]LIBRARY\f[R] section).
.PP
This is a \f[B]non-portable extension\f[R].
.RE
-.TP
-\f[B]-e\f[R] \f[I]expr\f[R], \f[B]--expression\f[R]=\f[I]expr\f[R]
-Evaluates \f[I]expr\f[R].
-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.
-.RS
-.PP
-If this option is given on the command-line (i.e., not in
-\f[B]BC_ENV_ARGS\f[R], see the \f[B]ENVIRONMENT VARIABLES\f[R] section),
-then after processing all expressions and files, bc(1) will exit, unless
-\f[B]-\f[R] (\f[B]stdin\f[R]) was given as an argument at least once to
-\f[B]-f\f[R] or \f[B]--file\f[R], whether on the command-line or in
-\f[B]BC_ENV_ARGS\f[R].
-However, if any other \f[B]-e\f[R], \f[B]--expression\f[R],
-\f[B]-f\f[R], or \f[B]--file\f[R] arguments are given after
-\f[B]-f-\f[R] or equivalent is given, bc(1) will give a fatal error and
-exit.
-.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
-.TP
-\f[B]-f\f[R] \f[I]file\f[R], \f[B]--file\f[R]=\f[I]file\f[R]
-Reads in \f[I]file\f[R] and evaluates it, line by line, as though it
-were read through \f[B]stdin\f[R].
-If expressions are also given (see above), the expressions are evaluated
-in the order given.
-.RS
-.PP
-If this option is given on the command-line (i.e., not in
-\f[B]BC_ENV_ARGS\f[R], see the \f[B]ENVIRONMENT VARIABLES\f[R] section),
-then after processing all expressions and files, bc(1) will exit, unless
-\f[B]-\f[R] (\f[B]stdin\f[R]) was given as an argument at least once to
-\f[B]-f\f[R] or \f[B]--file\f[R].
-However, if any other \f[B]-e\f[R], \f[B]--expression\f[R],
-\f[B]-f\f[R], or \f[B]--file\f[R] arguments are given after
-\f[B]-f-\f[R] or equivalent is given, bc(1) will give a fatal error and
-exit.
-.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
-.TP
-\f[B]-I\f[R] \f[I]ibase\f[R], \f[B]--ibase\f[R]=\f[I]ibase\f[R]
-Sets the builtin variable \f[B]ibase\f[R] to the value \f[I]ibase\f[R]
-assuming that \f[I]ibase\f[R] is in base 10.
-It is a fatal error if \f[I]ibase\f[R] is not a valid number.
-.RS
-.PP
-If multiple instances of this option are given, the last is used.
-.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
-.TP
-\f[B]-O\f[R] \f[I]obase\f[R], \f[B]--obase\f[R]=\f[I]obase\f[R]
-Sets the builtin variable \f[B]obase\f[R] to the value \f[I]obase\f[R]
-assuming that \f[I]obase\f[R] is in base 10.
-It is a fatal error if \f[I]obase\f[R] is not a valid number.
-.RS
-.PP
-If multiple instances of this option are given, the last is used.
-.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
-.TP
-\f[B]-S\f[R] \f[I]scale\f[R], \f[B]--scale\f[R]=\f[I]scale\f[R]
-Sets the builtin variable \f[B]scale\f[R] to the value \f[I]scale\f[R]
-assuming that \f[I]scale\f[R] is in base 10.
-It is a fatal error if \f[I]scale\f[R] is not a valid number.
-.RS
-.PP
-If multiple instances of this option are given, the last is used.
-.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
.PP
All long options are \f[B]non-portable extensions\f[R].
.SH STDIN
@@ -445,10 +491,9 @@ redirect \f[B]stderr\f[R] to \f[B]/dev/null\f[R].
.SH SYNTAX
.PP
The syntax for bc(1) programs is mostly C-like, with some differences.
-This bc(1) follows the POSIX standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html),
-which is a much more thorough resource for the language this bc(1)
-accepts.
+This bc(1) follows the POSIX standard (see the \f[B]STANDARDS\f[R]
+section), 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.
.PP
@@ -655,17 +700,49 @@ This is a \f[B]non-portable extension\f[R].
Numbers are strings made up of digits, uppercase letters, and at most
\f[B]1\f[R] period for a radix.
Numbers can have up to \f[B]BC_NUM_MAX\f[R] digits.
-Uppercase letters are equal to \f[B]9\f[R] + their position in the
-alphabet (i.e., \f[B]A\f[R] equals \f[B]10\f[R], or \f[B]9+1\f[R]).
-If a digit or letter makes no sense with the current value of
-\f[B]ibase\f[R], they are set to the value of the highest valid digit in
-\f[B]ibase\f[R].
+Uppercase letters are equal to \f[B]9\f[R] plus their position in the
+alphabet, starting from \f[B]1\f[R] (i.e., \f[B]A\f[R] equals
+\f[B]10\f[R], or \f[B]9+1\f[R]).
.PP
-Single-character numbers (i.e., \f[B]A\f[R] alone) take the value that
-they would have if they were valid digits, regardless of the value of
-\f[B]ibase\f[R].
+If a digit or letter makes no sense with the current value of
+\f[B]ibase\f[R] (i.e., they are greater than or equal to the current
+value of \f[B]ibase\f[R]), then the behavior depends on the existence of
+the \f[B]-c\f[R]/\f[B]--digit-clamp\f[R] or
+\f[B]-C\f[R]/\f[B]--no-digit-clamp\f[R] options (see the
+\f[B]OPTIONS\f[R] section), the existence and setting of the
+\f[B]BC_DIGIT_CLAMP\f[R] environment variable (see the \f[B]ENVIRONMENT
+VARIABLES\f[R] section), or the default, which can be queried with the
+\f[B]-h\f[R]/\f[B]--help\f[R] option.
+.PP
+If clamping is off, then digits or letters that are greater than or
+equal to the current value of \f[B]ibase\f[R] are not changed.
+Instead, their given value is multiplied by the appropriate power of
+\f[B]ibase\f[R] and added into the number.
+This means that, with an \f[B]ibase\f[R] of \f[B]3\f[R], the number
+\f[B]AB\f[R] is equal to \f[B]3\[ha]1*A+3\[ha]0*B\f[R], which is
+\f[B]3\f[R] times \f[B]10\f[R] plus \f[B]11\f[R], or \f[B]41\f[R].
+.PP
+If clamping is on, then digits or letters that are greater than or equal
+to the current value of \f[B]ibase\f[R] are set to the value of the
+highest valid digit in \f[B]ibase\f[R] before being multiplied by the
+appropriate power of \f[B]ibase\f[R] and added into the number.
+This means that, with an \f[B]ibase\f[R] of \f[B]3\f[R], the number
+\f[B]AB\f[R] is equal to \f[B]3\[ha]1*2+3\[ha]0*2\f[R], which is
+\f[B]3\f[R] times \f[B]2\f[R] plus \f[B]2\f[R], or \f[B]8\f[R].
+.PP
+There is one exception to clamping: single-character numbers (i.e.,
+\f[B]A\f[R] alone).
+Such numbers are never clamped and always take the value they would have
+in the highest possible \f[B]ibase\f[R].
This means that \f[B]A\f[R] alone always equals decimal \f[B]10\f[R] and
\f[B]Z\f[R] alone always equals decimal \f[B]35\f[R].
+This behavior is mandated by the standard (see the STANDARDS section)
+and is meant to provide an easy way to set the current \f[B]ibase\f[R]
+(with the \f[B]i\f[R] command) regardless of the current value of
+\f[B]ibase\f[R].
+.PP
+If clamping is on, and the clamped value of a character is needed, use a
+leading zero, i.e., for \f[B]A\f[R], use \f[B]0A\f[R].
.SS Operators
.PP
The following arithmetic and logical operators can be used.
@@ -853,8 +930,7 @@ Note that unlike in C, these operators have a lower precedence than the
\f[B]assignment\f[R] operators, which means that \f[B]a=b>c\f[R] is
interpreted as \f[B](a=b)>c\f[R].
.PP
-Also, unlike the standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html)
+Also, unlike the standard (see the \f[B]STANDARDS\f[R] section)
requires, these operators can appear anywhere any other expressions can
be used.
This allowance is a \f[B]non-portable extension\f[R].
@@ -886,8 +962,8 @@ The following items are statements:
.IP " 1." 4
\f[B]E\f[R]
.IP " 2." 4
-\f[B]{\f[R] \f[B]S\f[R] \f[B];\f[R] \&... \f[B];\f[R] \f[B]S\f[R]
-\f[B]}\f[R]
+\f[B]{\f[R] \f[B]S\f[R] \f[B];\f[R] \&...
+\f[B];\f[R] \f[B]S\f[R] \f[B]}\f[R]
.IP " 3." 4
\f[B]if\f[R] \f[B](\f[R] \f[B]E\f[R] \f[B])\f[R] \f[B]S\f[R]
.IP " 4." 4
@@ -913,9 +989,11 @@ An empty statement
.IP "13." 4
A string of characters, enclosed in double quotes
.IP "14." 4
-\f[B]print\f[R] \f[B]E\f[R] \f[B],\f[R] \&... \f[B],\f[R] \f[B]E\f[R]
+\f[B]print\f[R] \f[B]E\f[R] \f[B],\f[R] \&...
+\f[B],\f[R] \f[B]E\f[R]
.IP "15." 4
-\f[B]stream\f[R] \f[B]E\f[R] \f[B],\f[R] \&... \f[B],\f[R] \f[B]E\f[R]
+\f[B]stream\f[R] \f[B]E\f[R] \f[B],\f[R] \&...
+\f[B],\f[R] \f[B]E\f[R]
.IP "16." 4
\f[B]I()\f[R], \f[B]I(E)\f[R], \f[B]I(E, E)\f[R], and so on, where
\f[B]I\f[R] is an identifier for a \f[B]void\f[R] function (see the
@@ -1143,9 +1221,8 @@ All of the functions below are available when the \f[B]-l\f[R] or
\f[B]--mathlib\f[R] command-line flags are given.
.SS Standard Library
.PP
-The standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html)
-defines the following functions for the math library:
+The standard (see the \f[B]STANDARDS\f[R] section) defines the following
+functions for the math library:
.TP
\f[B]s(x)\f[R]
Returns the sine of \f[B]x\f[R], which is assumed to be in radians.
@@ -1333,7 +1410,8 @@ at which they become a problem.
In fact, memory should be exhausted before these limits should be hit.
.SH ENVIRONMENT VARIABLES
.PP
-bc(1) recognizes the following environment variables:
+As \f[B]non-portable extensions\f[R], bc(1) recognizes the following
+environment variables:
.TP
\f[B]POSIXLY_CORRECT\f[R]
If this variable exists (no matter the contents), bc(1) behaves as if
@@ -1453,6 +1531,22 @@ expressions and expression files, and a zero value makes bc(1) not exit.
This environment variable overrides the default, which can be queried
with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
.RE
+.TP
+\f[B]BC_DIGIT_CLAMP\f[R]
+When parsing numbers and if this environment variable exists and
+contains an integer, a non-zero value makes bc(1) clamp digits that are
+greater than or equal to the current \f[B]ibase\f[R] so that all such
+digits are considered equal to the \f[B]ibase\f[R] minus 1, and a zero
+value disables such clamping so that those digits are always equal to
+their value, which is multiplied by the power of the \f[B]ibase\f[R].
+.RS
+.PP
+This never applies to single-digit numbers, as per the standard (see the
+\f[B]STANDARDS\f[R] section).
+.PP
+This environment variable overrides the default, which can be queried
+with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
+.RE
.SH EXIT STATUS
.PP
bc(1) returns the following exit statuses:
@@ -1532,9 +1626,8 @@ checking, and its normal behavior can be forced by using the
\f[B]-i\f[R] flag or \f[B]--interactive\f[R] option.
.SH INTERACTIVE MODE
.PP
-Per the standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html),
-bc(1) has an interactive mode and a non-interactive mode.
+Per the standard (see the \f[B]STANDARDS\f[R] section), bc(1) has an
+interactive mode and a non-interactive mode.
Interactive mode is turned on automatically when both \f[B]stdin\f[R]
and \f[B]stdout\f[R] are hooked to a terminal, but the \f[B]-i\f[R] flag
and \f[B]--interactive\f[R] option can turn it on in other situations.
@@ -1566,8 +1659,7 @@ The default setting can be queried with the \f[B]-h\f[R] or
\f[B]--help\f[R] options.
.PP
TTY mode is different from interactive mode because interactive mode is
-required in the bc(1) standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html),
+required in the bc(1) standard (see the \f[B]STANDARDS\f[R] section),
and interactive mode requires only \f[B]stdin\f[R] and \f[B]stdout\f[R]
to be connected to a terminal.
.SS Command-Line History
diff --git a/manuals/bc/EN.1.md b/manuals/bc/EN.1.md
index 3ebd10f8ecb5..2e76a2d3b289 100644
--- a/manuals/bc/EN.1.md
+++ b/manuals/bc/EN.1.md
@@ -34,21 +34,21 @@ 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*...]
+**bc** [**-cCghilPqRsvVw**] [**-\-digit-clamp**] [**-\-no-digit-clamp**] [**-\-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 at
-https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html .) The
-language provides unlimited precision decimal arithmetic and is somewhat C-like,
-but there are differences. Such differences will be noted in this document.
+POSIX. (See the **STANDARDS** section.) 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**.
-This bc(1) is a drop-in replacement for *any* bc(1), including (and especially)
-the GNU bc(1).
+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.
**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
@@ -63,6 +63,77 @@ that is a bug and should be reported. See the **BUGS** section.
The following are the options that bc(1) accepts.
+**-C**, **-\-no-digit-clamp**
+
+: Disables clamping of digits greater than or equal to the current **ibase**
+ when parsing numbers.
+
+ This means that the value added to a number from a digit is always that
+ digit's value multiplied by the value of ibase raised to the power of the
+ digit's position, which starts from 0 at the least significant digit.
+
+ If this and/or the **-c** or **-\-digit-clamp** options are given multiple
+ times, the last one given is used.
+
+ This option overrides the **BC_DIGIT_CLAMP** environment variable (see the
+ **ENVIRONMENT VARIABLES** section) and the default, which can be queried
+ with the **-h** or **-\-help** options.
+
+ This is a **non-portable extension**.
+
+**-c**, **-\-digit-clamp**
+
+: Enables clamping of digits greater than or equal to the current **ibase**
+ when parsing numbers.
+
+ This means that digits that the value added to a number from a digit that is
+ greater than or equal to the ibase is the value of ibase minus 1 all
+ multiplied by the value of ibase raised to the power of the digit's
+ position, which starts from 0 at the least significant digit.
+
+ If this and/or the **-C** or **-\-no-digit-clamp** options are given
+ multiple times, the last one given is used.
+
+ This option overrides the **BC_DIGIT_CLAMP** environment variable (see the
+ **ENVIRONMENT VARIABLES** section) and the default, which can be queried
+ with the **-h** or **-\-help** options.
+
+ 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 the **-f** and **-\-file** options),
+ 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 the **-e** and
+ **-\-expression** options), 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**.
+
**-g**, **-\-global-stacks**
: Turns the globals **ibase**, **obase**, and **scale** into stacks.
@@ -118,7 +189,16 @@ The following are the options that bc(1) accepts.
**-h**, **-\-help**
-: Prints a usage message and quits.
+: Prints a usage message and exits.
+
+**-I** *ibase*, **-\-ibase**=*ibase*
+
+: Sets the builtin variable **ibase** to the value *ibase* assuming that
+ *ibase* is in base 10. It is a fatal error if *ibase* is not a valid number.
+
+ If multiple instances of this option are given, the last is used.
+
+ This is a **non-portable extension**.
**-i**, **-\-interactive**
@@ -142,6 +222,15 @@ The following are the options that bc(1) accepts.
To learn what is in the library, see the **LIBRARY** section.
+**-O** *obase*, **-\-obase**=*obase*
+
+: Sets the builtin variable **obase** to the value *obase* assuming that
+ *obase* is in base 10. It is a fatal error if *obase* is not a valid number.
+
+ If multiple instances of this option are given, the last is used.
+
+ This is a **non-portable extension**.
+
**-P**, **-\-no-prompt**
: Disables the prompt in TTY mode. (The prompt is only enabled in TTY mode.
@@ -155,6 +244,19 @@ The following are the options that bc(1) accepts.
This is a **non-portable extension**.
+**-q**, **-\-quiet**
+
+: This option is for compatibility with the GNU bc(1)
+ (https://www.gnu.org/software/bc/); 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
+ unless the **BC_BANNER** environment variable is set and contains a non-zero
+ integer or if this bc(1) was built with the header displayed by default. If
+ *any* of that is the case, then this option *does* prevent bc(1) from
+ printing the header.
+
+ This is a **non-portable extension**.
+
**-R**, **-\-no-read-prompt**
: Disables the read prompt in TTY mode. (The read prompt is only enabled in
@@ -204,35 +306,29 @@ The following are the options that bc(1) accepts.
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
- (https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html). It is
- a fatal error to attempt to redefine words that this bc(1) does not reserve
- as keywords.
+ It is a fatal error to redefine keywords mandated by the POSIX standard (see
+ the **STANDARDS** section). It is a fatal error to attempt to redefine words
+ that this bc(1) does not reserve as keywords.
-**-q**, **-\-quiet**
+**-S** *scale*, **-\-scale**=*scale*
-: This option is for compatibility with the GNU bc(1)
- (https://www.gnu.org/software/bc/); 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
- unless the **BC_BANNER** environment variable is set and contains a non-zero
- integer or if this bc(1) was built with the header displayed by default. If
- *any* of that is the case, then this option *does* prevent bc(1) from
- printing the header.
+: Sets the builtin variable **scale** to the value *scale* assuming that
+ *scale* is in base 10. It is a fatal error if *scale* is not a valid number.
+
+ If multiple instances of this option are given, the last is used.
This is a **non-portable extension**.
**-s**, **-\-standard**
-: Process exactly the language defined by the standard
- (https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html) and
- error if any extensions are used.
+: Process exactly the language defined by the standard (see the **STANDARDS**
+ section) and error if any extensions are used.
This is a **non-portable extension**.
**-v**, **-V**, **-\-version**
-: Print the version information (copyright header) and exit.
+: Print the version information (copyright header) and exits.
This is a **non-portable extension**.
@@ -254,65 +350,6 @@ The following are the options that bc(1) accepts.
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**.
-
-**-I** *ibase*, **-\-ibase**=*ibase*
-
-: Sets the builtin variable **ibase** to the value *ibase* assuming that
- *ibase* is in base 10. It is a fatal error if *ibase* is not a valid number.
-
- If multiple instances of this option are given, the last is used.
-
- This is a **non-portable extension**.
-
-**-O** *obase*, **-\-obase**=*obase*
-
-: Sets the builtin variable **obase** to the value *obase* assuming that
- *obase* is in base 10. It is a fatal error if *obase* is not a valid number.
-
- If multiple instances of this option are given, the last is used.
-
- This is a **non-portable extension**.
-
-**-S** *scale*, **-\-scale**=*scale*
-
-: Sets the builtin variable **scale** to the value *scale* assuming that
- *scale* is in base 10. It is a fatal error if *scale* is not a valid number.
-
- If multiple instances of this option are given, the last is used.
-
- This is a **non-portable extension**.
-
All long options are **non-portable extensions**.
# STDIN
@@ -364,8 +401,7 @@ it is recommended that those scripts be changed to redirect **stderr** to
# SYNTAX
The syntax for bc(1) programs is mostly C-like, with some differences. This
-bc(1) follows the POSIX standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html), which is a
+bc(1) follows the POSIX standard (see the **STANDARDS** section), 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.
@@ -509,14 +545,40 @@ The following are valid operands in bc(1):
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**.
+letters are equal to **9** plus their position in the alphabet, starting from
+**1** (i.e., **A** equals **10**, or **9+1**).
+
+If a digit or letter makes no sense with the current value of **ibase** (i.e.,
+they are greater than or equal to the current value of **ibase**), then the
+behavior depends on the existence of the **-c**/**-\-digit-clamp** or
+**-C**/**-\-no-digit-clamp** options (see the **OPTIONS** section), the
+existence and setting of the **BC_DIGIT_CLAMP** environment variable (see the
+**ENVIRONMENT VARIABLES** section), or the default, which can be queried with
+the **-h**/**-\-help** option.
+
+If clamping is off, then digits or letters that are greater than or equal to the
+current value of **ibase** are not changed. Instead, their given value is
+multiplied by the appropriate power of **ibase** and added into the number. This
+means that, with an **ibase** of **3**, the number **AB** is equal to
+**3\^1\*A+3\^0\*B**, which is **3** times **10** plus **11**, or **41**.
+
+If clamping is on, then digits or letters that are greater than or equal to the
+current value of **ibase** are set to the value of the highest valid digit in
+**ibase** before being multiplied by the appropriate power of **ibase** and
+added into the number. This means that, with an **ibase** of **3**, the number
+**AB** is equal to **3\^1\*2+3\^0\*2**, which is **3** times **2** plus **2**,
+or **8**.
+
+There is one exception to clamping: single-character numbers (i.e., **A**
+alone). Such numbers are never clamped and always take the value they would have
+in the highest possible **ibase**. This means that **A** alone always equals
+decimal **10** and **Z** alone always equals decimal **35**. This behavior is
+mandated by the standard (see the STANDARDS section) and is meant to provide an
+easy way to set the current **ibase** (with the **i** command) regardless of the
+current value of **ibase**.
+
+If clamping is on, and the clamped value of a character is needed, use a leading
+zero, i.e., for **A**, use **0A**.
## Operators
@@ -683,10 +745,9 @@ The operators will be described in more detail below.
**assignment** operators, which means that **a=b\>c** is interpreted as
**(a=b)\>c**.
- Also, unlike the standard
- (https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html)
- requires, these operators can appear anywhere any other expressions can be
- used. This allowance is a **non-portable extension**.
+ Also, unlike the standard (see the **STANDARDS** section) requires, these
+ operators can appear anywhere any other expressions can be used. This
+ allowance is a **non-portable extension**.
**&&**
@@ -919,9 +980,8 @@ command-line flags are given.
## Standard Library
-The standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html) defines the
-following functions for the math library:
+The standard (see the **STANDARDS** section) defines the following functions for
+the math library:
**s(x)**
@@ -1093,7 +1153,8 @@ be hit.
# ENVIRONMENT VARIABLES
-bc(1) recognizes the following environment variables:
+As **non-portable extensions**, bc(1) recognizes the following environment
+variables:
**POSIXLY_CORRECT**
@@ -1199,6 +1260,21 @@ bc(1) recognizes the following environment variables:
This environment variable overrides the default, which can be queried with
the **-h** or **-\-help** options.
+**BC_DIGIT_CLAMP**
+
+: When parsing numbers and if this environment variable exists and contains an
+ integer, a non-zero value makes bc(1) clamp digits that are greater than or
+ equal to the current **ibase** so that all such digits are considered equal
+ to the **ibase** minus 1, and a zero value disables such clamping so that
+ those digits are always equal to their value, which is multiplied by the
+ power of the **ibase**.
+
+ This never applies to single-digit numbers, as per the standard (see the
+ **STANDARDS** section).
+
+ 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:
@@ -1272,12 +1348,10 @@ checking, and its normal behavior can be forced by using the **-i** flag or
# INTERACTIVE MODE
-Per the standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html), 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.
+Per the standard (see the **STANDARDS** section), 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
@@ -1303,10 +1377,8 @@ 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) standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html), and
-interactive mode requires only **stdin** and **stdout** to be connected to a
-terminal.
+in the bc(1) standard (see the **STANDARDS** section), and interactive mode
+requires only **stdin** and **stdout** to be connected to a terminal.
## Command-Line History
diff --git a/manuals/bc/H.1 b/manuals/bc/H.1
index b3e3880b0723..750b38976a26 100644
--- a/manuals/bc/H.1
+++ b/manuals/bc/H.1
@@ -25,7 +25,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.TH "BC" "1" "June 2022" "Gavin D. Howard" "General Commands Manual"
+.TH "BC" "1" "August 2022" "Gavin D. Howard" "General Commands Manual"
.nh
.ad l
.SH NAME
@@ -33,24 +33,25 @@
bc - arbitrary-precision decimal arithmetic language and calculator
.SH SYNOPSIS
.PP
-\f[B]bc\f[R] [\f[B]-ghilPqRsvVw\f[R]] [\f[B]--global-stacks\f[R]]
+\f[B]bc\f[R] [\f[B]-cCghilPqRsvVw\f[R]] [\f[B]--digit-clamp\f[R]]
+[\f[B]--no-digit-clamp\f[R]] [\f[B]--global-stacks\f[R]]
[\f[B]--help\f[R]] [\f[B]--interactive\f[R]] [\f[B]--mathlib\f[R]]
[\f[B]--no-prompt\f[R]] [\f[B]--no-read-prompt\f[R]] [\f[B]--quiet\f[R]]
[\f[B]--standard\f[R]] [\f[B]--warn\f[R]] [\f[B]--version\f[R]]
[\f[B]-e\f[R] \f[I]expr\f[R]]
-[\f[B]--expression\f[R]=\f[I]expr\f[R]\&...] [\f[B]-f\f[R]
-\f[I]file\f[R]\&...] [\f[B]--file\f[R]=\f[I]file\f[R]\&...]
-[\f[I]file\f[R]\&...] [\f[B]-I\f[R] \f[I]ibase\f[R]]
-[\f[B]--ibase\f[R]=\f[I]ibase\f[R]] [\f[B]-O\f[R] \f[I]obase\f[R]]
-[\f[B]--obase\f[R]=\f[I]obase\f[R]] [\f[B]-S\f[R] \f[I]scale\f[R]]
-[\f[B]--scale\f[R]=\f[I]scale\f[R]] [\f[B]-E\f[R] \f[I]seed\f[R]]
-[\f[B]--seed\f[R]=\f[I]seed\f[R]]
+[\f[B]--expression\f[R]=\f[I]expr\f[R]\&...]
+[\f[B]-f\f[R] \f[I]file\f[R]\&...]
+[\f[B]--file\f[R]=\f[I]file\f[R]\&...]
+[\f[I]file\f[R]\&...]
+[\f[B]-I\f[R] \f[I]ibase\f[R]] [\f[B]--ibase\f[R]=\f[I]ibase\f[R]]
+[\f[B]-O\f[R] \f[I]obase\f[R]] [\f[B]--obase\f[R]=\f[I]obase\f[R]]
+[\f[B]-S\f[R] \f[I]scale\f[R]] [\f[B]--scale\f[R]=\f[I]scale\f[R]]
+[\f[B]-E\f[R] \f[I]seed\f[R]] [\f[B]--seed\f[R]=\f[I]seed\f[R]]
.SH DESCRIPTION
.PP
bc(1) is an interactive processor for a language first standardized in
1991 by POSIX.
-(The current standard is at
-https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html .)
+(See the \f[B]STANDARDS\f[R] section.)
The language provides unlimited precision decimal arithmetic and is
somewhat C-like, but there are differences.
Such differences will be noted in this document.
@@ -79,6 +80,102 @@ See the \f[B]BUGS\f[R] section.
.PP
The following are the options that bc(1) accepts.
.TP
+\f[B]-C\f[R], \f[B]--no-digit-clamp\f[R]
+Disables clamping of digits greater than or equal to the current
+\f[B]ibase\f[R] when parsing numbers.
+.RS
+.PP
+This means that the value added to a number from a digit is always that
+digit\[cq]s value multiplied by the value of ibase raised to the power
+of the digit\[cq]s position, which starts from 0 at the least
+significant digit.
+.PP
+If this and/or the \f[B]-c\f[R] or \f[B]--digit-clamp\f[R] options are
+given multiple times, the last one given is used.
+.PP
+This option overrides the \f[B]BC_DIGIT_CLAMP\f[R] environment variable
+(see the \f[B]ENVIRONMENT VARIABLES\f[R] section) and the default, which
+can be queried with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
+\f[B]-c\f[R], \f[B]--digit-clamp\f[R]
+Enables clamping of digits greater than or equal to the current
+\f[B]ibase\f[R] when parsing numbers.
+.RS
+.PP
+This means that digits that the value added to a number from a digit
+that is greater than or equal to the ibase is the value of ibase minus 1
+all multiplied by the value of ibase raised to the power of the
+digit\[cq]s position, which starts from 0 at the least significant
+digit.
+.PP
+If this and/or the \f[B]-C\f[R] or \f[B]--no-digit-clamp\f[R] options
+are given multiple times, the last one given is used.
+.PP
+This option overrides the \f[B]BC_DIGIT_CLAMP\f[R] environment variable
+(see the \f[B]ENVIRONMENT VARIABLES\f[R] section) and the default, which
+can be queried with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
+\f[B]-E\f[R] \f[I]seed\f[R], \f[B]--seed\f[R]=\f[I]seed\f[R]
+Sets the builtin variable \f[B]seed\f[R] to the value \f[I]seed\f[R]
+assuming that \f[I]seed\f[R] is in base 10.
+It is a fatal error if \f[I]seed\f[R] is not a valid number.
+.RS
+.PP
+If multiple instances of this option are given, the last is used.
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
+\f[B]-e\f[R] \f[I]expr\f[R], \f[B]--expression\f[R]=\f[I]expr\f[R]
+Evaluates \f[I]expr\f[R].
+If multiple expressions are given, they are evaluated in order.
+If files are given as well (see the \f[B]-f\f[R] and \f[B]--file\f[R]
+options), 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.
+.RS
+.PP
+If this option is given on the command-line (i.e., not in
+\f[B]BC_ENV_ARGS\f[R], see the \f[B]ENVIRONMENT VARIABLES\f[R] section),
+then after processing all expressions and files, bc(1) will exit, unless
+\f[B]-\f[R] (\f[B]stdin\f[R]) was given as an argument at least once to
+\f[B]-f\f[R] or \f[B]--file\f[R], whether on the command-line or in
+\f[B]BC_ENV_ARGS\f[R].
+However, if any other \f[B]-e\f[R], \f[B]--expression\f[R],
+\f[B]-f\f[R], or \f[B]--file\f[R] arguments are given after
+\f[B]-f-\f[R] or equivalent is given, bc(1) will give a fatal error and
+exit.
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
+\f[B]-f\f[R] \f[I]file\f[R], \f[B]--file\f[R]=\f[I]file\f[R]
+Reads in \f[I]file\f[R] and evaluates it, line by line, as though it
+were read through \f[B]stdin\f[R].
+If expressions are also given (see the \f[B]-e\f[R] and
+\f[B]--expression\f[R] options), the expressions are evaluated in the
+order given.
+.RS
+.PP
+If this option is given on the command-line (i.e., not in
+\f[B]BC_ENV_ARGS\f[R], see the \f[B]ENVIRONMENT VARIABLES\f[R] section),
+then after processing all expressions and files, bc(1) will exit, unless
+\f[B]-\f[R] (\f[B]stdin\f[R]) was given as an argument at least once to
+\f[B]-f\f[R] or \f[B]--file\f[R].
+However, if any other \f[B]-e\f[R], \f[B]--expression\f[R],
+\f[B]-f\f[R], or \f[B]--file\f[R] arguments are given after
+\f[B]-f-\f[R] or equivalent is given, bc(1) will give a fatal error and
+exit.
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
\f[B]-g\f[R], \f[B]--global-stacks\f[R]
Turns the globals \f[B]ibase\f[R], \f[B]obase\f[R], \f[B]scale\f[R], and
\f[B]seed\f[R] into stacks.
@@ -172,7 +269,18 @@ This is a \f[B]non-portable extension\f[R].
.RE
.TP
\f[B]-h\f[R], \f[B]--help\f[R]
-Prints a usage message and quits.
+Prints a usage message and exits.
+.TP
+\f[B]-I\f[R] \f[I]ibase\f[R], \f[B]--ibase\f[R]=\f[I]ibase\f[R]
+Sets the builtin variable \f[B]ibase\f[R] to the value \f[I]ibase\f[R]
+assuming that \f[I]ibase\f[R] is in base 10.
+It is a fatal error if \f[I]ibase\f[R] is not a valid number.
+.RS
+.PP
+If multiple instances of this option are given, the last is used.
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
.TP
\f[B]-i\f[R], \f[B]--interactive\f[R]
Forces interactive mode.
@@ -202,11 +310,23 @@ command line.
To learn what is in the libraries, see the \f[B]LIBRARY\f[R] section.
.RE
.TP
+\f[B]-O\f[R] \f[I]obase\f[R], \f[B]--obase\f[R]=\f[I]obase\f[R]
+Sets the builtin variable \f[B]obase\f[R] to the value \f[I]obase\f[R]
+assuming that \f[I]obase\f[R] is in base 10.
+It is a fatal error if \f[I]obase\f[R] is not a valid number.
+.RS
+.PP
+If multiple instances of this option are given, the last is used.
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
\f[B]-P\f[R], \f[B]--no-prompt\f[R]
Disables the prompt in TTY mode.
(The prompt is only enabled in TTY mode.
-See the \f[B]TTY MODE\f[R] section.) This is mostly for those users that
-do not want a prompt or are not used to having them in bc(1).
+See the \f[B]TTY MODE\f[R] 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
\f[B]BC_ENV_ARGS\f[R] (see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
.RS
@@ -217,11 +337,28 @@ environment variables (see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
This is a \f[B]non-portable extension\f[R].
.RE
.TP
+\f[B]-q\f[R], \f[B]--quiet\f[R]
+This option is for compatibility with the GNU bc(1)
+(https://www.gnu.org/software/bc/); 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
+\f[B]-v\f[R], \f[B]-V\f[R], or \f[B]--version\f[R] options are given
+unless the \f[B]BC_BANNER\f[R] environment variable is set and contains
+a non-zero integer or if this bc(1) was built with the header displayed
+by default.
+If \f[I]any\f[R] of that is the case, then this option \f[I]does\f[R]
+prevent bc(1) from printing the header.
+.RS
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
\f[B]-R\f[R], \f[B]--no-read-prompt\f[R]
Disables the read prompt in TTY mode.
(The read prompt is only enabled in TTY mode.
-See the \f[B]TTY MODE\f[R] section.) This is mostly for those users that
-do not want a read prompt or are not used to having them in bc(1).
+See the \f[B]TTY MODE\f[R] 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
\f[B]BC_ENV_ARGS\f[R] (see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
This option is also useful in hash bang lines of bc(1) scripts that
@@ -294,38 +431,32 @@ Keywords are \f[I]not\f[R] redefined when parsing the builtin math
library (see the \f[B]LIBRARY\f[R] section).
.PP
It is a fatal error to redefine keywords mandated by the POSIX standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html).
+(see the \f[B]STANDARDS\f[R] section).
It is a fatal error to attempt to redefine words that this bc(1) does
not reserve as keywords.
.RE
.TP
-\f[B]-q\f[R], \f[B]--quiet\f[R]
-This option is for compatibility with the GNU bc(1)
-(https://www.gnu.org/software/bc/); 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
-\f[B]-v\f[R], \f[B]-V\f[R], or \f[B]--version\f[R] options are given
-unless the \f[B]BC_BANNER\f[R] environment variable is set and contains
-a non-zero integer or if this bc(1) was built with the header displayed
-by default.
-If \f[I]any\f[R] of that is the case, then this option \f[I]does\f[R]
-prevent bc(1) from printing the header.
+\f[B]-S\f[R] \f[I]scale\f[R], \f[B]--scale\f[R]=\f[I]scale\f[R]
+Sets the builtin variable \f[B]scale\f[R] to the value \f[I]scale\f[R]
+assuming that \f[I]scale\f[R] is in base 10.
+It is a fatal error if \f[I]scale\f[R] is not a valid number.
.RS
.PP
+If multiple instances of this option are given, the last is used.
+.PP
This is a \f[B]non-portable extension\f[R].
.RE
.TP
\f[B]-s\f[R], \f[B]--standard\f[R]
-Process exactly the language defined by the standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html) and
-error if any extensions are used.
+Process exactly the language defined by the standard (see the
+\f[B]STANDARDS\f[R] section) and error if any extensions are used.
.RS
.PP
This is a \f[B]non-portable extension\f[R].
.RE
.TP
\f[B]-v\f[R], \f[B]-V\f[R], \f[B]--version\f[R]
-Print the version information (copyright header) and exit.
+Print the version information (copyright header) and exits.
.RS
.PP
This is a \f[B]non-portable extension\f[R].
@@ -351,93 +482,6 @@ extended math library (see the \f[B]LIBRARY\f[R] section).
.PP
This is a \f[B]non-portable extension\f[R].
.RE
-.TP
-\f[B]-e\f[R] \f[I]expr\f[R], \f[B]--expression\f[R]=\f[I]expr\f[R]
-Evaluates \f[I]expr\f[R].
-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.
-.RS
-.PP
-If this option is given on the command-line (i.e., not in
-\f[B]BC_ENV_ARGS\f[R], see the \f[B]ENVIRONMENT VARIABLES\f[R] section),
-then after processing all expressions and files, bc(1) will exit, unless
-\f[B]-\f[R] (\f[B]stdin\f[R]) was given as an argument at least once to
-\f[B]-f\f[R] or \f[B]--file\f[R], whether on the command-line or in
-\f[B]BC_ENV_ARGS\f[R].
-However, if any other \f[B]-e\f[R], \f[B]--expression\f[R],
-\f[B]-f\f[R], or \f[B]--file\f[R] arguments are given after
-\f[B]-f-\f[R] or equivalent is given, bc(1) will give a fatal error and
-exit.
-.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
-.TP
-\f[B]-f\f[R] \f[I]file\f[R], \f[B]--file\f[R]=\f[I]file\f[R]
-Reads in \f[I]file\f[R] and evaluates it, line by line, as though it
-were read through \f[B]stdin\f[R].
-If expressions are also given (see above), the expressions are evaluated
-in the order given.
-.RS
-.PP
-If this option is given on the command-line (i.e., not in
-\f[B]BC_ENV_ARGS\f[R], see the \f[B]ENVIRONMENT VARIABLES\f[R] section),
-then after processing all expressions and files, bc(1) will exit, unless
-\f[B]-\f[R] (\f[B]stdin\f[R]) was given as an argument at least once to
-\f[B]-f\f[R] or \f[B]--file\f[R].
-However, if any other \f[B]-e\f[R], \f[B]--expression\f[R],
-\f[B]-f\f[R], or \f[B]--file\f[R] arguments are given after
-\f[B]-f-\f[R] or equivalent is given, bc(1) will give a fatal error and
-exit.
-.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
-.TP
-\f[B]-I\f[R] \f[I]ibase\f[R], \f[B]--ibase\f[R]=\f[I]ibase\f[R]
-Sets the builtin variable \f[B]ibase\f[R] to the value \f[I]ibase\f[R]
-assuming that \f[I]ibase\f[R] is in base 10.
-It is a fatal error if \f[I]ibase\f[R] is not a valid number.
-.RS
-.PP
-If multiple instances of this option are given, the last is used.
-.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
-.TP
-\f[B]-O\f[R] \f[I]obase\f[R], \f[B]--obase\f[R]=\f[I]obase\f[R]
-Sets the builtin variable \f[B]obase\f[R] to the value \f[I]obase\f[R]
-assuming that \f[I]obase\f[R] is in base 10.
-It is a fatal error if \f[I]obase\f[R] is not a valid number.
-.RS
-.PP
-If multiple instances of this option are given, the last is used.
-.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
-.TP
-\f[B]-S\f[R] \f[I]scale\f[R], \f[B]--scale\f[R]=\f[I]scale\f[R]
-Sets the builtin variable \f[B]scale\f[R] to the value \f[I]scale\f[R]
-assuming that \f[I]scale\f[R] is in base 10.
-It is a fatal error if \f[I]scale\f[R] is not a valid number.
-.RS
-.PP
-If multiple instances of this option are given, the last is used.
-.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
-.TP
-\f[B]-E\f[R] \f[I]seed\f[R], \f[B]--seed\f[R]=\f[I]seed\f[R]
-Sets the builtin variable \f[B]seed\f[R] to the value \f[I]seed\f[R]
-assuming that \f[I]seed\f[R] is in base 10.
-It is a fatal error if \f[I]seed\f[R] is not a valid number.
-.RS
-.PP
-If multiple instances of this option are given, the last is used.
-.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
.PP
All long options are \f[B]non-portable extensions\f[R].
.SH STDIN
@@ -491,10 +535,9 @@ redirect \f[B]stderr\f[R] to \f[B]/dev/null\f[R].
.SH SYNTAX
.PP
The syntax for bc(1) programs is mostly C-like, with some differences.
-This bc(1) follows the POSIX standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html),
-which is a much more thorough resource for the language this bc(1)
-accepts.
+This bc(1) follows the POSIX standard (see the \f[B]STANDARDS\f[R]
+section), 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.
.PP
@@ -776,17 +819,49 @@ In any other case, use a non-seeded pseudo-random number generator.
Numbers are strings made up of digits, uppercase letters, and at most
\f[B]1\f[R] period for a radix.
Numbers can have up to \f[B]BC_NUM_MAX\f[R] digits.
-Uppercase letters are equal to \f[B]9\f[R] + their position in the
-alphabet (i.e., \f[B]A\f[R] equals \f[B]10\f[R], or \f[B]9+1\f[R]).
-If a digit or letter makes no sense with the current value of
-\f[B]ibase\f[R], they are set to the value of the highest valid digit in
-\f[B]ibase\f[R].
+Uppercase letters are equal to \f[B]9\f[R] plus their position in the
+alphabet, starting from \f[B]1\f[R] (i.e., \f[B]A\f[R] equals
+\f[B]10\f[R], or \f[B]9+1\f[R]).
.PP
-Single-character numbers (i.e., \f[B]A\f[R] alone) take the value that
-they would have if they were valid digits, regardless of the value of
-\f[B]ibase\f[R].
+If a digit or letter makes no sense with the current value of
+\f[B]ibase\f[R] (i.e., they are greater than or equal to the current
+value of \f[B]ibase\f[R]), then the behavior depends on the existence of
+the \f[B]-c\f[R]/\f[B]--digit-clamp\f[R] or
+\f[B]-C\f[R]/\f[B]--no-digit-clamp\f[R] options (see the
+\f[B]OPTIONS\f[R] section), the existence and setting of the
+\f[B]BC_DIGIT_CLAMP\f[R] environment variable (see the \f[B]ENVIRONMENT
+VARIABLES\f[R] section), or the default, which can be queried with the
+\f[B]-h\f[R]/\f[B]--help\f[R] option.
+.PP
+If clamping is off, then digits or letters that are greater than or
+equal to the current value of \f[B]ibase\f[R] are not changed.
+Instead, their given value is multiplied by the appropriate power of
+\f[B]ibase\f[R] and added into the number.
+This means that, with an \f[B]ibase\f[R] of \f[B]3\f[R], the number
+\f[B]AB\f[R] is equal to \f[B]3\[ha]1*A+3\[ha]0*B\f[R], which is
+\f[B]3\f[R] times \f[B]10\f[R] plus \f[B]11\f[R], or \f[B]41\f[R].
+.PP
+If clamping is on, then digits or letters that are greater than or equal
+to the current value of \f[B]ibase\f[R] are set to the value of the
+highest valid digit in \f[B]ibase\f[R] before being multiplied by the
+appropriate power of \f[B]ibase\f[R] and added into the number.
+This means that, with an \f[B]ibase\f[R] of \f[B]3\f[R], the number
+\f[B]AB\f[R] is equal to \f[B]3\[ha]1*2+3\[ha]0*2\f[R], which is
+\f[B]3\f[R] times \f[B]2\f[R] plus \f[B]2\f[R], or \f[B]8\f[R].
+.PP
+There is one exception to clamping: single-character numbers (i.e.,
+\f[B]A\f[R] alone).
+Such numbers are never clamped and always take the value they would have
+in the highest possible \f[B]ibase\f[R].
This means that \f[B]A\f[R] alone always equals decimal \f[B]10\f[R] and
\f[B]Z\f[R] alone always equals decimal \f[B]35\f[R].
+This behavior is mandated by the standard (see the STANDARDS section)
+and is meant to provide an easy way to set the current \f[B]ibase\f[R]
+(with the \f[B]i\f[R] command) regardless of the current value of
+\f[B]ibase\f[R].
+.PP
+If clamping is on, and the clamped value of a character is needed, use a
+leading zero, i.e., for \f[B]A\f[R], use \f[B]0A\f[R].
.PP
In addition, bc(1) accepts numbers in scientific notation.
These have the form \f[B]<number>e<integer>\f[R].
@@ -1076,8 +1151,7 @@ Note that unlike in C, these operators have a lower precedence than the
\f[B]assignment\f[R] operators, which means that \f[B]a=b>c\f[R] is
interpreted as \f[B](a=b)>c\f[R].
.PP
-Also, unlike the standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html)
+Also, unlike the standard (see the \f[B]STANDARDS\f[R] section)
requires, these operators can appear anywhere any other expressions can
be used.
This allowance is a \f[B]non-portable extension\f[R].
@@ -1109,8 +1183,8 @@ The following items are statements:
.IP " 1." 4
\f[B]E\f[R]
.IP " 2." 4
-\f[B]{\f[R] \f[B]S\f[R] \f[B];\f[R] \&... \f[B];\f[R] \f[B]S\f[R]
-\f[B]}\f[R]
+\f[B]{\f[R] \f[B]S\f[R] \f[B];\f[R] \&...
+\f[B];\f[R] \f[B]S\f[R] \f[B]}\f[R]
.IP " 3." 4
\f[B]if\f[R] \f[B](\f[R] \f[B]E\f[R] \f[B])\f[R] \f[B]S\f[R]
.IP " 4." 4
@@ -1136,9 +1210,11 @@ An empty statement
.IP "13." 4
A string of characters, enclosed in double quotes
.IP "14." 4
-\f[B]print\f[R] \f[B]E\f[R] \f[B],\f[R] \&... \f[B],\f[R] \f[B]E\f[R]
+\f[B]print\f[R] \f[B]E\f[R] \f[B],\f[R] \&...
+\f[B],\f[R] \f[B]E\f[R]
.IP "15." 4
-\f[B]stream\f[R] \f[B]E\f[R] \f[B],\f[R] \&... \f[B],\f[R] \f[B]E\f[R]
+\f[B]stream\f[R] \f[B]E\f[R] \f[B],\f[R] \&...
+\f[B],\f[R] \f[B]E\f[R]
.IP "16." 4
\f[B]I()\f[R], \f[B]I(E)\f[R], \f[B]I(E, E)\f[R], and so on, where
\f[B]I\f[R] is an identifier for a \f[B]void\f[R] function (see the
@@ -1384,9 +1460,8 @@ when the \f[B]-s\f[R] option, the \f[B]-w\f[R] option, or equivalents
are given.
.SS Standard Library
.PP
-The standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html)
-defines the following functions for the math library:
+The standard (see the \f[B]STANDARDS\f[R] section) defines the following
+functions for the math library:
.TP
\f[B]s(x)\f[R]
Returns the sine of \f[B]x\f[R], which is assumed to be in radians.
@@ -1441,8 +1516,7 @@ Functions\f[R] subsection below).
The extended library is \f[I]not\f[R] loaded when the
\f[B]-s\f[R]/\f[B]--standard\f[R] or \f[B]-w\f[R]/\f[B]--warn\f[R]
options are given since they are not part of the library defined by the
-standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html).
+standard (see the \f[B]STANDARDS\f[R] section).
.PP
The extended library is a \f[B]non-portable extension\f[R].
.TP
@@ -2501,7 +2575,8 @@ at which they become a problem.
In fact, memory should be exhausted before these limits should be hit.
.SH ENVIRONMENT VARIABLES
.PP
-bc(1) recognizes the following environment variables:
+As \f[B]non-portable extensions\f[R], bc(1) recognizes the following
+environment variables:
.TP
\f[B]POSIXLY_CORRECT\f[R]
If this variable exists (no matter the contents), bc(1) behaves as if
@@ -2621,6 +2696,22 @@ expressions and expression files, and a zero value makes bc(1) not exit.
This environment variable overrides the default, which can be queried
with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
.RE
+.TP
+\f[B]BC_DIGIT_CLAMP\f[R]
+When parsing numbers and if this environment variable exists and
+contains an integer, a non-zero value makes bc(1) clamp digits that are
+greater than or equal to the current \f[B]ibase\f[R] so that all such
+digits are considered equal to the \f[B]ibase\f[R] minus 1, and a zero
+value disables such clamping so that those digits are always equal to
+their value, which is multiplied by the power of the \f[B]ibase\f[R].
+.RS
+.PP
+This never applies to single-digit numbers, as per the standard (see the
+\f[B]STANDARDS\f[R] section).
+.PP
+This environment variable overrides the default, which can be queried
+with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
+.RE
.SH EXIT STATUS
.PP
bc(1) returns the following exit statuses:
@@ -2702,9 +2793,8 @@ checking, and its normal behavior can be forced by using the
\f[B]-i\f[R] flag or \f[B]--interactive\f[R] option.
.SH INTERACTIVE MODE
.PP
-Per the standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html),
-bc(1) has an interactive mode and a non-interactive mode.
+Per the standard (see the \f[B]STANDARDS\f[R] section), bc(1) has an
+interactive mode and a non-interactive mode.
Interactive mode is turned on automatically when both \f[B]stdin\f[R]
and \f[B]stdout\f[R] are hooked to a terminal, but the \f[B]-i\f[R] flag
and \f[B]--interactive\f[R] option can turn it on in other situations.
@@ -2736,8 +2826,7 @@ The default setting can be queried with the \f[B]-h\f[R] or
\f[B]--help\f[R] options.
.PP
TTY mode is different from interactive mode because interactive mode is
-required in the bc(1) standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html),
+required in the bc(1) standard (see the \f[B]STANDARDS\f[R] section),
and interactive mode requires only \f[B]stdin\f[R] and \f[B]stdout\f[R]
to be connected to a terminal.
.SS Prompt
diff --git a/manuals/bc/H.1.md b/manuals/bc/H.1.md
index f494e5632967..b242b7cfa393 100644
--- a/manuals/bc/H.1.md
+++ b/manuals/bc/H.1.md
@@ -34,15 +34,14 @@ 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*...] [**-I** *ibase*] [**-\-ibase**=*ibase*] [**-O** *obase*] [**-\-obase**=*obase*] [**-S** *scale*] [**-\-scale**=*scale*] [**-E** *seed*] [**-\-seed**=*seed*]
+**bc** [**-cCghilPqRsvVw**] [**-\-digit-clamp**] [**-\-no-digit-clamp**] [**-\-global-stacks**] [**-\-help**] [**-\-interactive**] [**-\-mathlib**] [**-\-no-prompt**] [**-\-no-read-prompt**] [**-\-quiet**] [**-\-standard**] [**-\-warn**] [**-\-version**] [**-e** *expr*] [**-\-expression**=*expr*...] [**-f** *file*...] [**-\-file**=*file*...] [*file*...] [**-I** *ibase*] [**-\-ibase**=*ibase*] [**-O** *obase*] [**-\-obase**=*obase*] [**-S** *scale*] [**-\-scale**=*scale*] [**-E** *seed*] [**-\-seed**=*seed*]
# DESCRIPTION
bc(1) is an interactive processor for a language first standardized in 1991 by
-POSIX. (The current standard is at
-https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html .) The
-language provides unlimited precision decimal arithmetic and is somewhat C-like,
-but there are differences. Such differences will be noted in this document.
+POSIX. (See the **STANDARDS** section.) 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**.
@@ -64,6 +63,86 @@ that is a bug and should be reported. See the **BUGS** section.
The following are the options that bc(1) accepts.
+**-C**, **-\-no-digit-clamp**
+
+: Disables clamping of digits greater than or equal to the current **ibase**
+ when parsing numbers.
+
+ This means that the value added to a number from a digit is always that
+ digit's value multiplied by the value of ibase raised to the power of the
+ digit's position, which starts from 0 at the least significant digit.
+
+ If this and/or the **-c** or **-\-digit-clamp** options are given multiple
+ times, the last one given is used.
+
+ This option overrides the **BC_DIGIT_CLAMP** environment variable (see the
+ **ENVIRONMENT VARIABLES** section) and the default, which can be queried
+ with the **-h** or **-\-help** options.
+
+ This is a **non-portable extension**.
+
+**-c**, **-\-digit-clamp**
+
+: Enables clamping of digits greater than or equal to the current **ibase**
+ when parsing numbers.
+
+ This means that digits that the value added to a number from a digit that is
+ greater than or equal to the ibase is the value of ibase minus 1 all
+ multiplied by the value of ibase raised to the power of the digit's
+ position, which starts from 0 at the least significant digit.
+
+ If this and/or the **-C** or **-\-no-digit-clamp** options are given
+ multiple times, the last one given is used.
+
+ This option overrides the **BC_DIGIT_CLAMP** environment variable (see the
+ **ENVIRONMENT VARIABLES** section) and the default, which can be queried
+ with the **-h** or **-\-help** options.
+
+ This is a **non-portable extension**.
+
+**-E** *seed*, **-\-seed**=*seed*
+
+: Sets the builtin variable **seed** to the value *seed* assuming that *seed*
+ is in base 10. It is a fatal error if *seed* is not a valid number.
+
+ If multiple instances of this option are given, the last is used.
+
+ 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 the **-f** and **-\-file** options),
+ 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 the **-e** and
+ **-\-expression** options), 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**.
+
**-g**, **-\-global-stacks**
: Turns the globals **ibase**, **obase**, **scale**, and **seed** into stacks.
@@ -134,7 +213,16 @@ The following are the options that bc(1) accepts.
**-h**, **-\-help**
-: Prints a usage message and quits.
+: Prints a usage message and exits.
+
+**-I** *ibase*, **-\-ibase**=*ibase*
+
+: Sets the builtin variable **ibase** to the value *ibase* assuming that
+ *ibase* is in base 10. It is a fatal error if *ibase* is not a valid number.
+
+ If multiple instances of this option are given, the last is used.
+
+ This is a **non-portable extension**.
**-i**, **-\-interactive**
@@ -158,6 +246,15 @@ The following are the options that bc(1) accepts.
To learn what is in the libraries, see the **LIBRARY** section.
+**-O** *obase*, **-\-obase**=*obase*
+
+: Sets the builtin variable **obase** to the value *obase* assuming that
+ *obase* is in base 10. It is a fatal error if *obase* is not a valid number.
+
+ If multiple instances of this option are given, the last is used.
+
+ This is a **non-portable extension**.
+
**-P**, **-\-no-prompt**
: Disables the prompt in TTY mode. (The prompt is only enabled in TTY mode.
@@ -171,6 +268,19 @@ The following are the options that bc(1) accepts.
This is a **non-portable extension**.
+**-q**, **-\-quiet**
+
+: This option is for compatibility with the GNU bc(1)
+ (https://www.gnu.org/software/bc/); 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
+ unless the **BC_BANNER** environment variable is set and contains a non-zero
+ integer or if this bc(1) was built with the header displayed by default. If
+ *any* of that is the case, then this option *does* prevent bc(1) from
+ printing the header.
+
+ This is a **non-portable extension**.
+
**-R**, **-\-no-read-prompt**
: Disables the read prompt in TTY mode. (The read prompt is only enabled in
@@ -224,35 +334,29 @@ The following are the options that bc(1) accepts.
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
- (https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html). It is
- a fatal error to attempt to redefine words that this bc(1) does not reserve
- as keywords.
+ It is a fatal error to redefine keywords mandated by the POSIX standard (see
+ the **STANDARDS** section). It is a fatal error to attempt to redefine words
+ that this bc(1) does not reserve as keywords.
-**-q**, **-\-quiet**
+**-S** *scale*, **-\-scale**=*scale*
-: This option is for compatibility with the GNU bc(1)
- (https://www.gnu.org/software/bc/); 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
- unless the **BC_BANNER** environment variable is set and contains a non-zero
- integer or if this bc(1) was built with the header displayed by default. If
- *any* of that is the case, then this option *does* prevent bc(1) from
- printing the header.
+: Sets the builtin variable **scale** to the value *scale* assuming that
+ *scale* is in base 10. It is a fatal error if *scale* is not a valid number.
+
+ If multiple instances of this option are given, the last is used.
This is a **non-portable extension**.
**-s**, **-\-standard**
-: Process exactly the language defined by the standard
- (https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html) and
- error if any extensions are used.
+: Process exactly the language defined by the standard (see the **STANDARDS**
+ section) and error if any extensions are used.
This is a **non-portable extension**.
**-v**, **-V**, **-\-version**
-: Print the version information (copyright header) and exit.
+: Print the version information (copyright header) and exits.
This is a **non-portable extension**.
@@ -274,74 +378,6 @@ The following are the options that bc(1) accepts.
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**.
-
-**-I** *ibase*, **-\-ibase**=*ibase*
-
-: Sets the builtin variable **ibase** to the value *ibase* assuming that
- *ibase* is in base 10. It is a fatal error if *ibase* is not a valid number.
-
- If multiple instances of this option are given, the last is used.
-
- This is a **non-portable extension**.
-
-**-O** *obase*, **-\-obase**=*obase*
-
-: Sets the builtin variable **obase** to the value *obase* assuming that
- *obase* is in base 10. It is a fatal error if *obase* is not a valid number.
-
- If multiple instances of this option are given, the last is used.
-
- This is a **non-portable extension**.
-
-**-S** *scale*, **-\-scale**=*scale*
-
-: Sets the builtin variable **scale** to the value *scale* assuming that
- *scale* is in base 10. It is a fatal error if *scale* is not a valid number.
-
- If multiple instances of this option are given, the last is used.
-
- This is a **non-portable extension**.
-
-**-E** *seed*, **-\-seed**=*seed*
-
-: Sets the builtin variable **seed** to the value *seed* assuming that *seed*
- is in base 10. It is a fatal error if *seed* is not a valid number.
-
- If multiple instances of this option are given, the last is used.
-
- This is a **non-portable extension**.
-
All long options are **non-portable extensions**.
# STDIN
@@ -393,8 +429,7 @@ it is recommended that those scripts be changed to redirect **stderr** to
# SYNTAX
The syntax for bc(1) programs is mostly C-like, with some differences. This
-bc(1) follows the POSIX standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html), which is a
+bc(1) follows the POSIX standard (see the **STANDARDS** section), 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.
@@ -592,14 +627,40 @@ use a non-seeded pseudo-random number generator.
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**.
+letters are equal to **9** plus their position in the alphabet, starting from
+**1** (i.e., **A** equals **10**, or **9+1**).
+
+If a digit or letter makes no sense with the current value of **ibase** (i.e.,
+they are greater than or equal to the current value of **ibase**), then the
+behavior depends on the existence of the **-c**/**-\-digit-clamp** or
+**-C**/**-\-no-digit-clamp** options (see the **OPTIONS** section), the
+existence and setting of the **BC_DIGIT_CLAMP** environment variable (see the
+**ENVIRONMENT VARIABLES** section), or the default, which can be queried with
+the **-h**/**-\-help** option.
+
+If clamping is off, then digits or letters that are greater than or equal to the
+current value of **ibase** are not changed. Instead, their given value is
+multiplied by the appropriate power of **ibase** and added into the number. This
+means that, with an **ibase** of **3**, the number **AB** is equal to
+**3\^1\*A+3\^0\*B**, which is **3** times **10** plus **11**, or **41**.
+
+If clamping is on, then digits or letters that are greater than or equal to the
+current value of **ibase** are set to the value of the highest valid digit in
+**ibase** before being multiplied by the appropriate power of **ibase** and
+added into the number. This means that, with an **ibase** of **3**, the number
+**AB** is equal to **3\^1\*2+3\^0\*2**, which is **3** times **2** plus **2**,
+or **8**.
+
+There is one exception to clamping: single-character numbers (i.e., **A**
+alone). Such numbers are never clamped and always take the value they would have
+in the highest possible **ibase**. This means that **A** alone always equals
+decimal **10** and **Z** alone always equals decimal **35**. This behavior is
+mandated by the standard (see the STANDARDS section) and is meant to provide an
+easy way to set the current **ibase** (with the **i** command) regardless of the
+current value of **ibase**.
+
+If clamping is on, and the clamped value of a character is needed, use a leading
+zero, i.e., for **A**, use **0A**.
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
@@ -849,10 +910,9 @@ The operators will be described in more detail below.
**assignment** operators, which means that **a=b\>c** is interpreted as
**(a=b)\>c**.
- Also, unlike the standard
- (https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html)
- requires, these operators can appear anywhere any other expressions can be
- used. This allowance is a **non-portable extension**.
+ Also, unlike the standard (see the **STANDARDS** section) requires, these
+ operators can appear anywhere any other expressions can be used. This
+ allowance is a **non-portable extension**.
**&&**
@@ -1099,9 +1159,8 @@ equivalents are given.
## Standard Library
-The standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html) defines the
-following functions for the math library:
+The standard (see the **STANDARDS** section) defines the following functions for
+the math library:
**s(x)**
@@ -1149,8 +1208,7 @@ following functions for the math 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
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html).
+defined by the standard (see the **STANDARDS** section).
The extended library is a **non-portable extension**.
@@ -2085,7 +2143,8 @@ be hit.
# ENVIRONMENT VARIABLES
-bc(1) recognizes the following environment variables:
+As **non-portable extensions**, bc(1) recognizes the following environment
+variables:
**POSIXLY_CORRECT**
@@ -2191,6 +2250,21 @@ bc(1) recognizes the following environment variables:
This environment variable overrides the default, which can be queried with
the **-h** or **-\-help** options.
+**BC_DIGIT_CLAMP**
+
+: When parsing numbers and if this environment variable exists and contains an
+ integer, a non-zero value makes bc(1) clamp digits that are greater than or
+ equal to the current **ibase** so that all such digits are considered equal
+ to the **ibase** minus 1, and a zero value disables such clamping so that
+ those digits are always equal to their value, which is multiplied by the
+ power of the **ibase**.
+
+ This never applies to single-digit numbers, as per the standard (see the
+ **STANDARDS** section).
+
+ 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:
@@ -2266,12 +2340,10 @@ checking, and its normal behavior can be forced by using the **-i** flag or
# INTERACTIVE MODE
-Per the standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html), 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.
+Per the standard (see the **STANDARDS** section), 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
@@ -2297,10 +2369,8 @@ 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) standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html), and
-interactive mode requires only **stdin** and **stdout** to be connected to a
-terminal.
+in the bc(1) standard (see the **STANDARDS** section), and interactive mode
+requires only **stdin** and **stdout** to be connected to a terminal.
## Prompt
diff --git a/manuals/bc/HN.1 b/manuals/bc/HN.1
index 6235a3b9931c..afecefae65f0 100644
--- a/manuals/bc/HN.1
+++ b/manuals/bc/HN.1
@@ -25,7 +25,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.TH "BC" "1" "June 2022" "Gavin D. Howard" "General Commands Manual"
+.TH "BC" "1" "August 2022" "Gavin D. Howard" "General Commands Manual"
.nh
.ad l
.SH NAME
@@ -33,24 +33,25 @@
bc - arbitrary-precision decimal arithmetic language and calculator
.SH SYNOPSIS
.PP
-\f[B]bc\f[R] [\f[B]-ghilPqRsvVw\f[R]] [\f[B]--global-stacks\f[R]]
+\f[B]bc\f[R] [\f[B]-cCghilPqRsvVw\f[R]] [\f[B]--digit-clamp\f[R]]
+[\f[B]--no-digit-clamp\f[R]] [\f[B]--global-stacks\f[R]]
[\f[B]--help\f[R]] [\f[B]--interactive\f[R]] [\f[B]--mathlib\f[R]]
[\f[B]--no-prompt\f[R]] [\f[B]--no-read-prompt\f[R]] [\f[B]--quiet\f[R]]
[\f[B]--standard\f[R]] [\f[B]--warn\f[R]] [\f[B]--version\f[R]]
[\f[B]-e\f[R] \f[I]expr\f[R]]
-[\f[B]--expression\f[R]=\f[I]expr\f[R]\&...] [\f[B]-f\f[R]
-\f[I]file\f[R]\&...] [\f[B]--file\f[R]=\f[I]file\f[R]\&...]
-[\f[I]file\f[R]\&...] [\f[B]-I\f[R] \f[I]ibase\f[R]]
-[\f[B]--ibase\f[R]=\f[I]ibase\f[R]] [\f[B]-O\f[R] \f[I]obase\f[R]]
-[\f[B]--obase\f[R]=\f[I]obase\f[R]] [\f[B]-S\f[R] \f[I]scale\f[R]]
-[\f[B]--scale\f[R]=\f[I]scale\f[R]] [\f[B]-E\f[R] \f[I]seed\f[R]]
-[\f[B]--seed\f[R]=\f[I]seed\f[R]]
+[\f[B]--expression\f[R]=\f[I]expr\f[R]\&...]
+[\f[B]-f\f[R] \f[I]file\f[R]\&...]
+[\f[B]--file\f[R]=\f[I]file\f[R]\&...]
+[\f[I]file\f[R]\&...]
+[\f[B]-I\f[R] \f[I]ibase\f[R]] [\f[B]--ibase\f[R]=\f[I]ibase\f[R]]
+[\f[B]-O\f[R] \f[I]obase\f[R]] [\f[B]--obase\f[R]=\f[I]obase\f[R]]
+[\f[B]-S\f[R] \f[I]scale\f[R]] [\f[B]--scale\f[R]=\f[I]scale\f[R]]
+[\f[B]-E\f[R] \f[I]seed\f[R]] [\f[B]--seed\f[R]=\f[I]seed\f[R]]
.SH DESCRIPTION
.PP
bc(1) is an interactive processor for a language first standardized in
1991 by POSIX.
-(The current standard is at
-https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html .)
+(See the \f[B]STANDARDS\f[R] section.)
The language provides unlimited precision decimal arithmetic and is
somewhat C-like, but there are differences.
Such differences will be noted in this document.
@@ -79,6 +80,102 @@ See the \f[B]BUGS\f[R] section.
.PP
The following are the options that bc(1) accepts.
.TP
+\f[B]-C\f[R], \f[B]--no-digit-clamp\f[R]
+Disables clamping of digits greater than or equal to the current
+\f[B]ibase\f[R] when parsing numbers.
+.RS
+.PP
+This means that the value added to a number from a digit is always that
+digit\[cq]s value multiplied by the value of ibase raised to the power
+of the digit\[cq]s position, which starts from 0 at the least
+significant digit.
+.PP
+If this and/or the \f[B]-c\f[R] or \f[B]--digit-clamp\f[R] options are
+given multiple times, the last one given is used.
+.PP
+This option overrides the \f[B]BC_DIGIT_CLAMP\f[R] environment variable
+(see the \f[B]ENVIRONMENT VARIABLES\f[R] section) and the default, which
+can be queried with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
+\f[B]-c\f[R], \f[B]--digit-clamp\f[R]
+Enables clamping of digits greater than or equal to the current
+\f[B]ibase\f[R] when parsing numbers.
+.RS
+.PP
+This means that digits that the value added to a number from a digit
+that is greater than or equal to the ibase is the value of ibase minus 1
+all multiplied by the value of ibase raised to the power of the
+digit\[cq]s position, which starts from 0 at the least significant
+digit.
+.PP
+If this and/or the \f[B]-C\f[R] or \f[B]--no-digit-clamp\f[R] options
+are given multiple times, the last one given is used.
+.PP
+This option overrides the \f[B]BC_DIGIT_CLAMP\f[R] environment variable
+(see the \f[B]ENVIRONMENT VARIABLES\f[R] section) and the default, which
+can be queried with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
+\f[B]-E\f[R] \f[I]seed\f[R], \f[B]--seed\f[R]=\f[I]seed\f[R]
+Sets the builtin variable \f[B]seed\f[R] to the value \f[I]seed\f[R]
+assuming that \f[I]seed\f[R] is in base 10.
+It is a fatal error if \f[I]seed\f[R] is not a valid number.
+.RS
+.PP
+If multiple instances of this option are given, the last is used.
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
+\f[B]-e\f[R] \f[I]expr\f[R], \f[B]--expression\f[R]=\f[I]expr\f[R]
+Evaluates \f[I]expr\f[R].
+If multiple expressions are given, they are evaluated in order.
+If files are given as well (see the \f[B]-f\f[R] and \f[B]--file\f[R]
+options), 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.
+.RS
+.PP
+If this option is given on the command-line (i.e., not in
+\f[B]BC_ENV_ARGS\f[R], see the \f[B]ENVIRONMENT VARIABLES\f[R] section),
+then after processing all expressions and files, bc(1) will exit, unless
+\f[B]-\f[R] (\f[B]stdin\f[R]) was given as an argument at least once to
+\f[B]-f\f[R] or \f[B]--file\f[R], whether on the command-line or in
+\f[B]BC_ENV_ARGS\f[R].
+However, if any other \f[B]-e\f[R], \f[B]--expression\f[R],
+\f[B]-f\f[R], or \f[B]--file\f[R] arguments are given after
+\f[B]-f-\f[R] or equivalent is given, bc(1) will give a fatal error and
+exit.
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
+\f[B]-f\f[R] \f[I]file\f[R], \f[B]--file\f[R]=\f[I]file\f[R]
+Reads in \f[I]file\f[R] and evaluates it, line by line, as though it
+were read through \f[B]stdin\f[R].
+If expressions are also given (see the \f[B]-e\f[R] and
+\f[B]--expression\f[R] options), the expressions are evaluated in the
+order given.
+.RS
+.PP
+If this option is given on the command-line (i.e., not in
+\f[B]BC_ENV_ARGS\f[R], see the \f[B]ENVIRONMENT VARIABLES\f[R] section),
+then after processing all expressions and files, bc(1) will exit, unless
+\f[B]-\f[R] (\f[B]stdin\f[R]) was given as an argument at least once to
+\f[B]-f\f[R] or \f[B]--file\f[R].
+However, if any other \f[B]-e\f[R], \f[B]--expression\f[R],
+\f[B]-f\f[R], or \f[B]--file\f[R] arguments are given after
+\f[B]-f-\f[R] or equivalent is given, bc(1) will give a fatal error and
+exit.
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
\f[B]-g\f[R], \f[B]--global-stacks\f[R]
Turns the globals \f[B]ibase\f[R], \f[B]obase\f[R], \f[B]scale\f[R], and
\f[B]seed\f[R] into stacks.
@@ -172,7 +269,18 @@ This is a \f[B]non-portable extension\f[R].
.RE
.TP
\f[B]-h\f[R], \f[B]--help\f[R]
-Prints a usage message and quits.
+Prints a usage message and exits.
+.TP
+\f[B]-I\f[R] \f[I]ibase\f[R], \f[B]--ibase\f[R]=\f[I]ibase\f[R]
+Sets the builtin variable \f[B]ibase\f[R] to the value \f[I]ibase\f[R]
+assuming that \f[I]ibase\f[R] is in base 10.
+It is a fatal error if \f[I]ibase\f[R] is not a valid number.
+.RS
+.PP
+If multiple instances of this option are given, the last is used.
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
.TP
\f[B]-i\f[R], \f[B]--interactive\f[R]
Forces interactive mode.
@@ -202,11 +310,23 @@ command line.
To learn what is in the libraries, see the \f[B]LIBRARY\f[R] section.
.RE
.TP
+\f[B]-O\f[R] \f[I]obase\f[R], \f[B]--obase\f[R]=\f[I]obase\f[R]
+Sets the builtin variable \f[B]obase\f[R] to the value \f[I]obase\f[R]
+assuming that \f[I]obase\f[R] is in base 10.
+It is a fatal error if \f[I]obase\f[R] is not a valid number.
+.RS
+.PP
+If multiple instances of this option are given, the last is used.
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
\f[B]-P\f[R], \f[B]--no-prompt\f[R]
Disables the prompt in TTY mode.
(The prompt is only enabled in TTY mode.
-See the \f[B]TTY MODE\f[R] section.) This is mostly for those users that
-do not want a prompt or are not used to having them in bc(1).
+See the \f[B]TTY MODE\f[R] 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
\f[B]BC_ENV_ARGS\f[R] (see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
.RS
@@ -217,11 +337,28 @@ environment variables (see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
This is a \f[B]non-portable extension\f[R].
.RE
.TP
+\f[B]-q\f[R], \f[B]--quiet\f[R]
+This option is for compatibility with the GNU bc(1)
+(https://www.gnu.org/software/bc/); 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
+\f[B]-v\f[R], \f[B]-V\f[R], or \f[B]--version\f[R] options are given
+unless the \f[B]BC_BANNER\f[R] environment variable is set and contains
+a non-zero integer or if this bc(1) was built with the header displayed
+by default.
+If \f[I]any\f[R] of that is the case, then this option \f[I]does\f[R]
+prevent bc(1) from printing the header.
+.RS
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
\f[B]-R\f[R], \f[B]--no-read-prompt\f[R]
Disables the read prompt in TTY mode.
(The read prompt is only enabled in TTY mode.
-See the \f[B]TTY MODE\f[R] section.) This is mostly for those users that
-do not want a read prompt or are not used to having them in bc(1).
+See the \f[B]TTY MODE\f[R] 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
\f[B]BC_ENV_ARGS\f[R] (see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
This option is also useful in hash bang lines of bc(1) scripts that
@@ -294,38 +431,32 @@ Keywords are \f[I]not\f[R] redefined when parsing the builtin math
library (see the \f[B]LIBRARY\f[R] section).
.PP
It is a fatal error to redefine keywords mandated by the POSIX standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html).
+(see the \f[B]STANDARDS\f[R] section).
It is a fatal error to attempt to redefine words that this bc(1) does
not reserve as keywords.
.RE
.TP
-\f[B]-q\f[R], \f[B]--quiet\f[R]
-This option is for compatibility with the GNU bc(1)
-(https://www.gnu.org/software/bc/); 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
-\f[B]-v\f[R], \f[B]-V\f[R], or \f[B]--version\f[R] options are given
-unless the \f[B]BC_BANNER\f[R] environment variable is set and contains
-a non-zero integer or if this bc(1) was built with the header displayed
-by default.
-If \f[I]any\f[R] of that is the case, then this option \f[I]does\f[R]
-prevent bc(1) from printing the header.
+\f[B]-S\f[R] \f[I]scale\f[R], \f[B]--scale\f[R]=\f[I]scale\f[R]
+Sets the builtin variable \f[B]scale\f[R] to the value \f[I]scale\f[R]
+assuming that \f[I]scale\f[R] is in base 10.
+It is a fatal error if \f[I]scale\f[R] is not a valid number.
.RS
.PP
+If multiple instances of this option are given, the last is used.
+.PP
This is a \f[B]non-portable extension\f[R].
.RE
.TP
\f[B]-s\f[R], \f[B]--standard\f[R]
-Process exactly the language defined by the standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html) and
-error if any extensions are used.
+Process exactly the language defined by the standard (see the
+\f[B]STANDARDS\f[R] section) and error if any extensions are used.
.RS
.PP
This is a \f[B]non-portable extension\f[R].
.RE
.TP
\f[B]-v\f[R], \f[B]-V\f[R], \f[B]--version\f[R]
-Print the version information (copyright header) and exit.
+Print the version information (copyright header) and exits.
.RS
.PP
This is a \f[B]non-portable extension\f[R].
@@ -351,93 +482,6 @@ extended math library (see the \f[B]LIBRARY\f[R] section).
.PP
This is a \f[B]non-portable extension\f[R].
.RE
-.TP
-\f[B]-e\f[R] \f[I]expr\f[R], \f[B]--expression\f[R]=\f[I]expr\f[R]
-Evaluates \f[I]expr\f[R].
-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.
-.RS
-.PP
-If this option is given on the command-line (i.e., not in
-\f[B]BC_ENV_ARGS\f[R], see the \f[B]ENVIRONMENT VARIABLES\f[R] section),
-then after processing all expressions and files, bc(1) will exit, unless
-\f[B]-\f[R] (\f[B]stdin\f[R]) was given as an argument at least once to
-\f[B]-f\f[R] or \f[B]--file\f[R], whether on the command-line or in
-\f[B]BC_ENV_ARGS\f[R].
-However, if any other \f[B]-e\f[R], \f[B]--expression\f[R],
-\f[B]-f\f[R], or \f[B]--file\f[R] arguments are given after
-\f[B]-f-\f[R] or equivalent is given, bc(1) will give a fatal error and
-exit.
-.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
-.TP
-\f[B]-f\f[R] \f[I]file\f[R], \f[B]--file\f[R]=\f[I]file\f[R]
-Reads in \f[I]file\f[R] and evaluates it, line by line, as though it
-were read through \f[B]stdin\f[R].
-If expressions are also given (see above), the expressions are evaluated
-in the order given.
-.RS
-.PP
-If this option is given on the command-line (i.e., not in
-\f[B]BC_ENV_ARGS\f[R], see the \f[B]ENVIRONMENT VARIABLES\f[R] section),
-then after processing all expressions and files, bc(1) will exit, unless
-\f[B]-\f[R] (\f[B]stdin\f[R]) was given as an argument at least once to
-\f[B]-f\f[R] or \f[B]--file\f[R].
-However, if any other \f[B]-e\f[R], \f[B]--expression\f[R],
-\f[B]-f\f[R], or \f[B]--file\f[R] arguments are given after
-\f[B]-f-\f[R] or equivalent is given, bc(1) will give a fatal error and
-exit.
-.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
-.TP
-\f[B]-I\f[R] \f[I]ibase\f[R], \f[B]--ibase\f[R]=\f[I]ibase\f[R]
-Sets the builtin variable \f[B]ibase\f[R] to the value \f[I]ibase\f[R]
-assuming that \f[I]ibase\f[R] is in base 10.
-It is a fatal error if \f[I]ibase\f[R] is not a valid number.
-.RS
-.PP
-If multiple instances of this option are given, the last is used.
-.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
-.TP
-\f[B]-O\f[R] \f[I]obase\f[R], \f[B]--obase\f[R]=\f[I]obase\f[R]
-Sets the builtin variable \f[B]obase\f[R] to the value \f[I]obase\f[R]
-assuming that \f[I]obase\f[R] is in base 10.
-It is a fatal error if \f[I]obase\f[R] is not a valid number.
-.RS
-.PP
-If multiple instances of this option are given, the last is used.
-.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
-.TP
-\f[B]-S\f[R] \f[I]scale\f[R], \f[B]--scale\f[R]=\f[I]scale\f[R]
-Sets the builtin variable \f[B]scale\f[R] to the value \f[I]scale\f[R]
-assuming that \f[I]scale\f[R] is in base 10.
-It is a fatal error if \f[I]scale\f[R] is not a valid number.
-.RS
-.PP
-If multiple instances of this option are given, the last is used.
-.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
-.TP
-\f[B]-E\f[R] \f[I]seed\f[R], \f[B]--seed\f[R]=\f[I]seed\f[R]
-Sets the builtin variable \f[B]seed\f[R] to the value \f[I]seed\f[R]
-assuming that \f[I]seed\f[R] is in base 10.
-It is a fatal error if \f[I]seed\f[R] is not a valid number.
-.RS
-.PP
-If multiple instances of this option are given, the last is used.
-.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
.PP
All long options are \f[B]non-portable extensions\f[R].
.SH STDIN
@@ -491,10 +535,9 @@ redirect \f[B]stderr\f[R] to \f[B]/dev/null\f[R].
.SH SYNTAX
.PP
The syntax for bc(1) programs is mostly C-like, with some differences.
-This bc(1) follows the POSIX standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html),
-which is a much more thorough resource for the language this bc(1)
-accepts.
+This bc(1) follows the POSIX standard (see the \f[B]STANDARDS\f[R]
+section), 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.
.PP
@@ -776,17 +819,49 @@ In any other case, use a non-seeded pseudo-random number generator.
Numbers are strings made up of digits, uppercase letters, and at most
\f[B]1\f[R] period for a radix.
Numbers can have up to \f[B]BC_NUM_MAX\f[R] digits.
-Uppercase letters are equal to \f[B]9\f[R] + their position in the
-alphabet (i.e., \f[B]A\f[R] equals \f[B]10\f[R], or \f[B]9+1\f[R]).
-If a digit or letter makes no sense with the current value of
-\f[B]ibase\f[R], they are set to the value of the highest valid digit in
-\f[B]ibase\f[R].
+Uppercase letters are equal to \f[B]9\f[R] plus their position in the
+alphabet, starting from \f[B]1\f[R] (i.e., \f[B]A\f[R] equals
+\f[B]10\f[R], or \f[B]9+1\f[R]).
.PP
-Single-character numbers (i.e., \f[B]A\f[R] alone) take the value that
-they would have if they were valid digits, regardless of the value of
-\f[B]ibase\f[R].
+If a digit or letter makes no sense with the current value of
+\f[B]ibase\f[R] (i.e., they are greater than or equal to the current
+value of \f[B]ibase\f[R]), then the behavior depends on the existence of
+the \f[B]-c\f[R]/\f[B]--digit-clamp\f[R] or
+\f[B]-C\f[R]/\f[B]--no-digit-clamp\f[R] options (see the
+\f[B]OPTIONS\f[R] section), the existence and setting of the
+\f[B]BC_DIGIT_CLAMP\f[R] environment variable (see the \f[B]ENVIRONMENT
+VARIABLES\f[R] section), or the default, which can be queried with the
+\f[B]-h\f[R]/\f[B]--help\f[R] option.
+.PP
+If clamping is off, then digits or letters that are greater than or
+equal to the current value of \f[B]ibase\f[R] are not changed.
+Instead, their given value is multiplied by the appropriate power of
+\f[B]ibase\f[R] and added into the number.
+This means that, with an \f[B]ibase\f[R] of \f[B]3\f[R], the number
+\f[B]AB\f[R] is equal to \f[B]3\[ha]1*A+3\[ha]0*B\f[R], which is
+\f[B]3\f[R] times \f[B]10\f[R] plus \f[B]11\f[R], or \f[B]41\f[R].
+.PP
+If clamping is on, then digits or letters that are greater than or equal
+to the current value of \f[B]ibase\f[R] are set to the value of the
+highest valid digit in \f[B]ibase\f[R] before being multiplied by the
+appropriate power of \f[B]ibase\f[R] and added into the number.
+This means that, with an \f[B]ibase\f[R] of \f[B]3\f[R], the number
+\f[B]AB\f[R] is equal to \f[B]3\[ha]1*2+3\[ha]0*2\f[R], which is
+\f[B]3\f[R] times \f[B]2\f[R] plus \f[B]2\f[R], or \f[B]8\f[R].
+.PP
+There is one exception to clamping: single-character numbers (i.e.,
+\f[B]A\f[R] alone).
+Such numbers are never clamped and always take the value they would have
+in the highest possible \f[B]ibase\f[R].
This means that \f[B]A\f[R] alone always equals decimal \f[B]10\f[R] and
\f[B]Z\f[R] alone always equals decimal \f[B]35\f[R].
+This behavior is mandated by the standard (see the STANDARDS section)
+and is meant to provide an easy way to set the current \f[B]ibase\f[R]
+(with the \f[B]i\f[R] command) regardless of the current value of
+\f[B]ibase\f[R].
+.PP
+If clamping is on, and the clamped value of a character is needed, use a
+leading zero, i.e., for \f[B]A\f[R], use \f[B]0A\f[R].
.PP
In addition, bc(1) accepts numbers in scientific notation.
These have the form \f[B]<number>e<integer>\f[R].
@@ -1076,8 +1151,7 @@ Note that unlike in C, these operators have a lower precedence than the
\f[B]assignment\f[R] operators, which means that \f[B]a=b>c\f[R] is
interpreted as \f[B](a=b)>c\f[R].
.PP
-Also, unlike the standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html)
+Also, unlike the standard (see the \f[B]STANDARDS\f[R] section)
requires, these operators can appear anywhere any other expressions can
be used.
This allowance is a \f[B]non-portable extension\f[R].
@@ -1109,8 +1183,8 @@ The following items are statements:
.IP " 1." 4
\f[B]E\f[R]
.IP " 2." 4
-\f[B]{\f[R] \f[B]S\f[R] \f[B];\f[R] \&... \f[B];\f[R] \f[B]S\f[R]
-\f[B]}\f[R]
+\f[B]{\f[R] \f[B]S\f[R] \f[B];\f[R] \&...
+\f[B];\f[R] \f[B]S\f[R] \f[B]}\f[R]
.IP " 3." 4
\f[B]if\f[R] \f[B](\f[R] \f[B]E\f[R] \f[B])\f[R] \f[B]S\f[R]
.IP " 4." 4
@@ -1136,9 +1210,11 @@ An empty statement
.IP "13." 4
A string of characters, enclosed in double quotes
.IP "14." 4
-\f[B]print\f[R] \f[B]E\f[R] \f[B],\f[R] \&... \f[B],\f[R] \f[B]E\f[R]
+\f[B]print\f[R] \f[B]E\f[R] \f[B],\f[R] \&...
+\f[B],\f[R] \f[B]E\f[R]
.IP "15." 4
-\f[B]stream\f[R] \f[B]E\f[R] \f[B],\f[R] \&... \f[B],\f[R] \f[B]E\f[R]
+\f[B]stream\f[R] \f[B]E\f[R] \f[B],\f[R] \&...
+\f[B],\f[R] \f[B]E\f[R]
.IP "16." 4
\f[B]I()\f[R], \f[B]I(E)\f[R], \f[B]I(E, E)\f[R], and so on, where
\f[B]I\f[R] is an identifier for a \f[B]void\f[R] function (see the
@@ -1384,9 +1460,8 @@ when the \f[B]-s\f[R] option, the \f[B]-w\f[R] option, or equivalents
are given.
.SS Standard Library
.PP
-The standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html)
-defines the following functions for the math library:
+The standard (see the \f[B]STANDARDS\f[R] section) defines the following
+functions for the math library:
.TP
\f[B]s(x)\f[R]
Returns the sine of \f[B]x\f[R], which is assumed to be in radians.
@@ -1441,8 +1516,7 @@ Functions\f[R] subsection below).
The extended library is \f[I]not\f[R] loaded when the
\f[B]-s\f[R]/\f[B]--standard\f[R] or \f[B]-w\f[R]/\f[B]--warn\f[R]
options are given since they are not part of the library defined by the
-standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html).
+standard (see the \f[B]STANDARDS\f[R] section).
.PP
The extended library is a \f[B]non-portable extension\f[R].
.TP
@@ -2501,7 +2575,8 @@ at which they become a problem.
In fact, memory should be exhausted before these limits should be hit.
.SH ENVIRONMENT VARIABLES
.PP
-bc(1) recognizes the following environment variables:
+As \f[B]non-portable extensions\f[R], bc(1) recognizes the following
+environment variables:
.TP
\f[B]POSIXLY_CORRECT\f[R]
If this variable exists (no matter the contents), bc(1) behaves as if
@@ -2621,6 +2696,22 @@ expressions and expression files, and a zero value makes bc(1) not exit.
This environment variable overrides the default, which can be queried
with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
.RE
+.TP
+\f[B]BC_DIGIT_CLAMP\f[R]
+When parsing numbers and if this environment variable exists and
+contains an integer, a non-zero value makes bc(1) clamp digits that are
+greater than or equal to the current \f[B]ibase\f[R] so that all such
+digits are considered equal to the \f[B]ibase\f[R] minus 1, and a zero
+value disables such clamping so that those digits are always equal to
+their value, which is multiplied by the power of the \f[B]ibase\f[R].
+.RS
+.PP
+This never applies to single-digit numbers, as per the standard (see the
+\f[B]STANDARDS\f[R] section).
+.PP
+This environment variable overrides the default, which can be queried
+with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
+.RE
.SH EXIT STATUS
.PP
bc(1) returns the following exit statuses:
@@ -2702,9 +2793,8 @@ checking, and its normal behavior can be forced by using the
\f[B]-i\f[R] flag or \f[B]--interactive\f[R] option.
.SH INTERACTIVE MODE
.PP
-Per the standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html),
-bc(1) has an interactive mode and a non-interactive mode.
+Per the standard (see the \f[B]STANDARDS\f[R] section), bc(1) has an
+interactive mode and a non-interactive mode.
Interactive mode is turned on automatically when both \f[B]stdin\f[R]
and \f[B]stdout\f[R] are hooked to a terminal, but the \f[B]-i\f[R] flag
and \f[B]--interactive\f[R] option can turn it on in other situations.
@@ -2736,8 +2826,7 @@ The default setting can be queried with the \f[B]-h\f[R] or
\f[B]--help\f[R] options.
.PP
TTY mode is different from interactive mode because interactive mode is
-required in the bc(1) standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html),
+required in the bc(1) standard (see the \f[B]STANDARDS\f[R] section),
and interactive mode requires only \f[B]stdin\f[R] and \f[B]stdout\f[R]
to be connected to a terminal.
.SS Prompt
diff --git a/manuals/bc/HN.1.md b/manuals/bc/HN.1.md
index 13f085a5cca7..2e89cd559804 100644
--- a/manuals/bc/HN.1.md
+++ b/manuals/bc/HN.1.md
@@ -34,15 +34,14 @@ 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*...] [**-I** *ibase*] [**-\-ibase**=*ibase*] [**-O** *obase*] [**-\-obase**=*obase*] [**-S** *scale*] [**-\-scale**=*scale*] [**-E** *seed*] [**-\-seed**=*seed*]
+**bc** [**-cCghilPqRsvVw**] [**-\-digit-clamp**] [**-\-no-digit-clamp**] [**-\-global-stacks**] [**-\-help**] [**-\-interactive**] [**-\-mathlib**] [**-\-no-prompt**] [**-\-no-read-prompt**] [**-\-quiet**] [**-\-standard**] [**-\-warn**] [**-\-version**] [**-e** *expr*] [**-\-expression**=*expr*...] [**-f** *file*...] [**-\-file**=*file*...] [*file*...] [**-I** *ibase*] [**-\-ibase**=*ibase*] [**-O** *obase*] [**-\-obase**=*obase*] [**-S** *scale*] [**-\-scale**=*scale*] [**-E** *seed*] [**-\-seed**=*seed*]
# DESCRIPTION
bc(1) is an interactive processor for a language first standardized in 1991 by
-POSIX. (The current standard is at
-https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html .) The
-language provides unlimited precision decimal arithmetic and is somewhat C-like,
-but there are differences. Such differences will be noted in this document.
+POSIX. (See the **STANDARDS** section.) 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**.
@@ -64,6 +63,86 @@ that is a bug and should be reported. See the **BUGS** section.
The following are the options that bc(1) accepts.
+**-C**, **-\-no-digit-clamp**
+
+: Disables clamping of digits greater than or equal to the current **ibase**
+ when parsing numbers.
+
+ This means that the value added to a number from a digit is always that
+ digit's value multiplied by the value of ibase raised to the power of the
+ digit's position, which starts from 0 at the least significant digit.
+
+ If this and/or the **-c** or **-\-digit-clamp** options are given multiple
+ times, the last one given is used.
+
+ This option overrides the **BC_DIGIT_CLAMP** environment variable (see the
+ **ENVIRONMENT VARIABLES** section) and the default, which can be queried
+ with the **-h** or **-\-help** options.
+
+ This is a **non-portable extension**.
+
+**-c**, **-\-digit-clamp**
+
+: Enables clamping of digits greater than or equal to the current **ibase**
+ when parsing numbers.
+
+ This means that digits that the value added to a number from a digit that is
+ greater than or equal to the ibase is the value of ibase minus 1 all
+ multiplied by the value of ibase raised to the power of the digit's
+ position, which starts from 0 at the least significant digit.
+
+ If this and/or the **-C** or **-\-no-digit-clamp** options are given
+ multiple times, the last one given is used.
+
+ This option overrides the **BC_DIGIT_CLAMP** environment variable (see the
+ **ENVIRONMENT VARIABLES** section) and the default, which can be queried
+ with the **-h** or **-\-help** options.
+
+ This is a **non-portable extension**.
+
+**-E** *seed*, **-\-seed**=*seed*
+
+: Sets the builtin variable **seed** to the value *seed* assuming that *seed*
+ is in base 10. It is a fatal error if *seed* is not a valid number.
+
+ If multiple instances of this option are given, the last is used.
+
+ 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 the **-f** and **-\-file** options),
+ 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 the **-e** and
+ **-\-expression** options), 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**.
+
**-g**, **-\-global-stacks**
: Turns the globals **ibase**, **obase**, **scale**, and **seed** into stacks.
@@ -134,7 +213,16 @@ The following are the options that bc(1) accepts.
**-h**, **-\-help**
-: Prints a usage message and quits.
+: Prints a usage message and exits.
+
+**-I** *ibase*, **-\-ibase**=*ibase*
+
+: Sets the builtin variable **ibase** to the value *ibase* assuming that
+ *ibase* is in base 10. It is a fatal error if *ibase* is not a valid number.
+
+ If multiple instances of this option are given, the last is used.
+
+ This is a **non-portable extension**.
**-i**, **-\-interactive**
@@ -158,6 +246,15 @@ The following are the options that bc(1) accepts.
To learn what is in the libraries, see the **LIBRARY** section.
+**-O** *obase*, **-\-obase**=*obase*
+
+: Sets the builtin variable **obase** to the value *obase* assuming that
+ *obase* is in base 10. It is a fatal error if *obase* is not a valid number.
+
+ If multiple instances of this option are given, the last is used.
+
+ This is a **non-portable extension**.
+
**-P**, **-\-no-prompt**
: Disables the prompt in TTY mode. (The prompt is only enabled in TTY mode.
@@ -171,6 +268,19 @@ The following are the options that bc(1) accepts.
This is a **non-portable extension**.
+**-q**, **-\-quiet**
+
+: This option is for compatibility with the GNU bc(1)
+ (https://www.gnu.org/software/bc/); 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
+ unless the **BC_BANNER** environment variable is set and contains a non-zero
+ integer or if this bc(1) was built with the header displayed by default. If
+ *any* of that is the case, then this option *does* prevent bc(1) from
+ printing the header.
+
+ This is a **non-portable extension**.
+
**-R**, **-\-no-read-prompt**
: Disables the read prompt in TTY mode. (The read prompt is only enabled in
@@ -224,35 +334,29 @@ The following are the options that bc(1) accepts.
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
- (https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html). It is
- a fatal error to attempt to redefine words that this bc(1) does not reserve
- as keywords.
+ It is a fatal error to redefine keywords mandated by the POSIX standard (see
+ the **STANDARDS** section). It is a fatal error to attempt to redefine words
+ that this bc(1) does not reserve as keywords.
-**-q**, **-\-quiet**
+**-S** *scale*, **-\-scale**=*scale*
-: This option is for compatibility with the GNU bc(1)
- (https://www.gnu.org/software/bc/); 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
- unless the **BC_BANNER** environment variable is set and contains a non-zero
- integer or if this bc(1) was built with the header displayed by default. If
- *any* of that is the case, then this option *does* prevent bc(1) from
- printing the header.
+: Sets the builtin variable **scale** to the value *scale* assuming that
+ *scale* is in base 10. It is a fatal error if *scale* is not a valid number.
+
+ If multiple instances of this option are given, the last is used.
This is a **non-portable extension**.
**-s**, **-\-standard**
-: Process exactly the language defined by the standard
- (https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html) and
- error if any extensions are used.
+: Process exactly the language defined by the standard (see the **STANDARDS**
+ section) and error if any extensions are used.
This is a **non-portable extension**.
**-v**, **-V**, **-\-version**
-: Print the version information (copyright header) and exit.
+: Print the version information (copyright header) and exits.
This is a **non-portable extension**.
@@ -274,74 +378,6 @@ The following are the options that bc(1) accepts.
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**.
-
-**-I** *ibase*, **-\-ibase**=*ibase*
-
-: Sets the builtin variable **ibase** to the value *ibase* assuming that
- *ibase* is in base 10. It is a fatal error if *ibase* is not a valid number.
-
- If multiple instances of this option are given, the last is used.
-
- This is a **non-portable extension**.
-
-**-O** *obase*, **-\-obase**=*obase*
-
-: Sets the builtin variable **obase** to the value *obase* assuming that
- *obase* is in base 10. It is a fatal error if *obase* is not a valid number.
-
- If multiple instances of this option are given, the last is used.
-
- This is a **non-portable extension**.
-
-**-S** *scale*, **-\-scale**=*scale*
-
-: Sets the builtin variable **scale** to the value *scale* assuming that
- *scale* is in base 10. It is a fatal error if *scale* is not a valid number.
-
- If multiple instances of this option are given, the last is used.
-
- This is a **non-portable extension**.
-
-**-E** *seed*, **-\-seed**=*seed*
-
-: Sets the builtin variable **seed** to the value *seed* assuming that *seed*
- is in base 10. It is a fatal error if *seed* is not a valid number.
-
- If multiple instances of this option are given, the last is used.
-
- This is a **non-portable extension**.
-
All long options are **non-portable extensions**.
# STDIN
@@ -393,8 +429,7 @@ it is recommended that those scripts be changed to redirect **stderr** to
# SYNTAX
The syntax for bc(1) programs is mostly C-like, with some differences. This
-bc(1) follows the POSIX standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html), which is a
+bc(1) follows the POSIX standard (see the **STANDARDS** section), 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.
@@ -592,14 +627,40 @@ use a non-seeded pseudo-random number generator.
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**.
+letters are equal to **9** plus their position in the alphabet, starting from
+**1** (i.e., **A** equals **10**, or **9+1**).
+
+If a digit or letter makes no sense with the current value of **ibase** (i.e.,
+they are greater than or equal to the current value of **ibase**), then the
+behavior depends on the existence of the **-c**/**-\-digit-clamp** or
+**-C**/**-\-no-digit-clamp** options (see the **OPTIONS** section), the
+existence and setting of the **BC_DIGIT_CLAMP** environment variable (see the
+**ENVIRONMENT VARIABLES** section), or the default, which can be queried with
+the **-h**/**-\-help** option.
+
+If clamping is off, then digits or letters that are greater than or equal to the
+current value of **ibase** are not changed. Instead, their given value is
+multiplied by the appropriate power of **ibase** and added into the number. This
+means that, with an **ibase** of **3**, the number **AB** is equal to
+**3\^1\*A+3\^0\*B**, which is **3** times **10** plus **11**, or **41**.
+
+If clamping is on, then digits or letters that are greater than or equal to the
+current value of **ibase** are set to the value of the highest valid digit in
+**ibase** before being multiplied by the appropriate power of **ibase** and
+added into the number. This means that, with an **ibase** of **3**, the number
+**AB** is equal to **3\^1\*2+3\^0\*2**, which is **3** times **2** plus **2**,
+or **8**.
+
+There is one exception to clamping: single-character numbers (i.e., **A**
+alone). Such numbers are never clamped and always take the value they would have
+in the highest possible **ibase**. This means that **A** alone always equals
+decimal **10** and **Z** alone always equals decimal **35**. This behavior is
+mandated by the standard (see the STANDARDS section) and is meant to provide an
+easy way to set the current **ibase** (with the **i** command) regardless of the
+current value of **ibase**.
+
+If clamping is on, and the clamped value of a character is needed, use a leading
+zero, i.e., for **A**, use **0A**.
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
@@ -849,10 +910,9 @@ The operators will be described in more detail below.
**assignment** operators, which means that **a=b\>c** is interpreted as
**(a=b)\>c**.
- Also, unlike the standard
- (https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html)
- requires, these operators can appear anywhere any other expressions can be
- used. This allowance is a **non-portable extension**.
+ Also, unlike the standard (see the **STANDARDS** section) requires, these
+ operators can appear anywhere any other expressions can be used. This
+ allowance is a **non-portable extension**.
**&&**
@@ -1099,9 +1159,8 @@ equivalents are given.
## Standard Library
-The standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html) defines the
-following functions for the math library:
+The standard (see the **STANDARDS** section) defines the following functions for
+the math library:
**s(x)**
@@ -1149,8 +1208,7 @@ following functions for the math 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
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html).
+defined by the standard (see the **STANDARDS** section).
The extended library is a **non-portable extension**.
@@ -2085,7 +2143,8 @@ be hit.
# ENVIRONMENT VARIABLES
-bc(1) recognizes the following environment variables:
+As **non-portable extensions**, bc(1) recognizes the following environment
+variables:
**POSIXLY_CORRECT**
@@ -2191,6 +2250,21 @@ bc(1) recognizes the following environment variables:
This environment variable overrides the default, which can be queried with
the **-h** or **-\-help** options.
+**BC_DIGIT_CLAMP**
+
+: When parsing numbers and if this environment variable exists and contains an
+ integer, a non-zero value makes bc(1) clamp digits that are greater than or
+ equal to the current **ibase** so that all such digits are considered equal
+ to the **ibase** minus 1, and a zero value disables such clamping so that
+ those digits are always equal to their value, which is multiplied by the
+ power of the **ibase**.
+
+ This never applies to single-digit numbers, as per the standard (see the
+ **STANDARDS** section).
+
+ 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:
@@ -2266,12 +2340,10 @@ checking, and its normal behavior can be forced by using the **-i** flag or
# INTERACTIVE MODE
-Per the standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html), 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.
+Per the standard (see the **STANDARDS** section), 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
@@ -2297,10 +2369,8 @@ 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) standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html), and
-interactive mode requires only **stdin** and **stdout** to be connected to a
-terminal.
+in the bc(1) standard (see the **STANDARDS** section), and interactive mode
+requires only **stdin** and **stdout** to be connected to a terminal.
## Prompt
diff --git a/manuals/bc/N.1 b/manuals/bc/N.1
index def2aee98bbc..88603995ca73 100644
--- a/manuals/bc/N.1
+++ b/manuals/bc/N.1
@@ -25,7 +25,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.TH "BC" "1" "June 2022" "Gavin D. Howard" "General Commands Manual"
+.TH "BC" "1" "August 2022" "Gavin D. Howard" "General Commands Manual"
.nh
.ad l
.SH NAME
@@ -33,24 +33,25 @@
bc - arbitrary-precision decimal arithmetic language and calculator
.SH SYNOPSIS
.PP
-\f[B]bc\f[R] [\f[B]-ghilPqRsvVw\f[R]] [\f[B]--global-stacks\f[R]]
+\f[B]bc\f[R] [\f[B]-cCghilPqRsvVw\f[R]] [\f[B]--digit-clamp\f[R]]
+[\f[B]--no-digit-clamp\f[R]] [\f[B]--global-stacks\f[R]]
[\f[B]--help\f[R]] [\f[B]--interactive\f[R]] [\f[B]--mathlib\f[R]]
[\f[B]--no-prompt\f[R]] [\f[B]--no-read-prompt\f[R]] [\f[B]--quiet\f[R]]
[\f[B]--standard\f[R]] [\f[B]--warn\f[R]] [\f[B]--version\f[R]]
[\f[B]-e\f[R] \f[I]expr\f[R]]
-[\f[B]--expression\f[R]=\f[I]expr\f[R]\&...] [\f[B]-f\f[R]
-\f[I]file\f[R]\&...] [\f[B]--file\f[R]=\f[I]file\f[R]\&...]
-[\f[I]file\f[R]\&...] [\f[B]-I\f[R] \f[I]ibase\f[R]]
-[\f[B]--ibase\f[R]=\f[I]ibase\f[R]] [\f[B]-O\f[R] \f[I]obase\f[R]]
-[\f[B]--obase\f[R]=\f[I]obase\f[R]] [\f[B]-S\f[R] \f[I]scale\f[R]]
-[\f[B]--scale\f[R]=\f[I]scale\f[R]] [\f[B]-E\f[R] \f[I]seed\f[R]]
-[\f[B]--seed\f[R]=\f[I]seed\f[R]]
+[\f[B]--expression\f[R]=\f[I]expr\f[R]\&...]
+[\f[B]-f\f[R] \f[I]file\f[R]\&...]
+[\f[B]--file\f[R]=\f[I]file\f[R]\&...]
+[\f[I]file\f[R]\&...]
+[\f[B]-I\f[R] \f[I]ibase\f[R]] [\f[B]--ibase\f[R]=\f[I]ibase\f[R]]
+[\f[B]-O\f[R] \f[I]obase\f[R]] [\f[B]--obase\f[R]=\f[I]obase\f[R]]
+[\f[B]-S\f[R] \f[I]scale\f[R]] [\f[B]--scale\f[R]=\f[I]scale\f[R]]
+[\f[B]-E\f[R] \f[I]seed\f[R]] [\f[B]--seed\f[R]=\f[I]seed\f[R]]
.SH DESCRIPTION
.PP
bc(1) is an interactive processor for a language first standardized in
1991 by POSIX.
-(The current standard is at
-https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html .)
+(See the \f[B]STANDARDS\f[R] section.)
The language provides unlimited precision decimal arithmetic and is
somewhat C-like, but there are differences.
Such differences will be noted in this document.
@@ -79,6 +80,102 @@ See the \f[B]BUGS\f[R] section.
.PP
The following are the options that bc(1) accepts.
.TP
+\f[B]-C\f[R], \f[B]--no-digit-clamp\f[R]
+Disables clamping of digits greater than or equal to the current
+\f[B]ibase\f[R] when parsing numbers.
+.RS
+.PP
+This means that the value added to a number from a digit is always that
+digit\[cq]s value multiplied by the value of ibase raised to the power
+of the digit\[cq]s position, which starts from 0 at the least
+significant digit.
+.PP
+If this and/or the \f[B]-c\f[R] or \f[B]--digit-clamp\f[R] options are
+given multiple times, the last one given is used.
+.PP
+This option overrides the \f[B]BC_DIGIT_CLAMP\f[R] environment variable
+(see the \f[B]ENVIRONMENT VARIABLES\f[R] section) and the default, which
+can be queried with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
+\f[B]-c\f[R], \f[B]--digit-clamp\f[R]
+Enables clamping of digits greater than or equal to the current
+\f[B]ibase\f[R] when parsing numbers.
+.RS
+.PP
+This means that digits that the value added to a number from a digit
+that is greater than or equal to the ibase is the value of ibase minus 1
+all multiplied by the value of ibase raised to the power of the
+digit\[cq]s position, which starts from 0 at the least significant
+digit.
+.PP
+If this and/or the \f[B]-C\f[R] or \f[B]--no-digit-clamp\f[R] options
+are given multiple times, the last one given is used.
+.PP
+This option overrides the \f[B]BC_DIGIT_CLAMP\f[R] environment variable
+(see the \f[B]ENVIRONMENT VARIABLES\f[R] section) and the default, which
+can be queried with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
+\f[B]-E\f[R] \f[I]seed\f[R], \f[B]--seed\f[R]=\f[I]seed\f[R]
+Sets the builtin variable \f[B]seed\f[R] to the value \f[I]seed\f[R]
+assuming that \f[I]seed\f[R] is in base 10.
+It is a fatal error if \f[I]seed\f[R] is not a valid number.
+.RS
+.PP
+If multiple instances of this option are given, the last is used.
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
+\f[B]-e\f[R] \f[I]expr\f[R], \f[B]--expression\f[R]=\f[I]expr\f[R]
+Evaluates \f[I]expr\f[R].
+If multiple expressions are given, they are evaluated in order.
+If files are given as well (see the \f[B]-f\f[R] and \f[B]--file\f[R]
+options), 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.
+.RS
+.PP
+If this option is given on the command-line (i.e., not in
+\f[B]BC_ENV_ARGS\f[R], see the \f[B]ENVIRONMENT VARIABLES\f[R] section),
+then after processing all expressions and files, bc(1) will exit, unless
+\f[B]-\f[R] (\f[B]stdin\f[R]) was given as an argument at least once to
+\f[B]-f\f[R] or \f[B]--file\f[R], whether on the command-line or in
+\f[B]BC_ENV_ARGS\f[R].
+However, if any other \f[B]-e\f[R], \f[B]--expression\f[R],
+\f[B]-f\f[R], or \f[B]--file\f[R] arguments are given after
+\f[B]-f-\f[R] or equivalent is given, bc(1) will give a fatal error and
+exit.
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
+\f[B]-f\f[R] \f[I]file\f[R], \f[B]--file\f[R]=\f[I]file\f[R]
+Reads in \f[I]file\f[R] and evaluates it, line by line, as though it
+were read through \f[B]stdin\f[R].
+If expressions are also given (see the \f[B]-e\f[R] and
+\f[B]--expression\f[R] options), the expressions are evaluated in the
+order given.
+.RS
+.PP
+If this option is given on the command-line (i.e., not in
+\f[B]BC_ENV_ARGS\f[R], see the \f[B]ENVIRONMENT VARIABLES\f[R] section),
+then after processing all expressions and files, bc(1) will exit, unless
+\f[B]-\f[R] (\f[B]stdin\f[R]) was given as an argument at least once to
+\f[B]-f\f[R] or \f[B]--file\f[R].
+However, if any other \f[B]-e\f[R], \f[B]--expression\f[R],
+\f[B]-f\f[R], or \f[B]--file\f[R] arguments are given after
+\f[B]-f-\f[R] or equivalent is given, bc(1) will give a fatal error and
+exit.
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
\f[B]-g\f[R], \f[B]--global-stacks\f[R]
Turns the globals \f[B]ibase\f[R], \f[B]obase\f[R], \f[B]scale\f[R], and
\f[B]seed\f[R] into stacks.
@@ -172,7 +269,18 @@ This is a \f[B]non-portable extension\f[R].
.RE
.TP
\f[B]-h\f[R], \f[B]--help\f[R]
-Prints a usage message and quits.
+Prints a usage message and exits.
+.TP
+\f[B]-I\f[R] \f[I]ibase\f[R], \f[B]--ibase\f[R]=\f[I]ibase\f[R]
+Sets the builtin variable \f[B]ibase\f[R] to the value \f[I]ibase\f[R]
+assuming that \f[I]ibase\f[R] is in base 10.
+It is a fatal error if \f[I]ibase\f[R] is not a valid number.
+.RS
+.PP
+If multiple instances of this option are given, the last is used.
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
.TP
\f[B]-i\f[R], \f[B]--interactive\f[R]
Forces interactive mode.
@@ -202,11 +310,23 @@ command line.
To learn what is in the libraries, see the \f[B]LIBRARY\f[R] section.
.RE
.TP
+\f[B]-O\f[R] \f[I]obase\f[R], \f[B]--obase\f[R]=\f[I]obase\f[R]
+Sets the builtin variable \f[B]obase\f[R] to the value \f[I]obase\f[R]
+assuming that \f[I]obase\f[R] is in base 10.
+It is a fatal error if \f[I]obase\f[R] is not a valid number.
+.RS
+.PP
+If multiple instances of this option are given, the last is used.
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
\f[B]-P\f[R], \f[B]--no-prompt\f[R]
Disables the prompt in TTY mode.
(The prompt is only enabled in TTY mode.
-See the \f[B]TTY MODE\f[R] section.) This is mostly for those users that
-do not want a prompt or are not used to having them in bc(1).
+See the \f[B]TTY MODE\f[R] 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
\f[B]BC_ENV_ARGS\f[R] (see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
.RS
@@ -217,11 +337,28 @@ environment variables (see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
This is a \f[B]non-portable extension\f[R].
.RE
.TP
+\f[B]-q\f[R], \f[B]--quiet\f[R]
+This option is for compatibility with the GNU bc(1)
+(https://www.gnu.org/software/bc/); 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
+\f[B]-v\f[R], \f[B]-V\f[R], or \f[B]--version\f[R] options are given
+unless the \f[B]BC_BANNER\f[R] environment variable is set and contains
+a non-zero integer or if this bc(1) was built with the header displayed
+by default.
+If \f[I]any\f[R] of that is the case, then this option \f[I]does\f[R]
+prevent bc(1) from printing the header.
+.RS
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
\f[B]-R\f[R], \f[B]--no-read-prompt\f[R]
Disables the read prompt in TTY mode.
(The read prompt is only enabled in TTY mode.
-See the \f[B]TTY MODE\f[R] section.) This is mostly for those users that
-do not want a read prompt or are not used to having them in bc(1).
+See the \f[B]TTY MODE\f[R] 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
\f[B]BC_ENV_ARGS\f[R] (see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
This option is also useful in hash bang lines of bc(1) scripts that
@@ -294,38 +431,32 @@ Keywords are \f[I]not\f[R] redefined when parsing the builtin math
library (see the \f[B]LIBRARY\f[R] section).
.PP
It is a fatal error to redefine keywords mandated by the POSIX standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html).
+(see the \f[B]STANDARDS\f[R] section).
It is a fatal error to attempt to redefine words that this bc(1) does
not reserve as keywords.
.RE
.TP
-\f[B]-q\f[R], \f[B]--quiet\f[R]
-This option is for compatibility with the GNU bc(1)
-(https://www.gnu.org/software/bc/); 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
-\f[B]-v\f[R], \f[B]-V\f[R], or \f[B]--version\f[R] options are given
-unless the \f[B]BC_BANNER\f[R] environment variable is set and contains
-a non-zero integer or if this bc(1) was built with the header displayed
-by default.
-If \f[I]any\f[R] of that is the case, then this option \f[I]does\f[R]
-prevent bc(1) from printing the header.
+\f[B]-S\f[R] \f[I]scale\f[R], \f[B]--scale\f[R]=\f[I]scale\f[R]
+Sets the builtin variable \f[B]scale\f[R] to the value \f[I]scale\f[R]
+assuming that \f[I]scale\f[R] is in base 10.
+It is a fatal error if \f[I]scale\f[R] is not a valid number.
.RS
.PP
+If multiple instances of this option are given, the last is used.
+.PP
This is a \f[B]non-portable extension\f[R].
.RE
.TP
\f[B]-s\f[R], \f[B]--standard\f[R]
-Process exactly the language defined by the standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html) and
-error if any extensions are used.
+Process exactly the language defined by the standard (see the
+\f[B]STANDARDS\f[R] section) and error if any extensions are used.
.RS
.PP
This is a \f[B]non-portable extension\f[R].
.RE
.TP
\f[B]-v\f[R], \f[B]-V\f[R], \f[B]--version\f[R]
-Print the version information (copyright header) and exit.
+Print the version information (copyright header) and exits.
.RS
.PP
This is a \f[B]non-portable extension\f[R].
@@ -351,93 +482,6 @@ extended math library (see the \f[B]LIBRARY\f[R] section).
.PP
This is a \f[B]non-portable extension\f[R].
.RE
-.TP
-\f[B]-e\f[R] \f[I]expr\f[R], \f[B]--expression\f[R]=\f[I]expr\f[R]
-Evaluates \f[I]expr\f[R].
-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.
-.RS
-.PP
-If this option is given on the command-line (i.e., not in
-\f[B]BC_ENV_ARGS\f[R], see the \f[B]ENVIRONMENT VARIABLES\f[R] section),
-then after processing all expressions and files, bc(1) will exit, unless
-\f[B]-\f[R] (\f[B]stdin\f[R]) was given as an argument at least once to
-\f[B]-f\f[R] or \f[B]--file\f[R], whether on the command-line or in
-\f[B]BC_ENV_ARGS\f[R].
-However, if any other \f[B]-e\f[R], \f[B]--expression\f[R],
-\f[B]-f\f[R], or \f[B]--file\f[R] arguments are given after
-\f[B]-f-\f[R] or equivalent is given, bc(1) will give a fatal error and
-exit.
-.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
-.TP
-\f[B]-f\f[R] \f[I]file\f[R], \f[B]--file\f[R]=\f[I]file\f[R]
-Reads in \f[I]file\f[R] and evaluates it, line by line, as though it
-were read through \f[B]stdin\f[R].
-If expressions are also given (see above), the expressions are evaluated
-in the order given.
-.RS
-.PP
-If this option is given on the command-line (i.e., not in
-\f[B]BC_ENV_ARGS\f[R], see the \f[B]ENVIRONMENT VARIABLES\f[R] section),
-then after processing all expressions and files, bc(1) will exit, unless
-\f[B]-\f[R] (\f[B]stdin\f[R]) was given as an argument at least once to
-\f[B]-f\f[R] or \f[B]--file\f[R].
-However, if any other \f[B]-e\f[R], \f[B]--expression\f[R],
-\f[B]-f\f[R], or \f[B]--file\f[R] arguments are given after
-\f[B]-f-\f[R] or equivalent is given, bc(1) will give a fatal error and
-exit.
-.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
-.TP
-\f[B]-I\f[R] \f[I]ibase\f[R], \f[B]--ibase\f[R]=\f[I]ibase\f[R]
-Sets the builtin variable \f[B]ibase\f[R] to the value \f[I]ibase\f[R]
-assuming that \f[I]ibase\f[R] is in base 10.
-It is a fatal error if \f[I]ibase\f[R] is not a valid number.
-.RS
-.PP
-If multiple instances of this option are given, the last is used.
-.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
-.TP
-\f[B]-O\f[R] \f[I]obase\f[R], \f[B]--obase\f[R]=\f[I]obase\f[R]
-Sets the builtin variable \f[B]obase\f[R] to the value \f[I]obase\f[R]
-assuming that \f[I]obase\f[R] is in base 10.
-It is a fatal error if \f[I]obase\f[R] is not a valid number.
-.RS
-.PP
-If multiple instances of this option are given, the last is used.
-.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
-.TP
-\f[B]-S\f[R] \f[I]scale\f[R], \f[B]--scale\f[R]=\f[I]scale\f[R]
-Sets the builtin variable \f[B]scale\f[R] to the value \f[I]scale\f[R]
-assuming that \f[I]scale\f[R] is in base 10.
-It is a fatal error if \f[I]scale\f[R] is not a valid number.
-.RS
-.PP
-If multiple instances of this option are given, the last is used.
-.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
-.TP
-\f[B]-E\f[R] \f[I]seed\f[R], \f[B]--seed\f[R]=\f[I]seed\f[R]
-Sets the builtin variable \f[B]seed\f[R] to the value \f[I]seed\f[R]
-assuming that \f[I]seed\f[R] is in base 10.
-It is a fatal error if \f[I]seed\f[R] is not a valid number.
-.RS
-.PP
-If multiple instances of this option are given, the last is used.
-.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
.PP
All long options are \f[B]non-portable extensions\f[R].
.SH STDIN
@@ -491,10 +535,9 @@ redirect \f[B]stderr\f[R] to \f[B]/dev/null\f[R].
.SH SYNTAX
.PP
The syntax for bc(1) programs is mostly C-like, with some differences.
-This bc(1) follows the POSIX standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html),
-which is a much more thorough resource for the language this bc(1)
-accepts.
+This bc(1) follows the POSIX standard (see the \f[B]STANDARDS\f[R]
+section), 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.
.PP
@@ -776,17 +819,49 @@ In any other case, use a non-seeded pseudo-random number generator.
Numbers are strings made up of digits, uppercase letters, and at most
\f[B]1\f[R] period for a radix.
Numbers can have up to \f[B]BC_NUM_MAX\f[R] digits.
-Uppercase letters are equal to \f[B]9\f[R] + their position in the
-alphabet (i.e., \f[B]A\f[R] equals \f[B]10\f[R], or \f[B]9+1\f[R]).
-If a digit or letter makes no sense with the current value of
-\f[B]ibase\f[R], they are set to the value of the highest valid digit in
-\f[B]ibase\f[R].
+Uppercase letters are equal to \f[B]9\f[R] plus their position in the
+alphabet, starting from \f[B]1\f[R] (i.e., \f[B]A\f[R] equals
+\f[B]10\f[R], or \f[B]9+1\f[R]).
.PP
-Single-character numbers (i.e., \f[B]A\f[R] alone) take the value that
-they would have if they were valid digits, regardless of the value of
-\f[B]ibase\f[R].
+If a digit or letter makes no sense with the current value of
+\f[B]ibase\f[R] (i.e., they are greater than or equal to the current
+value of \f[B]ibase\f[R]), then the behavior depends on the existence of
+the \f[B]-c\f[R]/\f[B]--digit-clamp\f[R] or
+\f[B]-C\f[R]/\f[B]--no-digit-clamp\f[R] options (see the
+\f[B]OPTIONS\f[R] section), the existence and setting of the
+\f[B]BC_DIGIT_CLAMP\f[R] environment variable (see the \f[B]ENVIRONMENT
+VARIABLES\f[R] section), or the default, which can be queried with the
+\f[B]-h\f[R]/\f[B]--help\f[R] option.
+.PP
+If clamping is off, then digits or letters that are greater than or
+equal to the current value of \f[B]ibase\f[R] are not changed.
+Instead, their given value is multiplied by the appropriate power of
+\f[B]ibase\f[R] and added into the number.
+This means that, with an \f[B]ibase\f[R] of \f[B]3\f[R], the number
+\f[B]AB\f[R] is equal to \f[B]3\[ha]1*A+3\[ha]0*B\f[R], which is
+\f[B]3\f[R] times \f[B]10\f[R] plus \f[B]11\f[R], or \f[B]41\f[R].
+.PP
+If clamping is on, then digits or letters that are greater than or equal
+to the current value of \f[B]ibase\f[R] are set to the value of the
+highest valid digit in \f[B]ibase\f[R] before being multiplied by the
+appropriate power of \f[B]ibase\f[R] and added into the number.
+This means that, with an \f[B]ibase\f[R] of \f[B]3\f[R], the number
+\f[B]AB\f[R] is equal to \f[B]3\[ha]1*2+3\[ha]0*2\f[R], which is
+\f[B]3\f[R] times \f[B]2\f[R] plus \f[B]2\f[R], or \f[B]8\f[R].
+.PP
+There is one exception to clamping: single-character numbers (i.e.,
+\f[B]A\f[R] alone).
+Such numbers are never clamped and always take the value they would have
+in the highest possible \f[B]ibase\f[R].
This means that \f[B]A\f[R] alone always equals decimal \f[B]10\f[R] and
\f[B]Z\f[R] alone always equals decimal \f[B]35\f[R].
+This behavior is mandated by the standard (see the STANDARDS section)
+and is meant to provide an easy way to set the current \f[B]ibase\f[R]
+(with the \f[B]i\f[R] command) regardless of the current value of
+\f[B]ibase\f[R].
+.PP
+If clamping is on, and the clamped value of a character is needed, use a
+leading zero, i.e., for \f[B]A\f[R], use \f[B]0A\f[R].
.PP
In addition, bc(1) accepts numbers in scientific notation.
These have the form \f[B]<number>e<integer>\f[R].
@@ -1076,8 +1151,7 @@ Note that unlike in C, these operators have a lower precedence than the
\f[B]assignment\f[R] operators, which means that \f[B]a=b>c\f[R] is
interpreted as \f[B](a=b)>c\f[R].
.PP
-Also, unlike the standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html)
+Also, unlike the standard (see the \f[B]STANDARDS\f[R] section)
requires, these operators can appear anywhere any other expressions can
be used.
This allowance is a \f[B]non-portable extension\f[R].
@@ -1109,8 +1183,8 @@ The following items are statements:
.IP " 1." 4
\f[B]E\f[R]
.IP " 2." 4
-\f[B]{\f[R] \f[B]S\f[R] \f[B];\f[R] \&... \f[B];\f[R] \f[B]S\f[R]
-\f[B]}\f[R]
+\f[B]{\f[R] \f[B]S\f[R] \f[B];\f[R] \&...
+\f[B];\f[R] \f[B]S\f[R] \f[B]}\f[R]
.IP " 3." 4
\f[B]if\f[R] \f[B](\f[R] \f[B]E\f[R] \f[B])\f[R] \f[B]S\f[R]
.IP " 4." 4
@@ -1136,9 +1210,11 @@ An empty statement
.IP "13." 4
A string of characters, enclosed in double quotes
.IP "14." 4
-\f[B]print\f[R] \f[B]E\f[R] \f[B],\f[R] \&... \f[B],\f[R] \f[B]E\f[R]
+\f[B]print\f[R] \f[B]E\f[R] \f[B],\f[R] \&...
+\f[B],\f[R] \f[B]E\f[R]
.IP "15." 4
-\f[B]stream\f[R] \f[B]E\f[R] \f[B],\f[R] \&... \f[B],\f[R] \f[B]E\f[R]
+\f[B]stream\f[R] \f[B]E\f[R] \f[B],\f[R] \&...
+\f[B],\f[R] \f[B]E\f[R]
.IP "16." 4
\f[B]I()\f[R], \f[B]I(E)\f[R], \f[B]I(E, E)\f[R], and so on, where
\f[B]I\f[R] is an identifier for a \f[B]void\f[R] function (see the
@@ -1384,9 +1460,8 @@ when the \f[B]-s\f[R] option, the \f[B]-w\f[R] option, or equivalents
are given.
.SS Standard Library
.PP
-The standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html)
-defines the following functions for the math library:
+The standard (see the \f[B]STANDARDS\f[R] section) defines the following
+functions for the math library:
.TP
\f[B]s(x)\f[R]
Returns the sine of \f[B]x\f[R], which is assumed to be in radians.
@@ -1441,8 +1516,7 @@ Functions\f[R] subsection below).
The extended library is \f[I]not\f[R] loaded when the
\f[B]-s\f[R]/\f[B]--standard\f[R] or \f[B]-w\f[R]/\f[B]--warn\f[R]
options are given since they are not part of the library defined by the
-standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html).
+standard (see the \f[B]STANDARDS\f[R] section).
.PP
The extended library is a \f[B]non-portable extension\f[R].
.TP
@@ -2501,7 +2575,8 @@ at which they become a problem.
In fact, memory should be exhausted before these limits should be hit.
.SH ENVIRONMENT VARIABLES
.PP
-bc(1) recognizes the following environment variables:
+As \f[B]non-portable extensions\f[R], bc(1) recognizes the following
+environment variables:
.TP
\f[B]POSIXLY_CORRECT\f[R]
If this variable exists (no matter the contents), bc(1) behaves as if
@@ -2621,6 +2696,22 @@ expressions and expression files, and a zero value makes bc(1) not exit.
This environment variable overrides the default, which can be queried
with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
.RE
+.TP
+\f[B]BC_DIGIT_CLAMP\f[R]
+When parsing numbers and if this environment variable exists and
+contains an integer, a non-zero value makes bc(1) clamp digits that are
+greater than or equal to the current \f[B]ibase\f[R] so that all such
+digits are considered equal to the \f[B]ibase\f[R] minus 1, and a zero
+value disables such clamping so that those digits are always equal to
+their value, which is multiplied by the power of the \f[B]ibase\f[R].
+.RS
+.PP
+This never applies to single-digit numbers, as per the standard (see the
+\f[B]STANDARDS\f[R] section).
+.PP
+This environment variable overrides the default, which can be queried
+with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
+.RE
.SH EXIT STATUS
.PP
bc(1) returns the following exit statuses:
@@ -2702,9 +2793,8 @@ checking, and its normal behavior can be forced by using the
\f[B]-i\f[R] flag or \f[B]--interactive\f[R] option.
.SH INTERACTIVE MODE
.PP
-Per the standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html),
-bc(1) has an interactive mode and a non-interactive mode.
+Per the standard (see the \f[B]STANDARDS\f[R] section), bc(1) has an
+interactive mode and a non-interactive mode.
Interactive mode is turned on automatically when both \f[B]stdin\f[R]
and \f[B]stdout\f[R] are hooked to a terminal, but the \f[B]-i\f[R] flag
and \f[B]--interactive\f[R] option can turn it on in other situations.
@@ -2736,8 +2826,7 @@ The default setting can be queried with the \f[B]-h\f[R] or
\f[B]--help\f[R] options.
.PP
TTY mode is different from interactive mode because interactive mode is
-required in the bc(1) standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html),
+required in the bc(1) standard (see the \f[B]STANDARDS\f[R] section),
and interactive mode requires only \f[B]stdin\f[R] and \f[B]stdout\f[R]
to be connected to a terminal.
.SS Command-Line History
diff --git a/manuals/bc/N.1.md b/manuals/bc/N.1.md
index 27cc68c8d39a..33b581185abb 100644
--- a/manuals/bc/N.1.md
+++ b/manuals/bc/N.1.md
@@ -34,15 +34,14 @@ 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*...] [**-I** *ibase*] [**-\-ibase**=*ibase*] [**-O** *obase*] [**-\-obase**=*obase*] [**-S** *scale*] [**-\-scale**=*scale*] [**-E** *seed*] [**-\-seed**=*seed*]
+**bc** [**-cCghilPqRsvVw**] [**-\-digit-clamp**] [**-\-no-digit-clamp**] [**-\-global-stacks**] [**-\-help**] [**-\-interactive**] [**-\-mathlib**] [**-\-no-prompt**] [**-\-no-read-prompt**] [**-\-quiet**] [**-\-standard**] [**-\-warn**] [**-\-version**] [**-e** *expr*] [**-\-expression**=*expr*...] [**-f** *file*...] [**-\-file**=*file*...] [*file*...] [**-I** *ibase*] [**-\-ibase**=*ibase*] [**-O** *obase*] [**-\-obase**=*obase*] [**-S** *scale*] [**-\-scale**=*scale*] [**-E** *seed*] [**-\-seed**=*seed*]
# DESCRIPTION
bc(1) is an interactive processor for a language first standardized in 1991 by
-POSIX. (The current standard is at
-https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html .) The
-language provides unlimited precision decimal arithmetic and is somewhat C-like,
-but there are differences. Such differences will be noted in this document.
+POSIX. (See the **STANDARDS** section.) 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**.
@@ -64,6 +63,86 @@ that is a bug and should be reported. See the **BUGS** section.
The following are the options that bc(1) accepts.
+**-C**, **-\-no-digit-clamp**
+
+: Disables clamping of digits greater than or equal to the current **ibase**
+ when parsing numbers.
+
+ This means that the value added to a number from a digit is always that
+ digit's value multiplied by the value of ibase raised to the power of the
+ digit's position, which starts from 0 at the least significant digit.
+
+ If this and/or the **-c** or **-\-digit-clamp** options are given multiple
+ times, the last one given is used.
+
+ This option overrides the **BC_DIGIT_CLAMP** environment variable (see the
+ **ENVIRONMENT VARIABLES** section) and the default, which can be queried
+ with the **-h** or **-\-help** options.
+
+ This is a **non-portable extension**.
+
+**-c**, **-\-digit-clamp**
+
+: Enables clamping of digits greater than or equal to the current **ibase**
+ when parsing numbers.
+
+ This means that digits that the value added to a number from a digit that is
+ greater than or equal to the ibase is the value of ibase minus 1 all
+ multiplied by the value of ibase raised to the power of the digit's
+ position, which starts from 0 at the least significant digit.
+
+ If this and/or the **-C** or **-\-no-digit-clamp** options are given
+ multiple times, the last one given is used.
+
+ This option overrides the **BC_DIGIT_CLAMP** environment variable (see the
+ **ENVIRONMENT VARIABLES** section) and the default, which can be queried
+ with the **-h** or **-\-help** options.
+
+ This is a **non-portable extension**.
+
+**-E** *seed*, **-\-seed**=*seed*
+
+: Sets the builtin variable **seed** to the value *seed* assuming that *seed*
+ is in base 10. It is a fatal error if *seed* is not a valid number.
+
+ If multiple instances of this option are given, the last is used.
+
+ 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 the **-f** and **-\-file** options),
+ 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 the **-e** and
+ **-\-expression** options), 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**.
+
**-g**, **-\-global-stacks**
: Turns the globals **ibase**, **obase**, **scale**, and **seed** into stacks.
@@ -134,7 +213,16 @@ The following are the options that bc(1) accepts.
**-h**, **-\-help**
-: Prints a usage message and quits.
+: Prints a usage message and exits.
+
+**-I** *ibase*, **-\-ibase**=*ibase*
+
+: Sets the builtin variable **ibase** to the value *ibase* assuming that
+ *ibase* is in base 10. It is a fatal error if *ibase* is not a valid number.
+
+ If multiple instances of this option are given, the last is used.
+
+ This is a **non-portable extension**.
**-i**, **-\-interactive**
@@ -158,6 +246,15 @@ The following are the options that bc(1) accepts.
To learn what is in the libraries, see the **LIBRARY** section.
+**-O** *obase*, **-\-obase**=*obase*
+
+: Sets the builtin variable **obase** to the value *obase* assuming that
+ *obase* is in base 10. It is a fatal error if *obase* is not a valid number.
+
+ If multiple instances of this option are given, the last is used.
+
+ This is a **non-portable extension**.
+
**-P**, **-\-no-prompt**
: Disables the prompt in TTY mode. (The prompt is only enabled in TTY mode.
@@ -171,6 +268,19 @@ The following are the options that bc(1) accepts.
This is a **non-portable extension**.
+**-q**, **-\-quiet**
+
+: This option is for compatibility with the GNU bc(1)
+ (https://www.gnu.org/software/bc/); 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
+ unless the **BC_BANNER** environment variable is set and contains a non-zero
+ integer or if this bc(1) was built with the header displayed by default. If
+ *any* of that is the case, then this option *does* prevent bc(1) from
+ printing the header.
+
+ This is a **non-portable extension**.
+
**-R**, **-\-no-read-prompt**
: Disables the read prompt in TTY mode. (The read prompt is only enabled in
@@ -224,35 +334,29 @@ The following are the options that bc(1) accepts.
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
- (https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html). It is
- a fatal error to attempt to redefine words that this bc(1) does not reserve
- as keywords.
+ It is a fatal error to redefine keywords mandated by the POSIX standard (see
+ the **STANDARDS** section). It is a fatal error to attempt to redefine words
+ that this bc(1) does not reserve as keywords.
-**-q**, **-\-quiet**
+**-S** *scale*, **-\-scale**=*scale*
-: This option is for compatibility with the GNU bc(1)
- (https://www.gnu.org/software/bc/); 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
- unless the **BC_BANNER** environment variable is set and contains a non-zero
- integer or if this bc(1) was built with the header displayed by default. If
- *any* of that is the case, then this option *does* prevent bc(1) from
- printing the header.
+: Sets the builtin variable **scale** to the value *scale* assuming that
+ *scale* is in base 10. It is a fatal error if *scale* is not a valid number.
+
+ If multiple instances of this option are given, the last is used.
This is a **non-portable extension**.
**-s**, **-\-standard**
-: Process exactly the language defined by the standard
- (https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html) and
- error if any extensions are used.
+: Process exactly the language defined by the standard (see the **STANDARDS**
+ section) and error if any extensions are used.
This is a **non-portable extension**.
**-v**, **-V**, **-\-version**
-: Print the version information (copyright header) and exit.
+: Print the version information (copyright header) and exits.
This is a **non-portable extension**.
@@ -274,74 +378,6 @@ The following are the options that bc(1) accepts.
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**.
-
-**-I** *ibase*, **-\-ibase**=*ibase*
-
-: Sets the builtin variable **ibase** to the value *ibase* assuming that
- *ibase* is in base 10. It is a fatal error if *ibase* is not a valid number.
-
- If multiple instances of this option are given, the last is used.
-
- This is a **non-portable extension**.
-
-**-O** *obase*, **-\-obase**=*obase*
-
-: Sets the builtin variable **obase** to the value *obase* assuming that
- *obase* is in base 10. It is a fatal error if *obase* is not a valid number.
-
- If multiple instances of this option are given, the last is used.
-
- This is a **non-portable extension**.
-
-**-S** *scale*, **-\-scale**=*scale*
-
-: Sets the builtin variable **scale** to the value *scale* assuming that
- *scale* is in base 10. It is a fatal error if *scale* is not a valid number.
-
- If multiple instances of this option are given, the last is used.
-
- This is a **non-portable extension**.
-
-**-E** *seed*, **-\-seed**=*seed*
-
-: Sets the builtin variable **seed** to the value *seed* assuming that *seed*
- is in base 10. It is a fatal error if *seed* is not a valid number.
-
- If multiple instances of this option are given, the last is used.
-
- This is a **non-portable extension**.
-
All long options are **non-portable extensions**.
# STDIN
@@ -393,8 +429,7 @@ it is recommended that those scripts be changed to redirect **stderr** to
# SYNTAX
The syntax for bc(1) programs is mostly C-like, with some differences. This
-bc(1) follows the POSIX standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html), which is a
+bc(1) follows the POSIX standard (see the **STANDARDS** section), 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.
@@ -592,14 +627,40 @@ use a non-seeded pseudo-random number generator.
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**.
+letters are equal to **9** plus their position in the alphabet, starting from
+**1** (i.e., **A** equals **10**, or **9+1**).
+
+If a digit or letter makes no sense with the current value of **ibase** (i.e.,
+they are greater than or equal to the current value of **ibase**), then the
+behavior depends on the existence of the **-c**/**-\-digit-clamp** or
+**-C**/**-\-no-digit-clamp** options (see the **OPTIONS** section), the
+existence and setting of the **BC_DIGIT_CLAMP** environment variable (see the
+**ENVIRONMENT VARIABLES** section), or the default, which can be queried with
+the **-h**/**-\-help** option.
+
+If clamping is off, then digits or letters that are greater than or equal to the
+current value of **ibase** are not changed. Instead, their given value is
+multiplied by the appropriate power of **ibase** and added into the number. This
+means that, with an **ibase** of **3**, the number **AB** is equal to
+**3\^1\*A+3\^0\*B**, which is **3** times **10** plus **11**, or **41**.
+
+If clamping is on, then digits or letters that are greater than or equal to the
+current value of **ibase** are set to the value of the highest valid digit in
+**ibase** before being multiplied by the appropriate power of **ibase** and
+added into the number. This means that, with an **ibase** of **3**, the number
+**AB** is equal to **3\^1\*2+3\^0\*2**, which is **3** times **2** plus **2**,
+or **8**.
+
+There is one exception to clamping: single-character numbers (i.e., **A**
+alone). Such numbers are never clamped and always take the value they would have
+in the highest possible **ibase**. This means that **A** alone always equals
+decimal **10** and **Z** alone always equals decimal **35**. This behavior is
+mandated by the standard (see the STANDARDS section) and is meant to provide an
+easy way to set the current **ibase** (with the **i** command) regardless of the
+current value of **ibase**.
+
+If clamping is on, and the clamped value of a character is needed, use a leading
+zero, i.e., for **A**, use **0A**.
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
@@ -849,10 +910,9 @@ The operators will be described in more detail below.
**assignment** operators, which means that **a=b\>c** is interpreted as
**(a=b)\>c**.
- Also, unlike the standard
- (https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html)
- requires, these operators can appear anywhere any other expressions can be
- used. This allowance is a **non-portable extension**.
+ Also, unlike the standard (see the **STANDARDS** section) requires, these
+ operators can appear anywhere any other expressions can be used. This
+ allowance is a **non-portable extension**.
**&&**
@@ -1099,9 +1159,8 @@ equivalents are given.
## Standard Library
-The standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html) defines the
-following functions for the math library:
+The standard (see the **STANDARDS** section) defines the following functions for
+the math library:
**s(x)**
@@ -1149,8 +1208,7 @@ following functions for the math 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
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html).
+defined by the standard (see the **STANDARDS** section).
The extended library is a **non-portable extension**.
@@ -2085,7 +2143,8 @@ be hit.
# ENVIRONMENT VARIABLES
-bc(1) recognizes the following environment variables:
+As **non-portable extensions**, bc(1) recognizes the following environment
+variables:
**POSIXLY_CORRECT**
@@ -2191,6 +2250,21 @@ bc(1) recognizes the following environment variables:
This environment variable overrides the default, which can be queried with
the **-h** or **-\-help** options.
+**BC_DIGIT_CLAMP**
+
+: When parsing numbers and if this environment variable exists and contains an
+ integer, a non-zero value makes bc(1) clamp digits that are greater than or
+ equal to the current **ibase** so that all such digits are considered equal
+ to the **ibase** minus 1, and a zero value disables such clamping so that
+ those digits are always equal to their value, which is multiplied by the
+ power of the **ibase**.
+
+ This never applies to single-digit numbers, as per the standard (see the
+ **STANDARDS** section).
+
+ 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:
@@ -2266,12 +2340,10 @@ checking, and its normal behavior can be forced by using the **-i** flag or
# INTERACTIVE MODE
-Per the standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html), 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.
+Per the standard (see the **STANDARDS** section), 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
@@ -2297,10 +2369,8 @@ 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) standard
-(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html), and
-interactive mode requires only **stdin** and **stdout** to be connected to a
-terminal.
+in the bc(1) standard (see the **STANDARDS** section), and interactive mode
+requires only **stdin** and **stdout** to be connected to a terminal.
## Command-Line History
diff --git a/manuals/bcl.3 b/manuals/bcl.3
index c0678722db0c..c1da21258a17 100644
--- a/manuals/bcl.3
+++ b/manuals/bcl.3
@@ -25,7 +25,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.TH "BCL" "3" "June 2022" "Gavin D. Howard" "Libraries Manual"
+.TH "BCL" "3" "August 2022" "Gavin D. Howard" "Libraries Manual"
.nh
.ad l
.SH NAME
@@ -36,19 +36,16 @@ bcl - library of arbitrary precision decimal arithmetic
.PP
\f[I]#include <bcl.h>\f[R]
.PP
-Link with \f[I]-lbcl\f[R].
-.SS Signals
-.PP
-This procedure will allow clients to use signals to interrupt
-computations running in bcl(3).
-.PP
-\f[B]void bcl_handleSignal(\f[R]\f[I]void\f[R]\f[B]);\f[R]
-.PP
-\f[B]bool bcl_running(\f[R]\f[I]void\f[R]\f[B]);\f[R]
+Link with \f[I]-lbcl\f[R], and on POSIX systems, \f[I]-lpthread\f[R] is
+also required.
.SS Setup
.PP
These items allow clients to set up bcl(3).
.PP
+\f[B]BclError bcl_start(\f[R]\f[I]void\f[R]\f[B]);\f[R]
+.PP
+\f[B]void bcl_end(\f[R]\f[I]void\f[R]\f[B]);\f[R]
+.PP
\f[B]BclError bcl_init(\f[R]\f[I]void\f[R]\f[B]);\f[R]
.PP
\f[B]void bcl_free(\f[R]\f[I]void\f[R]\f[B]);\f[R]
@@ -63,6 +60,10 @@ These items allow clients to set up bcl(3).
\f[I]leadingZeroes\f[R]\f[B]);\f[R]
.PP
\f[B]void bcl_gc(\f[R]\f[I]void\f[R]\f[B]);\f[R]
+.PP
+\f[B]bool bcl_digitClamp(\f[R]\f[I]void\f[R]\f[B]);\f[R]
+.PP
+\f[B]void bcl_setDigitClamp(bool\f[R] \f[I]digitClamp\f[R]\f[B]);\f[R]
.SS Contexts
.PP
These items will allow clients to handle contexts, which are isolated
@@ -234,10 +235,6 @@ standardized by POSIX
(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html) in
bc(1).
.PP
-bcl(3) is async-signal-safe if
-\f[B]bcl_handleSignal(\f[R]\f[I]void\f[R]\f[B])\f[R] is used properly.
-(See the \f[B]SIGNAL HANDLING\f[R] section.)
-.PP
bcl(3) assumes that it is allowed to use the \f[B]bcl\f[R],
\f[B]Bcl\f[R], \f[B]bc\f[R], and \f[B]Bc\f[R] prefixes for symbol names
without collision.
@@ -245,53 +242,66 @@ without collision.
All of the items in its interface are described below.
See the documentation for each function for what each function can
return.
-.SS Signals
-.TP
-\f[B]void bcl_handleSignal(\f[R]\f[I]void\f[R]\f[B])\f[R]
-An async-signal-safe function that can be called from a signal handler.
-If called from a signal handler on the same thread as any executing
-bcl(3) functions, it will interrupt the functions and force them to
-return early.
-It is undefined behavior if this function is called from a thread that
-is \f[I]not\f[R] executing any bcl(3) functions while any bcl(3)
-functions are executing.
+.SS Setup
+.TP
+\f[B]BclError bcl_start(\f[R]\f[I]void\f[R]\f[B])\f[R]
+Initializes this library.
+This function can be called multiple times, but \f[B]bcl_end()\f[R] must
+only be called \f[I]once\f[R].
+This is to make it possible for multiple libraries and applications to
+initialize bcl(3) without problem.
.RS
.PP
-If execution \f[I]is\f[R] interrupted,
-\f[B]bcl_handleSignal(\f[R]\f[I]void\f[R]\f[B])\f[R] does \f[I]not\f[R]
-return to its caller.
+It is suggested that client libraries call this function, but do not
+call \f[B]bcl_end()\f[R], and client applications should call both.
+.PP
+If there was no error, \f[B]BCL_ERROR_NONE\f[R] is returned.
+Otherwise, this function can return:
+.IP \[bu] 2
+\f[B]BCL_ERROR_FATAL_ALLOC_ERR\f[R]
.PP
-See the \f[B]SIGNAL HANDLING\f[R] section.
+This function must be the first one clients call.
+Calling any other function without calling this one first is undefined
+behavior.
.RE
.TP
-\f[B]bool bcl_running(\f[R]\f[I]void\f[R]\f[B])\f[R]
-An async-signal-safe function that can be called from a signal handler.
-It will return \f[B]true\f[R] if any bcl(3) procedures are running,
-which means it is safe to call
-\f[B]bcl_handleSignal(\f[R]\f[I]void\f[R]\f[B])\f[R].
-Otherwise, it returns \f[B]false\f[R].
+\f[B]void bcl_end(\f[R]\f[I]void\f[R]\f[B])\f[R]
+Deinitializes this library.
+This function must only be called \f[I]once\f[R].
.RS
.PP
-See the \f[B]SIGNAL HANDLING\f[R] section.
+All data must have been freed before calling this function.
+.PP
+This function must be the last one clients call.
+Calling this function before calling any other function is undefined
+behavior.
.RE
-.SS Setup
.TP
\f[B]BclError bcl_init(\f[R]\f[I]void\f[R]\f[B])\f[R]
-Initializes this library.
+Initializes the library for the current thread.
This function can be called multiple times, but each call must be
matched by a call to \f[B]bcl_free(\f[R]\f[I]void\f[R]\f[B])\f[R].
This is to make it possible for multiple libraries and applications to
-initialize bcl(3) without problem.
+initialize threads for bcl(3) without problem.
.RS
.PP
+This function \f[I]must\f[R] be called from the thread that it is
+supposed to initialize.
+.PP
If there was no error, \f[B]BCL_ERROR_NONE\f[R] is returned.
Otherwise, this function can return:
.IP \[bu] 2
\f[B]BCL_ERROR_FATAL_ALLOC_ERR\f[R]
.PP
-This function must be the first one clients call.
-Calling any other function without calling this one first is undefined
-behavior.
+This function must be the second one clients call.
+Calling any other function without calling \f[B]bcl_start()\f[R] and
+then this one first is undefined behavior, except in the case of new
+threads.
+New threads can safely call this function without calling
+\f[B]bcl_start()\f[R] if another thread has previously called
+\f[B]bcl_start()\f[R].
+But this function must still be the first function in bcl(3) called by
+that new thread.
.RE
.TP
\f[B]void bcl_free(\f[R]\f[I]void\f[R]\f[B])\f[R]
@@ -299,9 +309,12 @@ Decrements bcl(3)\[cq]s reference count and frees the data associated
with it if the reference count is \f[B]0\f[R].
.RS
.PP
-This function must be the last one clients call.
-Calling this function before calling any other function is undefined
-behavior.
+This function \f[I]must\f[R] be called from the thread that it is
+supposed to deinitialize.
+.PP
+This function must be the second to last one clients call.
+Calling this function before calling any other function besides
+\f[B]bcl_end()\f[R] is undefined behavior.
.RE
.TP
\f[B]bool bcl_abortOnFatalError(\f[R]\f[I]void\f[R]\f[B])\f[R]
@@ -313,6 +326,9 @@ a fatal error occurs.
.PP
If activated, clients do not need to check for fatal errors.
.PP
+This value is \f[I]thread-local\f[R]; it applies to just the thread it
+is read on.
+.PP
The default is \f[B]false\f[R].
.RE
.TP
@@ -324,6 +340,9 @@ If \f[I]abrt\f[R] is \f[B]true\f[R], bcl(3) will cause a
\f[B]SIGABRT\f[R] on fatal errors after the call.
.RS
.PP
+This value is \f[I]thread-local\f[R]; it applies to just the thread it
+is set on.
+.PP
If activated, clients do not need to check for fatal errors.
.RE
.TP
@@ -334,6 +353,9 @@ strings returned by \f[B]bcl_string()\f[R] when numbers are greater than
If \f[B]true\f[R] is returned, then leading zeroes will be added.
.RS
.PP
+This value is \f[I]thread-local\f[R]; it applies to just the thread it
+is read on.
+.PP
The default is \f[B]false\f[R].
.RE
.TP
@@ -343,6 +365,48 @@ by \f[B]bcl_string()\f[R] when numbers are greater than \f[B]-1\f[R],
less than \f[B]1\f[R], and not equal to \f[B]0\f[R].
If \f[I]leadingZeroes\f[R] is \f[B]true\f[R], leading zeroes will be
added to strings returned by \f[B]bcl_string()\f[R].
+.RS
+.PP
+This value is \f[I]thread-local\f[R]; it applies to just the thread it
+is set on.
+.RE
+.TP
+\f[B]bool bcl_digitClamp(\f[R]\f[I]void\f[R]\f[B])\f[R]
+Queries and returns the state of whether digits in number strings that
+are greater than or equal to the current \f[B]ibase\f[R] are clamped or
+not.
+.RS
+.PP
+If \f[B]true\f[R] is returned, then digits are treated as though they
+are equal to the value of \f[B]ibase\f[R] minus \f[B]1\f[R].
+If this is \f[I]not\f[R] true, then digits are treated as though they
+are equal to the value they would have if \f[B]ibase\f[R] was large
+enough.
+They are then multiplied by the appropriate power of \f[B]ibase\f[R].
+.PP
+For example, with clamping off and an \f[B]ibase\f[R] of \f[B]3\f[R],
+the string \[lq]AB\[rq] would equal \f[B]3\[ha]1*A+3\[ha]0*B\f[R], which
+is \f[B]3\f[R] times \f[B]10\f[R] plus \f[B]11\f[R], or \f[B]41\f[R],
+while with clamping on and an \f[B]ibase\f[R] of \f[B]3\f[R], the string
+\[lq]AB\[rq] would be equal to \f[B]3\[ha]1*2+3\[ha]0*2\f[R], which is
+\f[B]3\f[R] times \f[B]2\f[R] plus \f[B]2\f[R], or \f[B]8\f[R].
+.PP
+This value is \f[I]thread-local\f[R]; it applies to just the thread it
+is read on.
+.PP
+The default is \f[B]true\f[R].
+.RE
+.TP
+\f[B]void bcl_setDigitClamp(bool\f[R] \f[I]digitClamp\f[R]\f[B])\f[R]
+Sets the state of whether digits in number strings that are greater than
+or equal to the current \f[B]ibase\f[R] are clamped or not.
+For more information, see the
+\f[B]bcl_digitClamp(\f[R]\f[I]void\f[R]\f[B])\f[R] function.
+.RS
+.PP
+This value is \f[I]thread-local\f[R]; it applies to just the thread it
+is set on.
+.RE
.TP
\f[B]void bcl_gc(\f[R]\f[I]void\f[R]\f[B])\f[R]
Garbage collects cached instances of arbitrary-precision numbers.
@@ -392,6 +456,15 @@ Numbers created in one context are not valid in another context.
It is undefined behavior to use a number created in a different context.
Contexts are meant to isolate the numbers used by different clients in
the same application.
+.PP
+Different threads also have different contexts, so any numbers created
+in one thread are not valid in another thread.
+To pass values between contexts and threads, use \f[B]bcl_string()\f[R]
+to produce a string to pass around, and use \f[B]bcl_parse()\f[R] to
+parse the string.
+It is suggested that the \f[B]obase\f[R] used to create the string be
+passed around with the string and used as the \f[B]ibase\f[R] for
+\f[B]bcl_parse()\f[R] to ensure that the number will be the same.
.RE
.TP
\f[B]BclContext bcl_ctxt_create(\f[R]\f[I]void\f[R]\f[B])\f[R]
@@ -1200,9 +1273,6 @@ An invalid \f[B]BclNumber\f[R] was given as a parameter.
\f[B]BCL_ERROR_INVALID_CONTEXT\f[R]
An invalid \f[B]BclContext\f[R] is being used.
.TP
-\f[B]BCL_ERROR_SIGNAL\f[R]
-A signal interrupted execution.
-.TP
\f[B]BCL_ERROR_MATH_NEGATIVE\f[R]
A negative number was given as an argument to a parameter that cannot
accept negative numbers, such as for square roots.
@@ -1278,11 +1348,16 @@ this behavior.
.RE
.SH ATTRIBUTES
.PP
-When \f[B]bcl_handleSignal(\f[R]\f[I]void\f[R]\f[B])\f[R] is used
-properly, bcl(3) is async-signal-safe.
+bcl(3) is \f[I]MT-Safe\f[R]: it is safe to call any functions from more
+than one thread.
+However, is is \f[I]not\f[R] safe to pass any data between threads
+except for strings returned by \f[B]bcl_string()\f[R].
.PP
-bcl(3) is \f[I]MT-Unsafe\f[R]: it is unsafe to call any functions from
-more than one thread.
+bcl(3) is not \f[I]async-signal-safe\f[R].
+It was not possible to make bcl(3) safe with signals and also make it
+safe with multiple threads.
+If it is necessary to be able to interrupt bcl(3), spawn a separate
+thread to run the calculation.
.SH PERFORMANCE
.PP
Most bc(1) implementations use \f[B]char\f[R] types to calculate the
@@ -1354,24 +1429,6 @@ 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.
-.SH SIGNAL HANDLING
-.PP
-If a signal handler calls
-\f[B]bcl_handleSignal(\f[R]\f[I]void\f[R]\f[B])\f[R] from the same
-thread that there are bcl(3) functions executing in, it will cause all
-execution to stop as soon as possible, interrupting long-running
-calculations, if necessary and cause the function that was executing to
-return.
-If possible, the error code \f[B]BC_ERROR_SIGNAL\f[R] is returned.
-.PP
-If execution \f[I]is\f[R] interrupted,
-\f[B]bcl_handleSignal(\f[R]\f[I]void\f[R]\f[B])\f[R] does \f[I]not\f[R]
-return to its caller.
-.PP
-It is undefined behavior if
-\f[B]bcl_handleSignal(\f[R]\f[I]void\f[R]\f[B])\f[R] is called from a
-thread that is not executing bcl(3) functions, if bcl(3) functions are
-executing.
.SH SEE ALSO
.PP
bc(1) and dc(1)
diff --git a/manuals/bcl.3.md b/manuals/bcl.3.md
index 1f694413f7d6..22c863b955d2 100644
--- a/manuals/bcl.3.md
+++ b/manuals/bcl.3.md
@@ -38,21 +38,16 @@ bcl - library of arbitrary precision decimal arithmetic
*#include <bcl.h>*
-Link with *-lbcl*.
-
-## Signals
-
-This procedure will allow clients to use signals to interrupt computations
-running in bcl(3).
-
-**void bcl_handleSignal(**_void_**);**
-
-**bool bcl_running(**_void_**);**
+Link with *-lbcl*, and on POSIX systems, *-lpthread* is also required.
## Setup
These items allow clients to set up bcl(3).
+**BclError bcl_start(**_void_**);**
+
+**void bcl_end(**_void_**);**
+
**BclError bcl_init(**_void_**);**
**void bcl_free(**_void_**);**
@@ -67,6 +62,10 @@ These items allow clients to set up bcl(3).
**void bcl_gc(**_void_**);**
+**bool bcl_digitClamp(**_void_**);**
+
+**void bcl_setDigitClamp(bool** _digitClamp_**);**
+
## Contexts
These items will allow clients to handle contexts, which are isolated from each
@@ -218,64 +217,73 @@ bcl(3) is a library that implements arbitrary-precision decimal math, as
standardized by POSIX
(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html) in bc(1).
-bcl(3) is async-signal-safe if **bcl_handleSignal(**_void_**)** is used
-properly. (See the **SIGNAL HANDLING** section.)
-
bcl(3) assumes that it is allowed to use the **bcl**, **Bcl**, **bc**, and
**Bc** prefixes for symbol names without collision.
All of the items in its interface are described below. See the documentation for
each function for what each function can return.
-## Signals
+## Setup
+
+**BclError bcl_start(**_void_**)**
+
+: Initializes this library. This function can be called multiple times, but
+ **bcl_end()** must only be called *once*. This is to make it possible for
+ multiple libraries and applications to initialize bcl(3) without problem.
-**void bcl_handleSignal(**_void_**)**
+ It is suggested that client libraries call this function, but do not call
+ **bcl_end()**, and client applications should call both.
-: An async-signal-safe function that can be called from a signal handler. If
- called from a signal handler on the same thread as any executing bcl(3)
- functions, it will interrupt the functions and force them to return early.
- It is undefined behavior if this function is called from a thread that is
- *not* executing any bcl(3) functions while any bcl(3) functions are
- executing.
+ If there was no error, **BCL_ERROR_NONE** is returned. Otherwise, this
+ function can return:
- If execution *is* interrupted, **bcl_handleSignal(**_void_**)** does *not*
- return to its caller.
+ * **BCL_ERROR_FATAL_ALLOC_ERR**
- See the **SIGNAL HANDLING** section.
+ This function must be the first one clients call. Calling any other
+ function without calling this one first is undefined behavior.
-**bool bcl_running(**_void_**)**
+**void bcl_end(**_void_**)**
-: An async-signal-safe function that can be called from a signal handler. It
- will return **true** if any bcl(3) procedures are running, which means it is
- safe to call **bcl_handleSignal(**_void_**)**. Otherwise, it returns
- **false**.
+: Deinitializes this library. This function must only be called *once*.
- See the **SIGNAL HANDLING** section.
+ All data must have been freed before calling this function.
-## Setup
+ This function must be the last one clients call. Calling this function
+ before calling any other function is undefined behavior.
**BclError bcl_init(**_void_**)**
-: Initializes this library. This function can be called multiple times, but
- each call must be matched by a call to **bcl_free(**_void_**)**. This is to
- make it possible for multiple libraries and applications to initialize
- bcl(3) without problem.
+: Initializes the library for the current thread. This function can be called
+ multiple times, but each call must be matched by a call to
+ **bcl_free(**_void_**)**. This is to make it possible for multiple libraries
+ and applications to initialize threads for bcl(3) without problem.
+
+ This function *must* be called from the thread that it is supposed to
+ initialize.
If there was no error, **BCL_ERROR_NONE** is returned. Otherwise, this
function can return:
* **BCL_ERROR_FATAL_ALLOC_ERR**
- This function must be the first one clients call. Calling any other
- function without calling this one first is undefined behavior.
+ This function must be the second one clients call. Calling any other
+ function without calling **bcl_start()** and then this one first is
+ undefined behavior, except in the case of new threads. New threads can
+ safely call this function without calling **bcl_start()** if another thread
+ has previously called **bcl_start()**. But this function must still be the
+ first function in bcl(3) called by that new thread.
**void bcl_free(**_void_**)**
: Decrements bcl(3)'s reference count and frees the data associated with it if
the reference count is **0**.
- This function must be the last one clients call. Calling this function
- before calling any other function is undefined behavior.
+ This function *must* be called from the thread that it is supposed to
+ deinitialize.
+
+ This function must be the second to last one clients call. Calling this
+ function before calling any other function besides **bcl_end()** is
+ undefined behavior.
**bool bcl_abortOnFatalError(**_void_**)**
@@ -285,6 +293,8 @@ each function for what each function can return.
If activated, clients do not need to check for fatal errors.
+ This value is *thread-local*; it applies to just the thread it is read on.
+
The default is **false**.
**void bcl_setAbortOnFatalError(bool** _abrt_**)**
@@ -294,6 +304,8 @@ each function for what each function can return.
call. If *abrt* is **true**, bcl(3) will cause a **SIGABRT** on fatal errors
after the call.
+ This value is *thread-local*; it applies to just the thread it is set on.
+
If activated, clients do not need to check for fatal errors.
**bool bcl_leadingZeroes(**_void_**)**
@@ -303,6 +315,8 @@ each function for what each function can return.
**1**, and not equal to **0**. If **true** is returned, then leading zeroes
will be added.
+ This value is *thread-local*; it applies to just the thread it is read on.
+
The default is **false**.
**void bcl_setLeadingZeroes(bool** _leadingZeroes_**)**
@@ -312,6 +326,37 @@ each function for what each function can return.
not equal to **0**. If *leadingZeroes* is **true**, leading zeroes will be
added to strings returned by **bcl_string()**.
+ This value is *thread-local*; it applies to just the thread it is set on.
+
+**bool bcl_digitClamp(**_void_**)**
+
+: Queries and returns the state of whether digits in number strings that are
+ greater than or equal to the current **ibase** are clamped or not.
+
+ If **true** is returned, then digits are treated as though they are equal to
+ the value of **ibase** minus **1**. If this is *not* true, then digits are
+ treated as though they are equal to the value they would have if **ibase**
+ was large enough. They are then multiplied by the appropriate power of
+ **ibase**.
+
+ For example, with clamping off and an **ibase** of **3**, the string "AB"
+ would equal **3\^1\*A+3\^0\*B**, which is **3** times **10** plus **11**, or
+ **41**, while with clamping on and an **ibase** of **3**, the string "AB"
+ would be equal to **3\^1\*2+3\^0\*2**, which is **3** times **2** plus
+ **2**, or **8**.
+
+ This value is *thread-local*; it applies to just the thread it is read on.
+
+ The default is **true**.
+
+**void bcl_setDigitClamp(bool** _digitClamp_**)**
+
+: Sets the state of whether digits in number strings that are greater than or
+ equal to the current **ibase** are clamped or not. For more information, see
+ the **bcl_digitClamp(**_void_**)** function.
+
+ This value is *thread-local*; it applies to just the thread it is set on.
+
**void bcl_gc(**_void_**)**
: Garbage collects cached instances of arbitrary-precision numbers. This only
@@ -357,6 +402,13 @@ an argument.
are meant to isolate the numbers used by different clients in the same
application.
+ Different threads also have different contexts, so any numbers created in
+ one thread are not valid in another thread. To pass values between contexts
+ and threads, use **bcl_string()** to produce a string to pass around, and
+ use **bcl_parse()** to parse the string. It is suggested that the **obase**
+ used to create the string be passed around with the string and used as the
+ **ibase** for **bcl_parse()** to ensure that the number will be the same.
+
**BclContext bcl_ctxt_create(**_void_**)**
: Creates a context and returns it. Returns **NULL** if there was an error.
@@ -1015,10 +1067,6 @@ codes defined in **BclError**. The complete list of codes is the following:
: An invalid **BclContext** is being used.
-**BCL_ERROR_SIGNAL**
-
-: A signal interrupted execution.
-
**BCL_ERROR_MATH_NEGATIVE**
: A negative number was given as an argument to a parameter that cannot accept
@@ -1088,11 +1136,13 @@ codes defined in **BclError**. The complete list of codes is the following:
# ATTRIBUTES
-When **bcl_handleSignal(**_void_**)** is used properly, bcl(3) is
-async-signal-safe.
+bcl(3) is *MT-Safe*: it is safe to call any functions from more than one thread.
+However, is is *not* safe to pass any data between threads except for strings
+returned by **bcl_string()**.
-bcl(3) is *MT-Unsafe*: it is unsafe to call any functions from more than one
-thread.
+bcl(3) is not *async-signal-safe*. It was not possible to make bcl(3) safe with
+signals and also make it safe with multiple threads. If it is necessary to be
+able to interrupt bcl(3), spawn a separate thread to run the calculation.
# PERFORMANCE
@@ -1164,21 +1214,6 @@ These limits are meant to be effectively non-existent; the limits are so large
become a problem. In fact, memory should be exhausted before these limits should
be hit.
-# SIGNAL HANDLING
-
-If a signal handler calls **bcl_handleSignal(**_void_**)** from the same thread
-that there are bcl(3) functions executing in, it will cause all execution to
-stop as soon as possible, interrupting long-running calculations, if necessary
-and cause the function that was executing to return. If possible, the error code
-**BC_ERROR_SIGNAL** is returned.
-
-If execution *is* interrupted, **bcl_handleSignal(**_void_**)** does *not*
-return to its caller.
-
-It is undefined behavior if **bcl_handleSignal(**_void_**)** is called from
-a thread that is not executing bcl(3) functions, if bcl(3) functions are
-executing.
-
# SEE ALSO
bc(1) and dc(1)
diff --git a/manuals/build.md b/manuals/build.md
index af0b7c15e0c3..14c1fb557984 100644
--- a/manuals/build.md
+++ b/manuals/build.md
@@ -205,6 +205,10 @@ Can be overridden by passing the `--prefix` option to `configure.sh`.
Defaults to `/usr/local`.
+***WARNING***: Locales ignore the prefix because they *must* be installed at a
+fixed location to work at all. If you do not want that to happen, you must
+disable locales (NLS) completely.
+
#### `DESTDIR`
Path to prepend onto `PREFIX`. This is mostly for distro and package
@@ -355,6 +359,30 @@ following forms:
--option=arg
```
+#### Predefined Builds
+
+To quickly get a release build of a `bc` and `dc` that is (by default)
+compatible with the BSD `bc` and `dc`, use the `-p` or `--predefined-build-type`
+options:
+
+```
+./configure.sh -pBSD
+./configure.sh --predefined-build-type=BSD
+```
+
+Both commands are equivalent.
+
+To quickly get a release build of a `bc` and `dc` that is (by default)
+compatible with the GNU `bc` and `dc`, use the `-p` or `--predefined-build-type`
+options:
+
+```
+./configure.sh -pGNU
+./configure.sh --predefined-build-type=GNU
+```
+
+Both commands are equivalent.
+
#### Library
To build the math library, use the following commands for the configure step:
@@ -435,7 +463,7 @@ This option affects the [build type][7].
History support can be provided by editline, in order to implement `vi`-like
keybindings and other features.
-To enable editline support pass either the `-e` flag or the `--enable-editline`
+To enable editline support, pass either the `-e` flag or the `--enable-editline`
option to `configure.sh`, as follows:
```
@@ -447,12 +475,16 @@ Both commands are equivalent.
This is ignored if history is disabled.
+This option is only used if it is after any other `-e`/`--enable-editline`
+options, any `-r`/`--enable-readline` options, and any
+`-i`/`--enable-internal-history` options.
+
##### Readline
History support can be provided by readline, in order to implement `vi`-like
keybindings and other features.
-To enable readline support pass either the `-r` flag or the `--enable-readline`
+To enable readline support, pass either the `-r` flag or the `--enable-readline`
option to `configure.sh`, as follows:
```
@@ -464,6 +496,30 @@ Both commands are equivalent.
This is ignored if history is disabled.
+This option is only used if it is after any other `-r`/`--enable-readline`
+options, any `-e`/`--enable-editline` options, and any
+`-i`/`--enable-internal-history` options.
+
+##### Internal History
+
+History support is also available as an internal implementation with no
+dependencies. This is the default if editline and readline are not selected.
+
+However, if `-p` option is used, then this option can be useful for selecting
+the internal history regardless of what the predefined build has.
+
+To enable the internal history, pass either the `-i` flag or the
+`--enable-internal-history` option to `configure.sh` as follows:
+
+```
+./configure.sh -i
+./configure.sh --enable-internal-history
+```
+
+This option is only used if it is after any other
+`-i`/`--enable-internal-history` options, any `-e`/`--enable-editline` options,
+and any `-r`/`--enable-readline` options.
+
#### NLS (Locale Support)
To disable locale support (use only English), pass either the `-N` flag or the
@@ -481,6 +537,10 @@ another platform that does not support the POSIX locale API or utilities.
This option affects the [build type][7].
+***WARNING***: Locales ignore the prefix because they *must* be installed at a
+fixed location to work at all. If you do not want that to happen, you must
+disable locales (NLS) completely.
+
#### Extra Math
This `bc` has 7 extra operators:
@@ -607,6 +667,32 @@ environment variables to override them, is below:
| | for dc should be on | | |
| | in tty mode. | | |
| --------------- | -------------------- | ------------ | -------------------- |
+| bc.expr_exit | Whether to exit bc | 1 | BC_EXPR_EXIT |
+| | if an expression or | | |
+| | expression file is | | |
+| | given with the -e or | | |
+| | -f options. | | |
+| --------------- | -------------------- | ------------ | -------------------- |
+| dc.expr_exit | Whether to exit dc | 1 | DC_EXPR_EXIT |
+| | if an expression or | | |
+| | expression file is | | |
+| | given with the -e or | | |
+| | -f options. | | |
+| --------------- | -------------------- | ------------ | -------------------- |
+| bc.digit_clamp | Whether to have bc | 0 | BC_DIGIT_CLAMP |
+| | clamp digits that | | |
+| | are greater than or | | |
+| | equal to the current | | |
+| | ibase when parsing | | |
+| | numbers. | | |
+| --------------- | -------------------- | ------------ | -------------------- |
+| dc.digit_clamp | Whether to have dc | 0 | DC_DIGIT_CLAMP |
+| | clamp digits that | | |
+| | are greater than or | | |
+| | equal to the current | | |
+| | ibase when parsing | | |
+| | numbers. | | |
+| --------------- | -------------------- | ------------ | -------------------- |
```
These settings are not meant to be changed on a whim. They are meant to ensure
@@ -637,6 +723,10 @@ They correspond to the environment variables `$PREFIX`, `$BINDIR`,
`$DATAROOTDIR`, `$DATADIR`, `$MANDIR`, `$MAN1DIR`, and `$LOCALEDIR`,
respectively.
+***WARNING***: Locales ignore the prefix because they *must* be installed at a
+fixed location to work at all. If you do not want that to happen, you must
+disable locales (NLS) completely.
+
***WARNING***: If the option is given, the value of the corresponding
environment variable is overridden.
@@ -672,6 +762,10 @@ have, regardless. To enable that behavior, you can pass the `-l` flag or the
Both commands are equivalent.
+***WARNING***: Locales ignore the prefix because they *must* be installed at a
+fixed location to work at all. If you do not want that to happen, you must
+disable locales (NLS) completely.
+
### Optimization
The `configure.sh` script will accept an optimization level to pass to the
@@ -873,6 +967,22 @@ Both commands are equivalent.
***WARNING***: Both `bc` and `dc` must be built for test coverage. Otherwise,
`configure.sh` will give an error.
+#### Problematic Tests
+
+Some tests are problematic, in that they can cause `SIGKILL` on FreeBSD or
+`SIGSEGV` on Linux from being killed by the "OOM Killer" part of the kernel. On
+Linux, these tests are usually fine, but on FreeBSD, they are usually a problem.
+
+To disable problematic tests, pass the `-P` flag or the
+`--disable-problematic-tests` option to `configure.sh` as follows:
+
+```
+./configure.sh -P
+./configure.sh --disable-problematic-tests
+```
+
+Both commands are equivalent.
+
[1]: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html
[2]: https://www.gnu.org/software/bc/
[3]: https://www.musl-libc.org/
diff --git a/manuals/dc/A.1 b/manuals/dc/A.1
index cc1ad0e7bb75..4771cb655ba1 100644
--- a/manuals/dc/A.1
+++ b/manuals/dc/A.1
@@ -25,7 +25,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.TH "DC" "1" "June 2022" "Gavin D. Howard" "General Commands Manual"
+.TH "DC" "1" "August 2022" "Gavin D. Howard" "General Commands Manual"
.nh
.ad l
.SH Name
@@ -33,17 +33,19 @@
dc - arbitrary-precision decimal reverse-Polish notation calculator
.SH SYNOPSIS
.PP
-\f[B]dc\f[R] [\f[B]-hiPRvVx\f[R]] [\f[B]--version\f[R]]
-[\f[B]--help\f[R]] [\f[B]--interactive\f[R]] [\f[B]--no-prompt\f[R]]
-[\f[B]--no-read-prompt\f[R]] [\f[B]--extended-register\f[R]]
-[\f[B]-e\f[R] \f[I]expr\f[R]]
-[\f[B]--expression\f[R]=\f[I]expr\f[R]\&...] [\f[B]-f\f[R]
-\f[I]file\f[R]\&...] [\f[B]--file\f[R]=\f[I]file\f[R]\&...]
-[\f[I]file\f[R]\&...] [\f[B]-I\f[R] \f[I]ibase\f[R]]
-[\f[B]--ibase\f[R]=\f[I]ibase\f[R]] [\f[B]-O\f[R] \f[I]obase\f[R]]
-[\f[B]--obase\f[R]=\f[I]obase\f[R]] [\f[B]-S\f[R] \f[I]scale\f[R]]
-[\f[B]--scale\f[R]=\f[I]scale\f[R]] [\f[B]-E\f[R] \f[I]seed\f[R]]
-[\f[B]--seed\f[R]=\f[I]seed\f[R]]
+\f[B]dc\f[R] [\f[B]-cChiPRvVx\f[R]] [\f[B]--version\f[R]]
+[\f[B]--help\f[R]] [\f[B]--digit-clamp\f[R]]
+[\f[B]--no-digit-clamp\f[R]] [\f[B]--interactive\f[R]]
+[\f[B]--no-prompt\f[R]] [\f[B]--no-read-prompt\f[R]]
+[\f[B]--extended-register\f[R]] [\f[B]-e\f[R] \f[I]expr\f[R]]
+[\f[B]--expression\f[R]=\f[I]expr\f[R]\&...]
+[\f[B]-f\f[R] \f[I]file\f[R]\&...]
+[\f[B]--file\f[R]=\f[I]file\f[R]\&...]
+[\f[I]file\f[R]\&...]
+[\f[B]-I\f[R] \f[I]ibase\f[R]] [\f[B]--ibase\f[R]=\f[I]ibase\f[R]]
+[\f[B]-O\f[R] \f[I]obase\f[R]] [\f[B]--obase\f[R]=\f[I]obase\f[R]]
+[\f[B]-S\f[R] \f[I]scale\f[R]] [\f[B]--scale\f[R]=\f[I]scale\f[R]]
+[\f[B]-E\f[R] \f[I]seed\f[R]] [\f[B]--seed\f[R]=\f[I]seed\f[R]]
.SH DESCRIPTION
.PP
dc(1) is an arbitrary-precision calculator.
@@ -65,83 +67,54 @@ and this dc(1) will always start with a \f[B]scale\f[R] of \f[B]10\f[R].
.PP
The following are the options that dc(1) accepts.
.TP
-\f[B]-h\f[R], \f[B]--help\f[R]
-Prints a usage message and quits.
-.TP
-\f[B]-v\f[R], \f[B]-V\f[R], \f[B]--version\f[R]
-Print the version information (copyright header) and exit.
-.TP
-\f[B]-i\f[R], \f[B]--interactive\f[R]
-Forces interactive mode.
-(See the \f[B]INTERACTIVE MODE\f[R] section.)
+\f[B]-C\f[R], \f[B]--no-digit-clamp\f[R]
+Disables clamping of digits greater than or equal to the current
+\f[B]ibase\f[R] when parsing numbers.
.RS
.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
-.TP
-\f[B]-L\f[R], \f[B]--no-line-length\f[R]
-Disables line length checking and prints numbers without backslashes and
-newlines.
-In other words, this option sets \f[B]BC_LINE_LENGTH\f[R] to \f[B]0\f[R]
-(see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
-.RS
+This means that the value added to a number from a digit is always that
+digit\[cq]s value multiplied by the value of ibase raised to the power
+of the digit\[cq]s position, which starts from 0 at the least
+significant digit.
.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
-.TP
-\f[B]-P\f[R], \f[B]--no-prompt\f[R]
-Disables the prompt in TTY mode.
-(The prompt is only enabled in TTY mode.
-See the \f[B]TTY MODE\f[R] 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
-\f[B]DC_ENV_ARGS\f[R].
-.RS
+If this and/or the \f[B]-c\f[R] or \f[B]--digit-clamp\f[R] options are
+given multiple times, the last one given is used.
.PP
-These options override the \f[B]DC_PROMPT\f[R] and \f[B]DC_TTY_MODE\f[R]
-environment variables (see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
+This option overrides the \f[B]DC_DIGIT_CLAMP\f[R] environment variable
+(see the \f[B]ENVIRONMENT VARIABLES\f[R] section) and the default, which
+can be queried with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
.PP
This is a \f[B]non-portable extension\f[R].
.RE
.TP
-\f[B]-R\f[R], \f[B]--no-read-prompt\f[R]
-Disables the read prompt in TTY mode.
-(The read prompt is only enabled in TTY mode.
-See the \f[B]TTY MODE\f[R] 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
-\f[B]BC_ENV_ARGS\f[R] (see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
-This option is also useful in hash bang lines of dc(1) scripts that
-prompt for user input.
+\f[B]-c\f[R], \f[B]--digit-clamp\f[R]
+Enables clamping of digits greater than or equal to the current
+\f[B]ibase\f[R] when parsing numbers.
.RS
.PP
-This option does not disable the regular prompt because the read prompt
-is only used when the \f[B]?\f[R] command is used.
+This means that digits that the value added to a number from a digit
+that is greater than or equal to the ibase is the value of ibase minus 1
+all multiplied by the value of ibase raised to the power of the
+digit\[cq]s position, which starts from 0 at the least significant
+digit.
.PP
-These options \f[I]do\f[R] override the \f[B]DC_PROMPT\f[R] and
-\f[B]DC_TTY_MODE\f[R] environment variables (see the \f[B]ENVIRONMENT
-VARIABLES\f[R] section), but only for the read prompt.
+If this and/or the \f[B]-C\f[R] or \f[B]--no-digit-clamp\f[R] options
+are given multiple times, the last one given is used.
.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
-.TP
-\f[B]-x\f[R] \f[B]--extended-register\f[R]
-Enables extended register mode.
-See the \f[I]Extended Register Mode\f[R] subsection of the
-\f[B]REGISTERS\f[R] section for more information.
-.RS
+This option overrides the \f[B]DC_DIGIT_CLAMP\f[R] environment variable
+(see the \f[B]ENVIRONMENT VARIABLES\f[R] section) and the default, which
+can be queried with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
.PP
This is a \f[B]non-portable extension\f[R].
.RE
.TP
-\f[B]-z\f[R], \f[B]--leading-zeroes\f[R]
-Makes dc(1) print all numbers greater than \f[B]-1\f[R] and less than
-\f[B]1\f[R], and not equal to \f[B]0\f[R], with a leading zero.
+\f[B]-E\f[R] \f[I]seed\f[R], \f[B]--seed\f[R]=\f[I]seed\f[R]
+Sets the builtin variable \f[B]seed\f[R] to the value \f[I]seed\f[R]
+assuming that \f[I]seed\f[R] is in base 10.
+It is a fatal error if \f[I]seed\f[R] is not a valid number.
.RS
.PP
-This can be set for individual numbers with the \f[B]plz(x)\f[R],
-plznl(x)**, \f[B]pnlz(x)\f[R], and \f[B]pnlznl(x)\f[R] functions in the
-extended math library (see the \f[B]LIBRARY\f[R] section).
+If multiple instances of this option are given, the last is used.
.PP
This is a \f[B]non-portable extension\f[R].
.RE
@@ -189,6 +162,9 @@ exit.
This is a \f[B]non-portable extension\f[R].
.RE
.TP
+\f[B]-h\f[R], \f[B]--help\f[R]
+Prints a usage message and exits.
+.TP
\f[B]-I\f[R] \f[I]ibase\f[R], \f[B]--ibase\f[R]=\f[I]ibase\f[R]
Sets the builtin variable \f[B]ibase\f[R] to the value \f[I]ibase\f[R]
assuming that \f[I]ibase\f[R] is in base 10.
@@ -200,6 +176,24 @@ If multiple instances of this option are given, the last is used.
This is a \f[B]non-portable extension\f[R].
.RE
.TP
+\f[B]-i\f[R], \f[B]--interactive\f[R]
+Forces interactive mode.
+(See the \f[B]INTERACTIVE MODE\f[R] section.)
+.RS
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
+\f[B]-L\f[R], \f[B]--no-line-length\f[R]
+Disables line length checking and prints numbers without backslashes and
+newlines.
+In other words, this option sets \f[B]BC_LINE_LENGTH\f[R] to \f[B]0\f[R]
+(see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
+.RS
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
\f[B]-O\f[R] \f[I]obase\f[R], \f[B]--obase\f[R]=\f[I]obase\f[R]
Sets the builtin variable \f[B]obase\f[R] to the value \f[I]obase\f[R]
assuming that \f[I]obase\f[R] is in base 10.
@@ -211,6 +205,44 @@ If multiple instances of this option are given, the last is used.
This is a \f[B]non-portable extension\f[R].
.RE
.TP
+\f[B]-P\f[R], \f[B]--no-prompt\f[R]
+Disables the prompt in TTY mode.
+(The prompt is only enabled in TTY mode.
+See the \f[B]TTY MODE\f[R] 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
+\f[B]DC_ENV_ARGS\f[R].
+.RS
+.PP
+These options override the \f[B]DC_PROMPT\f[R] and \f[B]DC_TTY_MODE\f[R]
+environment variables (see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
+\f[B]-R\f[R], \f[B]--no-read-prompt\f[R]
+Disables the read prompt in TTY mode.
+(The read prompt is only enabled in TTY mode.
+See the \f[B]TTY MODE\f[R] 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
+\f[B]BC_ENV_ARGS\f[R] (see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
+This option is also useful in hash bang lines of dc(1) scripts that
+prompt for user input.
+.RS
+.PP
+This option does not disable the regular prompt because the read prompt
+is only used when the \f[B]?\f[R] command is used.
+.PP
+These options \f[I]do\f[R] override the \f[B]DC_PROMPT\f[R] and
+\f[B]DC_TTY_MODE\f[R] environment variables (see the \f[B]ENVIRONMENT
+VARIABLES\f[R] section), but only for the read prompt.
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
\f[B]-S\f[R] \f[I]scale\f[R], \f[B]--scale\f[R]=\f[I]scale\f[R]
Sets the builtin variable \f[B]scale\f[R] to the value \f[I]scale\f[R]
assuming that \f[I]scale\f[R] is in base 10.
@@ -222,13 +254,26 @@ If multiple instances of this option are given, the last is used.
This is a \f[B]non-portable extension\f[R].
.RE
.TP
-\f[B]-E\f[R] \f[I]seed\f[R], \f[B]--seed\f[R]=\f[I]seed\f[R]
-Sets the builtin variable \f[B]seed\f[R] to the value \f[I]seed\f[R]
-assuming that \f[I]seed\f[R] is in base 10.
-It is a fatal error if \f[I]seed\f[R] is not a valid number.
+\f[B]-v\f[R], \f[B]-V\f[R], \f[B]--version\f[R]
+Print the version information (copyright header) and exits.
+.TP
+\f[B]-x\f[R] \f[B]--extended-register\f[R]
+Enables extended register mode.
+See the \f[I]Extended Register Mode\f[R] subsection of the
+\f[B]REGISTERS\f[R] section for more information.
.RS
.PP
-If multiple instances of this option are given, the last is used.
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
+\f[B]-z\f[R], \f[B]--leading-zeroes\f[R]
+Makes dc(1) print all numbers greater than \f[B]-1\f[R] and less than
+\f[B]1\f[R], and not equal to \f[B]0\f[R], with a leading zero.
+.RS
+.PP
+This can be set for individual numbers with the \f[B]plz(x)\f[R],
+plznl(x)**, \f[B]pnlz(x)\f[R], and \f[B]pnlznl(x)\f[R] functions in the
+extended math library (see the \f[B]LIBRARY\f[R] section).
.PP
This is a \f[B]non-portable extension\f[R].
.RE
@@ -360,17 +405,48 @@ This is a \f[B]non-portable extension\f[R].
Numbers are strings made up of digits, uppercase letters up to
\f[B]F\f[R], and at most \f[B]1\f[R] period for a radix.
Numbers can have up to \f[B]DC_NUM_MAX\f[R] digits.
-Uppercase letters are equal to \f[B]9\f[R] + their position in the
+Uppercase letters are equal to \f[B]9\f[R] plus their position in the
alphabet (i.e., \f[B]A\f[R] equals \f[B]10\f[R], or \f[B]9+1\f[R]).
-If a digit or letter makes no sense with the current value of
-\f[B]ibase\f[R], they are set to the value of the highest valid digit in
-\f[B]ibase\f[R].
.PP
-Single-character numbers (i.e., \f[B]A\f[R] alone) take the value that
-they would have if they were valid digits, regardless of the value of
-\f[B]ibase\f[R].
+If a digit or letter makes no sense with the current value of
+\f[B]ibase\f[R] (i.e., they are greater than or equal to the current
+value of \f[B]ibase\f[R]), then the behavior depends on the existence of
+the \f[B]-c\f[R]/\f[B]--digit-clamp\f[R] or
+\f[B]-C\f[R]/\f[B]--no-digit-clamp\f[R] options (see the
+\f[B]OPTIONS\f[R] section), the existence and setting of the
+\f[B]DC_DIGIT_CLAMP\f[R] environment variable (see the \f[B]ENVIRONMENT
+VARIABLES\f[R] section), or the default, which can be queried with the
+\f[B]-h\f[R]/\f[B]--help\f[R] option.
+.PP
+If clamping is off, then digits or letters that are greater than or
+equal to the current value of \f[B]ibase\f[R] are not changed.
+Instead, their given value is multiplied by the appropriate power of
+\f[B]ibase\f[R] and added into the number.
+This means that, with an \f[B]ibase\f[R] of \f[B]3\f[R], the number
+\f[B]AB\f[R] is equal to \f[B]3\[ha]1*A+3\[ha]0*B\f[R], which is
+\f[B]3\f[R] times \f[B]10\f[R] plus \f[B]11\f[R], or \f[B]41\f[R].
+.PP
+If clamping is on, then digits or letters that are greater than or equal
+to the current value of \f[B]ibase\f[R] are set to the value of the
+highest valid digit in \f[B]ibase\f[R] before being multiplied by the
+appropriate power of \f[B]ibase\f[R] and added into the number.
+This means that, with an \f[B]ibase\f[R] of \f[B]3\f[R], the number
+\f[B]AB\f[R] is equal to \f[B]3\[ha]1*2+3\[ha]0*2\f[R], which is
+\f[B]3\f[R] times \f[B]2\f[R] plus \f[B]2\f[R], or \f[B]8\f[R].
+.PP
+There is one exception to clamping: single-character numbers (i.e.,
+\f[B]A\f[R] alone).
+Such numbers are never clamped and always take the value they would have
+in the highest possible \f[B]ibase\f[R].
This means that \f[B]A\f[R] alone always equals decimal \f[B]10\f[R] and
-\f[B]F\f[R] alone always equals decimal \f[B]15\f[R].
+\f[B]Z\f[R] alone always equals decimal \f[B]35\f[R].
+This behavior is mandated by the standard for bc(1) (see the STANDARDS
+section) and is meant to provide an easy way to set the current
+\f[B]ibase\f[R] (with the \f[B]i\f[R] command) regardless of the current
+value of \f[B]ibase\f[R].
+.PP
+If clamping is on, and the clamped value of a character is needed, use a
+leading zero, i.e., for \f[B]A\f[R], use \f[B]0A\f[R].
.PP
In addition, dc(1) accepts numbers in scientific notation.
These have the form \f[B]<number>e<integer>\f[R].
@@ -1298,7 +1374,8 @@ at which they become a problem.
In fact, memory should be exhausted before these limits should be hit.
.SH ENVIRONMENT VARIABLES
.PP
-dc(1) recognizes the following environment variables:
+As \f[B]non-portable extensions\f[R], dc(1) recognizes the following
+environment variables:
.TP
\f[B]DC_ENV_ARGS\f[R]
This is another way to give command-line arguments to dc(1).
@@ -1402,6 +1479,22 @@ expressions and expression files, and a zero value makes dc(1) not exit.
This environment variable overrides the default, which can be queried
with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
.RE
+.TP
+\f[B]DC_DIGIT_CLAMP\f[R]
+When parsing numbers and if this environment variable exists and
+contains an integer, a non-zero value makes dc(1) clamp digits that are
+greater than or equal to the current \f[B]ibase\f[R] so that all such
+digits are considered equal to the \f[B]ibase\f[R] minus 1, and a zero
+value disables such clamping so that those digits are always equal to
+their value, which is multiplied by the power of the \f[B]ibase\f[R].
+.RS
+.PP
+This never applies to single-digit numbers, as per the bc(1) standard
+(see the \f[B]STANDARDS\f[R] section).
+.PP
+This environment variable overrides the default, which can be queried
+with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
+.RE
.SH EXIT STATUS
.PP
dc(1) returns the following exit statuses:
@@ -1505,10 +1598,9 @@ The default setting can be queried with the \f[B]-h\f[R] or
\f[B]--help\f[R] options.
.PP
TTY mode is different from interactive mode because interactive mode is
-required in the bc(1) specification at
-https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html , and
-interactive mode requires only \f[B]stdin\f[R] and \f[B]stdout\f[R] to
-be connected to a terminal.
+required in the bc(1) specification (see the \f[B]STANDARDS\f[R]
+section), and interactive mode requires only \f[B]stdin\f[R] and
+\f[B]stdout\f[R] to be connected to a terminal.
.SS Command-Line History
.PP
Command-line history is only enabled if TTY mode is, i.e., that
@@ -1597,10 +1689,10 @@ locales and thus, supports \f[B]LC_MESSAGES\f[R].
bc(1)
.SH STANDARDS
.PP
-The dc(1) utility operators are compliant with the operators in the IEEE
-Std 1003.1-2017 (\[lq]POSIX.1-2017\[rq]) specification at
-https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html for
-bc(1).
+The dc(1) utility operators and some behavior are compliant with the
+operators in the IEEE Std 1003.1-2017 (\[lq]POSIX.1-2017\[rq]) bc(1)
+specification at
+https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html .
.SH BUGS
.PP
None are known.
diff --git a/manuals/dc/A.1.md b/manuals/dc/A.1.md
index f678c5f5a869..0b781da0daf5 100644
--- a/manuals/dc/A.1.md
+++ b/manuals/dc/A.1.md
@@ -34,7 +34,7 @@ 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*...] [**-I** *ibase*] [**-\-ibase**=*ibase*] [**-O** *obase*] [**-\-obase**=*obase*] [**-S** *scale*] [**-\-scale**=*scale*] [**-E** *seed*] [**-\-seed**=*seed*]
+**dc** [**-cChiPRvVx**] [**-\-version**] [**-\-help**] [**-\-digit-clamp**] [**-\-no-digit-clamp**] [**-\-interactive**] [**-\-no-prompt**] [**-\-no-read-prompt**] [**-\-extended-register**] [**-e** *expr*] [**-\-expression**=*expr*...] [**-f** *file*...] [**-\-file**=*file*...] [*file*...] [**-I** *ibase*] [**-\-ibase**=*ibase*] [**-O** *obase*] [**-\-obase**=*obase*] [**-S** *scale*] [**-\-scale**=*scale*] [**-E** *seed*] [**-\-seed**=*seed*]
# DESCRIPTION
@@ -55,73 +55,49 @@ this dc(1) will always start with a **scale** of **10**.
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).
+**-C**, **-\-no-digit-clamp**
- This is a **non-portable extension**.
+: Disables clamping of digits greater than or equal to the current **ibase**
+ when parsing numbers.
-**-P**, **-\-no-prompt**
+ This means that the value added to a number from a digit is always that
+ digit's value multiplied by the value of ibase raised to the power of the
+ digit's position, which starts from 0 at the least significant digit.
-: 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**.
+ If this and/or the **-c** or **-\-digit-clamp** options are given multiple
+ times, the last one given is used.
- These options override the **DC_PROMPT** and **DC_TTY_MODE** environment
- variables (see the **ENVIRONMENT VARIABLES** section).
+ This option overrides the **DC_DIGIT_CLAMP** environment variable (see the
+ **ENVIRONMENT VARIABLES** section) and the default, which can be queried
+ with the **-h** or **-\-help** options.
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.
+**-c**, **-\-digit-clamp**
- These options *do* override the **DC_PROMPT** and **DC_TTY_MODE**
- environment variables (see the **ENVIRONMENT VARIABLES** section), but only
- for the read prompt.
+: Enables clamping of digits greater than or equal to the current **ibase**
+ when parsing numbers.
- This is a **non-portable extension**.
+ This means that digits that the value added to a number from a digit that is
+ greater than or equal to the ibase is the value of ibase minus 1 all
+ multiplied by the value of ibase raised to the power of the digit's
+ position, which starts from 0 at the least significant digit.
-**-x** **-\-extended-register**
+ If this and/or the **-C** or **-\-no-digit-clamp** options are given
+ multiple times, the last one given is used.
-: Enables extended register mode. See the *Extended Register Mode* subsection
- of the **REGISTERS** section for more information.
+ This option overrides the **DC_DIGIT_CLAMP** environment variable (see the
+ **ENVIRONMENT VARIABLES** section) and the default, which can be queried
+ with the **-h** or **-\-help** options.
This is a **non-portable extension**.
-**-z**, **-\-leading-zeroes**
+**-E** *seed*, **-\-seed**=*seed*
-: Makes dc(1) print all numbers greater than **-1** and less than **1**, and
- not equal to **0**, with a leading zero.
+: Sets the builtin variable **seed** to the value *seed* assuming that *seed*
+ is in base 10. It is a fatal error if *seed* is not a valid number.
- 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).
+ If multiple instances of this option are given, the last is used.
This is a **non-portable extension**.
@@ -157,6 +133,10 @@ The following are the options that dc(1) accepts.
This is a **non-portable extension**.
+**-h**, **-\-help**
+
+: Prints a usage message and exits.
+
**-I** *ibase*, **-\-ibase**=*ibase*
: Sets the builtin variable **ibase** to the value *ibase* assuming that
@@ -166,6 +146,20 @@ The following are the options that dc(1) accepts.
This is a **non-portable extension**.
+**-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**.
+
**-O** *obase*, **-\-obase**=*obase*
: Sets the builtin variable **obase** to the value *obase* assuming that
@@ -175,6 +169,36 @@ The following are the options that dc(1) accepts.
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**.
+
**-S** *scale*, **-\-scale**=*scale*
: Sets the builtin variable **scale** to the value *scale* assuming that
@@ -184,12 +208,25 @@ The following are the options that dc(1) accepts.
This is a **non-portable extension**.
-**-E** *seed*, **-\-seed**=*seed*
+**-v**, **-V**, **-\-version**
-: Sets the builtin variable **seed** to the value *seed* assuming that *seed*
- is in base 10. It is a fatal error if *seed* is not a valid number.
+: Print the version information (copyright header) and exits.
- If multiple instances of this option are given, the last is used.
+**-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 dc(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**.
@@ -302,15 +339,40 @@ Comments go from **#** until, and not including, the next newline. This is a
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**.
+Uppercase letters are equal to **9** plus 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** (i.e.,
+they are greater than or equal to the current value of **ibase**), then the
+behavior depends on the existence of the **-c**/**-\-digit-clamp** or
+**-C**/**-\-no-digit-clamp** options (see the **OPTIONS** section), the
+existence and setting of the **DC_DIGIT_CLAMP** environment variable (see the
+**ENVIRONMENT VARIABLES** section), or the default, which can be queried with
+the **-h**/**-\-help** option.
+
+If clamping is off, then digits or letters that are greater than or equal to the
+current value of **ibase** are not changed. Instead, their given value is
+multiplied by the appropriate power of **ibase** and added into the number. This
+means that, with an **ibase** of **3**, the number **AB** is equal to
+**3\^1\*A+3\^0\*B**, which is **3** times **10** plus **11**, or **41**.
+
+If clamping is on, then digits or letters that are greater than or equal to the
+current value of **ibase** are set to the value of the highest valid digit in
+**ibase** before being multiplied by the appropriate power of **ibase** and
+added into the number. This means that, with an **ibase** of **3**, the number
+**AB** is equal to **3\^1\*2+3\^0\*2**, which is **3** times **2** plus **2**,
+or **8**.
+
+There is one exception to clamping: single-character numbers (i.e., **A**
+alone). Such numbers are never clamped and always take the value they would have
+in the highest possible **ibase**. This means that **A** alone always equals
+decimal **10** and **Z** alone always equals decimal **35**. This behavior is
+mandated by the standard for bc(1) (see the STANDARDS section) and is meant to
+provide an easy way to set the current **ibase** (with the **i** command)
+regardless of the current value of **ibase**.
+
+If clamping is on, and the clamped value of a character is needed, use a leading
+zero, i.e., for **A**, use **0A**.
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
@@ -1148,7 +1210,8 @@ be hit.
# ENVIRONMENT VARIABLES
-dc(1) recognizes the following environment variables:
+As **non-portable extensions**, dc(1) recognizes the following environment
+variables:
**DC_ENV_ARGS**
@@ -1237,6 +1300,21 @@ dc(1) recognizes the following environment variables:
This environment variable overrides the default, which can be queried with
the **-h** or **-\-help** options.
+**DC_DIGIT_CLAMP**
+
+: When parsing numbers and if this environment variable exists and contains an
+ integer, a non-zero value makes dc(1) clamp digits that are greater than or
+ equal to the current **ibase** so that all such digits are considered equal
+ to the **ibase** minus 1, and a zero value disables such clamping so that
+ those digits are always equal to their value, which is multiplied by the
+ power of the **ibase**.
+
+ This never applies to single-digit numbers, as per the bc(1) standard (see
+ the **STANDARDS** section).
+
+ 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:
@@ -1333,10 +1411,8 @@ 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 at
-https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html , and
-interactive mode requires only **stdin** and **stdout** to be connected to a
-terminal.
+in the bc(1) specification (see the **STANDARDS** section), and interactive mode
+requires only **stdin** and **stdout** to be connected to a terminal.
## Command-Line History
@@ -1419,9 +1495,9 @@ bc(1)
# STANDARDS
-The dc(1) utility operators are compliant with the operators in the IEEE Std
-1003.1-2017 (“POSIX.1-2017”) specification at
-https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html for bc(1).
+The dc(1) utility operators and some behavior are compliant with the operators
+in the IEEE Std 1003.1-2017 (“POSIX.1-2017”) bc(1) specification at
+https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html .
# BUGS
diff --git a/manuals/dc/E.1 b/manuals/dc/E.1
index 7f90beac6b1c..525bfe41feaa 100644
--- a/manuals/dc/E.1
+++ b/manuals/dc/E.1
@@ -25,7 +25,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.TH "DC" "1" "June 2022" "Gavin D. Howard" "General Commands Manual"
+.TH "DC" "1" "August 2022" "Gavin D. Howard" "General Commands Manual"
.nh
.ad l
.SH Name
@@ -33,12 +33,14 @@
dc - arbitrary-precision decimal reverse-Polish notation calculator
.SH SYNOPSIS
.PP
-\f[B]dc\f[R] [\f[B]-hiPRvVx\f[R]] [\f[B]--version\f[R]]
-[\f[B]--help\f[R]] [\f[B]--interactive\f[R]] [\f[B]--no-prompt\f[R]]
-[\f[B]--no-read-prompt\f[R]] [\f[B]--extended-register\f[R]]
-[\f[B]-e\f[R] \f[I]expr\f[R]]
-[\f[B]--expression\f[R]=\f[I]expr\f[R]\&...] [\f[B]-f\f[R]
-\f[I]file\f[R]\&...] [\f[B]--file\f[R]=\f[I]file\f[R]\&...]
+\f[B]dc\f[R] [\f[B]-cChiPRvVx\f[R]] [\f[B]--version\f[R]]
+[\f[B]--help\f[R]] [\f[B]--digit-clamp\f[R]]
+[\f[B]--no-digit-clamp\f[R]] [\f[B]--interactive\f[R]]
+[\f[B]--no-prompt\f[R]] [\f[B]--no-read-prompt\f[R]]
+[\f[B]--extended-register\f[R]] [\f[B]-e\f[R] \f[I]expr\f[R]]
+[\f[B]--expression\f[R]=\f[I]expr\f[R]\&...]
+[\f[B]-f\f[R] \f[I]file\f[R]\&...]
+[\f[B]--file\f[R]=\f[I]file\f[R]\&...]
[\f[I]file\f[R]\&...]
.SH DESCRIPTION
.PP
@@ -61,83 +63,43 @@ and this dc(1) will always start with a \f[B]scale\f[R] of \f[B]10\f[R].
.PP
The following are the options that dc(1) accepts.
.TP
-\f[B]-h\f[R], \f[B]--help\f[R]
-Prints a usage message and quits.
-.TP
-\f[B]-v\f[R], \f[B]-V\f[R], \f[B]--version\f[R]
-Print the version information (copyright header) and exit.
-.TP
-\f[B]-i\f[R], \f[B]--interactive\f[R]
-Forces interactive mode.
-(See the \f[B]INTERACTIVE MODE\f[R] section.)
+\f[B]-C\f[R], \f[B]--no-digit-clamp\f[R]
+Disables clamping of digits greater than or equal to the current
+\f[B]ibase\f[R] when parsing numbers.
.RS
.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
-.TP
-\f[B]-L\f[R], \f[B]--no-line-length\f[R]
-Disables line length checking and prints numbers without backslashes and
-newlines.
-In other words, this option sets \f[B]BC_LINE_LENGTH\f[R] to \f[B]0\f[R]
-(see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
-.RS
+This means that the value added to a number from a digit is always that
+digit\[cq]s value multiplied by the value of ibase raised to the power
+of the digit\[cq]s position, which starts from 0 at the least
+significant digit.
.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
-.TP
-\f[B]-P\f[R], \f[B]--no-prompt\f[R]
-Disables the prompt in TTY mode.
-(The prompt is only enabled in TTY mode.
-See the \f[B]TTY MODE\f[R] 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
-\f[B]DC_ENV_ARGS\f[R].
-.RS
+If this and/or the \f[B]-c\f[R] or \f[B]--digit-clamp\f[R] options are
+given multiple times, the last one given is used.
.PP
-These options override the \f[B]DC_PROMPT\f[R] and \f[B]DC_TTY_MODE\f[R]
-environment variables (see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
+This option overrides the \f[B]DC_DIGIT_CLAMP\f[R] environment variable
+(see the \f[B]ENVIRONMENT VARIABLES\f[R] section) and the default, which
+can be queried with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
.PP
This is a \f[B]non-portable extension\f[R].
.RE
.TP
-\f[B]-R\f[R], \f[B]--no-read-prompt\f[R]
-Disables the read prompt in TTY mode.
-(The read prompt is only enabled in TTY mode.
-See the \f[B]TTY MODE\f[R] 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
-\f[B]BC_ENV_ARGS\f[R] (see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
-This option is also useful in hash bang lines of dc(1) scripts that
-prompt for user input.
+\f[B]-c\f[R], \f[B]--digit-clamp\f[R]
+Enables clamping of digits greater than or equal to the current
+\f[B]ibase\f[R] when parsing numbers.
.RS
.PP
-This option does not disable the regular prompt because the read prompt
-is only used when the \f[B]?\f[R] command is used.
-.PP
-These options \f[I]do\f[R] override the \f[B]DC_PROMPT\f[R] and
-\f[B]DC_TTY_MODE\f[R] environment variables (see the \f[B]ENVIRONMENT
-VARIABLES\f[R] section), but only for the read prompt.
-.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
-.TP
-\f[B]-x\f[R] \f[B]--extended-register\f[R]
-Enables extended register mode.
-See the \f[I]Extended Register Mode\f[R] subsection of the
-\f[B]REGISTERS\f[R] section for more information.
-.RS
+This means that digits that the value added to a number from a digit
+that is greater than or equal to the ibase is the value of ibase minus 1
+all multiplied by the value of ibase raised to the power of the
+digit\[cq]s position, which starts from 0 at the least significant
+digit.
.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
-.TP
-\f[B]-z\f[R], \f[B]--leading-zeroes\f[R]
-Makes dc(1) print all numbers greater than \f[B]-1\f[R] and less than
-\f[B]1\f[R], and not equal to \f[B]0\f[R], with a leading zero.
-.RS
+If this and/or the \f[B]-C\f[R] or \f[B]--no-digit-clamp\f[R] options
+are given multiple times, the last one given is used.
.PP
-This can be set for individual numbers with the \f[B]plz(x)\f[R],
-plznl(x)**, \f[B]pnlz(x)\f[R], and \f[B]pnlznl(x)\f[R] functions in the
-extended math library (see the \f[B]LIBRARY\f[R] section).
+This option overrides the \f[B]DC_DIGIT_CLAMP\f[R] environment variable
+(see the \f[B]ENVIRONMENT VARIABLES\f[R] section) and the default, which
+can be queried with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
.PP
This is a \f[B]non-portable extension\f[R].
.RE
@@ -185,6 +147,9 @@ exit.
This is a \f[B]non-portable extension\f[R].
.RE
.TP
+\f[B]-h\f[R], \f[B]--help\f[R]
+Prints a usage message and exits.
+.TP
\f[B]-I\f[R] \f[I]ibase\f[R], \f[B]--ibase\f[R]=\f[I]ibase\f[R]
Sets the builtin variable \f[B]ibase\f[R] to the value \f[I]ibase\f[R]
assuming that \f[I]ibase\f[R] is in base 10.
@@ -196,6 +161,24 @@ If multiple instances of this option are given, the last is used.
This is a \f[B]non-portable extension\f[R].
.RE
.TP
+\f[B]-i\f[R], \f[B]--interactive\f[R]
+Forces interactive mode.
+(See the \f[B]INTERACTIVE MODE\f[R] section.)
+.RS
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
+\f[B]-L\f[R], \f[B]--no-line-length\f[R]
+Disables line length checking and prints numbers without backslashes and
+newlines.
+In other words, this option sets \f[B]BC_LINE_LENGTH\f[R] to \f[B]0\f[R]
+(see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
+.RS
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
\f[B]-O\f[R] \f[I]obase\f[R], \f[B]--obase\f[R]=\f[I]obase\f[R]
Sets the builtin variable \f[B]obase\f[R] to the value \f[I]obase\f[R]
assuming that \f[I]obase\f[R] is in base 10.
@@ -207,6 +190,44 @@ If multiple instances of this option are given, the last is used.
This is a \f[B]non-portable extension\f[R].
.RE
.TP
+\f[B]-P\f[R], \f[B]--no-prompt\f[R]
+Disables the prompt in TTY mode.
+(The prompt is only enabled in TTY mode.
+See the \f[B]TTY MODE\f[R] 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
+\f[B]DC_ENV_ARGS\f[R].
+.RS
+.PP
+These options override the \f[B]DC_PROMPT\f[R] and \f[B]DC_TTY_MODE\f[R]
+environment variables (see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
+\f[B]-R\f[R], \f[B]--no-read-prompt\f[R]
+Disables the read prompt in TTY mode.
+(The read prompt is only enabled in TTY mode.
+See the \f[B]TTY MODE\f[R] 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
+\f[B]BC_ENV_ARGS\f[R] (see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
+This option is also useful in hash bang lines of dc(1) scripts that
+prompt for user input.
+.RS
+.PP
+This option does not disable the regular prompt because the read prompt
+is only used when the \f[B]?\f[R] command is used.
+.PP
+These options \f[I]do\f[R] override the \f[B]DC_PROMPT\f[R] and
+\f[B]DC_TTY_MODE\f[R] environment variables (see the \f[B]ENVIRONMENT
+VARIABLES\f[R] section), but only for the read prompt.
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
\f[B]-S\f[R] \f[I]scale\f[R], \f[B]--scale\f[R]=\f[I]scale\f[R]
Sets the builtin variable \f[B]scale\f[R] to the value \f[I]scale\f[R]
assuming that \f[I]scale\f[R] is in base 10.
@@ -217,6 +238,30 @@ If multiple instances of this option are given, the last is used.
.PP
This is a \f[B]non-portable extension\f[R].
.RE
+.TP
+\f[B]-v\f[R], \f[B]-V\f[R], \f[B]--version\f[R]
+Print the version information (copyright header) and exits.
+.TP
+\f[B]-x\f[R] \f[B]--extended-register\f[R]
+Enables extended register mode.
+See the \f[I]Extended Register Mode\f[R] subsection of the
+\f[B]REGISTERS\f[R] section for more information.
+.RS
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
+\f[B]-z\f[R], \f[B]--leading-zeroes\f[R]
+Makes dc(1) print all numbers greater than \f[B]-1\f[R] and less than
+\f[B]1\f[R], and not equal to \f[B]0\f[R], with a leading zero.
+.RS
+.PP
+This can be set for individual numbers with the \f[B]plz(x)\f[R],
+plznl(x)**, \f[B]pnlz(x)\f[R], and \f[B]pnlznl(x)\f[R] functions in the
+extended math library (see the \f[B]LIBRARY\f[R] section).
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
.PP
All long options are \f[B]non-portable extensions\f[R].
.SH STDIN
@@ -307,17 +352,48 @@ This is a \f[B]non-portable extension\f[R].
Numbers are strings made up of digits, uppercase letters up to
\f[B]F\f[R], and at most \f[B]1\f[R] period for a radix.
Numbers can have up to \f[B]DC_NUM_MAX\f[R] digits.
-Uppercase letters are equal to \f[B]9\f[R] + their position in the
+Uppercase letters are equal to \f[B]9\f[R] plus their position in the
alphabet (i.e., \f[B]A\f[R] equals \f[B]10\f[R], or \f[B]9+1\f[R]).
-If a digit or letter makes no sense with the current value of
-\f[B]ibase\f[R], they are set to the value of the highest valid digit in
-\f[B]ibase\f[R].
.PP
-Single-character numbers (i.e., \f[B]A\f[R] alone) take the value that
-they would have if they were valid digits, regardless of the value of
-\f[B]ibase\f[R].
+If a digit or letter makes no sense with the current value of
+\f[B]ibase\f[R] (i.e., they are greater than or equal to the current
+value of \f[B]ibase\f[R]), then the behavior depends on the existence of
+the \f[B]-c\f[R]/\f[B]--digit-clamp\f[R] or
+\f[B]-C\f[R]/\f[B]--no-digit-clamp\f[R] options (see the
+\f[B]OPTIONS\f[R] section), the existence and setting of the
+\f[B]DC_DIGIT_CLAMP\f[R] environment variable (see the \f[B]ENVIRONMENT
+VARIABLES\f[R] section), or the default, which can be queried with the
+\f[B]-h\f[R]/\f[B]--help\f[R] option.
+.PP
+If clamping is off, then digits or letters that are greater than or
+equal to the current value of \f[B]ibase\f[R] are not changed.
+Instead, their given value is multiplied by the appropriate power of
+\f[B]ibase\f[R] and added into the number.
+This means that, with an \f[B]ibase\f[R] of \f[B]3\f[R], the number
+\f[B]AB\f[R] is equal to \f[B]3\[ha]1*A+3\[ha]0*B\f[R], which is
+\f[B]3\f[R] times \f[B]10\f[R] plus \f[B]11\f[R], or \f[B]41\f[R].
+.PP
+If clamping is on, then digits or letters that are greater than or equal
+to the current value of \f[B]ibase\f[R] are set to the value of the
+highest valid digit in \f[B]ibase\f[R] before being multiplied by the
+appropriate power of \f[B]ibase\f[R] and added into the number.
+This means that, with an \f[B]ibase\f[R] of \f[B]3\f[R], the number
+\f[B]AB\f[R] is equal to \f[B]3\[ha]1*2+3\[ha]0*2\f[R], which is
+\f[B]3\f[R] times \f[B]2\f[R] plus \f[B]2\f[R], or \f[B]8\f[R].
+.PP
+There is one exception to clamping: single-character numbers (i.e.,
+\f[B]A\f[R] alone).
+Such numbers are never clamped and always take the value they would have
+in the highest possible \f[B]ibase\f[R].
This means that \f[B]A\f[R] alone always equals decimal \f[B]10\f[R] and
-\f[B]F\f[R] alone always equals decimal \f[B]15\f[R].
+\f[B]Z\f[R] alone always equals decimal \f[B]35\f[R].
+This behavior is mandated by the standard for bc(1) (see the STANDARDS
+section) and is meant to provide an easy way to set the current
+\f[B]ibase\f[R] (with the \f[B]i\f[R] command) regardless of the current
+value of \f[B]ibase\f[R].
+.PP
+If clamping is on, and the clamped value of a character is needed, use a
+leading zero, i.e., for \f[B]A\f[R], use \f[B]0A\f[R].
.SH COMMANDS
.PP
The valid commands are listed below.
@@ -1078,7 +1154,8 @@ at which they become a problem.
In fact, memory should be exhausted before these limits should be hit.
.SH ENVIRONMENT VARIABLES
.PP
-dc(1) recognizes the following environment variables:
+As \f[B]non-portable extensions\f[R], dc(1) recognizes the following
+environment variables:
.TP
\f[B]DC_ENV_ARGS\f[R]
This is another way to give command-line arguments to dc(1).
@@ -1182,6 +1259,22 @@ expressions and expression files, and a zero value makes dc(1) not exit.
This environment variable overrides the default, which can be queried
with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
.RE
+.TP
+\f[B]DC_DIGIT_CLAMP\f[R]
+When parsing numbers and if this environment variable exists and
+contains an integer, a non-zero value makes dc(1) clamp digits that are
+greater than or equal to the current \f[B]ibase\f[R] so that all such
+digits are considered equal to the \f[B]ibase\f[R] minus 1, and a zero
+value disables such clamping so that those digits are always equal to
+their value, which is multiplied by the power of the \f[B]ibase\f[R].
+.RS
+.PP
+This never applies to single-digit numbers, as per the bc(1) standard
+(see the \f[B]STANDARDS\f[R] section).
+.PP
+This environment variable overrides the default, which can be queried
+with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
+.RE
.SH EXIT STATUS
.PP
dc(1) returns the following exit statuses:
@@ -1283,10 +1376,9 @@ The default setting can be queried with the \f[B]-h\f[R] or
\f[B]--help\f[R] options.
.PP
TTY mode is different from interactive mode because interactive mode is
-required in the bc(1) specification at
-https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html , and
-interactive mode requires only \f[B]stdin\f[R] and \f[B]stdout\f[R] to
-be connected to a terminal.
+required in the bc(1) specification (see the \f[B]STANDARDS\f[R]
+section), and interactive mode requires only \f[B]stdin\f[R] and
+\f[B]stdout\f[R] to be connected to a terminal.
.SS Command-Line History
.PP
Command-line history is only enabled if TTY mode is, i.e., that
@@ -1375,10 +1467,10 @@ locales and thus, supports \f[B]LC_MESSAGES\f[R].
bc(1)
.SH STANDARDS
.PP
-The dc(1) utility operators are compliant with the operators in the IEEE
-Std 1003.1-2017 (\[lq]POSIX.1-2017\[rq]) specification at
-https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html for
-bc(1).
+The dc(1) utility operators and some behavior are compliant with the
+operators in the IEEE Std 1003.1-2017 (\[lq]POSIX.1-2017\[rq]) bc(1)
+specification at
+https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html .
.SH BUGS
.PP
None are known.
diff --git a/manuals/dc/E.1.md b/manuals/dc/E.1.md
index f854cbba874b..ac83e63bac7d 100644
--- a/manuals/dc/E.1.md
+++ b/manuals/dc/E.1.md
@@ -34,7 +34,7 @@ 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*...]
+**dc** [**-cChiPRvVx**] [**-\-version**] [**-\-help**] [**-\-digit-clamp**] [**-\-no-digit-clamp**] [**-\-interactive**] [**-\-no-prompt**] [**-\-no-read-prompt**] [**-\-extended-register**] [**-e** *expr*] [**-\-expression**=*expr*...] [**-f** *file*...] [**-\-file**=*file*...] [*file*...]
# DESCRIPTION
@@ -55,73 +55,40 @@ this dc(1) will always start with a **scale** of **10**.
The following are the options that dc(1) accepts.
-**-h**, **-\-help**
+**-C**, **-\-no-digit-clamp**
-: Prints a usage message and quits.
+: Disables clamping of digits greater than or equal to the current **ibase**
+ when parsing numbers.
-**-v**, **-V**, **-\-version**
+ This means that the value added to a number from a digit is always that
+ digit's value multiplied by the value of ibase raised to the power of the
+ digit's position, which starts from 0 at the least significant digit.
-: Print the version information (copyright header) and exit.
+ If this and/or the **-c** or **-\-digit-clamp** options are given multiple
+ times, the last one given is used.
-**-i**, **-\-interactive**
-
-: Forces interactive mode. (See the **INTERACTIVE MODE** section.)
+ This option overrides the **DC_DIGIT_CLAMP** environment variable (see the
+ **ENVIRONMENT VARIABLES** section) and the default, which can be queried
+ with the **-h** or **-\-help** options.
This is a **non-portable extension**.
-**-L**, **-\-no-line-length**
+**-c**, **-\-digit-clamp**
-: 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).
+: Enables clamping of digits greater than or equal to the current **ibase**
+ when parsing numbers.
- This is a **non-portable extension**.
+ This means that digits that the value added to a number from a digit that is
+ greater than or equal to the ibase is the value of ibase minus 1 all
+ multiplied by the value of ibase raised to the power of the digit's
+ position, which starts from 0 at the least significant digit.
-**-P**, **-\-no-prompt**
+ If this and/or the **-C** or **-\-no-digit-clamp** options are given
+ multiple times, the last one given is used.
-: 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 dc(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 option overrides the **DC_DIGIT_CLAMP** environment variable (see the
+ **ENVIRONMENT VARIABLES** section) and the default, which can be queried
+ with the **-h** or **-\-help** options.
This is a **non-portable extension**.
@@ -157,6 +124,10 @@ The following are the options that dc(1) accepts.
This is a **non-portable extension**.
+**-h**, **-\-help**
+
+: Prints a usage message and exits.
+
**-I** *ibase*, **-\-ibase**=*ibase*
: Sets the builtin variable **ibase** to the value *ibase* assuming that
@@ -166,6 +137,20 @@ The following are the options that dc(1) accepts.
This is a **non-portable extension**.
+**-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**.
+
**-O** *obase*, **-\-obase**=*obase*
: Sets the builtin variable **obase** to the value *obase* assuming that
@@ -175,6 +160,36 @@ The following are the options that dc(1) accepts.
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**.
+
**-S** *scale*, **-\-scale**=*scale*
: Sets the builtin variable **scale** to the value *scale* assuming that
@@ -184,6 +199,28 @@ The following are the options that dc(1) accepts.
This is a **non-portable extension**.
+**-v**, **-V**, **-\-version**
+
+: Print the version information (copyright header) and exits.
+
+**-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 dc(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**.
+
All long options are **non-portable extensions**.
# STDIN
@@ -263,15 +300,40 @@ Comments go from **#** until, and not including, the next newline. This is a
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**.
+Uppercase letters are equal to **9** plus 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** (i.e.,
+they are greater than or equal to the current value of **ibase**), then the
+behavior depends on the existence of the **-c**/**-\-digit-clamp** or
+**-C**/**-\-no-digit-clamp** options (see the **OPTIONS** section), the
+existence and setting of the **DC_DIGIT_CLAMP** environment variable (see the
+**ENVIRONMENT VARIABLES** section), or the default, which can be queried with
+the **-h**/**-\-help** option.
+
+If clamping is off, then digits or letters that are greater than or equal to the
+current value of **ibase** are not changed. Instead, their given value is
+multiplied by the appropriate power of **ibase** and added into the number. This
+means that, with an **ibase** of **3**, the number **AB** is equal to
+**3\^1\*A+3\^0\*B**, which is **3** times **10** plus **11**, or **41**.
+
+If clamping is on, then digits or letters that are greater than or equal to the
+current value of **ibase** are set to the value of the highest valid digit in
+**ibase** before being multiplied by the appropriate power of **ibase** and
+added into the number. This means that, with an **ibase** of **3**, the number
+**AB** is equal to **3\^1\*2+3\^0\*2**, which is **3** times **2** plus **2**,
+or **8**.
+
+There is one exception to clamping: single-character numbers (i.e., **A**
+alone). Such numbers are never clamped and always take the value they would have
+in the highest possible **ibase**. This means that **A** alone always equals
+decimal **10** and **Z** alone always equals decimal **35**. This behavior is
+mandated by the standard for bc(1) (see the STANDARDS section) and is meant to
+provide an easy way to set the current **ibase** (with the **i** command)
+regardless of the current value of **ibase**.
+
+If clamping is on, and the clamped value of a character is needed, use a leading
+zero, i.e., for **A**, use **0A**.
# COMMANDS
@@ -974,7 +1036,8 @@ be hit.
# ENVIRONMENT VARIABLES
-dc(1) recognizes the following environment variables:
+As **non-portable extensions**, dc(1) recognizes the following environment
+variables:
**DC_ENV_ARGS**
@@ -1063,6 +1126,21 @@ dc(1) recognizes the following environment variables:
This environment variable overrides the default, which can be queried with
the **-h** or **-\-help** options.
+**DC_DIGIT_CLAMP**
+
+: When parsing numbers and if this environment variable exists and contains an
+ integer, a non-zero value makes dc(1) clamp digits that are greater than or
+ equal to the current **ibase** so that all such digits are considered equal
+ to the **ibase** minus 1, and a zero value disables such clamping so that
+ those digits are always equal to their value, which is multiplied by the
+ power of the **ibase**.
+
+ This never applies to single-digit numbers, as per the bc(1) standard (see
+ the **STANDARDS** section).
+
+ 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:
@@ -1157,10 +1235,8 @@ 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 at
-https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html , and
-interactive mode requires only **stdin** and **stdout** to be connected to a
-terminal.
+in the bc(1) specification (see the **STANDARDS** section), and interactive mode
+requires only **stdin** and **stdout** to be connected to a terminal.
## Command-Line History
@@ -1243,9 +1319,9 @@ bc(1)
# STANDARDS
-The dc(1) utility operators are compliant with the operators in the IEEE Std
-1003.1-2017 (“POSIX.1-2017”) specification at
-https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html for bc(1).
+The dc(1) utility operators and some behavior are compliant with the operators
+in the IEEE Std 1003.1-2017 (“POSIX.1-2017”) bc(1) specification at
+https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html .
# BUGS
diff --git a/manuals/dc/EH.1 b/manuals/dc/EH.1
index 96cb156e789f..daad57d73dc6 100644
--- a/manuals/dc/EH.1
+++ b/manuals/dc/EH.1
@@ -25,7 +25,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.TH "DC" "1" "June 2022" "Gavin D. Howard" "General Commands Manual"
+.TH "DC" "1" "August 2022" "Gavin D. Howard" "General Commands Manual"
.nh
.ad l
.SH Name
@@ -33,12 +33,14 @@
dc - arbitrary-precision decimal reverse-Polish notation calculator
.SH SYNOPSIS
.PP
-\f[B]dc\f[R] [\f[B]-hiPRvVx\f[R]] [\f[B]--version\f[R]]
-[\f[B]--help\f[R]] [\f[B]--interactive\f[R]] [\f[B]--no-prompt\f[R]]
-[\f[B]--no-read-prompt\f[R]] [\f[B]--extended-register\f[R]]
-[\f[B]-e\f[R] \f[I]expr\f[R]]
-[\f[B]--expression\f[R]=\f[I]expr\f[R]\&...] [\f[B]-f\f[R]
-\f[I]file\f[R]\&...] [\f[B]--file\f[R]=\f[I]file\f[R]\&...]
+\f[B]dc\f[R] [\f[B]-cChiPRvVx\f[R]] [\f[B]--version\f[R]]
+[\f[B]--help\f[R]] [\f[B]--digit-clamp\f[R]]
+[\f[B]--no-digit-clamp\f[R]] [\f[B]--interactive\f[R]]
+[\f[B]--no-prompt\f[R]] [\f[B]--no-read-prompt\f[R]]
+[\f[B]--extended-register\f[R]] [\f[B]-e\f[R] \f[I]expr\f[R]]
+[\f[B]--expression\f[R]=\f[I]expr\f[R]\&...]
+[\f[B]-f\f[R] \f[I]file\f[R]\&...]
+[\f[B]--file\f[R]=\f[I]file\f[R]\&...]
[\f[I]file\f[R]\&...]
.SH DESCRIPTION
.PP
@@ -61,83 +63,43 @@ and this dc(1) will always start with a \f[B]scale\f[R] of \f[B]10\f[R].
.PP
The following are the options that dc(1) accepts.
.TP
-\f[B]-h\f[R], \f[B]--help\f[R]
-Prints a usage message and quits.
-.TP
-\f[B]-v\f[R], \f[B]-V\f[R], \f[B]--version\f[R]
-Print the version information (copyright header) and exit.
-.TP
-\f[B]-i\f[R], \f[B]--interactive\f[R]
-Forces interactive mode.
-(See the \f[B]INTERACTIVE MODE\f[R] section.)
+\f[B]-C\f[R], \f[B]--no-digit-clamp\f[R]
+Disables clamping of digits greater than or equal to the current
+\f[B]ibase\f[R] when parsing numbers.
.RS
.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
-.TP
-\f[B]-L\f[R], \f[B]--no-line-length\f[R]
-Disables line length checking and prints numbers without backslashes and
-newlines.
-In other words, this option sets \f[B]BC_LINE_LENGTH\f[R] to \f[B]0\f[R]
-(see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
-.RS
+This means that the value added to a number from a digit is always that
+digit\[cq]s value multiplied by the value of ibase raised to the power
+of the digit\[cq]s position, which starts from 0 at the least
+significant digit.
.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
-.TP
-\f[B]-P\f[R], \f[B]--no-prompt\f[R]
-Disables the prompt in TTY mode.
-(The prompt is only enabled in TTY mode.
-See the \f[B]TTY MODE\f[R] 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
-\f[B]DC_ENV_ARGS\f[R].
-.RS
+If this and/or the \f[B]-c\f[R] or \f[B]--digit-clamp\f[R] options are
+given multiple times, the last one given is used.
.PP
-These options override the \f[B]DC_PROMPT\f[R] and \f[B]DC_TTY_MODE\f[R]
-environment variables (see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
+This option overrides the \f[B]DC_DIGIT_CLAMP\f[R] environment variable
+(see the \f[B]ENVIRONMENT VARIABLES\f[R] section) and the default, which
+can be queried with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
.PP
This is a \f[B]non-portable extension\f[R].
.RE
.TP
-\f[B]-R\f[R], \f[B]--no-read-prompt\f[R]
-Disables the read prompt in TTY mode.
-(The read prompt is only enabled in TTY mode.
-See the \f[B]TTY MODE\f[R] 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
-\f[B]BC_ENV_ARGS\f[R] (see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
-This option is also useful in hash bang lines of dc(1) scripts that
-prompt for user input.
+\f[B]-c\f[R], \f[B]--digit-clamp\f[R]
+Enables clamping of digits greater than or equal to the current
+\f[B]ibase\f[R] when parsing numbers.
.RS
.PP
-This option does not disable the regular prompt because the read prompt
-is only used when the \f[B]?\f[R] command is used.
-.PP
-These options \f[I]do\f[R] override the \f[B]DC_PROMPT\f[R] and
-\f[B]DC_TTY_MODE\f[R] environment variables (see the \f[B]ENVIRONMENT
-VARIABLES\f[R] section), but only for the read prompt.
-.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
-.TP
-\f[B]-x\f[R] \f[B]--extended-register\f[R]
-Enables extended register mode.
-See the \f[I]Extended Register Mode\f[R] subsection of the
-\f[B]REGISTERS\f[R] section for more information.
-.RS
+This means that digits that the value added to a number from a digit
+that is greater than or equal to the ibase is the value of ibase minus 1
+all multiplied by the value of ibase raised to the power of the
+digit\[cq]s position, which starts from 0 at the least significant
+digit.
.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
-.TP
-\f[B]-z\f[R], \f[B]--leading-zeroes\f[R]
-Makes dc(1) print all numbers greater than \f[B]-1\f[R] and less than
-\f[B]1\f[R], and not equal to \f[B]0\f[R], with a leading zero.
-.RS
+If this and/or the \f[B]-C\f[R] or \f[B]--no-digit-clamp\f[R] options
+are given multiple times, the last one given is used.
.PP
-This can be set for individual numbers with the \f[B]plz(x)\f[R],
-plznl(x)**, \f[B]pnlz(x)\f[R], and \f[B]pnlznl(x)\f[R] functions in the
-extended math library (see the \f[B]LIBRARY\f[R] section).
+This option overrides the \f[B]DC_DIGIT_CLAMP\f[R] environment variable
+(see the \f[B]ENVIRONMENT VARIABLES\f[R] section) and the default, which
+can be queried with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
.PP
This is a \f[B]non-portable extension\f[R].
.RE
@@ -185,6 +147,9 @@ exit.
This is a \f[B]non-portable extension\f[R].
.RE
.TP
+\f[B]-h\f[R], \f[B]--help\f[R]
+Prints a usage message and exits.
+.TP
\f[B]-I\f[R] \f[I]ibase\f[R], \f[B]--ibase\f[R]=\f[I]ibase\f[R]
Sets the builtin variable \f[B]ibase\f[R] to the value \f[I]ibase\f[R]
assuming that \f[I]ibase\f[R] is in base 10.
@@ -196,6 +161,24 @@ If multiple instances of this option are given, the last is used.
This is a \f[B]non-portable extension\f[R].
.RE
.TP
+\f[B]-i\f[R], \f[B]--interactive\f[R]
+Forces interactive mode.
+(See the \f[B]INTERACTIVE MODE\f[R] section.)
+.RS
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
+\f[B]-L\f[R], \f[B]--no-line-length\f[R]
+Disables line length checking and prints numbers without backslashes and
+newlines.
+In other words, this option sets \f[B]BC_LINE_LENGTH\f[R] to \f[B]0\f[R]
+(see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
+.RS
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
\f[B]-O\f[R] \f[I]obase\f[R], \f[B]--obase\f[R]=\f[I]obase\f[R]
Sets the builtin variable \f[B]obase\f[R] to the value \f[I]obase\f[R]
assuming that \f[I]obase\f[R] is in base 10.
@@ -207,6 +190,44 @@ If multiple instances of this option are given, the last is used.
This is a \f[B]non-portable extension\f[R].
.RE
.TP
+\f[B]-P\f[R], \f[B]--no-prompt\f[R]
+Disables the prompt in TTY mode.
+(The prompt is only enabled in TTY mode.
+See the \f[B]TTY MODE\f[R] 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
+\f[B]DC_ENV_ARGS\f[R].
+.RS
+.PP
+These options override the \f[B]DC_PROMPT\f[R] and \f[B]DC_TTY_MODE\f[R]
+environment variables (see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
+\f[B]-R\f[R], \f[B]--no-read-prompt\f[R]
+Disables the read prompt in TTY mode.
+(The read prompt is only enabled in TTY mode.
+See the \f[B]TTY MODE\f[R] 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
+\f[B]BC_ENV_ARGS\f[R] (see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
+This option is also useful in hash bang lines of dc(1) scripts that
+prompt for user input.
+.RS
+.PP
+This option does not disable the regular prompt because the read prompt
+is only used when the \f[B]?\f[R] command is used.
+.PP
+These options \f[I]do\f[R] override the \f[B]DC_PROMPT\f[R] and
+\f[B]DC_TTY_MODE\f[R] environment variables (see the \f[B]ENVIRONMENT
+VARIABLES\f[R] section), but only for the read prompt.
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
\f[B]-S\f[R] \f[I]scale\f[R], \f[B]--scale\f[R]=\f[I]scale\f[R]
Sets the builtin variable \f[B]scale\f[R] to the value \f[I]scale\f[R]
assuming that \f[I]scale\f[R] is in base 10.
@@ -217,6 +238,30 @@ If multiple instances of this option are given, the last is used.
.PP
This is a \f[B]non-portable extension\f[R].
.RE
+.TP
+\f[B]-v\f[R], \f[B]-V\f[R], \f[B]--version\f[R]
+Print the version information (copyright header) and exits.
+.TP
+\f[B]-x\f[R] \f[B]--extended-register\f[R]
+Enables extended register mode.
+See the \f[I]Extended Register Mode\f[R] subsection of the
+\f[B]REGISTERS\f[R] section for more information.
+.RS
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
+\f[B]-z\f[R], \f[B]--leading-zeroes\f[R]
+Makes dc(1) print all numbers greater than \f[B]-1\f[R] and less than
+\f[B]1\f[R], and not equal to \f[B]0\f[R], with a leading zero.
+.RS
+.PP
+This can be set for individual numbers with the \f[B]plz(x)\f[R],
+plznl(x)**, \f[B]pnlz(x)\f[R], and \f[B]pnlznl(x)\f[R] functions in the
+extended math library (see the \f[B]LIBRARY\f[R] section).
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
.PP
All long options are \f[B]non-portable extensions\f[R].
.SH STDIN
@@ -307,17 +352,48 @@ This is a \f[B]non-portable extension\f[R].
Numbers are strings made up of digits, uppercase letters up to
\f[B]F\f[R], and at most \f[B]1\f[R] period for a radix.
Numbers can have up to \f[B]DC_NUM_MAX\f[R] digits.
-Uppercase letters are equal to \f[B]9\f[R] + their position in the
+Uppercase letters are equal to \f[B]9\f[R] plus their position in the
alphabet (i.e., \f[B]A\f[R] equals \f[B]10\f[R], or \f[B]9+1\f[R]).
-If a digit or letter makes no sense with the current value of
-\f[B]ibase\f[R], they are set to the value of the highest valid digit in
-\f[B]ibase\f[R].
.PP
-Single-character numbers (i.e., \f[B]A\f[R] alone) take the value that
-they would have if they were valid digits, regardless of the value of
-\f[B]ibase\f[R].
+If a digit or letter makes no sense with the current value of
+\f[B]ibase\f[R] (i.e., they are greater than or equal to the current
+value of \f[B]ibase\f[R]), then the behavior depends on the existence of
+the \f[B]-c\f[R]/\f[B]--digit-clamp\f[R] or
+\f[B]-C\f[R]/\f[B]--no-digit-clamp\f[R] options (see the
+\f[B]OPTIONS\f[R] section), the existence and setting of the
+\f[B]DC_DIGIT_CLAMP\f[R] environment variable (see the \f[B]ENVIRONMENT
+VARIABLES\f[R] section), or the default, which can be queried with the
+\f[B]-h\f[R]/\f[B]--help\f[R] option.
+.PP
+If clamping is off, then digits or letters that are greater than or
+equal to the current value of \f[B]ibase\f[R] are not changed.
+Instead, their given value is multiplied by the appropriate power of
+\f[B]ibase\f[R] and added into the number.
+This means that, with an \f[B]ibase\f[R] of \f[B]3\f[R], the number
+\f[B]AB\f[R] is equal to \f[B]3\[ha]1*A+3\[ha]0*B\f[R], which is
+\f[B]3\f[R] times \f[B]10\f[R] plus \f[B]11\f[R], or \f[B]41\f[R].
+.PP
+If clamping is on, then digits or letters that are greater than or equal
+to the current value of \f[B]ibase\f[R] are set to the value of the
+highest valid digit in \f[B]ibase\f[R] before being multiplied by the
+appropriate power of \f[B]ibase\f[R] and added into the number.
+This means that, with an \f[B]ibase\f[R] of \f[B]3\f[R], the number
+\f[B]AB\f[R] is equal to \f[B]3\[ha]1*2+3\[ha]0*2\f[R], which is
+\f[B]3\f[R] times \f[B]2\f[R] plus \f[B]2\f[R], or \f[B]8\f[R].
+.PP
+There is one exception to clamping: single-character numbers (i.e.,
+\f[B]A\f[R] alone).
+Such numbers are never clamped and always take the value they would have
+in the highest possible \f[B]ibase\f[R].
This means that \f[B]A\f[R] alone always equals decimal \f[B]10\f[R] and
-\f[B]F\f[R] alone always equals decimal \f[B]15\f[R].
+\f[B]Z\f[R] alone always equals decimal \f[B]35\f[R].
+This behavior is mandated by the standard for bc(1) (see the STANDARDS
+section) and is meant to provide an easy way to set the current
+\f[B]ibase\f[R] (with the \f[B]i\f[R] command) regardless of the current
+value of \f[B]ibase\f[R].
+.PP
+If clamping is on, and the clamped value of a character is needed, use a
+leading zero, i.e., for \f[B]A\f[R], use \f[B]0A\f[R].
.SH COMMANDS
.PP
The valid commands are listed below.
@@ -1078,7 +1154,8 @@ at which they become a problem.
In fact, memory should be exhausted before these limits should be hit.
.SH ENVIRONMENT VARIABLES
.PP
-dc(1) recognizes the following environment variables:
+As \f[B]non-portable extensions\f[R], dc(1) recognizes the following
+environment variables:
.TP
\f[B]DC_ENV_ARGS\f[R]
This is another way to give command-line arguments to dc(1).
@@ -1182,6 +1259,22 @@ expressions and expression files, and a zero value makes dc(1) not exit.
This environment variable overrides the default, which can be queried
with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
.RE
+.TP
+\f[B]DC_DIGIT_CLAMP\f[R]
+When parsing numbers and if this environment variable exists and
+contains an integer, a non-zero value makes dc(1) clamp digits that are
+greater than or equal to the current \f[B]ibase\f[R] so that all such
+digits are considered equal to the \f[B]ibase\f[R] minus 1, and a zero
+value disables such clamping so that those digits are always equal to
+their value, which is multiplied by the power of the \f[B]ibase\f[R].
+.RS
+.PP
+This never applies to single-digit numbers, as per the bc(1) standard
+(see the \f[B]STANDARDS\f[R] section).
+.PP
+This environment variable overrides the default, which can be queried
+with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
+.RE
.SH EXIT STATUS
.PP
dc(1) returns the following exit statuses:
@@ -1283,10 +1376,9 @@ The default setting can be queried with the \f[B]-h\f[R] or
\f[B]--help\f[R] options.
.PP
TTY mode is different from interactive mode because interactive mode is
-required in the bc(1) specification at
-https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html , and
-interactive mode requires only \f[B]stdin\f[R] and \f[B]stdout\f[R] to
-be connected to a terminal.
+required in the bc(1) specification (see the \f[B]STANDARDS\f[R]
+section), and interactive mode requires only \f[B]stdin\f[R] and
+\f[B]stdout\f[R] to be connected to a terminal.
.SS Prompt
.PP
If TTY mode is available, then a prompt can be enabled.
@@ -1349,10 +1441,10 @@ locales and thus, supports \f[B]LC_MESSAGES\f[R].
bc(1)
.SH STANDARDS
.PP
-The dc(1) utility operators are compliant with the operators in the IEEE
-Std 1003.1-2017 (\[lq]POSIX.1-2017\[rq]) specification at
-https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html for
-bc(1).
+The dc(1) utility operators and some behavior are compliant with the
+operators in the IEEE Std 1003.1-2017 (\[lq]POSIX.1-2017\[rq]) bc(1)
+specification at
+https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html .
.SH BUGS
.PP
None are known.
diff --git a/manuals/dc/EH.1.md b/manuals/dc/EH.1.md
index 50850226ddbe..8b5891f14e6e 100644
--- a/manuals/dc/EH.1.md
+++ b/manuals/dc/EH.1.md
@@ -34,7 +34,7 @@ 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*...]
+**dc** [**-cChiPRvVx**] [**-\-version**] [**-\-help**] [**-\-digit-clamp**] [**-\-no-digit-clamp**] [**-\-interactive**] [**-\-no-prompt**] [**-\-no-read-prompt**] [**-\-extended-register**] [**-e** *expr*] [**-\-expression**=*expr*...] [**-f** *file*...] [**-\-file**=*file*...] [*file*...]
# DESCRIPTION
@@ -55,73 +55,40 @@ this dc(1) will always start with a **scale** of **10**.
The following are the options that dc(1) accepts.
-**-h**, **-\-help**
+**-C**, **-\-no-digit-clamp**
-: Prints a usage message and quits.
+: Disables clamping of digits greater than or equal to the current **ibase**
+ when parsing numbers.
-**-v**, **-V**, **-\-version**
+ This means that the value added to a number from a digit is always that
+ digit's value multiplied by the value of ibase raised to the power of the
+ digit's position, which starts from 0 at the least significant digit.
-: Print the version information (copyright header) and exit.
+ If this and/or the **-c** or **-\-digit-clamp** options are given multiple
+ times, the last one given is used.
-**-i**, **-\-interactive**
-
-: Forces interactive mode. (See the **INTERACTIVE MODE** section.)
+ This option overrides the **DC_DIGIT_CLAMP** environment variable (see the
+ **ENVIRONMENT VARIABLES** section) and the default, which can be queried
+ with the **-h** or **-\-help** options.
This is a **non-portable extension**.
-**-L**, **-\-no-line-length**
+**-c**, **-\-digit-clamp**
-: 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).
+: Enables clamping of digits greater than or equal to the current **ibase**
+ when parsing numbers.
- This is a **non-portable extension**.
+ This means that digits that the value added to a number from a digit that is
+ greater than or equal to the ibase is the value of ibase minus 1 all
+ multiplied by the value of ibase raised to the power of the digit's
+ position, which starts from 0 at the least significant digit.
-**-P**, **-\-no-prompt**
+ If this and/or the **-C** or **-\-no-digit-clamp** options are given
+ multiple times, the last one given is used.
-: 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 dc(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 option overrides the **DC_DIGIT_CLAMP** environment variable (see the
+ **ENVIRONMENT VARIABLES** section) and the default, which can be queried
+ with the **-h** or **-\-help** options.
This is a **non-portable extension**.
@@ -157,6 +124,10 @@ The following are the options that dc(1) accepts.
This is a **non-portable extension**.
+**-h**, **-\-help**
+
+: Prints a usage message and exits.
+
**-I** *ibase*, **-\-ibase**=*ibase*
: Sets the builtin variable **ibase** to the value *ibase* assuming that
@@ -166,6 +137,20 @@ The following are the options that dc(1) accepts.
This is a **non-portable extension**.
+**-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**.
+
**-O** *obase*, **-\-obase**=*obase*
: Sets the builtin variable **obase** to the value *obase* assuming that
@@ -175,6 +160,36 @@ The following are the options that dc(1) accepts.
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**.
+
**-S** *scale*, **-\-scale**=*scale*
: Sets the builtin variable **scale** to the value *scale* assuming that
@@ -184,6 +199,28 @@ The following are the options that dc(1) accepts.
This is a **non-portable extension**.
+**-v**, **-V**, **-\-version**
+
+: Print the version information (copyright header) and exits.
+
+**-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 dc(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**.
+
All long options are **non-portable extensions**.
# STDIN
@@ -263,15 +300,40 @@ Comments go from **#** until, and not including, the next newline. This is a
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**.
+Uppercase letters are equal to **9** plus 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** (i.e.,
+they are greater than or equal to the current value of **ibase**), then the
+behavior depends on the existence of the **-c**/**-\-digit-clamp** or
+**-C**/**-\-no-digit-clamp** options (see the **OPTIONS** section), the
+existence and setting of the **DC_DIGIT_CLAMP** environment variable (see the
+**ENVIRONMENT VARIABLES** section), or the default, which can be queried with
+the **-h**/**-\-help** option.
+
+If clamping is off, then digits or letters that are greater than or equal to the
+current value of **ibase** are not changed. Instead, their given value is
+multiplied by the appropriate power of **ibase** and added into the number. This
+means that, with an **ibase** of **3**, the number **AB** is equal to
+**3\^1\*A+3\^0\*B**, which is **3** times **10** plus **11**, or **41**.
+
+If clamping is on, then digits or letters that are greater than or equal to the
+current value of **ibase** are set to the value of the highest valid digit in
+**ibase** before being multiplied by the appropriate power of **ibase** and
+added into the number. This means that, with an **ibase** of **3**, the number
+**AB** is equal to **3\^1\*2+3\^0\*2**, which is **3** times **2** plus **2**,
+or **8**.
+
+There is one exception to clamping: single-character numbers (i.e., **A**
+alone). Such numbers are never clamped and always take the value they would have
+in the highest possible **ibase**. This means that **A** alone always equals
+decimal **10** and **Z** alone always equals decimal **35**. This behavior is
+mandated by the standard for bc(1) (see the STANDARDS section) and is meant to
+provide an easy way to set the current **ibase** (with the **i** command)
+regardless of the current value of **ibase**.
+
+If clamping is on, and the clamped value of a character is needed, use a leading
+zero, i.e., for **A**, use **0A**.
# COMMANDS
@@ -974,7 +1036,8 @@ be hit.
# ENVIRONMENT VARIABLES
-dc(1) recognizes the following environment variables:
+As **non-portable extensions**, dc(1) recognizes the following environment
+variables:
**DC_ENV_ARGS**
@@ -1063,6 +1126,21 @@ dc(1) recognizes the following environment variables:
This environment variable overrides the default, which can be queried with
the **-h** or **-\-help** options.
+**DC_DIGIT_CLAMP**
+
+: When parsing numbers and if this environment variable exists and contains an
+ integer, a non-zero value makes dc(1) clamp digits that are greater than or
+ equal to the current **ibase** so that all such digits are considered equal
+ to the **ibase** minus 1, and a zero value disables such clamping so that
+ those digits are always equal to their value, which is multiplied by the
+ power of the **ibase**.
+
+ This never applies to single-digit numbers, as per the bc(1) standard (see
+ the **STANDARDS** section).
+
+ 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:
@@ -1157,10 +1235,8 @@ 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 at
-https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html , and
-interactive mode requires only **stdin** and **stdout** to be connected to a
-terminal.
+in the bc(1) specification (see the **STANDARDS** section), and interactive mode
+requires only **stdin** and **stdout** to be connected to a terminal.
## Prompt
@@ -1220,9 +1296,9 @@ bc(1)
# STANDARDS
-The dc(1) utility operators are compliant with the operators in the IEEE Std
-1003.1-2017 (“POSIX.1-2017”) specification at
-https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html for bc(1).
+The dc(1) utility operators and some behavior are compliant with the operators
+in the IEEE Std 1003.1-2017 (“POSIX.1-2017”) bc(1) specification at
+https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html .
# BUGS
diff --git a/manuals/dc/EHN.1 b/manuals/dc/EHN.1
index 31e60102b971..e60d3cf47fb1 100644
--- a/manuals/dc/EHN.1
+++ b/manuals/dc/EHN.1
@@ -25,7 +25,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.TH "DC" "1" "June 2022" "Gavin D. Howard" "General Commands Manual"
+.TH "DC" "1" "August 2022" "Gavin D. Howard" "General Commands Manual"
.nh
.ad l
.SH Name
@@ -33,12 +33,14 @@
dc - arbitrary-precision decimal reverse-Polish notation calculator
.SH SYNOPSIS
.PP
-\f[B]dc\f[R] [\f[B]-hiPRvVx\f[R]] [\f[B]--version\f[R]]
-[\f[B]--help\f[R]] [\f[B]--interactive\f[R]] [\f[B]--no-prompt\f[R]]
-[\f[B]--no-read-prompt\f[R]] [\f[B]--extended-register\f[R]]
-[\f[B]-e\f[R] \f[I]expr\f[R]]
-[\f[B]--expression\f[R]=\f[I]expr\f[R]\&...] [\f[B]-f\f[R]
-\f[I]file\f[R]\&...] [\f[B]--file\f[R]=\f[I]file\f[R]\&...]
+\f[B]dc\f[R] [\f[B]-cChiPRvVx\f[R]] [\f[B]--version\f[R]]
+[\f[B]--help\f[R]] [\f[B]--digit-clamp\f[R]]
+[\f[B]--no-digit-clamp\f[R]] [\f[B]--interactive\f[R]]
+[\f[B]--no-prompt\f[R]] [\f[B]--no-read-prompt\f[R]]
+[\f[B]--extended-register\f[R]] [\f[B]-e\f[R] \f[I]expr\f[R]]
+[\f[B]--expression\f[R]=\f[I]expr\f[R]\&...]
+[\f[B]-f\f[R] \f[I]file\f[R]\&...]
+[\f[B]--file\f[R]=\f[I]file\f[R]\&...]
[\f[I]file\f[R]\&...]
.SH DESCRIPTION
.PP
@@ -61,83 +63,43 @@ and this dc(1) will always start with a \f[B]scale\f[R] of \f[B]10\f[R].
.PP
The following are the options that dc(1) accepts.
.TP
-\f[B]-h\f[R], \f[B]--help\f[R]
-Prints a usage message and quits.
-.TP
-\f[B]-v\f[R], \f[B]-V\f[R], \f[B]--version\f[R]
-Print the version information (copyright header) and exit.
-.TP
-\f[B]-i\f[R], \f[B]--interactive\f[R]
-Forces interactive mode.
-(See the \f[B]INTERACTIVE MODE\f[R] section.)
+\f[B]-C\f[R], \f[B]--no-digit-clamp\f[R]
+Disables clamping of digits greater than or equal to the current
+\f[B]ibase\f[R] when parsing numbers.
.RS
.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
-.TP
-\f[B]-L\f[R], \f[B]--no-line-length\f[R]
-Disables line length checking and prints numbers without backslashes and
-newlines.
-In other words, this option sets \f[B]BC_LINE_LENGTH\f[R] to \f[B]0\f[R]
-(see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
-.RS
+This means that the value added to a number from a digit is always that
+digit\[cq]s value multiplied by the value of ibase raised to the power
+of the digit\[cq]s position, which starts from 0 at the least
+significant digit.
.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
-.TP
-\f[B]-P\f[R], \f[B]--no-prompt\f[R]
-Disables the prompt in TTY mode.
-(The prompt is only enabled in TTY mode.
-See the \f[B]TTY MODE\f[R] 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
-\f[B]DC_ENV_ARGS\f[R].
-.RS
+If this and/or the \f[B]-c\f[R] or \f[B]--digit-clamp\f[R] options are
+given multiple times, the last one given is used.
.PP
-These options override the \f[B]DC_PROMPT\f[R] and \f[B]DC_TTY_MODE\f[R]
-environment variables (see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
+This option overrides the \f[B]DC_DIGIT_CLAMP\f[R] environment variable
+(see the \f[B]ENVIRONMENT VARIABLES\f[R] section) and the default, which
+can be queried with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
.PP
This is a \f[B]non-portable extension\f[R].
.RE
.TP
-\f[B]-R\f[R], \f[B]--no-read-prompt\f[R]
-Disables the read prompt in TTY mode.
-(The read prompt is only enabled in TTY mode.
-See the \f[B]TTY MODE\f[R] 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
-\f[B]BC_ENV_ARGS\f[R] (see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
-This option is also useful in hash bang lines of dc(1) scripts that
-prompt for user input.
+\f[B]-c\f[R], \f[B]--digit-clamp\f[R]
+Enables clamping of digits greater than or equal to the current
+\f[B]ibase\f[R] when parsing numbers.
.RS
.PP
-This option does not disable the regular prompt because the read prompt
-is only used when the \f[B]?\f[R] command is used.
-.PP
-These options \f[I]do\f[R] override the \f[B]DC_PROMPT\f[R] and
-\f[B]DC_TTY_MODE\f[R] environment variables (see the \f[B]ENVIRONMENT
-VARIABLES\f[R] section), but only for the read prompt.
-.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
-.TP
-\f[B]-x\f[R] \f[B]--extended-register\f[R]
-Enables extended register mode.
-See the \f[I]Extended Register Mode\f[R] subsection of the
-\f[B]REGISTERS\f[R] section for more information.
-.RS
+This means that digits that the value added to a number from a digit
+that is greater than or equal to the ibase is the value of ibase minus 1
+all multiplied by the value of ibase raised to the power of the
+digit\[cq]s position, which starts from 0 at the least significant
+digit.
.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
-.TP
-\f[B]-z\f[R], \f[B]--leading-zeroes\f[R]
-Makes dc(1) print all numbers greater than \f[B]-1\f[R] and less than
-\f[B]1\f[R], and not equal to \f[B]0\f[R], with a leading zero.
-.RS
+If this and/or the \f[B]-C\f[R] or \f[B]--no-digit-clamp\f[R] options
+are given multiple times, the last one given is used.
.PP
-This can be set for individual numbers with the \f[B]plz(x)\f[R],
-plznl(x)**, \f[B]pnlz(x)\f[R], and \f[B]pnlznl(x)\f[R] functions in the
-extended math library (see the \f[B]LIBRARY\f[R] section).
+This option overrides the \f[B]DC_DIGIT_CLAMP\f[R] environment variable
+(see the \f[B]ENVIRONMENT VARIABLES\f[R] section) and the default, which
+can be queried with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
.PP
This is a \f[B]non-portable extension\f[R].
.RE
@@ -185,6 +147,9 @@ exit.
This is a \f[B]non-portable extension\f[R].
.RE
.TP
+\f[B]-h\f[R], \f[B]--help\f[R]
+Prints a usage message and exits.
+.TP
\f[B]-I\f[R] \f[I]ibase\f[R], \f[B]--ibase\f[R]=\f[I]ibase\f[R]
Sets the builtin variable \f[B]ibase\f[R] to the value \f[I]ibase\f[R]
assuming that \f[I]ibase\f[R] is in base 10.
@@ -196,6 +161,24 @@ If multiple instances of this option are given, the last is used.
This is a \f[B]non-portable extension\f[R].
.RE
.TP
+\f[B]-i\f[R], \f[B]--interactive\f[R]
+Forces interactive mode.
+(See the \f[B]INTERACTIVE MODE\f[R] section.)
+.RS
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
+\f[B]-L\f[R], \f[B]--no-line-length\f[R]
+Disables line length checking and prints numbers without backslashes and
+newlines.
+In other words, this option sets \f[B]BC_LINE_LENGTH\f[R] to \f[B]0\f[R]
+(see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
+.RS
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
\f[B]-O\f[R] \f[I]obase\f[R], \f[B]--obase\f[R]=\f[I]obase\f[R]
Sets the builtin variable \f[B]obase\f[R] to the value \f[I]obase\f[R]
assuming that \f[I]obase\f[R] is in base 10.
@@ -207,6 +190,44 @@ If multiple instances of this option are given, the last is used.
This is a \f[B]non-portable extension\f[R].
.RE
.TP
+\f[B]-P\f[R], \f[B]--no-prompt\f[R]
+Disables the prompt in TTY mode.
+(The prompt is only enabled in TTY mode.
+See the \f[B]TTY MODE\f[R] 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
+\f[B]DC_ENV_ARGS\f[R].
+.RS
+.PP
+These options override the \f[B]DC_PROMPT\f[R] and \f[B]DC_TTY_MODE\f[R]
+environment variables (see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
+\f[B]-R\f[R], \f[B]--no-read-prompt\f[R]
+Disables the read prompt in TTY mode.
+(The read prompt is only enabled in TTY mode.
+See the \f[B]TTY MODE\f[R] 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
+\f[B]BC_ENV_ARGS\f[R] (see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
+This option is also useful in hash bang lines of dc(1) scripts that
+prompt for user input.
+.RS
+.PP
+This option does not disable the regular prompt because the read prompt
+is only used when the \f[B]?\f[R] command is used.
+.PP
+These options \f[I]do\f[R] override the \f[B]DC_PROMPT\f[R] and
+\f[B]DC_TTY_MODE\f[R] environment variables (see the \f[B]ENVIRONMENT
+VARIABLES\f[R] section), but only for the read prompt.
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
\f[B]-S\f[R] \f[I]scale\f[R], \f[B]--scale\f[R]=\f[I]scale\f[R]
Sets the builtin variable \f[B]scale\f[R] to the value \f[I]scale\f[R]
assuming that \f[I]scale\f[R] is in base 10.
@@ -217,6 +238,30 @@ If multiple instances of this option are given, the last is used.
.PP
This is a \f[B]non-portable extension\f[R].
.RE
+.TP
+\f[B]-v\f[R], \f[B]-V\f[R], \f[B]--version\f[R]
+Print the version information (copyright header) and exits.
+.TP
+\f[B]-x\f[R] \f[B]--extended-register\f[R]
+Enables extended register mode.
+See the \f[I]Extended Register Mode\f[R] subsection of the
+\f[B]REGISTERS\f[R] section for more information.
+.RS
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
+\f[B]-z\f[R], \f[B]--leading-zeroes\f[R]
+Makes dc(1) print all numbers greater than \f[B]-1\f[R] and less than
+\f[B]1\f[R], and not equal to \f[B]0\f[R], with a leading zero.
+.RS
+.PP
+This can be set for individual numbers with the \f[B]plz(x)\f[R],
+plznl(x)**, \f[B]pnlz(x)\f[R], and \f[B]pnlznl(x)\f[R] functions in the
+extended math library (see the \f[B]LIBRARY\f[R] section).
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
.PP
All long options are \f[B]non-portable extensions\f[R].
.SH STDIN
@@ -307,17 +352,48 @@ This is a \f[B]non-portable extension\f[R].
Numbers are strings made up of digits, uppercase letters up to
\f[B]F\f[R], and at most \f[B]1\f[R] period for a radix.
Numbers can have up to \f[B]DC_NUM_MAX\f[R] digits.
-Uppercase letters are equal to \f[B]9\f[R] + their position in the
+Uppercase letters are equal to \f[B]9\f[R] plus their position in the
alphabet (i.e., \f[B]A\f[R] equals \f[B]10\f[R], or \f[B]9+1\f[R]).
-If a digit or letter makes no sense with the current value of
-\f[B]ibase\f[R], they are set to the value of the highest valid digit in
-\f[B]ibase\f[R].
.PP
-Single-character numbers (i.e., \f[B]A\f[R] alone) take the value that
-they would have if they were valid digits, regardless of the value of
-\f[B]ibase\f[R].
+If a digit or letter makes no sense with the current value of
+\f[B]ibase\f[R] (i.e., they are greater than or equal to the current
+value of \f[B]ibase\f[R]), then the behavior depends on the existence of
+the \f[B]-c\f[R]/\f[B]--digit-clamp\f[R] or
+\f[B]-C\f[R]/\f[B]--no-digit-clamp\f[R] options (see the
+\f[B]OPTIONS\f[R] section), the existence and setting of the
+\f[B]DC_DIGIT_CLAMP\f[R] environment variable (see the \f[B]ENVIRONMENT
+VARIABLES\f[R] section), or the default, which can be queried with the
+\f[B]-h\f[R]/\f[B]--help\f[R] option.
+.PP
+If clamping is off, then digits or letters that are greater than or
+equal to the current value of \f[B]ibase\f[R] are not changed.
+Instead, their given value is multiplied by the appropriate power of
+\f[B]ibase\f[R] and added into the number.
+This means that, with an \f[B]ibase\f[R] of \f[B]3\f[R], the number
+\f[B]AB\f[R] is equal to \f[B]3\[ha]1*A+3\[ha]0*B\f[R], which is
+\f[B]3\f[R] times \f[B]10\f[R] plus \f[B]11\f[R], or \f[B]41\f[R].
+.PP
+If clamping is on, then digits or letters that are greater than or equal
+to the current value of \f[B]ibase\f[R] are set to the value of the
+highest valid digit in \f[B]ibase\f[R] before being multiplied by the
+appropriate power of \f[B]ibase\f[R] and added into the number.
+This means that, with an \f[B]ibase\f[R] of \f[B]3\f[R], the number
+\f[B]AB\f[R] is equal to \f[B]3\[ha]1*2+3\[ha]0*2\f[R], which is
+\f[B]3\f[R] times \f[B]2\f[R] plus \f[B]2\f[R], or \f[B]8\f[R].
+.PP
+There is one exception to clamping: single-character numbers (i.e.,
+\f[B]A\f[R] alone).
+Such numbers are never clamped and always take the value they would have
+in the highest possible \f[B]ibase\f[R].
This means that \f[B]A\f[R] alone always equals decimal \f[B]10\f[R] and
-\f[B]F\f[R] alone always equals decimal \f[B]15\f[R].
+\f[B]Z\f[R] alone always equals decimal \f[B]35\f[R].
+This behavior is mandated by the standard for bc(1) (see the STANDARDS
+section) and is meant to provide an easy way to set the current
+\f[B]ibase\f[R] (with the \f[B]i\f[R] command) regardless of the current
+value of \f[B]ibase\f[R].
+.PP
+If clamping is on, and the clamped value of a character is needed, use a
+leading zero, i.e., for \f[B]A\f[R], use \f[B]0A\f[R].
.SH COMMANDS
.PP
The valid commands are listed below.
@@ -1078,7 +1154,8 @@ at which they become a problem.
In fact, memory should be exhausted before these limits should be hit.
.SH ENVIRONMENT VARIABLES
.PP
-dc(1) recognizes the following environment variables:
+As \f[B]non-portable extensions\f[R], dc(1) recognizes the following
+environment variables:
.TP
\f[B]DC_ENV_ARGS\f[R]
This is another way to give command-line arguments to dc(1).
@@ -1182,6 +1259,22 @@ expressions and expression files, and a zero value makes dc(1) not exit.
This environment variable overrides the default, which can be queried
with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
.RE
+.TP
+\f[B]DC_DIGIT_CLAMP\f[R]
+When parsing numbers and if this environment variable exists and
+contains an integer, a non-zero value makes dc(1) clamp digits that are
+greater than or equal to the current \f[B]ibase\f[R] so that all such
+digits are considered equal to the \f[B]ibase\f[R] minus 1, and a zero
+value disables such clamping so that those digits are always equal to
+their value, which is multiplied by the power of the \f[B]ibase\f[R].
+.RS
+.PP
+This never applies to single-digit numbers, as per the bc(1) standard
+(see the \f[B]STANDARDS\f[R] section).
+.PP
+This environment variable overrides the default, which can be queried
+with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
+.RE
.SH EXIT STATUS
.PP
dc(1) returns the following exit statuses:
@@ -1283,10 +1376,9 @@ The default setting can be queried with the \f[B]-h\f[R] or
\f[B]--help\f[R] options.
.PP
TTY mode is different from interactive mode because interactive mode is
-required in the bc(1) specification at
-https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html , and
-interactive mode requires only \f[B]stdin\f[R] and \f[B]stdout\f[R] to
-be connected to a terminal.
+required in the bc(1) specification (see the \f[B]STANDARDS\f[R]
+section), and interactive mode requires only \f[B]stdin\f[R] and
+\f[B]stdout\f[R] to be connected to a terminal.
.SS Prompt
.PP
If TTY mode is available, then a prompt can be enabled.
@@ -1345,10 +1437,10 @@ exit, and it uses the default handler for all other signals.
bc(1)
.SH STANDARDS
.PP
-The dc(1) utility operators are compliant with the operators in the IEEE
-Std 1003.1-2017 (\[lq]POSIX.1-2017\[rq]) specification at
-https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html for
-bc(1).
+The dc(1) utility operators and some behavior are compliant with the
+operators in the IEEE Std 1003.1-2017 (\[lq]POSIX.1-2017\[rq]) bc(1)
+specification at
+https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html .
.SH BUGS
.PP
None are known.
diff --git a/manuals/dc/EHN.1.md b/manuals/dc/EHN.1.md
index e3b42d4453f6..96a020662b38 100644
--- a/manuals/dc/EHN.1.md
+++ b/manuals/dc/EHN.1.md
@@ -34,7 +34,7 @@ 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*...]
+**dc** [**-cChiPRvVx**] [**-\-version**] [**-\-help**] [**-\-digit-clamp**] [**-\-no-digit-clamp**] [**-\-interactive**] [**-\-no-prompt**] [**-\-no-read-prompt**] [**-\-extended-register**] [**-e** *expr*] [**-\-expression**=*expr*...] [**-f** *file*...] [**-\-file**=*file*...] [*file*...]
# DESCRIPTION
@@ -55,73 +55,40 @@ this dc(1) will always start with a **scale** of **10**.
The following are the options that dc(1) accepts.
-**-h**, **-\-help**
+**-C**, **-\-no-digit-clamp**
-: Prints a usage message and quits.
+: Disables clamping of digits greater than or equal to the current **ibase**
+ when parsing numbers.
-**-v**, **-V**, **-\-version**
+ This means that the value added to a number from a digit is always that
+ digit's value multiplied by the value of ibase raised to the power of the
+ digit's position, which starts from 0 at the least significant digit.
-: Print the version information (copyright header) and exit.
+ If this and/or the **-c** or **-\-digit-clamp** options are given multiple
+ times, the last one given is used.
-**-i**, **-\-interactive**
-
-: Forces interactive mode. (See the **INTERACTIVE MODE** section.)
+ This option overrides the **DC_DIGIT_CLAMP** environment variable (see the
+ **ENVIRONMENT VARIABLES** section) and the default, which can be queried
+ with the **-h** or **-\-help** options.
This is a **non-portable extension**.
-**-L**, **-\-no-line-length**
+**-c**, **-\-digit-clamp**
-: 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).
+: Enables clamping of digits greater than or equal to the current **ibase**
+ when parsing numbers.
- This is a **non-portable extension**.
+ This means that digits that the value added to a number from a digit that is
+ greater than or equal to the ibase is the value of ibase minus 1 all
+ multiplied by the value of ibase raised to the power of the digit's
+ position, which starts from 0 at the least significant digit.
-**-P**, **-\-no-prompt**
+ If this and/or the **-C** or **-\-no-digit-clamp** options are given
+ multiple times, the last one given is used.
-: 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 dc(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 option overrides the **DC_DIGIT_CLAMP** environment variable (see the
+ **ENVIRONMENT VARIABLES** section) and the default, which can be queried
+ with the **-h** or **-\-help** options.
This is a **non-portable extension**.
@@ -157,6 +124,10 @@ The following are the options that dc(1) accepts.
This is a **non-portable extension**.
+**-h**, **-\-help**
+
+: Prints a usage message and exits.
+
**-I** *ibase*, **-\-ibase**=*ibase*
: Sets the builtin variable **ibase** to the value *ibase* assuming that
@@ -166,6 +137,20 @@ The following are the options that dc(1) accepts.
This is a **non-portable extension**.
+**-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**.
+
**-O** *obase*, **-\-obase**=*obase*
: Sets the builtin variable **obase** to the value *obase* assuming that
@@ -175,6 +160,36 @@ The following are the options that dc(1) accepts.
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**.
+
**-S** *scale*, **-\-scale**=*scale*
: Sets the builtin variable **scale** to the value *scale* assuming that
@@ -184,6 +199,28 @@ The following are the options that dc(1) accepts.
This is a **non-portable extension**.
+**-v**, **-V**, **-\-version**
+
+: Print the version information (copyright header) and exits.
+
+**-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 dc(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**.
+
All long options are **non-portable extensions**.
# STDIN
@@ -263,15 +300,40 @@ Comments go from **#** until, and not including, the next newline. This is a
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**.
+Uppercase letters are equal to **9** plus 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** (i.e.,
+they are greater than or equal to the current value of **ibase**), then the
+behavior depends on the existence of the **-c**/**-\-digit-clamp** or
+**-C**/**-\-no-digit-clamp** options (see the **OPTIONS** section), the
+existence and setting of the **DC_DIGIT_CLAMP** environment variable (see the
+**ENVIRONMENT VARIABLES** section), or the default, which can be queried with
+the **-h**/**-\-help** option.
+
+If clamping is off, then digits or letters that are greater than or equal to the
+current value of **ibase** are not changed. Instead, their given value is
+multiplied by the appropriate power of **ibase** and added into the number. This
+means that, with an **ibase** of **3**, the number **AB** is equal to
+**3\^1\*A+3\^0\*B**, which is **3** times **10** plus **11**, or **41**.
+
+If clamping is on, then digits or letters that are greater than or equal to the
+current value of **ibase** are set to the value of the highest valid digit in
+**ibase** before being multiplied by the appropriate power of **ibase** and
+added into the number. This means that, with an **ibase** of **3**, the number
+**AB** is equal to **3\^1\*2+3\^0\*2**, which is **3** times **2** plus **2**,
+or **8**.
+
+There is one exception to clamping: single-character numbers (i.e., **A**
+alone). Such numbers are never clamped and always take the value they would have
+in the highest possible **ibase**. This means that **A** alone always equals
+decimal **10** and **Z** alone always equals decimal **35**. This behavior is
+mandated by the standard for bc(1) (see the STANDARDS section) and is meant to
+provide an easy way to set the current **ibase** (with the **i** command)
+regardless of the current value of **ibase**.
+
+If clamping is on, and the clamped value of a character is needed, use a leading
+zero, i.e., for **A**, use **0A**.
# COMMANDS
@@ -974,7 +1036,8 @@ be hit.
# ENVIRONMENT VARIABLES
-dc(1) recognizes the following environment variables:
+As **non-portable extensions**, dc(1) recognizes the following environment
+variables:
**DC_ENV_ARGS**
@@ -1063,6 +1126,21 @@ dc(1) recognizes the following environment variables:
This environment variable overrides the default, which can be queried with
the **-h** or **-\-help** options.
+**DC_DIGIT_CLAMP**
+
+: When parsing numbers and if this environment variable exists and contains an
+ integer, a non-zero value makes dc(1) clamp digits that are greater than or
+ equal to the current **ibase** so that all such digits are considered equal
+ to the **ibase** minus 1, and a zero value disables such clamping so that
+ those digits are always equal to their value, which is multiplied by the
+ power of the **ibase**.
+
+ This never applies to single-digit numbers, as per the bc(1) standard (see
+ the **STANDARDS** section).
+
+ 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:
@@ -1157,10 +1235,8 @@ 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 at
-https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html , and
-interactive mode requires only **stdin** and **stdout** to be connected to a
-terminal.
+in the bc(1) specification (see the **STANDARDS** section), and interactive mode
+requires only **stdin** and **stdout** to be connected to a terminal.
## Prompt
@@ -1215,9 +1291,9 @@ bc(1)
# STANDARDS
-The dc(1) utility operators are compliant with the operators in the IEEE Std
-1003.1-2017 (“POSIX.1-2017”) specification at
-https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html for bc(1).
+The dc(1) utility operators and some behavior are compliant with the operators
+in the IEEE Std 1003.1-2017 (“POSIX.1-2017”) bc(1) specification at
+https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html .
# BUGS
diff --git a/manuals/dc/EN.1 b/manuals/dc/EN.1
index d941c130e847..a1eb86cc5096 100644
--- a/manuals/dc/EN.1
+++ b/manuals/dc/EN.1
@@ -25,7 +25,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.TH "DC" "1" "June 2022" "Gavin D. Howard" "General Commands Manual"
+.TH "DC" "1" "August 2022" "Gavin D. Howard" "General Commands Manual"
.nh
.ad l
.SH Name
@@ -33,12 +33,14 @@
dc - arbitrary-precision decimal reverse-Polish notation calculator
.SH SYNOPSIS
.PP
-\f[B]dc\f[R] [\f[B]-hiPRvVx\f[R]] [\f[B]--version\f[R]]
-[\f[B]--help\f[R]] [\f[B]--interactive\f[R]] [\f[B]--no-prompt\f[R]]
-[\f[B]--no-read-prompt\f[R]] [\f[B]--extended-register\f[R]]
-[\f[B]-e\f[R] \f[I]expr\f[R]]
-[\f[B]--expression\f[R]=\f[I]expr\f[R]\&...] [\f[B]-f\f[R]
-\f[I]file\f[R]\&...] [\f[B]--file\f[R]=\f[I]file\f[R]\&...]
+\f[B]dc\f[R] [\f[B]-cChiPRvVx\f[R]] [\f[B]--version\f[R]]
+[\f[B]--help\f[R]] [\f[B]--digit-clamp\f[R]]
+[\f[B]--no-digit-clamp\f[R]] [\f[B]--interactive\f[R]]
+[\f[B]--no-prompt\f[R]] [\f[B]--no-read-prompt\f[R]]
+[\f[B]--extended-register\f[R]] [\f[B]-e\f[R] \f[I]expr\f[R]]
+[\f[B]--expression\f[R]=\f[I]expr\f[R]\&...]
+[\f[B]-f\f[R] \f[I]file\f[R]\&...]
+[\f[B]--file\f[R]=\f[I]file\f[R]\&...]
[\f[I]file\f[R]\&...]
.SH DESCRIPTION
.PP
@@ -61,83 +63,43 @@ and this dc(1) will always start with a \f[B]scale\f[R] of \f[B]10\f[R].
.PP
The following are the options that dc(1) accepts.
.TP
-\f[B]-h\f[R], \f[B]--help\f[R]
-Prints a usage message and quits.
-.TP
-\f[B]-v\f[R], \f[B]-V\f[R], \f[B]--version\f[R]
-Print the version information (copyright header) and exit.
-.TP
-\f[B]-i\f[R], \f[B]--interactive\f[R]
-Forces interactive mode.
-(See the \f[B]INTERACTIVE MODE\f[R] section.)
+\f[B]-C\f[R], \f[B]--no-digit-clamp\f[R]
+Disables clamping of digits greater than or equal to the current
+\f[B]ibase\f[R] when parsing numbers.
.RS
.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
-.TP
-\f[B]-L\f[R], \f[B]--no-line-length\f[R]
-Disables line length checking and prints numbers without backslashes and
-newlines.
-In other words, this option sets \f[B]BC_LINE_LENGTH\f[R] to \f[B]0\f[R]
-(see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
-.RS
+This means that the value added to a number from a digit is always that
+digit\[cq]s value multiplied by the value of ibase raised to the power
+of the digit\[cq]s position, which starts from 0 at the least
+significant digit.
.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
-.TP
-\f[B]-P\f[R], \f[B]--no-prompt\f[R]
-Disables the prompt in TTY mode.
-(The prompt is only enabled in TTY mode.
-See the \f[B]TTY MODE\f[R] 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
-\f[B]DC_ENV_ARGS\f[R].
-.RS
+If this and/or the \f[B]-c\f[R] or \f[B]--digit-clamp\f[R] options are
+given multiple times, the last one given is used.
.PP
-These options override the \f[B]DC_PROMPT\f[R] and \f[B]DC_TTY_MODE\f[R]
-environment variables (see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
+This option overrides the \f[B]DC_DIGIT_CLAMP\f[R] environment variable
+(see the \f[B]ENVIRONMENT VARIABLES\f[R] section) and the default, which
+can be queried with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
.PP
This is a \f[B]non-portable extension\f[R].
.RE
.TP
-\f[B]-R\f[R], \f[B]--no-read-prompt\f[R]
-Disables the read prompt in TTY mode.
-(The read prompt is only enabled in TTY mode.
-See the \f[B]TTY MODE\f[R] 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
-\f[B]BC_ENV_ARGS\f[R] (see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
-This option is also useful in hash bang lines of dc(1) scripts that
-prompt for user input.
+\f[B]-c\f[R], \f[B]--digit-clamp\f[R]
+Enables clamping of digits greater than or equal to the current
+\f[B]ibase\f[R] when parsing numbers.
.RS
.PP
-This option does not disable the regular prompt because the read prompt
-is only used when the \f[B]?\f[R] command is used.
-.PP
-These options \f[I]do\f[R] override the \f[B]DC_PROMPT\f[R] and
-\f[B]DC_TTY_MODE\f[R] environment variables (see the \f[B]ENVIRONMENT
-VARIABLES\f[R] section), but only for the read prompt.
-.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
-.TP
-\f[B]-x\f[R] \f[B]--extended-register\f[R]
-Enables extended register mode.
-See the \f[I]Extended Register Mode\f[R] subsection of the
-\f[B]REGISTERS\f[R] section for more information.
-.RS
+This means that digits that the value added to a number from a digit
+that is greater than or equal to the ibase is the value of ibase minus 1
+all multiplied by the value of ibase raised to the power of the
+digit\[cq]s position, which starts from 0 at the least significant
+digit.
.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
-.TP
-\f[B]-z\f[R], \f[B]--leading-zeroes\f[R]
-Makes dc(1) print all numbers greater than \f[B]-1\f[R] and less than
-\f[B]1\f[R], and not equal to \f[B]0\f[R], with a leading zero.
-.RS
+If this and/or the \f[B]-C\f[R] or \f[B]--no-digit-clamp\f[R] options
+are given multiple times, the last one given is used.
.PP
-This can be set for individual numbers with the \f[B]plz(x)\f[R],
-plznl(x)**, \f[B]pnlz(x)\f[R], and \f[B]pnlznl(x)\f[R] functions in the
-extended math library (see the \f[B]LIBRARY\f[R] section).
+This option overrides the \f[B]DC_DIGIT_CLAMP\f[R] environment variable
+(see the \f[B]ENVIRONMENT VARIABLES\f[R] section) and the default, which
+can be queried with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
.PP
This is a \f[B]non-portable extension\f[R].
.RE
@@ -185,6 +147,9 @@ exit.
This is a \f[B]non-portable extension\f[R].
.RE
.TP
+\f[B]-h\f[R], \f[B]--help\f[R]
+Prints a usage message and exits.
+.TP
\f[B]-I\f[R] \f[I]ibase\f[R], \f[B]--ibase\f[R]=\f[I]ibase\f[R]
Sets the builtin variable \f[B]ibase\f[R] to the value \f[I]ibase\f[R]
assuming that \f[I]ibase\f[R] is in base 10.
@@ -196,6 +161,24 @@ If multiple instances of this option are given, the last is used.
This is a \f[B]non-portable extension\f[R].
.RE
.TP
+\f[B]-i\f[R], \f[B]--interactive\f[R]
+Forces interactive mode.
+(See the \f[B]INTERACTIVE MODE\f[R] section.)
+.RS
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
+\f[B]-L\f[R], \f[B]--no-line-length\f[R]
+Disables line length checking and prints numbers without backslashes and
+newlines.
+In other words, this option sets \f[B]BC_LINE_LENGTH\f[R] to \f[B]0\f[R]
+(see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
+.RS
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
\f[B]-O\f[R] \f[I]obase\f[R], \f[B]--obase\f[R]=\f[I]obase\f[R]
Sets the builtin variable \f[B]obase\f[R] to the value \f[I]obase\f[R]
assuming that \f[I]obase\f[R] is in base 10.
@@ -207,6 +190,44 @@ If multiple instances of this option are given, the last is used.
This is a \f[B]non-portable extension\f[R].
.RE
.TP
+\f[B]-P\f[R], \f[B]--no-prompt\f[R]
+Disables the prompt in TTY mode.
+(The prompt is only enabled in TTY mode.
+See the \f[B]TTY MODE\f[R] 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
+\f[B]DC_ENV_ARGS\f[R].
+.RS
+.PP
+These options override the \f[B]DC_PROMPT\f[R] and \f[B]DC_TTY_MODE\f[R]
+environment variables (see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
+\f[B]-R\f[R], \f[B]--no-read-prompt\f[R]
+Disables the read prompt in TTY mode.
+(The read prompt is only enabled in TTY mode.
+See the \f[B]TTY MODE\f[R] 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
+\f[B]BC_ENV_ARGS\f[R] (see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
+This option is also useful in hash bang lines of dc(1) scripts that
+prompt for user input.
+.RS
+.PP
+This option does not disable the regular prompt because the read prompt
+is only used when the \f[B]?\f[R] command is used.
+.PP
+These options \f[I]do\f[R] override the \f[B]DC_PROMPT\f[R] and
+\f[B]DC_TTY_MODE\f[R] environment variables (see the \f[B]ENVIRONMENT
+VARIABLES\f[R] section), but only for the read prompt.
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
\f[B]-S\f[R] \f[I]scale\f[R], \f[B]--scale\f[R]=\f[I]scale\f[R]
Sets the builtin variable \f[B]scale\f[R] to the value \f[I]scale\f[R]
assuming that \f[I]scale\f[R] is in base 10.
@@ -217,6 +238,30 @@ If multiple instances of this option are given, the last is used.
.PP
This is a \f[B]non-portable extension\f[R].
.RE
+.TP
+\f[B]-v\f[R], \f[B]-V\f[R], \f[B]--version\f[R]
+Print the version information (copyright header) and exits.
+.TP
+\f[B]-x\f[R] \f[B]--extended-register\f[R]
+Enables extended register mode.
+See the \f[I]Extended Register Mode\f[R] subsection of the
+\f[B]REGISTERS\f[R] section for more information.
+.RS
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
+\f[B]-z\f[R], \f[B]--leading-zeroes\f[R]
+Makes dc(1) print all numbers greater than \f[B]-1\f[R] and less than
+\f[B]1\f[R], and not equal to \f[B]0\f[R], with a leading zero.
+.RS
+.PP
+This can be set for individual numbers with the \f[B]plz(x)\f[R],
+plznl(x)**, \f[B]pnlz(x)\f[R], and \f[B]pnlznl(x)\f[R] functions in the
+extended math library (see the \f[B]LIBRARY\f[R] section).
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
.PP
All long options are \f[B]non-portable extensions\f[R].
.SH STDIN
@@ -307,17 +352,48 @@ This is a \f[B]non-portable extension\f[R].
Numbers are strings made up of digits, uppercase letters up to
\f[B]F\f[R], and at most \f[B]1\f[R] period for a radix.
Numbers can have up to \f[B]DC_NUM_MAX\f[R] digits.
-Uppercase letters are equal to \f[B]9\f[R] + their position in the
+Uppercase letters are equal to \f[B]9\f[R] plus their position in the
alphabet (i.e., \f[B]A\f[R] equals \f[B]10\f[R], or \f[B]9+1\f[R]).
-If a digit or letter makes no sense with the current value of
-\f[B]ibase\f[R], they are set to the value of the highest valid digit in
-\f[B]ibase\f[R].
.PP
-Single-character numbers (i.e., \f[B]A\f[R] alone) take the value that
-they would have if they were valid digits, regardless of the value of
-\f[B]ibase\f[R].
+If a digit or letter makes no sense with the current value of
+\f[B]ibase\f[R] (i.e., they are greater than or equal to the current
+value of \f[B]ibase\f[R]), then the behavior depends on the existence of
+the \f[B]-c\f[R]/\f[B]--digit-clamp\f[R] or
+\f[B]-C\f[R]/\f[B]--no-digit-clamp\f[R] options (see the
+\f[B]OPTIONS\f[R] section), the existence and setting of the
+\f[B]DC_DIGIT_CLAMP\f[R] environment variable (see the \f[B]ENVIRONMENT
+VARIABLES\f[R] section), or the default, which can be queried with the
+\f[B]-h\f[R]/\f[B]--help\f[R] option.
+.PP
+If clamping is off, then digits or letters that are greater than or
+equal to the current value of \f[B]ibase\f[R] are not changed.
+Instead, their given value is multiplied by the appropriate power of
+\f[B]ibase\f[R] and added into the number.
+This means that, with an \f[B]ibase\f[R] of \f[B]3\f[R], the number
+\f[B]AB\f[R] is equal to \f[B]3\[ha]1*A+3\[ha]0*B\f[R], which is
+\f[B]3\f[R] times \f[B]10\f[R] plus \f[B]11\f[R], or \f[B]41\f[R].
+.PP
+If clamping is on, then digits or letters that are greater than or equal
+to the current value of \f[B]ibase\f[R] are set to the value of the
+highest valid digit in \f[B]ibase\f[R] before being multiplied by the
+appropriate power of \f[B]ibase\f[R] and added into the number.
+This means that, with an \f[B]ibase\f[R] of \f[B]3\f[R], the number
+\f[B]AB\f[R] is equal to \f[B]3\[ha]1*2+3\[ha]0*2\f[R], which is
+\f[B]3\f[R] times \f[B]2\f[R] plus \f[B]2\f[R], or \f[B]8\f[R].
+.PP
+There is one exception to clamping: single-character numbers (i.e.,
+\f[B]A\f[R] alone).
+Such numbers are never clamped and always take the value they would have
+in the highest possible \f[B]ibase\f[R].
This means that \f[B]A\f[R] alone always equals decimal \f[B]10\f[R] and
-\f[B]F\f[R] alone always equals decimal \f[B]15\f[R].
+\f[B]Z\f[R] alone always equals decimal \f[B]35\f[R].
+This behavior is mandated by the standard for bc(1) (see the STANDARDS
+section) and is meant to provide an easy way to set the current
+\f[B]ibase\f[R] (with the \f[B]i\f[R] command) regardless of the current
+value of \f[B]ibase\f[R].
+.PP
+If clamping is on, and the clamped value of a character is needed, use a
+leading zero, i.e., for \f[B]A\f[R], use \f[B]0A\f[R].
.SH COMMANDS
.PP
The valid commands are listed below.
@@ -1078,7 +1154,8 @@ at which they become a problem.
In fact, memory should be exhausted before these limits should be hit.
.SH ENVIRONMENT VARIABLES
.PP
-dc(1) recognizes the following environment variables:
+As \f[B]non-portable extensions\f[R], dc(1) recognizes the following
+environment variables:
.TP
\f[B]DC_ENV_ARGS\f[R]
This is another way to give command-line arguments to dc(1).
@@ -1182,6 +1259,22 @@ expressions and expression files, and a zero value makes dc(1) not exit.
This environment variable overrides the default, which can be queried
with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
.RE
+.TP
+\f[B]DC_DIGIT_CLAMP\f[R]
+When parsing numbers and if this environment variable exists and
+contains an integer, a non-zero value makes dc(1) clamp digits that are
+greater than or equal to the current \f[B]ibase\f[R] so that all such
+digits are considered equal to the \f[B]ibase\f[R] minus 1, and a zero
+value disables such clamping so that those digits are always equal to
+their value, which is multiplied by the power of the \f[B]ibase\f[R].
+.RS
+.PP
+This never applies to single-digit numbers, as per the bc(1) standard
+(see the \f[B]STANDARDS\f[R] section).
+.PP
+This environment variable overrides the default, which can be queried
+with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
+.RE
.SH EXIT STATUS
.PP
dc(1) returns the following exit statuses:
@@ -1283,10 +1376,9 @@ The default setting can be queried with the \f[B]-h\f[R] or
\f[B]--help\f[R] options.
.PP
TTY mode is different from interactive mode because interactive mode is
-required in the bc(1) specification at
-https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html , and
-interactive mode requires only \f[B]stdin\f[R] and \f[B]stdout\f[R] to
-be connected to a terminal.
+required in the bc(1) specification (see the \f[B]STANDARDS\f[R]
+section), and interactive mode requires only \f[B]stdin\f[R] and
+\f[B]stdout\f[R] to be connected to a terminal.
.SS Command-Line History
.PP
Command-line history is only enabled if TTY mode is, i.e., that
@@ -1371,10 +1463,10 @@ section).
bc(1)
.SH STANDARDS
.PP
-The dc(1) utility operators are compliant with the operators in the IEEE
-Std 1003.1-2017 (\[lq]POSIX.1-2017\[rq]) specification at
-https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html for
-bc(1).
+The dc(1) utility operators and some behavior are compliant with the
+operators in the IEEE Std 1003.1-2017 (\[lq]POSIX.1-2017\[rq]) bc(1)
+specification at
+https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html .
.SH BUGS
.PP
None are known.
diff --git a/manuals/dc/EN.1.md b/manuals/dc/EN.1.md
index fa02ccf4b43f..357c5d250666 100644
--- a/manuals/dc/EN.1.md
+++ b/manuals/dc/EN.1.md
@@ -34,7 +34,7 @@ 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*...]
+**dc** [**-cChiPRvVx**] [**-\-version**] [**-\-help**] [**-\-digit-clamp**] [**-\-no-digit-clamp**] [**-\-interactive**] [**-\-no-prompt**] [**-\-no-read-prompt**] [**-\-extended-register**] [**-e** *expr*] [**-\-expression**=*expr*...] [**-f** *file*...] [**-\-file**=*file*...] [*file*...]
# DESCRIPTION
@@ -55,73 +55,40 @@ this dc(1) will always start with a **scale** of **10**.
The following are the options that dc(1) accepts.
-**-h**, **-\-help**
+**-C**, **-\-no-digit-clamp**
-: Prints a usage message and quits.
+: Disables clamping of digits greater than or equal to the current **ibase**
+ when parsing numbers.
-**-v**, **-V**, **-\-version**
+ This means that the value added to a number from a digit is always that
+ digit's value multiplied by the value of ibase raised to the power of the
+ digit's position, which starts from 0 at the least significant digit.
-: Print the version information (copyright header) and exit.
+ If this and/or the **-c** or **-\-digit-clamp** options are given multiple
+ times, the last one given is used.
-**-i**, **-\-interactive**
-
-: Forces interactive mode. (See the **INTERACTIVE MODE** section.)
+ This option overrides the **DC_DIGIT_CLAMP** environment variable (see the
+ **ENVIRONMENT VARIABLES** section) and the default, which can be queried
+ with the **-h** or **-\-help** options.
This is a **non-portable extension**.
-**-L**, **-\-no-line-length**
+**-c**, **-\-digit-clamp**
-: 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).
+: Enables clamping of digits greater than or equal to the current **ibase**
+ when parsing numbers.
- This is a **non-portable extension**.
+ This means that digits that the value added to a number from a digit that is
+ greater than or equal to the ibase is the value of ibase minus 1 all
+ multiplied by the value of ibase raised to the power of the digit's
+ position, which starts from 0 at the least significant digit.
-**-P**, **-\-no-prompt**
+ If this and/or the **-C** or **-\-no-digit-clamp** options are given
+ multiple times, the last one given is used.
-: 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 dc(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 option overrides the **DC_DIGIT_CLAMP** environment variable (see the
+ **ENVIRONMENT VARIABLES** section) and the default, which can be queried
+ with the **-h** or **-\-help** options.
This is a **non-portable extension**.
@@ -157,6 +124,10 @@ The following are the options that dc(1) accepts.
This is a **non-portable extension**.
+**-h**, **-\-help**
+
+: Prints a usage message and exits.
+
**-I** *ibase*, **-\-ibase**=*ibase*
: Sets the builtin variable **ibase** to the value *ibase* assuming that
@@ -166,6 +137,20 @@ The following are the options that dc(1) accepts.
This is a **non-portable extension**.
+**-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**.
+
**-O** *obase*, **-\-obase**=*obase*
: Sets the builtin variable **obase** to the value *obase* assuming that
@@ -175,6 +160,36 @@ The following are the options that dc(1) accepts.
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**.
+
**-S** *scale*, **-\-scale**=*scale*
: Sets the builtin variable **scale** to the value *scale* assuming that
@@ -184,6 +199,28 @@ The following are the options that dc(1) accepts.
This is a **non-portable extension**.
+**-v**, **-V**, **-\-version**
+
+: Print the version information (copyright header) and exits.
+
+**-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 dc(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**.
+
All long options are **non-portable extensions**.
# STDIN
@@ -263,15 +300,40 @@ Comments go from **#** until, and not including, the next newline. This is a
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**.
+Uppercase letters are equal to **9** plus 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** (i.e.,
+they are greater than or equal to the current value of **ibase**), then the
+behavior depends on the existence of the **-c**/**-\-digit-clamp** or
+**-C**/**-\-no-digit-clamp** options (see the **OPTIONS** section), the
+existence and setting of the **DC_DIGIT_CLAMP** environment variable (see the
+**ENVIRONMENT VARIABLES** section), or the default, which can be queried with
+the **-h**/**-\-help** option.
+
+If clamping is off, then digits or letters that are greater than or equal to the
+current value of **ibase** are not changed. Instead, their given value is
+multiplied by the appropriate power of **ibase** and added into the number. This
+means that, with an **ibase** of **3**, the number **AB** is equal to
+**3\^1\*A+3\^0\*B**, which is **3** times **10** plus **11**, or **41**.
+
+If clamping is on, then digits or letters that are greater than or equal to the
+current value of **ibase** are set to the value of the highest valid digit in
+**ibase** before being multiplied by the appropriate power of **ibase** and
+added into the number. This means that, with an **ibase** of **3**, the number
+**AB** is equal to **3\^1\*2+3\^0\*2**, which is **3** times **2** plus **2**,
+or **8**.
+
+There is one exception to clamping: single-character numbers (i.e., **A**
+alone). Such numbers are never clamped and always take the value they would have
+in the highest possible **ibase**. This means that **A** alone always equals
+decimal **10** and **Z** alone always equals decimal **35**. This behavior is
+mandated by the standard for bc(1) (see the STANDARDS section) and is meant to
+provide an easy way to set the current **ibase** (with the **i** command)
+regardless of the current value of **ibase**.
+
+If clamping is on, and the clamped value of a character is needed, use a leading
+zero, i.e., for **A**, use **0A**.
# COMMANDS
@@ -974,7 +1036,8 @@ be hit.
# ENVIRONMENT VARIABLES
-dc(1) recognizes the following environment variables:
+As **non-portable extensions**, dc(1) recognizes the following environment
+variables:
**DC_ENV_ARGS**
@@ -1063,6 +1126,21 @@ dc(1) recognizes the following environment variables:
This environment variable overrides the default, which can be queried with
the **-h** or **-\-help** options.
+**DC_DIGIT_CLAMP**
+
+: When parsing numbers and if this environment variable exists and contains an
+ integer, a non-zero value makes dc(1) clamp digits that are greater than or
+ equal to the current **ibase** so that all such digits are considered equal
+ to the **ibase** minus 1, and a zero value disables such clamping so that
+ those digits are always equal to their value, which is multiplied by the
+ power of the **ibase**.
+
+ This never applies to single-digit numbers, as per the bc(1) standard (see
+ the **STANDARDS** section).
+
+ 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:
@@ -1157,10 +1235,8 @@ 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 at
-https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html , and
-interactive mode requires only **stdin** and **stdout** to be connected to a
-terminal.
+in the bc(1) specification (see the **STANDARDS** section), and interactive mode
+requires only **stdin** and **stdout** to be connected to a terminal.
## Command-Line History
@@ -1238,9 +1314,9 @@ bc(1)
# STANDARDS
-The dc(1) utility operators are compliant with the operators in the IEEE Std
-1003.1-2017 (“POSIX.1-2017”) specification at
-https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html for bc(1).
+The dc(1) utility operators and some behavior are compliant with the operators
+in the IEEE Std 1003.1-2017 (“POSIX.1-2017”) bc(1) specification at
+https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html .
# BUGS
diff --git a/manuals/dc/H.1 b/manuals/dc/H.1
index 58703e03be34..7f9a18051ccf 100644
--- a/manuals/dc/H.1
+++ b/manuals/dc/H.1
@@ -25,7 +25,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.TH "DC" "1" "June 2022" "Gavin D. Howard" "General Commands Manual"
+.TH "DC" "1" "August 2022" "Gavin D. Howard" "General Commands Manual"
.nh
.ad l
.SH Name
@@ -33,17 +33,19 @@
dc - arbitrary-precision decimal reverse-Polish notation calculator
.SH SYNOPSIS
.PP
-\f[B]dc\f[R] [\f[B]-hiPRvVx\f[R]] [\f[B]--version\f[R]]
-[\f[B]--help\f[R]] [\f[B]--interactive\f[R]] [\f[B]--no-prompt\f[R]]
-[\f[B]--no-read-prompt\f[R]] [\f[B]--extended-register\f[R]]
-[\f[B]-e\f[R] \f[I]expr\f[R]]
-[\f[B]--expression\f[R]=\f[I]expr\f[R]\&...] [\f[B]-f\f[R]
-\f[I]file\f[R]\&...] [\f[B]--file\f[R]=\f[I]file\f[R]\&...]
-[\f[I]file\f[R]\&...] [\f[B]-I\f[R] \f[I]ibase\f[R]]
-[\f[B]--ibase\f[R]=\f[I]ibase\f[R]] [\f[B]-O\f[R] \f[I]obase\f[R]]
-[\f[B]--obase\f[R]=\f[I]obase\f[R]] [\f[B]-S\f[R] \f[I]scale\f[R]]
-[\f[B]--scale\f[R]=\f[I]scale\f[R]] [\f[B]-E\f[R] \f[I]seed\f[R]]
-[\f[B]--seed\f[R]=\f[I]seed\f[R]]
+\f[B]dc\f[R] [\f[B]-cChiPRvVx\f[R]] [\f[B]--version\f[R]]
+[\f[B]--help\f[R]] [\f[B]--digit-clamp\f[R]]
+[\f[B]--no-digit-clamp\f[R]] [\f[B]--interactive\f[R]]
+[\f[B]--no-prompt\f[R]] [\f[B]--no-read-prompt\f[R]]
+[\f[B]--extended-register\f[R]] [\f[B]-e\f[R] \f[I]expr\f[R]]
+[\f[B]--expression\f[R]=\f[I]expr\f[R]\&...]
+[\f[B]-f\f[R] \f[I]file\f[R]\&...]
+[\f[B]--file\f[R]=\f[I]file\f[R]\&...]
+[\f[I]file\f[R]\&...]
+[\f[B]-I\f[R] \f[I]ibase\f[R]] [\f[B]--ibase\f[R]=\f[I]ibase\f[R]]
+[\f[B]-O\f[R] \f[I]obase\f[R]] [\f[B]--obase\f[R]=\f[I]obase\f[R]]
+[\f[B]-S\f[R] \f[I]scale\f[R]] [\f[B]--scale\f[R]=\f[I]scale\f[R]]
+[\f[B]-E\f[R] \f[I]seed\f[R]] [\f[B]--seed\f[R]=\f[I]seed\f[R]]
.SH DESCRIPTION
.PP
dc(1) is an arbitrary-precision calculator.
@@ -65,83 +67,54 @@ and this dc(1) will always start with a \f[B]scale\f[R] of \f[B]10\f[R].
.PP
The following are the options that dc(1) accepts.
.TP
-\f[B]-h\f[R], \f[B]--help\f[R]
-Prints a usage message and quits.
-.TP
-\f[B]-v\f[R], \f[B]-V\f[R], \f[B]--version\f[R]
-Print the version information (copyright header) and exit.
-.TP
-\f[B]-i\f[R], \f[B]--interactive\f[R]
-Forces interactive mode.
-(See the \f[B]INTERACTIVE MODE\f[R] section.)
+\f[B]-C\f[R], \f[B]--no-digit-clamp\f[R]
+Disables clamping of digits greater than or equal to the current
+\f[B]ibase\f[R] when parsing numbers.
.RS
.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
-.TP
-\f[B]-L\f[R], \f[B]--no-line-length\f[R]
-Disables line length checking and prints numbers without backslashes and
-newlines.
-In other words, this option sets \f[B]BC_LINE_LENGTH\f[R] to \f[B]0\f[R]
-(see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
-.RS
+This means that the value added to a number from a digit is always that
+digit\[cq]s value multiplied by the value of ibase raised to the power
+of the digit\[cq]s position, which starts from 0 at the least
+significant digit.
.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
-.TP
-\f[B]-P\f[R], \f[B]--no-prompt\f[R]
-Disables the prompt in TTY mode.
-(The prompt is only enabled in TTY mode.
-See the \f[B]TTY MODE\f[R] 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
-\f[B]DC_ENV_ARGS\f[R].
-.RS
+If this and/or the \f[B]-c\f[R] or \f[B]--digit-clamp\f[R] options are
+given multiple times, the last one given is used.
.PP
-These options override the \f[B]DC_PROMPT\f[R] and \f[B]DC_TTY_MODE\f[R]
-environment variables (see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
+This option overrides the \f[B]DC_DIGIT_CLAMP\f[R] environment variable
+(see the \f[B]ENVIRONMENT VARIABLES\f[R] section) and the default, which
+can be queried with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
.PP
This is a \f[B]non-portable extension\f[R].
.RE
.TP
-\f[B]-R\f[R], \f[B]--no-read-prompt\f[R]
-Disables the read prompt in TTY mode.
-(The read prompt is only enabled in TTY mode.
-See the \f[B]TTY MODE\f[R] 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
-\f[B]BC_ENV_ARGS\f[R] (see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
-This option is also useful in hash bang lines of dc(1) scripts that
-prompt for user input.
+\f[B]-c\f[R], \f[B]--digit-clamp\f[R]
+Enables clamping of digits greater than or equal to the current
+\f[B]ibase\f[R] when parsing numbers.
.RS
.PP
-This option does not disable the regular prompt because the read prompt
-is only used when the \f[B]?\f[R] command is used.
+This means that digits that the value added to a number from a digit
+that is greater than or equal to the ibase is the value of ibase minus 1
+all multiplied by the value of ibase raised to the power of the
+digit\[cq]s position, which starts from 0 at the least significant
+digit.
.PP
-These options \f[I]do\f[R] override the \f[B]DC_PROMPT\f[R] and
-\f[B]DC_TTY_MODE\f[R] environment variables (see the \f[B]ENVIRONMENT
-VARIABLES\f[R] section), but only for the read prompt.
+If this and/or the \f[B]-C\f[R] or \f[B]--no-digit-clamp\f[R] options
+are given multiple times, the last one given is used.
.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
-.TP
-\f[B]-x\f[R] \f[B]--extended-register\f[R]
-Enables extended register mode.
-See the \f[I]Extended Register Mode\f[R] subsection of the
-\f[B]REGISTERS\f[R] section for more information.
-.RS
+This option overrides the \f[B]DC_DIGIT_CLAMP\f[R] environment variable
+(see the \f[B]ENVIRONMENT VARIABLES\f[R] section) and the default, which
+can be queried with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
.PP
This is a \f[B]non-portable extension\f[R].
.RE
.TP
-\f[B]-z\f[R], \f[B]--leading-zeroes\f[R]
-Makes dc(1) print all numbers greater than \f[B]-1\f[R] and less than
-\f[B]1\f[R], and not equal to \f[B]0\f[R], with a leading zero.
+\f[B]-E\f[R] \f[I]seed\f[R], \f[B]--seed\f[R]=\f[I]seed\f[R]
+Sets the builtin variable \f[B]seed\f[R] to the value \f[I]seed\f[R]
+assuming that \f[I]seed\f[R] is in base 10.
+It is a fatal error if \f[I]seed\f[R] is not a valid number.
.RS
.PP
-This can be set for individual numbers with the \f[B]plz(x)\f[R],
-plznl(x)**, \f[B]pnlz(x)\f[R], and \f[B]pnlznl(x)\f[R] functions in the
-extended math library (see the \f[B]LIBRARY\f[R] section).
+If multiple instances of this option are given, the last is used.
.PP
This is a \f[B]non-portable extension\f[R].
.RE
@@ -189,6 +162,9 @@ exit.
This is a \f[B]non-portable extension\f[R].
.RE
.TP
+\f[B]-h\f[R], \f[B]--help\f[R]
+Prints a usage message and exits.
+.TP
\f[B]-I\f[R] \f[I]ibase\f[R], \f[B]--ibase\f[R]=\f[I]ibase\f[R]
Sets the builtin variable \f[B]ibase\f[R] to the value \f[I]ibase\f[R]
assuming that \f[I]ibase\f[R] is in base 10.
@@ -200,6 +176,24 @@ If multiple instances of this option are given, the last is used.
This is a \f[B]non-portable extension\f[R].
.RE
.TP
+\f[B]-i\f[R], \f[B]--interactive\f[R]
+Forces interactive mode.
+(See the \f[B]INTERACTIVE MODE\f[R] section.)
+.RS
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
+\f[B]-L\f[R], \f[B]--no-line-length\f[R]
+Disables line length checking and prints numbers without backslashes and
+newlines.
+In other words, this option sets \f[B]BC_LINE_LENGTH\f[R] to \f[B]0\f[R]
+(see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
+.RS
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
\f[B]-O\f[R] \f[I]obase\f[R], \f[B]--obase\f[R]=\f[I]obase\f[R]
Sets the builtin variable \f[B]obase\f[R] to the value \f[I]obase\f[R]
assuming that \f[I]obase\f[R] is in base 10.
@@ -211,6 +205,44 @@ If multiple instances of this option are given, the last is used.
This is a \f[B]non-portable extension\f[R].
.RE
.TP
+\f[B]-P\f[R], \f[B]--no-prompt\f[R]
+Disables the prompt in TTY mode.
+(The prompt is only enabled in TTY mode.
+See the \f[B]TTY MODE\f[R] 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
+\f[B]DC_ENV_ARGS\f[R].
+.RS
+.PP
+These options override the \f[B]DC_PROMPT\f[R] and \f[B]DC_TTY_MODE\f[R]
+environment variables (see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
+\f[B]-R\f[R], \f[B]--no-read-prompt\f[R]
+Disables the read prompt in TTY mode.
+(The read prompt is only enabled in TTY mode.
+See the \f[B]TTY MODE\f[R] 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
+\f[B]BC_ENV_ARGS\f[R] (see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
+This option is also useful in hash bang lines of dc(1) scripts that
+prompt for user input.
+.RS
+.PP
+This option does not disable the regular prompt because the read prompt
+is only used when the \f[B]?\f[R] command is used.
+.PP
+These options \f[I]do\f[R] override the \f[B]DC_PROMPT\f[R] and
+\f[B]DC_TTY_MODE\f[R] environment variables (see the \f[B]ENVIRONMENT
+VARIABLES\f[R] section), but only for the read prompt.
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
\f[B]-S\f[R] \f[I]scale\f[R], \f[B]--scale\f[R]=\f[I]scale\f[R]
Sets the builtin variable \f[B]scale\f[R] to the value \f[I]scale\f[R]
assuming that \f[I]scale\f[R] is in base 10.
@@ -222,13 +254,26 @@ If multiple instances of this option are given, the last is used.
This is a \f[B]non-portable extension\f[R].
.RE
.TP
-\f[B]-E\f[R] \f[I]seed\f[R], \f[B]--seed\f[R]=\f[I]seed\f[R]
-Sets the builtin variable \f[B]seed\f[R] to the value \f[I]seed\f[R]
-assuming that \f[I]seed\f[R] is in base 10.
-It is a fatal error if \f[I]seed\f[R] is not a valid number.
+\f[B]-v\f[R], \f[B]-V\f[R], \f[B]--version\f[R]
+Print the version information (copyright header) and exits.
+.TP
+\f[B]-x\f[R] \f[B]--extended-register\f[R]
+Enables extended register mode.
+See the \f[I]Extended Register Mode\f[R] subsection of the
+\f[B]REGISTERS\f[R] section for more information.
.RS
.PP
-If multiple instances of this option are given, the last is used.
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
+\f[B]-z\f[R], \f[B]--leading-zeroes\f[R]
+Makes dc(1) print all numbers greater than \f[B]-1\f[R] and less than
+\f[B]1\f[R], and not equal to \f[B]0\f[R], with a leading zero.
+.RS
+.PP
+This can be set for individual numbers with the \f[B]plz(x)\f[R],
+plznl(x)**, \f[B]pnlz(x)\f[R], and \f[B]pnlznl(x)\f[R] functions in the
+extended math library (see the \f[B]LIBRARY\f[R] section).
.PP
This is a \f[B]non-portable extension\f[R].
.RE
@@ -360,17 +405,48 @@ This is a \f[B]non-portable extension\f[R].
Numbers are strings made up of digits, uppercase letters up to
\f[B]F\f[R], and at most \f[B]1\f[R] period for a radix.
Numbers can have up to \f[B]DC_NUM_MAX\f[R] digits.
-Uppercase letters are equal to \f[B]9\f[R] + their position in the
+Uppercase letters are equal to \f[B]9\f[R] plus their position in the
alphabet (i.e., \f[B]A\f[R] equals \f[B]10\f[R], or \f[B]9+1\f[R]).
-If a digit or letter makes no sense with the current value of
-\f[B]ibase\f[R], they are set to the value of the highest valid digit in
-\f[B]ibase\f[R].
.PP
-Single-character numbers (i.e., \f[B]A\f[R] alone) take the value that
-they would have if they were valid digits, regardless of the value of
-\f[B]ibase\f[R].
+If a digit or letter makes no sense with the current value of
+\f[B]ibase\f[R] (i.e., they are greater than or equal to the current
+value of \f[B]ibase\f[R]), then the behavior depends on the existence of
+the \f[B]-c\f[R]/\f[B]--digit-clamp\f[R] or
+\f[B]-C\f[R]/\f[B]--no-digit-clamp\f[R] options (see the
+\f[B]OPTIONS\f[R] section), the existence and setting of the
+\f[B]DC_DIGIT_CLAMP\f[R] environment variable (see the \f[B]ENVIRONMENT
+VARIABLES\f[R] section), or the default, which can be queried with the
+\f[B]-h\f[R]/\f[B]--help\f[R] option.
+.PP
+If clamping is off, then digits or letters that are greater than or
+equal to the current value of \f[B]ibase\f[R] are not changed.
+Instead, their given value is multiplied by the appropriate power of
+\f[B]ibase\f[R] and added into the number.
+This means that, with an \f[B]ibase\f[R] of \f[B]3\f[R], the number
+\f[B]AB\f[R] is equal to \f[B]3\[ha]1*A+3\[ha]0*B\f[R], which is
+\f[B]3\f[R] times \f[B]10\f[R] plus \f[B]11\f[R], or \f[B]41\f[R].
+.PP
+If clamping is on, then digits or letters that are greater than or equal
+to the current value of \f[B]ibase\f[R] are set to the value of the
+highest valid digit in \f[B]ibase\f[R] before being multiplied by the
+appropriate power of \f[B]ibase\f[R] and added into the number.
+This means that, with an \f[B]ibase\f[R] of \f[B]3\f[R], the number
+\f[B]AB\f[R] is equal to \f[B]3\[ha]1*2+3\[ha]0*2\f[R], which is
+\f[B]3\f[R] times \f[B]2\f[R] plus \f[B]2\f[R], or \f[B]8\f[R].
+.PP
+There is one exception to clamping: single-character numbers (i.e.,
+\f[B]A\f[R] alone).
+Such numbers are never clamped and always take the value they would have
+in the highest possible \f[B]ibase\f[R].
This means that \f[B]A\f[R] alone always equals decimal \f[B]10\f[R] and
-\f[B]F\f[R] alone always equals decimal \f[B]15\f[R].
+\f[B]Z\f[R] alone always equals decimal \f[B]35\f[R].
+This behavior is mandated by the standard for bc(1) (see the STANDARDS
+section) and is meant to provide an easy way to set the current
+\f[B]ibase\f[R] (with the \f[B]i\f[R] command) regardless of the current
+value of \f[B]ibase\f[R].
+.PP
+If clamping is on, and the clamped value of a character is needed, use a
+leading zero, i.e., for \f[B]A\f[R], use \f[B]0A\f[R].
.PP
In addition, dc(1) accepts numbers in scientific notation.
These have the form \f[B]<number>e<integer>\f[R].
@@ -1298,7 +1374,8 @@ at which they become a problem.
In fact, memory should be exhausted before these limits should be hit.
.SH ENVIRONMENT VARIABLES
.PP
-dc(1) recognizes the following environment variables:
+As \f[B]non-portable extensions\f[R], dc(1) recognizes the following
+environment variables:
.TP
\f[B]DC_ENV_ARGS\f[R]
This is another way to give command-line arguments to dc(1).
@@ -1402,6 +1479,22 @@ expressions and expression files, and a zero value makes dc(1) not exit.
This environment variable overrides the default, which can be queried
with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
.RE
+.TP
+\f[B]DC_DIGIT_CLAMP\f[R]
+When parsing numbers and if this environment variable exists and
+contains an integer, a non-zero value makes dc(1) clamp digits that are
+greater than or equal to the current \f[B]ibase\f[R] so that all such
+digits are considered equal to the \f[B]ibase\f[R] minus 1, and a zero
+value disables such clamping so that those digits are always equal to
+their value, which is multiplied by the power of the \f[B]ibase\f[R].
+.RS
+.PP
+This never applies to single-digit numbers, as per the bc(1) standard
+(see the \f[B]STANDARDS\f[R] section).
+.PP
+This environment variable overrides the default, which can be queried
+with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
+.RE
.SH EXIT STATUS
.PP
dc(1) returns the following exit statuses:
@@ -1505,10 +1598,9 @@ The default setting can be queried with the \f[B]-h\f[R] or
\f[B]--help\f[R] options.
.PP
TTY mode is different from interactive mode because interactive mode is
-required in the bc(1) specification at
-https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html , and
-interactive mode requires only \f[B]stdin\f[R] and \f[B]stdout\f[R] to
-be connected to a terminal.
+required in the bc(1) specification (see the \f[B]STANDARDS\f[R]
+section), and interactive mode requires only \f[B]stdin\f[R] and
+\f[B]stdout\f[R] to be connected to a terminal.
.SS Prompt
.PP
If TTY mode is available, then a prompt can be enabled.
@@ -1571,10 +1663,10 @@ locales and thus, supports \f[B]LC_MESSAGES\f[R].
bc(1)
.SH STANDARDS
.PP
-The dc(1) utility operators are compliant with the operators in the IEEE
-Std 1003.1-2017 (\[lq]POSIX.1-2017\[rq]) specification at
-https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html for
-bc(1).
+The dc(1) utility operators and some behavior are compliant with the
+operators in the IEEE Std 1003.1-2017 (\[lq]POSIX.1-2017\[rq]) bc(1)
+specification at
+https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html .
.SH BUGS
.PP
None are known.
diff --git a/manuals/dc/H.1.md b/manuals/dc/H.1.md
index 50111044d265..feab8309b693 100644
--- a/manuals/dc/H.1.md
+++ b/manuals/dc/H.1.md
@@ -34,7 +34,7 @@ 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*...] [**-I** *ibase*] [**-\-ibase**=*ibase*] [**-O** *obase*] [**-\-obase**=*obase*] [**-S** *scale*] [**-\-scale**=*scale*] [**-E** *seed*] [**-\-seed**=*seed*]
+**dc** [**-cChiPRvVx**] [**-\-version**] [**-\-help**] [**-\-digit-clamp**] [**-\-no-digit-clamp**] [**-\-interactive**] [**-\-no-prompt**] [**-\-no-read-prompt**] [**-\-extended-register**] [**-e** *expr*] [**-\-expression**=*expr*...] [**-f** *file*...] [**-\-file**=*file*...] [*file*...] [**-I** *ibase*] [**-\-ibase**=*ibase*] [**-O** *obase*] [**-\-obase**=*obase*] [**-S** *scale*] [**-\-scale**=*scale*] [**-E** *seed*] [**-\-seed**=*seed*]
# DESCRIPTION
@@ -55,73 +55,49 @@ this dc(1) will always start with a **scale** of **10**.
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).
+**-C**, **-\-no-digit-clamp**
- This is a **non-portable extension**.
+: Disables clamping of digits greater than or equal to the current **ibase**
+ when parsing numbers.
-**-P**, **-\-no-prompt**
+ This means that the value added to a number from a digit is always that
+ digit's value multiplied by the value of ibase raised to the power of the
+ digit's position, which starts from 0 at the least significant digit.
-: 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**.
+ If this and/or the **-c** or **-\-digit-clamp** options are given multiple
+ times, the last one given is used.
- These options override the **DC_PROMPT** and **DC_TTY_MODE** environment
- variables (see the **ENVIRONMENT VARIABLES** section).
+ This option overrides the **DC_DIGIT_CLAMP** environment variable (see the
+ **ENVIRONMENT VARIABLES** section) and the default, which can be queried
+ with the **-h** or **-\-help** options.
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.
+**-c**, **-\-digit-clamp**
- These options *do* override the **DC_PROMPT** and **DC_TTY_MODE**
- environment variables (see the **ENVIRONMENT VARIABLES** section), but only
- for the read prompt.
+: Enables clamping of digits greater than or equal to the current **ibase**
+ when parsing numbers.
- This is a **non-portable extension**.
+ This means that digits that the value added to a number from a digit that is
+ greater than or equal to the ibase is the value of ibase minus 1 all
+ multiplied by the value of ibase raised to the power of the digit's
+ position, which starts from 0 at the least significant digit.
-**-x** **-\-extended-register**
+ If this and/or the **-C** or **-\-no-digit-clamp** options are given
+ multiple times, the last one given is used.
-: Enables extended register mode. See the *Extended Register Mode* subsection
- of the **REGISTERS** section for more information.
+ This option overrides the **DC_DIGIT_CLAMP** environment variable (see the
+ **ENVIRONMENT VARIABLES** section) and the default, which can be queried
+ with the **-h** or **-\-help** options.
This is a **non-portable extension**.
-**-z**, **-\-leading-zeroes**
+**-E** *seed*, **-\-seed**=*seed*
-: Makes dc(1) print all numbers greater than **-1** and less than **1**, and
- not equal to **0**, with a leading zero.
+: Sets the builtin variable **seed** to the value *seed* assuming that *seed*
+ is in base 10. It is a fatal error if *seed* is not a valid number.
- 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).
+ If multiple instances of this option are given, the last is used.
This is a **non-portable extension**.
@@ -157,6 +133,10 @@ The following are the options that dc(1) accepts.
This is a **non-portable extension**.
+**-h**, **-\-help**
+
+: Prints a usage message and exits.
+
**-I** *ibase*, **-\-ibase**=*ibase*
: Sets the builtin variable **ibase** to the value *ibase* assuming that
@@ -166,6 +146,20 @@ The following are the options that dc(1) accepts.
This is a **non-portable extension**.
+**-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**.
+
**-O** *obase*, **-\-obase**=*obase*
: Sets the builtin variable **obase** to the value *obase* assuming that
@@ -175,6 +169,36 @@ The following are the options that dc(1) accepts.
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**.
+
**-S** *scale*, **-\-scale**=*scale*
: Sets the builtin variable **scale** to the value *scale* assuming that
@@ -184,12 +208,25 @@ The following are the options that dc(1) accepts.
This is a **non-portable extension**.
-**-E** *seed*, **-\-seed**=*seed*
+**-v**, **-V**, **-\-version**
-: Sets the builtin variable **seed** to the value *seed* assuming that *seed*
- is in base 10. It is a fatal error if *seed* is not a valid number.
+: Print the version information (copyright header) and exits.
- If multiple instances of this option are given, the last is used.
+**-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 dc(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**.
@@ -302,15 +339,40 @@ Comments go from **#** until, and not including, the next newline. This is a
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**.
+Uppercase letters are equal to **9** plus 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** (i.e.,
+they are greater than or equal to the current value of **ibase**), then the
+behavior depends on the existence of the **-c**/**-\-digit-clamp** or
+**-C**/**-\-no-digit-clamp** options (see the **OPTIONS** section), the
+existence and setting of the **DC_DIGIT_CLAMP** environment variable (see the
+**ENVIRONMENT VARIABLES** section), or the default, which can be queried with
+the **-h**/**-\-help** option.
+
+If clamping is off, then digits or letters that are greater than or equal to the
+current value of **ibase** are not changed. Instead, their given value is
+multiplied by the appropriate power of **ibase** and added into the number. This
+means that, with an **ibase** of **3**, the number **AB** is equal to
+**3\^1\*A+3\^0\*B**, which is **3** times **10** plus **11**, or **41**.
+
+If clamping is on, then digits or letters that are greater than or equal to the
+current value of **ibase** are set to the value of the highest valid digit in
+**ibase** before being multiplied by the appropriate power of **ibase** and
+added into the number. This means that, with an **ibase** of **3**, the number
+**AB** is equal to **3\^1\*2+3\^0\*2**, which is **3** times **2** plus **2**,
+or **8**.
+
+There is one exception to clamping: single-character numbers (i.e., **A**
+alone). Such numbers are never clamped and always take the value they would have
+in the highest possible **ibase**. This means that **A** alone always equals
+decimal **10** and **Z** alone always equals decimal **35**. This behavior is
+mandated by the standard for bc(1) (see the STANDARDS section) and is meant to
+provide an easy way to set the current **ibase** (with the **i** command)
+regardless of the current value of **ibase**.
+
+If clamping is on, and the clamped value of a character is needed, use a leading
+zero, i.e., for **A**, use **0A**.
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
@@ -1148,7 +1210,8 @@ be hit.
# ENVIRONMENT VARIABLES
-dc(1) recognizes the following environment variables:
+As **non-portable extensions**, dc(1) recognizes the following environment
+variables:
**DC_ENV_ARGS**
@@ -1237,6 +1300,21 @@ dc(1) recognizes the following environment variables:
This environment variable overrides the default, which can be queried with
the **-h** or **-\-help** options.
+**DC_DIGIT_CLAMP**
+
+: When parsing numbers and if this environment variable exists and contains an
+ integer, a non-zero value makes dc(1) clamp digits that are greater than or
+ equal to the current **ibase** so that all such digits are considered equal
+ to the **ibase** minus 1, and a zero value disables such clamping so that
+ those digits are always equal to their value, which is multiplied by the
+ power of the **ibase**.
+
+ This never applies to single-digit numbers, as per the bc(1) standard (see
+ the **STANDARDS** section).
+
+ 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:
@@ -1333,10 +1411,8 @@ 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 at
-https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html , and
-interactive mode requires only **stdin** and **stdout** to be connected to a
-terminal.
+in the bc(1) specification (see the **STANDARDS** section), and interactive mode
+requires only **stdin** and **stdout** to be connected to a terminal.
## Prompt
@@ -1396,9 +1472,9 @@ bc(1)
# STANDARDS
-The dc(1) utility operators are compliant with the operators in the IEEE Std
-1003.1-2017 (“POSIX.1-2017”) specification at
-https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html for bc(1).
+The dc(1) utility operators and some behavior are compliant with the operators
+in the IEEE Std 1003.1-2017 (“POSIX.1-2017”) bc(1) specification at
+https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html .
# BUGS
diff --git a/manuals/dc/HN.1 b/manuals/dc/HN.1
index d67e2325817e..0c5db06234b7 100644
--- a/manuals/dc/HN.1
+++ b/manuals/dc/HN.1
@@ -25,7 +25,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.TH "DC" "1" "June 2022" "Gavin D. Howard" "General Commands Manual"
+.TH "DC" "1" "August 2022" "Gavin D. Howard" "General Commands Manual"
.nh
.ad l
.SH Name
@@ -33,17 +33,19 @@
dc - arbitrary-precision decimal reverse-Polish notation calculator
.SH SYNOPSIS
.PP
-\f[B]dc\f[R] [\f[B]-hiPRvVx\f[R]] [\f[B]--version\f[R]]
-[\f[B]--help\f[R]] [\f[B]--interactive\f[R]] [\f[B]--no-prompt\f[R]]
-[\f[B]--no-read-prompt\f[R]] [\f[B]--extended-register\f[R]]
-[\f[B]-e\f[R] \f[I]expr\f[R]]
-[\f[B]--expression\f[R]=\f[I]expr\f[R]\&...] [\f[B]-f\f[R]
-\f[I]file\f[R]\&...] [\f[B]--file\f[R]=\f[I]file\f[R]\&...]
-[\f[I]file\f[R]\&...] [\f[B]-I\f[R] \f[I]ibase\f[R]]
-[\f[B]--ibase\f[R]=\f[I]ibase\f[R]] [\f[B]-O\f[R] \f[I]obase\f[R]]
-[\f[B]--obase\f[R]=\f[I]obase\f[R]] [\f[B]-S\f[R] \f[I]scale\f[R]]
-[\f[B]--scale\f[R]=\f[I]scale\f[R]] [\f[B]-E\f[R] \f[I]seed\f[R]]
-[\f[B]--seed\f[R]=\f[I]seed\f[R]]
+\f[B]dc\f[R] [\f[B]-cChiPRvVx\f[R]] [\f[B]--version\f[R]]
+[\f[B]--help\f[R]] [\f[B]--digit-clamp\f[R]]
+[\f[B]--no-digit-clamp\f[R]] [\f[B]--interactive\f[R]]
+[\f[B]--no-prompt\f[R]] [\f[B]--no-read-prompt\f[R]]
+[\f[B]--extended-register\f[R]] [\f[B]-e\f[R] \f[I]expr\f[R]]
+[\f[B]--expression\f[R]=\f[I]expr\f[R]\&...]
+[\f[B]-f\f[R] \f[I]file\f[R]\&...]
+[\f[B]--file\f[R]=\f[I]file\f[R]\&...]
+[\f[I]file\f[R]\&...]
+[\f[B]-I\f[R] \f[I]ibase\f[R]] [\f[B]--ibase\f[R]=\f[I]ibase\f[R]]
+[\f[B]-O\f[R] \f[I]obase\f[R]] [\f[B]--obase\f[R]=\f[I]obase\f[R]]
+[\f[B]-S\f[R] \f[I]scale\f[R]] [\f[B]--scale\f[R]=\f[I]scale\f[R]]
+[\f[B]-E\f[R] \f[I]seed\f[R]] [\f[B]--seed\f[R]=\f[I]seed\f[R]]
.SH DESCRIPTION
.PP
dc(1) is an arbitrary-precision calculator.
@@ -65,83 +67,54 @@ and this dc(1) will always start with a \f[B]scale\f[R] of \f[B]10\f[R].
.PP
The following are the options that dc(1) accepts.
.TP
-\f[B]-h\f[R], \f[B]--help\f[R]
-Prints a usage message and quits.
-.TP
-\f[B]-v\f[R], \f[B]-V\f[R], \f[B]--version\f[R]
-Print the version information (copyright header) and exit.
-.TP
-\f[B]-i\f[R], \f[B]--interactive\f[R]
-Forces interactive mode.
-(See the \f[B]INTERACTIVE MODE\f[R] section.)
+\f[B]-C\f[R], \f[B]--no-digit-clamp\f[R]
+Disables clamping of digits greater than or equal to the current
+\f[B]ibase\f[R] when parsing numbers.
.RS
.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
-.TP
-\f[B]-L\f[R], \f[B]--no-line-length\f[R]
-Disables line length checking and prints numbers without backslashes and
-newlines.
-In other words, this option sets \f[B]BC_LINE_LENGTH\f[R] to \f[B]0\f[R]
-(see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
-.RS
+This means that the value added to a number from a digit is always that
+digit\[cq]s value multiplied by the value of ibase raised to the power
+of the digit\[cq]s position, which starts from 0 at the least
+significant digit.
.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
-.TP
-\f[B]-P\f[R], \f[B]--no-prompt\f[R]
-Disables the prompt in TTY mode.
-(The prompt is only enabled in TTY mode.
-See the \f[B]TTY MODE\f[R] 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
-\f[B]DC_ENV_ARGS\f[R].
-.RS
+If this and/or the \f[B]-c\f[R] or \f[B]--digit-clamp\f[R] options are
+given multiple times, the last one given is used.
.PP
-These options override the \f[B]DC_PROMPT\f[R] and \f[B]DC_TTY_MODE\f[R]
-environment variables (see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
+This option overrides the \f[B]DC_DIGIT_CLAMP\f[R] environment variable
+(see the \f[B]ENVIRONMENT VARIABLES\f[R] section) and the default, which
+can be queried with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
.PP
This is a \f[B]non-portable extension\f[R].
.RE
.TP
-\f[B]-R\f[R], \f[B]--no-read-prompt\f[R]
-Disables the read prompt in TTY mode.
-(The read prompt is only enabled in TTY mode.
-See the \f[B]TTY MODE\f[R] 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
-\f[B]BC_ENV_ARGS\f[R] (see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
-This option is also useful in hash bang lines of dc(1) scripts that
-prompt for user input.
+\f[B]-c\f[R], \f[B]--digit-clamp\f[R]
+Enables clamping of digits greater than or equal to the current
+\f[B]ibase\f[R] when parsing numbers.
.RS
.PP
-This option does not disable the regular prompt because the read prompt
-is only used when the \f[B]?\f[R] command is used.
+This means that digits that the value added to a number from a digit
+that is greater than or equal to the ibase is the value of ibase minus 1
+all multiplied by the value of ibase raised to the power of the
+digit\[cq]s position, which starts from 0 at the least significant
+digit.
.PP
-These options \f[I]do\f[R] override the \f[B]DC_PROMPT\f[R] and
-\f[B]DC_TTY_MODE\f[R] environment variables (see the \f[B]ENVIRONMENT
-VARIABLES\f[R] section), but only for the read prompt.
+If this and/or the \f[B]-C\f[R] or \f[B]--no-digit-clamp\f[R] options
+are given multiple times, the last one given is used.
.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
-.TP
-\f[B]-x\f[R] \f[B]--extended-register\f[R]
-Enables extended register mode.
-See the \f[I]Extended Register Mode\f[R] subsection of the
-\f[B]REGISTERS\f[R] section for more information.
-.RS
+This option overrides the \f[B]DC_DIGIT_CLAMP\f[R] environment variable
+(see the \f[B]ENVIRONMENT VARIABLES\f[R] section) and the default, which
+can be queried with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
.PP
This is a \f[B]non-portable extension\f[R].
.RE
.TP
-\f[B]-z\f[R], \f[B]--leading-zeroes\f[R]
-Makes dc(1) print all numbers greater than \f[B]-1\f[R] and less than
-\f[B]1\f[R], and not equal to \f[B]0\f[R], with a leading zero.
+\f[B]-E\f[R] \f[I]seed\f[R], \f[B]--seed\f[R]=\f[I]seed\f[R]
+Sets the builtin variable \f[B]seed\f[R] to the value \f[I]seed\f[R]
+assuming that \f[I]seed\f[R] is in base 10.
+It is a fatal error if \f[I]seed\f[R] is not a valid number.
.RS
.PP
-This can be set for individual numbers with the \f[B]plz(x)\f[R],
-plznl(x)**, \f[B]pnlz(x)\f[R], and \f[B]pnlznl(x)\f[R] functions in the
-extended math library (see the \f[B]LIBRARY\f[R] section).
+If multiple instances of this option are given, the last is used.
.PP
This is a \f[B]non-portable extension\f[R].
.RE
@@ -189,6 +162,9 @@ exit.
This is a \f[B]non-portable extension\f[R].
.RE
.TP
+\f[B]-h\f[R], \f[B]--help\f[R]
+Prints a usage message and exits.
+.TP
\f[B]-I\f[R] \f[I]ibase\f[R], \f[B]--ibase\f[R]=\f[I]ibase\f[R]
Sets the builtin variable \f[B]ibase\f[R] to the value \f[I]ibase\f[R]
assuming that \f[I]ibase\f[R] is in base 10.
@@ -200,6 +176,24 @@ If multiple instances of this option are given, the last is used.
This is a \f[B]non-portable extension\f[R].
.RE
.TP
+\f[B]-i\f[R], \f[B]--interactive\f[R]
+Forces interactive mode.
+(See the \f[B]INTERACTIVE MODE\f[R] section.)
+.RS
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
+\f[B]-L\f[R], \f[B]--no-line-length\f[R]
+Disables line length checking and prints numbers without backslashes and
+newlines.
+In other words, this option sets \f[B]BC_LINE_LENGTH\f[R] to \f[B]0\f[R]
+(see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
+.RS
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
\f[B]-O\f[R] \f[I]obase\f[R], \f[B]--obase\f[R]=\f[I]obase\f[R]
Sets the builtin variable \f[B]obase\f[R] to the value \f[I]obase\f[R]
assuming that \f[I]obase\f[R] is in base 10.
@@ -211,6 +205,44 @@ If multiple instances of this option are given, the last is used.
This is a \f[B]non-portable extension\f[R].
.RE
.TP
+\f[B]-P\f[R], \f[B]--no-prompt\f[R]
+Disables the prompt in TTY mode.
+(The prompt is only enabled in TTY mode.
+See the \f[B]TTY MODE\f[R] 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
+\f[B]DC_ENV_ARGS\f[R].
+.RS
+.PP
+These options override the \f[B]DC_PROMPT\f[R] and \f[B]DC_TTY_MODE\f[R]
+environment variables (see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
+\f[B]-R\f[R], \f[B]--no-read-prompt\f[R]
+Disables the read prompt in TTY mode.
+(The read prompt is only enabled in TTY mode.
+See the \f[B]TTY MODE\f[R] 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
+\f[B]BC_ENV_ARGS\f[R] (see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
+This option is also useful in hash bang lines of dc(1) scripts that
+prompt for user input.
+.RS
+.PP
+This option does not disable the regular prompt because the read prompt
+is only used when the \f[B]?\f[R] command is used.
+.PP
+These options \f[I]do\f[R] override the \f[B]DC_PROMPT\f[R] and
+\f[B]DC_TTY_MODE\f[R] environment variables (see the \f[B]ENVIRONMENT
+VARIABLES\f[R] section), but only for the read prompt.
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
\f[B]-S\f[R] \f[I]scale\f[R], \f[B]--scale\f[R]=\f[I]scale\f[R]
Sets the builtin variable \f[B]scale\f[R] to the value \f[I]scale\f[R]
assuming that \f[I]scale\f[R] is in base 10.
@@ -222,13 +254,26 @@ If multiple instances of this option are given, the last is used.
This is a \f[B]non-portable extension\f[R].
.RE
.TP
-\f[B]-E\f[R] \f[I]seed\f[R], \f[B]--seed\f[R]=\f[I]seed\f[R]
-Sets the builtin variable \f[B]seed\f[R] to the value \f[I]seed\f[R]
-assuming that \f[I]seed\f[R] is in base 10.
-It is a fatal error if \f[I]seed\f[R] is not a valid number.
+\f[B]-v\f[R], \f[B]-V\f[R], \f[B]--version\f[R]
+Print the version information (copyright header) and exits.
+.TP
+\f[B]-x\f[R] \f[B]--extended-register\f[R]
+Enables extended register mode.
+See the \f[I]Extended Register Mode\f[R] subsection of the
+\f[B]REGISTERS\f[R] section for more information.
.RS
.PP
-If multiple instances of this option are given, the last is used.
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
+\f[B]-z\f[R], \f[B]--leading-zeroes\f[R]
+Makes dc(1) print all numbers greater than \f[B]-1\f[R] and less than
+\f[B]1\f[R], and not equal to \f[B]0\f[R], with a leading zero.
+.RS
+.PP
+This can be set for individual numbers with the \f[B]plz(x)\f[R],
+plznl(x)**, \f[B]pnlz(x)\f[R], and \f[B]pnlznl(x)\f[R] functions in the
+extended math library (see the \f[B]LIBRARY\f[R] section).
.PP
This is a \f[B]non-portable extension\f[R].
.RE
@@ -360,17 +405,48 @@ This is a \f[B]non-portable extension\f[R].
Numbers are strings made up of digits, uppercase letters up to
\f[B]F\f[R], and at most \f[B]1\f[R] period for a radix.
Numbers can have up to \f[B]DC_NUM_MAX\f[R] digits.
-Uppercase letters are equal to \f[B]9\f[R] + their position in the
+Uppercase letters are equal to \f[B]9\f[R] plus their position in the
alphabet (i.e., \f[B]A\f[R] equals \f[B]10\f[R], or \f[B]9+1\f[R]).
-If a digit or letter makes no sense with the current value of
-\f[B]ibase\f[R], they are set to the value of the highest valid digit in
-\f[B]ibase\f[R].
.PP
-Single-character numbers (i.e., \f[B]A\f[R] alone) take the value that
-they would have if they were valid digits, regardless of the value of
-\f[B]ibase\f[R].
+If a digit or letter makes no sense with the current value of
+\f[B]ibase\f[R] (i.e., they are greater than or equal to the current
+value of \f[B]ibase\f[R]), then the behavior depends on the existence of
+the \f[B]-c\f[R]/\f[B]--digit-clamp\f[R] or
+\f[B]-C\f[R]/\f[B]--no-digit-clamp\f[R] options (see the
+\f[B]OPTIONS\f[R] section), the existence and setting of the
+\f[B]DC_DIGIT_CLAMP\f[R] environment variable (see the \f[B]ENVIRONMENT
+VARIABLES\f[R] section), or the default, which can be queried with the
+\f[B]-h\f[R]/\f[B]--help\f[R] option.
+.PP
+If clamping is off, then digits or letters that are greater than or
+equal to the current value of \f[B]ibase\f[R] are not changed.
+Instead, their given value is multiplied by the appropriate power of
+\f[B]ibase\f[R] and added into the number.
+This means that, with an \f[B]ibase\f[R] of \f[B]3\f[R], the number
+\f[B]AB\f[R] is equal to \f[B]3\[ha]1*A+3\[ha]0*B\f[R], which is
+\f[B]3\f[R] times \f[B]10\f[R] plus \f[B]11\f[R], or \f[B]41\f[R].
+.PP
+If clamping is on, then digits or letters that are greater than or equal
+to the current value of \f[B]ibase\f[R] are set to the value of the
+highest valid digit in \f[B]ibase\f[R] before being multiplied by the
+appropriate power of \f[B]ibase\f[R] and added into the number.
+This means that, with an \f[B]ibase\f[R] of \f[B]3\f[R], the number
+\f[B]AB\f[R] is equal to \f[B]3\[ha]1*2+3\[ha]0*2\f[R], which is
+\f[B]3\f[R] times \f[B]2\f[R] plus \f[B]2\f[R], or \f[B]8\f[R].
+.PP
+There is one exception to clamping: single-character numbers (i.e.,
+\f[B]A\f[R] alone).
+Such numbers are never clamped and always take the value they would have
+in the highest possible \f[B]ibase\f[R].
This means that \f[B]A\f[R] alone always equals decimal \f[B]10\f[R] and
-\f[B]F\f[R] alone always equals decimal \f[B]15\f[R].
+\f[B]Z\f[R] alone always equals decimal \f[B]35\f[R].
+This behavior is mandated by the standard for bc(1) (see the STANDARDS
+section) and is meant to provide an easy way to set the current
+\f[B]ibase\f[R] (with the \f[B]i\f[R] command) regardless of the current
+value of \f[B]ibase\f[R].
+.PP
+If clamping is on, and the clamped value of a character is needed, use a
+leading zero, i.e., for \f[B]A\f[R], use \f[B]0A\f[R].
.PP
In addition, dc(1) accepts numbers in scientific notation.
These have the form \f[B]<number>e<integer>\f[R].
@@ -1298,7 +1374,8 @@ at which they become a problem.
In fact, memory should be exhausted before these limits should be hit.
.SH ENVIRONMENT VARIABLES
.PP
-dc(1) recognizes the following environment variables:
+As \f[B]non-portable extensions\f[R], dc(1) recognizes the following
+environment variables:
.TP
\f[B]DC_ENV_ARGS\f[R]
This is another way to give command-line arguments to dc(1).
@@ -1402,6 +1479,22 @@ expressions and expression files, and a zero value makes dc(1) not exit.
This environment variable overrides the default, which can be queried
with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
.RE
+.TP
+\f[B]DC_DIGIT_CLAMP\f[R]
+When parsing numbers and if this environment variable exists and
+contains an integer, a non-zero value makes dc(1) clamp digits that are
+greater than or equal to the current \f[B]ibase\f[R] so that all such
+digits are considered equal to the \f[B]ibase\f[R] minus 1, and a zero
+value disables such clamping so that those digits are always equal to
+their value, which is multiplied by the power of the \f[B]ibase\f[R].
+.RS
+.PP
+This never applies to single-digit numbers, as per the bc(1) standard
+(see the \f[B]STANDARDS\f[R] section).
+.PP
+This environment variable overrides the default, which can be queried
+with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
+.RE
.SH EXIT STATUS
.PP
dc(1) returns the following exit statuses:
@@ -1505,10 +1598,9 @@ The default setting can be queried with the \f[B]-h\f[R] or
\f[B]--help\f[R] options.
.PP
TTY mode is different from interactive mode because interactive mode is
-required in the bc(1) specification at
-https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html , and
-interactive mode requires only \f[B]stdin\f[R] and \f[B]stdout\f[R] to
-be connected to a terminal.
+required in the bc(1) specification (see the \f[B]STANDARDS\f[R]
+section), and interactive mode requires only \f[B]stdin\f[R] and
+\f[B]stdout\f[R] to be connected to a terminal.
.SS Prompt
.PP
If TTY mode is available, then a prompt can be enabled.
@@ -1567,10 +1659,10 @@ exit, and it uses the default handler for all other signals.
bc(1)
.SH STANDARDS
.PP
-The dc(1) utility operators are compliant with the operators in the IEEE
-Std 1003.1-2017 (\[lq]POSIX.1-2017\[rq]) specification at
-https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html for
-bc(1).
+The dc(1) utility operators and some behavior are compliant with the
+operators in the IEEE Std 1003.1-2017 (\[lq]POSIX.1-2017\[rq]) bc(1)
+specification at
+https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html .
.SH BUGS
.PP
None are known.
diff --git a/manuals/dc/HN.1.md b/manuals/dc/HN.1.md
index 79292243304c..81badc9edb67 100644
--- a/manuals/dc/HN.1.md
+++ b/manuals/dc/HN.1.md
@@ -34,7 +34,7 @@ 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*...] [**-I** *ibase*] [**-\-ibase**=*ibase*] [**-O** *obase*] [**-\-obase**=*obase*] [**-S** *scale*] [**-\-scale**=*scale*] [**-E** *seed*] [**-\-seed**=*seed*]
+**dc** [**-cChiPRvVx**] [**-\-version**] [**-\-help**] [**-\-digit-clamp**] [**-\-no-digit-clamp**] [**-\-interactive**] [**-\-no-prompt**] [**-\-no-read-prompt**] [**-\-extended-register**] [**-e** *expr*] [**-\-expression**=*expr*...] [**-f** *file*...] [**-\-file**=*file*...] [*file*...] [**-I** *ibase*] [**-\-ibase**=*ibase*] [**-O** *obase*] [**-\-obase**=*obase*] [**-S** *scale*] [**-\-scale**=*scale*] [**-E** *seed*] [**-\-seed**=*seed*]
# DESCRIPTION
@@ -55,73 +55,49 @@ this dc(1) will always start with a **scale** of **10**.
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).
+**-C**, **-\-no-digit-clamp**
- This is a **non-portable extension**.
+: Disables clamping of digits greater than or equal to the current **ibase**
+ when parsing numbers.
-**-P**, **-\-no-prompt**
+ This means that the value added to a number from a digit is always that
+ digit's value multiplied by the value of ibase raised to the power of the
+ digit's position, which starts from 0 at the least significant digit.
-: 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**.
+ If this and/or the **-c** or **-\-digit-clamp** options are given multiple
+ times, the last one given is used.
- These options override the **DC_PROMPT** and **DC_TTY_MODE** environment
- variables (see the **ENVIRONMENT VARIABLES** section).
+ This option overrides the **DC_DIGIT_CLAMP** environment variable (see the
+ **ENVIRONMENT VARIABLES** section) and the default, which can be queried
+ with the **-h** or **-\-help** options.
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.
+**-c**, **-\-digit-clamp**
- These options *do* override the **DC_PROMPT** and **DC_TTY_MODE**
- environment variables (see the **ENVIRONMENT VARIABLES** section), but only
- for the read prompt.
+: Enables clamping of digits greater than or equal to the current **ibase**
+ when parsing numbers.
- This is a **non-portable extension**.
+ This means that digits that the value added to a number from a digit that is
+ greater than or equal to the ibase is the value of ibase minus 1 all
+ multiplied by the value of ibase raised to the power of the digit's
+ position, which starts from 0 at the least significant digit.
-**-x** **-\-extended-register**
+ If this and/or the **-C** or **-\-no-digit-clamp** options are given
+ multiple times, the last one given is used.
-: Enables extended register mode. See the *Extended Register Mode* subsection
- of the **REGISTERS** section for more information.
+ This option overrides the **DC_DIGIT_CLAMP** environment variable (see the
+ **ENVIRONMENT VARIABLES** section) and the default, which can be queried
+ with the **-h** or **-\-help** options.
This is a **non-portable extension**.
-**-z**, **-\-leading-zeroes**
+**-E** *seed*, **-\-seed**=*seed*
-: Makes dc(1) print all numbers greater than **-1** and less than **1**, and
- not equal to **0**, with a leading zero.
+: Sets the builtin variable **seed** to the value *seed* assuming that *seed*
+ is in base 10. It is a fatal error if *seed* is not a valid number.
- 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).
+ If multiple instances of this option are given, the last is used.
This is a **non-portable extension**.
@@ -157,6 +133,10 @@ The following are the options that dc(1) accepts.
This is a **non-portable extension**.
+**-h**, **-\-help**
+
+: Prints a usage message and exits.
+
**-I** *ibase*, **-\-ibase**=*ibase*
: Sets the builtin variable **ibase** to the value *ibase* assuming that
@@ -166,6 +146,20 @@ The following are the options that dc(1) accepts.
This is a **non-portable extension**.
+**-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**.
+
**-O** *obase*, **-\-obase**=*obase*
: Sets the builtin variable **obase** to the value *obase* assuming that
@@ -175,6 +169,36 @@ The following are the options that dc(1) accepts.
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**.
+
**-S** *scale*, **-\-scale**=*scale*
: Sets the builtin variable **scale** to the value *scale* assuming that
@@ -184,12 +208,25 @@ The following are the options that dc(1) accepts.
This is a **non-portable extension**.
-**-E** *seed*, **-\-seed**=*seed*
+**-v**, **-V**, **-\-version**
-: Sets the builtin variable **seed** to the value *seed* assuming that *seed*
- is in base 10. It is a fatal error if *seed* is not a valid number.
+: Print the version information (copyright header) and exits.
- If multiple instances of this option are given, the last is used.
+**-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 dc(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**.
@@ -302,15 +339,40 @@ Comments go from **#** until, and not including, the next newline. This is a
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**.
+Uppercase letters are equal to **9** plus 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** (i.e.,
+they are greater than or equal to the current value of **ibase**), then the
+behavior depends on the existence of the **-c**/**-\-digit-clamp** or
+**-C**/**-\-no-digit-clamp** options (see the **OPTIONS** section), the
+existence and setting of the **DC_DIGIT_CLAMP** environment variable (see the
+**ENVIRONMENT VARIABLES** section), or the default, which can be queried with
+the **-h**/**-\-help** option.
+
+If clamping is off, then digits or letters that are greater than or equal to the
+current value of **ibase** are not changed. Instead, their given value is
+multiplied by the appropriate power of **ibase** and added into the number. This
+means that, with an **ibase** of **3**, the number **AB** is equal to
+**3\^1\*A+3\^0\*B**, which is **3** times **10** plus **11**, or **41**.
+
+If clamping is on, then digits or letters that are greater than or equal to the
+current value of **ibase** are set to the value of the highest valid digit in
+**ibase** before being multiplied by the appropriate power of **ibase** and
+added into the number. This means that, with an **ibase** of **3**, the number
+**AB** is equal to **3\^1\*2+3\^0\*2**, which is **3** times **2** plus **2**,
+or **8**.
+
+There is one exception to clamping: single-character numbers (i.e., **A**
+alone). Such numbers are never clamped and always take the value they would have
+in the highest possible **ibase**. This means that **A** alone always equals
+decimal **10** and **Z** alone always equals decimal **35**. This behavior is
+mandated by the standard for bc(1) (see the STANDARDS section) and is meant to
+provide an easy way to set the current **ibase** (with the **i** command)
+regardless of the current value of **ibase**.
+
+If clamping is on, and the clamped value of a character is needed, use a leading
+zero, i.e., for **A**, use **0A**.
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
@@ -1148,7 +1210,8 @@ be hit.
# ENVIRONMENT VARIABLES
-dc(1) recognizes the following environment variables:
+As **non-portable extensions**, dc(1) recognizes the following environment
+variables:
**DC_ENV_ARGS**
@@ -1237,6 +1300,21 @@ dc(1) recognizes the following environment variables:
This environment variable overrides the default, which can be queried with
the **-h** or **-\-help** options.
+**DC_DIGIT_CLAMP**
+
+: When parsing numbers and if this environment variable exists and contains an
+ integer, a non-zero value makes dc(1) clamp digits that are greater than or
+ equal to the current **ibase** so that all such digits are considered equal
+ to the **ibase** minus 1, and a zero value disables such clamping so that
+ those digits are always equal to their value, which is multiplied by the
+ power of the **ibase**.
+
+ This never applies to single-digit numbers, as per the bc(1) standard (see
+ the **STANDARDS** section).
+
+ 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:
@@ -1333,10 +1411,8 @@ 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 at
-https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html , and
-interactive mode requires only **stdin** and **stdout** to be connected to a
-terminal.
+in the bc(1) specification (see the **STANDARDS** section), and interactive mode
+requires only **stdin** and **stdout** to be connected to a terminal.
## Prompt
@@ -1391,9 +1467,9 @@ bc(1)
# STANDARDS
-The dc(1) utility operators are compliant with the operators in the IEEE Std
-1003.1-2017 (“POSIX.1-2017”) specification at
-https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html for bc(1).
+The dc(1) utility operators and some behavior are compliant with the operators
+in the IEEE Std 1003.1-2017 (“POSIX.1-2017”) bc(1) specification at
+https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html .
# BUGS
diff --git a/manuals/dc/N.1 b/manuals/dc/N.1
index 39782bf95e5e..b3e13537e6a8 100644
--- a/manuals/dc/N.1
+++ b/manuals/dc/N.1
@@ -25,7 +25,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.TH "DC" "1" "June 2022" "Gavin D. Howard" "General Commands Manual"
+.TH "DC" "1" "August 2022" "Gavin D. Howard" "General Commands Manual"
.nh
.ad l
.SH Name
@@ -33,17 +33,19 @@
dc - arbitrary-precision decimal reverse-Polish notation calculator
.SH SYNOPSIS
.PP
-\f[B]dc\f[R] [\f[B]-hiPRvVx\f[R]] [\f[B]--version\f[R]]
-[\f[B]--help\f[R]] [\f[B]--interactive\f[R]] [\f[B]--no-prompt\f[R]]
-[\f[B]--no-read-prompt\f[R]] [\f[B]--extended-register\f[R]]
-[\f[B]-e\f[R] \f[I]expr\f[R]]
-[\f[B]--expression\f[R]=\f[I]expr\f[R]\&...] [\f[B]-f\f[R]
-\f[I]file\f[R]\&...] [\f[B]--file\f[R]=\f[I]file\f[R]\&...]
-[\f[I]file\f[R]\&...] [\f[B]-I\f[R] \f[I]ibase\f[R]]
-[\f[B]--ibase\f[R]=\f[I]ibase\f[R]] [\f[B]-O\f[R] \f[I]obase\f[R]]
-[\f[B]--obase\f[R]=\f[I]obase\f[R]] [\f[B]-S\f[R] \f[I]scale\f[R]]
-[\f[B]--scale\f[R]=\f[I]scale\f[R]] [\f[B]-E\f[R] \f[I]seed\f[R]]
-[\f[B]--seed\f[R]=\f[I]seed\f[R]]
+\f[B]dc\f[R] [\f[B]-cChiPRvVx\f[R]] [\f[B]--version\f[R]]
+[\f[B]--help\f[R]] [\f[B]--digit-clamp\f[R]]
+[\f[B]--no-digit-clamp\f[R]] [\f[B]--interactive\f[R]]
+[\f[B]--no-prompt\f[R]] [\f[B]--no-read-prompt\f[R]]
+[\f[B]--extended-register\f[R]] [\f[B]-e\f[R] \f[I]expr\f[R]]
+[\f[B]--expression\f[R]=\f[I]expr\f[R]\&...]
+[\f[B]-f\f[R] \f[I]file\f[R]\&...]
+[\f[B]--file\f[R]=\f[I]file\f[R]\&...]
+[\f[I]file\f[R]\&...]
+[\f[B]-I\f[R] \f[I]ibase\f[R]] [\f[B]--ibase\f[R]=\f[I]ibase\f[R]]
+[\f[B]-O\f[R] \f[I]obase\f[R]] [\f[B]--obase\f[R]=\f[I]obase\f[R]]
+[\f[B]-S\f[R] \f[I]scale\f[R]] [\f[B]--scale\f[R]=\f[I]scale\f[R]]
+[\f[B]-E\f[R] \f[I]seed\f[R]] [\f[B]--seed\f[R]=\f[I]seed\f[R]]
.SH DESCRIPTION
.PP
dc(1) is an arbitrary-precision calculator.
@@ -65,83 +67,54 @@ and this dc(1) will always start with a \f[B]scale\f[R] of \f[B]10\f[R].
.PP
The following are the options that dc(1) accepts.
.TP
-\f[B]-h\f[R], \f[B]--help\f[R]
-Prints a usage message and quits.
-.TP
-\f[B]-v\f[R], \f[B]-V\f[R], \f[B]--version\f[R]
-Print the version information (copyright header) and exit.
-.TP
-\f[B]-i\f[R], \f[B]--interactive\f[R]
-Forces interactive mode.
-(See the \f[B]INTERACTIVE MODE\f[R] section.)
+\f[B]-C\f[R], \f[B]--no-digit-clamp\f[R]
+Disables clamping of digits greater than or equal to the current
+\f[B]ibase\f[R] when parsing numbers.
.RS
.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
-.TP
-\f[B]-L\f[R], \f[B]--no-line-length\f[R]
-Disables line length checking and prints numbers without backslashes and
-newlines.
-In other words, this option sets \f[B]BC_LINE_LENGTH\f[R] to \f[B]0\f[R]
-(see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
-.RS
+This means that the value added to a number from a digit is always that
+digit\[cq]s value multiplied by the value of ibase raised to the power
+of the digit\[cq]s position, which starts from 0 at the least
+significant digit.
.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
-.TP
-\f[B]-P\f[R], \f[B]--no-prompt\f[R]
-Disables the prompt in TTY mode.
-(The prompt is only enabled in TTY mode.
-See the \f[B]TTY MODE\f[R] 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
-\f[B]DC_ENV_ARGS\f[R].
-.RS
+If this and/or the \f[B]-c\f[R] or \f[B]--digit-clamp\f[R] options are
+given multiple times, the last one given is used.
.PP
-These options override the \f[B]DC_PROMPT\f[R] and \f[B]DC_TTY_MODE\f[R]
-environment variables (see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
+This option overrides the \f[B]DC_DIGIT_CLAMP\f[R] environment variable
+(see the \f[B]ENVIRONMENT VARIABLES\f[R] section) and the default, which
+can be queried with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
.PP
This is a \f[B]non-portable extension\f[R].
.RE
.TP
-\f[B]-R\f[R], \f[B]--no-read-prompt\f[R]
-Disables the read prompt in TTY mode.
-(The read prompt is only enabled in TTY mode.
-See the \f[B]TTY MODE\f[R] 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
-\f[B]BC_ENV_ARGS\f[R] (see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
-This option is also useful in hash bang lines of dc(1) scripts that
-prompt for user input.
+\f[B]-c\f[R], \f[B]--digit-clamp\f[R]
+Enables clamping of digits greater than or equal to the current
+\f[B]ibase\f[R] when parsing numbers.
.RS
.PP
-This option does not disable the regular prompt because the read prompt
-is only used when the \f[B]?\f[R] command is used.
+This means that digits that the value added to a number from a digit
+that is greater than or equal to the ibase is the value of ibase minus 1
+all multiplied by the value of ibase raised to the power of the
+digit\[cq]s position, which starts from 0 at the least significant
+digit.
.PP
-These options \f[I]do\f[R] override the \f[B]DC_PROMPT\f[R] and
-\f[B]DC_TTY_MODE\f[R] environment variables (see the \f[B]ENVIRONMENT
-VARIABLES\f[R] section), but only for the read prompt.
+If this and/or the \f[B]-C\f[R] or \f[B]--no-digit-clamp\f[R] options
+are given multiple times, the last one given is used.
.PP
-This is a \f[B]non-portable extension\f[R].
-.RE
-.TP
-\f[B]-x\f[R] \f[B]--extended-register\f[R]
-Enables extended register mode.
-See the \f[I]Extended Register Mode\f[R] subsection of the
-\f[B]REGISTERS\f[R] section for more information.
-.RS
+This option overrides the \f[B]DC_DIGIT_CLAMP\f[R] environment variable
+(see the \f[B]ENVIRONMENT VARIABLES\f[R] section) and the default, which
+can be queried with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
.PP
This is a \f[B]non-portable extension\f[R].
.RE
.TP
-\f[B]-z\f[R], \f[B]--leading-zeroes\f[R]
-Makes dc(1) print all numbers greater than \f[B]-1\f[R] and less than
-\f[B]1\f[R], and not equal to \f[B]0\f[R], with a leading zero.
+\f[B]-E\f[R] \f[I]seed\f[R], \f[B]--seed\f[R]=\f[I]seed\f[R]
+Sets the builtin variable \f[B]seed\f[R] to the value \f[I]seed\f[R]
+assuming that \f[I]seed\f[R] is in base 10.
+It is a fatal error if \f[I]seed\f[R] is not a valid number.
.RS
.PP
-This can be set for individual numbers with the \f[B]plz(x)\f[R],
-plznl(x)**, \f[B]pnlz(x)\f[R], and \f[B]pnlznl(x)\f[R] functions in the
-extended math library (see the \f[B]LIBRARY\f[R] section).
+If multiple instances of this option are given, the last is used.
.PP
This is a \f[B]non-portable extension\f[R].
.RE
@@ -189,6 +162,9 @@ exit.
This is a \f[B]non-portable extension\f[R].
.RE
.TP
+\f[B]-h\f[R], \f[B]--help\f[R]
+Prints a usage message and exits.
+.TP
\f[B]-I\f[R] \f[I]ibase\f[R], \f[B]--ibase\f[R]=\f[I]ibase\f[R]
Sets the builtin variable \f[B]ibase\f[R] to the value \f[I]ibase\f[R]
assuming that \f[I]ibase\f[R] is in base 10.
@@ -200,6 +176,24 @@ If multiple instances of this option are given, the last is used.
This is a \f[B]non-portable extension\f[R].
.RE
.TP
+\f[B]-i\f[R], \f[B]--interactive\f[R]
+Forces interactive mode.
+(See the \f[B]INTERACTIVE MODE\f[R] section.)
+.RS
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
+\f[B]-L\f[R], \f[B]--no-line-length\f[R]
+Disables line length checking and prints numbers without backslashes and
+newlines.
+In other words, this option sets \f[B]BC_LINE_LENGTH\f[R] to \f[B]0\f[R]
+(see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
+.RS
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
\f[B]-O\f[R] \f[I]obase\f[R], \f[B]--obase\f[R]=\f[I]obase\f[R]
Sets the builtin variable \f[B]obase\f[R] to the value \f[I]obase\f[R]
assuming that \f[I]obase\f[R] is in base 10.
@@ -211,6 +205,44 @@ If multiple instances of this option are given, the last is used.
This is a \f[B]non-portable extension\f[R].
.RE
.TP
+\f[B]-P\f[R], \f[B]--no-prompt\f[R]
+Disables the prompt in TTY mode.
+(The prompt is only enabled in TTY mode.
+See the \f[B]TTY MODE\f[R] 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
+\f[B]DC_ENV_ARGS\f[R].
+.RS
+.PP
+These options override the \f[B]DC_PROMPT\f[R] and \f[B]DC_TTY_MODE\f[R]
+environment variables (see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
+\f[B]-R\f[R], \f[B]--no-read-prompt\f[R]
+Disables the read prompt in TTY mode.
+(The read prompt is only enabled in TTY mode.
+See the \f[B]TTY MODE\f[R] 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
+\f[B]BC_ENV_ARGS\f[R] (see the \f[B]ENVIRONMENT VARIABLES\f[R] section).
+This option is also useful in hash bang lines of dc(1) scripts that
+prompt for user input.
+.RS
+.PP
+This option does not disable the regular prompt because the read prompt
+is only used when the \f[B]?\f[R] command is used.
+.PP
+These options \f[I]do\f[R] override the \f[B]DC_PROMPT\f[R] and
+\f[B]DC_TTY_MODE\f[R] environment variables (see the \f[B]ENVIRONMENT
+VARIABLES\f[R] section), but only for the read prompt.
+.PP
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
\f[B]-S\f[R] \f[I]scale\f[R], \f[B]--scale\f[R]=\f[I]scale\f[R]
Sets the builtin variable \f[B]scale\f[R] to the value \f[I]scale\f[R]
assuming that \f[I]scale\f[R] is in base 10.
@@ -222,13 +254,26 @@ If multiple instances of this option are given, the last is used.
This is a \f[B]non-portable extension\f[R].
.RE
.TP
-\f[B]-E\f[R] \f[I]seed\f[R], \f[B]--seed\f[R]=\f[I]seed\f[R]
-Sets the builtin variable \f[B]seed\f[R] to the value \f[I]seed\f[R]
-assuming that \f[I]seed\f[R] is in base 10.
-It is a fatal error if \f[I]seed\f[R] is not a valid number.
+\f[B]-v\f[R], \f[B]-V\f[R], \f[B]--version\f[R]
+Print the version information (copyright header) and exits.
+.TP
+\f[B]-x\f[R] \f[B]--extended-register\f[R]
+Enables extended register mode.
+See the \f[I]Extended Register Mode\f[R] subsection of the
+\f[B]REGISTERS\f[R] section for more information.
.RS
.PP
-If multiple instances of this option are given, the last is used.
+This is a \f[B]non-portable extension\f[R].
+.RE
+.TP
+\f[B]-z\f[R], \f[B]--leading-zeroes\f[R]
+Makes dc(1) print all numbers greater than \f[B]-1\f[R] and less than
+\f[B]1\f[R], and not equal to \f[B]0\f[R], with a leading zero.
+.RS
+.PP
+This can be set for individual numbers with the \f[B]plz(x)\f[R],
+plznl(x)**, \f[B]pnlz(x)\f[R], and \f[B]pnlznl(x)\f[R] functions in the
+extended math library (see the \f[B]LIBRARY\f[R] section).
.PP
This is a \f[B]non-portable extension\f[R].
.RE
@@ -360,17 +405,48 @@ This is a \f[B]non-portable extension\f[R].
Numbers are strings made up of digits, uppercase letters up to
\f[B]F\f[R], and at most \f[B]1\f[R] period for a radix.
Numbers can have up to \f[B]DC_NUM_MAX\f[R] digits.
-Uppercase letters are equal to \f[B]9\f[R] + their position in the
+Uppercase letters are equal to \f[B]9\f[R] plus their position in the
alphabet (i.e., \f[B]A\f[R] equals \f[B]10\f[R], or \f[B]9+1\f[R]).
-If a digit or letter makes no sense with the current value of
-\f[B]ibase\f[R], they are set to the value of the highest valid digit in
-\f[B]ibase\f[R].
.PP
-Single-character numbers (i.e., \f[B]A\f[R] alone) take the value that
-they would have if they were valid digits, regardless of the value of
-\f[B]ibase\f[R].
+If a digit or letter makes no sense with the current value of
+\f[B]ibase\f[R] (i.e., they are greater than or equal to the current
+value of \f[B]ibase\f[R]), then the behavior depends on the existence of
+the \f[B]-c\f[R]/\f[B]--digit-clamp\f[R] or
+\f[B]-C\f[R]/\f[B]--no-digit-clamp\f[R] options (see the
+\f[B]OPTIONS\f[R] section), the existence and setting of the
+\f[B]DC_DIGIT_CLAMP\f[R] environment variable (see the \f[B]ENVIRONMENT
+VARIABLES\f[R] section), or the default, which can be queried with the
+\f[B]-h\f[R]/\f[B]--help\f[R] option.
+.PP
+If clamping is off, then digits or letters that are greater than or
+equal to the current value of \f[B]ibase\f[R] are not changed.
+Instead, their given value is multiplied by the appropriate power of
+\f[B]ibase\f[R] and added into the number.
+This means that, with an \f[B]ibase\f[R] of \f[B]3\f[R], the number
+\f[B]AB\f[R] is equal to \f[B]3\[ha]1*A+3\[ha]0*B\f[R], which is
+\f[B]3\f[R] times \f[B]10\f[R] plus \f[B]11\f[R], or \f[B]41\f[R].
+.PP
+If clamping is on, then digits or letters that are greater than or equal
+to the current value of \f[B]ibase\f[R] are set to the value of the
+highest valid digit in \f[B]ibase\f[R] before being multiplied by the
+appropriate power of \f[B]ibase\f[R] and added into the number.
+This means that, with an \f[B]ibase\f[R] of \f[B]3\f[R], the number
+\f[B]AB\f[R] is equal to \f[B]3\[ha]1*2+3\[ha]0*2\f[R], which is
+\f[B]3\f[R] times \f[B]2\f[R] plus \f[B]2\f[R], or \f[B]8\f[R].
+.PP
+There is one exception to clamping: single-character numbers (i.e.,
+\f[B]A\f[R] alone).
+Such numbers are never clamped and always take the value they would have
+in the highest possible \f[B]ibase\f[R].
This means that \f[B]A\f[R] alone always equals decimal \f[B]10\f[R] and
-\f[B]F\f[R] alone always equals decimal \f[B]15\f[R].
+\f[B]Z\f[R] alone always equals decimal \f[B]35\f[R].
+This behavior is mandated by the standard for bc(1) (see the STANDARDS
+section) and is meant to provide an easy way to set the current
+\f[B]ibase\f[R] (with the \f[B]i\f[R] command) regardless of the current
+value of \f[B]ibase\f[R].
+.PP
+If clamping is on, and the clamped value of a character is needed, use a
+leading zero, i.e., for \f[B]A\f[R], use \f[B]0A\f[R].
.PP
In addition, dc(1) accepts numbers in scientific notation.
These have the form \f[B]<number>e<integer>\f[R].
@@ -1298,7 +1374,8 @@ at which they become a problem.
In fact, memory should be exhausted before these limits should be hit.
.SH ENVIRONMENT VARIABLES
.PP
-dc(1) recognizes the following environment variables:
+As \f[B]non-portable extensions\f[R], dc(1) recognizes the following
+environment variables:
.TP
\f[B]DC_ENV_ARGS\f[R]
This is another way to give command-line arguments to dc(1).
@@ -1402,6 +1479,22 @@ expressions and expression files, and a zero value makes dc(1) not exit.
This environment variable overrides the default, which can be queried
with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
.RE
+.TP
+\f[B]DC_DIGIT_CLAMP\f[R]
+When parsing numbers and if this environment variable exists and
+contains an integer, a non-zero value makes dc(1) clamp digits that are
+greater than or equal to the current \f[B]ibase\f[R] so that all such
+digits are considered equal to the \f[B]ibase\f[R] minus 1, and a zero
+value disables such clamping so that those digits are always equal to
+their value, which is multiplied by the power of the \f[B]ibase\f[R].
+.RS
+.PP
+This never applies to single-digit numbers, as per the bc(1) standard
+(see the \f[B]STANDARDS\f[R] section).
+.PP
+This environment variable overrides the default, which can be queried
+with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
+.RE
.SH EXIT STATUS
.PP
dc(1) returns the following exit statuses:
@@ -1505,10 +1598,9 @@ The default setting can be queried with the \f[B]-h\f[R] or
\f[B]--help\f[R] options.
.PP
TTY mode is different from interactive mode because interactive mode is
-required in the bc(1) specification at
-https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html , and
-interactive mode requires only \f[B]stdin\f[R] and \f[B]stdout\f[R] to
-be connected to a terminal.
+required in the bc(1) specification (see the \f[B]STANDARDS\f[R]
+section), and interactive mode requires only \f[B]stdin\f[R] and
+\f[B]stdout\f[R] to be connected to a terminal.
.SS Command-Line History
.PP
Command-line history is only enabled if TTY mode is, i.e., that
@@ -1593,10 +1685,10 @@ section).
bc(1)
.SH STANDARDS
.PP
-The dc(1) utility operators are compliant with the operators in the IEEE
-Std 1003.1-2017 (\[lq]POSIX.1-2017\[rq]) specification at
-https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html for
-bc(1).
+The dc(1) utility operators and some behavior are compliant with the
+operators in the IEEE Std 1003.1-2017 (\[lq]POSIX.1-2017\[rq]) bc(1)
+specification at
+https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html .
.SH BUGS
.PP
None are known.
diff --git a/manuals/dc/N.1.md b/manuals/dc/N.1.md
index 25c13b7c2fd4..694a0cb907e8 100644
--- a/manuals/dc/N.1.md
+++ b/manuals/dc/N.1.md
@@ -34,7 +34,7 @@ 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*...] [**-I** *ibase*] [**-\-ibase**=*ibase*] [**-O** *obase*] [**-\-obase**=*obase*] [**-S** *scale*] [**-\-scale**=*scale*] [**-E** *seed*] [**-\-seed**=*seed*]
+**dc** [**-cChiPRvVx**] [**-\-version**] [**-\-help**] [**-\-digit-clamp**] [**-\-no-digit-clamp**] [**-\-interactive**] [**-\-no-prompt**] [**-\-no-read-prompt**] [**-\-extended-register**] [**-e** *expr*] [**-\-expression**=*expr*...] [**-f** *file*...] [**-\-file**=*file*...] [*file*...] [**-I** *ibase*] [**-\-ibase**=*ibase*] [**-O** *obase*] [**-\-obase**=*obase*] [**-S** *scale*] [**-\-scale**=*scale*] [**-E** *seed*] [**-\-seed**=*seed*]
# DESCRIPTION
@@ -55,73 +55,49 @@ this dc(1) will always start with a **scale** of **10**.
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).
+**-C**, **-\-no-digit-clamp**
- This is a **non-portable extension**.
+: Disables clamping of digits greater than or equal to the current **ibase**
+ when parsing numbers.
-**-P**, **-\-no-prompt**
+ This means that the value added to a number from a digit is always that
+ digit's value multiplied by the value of ibase raised to the power of the
+ digit's position, which starts from 0 at the least significant digit.
-: 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**.
+ If this and/or the **-c** or **-\-digit-clamp** options are given multiple
+ times, the last one given is used.
- These options override the **DC_PROMPT** and **DC_TTY_MODE** environment
- variables (see the **ENVIRONMENT VARIABLES** section).
+ This option overrides the **DC_DIGIT_CLAMP** environment variable (see the
+ **ENVIRONMENT VARIABLES** section) and the default, which can be queried
+ with the **-h** or **-\-help** options.
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.
+**-c**, **-\-digit-clamp**
- These options *do* override the **DC_PROMPT** and **DC_TTY_MODE**
- environment variables (see the **ENVIRONMENT VARIABLES** section), but only
- for the read prompt.
+: Enables clamping of digits greater than or equal to the current **ibase**
+ when parsing numbers.
- This is a **non-portable extension**.
+ This means that digits that the value added to a number from a digit that is
+ greater than or equal to the ibase is the value of ibase minus 1 all
+ multiplied by the value of ibase raised to the power of the digit's
+ position, which starts from 0 at the least significant digit.
-**-x** **-\-extended-register**
+ If this and/or the **-C** or **-\-no-digit-clamp** options are given
+ multiple times, the last one given is used.
-: Enables extended register mode. See the *Extended Register Mode* subsection
- of the **REGISTERS** section for more information.
+ This option overrides the **DC_DIGIT_CLAMP** environment variable (see the
+ **ENVIRONMENT VARIABLES** section) and the default, which can be queried
+ with the **-h** or **-\-help** options.
This is a **non-portable extension**.
-**-z**, **-\-leading-zeroes**
+**-E** *seed*, **-\-seed**=*seed*
-: Makes dc(1) print all numbers greater than **-1** and less than **1**, and
- not equal to **0**, with a leading zero.
+: Sets the builtin variable **seed** to the value *seed* assuming that *seed*
+ is in base 10. It is a fatal error if *seed* is not a valid number.
- 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).
+ If multiple instances of this option are given, the last is used.
This is a **non-portable extension**.
@@ -157,6 +133,10 @@ The following are the options that dc(1) accepts.
This is a **non-portable extension**.
+**-h**, **-\-help**
+
+: Prints a usage message and exits.
+
**-I** *ibase*, **-\-ibase**=*ibase*
: Sets the builtin variable **ibase** to the value *ibase* assuming that
@@ -166,6 +146,20 @@ The following are the options that dc(1) accepts.
This is a **non-portable extension**.
+**-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**.
+
**-O** *obase*, **-\-obase**=*obase*
: Sets the builtin variable **obase** to the value *obase* assuming that
@@ -175,6 +169,36 @@ The following are the options that dc(1) accepts.
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**.
+
**-S** *scale*, **-\-scale**=*scale*
: Sets the builtin variable **scale** to the value *scale* assuming that
@@ -184,12 +208,25 @@ The following are the options that dc(1) accepts.
This is a **non-portable extension**.
-**-E** *seed*, **-\-seed**=*seed*
+**-v**, **-V**, **-\-version**
-: Sets the builtin variable **seed** to the value *seed* assuming that *seed*
- is in base 10. It is a fatal error if *seed* is not a valid number.
+: Print the version information (copyright header) and exits.
- If multiple instances of this option are given, the last is used.
+**-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 dc(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**.
@@ -302,15 +339,40 @@ Comments go from **#** until, and not including, the next newline. This is a
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**.
+Uppercase letters are equal to **9** plus 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** (i.e.,
+they are greater than or equal to the current value of **ibase**), then the
+behavior depends on the existence of the **-c**/**-\-digit-clamp** or
+**-C**/**-\-no-digit-clamp** options (see the **OPTIONS** section), the
+existence and setting of the **DC_DIGIT_CLAMP** environment variable (see the
+**ENVIRONMENT VARIABLES** section), or the default, which can be queried with
+the **-h**/**-\-help** option.
+
+If clamping is off, then digits or letters that are greater than or equal to the
+current value of **ibase** are not changed. Instead, their given value is
+multiplied by the appropriate power of **ibase** and added into the number. This
+means that, with an **ibase** of **3**, the number **AB** is equal to
+**3\^1\*A+3\^0\*B**, which is **3** times **10** plus **11**, or **41**.
+
+If clamping is on, then digits or letters that are greater than or equal to the
+current value of **ibase** are set to the value of the highest valid digit in
+**ibase** before being multiplied by the appropriate power of **ibase** and
+added into the number. This means that, with an **ibase** of **3**, the number
+**AB** is equal to **3\^1\*2+3\^0\*2**, which is **3** times **2** plus **2**,
+or **8**.
+
+There is one exception to clamping: single-character numbers (i.e., **A**
+alone). Such numbers are never clamped and always take the value they would have
+in the highest possible **ibase**. This means that **A** alone always equals
+decimal **10** and **Z** alone always equals decimal **35**. This behavior is
+mandated by the standard for bc(1) (see the STANDARDS section) and is meant to
+provide an easy way to set the current **ibase** (with the **i** command)
+regardless of the current value of **ibase**.
+
+If clamping is on, and the clamped value of a character is needed, use a leading
+zero, i.e., for **A**, use **0A**.
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
@@ -1148,7 +1210,8 @@ be hit.
# ENVIRONMENT VARIABLES
-dc(1) recognizes the following environment variables:
+As **non-portable extensions**, dc(1) recognizes the following environment
+variables:
**DC_ENV_ARGS**
@@ -1237,6 +1300,21 @@ dc(1) recognizes the following environment variables:
This environment variable overrides the default, which can be queried with
the **-h** or **-\-help** options.
+**DC_DIGIT_CLAMP**
+
+: When parsing numbers and if this environment variable exists and contains an
+ integer, a non-zero value makes dc(1) clamp digits that are greater than or
+ equal to the current **ibase** so that all such digits are considered equal
+ to the **ibase** minus 1, and a zero value disables such clamping so that
+ those digits are always equal to their value, which is multiplied by the
+ power of the **ibase**.
+
+ This never applies to single-digit numbers, as per the bc(1) standard (see
+ the **STANDARDS** section).
+
+ 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:
@@ -1333,10 +1411,8 @@ 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 at
-https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html , and
-interactive mode requires only **stdin** and **stdout** to be connected to a
-terminal.
+in the bc(1) specification (see the **STANDARDS** section), and interactive mode
+requires only **stdin** and **stdout** to be connected to a terminal.
## Command-Line History
@@ -1414,9 +1490,9 @@ bc(1)
# STANDARDS
-The dc(1) utility operators are compliant with the operators in the IEEE Std
-1003.1-2017 (“POSIX.1-2017”) specification at
-https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html for bc(1).
+The dc(1) utility operators and some behavior are compliant with the operators
+in the IEEE Std 1003.1-2017 (“POSIX.1-2017”) bc(1) specification at
+https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html .
# BUGS
diff --git a/scripts/format.sh b/scripts/format.sh
index 3e399da5777c..74ca9dc35432 100755
--- a/scripts/format.sh
+++ b/scripts/format.sh
@@ -47,3 +47,5 @@ for f in $files; do
sed -i 's|^#else //|#else //|g' "$f"
done
+
+sed -i 's|^ // clang-format on| // clang-format on|g' src/program.c
diff --git a/src/args.c b/src/args.c
index 64fd02c1d7b8..8e3b2ea14495 100644
--- a/src/args.c
+++ b/src/args.c
@@ -48,6 +48,7 @@
#include <args.h>
#include <opt.h>
#include <num.h>
+#include <vm.h>
/**
* Adds @a str to the list of expressions to execute later.
@@ -57,9 +58,14 @@ static void
bc_args_exprs(const char* str)
{
BC_SIG_ASSERT_LOCKED;
- if (vm.exprs.v == NULL) bc_vec_init(&vm.exprs, sizeof(uchar), BC_DTOR_NONE);
- bc_vec_concat(&vm.exprs, str);
- bc_vec_concat(&vm.exprs, "\n");
+
+ if (vm->exprs.v == NULL)
+ {
+ bc_vec_init(&vm->exprs, sizeof(uchar), BC_DTOR_NONE);
+ }
+
+ bc_vec_concat(&vm->exprs, str);
+ bc_vec_concat(&vm->exprs, "\n");
}
/**
@@ -74,7 +80,7 @@ bc_args_file(const char* file)
BC_SIG_ASSERT_LOCKED;
- vm.file = file;
+ vm->file = file;
buf = bc_read_file(file);
@@ -131,7 +137,7 @@ bc_args_redefine(const char* keyword)
{
if (BC_LEX_KW_POSIX(kw)) break;
- vm.redefined_kws[i] = true;
+ vm->redefined_kws[i] = true;
return;
}
@@ -143,13 +149,13 @@ bc_args_redefine(const char* keyword)
#endif // BC_ENABLED
void
-bc_args(int argc, char* argv[], bool exit_exprs, BcBigDig scale)
+bc_args(int argc, char* argv[], bool exit_exprs, BcBigDig* scale,
+ BcBigDig* ibase, BcBigDig* obase)
{
int c;
size_t i;
bool do_exit = false, version = false;
BcOpt opts;
- BcBigDig newscale = scale, ibase = BC_BASE, obase = BC_BASE;
#if BC_ENABLE_EXTRA_MATH
char* seed = NULL;
#endif // BC_ENABLE_EXTRA_MATH
@@ -164,17 +170,29 @@ bc_args(int argc, char* argv[], bool exit_exprs, BcBigDig scale)
{
switch (c)
{
+ case 'c':
+ {
+ vm->flags |= BC_FLAG_DIGIT_CLAMP;
+ break;
+ }
+
+ case 'C':
+ {
+ vm->flags &= ~BC_FLAG_DIGIT_CLAMP;
+ break;
+ }
+
case 'e':
{
// Barf if not allowed.
- if (vm.no_exprs)
+ if (vm->no_exprs)
{
bc_verr(BC_ERR_FATAL_OPTION, "-e (--expression)");
}
// Add the expressions and set exit.
bc_args_exprs(opts.optarg);
- vm.exit_exprs = (exit_exprs || vm.exit_exprs);
+ vm->exit_exprs = (exit_exprs || vm->exit_exprs);
break;
}
@@ -182,18 +200,18 @@ bc_args(int argc, char* argv[], bool exit_exprs, BcBigDig scale)
case 'f':
{
// Figure out if exiting on expressions is disabled.
- if (!strcmp(opts.optarg, "-")) vm.no_exprs = true;
+ if (!strcmp(opts.optarg, "-")) vm->no_exprs = true;
else
{
// Barf if not allowed.
- if (vm.no_exprs)
+ if (vm->no_exprs)
{
bc_verr(BC_ERR_FATAL_OPTION, "-f (--file)");
}
// Add the expressions and set exit.
bc_args_file(opts.optarg);
- vm.exit_exprs = (exit_exprs || vm.exit_exprs);
+ vm->exit_exprs = (exit_exprs || vm->exit_exprs);
}
break;
@@ -201,56 +219,56 @@ bc_args(int argc, char* argv[], bool exit_exprs, BcBigDig scale)
case 'h':
{
- bc_vm_info(vm.help);
+ bc_vm_info(vm->help);
do_exit = true;
break;
}
case 'i':
{
- vm.flags |= BC_FLAG_I;
+ vm->flags |= BC_FLAG_I;
break;
}
case 'I':
{
- ibase = bc_args_builtin(opts.optarg);
+ *ibase = bc_args_builtin(opts.optarg);
break;
}
case 'z':
{
- vm.flags |= BC_FLAG_Z;
+ vm->flags |= BC_FLAG_Z;
break;
}
case 'L':
{
- vm.line_len = 0;
+ vm->line_len = 0;
break;
}
case 'O':
{
- obase = bc_args_builtin(opts.optarg);
+ *obase = bc_args_builtin(opts.optarg);
break;
}
case 'P':
{
- vm.flags &= ~(BC_FLAG_P);
+ vm->flags &= ~(BC_FLAG_P);
break;
}
case 'R':
{
- vm.flags &= ~(BC_FLAG_R);
+ vm->flags &= ~(BC_FLAG_R);
break;
}
case 'S':
{
- newscale = bc_args_builtin(opts.optarg);
+ *scale = bc_args_builtin(opts.optarg);
break;
}
@@ -272,21 +290,21 @@ bc_args(int argc, char* argv[], bool exit_exprs, BcBigDig scale)
case 'g':
{
assert(BC_IS_BC);
- vm.flags |= BC_FLAG_G;
+ vm->flags |= BC_FLAG_G;
break;
}
case 'l':
{
assert(BC_IS_BC);
- vm.flags |= BC_FLAG_L;
+ vm->flags |= BC_FLAG_L;
break;
}
case 'q':
{
assert(BC_IS_BC);
- vm.flags &= ~(BC_FLAG_Q);
+ vm->flags &= ~(BC_FLAG_Q);
break;
}
@@ -299,14 +317,14 @@ bc_args(int argc, char* argv[], bool exit_exprs, BcBigDig scale)
case 's':
{
assert(BC_IS_BC);
- vm.flags |= BC_FLAG_S;
+ vm->flags |= BC_FLAG_S;
break;
}
case 'w':
{
assert(BC_IS_BC);
- vm.flags |= BC_FLAG_W;
+ vm->flags |= BC_FLAG_W;
break;
}
#endif // BC_ENABLED
@@ -322,7 +340,7 @@ bc_args(int argc, char* argv[], bool exit_exprs, BcBigDig scale)
case 'x':
{
assert(BC_IS_DC);
- vm.flags |= DC_FLAG_X;
+ vm->flags |= DC_FLAG_X;
break;
}
#endif // DC_ENABLED
@@ -335,7 +353,9 @@ bc_args(int argc, char* argv[], bool exit_exprs, BcBigDig scale)
default:
{
BC_UNREACHABLE
+#if !BC_CLANG
abort();
+#endif // !BC_CLANG
}
#endif // NDEBUG
}
@@ -344,24 +364,24 @@ bc_args(int argc, char* argv[], bool exit_exprs, BcBigDig scale)
if (version) bc_vm_info(NULL);
if (do_exit)
{
- vm.status = (sig_atomic_t) BC_STATUS_QUIT;
+ vm->status = (sig_atomic_t) BC_STATUS_QUIT;
BC_JMP;
}
// We do not print the banner if expressions are used or dc is used.
- if (!BC_IS_BC || vm.exprs.len > 1) vm.flags &= ~(BC_FLAG_Q);
+ if (BC_ARGS_SHOULD_BE_QUIET) vm->flags &= ~(BC_FLAG_Q);
// We need to make sure the files list is initialized. We don't want to
// initialize it if there are no files because it's just a waste of memory.
- if (opts.optind < (size_t) argc && vm.files.v == NULL)
+ if (opts.optind < (size_t) argc && vm->files.v == NULL)
{
- bc_vec_init(&vm.files, sizeof(char*), BC_DTOR_NONE);
+ bc_vec_init(&vm->files, sizeof(char*), BC_DTOR_NONE);
}
// Add all the files to the vector.
for (i = opts.optind; i < (size_t) argc; ++i)
{
- bc_vec_push(&vm.files, argv + i);
+ bc_vec_push(&vm->files, argv + i);
}
#if BC_ENABLE_EXTRA_MATH
@@ -375,31 +395,11 @@ bc_args(int argc, char* argv[], bool exit_exprs, BcBigDig scale)
bc_num_parse(&n, seed, BC_BASE);
- bc_program_assignSeed(&vm.prog, &n);
+ bc_program_assignSeed(&vm->prog, &n);
BC_SIG_LOCK;
bc_num_free(&n);
}
#endif // BC_ENABLE_EXTRA_MATH
-
- BC_SIG_UNLOCK;
-
- if (newscale != scale)
- {
- bc_program_assignBuiltin(&vm.prog, true, false, newscale);
- }
-
- if (obase != BC_BASE)
- {
- bc_program_assignBuiltin(&vm.prog, false, true, obase);
- }
-
- // This is last to avoid it affecting the value of the others.
- if (ibase != BC_BASE)
- {
- bc_program_assignBuiltin(&vm.prog, false, false, ibase);
- }
-
- BC_SIG_LOCK;
}
diff --git a/src/bc.c b/src/bc.c
index 77fa06512dda..bffb096183c0 100644
--- a/src/bc.c
+++ b/src/bc.c
@@ -50,14 +50,14 @@ bc_main(int argc, char* argv[])
{
// All of these just set bc-specific items in BcVm.
- vm.read_ret = BC_INST_RET;
- vm.help = bc_help;
- vm.sigmsg = bc_sig_msg;
- vm.siglen = bc_sig_msg_len;
+ vm->read_ret = BC_INST_RET;
+ vm->help = bc_help;
+ vm->sigmsg = bc_sig_msg;
+ vm->siglen = bc_sig_msg_len;
- vm.next = bc_lex_token;
- vm.parse = bc_parse_parse;
- vm.expr = bc_parse_expr;
+ vm->next = bc_lex_token;
+ vm->parse = bc_parse_parse;
+ vm->expr = bc_parse_expr;
bc_vm_boot(argc, argv);
}
diff --git a/src/bc_lex.c b/src/bc_lex.c
index 1097b92647a6..5248aa54ba5e 100644
--- a/src/bc_lex.c
+++ b/src/bc_lex.c
@@ -66,7 +66,7 @@ bc_lex_identifier(BcLex* l)
// (it is not allowed for builtin libraries), break out of the loop
// and use it as a name. This depends on the argument parser to
// ensure that only non-POSIX keywords get redefined.
- if (!vm.no_redefine && vm.redefined_kws[i]) break;
+ if (!vm->no_redefine && vm->redefined_kws[i]) break;
l->t = BC_LEX_KW_AUTO + (BcLexType) i;
@@ -115,7 +115,7 @@ bc_lex_string(BcLex* l)
buf = l->buf;
got_more = false;
- assert(!vm.is_stdin || buf == vm.buffer.v);
+ assert(!vm->is_stdin || buf == vm->buffer.v);
// Fortunately for us, bc doesn't escape quotes. Instead, the equivalent
// is '\q', which makes this loop simpler.
@@ -124,7 +124,7 @@ bc_lex_string(BcLex* l)
nlines += (c == '\n');
}
- if (BC_ERR(c == '\0') && !vm.eof && (l->is_stdin || l->is_exprs))
+ if (BC_ERR(c == '\0') && !vm->eof && (l->is_stdin || l->is_exprs))
{
got_more = bc_lex_readLine(l);
}
diff --git a/src/bc_parse.c b/src/bc_parse.c
index 33f98c896398..8da5557195f8 100644
--- a/src/bc_parse.c
+++ b/src/bc_parse.c
@@ -71,11 +71,12 @@ bc_parse_expr_status(BcParse* p, uint8_t flags, BcParseNext next);
* Returns true if an instruction could only have come from a "leaf" expression.
* For more on what leaf expressions are, read the comment for BC_PARSE_LEAF().
* @param t The instruction to test.
+ * @return True if the instruction is a from a leaf expression.
*/
static bool
bc_parse_inst_isLeaf(BcInst t)
{
- return (t >= BC_INST_NUM && t <= BC_INST_MAXSCALE) ||
+ return (t >= BC_INST_NUM && t <= BC_INST_LEADING_ZERO) ||
#if BC_ENABLE_EXTRA_MATH
t == BC_INST_TRUNC ||
#endif // BC_ENABLE_EXTRA_MATH
@@ -401,7 +402,7 @@ bc_parse_name(BcParse* p, BcInst* type, bool* can_assign, uint8_t flags)
// We want a copy of the name since the lexer might overwrite its copy.
name = bc_vm_strdup(p->l.str.v);
- BC_SETJMP_LOCKED(err);
+ BC_SETJMP_LOCKED(vm, err);
// We need the next token to see if it's just a variable or something more.
bc_lex_next(&p->l);
@@ -474,7 +475,7 @@ bc_parse_name(BcParse* p, BcInst* type, bool* can_assign, uint8_t flags)
err:
// Need to make sure to unallocate the name.
free(name);
- BC_LONGJMP_CONT;
+ BC_LONGJMP_CONT(vm);
BC_SIG_MAYLOCK;
}
@@ -1090,9 +1091,9 @@ bc_parse_endif(BcParse* p)
{
// We set this to restore it later. We don't want the parser thinking
// that we are on stdin for this one because it will want more.
- bool is_stdin = vm.is_stdin;
+ bool is_stdin = vm->is_stdin;
- vm.is_stdin = false;
+ vm->is_stdin = false;
// End all of the if statements and loops.
while (p->flags.len > 1 || BC_PARSE_IF_END(p))
@@ -1101,10 +1102,10 @@ bc_parse_endif(BcParse* p)
if (p->flags.len > 1) bc_parse_endBody(p, false);
}
- vm.is_stdin = is_stdin;
+ vm->is_stdin = is_stdin;
}
// If we reach here, a block was not properly closed, and we should error.
- else bc_parse_err(&vm.prs, BC_ERR_PARSE_BLOCK);
+ else bc_parse_err(&vm->prs, BC_ERR_PARSE_BLOCK);
}
/**
@@ -1803,7 +1804,7 @@ bc_parse_stmt(BcParse* p)
{
// Quit is a compile-time command. We don't exit directly, so the vm
// can clean up.
- vm.status = BC_STATUS_QUIT;
+ vm->status = BC_STATUS_QUIT;
BC_JMP;
break;
}
@@ -1820,7 +1821,77 @@ bc_parse_stmt(BcParse* p)
break;
}
- default:
+ case BC_LEX_EOF:
+ case BC_LEX_INVALID:
+ case BC_LEX_NEG:
+#if BC_ENABLE_EXTRA_MATH
+ case BC_LEX_OP_TRUNC:
+#endif // BC_ENABLE_EXTRA_MATH
+ case BC_LEX_OP_POWER:
+ case BC_LEX_OP_MULTIPLY:
+ case BC_LEX_OP_DIVIDE:
+ case BC_LEX_OP_MODULUS:
+ case BC_LEX_OP_PLUS:
+#if BC_ENABLE_EXTRA_MATH
+ case BC_LEX_OP_PLACES:
+ case BC_LEX_OP_LSHIFT:
+ case BC_LEX_OP_RSHIFT:
+#endif // BC_ENABLE_EXTRA_MATH
+ case BC_LEX_OP_REL_EQ:
+ case BC_LEX_OP_REL_LE:
+ case BC_LEX_OP_REL_GE:
+ case BC_LEX_OP_REL_NE:
+ case BC_LEX_OP_REL_LT:
+ case BC_LEX_OP_REL_GT:
+ case BC_LEX_OP_BOOL_OR:
+ case BC_LEX_OP_BOOL_AND:
+ case BC_LEX_OP_ASSIGN_POWER:
+ case BC_LEX_OP_ASSIGN_MULTIPLY:
+ case BC_LEX_OP_ASSIGN_DIVIDE:
+ case BC_LEX_OP_ASSIGN_MODULUS:
+ case BC_LEX_OP_ASSIGN_PLUS:
+ case BC_LEX_OP_ASSIGN_MINUS:
+#if BC_ENABLE_EXTRA_MATH
+ case BC_LEX_OP_ASSIGN_PLACES:
+ case BC_LEX_OP_ASSIGN_LSHIFT:
+ case BC_LEX_OP_ASSIGN_RSHIFT:
+#endif // BC_ENABLE_EXTRA_MATH
+ case BC_LEX_OP_ASSIGN:
+ case BC_LEX_NLINE:
+ case BC_LEX_WHITESPACE:
+ case BC_LEX_RPAREN:
+ case BC_LEX_LBRACKET:
+ case BC_LEX_COMMA:
+ case BC_LEX_RBRACKET:
+ case BC_LEX_LBRACE:
+ case BC_LEX_KW_AUTO:
+ case BC_LEX_KW_DEFINE:
+#if DC_ENABLED
+ case BC_LEX_EQ_NO_REG:
+ case BC_LEX_COLON:
+ case BC_LEX_EXECUTE:
+ case BC_LEX_PRINT_STACK:
+ case BC_LEX_CLEAR_STACK:
+ case BC_LEX_REG_STACK_LEVEL:
+ case BC_LEX_STACK_LEVEL:
+ case BC_LEX_DUPLICATE:
+ case BC_LEX_SWAP:
+ case BC_LEX_POP:
+ case BC_LEX_STORE_IBASE:
+ case BC_LEX_STORE_OBASE:
+ case BC_LEX_STORE_SCALE:
+#if BC_ENABLE_EXTRA_MATH
+ case BC_LEX_STORE_SEED:
+#endif // BC_ENABLE_EXTRA_MATH
+ case BC_LEX_LOAD:
+ case BC_LEX_LOAD_POP:
+ case BC_LEX_STORE_PUSH:
+ case BC_LEX_PRINT_POP:
+ case BC_LEX_NQUIT:
+ case BC_LEX_EXEC_STACK_LENGTH:
+ case BC_LEX_SCALE_FACTOR:
+ case BC_LEX_ARRAY_LENGTH:
+#endif // DC_ENABLED
{
bc_parse_err(p, BC_ERR_PARSE_TOKEN);
}
@@ -1855,7 +1926,7 @@ bc_parse_parse(BcParse* p)
{
assert(p);
- BC_SETJMP_LOCKED(exit);
+ BC_SETJMP_LOCKED(vm, exit);
// We should not let an EOF get here unless some partial parse was not
// completed, in which case, it's the user's fault.
@@ -1881,12 +1952,12 @@ bc_parse_parse(BcParse* p)
exit:
// We need to reset on error.
- if (BC_ERR(((vm.status && vm.status != BC_STATUS_QUIT) || vm.sig)))
+ if (BC_ERR(((vm->status && vm->status != BC_STATUS_QUIT) || vm->sig)))
{
bc_parse_reset(p);
}
- BC_LONGJMP_CONT;
+ BC_LONGJMP_CONT(vm);
BC_SIG_MAYLOCK;
}
@@ -2316,7 +2387,57 @@ bc_parse_expr_err(BcParse* p, uint8_t flags, BcParseNext next)
break;
}
- default:
+ case BC_LEX_EOF:
+ case BC_LEX_INVALID:
+ case BC_LEX_NEG:
+ case BC_LEX_NLINE:
+ case BC_LEX_WHITESPACE:
+ case BC_LEX_LBRACKET:
+ case BC_LEX_COMMA:
+ case BC_LEX_RBRACKET:
+ case BC_LEX_LBRACE:
+ case BC_LEX_SCOLON:
+ case BC_LEX_RBRACE:
+ case BC_LEX_KW_AUTO:
+ case BC_LEX_KW_BREAK:
+ case BC_LEX_KW_CONTINUE:
+ case BC_LEX_KW_DEFINE:
+ case BC_LEX_KW_FOR:
+ case BC_LEX_KW_IF:
+ case BC_LEX_KW_LIMITS:
+ case BC_LEX_KW_RETURN:
+ case BC_LEX_KW_WHILE:
+ case BC_LEX_KW_HALT:
+ case BC_LEX_KW_PRINT:
+ case BC_LEX_KW_QUIT:
+ case BC_LEX_KW_STREAM:
+ case BC_LEX_KW_ELSE:
+#if DC_ENABLED
+ case BC_LEX_EQ_NO_REG:
+ case BC_LEX_COLON:
+ case BC_LEX_EXECUTE:
+ case BC_LEX_PRINT_STACK:
+ case BC_LEX_CLEAR_STACK:
+ case BC_LEX_REG_STACK_LEVEL:
+ case BC_LEX_STACK_LEVEL:
+ case BC_LEX_DUPLICATE:
+ case BC_LEX_SWAP:
+ case BC_LEX_POP:
+ case BC_LEX_STORE_IBASE:
+ case BC_LEX_STORE_OBASE:
+ case BC_LEX_STORE_SCALE:
+#if BC_ENABLE_EXTRA_MATH
+ case BC_LEX_STORE_SEED:
+#endif // BC_ENABLE_EXTRA_MATH
+ case BC_LEX_LOAD:
+ case BC_LEX_LOAD_POP:
+ case BC_LEX_STORE_PUSH:
+ case BC_LEX_PRINT_POP:
+ case BC_LEX_NQUIT:
+ case BC_LEX_EXEC_STACK_LENGTH:
+ case BC_LEX_SCALE_FACTOR:
+ case BC_LEX_ARRAY_LENGTH:
+#endif // DC_ENABLED
{
#ifndef NDEBUG
// We should never get here, even in debug builds.
diff --git a/src/data.c b/src/data.c
index 4009dcc1f0d1..f743d625554a 100644
--- a/src/data.c
+++ b/src/data.c
@@ -141,6 +141,7 @@ const char bc_pledge_end[] = "";
/// end.
const BcOptLong bc_args_lopt[] = {
+ { "digit-clamp", BC_OPT_NONE, 'c' },
{ "expression", BC_OPT_REQUIRED, 'e' },
{ "file", BC_OPT_REQUIRED, 'f' },
{ "help", BC_OPT_NONE, 'h' },
@@ -149,6 +150,7 @@ const BcOptLong bc_args_lopt[] = {
{ "leading-zeroes", BC_OPT_NONE, 'z' },
{ "no-line-length", BC_OPT_NONE, 'L' },
{ "obase", BC_OPT_REQUIRED, 'O' },
+ { "no-digit-clamp", BC_OPT_NONE, 'C' },
{ "no-prompt", BC_OPT_NONE, 'P' },
{ "no-read-prompt", BC_OPT_NONE, 'R' },
{ "scale", BC_OPT_REQUIRED, 'S' },
diff --git a/src/dc.c b/src/dc.c
index f873241286e0..838f65377914 100644
--- a/src/dc.c
+++ b/src/dc.c
@@ -50,14 +50,14 @@ dc_main(int argc, char* argv[])
{
// All of these just set dc-specific items in BcVm.
- vm.read_ret = BC_INST_POP_EXEC;
- vm.help = dc_help;
- vm.sigmsg = dc_sig_msg;
- vm.siglen = dc_sig_msg_len;
+ vm->read_ret = BC_INST_POP_EXEC;
+ vm->help = dc_help;
+ vm->sigmsg = dc_sig_msg;
+ vm->siglen = dc_sig_msg_len;
- vm.next = dc_lex_token;
- vm.parse = dc_parse_parse;
- vm.expr = dc_parse_expr;
+ vm->next = dc_lex_token;
+ vm->parse = dc_parse_parse;
+ vm->expr = dc_parse_expr;
bc_vm_boot(argc, argv);
}
diff --git a/src/dc_lex.c b/src/dc_lex.c
index b76c966f6059..1277411fde5a 100644
--- a/src/dc_lex.c
+++ b/src/dc_lex.c
@@ -114,7 +114,7 @@ dc_lex_string(BcLex* l)
nls = 0;
got_more = false;
- assert(!l->is_stdin || l->buf == vm.buffer.v);
+ assert(!l->is_stdin || l->buf == vm->buffer.v);
// This is the meat. As long as we don't run into the NUL byte, and we
// have "depth", which means we haven't completely balanced brackets
@@ -141,7 +141,7 @@ dc_lex_string(BcLex* l)
if (BC_ERR(c == '\0' && depth))
{
- if (!vm.eof && (l->is_stdin || l->is_exprs))
+ if (!vm->eof && (l->is_stdin || l->is_exprs))
{
got_more = bc_lex_readLine(l);
}
diff --git a/src/dc_parse.c b/src/dc_parse.c
index d45f951bad4f..106f54ed1321 100644
--- a/src/dc_parse.c
+++ b/src/dc_parse.c
@@ -255,7 +255,110 @@ dc_parse_token(BcParse* p, BcLexType t, uint8_t flags)
break;
}
- default:
+ case BC_LEX_EOF:
+ case BC_LEX_INVALID:
+#if BC_ENABLED
+ case BC_LEX_OP_INC:
+ case BC_LEX_OP_DEC:
+#endif // BC_ENABLED
+ case BC_LEX_OP_BOOL_NOT:
+#if BC_ENABLE_EXTRA_MATH
+ case BC_LEX_OP_TRUNC:
+#endif // BC_ENABLE_EXTRA_MATH
+ case BC_LEX_OP_POWER:
+ case BC_LEX_OP_MULTIPLY:
+ case BC_LEX_OP_DIVIDE:
+ case BC_LEX_OP_MODULUS:
+ case BC_LEX_OP_PLUS:
+ case BC_LEX_OP_MINUS:
+#if BC_ENABLE_EXTRA_MATH
+ case BC_LEX_OP_PLACES:
+ case BC_LEX_OP_LSHIFT:
+ case BC_LEX_OP_RSHIFT:
+#endif // BC_ENABLE_EXTRA_MATH
+ case BC_LEX_OP_BOOL_OR:
+ case BC_LEX_OP_BOOL_AND:
+#if BC_ENABLED
+ case BC_LEX_OP_ASSIGN_POWER:
+ case BC_LEX_OP_ASSIGN_MULTIPLY:
+ case BC_LEX_OP_ASSIGN_DIVIDE:
+ case BC_LEX_OP_ASSIGN_MODULUS:
+ case BC_LEX_OP_ASSIGN_PLUS:
+ case BC_LEX_OP_ASSIGN_MINUS:
+#if BC_ENABLE_EXTRA_MATH
+ case BC_LEX_OP_ASSIGN_PLACES:
+ case BC_LEX_OP_ASSIGN_LSHIFT:
+ case BC_LEX_OP_ASSIGN_RSHIFT:
+#endif // BC_ENABLE_EXTRA_MATH
+#endif // BC_ENABLED
+ case BC_LEX_NLINE:
+ case BC_LEX_WHITESPACE:
+ case BC_LEX_LPAREN:
+ case BC_LEX_RPAREN:
+ case BC_LEX_LBRACKET:
+ case BC_LEX_COMMA:
+ case BC_LEX_RBRACKET:
+ case BC_LEX_LBRACE:
+ case BC_LEX_NAME:
+ case BC_LEX_RBRACE:
+#if BC_ENABLED
+ case BC_LEX_KW_AUTO:
+ case BC_LEX_KW_BREAK:
+ case BC_LEX_KW_CONTINUE:
+ case BC_LEX_KW_DEFINE:
+ case BC_LEX_KW_FOR:
+ case BC_LEX_KW_IF:
+ case BC_LEX_KW_LIMITS:
+ case BC_LEX_KW_RETURN:
+ case BC_LEX_KW_WHILE:
+ case BC_LEX_KW_HALT:
+ case BC_LEX_KW_LAST:
+#endif // BC_ENABLED
+ case BC_LEX_KW_IBASE:
+ case BC_LEX_KW_OBASE:
+ case BC_LEX_KW_SCALE:
+#if BC_ENABLE_EXTRA_MATH
+ case BC_LEX_KW_SEED:
+#endif // BC_ENABLE_EXTRA_MATH
+ case BC_LEX_KW_LENGTH:
+ case BC_LEX_KW_PRINT:
+ case BC_LEX_KW_SQRT:
+ case BC_LEX_KW_ABS:
+#if BC_ENABLE_EXTRA_MATH
+ case BC_LEX_KW_IRAND:
+#endif // BC_ENABLE_EXTRA_MATH
+ case BC_LEX_KW_ASCIIFY:
+ case BC_LEX_KW_MODEXP:
+ case BC_LEX_KW_DIVMOD:
+ case BC_LEX_KW_QUIT:
+#if BC_ENABLE_EXTRA_MATH
+ case BC_LEX_KW_RAND:
+#endif // BC_ENABLE_EXTRA_MATH
+ case BC_LEX_KW_MAXIBASE:
+ case BC_LEX_KW_MAXOBASE:
+ case BC_LEX_KW_MAXSCALE:
+#if BC_ENABLE_EXTRA_MATH
+ case BC_LEX_KW_MAXRAND:
+#endif // BC_ENABLE_EXTRA_MATH
+ case BC_LEX_KW_LINE_LENGTH:
+#if BC_ENABLED
+ case BC_LEX_KW_GLOBAL_STACKS:
+#endif // BC_ENABLED
+ case BC_LEX_KW_LEADING_ZERO:
+ case BC_LEX_KW_STREAM:
+ case BC_LEX_KW_ELSE:
+ case BC_LEX_EQ_NO_REG:
+ case BC_LEX_EXECUTE:
+ case BC_LEX_PRINT_STACK:
+ case BC_LEX_CLEAR_STACK:
+ case BC_LEX_STACK_LEVEL:
+ case BC_LEX_DUPLICATE:
+ case BC_LEX_SWAP:
+ case BC_LEX_POP:
+ case BC_LEX_PRINT_POP:
+ case BC_LEX_NQUIT:
+ case BC_LEX_EXEC_STACK_LENGTH:
+ case BC_LEX_SCALE_FACTOR:
{
// All other tokens should be taken care of by the caller, or they
// actually *are* invalid.
@@ -320,7 +423,7 @@ dc_parse_parse(BcParse* p)
{
assert(p != NULL);
- BC_SETJMP_LOCKED(exit);
+ BC_SETJMP_LOCKED(vm, exit);
// If we have EOF, someone called this function one too many times.
// Otherwise, parse.
@@ -330,9 +433,9 @@ dc_parse_parse(BcParse* p)
exit:
// Need to reset if there was an error.
- if (BC_SIG_EXC) bc_parse_reset(p);
+ if (BC_SIG_EXC(vm)) bc_parse_reset(p);
- BC_LONGJMP_CONT;
+ BC_LONGJMP_CONT(vm);
BC_SIG_MAYLOCK;
}
#endif // DC_ENABLED
diff --git a/src/file.c b/src/file.c
index e5d2f6ac73d8..24ca89765646 100644
--- a/src/file.c
+++ b/src/file.c
@@ -159,12 +159,12 @@ bc_file_flushErr(BcFile* restrict f, BcFlushType type)
i += 1;
// Save the extras.
- bc_vec_string(&vm.history.extras, f->len - i, f->buf + i);
+ bc_vec_string(&vm->history.extras, f->len - i, f->buf + i);
}
// Else clear the extras if told to.
else if (type >= BC_FLUSH_NO_EXTRAS_CLEAR)
{
- bc_vec_popAll(&vm.history.extras);
+ bc_vec_popAll(&vm->history.extras);
}
}
#endif // BC_ENABLE_HISTORY
@@ -196,7 +196,7 @@ bc_file_flush(BcFile* restrict f, BcFlushType type)
// For EOF, set it and jump.
if (s == BC_STATUS_EOF)
{
- vm.status = (sig_atomic_t) s;
+ vm->status = (sig_atomic_t) s;
BC_SIG_TRYUNLOCK(lock);
BC_JMP;
}
@@ -234,7 +234,7 @@ bc_file_write(BcFile* restrict f, BcFlushType type, const char* buf, size_t n)
// For EOF, set it and jump.
if (s == BC_STATUS_EOF)
{
- vm.status = (sig_atomic_t) s;
+ vm->status = (sig_atomic_t) s;
BC_SIG_TRYUNLOCK(lock);
BC_JMP;
}
@@ -276,103 +276,118 @@ bc_file_vprintf(BcFile* restrict f, const char* fmt, va_list args)
#if BC_ENABLE_LINE_LIB
- // Just print and propagate the error.
- if (BC_ERR(vfprintf(f->f, fmt, args) < 0))
{
- bc_vm_fatalError(BC_ERR_FATAL_IO_ERR);
+ int r;
+
+ // This mess is to silence a warning.
+#if BC_CLANG
+#pragma clang diagnostic ignored "-Wformat-nonliteral"
+#endif // BC_CLANG
+ r = vfprintf(f->f, fmt, args);
+#if BC_CLANG
+#pragma clang diagnostic warning "-Wformat-nonliteral"
+#endif // BC_CLANG
+
+ // Just print and propagate the error.
+ if (BC_ERR(r < 0))
+ {
+ bc_vm_fatalError(BC_ERR_FATAL_IO_ERR);
+ }
}
#else // BC_ENABLE_LINE_LIB
- char* percent;
- const char* ptr = fmt;
- char buf[BC_FILE_ULL_LENGTH];
-
- // This is a poor man's printf(). While I could look up algorithms to make
- // it as fast as possible, and should when I write the standard library for
- // a new language, for bc, outputting is not the bottleneck. So we cheese it
- // for now.
-
- // Find each percent sign.
- while ((percent = strchr(ptr, '%')) != NULL)
{
- char c;
+ char* percent;
+ const char* ptr = fmt;
+ char buf[BC_FILE_ULL_LENGTH];
- // If the percent sign is not where we are, write what's inbetween to
- // the buffer.
- if (percent != ptr)
- {
- size_t len = (size_t) (percent - ptr);
- bc_file_write(f, bc_flush_none, ptr, len);
- }
+ // This is a poor man's printf(). While I could look up algorithms to
+ // make it as fast as possible, and should when I write the standard
+ // library for a new language, for bc, outputting is not the bottleneck.
+ // So we cheese it for now.
- c = percent[1];
-
- // We only parse some format specifiers, the ones bc uses. If you add
- // more, you need to make sure to add them here.
- if (c == 'c')
+ // Find each percent sign.
+ while ((percent = strchr(ptr, '%')) != NULL)
{
- uchar uc = (uchar) va_arg(args, int);
+ char c;
- bc_file_putchar(f, bc_flush_none, uc);
- }
- else if (c == 's')
- {
- char* s = va_arg(args, char*);
+ // If the percent sign is not where we are, write what's inbetween
+ // to the buffer.
+ if (percent != ptr)
+ {
+ size_t len = (size_t) (percent - ptr);
+ bc_file_write(f, bc_flush_none, ptr, len);
+ }
- bc_file_puts(f, bc_flush_none, s);
- }
-#if BC_DEBUG_CODE
- // We only print signed integers in debug code.
- else if (c == 'd')
- {
- int d = va_arg(args, int);
+ c = percent[1];
- // Take care of negative. Let's not worry about overflow.
- if (d < 0)
+ // We only parse some format specifiers, the ones bc uses. If you
+ // add more, you need to make sure to add them here.
+ if (c == 'c')
{
- bc_file_putchar(f, bc_flush_none, '-');
- d = -d;
+ uchar uc = (uchar) va_arg(args, int);
+
+ bc_file_putchar(f, bc_flush_none, uc);
}
+ else if (c == 's')
+ {
+ char* s = va_arg(args, char*);
- // Either print 0 or translate and print.
- if (!d) bc_file_putchar(f, bc_flush_none, '0');
- else
+ bc_file_puts(f, bc_flush_none, s);
+ }
+#if BC_DEBUG_CODE
+ // We only print signed integers in debug code.
+ else if (c == 'd')
{
- bc_file_ultoa((unsigned long long) d, buf);
- bc_file_puts(f, bc_flush_none, buf);
+ int d = va_arg(args, int);
+
+ // Take care of negative. Let's not worry about overflow.
+ if (d < 0)
+ {
+ bc_file_putchar(f, bc_flush_none, '-');
+ d = -d;
+ }
+
+ // Either print 0 or translate and print.
+ if (!d) bc_file_putchar(f, bc_flush_none, '0');
+ else
+ {
+ bc_file_ultoa((unsigned long long) d, buf);
+ bc_file_puts(f, bc_flush_none, buf);
+ }
}
- }
#endif // BC_DEBUG_CODE
- else
- {
- unsigned long long ull;
+ else
+ {
+ unsigned long long ull;
- // These are the ones that it expects from here. Fortunately, all of
- // these are unsigned types, so they can use the same code, more or
- // less.
- assert((c == 'l' || c == 'z') && percent[2] == 'u');
+ // These are the ones that it expects from here. Fortunately,
+ // all of these are unsigned types, so they can use the same
+ // code, more or less.
+ assert((c == 'l' || c == 'z') && percent[2] == 'u');
- if (c == 'z') ull = (unsigned long long) va_arg(args, size_t);
- else ull = (unsigned long long) va_arg(args, unsigned long);
+ if (c == 'z') ull = (unsigned long long) va_arg(args, size_t);
+ else ull = (unsigned long long) va_arg(args, unsigned long);
- // Either print 0 or translate and print.
- if (!ull) bc_file_putchar(f, bc_flush_none, '0');
- else
- {
- bc_file_ultoa(ull, buf);
- bc_file_puts(f, bc_flush_none, buf);
+ // Either print 0 or translate and print.
+ if (!ull) bc_file_putchar(f, bc_flush_none, '0');
+ else
+ {
+ bc_file_ultoa(ull, buf);
+ bc_file_puts(f, bc_flush_none, buf);
+ }
}
+
+ // Increment to the next spot after the specifier.
+ ptr = percent + 2 + (c == 'l' || c == 'z');
}
- // Increment to the next spot after the specifier.
- ptr = percent + 2 + (c == 'l' || c == 'z');
+ // If we get here, there are no more percent signs, so we just output
+ // whatever is left.
+ if (ptr[0]) bc_file_puts(f, bc_flush_none, ptr);
}
- // If we get here, there are no more percent signs, so we just output
- // whatever is left.
- if (ptr[0]) bc_file_puts(f, bc_flush_none, ptr);
-
#endif // BC_ENABLE_LINE_LIB
}
diff --git a/src/history.c b/src/history.c
index 3433c0ed8ddf..bc15da5b8f1d 100644
--- a/src/history.c
+++ b/src/history.c
@@ -195,7 +195,7 @@ bc_history_init(BcHistory* h)
h->hist = history_init();
if (BC_ERR(h->hist == NULL)) bc_vm_fatalError(BC_ERR_FATAL_ALLOC_ERR);
- h->el = el_init(vm.name, stdin, stdout, stderr);
+ h->el = el_init(vm->name, stdin, stdout, stderr);
if (BC_ERR(h->el == NULL)) bc_vm_fatalError(BC_ERR_FATAL_ALLOC_ERR);
// I want history and a prompt.
@@ -269,7 +269,7 @@ bc_history_line(BcHistory* h, BcVec* vec, const char* prompt)
}
else
{
- bc_file_printf(&vm.fout, "\n");
+ bc_file_printf(&vm->fout, "\n");
s = BC_STATUS_EOF;
}
}
@@ -368,7 +368,7 @@ bc_history_line(BcHistory* h, BcVec* vec, const char* prompt)
}
else if (h->line == NULL)
{
- bc_file_printf(&vm.fout, "%s\n", "^D");
+ bc_file_printf(&vm->fout, "%s\n", "^D");
s = BC_STATUS_EOF;
}
else bc_vec_string(vec, 1, "\n");
@@ -566,9 +566,11 @@ bc_history_nextLen(const char* buf, size_t buf_len, size_t pos, size_t* col_len)
{
BC_UNREACHABLE
+#if !BC_CLANG
if (col_len != NULL) *col_len = 0;
return 0;
+#endif // !BC_CLANG
}
// Store the width of the character on screen.
@@ -617,7 +619,9 @@ bc_history_prevLen(const char* buf, size_t pos)
BC_UNREACHABLE
+#if !BC_CLANG
return 0;
+#endif // BC_CLANG
}
/**
@@ -670,6 +674,7 @@ static BcStatus
bc_history_readCode(char* buf, size_t buf_len, uint32_t* cp, size_t* nread)
{
ssize_t n;
+ uchar byte;
assert(buf_len >= 1);
@@ -683,7 +688,7 @@ bc_history_readCode(char* buf, size_t buf_len, uint32_t* cp, size_t* nread)
if (BC_ERR(n <= 0)) goto err;
// Get the byte.
- uchar byte = ((uchar*) buf)[0];
+ byte = ((uchar*) buf)[0];
// Once again, this is the UTF-8 decoding algorithm, but it has reads
// instead of actual decoding.
@@ -898,8 +903,8 @@ bc_history_cursorPos(void)
BC_SIG_ASSERT_LOCKED;
// Report cursor location.
- bc_file_write(&vm.fout, bc_flush_none, "\x1b[6n", 4);
- bc_file_flush(&vm.fout, bc_flush_none);
+ bc_file_write(&vm->fout, bc_flush_none, "\x1b[6n", 4);
+ bc_file_flush(&vm->fout, bc_flush_none);
// Read the response: ESC [ rows ; cols R.
for (i = 0; i < sizeof(buf) - 1; ++i)
@@ -942,7 +947,7 @@ bc_history_columns(void)
struct winsize ws;
int ret;
- ret = ioctl(vm.fout.fd, TIOCGWINSZ, &ws);
+ ret = ioctl(vm->fout.fd, TIOCGWINSZ, &ws);
if (BC_ERR(ret == -1 || !ws.ws_col))
{
@@ -954,16 +959,16 @@ bc_history_columns(void)
if (BC_ERR(start == SIZE_MAX)) return BC_HIST_DEF_COLS;
// Go to right margin and get position.
- bc_file_write(&vm.fout, bc_flush_none, "\x1b[999C", 6);
- bc_file_flush(&vm.fout, bc_flush_none);
+ bc_file_write(&vm->fout, bc_flush_none, "\x1b[999C", 6);
+ bc_file_flush(&vm->fout, bc_flush_none);
cols = bc_history_cursorPos();
if (BC_ERR(cols == SIZE_MAX)) return BC_HIST_DEF_COLS;
// Restore position.
if (cols > start)
{
- bc_file_printf(&vm.fout, "\x1b[%zuD", cols - start);
- bc_file_flush(&vm.fout, bc_flush_none);
+ bc_file_printf(&vm->fout, "\x1b[%zuD", cols - start);
+ bc_file_flush(&vm->fout, bc_flush_none);
}
return cols;
@@ -1021,7 +1026,7 @@ bc_history_refresh(BcHistory* h)
BC_SIG_ASSERT_LOCKED;
- bc_file_flush(&vm.fout, bc_flush_none);
+ bc_file_flush(&vm->fout, bc_flush_none);
// Get to the prompt column position from the left.
while (h->pcol + bc_history_colPos(buf, len, pos) >= h->cols)
@@ -1040,7 +1045,7 @@ bc_history_refresh(BcHistory* h)
}
// Cursor to left edge.
- bc_file_write(&vm.fout, bc_flush_none, "\r", 1);
+ bc_file_write(&vm->fout, bc_flush_none, "\r", 1);
// Take the extra stuff into account. This is where history makes sure to
// preserve stuff that was printed without a newline.
@@ -1053,16 +1058,16 @@ bc_history_refresh(BcHistory* h)
len += extras_len;
pos += extras_len;
- bc_file_write(&vm.fout, bc_flush_none, h->extras.v, extras_len);
+ bc_file_write(&vm->fout, bc_flush_none, h->extras.v, extras_len);
}
// Write the prompt, if desired.
- if (BC_PROMPT) bc_file_write(&vm.fout, bc_flush_none, h->prompt, h->plen);
+ if (BC_PROMPT) bc_file_write(&vm->fout, bc_flush_none, h->prompt, h->plen);
- bc_file_write(&vm.fout, bc_flush_none, h->buf.v, len - extras_len);
+ bc_file_write(&vm->fout, bc_flush_none, h->buf.v, len - extras_len);
// Erase to right.
- bc_file_write(&vm.fout, bc_flush_none, "\x1b[0K", 4);
+ bc_file_write(&vm->fout, bc_flush_none, "\x1b[0K", 4);
// We need to be sure to grow this.
if (pos >= h->buf.len - extras_len) bc_vec_grow(&h->buf, pos + extras_len);
@@ -1070,13 +1075,13 @@ bc_history_refresh(BcHistory* h)
// Move cursor to original position. Do NOT move the putchar of '\r' to the
// printf with colpos. That causes a bug where the cursor will go to the end
// of the line when there is no prompt.
- bc_file_putchar(&vm.fout, bc_flush_none, '\r');
+ bc_file_putchar(&vm->fout, bc_flush_none, '\r');
colpos = bc_history_colPos(h->buf.v, len - extras_len, pos) + h->pcol;
// Set the cursor position again.
- if (colpos) bc_file_printf(&vm.fout, "\x1b[%zuC", colpos);
+ if (colpos) bc_file_printf(&vm->fout, "\x1b[%zuC", colpos);
- bc_file_flush(&vm.fout, bc_flush_none);
+ bc_file_flush(&vm->fout, bc_flush_none);
}
/**
@@ -1114,8 +1119,8 @@ bc_history_edit_insert(BcHistory* h, const char* cbuf, size_t clen)
if (colpos < h->cols)
{
// Avoid a full update of the line in the trivial case.
- bc_file_write(&vm.fout, bc_flush_none, cbuf, clen);
- bc_file_flush(&vm.fout, bc_flush_none);
+ bc_file_write(&vm->fout, bc_flush_none, cbuf, clen);
+ bc_file_flush(&vm->fout, bc_flush_none);
}
else bc_history_refresh(h);
}
@@ -1706,10 +1711,10 @@ bc_history_add(BcHistory* h, char* line)
static void
bc_history_add_empty(BcHistory* h)
{
- BC_SIG_ASSERT_LOCKED;
-
const char* line = "";
+ BC_SIG_ASSERT_LOCKED;
+
// If there is something already there...
if (h->history.len)
{
@@ -1773,7 +1778,7 @@ bc_history_printCtrl(BcHistory* h, unsigned int c)
{
// We sometimes want to print a newline; for the times we don't; it's
// because newlines are taken care of elsewhere.
- bc_file_write(&vm.fout, bc_flush_none, newline, sizeof(newline) - 1);
+ bc_file_write(&vm->fout, bc_flush_none, newline, sizeof(newline) - 1);
bc_history_refresh(h);
}
}
@@ -1796,7 +1801,7 @@ bc_history_edit(BcHistory* h, const char* prompt)
// Don't write the saved output the first time. This is because it has
// already been written to output. In other words, don't uncomment the
// line below or add anything like it.
- // bc_file_write(&vm.fout, bc_flush_none, h->extras.v, h->extras.len - 1);
+ // bc_file_write(&vm->fout, bc_flush_none, h->extras.v, h->extras.len - 1);
// Write the prompt if desired.
if (BC_PROMPT)
@@ -1805,8 +1810,8 @@ bc_history_edit(BcHistory* h, const char* prompt)
h->plen = strlen(prompt);
h->pcol = bc_history_promptColLen(prompt, h->plen);
- bc_file_write(&vm.fout, bc_flush_none, prompt, h->plen);
- bc_file_flush(&vm.fout, bc_flush_none);
+ bc_file_write(&vm->fout, bc_flush_none, prompt, h->plen);
+ bc_file_flush(&vm->fout, bc_flush_none);
}
// This is the input loop.
@@ -1851,14 +1856,14 @@ bc_history_edit(BcHistory* h, const char* prompt)
// Quit if the user wants it.
if (!BC_SIGINT)
{
- vm.status = BC_STATUS_QUIT;
+ vm->status = BC_STATUS_QUIT;
BC_SIG_UNLOCK;
BC_JMP;
}
// Print the ready message.
- bc_file_write(&vm.fout, bc_flush_none, vm.sigmsg, vm.siglen);
- bc_file_write(&vm.fout, bc_flush_none, bc_program_ready_msg,
+ bc_file_write(&vm->fout, bc_flush_none, vm->sigmsg, vm->siglen);
+ bc_file_write(&vm->fout, bc_flush_none, bc_program_ready_msg,
bc_program_ready_msg_len);
bc_history_reset(h);
bc_history_refresh(h);
@@ -1964,7 +1969,7 @@ bc_history_edit(BcHistory* h, const char* prompt)
// Clear screen.
case BC_ACTION_CTRL_L:
{
- bc_file_write(&vm.fout, bc_flush_none, "\x1b[H\x1b[2J", 7);
+ bc_file_write(&vm->fout, bc_flush_none, "\x1b[H\x1b[2J", 7);
bc_history_refresh(h);
break;
}
@@ -1992,7 +1997,7 @@ bc_history_edit(BcHistory* h, const char* prompt)
bc_history_raise(h, SIGQUIT);
}
#else // _WIN32
- vm.status = BC_STATUS_QUIT;
+ vm->status = BC_STATUS_QUIT;
BC_SIG_UNLOCK;
BC_JMP;
#endif // _WIN32
@@ -2032,7 +2037,7 @@ bc_history_line(BcHistory* h, BcVec* vec, const char* prompt)
BcStatus s;
char* line;
- assert(vm.fout.len == 0);
+ assert(vm->fout.len == 0);
bc_history_enableRaw(h);
@@ -2042,8 +2047,8 @@ bc_history_line(BcHistory* h, BcVec* vec, const char* prompt)
s = bc_history_edit(h, prompt);
// Print a newline and flush.
- bc_file_write(&vm.fout, bc_flush_none, "\n", 1);
- bc_file_flush(&vm.fout, bc_flush_none);
+ bc_file_write(&vm->fout, bc_flush_none, "\n", 1);
+ bc_file_flush(&vm->fout, bc_flush_none);
BC_SIG_LOCK;
@@ -2212,7 +2217,7 @@ bc_history_printKeyCodes(BcHistory* h)
// Go left edge manually, we are in raw mode.
bc_vm_putchar('\r', bc_flush_none);
- bc_file_flush(&vm.fout, bc_flush_none);
+ bc_file_flush(&vm->fout, bc_flush_none);
}
bc_history_disableRaw(h);
diff --git a/src/lex.c b/src/lex.c
index 0fc405e50f88..a26302a65a62 100644
--- a/src/lex.c
+++ b/src/lex.c
@@ -79,7 +79,7 @@ bc_lex_comment(BcLex* l)
got_more = false;
// If we are in stdin mode, the buffer must be the one used for stdin.
- assert(!vm.is_stdin || buf == vm.buffer.v);
+ assert(!vm->is_stdin || buf == vm->buffer.v);
// Find the end of the comment.
for (i = l->i; !end; i += !end)
@@ -94,7 +94,7 @@ bc_lex_comment(BcLex* l)
if (BC_ERR(!c || buf[i + 1] == '\0'))
{
// Read more, if possible.
- if (!vm.eof && (l->is_stdin || l->is_exprs))
+ if (!vm->eof && (l->is_stdin || l->is_exprs))
{
got_more = bc_lex_readLine(l);
}
@@ -293,7 +293,7 @@ bc_lex_file(BcLex* l, const char* file)
{
assert(l != NULL && file != NULL);
l->line = 1;
- vm.file = file;
+ vm->file = file;
}
void
@@ -320,7 +320,7 @@ bc_lex_next(BcLex* l)
// is so the parser doesn't get inundated with whitespace.
do
{
- vm.next(l);
+ vm->next(l);
}
while (l->t == BC_LEX_WHITESPACE);
}
@@ -358,7 +358,7 @@ bc_lex_readLine(BcLex* l)
BC_SIG_LOCK;
- bc_lex_fixText(l, vm.buffer.v, vm.buffer.len - 1);
+ bc_lex_fixText(l, vm->buffer.v, vm->buffer.len - 1);
return good;
}
diff --git a/src/library.c b/src/library.c
index b72b83589135..6286afcc73cb 100644
--- a/src/library.c
+++ b/src/library.c
@@ -45,86 +45,173 @@
#include <num.h>
#include <vm.h>
+#ifndef _WIN32
+#include <pthread.h>
+#endif // _WIN32
+
// The asserts in this file are important to testing; in many cases, the test
// would not work without the asserts, so don't remove them without reason.
//
// Also, there are many uses of bc_num_clear() here; that is because numbers are
// being reused, and a clean slate is required.
//
-// Also, there are a bunch of BC_UNSETJMP and BC_SETJMP_LOCKED() between calls
-// to bc_num_init(). That is because locals are being initialized, and unlike bc
-// proper, this code cannot assume that allocation failures are fatal. So we
-// have to reset the jumps every time to ensure that the locals will be correct
-// after jumping.
+// Also, there are a bunch of BC_UNSETJMP between calls to bc_num_init(). That
+// is because locals are being initialized, and unlike bc proper, this code
+// cannot assume that allocation failures are fatal. So we have to reset the
+// jumps every time to ensure that the locals will be correct after jumping.
-void
-bcl_handleSignal(void)
+static BclTls* tls = NULL;
+static BclTls tls_real;
+
+BclError
+bcl_start(void)
{
- // Signal already in flight, or bc is not executing.
- if (vm.sig || !vm.running) return;
+#ifndef _WIN32
- vm.sig = 1;
+ int r;
- assert(vm.jmp_bufs.len);
+ if (tls != NULL) return BCL_ERROR_NONE;
- if (!vm.sig_lock) BC_JMP;
+ r = pthread_key_create(&tls_real, NULL);
+ if (BC_ERR(r != 0)) return BCL_ERROR_FATAL_ALLOC_ERR;
+
+#else // _WIN32
+
+ if (tls != NULL) return BCL_ERROR_NONE;
+
+ tls_real = TlsAlloc();
+ if (BC_ERR(tls_real == TLS_OUT_OF_INDEXES))
+ {
+ return BCL_ERROR_FATAL_ALLOC_ERR;
+ }
+
+#endif // _WIN32
+
+ tls = &tls_real;
+
+ return BCL_ERROR_NONE;
}
-bool
-bcl_running(void)
+/**
+ * Sets the thread-specific data for the thread.
+ * @param vm The @a BcVm to set as the thread data.
+ * @return An error code, if any.
+ */
+static BclError
+bcl_setspecific(BcVm* vm)
{
- return vm.running != 0;
+#ifndef _WIN32
+
+ int r;
+
+ assert(tls != NULL);
+
+ r = pthread_setspecific(tls_real, vm);
+ if (BC_ERR(r != 0)) return BCL_ERROR_FATAL_ALLOC_ERR;
+
+#else // _WIN32
+
+ bool r;
+
+ assert(tls != NULL);
+
+ r = TlsSetValue(tls_real, vm);
+ if (BC_ERR(!r)) return BCL_ERROR_FATAL_ALLOC_ERR;
+
+#endif // _WIN32
+
+ return BCL_ERROR_NONE;
+}
+
+BcVm*
+bcl_getspecific(void)
+{
+ BcVm* vm;
+
+#ifndef _WIN32
+
+ vm = pthread_getspecific(tls_real);
+
+#else // _WIN32
+
+ vm = TlsGetValue(tls_real);
+
+#endif // _WIN32
+
+ return vm;
}
BclError
bcl_init(void)
{
BclError e = BCL_ERROR_NONE;
+ BcVm* vm;
+
+ assert(tls != NULL);
+
+ vm = bcl_getspecific();
+ if (vm != NULL)
+ {
+ assert(vm->refs >= 1);
- BC_SIG_LOCK;
+ vm->refs += 1;
- vm.refs += 1;
+ return e;
+ }
- if (vm.refs > 1)
+ vm = bc_vm_malloc(sizeof(BcVm));
+ if (BC_ERR(vm == NULL)) return BCL_ERROR_FATAL_ALLOC_ERR;
+
+ e = bcl_setspecific(vm);
+ if (BC_ERR(e != BCL_ERROR_NONE))
{
- BC_SIG_UNLOCK;
+ free(vm);
return e;
}
+ memset(vm, 0, sizeof(BcVm));
+
+ vm->refs += 1;
+
+ assert(vm->refs == 1);
+
// Setting these to NULL ensures that if an error occurs, we only free what
// is necessary.
- vm.ctxts.v = NULL;
- vm.jmp_bufs.v = NULL;
- vm.out.v = NULL;
+ vm->ctxts.v = NULL;
+ vm->jmp_bufs.v = NULL;
+ vm->out.v = NULL;
- vm.abrt = false;
+ vm->abrt = false;
+ vm->leading_zeroes = false;
+ vm->digit_clamp = true;
// The jmp_bufs always has to be initialized first.
- bc_vec_init(&vm.jmp_bufs, sizeof(sigjmp_buf), BC_DTOR_NONE);
+ bc_vec_init(&vm->jmp_bufs, sizeof(sigjmp_buf), BC_DTOR_NONE);
- BC_FUNC_HEADER_INIT(err);
+ BC_FUNC_HEADER(vm, err);
bc_vm_init();
- bc_vec_init(&vm.ctxts, sizeof(BclContext), BC_DTOR_NONE);
- bc_vec_init(&vm.out, sizeof(uchar), BC_DTOR_NONE);
+ bc_vec_init(&vm->ctxts, sizeof(BclContext), BC_DTOR_NONE);
+ bc_vec_init(&vm->out, sizeof(uchar), BC_DTOR_NONE);
// We need to seed this in case /dev/random and /dev/urandm don't work.
srand((unsigned int) time(NULL));
- bc_rand_init(&vm.rng);
+ bc_rand_init(&vm->rng);
err:
+
// This is why we had to set them to NULL.
- if (BC_ERR(vm.err))
+ if (BC_ERR(vm != NULL && vm->err))
{
- if (vm.out.v != NULL) bc_vec_free(&vm.out);
- if (vm.jmp_bufs.v != NULL) bc_vec_free(&vm.jmp_bufs);
- if (vm.ctxts.v != NULL) bc_vec_free(&vm.ctxts);
+ if (vm->out.v != NULL) bc_vec_free(&vm->out);
+ if (vm->jmp_bufs.v != NULL) bc_vec_free(&vm->jmp_bufs);
+ if (vm->ctxts.v != NULL) bc_vec_free(&vm->ctxts);
+ bcl_setspecific(NULL);
+ free(vm);
}
- BC_FUNC_FOOTER_UNLOCK(e);
-
- assert(!vm.running && !vm.sig && !vm.sig_lock);
+ BC_FUNC_FOOTER(vm, e);
return e;
}
@@ -133,102 +220,144 @@ BclError
bcl_pushContext(BclContext ctxt)
{
BclError e = BCL_ERROR_NONE;
+ BcVm* vm = bcl_getspecific();
- BC_FUNC_HEADER_LOCK(err);
+ BC_FUNC_HEADER(vm, err);
- bc_vec_push(&vm.ctxts, &ctxt);
+ bc_vec_push(&vm->ctxts, &ctxt);
err:
- BC_FUNC_FOOTER_UNLOCK(e);
+ BC_FUNC_FOOTER(vm, e);
return e;
}
void
bcl_popContext(void)
{
- if (vm.ctxts.len) bc_vec_pop(&vm.ctxts);
+ BcVm* vm = bcl_getspecific();
+
+ if (vm->ctxts.len) bc_vec_pop(&vm->ctxts);
+}
+
+static BclContext
+bcl_contextHelper(BcVm* vm)
+{
+ if (!vm->ctxts.len) return NULL;
+ return *((BclContext*) bc_vec_top(&vm->ctxts));
}
BclContext
bcl_context(void)
{
- if (!vm.ctxts.len) return NULL;
- return *((BclContext*) bc_vec_top(&vm.ctxts));
+ BcVm* vm = bcl_getspecific();
+ return bcl_contextHelper(vm);
}
void
bcl_free(void)
{
size_t i;
+ BcVm* vm = bcl_getspecific();
- BC_SIG_LOCK;
-
- vm.refs -= 1;
-
- if (vm.refs)
- {
- BC_SIG_UNLOCK;
- return;
- }
+ vm->refs -= 1;
+ if (vm->refs) return;
- bc_rand_free(&vm.rng);
- bc_vec_free(&vm.out);
+ bc_rand_free(&vm->rng);
+ bc_vec_free(&vm->out);
- for (i = 0; i < vm.ctxts.len; ++i)
+ for (i = 0; i < vm->ctxts.len; ++i)
{
- BclContext ctxt = *((BclContext*) bc_vec_item(&vm.ctxts, i));
+ BclContext ctxt = *((BclContext*) bc_vec_item(&vm->ctxts, i));
bcl_ctxt_free(ctxt);
}
- bc_vec_free(&vm.ctxts);
+ bc_vec_free(&vm->ctxts);
bc_vm_atexit();
- BC_SIG_UNLOCK;
+ free(vm);
+ bcl_setspecific(NULL);
+}
+
+void
+bcl_end(void)
+{
+#ifndef _WIN32
+
+ // We ignore the return value.
+ pthread_key_delete(tls_real);
- memset(&vm, 0, sizeof(BcVm));
+#else // _WIN32
- assert(!vm.running && !vm.sig && !vm.sig_lock);
+ // We ignore the return value.
+ TlsFree(tls_real);
+
+#endif // _WIN32
+
+ tls = NULL;
}
void
bcl_gc(void)
{
- BC_SIG_LOCK;
bc_vm_freeTemps();
- BC_SIG_UNLOCK;
}
bool
bcl_abortOnFatalError(void)
{
- return vm.abrt;
+ BcVm* vm = bcl_getspecific();
+
+ return vm->abrt;
}
void
bcl_setAbortOnFatalError(bool abrt)
{
- vm.abrt = abrt;
+ BcVm* vm = bcl_getspecific();
+
+ vm->abrt = abrt;
}
bool
bcl_leadingZeroes(void)
{
- return vm.leading_zeroes;
+ BcVm* vm = bcl_getspecific();
+
+ return vm->leading_zeroes;
}
void
bcl_setLeadingZeroes(bool leadingZeroes)
{
- vm.leading_zeroes = leadingZeroes;
+ BcVm* vm = bcl_getspecific();
+
+ vm->leading_zeroes = leadingZeroes;
+}
+
+bool
+bcl_digitClamp(void)
+{
+ BcVm* vm = bcl_getspecific();
+
+ return vm->digit_clamp;
+}
+
+void
+bcl_setDigitClamp(bool digitClamp)
+{
+ BcVm* vm = bcl_getspecific();
+
+ vm->digit_clamp = digitClamp;
}
BclContext
bcl_ctxt_create(void)
{
+ BcVm* vm = bcl_getspecific();
BclContext ctxt = NULL;
- BC_FUNC_HEADER_LOCK(err);
+ BC_FUNC_HEADER(vm, err);
// We want the context to be free of any interference of other parties, so
// malloc() is appropriate here.
@@ -242,16 +371,15 @@ bcl_ctxt_create(void)
ctxt->obase = 10;
err:
- if (BC_ERR(vm.err && ctxt != NULL))
+
+ if (BC_ERR(vm->err && ctxt != NULL))
{
if (ctxt->nums.v != NULL) bc_vec_free(&ctxt->nums);
free(ctxt);
ctxt = NULL;
}
- BC_FUNC_FOOTER_NO_ERR;
-
- assert(!vm.running && !vm.sig && !vm.sig_lock);
+ BC_FUNC_FOOTER_NO_ERR(vm);
return ctxt;
}
@@ -259,11 +387,9 @@ err:
void
bcl_ctxt_free(BclContext ctxt)
{
- BC_SIG_LOCK;
bc_vec_free(&ctxt->free_nums);
bc_vec_free(&ctxt->nums);
free(ctxt);
- BC_SIG_UNLOCK;
}
void
@@ -315,8 +441,9 @@ BclError
bcl_err(BclNumber n)
{
BclContext ctxt;
+ BcVm* vm = bcl_getspecific();
- BC_CHECK_CTXT_ERR(ctxt);
+ BC_CHECK_CTXT_ERR(vm, ctxt);
// Errors are encoded as (0 - error_code). If the index is in that range, it
// is an encoded error.
@@ -359,8 +486,6 @@ bcl_num_insert(BclContext ctxt, BcNum* restrict n)
bc_vec_push(&ctxt->nums, n);
}
- assert(!vm.running && !vm.sig && !vm.sig_lock);
-
return idx;
}
@@ -371,21 +496,20 @@ bcl_num_create(void)
BcNum n;
BclNumber idx;
BclContext ctxt;
+ BcVm* vm = bcl_getspecific();
- BC_CHECK_CTXT(ctxt);
+ BC_CHECK_CTXT(vm, ctxt);
- BC_FUNC_HEADER_LOCK(err);
+ BC_FUNC_HEADER(vm, err);
bc_vec_grow(&ctxt->nums, 1);
bc_num_init(&n, BC_NUM_DEF_SIZE);
err:
- BC_FUNC_FOOTER_UNLOCK(e);
+ BC_FUNC_FOOTER(vm, e);
BC_MAYBE_SETUP(ctxt, e, n, idx);
- assert(!vm.running && !vm.sig && !vm.sig_lock);
-
return idx;
}
@@ -398,8 +522,6 @@ err:
static void
bcl_num_dtor(BclContext ctxt, BclNumber n, BcNum* restrict num)
{
- BC_SIG_ASSERT_LOCKED;
-
assert(num != NULL && num->num != NULL);
bcl_num_destruct(num);
@@ -411,18 +533,15 @@ bcl_num_free(BclNumber n)
{
BcNum* num;
BclContext ctxt;
+ BcVm* vm = bcl_getspecific();
- BC_CHECK_CTXT_ASSERT(ctxt);
-
- BC_SIG_LOCK;
+ BC_CHECK_CTXT_ASSERT(vm, ctxt);
assert(n.i < ctxt->nums.len);
num = BC_NUM(ctxt, n);
bcl_num_dtor(ctxt, n, num);
-
- BC_SIG_UNLOCK;
}
BclError
@@ -432,10 +551,11 @@ bcl_copy(BclNumber d, BclNumber s)
BcNum* dest;
BcNum* src;
BclContext ctxt;
+ BcVm* vm = bcl_getspecific();
- BC_CHECK_CTXT_ERR(ctxt);
+ BC_CHECK_CTXT_ERR(vm, ctxt);
- BC_FUNC_HEADER_LOCK(err);
+ BC_FUNC_HEADER(vm, err);
assert(d.i < ctxt->nums.len && s.i < ctxt->nums.len);
@@ -448,9 +568,7 @@ bcl_copy(BclNumber d, BclNumber s)
bc_num_copy(dest, src);
err:
- BC_FUNC_FOOTER_UNLOCK(e);
-
- assert(!vm.running && !vm.sig && !vm.sig_lock);
+ BC_FUNC_FOOTER(vm, e);
return e;
}
@@ -462,10 +580,11 @@ bcl_dup(BclNumber s)
BcNum *src, dest;
BclNumber idx;
BclContext ctxt;
+ BcVm* vm = bcl_getspecific();
- BC_CHECK_CTXT(ctxt);
+ BC_CHECK_CTXT(vm, ctxt);
- BC_FUNC_HEADER_LOCK(err);
+ BC_FUNC_HEADER(vm, err);
bc_vec_grow(&ctxt->nums, 1);
@@ -480,11 +599,9 @@ bcl_dup(BclNumber s)
bc_num_createCopy(&dest, src);
err:
- BC_FUNC_FOOTER_UNLOCK(e);
+ BC_FUNC_FOOTER(vm, e);
BC_MAYBE_SETUP(ctxt, e, dest, idx);
- assert(!vm.running && !vm.sig && !vm.sig_lock);
-
return idx;
}
@@ -506,8 +623,9 @@ bcl_num_neg(BclNumber n)
{
BcNum* num;
BclContext ctxt;
+ BcVm* vm = bcl_getspecific();
- BC_CHECK_CTXT_ASSERT(ctxt);
+ BC_CHECK_CTXT_ASSERT(vm, ctxt);
assert(n.i < ctxt->nums.len);
@@ -523,8 +641,9 @@ bcl_num_setNeg(BclNumber n, bool neg)
{
BcNum* num;
BclContext ctxt;
+ BcVm* vm = bcl_getspecific();
- BC_CHECK_CTXT_ASSERT(ctxt);
+ BC_CHECK_CTXT_ASSERT(vm, ctxt);
assert(n.i < ctxt->nums.len);
@@ -540,8 +659,9 @@ bcl_num_scale(BclNumber n)
{
BcNum* num;
BclContext ctxt;
+ BcVm* vm = bcl_getspecific();
- BC_CHECK_CTXT_ASSERT(ctxt);
+ BC_CHECK_CTXT_ASSERT(vm, ctxt);
assert(n.i < ctxt->nums.len);
@@ -558,12 +678,13 @@ bcl_num_setScale(BclNumber n, size_t scale)
BclError e = BCL_ERROR_NONE;
BcNum* nptr;
BclContext ctxt;
+ BcVm* vm = bcl_getspecific();
- BC_CHECK_CTXT_ERR(ctxt);
+ BC_CHECK_CTXT_ERR(vm, ctxt);
BC_CHECK_NUM_ERR(ctxt, n);
- BC_FUNC_HEADER(err);
+ BC_FUNC_HEADER(vm, err);
assert(n.i < ctxt->nums.len);
@@ -575,10 +696,7 @@ bcl_num_setScale(BclNumber n, size_t scale)
else if (scale < nptr->scale) bc_num_truncate(nptr, nptr->scale - scale);
err:
- BC_SIG_MAYLOCK;
- BC_FUNC_FOOTER(e);
-
- assert(!vm.running && !vm.sig && !vm.sig_lock);
+ BC_FUNC_FOOTER(vm, e);
return e;
}
@@ -588,8 +706,9 @@ bcl_num_len(BclNumber n)
{
BcNum* num;
BclContext ctxt;
+ BcVm* vm = bcl_getspecific();
- BC_CHECK_CTXT_ASSERT(ctxt);
+ BC_CHECK_CTXT_ASSERT(vm, ctxt);
assert(n.i < ctxt->nums.len);
@@ -606,10 +725,11 @@ bcl_bigdig(BclNumber n, BclBigDig* result)
BclError e = BCL_ERROR_NONE;
BcNum* num;
BclContext ctxt;
+ BcVm* vm = bcl_getspecific();
- BC_CHECK_CTXT_ERR(ctxt);
+ BC_CHECK_CTXT_ERR(vm, ctxt);
- BC_FUNC_HEADER_LOCK(err);
+ BC_FUNC_HEADER(vm, err);
assert(n.i < ctxt->nums.len);
assert(result != NULL);
@@ -622,9 +742,7 @@ bcl_bigdig(BclNumber n, BclBigDig* result)
err:
bcl_num_dtor(ctxt, n, num);
- BC_FUNC_FOOTER_UNLOCK(e);
-
- assert(!vm.running && !vm.sig && !vm.sig_lock);
+ BC_FUNC_FOOTER(vm, e);
return e;
}
@@ -636,21 +754,20 @@ bcl_bigdig2num(BclBigDig val)
BcNum n;
BclNumber idx;
BclContext ctxt;
+ BcVm* vm = bcl_getspecific();
- BC_CHECK_CTXT(ctxt);
+ BC_CHECK_CTXT(vm, ctxt);
- BC_FUNC_HEADER_LOCK(err);
+ BC_FUNC_HEADER(vm, err);
bc_vec_grow(&ctxt->nums, 1);
bc_num_createFromBigdig(&n, val);
err:
- BC_FUNC_FOOTER_UNLOCK(e);
+ BC_FUNC_FOOTER(vm, e);
BC_MAYBE_SETUP(ctxt, e, n, idx);
- assert(!vm.running && !vm.sig && !vm.sig_lock);
-
return idx;
}
@@ -672,13 +789,14 @@ bcl_binary(BclNumber a, BclNumber b, const BcNumBinaryOp op,
BcNum c;
BclNumber idx;
BclContext ctxt;
+ BcVm* vm = bcl_getspecific();
- BC_CHECK_CTXT(ctxt);
+ BC_CHECK_CTXT(vm, ctxt);
BC_CHECK_NUM(ctxt, a);
BC_CHECK_NUM(ctxt, b);
- BC_FUNC_HEADER_LOCK(err);
+ BC_FUNC_HEADER(vm, err);
bc_vec_grow(&ctxt->nums, 1);
@@ -694,23 +812,17 @@ bcl_binary(BclNumber a, BclNumber b, const BcNumBinaryOp op,
bc_num_clear(&c);
bc_num_init(&c, req(aptr, bptr, ctxt->scale));
- BC_SIG_UNLOCK;
-
op(aptr, bptr, &c, ctxt->scale);
err:
- BC_SIG_MAYLOCK;
-
// Eat the operands.
bcl_num_dtor(ctxt, a, aptr);
if (b.i != a.i) bcl_num_dtor(ctxt, b, bptr);
- BC_FUNC_FOOTER(e);
+ BC_FUNC_FOOTER(vm, e);
BC_MAYBE_SETUP(ctxt, e, c, idx);
- assert(!vm.running && !vm.sig && !vm.sig_lock);
-
return idx;
}
@@ -770,12 +882,13 @@ bcl_sqrt(BclNumber a)
BcNum b;
BclNumber idx;
BclContext ctxt;
+ BcVm* vm = bcl_getspecific();
- BC_CHECK_CTXT(ctxt);
+ BC_CHECK_CTXT(vm, ctxt);
BC_CHECK_NUM(ctxt, a);
- BC_FUNC_HEADER(err);
+ BC_FUNC_HEADER(vm, err);
bc_vec_grow(&ctxt->nums, 1);
@@ -786,13 +899,10 @@ bcl_sqrt(BclNumber a)
bc_num_sqrt(aptr, &b, ctxt->scale);
err:
- BC_SIG_MAYLOCK;
bcl_num_dtor(ctxt, a, aptr);
- BC_FUNC_FOOTER(e);
+ BC_FUNC_FOOTER(vm, e);
BC_MAYBE_SETUP(ctxt, e, b, idx);
- assert(!vm.running && !vm.sig && !vm.sig_lock);
-
return idx;
}
@@ -805,13 +915,14 @@ bcl_divmod(BclNumber a, BclNumber b, BclNumber* c, BclNumber* d)
BcNum* bptr;
BcNum cnum, dnum;
BclContext ctxt;
+ BcVm* vm = bcl_getspecific();
- BC_CHECK_CTXT_ERR(ctxt);
+ BC_CHECK_CTXT_ERR(vm, ctxt);
BC_CHECK_NUM_ERR(ctxt, a);
BC_CHECK_NUM_ERR(ctxt, b);
- BC_FUNC_HEADER_LOCK(err);
+ BC_FUNC_HEADER(vm, err);
bc_vec_grow(&ctxt->nums, 2);
@@ -830,23 +941,20 @@ bcl_divmod(BclNumber a, BclNumber b, BclNumber* c, BclNumber* d)
// Initialize the numbers.
bc_num_init(&cnum, req);
- BC_UNSETJMP;
- BC_SETJMP_LOCKED(err);
+ BC_UNSETJMP(vm);
+ BC_SETJMP(vm, err);
bc_num_init(&dnum, req);
- BC_SIG_UNLOCK;
-
bc_num_divmod(aptr, bptr, &cnum, &dnum, ctxt->scale);
err:
- BC_SIG_MAYLOCK;
// Eat the operands.
bcl_num_dtor(ctxt, a, aptr);
if (b.i != a.i) bcl_num_dtor(ctxt, b, bptr);
// If there was an error...
- if (BC_ERR(vm.err))
+ if (BC_ERR(vm->err))
{
// Free the results.
if (cnum.num != NULL) bc_num_free(&cnum);
@@ -856,19 +964,17 @@ err:
c->i = 0 - (size_t) BCL_ERROR_INVALID_NUM;
d->i = c->i;
- BC_FUNC_FOOTER(e);
+ BC_FUNC_FOOTER(vm, e);
}
else
{
- BC_FUNC_FOOTER(e);
+ BC_FUNC_FOOTER(vm, e);
// Insert the results into the context.
*c = bcl_num_insert(ctxt, &cnum);
*d = bcl_num_insert(ctxt, &dnum);
}
- assert(!vm.running && !vm.sig && !vm.sig_lock);
-
return e;
}
@@ -883,14 +989,15 @@ bcl_modexp(BclNumber a, BclNumber b, BclNumber c)
BcNum d;
BclNumber idx;
BclContext ctxt;
+ BcVm* vm = bcl_getspecific();
- BC_CHECK_CTXT(ctxt);
+ BC_CHECK_CTXT(vm, ctxt);
BC_CHECK_NUM(ctxt, a);
BC_CHECK_NUM(ctxt, b);
BC_CHECK_NUM(ctxt, c);
- BC_FUNC_HEADER_LOCK(err);
+ BC_FUNC_HEADER(vm, err);
bc_vec_grow(&ctxt->nums, 1);
@@ -912,23 +1019,18 @@ bcl_modexp(BclNumber a, BclNumber b, BclNumber c)
// Initialize the result.
bc_num_init(&d, req);
- BC_SIG_UNLOCK;
-
bc_num_modexp(aptr, bptr, cptr, &d);
err:
- BC_SIG_MAYLOCK;
// Eat the operands.
bcl_num_dtor(ctxt, a, aptr);
if (b.i != a.i) bcl_num_dtor(ctxt, b, bptr);
if (c.i != a.i && c.i != b.i) bcl_num_dtor(ctxt, c, cptr);
- BC_FUNC_FOOTER(e);
+ BC_FUNC_FOOTER(vm, e);
BC_MAYBE_SETUP(ctxt, e, d, idx);
- assert(!vm.running && !vm.sig && !vm.sig_lock);
-
return idx;
}
@@ -938,8 +1040,9 @@ bcl_cmp(BclNumber a, BclNumber b)
BcNum* aptr;
BcNum* bptr;
BclContext ctxt;
+ BcVm* vm = bcl_getspecific();
- BC_CHECK_CTXT_ASSERT(ctxt);
+ BC_CHECK_CTXT_ASSERT(vm, ctxt);
assert(a.i < ctxt->nums.len && b.i < ctxt->nums.len);
@@ -957,8 +1060,9 @@ bcl_zero(BclNumber n)
{
BcNum* nptr;
BclContext ctxt;
+ BcVm* vm = bcl_getspecific();
- BC_CHECK_CTXT_ASSERT(ctxt);
+ BC_CHECK_CTXT_ASSERT(vm, ctxt);
assert(n.i < ctxt->nums.len);
@@ -974,8 +1078,9 @@ bcl_one(BclNumber n)
{
BcNum* nptr;
BclContext ctxt;
+ BcVm* vm = bcl_getspecific();
- BC_CHECK_CTXT_ASSERT(ctxt);
+ BC_CHECK_CTXT_ASSERT(vm, ctxt);
assert(n.i < ctxt->nums.len);
@@ -993,11 +1098,12 @@ bcl_parse(const char* restrict val)
BcNum n;
BclNumber idx;
BclContext ctxt;
+ BcVm* vm = bcl_getspecific();
bool neg;
- BC_CHECK_CTXT(ctxt);
+ BC_CHECK_CTXT(vm, ctxt);
- BC_FUNC_HEADER_LOCK(err);
+ BC_FUNC_HEADER(vm, err);
bc_vec_grow(&ctxt->nums, 1);
@@ -1011,7 +1117,7 @@ bcl_parse(const char* restrict val)
if (!bc_num_strValid(val))
{
- vm.err = BCL_ERROR_PARSE_INVALID_STR;
+ vm->err = BCL_ERROR_PARSE_INVALID_STR;
goto err;
}
@@ -1019,20 +1125,15 @@ bcl_parse(const char* restrict val)
bc_num_clear(&n);
bc_num_init(&n, BC_NUM_DEF_SIZE);
- BC_SIG_UNLOCK;
-
bc_num_parse(&n, val, (BcBigDig) ctxt->ibase);
// Set the negative.
n.rdx = BC_NUM_NEG_VAL_NP(n, neg);
err:
- BC_SIG_MAYLOCK;
- BC_FUNC_FOOTER(e);
+ BC_FUNC_FOOTER(vm, e);
BC_MAYBE_SETUP(ctxt, e, n, idx);
- assert(!vm.running && !vm.sig && !vm.sig_lock);
-
return idx;
}
@@ -1042,12 +1143,13 @@ bcl_string(BclNumber n)
BcNum* nptr;
char* str = NULL;
BclContext ctxt;
+ BcVm* vm = bcl_getspecific();
- BC_CHECK_CTXT_ASSERT(ctxt);
+ BC_CHECK_CTXT_ASSERT(vm, ctxt);
if (BC_ERR(n.i >= ctxt->nums.len)) return str;
- BC_FUNC_HEADER(err);
+ BC_FUNC_HEADER(vm, err);
assert(n.i < ctxt->nums.len);
@@ -1056,25 +1158,21 @@ bcl_string(BclNumber n)
assert(nptr != NULL && nptr->num != NULL);
// Clear the buffer.
- bc_vec_popAll(&vm.out);
+ bc_vec_popAll(&vm->out);
// Print to the buffer.
bc_num_print(nptr, (BcBigDig) ctxt->obase, false);
- bc_vec_pushByte(&vm.out, '\0');
-
- BC_SIG_LOCK;
+ bc_vec_pushByte(&vm->out, '\0');
// Just dup the string; the caller is responsible for it.
- str = bc_vm_strdup(vm.out.v);
+ str = bc_vm_strdup(vm->out.v);
err:
// Eat the operand.
bcl_num_dtor(ctxt, n, nptr);
- BC_FUNC_FOOTER_NO_ERR;
-
- assert(!vm.running && !vm.sig && !vm.sig_lock);
+ BC_FUNC_FOOTER_NO_ERR(vm);
return str;
}
@@ -1087,12 +1185,13 @@ bcl_irand(BclNumber a)
BcNum b;
BclNumber idx;
BclContext ctxt;
+ BcVm* vm = bcl_getspecific();
- BC_CHECK_CTXT(ctxt);
+ BC_CHECK_CTXT(vm, ctxt);
BC_CHECK_NUM(ctxt, a);
- BC_FUNC_HEADER_LOCK(err);
+ BC_FUNC_HEADER(vm, err);
bc_vec_grow(&ctxt->nums, 1);
@@ -1106,21 +1205,16 @@ bcl_irand(BclNumber a)
bc_num_clear(&b);
bc_num_init(&b, BC_NUM_DEF_SIZE);
- BC_SIG_UNLOCK;
-
- bc_num_irand(aptr, &b, &vm.rng);
+ bc_num_irand(aptr, &b, &vm->rng);
err:
- BC_SIG_MAYLOCK;
// Eat the operand.
bcl_num_dtor(ctxt, a, aptr);
- BC_FUNC_FOOTER(e);
+ BC_FUNC_FOOTER(vm, e);
BC_MAYBE_SETUP(ctxt, e, b, idx);
- assert(!vm.running && !vm.sig && !vm.sig_lock);
-
return idx;
}
@@ -1136,6 +1230,7 @@ bcl_frandHelper(BcNum* restrict b, size_t places)
BcNum exp, pow, ten;
BcDig exp_digs[BC_NUM_BIGDIG_LOG10];
BcDig ten_digs[BC_NUM_BIGDIG_LOG10];
+ BcVm* vm = bcl_getspecific();
// Set up temporaries.
bc_num_setup(&exp, exp_digs, BC_NUM_BIGDIG_LOG10);
@@ -1149,26 +1244,21 @@ bcl_frandHelper(BcNum* restrict b, size_t places)
// Clear the temporary that might need to grow.
bc_num_clear(&pow);
- BC_SIG_LOCK;
-
// Initialize the temporary that might need to grow.
bc_num_init(&pow, bc_num_powReq(&ten, &exp, 0));
- BC_SETJMP_LOCKED(err);
-
- BC_SIG_UNLOCK;
+ BC_SETJMP(vm, err);
// Generate the number.
bc_num_pow(&ten, &exp, &pow, 0);
- bc_num_irand(&pow, b, &vm.rng);
+ bc_num_irand(&pow, b, &vm->rng);
// Make the number entirely fraction.
bc_num_shiftRight(b, places);
err:
- BC_SIG_MAYLOCK;
bc_num_free(&pow);
- BC_LONGJMP_CONT;
+ BC_LONGJMP_CONT(vm);
}
BclNumber
@@ -1178,10 +1268,11 @@ bcl_frand(size_t places)
BcNum n;
BclNumber idx;
BclContext ctxt;
+ BcVm* vm = bcl_getspecific();
- BC_CHECK_CTXT(ctxt);
+ BC_CHECK_CTXT(vm, ctxt);
- BC_FUNC_HEADER_LOCK(err);
+ BC_FUNC_HEADER(vm, err);
bc_vec_grow(&ctxt->nums, 1);
@@ -1189,18 +1280,13 @@ bcl_frand(size_t places)
bc_num_clear(&n);
bc_num_init(&n, BC_NUM_DEF_SIZE);
- BC_SIG_UNLOCK;
-
bcl_frandHelper(&n, places);
err:
- BC_SIG_MAYLOCK;
- BC_FUNC_FOOTER(e);
+ BC_FUNC_FOOTER(vm, e);
BC_MAYBE_SETUP(ctxt, e, n, idx);
- assert(!vm.running && !vm.sig && !vm.sig_lock);
-
return idx;
}
@@ -1215,31 +1301,27 @@ static void
bcl_ifrandHelper(BcNum* restrict a, BcNum* restrict b, size_t places)
{
BcNum ir, fr;
+ BcVm* vm = bcl_getspecific();
// Clear the integer and fractional numbers.
bc_num_clear(&ir);
bc_num_clear(&fr);
- BC_SIG_LOCK;
-
// Initialize the integer and fractional numbers.
bc_num_init(&ir, BC_NUM_DEF_SIZE);
bc_num_init(&fr, BC_NUM_DEF_SIZE);
- BC_SETJMP_LOCKED(err);
+ BC_SETJMP(vm, err);
- BC_SIG_UNLOCK;
-
- bc_num_irand(a, &ir, &vm.rng);
+ bc_num_irand(a, &ir, &vm->rng);
bcl_frandHelper(&fr, places);
bc_num_add(&ir, &fr, b, 0);
err:
- BC_SIG_MAYLOCK;
bc_num_free(&fr);
bc_num_free(&ir);
- BC_LONGJMP_CONT;
+ BC_LONGJMP_CONT(vm);
}
BclNumber
@@ -1250,11 +1332,12 @@ bcl_ifrand(BclNumber a, size_t places)
BcNum b;
BclNumber idx;
BclContext ctxt;
+ BcVm* vm = bcl_getspecific();
- BC_CHECK_CTXT(ctxt);
+ BC_CHECK_CTXT(vm, ctxt);
BC_CHECK_NUM(ctxt, a);
- BC_FUNC_HEADER_LOCK(err);
+ BC_FUNC_HEADER(vm, err);
bc_vec_grow(&ctxt->nums, 1);
@@ -1268,21 +1351,16 @@ bcl_ifrand(BclNumber a, size_t places)
bc_num_clear(&b);
bc_num_init(&b, BC_NUM_DEF_SIZE);
- BC_SIG_UNLOCK;
-
bcl_ifrandHelper(aptr, &b, places);
err:
- BC_SIG_MAYLOCK;
// Eat the oprand.
bcl_num_dtor(ctxt, a, aptr);
- BC_FUNC_FOOTER(e);
+ BC_FUNC_FOOTER(vm, e);
BC_MAYBE_SETUP(ctxt, e, b, idx);
- assert(!vm.running && !vm.sig && !vm.sig_lock);
-
return idx;
}
@@ -1292,11 +1370,12 @@ bcl_rand_seedWithNum(BclNumber n)
BclError e = BCL_ERROR_NONE;
BcNum* nptr;
BclContext ctxt;
+ BcVm* vm = bcl_getspecific();
- BC_CHECK_CTXT_ERR(ctxt);
+ BC_CHECK_CTXT_ERR(vm, ctxt);
BC_CHECK_NUM_ERR(ctxt, n);
- BC_FUNC_HEADER(err);
+ BC_FUNC_HEADER(vm, err);
assert(n.i < ctxt->nums.len);
@@ -1304,14 +1383,10 @@ bcl_rand_seedWithNum(BclNumber n)
assert(nptr != NULL && nptr->num != NULL);
- bc_num_rng(nptr, &vm.rng);
+ bc_num_rng(nptr, &vm->rng);
err:
- BC_SIG_MAYLOCK;
- BC_FUNC_FOOTER(e);
-
- assert(!vm.running && !vm.sig && !vm.sig_lock);
-
+ BC_FUNC_FOOTER(vm, e);
return e;
}
@@ -1321,8 +1396,9 @@ bcl_rand_seed(unsigned char seed[BCL_SEED_SIZE])
BclError e = BCL_ERROR_NONE;
size_t i;
ulong vals[BCL_SEED_ULONGS];
+ BcVm* vm = bcl_getspecific();
- BC_FUNC_HEADER(err);
+ BC_FUNC_HEADER(vm, err);
// Fill the array.
for (i = 0; i < BCL_SEED_SIZE; ++i)
@@ -1332,18 +1408,19 @@ bcl_rand_seed(unsigned char seed[BCL_SEED_SIZE])
vals[i / sizeof(long)] |= val;
}
- bc_rand_seed(&vm.rng, vals[0], vals[1], vals[2], vals[3]);
+ bc_rand_seed(&vm->rng, vals[0], vals[1], vals[2], vals[3]);
err:
- BC_SIG_MAYLOCK;
- BC_FUNC_FOOTER(e);
+ BC_FUNC_FOOTER(vm, e);
return e;
}
void
bcl_rand_reseed(void)
{
- bc_rand_srand(bc_vec_top(&vm.rng.v));
+ BcVm* vm = bcl_getspecific();
+
+ bc_rand_srand(bc_vec_top(&vm->rng.v));
}
BclNumber
@@ -1353,40 +1430,40 @@ bcl_rand_seed2num(void)
BcNum n;
BclNumber idx;
BclContext ctxt;
+ BcVm* vm = bcl_getspecific();
- BC_CHECK_CTXT(ctxt);
+ BC_CHECK_CTXT(vm, ctxt);
- BC_FUNC_HEADER_LOCK(err);
+ BC_FUNC_HEADER(vm, err);
// Clear and initialize the number.
bc_num_clear(&n);
bc_num_init(&n, BC_NUM_DEF_SIZE);
- BC_SIG_UNLOCK;
-
- bc_num_createFromRNG(&n, &vm.rng);
+ bc_num_createFromRNG(&n, &vm->rng);
err:
- BC_SIG_MAYLOCK;
- BC_FUNC_FOOTER(e);
+ BC_FUNC_FOOTER(vm, e);
BC_MAYBE_SETUP(ctxt, e, n, idx);
- assert(!vm.running && !vm.sig && !vm.sig_lock);
-
return idx;
}
BclRandInt
bcl_rand_int(void)
{
- return (BclRandInt) bc_rand_int(&vm.rng);
+ BcVm* vm = bcl_getspecific();
+
+ return (BclRandInt) bc_rand_int(&vm->rng);
}
BclRandInt
bcl_rand_bounded(BclRandInt bound)
{
+ BcVm* vm = bcl_getspecific();
+
if (bound <= 1) return 0;
- return (BclRandInt) bc_rand_bounded(&vm.rng, (BcRand) bound);
+ return (BclRandInt) bc_rand_bounded(&vm->rng, (BcRand) bound);
}
#endif // BC_ENABLE_LIBRARY
diff --git a/src/main.c b/src/main.c
index 3c86088fcafc..92d85797bd46 100644
--- a/src/main.c
+++ b/src/main.c
@@ -61,7 +61,7 @@ main(int argc, char* argv[])
#if BC_ENABLE_NLS
// Must set the locale properly in order to have the right error messages.
- vm.locale = setlocale(LC_ALL, "");
+ vm->locale = setlocale(LC_ALL, "");
#endif // BC_ENABLE_NLS
// Set the start pledge().
@@ -74,37 +74,37 @@ main(int argc, char* argv[])
// basename because it's not portable, but yes, this is stripping off
// the directory.
name = strrchr(argv[0], BC_FILE_SEP);
- vm.name = (name == NULL) ? argv[0] : name + 1;
+ vm->name = (name == NULL) ? argv[0] : name + 1;
}
else
{
#if !DC_ENABLED
- vm.name = "bc";
+ vm->name = "bc";
#elif !BC_ENABLED
- vm.name = "dc";
+ vm->name = "dc";
#else
// Just default to bc in that case.
- vm.name = "bc";
+ vm->name = "bc";
#endif
}
// If the name is longer than the length of the prefix, skip the prefix.
- if (strlen(vm.name) > len) vm.name += len;
+ if (strlen(vm->name) > len) vm->name += len;
BC_SIG_LOCK;
// We *must* do this here. Otherwise, other code could not jump out all of
// the way.
- bc_vec_init(&vm.jmp_bufs, sizeof(sigjmp_buf), BC_DTOR_NONE);
+ bc_vec_init(&vm->jmp_bufs, sizeof(sigjmp_buf), BC_DTOR_NONE);
- BC_SETJMP_LOCKED(exit);
+ BC_SETJMP_LOCKED(vm, exit);
#if !DC_ENABLED
bc_main(argc, argv);
#elif !BC_ENABLED
dc_main(argc, argv);
#else
- // BC_IS_BC uses vm.name, which was set above. So we're good.
+ // BC_IS_BC uses vm->name, which was set above. So we're good.
if (BC_IS_BC) bc_main(argc, argv);
else dc_main(argc, argv);
#endif
@@ -113,5 +113,5 @@ exit:
BC_SIG_MAYLOCK;
// Ensure we exit appropriately.
- return bc_vm_atexit((int) vm.status);
+ return bc_vm_atexit((int) vm->status);
}
diff --git a/src/num.c b/src/num.c
index 4839a4b87353..a15297bb4df3 100644
--- a/src/num.c
+++ b/src/num.c
@@ -44,6 +44,9 @@
#include <num.h>
#include <rand.h>
#include <vm.h>
+#if BC_ENABLE_LIBRARY
+#include <library.h>
+#endif // BC_ENABLE_LIBRARY
// Before you try to understand this code, see the development manual
// (manuals/development.md#numbers).
@@ -263,8 +266,8 @@ static BcDig
bc_num_addDigits(BcDig a, BcDig b, bool* carry)
{
assert(((BcBigDig) BC_BASE_POW) * 2 == ((BcDig) BC_BASE_POW) * 2);
- assert(a < BC_BASE_POW);
- assert(b < BC_BASE_POW);
+ assert(a < BC_BASE_POW && a >= 0);
+ assert(b < BC_BASE_POW && b >= 0);
a += b + *carry;
*carry = (a >= BC_BASE_POW);
@@ -287,8 +290,8 @@ bc_num_addDigits(BcDig a, BcDig b, bool* carry)
static BcDig
bc_num_subDigits(BcDig a, BcDig b, bool* carry)
{
- assert(a < BC_BASE_POW);
- assert(b < BC_BASE_POW);
+ assert(a < BC_BASE_POW && a >= 0);
+ assert(b < BC_BASE_POW && b >= 0);
b += *carry;
*carry = (a < b);
@@ -382,6 +385,7 @@ bc_num_mulArray(const BcNum* restrict a, BcBigDig b, BcNum* restrict c)
// Finishing touches.
c->num[i] = (BcDig) carry;
+ assert(c->num[i] >= 0 && c->num[i] < BC_BASE_POW);
c->len = a->len;
c->len += (carry != 0);
@@ -416,6 +420,7 @@ bc_num_divArray(const BcNum* restrict a, BcBigDig b, BcNum* restrict c,
BcBigDig in = ((BcBigDig) a->num[i]) + carry * BC_BASE_POW;
assert(in / b < BC_BASE_POW);
c->num[i] = (BcDig) (in / b);
+ assert(c->num[i] >= 0 && c->num[i] < BC_BASE_POW);
carry = in % b;
}
@@ -685,7 +690,8 @@ bc_num_shiftRdx(const BcNum* restrict n, BcNum* restrict r)
static size_t
bc_num_shiftZero(BcNum* restrict n)
{
- size_t i;
+ // This is volatile to quiet a GCC warning about longjmp() clobbering.
+ volatile size_t i;
// If we don't have an integer, that is a problem, but it's also a bug
// because the caller should have set everything up right.
@@ -745,6 +751,7 @@ bc_num_shift(BcNum* restrict n, BcBigDig dig)
temp = carry * dig;
carry = in % pow;
ptr[i] = ((BcDig) (in / pow)) + (BcDig) temp;
+ assert(ptr[i] >= 0 && ptr[i] < BC_BASE_POW);
}
assert(!carry);
@@ -918,19 +925,6 @@ bc_num_shiftRight(BcNum* restrict n, size_t places)
}
/**
- * Invert @a into @a b at the current scale.
- * @param a The number to invert.
- * @param b The return parameter. This must be preallocated.
- * @param scale The current scale.
- */
-static inline void
-bc_num_inv(BcNum* a, BcNum* b, size_t scale)
-{
- assert(BC_NUM_NONZERO(a));
- bc_num_div(&vm.one, a, b, scale);
-}
-
-/**
* Tests if a number is a integer with scale or not. Returns true if the number
* is not an integer. If it is, its integer shifted form is copied into the
* result parameter for use where only integers are allowed.
@@ -981,6 +975,12 @@ bc_num_intop(const BcNum* a, const BcNum* b, BcNum* restrict c)
{
BcNum temp;
+#if BC_GCC
+ temp.len = 0;
+ temp.rdx = 0;
+ temp.num = NULL;
+#endif // BC_GCC
+
if (BC_ERR(bc_num_nonInt(b, &temp))) bc_err(BC_ERR_MATH_NON_INTEGER);
bc_num_copy(c, a);
@@ -1289,6 +1289,9 @@ bc_num_k(const BcNum* a, const BcNum* b, BcNum* restrict c)
BcDig* dig_ptr;
BcNumShiftAddOp op;
bool aone = BC_NUM_ONE(a);
+#if BC_ENABLE_LIBRARY
+ BcVm* vm = bcl_getspecific();
+#endif // BC_ENABLE_LIBRARY
assert(BC_NUM_ZERO(c));
@@ -1345,7 +1348,7 @@ bc_num_k(const BcNum* a, const BcNum* b, BcNum* restrict c)
max = bc_vm_growSize(max, max) + 1;
bc_num_init(&temp, max);
- BC_SETJMP_LOCKED(err);
+ BC_SETJMP_LOCKED(vm, err);
BC_SIG_UNLOCK;
@@ -1413,7 +1416,7 @@ err:
bc_num_free(&z2);
bc_num_free(&z1);
bc_num_free(&z0);
- BC_LONGJMP_CONT;
+ BC_LONGJMP_CONT(vm);
}
/**
@@ -1429,7 +1432,17 @@ static void
bc_num_m(BcNum* a, BcNum* b, BcNum* restrict c, size_t scale)
{
BcNum cpa, cpb;
- size_t ascale, bscale, ardx, brdx, azero = 0, bzero = 0, zero, len, rscale;
+ size_t ascale, bscale, ardx, brdx, zero, len, rscale;
+ // These are meant to quiet warnings on GCC about longjmp() clobbering.
+ // The problem is real here.
+ size_t scale1, scale2, realscale;
+ // These are meant to quiet the GCC longjmp() clobbering, even though it
+ // does not apply here.
+ volatile size_t azero;
+ volatile size_t bzero;
+#if BC_ENABLE_LIBRARY
+ BcVm* vm = bcl_getspecific();
+#endif // BC_ENABLE_LIBRARY
assert(BC_NUM_RDX_VALID(a));
assert(BC_NUM_RDX_VALID(b));
@@ -1440,10 +1453,10 @@ bc_num_m(BcNum* a, BcNum* b, BcNum* restrict c, size_t scale)
bscale = b->scale;
// This sets the final scale according to the bc spec.
- scale = BC_MAX(scale, ascale);
- scale = BC_MAX(scale, bscale);
+ scale1 = BC_MAX(scale, ascale);
+ scale2 = BC_MAX(scale1, bscale);
rscale = ascale + bscale;
- scale = BC_MIN(rscale, scale);
+ realscale = BC_MIN(rscale, scale2);
// If this condition is true, we can use bc_num_mulArray(), which would be
// much faster.
@@ -1485,7 +1498,7 @@ bc_num_m(BcNum* a, BcNum* b, BcNum* restrict c, size_t scale)
bc_num_init(&cpa, a->len + BC_NUM_RDX_VAL(a));
bc_num_init(&cpb, b->len + BC_NUM_RDX_VAL(b));
- BC_SETJMP_LOCKED(err);
+ BC_SETJMP_LOCKED(vm, init_err);
BC_SIG_UNLOCK;
@@ -1513,13 +1526,13 @@ bc_num_m(BcNum* a, BcNum* b, BcNum* restrict c, size_t scale)
// jump.
BC_SIG_LOCK;
- BC_UNSETJMP;
+ BC_UNSETJMP(vm);
// We want to ignore zero limbs.
azero = bc_num_shiftZero(&cpa);
bzero = bc_num_shiftZero(&cpb);
- BC_SETJMP_LOCKED(err);
+ BC_SETJMP_LOCKED(vm, err);
BC_SIG_UNLOCK;
@@ -1540,15 +1553,17 @@ bc_num_m(BcNum* a, BcNum* b, BcNum* restrict c, size_t scale)
bc_num_shiftLeft(c, (len - c->len) * BC_BASE_DIGS);
bc_num_shiftRight(c, ardx + brdx);
- bc_num_retireMul(c, scale, BC_NUM_NEG(a), BC_NUM_NEG(b));
+ bc_num_retireMul(c, realscale, BC_NUM_NEG(a), BC_NUM_NEG(b));
err:
BC_SIG_MAYLOCK;
bc_num_unshiftZero(&cpb, bzero);
- bc_num_free(&cpb);
bc_num_unshiftZero(&cpa, azero);
+init_err:
+ BC_SIG_MAYLOCK;
+ bc_num_free(&cpb);
bc_num_free(&cpa);
- BC_LONGJMP_CONT;
+ BC_LONGJMP_CONT(vm);
}
/**
@@ -1562,14 +1577,12 @@ bc_num_nonZeroDig(BcDig* restrict a, size_t len)
{
size_t i;
- bool nonzero = false;
-
- for (i = len - 1; !nonzero && i < len; --i)
+ for (i = len - 1; i < len; --i)
{
- nonzero = (a[i] != 0);
+ if (a[i] != 0) return true;
}
- return nonzero;
+ return false;
}
/**
@@ -1631,9 +1644,23 @@ bc_num_d_long(BcNum* restrict a, BcNum* restrict b, BcNum* restrict c,
size_t scale)
{
BcBigDig divisor;
- size_t len, end, i, rdx;
+ size_t i, rdx;
+ // This is volatile and len 2 and reallen exist to quiet the GCC warning
+ // about clobbering on longjmp(). This one is possible, I think.
+ volatile size_t len;
+ size_t len2, reallen;
+ // This is volatile and realend exists to quiet the GCC warning about
+ // clobbering on longjmp(). This one is possible, I think.
+ volatile size_t end;
+ size_t realend;
BcNum cpb;
- bool nonzero = false;
+ // This is volatile and realnonzero exists to quiet the GCC warning about
+ // clobbering on longjmp(). This one is possible, I think.
+ volatile bool nonzero;
+ bool realnonzero;
+#if BC_ENABLE_LIBRARY
+ BcVm* vm = bcl_getspecific();
+#endif // BC_ENABLE_LIBRARY
assert(b->len < a->len);
@@ -1678,25 +1705,35 @@ bc_num_d_long(BcNum* restrict a, BcNum* restrict b, BcNum* restrict c,
// Check bc_num_d(). In there, we grow a again and again. We do it
// again here; we *always* want to be sure it is big enough.
- len = BC_MAX(a->len, b->len);
- bc_num_expand(a, len + 1);
+ len2 = BC_MAX(a->len, b->len);
+ bc_num_expand(a, len2 + 1);
// Make a have a zero most significant limb to match the len.
- if (len + 1 > a->len) a->len = len + 1;
+ if (len2 + 1 > a->len) a->len = len2 + 1;
// Grab the new divisor estimate, new because the shift has made it
// different.
- len = b->len;
- end = a->len - len;
- divisor = (BcBigDig) b->num[len - 1];
+ reallen = b->len;
+ realend = a->len - reallen;
+ divisor = (BcBigDig) b->num[reallen - 1];
- nonzero = bc_num_nonZeroDig(b->num, len - 1);
+ realnonzero = bc_num_nonZeroDig(b->num, reallen - 1);
+ }
+ else
+ {
+ realend = end;
+ realnonzero = nonzero;
}
}
+ else
+ {
+ realend = end;
+ realnonzero = false;
+ }
// If b has other nonzero limbs, we want the divisor to be one higher, so
// that it is an upper bound.
- divisor += nonzero;
+ divisor += realnonzero;
// Make sure c can fit the new length.
bc_num_expand(c, a->len);
@@ -1710,12 +1747,12 @@ bc_num_d_long(BcNum* restrict a, BcNum* restrict b, BcNum* restrict c,
bc_num_init(&cpb, len + 1);
- BC_SETJMP_LOCKED(err);
+ BC_SETJMP_LOCKED(vm, err);
BC_SIG_UNLOCK;
// This is the actual division loop.
- for (i = end - 1; i < end && i >= rdx && BC_NUM_NONZERO(a); --i)
+ for (i = realend - 1; i < realend && i >= rdx && BC_NUM_NONZERO(a); --i)
{
ssize_t cmp;
BcDig* n;
@@ -1765,7 +1802,7 @@ bc_num_d_long(BcNum* restrict a, BcNum* restrict b, BcNum* restrict c,
// And here's why it might take multiple trips: n might *still* be
// greater than b. So we have to loop again. That's what this is
// setting up for: the condition of the while loop.
- if (nonzero) cmp = bc_num_divCmp(n, b, len);
+ if (realnonzero) cmp = bc_num_divCmp(n, b, len);
else cmp = -1;
}
@@ -1778,7 +1815,7 @@ bc_num_d_long(BcNum* restrict a, BcNum* restrict b, BcNum* restrict c,
err:
BC_SIG_MAYLOCK;
bc_num_free(&cpb);
- BC_LONGJMP_CONT;
+ BC_LONGJMP_CONT(vm);
}
/**
@@ -1793,6 +1830,9 @@ bc_num_d(BcNum* a, BcNum* b, BcNum* restrict c, size_t scale)
{
size_t len, cpardx;
BcNum cpa, cpb;
+#if BC_ENABLE_LIBRARY
+ BcVm* vm = bcl_getspecific();
+#endif // BC_ENABLE_LIBRARY
if (BC_NUM_ZERO(b)) bc_err(BC_ERR_MATH_DIVIDE_BY_ZERO);
@@ -1829,7 +1869,7 @@ bc_num_d(BcNum* a, BcNum* b, BcNum* restrict c, size_t scale)
bc_num_copy(&cpa, a);
bc_num_createCopy(&cpb, b);
- BC_SETJMP_LOCKED(err);
+ BC_SETJMP_LOCKED(vm, err);
BC_SIG_UNLOCK;
@@ -1884,7 +1924,7 @@ err:
BC_SIG_MAYLOCK;
bc_num_free(&cpb);
bc_num_free(&cpa);
- BC_LONGJMP_CONT;
+ BC_LONGJMP_CONT(vm);
}
/**
@@ -1904,7 +1944,13 @@ bc_num_r(BcNum* a, BcNum* b, BcNum* restrict c, BcNum* restrict d, size_t scale,
size_t ts)
{
BcNum temp;
+ // realscale is meant to quiet a warning on GCC about longjmp() clobbering.
+ // This one is real.
+ size_t realscale;
bool neg;
+#if BC_ENABLE_LIBRARY
+ BcVm* vm = bcl_getspecific();
+#endif // BC_ENABLE_LIBRARY
if (BC_NUM_ZERO(b)) bc_err(BC_ERR_MATH_DIVIDE_BY_ZERO);
@@ -1919,7 +1965,7 @@ bc_num_r(BcNum* a, BcNum* b, BcNum* restrict c, BcNum* restrict d, size_t scale,
bc_num_init(&temp, d->cap);
- BC_SETJMP_LOCKED(err);
+ BC_SETJMP_LOCKED(vm, err);
BC_SIG_UNLOCK;
@@ -1927,14 +1973,15 @@ bc_num_r(BcNum* a, BcNum* b, BcNum* restrict c, BcNum* restrict d, size_t scale,
bc_num_d(a, b, c, scale);
// We want an extra digit so we can safely truncate.
- if (scale) scale = ts + 1;
+ if (scale) realscale = ts + 1;
+ else realscale = scale;
assert(BC_NUM_RDX_VALID(c));
assert(BC_NUM_RDX_VALID(b));
// Implement the rest of the (a - (a / b) * b) formula.
- bc_num_m(c, b, &temp, scale);
- bc_num_sub(a, &temp, d, scale);
+ bc_num_m(c, b, &temp, realscale);
+ bc_num_sub(a, &temp, d, realscale);
// Extend if necessary.
if (ts > d->scale && BC_NUM_NONZERO(d)) bc_num_extend(d, ts - d->scale);
@@ -1946,7 +1993,7 @@ bc_num_r(BcNum* a, BcNum* b, BcNum* restrict c, BcNum* restrict d, size_t scale,
err:
BC_SIG_MAYLOCK;
bc_num_free(&temp);
- BC_LONGJMP_CONT;
+ BC_LONGJMP_CONT(vm);
}
/**
@@ -1962,6 +2009,9 @@ bc_num_rem(BcNum* a, BcNum* b, BcNum* restrict c, size_t scale)
{
BcNum c1;
size_t ts;
+#if BC_ENABLE_LIBRARY
+ BcVm* vm = bcl_getspecific();
+#endif // BC_ENABLE_LIBRARY
ts = bc_vm_growSize(scale, b->scale);
ts = BC_MAX(ts, a->scale);
@@ -1971,7 +2021,7 @@ bc_num_rem(BcNum* a, BcNum* b, BcNum* restrict c, size_t scale)
// Need a temp for the quotient.
bc_num_init(&c1, bc_num_mulReq(a, b, ts));
- BC_SETJMP_LOCKED(err);
+ BC_SETJMP_LOCKED(vm, err);
BC_SIG_UNLOCK;
@@ -1980,7 +2030,7 @@ bc_num_rem(BcNum* a, BcNum* b, BcNum* restrict c, size_t scale)
err:
BC_SIG_MAYLOCK;
bc_num_free(&c1);
- BC_LONGJMP_CONT;
+ BC_LONGJMP_CONT(vm);
}
/**
@@ -1995,11 +2045,25 @@ bc_num_p(BcNum* a, BcNum* b, BcNum* restrict c, size_t scale)
{
BcNum copy, btemp;
BcBigDig exp;
- size_t powrdx, resrdx;
+ // realscale is meant to quiet a warning on GCC about longjmp() clobbering.
+ // This one is real.
+ size_t powrdx, resrdx, realscale;
bool neg;
+#if BC_ENABLE_LIBRARY
+ BcVm* vm = bcl_getspecific();
+#endif // BC_ENABLE_LIBRARY
+
+ // This is here to silence a warning from GCC.
+#if BC_GCC
+ btemp.len = 0;
+ btemp.rdx = 0;
+ btemp.num = NULL;
+#endif // BC_GCC
if (BC_ERR(bc_num_nonInt(b, &btemp))) bc_err(BC_ERR_MATH_NON_INTEGER);
+ assert(btemp.len == 0 || btemp.num != NULL);
+
if (BC_NUM_ZERO(&btemp))
{
bc_num_one(c);
@@ -2029,7 +2093,7 @@ bc_num_p(BcNum* a, BcNum* b, BcNum* restrict c, size_t scale)
bc_num_createCopy(&copy, a);
- BC_SETJMP_LOCKED(err);
+ BC_SETJMP_LOCKED(vm, err);
BC_SIG_UNLOCK;
@@ -2039,8 +2103,9 @@ bc_num_p(BcNum* a, BcNum* b, BcNum* restrict c, size_t scale)
{
size_t max = BC_MAX(scale, a->scale), scalepow;
scalepow = bc_num_mulOverflow(a->scale, exp);
- scale = BC_MIN(scalepow, max);
+ realscale = BC_MIN(scalepow, max);
}
+ else realscale = scale;
// This is only implementing the first exponentiation by squaring, until it
// reaches the first time where the square is actually used.
@@ -2076,17 +2141,17 @@ bc_num_p(BcNum* a, BcNum* b, BcNum* restrict c, size_t scale)
}
// Invert if necessary.
- if (neg) bc_num_inv(c, c, scale);
+ if (neg) bc_num_inv(c, c, realscale);
// Truncate if necessary.
- if (c->scale > scale) bc_num_truncate(c, c->scale - scale);
+ if (c->scale > realscale) bc_num_truncate(c, c->scale - realscale);
bc_num_clean(c);
err:
BC_SIG_MAYLOCK;
bc_num_free(&copy);
- BC_LONGJMP_CONT;
+ BC_LONGJMP_CONT(vm);
}
#if BC_ENABLE_EXTRA_MATH
@@ -2169,7 +2234,9 @@ bc_num_binary(BcNum* a, BcNum* b, BcNum* c, size_t scale, BcNumBinOp op,
BcNum* ptr_a;
BcNum* ptr_b;
BcNum num2;
- bool init = false;
+#if BC_ENABLE_LIBRARY
+ BcVm* vm = NULL;
+#endif // BC_ENABLE_LIBRARY
assert(a != NULL && b != NULL && c != NULL && op != NULL);
@@ -2178,46 +2245,25 @@ bc_num_binary(BcNum* a, BcNum* b, BcNum* c, size_t scale, BcNumBinOp op,
BC_SIG_LOCK;
- // Reallocate if c == a.
- if (c == a)
- {
- ptr_a = &num2;
-
- // NOLINTNEXTLINE
- memcpy(ptr_a, c, sizeof(BcNum));
- init = true;
- }
- else
- {
- ptr_a = a;
- }
-
- // Also reallocate if c == b.
- if (c == b)
- {
- ptr_b = &num2;
-
- if (c != a)
- {
- // NOLINTNEXTLINE
- memcpy(ptr_b, c, sizeof(BcNum));
- init = true;
- }
- }
- else
- {
- ptr_b = b;
- }
+ ptr_a = c == a ? &num2 : a;
+ ptr_b = c == b ? &num2 : b;
// Actually reallocate. If we don't reallocate, we want to expand at the
// very least.
- if (init)
+ if (c == a || c == b)
{
+#if BC_ENABLE_LIBRARY
+ vm = bcl_getspecific();
+#endif // BC_ENABLE_LIBRARY
+
+ // NOLINTNEXTLINE
+ memcpy(&num2, c, sizeof(BcNum));
+
bc_num_init(c, req);
// Must prepare for cleanup. We want this here so that locals that got
// set stay set since a longjmp() is not guaranteed to preserve locals.
- BC_SETJMP_LOCKED(err);
+ BC_SETJMP_LOCKED(vm, err);
BC_SIG_UNLOCK;
}
else
@@ -2240,11 +2286,11 @@ bc_num_binary(BcNum* a, BcNum* b, BcNum* c, size_t scale, BcNumBinOp op,
err:
// Cleanup only needed if we initialized c to a new number.
- if (init)
+ if (c == a || c == b)
{
BC_SIG_MAYLOCK;
bc_num_free(&num2);
- BC_LONGJMP_CONT;
+ BC_LONGJMP_CONT(vm);
}
}
@@ -2307,11 +2353,18 @@ bc_num_parseChar(char c, size_t base)
// If a letter...
if (isupper(c))
{
+#if BC_ENABLE_LIBRARY
+ BcVm* vm = bcl_getspecific();
+#endif // BC_ENABLE_LIBRARY
+
// This returns the digit that directly corresponds with the letter.
c = BC_NUM_NUM_LETTER(c);
// If the digit is greater than the base, we clamp.
- c = ((size_t) c) >= base ? (char) base - 1 : c;
+ if (BC_DIGIT_CLAMP)
+ {
+ c = ((size_t) c) >= base ? (char) base - 1 : c;
+ }
}
// Straight convert the digit to a number.
else c -= '0';
@@ -2331,6 +2384,9 @@ bc_num_parseDecimal(BcNum* restrict n, const char* restrict val)
size_t len, i, temp, mod;
const char* ptr;
bool zero = true, rdx;
+#if BC_ENABLE_LIBRARY
+ BcVm* vm = bcl_getspecific();
+#endif // BC_ENABLE_LIBRARY
// Eat leading zeroes.
for (i = 0; val[i] == '0'; ++i)
@@ -2378,10 +2434,11 @@ bc_num_parseDecimal(BcNum* restrict n, const char* restrict val)
i = mod ? BC_BASE_DIGS - mod : 0;
n->len = ((temp + i) / BC_BASE_DIGS);
- // Expand and zero.
- bc_num_expand(n, n->len);
+ // Expand and zero. The plus extra is in case the lack of clamping causes
+ // the number to overflow the original bounds.
+ bc_num_expand(n, n->len + !BC_DIGIT_CLAMP);
// NOLINTNEXTLINE
- memset(n->num, 0, BC_NUM_SIZE(n->len));
+ memset(n->num, 0, BC_NUM_SIZE(n->len + !BC_DIGIT_CLAMP));
if (zero)
{
@@ -2412,12 +2469,35 @@ bc_num_parseDecimal(BcNum* restrict n, const char* restrict val)
{
// The index of the limb.
size_t idx = exp / BC_BASE_DIGS;
+ BcBigDig dig;
- // Clamp for the base.
- if (isupper(c)) c = '9';
+ if (isupper(c))
+ {
+ // Clamp for the base.
+ if (!BC_DIGIT_CLAMP) c = BC_NUM_NUM_LETTER(c);
+ else c = 9;
+ }
+ else c -= '0';
- // Add the digit to the limb.
- n->num[idx] += (((BcBigDig) c) - '0') * pow;
+ // Add the digit to the limb. This takes care of overflow from
+ // lack of clamping.
+ dig = ((BcBigDig) n->num[idx]) + ((BcBigDig) c) * pow;
+ if (dig >= BC_BASE_POW)
+ {
+ // We cannot go over BC_BASE_POW with clamping.
+ assert(!BC_DIGIT_CLAMP);
+
+ n->num[idx + 1] = (BcDig) (dig / BC_BASE_POW);
+ n->num[idx] = (BcDig) (dig % BC_BASE_POW);
+ assert(n->num[idx] >= 0 && n->num[idx] < BC_BASE_POW);
+ assert(n->num[idx + 1] >= 0 &&
+ n->num[idx + 1] < BC_BASE_POW);
+ }
+ else
+ {
+ n->num[idx] = (BcDig) dig;
+ assert(n->num[idx] >= 0 && n->num[idx] < BC_BASE_POW);
+ }
// Adjust the power and exponent.
if ((exp + 1) % BC_BASE_DIGS == 0) pow = 1;
@@ -2425,6 +2505,9 @@ bc_num_parseDecimal(BcNum* restrict n, const char* restrict val)
}
}
}
+
+ // Make sure to add one to the length if needed from lack of clamping.
+ n->len += (!BC_DIGIT_CLAMP && n->num[n->len] != 0);
}
/**
@@ -2443,7 +2526,12 @@ bc_num_parseBase(BcNum* restrict n, const char* restrict val, BcBigDig base)
char c = 0;
bool zero = true;
BcBigDig v;
- size_t i, digs, len = strlen(val);
+ size_t digs, len = strlen(val);
+ // This is volatile to quiet a warning on GCC about longjmp() clobbering.
+ volatile size_t i;
+#if BC_ENABLE_LIBRARY
+ BcVm* vm = bcl_getspecific();
+#endif // BC_ENABLE_LIBRARY
// If zero, just return because the number should be virgin (already 0).
for (i = 0; zero && i < len; ++i)
@@ -2457,7 +2545,7 @@ bc_num_parseBase(BcNum* restrict n, const char* restrict val, BcBigDig base)
bc_num_init(&temp, BC_NUM_BIGDIG_LOG10);
bc_num_init(&mult1, BC_NUM_BIGDIG_LOG10);
- BC_SETJMP_LOCKED(int_err);
+ BC_SETJMP_LOCKED(vm, int_err);
BC_SIG_UNLOCK;
@@ -2489,14 +2577,14 @@ bc_num_parseBase(BcNum* restrict n, const char* restrict val, BcBigDig base)
BC_SIG_LOCK;
// Unset the jump to reset in for these new initializations.
- BC_UNSETJMP;
+ BC_UNSETJMP(vm);
bc_num_init(&mult2, BC_NUM_BIGDIG_LOG10);
bc_num_init(&result1, BC_NUM_DEF_SIZE);
bc_num_init(&result2, BC_NUM_DEF_SIZE);
bc_num_one(&mult1);
- BC_SETJMP_LOCKED(err);
+ BC_SETJMP_LOCKED(vm, err);
BC_SIG_UNLOCK;
@@ -2564,7 +2652,7 @@ int_err:
BC_SIG_MAYLOCK;
bc_num_free(&mult1);
bc_num_free(&temp);
- BC_LONGJMP_CONT;
+ BC_LONGJMP_CONT(vm);
}
/**
@@ -2575,7 +2663,7 @@ static inline void
bc_num_printNewline(void)
{
#if !BC_ENABLE_LIBRARY
- if (vm.nchars >= vm.line_len - 1 && vm.line_len)
+ if (vm->nchars >= vm->line_len - 1 && vm->line_len)
{
bc_vm_putchar('\\', bc_flush_none);
bc_vm_putchar('\n', bc_flush_err);
@@ -2756,12 +2844,15 @@ bc_num_printExponent(const BcNum* restrict n, bool eng, bool newline)
bool neg = (n->len <= nrdx);
BcNum temp, exp;
BcDig digs[BC_NUM_BIGDIG_LOG10];
+#if BC_ENABLE_LIBRARY
+ BcVm* vm = bcl_getspecific();
+#endif // BC_ENABLE_LIBRARY
BC_SIG_LOCK;
bc_num_createCopy(&temp, n);
- BC_SETJMP_LOCKED(exit);
+ BC_SETJMP_LOCKED(vm, exit);
BC_SIG_UNLOCK;
@@ -2833,7 +2924,7 @@ bc_num_printExponent(const BcNum* restrict n, bool eng, bool newline)
exit:
BC_SIG_MAYLOCK;
bc_num_free(&temp);
- BC_LONGJMP_CONT;
+ BC_LONGJMP_CONT(vm);
}
#endif // BC_ENABLE_EXTRA_MATH
@@ -2970,6 +3061,9 @@ bc_num_printNum(BcNum* restrict n, BcBigDig base, size_t len,
size_t i, j, nrdx, idigits;
bool radix;
BcDig digit_digs[BC_NUM_BIGDIG_LOG10 + 1];
+#if BC_ENABLE_LIBRARY
+ BcVm* vm = bcl_getspecific();
+#endif // BC_ENABLE_LIBRARY
assert(base > 1);
@@ -3029,7 +3123,7 @@ bc_num_printNum(BcNum* restrict n, BcBigDig base, size_t len,
// intp will be the "integer part" of the number, so copy it.
bc_num_createCopy(&intp, n);
- BC_SETJMP_LOCKED(err);
+ BC_SETJMP_LOCKED(vm, err);
BC_SIG_UNLOCK;
@@ -3044,30 +3138,33 @@ bc_num_printNum(BcNum* restrict n, BcBigDig base, size_t len,
// exponent and power. That is to prevent us from calculating them every
// time because printing will probably happen multiple times on the same
// base.
- if (base != vm.last_base)
+ if (base != vm->last_base)
{
- vm.last_pow = 1;
- vm.last_exp = 0;
+ vm->last_pow = 1;
+ vm->last_exp = 0;
// Calculate the exponent and power.
- while (vm.last_pow * base <= BC_BASE_POW)
+ while (vm->last_pow * base <= BC_BASE_POW)
{
- vm.last_pow *= base;
- vm.last_exp += 1;
+ vm->last_pow *= base;
+ vm->last_exp += 1;
}
// Also, the remainder and base itself.
- vm.last_rem = BC_BASE_POW - vm.last_pow;
- vm.last_base = base;
+ vm->last_rem = BC_BASE_POW - vm->last_pow;
+ vm->last_base = base;
}
- exp = vm.last_exp;
+ exp = vm->last_exp;
- // If vm.last_rem is 0, then the base we are printing in is a divisor of
+ // If vm->last_rem is 0, then the base we are printing in is a divisor of
// BC_BASE_POW, which is the easy case because it means that BC_BASE_POW is
// a power of obase, and no conversion is needed. If it *is* 0, then we have
// the hard case, and we have to prepare the number for the base.
- if (vm.last_rem != 0) bc_num_printPrepare(&intp, vm.last_rem, vm.last_pow);
+ if (vm->last_rem != 0)
+ {
+ bc_num_printPrepare(&intp, vm->last_rem, vm->last_pow);
+ }
// After the conversion comes the surprisingly easy part. From here on out,
// this is basically naive code that I wrote, adjusted for the larger bases.
@@ -3124,14 +3221,14 @@ bc_num_printNum(BcNum* restrict n, BcBigDig base, size_t len,
BC_SIG_LOCK;
// Reset the jump because some locals are changing.
- BC_UNSETJMP;
+ BC_UNSETJMP(vm);
bc_num_init(&fracp2, nrdx);
bc_num_setup(&digit, digit_digs, sizeof(digit_digs) / sizeof(BcDig));
bc_num_init(&flen1, BC_NUM_BIGDIG_LOG10);
bc_num_init(&flen2, BC_NUM_BIGDIG_LOG10);
- BC_SETJMP_LOCKED(frac_err);
+ BC_SETJMP_LOCKED(vm, frac_err);
BC_SIG_UNLOCK;
@@ -3193,7 +3290,7 @@ err:
bc_num_free(&fracp1);
bc_num_free(&intp);
bc_vec_free(&stack);
- BC_LONGJMP_CONT;
+ BC_LONGJMP_CONT(vm);
}
/**
@@ -3268,9 +3365,11 @@ bc_num_init(BcNum* restrict n, size_t req)
req = req >= BC_NUM_DEF_SIZE ? req : BC_NUM_DEF_SIZE;
// If we can't use a temp, allocate.
- if (req != BC_NUM_DEF_SIZE || (num = bc_vm_takeTemp()) == NULL)
+ if (req != BC_NUM_DEF_SIZE) num = bc_vm_malloc(BC_NUM_SIZE(req));
+ else
{
- num = bc_vm_malloc(BC_NUM_SIZE(req));
+ num = bc_vm_getTemp() == NULL ? bc_vm_malloc(BC_NUM_SIZE(req)) :
+ bc_vm_takeTemp();
}
bc_num_setup(n, num, req);
@@ -3375,8 +3474,14 @@ bc_num_len(const BcNum* restrict n)
void
bc_num_parse(BcNum* restrict n, const char* restrict val, BcBigDig base)
{
+#ifndef NDEBUG
+#if BC_ENABLE_LIBRARY
+ BcVm* vm = bcl_getspecific();
+#endif // BC_ENABLE_LIBRARY
+#endif // NDEBUG
+
assert(n != NULL && val != NULL && base);
- assert(base >= BC_NUM_MIN_BASE && base <= vm.maxes[BC_PROG_GLOBALS_IBASE]);
+ assert(base >= BC_NUM_MIN_BASE && base <= vm->maxes[BC_PROG_GLOBALS_IBASE]);
assert(bc_num_strValid(val));
// A one character number is *always* parsed as though the base was the
@@ -3403,6 +3508,10 @@ bc_num_print(BcNum* restrict n, BcBigDig base, bool newline)
if (BC_NUM_NONZERO(n))
{
+#if BC_ENABLE_LIBRARY
+ BcVm* vm = bcl_getspecific();
+#endif // BC_ENABLE_LIBRARY
+
// Print the sign.
if (BC_NUM_NEG(n)) bc_num_putchar('-', true);
@@ -3430,9 +3539,15 @@ bc_num_print(BcNum* restrict n, BcBigDig base, bool newline)
BcBigDig
bc_num_bigdig2(const BcNum* restrict n)
{
+#ifndef NDEBUG
+#if BC_ENABLE_LIBRARY
+ BcVm* vm = bcl_getspecific();
+#endif // BC_ENABLE_LIBRARY
+#endif // NDEBUG
+
// This function returns no errors because it's guaranteed to succeed if
// its preconditions are met. Those preconditions include both n needs to
- // be non-NULL, n being non-negative, and n being less than vm.max. If all
+ // be non-NULL, n being non-negative, and n being less than vm->max. If all
// of that is true, then we can just convert without worrying about negative
// errors or overflow.
@@ -3441,7 +3556,7 @@ bc_num_bigdig2(const BcNum* restrict n)
assert(n != NULL);
assert(!BC_NUM_NEG(n));
- assert(bc_num_cmp(n, &vm.max) < 0);
+ assert(bc_num_cmp(n, &vm->max) < 0);
assert(n->len - nrdx <= 3);
// There is a small speed win from unrolling the loop here, and since it
@@ -3476,6 +3591,10 @@ bc_num_bigdig2(const BcNum* restrict n)
BcBigDig
bc_num_bigdig(const BcNum* restrict n)
{
+#if BC_ENABLE_LIBRARY
+ BcVm* vm = bcl_getspecific();
+#endif // BC_ENABLE_LIBRARY
+
assert(n != NULL);
// This error checking is extremely important, and if you do not have a
@@ -3484,7 +3603,7 @@ bc_num_bigdig(const BcNum* restrict n)
// includes all instances of numbers inputted by the user or calculated by
// the user. Otherwise, you can call the faster bc_num_bigdig2().
if (BC_ERR(BC_NUM_NEG(n))) bc_err(BC_ERR_MATH_NEGATIVE);
- if (BC_ERR(bc_num_cmp(n, &vm.max) >= 0)) bc_err(BC_ERR_MATH_OVERFLOW);
+ if (BC_ERR(bc_num_cmp(n, &vm->max) >= 0)) bc_err(BC_ERR_MATH_OVERFLOW);
return bc_num_bigdig2(n);
}
@@ -3524,6 +3643,9 @@ bc_num_rng(const BcNum* restrict n, BcRNG* rng)
BcNum temp, temp2, intn, frac;
BcRand state1, state2, inc1, inc2;
size_t nrdx = BC_NUM_RDX_VAL(n);
+#if BC_ENABLE_LIBRARY
+ BcVm* vm = bcl_getspecific();
+#endif // BC_ENABLE_LIBRARY
// This function holds the secret of how I interpret a seed number for the
// PRNG. Well, it's actually in the development manual
@@ -3537,11 +3659,11 @@ bc_num_rng(const BcNum* restrict n, BcRNG* rng)
bc_num_init(&frac, nrdx);
bc_num_init(&intn, bc_num_int(n));
- BC_SETJMP_LOCKED(err);
+ BC_SETJMP_LOCKED(vm, err);
BC_SIG_UNLOCK;
- assert(BC_NUM_RDX_VALID_NP(vm.max));
+ assert(BC_NUM_RDX_VALID_NP(vm->max));
// NOLINTNEXTLINE
memcpy(frac.num, n->num, BC_NUM_SIZE(nrdx));
@@ -3550,11 +3672,11 @@ bc_num_rng(const BcNum* restrict n, BcRNG* rng)
frac.scale = n->scale;
assert(BC_NUM_RDX_VALID_NP(frac));
- assert(BC_NUM_RDX_VALID_NP(vm.max2));
+ assert(BC_NUM_RDX_VALID_NP(vm->max2));
// Multiply the fraction and truncate so that it's an integer. The
// truncation is what clamps it, by the way.
- bc_num_mul(&frac, &vm.max2, &temp, 0);
+ bc_num_mul(&frac, &vm->max2, &temp, 0);
bc_num_truncate(&temp, temp.scale);
bc_num_copy(&frac, &temp);
@@ -3565,17 +3687,17 @@ bc_num_rng(const BcNum* restrict n, BcRNG* rng)
// This assert is here because it has to be true. It is also here to justify
// some optimizations.
- assert(BC_NUM_NONZERO(&vm.max));
+ assert(BC_NUM_NONZERO(&vm->max));
// If there *was* a fractional part...
if (BC_NUM_NONZERO(&frac))
{
// This divmod splits frac into the two state parts.
- bc_num_divmod(&frac, &vm.max, &temp, &temp2, 0);
+ bc_num_divmod(&frac, &vm->max, &temp, &temp2, 0);
- // frac is guaranteed to be smaller than vm.max * vm.max (pow).
- // This means that when dividing frac by vm.max, as above, the
- // quotient and remainder are both guaranteed to be less than vm.max,
+ // frac is guaranteed to be smaller than vm->max * vm->max (pow).
+ // This means that when dividing frac by vm->max, as above, the
+ // quotient and remainder are both guaranteed to be less than vm->max,
// which means we can use bc_num_bigdig2() here and not worry about
// overflow.
state1 = (BcRand) bc_num_bigdig2(&temp2);
@@ -3587,20 +3709,20 @@ bc_num_rng(const BcNum* restrict n, BcRNG* rng)
if (BC_NUM_NONZERO(&intn))
{
// This divmod splits intn into the two inc parts.
- bc_num_divmod(&intn, &vm.max, &temp, &temp2, 0);
+ bc_num_divmod(&intn, &vm->max, &temp, &temp2, 0);
- // Because temp2 is the mod of vm.max, from above, it is guaranteed
+ // Because temp2 is the mod of vm->max, from above, it is guaranteed
// to be small enough to use bc_num_bigdig2().
inc1 = (BcRand) bc_num_bigdig2(&temp2);
// Clamp the second inc part.
- if (bc_num_cmp(&temp, &vm.max) >= 0)
+ if (bc_num_cmp(&temp, &vm->max) >= 0)
{
bc_num_copy(&temp2, &temp);
- bc_num_mod(&temp2, &vm.max, &temp, 0);
+ bc_num_mod(&temp2, &vm->max, &temp, 0);
}
- // The if statement above ensures that temp is less than vm.max, which
+ // The if statement above ensures that temp is less than vm->max, which
// means that we can use bc_num_bigdig2() here.
inc2 = (BcRand) bc_num_bigdig2(&temp);
}
@@ -3614,7 +3736,7 @@ err:
bc_num_free(&frac);
bc_num_free(&temp2);
bc_num_free(&temp);
- BC_LONGJMP_CONT;
+ BC_LONGJMP_CONT(vm);
}
void
@@ -3624,12 +3746,15 @@ bc_num_createFromRNG(BcNum* restrict n, BcRNG* rng)
BcNum conv, temp1, temp2, temp3;
BcDig temp1_num[BC_RAND_NUM_SIZE], temp2_num[BC_RAND_NUM_SIZE];
BcDig conv_num[BC_NUM_BIGDIG_LOG10];
+#if BC_ENABLE_LIBRARY
+ BcVm* vm = bcl_getspecific();
+#endif // BC_ENABLE_LIBRARY
BC_SIG_LOCK;
bc_num_init(&temp3, 2 * BC_RAND_NUM_SIZE);
- BC_SETJMP_LOCKED(err);
+ BC_SETJMP_LOCKED(vm, err);
BC_SIG_UNLOCK;
@@ -3638,12 +3763,12 @@ bc_num_createFromRNG(BcNum* restrict n, BcRNG* rng)
bc_num_setup(&conv, conv_num, sizeof(conv_num) / sizeof(BcDig));
// This assert is here because it has to be true. It is also here to justify
- // the assumption that vm.max is not zero.
- assert(BC_NUM_NONZERO(&vm.max));
+ // the assumption that vm->max is not zero.
+ assert(BC_NUM_NONZERO(&vm->max));
// Because this is true, we can just ignore math errors that would happen
// otherwise.
- assert(BC_NUM_NONZERO(&vm.max2));
+ assert(BC_NUM_NONZERO(&vm->max2));
bc_rand_getRands(rng, &s1, &s2, &i1, &i2);
@@ -3653,14 +3778,14 @@ bc_num_createFromRNG(BcNum* restrict n, BcRNG* rng)
assert(BC_NUM_RDX_VALID_NP(conv));
// Multiply by max to make room for the first piece of state.
- bc_num_mul(&conv, &vm.max, &temp1, 0);
+ bc_num_mul(&conv, &vm->max, &temp1, 0);
// Add in the first piece of state.
bc_num_bigdig2num(&conv, (BcBigDig) s1);
bc_num_add(&conv, &temp1, &temp2, 0);
// Divide to make it an entirely fractional part.
- bc_num_div(&temp2, &vm.max2, &temp3, BC_RAND_STATE_BITS);
+ bc_num_div(&temp2, &vm->max2, &temp3, BC_RAND_STATE_BITS);
// Now start on the increment parts. It's the same process without the
// divide, so put the second piece of increment into a number.
@@ -3669,7 +3794,7 @@ bc_num_createFromRNG(BcNum* restrict n, BcRNG* rng)
assert(BC_NUM_RDX_VALID_NP(conv));
// Multiply by max to make room for the first piece of increment.
- bc_num_mul(&conv, &vm.max, &temp1, 0);
+ bc_num_mul(&conv, &vm->max, &temp1, 0);
// Add in the first piece of increment.
bc_num_bigdig2num(&conv, (BcBigDig) i1);
@@ -3683,7 +3808,7 @@ bc_num_createFromRNG(BcNum* restrict n, BcRNG* rng)
err:
BC_SIG_MAYLOCK;
bc_num_free(&temp3);
- BC_LONGJMP_CONT;
+ BC_LONGJMP_CONT(vm);
}
void
@@ -3699,8 +3824,15 @@ bc_num_irand(BcNum* restrict a, BcNum* restrict b, BcRNG* restrict rng)
// If either of these are true, then the numbers are integers.
if (BC_NUM_ZERO(a) || BC_NUM_ONE(a)) return;
+#if BC_GCC
+ // This is here in GCC to quiet the "maybe-uninitialized" warning.
+ atemp.num = NULL;
+ atemp.len = 0;
+#endif // BC_GCC
+
if (BC_ERR(bc_num_nonInt(a, &atemp))) bc_err(BC_ERR_MATH_NON_INTEGER);
+ assert(atemp.num != NULL);
assert(atemp.len);
len = atemp.len - 1;
@@ -3883,8 +4015,13 @@ bc_num_sqrt(BcNum* restrict a, BcNum* restrict b, size_t scale)
BcNum* x0;
BcNum* x1;
BcNum* temp;
- size_t pow, len, rdx, req, resscale;
+ // realscale is meant to quiet a warning on GCC about longjmp() clobbering.
+ // This one is real.
+ size_t pow, len, rdx, req, resscale, realscale;
BcDig half_digs[1];
+#if BC_ENABLE_LIBRARY
+ BcVm* vm = bcl_getspecific();
+#endif // BC_ENABLE_LIBRARY
assert(a != NULL && b != NULL && a != b);
@@ -3892,11 +4029,12 @@ bc_num_sqrt(BcNum* restrict a, BcNum* restrict b, size_t scale)
// We want to calculate to a's scale if it is bigger so that the result will
// truncate properly.
- if (a->scale > scale) scale = a->scale;
+ if (a->scale > scale) realscale = a->scale;
+ else realscale = scale;
// Set parameters for the result.
len = bc_vm_growSize(bc_num_intDigits(a), 1);
- rdx = BC_NUM_RDX(scale);
+ rdx = BC_NUM_RDX(realscale);
// Square root needs half of the length of the parameter.
req = bc_vm_growSize(BC_MAX(rdx, BC_NUM_RDX_VAL(a)), len >> 1);
@@ -3916,7 +4054,7 @@ bc_num_sqrt(BcNum* restrict a, BcNum* restrict b, size_t scale)
// Easy case.
if (BC_NUM_ZERO(a))
{
- bc_num_setToZero(b, scale);
+ bc_num_setToZero(b, realscale);
return;
}
@@ -3924,12 +4062,12 @@ bc_num_sqrt(BcNum* restrict a, BcNum* restrict b, size_t scale)
if (BC_NUM_ONE(a))
{
bc_num_one(b);
- bc_num_extend(b, scale);
+ bc_num_extend(b, realscale);
return;
}
// Set the parameters again.
- rdx = BC_NUM_RDX(scale);
+ rdx = BC_NUM_RDX(realscale);
rdx = BC_MAX(rdx, BC_NUM_RDX_VAL(a));
len = bc_vm_growSize(a->len, rdx);
@@ -3950,7 +4088,7 @@ bc_num_sqrt(BcNum* restrict a, BcNum* restrict b, size_t scale)
bc_num_init(&f, len);
bc_num_init(&fprime, len);
- BC_SETJMP_LOCKED(err);
+ BC_SETJMP_LOCKED(vm, err);
BC_SIG_UNLOCK;
@@ -3980,7 +4118,7 @@ bc_num_sqrt(BcNum* restrict a, BcNum* restrict b, size_t scale)
// I can set the rdx here directly because neg should be false.
x0->scale = x0->rdx = 0;
- resscale = (scale + BC_BASE_DIGS) + 2;
+ resscale = (realscale + BC_BASE_DIGS) + 2;
// This is the calculation loop. This compare goes to 0 eventually as the
// difference between the two numbers gets smaller than resscale.
@@ -4007,7 +4145,7 @@ bc_num_sqrt(BcNum* restrict a, BcNum* restrict b, size_t scale)
// Copy to the result and truncate.
bc_num_copy(b, x0);
- if (b->scale > scale) bc_num_truncate(b, b->scale - scale);
+ if (b->scale > realscale) bc_num_truncate(b, b->scale - realscale);
assert(!BC_NUM_NEG(b) || BC_NUM_NONZERO(b));
assert(BC_NUM_RDX_VALID(b));
@@ -4020,7 +4158,7 @@ err:
bc_num_free(&f);
bc_num_free(&num2);
bc_num_free(&num1);
- BC_LONGJMP_CONT;
+ BC_LONGJMP_CONT(vm);
}
void
@@ -4028,7 +4166,12 @@ bc_num_divmod(BcNum* a, BcNum* b, BcNum* c, BcNum* d, size_t scale)
{
size_t ts, len;
BcNum *ptr_a, num2;
- bool init = false;
+ // This is volatile to quiet a warning on GCC about clobbering with
+ // longjmp().
+ volatile bool init = false;
+#if BC_ENABLE_LIBRARY
+ BcVm* vm = bcl_getspecific();
+#endif // BC_ENABLE_LIBRARY
// The bulk of this function is just doing what bc_num_binary() does for the
// binary operators. However, it assumes that only c and a can be equal.
@@ -4053,7 +4196,7 @@ bc_num_divmod(BcNum* a, BcNum* b, BcNum* c, BcNum* d, size_t scale)
init = true;
- BC_SETJMP_LOCKED(err);
+ BC_SETJMP_LOCKED(vm, err);
BC_SIG_UNLOCK;
}
@@ -4094,7 +4237,7 @@ err:
{
BC_SIG_MAYLOCK;
bc_num_free(&num2);
- BC_LONGJMP_CONT;
+ BC_LONGJMP_CONT(vm);
}
}
@@ -4103,12 +4246,14 @@ bc_num_modexp(BcNum* a, BcNum* b, BcNum* c, BcNum* restrict d)
{
BcNum base, exp, two, temp, atemp, btemp, ctemp;
BcDig two_digs[2];
+#if BC_ENABLE_LIBRARY
+ BcVm* vm = bcl_getspecific();
+#endif // BC_ENABLE_LIBRARY
assert(a != NULL && b != NULL && c != NULL && d != NULL);
assert(a != d && b != d && c != d);
if (BC_ERR(BC_NUM_ZERO(c))) bc_err(BC_ERR_MATH_DIVIDE_BY_ZERO);
-
if (BC_ERR(BC_NUM_NEG(b))) bc_err(BC_ERR_MATH_NEGATIVE);
#ifndef NDEBUG
@@ -4133,7 +4278,7 @@ bc_num_modexp(BcNum* a, BcNum* b, BcNum* c, BcNum* restrict d)
bc_num_init(&temp, btemp.len + 1);
bc_num_createCopy(&exp, &btemp);
- BC_SETJMP_LOCKED(err);
+ BC_SETJMP_LOCKED(vm, err);
BC_SIG_UNLOCK;
@@ -4175,7 +4320,7 @@ err:
bc_num_free(&exp);
bc_num_free(&temp);
bc_num_free(&base);
- BC_LONGJMP_CONT;
+ BC_LONGJMP_CONT(vm);
assert(!BC_NUM_NEG(d) || d->len);
assert(BC_NUM_RDX_VALID(d));
assert(!d->len || d->num[d->len - 1] || BC_NUM_RDX_VAL(d) == d->len);
@@ -4185,12 +4330,12 @@ err:
void
bc_num_printDebug(const BcNum* n, const char* name, bool emptyline)
{
- bc_file_puts(&vm.fout, bc_flush_none, name);
- bc_file_puts(&vm.fout, bc_flush_none, ": ");
+ bc_file_puts(&vm->fout, bc_flush_none, name);
+ bc_file_puts(&vm->fout, bc_flush_none, ": ");
bc_num_printDecimal(n, true);
- bc_file_putchar(&vm.fout, bc_flush_err, '\n');
- if (emptyline) bc_file_putchar(&vm.fout, bc_flush_err, '\n');
- vm.nchars = 0;
+ bc_file_putchar(&vm->fout, bc_flush_err, '\n');
+ if (emptyline) bc_file_putchar(&vm->fout, bc_flush_err, '\n');
+ vm->nchars = 0;
}
void
@@ -4200,19 +4345,19 @@ bc_num_printDigs(const BcDig* n, size_t len, bool emptyline)
for (i = len - 1; i < len; --i)
{
- bc_file_printf(&vm.fout, " %lu", (unsigned long) n[i]);
+ bc_file_printf(&vm->fout, " %lu", (unsigned long) n[i]);
}
- bc_file_putchar(&vm.fout, bc_flush_err, '\n');
- if (emptyline) bc_file_putchar(&vm.fout, bc_flush_err, '\n');
- vm.nchars = 0;
+ bc_file_putchar(&vm->fout, bc_flush_err, '\n');
+ if (emptyline) bc_file_putchar(&vm->fout, bc_flush_err, '\n');
+ vm->nchars = 0;
}
void
bc_num_printWithDigs(const BcNum* n, const char* name, bool emptyline)
{
- bc_file_puts(&vm.fout, bc_flush_none, name);
- bc_file_printf(&vm.fout, " len: %zu, rdx: %zu, scale: %zu\n", name, n->len,
+ bc_file_puts(&vm->fout, bc_flush_none, name);
+ bc_file_printf(&vm->fout, " len: %zu, rdx: %zu, scale: %zu\n", name, n->len,
BC_NUM_RDX_VAL(n), n->scale);
bc_num_printDigs(n->num, n->len, emptyline);
}
@@ -4222,19 +4367,19 @@ bc_num_dump(const char* varname, const BcNum* n)
{
ulong i, scale = n->scale;
- bc_file_printf(&vm.ferr, "\n%s = %s", varname,
+ bc_file_printf(&vm->ferr, "\n%s = %s", varname,
n->len ? (BC_NUM_NEG(n) ? "-" : "+") : "0 ");
for (i = n->len - 1; i < n->len; --i)
{
if (i + 1 == BC_NUM_RDX_VAL(n))
{
- bc_file_puts(&vm.ferr, bc_flush_none, ". ");
+ bc_file_puts(&vm->ferr, bc_flush_none, ". ");
}
if (scale / BC_BASE_DIGS != BC_NUM_RDX_VAL(n) - i - 1)
{
- bc_file_printf(&vm.ferr, "%lu ", (unsigned long) n->num[i]);
+ bc_file_printf(&vm->ferr, "%lu ", (unsigned long) n->num[i]);
}
else
{
@@ -4245,17 +4390,17 @@ bc_num_dump(const char* varname, const BcNum* n)
if (mod != 0)
{
div = n->num[i] / ((BcDig) bc_num_pow10[(ulong) d]);
- bc_file_printf(&vm.ferr, "%lu", (unsigned long) div);
+ bc_file_printf(&vm->ferr, "%lu", (unsigned long) div);
}
div = n->num[i] % ((BcDig) bc_num_pow10[(ulong) d]);
- bc_file_printf(&vm.ferr, " ' %lu ", (unsigned long) div);
+ bc_file_printf(&vm->ferr, " ' %lu ", (unsigned long) div);
}
}
- bc_file_printf(&vm.ferr, "(%zu | %zu.%zu / %zu) %lu\n", n->scale, n->len,
+ bc_file_printf(&vm->ferr, "(%zu | %zu.%zu / %zu) %lu\n", n->scale, n->len,
BC_NUM_RDX_VAL(n), n->cap, (unsigned long) (void*) n->num);
- bc_file_flush(&vm.ferr, bc_flush_err);
+ bc_file_flush(&vm->ferr, bc_flush_err);
}
#endif // BC_DEBUG_CODE
diff --git a/src/opt.c b/src/opt.c
index 9aaafcbfa780..14ef989f1545 100644
--- a/src/opt.c
+++ b/src/opt.c
@@ -77,7 +77,9 @@ bc_opt_longopt(const BcOptLong* longopts, int c)
BC_UNREACHABLE
+#if !BC_CLANG
return "NULL";
+#endif // !BC_CLANG
}
/**
@@ -197,11 +199,13 @@ bc_opt_parseShort(BcOpt* o, const BcOptLong* longopts)
case BC_OPT_REQUIRED_BC_ONLY:
{
+#if DC_ENABLED
if (BC_IS_DC)
{
bc_opt_error(BC_ERR_FATAL_OPTION, option[0],
bc_opt_longopt(longopts, option[0]), true);
}
+#endif // DC_ENABLED
// Fallthrough
BC_FALLTHROUGH
@@ -375,7 +379,9 @@ bc_opt_parse(BcOpt* o, const BcOptLong* longopts)
BC_UNREACHABLE
+#if !BC_CLANG
return -1;
+#endif // !BC_CLANG
}
void
diff --git a/src/parse.c b/src/parse.c
index 43f4cfdd70f1..0cb379a45130 100644
--- a/src/parse.c
+++ b/src/parse.c
@@ -113,8 +113,8 @@ bc_parse_addNum(BcParse* p, const char* string)
// Get the right slab.
slabs = p->fidx == BC_PROG_MAIN || p->fidx == BC_PROG_READ ?
- &vm.main_const_slab :
- &vm.other_slabs;
+ &vm->main_const_slab :
+ &vm->other_slabs;
// Push an empty constant.
c = bc_vec_pushEmpty(consts);
@@ -207,7 +207,7 @@ bc_parse_reset(BcParse* p)
bc_program_reset(p->prog);
// Jump if there is an error.
- if (BC_ERR(vm.status)) BC_JMP;
+ if (BC_ERR(vm->status)) BC_JMP;
}
#ifndef NDEBUG
diff --git a/src/program.c b/src/program.c
index 20121828fa92..abe203ddee46 100644
--- a/src/program.c
+++ b/src/program.c
@@ -207,6 +207,7 @@ bc_program_dereference(const BcProgram* p, BcVec* vec)
return v;
}
+
#endif // BC_ENABLED
/**
@@ -246,8 +247,8 @@ bc_program_addString(BcProgram* p, const char* str, size_t fidx)
// Figure out which slab vector to use.
slabs = fidx == BC_PROG_MAIN || fidx == BC_PROG_READ ?
- &vm.main_slabs :
- &vm.other_slabs;
+ &vm->main_slabs :
+ &vm->other_slabs;
*str_ptr = bc_slabvec_strdup(slabs, str);
@@ -390,13 +391,13 @@ bc_program_num(BcProgram* p, BcResult* r)
case BC_RESULT_ZERO:
{
- n = &vm.zero;
+ n = &vm->zero;
break;
}
case BC_RESULT_ONE:
{
- n = &vm.one;
+ n = &vm->one;
break;
}
@@ -407,15 +408,23 @@ bc_program_num(BcProgram* p, BcResult* r)
#ifndef NDEBUG
{
abort();
+ // Fallthrough
}
#endif // NDEBUG
- // Fallthrough
case BC_RESULT_LAST:
{
n = &p->last;
break;
}
#endif // BC_ENABLED
+
+#if BC_GCC
+ // This is here in GCC to quiet the "maybe-uninitialized" warning.
+ default:
+ {
+ abort();
+ }
+#endif // BC_GCC
}
return n;
@@ -541,6 +550,7 @@ bc_program_assignPrep(BcProgram* p, BcResult** l, BcNum** ln, BcResult** r,
BcNum** rn)
{
BcResultType lt, min;
+ bool good;
// This is the min non-allowable result type. dc allows strings.
min = BC_RESULT_TEMP - ((unsigned int) (BC_IS_BC));
@@ -555,7 +565,7 @@ bc_program_assignPrep(BcProgram* p, BcResult** l, BcNum** ln, BcResult** r,
// Strings can be assigned to variables. We are already good if we are
// assigning a string.
- bool good = ((*r)->t == BC_RESULT_STR && lt <= BC_RESULT_ARRAY_ELEM);
+ good = ((*r)->t == BC_RESULT_STR && lt <= BC_RESULT_ARRAY_ELEM);
assert(BC_PROG_STR(*rn) || (*r)->t != BC_RESULT_STR);
@@ -636,8 +646,11 @@ bc_program_const(BcProgram* p, const char* code, size_t* bgn)
// Allocate if we haven't yet.
if (c->num.num == NULL)
{
+ // The plus 1 is in case of overflow with lack of clamping.
+ size_t len = strlen(c->val) + (BC_DIGIT_CLAMP == 0);
+
BC_SIG_LOCK;
- bc_num_init(&c->num, BC_NUM_RDX(strlen(c->val)));
+ bc_num_init(&c->num, BC_NUM_RDX(len));
BC_SIG_UNLOCK;
}
@@ -716,55 +729,55 @@ bc_program_read(BcProgram* p)
BC_SIG_LOCK;
// Save the filename because we are going to overwrite it.
- file = vm.file;
- is_stdin = vm.is_stdin;
+ file = vm->file;
+ is_stdin = vm->is_stdin;
// It is a parse error if there needs to be more than one line, so we unset
// this to tell the lexer to not request more. We set it back later.
- vm.is_stdin = false;
+ vm->is_stdin = false;
- if (!BC_PARSE_IS_INITED(&vm.read_prs, p))
+ if (!BC_PARSE_IS_INITED(&vm->read_prs, p))
{
// We need to parse, but we don't want to use the existing parser
// because it has state it needs to keep. (It could have a partial parse
// state.) So we create a new parser. This parser is in the BcVm struct
// so that it is not local, which means that a longjmp() could change
// it.
- bc_parse_init(&vm.read_prs, p, BC_PROG_READ);
+ bc_parse_init(&vm->read_prs, p, BC_PROG_READ);
// We need a separate input buffer; that's why it is also in the BcVm
// struct.
- bc_vec_init(&vm.read_buf, sizeof(char), BC_DTOR_NONE);
+ bc_vec_init(&vm->read_buf, sizeof(char), BC_DTOR_NONE);
}
// This needs to be updated because the parser could have been used
// somewhere else
- else bc_parse_updateFunc(&vm.read_prs, BC_PROG_READ);
+ else bc_parse_updateFunc(&vm->read_prs, BC_PROG_READ);
- BC_SETJMP_LOCKED(exec_err);
+ BC_SETJMP_LOCKED(vm, exec_err);
BC_SIG_UNLOCK;
// Set up the lexer and the read function.
- bc_lex_file(&vm.read_prs.l, bc_program_stdin_name);
+ bc_lex_file(&vm->read_prs.l, bc_program_stdin_name);
bc_vec_popAll(&f->code);
// Read a line.
- if (!BC_R) s = bc_read_line(&vm.read_buf, "");
- else s = bc_read_line(&vm.read_buf, BC_IS_BC ? "read> " : "?> ");
+ if (!BC_R) s = bc_read_line(&vm->read_buf, "");
+ else s = bc_read_line(&vm->read_buf, BC_VM_READ_PROMPT);
// We should *not* have run into EOF.
if (s == BC_STATUS_EOF) bc_err(BC_ERR_EXEC_READ_EXPR);
// Parse *one* expression, so is_stdin should be false.
- bc_parse_text(&vm.read_prs, vm.read_buf.v, false, 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);
+ vm->expr(&vm->read_prs, BC_PARSE_NOREAD | BC_PARSE_NEEDVAL);
BC_SIG_UNLOCK;
// We *must* have a valid expression. A semicolon cannot end an expression,
// although EOF can.
- if (BC_ERR(vm.read_prs.l.t != BC_LEX_NLINE &&
- vm.read_prs.l.t != BC_LEX_EOF))
+ if (BC_ERR(vm->read_prs.l.t != BC_LEX_NLINE &&
+ vm->read_prs.l.t != BC_LEX_EOF))
{
bc_err(BC_ERR_EXEC_READ_EXPR);
}
@@ -783,7 +796,7 @@ bc_program_read(BcProgram* p)
f = bc_vec_item(&p->fns, BC_PROG_READ);
// We want a return instruction to simplify things.
- bc_vec_pushByte(&f->code, vm.read_ret);
+ bc_vec_pushByte(&f->code, vm->read_ret);
// This lock is here to make sure dc's tail calls are the same length.
BC_SIG_LOCK;
@@ -800,9 +813,9 @@ bc_program_read(BcProgram* p)
exec_err:
BC_SIG_MAYLOCK;
- vm.is_stdin = is_stdin;
- vm.file = file;
- BC_LONGJMP_CONT;
+ vm->is_stdin = is_stdin;
+ vm->file = file;
+ BC_LONGJMP_CONT(vm);
}
#if BC_ENABLE_EXTRA_MATH
@@ -837,12 +850,12 @@ static void
bc_program_printChars(const char* str)
{
const char* nl;
- size_t len = vm.nchars + strlen(str);
+ size_t len = vm->nchars + strlen(str);
sig_atomic_t lock;
BC_SIG_TRYLOCK(lock);
- bc_file_puts(&vm.fout, bc_flush_save, str);
+ bc_file_puts(&vm->fout, bc_flush_save, str);
// We need to update the number of characters, so we find the last newline
// and set the characters accordingly.
@@ -850,7 +863,7 @@ bc_program_printChars(const char* str)
if (nl != NULL) len = strlen(nl + 1);
- vm.nchars = len > UINT16_MAX ? UINT16_MAX : (uint16_t) len;
+ vm->nchars = len > UINT16_MAX ? UINT16_MAX : (uint16_t) len;
BC_SIG_TRYUNLOCK(lock);
}
@@ -894,7 +907,7 @@ bc_program_printString(const char* restrict str)
if (c == 'n')
{
BC_SIG_LOCK;
- vm.nchars = UINT16_MAX;
+ vm->nchars = UINT16_MAX;
BC_SIG_UNLOCK;
}
@@ -977,7 +990,7 @@ bc_program_print(BcProgram* p, uchar inst, size_t idx)
else
{
// We want to flush any stuff in the stdout buffer first.
- bc_file_flush(&vm.fout, bc_flush_save);
+ bc_file_flush(&vm->fout, bc_flush_save);
str = bc_program_string(p, n);
#if BC_ENABLED
@@ -992,8 +1005,8 @@ bc_program_print(BcProgram* p, uchar inst, size_t idx)
}
}
- // bc always pops.
- if (BC_IS_BC || pop) bc_vec_pop(&p->results);
+ // bc always pops. This macro makes sure that happens.
+ if (BC_PROGRAM_POP(pop)) bc_vec_pop(&p->results);
}
void
@@ -1339,10 +1352,12 @@ bc_program_copyToVar(BcProgram* p, size_t idx, BcType t, bool last)
void
bc_program_assignBuiltin(BcProgram* p, bool scale, bool obase, BcBigDig val)
{
- BcVec* v;
- BcBigDig* ptr;
BcBigDig* ptr_t;
BcBigDig max, min;
+#if BC_ENABLED
+ BcVec* v;
+ BcBigDig* ptr;
+#endif // BC_ENABLED
assert(!scale || !obase);
@@ -1351,10 +1366,14 @@ bc_program_assignBuiltin(BcProgram* p, bool scale, bool obase, BcBigDig val)
{
// Set the min and max.
min = 0;
- max = vm.maxes[BC_PROG_GLOBALS_SCALE];
+ max = vm->maxes[BC_PROG_GLOBALS_SCALE];
- // Get a pointer to the stack and to the current value.
+#if BC_ENABLED
+ // Get a pointer to the stack.
v = p->globals_v + BC_PROG_GLOBALS_SCALE;
+#endif // BC_ENABLED
+
+ // Get a pointer to the current value.
ptr_t = p->globals + BC_PROG_GLOBALS_SCALE;
}
else
@@ -1365,10 +1384,14 @@ bc_program_assignBuiltin(BcProgram* p, bool scale, bool obase, BcBigDig val)
{
min = 0;
}
- max = vm.maxes[obase + BC_PROG_GLOBALS_IBASE];
+ max = vm->maxes[obase + BC_PROG_GLOBALS_IBASE];
- // Get a pointer to the stack and to the current value.
+#if BC_ENABLED
+ // Get a pointer to the stack.
v = p->globals_v + BC_PROG_GLOBALS_IBASE + obase;
+#endif // BC_ENABLED
+
+ // Get a pointer to the current value.
ptr_t = p->globals + BC_PROG_GLOBALS_IBASE + obase;
}
@@ -1385,9 +1408,13 @@ bc_program_assignBuiltin(BcProgram* p, bool scale, bool obase, BcBigDig val)
bc_verr(e, min, max);
}
- // Set the top of the stack and the actual global value.
+#if BC_ENABLED
+ // Set the top of the stack.
ptr = bc_vec_top(v);
*ptr = val;
+#endif // BC_ENABLED
+
+ // Set the actual global variable.
*ptr_t = val;
}
@@ -1705,7 +1732,7 @@ bc_program_incdec(BcProgram* p, uchar inst)
copy.t = BC_RESULT_TEMP;
bc_num_createCopy(&copy.d.n, num);
- BC_SETJMP_LOCKED(exit);
+ BC_SETJMP_LOCKED(vm, exit);
BC_SIG_UNLOCK;
@@ -1720,7 +1747,7 @@ bc_program_incdec(BcProgram* p, uchar inst)
bc_vec_push(&p->results, &copy);
- BC_UNSETJMP;
+ BC_UNSETJMP(vm);
BC_SIG_UNLOCK;
@@ -1730,7 +1757,7 @@ bc_program_incdec(BcProgram* p, uchar inst)
exit:
BC_SIG_MAYLOCK;
bc_num_free(&copy.d.n);
- BC_LONGJMP_CONT;
+ BC_LONGJMP_CONT(vm);
}
/**
@@ -2174,42 +2201,20 @@ bc_program_modexp(BcProgram* p)
static uchar
bc_program_asciifyNum(BcProgram* p, BcNum* n)
{
- BcNum num;
- BcBigDig val;
-
-#ifndef NDEBUG
- // This is entirely to satisfy a useless scan-build error.
- val = 0;
-#endif // NDEBUG
-
- bc_num_clear(&num);
-
- BC_SETJMP(num_err);
-
- BC_SIG_LOCK;
-
- bc_num_createCopy(&num, n);
-
- BC_SIG_UNLOCK;
+ bc_num_copy(&p->asciify, n);
// We want to clear the scale and sign for easy mod later.
- bc_num_truncate(&num, num.scale);
- BC_NUM_NEG_CLR_NP(num);
+ bc_num_truncate(&p->asciify, p->asciify.scale);
+ BC_NUM_NEG_CLR(&p->asciify);
// This is guaranteed to not have a divide by 0
// because strmb is equal to 256.
- bc_num_mod(&num, &p->strmb, &num, 0);
+ bc_num_mod(&p->asciify, &p->strmb, &p->asciify, 0);
// This is also guaranteed to not error because num is in the range
// [0, UCHAR_MAX], which is definitely in range for a BcBigDig. And
// it is not negative.
- val = bc_num_bigdig2(&num);
-
-num_err:
- BC_SIG_MAYLOCK;
- bc_num_free(&num);
- BC_LONGJMP_CONT;
- return (uchar) val;
+ return (uchar) bc_num_bigdig2(&p->asciify);
}
/**
@@ -2365,7 +2370,7 @@ bc_program_nquit(BcProgram* p, uchar inst)
// If we don't have enough executions, just quit.
if (i == p->stack.len)
{
- vm.status = BC_STATUS_QUIT;
+ vm->status = BC_STATUS_QUIT;
BC_JMP;
}
else
@@ -2434,7 +2439,11 @@ bc_program_execStr(BcProgram* p, const char* restrict code,
if (cond)
{
bool exec;
- size_t idx, then_idx, else_idx;
+ size_t then_idx;
+ // These are volatile to quiet warnings on GCC about clobbering with
+ // longjmp().
+ volatile size_t else_idx;
+ volatile size_t idx;
// Get the index of the "then" var and "else" var.
then_idx = bc_program_index(code, bgn);
@@ -2446,7 +2455,7 @@ bc_program_execStr(BcProgram* p, const char* restrict code,
idx = exec ? then_idx : else_idx;
BC_SIG_LOCK;
- BC_SETJMP_LOCKED(exit);
+ BC_SETJMP_LOCKED(vm, exit);
// If we are supposed to execute, execute. If else_idx == SIZE_MAX, that
// means there was no else clause, so if execute is false and else does
@@ -2460,7 +2469,7 @@ bc_program_execStr(BcProgram* p, const char* restrict code,
if (BC_ERR(!BC_PROG_STR(n))) bc_err(BC_ERR_EXEC_TYPE);
- BC_UNSETJMP;
+ BC_UNSETJMP(vm);
BC_SIG_UNLOCK;
}
else
@@ -2489,35 +2498,35 @@ bc_program_execStr(BcProgram* p, const char* restrict code,
{
BC_SIG_LOCK;
- if (!BC_PARSE_IS_INITED(&vm.read_prs, p))
+ if (!BC_PARSE_IS_INITED(&vm->read_prs, p))
{
- bc_parse_init(&vm.read_prs, p, fidx);
+ bc_parse_init(&vm->read_prs, p, fidx);
// Initialize this too because bc_vm_shutdown() expects them to be
// initialized togther.
- bc_vec_init(&vm.read_buf, sizeof(char), BC_DTOR_NONE);
+ bc_vec_init(&vm->read_buf, sizeof(char), BC_DTOR_NONE);
}
// This needs to be updated because the parser could have been used
// somewhere else
- else bc_parse_updateFunc(&vm.read_prs, fidx);
+ else bc_parse_updateFunc(&vm->read_prs, fidx);
- bc_lex_file(&vm.read_prs.l, vm.file);
+ bc_lex_file(&vm->read_prs.l, vm->file);
- BC_SETJMP_LOCKED(err);
+ BC_SETJMP_LOCKED(vm, err);
BC_SIG_UNLOCK;
// Parse.
- bc_parse_text(&vm.read_prs, str, false, false);
+ bc_parse_text(&vm->read_prs, str, false, false);
BC_SIG_LOCK;
- vm.expr(&vm.read_prs, BC_PARSE_NOCALL);
+ vm->expr(&vm->read_prs, BC_PARSE_NOCALL);
- BC_UNSETJMP;
+ BC_UNSETJMP(vm);
// We can just assert this here because
// dc should parse everything until EOF.
- assert(vm.read_prs.l.t == BC_LEX_EOF);
+ assert(vm->read_prs.l.t == BC_LEX_EOF);
BC_SIG_UNLOCK;
}
@@ -2566,7 +2575,7 @@ err:
exit:
bc_vec_pop(&p->results);
- BC_LONGJMP_CONT;
+ BC_LONGJMP_CONT(vm);
}
/**
@@ -2616,7 +2625,7 @@ bc_program_globalSetting(BcProgram* p, uchar inst)
// Make sure the instruction is valid.
assert(inst >= BC_INST_LINE_LENGTH && inst <= BC_INST_LEADING_ZERO);
- if (inst == BC_INST_LINE_LENGTH) val = (BcBigDig) vm.line_len;
+ if (inst == BC_INST_LINE_LENGTH) val = (BcBigDig) vm->line_len;
#if BC_ENABLED
else if (inst == BC_INST_GLOBAL_STACKS) val = (BC_G != 0);
#endif // BC_ENABLED
@@ -2716,17 +2725,21 @@ bc_program_insertFunc(BcProgram* p, const char* name)
void
bc_program_free(BcProgram* p)
{
+#if BC_ENABLED
size_t i;
+#endif // BC_ENABLED
BC_SIG_ASSERT_LOCKED;
assert(p != NULL);
+#if BC_ENABLED
// Free the globals stacks.
for (i = 0; i < BC_PROG_GLOBALS_LEN; ++i)
{
bc_vec_free(p->globals_v + i);
}
+#endif // BC_ENABLED
bc_vec_free(&p->fns);
bc_vec_free(&p->fn_map);
@@ -2737,6 +2750,8 @@ bc_program_free(BcProgram* p)
bc_vec_free(&p->results);
bc_vec_free(&p->stack);
+ bc_num_free(&p->asciify);
+
#if BC_ENABLED
if (BC_IS_BC) bc_num_free(&p->last);
#endif // BC_ENABLED
@@ -2770,8 +2785,10 @@ bc_program_init(BcProgram* p)
{
BcBigDig val = i == BC_PROG_GLOBALS_SCALE ? 0 : BC_BASE;
+#if BC_ENABLED
bc_vec_init(p->globals_v + i, sizeof(BcBigDig), BC_DTOR_NONE);
bc_vec_push(p->globals_v + i, &val);
+#endif // BC_ENABLED
p->globals[i] = val;
}
@@ -2791,6 +2808,8 @@ bc_program_init(BcProgram* p)
bc_num_setup(&p->strmb, p->strmb_num, BC_NUM_BIGDIG_LOG10);
bc_num_bigdig2num(&p->strmb, BC_NUM_STREAM_BASE);
+ bc_num_init(&p->asciify, BC_NUM_DEF_SIZE);
+
#if BC_ENABLE_EXTRA_MATH
// We need to initialize srand() just in case /dev/urandom and /dev/random
// are not available.
@@ -2857,11 +2876,11 @@ bc_program_reset(BcProgram* p)
memset(ip, 0, sizeof(BcInstPtr));
// Write the ready message for a signal, and clear the signal.
- if (vm.sig)
+ if (vm->sig)
{
- bc_file_printf(&vm.fout, "%s", bc_program_ready_msg);
- bc_file_flush(&vm.fout, bc_flush_err);
- vm.sig = 0;
+ bc_file_printf(&vm->fout, "%s", bc_program_ready_msg);
+ bc_file_flush(&vm->fout, bc_flush_err);
+ vm->sig = 0;
}
}
@@ -2886,9 +2905,26 @@ bc_program_exec(BcProgram* p)
#endif // !BC_HAS_COMPUTED_GOTO
#if BC_HAS_COMPUTED_GOTO
+
+#if BC_GCC
+#pragma GCC diagnostic ignored "-Wpedantic"
+#endif // BC_GCC
+
+#if BC_CLANG
+#pragma clang diagnostic ignored "-Wgnu-label-as-value"
+#endif // BC_CLANG
+
BC_PROG_LBLS;
BC_PROG_LBLS_ASSERT;
+#if BC_CLANG
+#pragma clang diagnostic warning "-Wgnu-label-as-value"
+#endif // BC_CLANG
+
+#if BC_GCC
+#pragma GCC diagnostic warning "-Wpedantic"
+#endif // BC_GCC
+
// BC_INST_INVALID is a marker for the end so that we don't have to have an
// execution loop.
func = (BcFunc*) bc_vec_item(&p->fns, BC_PROG_MAIN);
@@ -2907,7 +2943,7 @@ bc_program_exec(BcProgram* p)
#if !BC_HAS_COMPUTED_GOTO
#ifndef NDEBUG
- jmp_bufs_len = vm.jmp_bufs.len;
+ jmp_bufs_len = vm->jmp_bufs.len;
#endif // NDEBUG
// This loop is the heart of the execution engine. It *is* the engine. For
@@ -2919,6 +2955,14 @@ bc_program_exec(BcProgram* p)
#if BC_HAS_COMPUTED_GOTO
+#if BC_GCC
+#pragma GCC diagnostic ignored "-Wpedantic"
+#endif // BC_GCC
+
+#if BC_CLANG
+#pragma clang diagnostic ignored "-Wgnu-label-as-value"
+#endif // BC_CLANG
+
BC_PROG_JUMP(inst, code, ip);
#else // BC_HAS_COMPUTED_GOTO
@@ -2929,8 +2973,8 @@ bc_program_exec(BcProgram* p)
#endif // BC_HAS_COMPUTED_GOTO
#if BC_DEBUG_CODE
- bc_file_printf(&vm.ferr, "inst: %s\n", bc_inst_names[inst]);
- bc_file_flush(&vm.ferr, bc_flush_none);
+ bc_file_printf(&vm->ferr, "inst: %s\n", bc_inst_names[inst]);
+ bc_file_flush(&vm->ferr, bc_flush_none);
#endif // BC_DEBUG_CODE
#if !BC_HAS_COMPUTED_GOTO
@@ -3010,7 +3054,7 @@ bc_program_exec(BcProgram* p)
BC_PROG_LBL(BC_INST_HALT):
// clang-format on
{
- vm.status = BC_STATUS_QUIT;
+ vm->status = BC_STATUS_QUIT;
// Just jump out. The jump series will take care of everything.
BC_JMP;
@@ -3060,7 +3104,7 @@ bc_program_exec(BcProgram* p)
{
// We want to flush output before
// this in case there is a prompt.
- bc_file_flush(&vm.fout, bc_flush_save);
+ bc_file_flush(&vm->fout, bc_flush_save);
bc_program_read(p);
@@ -3093,9 +3137,9 @@ bc_program_exec(BcProgram* p)
#if BC_ENABLE_EXTRA_MATH
BC_PROG_LBL(BC_INST_MAXRAND):
#endif // BC_ENABLE_EXTRA_MATH
- // clang-format on
+ // clang-format on
{
- BcBigDig dig = vm.maxes[inst - BC_INST_MAXIBASE];
+ BcBigDig dig = vm->maxes[inst - BC_INST_MAXIBASE];
bc_program_pushBigdig(p, dig, BC_RESULT_TEMP);
BC_PROG_JUMP(inst, code, ip);
}
@@ -3157,7 +3201,7 @@ bc_program_exec(BcProgram* p)
#if BC_ENABLE_EXTRA_MATH
BC_PROG_LBL(BC_INST_IRAND):
#endif // BC_ENABLE_EXTRA_MATH
- // clang-format on
+ // clang-format on
{
bc_program_builtin(p, inst);
BC_PROG_JUMP(inst, code, ip);
@@ -3195,7 +3239,7 @@ bc_program_exec(BcProgram* p)
#if BC_ENABLED
BC_PROG_LBL(BC_INST_LAST):
#endif // BC_ENABLED
- // clang-format on
+ // clang-format on
{
r.t = BC_RESULT_ZERO + (inst - BC_INST_ZERO);
bc_vec_push(&p->results, &r);
@@ -3208,13 +3252,13 @@ bc_program_exec(BcProgram* p)
#if BC_ENABLED
BC_PROG_LBL(BC_INST_PRINT_STR):
#endif // BC_ENABLED
- // clang-format on
+ // clang-format on
{
bc_program_print(p, inst, 0);
// We want to flush right away to save the output for history,
// if history must preserve it when taking input.
- bc_file_flush(&vm.fout, bc_flush_save);
+ bc_file_flush(&vm->fout, bc_flush_save);
BC_PROG_JUMP(inst, code, ip);
}
@@ -3244,7 +3288,7 @@ bc_program_exec(BcProgram* p)
BC_PROG_LBL(BC_INST_LSHIFT):
BC_PROG_LBL(BC_INST_RSHIFT):
#endif // BC_ENABLE_EXTRA_MATH
- // clang-format on
+ // clang-format on
{
bc_program_op(p, inst);
BC_PROG_JUMP(inst, code, ip);
@@ -3256,7 +3300,7 @@ bc_program_exec(BcProgram* p)
#if BC_ENABLE_EXTRA_MATH
BC_PROG_LBL(BC_INST_TRUNC):
#endif // BC_ENABLE_EXTRA_MATH
- // clang-format on
+ // clang-format on
{
bc_program_unary(p, inst);
BC_PROG_JUMP(inst, code, ip);
@@ -3531,21 +3575,33 @@ bc_program_exec(BcProgram* p)
default:
{
BC_UNREACHABLE
-#ifndef NDEBUG
+#if !defined(NDEBUG) && !BC_CLANG
abort();
-#endif // NDEBUG
+#endif // !defined(NDEBUG) && !BC_CLANG
}
#endif // BC_HAS_COMPUTED_GOTO
}
-#if !BC_HAS_COMPUTED_GOTO
+#if BC_HAS_COMPUTED_GOTO
+
+#if BC_CLANG
+#pragma clang diagnostic warning "-Wgnu-label-as-value"
+#endif // BC_CLANG
+
+#if BC_GCC
+#pragma GCC diagnostic warning "-Wpedantic"
+#endif // BC_GCC
+
+#else // BC_HAS_COMPUTED_GOTO
+
#ifndef NDEBUG
// This is to allow me to use a debugger to see the last instruction,
// which will point to which function was the problem. But it's also a
// good smoke test for error handling changes.
- assert(jmp_bufs_len == vm.jmp_bufs.len);
+ assert(jmp_bufs_len == vm->jmp_bufs.len);
#endif // NDEBUG
-#endif // !BC_HAS_COMPUTED_GOTO
+
+#endif // BC_HAS_COMPUTED_GOTO
}
}
@@ -3554,9 +3610,9 @@ bc_program_exec(BcProgram* p)
void
bc_program_printStackDebug(BcProgram* p)
{
- bc_file_puts(&vm.fout, bc_flush_err, "-------------- Stack ----------\n");
+ bc_file_puts(&vm->fout, bc_flush_err, "-------------- Stack ----------\n");
bc_program_printStack(p);
- bc_file_puts(&vm.fout, bc_flush_err, "-------------- Stack End ------\n");
+ bc_file_puts(&vm->fout, bc_flush_err, "-------------- Stack End ------\n");
}
static void
@@ -3638,7 +3694,7 @@ bc_program_code(const BcProgram* p)
{
bc_program_printInst(p, code, &ip.idx);
}
- bc_file_puts(&vm.fout, bc_flush_err, "\n\n");
+ bc_file_puts(&vm->fout, bc_flush_err, "\n\n");
}
}
#endif // BC_ENABLED && DC_ENABLED
diff --git a/src/read.c b/src/read.c
index 13a34fd66e53..d6b0deb7814a 100644
--- a/src/read.c
+++ b/src/read.c
@@ -143,12 +143,12 @@ bc_read_chars(BcVec* vec, const char* prompt)
// Handle the prompt, if desired.
if (BC_PROMPT)
{
- bc_file_puts(&vm.fout, bc_flush_none, prompt);
- bc_file_flush(&vm.fout, bc_flush_none);
+ bc_file_puts(&vm->fout, bc_flush_none, prompt);
+ bc_file_flush(&vm->fout, bc_flush_none);
}
// Try reading from the buffer, and if successful, just return.
- if (bc_read_buf(vec, vm.buf, &vm.buf_len))
+ if (bc_read_buf(vec, vm->buf, &vm->buf_len))
{
bc_vec_pushByte(vec, '\0');
return BC_STATUS_SUCCESS;
@@ -162,8 +162,8 @@ bc_read_chars(BcVec* vec, const char* prompt)
BC_SIG_LOCK;
// Read data from stdin.
- r = read(STDIN_FILENO, vm.buf + vm.buf_len,
- BC_VM_STDIN_BUF_SIZE - vm.buf_len);
+ r = read(STDIN_FILENO, vm->buf + vm->buf_len,
+ BC_VM_STDIN_BUF_SIZE - vm->buf_len);
// If there was an error...
if (BC_UNLIKELY(r < 0))
@@ -173,18 +173,18 @@ bc_read_chars(BcVec* vec, const char* prompt)
{
// Jump out if we are supposed to quit, which certain signals
// will require.
- if (vm.status == (sig_atomic_t) BC_STATUS_QUIT) BC_JMP;
+ if (vm->status == (sig_atomic_t) BC_STATUS_QUIT) BC_JMP;
- assert(vm.sig);
+ assert(vm->sig);
// Clear the signal and status.
- vm.sig = 0;
- vm.status = (sig_atomic_t) BC_STATUS_SUCCESS;
+ vm->sig = 0;
+ vm->status = (sig_atomic_t) BC_STATUS_SUCCESS;
// Print the ready message and prompt again.
- bc_file_puts(&vm.fout, bc_flush_none, bc_program_ready_msg);
- if (BC_PROMPT) bc_file_puts(&vm.fout, bc_flush_none, prompt);
- bc_file_flush(&vm.fout, bc_flush_none);
+ bc_file_puts(&vm->fout, bc_flush_none, bc_program_ready_msg);
+ if (BC_PROMPT) bc_file_puts(&vm->fout, bc_flush_none, prompt);
+ bc_file_flush(&vm->fout, bc_flush_none);
BC_SIG_UNLOCK;
@@ -209,11 +209,11 @@ bc_read_chars(BcVec* vec, const char* prompt)
BC_SIG_LOCK;
// Add to the buffer.
- vm.buf_len += (size_t) r;
- vm.buf[vm.buf_len] = '\0';
+ vm->buf_len += (size_t) r;
+ vm->buf[vm->buf_len] = '\0';
// Read from the buffer.
- done = bc_read_buf(vec, vm.buf, &vm.buf_len);
+ done = bc_read_buf(vec, vm->buf, &vm->buf_len);
BC_SIG_UNLOCK;
}
@@ -231,9 +231,9 @@ bc_read_line(BcVec* vec, const char* prompt)
#if BC_ENABLE_HISTORY
// Get a line from either history or manual reading.
- if (BC_TTY && !vm.history.badTerm)
+ if (BC_TTY && !vm->history.badTerm)
{
- s = bc_history_line(&vm.history, vec, prompt);
+ s = bc_history_line(&vm->history, vec, prompt);
}
else s = bc_read_chars(vec, prompt);
#else // BC_ENABLE_HISTORY
diff --git a/src/vector.c b/src/vector.c
index 7d492974a48c..92da4ba44eca 100644
--- a/src/vector.c
+++ b/src/vector.c
@@ -46,7 +46,9 @@ void
bc_vec_grow(BcVec* restrict v, size_t n)
{
size_t cap, len;
+#if !BC_ENABLE_LIBRARY
sig_atomic_t lock;
+#endif // !BC_ENABLE_LIBRARY
cap = v->cap;
len = v->len + n;
@@ -93,7 +95,9 @@ bc_vec_expand(BcVec* restrict v, size_t req)
// Only expand if necessary.
if (v->cap < req)
{
+#if !BC_ENABLE_LIBRARY
sig_atomic_t lock;
+#endif // !BC_ENABLE_LIBRARY
BC_SIG_TRYLOCK(lock);
@@ -107,7 +111,9 @@ bc_vec_expand(BcVec* restrict v, size_t req)
void
bc_vec_npop(BcVec* restrict v, size_t n)
{
+#if !BC_ENABLE_LIBRARY
sig_atomic_t lock;
+#endif // !BC_ENABLE_LIBRARY
assert(v != NULL && n <= v->len);
@@ -135,7 +141,9 @@ bc_vec_npopAt(BcVec* restrict v, size_t n, size_t idx)
{
char* ptr;
char* data;
+#if !BC_ENABLE_LIBRARY
sig_atomic_t lock;
+#endif // !BC_ENABLE_LIBRARY
assert(v != NULL);
assert(idx + n < v->len);
@@ -168,7 +176,9 @@ bc_vec_npopAt(BcVec* restrict v, size_t n, size_t idx)
void
bc_vec_npush(BcVec* restrict v, size_t n, const void* data)
{
+#if !BC_ENABLE_LIBRARY
sig_atomic_t lock;
+#endif // !BC_ENABLE_LIBRARY
size_t esize;
assert(v != NULL && data != NULL);
@@ -197,7 +207,9 @@ bc_vec_push(BcVec* restrict v, const void* data)
void*
bc_vec_pushEmpty(BcVec* restrict v)
{
+#if !BC_ENABLE_LIBRARY
sig_atomic_t lock;
+#endif // !BC_ENABLE_LIBRARY
void* ptr;
assert(v != NULL);
@@ -275,7 +287,9 @@ bc_vec_pushAt(BcVec* restrict v, const void* data, size_t idx)
void
bc_vec_string(BcVec* restrict v, size_t len, const char* restrict str)
{
+#if !BC_ENABLE_LIBRARY
sig_atomic_t lock;
+#endif // !BC_ENABLE_LIBRARY
assert(v != NULL && v->size == sizeof(char));
assert(!v->dtor);
@@ -298,7 +312,9 @@ bc_vec_string(BcVec* restrict v, size_t len, const char* restrict str)
void
bc_vec_concat(BcVec* restrict v, const char* restrict str)
{
+#if !BC_ENABLE_LIBRARY
sig_atomic_t lock;
+#endif // !BC_ENABLE_LIBRARY
assert(v != NULL && v->size == sizeof(char));
assert(!v->dtor);
@@ -318,7 +334,9 @@ bc_vec_concat(BcVec* restrict v, const char* restrict str)
void
bc_vec_empty(BcVec* restrict v)
{
+#if !BC_ENABLE_LIBRARY
sig_atomic_t lock;
+#endif // !BC_ENABLE_LIBRARY
assert(v != NULL && v->size == sizeof(char));
assert(!v->dtor);
@@ -432,11 +450,8 @@ bc_map_insert(BcVec* restrict v, const char* name, size_t idx,
return false;
}
-#if BC_ENABLED
- slabs = BC_IS_DC ? &vm.main_slabs : &vm.other_slabs;
-#else // BC_ENABLED
- slabs = &vm.main_slabs;
-#endif // BC_ENABLED
+ // This macro returns the correct slabs for the calculator.
+ slabs = BC_VEC_MAP_SLABS;
id.name = bc_slabvec_strdup(slabs, name);
id.idx = idx;
@@ -478,7 +493,9 @@ bc_map_name(const BcVec* restrict v, size_t idx)
BC_UNREACHABLE
+#if !BC_CLANG
return "";
+#endif // !BC_CLANG
}
#endif // DC_ENABLED
@@ -632,17 +649,17 @@ bc_slabvec_print(BcVec* v, const char* func)
size_t i;
BcSlab* s;
- bc_file_printf(&vm.ferr, "%s\n", func);
+ bc_file_printf(&vm->ferr, "%s\n", func);
for (i = 0; i < v->len; ++i)
{
s = bc_vec_item(v, i);
- bc_file_printf(&vm.ferr, "%zu { s = %zu, len = %zu }\n", i,
+ bc_file_printf(&vm->ferr, "%zu { s = %zu, len = %zu }\n", i,
(uintptr_t) s->s, s->len);
}
- bc_file_puts(&vm.ferr, bc_flush_none, "\n");
- bc_file_flush(&vm.ferr, bc_flush_none);
+ bc_file_puts(&vm->ferr, bc_flush_none, "\n");
+ bc_file_flush(&vm->ferr, bc_flush_none);
}
#endif // BC_DEBUG_CODE
diff --git a/src/vm.c b/src/vm.c
index 0e4a2b1216e9..7a5166d2203d 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -63,11 +63,16 @@
#include <vm.h>
#include <read.h>
#include <bc.h>
+#if BC_ENABLE_LIBRARY
+#include <library.h>
+#endif // BC_ENABLE_LIBRARY
+#if !BC_ENABLE_LIBRARY
// The actual globals.
-static BcDig* temps_buf[BC_VM_MAX_TEMPS];
char output_bufs[BC_VM_BUF_SIZE];
-BcVm vm;
+BcVm vm_data;
+BcVm* vm = &vm_data;
+#endif // !BC_ENABLE_LIBRARY
#if BC_DEBUG_CODE
BC_NORETURN void
@@ -79,26 +84,30 @@ bc_vm_jmp(void)
{
#endif
- assert(BC_SIG_EXC);
+#if BC_ENABLE_LIBRARY
+ BcVm* vm = bcl_getspecific();
+#endif // BC_ENABLE_LIBRARY
+
+ assert(BC_SIG_EXC(vm));
BC_SIG_MAYLOCK;
#if BC_DEBUG_CODE
- bc_file_puts(&vm.ferr, bc_flush_none, "Longjmp: ");
- bc_file_puts(&vm.ferr, bc_flush_none, f);
- bc_file_putchar(&vm.ferr, bc_flush_none, '\n');
- bc_file_flush(&vm.ferr, bc_flush_none);
+ bc_file_puts(&vm->ferr, bc_flush_none, "Longjmp: ");
+ bc_file_puts(&vm->ferr, bc_flush_none, f);
+ bc_file_putchar(&vm->ferr, bc_flush_none, '\n');
+ bc_file_flush(&vm->ferr, bc_flush_none);
#endif // BC_DEBUG_CODE
#ifndef NDEBUG
- assert(vm.jmp_bufs.len - (size_t) vm.sig_pop);
+ assert(vm->jmp_bufs.len - (size_t) vm->sig_pop);
#endif // NDEBUG
- if (vm.jmp_bufs.len == 0) abort();
- if (vm.sig_pop) bc_vec_pop(&vm.jmp_bufs);
- else vm.sig_pop = 1;
+ if (vm->jmp_bufs.len == 0) abort();
+ if (vm->sig_pop) bc_vec_pop(&vm->jmp_bufs);
+ else vm->sig_pop = 1;
- siglongjmp(*((sigjmp_buf*) bc_vec_top(&vm.jmp_bufs)), 1);
+ siglongjmp(*((sigjmp_buf*) bc_vec_top(&vm->jmp_bufs)), 1);
}
#if !BC_ENABLE_LIBRARY
@@ -111,9 +120,9 @@ static void
bc_vm_sig(int sig)
{
// There is already a signal in flight.
- if (vm.status == (sig_atomic_t) BC_STATUS_QUIT || vm.sig)
+ if (vm->status == (sig_atomic_t) BC_STATUS_QUIT || vm->sig)
{
- if (!BC_I || sig != SIGINT) vm.status = BC_STATUS_QUIT;
+ if (!BC_I || sig != SIGINT) vm->status = BC_STATUS_QUIT;
return;
}
@@ -121,7 +130,7 @@ bc_vm_sig(int sig)
// Editline needs this to resize the terminal.
if (sig == SIGWINCH)
{
- el_resize(vm.history.el);
+ el_resize(vm->history.el);
return;
}
#endif // BC_ENABLE_EDITLINE
@@ -135,16 +144,17 @@ bc_vm_sig(int sig)
// Editline needs this, for some unknown reason.
if (write(STDOUT_FILENO, "^C", 2) != (ssize_t) 2)
{
- vm.status = BC_STATUS_ERROR_FATAL;
+ vm->status = BC_STATUS_ERROR_FATAL;
}
#endif // BC_ENABLE_EDITLINE
// Write the message.
- if (write(STDOUT_FILENO, vm.sigmsg, vm.siglen) != (ssize_t) vm.siglen)
+ if (write(STDOUT_FILENO, vm->sigmsg, vm->siglen) !=
+ (ssize_t) vm->siglen)
{
- vm.status = BC_STATUS_ERROR_FATAL;
+ vm->status = BC_STATUS_ERROR_FATAL;
}
- else vm.sig = 1;
+ else vm->sig = 1;
errno = err;
}
@@ -153,12 +163,12 @@ bc_vm_sig(int sig)
#if BC_ENABLE_EDITLINE
if (write(STDOUT_FILENO, "^C", 2) != (ssize_t) 2)
{
- vm.status = BC_STATUS_ERROR_FATAL;
+ vm->status = BC_STATUS_ERROR_FATAL;
return;
}
#endif // BC_ENABLE_EDITLINE
- vm.status = BC_STATUS_QUIT;
+ vm->status = BC_STATUS_QUIT;
}
#if BC_ENABLE_LINE_LIB
@@ -170,11 +180,11 @@ bc_vm_sig(int sig)
}
#endif // BC_ENABLE_LINE_LIB
- assert(vm.jmp_bufs.len);
+ assert(vm->jmp_bufs.len);
// Only jump if signals are not locked. The jump will happen by whoever
// unlocks signals.
- if (!vm.sig_lock) BC_JMP;
+ if (!vm->sig_lock) BC_JMP;
}
/**
@@ -188,9 +198,18 @@ bc_vm_sigaction(void)
struct sigaction sa;
sigemptyset(&sa.sa_mask);
- sa.sa_handler = bc_vm_sig;
sa.sa_flags = SA_NODEFER;
+ // This mess is to silence a warning on Clang with regards to glibc's
+ // sigaction handler, which activates the warning here.
+#if BC_CLANG
+#pragma clang diagnostic ignored "-Wdisabled-macro-expansion"
+#endif // BC_CLANG
+ sa.sa_handler = bc_vm_sig;
+#if BC_CLANG
+#pragma clang diagnostic warning "-Wdisabled-macro-expansion"
+#endif // BC_CLANG
+
sigaction(SIGTERM, &sa, NULL);
sigaction(SIGQUIT, &sa, NULL);
sigaction(SIGINT, &sa, NULL);
@@ -218,12 +237,12 @@ bc_vm_info(const char* const help)
BC_SIG_ASSERT_LOCKED;
// Print the banner.
- bc_file_printf(&vm.fout, "%s %s\n%s", vm.name, BC_VERSION, bc_copyright);
+ bc_file_printf(&vm->fout, "%s %s\n%s", vm->name, BC_VERSION, bc_copyright);
// Print the help.
if (help != NULL)
{
- bc_file_putchar(&vm.fout, bc_flush_none, '\n');
+ bc_file_putchar(&vm->fout, bc_flush_none, '\n');
#if BC_ENABLED
if (BC_IS_BC)
@@ -237,9 +256,12 @@ bc_vm_info(const char* const help)
"disabled";
const char* const expr = BC_DEFAULT_EXPR_EXIT ? "to exit" :
"to not exit";
+ const char* const clamp = BC_DEFAULT_DIGIT_CLAMP ? "to clamp" :
+ "to not clamp";
- bc_file_printf(&vm.fout, help, vm.name, vm.name, BC_VERSION,
- BC_BUILD_TYPE, banner, sigint, tty, prompt, expr);
+ bc_file_printf(&vm->fout, help, vm->name, vm->name, BC_VERSION,
+ BC_BUILD_TYPE, banner, sigint, tty, prompt, expr,
+ clamp);
}
#endif // BC_ENABLED
@@ -254,15 +276,17 @@ bc_vm_info(const char* const help)
"disabled";
const char* const expr = DC_DEFAULT_EXPR_EXIT ? "to exit" :
"to not exit";
+ const char* const clamp = DC_DEFAULT_DIGIT_CLAMP ? "to clamp" :
+ "to not clamp";
- bc_file_printf(&vm.fout, help, vm.name, vm.name, BC_VERSION,
- BC_BUILD_TYPE, sigint, tty, prompt, expr);
+ bc_file_printf(&vm->fout, help, vm->name, vm->name, BC_VERSION,
+ BC_BUILD_TYPE, sigint, tty, prompt, expr, clamp);
}
#endif // DC_ENABLED
}
// Flush.
- bc_file_flush(&vm.fout, bc_flush_none);
+ bc_file_flush(&vm->fout, bc_flush_none);
}
#endif // !BC_ENABLE_LIBRARY
@@ -275,16 +299,22 @@ bc_vm_fatalError(BcErr e)
bc_err(e);
#if !BC_ENABLE_LIBRARY && !BC_ENABLE_MEMCHECK
BC_UNREACHABLE
+#if !BC_CLANG
abort();
+#endif // !BC_CLANG
#endif // !BC_ENABLE_LIBRARY && !BC_ENABLE_MEMCHECK
}
#if BC_ENABLE_LIBRARY
-void
+BC_NORETURN void
bc_vm_handleError(BcErr e)
{
+#if BC_ENABLE_LIBRARY
+ BcVm* vm = bcl_getspecific();
+#endif // BC_ENABLE_LIBRARY
+
assert(e < BC_ERR_NELEMS);
- assert(!vm.sig_pop);
+ assert(!vm->sig_pop);
BC_SIG_LOCK;
@@ -292,13 +322,13 @@ bc_vm_handleError(BcErr e)
if (e <= BC_ERR_MATH_DIVIDE_BY_ZERO)
{
// Set the error.
- vm.err = (BclError) (e - BC_ERR_MATH_NEGATIVE +
- BCL_ERROR_MATH_NEGATIVE);
+ vm->err = (BclError) (e - BC_ERR_MATH_NEGATIVE +
+ BCL_ERROR_MATH_NEGATIVE);
}
// Abort if we should.
- else if (vm.abrt) abort();
- else if (e == BC_ERR_FATAL_ALLOC_ERR) vm.err = BCL_ERROR_FATAL_ALLOC_ERR;
- else vm.err = BCL_ERROR_FATAL_UNKNOWN_ERR;
+ else if (vm->abrt) abort();
+ else if (e == BC_ERR_FATAL_ALLOC_ERR) vm->err = BCL_ERROR_FATAL_ALLOC_ERR;
+ else vm->err = BCL_ERROR_FATAL_UNKNOWN_ERR;
BC_JMP;
}
@@ -309,11 +339,11 @@ bc_vm_handleError(BcErr e, size_t line, ...)
BcStatus s;
va_list args;
uchar id = bc_err_ids[e];
- const char* err_type = vm.err_ids[id];
+ const char* err_type = vm->err_ids[id];
sig_atomic_t lock;
assert(e < BC_ERR_NELEMS);
- assert(!vm.sig_pop);
+ assert(!vm->sig_pop);
#if BC_ENABLED
// Figure out if the POSIX error should be an error, a warning, or nothing.
@@ -323,7 +353,7 @@ bc_vm_handleError(BcErr e, size_t line, ...)
{
// Make sure to not return an error.
id = UCHAR_MAX;
- err_type = vm.err_ids[BC_ERR_IDX_WARN];
+ err_type = vm->err_ids[BC_ERR_IDX_WARN];
}
else return;
}
@@ -332,57 +362,57 @@ bc_vm_handleError(BcErr e, size_t line, ...)
BC_SIG_TRYLOCK(lock);
// Make sure all of stdout is written first.
- s = bc_file_flushErr(&vm.fout, bc_flush_err);
+ s = bc_file_flushErr(&vm->fout, bc_flush_err);
// Just jump out if the flush failed; there's nothing we can do.
if (BC_ERR(s == BC_STATUS_ERROR_FATAL))
{
- vm.status = (sig_atomic_t) s;
+ vm->status = (sig_atomic_t) s;
BC_JMP;
}
// Print the error message.
va_start(args, line);
- bc_file_putchar(&vm.ferr, bc_flush_none, '\n');
- bc_file_puts(&vm.ferr, bc_flush_none, err_type);
- bc_file_putchar(&vm.ferr, bc_flush_none, ' ');
- bc_file_vprintf(&vm.ferr, vm.err_msgs[e], args);
+ bc_file_putchar(&vm->ferr, bc_flush_none, '\n');
+ bc_file_puts(&vm->ferr, bc_flush_none, err_type);
+ bc_file_putchar(&vm->ferr, bc_flush_none, ' ');
+ bc_file_vprintf(&vm->ferr, vm->err_msgs[e], args);
va_end(args);
// Print the extra information if we have it.
- if (BC_NO_ERR(vm.file != NULL))
+ if (BC_NO_ERR(vm->file != NULL))
{
// This is the condition for parsing vs runtime.
// If line is not 0, it is parsing.
if (line)
{
- bc_file_puts(&vm.ferr, bc_flush_none, "\n ");
- bc_file_puts(&vm.ferr, bc_flush_none, vm.file);
- bc_file_printf(&vm.ferr, bc_err_line, line);
+ bc_file_puts(&vm->ferr, bc_flush_none, "\n ");
+ bc_file_puts(&vm->ferr, bc_flush_none, vm->file);
+ bc_file_printf(&vm->ferr, bc_err_line, line);
}
else
{
- BcInstPtr* ip = bc_vec_item_rev(&vm.prog.stack, 0);
- BcFunc* f = bc_vec_item(&vm.prog.fns, ip->func);
+ BcInstPtr* ip = bc_vec_item_rev(&vm->prog.stack, 0);
+ BcFunc* f = bc_vec_item(&vm->prog.fns, ip->func);
- bc_file_puts(&vm.ferr, bc_flush_none, "\n ");
- bc_file_puts(&vm.ferr, bc_flush_none, vm.func_header);
- bc_file_putchar(&vm.ferr, bc_flush_none, ' ');
- bc_file_puts(&vm.ferr, bc_flush_none, f->name);
+ bc_file_puts(&vm->ferr, bc_flush_none, "\n ");
+ bc_file_puts(&vm->ferr, bc_flush_none, vm->func_header);
+ bc_file_putchar(&vm->ferr, bc_flush_none, ' ');
+ bc_file_puts(&vm->ferr, bc_flush_none, f->name);
#if BC_ENABLED
if (BC_IS_BC && ip->func != BC_PROG_MAIN &&
ip->func != BC_PROG_READ)
{
- bc_file_puts(&vm.ferr, bc_flush_none, "()");
+ bc_file_puts(&vm->ferr, bc_flush_none, "()");
}
#endif // BC_ENABLED
}
}
- bc_file_puts(&vm.ferr, bc_flush_none, "\n\n");
+ bc_file_puts(&vm->ferr, bc_flush_none, "\n\n");
- s = bc_file_flushErr(&vm.ferr, bc_flush_err);
+ s = bc_file_flushErr(&vm->ferr, bc_flush_err);
#if !BC_ENABLE_MEMCHECK
// Because this function is called by a BC_NORETURN function when fatal
@@ -393,15 +423,15 @@ bc_vm_handleError(BcErr e, size_t line, ...)
exit(bc_vm_atexit((int) BC_STATUS_ERROR_FATAL));
}
#else // !BC_ENABLE_MEMCHECK
- if (BC_ERR(s == BC_STATUS_ERROR_FATAL)) vm.status = (sig_atomic_t) s;
+ if (BC_ERR(s == BC_STATUS_ERROR_FATAL)) vm->status = (sig_atomic_t) s;
else
#endif // !BC_ENABLE_MEMCHECK
{
- vm.status = (sig_atomic_t) (uchar) (id + 1);
+ vm->status = (sig_atomic_t) (uchar) (id + 1);
}
// Only jump if there is an error.
- if (BC_ERR(vm.status)) BC_JMP;
+ if (BC_ERR(vm->status)) BC_JMP;
BC_SIG_TRYUNLOCK(lock);
}
@@ -445,12 +475,12 @@ bc_vm_setenvFlag(const char* const var, int def, uint16_t flag)
if (val == NULL)
{
// Set the default.
- if (def) vm.flags |= flag;
- else vm.flags &= ~(flag);
+ if (def) vm->flags |= flag;
+ else vm->flags &= ~(flag);
}
// Parse the value.
- else if (strtoul(val, NULL, 0)) vm.flags |= flag;
- else vm.flags &= ~(flag);
+ else if (strtoul(val, NULL, 0)) vm->flags |= flag;
+ else vm->flags &= ~(flag);
bc_vm_getenvFree(val);
}
@@ -458,9 +488,16 @@ bc_vm_setenvFlag(const char* const var, int def, uint16_t flag)
/**
* Parses the arguments in {B,D]C_ENV_ARGS.
* @param env_args_name The environment variable to use.
+ * @param scale A pointer to return the scale that the arguments set,
+ * if any.
+ * @param ibase A pointer to return the ibase that the arguments set,
+ * if any.
+ * @param obase A pointer to return the obase that the arguments set,
+ * if any.
*/
static void
-bc_vm_envArgs(const char* const env_args_name)
+bc_vm_envArgs(const char* const env_args_name, BcBigDig* scale, BcBigDig* ibase,
+ BcBigDig* obase)
{
char *env_args = bc_vm_getenv(env_args_name), *buf, *start;
char instr = '\0';
@@ -471,9 +508,9 @@ bc_vm_envArgs(const char* const env_args_name)
// Windows already allocates, so we don't need to.
#ifndef _WIN32
- start = buf = vm.env_args_buffer = bc_vm_strdup(env_args);
+ start = buf = vm->env_args_buffer = bc_vm_strdup(env_args);
#else // _WIN32
- start = buf = vm.env_args_buffer = env_args;
+ start = buf = vm->env_args_buffer = env_args;
#endif // _WIN32
assert(buf != NULL);
@@ -481,8 +518,8 @@ bc_vm_envArgs(const char* const env_args_name)
// Create two buffers for parsing. These need to stay throughout the entire
// execution of bc, unfortunately, because of filenames that might be in
// there.
- bc_vec_init(&vm.env_args, sizeof(char*), BC_DTOR_NONE);
- bc_vec_push(&vm.env_args, &env_args_name);
+ bc_vec_init(&vm->env_args, sizeof(char*), BC_DTOR_NONE);
+ bc_vec_push(&vm->env_args, &env_args_name);
// While we haven't reached the end of the args...
while (*buf)
@@ -507,7 +544,7 @@ bc_vm_envArgs(const char* const env_args_name)
}
// Push the pointer to the args buffer.
- bc_vec_push(&vm.env_args, &buf);
+ bc_vec_push(&vm->env_args, &buf);
// Parse the string.
while (*buf &&
@@ -534,11 +571,11 @@ bc_vm_envArgs(const char* const env_args_name)
// Make sure to push a NULL pointer at the end.
buf = NULL;
- bc_vec_push(&vm.env_args, &buf);
+ bc_vec_push(&vm->env_args, &buf);
// Parse the arguments.
- bc_args((int) vm.env_args.len - 1, bc_vec_item(&vm.env_args, 0), false,
- BC_PROG_SCALE(&vm.prog));
+ bc_args((int) vm->env_args.len - 1, bc_vec_item(&vm->env_args, 0), false,
+ scale, ibase, obase);
}
/**
@@ -586,35 +623,35 @@ bc_vm_shutdown(void)
BC_SIG_ASSERT_LOCKED;
#if BC_ENABLE_NLS
- if (vm.catalog != BC_VM_INVALID_CATALOG) catclose(vm.catalog);
+ if (vm->catalog != BC_VM_INVALID_CATALOG) catclose(vm->catalog);
#endif // BC_ENABLE_NLS
#if BC_ENABLE_HISTORY
// This must always run to ensure that the terminal is back to normal, i.e.,
// has raw mode disabled. But we should only do it if we did not have a bad
// terminal because history was not initialized if it is a bad terminal.
- if (BC_TTY && !vm.history.badTerm) bc_history_free(&vm.history);
+ if (BC_TTY && !vm->history.badTerm) bc_history_free(&vm->history);
#endif // BC_ENABLE_HISTORY
#ifndef NDEBUG
#if !BC_ENABLE_LIBRARY
- bc_vec_free(&vm.env_args);
- free(vm.env_args_buffer);
- bc_vec_free(&vm.files);
- bc_vec_free(&vm.exprs);
+ bc_vec_free(&vm->env_args);
+ free(vm->env_args_buffer);
+ bc_vec_free(&vm->files);
+ bc_vec_free(&vm->exprs);
- if (BC_PARSE_IS_INITED(&vm.read_prs, &vm.prog))
+ if (BC_PARSE_IS_INITED(&vm->read_prs, &vm->prog))
{
- bc_vec_free(&vm.read_buf);
- bc_parse_free(&vm.read_prs);
+ bc_vec_free(&vm->read_buf);
+ bc_parse_free(&vm->read_prs);
}
- bc_parse_free(&vm.prs);
- bc_program_free(&vm.prog);
+ bc_parse_free(&vm->prs);
+ bc_program_free(&vm->prog);
- bc_slabvec_free(&vm.other_slabs);
- bc_slabvec_free(&vm.main_slabs);
- bc_slabvec_free(&vm.main_const_slab);
+ bc_slabvec_free(&vm->other_slabs);
+ bc_slabvec_free(&vm->main_slabs);
+ bc_slabvec_free(&vm->main_const_slab);
#endif // !BC_ENABLE_LIBRARY
bc_vm_freeTemps();
@@ -622,64 +659,91 @@ bc_vm_shutdown(void)
#if !BC_ENABLE_LIBRARY
// We always want to flush.
- bc_file_free(&vm.fout);
- bc_file_free(&vm.ferr);
+ bc_file_free(&vm->fout);
+ bc_file_free(&vm->ferr);
#endif // !BC_ENABLE_LIBRARY
}
void
bc_vm_addTemp(BcDig* num)
{
+#if BC_ENABLE_LIBRARY
+ BcVm* vm = bcl_getspecific();
+#endif // BC_ENABLE_LIBRARY
+
BC_SIG_ASSERT_LOCKED;
// If we don't have room, just free.
- if (vm.temps_len == BC_VM_MAX_TEMPS) free(num);
+ if (vm->temps_len == BC_VM_MAX_TEMPS) free(num);
else
{
// Add to the buffer and length.
- temps_buf[vm.temps_len] = num;
- vm.temps_len += 1;
+ vm->temps_buf[vm->temps_len] = num;
+ vm->temps_len += 1;
}
}
BcDig*
bc_vm_takeTemp(void)
{
+#if BC_ENABLE_LIBRARY
+ BcVm* vm = bcl_getspecific();
+#endif // BC_ENABLE_LIBRARY
+
BC_SIG_ASSERT_LOCKED;
- if (!vm.temps_len) return NULL;
+ if (!vm->temps_len) return NULL;
- vm.temps_len -= 1;
+ vm->temps_len -= 1;
- return temps_buf[vm.temps_len];
+ return vm->temps_buf[vm->temps_len];
+}
+
+BcDig*
+bc_vm_getTemp(void)
+{
+#if BC_ENABLE_LIBRARY
+ BcVm* vm = bcl_getspecific();
+#endif // BC_ENABLE_LIBRARY
+
+ BC_SIG_ASSERT_LOCKED;
+
+ if (!vm->temps_len) return NULL;
+
+ return vm->temps_buf[vm->temps_len - 1];
}
void
bc_vm_freeTemps(void)
{
size_t i;
+#if BC_ENABLE_LIBRARY
+ BcVm* vm = bcl_getspecific();
+#endif // BC_ENABLE_LIBRARY
BC_SIG_ASSERT_LOCKED;
- if (!vm.temps_len) return;
+ if (!vm->temps_len) return;
// Free them all...
- for (i = 0; i < vm.temps_len; ++i)
+ for (i = 0; i < vm->temps_len; ++i)
{
- free(temps_buf[i]);
+ free(vm->temps_buf[i]);
}
- vm.temps_len = 0;
+ vm->temps_len = 0;
}
inline size_t
bc_vm_arraySize(size_t n, size_t size)
{
size_t res = n * size;
+
if (BC_ERR(BC_VM_MUL_OVERFLOW(n, size, res)))
{
bc_vm_fatalError(BC_ERR_FATAL_ALLOC_ERR);
}
+
return res;
}
@@ -687,10 +751,12 @@ inline size_t
bc_vm_growSize(size_t a, size_t b)
{
size_t res = a + b;
+
if (BC_ERR(res >= SIZE_MAX || res < a))
{
bc_vm_fatalError(BC_ERR_FATAL_ALLOC_ERR);
}
+
return res;
}
@@ -762,15 +828,19 @@ void
bc_vm_printf(const char* fmt, ...)
{
va_list args;
+#if BC_ENABLE_LIBRARY
+ BcVm* vm = bcl_getspecific();
+#else // BC_ENABLE_LIBRARY
sig_atomic_t lock;
+#endif // BC_ENABLE_LIBRARY
BC_SIG_TRYLOCK(lock);
va_start(args, fmt);
- bc_file_vprintf(&vm.fout, fmt, args);
+ bc_file_vprintf(&vm->fout, fmt, args);
va_end(args);
- vm.nchars = 0;
+ vm->nchars = 0;
BC_SIG_TRYUNLOCK(lock);
}
@@ -780,10 +850,11 @@ void
bc_vm_putchar(int c, BcFlushType type)
{
#if BC_ENABLE_LIBRARY
- bc_vec_pushByte(&vm.out, (uchar) c);
+ BcVm* vm = bcl_getspecific();
+ bc_vec_pushByte(&vm->out, (uchar) c);
#else // BC_ENABLE_LIBRARY
- bc_file_putchar(&vm.fout, type, (uchar) c);
- vm.nchars = (c == '\n' ? 0 : vm.nchars + 1);
+ bc_file_putchar(&vm->fout, type, (uchar) c);
+ vm->nchars = (c == '\n' ? 0 : vm->nchars + 1);
#endif // BC_ENABLE_LIBRARY
}
@@ -800,9 +871,9 @@ bc_vm_putchar(int c, BcFlushType type)
BC_NORETURN static void
bc_abortm(const char* msg)
{
- bc_file_puts(&vm.ferr, bc_flush_none, msg);
- bc_file_puts(&vm.ferr, bc_flush_none, "; this is a bug");
- bc_file_flush(&vm.ferr, bc_flush_none);
+ bc_file_puts(&vm->ferr, bc_flush_none, msg);
+ bc_file_puts(&vm->ferr, bc_flush_none, "; this is a bug");
+ bc_file_flush(&vm->ferr, bc_flush_none);
abort();
}
@@ -826,6 +897,7 @@ bc_unveil(const char* path, const char* permissions)
int r = unveil(path, permissions);
if (r) bc_abortm("unveil() failed");
}
+
#endif // BC_ENABLE_EXTRA_MATH
#else // __OpenBSD__
@@ -856,20 +928,20 @@ bc_unveil(const char* path, const char* permissions)
static void
bc_vm_clean(void)
{
- BcVec* fns = &vm.prog.fns;
+ BcVec* fns = &vm->prog.fns;
BcFunc* f = bc_vec_item(fns, BC_PROG_MAIN);
- BcInstPtr* ip = bc_vec_item(&vm.prog.stack, 0);
- bool good = ((vm.status && vm.status != BC_STATUS_QUIT) || vm.sig);
+ BcInstPtr* ip = bc_vec_item(&vm->prog.stack, 0);
+ bool good = ((vm->status && vm->status != BC_STATUS_QUIT) || vm->sig);
BC_SIG_ASSERT_LOCKED;
// If all is good, go ahead and reset.
- if (good) bc_program_reset(&vm.prog);
+ if (good) bc_program_reset(&vm->prog);
#if BC_ENABLED
// bc has this extra condition. If it not satisfied, it is in the middle of
// a parse.
- if (good && BC_IS_BC) good = !BC_PARSE_NO_EXEC(&vm.prs);
+ if (good && BC_IS_BC) good = !BC_PARSE_NO_EXEC(&vm->prs);
#endif // BC_ENABLED
#if DC_ENABLED
@@ -882,9 +954,9 @@ bc_vm_clean(void)
good = true;
- for (i = 0; good && i < vm.prog.results.len; ++i)
+ for (i = 0; good && i < vm->prog.results.len; ++i)
{
- BcResult* r = (BcResult*) bc_vec_item(&vm.prog.results, i);
+ BcResult* r = (BcResult*) bc_vec_item(&vm->prog.results, i);
good = BC_VM_SAFE_RESULT(r);
}
}
@@ -892,7 +964,7 @@ bc_vm_clean(void)
// If this condition is true, we can get rid of strings,
// constants, and code.
- if (good && vm.prog.stack.len == 1 && ip->idx == f->code.len)
+ if (good && vm->prog.stack.len == 1 && ip->idx == f->code.len)
{
#if BC_ENABLED
if (BC_IS_BC)
@@ -904,8 +976,8 @@ bc_vm_clean(void)
// I can't clear out the other_slabs because it has functions,
// consts, strings, vars, and arrays. It has strings from *other*
// functions, specifically.
- bc_slabvec_clear(&vm.main_const_slab);
- bc_slabvec_clear(&vm.main_slabs);
+ bc_slabvec_clear(&vm->main_const_slab);
+ bc_slabvec_clear(&vm->main_slabs);
}
#endif // BC_ENABLED
@@ -913,8 +985,8 @@ bc_vm_clean(void)
// Note to self: you cannot delete strings and functions. Deal with it.
if (BC_IS_DC)
{
- bc_vec_popAll(vm.prog.consts);
- bc_slabvec_clear(&vm.main_const_slab);
+ bc_vec_popAll(vm->prog.consts);
+ bc_slabvec_clear(&vm->main_const_slab);
}
#endif // DC_ENABLED
@@ -935,7 +1007,7 @@ 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, is_exprs);
+ bc_parse_text(&vm->prs, text, is_stdin, is_exprs);
do
{
@@ -944,26 +1016,26 @@ bc_vm_process(const char* text, bool is_stdin, bool is_exprs)
#if BC_ENABLED
// If the first token is the keyword define, then we need to do this
// specially because bc thinks it may not be able to parse.
- if (vm.prs.l.t == BC_LEX_KW_DEFINE) vm.parse(&vm.prs);
+ if (vm->prs.l.t == BC_LEX_KW_DEFINE) vm->parse(&vm->prs);
#endif // BC_ENABLED
// Parse it all.
- while (BC_PARSE_CAN_PARSE(vm.prs))
+ while (BC_PARSE_CAN_PARSE(vm->prs))
{
- vm.parse(&vm.prs);
+ vm->parse(&vm->prs);
}
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);
+ assert(BC_IS_DC || vm->prog.results.len == 0);
// Flush in interactive mode.
- if (BC_I) bc_file_flush(&vm.fout, bc_flush_save);
+ if (BC_I) bc_file_flush(&vm->fout, bc_flush_save);
}
- while (vm.prs.l.t != BC_LEX_EOF);
+ while (vm->prs.l.t != BC_LEX_EOF);
}
#if BC_ENABLED
@@ -977,8 +1049,8 @@ bc_vm_process(const char* text, bool is_stdin, bool is_exprs)
static void
bc_vm_endif(void)
{
- bc_parse_endif(&vm.prs);
- bc_program_exec(&vm.prog);
+ bc_parse_endif(&vm->prs);
+ bc_program_exec(&vm->prog);
}
#endif // BC_ENABLED
@@ -990,11 +1062,14 @@ static void
bc_vm_file(const char* file)
{
char* data = NULL;
+#if BC_ENABLE_LIBRARY
+ BcVm* vm = bcl_getspecific();
+#endif // BC_ENABLE_LIBRARY
- assert(!vm.sig_pop);
+ assert(!vm->sig_pop);
// Set up the lexer.
- bc_lex_file(&vm.prs.l, file);
+ bc_lex_file(&vm->prs.l, file);
BC_SIG_LOCK;
@@ -1003,7 +1078,7 @@ bc_vm_file(const char* file)
assert(data != NULL);
- BC_SETJMP_LOCKED(err);
+ BC_SETJMP_LOCKED(vm, err);
BC_SIG_UNLOCK;
@@ -1016,6 +1091,7 @@ bc_vm_file(const char* file)
#endif // BC_ENABLED
err:
+
BC_SIG_MAYLOCK;
// Cleanup.
@@ -1024,9 +1100,9 @@ err:
// bc_program_reset(), called by bc_vm_clean(), resets the status.
// We want it to clear the sig_pop variable in case it was set.
- if (vm.status == (sig_atomic_t) BC_STATUS_SUCCESS) BC_LONGJMP_STOP;
+ if (vm->status == (sig_atomic_t) BC_STATUS_SUCCESS) BC_LONGJMP_STOP;
- BC_LONGJMP_CONT;
+ BC_LONGJMP_CONT(vm);
}
bool
@@ -1038,27 +1114,27 @@ bc_vm_readLine(bool clear)
BC_SIG_ASSERT_NOT_LOCKED;
// Clear the buffer if desired.
- if (clear) bc_vec_empty(&vm.buffer);
+ if (clear) bc_vec_empty(&vm->buffer);
// Empty the line buffer.
- bc_vec_empty(&vm.line_buf);
+ bc_vec_empty(&vm->line_buf);
- if (vm.eof) return false;
+ if (vm->eof) return false;
do
{
// bc_read_line() must always return either BC_STATUS_SUCCESS or
// BC_STATUS_EOF. Everything else, it and whatever it calls, must jump
// out instead.
- s = bc_read_line(&vm.line_buf, ">>> ");
- vm.eof = (s == BC_STATUS_EOF);
+ s = bc_read_line(&vm->line_buf, ">>> ");
+ vm->eof = (s == BC_STATUS_EOF);
}
- while (!(s) && !vm.eof && vm.line_buf.len < 1);
+ while (!(s) && !vm->eof && vm->line_buf.len < 1);
- good = (vm.line_buf.len > 1);
+ good = (vm->line_buf.len > 1);
// Concat if we found something.
- if (good) bc_vec_concat(&vm.buffer, vm.line_buf.v);
+ if (good) bc_vec_concat(&vm->buffer, vm->line_buf.v);
return good;
}
@@ -1069,25 +1145,28 @@ bc_vm_readLine(bool clear)
static void
bc_vm_stdin(void)
{
- bool clear = true;
+#if BC_ENABLE_LIBRARY
+ BcVm* vm = bcl_getspecific();
+#endif // BC_ENABLE_LIBRARY
- vm.is_stdin = true;
+ vm->clear = true;
+ vm->is_stdin = true;
// Set up the lexer.
- bc_lex_file(&vm.prs.l, bc_program_stdin_name);
+ bc_lex_file(&vm->prs.l, bc_program_stdin_name);
// 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
+ // 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);
- BC_SETJMP_LOCKED(err);
+ bc_vec_init(&vm->buffer, sizeof(uchar), BC_DTOR_NONE);
+ bc_vec_init(&vm->line_buf, sizeof(uchar), BC_DTOR_NONE);
+ BC_SETJMP_LOCKED(vm, err);
BC_SIG_UNLOCK;
// This label exists because errors can cause jumps to end up at the err label
@@ -1096,20 +1175,20 @@ bc_vm_stdin(void)
restart:
// While we still read data from stdin.
- while (bc_vm_readLine(clear))
+ while (bc_vm_readLine(vm->clear))
{
- size_t len = vm.buffer.len - 1;
- const char* str = vm.buffer.v;
+ 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;
+ vm->clear = (len < 2 || str[len - 2] != '\\' || str[len - 1] != '\n');
+ if (!vm->clear) continue;
// Process the data.
- bc_vm_process(vm.buffer.v, true, false);
+ bc_vm_process(vm->buffer.v, true, false);
- if (vm.eof) break;
+ if (vm->eof) break;
else
{
BC_SIG_LOCK;
@@ -1131,20 +1210,20 @@ err:
bc_vm_clean();
#if !BC_ENABLE_MEMCHECK
- assert(vm.status != BC_STATUS_ERROR_FATAL);
+ assert(vm->status != BC_STATUS_ERROR_FATAL);
- vm.status = vm.status == BC_STATUS_QUIT || !BC_I ? vm.status :
- BC_STATUS_SUCCESS;
+ vm->status = vm->status == BC_STATUS_QUIT || !BC_I ? vm->status :
+ BC_STATUS_SUCCESS;
#else // !BC_ENABLE_MEMCHECK
- vm.status = vm.status == BC_STATUS_ERROR_FATAL ||
- vm.status == BC_STATUS_QUIT || !BC_I ?
- vm.status :
- BC_STATUS_SUCCESS;
+ vm->status = vm->status == BC_STATUS_ERROR_FATAL ||
+ vm->status == BC_STATUS_QUIT || !BC_I ?
+ vm->status :
+ BC_STATUS_SUCCESS;
#endif // !BC_ENABLE_MEMCHECK
- if (!vm.status && !vm.eof)
+ if (!vm->status && !vm->eof)
{
- bc_vec_empty(&vm.buffer);
+ bc_vec_empty(&vm->buffer);
BC_LONGJMP_STOP;
BC_SIG_UNLOCK;
goto restart;
@@ -1153,31 +1232,31 @@ err:
#ifndef NDEBUG
// 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);
+ bc_vec_free(&vm->line_buf);
+ bc_vec_free(&vm->buffer);
#endif // NDEBUG
- BC_LONGJMP_CONT;
+ BC_LONGJMP_CONT(vm);
}
bool
bc_vm_readBuf(bool clear)
{
- size_t len = vm.exprs.len - 1;
+ 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);
+ 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);
+ 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');
+ more = bc_read_buf(&vm->buffer, vm->exprs.v, &len);
+ bc_vec_pushByte(&vm->buffer, '\0');
return more;
}
@@ -1185,37 +1264,41 @@ bc_vm_readBuf(bool clear)
static void
bc_vm_exprs(void)
{
- bool clear = true;
+#if BC_ENABLE_LIBRARY
+ BcVm* vm = bcl_getspecific();
+#endif // BC_ENABLE_LIBRARY
+
+ vm->clear = true;
// Prepare the lexer.
- bc_lex_file(&vm.prs.l, bc_program_exprs_name);
+ 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
+ // 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_vec_init(&vm->buffer, sizeof(uchar), BC_DTOR_NONE);
+ BC_SETJMP_LOCKED(vm, err);
BC_SIG_UNLOCK;
- while (bc_vm_readBuf(clear))
+ while (bc_vm_readBuf(vm->clear))
{
- size_t len = vm.buffer.len - 1;
- const char* str = vm.buffer.v;
+ 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;
+ vm->clear = (len < 2 || str[len - 2] != '\\' || str[len - 1] != '\n');
+ if (!vm->clear) continue;
// Process the data.
- bc_vm_process(vm.buffer.v, false, true);
+ 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);
+ if (!vm->clear) bc_vm_process(vm->buffer.v, false, true);
err:
@@ -1224,11 +1307,15 @@ err:
// Cleanup.
bc_vm_clean();
+ // bc_program_reset(), called by bc_vm_clean(), resets the status.
+ // We want it to clear the sig_pop variable in case it was set.
+ if (vm->status == (sig_atomic_t) BC_STATUS_SUCCESS) BC_LONGJMP_STOP;
+
// 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_vec_free(&vm->buffer);
- BC_LONGJMP_CONT;
+ BC_LONGJMP_CONT(vm);
}
#if BC_ENABLED
@@ -1241,14 +1328,14 @@ 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, false);
+ bc_lex_file(&vm->prs.l, name);
+ bc_parse_text(&vm->prs, text, false, false);
BC_SIG_LOCK;
- while (vm.prs.l.t != BC_LEX_EOF)
+ while (vm->prs.l.t != BC_LEX_EOF)
{
- vm.parse(&vm.prs);
+ vm->parse(&vm->prs);
}
BC_SIG_UNLOCK;
@@ -1264,18 +1351,18 @@ bc_vm_defaultMsgs(void)
{
size_t i;
- vm.func_header = bc_err_func_header;
+ vm->func_header = bc_err_func_header;
// Load the error categories.
for (i = 0; i < BC_ERR_IDX_NELEMS + BC_ENABLED; ++i)
{
- vm.err_ids[i] = bc_errs[i];
+ vm->err_ids[i] = bc_errs[i];
}
// Load the error messages.
for (i = 0; i < BC_ERR_NELEMS; ++i)
{
- vm.err_msgs[i] = bc_err_msgs[i];
+ vm->err_msgs[i] = bc_err_msgs[i];
}
}
@@ -1292,29 +1379,29 @@ bc_vm_gettext(void)
size_t i;
// If no locale, load the defaults.
- if (vm.locale == NULL)
+ if (vm->locale == NULL)
{
- vm.catalog = BC_VM_INVALID_CATALOG;
+ vm->catalog = BC_VM_INVALID_CATALOG;
bc_vm_defaultMsgs();
return;
}
- vm.catalog = catopen(BC_MAINEXEC, NL_CAT_LOCALE);
+ vm->catalog = catopen(BC_MAINEXEC, NL_CAT_LOCALE);
// If no catalog, load the defaults.
- if (vm.catalog == BC_VM_INVALID_CATALOG)
+ if (vm->catalog == BC_VM_INVALID_CATALOG)
{
bc_vm_defaultMsgs();
return;
}
// Load the function header.
- vm.func_header = catgets(vm.catalog, set, msg, bc_err_func_header);
+ vm->func_header = catgets(vm->catalog, set, msg, bc_err_func_header);
// Load the error categories.
for (set += 1; msg <= BC_ERR_IDX_NELEMS + BC_ENABLED; ++msg)
{
- vm.err_ids[msg - 1] = catgets(vm.catalog, set, msg, bc_errs[msg - 1]);
+ vm->err_ids[msg - 1] = catgets(vm->catalog, set, msg, bc_errs[msg - 1]);
}
i = 0;
@@ -1331,7 +1418,7 @@ bc_vm_gettext(void)
set = id + 3;
}
- vm.err_msgs[i] = catgets(vm.catalog, set, msg, bc_err_msgs[i]);
+ vm->err_msgs[i] = catgets(vm->catalog, set, msg, bc_err_msgs[i]);
}
#else // BC_ENABLE_NLS
bc_vm_defaultMsgs();
@@ -1347,14 +1434,16 @@ static void
bc_vm_exec(void)
{
size_t i;
+#if DC_ENABLED
bool has_file = false;
+#endif // DC_ENABLED
#if BC_ENABLED
// Load the math libraries.
- if (BC_IS_BC && (vm.flags & BC_FLAG_L))
+ if (BC_IS_BC && (vm->flags & BC_FLAG_L))
{
// Can't allow redefinitions in the builtin library.
- vm.no_redefine = true;
+ vm->no_redefine = true;
bc_vm_load(bc_lib_name, bc_lib);
@@ -1363,30 +1452,32 @@ bc_vm_exec(void)
#endif // BC_ENABLE_EXTRA_MATH
// Make sure to clear this.
- vm.no_redefine = false;
+ vm->no_redefine = false;
// Execute to ensure that all is hunky dory. Without this, scale can be
// set improperly.
- bc_program_exec(&vm.prog);
+ bc_program_exec(&vm->prog);
}
#endif // BC_ENABLED
// If there are expressions to execute...
- if (vm.exprs.len)
+ if (vm->exprs.len)
{
// 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;
+ if (!vm->no_exprs && vm->exit_exprs && BC_EXPR_EXIT) return;
}
// Process files.
- for (i = 0; i < vm.files.len; ++i)
+ for (i = 0; i < vm->files.len; ++i)
{
- char* path = *((char**) bc_vec_item(&vm.files, i));
+ char* path = *((char**) bc_vec_item(&vm->files, i));
if (!strcmp(path, "")) continue;
+#if DC_ENABLED
has_file = true;
+#endif // DC_ENABLED
bc_vm_file(path);
}
@@ -1401,7 +1492,7 @@ bc_vm_exec(void)
// We need to keep tty if history is enabled, and we need to keep rpath for
// the times when we read from /dev/urandom.
- if (BC_TTY && !vm.history.badTerm) bc_pledge(bc_pledge_end_history, NULL);
+ if (BC_TTY && !vm->history.badTerm) bc_pledge(bc_pledge_end_history, NULL);
else
#endif // BC_ENABLE_HISTORY
{
@@ -1417,7 +1508,7 @@ bc_vm_exec(void)
#endif // BC_ENABLE_AFL
// Execute from stdin. bc always does.
- if (BC_IS_BC || !has_file) bc_vm_stdin();
+ if (BC_VM_RUN_STDIN(has_file)) bc_vm_stdin();
}
void
@@ -1425,10 +1516,18 @@ bc_vm_boot(int argc, char* argv[])
{
int ttyin, ttyout, ttyerr;
bool tty;
- const char* const env_len = BC_IS_BC ? "BC_LINE_LENGTH" : "DC_LINE_LENGTH";
- const char* const env_args = BC_IS_BC ? "BC_ENV_ARGS" : "DC_ENV_ARGS";
- const char* const env_exit = BC_IS_BC ? "BC_EXPR_EXIT" : "DC_EXPR_EXIT";
- int env_exit_def = BC_IS_BC ? BC_DEFAULT_EXPR_EXIT : DC_DEFAULT_EXPR_EXIT;
+ const char* const env_len = BC_VM_LINE_LENGTH_STR;
+ const char* const env_args = BC_VM_ENV_ARGS_STR;
+ const char* const env_exit = BC_VM_EXPR_EXIT_STR;
+ const char* const env_clamp = BC_VM_DIGIT_CLAMP_STR;
+ int env_exit_def = BC_VM_EXPR_EXIT_DEF;
+ int env_clamp_def = BC_VM_DIGIT_CLAMP_DEF;
+ BcBigDig scale = BC_NUM_BIGDIG_MAX;
+ BcBigDig env_scale = BC_NUM_BIGDIG_MAX;
+ BcBigDig ibase = BC_NUM_BIGDIG_MAX;
+ BcBigDig env_ibase = BC_NUM_BIGDIG_MAX;
+ BcBigDig obase = BC_NUM_BIGDIG_MAX;
+ BcBigDig env_obase = BC_NUM_BIGDIG_MAX;
// We need to know which of stdin, stdout, and stderr are tty's.
ttyin = isatty(STDIN_FILENO);
@@ -1436,9 +1535,9 @@ bc_vm_boot(int argc, char* argv[])
ttyerr = isatty(STDERR_FILENO);
tty = (ttyin != 0 && ttyout != 0 && ttyerr != 0);
- vm.flags |= ttyin ? BC_FLAG_TTYIN : 0;
- vm.flags |= tty ? BC_FLAG_TTY : 0;
- vm.flags |= ttyin && ttyout ? BC_FLAG_I : 0;
+ vm->flags |= ttyin ? BC_FLAG_TTYIN : 0;
+ vm->flags |= tty ? BC_FLAG_TTY : 0;
+ vm->flags |= ttyin && ttyout ? BC_FLAG_I : 0;
// Set up signals.
bc_vm_sigaction();
@@ -1448,58 +1547,59 @@ bc_vm_boot(int argc, char* argv[])
bc_vm_init();
// Explicitly set this in case NULL isn't all zeroes.
- vm.file = NULL;
+ vm->file = NULL;
// Set the error messages.
bc_vm_gettext();
#if BC_ENABLE_LINE_LIB
// Initialize the output file buffers.
- bc_file_init(&vm.ferr, stderr);
- bc_file_init(&vm.fout, stdout);
+ bc_file_init(&vm->ferr, stderr);
+ bc_file_init(&vm->fout, stdout);
// Set the input buffer.
- vm.buf = output_bufs;
+ vm->buf = output_bufs;
#else // BC_ENABLE_LINE_LIB
// Initialize the output file buffers. They each take portions of the global
// buffer. stdout gets more because it will probably have more data.
- bc_file_init(&vm.ferr, STDERR_FILENO, output_bufs + BC_VM_STDOUT_BUF_SIZE,
+ bc_file_init(&vm->ferr, STDERR_FILENO, output_bufs + BC_VM_STDOUT_BUF_SIZE,
BC_VM_STDERR_BUF_SIZE);
- bc_file_init(&vm.fout, STDOUT_FILENO, output_bufs, BC_VM_STDOUT_BUF_SIZE);
+ bc_file_init(&vm->fout, STDOUT_FILENO, output_bufs, BC_VM_STDOUT_BUF_SIZE);
// Set the input buffer to the rest of the global buffer.
- vm.buf = output_bufs + BC_VM_STDOUT_BUF_SIZE + BC_VM_STDERR_BUF_SIZE;
+ vm->buf = output_bufs + BC_VM_STDOUT_BUF_SIZE + BC_VM_STDERR_BUF_SIZE;
#endif // BC_ENABLE_LINE_LIB
// Set the line length by environment variable.
- vm.line_len = (uint16_t) bc_vm_envLen(env_len);
+ vm->line_len = (uint16_t) bc_vm_envLen(env_len);
bc_vm_setenvFlag(env_exit, env_exit_def, BC_FLAG_EXPR_EXIT);
+ bc_vm_setenvFlag(env_clamp, env_clamp_def, BC_FLAG_DIGIT_CLAMP);
// Clear the files and expressions vectors, just in case. This marks them as
// *not* allocated.
- bc_vec_clear(&vm.files);
- bc_vec_clear(&vm.exprs);
+ bc_vec_clear(&vm->files);
+ bc_vec_clear(&vm->exprs);
#if !BC_ENABLE_LIBRARY
// Initialize the slab vectors.
- bc_slabvec_init(&vm.main_const_slab);
- bc_slabvec_init(&vm.main_slabs);
- bc_slabvec_init(&vm.other_slabs);
+ bc_slabvec_init(&vm->main_const_slab);
+ bc_slabvec_init(&vm->main_slabs);
+ bc_slabvec_init(&vm->other_slabs);
#endif // !BC_ENABLE_LIBRARY
// Initialize the program and main parser. These have to be in this order
// because the program has to be initialized first, since a pointer to it is
// passed to the parser.
- bc_program_init(&vm.prog);
- bc_parse_init(&vm.prs, &vm.prog, BC_PROG_MAIN);
+ bc_program_init(&vm->prog);
+ bc_parse_init(&vm->prs, &vm->prog, BC_PROG_MAIN);
// Set defaults.
- vm.flags |= BC_TTY ? BC_FLAG_P | BC_FLAG_R : 0;
- vm.flags |= BC_I ? BC_FLAG_Q : 0;
+ vm->flags |= BC_TTY ? BC_FLAG_P | BC_FLAG_R : 0;
+ vm->flags |= BC_I ? BC_FLAG_Q : 0;
#if BC_ENABLED
if (BC_IS_BC)
@@ -1508,7 +1608,7 @@ bc_vm_boot(int argc, char* argv[])
// standard mode.
char* var = bc_vm_getenv("POSIXLY_CORRECT");
- vm.flags |= BC_FLAG_S * (var != NULL);
+ vm->flags |= BC_FLAG_S * (var != NULL);
bc_vm_getenvFree(var);
// Set whether we print the banner or not.
@@ -1519,10 +1619,10 @@ bc_vm_boot(int argc, char* argv[])
// Are we in TTY mode?
if (BC_TTY)
{
- const char* const env_tty = BC_IS_BC ? "BC_TTY_MODE" : "DC_TTY_MODE";
- int env_tty_def = BC_IS_BC ? BC_DEFAULT_TTY_MODE : DC_DEFAULT_TTY_MODE;
- const char* const env_prompt = BC_IS_BC ? "BC_PROMPT" : "DC_PROMPT";
- int env_prompt_def = BC_IS_BC ? BC_DEFAULT_PROMPT : DC_DEFAULT_PROMPT;
+ const char* const env_tty = BC_VM_TTY_MODE_STR;
+ int env_tty_def = BC_VM_TTY_MODE_DEF;
+ const char* const env_prompt = BC_VM_PROMPT_STR;
+ int env_prompt_def = BC_VM_PROMPT_DEF;
// Set flags for TTY mode and prompt.
bc_vm_setenvFlag(env_tty, env_tty_def, BC_FLAG_TTY);
@@ -1530,21 +1630,52 @@ bc_vm_boot(int argc, char* argv[])
#if BC_ENABLE_HISTORY
// If TTY mode is used, activate history.
- if (BC_TTY) bc_history_init(&vm.history);
+ if (BC_TTY) bc_history_init(&vm->history);
#endif // BC_ENABLE_HISTORY
}
// Process environment and command-line arguments.
- bc_vm_envArgs(env_args);
- bc_args(argc, argv, true, BC_PROG_SCALE(&vm.prog));
+ bc_vm_envArgs(env_args, &env_scale, &env_ibase, &env_obase);
+ bc_args(argc, argv, true, &scale, &ibase, &obase);
+
+ // This section is here because we don't want the math library to stomp on
+ // the user's given value for scale. And we don't want ibase affecting how
+ // the scale is interpreted. Also, it's sectioned off just for this comment.
+ {
+ BC_SIG_UNLOCK;
+
+ scale = scale == BC_NUM_BIGDIG_MAX ? env_scale : scale;
+#if BC_ENABLED
+ // Assign the library value only if it is used and no value was set.
+ scale = scale == BC_NUM_BIGDIG_MAX && BC_L ? 20 : scale;
+#endif // BC_ENABLED
+ obase = obase == BC_NUM_BIGDIG_MAX ? env_obase : obase;
+ ibase = ibase == BC_NUM_BIGDIG_MAX ? env_ibase : ibase;
+
+ if (scale != BC_NUM_BIGDIG_MAX)
+ {
+ bc_program_assignBuiltin(&vm->prog, true, false, scale);
+ }
+
+ if (obase != BC_NUM_BIGDIG_MAX)
+ {
+ bc_program_assignBuiltin(&vm->prog, false, true, obase);
+ }
+
+ // This is last to avoid it affecting the value of the others.
+ if (ibase != BC_NUM_BIGDIG_MAX)
+ {
+ bc_program_assignBuiltin(&vm->prog, false, false, ibase);
+ }
+
+ BC_SIG_LOCK;
+ }
// If we are in interactive mode...
if (BC_I)
{
- const char* const env_sigint = BC_IS_BC ? "BC_SIGINT_RESET" :
- "DC_SIGINT_RESET";
- int env_sigint_def = BC_IS_BC ? BC_DEFAULT_SIGINT_RESET :
- DC_DEFAULT_SIGINT_RESET;
+ const char* const env_sigint = BC_VM_SIGINT_RESET_STR;
+ int env_sigint_def = BC_VM_SIGINT_RESET_DEF;
// Set whether we reset on SIGINT or not.
bc_vm_setenvFlag(env_sigint, env_sigint_def, BC_FLAG_SIGINT);
@@ -1552,15 +1683,15 @@ bc_vm_boot(int argc, char* argv[])
#if BC_ENABLED
// Disable global stacks in POSIX mode.
- if (BC_IS_POSIX) vm.flags &= ~(BC_FLAG_G);
+ if (BC_IS_POSIX) vm->flags &= ~(BC_FLAG_G);
// Print the banner if allowed. We have to be in bc, in interactive mode,
// and not be quieted by command-line option or environment variable.
- if (BC_IS_BC && BC_I && (vm.flags & BC_FLAG_Q))
+ if (BC_IS_BC && BC_I && (vm->flags & BC_FLAG_Q))
{
bc_vm_info(NULL);
- bc_file_putchar(&vm.fout, bc_flush_none, '\n');
- bc_file_flush(&vm.fout, bc_flush_none);
+ bc_file_putchar(&vm->fout, bc_flush_none, '\n');
+ bc_file_flush(&vm->fout, bc_flush_none);
}
#endif // BC_ENABLED
@@ -1574,35 +1705,40 @@ bc_vm_boot(int argc, char* argv[])
void
bc_vm_init(void)
{
+#if BC_ENABLE_LIBRARY
+ BcVm* vm = bcl_getspecific();
+#endif // BC_ENABLE_LIBRARY
+
BC_SIG_ASSERT_LOCKED;
#if !BC_ENABLE_LIBRARY
// Set up the constant zero.
- bc_num_setup(&vm.zero, vm.zero_num, BC_VM_ONE_CAP);
+ bc_num_setup(&vm->zero, vm->zero_num, BC_VM_ONE_CAP);
#endif // !BC_ENABLE_LIBRARY
// Set up more constant BcNum's.
- bc_num_setup(&vm.one, vm.one_num, BC_VM_ONE_CAP);
- bc_num_one(&vm.one);
+ bc_num_setup(&vm->one, vm->one_num, BC_VM_ONE_CAP);
+ bc_num_one(&vm->one);
// Set up more constant BcNum's.
// NOLINTNEXTLINE
- memcpy(vm.max_num, bc_num_bigdigMax, bc_num_bigdigMax_size * sizeof(BcDig));
+ memcpy(vm->max_num, bc_num_bigdigMax,
+ bc_num_bigdigMax_size * sizeof(BcDig));
// NOLINTNEXTLINE
- memcpy(vm.max2_num, bc_num_bigdigMax2,
+ memcpy(vm->max2_num, bc_num_bigdigMax2,
bc_num_bigdigMax2_size * sizeof(BcDig));
- bc_num_setup(&vm.max, vm.max_num, BC_NUM_BIGDIG_LOG10);
- bc_num_setup(&vm.max2, vm.max2_num, BC_NUM_BIGDIG_LOG10);
- vm.max.len = bc_num_bigdigMax_size;
- vm.max2.len = bc_num_bigdigMax2_size;
+ bc_num_setup(&vm->max, vm->max_num, BC_NUM_BIGDIG_LOG10);
+ bc_num_setup(&vm->max2, vm->max2_num, BC_NUM_BIGDIG_LOG10);
+ vm->max.len = bc_num_bigdigMax_size;
+ vm->max2.len = bc_num_bigdigMax2_size;
// Set up the maxes for the globals.
- vm.maxes[BC_PROG_GLOBALS_IBASE] = BC_NUM_MAX_POSIX_IBASE;
- vm.maxes[BC_PROG_GLOBALS_OBASE] = BC_MAX_OBASE;
- vm.maxes[BC_PROG_GLOBALS_SCALE] = BC_MAX_SCALE;
+ vm->maxes[BC_PROG_GLOBALS_IBASE] = BC_NUM_MAX_POSIX_IBASE;
+ vm->maxes[BC_PROG_GLOBALS_OBASE] = BC_MAX_OBASE;
+ vm->maxes[BC_PROG_GLOBALS_SCALE] = BC_MAX_SCALE;
#if BC_ENABLE_EXTRA_MATH
- vm.maxes[BC_PROG_MAX_RAND] = ((BcRand) 0) - 1;
+ vm->maxes[BC_PROG_MAX_RAND] = ((BcRand) 0) - 1;
#endif // BC_ENABLE_EXTRA_MATH
#if BC_ENABLED
@@ -1611,7 +1747,7 @@ bc_vm_init(void)
if (BC_IS_BC && !BC_IS_POSIX)
#endif // !BC_ENABLE_LIBRARY
{
- vm.maxes[BC_PROG_GLOBALS_IBASE] = BC_NUM_MAX_IBASE;
+ vm->maxes[BC_PROG_GLOBALS_IBASE] = BC_NUM_MAX_IBASE;
}
#endif // BC_ENABLED
}
@@ -1620,10 +1756,16 @@ bc_vm_init(void)
void
bc_vm_atexit(void)
{
+#ifndef NDEBUG
+#if BC_ENABLE_LIBRARY
+ BcVm* vm = bcl_getspecific();
+#endif // BC_ENABLE_LIBRARY
+#endif // NDEBUG
+
bc_vm_shutdown();
#ifndef NDEBUG
- bc_vec_free(&vm.jmp_bufs);
+ bc_vec_free(&vm->jmp_bufs);
#endif // NDEBUG
}
#else // BC_ENABLE_LIBRARY
@@ -1636,7 +1778,7 @@ bc_vm_atexit(int status)
bc_vm_shutdown();
#ifndef NDEBUG
- bc_vec_free(&vm.jmp_bufs);
+ bc_vec_free(&vm->jmp_bufs);
#endif // NDEBUG
return s;
diff --git a/tests/all.sh b/tests/all.sh
index d3e79ef80ece..76f2ac10ba1e 100755
--- a/tests/all.sh
+++ b/tests/all.sh
@@ -49,7 +49,7 @@ if [ "$#" -ge 1 ]; then
d="$1"
shift
else
- err_exit "usage: $script [-n] dir [run_extra_tests] [run_stack_tests] [gen_tests] [time_tests] [exec args...]" 1
+ err_exit "usage: $script [-n] dir [run_extra_tests] [run_stack_tests] [gen_tests] [run_problematic_tests] [time_tests] [exec args...]" 1
fi
if [ "$#" -lt 1 ]; then
@@ -74,6 +74,13 @@ else
fi
if [ "$#" -lt 1 ]; then
+ problematic_tests=1
+else
+ problematic_tests="$1"
+ shift
+fi
+
+if [ "$#" -lt 1 ]; then
time_tests=0
else
time_tests="$1"
@@ -172,10 +179,10 @@ for testfile in $testdir/$d/errors/*.txt; do
b=$(basename "$testfile")
if [ "$pll" -ne 0 ]; then
- sh "$testdir/error.sh" "$d" "$b" "$@" &
+ sh "$testdir/error.sh" "$d" "$b" "$problematic_tests" "$@" &
pids="$pids $!"
else
- sh "$testdir/error.sh" "$d" "$b" "$@"
+ sh "$testdir/error.sh" "$d" "$b" "$problematic_tests" "$@"
fi
done
diff --git a/tests/bc/errors/33.txt b/tests/bc/errors/33.txt
new file mode 100644
index 000000000000..a16568bb2d98
--- /dev/null
+++ b/tests/bc/errors/33.txt
@@ -0,0 +1,2 @@
+pi(NNNNNNNNNNNN80)
+d?r(9180)
diff --git a/tests/bcl.c b/tests/bcl.c
index 6f462ce9dc4f..2de7d74c06f5 100644
--- a/tests/bcl.c
+++ b/tests/bcl.c
@@ -59,6 +59,9 @@ main(void)
char* res;
BclBigDig b = 0;
+ e = bcl_start();
+ err(e);
+
// We do this twice to test the reference counting code.
e = bcl_init();
err(e);
@@ -335,5 +338,7 @@ main(void)
bcl_free();
+ bcl_end();
+
return 0;
}
diff --git a/tests/dc/scripts/all.txt b/tests/dc/scripts/all.txt
index e15dae5e15ff..58c6d295bb2d 100644
--- a/tests/dc/scripts/all.txt
+++ b/tests/dc/scripts/all.txt
@@ -7,3 +7,4 @@ factorial.dc
loop.dc
quit.dc
weird.dc
+no_clamp.dc
diff --git a/tests/dc/scripts/no_clamp.dc b/tests/dc/scripts/no_clamp.dc
new file mode 100644
index 000000000000..bad184a54401
--- /dev/null
+++ b/tests/dc/scripts/no_clamp.dc
@@ -0,0 +1,29 @@
+Ip
+Ap
+A0p
+AAp
+AA0p
+Fp
+F0p
+FFp
+FF0p
+47FBFE71026C816CDD99EDC9237F65023488025022006E79F92017CBA906P
+2iIp
+Ap
+A0p
+AAp
+ABp
+3iIp
+Ap
+A0p
+ABp
+AB0p
+ABBp
+5iIp
+Bp
+B0p
+BCp
+BC0p
+BCDp
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFp
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFp
diff --git a/tests/dc/scripts/no_clamp.txt b/tests/dc/scripts/no_clamp.txt
new file mode 100644
index 000000000000..c8b680be10aa
--- /dev/null
+++ b/tests/dc/scripts/no_clamp.txt
@@ -0,0 +1,29 @@
+10
+10
+100
+110
+1100
+15
+150
+165
+1650
+Mwhuaaahahahahahhaaaa...
+2
+10
+20
+30
+31
+3
+10
+30
+41
+123
+134
+5
+11
+55
+67
+335
+348
+54569682106375694274902340
+794093388050906567876552344387164339423179626464840
diff --git a/tests/error.sh b/tests/error.sh
index c76dcdf113dd..b9c5bbe3be6e 100755
--- a/tests/error.sh
+++ b/tests/error.sh
@@ -36,14 +36,21 @@ outputdir=${BC_TEST_OUTPUT_DIR:-$testdir}
# Command-line processing.
if [ "$#" -lt 2 ]; then
- printf 'usage: %s dir test [exec args...]\n' "$script"
+
+ printf 'usage: %s dir test problematic_tests [exec args...]\n' "$script"
exit 1
+
else
+
d="$1"
shift
t="$1"
shift
+
+ problematic="$1"
+ shift
+
fi
if [ "$#" -lt 1 ]; then
@@ -53,6 +60,15 @@ else
shift
fi
+# Just skip tests that are problematic on FreeBSD. These tests can cause FreeBSD
+# to kill bc from memory exhaustion because of overcommit.
+if [ "$d" = "bc" ] && [ "$problematic" -eq 0 ]; then
+ if [ "$t" = "33.txt" ]; then
+ printf 'Skipping problematic %s error file %s...\n' "$d" "$t"
+ exit 0
+ fi
+fi
+
# I use these, so unset them to make the tests work.
unset BC_ENV_ARGS
unset BC_LINE_LENGTH
@@ -80,20 +96,38 @@ fi
testfile="$testdir/$d/errors/$t"
-printf 'Running %s error file %s...' "$d" "$t"
+printf 'Running %s error file %s with clamping...' "$d" "$t"
-printf '%s\n' "$halt" | "$exe" "$@" $opts "$testfile" 2> "$out" > /dev/null
+printf '%s\n' "$halt" | "$exe" "$@" $opts -c "$testfile" 2> "$out" > /dev/null
err="$?"
checkerrtest "$d" "$err" "$testfile" "$out" "$exebase" > /dev/null
printf 'pass\n'
-printf 'Running %s error file %s through cat...' "$d" "$t"
+printf 'Running %s error file %s without clamping...' "$d" "$t"
+
+printf '%s\n' "$halt" | "$exe" "$@" $opts -C "$testfile" 2> "$out" > /dev/null
+err="$?"
+
+checkerrtest "$d" "$err" "$testfile" "$out" "$exebase" > /dev/null
+
+printf 'pass\n'
+
+printf 'Running %s error file %s through cat with clamping...' "$d" "$t"
+
+cat "$testfile" | "$exe" "$@" $opts -c 2> "$out" > /dev/null
+err="$?"
+
+checkerrtest "$d" "$err" "$testfile" "$out" "$exebase"
+
+printf 'pass\n'
+
+printf 'Running %s error file %s through cat without clamping...' "$d" "$t"
-cat "$testfile" | "$exe" "$@" $opts 2> "$out" > /dev/null
+cat "$testfile" | "$exe" "$@" $opts -C 2> "$out" > /dev/null
err="$?"
-checkcrash "$d" "$err" "$testfile"
+checkerrtest "$d" "$err" "$testfile" "$out" "$exebase"
printf 'pass\n'
diff --git a/tests/other.sh b/tests/other.sh
index 4e277059a32c..41c5f78e2b40 100755
--- a/tests/other.sh
+++ b/tests/other.sh
@@ -131,7 +131,7 @@ if [ "$d" = "bc" ]; then
checktest_retcode "$d" "$?" "environment var"
- "$exe" "$@" -e 4 > /dev/null
+ printf 'halt\n' | "$exe" "$@" -e 4 > /dev/null
err="$?"
checktest_retcode "$d" "$?" "environment var"
@@ -153,19 +153,19 @@ if [ "$d" = "bc" ]; then
printf '5\n0\n' > "$redefine_res"
- "$exe" "$@" --redefine=print -e 'define print(x) { x }' -e 'print(5)' > "$redefine_out"
+ printf 'halt\n' | "$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"
+ printf 'halt\n' | "$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"
+ printf 'halt\n' | "$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"
@@ -189,7 +189,7 @@ if [ "$d" = "bc" ]; then
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"
+ printf 'halt\n' | "$exe" "$@" -f "$testdir/bc/misc1.txt" > "$multiline_expr_out"
err="$?"
checktest "$d" "$err" "multiline comment in expression file" "$testdir/bc/misc1_results.txt" \
@@ -198,7 +198,7 @@ if [ "$d" = "bc" ]; then
printf 'pass\n'
printf 'Running multiline comment expression file error test...'
- "$exe" "$@" -f "$testdir/bc/errors/05.txt" 2> "$multiline_expr_out"
+ printf 'halt\n' | "$exe" "$@" -f "$testdir/bc/errors/05.txt" 2> "$multiline_expr_out"
err="$?"
checkerrtest "$d" "$err" "multiline comment in expression file error" \
@@ -208,7 +208,7 @@ if [ "$d" = "bc" ]; then
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"
+ printf 'halt\n' | "$exe" "$@" -f "$testdir/bc/strings.txt" > "$multiline_expr_out"
err="$?"
checktest "$d" "$err" "multiline string in expression file" "$testdir/bc/strings_results.txt" \
@@ -217,13 +217,13 @@ if [ "$d" = "bc" ]; then
printf 'pass\n'
printf 'Running multiline string expression file error test...'
- "$exe" "$@" -f "$testdir/bc/errors/16.txt" 2> "$multiline_expr_out"
+ printf 'halt\n' | "$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"
+ printf 'halt\n' | "$exe" "$@" -f "$testdir/bc/errors/04.txt" 2> "$multiline_expr_out"
err="$?"
checkerrtest "$d" "$err" "multiline string in expression file error" \
@@ -456,6 +456,37 @@ else
fi
+if [ "$d" = "bc" ]; then
+
+ out=$(printf '100\n')
+ printf '%s\n' "$out" > "$out1"
+
+ printf 'scale\n' | "$exe" "$@" -S100 -l > "$out2"
+ checktest "$d" "$?" "builtin variable args with math lib" "$out1" "$out2"
+
+ printf 'scale\n' | "$exe" "$@" --scale=100 --mathlib > "$out2"
+ checktest "$d" "$?" "builtin variable long args with math lib" "$out1" "$out2"
+
+ export BC_ENV_ARGS="-l"
+
+ printf 'scale\n' | "$exe" "$@" -S100 > "$out2"
+ checktest "$d" "$?" "builtin variable args with math lib env arg" "$out1" "$out2"
+
+ printf 'scale\n' | "$exe" "$@" --scale=100 > "$out2"
+ checktest "$d" "$?" "builtin variable long args with math lib env arg" "$out1" "$out2"
+
+ export BC_ENV_ARGS="-S100"
+
+ printf 'scale\n' | "$exe" "$@" -l > "$out2"
+ checktest "$d" "$?" "builtin variable args with math lib arg" "$out1" "$out2"
+
+ export BC_ENV_ARGS="--scale=100"
+
+ printf 'scale\n' | "$exe" "$@" -l > "$out2"
+ checktest "$d" "$?" "builtin variable long args with math lib arg" "$out1" "$out2"
+
+fi
+
printf 'scale\n' | "$exe" "$@" --scale=18923c.rlg > /dev/null 2> "$out2"
err="$?"
diff --git a/tests/script.sh b/tests/script.sh
index 5942e13159fe..f59daf343339 100755
--- a/tests/script.sh
+++ b/tests/script.sh
@@ -88,15 +88,15 @@ fi
if [ "$d" = "bc" ]; then
if [ "$run_stack_tests" -ne 0 ]; then
- options="-lgq"
+ options="-lgqC"
else
- options="-lq"
+ options="-lqC"
fi
halt="halt"
else
- options="-x"
+ options="-xC"
halt="q"
fi
@@ -159,7 +159,7 @@ else
# This is to check that the command exists. If not, we should not try to
# generate the test. Instead, we should just skip.
- command -v "$d"
+ command -v "$d" 1>/dev/null 2>&1
err="$?"
set -e
diff --git a/tests/test.sh b/tests/test.sh
index 9d557a715dc0..8e292a524354 100755
--- a/tests/test.sh
+++ b/tests/test.sh
@@ -123,9 +123,11 @@ if [ ! -f "$results" ]; then
printf 'done\n'
fi
-# We set this here because GNU dc does not have it.
-if [ "$d" = "dc" ]; then
- options="-x"
+# We set this here because GNU bc and dc does not have these options.
+if [ "$d" = "bc" ]; then
+ options="-lqc"
+else
+ options="-xc"
fi
export $var=string
diff --git a/vs/bc.vcxproj b/vs/bc.vcxproj
index ce34162118e1..3579f9094bec 100644
--- a/vs/bc.vcxproj
+++ b/vs/bc.vcxproj
@@ -102,7 +102,7 @@
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
- <PreprocessorDefinitions>BC_ENABLED=1;DC_ENABLED=1;BC_ENABLE_EXTRA_MATH=1;BC_ENABLE_HISTORY=1;BC_ENABLE_NLS=0;BC_DEBUG_CODE=0;BC_ENABLE_LIBRARY=0;BC_ENABLE_EDITLINE=0;BC_ENABLE_READLINE=0;BUILD_TYPE=N;BC_DEFAULT_BANNER=1;BC_DEFAULT_SIGINT_RESET=0;DC_DEFAULT_SIGINT_RESET=0;BC_DEFAULT_TTY_MODE=1;DC_DEFAULT_TTY_MODE=1;BC_DEFAULT_PROMPT=1;DC_DEFAULT_PROMPT=1;BC_DEFAULT_EXPR_EXIT=1;DC_DEFAULT_EXPR_EXIT=1;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>BC_ENABLED=1;DC_ENABLED=1;BC_ENABLE_EXTRA_MATH=1;BC_ENABLE_HISTORY=1;BC_ENABLE_NLS=0;BC_DEBUG_CODE=0;BC_ENABLE_LIBRARY=0;BC_ENABLE_EDITLINE=0;BC_ENABLE_READLINE=0;BUILD_TYPE=N;BC_DEFAULT_BANNER=1;BC_DEFAULT_SIGINT_RESET=0;DC_DEFAULT_SIGINT_RESET=0;BC_DEFAULT_TTY_MODE=1;DC_DEFAULT_TTY_MODE=1;BC_DEFAULT_PROMPT=1;DC_DEFAULT_PROMPT=1;BC_DEFAULT_EXPR_EXIT=1;DC_DEFAULT_EXPR_EXIT=1;BC_DEFAULT_DIGIT_CLAMP=1;DC_DEFAULT_DIGIT_CLAMP=1;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>..\include</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<ConformanceMode>true</ConformanceMode>
@@ -123,7 +123,7 @@
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
- <PreprocessorDefinitions>BC_ENABLED=1;DC_ENABLED=1;BC_ENABLE_EXTRA_MATH=1;BC_ENABLE_HISTORY=1;BC_ENABLE_NLS=0;BC_DEBUG_CODE=0;BC_ENABLE_LIBRARY=0;BC_ENABLE_EDITLINE=0;BC_ENABLE_READLINE=0;BUILD_TYPE=N;BC_DEFAULT_BANNER=1;BC_DEFAULT_SIGINT_RESET=0;DC_DEFAULT_SIGINT_RESET=0;BC_DEFAULT_TTY_MODE=1;DC_DEFAULT_TTY_MODE=1;BC_DEFAULT_PROMPT=1;DC_DEFAULT_PROMPT=1;BC_DEFAULT_EXPR_EXIT=1;DC_DEFAULT_EXPR_EXIT=1;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>BC_ENABLED=1;DC_ENABLED=1;BC_ENABLE_EXTRA_MATH=1;BC_ENABLE_HISTORY=1;BC_ENABLE_NLS=0;BC_DEBUG_CODE=0;BC_ENABLE_LIBRARY=0;BC_ENABLE_EDITLINE=0;BC_ENABLE_READLINE=0;BUILD_TYPE=N;BC_DEFAULT_BANNER=1;BC_DEFAULT_SIGINT_RESET=0;DC_DEFAULT_SIGINT_RESET=0;BC_DEFAULT_TTY_MODE=1;DC_DEFAULT_TTY_MODE=1;BC_DEFAULT_PROMPT=1;DC_DEFAULT_PROMPT=1;BC_DEFAULT_EXPR_EXIT=1;DC_DEFAULT_EXPR_EXIT=1;BC_DEFAULT_DIGIT_CLAMP=1;DC_DEFAULT_DIGIT_CLAMP=1;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>..\include</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<ConformanceMode>true</ConformanceMode>
@@ -144,7 +144,7 @@
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
- <PreprocessorDefinitions>BC_ENABLED=1;DC_ENABLED=1;BC_ENABLE_EXTRA_MATH=1;BC_ENABLE_HISTORY=1;BC_ENABLE_NLS=0;BC_DEBUG_CODE=0;BC_ENABLE_LIBRARY=0;BC_ENABLE_EDITLINE=0;BC_ENABLE_READLINE=0;BUILD_TYPE=N;BC_DEFAULT_BANNER=1;BC_DEFAULT_SIGINT_RESET=0;DC_DEFAULT_SIGINT_RESET=0;BC_DEFAULT_TTY_MODE=1;DC_DEFAULT_TTY_MODE=1;BC_DEFAULT_PROMPT=1;DC_DEFAULT_PROMPT=1;BC_DEFAULT_EXPR_EXIT=1;DC_DEFAULT_EXPR_EXIT=1;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>BC_ENABLED=1;DC_ENABLED=1;BC_ENABLE_EXTRA_MATH=1;BC_ENABLE_HISTORY=1;BC_ENABLE_NLS=0;BC_DEBUG_CODE=0;BC_ENABLE_LIBRARY=0;BC_ENABLE_EDITLINE=0;BC_ENABLE_READLINE=0;BUILD_TYPE=N;BC_DEFAULT_BANNER=1;BC_DEFAULT_SIGINT_RESET=0;DC_DEFAULT_SIGINT_RESET=0;BC_DEFAULT_TTY_MODE=1;DC_DEFAULT_TTY_MODE=1;BC_DEFAULT_PROMPT=1;DC_DEFAULT_PROMPT=1;BC_DEFAULT_EXPR_EXIT=1;DC_DEFAULT_EXPR_EXIT=1;BC_DEFAULT_DIGIT_CLAMP=1;DC_DEFAULT_DIGIT_CLAMP=1;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>..\include</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<ConformanceMode>true</ConformanceMode>
@@ -164,7 +164,7 @@
<WarningLevel>Level3</WarningLevel>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
- <PreprocessorDefinitions>BC_ENABLED=1;DC_ENABLED=1;BC_ENABLE_EXTRA_MATH=1;BC_ENABLE_HISTORY=1;BC_ENABLE_NLS=0;BC_DEBUG_CODE=0;BC_ENABLE_LIBRARY=0;BC_ENABLE_EDITLINE=0;BC_ENABLE_READLINE=0;BUILD_TYPE=N;BC_DEFAULT_BANNER=1;BC_DEFAULT_SIGINT_RESET=0;DC_DEFAULT_SIGINT_RESET=0;BC_DEFAULT_TTY_MODE=1;DC_DEFAULT_TTY_MODE=1;BC_DEFAULT_PROMPT=1;DC_DEFAULT_PROMPT=1;BC_DEFAULT_EXPR_EXIT=1;DC_DEFAULT_EXPR_EXIT=1;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>BC_ENABLED=1;DC_ENABLED=1;BC_ENABLE_EXTRA_MATH=1;BC_ENABLE_HISTORY=1;BC_ENABLE_NLS=0;BC_DEBUG_CODE=0;BC_ENABLE_LIBRARY=0;BC_ENABLE_EDITLINE=0;BC_ENABLE_READLINE=0;BUILD_TYPE=N;BC_DEFAULT_BANNER=1;BC_DEFAULT_SIGINT_RESET=0;DC_DEFAULT_SIGINT_RESET=0;BC_DEFAULT_TTY_MODE=1;DC_DEFAULT_TTY_MODE=1;BC_DEFAULT_PROMPT=1;DC_DEFAULT_PROMPT=1;BC_DEFAULT_EXPR_EXIT=1;DC_DEFAULT_EXPR_EXIT=1;BC_DEFAULT_DIGIT_CLAMP=1;DC_DEFAULT_DIGIT_CLAMP=1;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>..\include</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
@@ -206,13 +206,13 @@
<ItemGroup>
<CustomBuild Include="..\gen\strgen.c">
<FileType>CppCode</FileType>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">cl.exe /Fo:$(OutDir)strgen.obj /Fe:$(OutDir)strgen.exe %(Identity)</Command>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">cl.exe /I..\include /DBC_ENABLE_LIBRARY=0 /Fo:$(OutDir)strgen.obj /Fe:$(OutDir)strgen.exe %(Identity)</Command>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(OutDir)strgen.exe</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">cl.exe /Fo:$(OutDir)strgen.obj /Fe:$(OutDir)strgen.exe %(Identity)</Command>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">cl.exe /I..\include /DBC_ENABLE_LIBRARY=0 /Fo:$(OutDir)strgen.obj /Fe:$(OutDir)strgen.exe %(Identity)</Command>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(OutDir)strgen.exe</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">cl.exe /Fo:$(OutDir)strgen.obj /Fe:$(OutDir)strgen.exe %(Identity)</Command>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">cl.exe /I..\include /DBC_ENABLE_LIBRARY=0 /Fo:$(OutDir)strgen.obj /Fe:$(OutDir)strgen.exe %(Identity)</Command>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(OutDir)strgen.exe</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">cl.exe /Fo:$(OutDir)strgen.obj /Fe:$(OutDir)strgen.exe %(Identity)</Command>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">cl.exe /I..\include /DBC_ENABLE_LIBRARY=0 /Fo:$(OutDir)strgen.obj /Fe:$(OutDir)strgen.exe %(Identity)</Command>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(OutDir)strgen.exe</Outputs>
</CustomBuild>
<ClCompile Include="src2\bc_help.c" />