diff options
author | Stefan Eßer <se@FreeBSD.org> | 2022-08-30 18:35:22 +0000 |
---|---|---|
committer | Stefan Eßer <se@FreeBSD.org> | 2022-08-30 18:37:36 +0000 |
commit | 161a37cc712bae177402d7143cb21b7d085c69c7 (patch) | |
tree | 8eabf221dc1a31abf6f88dd6fcdb0b4e2a78fc82 | |
parent | 1576f66712876ee8b0fcc8b35fb062e1813b4fc0 (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
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%% @@ -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; } @@ -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' }, @@ -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(©, 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(©); - 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(©.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, ©); - 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(©.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 @@ -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" /> |