dc: Add initial version

This is the initial version of dc already tested in deep and
with a considerable good set of tests.
This commit is contained in:
Roberto E. Vargas Caballero 2025-12-15 16:01:56 +01:00
parent a1bf3adbc5
commit 608f88f08f
22 changed files with 4871 additions and 0 deletions

View File

@ -110,6 +110,7 @@ BIN =\
cron\
cut\
date\
dc\
dd\
dirname\
du\

260
dc.1 Normal file
View File

@ -0,0 +1,260 @@
.Dd January 14, 2026
.Dt DC 1
.Os sbase
.Sh NAME
.Nm dc
.Nd arbitrary-precision desk calculator
.Sh SYNOPSIS
.Nm
.Op Fl i
.Op Ar file ...
.Sh DESCRIPTION
.Nm
is a reverse-polish notation arbitrary-precision desk calculator.
It reads and executes commands from each
.Ar file
in sequence.
After processing all files,
.Nm
reads from stdin.
.Pp
Numbers are arbitrary-precision decimal values.
Numbers may contain a decimal point and use
.Ql _
as a negative sign prefix.
When the input base is greater than 10, letters A-F or a-f represent digits 10-15.
A hexadecimal number beginning with a lower case letter
must be preceded by a zero to distinguish it from the command associated with the letter.
.Sh OPTIONS
.Bl -tag -width Ds
.It Fl i
Extended identifier mode.
Register names can be enclosed in
.Ql < Ns No ... Ns >
(numeric identifiers) or
.Ql \&" Ns No ... Ns \&"
(string identifiers).
.El
.Sh COMMANDS
.Ss Printing
.Bl -tag -width Ds
.It Ic p
Print the value on top of the stack with a newline,
without popping it.
.It Ic n
Print the value on top of the stack without a newline,
and pop it.
.It Ic P
Print the value on top of the stack as a byte stream.
For strings, print the characters directly.
For numbers, print it in base 100 representing the internal representation.
The value is popped.
.It Ic f
Print all values on the stack, one per line, from top to bottom.
.El
.Ss Arithmetic
.Bl -tag -width Ds
.It Ic +
Pop two values, add them, and push the result.
.It Ic \-
Pop two values, subtract the top from the second, and push the result.
.It Ic *
Pop two values, multiply them, and push the result.
.It Ic /
Pop two values, divide the second by the top, and push the quotient.
The scale of the result is determined by the
.Ic scale
parameter.
.It Ic %
Pop two values, compute the remainder of dividing the second by the top,
and push the result.
.It Ic ~
Pop two values, compute both quotient and remainder,
pushing the quotient first then the remainder on top.
.It Ic ^
Pop two values, raise the second to the power of the top, and push the result.
The exponent is truncated to an integer.
.It Ic v
Pop the top value, compute its square root, and push the result.
The precision is determined by the
.Ic scale
parameter.
.El
.Ss Stack
.Bl -tag -width Ds
.It Ic c
Clear the stack.
.It Ic d
Duplicate the top of the stack.
.It Ic r
Reverse the order of the top two values on the stack.
.It Ic z
Push the current stack depth.
.El
.Ss Registers
Registers are named storage locations.
In normal mode, register names are single characters.
With the
.Fl i
option, extended names are available.
Each register also has an associated stack.
.Bl -tag -width Ds
.It Ic s Ns Ar x
Pop the top value and store it in register
.Ar x .
.It Ic l Ns Ar x
Push a copy of the value in register
.Ar x
onto the stack.
.It Ic S Ns Ar x
Pop the top value and push it onto register
.Ar x Ns 's
stack.
.It Ic L Ns Ar x
Pop the top value from register
.Ar x Ns 's
stack and push it onto the main stack.
.El
.Ss Arrays
Each register has an associated array.
.Bl -tag -width Ds
.It Ic : Ns Ar x
Pop an index, then pop a value, and store the value at that index in array
.Ar x .
.It Ic ; Ns Ar x
Pop an index and push the value at that index in array
.Ar x .
.El
.Ss Parameters
.Bl -tag -width Ds
.It Ic i
Pop the top value and use it as the input radix.
The input base must be between 2 and 16.
.It Ic o
Pop the top value and use it as the output radix.
The output base must be at least 2.
.It Ic k
Pop the top value and use it as the scale
.Pq number of decimal places
for arithmetic operations.
The scale must be non-negative.
.It Ic I
Push the current input radix.
.It Ic O
Push the current output radix.
.It Ic K
Push the current scale.
.El
.Ss Strings and Macros
.Bl -tag -width Ds
.It Ic \&[ Ns Ar string Ns Ic \&]
Push
.Ar string
onto the stack.
Brackets inside the string must be balanced or escaped with a backslash.
.It Ic x
Pop the top value.
If it is a string, execute it as a macro.
If it is a number, push it back.
.El
.Ss Conditionals
The conditional commands pop two values, compare them,
and if the condition is true, execute the contents of register
.Ar x
as a macro.
.Bl -tag -width Ds
.It Ic > Ns Ar x
Execute register
.Ar x
if the second value is greater than the top.
.It Ic < Ns Ar x
Execute register
.Ar x
if the second value is less than the top.
.It Ic = Ns Ar x
Execute register
.Ar x
if the two values are equal.
.It Ic !> Ns Ar x
Execute register
.Ar x
if the second value is not greater than (less or equal to) the top.
.It Ic !< Ns Ar x
Execute register
.Ar x
if the second value is not less than (greater or equal to) the top.
.It Ic != Ns Ar x
Execute register
.Ar x
if the two values are not equal.
.El
.Ss Control
.Bl -tag -width Ds
.It Ic q
Quit.
If executing a macro, exit two macro levels.
.It Ic Q
Pop a value and quit that many macro levels.
.El
.Ss Input
.Bl -tag -width Ds
.It Ic ?
Read a line from stdin and execute it.
.It Ic #
Comment.
The rest of the line is ignored.
.It Ic !\& Ns Ar command
Execute
.Ar command
as a shell command.
.El
.Ss Number Information
.Bl -tag -width Ds
.It Ic Z
Pop a value and push its length.
For numbers, push the number of significant digits.
For strings, push the number of characters.
.It Ic X
Pop a value and push its scale (number of fractional digits).
For strings, push 0.
.El
.Sh EXAMPLES
Compute 6 * 7:
.Bd -literal -offset indent
6 7*p
.Ed
.Pp
Compute 2^10:
.Bd -literal -offset indent
2 10^p
.Ed
.Pp
Compute square root of 2 with 20 decimal places:
.Bd -literal -offset indent
20k 2vp
.Ed
.Pp
Factorial using recursion (store in register f):
.Bd -literal -offset indent
[d1-d1<f*]sf 10lf xp
.Ed
.Sh SEE ALSO
.Xr bc 1
.Rs
.%A R. H. Morris
.%A L. L. Cherry
.%T "DC \(em An Interactive Desk Calculator"
.Re
.Sh STANDARDS
.Nm
is compatible with traditional UNIX dc implementations.
The
.Fl i
flag,
.Ic #
comments,
the
.Ic ~
operator, and lowercase hexadecimal digits
.Pq a-f
are extensions to the traditional dc specification.

2199
dc.c Normal file

File diff suppressed because it is too large Load Diff

68
tests/0026-dc.sh Executable file
View File

