diff options
Diffstat (limited to 'contrib/bc/manuals/bc/NP.1')
-rw-r--r-- | contrib/bc/manuals/bc/NP.1 | 2031 |
1 files changed, 2031 insertions, 0 deletions
diff --git a/contrib/bc/manuals/bc/NP.1 b/contrib/bc/manuals/bc/NP.1 new file mode 100644 index 000000000000..0e45d6dcab62 --- /dev/null +++ b/contrib/bc/manuals/bc/NP.1 @@ -0,0 +1,2031 @@ +.\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" +.\" Copyright (c) 2018-2021 Gavin D. Howard and contributors. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions are met: +.\" +.\" * Redistributions of source code must retain the above copyright notice, +.\" this list of conditions and the following disclaimer. +.\" +.\" * Redistributions in binary form must reproduce the above copyright notice, +.\" this list of conditions and the following disclaimer in the documentation +.\" and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +.\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +.\" LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +.\" POSSIBILITY OF SUCH DAMAGE. +.\" +.TH "BC" "1" "January 2021" "Gavin D. Howard" "General Commands Manual" +.SH NAME +.PP +bc - arbitrary-precision decimal arithmetic language and calculator +.SH SYNOPSIS +.PP +\f[B]bc\f[R] [\f[B]-ghilPqsvVw\f[R]] [\f[B]\[en]global-stacks\f[R]] +[\f[B]\[en]help\f[R]] [\f[B]\[en]interactive\f[R]] +[\f[B]\[en]mathlib\f[R]] [\f[B]\[en]no-prompt\f[R]] +[\f[B]\[en]quiet\f[R]] [\f[B]\[en]standard\f[R]] [\f[B]\[en]warn\f[R]] +[\f[B]\[en]version\f[R]] [\f[B]-e\f[R] \f[I]expr\f[R]] +[\f[B]\[en]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 +here (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. +.PP +After parsing and handling options, this bc(1) reads any files given on +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. +.SH OPTIONS +.PP +The following are the options that bc(1) accepts. +.TP +\f[B]-g\f[R], \f[B]\[en]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. +.RS +.PP +This has the effect that a copy of the current value of all four are +pushed onto a stack for every function call, as well as popped when +every function returns. +This means that functions can assign to any and all of those globals +without worrying that the change will affect other functions. +Thus, a hypothetical function named \f[B]output(x,b)\f[R] that simply +printed \f[B]x\f[R] in base \f[B]b\f[R] could be written like this: +.IP +.nf +\f[C] +define void output(x, b) { + obase=b + x +} +\f[R] +.fi +.PP +instead of like this: +.IP +.nf +\f[C] +define void output(x, b) { + auto c + c=obase + obase=b + x + obase=c +} +\f[R] +.fi +.PP +This makes writing functions much easier. +.PP +(\f[B]Note\f[R]: the function \f[B]output(x,b)\f[R] exists in the +extended math library. +See the \f[B]LIBRARY\f[R] section.) +.PP +However, since using this flag means that functions cannot set +\f[B]ibase\f[R], \f[B]obase\f[R], \f[B]scale\f[R], or \f[B]seed\f[R] +globally, functions that are made to do so cannot work anymore. +There are two possible use cases for that, and each has a solution. +.PP +First, if a function is called on startup to turn bc(1) into a number +converter, it is possible to replace that capability with various shell +aliases. +Examples: +.IP +.nf +\f[C] +alias d2o=\[dq]bc -e ibase=A -e obase=8\[dq] +alias h2b=\[dq]bc -e ibase=G -e obase=2\[dq] +\f[R] +.fi +.PP +Second, if the purpose of a function is to set \f[B]ibase\f[R], +\f[B]obase\f[R], \f[B]scale\f[R], or \f[B]seed\f[R] globally for any +other purpose, it could be split into one to four functions (based on +how many globals it sets) and each of those functions could return the +desired value for a global. +.PP +For functions that set \f[B]seed\f[R], the value assigned to +\f[B]seed\f[R] is not propagated to parent functions. +This means that the sequence of pseudo-random numbers that they see will +not be the same sequence of pseudo-random numbers that any parent sees. +This is only the case once \f[B]seed\f[R] has been set. +.PP +If a function desires to not affect the sequence of pseudo-random +numbers of its parents, but wants to use the same \f[B]seed\f[R], it can +use the following line: +.IP +.nf +\f[C] +seed = seed +\f[R] +.fi +.PP +If the behavior of this option is desired for every run of bc(1), then +users could make sure to define \f[B]BC_ENV_ARGS\f[R] and include this +option (see the \f[B]ENVIRONMENT VARIABLES\f[R] section for more +details). +.PP +If \f[B]-s\f[R], \f[B]-w\f[R], or any equivalents are used, this option +is ignored. +.PP +This is a \f[B]non-portable extension\f[R]. +.RE +.TP +\f[B]-h\f[R], \f[B]\[en]help\f[R] +Prints a usage message and quits. +.TP +\f[B]-i\f[R], \f[B]\[en]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]\[en]mathlib\f[R] +Sets \f[B]scale\f[R] (see the \f[B]SYNTAX\f[R] section) to \f[B]20\f[R] +and loads the included math library and the extended math library before +running any code, including any expressions or files specified on the +command line. +.RS +.PP +To learn what is in the libraries, see the \f[B]LIBRARY\f[R] section. +.RE +.TP +\f[B]-P\f[R], \f[B]\[en]no-prompt\f[R] +This option is a no-op. +.RS +.PP +This is a \f[B]non-portable extension\f[R]. +.RE +.TP +\f[B]-q\f[R], \f[B]\[en]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]\[en]version\f[R] options are given. +.RS +.PP +This is a \f[B]non-portable extension\f[R]. +.RE +.TP +\f[B]-s\f[R], \f[B]\[en]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. +.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]\[en]version\f[R] +Print the version information (copyright header) and exit. +.RS +.PP +This is a \f[B]non-portable extension\f[R]. +.RE +.TP +\f[B]-w\f[R], \f[B]\[en]warn\f[R] +Like \f[B]-s\f[R] and \f[B]\[en]standard\f[R], except that warnings (and +not errors) are printed for non-standard extensions and execution +continues normally. +.RS +.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]\[en]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 +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]\[en]file\f[R]. +However, if any other \f[B]-e\f[R], \f[B]\[en]expression\f[R], +\f[B]-f\f[R], or \f[B]\[en]file\f[R] arguments are given after that, +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]\[en]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 +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]\[en]file\f[R]. +.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 STDOUT +.PP +Any non-error output is written to \f[B]stdout\f[R]. +.PP +\f[B]Note\f[R]: Unlike other bc(1) implementations, this bc(1) will +issue a fatal error (see the \f[B]EXIT STATUS\f[R] section) if it cannot +write to \f[B]stdout\f[R], so if \f[B]stdout\f[R] is closed, as in +\f[B]bc >&-\f[R], it will quit with an error. +This is done so that bc(1) can report problems when \f[B]stdout\f[R] is +redirected to a file. +.PP +If there are scripts that depend on the behavior of other bc(1) +implementations, it is recommended that those scripts be changed to +redirect \f[B]stdout\f[R] to \f[B]/dev/null\f[R]. +.SH STDERR +.PP +Any error output is written to \f[B]stderr\f[R]. +.PP +\f[B]Note\f[R]: Unlike other bc(1) implementations, this bc(1) will +issue a fatal error (see the \f[B]EXIT STATUS\f[R] section) if it cannot +write to \f[B]stderr\f[R], so if \f[B]stderr\f[R] is closed, as in +\f[B]bc 2>&-\f[R], it will quit with an error. +This is done so that bc(1) can exit with an error code when +\f[B]stderr\f[R] is redirected to a file. +.PP +If there are scripts that depend on the behavior of other bc(1) +implementations, it is recommended that those scripts be changed to +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 section is meant to be a summary and a listing of all the +extensions to the standard. +.PP +In the sections below, \f[B]E\f[R] means expression, \f[B]S\f[R] means +statement, and \f[B]I\f[R] means identifier. +.PP +Identifiers (\f[B]I\f[R]) start with a lowercase letter and can be +followed by any number (up to \f[B]BC_NAME_MAX-1\f[R]) of lowercase +letters (\f[B]a-z\f[R]), digits (\f[B]0-9\f[R]), and underscores +(\f[B]_\f[R]). +The regex is \f[B][a-z][a-z0-9_]*\f[R]. +Identifiers with more than one character (letter) are a +\f[B]non-portable extension\f[R]. +.PP +\f[B]ibase\f[R] is a global variable determining how to interpret +constant numbers. +It is the \[lq]input\[rq] base, or the number base used for interpreting +input numbers. +\f[B]ibase\f[R] is initially \f[B]10\f[R]. +If the \f[B]-s\f[R] (\f[B]\[en]standard\f[R]) and \f[B]-w\f[R] +(\f[B]\[en]warn\f[R]) flags were not given on the command line, the max +allowable value for \f[B]ibase\f[R] is \f[B]36\f[R]. +Otherwise, it is \f[B]16\f[R]. +The min allowable value for \f[B]ibase\f[R] is \f[B]2\f[R]. +The max allowable value for \f[B]ibase\f[R] can be queried in bc(1) +programs with the \f[B]maxibase()\f[R] built-in function. +.PP +\f[B]obase\f[R] is a global variable determining how to output results. +It is the \[lq]output\[rq] base, or the number base used for outputting +numbers. +\f[B]obase\f[R] is initially \f[B]10\f[R]. +The max allowable value for \f[B]obase\f[R] is \f[B]BC_BASE_MAX\f[R] and +can be queried in bc(1) programs with the \f[B]maxobase()\f[R] built-in +function. +The min allowable value for \f[B]obase\f[R] is \f[B]0\f[R]. +If \f[B]obase\f[R] is \f[B]0\f[R], values are output in scientific +notation, and if \f[B]obase\f[R] is \f[B]1\f[R], values are output in +engineering notation. +Otherwise, values are output in the specified base. +.PP +Outputting in scientific and engineering notations are \f[B]non-portable +extensions\f[R]. +.PP +The \f[I]scale\f[R] of an expression is the number of digits in the +result of the expression right of the decimal point, and \f[B]scale\f[R] +is a global variable that sets the precision of any operations, with +exceptions. +\f[B]scale\f[R] is initially \f[B]0\f[R]. +\f[B]scale\f[R] cannot be negative. +The max allowable value for \f[B]scale\f[R] is \f[B]BC_SCALE_MAX\f[R] +and can be queried in bc(1) programs with the \f[B]maxscale()\f[R] +built-in function. +.PP +bc(1) has both \f[I]global\f[R] variables and \f[I]local\f[R] variables. +All \f[I]local\f[R] variables are local to the function; they are +parameters or are introduced in the \f[B]auto\f[R] list of a function +(see the \f[B]FUNCTIONS\f[R] section). +If a variable is accessed which is not a parameter or in the +\f[B]auto\f[R] list, it is assumed to be \f[I]global\f[R]. +If a parent function has a \f[I]local\f[R] variable version of a +variable that a child function considers \f[I]global\f[R], the value of +that \f[I]global\f[R] variable in the child function is the value of the +variable in the parent function, not the value of the actual +\f[I]global\f[R] variable. +.PP +All of the above applies to arrays as well. +.PP +The value of a statement that is an expression (i.e., any of the named +expressions or operands) is printed unless the lowest precedence +operator is an assignment operator \f[I]and\f[R] the expression is +notsurrounded by parentheses. +.PP +The value that is printed is also assigned to the special variable +\f[B]last\f[R]. +A single dot (\f[B].\f[R]) may also be used as a synonym for +\f[B]last\f[R]. +These are \f[B]non-portable extensions\f[R]. +.PP +Either semicolons or newlines may separate statements. +.SS Comments +.PP +There are two kinds of comments: +.IP "1." 3 +Block comments are enclosed in \f[B]/*\f[R] and \f[B]*/\f[R]. +.IP "2." 3 +Line comments go from \f[B]#\f[R] until, and not including, the next +newline. +This is a \f[B]non-portable extension\f[R]. +.SS Named Expressions +.PP +The following are named expressions in bc(1): +.IP "1." 3 +Variables: \f[B]I\f[R] +.IP "2." 3 +Array Elements: \f[B]I[E]\f[R] +.IP "3." 3 +\f[B]ibase\f[R] +.IP "4." 3 +\f[B]obase\f[R] +.IP "5." 3 +\f[B]scale\f[R] +.IP "6." 3 +\f[B]seed\f[R] +.IP "7." 3 +\f[B]last\f[R] or a single dot (\f[B].\f[R]) +.PP +Numbers 6 and 7 are \f[B]non-portable extensions\f[R]. +.PP +The meaning of \f[B]seed\f[R] is dependent on the current pseudo-random +number generator but is guaranteed to not change except for new major +versions. +.PP +The \f[I]scale\f[R] and sign of the value may be significant. +.PP +If a previously used \f[B]seed\f[R] value is assigned to \f[B]seed\f[R] +and used again, the pseudo-random number generator is guaranteed to +produce the same sequence of pseudo-random numbers as it did when the +\f[B]seed\f[R] value was previously used. +.PP +The exact value assigned to \f[B]seed\f[R] is not guaranteed to be +returned if \f[B]seed\f[R] is queried again immediately. +However, if \f[B]seed\f[R] \f[I]does\f[R] return a different value, both +values, when assigned to \f[B]seed\f[R], are guaranteed to produce the +same sequence of pseudo-random numbers. +This means that certain values assigned to \f[B]seed\f[R] will +\f[I]not\f[R] produce unique sequences of pseudo-random numbers. +The value of \f[B]seed\f[R] will change after any use of the +\f[B]rand()\f[R] and \f[B]irand(E)\f[R] operands (see the +\f[I]Operands\f[R] subsection below), except if the parameter passed to +\f[B]irand(E)\f[R] is \f[B]0\f[R], \f[B]1\f[R], or negative. +.PP +There is no limit to the length (number of significant decimal digits) +or \f[I]scale\f[R] of the value that can be assigned to \f[B]seed\f[R]. +.PP +Variables and arrays do not interfere; users can have arrays named the +same as variables. +This also applies to functions (see the \f[B]FUNCTIONS\f[R] section), so +a user can have a variable, array, and function that all have the same +name, and they will not shadow each other, whether inside of functions +or not. +.PP +Named expressions are required as the operand of +\f[B]increment\f[R]/\f[B]decrement\f[R] operators and as the left side +of \f[B]assignment\f[R] operators (see the \f[I]Operators\f[R] +subsection). +.SS Operands +.PP +The following are valid operands in bc(1): +.IP " 1." 4 +Numbers (see the \f[I]Numbers\f[R] subsection below). +.IP " 2." 4 +Array indices (\f[B]I[E]\f[R]). +.IP " 3." 4 +\f[B](E)\f[R]: The value of \f[B]E\f[R] (used to change precedence). +.IP " 4." 4 +\f[B]sqrt(E)\f[R]: The square root of \f[B]E\f[R]. +\f[B]E\f[R] must be non-negative. +.IP " 5." 4 +\f[B]length(E)\f[R]: The number of significant decimal digits in +\f[B]E\f[R]. +.IP " 6." 4 +\f[B]length(I[])\f[R]: The number of elements in the array \f[B]I\f[R]. +This is a \f[B]non-portable extension\f[R]. +.IP " 7." 4 +\f[B]scale(E)\f[R]: The \f[I]scale\f[R] of \f[B]E\f[R]. +.IP " 8." 4 +\f[B]abs(E)\f[R]: The absolute value of \f[B]E\f[R]. +This is a \f[B]non-portable extension\f[R]. +.IP " 9." 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 non-\f[B]void\f[R] function (see the +\f[I]Void Functions\f[R] subsection of the \f[B]FUNCTIONS\f[R] section). +The \f[B]E\f[R] argument(s) may also be arrays of the form +\f[B]I[]\f[R], which will automatically be turned into array references +(see the \f[I]Array References\f[R] subsection of the +\f[B]FUNCTIONS\f[R] section) if the corresponding parameter in the +function definition is an array reference. +.IP "10." 4 +\f[B]read()\f[R]: Reads a line from \f[B]stdin\f[R] and uses that as an +expression. +The result of that expression is the result of the \f[B]read()\f[R] +operand. +This is a \f[B]non-portable extension\f[R]. +.IP "11." 4 +\f[B]maxibase()\f[R]: The max allowable \f[B]ibase\f[R]. +This is a \f[B]non-portable extension\f[R]. +.IP "12." 4 +\f[B]maxobase()\f[R]: The max allowable \f[B]obase\f[R]. +This is a \f[B]non-portable extension\f[R]. +.IP "13." 4 +\f[B]maxscale()\f[R]: The max allowable \f[B]scale\f[R]. +This is a \f[B]non-portable extension\f[R]. +.IP "14." 4 +\f[B]rand()\f[R]: A pseudo-random integer between \f[B]0\f[R] +(inclusive) and \f[B]BC_RAND_MAX\f[R] (inclusive). +Using this operand will change the value of \f[B]seed\f[R]. +This is a \f[B]non-portable extension\f[R]. +.IP "15." 4 +\f[B]irand(E)\f[R]: A pseudo-random integer between \f[B]0\f[R] +(inclusive) and the value of \f[B]E\f[R] (exclusive). +If \f[B]E\f[R] is negative or is a non-integer (\f[B]E\f[R]\[cq]s +\f[I]scale\f[R] is not \f[B]0\f[R]), an error is raised, and bc(1) +resets (see the \f[B]RESET\f[R] section) while \f[B]seed\f[R] remains +unchanged. +If \f[B]E\f[R] is larger than \f[B]BC_RAND_MAX\f[R], the higher bound is +honored by generating several pseudo-random integers, multiplying them +by appropriate powers of \f[B]BC_RAND_MAX+1\f[R], and adding them +together. +Thus, the size of integer that can be generated with this operand is +unbounded. +Using this operand will change the value of \f[B]seed\f[R], unless the +value of \f[B]E\f[R] is \f[B]0\f[R] or \f[B]1\f[R]. +In that case, \f[B]0\f[R] is returned, and \f[B]seed\f[R] is +\f[I]not\f[R] changed. +This is a \f[B]non-portable extension\f[R]. +.IP "16." 4 +\f[B]maxrand()\f[R]: The max integer returned by \f[B]rand()\f[R]. +This is a \f[B]non-portable extension\f[R]. +.PP +The integers generated by \f[B]rand()\f[R] and \f[B]irand(E)\f[R] are +guaranteed to be as unbiased as possible, subject to the limitations of +the pseudo-random number generator. +.PP +\f[B]Note\f[R]: The values returned by the pseudo-random number +generator with \f[B]rand()\f[R] and \f[B]irand(E)\f[R] are guaranteed to +\f[I]NOT\f[R] be cryptographically secure. +This is a consequence of using a seeded pseudo-random number generator. +However, they \f[I]are\f[R] guaranteed to be reproducible with identical +\f[B]seed\f[R] values. +This means that the pseudo-random values from bc(1) should only be used +where a reproducible stream of pseudo-random numbers is +\f[I]ESSENTIAL\f[R]. +In any other case, use a non-seeded pseudo-random number generator. +.SS Numbers +.PP +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]. +.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]. +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]. +.PP +In addition, bc(1) accepts numbers in scientific notation. +These have the form \f[B]<number>e<integer>\f[R]. +The exponent (the portion after the \f[B]e\f[R]) must be an integer. +An example is \f[B]1.89237e9\f[R], which is equal to +\f[B]1892370000\f[R]. +Negative exponents are also allowed, so \f[B]4.2890e-3\f[R] is equal to +\f[B]0.0042890\f[R]. +.PP +Using scientific notation is an error or warning if the \f[B]-s\f[R] or +\f[B]-w\f[R], respectively, command-line options (or equivalents) are +given. +.PP +\f[B]WARNING\f[R]: Both the number and the exponent in scientific +notation are interpreted according to the current \f[B]ibase\f[R], but +the number is still multiplied by \f[B]10\[ha]exponent\f[R] regardless +of the current \f[B]ibase\f[R]. +For example, if \f[B]ibase\f[R] is \f[B]16\f[R] and bc(1) is given the +number string \f[B]FFeA\f[R], the resulting decimal number will be +\f[B]2550000000000\f[R], and if bc(1) is given the number string +\f[B]10e-4\f[R], the resulting decimal number will be \f[B]0.0016\f[R]. +.PP +Accepting input as scientific notation is a \f[B]non-portable +extension\f[R]. +.SS Operators +.PP +The following arithmetic and logical operators can be used. +They are listed in order of decreasing precedence. +Operators in the same group have the same precedence. +.TP +\f[B]++\f[R] \f[B]\[en]\f[R] +Type: Prefix and Postfix +.RS +.PP +Associativity: None +.PP +Description: \f[B]increment\f[R], \f[B]decrement\f[R] +.RE +.TP +\f[B]-\f[R] \f[B]!\f[R] +Type: Prefix +.RS +.PP +Associativity: None +.PP +Description: \f[B]negation\f[R], \f[B]boolean not\f[R] +.RE +.TP +\f[B]$\f[R] +Type: Postfix +.RS +.PP +Associativity: None +.PP +Description: \f[B]truncation\f[R] +.RE +.TP +\f[B]\[at]\f[R] +Type: Binary +.RS +.PP +Associativity: Right +.PP +Description: \f[B]set precision\f[R] +.RE +.TP +\f[B]\[ha]\f[R] +Type: Binary +.RS +.PP +Associativity: Right +.PP +Description: \f[B]power\f[R] +.RE +.TP +\f[B]*\f[R] \f[B]/\f[R] \f[B]%\f[R] +Type: Binary +.RS +.PP +Associativity: Left +.PP +Description: \f[B]multiply\f[R], \f[B]divide\f[R], \f[B]modulus\f[R] +.RE +.TP +\f[B]+\f[R] \f[B]-\f[R] +Type: Binary +.RS +.PP +Associativity: Left +.PP +Description: \f[B]add\f[R], \f[B]subtract\f[R] +.RE +.TP +\f[B]<<\f[R] \f[B]>>\f[R] +Type: Binary +.RS +.PP +Associativity: Left +.PP +Description: \f[B]shift left\f[R], \f[B]shift right\f[R] +.RE +.TP +\f[B]=\f[R] \f[B]<<=\f[R] \f[B]>>=\f[R] \f[B]+=\f[R] \f[B]-=\f[R] \f[B]*=\f[R] \f[B]/=\f[R] \f[B]%=\f[R] \f[B]\[ha]=\f[R] \f[B]\[at]=\f[R] +Type: Binary +.RS +.PP +Associativity: Right +.PP +Description: \f[B]assignment\f[R] +.RE +.TP +\f[B]==\f[R] \f[B]<=\f[R] \f[B]>=\f[R] \f[B]!=\f[R] \f[B]<\f[R] \f[B]>\f[R] +Type: Binary +.RS +.PP +Associativity: Left +.PP +Description: \f[B]relational\f[R] +.RE +.TP +\f[B]&&\f[R] +Type: Binary +.RS +.PP +Associativity: Left +.PP +Description: \f[B]boolean and\f[R] +.RE +.TP +\f[B]||\f[R] +Type: Binary +.RS +.PP +Associativity: Left +.PP +Description: \f[B]boolean or\f[R] +.RE +.PP +The operators will be described in more detail below. +.TP +\f[B]++\f[R] \f[B]\[en]\f[R] +The prefix and postfix \f[B]increment\f[R] and \f[B]decrement\f[R] +operators behave exactly like they would in C. +They require a named expression (see the \f[I]Named Expressions\f[R] +subsection) as an operand. +.RS +.PP +The prefix versions of these operators are more efficient; use them +where possible. +.RE +.TP +\f[B]-\f[R] +The \f[B]negation\f[R] operator returns \f[B]0\f[R] if a user attempts +to negate any expression with the value \f[B]0\f[R]. +Otherwise, a copy of the expression with its sign flipped is returned. +.TP +\f[B]!\f[R] +The \f[B]boolean not\f[R] operator returns \f[B]1\f[R] if the expression +is \f[B]0\f[R], or \f[B]0\f[R] otherwise. +.RS +.PP +This is a \f[B]non-portable extension\f[R]. +.RE +.TP +\f[B]$\f[R] +The \f[B]truncation\f[R] operator returns a copy of the given expression +with all of its \f[I]scale\f[R] removed. +.RS +.PP +This is a \f[B]non-portable extension\f[R]. +.RE +.TP +\f[B]\[at]\f[R] +The \f[B]set precision\f[R] operator takes two expressions and returns a +copy of the first with its \f[I]scale\f[R] equal to the value of the +second expression. +That could either mean that the number is returned without change (if +the \f[I]scale\f[R] of the first expression matches the value of the +second expression), extended (if it is less), or truncated (if it is +more). +.RS +.PP +The second expression must be an integer (no \f[I]scale\f[R]) and +non-negative. +.PP +This is a \f[B]non-portable extension\f[R]. +.RE +.TP +\f[B]\[ha]\f[R] +The \f[B]power\f[R] operator (not the \f[B]exclusive or\f[R] operator, +as it would be in C) takes two expressions and raises the first to the +power of the value of the second. +The \f[I]scale\f[R] of the result is equal to \f[B]scale\f[R]. +.RS +.PP +The second expression must be an integer (no \f[I]scale\f[R]), and if it +is negative, the first value must be non-zero. +.RE +.TP +\f[B]*\f[R] +The \f[B]multiply\f[R] operator takes two expressions, multiplies them, +and returns the product. +If \f[B]a\f[R] is the \f[I]scale\f[R] of the first expression and +\f[B]b\f[R] is the \f[I]scale\f[R] of the second expression, the +\f[I]scale\f[R] of the result is equal to +\f[B]min(a+b,max(scale,a,b))\f[R] where \f[B]min()\f[R] and +\f[B]max()\f[R] return the obvious values. +.TP +\f[B]/\f[R] +The \f[B]divide\f[R] operator takes two expressions, divides them, and +returns the quotient. +The \f[I]scale\f[R] of the result shall be the value of \f[B]scale\f[R]. +.RS +.PP +The second expression must be non-zero. +.RE +.TP +\f[B]%\f[R] +The \f[B]modulus\f[R] operator takes two expressions, \f[B]a\f[R] and +\f[B]b\f[R], and evaluates them by 1) Computing \f[B]a/b\f[R] to current +\f[B]scale\f[R] and 2) Using the result of step 1 to calculate +\f[B]a-(a/b)*b\f[R] to \f[I]scale\f[R] +\f[B]max(scale+scale(b),scale(a))\f[R]. +.RS +.PP +The second expression must be non-zero. +.RE +.TP +\f[B]+\f[R] +The \f[B]add\f[R] operator takes two expressions, \f[B]a\f[R] and +\f[B]b\f[R], and returns the sum, with a \f[I]scale\f[R] equal to the +max of the \f[I]scale\f[R]s of \f[B]a\f[R] and \f[B]b\f[R]. +.TP +\f[B]-\f[R] +The \f[B]subtract\f[R] operator takes two expressions, \f[B]a\f[R] and +\f[B]b\f[R], and returns the difference, with a \f[I]scale\f[R] equal to +the max of the \f[I]scale\f[R]s of \f[B]a\f[R] and \f[B]b\f[R]. +.TP +\f[B]<<\f[R] +The \f[B]left shift\f[R] operator takes two expressions, \f[B]a\f[R] and +\f[B]b\f[R], and returns a copy of the value of \f[B]a\f[R] with its +decimal point moved \f[B]b\f[R] places to the right. +.RS +.PP +The second expression must be an integer (no \f[I]scale\f[R]) and +non-negative. +.PP +This is a \f[B]non-portable extension\f[R]. +.RE +.TP +\f[B]>>\f[R] +The \f[B]right shift\f[R] operator takes two expressions, \f[B]a\f[R] +and \f[B]b\f[R], and returns a copy of the value of \f[B]a\f[R] with its +decimal point moved \f[B]b\f[R] places to the left. +.RS +.PP +The second expression must be an integer (no \f[I]scale\f[R]) and +non-negative. +.PP +This is a \f[B]non-portable extension\f[R]. +.RE +.TP +\f[B]=\f[R] \f[B]<<=\f[R] \f[B]>>=\f[R] \f[B]+=\f[R] \f[B]-=\f[R] \f[B]*=\f[R] \f[B]/=\f[R] \f[B]%=\f[R] \f[B]\[ha]=\f[R] \f[B]\[at]=\f[R] +The \f[B]assignment\f[R] operators take two expressions, \f[B]a\f[R] and +\f[B]b\f[R] where \f[B]a\f[R] is a named expression (see the \f[I]Named +Expressions\f[R] subsection). +.RS +.PP +For \f[B]=\f[R], \f[B]b\f[R] is copied and the result is assigned to +\f[B]a\f[R]. +For all others, \f[B]a\f[R] and \f[B]b\f[R] are applied as operands to +the corresponding arithmetic operator and the result is assigned to +\f[B]a\f[R]. +.PP +The \f[B]assignment\f[R] operators that correspond to operators that are +extensions are themselves \f[B]non-portable extensions\f[R]. +.RE +.TP +\f[B]==\f[R] \f[B]<=\f[R] \f[B]>=\f[R] \f[B]!=\f[R] \f[B]<\f[R] \f[B]>\f[R] +The \f[B]relational\f[R] operators compare two expressions, \f[B]a\f[R] +and \f[B]b\f[R], and if the relation holds, according to C language +semantics, the result is \f[B]1\f[R]. +Otherwise, it is \f[B]0\f[R]. +.RS +.PP +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) +requires, these operators can appear anywhere any other expressions can +be used. +This allowance is a \f[B]non-portable extension\f[R]. +.RE +.TP +\f[B]&&\f[R] +The \f[B]boolean and\f[R] operator takes two expressions and returns +\f[B]1\f[R] if both expressions are non-zero, \f[B]0\f[R] otherwise. +.RS +.PP +This is \f[I]not\f[R] a short-circuit operator. +.PP +This is a \f[B]non-portable extension\f[R]. +.RE +.TP +\f[B]||\f[R] +The \f[B]boolean or\f[R] operator takes two expressions and returns +\f[B]1\f[R] if one of the expressions is non-zero, \f[B]0\f[R] +otherwise. +.RS +.PP +This is \f[I]not\f[R] a short-circuit operator. +.PP +This is a \f[B]non-portable extension\f[R]. +.RE +.SS Statements +.PP +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] +.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 +\f[B]if\f[R] \f[B](\f[R] \f[B]E\f[R] \f[B])\f[R] \f[B]S\f[R] +\f[B]else\f[R] \f[B]S\f[R] +.IP " 5." 4 +\f[B]while\f[R] \f[B](\f[R] \f[B]E\f[R] \f[B])\f[R] \f[B]S\f[R] +.IP " 6." 4 +\f[B]for\f[R] \f[B](\f[R] \f[B]E\f[R] \f[B];\f[R] \f[B]E\f[R] +\f[B];\f[R] \f[B]E\f[R] \f[B])\f[R] \f[B]S\f[R] +.IP " 7." 4 +An empty statement +.IP " 8." 4 +\f[B]break\f[R] +.IP " 9." 4 +\f[B]continue\f[R] +.IP "10." 4 +\f[B]quit\f[R] +.IP "11." 4 +\f[B]halt\f[R] +.IP "12." 4 +\f[B]limits\f[R] +.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] +.IP "15." 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 +\f[I]Void Functions\f[R] subsection of the \f[B]FUNCTIONS\f[R] section). +The \f[B]E\f[R] argument(s) may also be arrays of the form +\f[B]I[]\f[R], which will automatically be turned into array references +(see the \f[I]Array References\f[R] subsection of the +\f[B]FUNCTIONS\f[R] section) if the corresponding parameter in the +function definition is an array reference. +.PP +Numbers 4, 9, 11, 12, 14, and 15 are \f[B]non-portable extensions\f[R]. +.PP +Also, as a \f[B]non-portable extension\f[R], any or all of the +expressions in the header of a for loop may be omitted. +If the condition (second expression) is omitted, it is assumed to be a +constant \f[B]1\f[R]. +.PP +The \f[B]break\f[R] statement causes a loop to stop iterating and resume +execution immediately following a loop. +This is only allowed in loops. +.PP +The \f[B]continue\f[R] statement causes a loop iteration to stop early +and returns to the start of the loop, including testing the loop +condition. +This is only allowed in loops. +.PP +The \f[B]if\f[R] \f[B]else\f[R] statement does the same thing as in C. +.PP +The \f[B]quit\f[R] statement causes bc(1) to quit, even if it is on a +branch that will not be executed (it is a compile-time command). +.PP +The \f[B]halt\f[R] statement causes bc(1) to quit, if it is executed. +(Unlike \f[B]quit\f[R] if it is on a branch of an \f[B]if\f[R] statement +that is not executed, bc(1) does not quit.) +.PP +The \f[B]limits\f[R] statement prints the limits that this bc(1) is +subject to. +This is like the \f[B]quit\f[R] statement in that it is a compile-time +command. +.PP +An expression by itself is evaluated and printed, followed by a newline. +.PP +Both scientific notation and engineering notation are available for +printing the results of expressions. +Scientific notation is activated by assigning \f[B]0\f[R] to +\f[B]obase\f[R], and engineering notation is activated by assigning +\f[B]1\f[R] to \f[B]obase\f[R]. +To deactivate them, just assign a different value to \f[B]obase\f[R]. +.PP +Scientific notation and engineering notation are disabled if bc(1) is +run with either the \f[B]-s\f[R] or \f[B]-w\f[R] command-line options +(or equivalents). +.PP +Printing numbers in scientific notation and/or engineering notation is a +\f[B]non-portable extension\f[R]. +.SS Print Statement +.PP +The \[lq]expressions\[rq] in a \f[B]print\f[R] statement may also be +strings. +If they are, there are backslash escape sequences that are interpreted +specially. +What those sequences are, and what they cause to be printed, are shown +below: +.PP +.TS +tab(@); +l l. +T{ +\f[B]\[rs]a\f[R] +T}@T{ +\f[B]\[rs]a\f[R] +T} +T{ +\f[B]\[rs]b\f[R] +T}@T{ +\f[B]\[rs]b\f[R] +T} +T{ +\f[B]\[rs]\[rs]\f[R] +T}@T{ +\f[B]\[rs]\f[R] +T} +T{ +\f[B]\[rs]e\f[R] +T}@T{ +\f[B]\[rs]\f[R] +T} +T{ +\f[B]\[rs]f\f[R] +T}@T{ +\f[B]\[rs]f\f[R] +T} +T{ +\f[B]\[rs]n\f[R] +T}@T{ +\f[B]\[rs]n\f[R] +T} +T{ +\f[B]\[rs]q\f[R] +T}@T{ +\f[B]\[dq]\f[R] +T} +T{ +\f[B]\[rs]r\f[R] +T}@T{ +\f[B]\[rs]r\f[R] +T} +T{ +\f[B]\[rs]t\f[R] +T}@T{ +\f[B]\[rs]t\f[R] +T} +.TE +.PP +Any other character following a backslash causes the backslash and +character to be printed as-is. +.PP +Any non-string expression in a print statement shall be assigned to +\f[B]last\f[R], like any other expression that is printed. +.SS Order of Evaluation +.PP +All expressions in a statment are evaluated left to right, except as +necessary to maintain order of operations. +This means, for example, assuming that \f[B]i\f[R] is equal to +\f[B]0\f[R], in the expression +.IP +.nf +\f[C] +a[i++] = i++ +\f[R] +.fi +.PP +the first (or 0th) element of \f[B]a\f[R] is set to \f[B]1\f[R], and +\f[B]i\f[R] is equal to \f[B]2\f[R] at the end of the expression. +.PP +This includes function arguments. +Thus, assuming \f[B]i\f[R] is equal to \f[B]0\f[R], this means that in +the expression +.IP +.nf +\f[C] +x(i++, i++) +\f[R] +.fi +.PP +the first argument passed to \f[B]x()\f[R] is \f[B]0\f[R], and the +second argument is \f[B]1\f[R], while \f[B]i\f[R] is equal to +\f[B]2\f[R] before the function starts executing. +.SH FUNCTIONS +.PP +Function definitions are as follows: +.IP +.nf +\f[C] +define I(I,...,I){ + auto I,...,I + S;...;S + return(E) +} +\f[R] +.fi +.PP +Any \f[B]I\f[R] in the parameter list or \f[B]auto\f[R] list may be +replaced with \f[B]I[]\f[R] to make a parameter or \f[B]auto\f[R] var an +array, and any \f[B]I\f[R] in the parameter list may be replaced with +\f[B]*I[]\f[R] to make a parameter an array reference. +Callers of functions that take array references should not put an +asterisk in the call; they must be called with just \f[B]I[]\f[R] like +normal array parameters and will be automatically converted into +references. +.PP +As a \f[B]non-portable extension\f[R], the opening brace of a +\f[B]define\f[R] statement may appear on the next line. +.PP +As a \f[B]non-portable extension\f[R], the return statement may also be +in one of the following forms: +.IP "1." 3 +\f[B]return\f[R] +.IP "2." 3 +\f[B]return\f[R] \f[B](\f[R] \f[B])\f[R] +.IP "3." 3 +\f[B]return\f[R] \f[B]E\f[R] +.PP +The first two, or not specifying a \f[B]return\f[R] statement, is +equivalent to \f[B]return (0)\f[R], unless the function is a +\f[B]void\f[R] function (see the \f[I]Void Functions\f[R] subsection +below). +.SS Void Functions +.PP +Functions can also be \f[B]void\f[R] functions, defined as follows: +.IP +.nf +\f[C] +define void I(I,...,I){ + auto I,...,I + S;...;S + return +} +\f[R] +.fi +.PP +They can only be used as standalone expressions, where such an +expression would be printed alone, except in a print statement. +.PP +Void functions can only use the first two \f[B]return\f[R] statements +listed above. +They can also omit the return statement entirely. +.PP +The word \[lq]void\[rq] is not treated as a keyword; it is still +possible to have variables, arrays, and functions named \f[B]void\f[R]. +The word \[lq]void\[rq] is only treated specially right after the +\f[B]define\f[R] keyword. +.PP +This is a \f[B]non-portable extension\f[R]. +.SS Array References +.PP +For any array in the parameter list, if the array is declared in the +form +.IP +.nf +\f[C] +*I[] +\f[R] +.fi +.PP +it is a \f[B]reference\f[R]. +Any changes to the array in the function are reflected, when the +function returns, to the array that was passed in. +.PP +Other than this, all function arguments are passed by value. +.PP +This is a \f[B]non-portable extension\f[R]. +.SH LIBRARY +.PP +All of the functions below, including the functions in the extended math +library (see the \f[I]Extended Library\f[R] subsection below), are +available when the \f[B]-l\f[R] or \f[B]\[en]mathlib\f[R] command-line +flags are given, except that the extended math library is not available +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: +.TP +\f[B]s(x)\f[R] +Returns the sine of \f[B]x\f[R], which is assumed to be in radians. +.RS +.PP +This is a transcendental function (see the \f[I]Transcendental +Functions\f[R] subsection below). +.RE +.TP +\f[B]c(x)\f[R] +Returns the cosine of \f[B]x\f[R], which is assumed to be in radians. +.RS +.PP +This is a transcendental function (see the \f[I]Transcendental +Functions\f[R] subsection below). +.RE +.TP +\f[B]a(x)\f[R] +Returns the arctangent of \f[B]x\f[R], in radians. +.RS +.PP +This is a transcendental function (see the \f[I]Transcendental +Functions\f[R] subsection below). +.RE +.TP +\f[B]l(x)\f[R] +Returns the natural logarithm of \f[B]x\f[R]. +.RS +.PP +This is a transcendental function (see the \f[I]Transcendental +Functions\f[R] subsection below). +.RE +.TP +\f[B]e(x)\f[R] +Returns the mathematical constant \f[B]e\f[R] raised to the power of +\f[B]x\f[R]. +.RS +.PP +This is a transcendental function (see the \f[I]Transcendental +Functions\f[R] subsection below). +.RE +.TP +\f[B]j(x, n)\f[R] +Returns the bessel integer order \f[B]n\f[R] (truncated) of \f[B]x\f[R]. +.RS +.PP +This is a transcendental function (see the \f[I]Transcendental +Functions\f[R] subsection below). +.RE +.SS Extended Library +.PP +The extended library is \f[I]not\f[R] loaded when the +\f[B]-s\f[R]/\f[B]\[en]standard\f[R] or \f[B]-w\f[R]/\f[B]\[en]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). +.PP +The extended library is a \f[B]non-portable extension\f[R]. +.TP +\f[B]p(x, y)\f[R] +Calculates \f[B]x\f[R] to the power of \f[B]y\f[R], even if \f[B]y\f[R] +is not an integer, and returns the result to the current +\f[B]scale\f[R]. +.RS +.PP +It is an error if \f[B]y\f[R] is negative and \f[B]x\f[R] is +\f[B]0\f[R]. +.PP +This is a transcendental function (see the \f[I]Transcendental +Functions\f[R] subsection below). +.RE +.TP +\f[B]r(x, p)\f[R] +Returns \f[B]x\f[R] rounded to \f[B]p\f[R] decimal places according to +the rounding mode round half away from +\f[B]0\f[R] (https://en.wikipedia.org/wiki/Rounding#Round_half_away_from_zero). +.TP +\f[B]ceil(x, p)\f[R] +Returns \f[B]x\f[R] rounded to \f[B]p\f[R] decimal places according to +the rounding mode round away from +\f[B]0\f[R] (https://en.wikipedia.org/wiki/Rounding#Rounding_away_from_zero). +.TP +\f[B]f(x)\f[R] +Returns the factorial of the truncated absolute value of \f[B]x\f[R]. +.TP +\f[B]perm(n, k)\f[R] +Returns the permutation of the truncated absolute value of \f[B]n\f[R] +of the truncated absolute value of \f[B]k\f[R], if \f[B]k <= n\f[R]. +If not, it returns \f[B]0\f[R]. +.TP +\f[B]comb(n, k)\f[R] +Returns the combination of the truncated absolute value of \f[B]n\f[R] +of the truncated absolute value of \f[B]k\f[R], if \f[B]k <= n\f[R]. +If not, it returns \f[B]0\f[R]. +.TP +\f[B]l2(x)\f[R] +Returns the logarithm base \f[B]2\f[R] of \f[B]x\f[R]. +.RS +.PP +This is a transcendental function (see the \f[I]Transcendental +Functions\f[R] subsection below). +.RE +.TP +\f[B]l10(x)\f[R] +Returns the logarithm base \f[B]10\f[R] of \f[B]x\f[R]. +.RS +.PP +This is a transcendental function (see the \f[I]Transcendental +Functions\f[R] subsection below). +.RE +.TP +\f[B]log(x, b)\f[R] +Returns the logarithm base \f[B]b\f[R] of \f[B]x\f[R]. +.RS +.PP +This is a transcendental function (see the \f[I]Transcendental +Functions\f[R] subsection below). +.RE +.TP +\f[B]cbrt(x)\f[R] +Returns the cube root of \f[B]x\f[R]. +.TP +\f[B]root(x, n)\f[R] +Calculates the truncated value of \f[B]n\f[R], \f[B]r\f[R], and returns +the \f[B]r\f[R]th root of \f[B]x\f[R] to the current \f[B]scale\f[R]. +.RS +.PP +If \f[B]r\f[R] is \f[B]0\f[R] or negative, this raises an error and +causes bc(1) to reset (see the \f[B]RESET\f[R] section). +It also raises an error and causes bc(1) to reset if \f[B]r\f[R] is even +and \f[B]x\f[R] is negative. +.RE +.TP +\f[B]pi(p)\f[R] +Returns \f[B]pi\f[R] to \f[B]p\f[R] decimal places. +.RS +.PP +This is a transcendental function (see the \f[I]Transcendental +Functions\f[R] subsection below). +.RE +.TP +\f[B]t(x)\f[R] +Returns the tangent of \f[B]x\f[R], which is assumed to be in radians. +.RS +.PP +This is a transcendental function (see the \f[I]Transcendental +Functions\f[R] subsection below). +.RE +.TP +\f[B]a2(y, x)\f[R] +Returns the arctangent of \f[B]y/x\f[R], in radians. +If both \f[B]y\f[R] and \f[B]x\f[R] are equal to \f[B]0\f[R], it raises +an error and causes bc(1) to reset (see the \f[B]RESET\f[R] section). +Otherwise, if \f[B]x\f[R] is greater than \f[B]0\f[R], it returns +\f[B]a(y/x)\f[R]. +If \f[B]x\f[R] is less than \f[B]0\f[R], and \f[B]y\f[R] is greater than +or equal to \f[B]0\f[R], it returns \f[B]a(y/x)+pi\f[R]. +If \f[B]x\f[R] is less than \f[B]0\f[R], and \f[B]y\f[R] is less than +\f[B]0\f[R], it returns \f[B]a(y/x)-pi\f[R]. +If \f[B]x\f[R] is equal to \f[B]0\f[R], and \f[B]y\f[R] is greater than +\f[B]0\f[R], it returns \f[B]pi/2\f[R]. +If \f[B]x\f[R] is equal to \f[B]0\f[R], and \f[B]y\f[R] is less than +\f[B]0\f[R], it returns \f[B]-pi/2\f[R]. +.RS +.PP +This function is the same as the \f[B]atan2()\f[R] function in many +programming languages. +.PP +This is a transcendental function (see the \f[I]Transcendental +Functions\f[R] subsection below). +.RE +.TP +\f[B]sin(x)\f[R] +Returns the sine of \f[B]x\f[R], which is assumed to be in radians. +.RS +.PP +This is an alias of \f[B]s(x)\f[R]. +.PP +This is a transcendental function (see the \f[I]Transcendental +Functions\f[R] subsection below). +.RE +.TP +\f[B]cos(x)\f[R] +Returns the cosine of \f[B]x\f[R], which is assumed to be in radians. +.RS +.PP +This is an alias of \f[B]c(x)\f[R]. +.PP +This is a transcendental function (see the \f[I]Transcendental +Functions\f[R] subsection below). +.RE +.TP +\f[B]tan(x)\f[R] +Returns the tangent of \f[B]x\f[R], which is assumed to be in radians. +.RS +.PP +If \f[B]x\f[R] is equal to \f[B]1\f[R] or \f[B]-1\f[R], this raises an +error and causes bc(1) to reset (see the \f[B]RESET\f[R] section). +.PP +This is an alias of \f[B]t(x)\f[R]. +.PP +This is a transcendental function (see the \f[I]Transcendental +Functions\f[R] subsection below). +.RE +.TP +\f[B]atan(x)\f[R] +Returns the arctangent of \f[B]x\f[R], in radians. +.RS +.PP +This is an alias of \f[B]a(x)\f[R]. +.PP +This is a transcendental function (see the \f[I]Transcendental +Functions\f[R] subsection below). +.RE +.TP +\f[B]atan2(y, x)\f[R] +Returns the arctangent of \f[B]y/x\f[R], in radians. +If both \f[B]y\f[R] and \f[B]x\f[R] are equal to \f[B]0\f[R], it raises +an error and causes bc(1) to reset (see the \f[B]RESET\f[R] section). +Otherwise, if \f[B]x\f[R] is greater than \f[B]0\f[R], it returns +\f[B]a(y/x)\f[R]. +If \f[B]x\f[R] is less than \f[B]0\f[R], and \f[B]y\f[R] is greater than +or equal to \f[B]0\f[R], it returns \f[B]a(y/x)+pi\f[R]. +If \f[B]x\f[R] is less than \f[B]0\f[R], and \f[B]y\f[R] is less than +\f[B]0\f[R], it returns \f[B]a(y/x)-pi\f[R]. +If \f[B]x\f[R] is equal to \f[B]0\f[R], and \f[B]y\f[R] is greater than +\f[B]0\f[R], it returns \f[B]pi/2\f[R]. +If \f[B]x\f[R] is equal to \f[B]0\f[R], and \f[B]y\f[R] is less than +\f[B]0\f[R], it returns \f[B]-pi/2\f[R]. +.RS +.PP +This function is the same as the \f[B]atan2()\f[R] function in many +programming languages. +.PP +This is an alias of \f[B]a2(y, x)\f[R]. +.PP +This is a transcendental function (see the \f[I]Transcendental +Functions\f[R] subsection below). +.RE +.TP +\f[B]r2d(x)\f[R] +Converts \f[B]x\f[R] from radians to degrees and returns the result. +.RS +.PP +This is a transcendental function (see the \f[I]Transcendental +Functions\f[R] subsection below). +.RE +.TP +\f[B]d2r(x)\f[R] +Converts \f[B]x\f[R] from degrees to radians and returns the result. +.RS +.PP +This is a transcendental function (see the \f[I]Transcendental +Functions\f[R] subsection below). +.RE +.TP +\f[B]frand(p)\f[R] +Generates a pseudo-random number between \f[B]0\f[R] (inclusive) and +\f[B]1\f[R] (exclusive) with the number of decimal digits after the +decimal point equal to the truncated absolute value of \f[B]p\f[R]. +If \f[B]p\f[R] is not \f[B]0\f[R], then calling this function will +change the value of \f[B]seed\f[R]. +If \f[B]p\f[R] is \f[B]0\f[R], then \f[B]0\f[R] is returned, and +\f[B]seed\f[R] is \f[I]not\f[R] changed. +.TP +\f[B]ifrand(i, p)\f[R] +Generates a pseudo-random number that is between \f[B]0\f[R] (inclusive) +and the truncated absolute value of \f[B]i\f[R] (exclusive) with the +number of decimal digits after the decimal point equal to the truncated +absolute value of \f[B]p\f[R]. +If the absolute value of \f[B]i\f[R] is greater than or equal to +\f[B]2\f[R], and \f[B]p\f[R] is not \f[B]0\f[R], then calling this +function will change the value of \f[B]seed\f[R]; otherwise, \f[B]0\f[R] +is returned and \f[B]seed\f[R] is not changed. +.TP +\f[B]srand(x)\f[R] +Returns \f[B]x\f[R] with its sign flipped with probability +\f[B]0.5\f[R]. +In other words, it randomizes the sign of \f[B]x\f[R]. +.TP +\f[B]brand()\f[R] +Returns a random boolean value (either \f[B]0\f[R] or \f[B]1\f[R]). +.TP +\f[B]ubytes(x)\f[R] +Returns the numbers of unsigned integer bytes required to hold the +truncated absolute value of \f[B]x\f[R]. +.TP +\f[B]sbytes(x)\f[R] +Returns the numbers of signed, two\[cq]s-complement integer bytes +required to hold the truncated value of \f[B]x\f[R]. +.TP +\f[B]hex(x)\f[R] +Outputs the hexadecimal (base \f[B]16\f[R]) representation of +\f[B]x\f[R]. +.RS +.PP +This is a \f[B]void\f[R] function (see the \f[I]Void Functions\f[R] +subsection of the \f[B]FUNCTIONS\f[R] section). +.RE +.TP +\f[B]binary(x)\f[R] +Outputs the binary (base \f[B]2\f[R]) representation of \f[B]x\f[R]. +.RS +.PP +This is a \f[B]void\f[R] function (see the \f[I]Void Functions\f[R] +subsection of the \f[B]FUNCTIONS\f[R] section). +.RE +.TP +\f[B]output(x, b)\f[R] +Outputs the base \f[B]b\f[R] representation of \f[B]x\f[R]. +.RS +.PP +This is a \f[B]void\f[R] function (see the \f[I]Void Functions\f[R] +subsection of the \f[B]FUNCTIONS\f[R] section). +.RE +.TP +\f[B]uint(x)\f[R] +Outputs the representation, in binary and hexadecimal, of \f[B]x\f[R] as +an unsigned integer in as few power of two bytes as possible. +Both outputs are split into bytes separated by spaces. +.RS +.PP +If \f[B]x\f[R] is not an integer or is negative, an error message is +printed instead, but bc(1) is not reset (see the \f[B]RESET\f[R] +section). +.PP +This is a \f[B]void\f[R] function (see the \f[I]Void Functions\f[R] +subsection of the \f[B]FUNCTIONS\f[R] section). +.RE +.TP +\f[B]int(x)\f[R] +Outputs the representation, in binary and hexadecimal, of \f[B]x\f[R] as +a signed, two\[cq]s-complement integer in as few power of two bytes as +possible. +Both outputs are split into bytes separated by spaces. +.RS +.PP +If \f[B]x\f[R] is not an integer, an error message is printed instead, +but bc(1) is not reset (see the \f[B]RESET\f[R] section). +.PP +This is a \f[B]void\f[R] function (see the \f[I]Void Functions\f[R] +subsection of the \f[B]FUNCTIONS\f[R] section). +.RE +.TP +\f[B]uintn(x, n)\f[R] +Outputs the representation, in binary and hexadecimal, of \f[B]x\f[R] as +an unsigned integer in \f[B]n\f[R] bytes. +Both outputs are split into bytes separated by spaces. +.RS +.PP +If \f[B]x\f[R] is not an integer, is negative, or cannot fit into +\f[B]n\f[R] bytes, an error message is printed instead, but bc(1) is not +reset (see the \f[B]RESET\f[R] section). +.PP +This is a \f[B]void\f[R] function (see the \f[I]Void Functions\f[R] +subsection of the \f[B]FUNCTIONS\f[R] section). +.RE +.TP +\f[B]intn(x, n)\f[R] +Outputs the representation, in binary and hexadecimal, of \f[B]x\f[R] as +a signed, two\[cq]s-complement integer in \f[B]n\f[R] bytes. +Both outputs are split into bytes separated by spaces. +.RS +.PP +If \f[B]x\f[R] is not an integer or cannot fit into \f[B]n\f[R] bytes, +an error message is printed instead, but bc(1) is not reset (see the +\f[B]RESET\f[R] section). +.PP +This is a \f[B]void\f[R] function (see the \f[I]Void Functions\f[R] +subsection of the \f[B]FUNCTIONS\f[R] section). +.RE +.TP +\f[B]uint8(x)\f[R] +Outputs the representation, in binary and hexadecimal, of \f[B]x\f[R] as +an unsigned integer in \f[B]1\f[R] byte. +Both outputs are split into bytes separated by spaces. +.RS +.PP +If \f[B]x\f[R] is not an integer, is negative, or cannot fit into +\f[B]1\f[R] byte, an error message is printed instead, but bc(1) is not +reset (see the \f[B]RESET\f[R] section). +.PP +This is a \f[B]void\f[R] function (see the \f[I]Void Functions\f[R] +subsection of the \f[B]FUNCTIONS\f[R] section). +.RE +.TP +\f[B]int8(x)\f[R] +Outputs the representation, in binary and hexadecimal, of \f[B]x\f[R] as +a signed, two\[cq]s-complement integer in \f[B]1\f[R] byte. +Both outputs are split into bytes separated by spaces. +.RS +.PP +If \f[B]x\f[R] is not an integer or cannot fit into \f[B]1\f[R] byte, an +error message is printed instead, but bc(1) is not reset (see the +\f[B]RESET\f[R] section). +.PP +This is a \f[B]void\f[R] function (see the \f[I]Void Functions\f[R] +subsection of the \f[B]FUNCTIONS\f[R] section). +.RE +.TP +\f[B]uint16(x)\f[R] +Outputs the representation, in binary and hexadecimal, of \f[B]x\f[R] as +an unsigned integer in \f[B]2\f[R] bytes. +Both outputs are split into bytes separated by spaces. +.RS +.PP +If \f[B]x\f[R] is not an integer, is negative, or cannot fit into +\f[B]2\f[R] bytes, an error message is printed instead, but bc(1) is not +reset (see the \f[B]RESET\f[R] section). +.PP +This is a \f[B]void\f[R] function (see the \f[I]Void Functions\f[R] +subsection of the \f[B]FUNCTIONS\f[R] section). +.RE +.TP +\f[B]int16(x)\f[R] +Outputs the representation, in binary and hexadecimal, of \f[B]x\f[R] as +a signed, two\[cq]s-complement integer in \f[B]2\f[R] bytes. +Both outputs are split into bytes separated by spaces. +.RS +.PP +If \f[B]x\f[R] is not an integer or cannot fit into \f[B]2\f[R] bytes, +an error message is printed instead, but bc(1) is not reset (see the +\f[B]RESET\f[R] section). +.PP +This is a \f[B]void\f[R] function (see the \f[I]Void Functions\f[R] +subsection of the \f[B]FUNCTIONS\f[R] section). +.RE +.TP +\f[B]uint32(x)\f[R] +Outputs the representation, in binary and hexadecimal, of \f[B]x\f[R] as +an unsigned integer in \f[B]4\f[R] bytes. +Both outputs are split into bytes separated by spaces. +.RS +.PP +If \f[B]x\f[R] is not an integer, is negative, or cannot fit into +\f[B]4\f[R] bytes, an error message is printed instead, but bc(1) is not +reset (see the \f[B]RESET\f[R] section). +.PP +This is a \f[B]void\f[R] function (see the \f[I]Void Functions\f[R] +subsection of the \f[B]FUNCTIONS\f[R] section). +.RE +.TP +\f[B]int32(x)\f[R] +Outputs the representation, in binary and hexadecimal, of \f[B]x\f[R] as +a signed, two\[cq]s-complement integer in \f[B]4\f[R] bytes. +Both outputs are split into bytes separated by spaces. +.RS +.PP +If \f[B]x\f[R] is not an integer or cannot fit into \f[B]4\f[R] bytes, +an error message is printed instead, but bc(1) is not reset (see the +\f[B]RESET\f[R] section). +.PP +This is a \f[B]void\f[R] function (see the \f[I]Void Functions\f[R] +subsection of the \f[B]FUNCTIONS\f[R] section). +.RE +.TP +\f[B]uint64(x)\f[R] +Outputs the representation, in binary and hexadecimal, of \f[B]x\f[R] as +an unsigned integer in \f[B]8\f[R] bytes. +Both outputs are split into bytes separated by spaces. +.RS +.PP +If \f[B]x\f[R] is not an integer, is negative, or cannot fit into +\f[B]8\f[R] bytes, an error message is printed instead, but bc(1) is not +reset (see the \f[B]RESET\f[R] section). +.PP +This is a \f[B]void\f[R] function (see the \f[I]Void Functions\f[R] +subsection of the \f[B]FUNCTIONS\f[R] section). +.RE +.TP +\f[B]int64(x)\f[R] +Outputs the representation, in binary and hexadecimal, of \f[B]x\f[R] as +a signed, two\[cq]s-complement integer in \f[B]8\f[R] bytes. +Both outputs are split into bytes separated by spaces. +.RS +.PP +If \f[B]x\f[R] is not an integer or cannot fit into \f[B]8\f[R] bytes, +an error message is printed instead, but bc(1) is not reset (see the +\f[B]RESET\f[R] section). +.PP +This is a \f[B]void\f[R] function (see the \f[I]Void Functions\f[R] +subsection of the \f[B]FUNCTIONS\f[R] section). +.RE +.TP +\f[B]hex_uint(x, n)\f[R] +Outputs the representation of the truncated absolute value of +\f[B]x\f[R] as an unsigned integer in hexadecimal using \f[B]n\f[R] +bytes. +Not all of the value will be output if \f[B]n\f[R] is too small. +.RS +.PP +This is a \f[B]void\f[R] function (see the \f[I]Void Functions\f[R] +subsection of the \f[B]FUNCTIONS\f[R] section). +.RE +.TP +\f[B]binary_uint(x, n)\f[R] +Outputs the representation of the truncated absolute value of +\f[B]x\f[R] as an unsigned integer in binary using \f[B]n\f[R] bytes. +Not all of the value will be output if \f[B]n\f[R] is too small. +.RS +.PP +This is a \f[B]void\f[R] function (see the \f[I]Void Functions\f[R] +subsection of the \f[B]FUNCTIONS\f[R] section). +.RE +.TP +\f[B]output_uint(x, n)\f[R] +Outputs the representation of the truncated absolute value of +\f[B]x\f[R] as an unsigned integer in the current \f[B]obase\f[R] (see +the \f[B]SYNTAX\f[R] section) using \f[B]n\f[R] bytes. +Not all of the value will be output if \f[B]n\f[R] is too small. +.RS +.PP +This is a \f[B]void\f[R] function (see the \f[I]Void Functions\f[R] +subsection of the \f[B]FUNCTIONS\f[R] section). +.RE +.TP +\f[B]output_byte(x, i)\f[R] +Outputs byte \f[B]i\f[R] of the truncated absolute value of \f[B]x\f[R], +where \f[B]0\f[R] is the least significant byte and \f[B]number_of_bytes +- 1\f[R] is the most significant byte. +.RS +.PP +This is a \f[B]void\f[R] function (see the \f[I]Void Functions\f[R] +subsection of the \f[B]FUNCTIONS\f[R] section). +.RE +.SS Transcendental Functions +.PP +All transcendental functions can return slightly inaccurate results (up +to 1 ULP (https://en.wikipedia.org/wiki/Unit_in_the_last_place)). +This is unavoidable, and this +article (https://people.eecs.berkeley.edu/~wkahan/LOG10HAF.TXT) explains +why it is impossible and unnecessary to calculate exact results for the +transcendental functions. +.PP +Because of the possible inaccuracy, I recommend that users call those +functions with the precision (\f[B]scale\f[R]) set to at least 1 higher +than is necessary. +If exact results are \f[I]absolutely\f[R] required, users can double the +precision (\f[B]scale\f[R]) and then truncate. +.PP +The transcendental functions in the standard math library are: +.IP \[bu] 2 +\f[B]s(x)\f[R] +.IP \[bu] 2 +\f[B]c(x)\f[R] +.IP \[bu] 2 +\f[B]a(x)\f[R] +.IP \[bu] 2 +\f[B]l(x)\f[R] +.IP \[bu] 2 +\f[B]e(x)\f[R] +.IP \[bu] 2 +\f[B]j(x, n)\f[R] +.PP +The transcendental functions in the extended math library are: +.IP \[bu] 2 +\f[B]l2(x)\f[R] +.IP \[bu] 2 +\f[B]l10(x)\f[R] +.IP \[bu] 2 +\f[B]log(x, b)\f[R] +.IP \[bu] 2 +\f[B]pi(p)\f[R] +.IP \[bu] 2 +\f[B]t(x)\f[R] +.IP \[bu] 2 +\f[B]a2(y, x)\f[R] +.IP \[bu] 2 +\f[B]sin(x)\f[R] +.IP \[bu] 2 +\f[B]cos(x)\f[R] +.IP \[bu] 2 +\f[B]tan(x)\f[R] +.IP \[bu] 2 +\f[B]atan(x)\f[R] +.IP \[bu] 2 +\f[B]atan2(y, x)\f[R] +.IP \[bu] 2 +\f[B]r2d(x)\f[R] +.IP \[bu] 2 +\f[B]d2r(x)\f[R] +.SH RESET +.PP +When bc(1) encounters an error or a signal that it has a non-default +handler for, it resets. +This means that several things happen. +.PP +First, any functions that are executing are stopped and popped off the +stack. +The behavior is not unlike that of exceptions in programming languages. +Then the execution point is set so that any code waiting to execute +(after all functions returned) is skipped. +.PP +Thus, when bc(1) resets, it skips any remaining code waiting to be +executed. +Then, if it is interactive mode, and the error was not a fatal error +(see the \f[B]EXIT STATUS\f[R] section), it asks for more input; +otherwise, it exits with the appropriate return code. +.PP +Note that this reset behavior is different from the GNU bc(1), which +attempts to start executing the statement right after the one that +caused an error. +.SH PERFORMANCE +.PP +Most bc(1) implementations use \f[B]char\f[R] types to calculate the +value of \f[B]1\f[R] decimal digit at a time, but that can be slow. +This bc(1) does something different. +.PP +It uses large integers to calculate more than \f[B]1\f[R] decimal digit +at a time. +If built in a environment where \f[B]BC_LONG_BIT\f[R] (see the +\f[B]LIMITS\f[R] section) is \f[B]64\f[R], then each integer has +\f[B]9\f[R] decimal digits. +If built in an environment where \f[B]BC_LONG_BIT\f[R] is \f[B]32\f[R] +then each integer has \f[B]4\f[R] decimal digits. +This value (the number of decimal digits per large integer) is called +\f[B]BC_BASE_DIGS\f[R]. +.PP +The actual values of \f[B]BC_LONG_BIT\f[R] and \f[B]BC_BASE_DIGS\f[R] +can be queried with the \f[B]limits\f[R] statement. +.PP +In addition, this bc(1) uses an even larger integer for overflow +checking. +This integer type depends on the value of \f[B]BC_LONG_BIT\f[R], but is +always at least twice as large as the integer type used to store digits. +.SH LIMITS +.PP +The following are the limits on bc(1): +.TP +\f[B]BC_LONG_BIT\f[R] +The number of bits in the \f[B]long\f[R] type in the environment where +bc(1) was built. +This determines how many decimal digits can be stored in a single large +integer (see the \f[B]PERFORMANCE\f[R] section). +.TP +\f[B]BC_BASE_DIGS\f[R] +The number of decimal digits per large integer (see the +\f[B]PERFORMANCE\f[R] section). +Depends on \f[B]BC_LONG_BIT\f[R]. +.TP +\f[B]BC_BASE_POW\f[R] +The max decimal number that each large integer can store (see +\f[B]BC_BASE_DIGS\f[R]) plus \f[B]1\f[R]. +Depends on \f[B]BC_BASE_DIGS\f[R]. +.TP +\f[B]BC_OVERFLOW_MAX\f[R] +The max number that the overflow type (see the \f[B]PERFORMANCE\f[R] +section) can hold. +Depends on \f[B]BC_LONG_BIT\f[R]. +.TP +\f[B]BC_BASE_MAX\f[R] +The maximum output base. +Set at \f[B]BC_BASE_POW\f[R]. +.TP +\f[B]BC_DIM_MAX\f[R] +The maximum size of arrays. +Set at \f[B]SIZE_MAX-1\f[R]. +.TP +\f[B]BC_SCALE_MAX\f[R] +The maximum \f[B]scale\f[R]. +Set at \f[B]BC_OVERFLOW_MAX-1\f[R]. +.TP +\f[B]BC_STRING_MAX\f[R] +The maximum length of strings. +Set at \f[B]BC_OVERFLOW_MAX-1\f[R]. +.TP +\f[B]BC_NAME_MAX\f[R] +The maximum length of identifiers. +Set at \f[B]BC_OVERFLOW_MAX-1\f[R]. +.TP +\f[B]BC_NUM_MAX\f[R] +The maximum length of a number (in decimal digits), which includes +digits after the decimal point. +Set at \f[B]BC_OVERFLOW_MAX-1\f[R]. +.TP +\f[B]BC_RAND_MAX\f[R] +The maximum integer (inclusive) returned by the \f[B]rand()\f[R] +operand. +Set at \f[B]2\[ha]BC_LONG_BIT-1\f[R]. +.TP +Exponent +The maximum allowable exponent (positive or negative). +Set at \f[B]BC_OVERFLOW_MAX\f[R]. +.TP +Number of vars +The maximum number of vars/arrays. +Set at \f[B]SIZE_MAX-1\f[R]. +.PP +The actual values can be queried with the \f[B]limits\f[R] statement. +.PP +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 ENVIRONMENT VARIABLES +.PP +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 +the \f[B]-s\f[R] option was given. +.TP +\f[B]BC_ENV_ARGS\f[R] +This is another way to give command-line arguments to bc(1). +They should be in the same format as all other command-line arguments. +These are always processed first, so any files given in +\f[B]BC_ENV_ARGS\f[R] will be processed before arguments and files given +on the command-line. +This gives the user the ability to set up \[lq]standard\[rq] options and +files to be used at every invocation. +The most useful thing for such files to contain would be useful +functions that the user might want every time bc(1) runs. +.RS +.PP +The code that parses \f[B]BC_ENV_ARGS\f[R] will correctly handle quoted +arguments, but it does not understand escape sequences. +For example, the string \f[B]\[lq]/home/gavin/some bc file.bc\[rq]\f[R] +will be correctly parsed, but the string \f[B]\[lq]/home/gavin/some +\[dq]bc\[dq] file.bc\[rq]\f[R] will include the backslashes. +.PP +The quote parsing will handle either kind of quotes, \f[B]\[cq]\f[R] or +\f[B]\[lq]\f[R]. Thus, if you have a file with any number of single +quotes in the name, you can use double quotes as the outside quotes, as +in \f[B]\[rq]some `bc' file.bc\[dq]\f[R], and vice versa if you have a +file with double quotes. +However, handling a file with both kinds of quotes in +\f[B]BC_ENV_ARGS\f[R] is not supported due to the complexity of the +parsing, though such files are still supported on the command-line where +the parsing is done by the shell. +.RE +.TP +\f[B]BC_LINE_LENGTH\f[R] +If this environment variable exists and contains an integer that is +greater than \f[B]1\f[R] and is less than \f[B]UINT16_MAX\f[R] +(\f[B]2\[ha]16-1\f[R]), bc(1) will output lines to that length, +including the backslash (\f[B]\[rs]\f[R]). +The default line length is \f[B]70\f[R]. +.SH EXIT STATUS +.PP +bc(1) returns the following exit statuses: +.TP +\f[B]0\f[R] +No error. +.TP +\f[B]1\f[R] +A math error occurred. +This follows standard practice of using \f[B]1\f[R] for expected errors, +since math errors will happen in the process of normal execution. +.RS +.PP +Math errors include divide by \f[B]0\f[R], taking the square root of a +negative number, using a negative number as a bound for the +pseudo-random number generator, attempting to convert a negative number +to a hardware integer, overflow when converting a number to a hardware +integer, and attempting to use a non-integer where an integer is +required. +.PP +Converting to a hardware integer happens for the second operand of the +power (\f[B]\[ha]\f[R]), places (\f[B]\[at]\f[R]), left shift +(\f[B]<<\f[R]), and right shift (\f[B]>>\f[R]) operators and their +corresponding assignment operators. +.RE +.TP +\f[B]2\f[R] +A parse error occurred. +.RS +.PP +Parse errors include unexpected \f[B]EOF\f[R], using an invalid +character, failing to find the end of a string or comment, using a token +where it is invalid, giving an invalid expression, giving an invalid +print statement, giving an invalid function definition, attempting to +assign to an expression that is not a named expression (see the +\f[I]Named Expressions\f[R] subsection of the \f[B]SYNTAX\f[R] section), +giving an invalid \f[B]auto\f[R] list, having a duplicate +\f[B]auto\f[R]/function parameter, failing to find the end of a code +block, attempting to return a value from a \f[B]void\f[R] function, +attempting to use a variable as a reference, and using any extensions +when the option \f[B]-s\f[R] or any equivalents were given. +.RE +.TP +\f[B]3\f[R] +A runtime error occurred. +.RS +.PP +Runtime errors include assigning an invalid number to \f[B]ibase\f[R], +\f[B]obase\f[R], or \f[B]scale\f[R]; give a bad expression to a +\f[B]read()\f[R] call, calling \f[B]read()\f[R] inside of a +\f[B]read()\f[R] call, type errors, passing the wrong number of +arguments to functions, attempting to call an undefined function, and +attempting to use a \f[B]void\f[R] function call as a value in an +expression. +.RE +.TP +\f[B]4\f[R] +A fatal error occurred. +.RS +.PP +Fatal errors include memory allocation errors, I/O errors, failing to +open files, attempting to use files that do not have only ASCII +characters (bc(1) only accepts ASCII characters), attempting to open a +directory as a file, and giving invalid command-line options. +.RE +.PP +The exit status \f[B]4\f[R] is special; when a fatal error occurs, bc(1) +always exits and returns \f[B]4\f[R], no matter what mode bc(1) is in. +.PP +The other statuses will only be returned when bc(1) is not in +interactive mode (see the \f[B]INTERACTIVE MODE\f[R] section), since +bc(1) resets its state (see the \f[B]RESET\f[R] section) and accepts +more input when one of those errors occurs in interactive mode. +This is also the case when interactive mode is forced by the +\f[B]-i\f[R] flag or \f[B]\[en]interactive\f[R] option. +.PP +These exit statuses allow bc(1) to be used in shell scripting with error +checking, and its normal behavior can be forced by using the +\f[B]-i\f[R] flag or \f[B]\[en]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. +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]\[en]interactive\f[R] option can turn it on in other cases. +.PP +In interactive mode, bc(1) attempts to recover from errors (see the +\f[B]RESET\f[R] section), and in normal execution, flushes +\f[B]stdout\f[R] as soon as execution is done for the current input. +.SH TTY MODE +.PP +If \f[B]stdin\f[R], \f[B]stdout\f[R], and \f[B]stderr\f[R] are all +connected to a TTY, bc(1) turns on \[lq]TTY mode.\[rq] +.PP +TTY mode is required for history to be enabled (see the \f[B]COMMAND +LINE HISTORY\f[R] section). +It is also required to enable special handling for \f[B]SIGINT\f[R] +signals. +.PP +TTY mode is different from interactive mode because interactive mode is +required in the bc(1) +specification (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. +.SH SIGNAL HANDLING +.PP +Sending a \f[B]SIGINT\f[R] will cause bc(1) to stop execution of the +current input. +If bc(1) is in TTY mode (see the \f[B]TTY MODE\f[R] section), it will +reset (see the \f[B]RESET\f[R] section). +Otherwise, it will clean up and exit. +.PP +Note that \[lq]current input\[rq] can mean one of two things. +If bc(1) is processing input from \f[B]stdin\f[R] in TTY mode, it will +ask for more input. +If bc(1) is processing input from a file in TTY mode, it will stop +processing the file and start processing the next file, if one exists, +or ask for input from \f[B]stdin\f[R] if no other file exists. +.PP +This means that if a \f[B]SIGINT\f[R] is sent to bc(1) as it is +executing a file, it can seem as though bc(1) did not respond to the +signal since it will immediately start executing the next file. +This is by design; most files that users execute when interacting with +bc(1) have function definitions, which are quick to parse. +If a file takes a long time to execute, there may be a bug in that file. +The rest of the files could still be executed without problem, allowing +the user to continue. +.PP +\f[B]SIGTERM\f[R] and \f[B]SIGQUIT\f[R] cause bc(1) to clean up and +exit, and it uses the default handler for all other signals. +The one exception is \f[B]SIGHUP\f[R]; in that case, when bc(1) is in +TTY mode, a \f[B]SIGHUP\f[R] will cause bc(1) to clean up and exit. +.SH COMMAND LINE HISTORY +.PP +bc(1) supports interactive command-line editing. +If bc(1) is in TTY mode (see the \f[B]TTY MODE\f[R] section), history is +enabled. +Previous lines can be recalled and edited with the arrow keys. +.PP +\f[B]Note\f[R]: tabs are converted to 8 spaces. +.SH SEE ALSO +.PP +dc(1) +.SH STANDARDS +.PP +bc(1) is compliant with the IEEE Std 1003.1-2017 +(\[lq]POSIX.1-2017\[rq]) (https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html) +specification. +The flags \f[B]-efghiqsvVw\f[R], all long options, and the extensions +noted above are extensions to that specification. +.PP +Note that the specification explicitly says that bc(1) only accepts +numbers that use a period (\f[B].\f[R]) as a radix point, regardless of +the value of \f[B]LC_NUMERIC\f[R]. +.SH BUGS +.PP +None are known. +Report bugs at https://git.yzena.com/gavin/bc. +.SH AUTHORS +.PP +Gavin D. +Howard <gavin@yzena.com> and contributors. |