You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1269 lines
38 KiB
1269 lines
38 KiB
.\" |
|
.\" SPDX-License-Identifier: BSD-2-Clause |
|
.\" |
|
.\" Copyright (c) 2018-2020 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 "DC" "1" "July 2020" "Gavin D. Howard" "General Commands Manual" |
|
.SH Name |
|
.PP |
|
dc \- arbitrary\-precision reverse\-Polish notation calculator |
|
.SH SYNOPSIS |
|
.PP |
|
\f[B]dc\f[] [\f[B]\-hiPvVx\f[]] [\f[B]\-\-version\f[]] |
|
[\f[B]\-\-help\f[]] [\f[B]\-\-interactive\f[]] [\f[B]\-\-no\-prompt\f[]] |
|
[\f[B]\-\-extended\-register\f[]] [\f[B]\-e\f[] \f[I]expr\f[]] |
|
[\f[B]\-\-expression\f[]=\f[I]expr\f[]...] [\f[B]\-f\f[] |
|
\f[I]file\f[]...] [\f[B]\-file\f[]=\f[I]file\f[]...] [\f[I]file\f[]...] |
|
.SH DESCRIPTION |
|
.PP |
|
dc(1) is an arbitrary\-precision calculator. |
|
It uses a stack (reverse Polish notation) to store numbers and results |
|
of computations. |
|
Arithmetic operations pop arguments off of the stack and push the |
|
results. |
|
.PP |
|
If no files are given on the command\-line as extra arguments (i.e., not |
|
as \f[B]\-f\f[] or \f[B]\-\-file\f[] arguments), then dc(1) reads from |
|
\f[B]stdin\f[]. |
|
Otherwise, those files are processed, and dc(1) will then exit. |
|
.PP |
|
This is different from the dc(1) on OpenBSD and possibly other dc(1) |
|
implementations, where \f[B]\-e\f[] (\f[B]\-\-expression\f[]) and |
|
\f[B]\-f\f[] (\f[B]\-\-file\f[]) arguments cause dc(1) to execute them |
|
and exit. |
|
The reason for this is that this dc(1) allows users to set arguments in |
|
the environment variable \f[B]DC_ENV_ARGS\f[] (see the \f[B]ENVIRONMENT |
|
VARIABLES\f[] section). |
|
Any expressions given on the command\-line should be used to set up a |
|
standard environment. |
|
For example, if a user wants the \f[B]scale\f[] always set to |
|
\f[B]10\f[], they can set \f[B]DC_ENV_ARGS\f[] to \f[B]\-e 10k\f[], and |
|
this dc(1) will always start with a \f[B]scale\f[] of \f[B]10\f[]. |
|
.PP |
|
If users want to have dc(1) exit after processing all input from |
|
\f[B]\-e\f[] and \f[B]\-f\f[] arguments (and their equivalents), then |
|
they can just simply add \f[B]\-e q\f[] as the last command\-line |
|
argument or define the environment variable \f[B]DC_EXPR_EXIT\f[]. |
|
.SH OPTIONS |
|
.PP |
|
The following are the options that dc(1) accepts. |
|
.IP \[bu] 2 |
|
\f[B]\-h\f[], \f[B]\-\-help\f[] |
|
.RS 2 |
|
.PP |
|
Prints a usage message and quits. |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]\-v\f[], \f[B]\-V\f[], \f[B]\-\-version\f[] |
|
.RS 2 |
|
.PP |
|
Print the version information (copyright header) and exit. |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]\-i\f[], \f[B]\-\-interactive\f[] |
|
.RS 2 |
|
.PP |
|
Forces interactive mode. |
|
(See the \f[B]INTERACTIVE MODE\f[] section.) |
|
.PP |
|
This is a \f[B]non\-portable extension\f[]. |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]\-P\f[], \f[B]\-\-no\-prompt\f[] |
|
.RS 2 |
|
.PP |
|
This option is a no\-op. |
|
.PP |
|
This is a \f[B]non\-portable extension\f[]. |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]\-x\f[] \f[B]\-\-extended\-register\f[] |
|
.RS 2 |
|
.PP |
|
Enables extended register mode. |
|
See the \f[I]Extended Register Mode\f[] subsection of the |
|
\f[B]REGISTERS\f[] section for more information. |
|
.PP |
|
This is a \f[B]non\-portable extension\f[]. |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]\-e\f[] \f[I]expr\f[], \f[B]\-\-expression\f[]=\f[I]expr\f[] |
|
.RS 2 |
|
.PP |
|
Evaluates \f[I]expr\f[]. |
|
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. |
|
.PP |
|
In other dc(1) implementations, this option causes the program to |
|
execute the expressions and then exit. |
|
This dc(1) does not, unless the \f[B]DC_EXPR_EXIT\f[] is defined (see |
|
the \f[B]ENVIRONMENT VARIABLES\f[] section). |
|
.PP |
|
This is a \f[B]non\-portable extension\f[]. |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]\-f\f[] \f[I]file\f[], \f[B]\-\-file\f[]=\f[I]file\f[] |
|
.RS 2 |
|
.PP |
|
Reads in \f[I]file\f[] and evaluates it. |
|
If expressions are also given (see above), the expressions are evaluated |
|
in the order given. |
|
.PP |
|
In other dc(1) implementations, this option causes the program to |
|
execute the files and then exit. |
|
This dc(1) does not, unless the \f[B]DC_EXPR_EXIT\f[] is defined (see |
|
the \f[B]ENVIRONMENT VARIABLES\f[] section). |
|
.PP |
|
This is a \f[B]non\-portable extension\f[]. |
|
.RE |
|
.PP |
|
All long options are \f[B]non\-portable extensions\f[]. |
|
.SH STDOUT |
|
.PP |
|
Any non\-error output is written to \f[B]stdout\f[]. |
|
.PP |
|
\f[B]Note\f[]: Unlike other dc(1) implementations, this dc(1) will issue |
|
a fatal error (see the \f[B]EXIT STATUS\f[] section) if it cannot write |
|
to \f[B]stdout\f[], so if \f[B]stdout\f[] is closed, as in \f[B]dc |
|
>&\-\f[], it will quit with an error. |
|
This is done so that dc(1) can report problems when \f[B]stdout\f[] is |
|
redirected to a file. |
|
.PP |
|
If there are scripts that depend on the behavior of other dc(1) |
|
implementations, it is recommended that those scripts be changed to |
|
redirect \f[B]stdout\f[] to \f[B]/dev/null\f[]. |
|
.SH STDERR |
|
.PP |
|
Any error output is written to \f[B]stderr\f[]. |
|
.PP |
|
\f[B]Note\f[]: Unlike other dc(1) implementations, this dc(1) will issue |
|
a fatal error (see the \f[B]EXIT STATUS\f[] section) if it cannot write |
|
to \f[B]stderr\f[], so if \f[B]stderr\f[] is closed, as in \f[B]dc |
|
2>&\-\f[], it will quit with an error. |
|
This is done so that dc(1) can exit with an error code when |
|
\f[B]stderr\f[] is redirected to a file. |
|
.PP |
|
If there are scripts that depend on the behavior of other dc(1) |
|
implementations, it is recommended that those scripts be changed to |
|
redirect \f[B]stderr\f[] to \f[B]/dev/null\f[]. |
|
.SH SYNTAX |
|
.PP |
|
Each item in the input source code, either a number (see the |
|
\f[B]NUMBERS\f[] section) or a command (see the \f[B]COMMANDS\f[] |
|
section), is processed and executed, in order. |
|
Input is processed immediately when entered. |
|
.PP |
|
\f[B]ibase\f[] is a register (see the \f[B]REGISTERS\f[] section) that |
|
determines how to interpret constant numbers. |
|
It is the "input" base, or the number base used for interpreting input |
|
numbers. |
|
\f[B]ibase\f[] is initially \f[B]10\f[]. |
|
The max allowable value for \f[B]ibase\f[] is \f[B]16\f[]. |
|
The min allowable value for \f[B]ibase\f[] is \f[B]2\f[]. |
|
The max allowable value for \f[B]ibase\f[] can be queried in dc(1) |
|
programs with the \f[B]T\f[] command. |
|
.PP |
|
\f[B]obase\f[] is a register (see the \f[B]REGISTERS\f[] section) that |
|
determines how to output results. |
|
It is the "output" base, or the number base used for outputting numbers. |
|
\f[B]obase\f[] is initially \f[B]10\f[]. |
|
The max allowable value for \f[B]obase\f[] is \f[B]DC_BASE_MAX\f[] and |
|
can be queried with the \f[B]U\f[] command. |
|
The min allowable value for \f[B]obase\f[] is \f[B]2\f[]. |
|
Values are output in the specified base. |
|
.PP |
|
The \f[I]scale\f[] of an expression is the number of digits in the |
|
result of the expression right of the decimal point, and \f[B]scale\f[] |
|
is a register (see the \f[B]REGISTERS\f[] section) that sets the |
|
precision of any operations (with exceptions). |
|
\f[B]scale\f[] is initially \f[B]0\f[]. |
|
\f[B]scale\f[] cannot be negative. |
|
The max allowable value for \f[B]scale\f[] can be queried in dc(1) |
|
programs with the \f[B]V\f[] command. |
|
.SS Comments |
|
.PP |
|
Comments go from \f[B]#\f[] until, and not including, the next newline. |
|
This is a \f[B]non\-portable extension\f[]. |
|
.SH NUMBERS |
|
.PP |
|
Numbers are strings made up of digits, uppercase letters up to |
|
\f[B]F\f[], and at most \f[B]1\f[] period for a radix. |
|
Numbers can have up to \f[B]DC_NUM_MAX\f[] digits. |
|
Uppercase letters are equal to \f[B]9\f[] + their position in the |
|
alphabet (i.e., \f[B]A\f[] equals \f[B]10\f[], or \f[B]9+1\f[]). |
|
If a digit or letter makes no sense with the current value of |
|
\f[B]ibase\f[], they are set to the value of the highest valid digit in |
|
\f[B]ibase\f[]. |
|
.PP |
|
Single\-character numbers (i.e., \f[B]A\f[] alone) take the value that |
|
they would have if they were valid digits, regardless of the value of |
|
\f[B]ibase\f[]. |
|
This means that \f[B]A\f[] alone always equals decimal \f[B]10\f[] and |
|
\f[B]F\f[] alone always equals decimal \f[B]15\f[]. |
|
.SH COMMANDS |
|
.PP |
|
The valid commands are listed below. |
|
.SS Printing |
|
.PP |
|
These commands are used for printing. |
|
.IP \[bu] 2 |
|
\f[B]p\f[] |
|
.RS 2 |
|
.PP |
|
Prints the value on top of the stack, whether number or string, and |
|
prints a newline after. |
|
.PP |
|
This does not alter the stack. |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]n\f[] |
|
.RS 2 |
|
.PP |
|
Prints the value on top of the stack, whether number or string, and pops |
|
it off of the stack. |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]P\f[] |
|
.RS 2 |
|
.PP |
|
Pops a value off the stack. |
|
.PP |
|
If the value is a number, it is truncated and the absolute value of the |
|
result is printed as though \f[B]obase\f[] is \f[B]UCHAR_MAX+1\f[] and |
|
each digit is interpreted as an ASCII character, making it a byte |
|
stream. |
|
.PP |
|
If the value is a string, it is printed without a trailing newline. |
|
.PP |
|
This is a \f[B]non\-portable extension\f[]. |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]f\f[] |
|
.RS 2 |
|
.PP |
|
Prints the entire contents of the stack, in order from newest to oldest, |
|
without altering anything. |
|
.PP |
|
Users should use this command when they get lost. |
|
.RE |
|
.SS Arithmetic |
|
.PP |
|
These are the commands used for arithmetic. |
|
.IP \[bu] 2 |
|
\f[B]+\f[] |
|
.RS 2 |
|
.PP |
|
The top two values are popped off the stack, added, and the result is |
|
pushed onto the stack. |
|
The \f[I]scale\f[] of the result is equal to the max \f[I]scale\f[] of |
|
both operands. |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]\-\f[] |
|
.RS 2 |
|
.PP |
|
The top two values are popped off the stack, subtracted, and the result |
|
is pushed onto the stack. |
|
The \f[I]scale\f[] of the result is equal to the max \f[I]scale\f[] of |
|
both operands. |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]*\f[] |
|
.RS 2 |
|
.PP |
|
The top two values are popped off the stack, multiplied, and the result |
|
is pushed onto the stack. |
|
If \f[B]a\f[] is the \f[I]scale\f[] of the first expression and |
|
\f[B]b\f[] is the \f[I]scale\f[] of the second expression, the |
|
\f[I]scale\f[] of the result is equal to |
|
\f[B]min(a+b,max(scale,a,b))\f[] where \f[B]min()\f[] and \f[B]max()\f[] |
|
return the obvious values. |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]/\f[] |
|
.RS 2 |
|
.PP |
|
The top two values are popped off the stack, divided, and the result is |
|
pushed onto the stack. |
|
The \f[I]scale\f[] of the result is equal to \f[B]scale\f[]. |
|
.PP |
|
The first value popped off of the stack must be non\-zero. |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]%\f[] |
|
.RS 2 |
|
.PP |
|
The top two values are popped off the stack, remaindered, and the result |
|
is pushed onto the stack. |
|
Remaindering is equivalent to 1) Computing \f[B]a/b\f[] to current |
|
\f[B]scale\f[], and |
|
.IP "2)" 3 |
|
Using the result of step 1 to calculate \f[B]a\-(a/b)*b\f[] to |
|
\f[I]scale\f[] \f[B]max(scale+scale(b),scale(a))\f[]. |
|
.PP |
|
The first value popped off of the stack must be non\-zero. |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]~\f[] |
|
.RS 2 |
|
.PP |
|
The top two values are popped off the stack, divided and remaindered, |
|
and the results (divided first, remainder second) are pushed onto the |
|
stack. |
|
This is equivalent to \f[B]x y / x y %\f[] except that \f[B]x\f[] and |
|
\f[B]y\f[] are only evaluated once. |
|
.PP |
|
The first value popped off of the stack must be non\-zero. |
|
.PP |
|
This is a \f[B]non\-portable extension\f[]. |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]^\f[] |
|
.RS 2 |
|
.PP |
|
The top two values are popped off the stack, the second is raised to the |
|
power of the first, and the result is pushed onto the stack. |
|
.PP |
|
The first value popped off of the stack must be an integer, and if that |
|
value is negative, the second value popped off of the stack must be |
|
non\-zero. |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]v\f[] |
|
.RS 2 |
|
.PP |
|
The top value is popped off the stack, its square root is computed, and |
|
the result is pushed onto the stack. |
|
The \f[I]scale\f[] of the result is equal to \f[B]scale\f[]. |
|
.PP |
|
The value popped off of the stack must be non\-negative. |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]_\f[] |
|
.RS 2 |
|
.PP |
|
If this command \f[I]immediately\f[] precedes a number (i.e., no spaces |
|
or other commands), then that number is input as a negative number. |
|
.PP |
|
Otherwise, the top value on the stack is popped and copied, and the copy |
|
is negated and pushed onto the stack. |
|
This behavior without a number is a \f[B]non\-portable extension\f[]. |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]b\f[] |
|
.RS 2 |
|
.PP |
|
The top value is popped off the stack, and if it is zero, it is pushed |
|
back onto the stack. |
|
Otherwise, its absolute value is pushed onto the stack. |
|
.PP |
|
This is a \f[B]non\-portable extension\f[]. |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]|\f[] |
|
.RS 2 |
|
.PP |
|
The top three values are popped off the stack, a modular exponentiation |
|
is computed, and the result is pushed onto the stack. |
|
.PP |
|
The first value popped is used as the reduction modulus and must be an |
|
integer and non\-zero. |
|
The second value popped is used as the exponent and must be an integer |
|
and non\-negative. |
|
The third value popped is the base and must be an integer. |
|
.PP |
|
This is a \f[B]non\-portable extension\f[]. |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]G\f[] |
|
.RS 2 |
|
.PP |
|
The top two values are popped off of the stack, they are compared, and a |
|
\f[B]1\f[] is pushed if they are equal, or \f[B]0\f[] otherwise. |
|
.PP |
|
This is a \f[B]non\-portable extension\f[]. |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]N\f[] |
|
.RS 2 |
|
.PP |
|
The top value is popped off of the stack, and if it a \f[B]0\f[], a |
|
\f[B]1\f[] is pushed; otherwise, a \f[B]0\f[] is pushed. |
|
.PP |
|
This is a \f[B]non\-portable extension\f[]. |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B](\f[] |
|
.RS 2 |
|
.PP |
|
The top two values are popped off of the stack, they are compared, and a |
|
\f[B]1\f[] is pushed if the first is less than the second, or \f[B]0\f[] |
|
otherwise. |
|
.PP |
|
This is a \f[B]non\-portable extension\f[]. |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]{\f[] |
|
.RS 2 |
|
.PP |
|
The top two values are popped off of the stack, they are compared, and a |
|
\f[B]1\f[] is pushed if the first is less than or equal to the second, |
|
or \f[B]0\f[] otherwise. |
|
.PP |
|
This is a \f[B]non\-portable extension\f[]. |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B])\f[] |
|
.RS 2 |
|
.PP |
|
The top two values are popped off of the stack, they are compared, and a |
|
\f[B]1\f[] is pushed if the first is greater than the second, or |
|
\f[B]0\f[] otherwise. |
|
.PP |
|
This is a \f[B]non\-portable extension\f[]. |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]}\f[] |
|
.RS 2 |
|
.PP |
|
The top two values are popped off of the stack, they are compared, and a |
|
\f[B]1\f[] is pushed if the first is greater than or equal to the |
|
second, or \f[B]0\f[] otherwise. |
|
.PP |
|
This is a \f[B]non\-portable extension\f[]. |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]M\f[] |
|
.RS 2 |
|
.PP |
|
The top two values are popped off of the stack. |
|
If they are both non\-zero, a \f[B]1\f[] is pushed onto the stack. |
|
If either of them is zero, or both of them are, then a \f[B]0\f[] is |
|
pushed onto the stack. |
|
.PP |
|
This is like the \f[B]&&\f[] operator in bc(1), and it is \f[I]not\f[] a |
|
short\-circuit operator. |
|
.PP |
|
This is a \f[B]non\-portable extension\f[]. |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]m\f[] |
|
.RS 2 |
|
.PP |
|
The top two values are popped off of the stack. |
|
If at least one of them is non\-zero, a \f[B]1\f[] is pushed onto the |
|
stack. |
|
If both of them are zero, then a \f[B]0\f[] is pushed onto the stack. |
|
.PP |
|
This is like the \f[B]||\f[] operator in bc(1), and it is \f[I]not\f[] a |
|
short\-circuit operator. |
|
.PP |
|
This is a \f[B]non\-portable extension\f[]. |
|
.RE |
|
.SS Stack Control |
|
.PP |
|
These commands control the stack. |
|
.IP \[bu] 2 |
|
\f[B]c\f[] |
|
.RS 2 |
|
.PP |
|
Removes all items from ("clears") the stack. |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]d\f[] |
|
.RS 2 |
|
.PP |
|
Copies the item on top of the stack ("duplicates") and pushes the copy |
|
onto the stack. |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]r\f[] |
|
.RS 2 |
|
.PP |
|
Swaps ("reverses") the two top items on the stack. |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]R\f[] |
|
.RS 2 |
|
.PP |
|
Pops ("removes") the top value from the stack. |
|
.RE |
|
.SS Register Control |
|
.PP |
|
These commands control registers (see the \f[B]REGISTERS\f[] section). |
|
.IP \[bu] 2 |
|
\f[B]s\f[]\f[I]r\f[] |
|
.RS 2 |
|
.PP |
|
Pops the value off the top of the stack and stores it into register |
|
\f[I]r\f[]. |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]l\f[]\f[I]r\f[] |
|
.RS 2 |
|
.PP |
|
Copies the value in register \f[I]r\f[] and pushes it onto the stack. |
|
This does not alter the contents of \f[I]r\f[]. |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]S\f[]\f[I]r\f[] |
|
.RS 2 |
|
.PP |
|
Pops the value off the top of the (main) stack and pushes it onto the |
|
stack of register \f[I]r\f[]. |
|
The previous value of the register becomes inaccessible. |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]L\f[]\f[I]r\f[] |
|
.RS 2 |
|
.PP |
|
Pops the value off the top of the stack for register \f[I]r\f[] and push |
|
it onto the main stack. |
|
The previous value in the stack for register \f[I]r\f[], if any, is now |
|
accessible via the \f[B]l\f[]\f[I]r\f[] command. |
|
.RE |
|
.SS Parameters |
|
.PP |
|
These commands control the values of \f[B]ibase\f[], \f[B]obase\f[], and |
|
\f[B]scale\f[]. |
|
Also see the \f[B]SYNTAX\f[] section. |
|
.IP \[bu] 2 |
|
\f[B]i\f[] |
|
.RS 2 |
|
.PP |
|
Pops the value off of the top of the stack and uses it to set |
|
\f[B]ibase\f[], which must be between \f[B]2\f[] and \f[B]16\f[], |
|
inclusive. |
|
.PP |
|
If the value on top of the stack has any \f[I]scale\f[], the |
|
\f[I]scale\f[] is ignored. |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]o\f[] |
|
.RS 2 |
|
.PP |
|
Pops the value off of the top of the stack and uses it to set |
|
\f[B]obase\f[], which must be between \f[B]2\f[] and |
|
\f[B]DC_BASE_MAX\f[], inclusive (see the \f[B]LIMITS\f[] section). |
|
.PP |
|
If the value on top of the stack has any \f[I]scale\f[], the |
|
\f[I]scale\f[] is ignored. |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]k\f[] |
|
.RS 2 |
|
.PP |
|
Pops the value off of the top of the stack and uses it to set |
|
\f[B]scale\f[], which must be non\-negative. |
|
.PP |
|
If the value on top of the stack has any \f[I]scale\f[], the |
|
\f[I]scale\f[] is ignored. |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]I\f[] |
|
.RS 2 |
|
.PP |
|
Pushes the current value of \f[B]ibase\f[] onto the main stack. |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]O\f[] |
|
.RS 2 |
|
.PP |
|
Pushes the current value of \f[B]obase\f[] onto the main stack. |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]K\f[] |
|
.RS 2 |
|
.PP |
|
Pushes the current value of \f[B]scale\f[] onto the main stack. |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]T\f[] |
|
.RS 2 |
|
.PP |
|
Pushes the maximum allowable value of \f[B]ibase\f[] onto the main |
|
stack. |
|
.PP |
|
This is a \f[B]non\-portable extension\f[]. |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]U\f[] |
|
.RS 2 |
|
.PP |
|
Pushes the maximum allowable value of \f[B]obase\f[] onto the main |
|
stack. |
|
.PP |
|
This is a \f[B]non\-portable extension\f[]. |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]V\f[] |
|
.RS 2 |
|
.PP |
|
Pushes the maximum allowable value of \f[B]scale\f[] onto the main |
|
stack. |
|
.PP |
|
This is a \f[B]non\-portable extension\f[]. |
|
.RE |
|
.SS Strings |
|
.PP |
|
The following commands control strings. |
|
.PP |
|
dc(1) can work with both numbers and strings, and registers (see the |
|
\f[B]REGISTERS\f[] section) can hold both strings and numbers. |
|
dc(1) always knows whether the contents of a register are a string or a |
|
number. |
|
.PP |
|
While arithmetic operations have to have numbers, and will print an |
|
error if given a string, other commands accept strings. |
|
.PP |
|
Strings can also be executed as macros. |
|
For example, if the string \f[B][1pR]\f[] is executed as a macro, then |
|
the code \f[B]1pR\f[] is executed, meaning that the \f[B]1\f[] will be |
|
printed with a newline after and then popped from the stack. |
|
.IP \[bu] 2 |
|
\f[B][\f[]\f[I]characters\f[]\f[B]]\f[] |
|
.RS 2 |
|
.PP |
|
Makes a string containing \f[I]characters\f[] and pushes it onto the |
|
stack. |
|
.PP |
|
If there are brackets (\f[B][\f[] and \f[B]]\f[]) in the string, then |
|
they must be balanced. |
|
Unbalanced brackets can be escaped using a backslash (\f[B]\\\f[]) |
|
character. |
|
.PP |
|
If there is a backslash character in the string, the character after it |
|
(even another backslash) is put into the string verbatim, but the |
|
(first) backslash is not. |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]a\f[] |
|
.RS 2 |
|
.PP |
|
The value on top of the stack is popped. |
|
.PP |
|
If it is a number, it is truncated and its absolute value is taken. |
|
The result mod \f[B]UCHAR_MAX+1\f[] is calculated. |
|
If that result is \f[B]0\f[], push an empty string; otherwise, push a |
|
one\-character string where the character is the result of the mod |
|
interpreted as an ASCII character. |
|
.PP |
|
If it is a string, then a new string is made. |
|
If the original string is empty, the new string is empty. |
|
If it is not, then the first character of the original string is used to |
|
create the new string as a one\-character string. |
|
The new string is then pushed onto the stack. |
|
.PP |
|
This is a \f[B]non\-portable extension\f[]. |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]x\f[] |
|
.RS 2 |
|
.PP |
|
Pops a value off of the top of the stack. |
|
.PP |
|
If it is a number, it is pushed back onto the stack. |
|
.PP |
|
If it is a string, it is executed as a macro. |
|
.PP |
|
This behavior is the norm whenever a macro is executed, whether by this |
|
command or by the conditional execution commands below. |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]>\f[]\f[I]r\f[] |
|
.RS 2 |
|
.PP |
|
Pops two values off of the stack that must be numbers and compares them. |
|
If the first value is greater than the second, then the contents of |
|
register \f[I]r\f[] are executed. |
|
.PP |
|
For example, \f[B]0 1>a\f[] will execute the contents of register |
|
\f[B]a\f[], and \f[B]1 0>a\f[] will not. |
|
.PP |
|
If either or both of the values are not numbers, dc(1) will raise an |
|
error and reset (see the \f[B]RESET\f[] section). |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]>\f[]\f[I]r\f[]\f[B]e\f[]\f[I]s\f[] |
|
.RS 2 |
|
.PP |
|
Like the above, but will execute register \f[I]s\f[] if the comparison |
|
fails. |
|
.PP |
|
If either or both of the values are not numbers, dc(1) will raise an |
|
error and reset (see the \f[B]RESET\f[] section). |
|
.PP |
|
This is a \f[B]non\-portable extension\f[]. |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]!>\f[]\f[I]r\f[] |
|
.RS 2 |
|
.PP |
|
Pops two values off of the stack that must be numbers and compares them. |
|
If the first value is not greater than the second (less than or equal |
|
to), then the contents of register \f[I]r\f[] are executed. |
|
.PP |
|
If either or both of the values are not numbers, dc(1) will raise an |
|
error and reset (see the \f[B]RESET\f[] section). |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]!>\f[]\f[I]r\f[]\f[B]e\f[]\f[I]s\f[] |
|
.RS 2 |
|
.PP |
|
Like the above, but will execute register \f[I]s\f[] if the comparison |
|
fails. |
|
.PP |
|
If either or both of the values are not numbers, dc(1) will raise an |
|
error and reset (see the \f[B]RESET\f[] section). |
|
.PP |
|
This is a \f[B]non\-portable extension\f[]. |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]<\f[]\f[I]r\f[] |
|
.RS 2 |
|
.PP |
|
Pops two values off of the stack that must be numbers and compares them. |
|
If the first value is less than the second, then the contents of |
|
register \f[I]r\f[] are executed. |
|
.PP |
|
If either or both of the values are not numbers, dc(1) will raise an |
|
error and reset (see the \f[B]RESET\f[] section). |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]<\f[]\f[I]r\f[]\f[B]e\f[]\f[I]s\f[] |
|
.RS 2 |
|
.PP |
|
Like the above, but will execute register \f[I]s\f[] if the comparison |
|
fails. |
|
.PP |
|
If either or both of the values are not numbers, dc(1) will raise an |
|
error and reset (see the \f[B]RESET\f[] section). |
|
.PP |
|
This is a \f[B]non\-portable extension\f[]. |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]!<\f[]\f[I]r\f[] |
|
.RS 2 |
|
.PP |
|
Pops two values off of the stack that must be numbers and compares them. |
|
If the first value is not less than the second (greater than or equal |
|
to), then the contents of register \f[I]r\f[] are executed. |
|
.PP |
|
If either or both of the values are not numbers, dc(1) will raise an |
|
error and reset (see the \f[B]RESET\f[] section). |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]!<\f[]\f[I]r\f[]\f[B]e\f[]\f[I]s\f[] |
|
.RS 2 |
|
.PP |
|
Like the above, but will execute register \f[I]s\f[] if the comparison |
|
fails. |
|
.PP |
|
If either or both of the values are not numbers, dc(1) will raise an |
|
error and reset (see the \f[B]RESET\f[] section). |
|
.PP |
|
This is a \f[B]non\-portable extension\f[]. |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]=\f[]\f[I]r\f[] |
|
.RS 2 |
|
.PP |
|
Pops two values off of the stack that must be numbers and compares them. |
|
If the first value is equal to the second, then the contents of register |
|
\f[I]r\f[] are executed. |
|
.PP |
|
If either or both of the values are not numbers, dc(1) will raise an |
|
error and reset (see the \f[B]RESET\f[] section). |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]=\f[]\f[I]r\f[]\f[B]e\f[]\f[I]s\f[] |
|
.RS 2 |
|
.PP |
|
Like the above, but will execute register \f[I]s\f[] if the comparison |
|
fails. |
|
.PP |
|
If either or both of the values are not numbers, dc(1) will raise an |
|
error and reset (see the \f[B]RESET\f[] section). |
|
.PP |
|
This is a \f[B]non\-portable extension\f[]. |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]!=\f[]\f[I]r\f[] |
|
.RS 2 |
|
.PP |
|
Pops two values off of the stack that must be numbers and compares them. |
|
If the first value is not equal to the second, then the contents of |
|
register \f[I]r\f[] are executed. |
|
.PP |
|
If either or both of the values are not numbers, dc(1) will raise an |
|
error and reset (see the \f[B]RESET\f[] section). |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]!=\f[]\f[I]r\f[]\f[B]e\f[]\f[I]s\f[] |
|
.RS 2 |
|
.PP |
|
Like the above, but will execute register \f[I]s\f[] if the comparison |
|
fails. |
|
.PP |
|
If either or both of the values are not numbers, dc(1) will raise an |
|
error and reset (see the \f[B]RESET\f[] section). |
|
.PP |
|
This is a \f[B]non\-portable extension\f[]. |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]?\f[] |
|
.RS 2 |
|
.PP |
|
Reads a line from the \f[B]stdin\f[] and executes it. |
|
This is to allow macros to request input from users. |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]q\f[] |
|
.RS 2 |
|
.PP |
|
During execution of a macro, this exits the execution of that macro and |
|
the execution of the macro that executed it. |
|
If there are no macros, or only one macro executing, dc(1) exits. |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]Q\f[] |
|
.RS 2 |
|
.PP |
|
Pops a value from the stack which must be non\-negative and is used the |
|
number of macro executions to pop off of the execution stack. |
|
If the number of levels to pop is greater than the number of executing |
|
macros, dc(1) exits. |
|
.RE |
|
.SS Status |
|
.PP |
|
These commands query status of the stack or its top value. |
|
.IP \[bu] 2 |
|
\f[B]Z\f[] |
|
.RS 2 |
|
.PP |
|
Pops a value off of the stack. |
|
.PP |
|
If it is a number, calculates the number of significant decimal digits |
|
it has and pushes the result. |
|
.PP |
|
If it is a string, pushes the number of characters the string has. |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]X\f[] |
|
.RS 2 |
|
.PP |
|
Pops a value off of the stack. |
|
.PP |
|
If it is a number, pushes the \f[I]scale\f[] of the value onto the |
|
stack. |
|
.PP |
|
If it is a string, pushes \f[B]0\f[]. |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]z\f[] |
|
.RS 2 |
|
.PP |
|
Pushes the current stack depth (before execution of this command). |
|
.RE |
|
.SS Arrays |
|
.PP |
|
These commands manipulate arrays. |
|
.IP \[bu] 2 |
|
\f[B]:\f[]\f[I]r\f[] |
|
.RS 2 |
|
.PP |
|
Pops the top two values off of the stack. |
|
The second value will be stored in the array \f[I]r\f[] (see the |
|
\f[B]REGISTERS\f[] section), indexed by the first value. |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B];\f[]\f[I]r\f[] |
|
.RS 2 |
|
.PP |
|
Pops the value on top of the stack and uses it as an index into the |
|
array \f[I]r\f[]. |
|
The selected value is then pushed onto the stack. |
|
.RE |
|
.SH REGISTERS |
|
.PP |
|
Registers are names that can store strings, numbers, and arrays. |
|
(Number/string registers do not interfere with array registers.) |
|
.PP |
|
Each register is also its own stack, so the current register value is |
|
the top of the stack for the register. |
|
All registers, when first referenced, have one value (\f[B]0\f[]) in |
|
their stack. |
|
.PP |
|
In non\-extended register mode, a register name is just the single |
|
character that follows any command that needs a register name. |
|
The only exception is a newline (\f[B]\[aq]\\n\[aq]\f[]); it is a parse |
|
error for a newline to be used as a register name. |
|
.SS Extended Register Mode |
|
.PP |
|
Unlike most other dc(1) implentations, this dc(1) provides nearly |
|
unlimited amounts of registers, if extended register mode is enabled. |
|
.PP |
|
If extended register mode is enabled (\f[B]\-x\f[] or |
|
\f[B]\-\-extended\-register\f[] command\-line arguments are given), then |
|
normal single character registers are used \f[I]unless\f[] the character |
|
immediately following a command that needs a register name is a space |
|
(according to \f[B]isspace()\f[]) and not a newline |
|
(\f[B]\[aq]\\n\[aq]\f[]). |
|
.PP |
|
In that case, the register name is found according to the regex |
|
\f[B][a\-z][a\-z0\-9_]*\f[] (like bc(1) identifiers), and it is a parse |
|
error if the next non\-space characters do not match that regex. |
|
.SH RESET |
|
.PP |
|
When dc(1) encounters an error or a signal that it has a non\-default |
|
handler for, it resets. |
|
This means that several things happen. |
|
.PP |
|
First, any macros that are executing are stopped and popped off the |
|
stack. |
|
The behavior is not unlike that of exceptions in programming languages. |
|
Then the execution point is set so that any code waiting to execute |
|
(after all macros returned) is skipped. |
|
.PP |
|
Thus, when dc(1) resets, it skips any remaining code waiting to be |
|
executed. |
|
Then, if it is interactive mode, and the error was not a fatal error |
|
(see the \f[B]EXIT STATUS\f[] section), it asks for more input; |
|
otherwise, it exits with the appropriate return code. |
|
.SH PERFORMANCE |
|
.PP |
|
Most dc(1) implementations use \f[B]char\f[] types to calculate the |
|
value of \f[B]1\f[] decimal digit at a time, but that can be slow. |
|
This dc(1) does something different. |
|
.PP |
|
It uses large integers to calculate more than \f[B]1\f[] decimal digit |
|
at a time. |
|
If built in a environment where \f[B]DC_LONG_BIT\f[] (see the |
|
\f[B]LIMITS\f[] section) is \f[B]64\f[], then each integer has |
|
\f[B]9\f[] decimal digits. |
|
If built in an environment where \f[B]DC_LONG_BIT\f[] is \f[B]32\f[] |
|
then each integer has \f[B]4\f[] decimal digits. |
|
This value (the number of decimal digits per large integer) is called |
|
\f[B]DC_BASE_DIGS\f[]. |
|
.PP |
|
In addition, this dc(1) uses an even larger integer for overflow |
|
checking. |
|
This integer type depends on the value of \f[B]DC_LONG_BIT\f[], 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 dc(1): |
|
.IP \[bu] 2 |
|
\f[B]DC_LONG_BIT\f[] |
|
.RS 2 |
|
.PP |
|
The number of bits in the \f[B]long\f[] type in the environment where |
|
dc(1) was built. |
|
This determines how many decimal digits can be stored in a single large |
|
integer (see the \f[B]PERFORMANCE\f[] section). |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]DC_BASE_DIGS\f[] |
|
.RS 2 |
|
.PP |
|
The number of decimal digits per large integer (see the |
|
\f[B]PERFORMANCE\f[] section). |
|
Depends on \f[B]DC_LONG_BIT\f[]. |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]DC_BASE_POW\f[] |
|
.RS 2 |
|
.PP |
|
The max decimal number that each large integer can store (see |
|
\f[B]DC_BASE_DIGS\f[]) plus \f[B]1\f[]. |
|
Depends on \f[B]DC_BASE_DIGS\f[]. |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]DC_OVERFLOW_MAX\f[] |
|
.RS 2 |
|
.PP |
|
The max number that the overflow type (see the \f[B]PERFORMANCE\f[] |
|
section) can hold. |
|
Depends on \f[B]DC_LONG_BIT\f[]. |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]DC_BASE_MAX\f[] |
|
.RS 2 |
|
.PP |
|
The maximum output base. |
|
Set at \f[B]DC_BASE_POW\f[]. |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]DC_DIM_MAX\f[] |
|
.RS 2 |
|
.PP |
|
The maximum size of arrays. |
|
Set at \f[B]SIZE_MAX\-1\f[]. |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]DC_SCALE_MAX\f[] |
|
.RS 2 |
|
.PP |
|
The maximum \f[B]scale\f[]. |
|
Set at \f[B]DC_OVERFLOW_MAX\-1\f[]. |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]DC_STRING_MAX\f[] |
|
.RS 2 |
|
.PP |
|
The maximum length of strings. |
|
Set at \f[B]DC_OVERFLOW_MAX\-1\f[]. |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]DC_NAME_MAX\f[] |
|
.RS 2 |
|
.PP |
|
The maximum length of identifiers. |
|
Set at \f[B]DC_OVERFLOW_MAX\-1\f[]. |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]DC_NUM_MAX\f[] |
|
.RS 2 |
|
.PP |
|
The maximum length of a number (in decimal digits), which includes |
|
digits after the decimal point. |
|
Set at \f[B]DC_OVERFLOW_MAX\-1\f[]. |
|
.RE |
|
.IP \[bu] 2 |
|
Exponent |
|
.RS 2 |
|
.PP |
|
The maximum allowable exponent (positive or negative). |
|
Set at \f[B]DC_OVERFLOW_MAX\f[]. |
|
.RE |
|
.IP \[bu] 2 |
|
Number of vars |
|
.RS 2 |
|
.PP |
|
The maximum number of vars/arrays. |
|
Set at \f[B]SIZE_MAX\-1\f[]. |
|
.RE |
|
.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 |
|
dc(1) recognizes the following environment variables: |
|
.IP \[bu] 2 |
|
\f[B]DC_ENV_ARGS\f[] |
|
.RS 2 |
|
.PP |
|
This is another way to give command\-line arguments to dc(1). |
|
They should be in the same format as all other command\-line arguments. |
|
These are always processed first, so any files given in |
|
\f[B]DC_ENV_ARGS\f[] will be processed before arguments and files given |
|
on the command\-line. |
|
This gives the user the ability to set up "standard" options and files |
|
to be used at every invocation. |
|
The most useful thing for such files to contain would be useful |
|
functions that the user might want every time dc(1) runs. |
|
Another use would be to use the \f[B]\-e\f[] option to set |
|
\f[B]scale\f[] to a value other than \f[B]0\f[]. |
|
.PP |
|
The code that parses \f[B]DC_ENV_ARGS\f[] will correctly handle quoted |
|
arguments, but it does not understand escape sequences. |
|
For example, the string \f[B]"/home/gavin/some dc file.dc"\f[] will be |
|
correctly parsed, but the string \f[B]"/home/gavin/some "dc" |
|
file.dc"\f[] will include the backslashes. |
|
.PP |
|
The quote parsing will handle either kind of quotes, \f[B]\[aq]\f[] or |
|
\f[B]"\f[]. |
|
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]"some |
|
\[aq]bc\[aq] file.bc"\f[], and vice versa if you have a file with double |
|
quotes. |
|
However, handling a file with both kinds of quotes in |
|
\f[B]DC_ENV_ARGS\f[] 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 |
|
.IP \[bu] 2 |
|
\f[B]DC_LINE_LENGTH\f[] |
|
.RS 2 |
|
.PP |
|
If this environment variable exists and contains an integer that is |
|
greater than \f[B]1\f[] and is less than \f[B]UINT16_MAX\f[] |
|
(\f[B]2^16\-1\f[]), dc(1) will output lines to that length, including |
|
the backslash newline combo. |
|
The default line length is \f[B]70\f[]. |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]DC_EXPR_EXIT\f[] |
|
.RS 2 |
|
.PP |
|
If this variable exists (no matter the contents), dc(1) will exit |
|
immediately after executing expressions and files given by the |
|
\f[B]\-e\f[] and/or \f[B]\-f\f[] command\-line options (and any |
|
equivalents). |
|
.RE |
|
.SH EXIT STATUS |
|
.PP |
|
dc(1) returns the following exit statuses: |
|
.IP \[bu] 2 |
|
\f[B]0\f[] |
|
.RS 2 |
|
.PP |
|
No error. |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]1\f[] |
|
.RS 2 |
|
.PP |
|
A math error occurred. |
|
This follows standard practice of using \f[B]1\f[] for expected errors, |
|
since math errors will happen in the process of normal execution. |
|
.PP |
|
Math errors include divide by \f[B]0\f[], taking the square root of a |
|
negative number, 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]^\f[]) operator. |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]2\f[] |
|
.RS 2 |
|
.PP |
|
A parse error occurred. |
|
.PP |
|
Parse errors include unexpected \f[B]EOF\f[], using an invalid |
|
character, failing to find the end of a string or comment, and using a |
|
token where it is invalid. |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]3\f[] |
|
.RS 2 |
|
.PP |
|
A runtime error occurred. |
|
.PP |
|
Runtime errors include assigning an invalid number to \f[B]ibase\f[], |
|
\f[B]obase\f[], or \f[B]scale\f[]; give a bad expression to a |
|
\f[B]read()\f[] call, calling \f[B]read()\f[] inside of a |
|
\f[B]read()\f[] call, type errors, and attempting an operation when the |
|
stack has too few elements. |
|
.RE |
|
.IP \[bu] 2 |
|
\f[B]4\f[] |
|
.RS 2 |
|
.PP |
|
A fatal error occurred. |
|
.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 (dc(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[] is special; when a fatal error occurs, dc(1) |
|
always exits and returns \f[B]4\f[], no matter what mode dc(1) is in. |
|
.PP |
|
The other statuses will only be returned when dc(1) is not in |
|
interactive mode (see the \f[B]INTERACTIVE MODE\f[] section), since |
|
dc(1) resets its state (see the \f[B]RESET\f[] 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[] flag or \f[B]\-\-interactive\f[] option. |
|
.PP |
|
These exit statuses allow dc(1) to be used in shell scripting with error |
|
checking, and its normal behavior can be forced by using the |
|
\f[B]\-i\f[] flag or \f[B]\-\-interactive\f[] option. |
|
.SH INTERACTIVE MODE |
|
.PP |
|
Like bc(1), dc(1) has an interactive mode and a non\-interactive mode. |
|
Interactive mode is turned on automatically when both \f[B]stdin\f[] and |
|
\f[B]stdout\f[] are hooked to a terminal, but the \f[B]\-i\f[] flag and |
|
\f[B]\-\-interactive\f[] option can turn it on in other cases. |
|
.PP |
|
In interactive mode, dc(1) attempts to recover from errors (see the |
|
\f[B]RESET\f[] section), and in normal execution, flushes |
|
\f[B]stdout\f[] as soon as execution is done for the current input. |
|
.SH TTY MODE |
|
.PP |
|
If \f[B]stdin\f[], \f[B]stdout\f[], and \f[B]stderr\f[] are all |
|
connected to a TTY, dc(1) turns on "TTY mode." |
|
.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[] and \f[B]stdout\f[] to |
|
be connected to a terminal. |
|
.SH SIGNAL HANDLING |
|
.PP |
|
Sending a \f[B]SIGINT\f[] will cause dc(1) to stop execution of the |
|
current input. |
|
If dc(1) is in TTY mode (see the \f[B]TTY MODE\f[] section), it will |
|
reset (see the \f[B]RESET\f[] section). |
|
Otherwise, it will clean up and exit. |
|
.PP |
|
Note that "current input" can mean one of two things. |
|
If dc(1) is processing input from \f[B]stdin\f[] in TTY mode, it will |
|
ask for more input. |
|
If dc(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[] if no other file exists. |
|
.PP |
|
This means that if a \f[B]SIGINT\f[] is sent to dc(1) as it is executing |
|
a file, it can seem as though dc(1) did not respond to the signal since |
|
it will immediately start executing the next file. |
|
This is by design; most files that users execute when interacting with |
|
dc(1) have function definitions, which are quick to parse. |
|
If a file takes a long time to execute, there may be a bug in that file. |
|
The rest of the files could still be executed without problem, allowing |
|
the user to continue. |
|
.PP |
|
\f[B]SIGTERM\f[] and \f[B]SIGQUIT\f[] cause dc(1) to clean up and exit, |
|
and it uses the default handler for all other signals. |
|
.SH LOCALES |
|
.PP |
|
This dc(1) ships with support for adding error messages for different |
|
locales and thus, supports \f[B]LC_MESSAGS\f[]. |
|
.SH SEE ALSO |
|
.PP |
|
bc(1) |
|
.SH STANDARDS |
|
.PP |
|
The dc(1) utility operators are compliant with the operators in the |
|
bc(1) IEEE Std 1003.1\-2017 |
|
(“POSIX.1\-2017”) (https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html) |
|
specification. |
|
.SH BUGS |
|
.PP |
|
None are known. |
|
Report bugs at https://git.yzena.com/gavin/bc. |
|
.SH AUTHOR |
|
.PP |
|
Gavin D. |
|
Howard <yzena.tech@gmail.com> and contributors.
|
|
|