@ -0,0 +1,68 @@
#!/bin/sh
tmp=$$.tmp
trap 'rm -f $tmp' EXIT
trap 'exit $?' HUP INT TERM
# Expected output for printnum tests
cat <<EOF >$tmp
test 1:
100
test 2:
0
test 3:
-42
test 4:
.5
test 5:
.05
test 6:
.001
test 7:
1.5
test 8:
-.5
test 9:
-1.25
test 10:
.4
test 11:
.0
.1
test 12:
.0
test 13:
1.0
test 14:
.2
test 15:
.1
test 16:
.01
test 17:
.001
test 18:
.8
EOF
$EXEC ../dc <<EOF | diff -u $tmp -
[test 1:]pc 100p
[test 2:]pc 0p
[test 3:]pc _42p
[test 4:]pc .5p
[test 5:]pc .05p
[test 6:]pc .001p
[test 7:]pc 1.5p
[test 8:]pc _.5p
[test 9:]pc _1.25p
[test 10:]pc 16o.3p
[test 11:]pc 2o.1p10op
[test 12:]pc 2o.3p
[test 13:]pc 2o1.1p
[test 14:]pc 3o.7p
[test 15:]pc 2o.5p
[test 16:]pc 2o.25p
[test 17:]pc 2o.125p
[test 18:]pc 16o.5p
EOF

138
tests/0027-dc.sh Executable file
View File

@ -0,0 +1,138 @@
#!/bin/sh
tmp=$$.tmp
trap 'rm -f $tmp' EXIT
trap 'exit $?' HUP INT TERM
cat <<EOF >$tmp
test 1:
5
test 2:
0
test 3:
-5
test 4:
200
test 5:
-200
test 6:
7
test 7:
-7
test 8:
7
test 9:
-7
test 10:
0
test 11:
0
test 12:
5
test 13:
-5
test 14:
5
test 15:
-5
test 16:
1.5
test 17:
2.50
test 18:
1.50
test 19:
.60
test 20:
1.234
test 21:
-.234
test 22:
0
test 23:
-.002
test 24:
-.003
test 25:
0
test 26:
99999999999999999999
test 27:
-99999999999999999999
test 28:
12345678901234567890
test 29:
0
test 30:
10
test 31:
1100
test 32:
100000000000000000000
test 33:
-100000000000000000000
test 34:
1
test 35:
-1
test 36:
0
test 37:
1.000001
test 38:
.0000000002
test 39:
-.000003
test 40:
-.001
test 41:
1.00
test 42:
.66666
EOF
$EXEC ../dc <<EOF | diff -u $tmp -
[test 1:]pc 2 3+p
[test 2:]pc 0 0+p
[test 3:]pc _2 _3+p
[test 4:]pc 100 100+p
[test 5:]pc _100 _100+p
[test 6:]pc 10 _3+p
[test 7:]pc 3 _10+p
[test 8:]pc _3 10+p
[test 9:]pc _10 3+p
[test 10:]pc 5 _5+p
[test 11:]pc _5 5+p
[test 12:]pc 0 5+p
[test 13:]pc 0 _5+p
[test 14:]pc 5 0+p
[test 15:]pc _5 0+p
[test 16:]pc 1.0 .5+p
[test 17:]pc 1.5 1.00+p
[test 18:]pc 1.00 .50+p
[test 19:]pc .1 .50+p
[test 20:]pc 1.004 .23+p
[test 21:]pc _.5 .266+p
[test 22:]pc 1.5 _1.5+p
[test 23:]pc _.001 _.001+p
[test 24:]pc _.001 _.002+p
[test 25:]pc .001 _.001+p
[test 26:]pc 99999999999999999999 0+p
[test 27:]pc _99999999999999999999 0+p
[test 28:]pc 12345678901234567890 0+p
[test 29:]pc 0 0+p
[test 30:]pc 9 1+p
[test 31:]pc 999 101+p
[test 32:]pc 99999999999999999999 1+p
[test 33:]pc _99999999999999999999 _1+p
[test 34:]pc 99999999999999999999 _99999999999999999998+p
[test 35:]pc 99999999999999999998 _99999999999999999999+p
[test 36:]pc 99999999999999999999 _99999999999999999999+p
[test 37:]pc .000001 1+p
[test 38:]pc .0000000001 .0000000001+p
[test 39:]pc _.000001 _.000002+p
[test 40:]pc .001 _.002+p
[test 41:]pc .99 .01+p
[test 42:]pc .12345 .54321+p
EOF

139
tests/0028-dc.sh Executable file
View File

@ -0,0 +1,139 @@
#!/bin/sh
tmp=$$.tmp
trap 'rm -f $tmp' EXIT
trap 'exit $?' HUP INT TERM
# Test - command: subtraction
cat <<EOF >$tmp
test 1:
-1
test 2:
0
test 3:
1
test 4:
0
test 5:
0
test 6:
13
test 7:
13
test 8:
-13
test 9:
-13
test 10:
10
test 11:
-10
test 12:
-5
test 13:
5
test 14:
5
test 15:
-5
test 16:
.5
test 17:
.50
test 18:
.50
test 19:
-.40
test 20:
.774
test 21:
-.766
test 22:
3.0
test 23:
0
test 24:
.001
test 25:
.002
test 26:
99999999999999999999
test 27:
-99999999999999999999
test 28:
12345678901234567890
test 29:
0
test 30:
8
test 31:
898
test 32:
99999999999999999998
test 33:
-99999999999999999998
test 34:
199999999999999999997
test 35:
199999999999999999997
test 36:
199999999999999999998
test 37:
-.999999
test 38:
0
test 39:
.000001
test 40:
.003
test 41:
.98
test 42:
-.41976
EOF
$EXEC ../dc <<EOF | diff -u $tmp -
[test 1:]pc 2 3-p
[test 2:]pc 0 0-p
[test 3:]pc _2 _3-p
[test 4:]pc 100 100-p
[test 5:]pc _100 _100-p
[test 6:]pc 10 _3-p
[test 7:]pc 3 _10-p
[test 8:]pc _3 10-p
[test 9:]pc _10 3-p
[test 10:]pc 5 _5-p
[test 11:]pc _5 5-p
[test 12:]pc 0 5-p
[test 13:]pc 0 _5-p
[test 14:]pc 5 0-p
[test 15:]pc _5 0-p
[test 16:]pc 1.0 .5-p
[test 17:]pc 1.5 1.00-p
[test 18:]pc 1.00 .50-p
[test 19:]pc .1 .50-p
[test 20:]pc 1.004 .23-p
[test 21:]pc _.5 .266-p
[test 22:]pc 1.5 _1.5-p
[test 23:]pc _.001 _.001-p
[test 24:]pc _.001 _.002-p
[test 25:]pc .001 _.001-p
[test 26:]pc 99999999999999999999 0-p
[test 27:]pc _99999999999999999999 0-p
[test 28:]pc 12345678901234567890 0-p
[test 29:]pc 0 0-p
[test 30:]pc 9 1-p
[test 31:]pc 999 101-p
[test 32:]pc 99999999999999999999 1-p
[test 33:]pc _99999999999999999999 _1-p
[test 34:]pc 99999999999999999999 _99999999999999999998-p
[test 35:]pc 99999999999999999998 _99999999999999999999-p
[test 36:]pc 99999999999999999999 _99999999999999999999-p
[test 37:]pc .000001 1-p
[test 38:]pc .0000000001 .0000000001-p
[test 39:]pc _.000001 _.000002-p
[test 40:]pc .001 _.002-p
[test 41:]pc .99 .01-p
[test 42:]pc .12345 .54321-p
EOF

196
tests/0029-dc.sh Executable file
View File

@ -0,0 +1,196 @@
#!/bin/sh
tmp=$$.tmp
trap 'rm -f $tmp' EXIT
trap 'exit $?' HUP INT TERM
# Test * command: multiplication
cat <<EOF >$tmp
test 1:
6
test 2:
0
test 3:
6
test 4:
10000
test 5:
10000
test 6:
-30
test 7:
-30
test 8:
-30
test 9:
-30
test 10:
-25
test 11:
-25
test 12:
0
test 13:
0
test 14:
0
test 15:
0
test 16:
5
test 17:
5
test 18:
-5
test 19:
-5
test 20:
.5
test 21:
1.50
test 22:
.50
test 23:
0
test 24:
3.7
test 25:
.2
test 26:
1.00
test 27:
1.000
test 28:
0
test 29:
-3.7
test 30:
-3.7
test 31:
3.7
test 32:
-.2
test 33:
-.2
test 34:
.2
test 35:
0
test 36:
0
test 37:
12345678901234567890
test 38:
-12345678901234567890
test 39:
81
test 40:
9801
test 41:
998001
test 42:
99980001
test 43:
9999999800000001
test 44:
0
test 45:
.10000
test 46:
1.0
test 47:
4.5
test 48:
4.5
test 49:
1.0
test 50:
1.00
test 51:
1.000
test 52:
4
test 53:
16
test 54:
64
test 55:
256
test 56:
65536
test 57:
1
test 58:
-1
test 59:
-1
test 60:
1
test 61:
0
EOF
$EXEC ../dc <<EOF | diff -u $tmp -
[test 1:]pc 2 3*p
[test 2:]pc 0 0*p
[test 3:]pc _2 _3*p
[test 4:]pc 100 100*p
[test 5:]pc _100 _100*p
[test 6:]pc 10 _3*p
[test 7:]pc 3 _10*p
[test 8:]pc _3 10*p
[test 9:]pc _10 3*p
[test 10:]pc 5 _5*p
[test 11:]pc _5 5*p
[test 12:]pc 0 5*p
[test 13:]pc 0 _5*p
[test 14:]pc 5 0*p
[test 15:]pc _5 0*p
[test 16:]pc 1 5*p
[test 17:]pc 5 1*p
[test 18:]pc _1 5*p
[test 19:]pc 5 _1*p
[test 20:]pc 1.0 .5*p
[test 21:]pc 1.5 1.00*p
[test 22:]pc 1.00 .50*p
[test 23:]pc .1 .5*p
[test 24:]pc 1.5 2.5*p
[test 25:]pc .5 .5*p
[test 26:]pc .25 4*p
[test 27:]pc .125 8*p
[test 28:]pc .001 .001*p
[test 29:]pc _1.5 2.5*p
[test 30:]pc 1.5 _2.5*p
[test 31:]pc _1.5 _2.5*p
[test 32:]pc _.5 .5*p
[test 33:]pc .5 _.5*p
[test 34:]pc _.5 _.5*p
[test 35:]pc 99999999999999999999 0*p
[test 36:]pc _99999999999999999999 0*p
[test 37:]pc 12345678901234567890 1*p
[test 38:]pc 12345678901234567890 _1*p
[test 39:]pc 9 9*p
[test 40:]pc 99 99*p
[test 41:]pc 999 999*p
[test 42:]pc 9999 9999*p
[test 43:]pc 99999999 99999999*p
[test 44:]pc .0001 .0001*p
[test 45:]pc .00001 10000*p
[test 46:]pc .1 10*p
[test 47:]pc 1.5 3*p
[test 48:]pc 3 1.5*p
[test 49:]pc 10 .1*p
[test 50:]pc 100 .01*p
[test 51:]pc 1000 .001*p
[test 52:]pc 2 2*p
[test 53:]pc 4 4*p
[test 54:]pc 8 8*p
[test 55:]pc 16 16*p
[test 56:]pc 256 256*p
[test 57:]pc 1 1*p
[test 58:]pc _1 1*p
[test 59:]pc 1 _1*p
[test 60:]pc _1 _1*p
[test 61:]pc 0 0*p
EOF

296
tests/0030-dc.sh Executable file
View File

@ -0,0 +1,296 @@
#!/bin/sh
tmp=$$.tmp
trap 'rm -f $tmp' EXIT
trap 'exit $?' HUP INT TERM
# Test / command: division
# Note: scale (k) persists between operations, so we reset it explicitly
cat <<EOF >$tmp
test 1:
3
test 2:
3
test 3:
10
test 4:
33
test 5:
-3
test 6:
-3
test 7:
3
test 8:
0
test 9:
1
test 10:
5
test 11:
0
test 12:
3.50
test 13:
.33
test 14:
.3333
test 15:
2.50
test 16:
3.14
test 17:
3.142857
test 18:
-3.50
test 19:
-3.50
test 20:
3.50
test 21:
-.33
test 22:
-.33
test 23:
.33
test 24:
3
test 25:
2
test 26:
3
test 27:
20
test 28:
0
test 29:
.05
test 30:
1000
test 31:
1000001
test 32:
1
test 33:
12345678901234567890
test 34:
.3333333333
test 35:
.6666666666
test 36:
.1428571428
test 37:
.1111111111
test 38:
.0909090909
test 39:
.5
test 40:
.500
test 41:
.50000
test 42:
.2
test 43:
.250
test 44:
.1
test 45:
.125
test 46:
-3
test 47:
-3
test 48:
3
test 49:
-2.50
test 50:
-2.50
test 51:
2.50
test 52:
1.00000000
test 53:
.00100000
test 54:
1000.00000000
test 55:
.01000000
test 56:
100.00000000
test 57:
1
test 58:
1
test 59:
-1
test 60:
-1
test 61:
0
test 62:
0
test 63:
0
test 64:
100
test 65:
-100
test 66:
-100
test 67:
100
test 68:
10
test 69:
100
test 70:
100
test 71:
1000
test 72:
0
test 73:
0
test 74:
0
test 75:
0
test 76:
0
test 77:
0
test 78:
.50
test 79:
.10
test 80:
.01
test 81:
.50
test 82:
.99
test 83:
9
test 84:
8
test 85:
7
test 86:
6
test 87:
5
test 88:
4
test 89:
3
test 90:
2
test 91:
1
test 92:
99999999999999999999
test 93:
0
test 94:
.00000000000000000001
EOF
$EXEC ../dc <<EOF | diff -u $tmp -
[test 1:]pc 0k 6 2/p
[test 2:]pc 0k 7 2/p
[test 3:]pc 0k 100 10/p
[test 4:]pc 0k 100 3/p
[test 5:]pc 0k _6 2/p
[test 6:]pc 0k 6 _2/p
[test 7:]pc 0k _6 _2/p
[test 8:]pc 0k 0 5/p
[test 9:]pc 0k 1 1/p
[test 10:]pc 0k 5 1/p
[test 11:]pc 0k 1 5/p
[test 12:]pc 2k 7 2/p
[test 13:]pc 2k 1 3/p
[test 14:]pc 4k 1 3/p
[test 15:]pc 2k 10 4/p
[test 16:]pc 2k 22 7/p
[test 17:]pc 6k 22 7/p
[test 18:]pc 2k _7 2/p
[test 19:]pc 2k 7 _2/p
[test 20:]pc 2k _7 _2/p
[test 21:]pc 2k _1 3/p
[test 22:]pc 2k 1 _3/p
[test 23:]pc 2k _1 _3/p
[test 24:]pc 0k 1.5 .5/p
[test 25:]pc 0k 3.0 1.5/p
[test 26:]pc 0k .75 .25/p
[test 27:]pc 0k 10 .5/p
[test 28:]pc 0k .5 10/p
[test 29:]pc 2k .5 10/p
[test 30:]pc 0k 1000000 1000/p
[test 31:]pc 0k 999999999999 999999/p
[test 32:]pc 0k 12345678901234567890 12345678901234567890/p
[test 33:]pc 0k 12345678901234567890 1/p
[test 34:]pc 10k 1 3/p
[test 35:]pc 10k 2 3/p
[test 36:]pc 10k 1 7/p
[test 37:]pc 10k 1 9/p
[test 38:]pc 10k 1 11/p
[test 39:]pc 1k 1 2/p
[test 40:]pc 3k 1 2/p
[test 41:]pc 5k 1 2/p
[test 42:]pc 1k 1 4/p
[test 43:]pc 3k 1 4/p
[test 44:]pc 1k 1 8/p
[test 45:]pc 3k 1 8/p
[test 46:]pc 0k _1.5 .5/p
[test 47:]pc 0k 1.5 _.5/p
[test 48:]pc 0k _1.5 _.5/p
[test 49:]pc 2k _10 4/p
[test 50:]pc 2k 10 _4/p
[test 51:]pc 2k _10 _4/p
[test 52:]pc 8k .001 .001/p
[test 53:]pc 8k .001 1/p
[test 54:]pc 8k 1 .001/p
[test 55:]pc 8k .0001 .01/p
[test 56:]pc 8k .01 .0001/p
[test 57:]pc 0k 1 1/p
[test 58:]pc 0k _1 _1/p
[test 59:]pc 0k _1 1/p
[test 60:]pc 0k 1 _1/p
[test 61:]pc 0k 0 1/p
[test 62:]pc 0k 0 _1/p
[test 63:]pc 0k 0 100/p
[test 64:]pc 0k 100 1/p
[test 65:]pc 0k _100 1/p
[test 66:]pc 0k 100 _1/p
[test 67:]pc 0k _100 _1/p
[test 68:]pc 0k 100 10/p
[test 69:]pc 0k 1000 10/p
[test 70:]pc 0k 10000 100/p
[test 71:]pc 0k 1000000 1000/p
[test 72:]pc 0k 10 100/p
[test 73:]pc 0k 10 1000/p
[test 74:]pc 0k 1 2/p
[test 75:]pc 0k 1 10/p
[test 76:]pc 0k 1 100/p
[test 77:]pc 0k 5 10/p
[test 78:]pc 2k 1 2/p
[test 79:]pc 2k 1 10/p
[test 80:]pc 2k 1 100/p
[test 81:]pc 2k 5 10/p
[test 82:]pc 2k 99 100/p
[test 83:]pc 0k 81 9/p
[test 84:]pc 0k 64 8/p
[test 85:]pc 0k 49 7/p
[test 86:]pc 0k 36 6/p
[test 87:]pc 0k 25 5/p
[test 88:]pc 0k 16 4/p
[test 89:]pc 0k 9 3/p
[test 90:]pc 0k 4 2/p
[test 91:]pc 0k 99999999999999999999 99999999999999999999/p
[test 92:]pc 0k 99999999999999999999 1/p
[test 93:]pc 0k 1 99999999999999999999/p
[test 94:]pc 20k 1 99999999999999999999/p
EOF

218
tests/0031-dc.sh Executable file
View File

@ -0,0 +1,218 @@
#!/bin/sh
tmp=$$.tmp
trap 'rm -f $tmp' EXIT
trap 'exit $?' HUP INT TERM
# Test % command: modulo (remainder)
# Note: scale (k) persists between operations, so we reset it explicitly
cat <<EOF >$tmp
test 1:
1
test 2:
1
test 3:
2
test 4:
0
test 5:
2
test 6:
0
test 7:
0
test 8:
3
test 9:
-1
test 10:
1
test 11:
-1
test 12:
-1
test 13:
1
test 14:
-1
test 15:
0
test 16:
0
test 17:
0
test 18:
1
test 19:
1
test 20:
1
test 21:
99
test 22:
0
test 23:
0
test 24:
0
test 25:
1
test 26:
789
test 27:
4
test 28:
0
test 29:
1
test 30:
0
test 31:
1
test 32:
0
test 33:
0
test 34:
0
test 35:
0
test 36:
7
test 37:
1
test 38:
15
test 39:
0
test 40:
1
test 41:
0
test 42:
0
test 43:
0
test 44:
1.5
test 45:
0
test 46:
0
test 47:
0
test 48:
0
test 49:
0
test 50:
0
test 51:
0
test 52:
0
test 53:
0
test 54:
.001
test 55:
.01
test 56:
.01
test 57:
0
test 58:
.02
test 59:
-.01
test 60:
.01
test 61:
-.01
test 62:
.0001
test 63:
.0002
test 64:
.0005
test 65:
0
test 66:
.005
test 67:
.0050
test 68:
0
EOF
$EXEC ../dc <<EOF | diff -u $tmp -
[test 1:]pc 0k 7 3%p
[test 2:]pc 0k 10 3%p
[test 3:]pc 0k 100 7%p
[test 4:]pc 0k 15 5%p
[test 5:]pc 0k 17 5%p
[test 6:]pc 0k 0 5%p
[test 7:]pc 0k 5 5%p
[test 8:]pc 0k 3 7%p
[test 9:]pc 0k _7 3%p
[test 10:]pc 0k 7 _3%p
[test 11:]pc 0k _7 _3%p
[test 12:]pc 0k _10 3%p
[test 13:]pc 0k 10 _3%p
[test 14:]pc 0k _10 _3%p
[test 15:]pc 0k 1 1%p
[test 16:]pc 0k 2 2%p
[test 17:]pc 0k 3 3%p
[test 18:]pc 0k 1 2%p
[test 19:]pc 0k 1 10%p
[test 20:]pc 0k 1 100%p
[test 21:]pc 0k 99 100%p
[test 22:]pc 0k 5 1%p
[test 23:]pc 0k 100 1%p
[test 24:]pc 0k _5 1%p
[test 25:]pc 0k 1000000 999999%p
[test 26:]pc 0k 123456789 1000%p
[test 27:]pc 0k 99999999999 7%p
[test 28:]pc 0k 12345678901234567890 9%p
[test 29:]pc 0k 99999999999999999999 2%p
[test 30:]pc 0k 99999999999999999999 3%p
[test 31:]pc 0k 99999999999999999999 99999999999999999998%p
[test 32:]pc 0k 99999999999999999999 99999999999999999999%p
[test 33:]pc 0k 8 2%p
[test 34:]pc 0k 8 4%p
[test 35:]pc 0k 16 8%p
[test 36:]pc 0k 15 8%p
[test 37:]pc 0k 17 8%p
[test 38:]pc 0k 255 16%p
[test 39:]pc 0k 256 16%p
[test 40:]pc 0k 257 16%p
[test 41:]pc 0k 7.5 2.5%p
[test 42:]pc 0k 1.5 .5%p
[test 43:]pc 0k 3.75 1.25%p
[test 44:]pc 0k 7.5 3%p
[test 45:]pc 0k 4.5 1.5%p
[test 46:]pc 0k 2.5 .5%p
[test 47:]pc 0k _7.5 2.5%p
[test 48:]pc 0k 7.5 _2.5%p
[test 49:]pc 0k _7.5 _2.5%p
[test 50:]pc 0k _1.5 .5%p
[test 51:]pc 0k 1.5 _.5%p
[test 52:]pc 0k _1.5 _.5%p
[test 53:]pc 0k .001 .001%p
[test 54:]pc 0k .01 .003%p
[test 55:]pc 2k 7 3%p
[test 56:]pc 2k 10 3%p
[test 57:]pc 2k 17 5%p
[test 58:]pc 2k 22 7%p
[test 59:]pc 2k _7 3%p
[test 60:]pc 2k 7 _3%p
[test 61:]pc 2k _7 _3%p
[test 62:]pc 4k 1 3%p
[test 63:]pc 4k 2 3%p
[test 64:]pc 4k 10 7%p
[test 65:]pc 2k 1.5 .5%p
[test 66:]pc 2k 3.5 1.5%p
[test 67:]pc 2k 7.25 2.25%p
[test 68:]pc 2k 10.5 3.5%p
EOF

287
tests/0032-dc.sh Executable file
View File

@ -0,0 +1,287 @@
#!/bin/sh
tmp=$$.tmp
trap 'rm -f $tmp' EXIT
trap 'exit $?' HUP INT TERM
# Test ~ command: divmod (pushes quotient then remainder, remainder on top)
# Output format: each ~ produces two lines: remainder (top), then quotient
# Note: ~ now uses divscale like / and %, so results should match
cat <<EOF >$tmp
test 1:
0
3
test 2:
1
3
test 3:
1
2
test 4:
1
3
test 5:
2
14
test 6:
0
10
test 7:
1
33
test 8:
0
3
test 9:
2
3
test 10:
0
0
test 11:
0
1
test 12:
3
0
test 13:
0
1
test 14:
1
0
test 15:
1
0
test 16:
1
0
test 17:
0
5
test 18:
0
100
test 19:
99
0
test 20:
0
-3
test 21:
0
-3
test 22:
0
3
test 23:
-1
-2
test 24:
1
-2
test 25:
-1
2
test 26:
-1
-3
test 27:
1
-3
test 28:
-1
3
test 29:
0
-10
test 30:
0
-10
test 31:
0
10
test 32:
0
-5
test 33:
0
-5
test 34:
0
5
test 35:
0
0
test 36:
1
1
test 37:
789
123456
test 38:
4
14285714285
test 39:
0
1371742100137174210
test 40:
1
49999999999999999999
test 41:
0
33333333333333333333
test 42:
1
1
test 43:
0
1
test 44:
0
3
test 45:
0
3
test 46:
1.5
3
test 47:
0
3
test 48:
1.5
2
test 49:
0
1
test 50:
0
5
test 51:
0
-3
test 52:
0
-3
test 53:
0
3
test 54:
0
-3
test 55:
0
-3
test 56:
0
3
test 57:
0
1
test 58:
.001
3
test 59:
.01
3
test 60:
0
20
test 61:
.5
0
test 62:
0
1000
test 63:
0
4
test 64:
0
4
test 65:
0
16
test 66:
15
15
test 67:
1
16
test 68:
0
32
EOF
$EXEC ../dc <<EOF | diff -u $tmp -
[test 1:]pc 6 2~f c
[test 2:]pc 7 2~f c
[test 3:]pc 7 3~f c
[test 4:]pc 10 3~f c
[test 5:]pc 100 7~f c
[test 6:]pc 100 10~f c
[test 7:]pc 100 3~f c
[test 8:]pc 15 5~f c
[test 9:]pc 17 5~f c
[test 10:]pc 0 5~f c
[test 11:]pc 5 5~f c
[test 12:]pc 3 7~f c
[test 13:]pc 1 1~f c
[test 14:]pc 1 2~f c
[test 15:]pc 1 5~f c
[test 16:]pc 1 10~f c
[test 17:]pc 5 1~f c
[test 18:]pc 100 1~f c
[test 19:]pc 99 100~f c
[test 20:]pc _6 2~f c
[test 21:]pc 6 _2~f c
[test 22:]pc _6 _2~f c
[test 23:]pc _7 3~f c
[test 24:]pc 7 _3~f c
[test 25:]pc _7 _3~f c
[test 26:]pc _10 3~f c
[test 27:]pc 10 _3~f c
[test 28:]pc _10 _3~f c
[test 29:]pc _100 10~f c
[test 30:]pc 100 _10~f c
[test 31:]pc _100 _10~f c
[test 32:]pc _5 1~f c
[test 33:]pc 5 _1~f c
[test 34:]pc _5 _1~f c
[test 35:]pc 0 _5~f c
[test 36:]pc 1000000 999999~f c
[test 37:]pc 123456789 1000~f c
[test 38:]pc 99999999999 7~f c
[test 39:]pc 12345678901234567890 9~f c
[test 40:]pc 99999999999999999999 2~f c
[test 41:]pc 99999999999999999999 3~f c
[test 42:]pc 99999999999999999999 99999999999999999998~f c
[test 43:]pc 99999999999999999999 99999999999999999999~f c
[test 44:]pc 7.5 2.5~f c
[test 45:]pc 1.5 .5~f c
[test 46:]pc 10.5 3~f c
[test 47:]pc 4.5 1.5~f c
[test 48:]pc 7.5 3~f c
[test 49:]pc .5 .5~f c
[test 50:]pc 2.5 .5~f c
[test 51:]pc _7.5 2.5~f c
[test 52:]pc 7.5 _2.5~f c
[test 53:]pc _7.5 _2.5~f c
[test 54:]pc _1.5 .5~f c
[test 55:]pc 1.5 _.5~f c
[test 56:]pc _1.5 _.5~f c
[test 57:]pc .001 .001~f c
[test 58:]pc .01 .003~f c
[test 59:]pc .1 .03~f c
[test 60:]pc 10 .5~f c
[test 61:]pc .5 10~f c
[test 62:]pc 100 .1~f c
[test 63:]pc 8 2~f c
[test 64:]pc 16 4~f c
[test 65:]pc 256 16~f c
[test 66:]pc 255 16~f c
[test 67:]pc 257 16~f c
[test 68:]pc 1024 32~f c
EOF

137
tests/0033-dc.sh Executable file
View File

@ -0,0 +1,137 @@
#!/bin/sh
tmp=$$.tmp
trap 'rm -f $tmp' EXIT
trap 'exit $?' HUP INT TERM
# Expected output for exponentiation tests
# Values derived from system bc
cat <<EOF >$tmp
test 1:
1
test 2:
2
test 3:
8
test 4:
1024
test 5:
243
test 6:
1000000
test 7:
4
test 8:
-8
test 9:
16
test 10:
-32
test 11:
-27
test 12:
81
test 13:
-1000
test 14:
-100000
test 15:
1000000
test 16:
1
test 17:
1
test 18:
1
test 19:
1
test 20:
.5000000000
test 21:
.2500000000
test 22:
.1250000000
test 23:
.0625000000
test 24:
.0010000000
test 25:
-.1250000000
test 26:
.0625000000
test 27:
2.25
test 28:
3.375
test 29:
.25
test 30:
.125
test 31:
2.25
test 32:
-3.375
test 33:
1.5625
test 34:
.0625
test 35:
.015625
test 36:
.0625
test 37:
-.015625
test 38:
.015625
test 39:
-.001953125
test 40:
4.0000000000
test 41:
8.0000000000
EOF
$EXEC ../dc <<EOF | diff -u $tmp -
[test 1:]pc 2 0^p
[test 2:]pc 2 1^p
[test 3:]pc 2 3^p
[test 4:]pc 2 10^p
[test 5:]pc 3 5^p
[test 6:]pc 10 6^p
[test 7:]pc _2 2^p
[test 8:]pc _2 3^p
[test 9:]pc _2 4^p
[test 10:]pc _2 5^p
[test 11:]pc _3 3^p
[test 12:]pc _3 4^p
[test 13:]pc _10 3^p
[test 14:]pc _10 5^p
[test 15:]pc _10 6^p
[test 16:]pc 0 0^p
[test 17:]pc 5 0^p
[test 18:]pc _5 0^p
[test 19:]pc 100 0^p
[test 20:]pc 10k 2 _1^p
[test 21:]pc 10k 2 _2^p
[test 22:]pc 10k 2 _3^p
[test 23:]pc 10k 4 _2^p
[test 24:]pc 10k 10 _3^p
[test 25:]pc 10k _2 _3^p
[test 26:]pc 10k _2 _4^p
[test 27:]pc 1.50 2^p
[test 28:]pc 1.500 3^p
[test 29:]pc .50 2^p
[test 30:]pc .500 3^p
[test 31:]pc _1.50 2^p
[test 32:]pc _1.500 3^p
[test 33:]pc 1.2500 2^p
[test 34:]pc .2500 2^p
[test 35:]pc .250000 3^p
[test 36:]pc _.2500 2^p
[test 37:]pc _.250000 3^p
[test 38:]pc .125000 2^p
[test 39:]pc _.125000000 3^p
[test 40:]pc 10k .50 _2^p
[test 41:]pc 10k .500 _3^p
EOF

150
tests/0034-dc.sh Executable file
View File

@ -0,0 +1,150 @@
#!/bin/sh
tmp=$$.tmp
trap 'rm -f $tmp' EXIT
trap 'exit $?' HUP INT TERM
cat <<EOF >$tmp
test 1:
0
test 2:
1
test 3:
2
test 4:
3
test 5:
5
test 6:
6
test 7:
7
test 8:
9
test 9:
10
test 10:
1
test 11:
1
test 12:
1.41
test 13:
1.4142
test 14:
1.414213
test 15:
1.7
test 16:
1.732
test 17:
1.73205
test 18:
.50
test 19:
.2500
test 20:
.10
test 21:
.0100
test 22:
.001000
test 23:
.7
test 24:
.353
test 25:
.3
test 26:
.316
test 27:
.31622
test 28:
.0316
test 29:
1.20
test 30:
1.5000
test 31:
1.22
test 32:
1.2247
test 33:
1.110
test 34:
1.11085
test 35:
.9486
test 36:
.999499
test 37:
1.58
test 38:
3.5128
test 39:
2.0
test 40:
2.00
test 41:
2.000
test 42:
2.0000000000
test 43:
100.0000
test 44:
11.111075
test 45:
100000000
test 46:
9999
EOF
$EXEC ../dc <<EOF | diff -u $tmp -
[test 1:]pc 0k 0vp
[test 2:]pc 0k 1vp
[test 3:]pc 0k 4vp
[test 4:]pc 0k 9vp
[test 5:]pc 0k 25vp
[test 6:]pc 0k 36vp
[test 7:]pc 0k 49vp
[test 8:]pc 0k 81vp
[test 9:]pc 0k 100vp
[test 10:]pc 0k 2vp
[test 11:]pc 0k 3vp
[test 12:]pc 2k 2vp
[test 13:]pc 4k 2vp
[test 14:]pc 6k 2vp
[test 15:]pc 1k 3vp
[test 16:]pc 3k 3vp
[test 17:]pc 5k 3vp
[test 18:]pc 2k .25vp
[test 19:]pc 4k .0625vp
[test 20:]pc 2k .01vp
[test 21:]pc 4k .0001vp
[test 22:]pc 6k .000001vp
[test 23:]pc 1k .5vp
[test 24:]pc 3k .125vp
[test 25:]pc 1k .1vp
[test 26:]pc 3k .1vp
[test 27:]pc 5k .1vp
[test 28:]pc 4k .001vp
[test 29:]pc 2k 1.44vp
[test 30:]pc 4k 2.25vp
[test 31:]pc 2k 1.5vp
[test 32:]pc 4k 1.5vp
[test 33:]pc 3k 1.234vp
[test 34:]pc 5k 1.234vp
[test 35:]pc 4k .9vp
[test 36:]pc 6k .999vp
[test 37:]pc 2k 2.5vp
[test 38:]pc 4k 12.34vp
[test 39:]pc 1k 4vp
[test 40:]pc 2k 4vp
[test 41:]pc 3k 4vp
[test 42:]pc 10k 4vp
[test 43:]pc 4k 10000vp
[test 44:]pc 6k 123.456vp
[test 45:]pc 0k 10000000000000000vp
[test 46:]pc 0k 99980001vp
EOF

30
tests/0035-dc.sh Executable file
View File

@ -0,0 +1,30 @@
#!/bin/sh
tmp=$$.tmp
trap 'rm -f $tmp' EXIT
trap 'exit $?' HUP INT TERM
# Test negative number sqrt - should produce error message and push 0
# Test negative numbers: integers, fractions, odd and even fraction digits
$EXEC ../dc <<EOF >$tmp 2>&1
[test 1:]pc _1vp
[test 2:]pc _4vp
[test 3:]pc _.5vp
[test 4:]pc _.25vp
EOF
diff -u - $tmp <<'EOF'
../dc: square root of negative number
../dc: square root of negative number
../dc: square root of negative number
../dc: square root of negative number
test 1:
0
test 2:
0
test 3:
0
test 4:
0
EOF

64
tests/0036-dc.sh Executable file
View File

@ -0,0 +1,64 @@
#!/bin/sh
set -e
tmp=$$.tmp
trap 'rm -f $tmp' EXIT
trap 'exit $?' HUP INT TERM
# Test i, o, k, I, O, K commands
cat <<'EOF' >$tmp
test 1:
10
test 2:
10
test 3:
0
test 4:
16
test 5:
16
10
test 6:
5
test 7:
A
test 8:
FF
test 9:
10
test 10:
1010
test 11:
10
test 12:
.33333
test 13:
12 15
test 14:
01 04 19 19
test 15:
01.10
test 16:
.05 00
EOF
$EXEC ../dc <<'EOF' | diff -u $tmp -
[test 1:]pc Ip
[test 2:]pc Op
[test 3:]pc Kp
[test 4:]pc 16i Ip
[test 5:]pc Ao Ip Op
[test 6:]pc Ai 5k Kp
[test 7:]pc 16o 10p
[test 8:]pc 255p
[test 9:]pc 10o 16i Ap
[test 10:]pc Ai 2o 10p
[test 11:]pc Ao 2i 1010p
[test 12:]pc Ai 5k 1 3/p
[test 13:]pc 20o 255p
[test 14:]pc 9999p
[test 15:]pc 1.5p
[test 16:]pc .25p
EOF

77
tests/0037-dc.sh Executable file
View File

@ -0,0 +1,77 @@
#!/bin/sh
tmp=$$.tmp
trap 'rm -f $tmp' EXIT
trap 'exit $?' HUP INT TERM
# Expected output for z, Z, and X operators
cat <<EOF >$tmp
test 1:
0
test 2:
1
test 3:
2
test 4:
3
test 5:
5
test 6:
1
test 7:
3
test 8:
2
test 9:
3
test 10:
4
test 11:
1
test 12:
1
test 13:
1
test 14:
1
test 15:
1
test 16:
1
test 17:
0
test 18:
1
test 19:
2
test 20:
3
test 21:
5
EOF
# Test z (stack depth), Z (digit count/string length), X (scale)
$EXEC ../dc <<EOF | diff -u $tmp -
[test 1:]pc zp c
[test 2:]pc 1 zp c
[test 3:]pc 1 2 zp c
[test 4:]pc 1 2 3 zp c
[test 5:]pc 12345Zp c
[test 6:]pc 0Zp c
[test 7:]pc 123Zp c
[test 8:]pc 1.5Zp c
[test 9:]pc 1.23Zp c
[test 10:]pc 1.001Zp c
[test 11:]pc 0.5Zp c
[test 12:]pc 0.05Zp c
[test 13:]pc 0.005Zp c
[test 14:]pc .5Zp c
[test 15:]pc .05Zp c
[test 16:]pc .005Zp c
[test 17:]pc 0Xp c
[test 18:]pc 1.2Xp c
[test 19:]pc 1.23Xp c
[test 20:]pc 1.234Xp c
[test 21:]pc [hello]Zp c
EOF

72
tests/0038-dc.sh Executable file
View File

@ -0,0 +1,72 @@
#!/bin/sh
tmp=$$.tmp
trap 'rm -f $tmp' EXIT
trap 'exit $?' HUP INT TERM
# Expected output for f, c, d, and r operators
cat <<EOF >$tmp
test 1:
test 2:
3
2
1
test 3:
0
test 4:
5
5
test 5:
3
3
2
1
test 6:
2
1
test 7:
2
3
1
test 8:
10
test 9:
1
test 10:
15
test 11:
test 12:
1
1
1
1
test 13:
-5
-5
test 14:
1.5
1.5
test 15:
2
3
1
EOF
$EXEC ../dc <<EOF | diff -u $tmp -
[test 1:]pc f
[test 2:]pc 1 2 3 f c
[test 3:]pc 1 2 3 c zp c
[test 4:]pc 5 d f c
[test 5:]pc 1 2 3 d f c
[test 6:]pc 2 1 r f c
[test 7:]pc 1 2 3 r f c
[test 8:]pc 5 d +p c
[test 9:]pc 1 2 r -p c
[test 10:]pc 5 d d + +p c
[test 11:]pc 1 2 3 c f
[test 12:]pc 1 d d d f c
[test 13:]pc _5 d f c
[test 14:]pc 1.5 d f c
[test 15:]pc 1 2 3 r f c
EOF

101
tests/0039-dc.sh Executable file
View File

@ -0,0 +1,101 @@
#!/bin/sh
tmp=$$.tmp
trap 'rm -f $tmp' EXIT
trap 'exit $?' HUP INT TERM
# Test s, l, S, L register commands
$EXEC ../dc <<'EOF' >$tmp 2>&1
[test 1:]pc 5 sa la p c
[test 2:]pc lz p c
[test 3:]pc 1 sb 2 lb p c
[test 4:]pc 1 sc 2 sc lc p c
[test 5:]pc 1 sd ld ld +p c
[test 6:]pc 5 Se le p c
[test 7:]pc 1 Sf 2 Sf 3 Sf lf p c
[test 8:]pc 1 Sg 2 Sg Lg p c
[test 9:]pc 1 Sh 2 Sh Lh Lh +p c
[test 10:]pc 1 Si Li p c
[test 11:]pc 1 sj 2 Sj 3 Sj Lj Lj lj p c
[test 12:]pc _42 sk lk p c
[test 13:]pc 1.5 sl ll p c
[test 14:]pc 99999999999999999999 sm lm p c
[test 15:]pc [hello] sn ln p c
[test 16:]pc 1 so 2 sp lo lp +p c
[test 17:]pc 1 Sq 2 Sr Lq Lr +p c
[test 18:]pc 1 St 2 St 3 St Lt p Lt p Lt p c
[test 19:]pc 1 2 3 Su Su Su Lu Lu Lu + +p c
[test 20:]pc 1 sv lv lv lv + +p c
[test 21:]pc 1 Sw 2 Sw 3 Sw 4 Sw 5 Sw Lw p Lw p Lw p Lw p Lw p c
[test 22:]pc 1 Sx 2 Sy 3 Sx 4 Sy Lx Ly * Lx Ly * +p c
[test 23:]pc 42 s0 100 S0 L0 p L0 p c
[test 24:]pc LA
[test 25:]pc 1 SB LB LB
[test 26:]pc sC
[test 27:]pc SD
EOF
diff -u - $tmp <<'EOF'
../dc: stack register 'A' (101) is empty
../dc: stack register 'B' (102) is empty
../dc: stack empty
../dc: stack empty
test 1:
5
test 2:
0
test 3:
1
test 4:
2
test 5:
2
test 6:
5
test 7:
3
test 8:
2
test 9:
3
test 10:
1
test 11:
1
test 12:
-42
test 13:
1.5
test 14:
99999999999999999999
test 15:
hello
test 16:
3
test 17:
3
test 18:
3
2
1
test 19:
6
test 20:
3
test 21:
5
4
3
2
1
test 22:
14
test 23:
100
42
test 24:
test 25:
test 26:
test 27:
EOF

135
tests/0040-dc.sh Executable file
View File

@ -0,0 +1,135 @@
#!/bin/sh
tmp=$$.tmp
trap 'rm -f $tmp' EXIT
trap 'exit $?' HUP INT TERM
# Test x, >, !>, <, !<, =, != commands
# Note: dc pops values and compares: first_popped OP second_popped
# So "3 5 >a" pops 5 then 3, checks 5 > 3 (true)
# And "5 3 >a" pops 3 then 5, checks 3 > 5 (false)
$EXEC ../dc <<'EOF' >$tmp 2>&1
[test 1:]pc [42p]x c
[test 2:]pc 5 x p c
[test 3:]pc []x c
[test 4:]pc [[10p]x]x c
[test 5:]pc [[YES]p]sa 3 5 >a c
[test 6:]pc [[NO]p]sa 5 3 >a c
[test 7:]pc [[NO]p]sa 5 5 >a c
[test 8:]pc [[YES]p]sa 5 3 <a c
[test 9:]pc [[NO]p]sa 3 5 <a c
[test 10:]pc [[NO]p]sa 5 5 <a c
[test 11:]pc [[YES]p]sa 5 5 =a c
[test 12:]pc [[NO]p]sa 5 3 =a c
[test 13:]pc [[NO]p]sa 3 5 !>a c
[test 14:]pc [[YES]p]sa 5 3 !>a c
[test 15:]pc [[YES]p]sa 5 5 !>a c
[test 16:]pc [[NO]p]sa 5 3 !<a c
[test 17:]pc [[YES]p]sa 3 5 !<a c
[test 18:]pc [[YES]p]sa 5 5 !<a c
[test 19:]pc [[YES]p]sa 5 3 !=a c
[test 20:]pc [[NO]p]sa 5 5 !=a c
[test 21:]pc [[NO]p]sa _3 _5 >a c
[test 22:]pc [[YES]p]sa _5 _3 >a c
[test 23:]pc [[NO]p]sa 3 _5 >a c
[test 24:]pc [[YES]p]sa _3 5 >a c
[test 25:]pc [[YES]p]sa 0 0 =a c
[test 26:]pc [[YES]p]sa _0 0 =a c
[test 27:]pc [[YES]p]sa 1.4 1.5 >a c
[test 28:]pc [[YES]p]sa 1.5 1.5 =a c
[test 29:]pc [[YES]p]sa 1.5 1.4 <a c
[test 30:]pc [[YES]p]sa 99999999999999999998 99999999999999999999 >a c
[test 31:]pc [d p 1 - d 0 <a]sa 5 la x c
[test 32:]pc [[YES]p]sa [2 2 =a]sb 2 2 =b c
[test 33:]pc 99 sa la x p c
[test 34:]pc [3p]sa [2p]sb 2 3 >a 3 2 <b c
[test 35:]pc [[NO]p]sa 1 2 <a z p c
[test 36:]pc [[[[[77p]]]]]x x x x x c
[test 37:]pc [[YES]p]sa 2k 1.50 1.5 =a c
[test 38:]pc [1p]x [2p]x [3p]x c
[test 39:]pc x
[test 40:]pc [[NO]p]sa 5 >a
[test 41:]pc [[NO]p]sa >a
EOF
diff -u - $tmp <<'EOF'
../dc: stack empty
../dc: stack empty
../dc: stack empty
test 1:
42
test 2:
5
test 3:
test 4:
10
test 5:
YES
test 6:
test 7:
test 8:
YES
test 9:
test 10:
test 11:
YES
test 12:
test 13:
test 14:
YES
test 15:
YES
test 16:
test 17:
YES
test 18:
YES
test 19:
YES
test 20:
test 21:
test 22:
YES
test 23:
test 24:
YES
test 25:
YES
test 26:
YES
test 27:
YES
test 28:
YES
test 29:
YES
test 30:
YES
test 31:
5
4
3
2
1
test 32:
YES
test 33:
99
test 34:
3
2
test 35:
0
test 36:
77
test 37:
YES
test 38:
1
2
3
test 39:
test 40:
test 41:
EOF

101
tests/0041-dc.sh Executable file
View File

@ -0,0 +1,101 @@
#!/bin/sh
tmp=$$.tmp
trap 'rm -f $tmp' EXIT
trap 'exit $?' HUP INT TERM
cat <<'EOF' > $tmp
../dc: stack empty
../dc: Q command argument exceeded string execution depth
../dc: Q command requires a number >= 0
../dc: Q command argument exceeded string execution depth
test 1:
test 2:
test 3:
test 4:
test 5:
99
test 6:
1
4
test 7:
in-macro
after-macro
test 8:
inner
after-all
test 9:
before
after
test 10:
not-equal
continued
test 11:
equal
continued
test 12:
3
2
done
test 12a:
3
done
test 13:
0
1
2
done
test 13a:
0
done
test 14:
deep
outer
final
test 15:
42
test 16:
done
test 17:
first
last
test 18:
before
test 19:
before-q
test 20:
equal
EOF
($EXEC ../dc <<'EOF'
[test 1:]pc Q
[test 2:]pc 1Q
[test 3:]pc _1Q
[test 4:]pc [100Q]x
[test 5:]pc 99 [1Q]x p
[test 6:]pc [[1p q 2p]x 3p]x 4p
[test 7:]pc [[in-macro]p 1Q [not-printed]p]x [after-macro]p
[test 8:]pc [[[inner]p 2Q [not1]p]x [not2]p]x [after-all]p
[test 9:]pc [before]p 0Q [after]p
[test 10:]pc [[equal-quit]p q]sa 5 3 =a [not-equal]p [continued]p
[test 11:]pc [[equal-quit]p q]sa 5 5 !=a [equal]p [continued]p
[test 12:]pc 3[[p 1- d 2 !>b 1Q]x]sb lbx [done]p
[test 12a:]pc 3[[p 1- d 2 >b 1Q]x]sb lbx [done]p
[test 13:]pc 0[[p 1+ d 2 !<b 1Q]x]sb lbx [done]p
[test 13a:]pc 0[[p 1+ d 2 <b 1Q]x]sb lbx [done]p
[test 14:]pc [[[[deep]p 2Q [x]p]x [y]p]x [outer]p]x [final]p
[test 15:]pc [[42 q]x [x]p]x p
[test 16:]pc [[1Q [not]p]x [done]p]x
[test 17:]pc [[[first]p q q q]x [x]p]x [last]p
[test 18:]pc [before]p q [after]p
EOF
$EXEC ../dc <<'EOF'
[test 19:]pc [[before-q]p q [after-q]p]x [never]p
EOF
$EXEC ../dc <<'EOF'
[test 20:]pc [[equal]p q]sa 5 5 =a [not-printed]p
EOF
) 2>&1 | diff -u - $tmp

107
tests/0042-dc.sh Executable file
View File

@ -0,0 +1,107 @@
#!/bin/sh
tmp=$$.tmp
trap 'rm -f $tmp' EXIT
trap 'exit $?' HUP INT TERM
# Test : and ; array commands
$EXEC ../dc <<'EOF' >$tmp 2>&1
[test 1:]pc 42 0:a 0;a p c
[test 2:]pc 10 0:b 20 1:b 30 2:b 0;b p 1;b p 2;b p c
[test 3:]pc 100 5:c 5;c p c
[test 4:]pc _42 0:d 0;d p c
[test 5:]pc 1.5 0:e 0;e p c
[test 6:]pc 99999999999999999999 0:f 0;f p c
[test 7:]pc [hello] 0:g 0;g p c
[test 8:]pc 1 0:h 2 0:h 0;h p c
[test 9:]pc 5 10:i 10;i p c
[test 10:]pc 1 0:j 2 1:j 3 2:j 0;j 1;j + 2;j +p c
[test 11:]pc 100 0:k 0;k 0;k *p c
[test 12:]pc 7 3:l 3;l 3;l 3;l + +p c
[test 13:]pc 1 0:0 2 1:0 0;0 1;0 +p c
[test 14:]pc 50 0:m 0;m 2/p c
[test 15:]pc 10 0:n 0;n 5 * 2:n 2;n p c
[test 16:]pc 42 _1:o
[test 17:]pc _1;p
[test 18:]pc 100 0:q 1 Sq 0;q p Lq p 0;q p c
[test 19:]pc 10 0:r 1 Sr 20 0:r 2 Sr 30 0:r 0;r p Lr p 0;r p Lr p 0;r p c
[test 20:]pc 5 0:s 1 Ss 2 Ss Ls p 0;s p Ls p 0;s p c
[test 21:]pc 42 0:t 99 st 0;t p lt p c
[test 22:]pc 1 0:u 2 1:u 99 Su 50 0:u 0;u p Lu p 0;u p 1;u p c
[test 23:]pc 10 0:v 20 1:v 1 Sv 2 Sv Lv p Lv p 0;v p 1;v p c
[test 24:]pc 100 5:w 1 Sw 200 5:w 2 Sw 300 5:w 5;w p Lw p 5;w p Lw p 5;w p c
EOF
diff -u - $tmp <<'EOF'
../dc: array index must fit in a positive integer
../dc: array index must fit in a positive integer
test 1:
42
test 2:
10
20
30
test 3:
100
test 4:
-42
test 5:
1.5
test 6:
99999999999999999999
test 7:
hello
test 8:
2
test 9:
5
test 10:
6
test 11:
10000
test 12:
21
test 13:
3
test 14:
25
test 15:
50
test 16:
test 17:
test 18:
0
1
100
test 19:
30
2
20
1
10
test 20:
2
0
1
5
test 21:
42
99
test 22:
50
99
1
2
test 23:
2
1
10
20
test 24:
300
2
200
1
100
EOF

59
tests/0043-dc.sh Executable file
View File

@ -0,0 +1,59 @@
#!/bin/sh
tmp=$$.tmp
trap 'rm -f $tmp' EXIT
trap 'exit $?' HUP INT TERM
# Test -i flag for extended register names
# <n> syntax: n is parsed as decimal and used as register name byte
# "str" syntax: str is used as multi-character register name
$EXEC ../dc -i <<'EOF' >$tmp 2>&1
[test 1:]pc 42 s<65> l<65> p c
[test 2:]pc 100 s"foo" l"foo" p c
[test 3:]pc 99 s<65> lA p c
[test 4:]pc 1 S<66> 2 S<66> L<66> p L<66> p c
[test 5:]pc 10 S"bar" 20 S"bar" L"bar" p L"bar" p c
[test 6:]pc 5 s<67> lC p c
[test 7:]pc 1 s"x" 2 s"xy" 3 s"xyz" l"x" p l"xy" p l"xyz" p c
[test 8:]pc 77 s<0> l<0> p c
[test 9:]pc 88 s"D" lD p c
[test 10:]pc [42p] s<69> l<69> x c
[test 11:]pc [99p] s"macro" l"macro" x c
[test 12:]pc 1 s<70> 2 s<70> 3 s<70> l<70> p c
[test 13:]pc 10 s"reg" 20 s"reg" 30 s"reg" l"reg" p c
EOF
diff -u - $tmp <<'EOF'
test 1:
42
test 2:
100
test 3:
99
test 4:
2
1
test 5:
20
10
test 6:
5
test 7:
1
2
3
test 8:
77
test 9:
88
test 10:
42
test 11:
99
test 12:
3
test 13:
30
EOF

36
tests/0044-dc.sh Executable file
View File

@ -0,0 +1,36 @@
#!/bin/sh
set -e
tmp=$$.tmp
trap 'rm -f $tmp' EXIT
trap 'exit $?' HUP INT TERM
# Expected output for line wrapping tests (derived from system dc)
cat <<'EOF' >$tmp
test 1:
327339060789614187001318969682759915221664204604306478948329136809613\
379640467455488327009232590415715088668412756007100921725654588539305\
3328527589376
test 2:
-32733906078961418700131896968275991522166420460430647894832913680961\
337964046745548832700923259041571508866841275600710092172565458853930\
53328527589376
test 3:
.33333333333333333333333333333333333333333333333333333333333333333333\
33333333333333333333333333333333
test 4:
123456789012345678901234567890123456789012345678901234567890123456789
test 5:
123456789012345678901234567890123456789012345678901234567890123456789\
0
EOF
$EXEC ../dc <<'EOF' | diff -u $tmp -
[test 1:]pc 2 500^ p
[test 2:]pc 0 2 500^ - p
[test 3:]pc 100k 1 3 / p
[test 4:]pc 123456789012345678901234567890123456789012345678901234567890123456789 p
[test 5:]pc 1234567890123456789012345678901234567890123456789012345678901234567890 p
EOF