mirror of
https://github.com/freebsd/freebsd-src.git
synced 2024-11-26 20:12:44 +00:00
usr.bin/bc: remove OpenBSD derived bc and dc commands
Some checks are pending
Cross-build Kernel / ${{ matrix.target_arch }} ${{ matrix.os }} (${{ matrix.compiler }}) (clang-14, /usr/lib/llvm-14/bin, ubuntu-22.04, bmake libarchive-dev clang-14 lld-14, amd64, amd64) (push) Waiting to run
Cross-build Kernel / ${{ matrix.target_arch }} ${{ matrix.os }} (${{ matrix.compiler }}) (clang-14, /usr/lib/llvm-14/bin, ubuntu-22.04, bmake libarchive-dev clang-14 lld-14, arm64, aarch64) (push) Waiting to run
Cross-build Kernel / ${{ matrix.target_arch }} ${{ matrix.os }} (${{ matrix.compiler }}) (clang-18, /opt/homebrew/opt/llvm@18/bin, macos-latest, bmake libarchive llvm@18, amd64, amd64) (push) Waiting to run
Cross-build Kernel / ${{ matrix.target_arch }} ${{ matrix.os }} (${{ matrix.compiler }}) (clang-18, /opt/homebrew/opt/llvm@18/bin, macos-latest, bmake libarchive llvm@18, arm64, aarch64) (push) Waiting to run
Cross-build Kernel / ${{ matrix.target_arch }} ${{ matrix.os }} (${{ matrix.compiler }}) (clang-18, /usr/lib/llvm-18/bin, ubuntu-24.04, bmake libarchive-dev clang-18 lld-18, amd64, amd64) (push) Waiting to run
Cross-build Kernel / ${{ matrix.target_arch }} ${{ matrix.os }} (${{ matrix.compiler }}) (clang-18, /usr/lib/llvm-18/bin, ubuntu-24.04, bmake libarchive-dev clang-18 lld-18, arm64, aarch64) (push) Waiting to run
Some checks are pending
Cross-build Kernel / ${{ matrix.target_arch }} ${{ matrix.os }} (${{ matrix.compiler }}) (clang-14, /usr/lib/llvm-14/bin, ubuntu-22.04, bmake libarchive-dev clang-14 lld-14, amd64, amd64) (push) Waiting to run
Cross-build Kernel / ${{ matrix.target_arch }} ${{ matrix.os }} (${{ matrix.compiler }}) (clang-14, /usr/lib/llvm-14/bin, ubuntu-22.04, bmake libarchive-dev clang-14 lld-14, arm64, aarch64) (push) Waiting to run
Cross-build Kernel / ${{ matrix.target_arch }} ${{ matrix.os }} (${{ matrix.compiler }}) (clang-18, /opt/homebrew/opt/llvm@18/bin, macos-latest, bmake libarchive llvm@18, amd64, amd64) (push) Waiting to run
Cross-build Kernel / ${{ matrix.target_arch }} ${{ matrix.os }} (${{ matrix.compiler }}) (clang-18, /opt/homebrew/opt/llvm@18/bin, macos-latest, bmake libarchive llvm@18, arm64, aarch64) (push) Waiting to run
Cross-build Kernel / ${{ matrix.target_arch }} ${{ matrix.os }} (${{ matrix.compiler }}) (clang-18, /usr/lib/llvm-18/bin, ubuntu-24.04, bmake libarchive-dev clang-18 lld-18, amd64, amd64) (push) Waiting to run
Cross-build Kernel / ${{ matrix.target_arch }} ${{ matrix.os }} (${{ matrix.compiler }}) (clang-18, /usr/lib/llvm-18/bin, ubuntu-24.04, bmake libarchive-dev clang-18 lld-18, arm64, aarch64) (push) Waiting to run
In 2020, an improved implementation of the bc and dc commands developed by Gavin D. Howard has been imported into FreeBSD. It has replaced the OpenBSD-derived versions of these commands in all currently supported FreeBSD releases. The OpenBSD versions could still be built using the WITHOUT_GH_BC option. There have been no reports of problems or unexpected deviations from the OpenBSD version for some time, therefore keeping the OpenBSD version is no longer required in FreeBSD. This commit removes the option to build the OpenBSD version and corresponding source files from -CURRENT. No MFC is planned, all currently released FreeBSD versions should retain the build option. The WITHOUT_GH_BC option is no longer accepted and will cause make buildworld to fail. Reviewed by: des, emaste Approved by: des Relnotes: yes Differential Revision: https://reviews.freebsd.org/D46876
This commit is contained in:
parent
e80419da6c
commit
8ea6c11540
@ -51,6 +51,13 @@
|
||||
# xargs -n1 | sort | uniq -d;
|
||||
# done
|
||||
|
||||
# 20241124: library and tests of OpenBSD dc
|
||||
OLD_FILES+=usr/share/misc/bc.library
|
||||
OLD_FILES+=usr/tests/usr.bin/dc/Kyuafile
|
||||
OLD_FILES+=usr/tests/usr.bin/dc/bcode
|
||||
OLD_FILES+=usr/tests/usr.bin/dc/inout
|
||||
OLD_DIRS+=usr/tests/usr.bin/dc
|
||||
|
||||
# 20241119: rewrite mv tests
|
||||
OLD_FILES+=usr/tests/bin/mv/legacy_test
|
||||
|
||||
|
5
UPDATING
5
UPDATING
@ -27,6 +27,11 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 15.x IS SLOW:
|
||||
world, or to merely disable the most expensive debugging functionality
|
||||
at runtime, run "ln -s 'abort:false,junk:false' /etc/malloc.conf".)
|
||||
|
||||
20241124:
|
||||
The OpenBSD derived bc and dc implementations and the WITHOUT_GH_BC
|
||||
option that allowed building them instead of the advanced version
|
||||
imported more than 4 years ago have been removed.
|
||||
|
||||
20241025:
|
||||
The support for the rc_fast_and_loose variable has been removed from
|
||||
rc.subr(8). Users setting rc_fast_and_loose on their systems are
|
||||
|
@ -712,12 +712,6 @@ and
|
||||
.Xr ftpd 8 .
|
||||
.It Va WITHOUT_GAMES
|
||||
Do not build games.
|
||||
.It Va WITHOUT_GH_BC
|
||||
Install the traditional FreeBSD
|
||||
.Xr bc 1
|
||||
and
|
||||
.Xr dc 1
|
||||
programs instead of the enhanced versions.
|
||||
.It Va WITHOUT_GNU_DIFF
|
||||
Do not build GNU
|
||||
.Xr diff3 1 ;
|
||||
|
@ -101,7 +101,6 @@ __DEFAULT_YES_OPTIONS = \
|
||||
FREEBSD_UPDATE \
|
||||
FTP \
|
||||
GAMES \
|
||||
GH_BC \
|
||||
GNU_DIFF \
|
||||
GOOGLETEST \
|
||||
GPIO \
|
||||
|
@ -2071,14 +2071,6 @@ OLD_FILES+=usr/share/man/man8/strfile.8.gz
|
||||
OLD_FILES+=usr/share/man/man8/unstr.8.gz
|
||||
.endif
|
||||
|
||||
.if ${MK_GH_BC} == no
|
||||
OLD_FILES+=usr/share/misc/bc.library
|
||||
OLD_FILES+=usr/tests/usr.bin/dc/Kyuafile
|
||||
OLD_FILES+=usr/tests/usr.bin/dc/bcode
|
||||
OLD_FILES+=usr/tests/usr.bin/dc/inout
|
||||
OLD_DIRS+=usr/tests/usr.bin/dc
|
||||
.endif
|
||||
|
||||
.if ${MK_GOOGLETEST} == no
|
||||
OLD_FILES+=usr/include/private/gmock/gmock-actions.h
|
||||
OLD_FILES+=usr/include/private/gmock/gmock-cardinalities.h
|
||||
|
@ -1,5 +0,0 @@
|
||||
Install the traditional FreeBSD
|
||||
.Xr bc 1
|
||||
and
|
||||
.Xr dc 1
|
||||
programs instead of the enhanced versions.
|
@ -207,12 +207,7 @@ SUBDIR.${MK_GAMES}+= number
|
||||
SUBDIR.${MK_GAMES}+= pom
|
||||
SUBDIR.${MK_GAMES}+= primes
|
||||
SUBDIR.${MK_GAMES}+= random
|
||||
.if ${MK_GH_BC} == "yes"
|
||||
SUBDIR+= gh-bc
|
||||
.else
|
||||
SUBDIR.${MK_OPENSSL}+= bc
|
||||
SUBDIR.${MK_OPENSSL}+= dc
|
||||
.endif
|
||||
.if ${MK_GNU_DIFF} == "no"
|
||||
SUBDIR+= diff3
|
||||
.endif
|
||||
|
@ -1,14 +0,0 @@
|
||||
# $OpenBSD: Makefile,v 1.7 2013/09/19 16:12:00 otto Exp $
|
||||
|
||||
PROG= bc
|
||||
SRCS= bc.y scan.l tty.c
|
||||
CFLAGS+= -I. -I${.CURDIR}
|
||||
|
||||
LIBADD= edit
|
||||
|
||||
NO_WMISSING_VARIABLE_DECLARATIONS=
|
||||
|
||||
FILES+= bc.library
|
||||
FILESDIR=${SHAREDIR}/misc
|
||||
|
||||
.include <bsd.prog.mk>
|
@ -1,17 +0,0 @@
|
||||
# Autogenerated - do NOT edit!
|
||||
|
||||
DIRDEPS = \
|
||||
include \
|
||||
include/xlocale \
|
||||
lib/${CSU_DIR} \
|
||||
lib/libc \
|
||||
lib/libcompiler_rt \
|
||||
lib/libedit \
|
||||
usr.bin/yacc.host \
|
||||
|
||||
|
||||
.include <dirdeps.mk>
|
||||
|
||||
.if ${DEP_RELDIR} == ${_DEP_RELDIR}
|
||||
# local dependencies - needed for -jN in clean tree
|
||||
.endif
|
413
usr.bin/bc/bc.1
413
usr.bin/bc/bc.1
@ -1,413 +0,0 @@
|
||||
.\" $OpenBSD: bc.1,v 1.32 2015/11/17 05:45:35 mmcc Exp $
|
||||
.\"
|
||||
.\" Copyright (C) Caldera International Inc. 2001-2002.
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code and documentation must retain the above
|
||||
.\" copyright notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. 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.
|
||||
.\" 3. All advertising materials mentioning features or use of this software
|
||||
.\" must display the following acknowledgement:
|
||||
.\" This product includes software developed or owned by Caldera
|
||||
.\" International, Inc.
|
||||
.\" 4. Neither the name of Caldera International, Inc. nor the names of other
|
||||
.\" contributors may be used to endorse or promote products derived from
|
||||
.\" this software without specific prior written permission.
|
||||
.\"
|
||||
.\" USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
|
||||
.\" INTERNATIONAL, INC. 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 CALDERA INTERNATIONAL, INC. 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.
|
||||
.\"
|
||||
.Dd November 21, 2015
|
||||
.Dt BC 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm bc
|
||||
.Nd arbitrary-precision arithmetic language and calculator
|
||||
.Sh SYNOPSIS
|
||||
.Nm bc
|
||||
.Op Fl chlv
|
||||
.Op Fl e Ar expression
|
||||
.Op Ar file ...
|
||||
.Sh DESCRIPTION
|
||||
.Nm
|
||||
is an interactive processor for a language which resembles
|
||||
C but provides unlimited precision arithmetic.
|
||||
It takes input from any expressions on the command line and
|
||||
any files given, then reads the standard input.
|
||||
.Pp
|
||||
Options available:
|
||||
.Bl -tag -width Ds
|
||||
.It Fl c
|
||||
.Nm
|
||||
is actually a preprocessor for
|
||||
.Xr dc 1 ,
|
||||
which it invokes automatically, unless the
|
||||
.Fl c
|
||||
.Pq compile only
|
||||
option is present.
|
||||
In this case the generated
|
||||
.Xr dc 1
|
||||
instructions are sent to the standard output,
|
||||
instead of being interpreted by a running
|
||||
.Xr dc 1
|
||||
process.
|
||||
.It Fl e Ar expression , Fl Fl expression Ar expression
|
||||
Evaluate
|
||||
.Ar expression .
|
||||
If multiple
|
||||
.Fl e
|
||||
options are specified, they are processed in the order given,
|
||||
separated by newlines.
|
||||
.It Fl h , Fl Fl help
|
||||
Prints usage information.
|
||||
.It Fl l , Fl Fl mathlib
|
||||
Allow specification of an arbitrary precision math library.
|
||||
The definitions in the library are available to command line
|
||||
expressions.
|
||||
.It Fl v , Fl Fl version
|
||||
Prints version information.
|
||||
.El
|
||||
.Pp
|
||||
The syntax for
|
||||
.Nm
|
||||
programs is as follows:
|
||||
.Sq L
|
||||
means letter a-z;
|
||||
.Sq E
|
||||
means expression;
|
||||
.Sq S
|
||||
means statement.
|
||||
As a non-portable extension, it is possible to use long names
|
||||
in addition to single letter names.
|
||||
A long name is a sequence starting with a lowercase letter
|
||||
followed by any number of lowercase letters and digits.
|
||||
The underscore character
|
||||
.Pq Sq _
|
||||
counts as a letter.
|
||||
.Pp
|
||||
Comments
|
||||
.Bd -unfilled -offset indent -compact
|
||||
are enclosed in /* and */
|
||||
are enclosed in # and the next newline
|
||||
.Ed
|
||||
.Pp
|
||||
The newline is not part of the line comment,
|
||||
which in itself is a non-portable extension.
|
||||
.Pp
|
||||
Names
|
||||
.Bd -unfilled -offset indent -compact
|
||||
simple variables: L
|
||||
array elements: L [ E ]
|
||||
The words `ibase', `obase', and `scale'
|
||||
The word `last' or a single dot
|
||||
.Ed
|
||||
.Pp
|
||||
Other operands
|
||||
.Bd -unfilled -offset indent -compact
|
||||
arbitrarily long numbers with optional sign and decimal point
|
||||
( E )
|
||||
sqrt ( E )
|
||||
length ( E ) number of significant decimal digits
|
||||
scale ( E ) number of digits right of decimal point
|
||||
L ( E , ... , E )
|
||||
.Ed
|
||||
.Pp
|
||||
The sequence
|
||||
.Sq \e<newline><whitespace>
|
||||
is ignored within numbers.
|
||||
.Pp
|
||||
Operators
|
||||
.Pp
|
||||
The following arithmetic and logical operators can be used.
|
||||
The semantics of the operators is the same as in the C language.
|
||||
They are listed in order of decreasing precedence.
|
||||
Operators in the same group have the same precedence.
|
||||
.Bl -column "= += \-= *= /= %= ^=" "Associativity" "multiply, divide, modulus" -offset indent
|
||||
.It Sy "Operator" Ta Sy "Associativity" Ta Sy "Description"
|
||||
.It "++ \-\-" Ta "none" Ta "increment, decrement"
|
||||
.It "\-" Ta "none" Ta "unary minus"
|
||||
.It "^" Ta "right" Ta "power"
|
||||
.It "* / %" Ta "left" Ta "multiply, divide, modulus"
|
||||
.It "+ \-" Ta "left" Ta "plus, minus"
|
||||
.It "= += -= *= /= %= ^=" Ta "right" Ta "assignment"
|
||||
.It "== <= >= != < >" Ta "none" Ta "relational"
|
||||
.It "!" Ta "none" Ta "boolean not"
|
||||
.It "&&" Ta "left" Ta "boolean and"
|
||||
.It "||" Ta "left" Ta "boolean or"
|
||||
.El
|
||||
.Pp
|
||||
Note the following:
|
||||
.Bl -bullet -offset indent
|
||||
.It
|
||||
The relational operators may appear in any expression.
|
||||
The
|
||||
.St -p1003.1-2008
|
||||
standard only allows them in the conditional expression of an
|
||||
.Sq if ,
|
||||
.Sq while
|
||||
or
|
||||
.Sq for
|
||||
statement.
|
||||
.It
|
||||
The relational operators have a lower precedence than the assignment
|
||||
operators.
|
||||
This has the consequence that the expression
|
||||
.Sy a = b < c
|
||||
is interpreted as
|
||||
.Sy (a = b) < c ,
|
||||
which is probably not what the programmer intended.
|
||||
.It
|
||||
In contrast with the C language, the relational operators all have
|
||||
the same precedence, and are non-associative.
|
||||
The expression
|
||||
.Sy a < b < c
|
||||
will produce a syntax error.
|
||||
.It
|
||||
The boolean operators (!, && and ||) are non-portable extensions.
|
||||
.It
|
||||
The boolean not
|
||||
(!) operator has much lower precedence than the same operator in the
|
||||
C language.
|
||||
This has the consequence that the expression
|
||||
.Sy !a < b
|
||||
is interpreted as
|
||||
.Sy !(a < b) .
|
||||
Prudent programmers use parentheses when writing expressions involving
|
||||
boolean operators.
|
||||
.El
|
||||
.Pp
|
||||
Statements
|
||||
.Bd -unfilled -offset indent -compact
|
||||
E
|
||||
{ S ; ... ; S }
|
||||
if ( E ) S
|
||||
if ( E ) S else S
|
||||
while ( E ) S
|
||||
for ( E ; E ; E ) S
|
||||
null statement
|
||||
break
|
||||
continue
|
||||
quit
|
||||
a string of characters, enclosed in double quotes
|
||||
print E ,..., E
|
||||
.Ed
|
||||
.Pp
|
||||
A string may contain any character, except double quote.
|
||||
The if statement with an else branch is a non-portable extension.
|
||||
All three E's in a for statement may be empty.
|
||||
This is a non-portable extension.
|
||||
The continue and print statements are also non-portable extensions.
|
||||
.Pp
|
||||
The print statement takes a list of comma-separated expressions.
|
||||
Each expression in the list is evaluated and the computed
|
||||
value is printed and assigned to the variable `last'.
|
||||
No trailing newline is printed.
|
||||
The expression may also be a string enclosed in double quotes.
|
||||
Within these strings the following escape sequences may be used:
|
||||
.Sq \ea
|
||||
for bell (alert),
|
||||
.Sq \eb
|
||||
for backspace,
|
||||
.Sq \ef
|
||||
for formfeed,
|
||||
.Sq \en
|
||||
for newline,
|
||||
.Sq \er
|
||||
for carriage return,
|
||||
.Sq \et
|
||||
for tab,
|
||||
.Sq \eq
|
||||
for double quote and
|
||||
.Sq \e\e
|
||||
for backslash.
|
||||
Any other character following a backslash will be ignored.
|
||||
Strings will not be assigned to `last'.
|
||||
.Pp
|
||||
Function definitions
|
||||
.Bd -unfilled -offset indent
|
||||
define L ( L ,..., L ) {
|
||||
auto L, ... , L
|
||||
S; ... S
|
||||
return ( E )
|
||||
}
|
||||
.Ed
|
||||
.Pp
|
||||
As a non-portable extension, the opening brace of the define statement
|
||||
may appear on the next line.
|
||||
The return statement may also appear in the following forms:
|
||||
.Bd -unfilled -offset indent
|
||||
return
|
||||
return ()
|
||||
return E
|
||||
.Ed
|
||||
.Pp
|
||||
The first two are equivalent to the statement
|
||||
.Dq return 0 .
|
||||
The last form is a non-portable extension.
|
||||
Not specifying a return statement is equivalent to writing
|
||||
.Dq return (0) .
|
||||
.Pp
|
||||
Functions available in the math library, which is loaded by specifying the
|
||||
.Fl l
|
||||
flag on the command line
|
||||
.Pp
|
||||
.Bl -tag -width j(n,x) -offset indent -compact
|
||||
.It s(x)
|
||||
sine
|
||||
.It c(x)
|
||||
cosine
|
||||
.It e(x)
|
||||
exponential
|
||||
.It l(x)
|
||||
log
|
||||
.It a(x)
|
||||
arctangent
|
||||
.It j(n,x)
|
||||
Bessel function
|
||||
.El
|
||||
.Pp
|
||||
All function arguments are passed by value.
|
||||
.Pp
|
||||
The value of a statement that is an expression is printed
|
||||
unless the main operator is an assignment.
|
||||
The value printed is assigned to the special variable `last'.
|
||||
This is a non-portable extension.
|
||||
A single dot may be used as a synonym for `last'.
|
||||
Either semicolons or newlines may separate statements.
|
||||
Assignment to
|
||||
.Ar scale
|
||||
influences the number of digits to be retained on arithmetic
|
||||
operations in the manner of
|
||||
.Xr dc 1 .
|
||||
Assignments to
|
||||
.Ar ibase
|
||||
or
|
||||
.Ar obase
|
||||
set the input and output number radix respectively.
|
||||
.Pp
|
||||
The same letter may be used as an array, a function,
|
||||
and a simple variable simultaneously.
|
||||
All variables are global to the program.
|
||||
`Auto' variables are pushed down during function calls.
|
||||
When using arrays as function arguments
|
||||
or defining them as automatic variables,
|
||||
empty square brackets must follow the array name.
|
||||
.Pp
|
||||
For example
|
||||
.Bd -literal -offset indent
|
||||
scale = 20
|
||||
define e(x){
|
||||
auto a, b, c, i, s
|
||||
a = 1
|
||||
b = 1
|
||||
s = 1
|
||||
for(i=1; 1==1; i++){
|
||||
a = a*x
|
||||
b = b*i
|
||||
c = a/b
|
||||
if(c == 0) return(s)
|
||||
s = s+c
|
||||
}
|
||||
}
|
||||
.Ed
|
||||
.Pp
|
||||
defines a function to compute an approximate value of
|
||||
the exponential function and
|
||||
.Pp
|
||||
.Dl for(i=1; i<=10; i++) e(i)
|
||||
.Pp
|
||||
prints approximate values of the exponential function of
|
||||
the first ten integers.
|
||||
.Bd -literal -offset indent
|
||||
$ bc -l -e 'scale = 500; 2 * a(2^10000)' -e quit
|
||||
.Ed
|
||||
.Pp
|
||||
prints an approximation of pi.
|
||||
.Sh COMMAND LINE EDITING
|
||||
.Nm
|
||||
supports interactive command line editing, via the
|
||||
.Xr editline 3
|
||||
library.
|
||||
It is enabled by default if input is from a tty.
|
||||
Previous lines can be recalled and edited with the arrow keys,
|
||||
and other GNU Emacs-style editing keys may be used as well.
|
||||
.Pp
|
||||
The
|
||||
.Xr editline 3
|
||||
library is configured with a
|
||||
.Pa .editrc
|
||||
file \- refer to
|
||||
.Xr editrc 5
|
||||
for more information.
|
||||
.Sh FILES
|
||||
.Bl -tag -width /usr/share/misc/bc.library -compact
|
||||
.It Pa /usr/share/misc/bc.library
|
||||
math library, read when the
|
||||
.Fl l
|
||||
option is specified on the command line.
|
||||
.El
|
||||
.Sh COMPATIBILITY
|
||||
The
|
||||
.Fl q
|
||||
and
|
||||
.Fl Fl quiet
|
||||
options are no-ops for compatibility with some other implementations of
|
||||
.Nm
|
||||
and their use is discouraged.
|
||||
.Sh SEE ALSO
|
||||
.Xr dc 1
|
||||
.Sh STANDARDS
|
||||
The
|
||||
.Nm
|
||||
utility is compliant with the
|
||||
.St -p1003.1-2008
|
||||
specification.
|
||||
.Pp
|
||||
The flags
|
||||
.Op Fl ce ,
|
||||
as well as the parts noted above,
|
||||
are extensions to that specification.
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
command first appeared in
|
||||
.At v6 .
|
||||
A complete rewrite of the
|
||||
.Nm
|
||||
command first appeared in
|
||||
.Ox 3.5 .
|
||||
.Sh AUTHORS
|
||||
.An -nosplit
|
||||
The original version of the
|
||||
.Nm
|
||||
command was written by
|
||||
.An Robert Morris
|
||||
and
|
||||
.An Lorinda Cherry .
|
||||
The current version of the
|
||||
.Nm
|
||||
utility was written by
|
||||
.An Otto Moerbeek .
|
||||
.Sh BUGS
|
||||
The
|
||||
.Ql quit
|
||||
statement is interpreted when read, not when executed.
|
||||
.Pp
|
||||
Some non-portable extensions, as found in the GNU version of the
|
||||
.Nm
|
||||
utility are not implemented (yet).
|
@ -1,272 +0,0 @@
|
||||
/* $OpenBSD: bc.library,v 1.4 2012/03/14 07:35:53 otto Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) Caldera International Inc. 2001-2002.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code and documentation must retain the above
|
||||
* copyright notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed or owned by Caldera
|
||||
* International, Inc.
|
||||
* 4. Neither the name of Caldera International, Inc. nor the names of other
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
|
||||
* INTERNATIONAL, INC. 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 CALDERA INTERNATIONAL, INC. 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
*/
|
||||
|
||||
scale = 20
|
||||
define e(x) {
|
||||
auto a, b, c, d, e, g, t, w, y, r
|
||||
|
||||
r = ibase
|
||||
ibase = A
|
||||
t = scale
|
||||
scale = 0
|
||||
if (x > 0) scale = (0.435*x)/1
|
||||
scale = scale + t + length(scale + t) + 1
|
||||
|
||||
w = 0
|
||||
if (x < 0) {
|
||||
x = -x
|
||||
w = 1
|
||||
}
|
||||
y = 0
|
||||
while (x > 2) {
|
||||
x = x/2
|
||||
y = y + 1
|
||||
}
|
||||
|
||||
a = 1
|
||||
b = 1
|
||||
c = b
|
||||
d = 1
|
||||
e = 1
|
||||
for (a = 1; 1 == 1; a++) {
|
||||
b = b*x
|
||||
c = c*a + b
|
||||
d = d*a
|
||||
g = c/d
|
||||
if (g == e) {
|
||||
g = g/1
|
||||
while (y--) {
|
||||
g = g*g
|
||||
}
|
||||
scale = t
|
||||
ibase = r
|
||||
if (w == 1) return (1/g)
|
||||
return (g/1)
|
||||
}
|
||||
e = g
|
||||
}
|
||||
}
|
||||
|
||||
define l(x) {
|
||||
auto a, b, c, d, e, f, g, u, s, t, r
|
||||
r = ibase
|
||||
ibase = A
|
||||
if (x <= 0) {
|
||||
a = (1 - 10^scale)
|
||||
ibase = r
|
||||
return (a)
|
||||
}
|
||||
t = scale
|
||||
|
||||
f = 1
|
||||
if (x < 1) {
|
||||
s = scale(x)
|
||||
} else {
|
||||
s = length(x)-scale(x)
|
||||
}
|
||||
scale = 0
|
||||
a = (2.31*s)/1 /* estimated integer part of the answer */
|
||||
s = t + length(a) + 2 /* estimated length of the answer */
|
||||
while (x > 2) {
|
||||
scale = 0
|
||||
scale = (length(x) + scale(x))/2 + 1
|
||||
if (scale < s) scale = s
|
||||
x = sqrt(x)
|
||||
f = f*2
|
||||
}
|
||||
while (x < .5) {
|
||||
scale = 0
|
||||
scale = scale(x)/2 + 1
|
||||
if (scale < s) scale = s
|
||||
x = sqrt(x)
|
||||
f = f*2
|
||||
}
|
||||
|
||||
scale = 0
|
||||
scale = t + length(f) + length((1.05*(t+length(f))/1)) + 1
|
||||
u = (x - 1)/(x + 1)
|
||||
s = u*u
|
||||
scale = t + 2
|
||||
b = 2*f
|
||||
c = b
|
||||
d = 1
|
||||
e = 1
|
||||
for (a = 3; 1 == 1 ; a = a + 2) {
|
||||
b = b*s
|
||||
c = c*a + d*b
|
||||
d = d*a
|
||||
g = c/d
|
||||
if (g == e) {
|
||||
scale = t
|
||||
ibase = r
|
||||
return (u*c/d)
|
||||
}
|
||||
e = g
|
||||
}
|
||||
}
|
||||
|
||||
define s(x) {
|
||||
auto a, b, c, s, t, y, p, n, i, r
|
||||
r = ibase
|
||||
ibase = A
|
||||
t = scale
|
||||
y = x/.7853
|
||||
s = t + length(y) - scale(y)
|
||||
if (s < t) s = t
|
||||
scale = s
|
||||
p = a(1)
|
||||
|
||||
scale = 0
|
||||
if (x >= 0) n = (x/(2*p) + 1)/2
|
||||
if (x < 0) n = (x/(2*p) - 1)/2
|
||||
x = x - 4*n*p
|
||||
if (n % 2 != 0) x = -x
|
||||
|
||||
scale = t + length(1.2*t) - scale(1.2*t)
|
||||
y = -x*x
|
||||
a = x
|
||||
b = 1
|
||||
s = x
|
||||
for (i =3 ; 1 == 1; i = i + 2) {
|
||||
a = a*y
|
||||
b = b*i*(i - 1)
|
||||
c = a/b
|
||||
if (c == 0) {
|
||||
scale = t
|
||||
ibase = r
|
||||
return (s/1)
|
||||
}
|
||||
s = s + c
|
||||
}
|
||||
}
|
||||
|
||||
define c(x) {
|
||||
auto t, r
|
||||
r = ibase
|
||||
ibase = A
|
||||
t = scale
|
||||
scale = scale + 1
|
||||
x = s(x + 2*a(1))
|
||||
scale = t
|
||||
ibase = r
|
||||
return (x/1)
|
||||
}
|
||||
|
||||
define a(x) {
|
||||
auto a, b, c, d, e, f, g, s, t, r
|
||||
if (x == 0) return(0)
|
||||
|
||||
r = ibase
|
||||
ibase = A
|
||||
if (x == 1) {
|
||||
if (scale < 52) {
|
||||
a = .7853981633974483096156608458198757210492923498437764/1
|
||||
ibase = r
|
||||
return (a)
|
||||
}
|
||||
}
|
||||
t = scale
|
||||
f = 1
|
||||
while (x > .5) {
|
||||
scale = scale + 1
|
||||
x = -(1 - sqrt(1. + x*x))/x
|
||||
f = f*2
|
||||
}
|
||||
while (x < -.5) {
|
||||
scale = scale + 1
|
||||
x = -(1 - sqrt(1. + x*x))/x
|
||||
f = f*2
|
||||
}
|
||||
s = -x*x
|
||||
b = f
|
||||
c = f
|
||||
d = 1
|
||||
e = 1
|
||||
for (a = 3; 1 == 1; a = a + 2) {
|
||||
b = b*s
|
||||
c = c*a + d*b
|
||||
d = d*a
|
||||
g = c/d
|
||||
if (g == e) {
|
||||
ibase = r
|
||||
scale = t
|
||||
return (x*c/d)
|
||||
}
|
||||
e = g
|
||||
}
|
||||
}
|
||||
|
||||
define j(n,x) {
|
||||
auto a, b, c, d, e, g, i, s, k, t, r
|
||||
|
||||
r = ibase
|
||||
ibase = A
|
||||
t = scale
|
||||
k = 1.36*x + 1.16*t - n
|
||||
k = length(k) - scale(k)
|
||||
if (k > 0) scale = scale + k
|
||||
|
||||
s = -x*x/4
|
||||
if (n < 0) {
|
||||
n = -n
|
||||
x = -x
|
||||
}
|
||||
a = 1
|
||||
c = 1
|
||||
for (i = 1; i <= n; i++) {
|
||||
a = a*x
|
||||
c = c*2*i
|
||||
}
|
||||
b = a
|
||||
d = 1
|
||||
e = 1
|
||||
for (i = 1; 1; i++) {
|
||||
a = a*s
|
||||
b = b*i*(n + i) + a
|
||||
c = c*i*(n + i)
|
||||
g = b/c
|
||||
if (g == e) {
|
||||
ibase = r
|
||||
scale = t
|
||||
return (g/1)
|
||||
}
|
||||
e = g
|
||||
}
|
||||
}
|
||||
/* vim: set filetype=bc shiftwidth=8 noexpandtab: */
|
1214
usr.bin/bc/bc.y
1214
usr.bin/bc/bc.y
File diff suppressed because it is too large
Load Diff
@ -1,46 +0,0 @@
|
||||
/* $OpenBSD: extern.h,v 1.12 2014/04/17 19:07:14 otto Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2003, Otto Moerbeek <otto@drijf.net>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
|
||||
struct lvalue {
|
||||
ssize_t load;
|
||||
ssize_t store;
|
||||
};
|
||||
|
||||
int yylex(void);
|
||||
void yyerror(const char *);
|
||||
void fatal(const char *);
|
||||
void abort_line(int);
|
||||
struct termios;
|
||||
int gettty(struct termios *);
|
||||
void tstpcont(int);
|
||||
unsigned char bc_eof(EditLine *, int);
|
||||
|
||||
extern int lineno;
|
||||
extern int fileindex;
|
||||
extern int sargc;
|
||||
extern const char **sargv;
|
||||
extern const char *filename;
|
||||
extern bool interactive;
|
||||
extern EditLine *el;
|
||||
extern History *hist;
|
||||
extern HistEvent he;
|
||||
extern char *cmdexpr;
|
||||
extern struct termios ttysaved;
|
@ -1,20 +0,0 @@
|
||||
/* $OpenBSD: pathnames.h,v 1.1 2003/09/25 19:32:44 otto Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2003, Otto Moerbeek <otto@drijf.net>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#define _PATH_LIBB "/usr/share/misc/bc.library"
|
||||
#define _PATH_DC "/usr/bin/dc"
|
@ -1,368 +0,0 @@
|
||||
%{
|
||||
/* $OpenBSD: scan.l,v 1.28 2013/09/19 16:12:01 otto Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2003, Otto Moerbeek <otto@drijf.net>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <histedit.h>
|
||||
#include <stdbool.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "extern.h"
|
||||
#include "bc.h"
|
||||
#include "pathnames.h"
|
||||
|
||||
int lineno;
|
||||
bool interactive;
|
||||
|
||||
HistEvent he;
|
||||
EditLine *el;
|
||||
History *hist;
|
||||
|
||||
static char *strbuf = NULL;
|
||||
static size_t strbuf_sz = 1;
|
||||
static bool dot_seen;
|
||||
static int use_el;
|
||||
static volatile sig_atomic_t skipchars;
|
||||
|
||||
static void init_strbuf(void);
|
||||
static void add_str(const char *);
|
||||
|
||||
static int bc_yyinput(char *, int);
|
||||
|
||||
#define YY_DECL int yylex(void)
|
||||
#define YY_NO_INPUT
|
||||
#undef YY_INPUT
|
||||
#define YY_INPUT(buf,retval,max) \
|
||||
(retval = bc_yyinput(buf, max))
|
||||
|
||||
%}
|
||||
|
||||
%option always-interactive
|
||||
|
||||
DIGIT [0-9A-F]
|
||||
ALPHA [a-z_]
|
||||
ALPHANUM [a-z_0-9]
|
||||
|
||||
%x comment string number
|
||||
|
||||
%%
|
||||
|
||||
"/*" BEGIN(comment);
|
||||
<comment>{
|
||||
"*/" BEGIN(INITIAL);
|
||||
\n lineno++;
|
||||
\* ;
|
||||
[^*\n]+ ;
|
||||
<<EOF>> fatal("end of file in comment");
|
||||
}
|
||||
|
||||
\" BEGIN(string); init_strbuf();
|
||||
<string>{
|
||||
[^"\n\\\[\]]+ add_str(yytext);
|
||||
\[ add_str("\\[");
|
||||
\] add_str("\\]");
|
||||
\\ add_str("\\\\");
|
||||
\n add_str("\n"); lineno++;
|
||||
\" BEGIN(INITIAL); yylval.str = strbuf; return STRING;
|
||||
<<EOF>> fatal("end of file in string");
|
||||
}
|
||||
|
||||
{DIGIT}+ {
|
||||
BEGIN(number);
|
||||
dot_seen = false;
|
||||
init_strbuf();
|
||||
add_str(yytext);
|
||||
}
|
||||
\. {
|
||||
BEGIN(number);
|
||||
dot_seen = true;
|
||||
init_strbuf();
|
||||
add_str(".");
|
||||
}
|
||||
<number>{
|
||||
{DIGIT}+ add_str(yytext);
|
||||
\. {
|
||||
if (dot_seen) {
|
||||
BEGIN(INITIAL);
|
||||
yylval.str = strbuf;
|
||||
unput('.');
|
||||
return NUMBER;
|
||||
} else {
|
||||
dot_seen = true;
|
||||
add_str(".");
|
||||
}
|
||||
}
|
||||
\\\n[ \t]* lineno++;
|
||||
[^0-9A-F\.] {
|
||||
BEGIN(INITIAL);
|
||||
unput(yytext[0]);
|
||||
if (strcmp(strbuf, ".") == 0)
|
||||
return DOT;
|
||||
else {
|
||||
yylval.str = strbuf;
|
||||
return NUMBER;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"auto" return AUTO;
|
||||
"break" return BREAK;
|
||||
"continue" return CONTINUE;
|
||||
"define" return DEFINE;
|
||||
"else" return ELSE;
|
||||
"ibase" return IBASE;
|
||||
"if" return IF;
|
||||
"last" return DOT;
|
||||
"for" return FOR;
|
||||
"length" return LENGTH;
|
||||
"obase" return OBASE;
|
||||
"print" return PRINT;
|
||||
"quit" return QUIT;
|
||||
"return" return RETURN;
|
||||
"scale" return SCALE;
|
||||
"sqrt" return SQRT;
|
||||
"while" return WHILE;
|
||||
|
||||
"^" return EXPONENT;
|
||||
"*" return MULTIPLY;
|
||||
"/" return DIVIDE;
|
||||
"%" return REMAINDER;
|
||||
|
||||
"!" return BOOL_NOT;
|
||||
"&&" return BOOL_AND;
|
||||
"||" return BOOL_OR;
|
||||
|
||||
"+" return PLUS;
|
||||
"-" return MINUS;
|
||||
|
||||
"++" return INCR;
|
||||
"--" return DECR;
|
||||
|
||||
"=" yylval.str = ""; return ASSIGN_OP;
|
||||
"+=" yylval.str = "+"; return ASSIGN_OP;
|
||||
"-=" yylval.str = "-"; return ASSIGN_OP;
|
||||
"*=" yylval.str = "*"; return ASSIGN_OP;
|
||||
"/=" yylval.str = "/"; return ASSIGN_OP;
|
||||
"%=" yylval.str = "%"; return ASSIGN_OP;
|
||||
"^=" yylval.str = "^"; return ASSIGN_OP;
|
||||
|
||||
"==" return EQUALS;
|
||||
"<=" return LESS_EQ;
|
||||
">=" return GREATER_EQ;
|
||||
"!=" return UNEQUALS;
|
||||
"<" return LESS;
|
||||
">" return GREATER;
|
||||
|
||||
"," return COMMA;
|
||||
";" return SEMICOLON;
|
||||
|
||||
"(" return LPAR;
|
||||
")" return RPAR;
|
||||
|
||||
"[" return LBRACKET;
|
||||
"]" return RBRACKET;
|
||||
|
||||
"{" return LBRACE;
|
||||
"}" return RBRACE;
|
||||
|
||||
{ALPHA}{ALPHANUM}* {
|
||||
/* alloc an extra byte for the type marker */
|
||||
char *p = malloc(yyleng + 2);
|
||||
if (p == NULL)
|
||||
err(1, NULL);
|
||||
strlcpy(p, yytext, yyleng + 1);
|
||||
yylval.astr = p;
|
||||
return LETTER;
|
||||
}
|
||||
|
||||
\\\n lineno++;
|
||||
\n lineno++; return NEWLINE;
|
||||
|
||||
#[^\n]* ;
|
||||
[ \t] ;
|
||||
<<EOF>> return QUIT;
|
||||
. yyerror("illegal character");
|
||||
|
||||
%%
|
||||
|
||||
static void
|
||||
init_strbuf(void)
|
||||
{
|
||||
if (strbuf == NULL) {
|
||||
strbuf = malloc(strbuf_sz);
|
||||
if (strbuf == NULL)
|
||||
err(1, NULL);
|
||||
}
|
||||
strbuf[0] = '\0';
|
||||
}
|
||||
|
||||
static void
|
||||
add_str(const char *str)
|
||||
{
|
||||
size_t arglen;
|
||||
|
||||
arglen = strlen(str);
|
||||
|
||||
if (strlen(strbuf) + arglen + 1 > strbuf_sz) {
|
||||
size_t newsize;
|
||||
char *p;
|
||||
|
||||
newsize = strbuf_sz + arglen + 1;
|
||||
p = realloc(strbuf, newsize);
|
||||
if (p == NULL) {
|
||||
free(strbuf);
|
||||
err(1, NULL);
|
||||
}
|
||||
strbuf_sz = newsize;
|
||||
strbuf = p;
|
||||
}
|
||||
strlcat(strbuf, str, strbuf_sz);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
void
|
||||
abort_line(int sig __unused)
|
||||
{
|
||||
static const char str1[] = "[\n]P\n";
|
||||
static const char str2[] = "[^C\n]P\n";
|
||||
int save_errno;
|
||||
const LineInfo *info;
|
||||
|
||||
save_errno = errno;
|
||||
if (use_el) {
|
||||
write(STDOUT_FILENO, str2, sizeof(str2) - 1);
|
||||
info = el_line(el);
|
||||
skipchars = info->lastchar - info->buffer;
|
||||
} else
|
||||
write(STDOUT_FILENO, str1, sizeof(str1) - 1);
|
||||
errno = save_errno;
|
||||
}
|
||||
|
||||
/*
|
||||
* Avoid the echo of ^D by the default code of editline and take
|
||||
* into account skipchars to make ^D work when the cursor is at start of
|
||||
* line after a ^C.
|
||||
*/
|
||||
unsigned char
|
||||
bc_eof(EditLine *e, int ch __unused)
|
||||
{
|
||||
const struct lineinfo *info = el_line(e);
|
||||
|
||||
if (info->buffer + skipchars == info->cursor &&
|
||||
info->cursor == info->lastchar)
|
||||
return (CC_EOF);
|
||||
else
|
||||
return (CC_ERROR);
|
||||
}
|
||||
|
||||
int
|
||||
yywrap(void)
|
||||
{
|
||||
static int state;
|
||||
static YY_BUFFER_STATE buf;
|
||||
|
||||
if (fileindex == 0 && sargc > 0 && strcmp(sargv[0], _PATH_LIBB) == 0) {
|
||||
filename = sargv[fileindex++];
|
||||
yyin = fopen(filename, "r");
|
||||
lineno = 1;
|
||||
if (yyin == NULL)
|
||||
err(1, "cannot open %s", filename);
|
||||
return (0);
|
||||
}
|
||||
if (state == 0 && cmdexpr[0] != '\0') {
|
||||
buf = yy_scan_string(cmdexpr);
|
||||
state++;
|
||||
lineno = 1;
|
||||
filename = "command line";
|
||||
return (0);
|
||||
} else if (state == 1) {
|
||||
yy_delete_buffer(buf);
|
||||
free(cmdexpr);
|
||||
state++;
|
||||
}
|
||||
if (yyin != NULL && yyin != stdin)
|
||||
fclose(yyin);
|
||||
if (fileindex < sargc) {
|
||||
filename = sargv[fileindex++];
|
||||
yyin = fopen(filename, "r");
|
||||
lineno = 1;
|
||||
if (yyin == NULL)
|
||||
err(1, "cannot open %s", filename);
|
||||
return (0);
|
||||
} else if (fileindex == sargc) {
|
||||
fileindex++;
|
||||
yyin = stdin;
|
||||
if (interactive) {
|
||||
signal(SIGINT, abort_line);
|
||||
signal(SIGTSTP, tstpcont);
|
||||
}
|
||||
lineno = 1;
|
||||
filename = "stdin";
|
||||
return (0);
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int
|
||||
bc_yyinput(char *buf, int maxlen)
|
||||
{
|
||||
int num;
|
||||
|
||||
if (el != NULL)
|
||||
el_get(el, EL_EDITMODE, &use_el);
|
||||
|
||||
if (yyin == stdin && interactive && use_el) {
|
||||
const char *bp;
|
||||
sigset_t oset, nset;
|
||||
|
||||
if ((bp = el_gets(el, &num)) == NULL || num == 0)
|
||||
return (0);
|
||||
sigemptyset(&nset);
|
||||
sigaddset(&nset, SIGINT);
|
||||
sigprocmask(SIG_BLOCK, &nset, &oset);
|
||||
if (skipchars < num) {
|
||||
bp += skipchars;
|
||||
num -= skipchars;
|
||||
}
|
||||
skipchars = 0;
|
||||
sigprocmask(SIG_SETMASK, &oset, NULL);
|
||||
if (num > maxlen) {
|
||||
el_push(el, bp + maxlen);
|
||||
num = maxlen;
|
||||
}
|
||||
memcpy(buf, bp, num);
|
||||
history(hist, &he, H_ENTER, bp);
|
||||
el_get(el, EL_EDITMODE, &use_el);
|
||||
} else {
|
||||
int c = '*';
|
||||
for (num = 0; num < maxlen &&
|
||||
(c = getc(yyin)) != EOF && c != '\n'; ++num)
|
||||
buf[num] = (char) c;
|
||||
if (c == '\n')
|
||||
buf[num++] = (char) c;
|
||||
if (c == EOF && ferror(yyin))
|
||||
YY_FATAL_ERROR( "input in flex scanner failed" );
|
||||
}
|
||||
return (num);
|
||||
}
|
||||
|
||||
|
@ -1,64 +0,0 @@
|
||||
/* $OpenBSD: tty.c,v 1.3 2015/09/05 09:49:24 jsg Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2013, Otto Moerbeek <otto@drijf.net>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <histedit.h>
|
||||
#include <termios.h>
|
||||
#include "extern.h"
|
||||
|
||||
struct termios ttysaved, ttyedit;
|
||||
|
||||
static int
|
||||
settty(struct termios *t)
|
||||
{
|
||||
int ret;
|
||||
|
||||
while ((ret = tcsetattr(0, TCSADRAIN, t)) == -1 && errno == EINTR)
|
||||
continue;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
gettty(struct termios *t)
|
||||
{
|
||||
int ret;
|
||||
|
||||
while ((ret = tcgetattr(0, t)) == -1 && errno == EINTR)
|
||||
continue;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
void
|
||||
tstpcont(int sig)
|
||||
{
|
||||
int save_errno = errno;
|
||||
|
||||
if (sig == SIGTSTP) {
|
||||
signal(SIGCONT, tstpcont);
|
||||
gettty(&ttyedit);
|
||||
settty(&ttysaved);
|
||||
} else {
|
||||
signal(SIGTSTP, tstpcont);
|
||||
settty(&ttyedit);
|
||||
}
|
||||
signal(sig, SIG_DFL);
|
||||
kill(0, sig);
|
||||
errno = save_errno;
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
# $OpenBSD: Makefile,v 1.2 2006/11/26 11:31:09 deraadt Exp $
|
||||
|
||||
.include <src.opts.mk>
|
||||
|
||||
PROG= dc
|
||||
SRCS= dc.c bcode.c inout.c mem.c stack.c
|
||||
LIBADD= crypto
|
||||
|
||||
HAS_TESTS=
|
||||
SUBDIR.${MK_TESTS}+= tests
|
||||
|
||||
.include <bsd.prog.mk>
|
@ -1,18 +0,0 @@
|
||||
# Autogenerated - do NOT edit!
|
||||
|
||||
DIRDEPS = \
|
||||
include \
|
||||
include/xlocale \
|
||||
lib/${CSU_DIR} \
|
||||
lib/libc \
|
||||
lib/libcapsicum \
|
||||
lib/libcasper/libcasper \
|
||||
lib/libcompiler_rt \
|
||||
secure/lib/libcrypto \
|
||||
|
||||
|
||||
.include <dirdeps.mk>
|
||||
|
||||
.if ${DEP_RELDIR} == ${_DEP_RELDIR}
|
||||
# local dependencies - needed for -jN in clean tree
|
||||
.endif
|
1773
usr.bin/dc/bcode.c
1773
usr.bin/dc/bcode.c
File diff suppressed because it is too large
Load Diff
@ -1,103 +0,0 @@
|
||||
/* $OpenBSD: bcode.h,v 1.7 2012/11/07 11:06:14 otto Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2003, Otto Moerbeek <otto@drijf.net>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <openssl/bn.h>
|
||||
|
||||
struct number {
|
||||
BIGNUM *number;
|
||||
u_int scale;
|
||||
};
|
||||
|
||||
enum stacktype {
|
||||
BCODE_NONE,
|
||||
BCODE_NUMBER,
|
||||
BCODE_STRING
|
||||
};
|
||||
|
||||
enum bcode_compare {
|
||||
BCODE_EQUAL,
|
||||
BCODE_NOT_EQUAL,
|
||||
BCODE_LESS,
|
||||
BCODE_NOT_LESS,
|
||||
BCODE_GREATER,
|
||||
BCODE_NOT_GREATER
|
||||
};
|
||||
|
||||
struct array;
|
||||
|
||||
struct value {
|
||||
union {
|
||||
struct number *num;
|
||||
char *string;
|
||||
} u;
|
||||
struct array *array;
|
||||
enum stacktype type;
|
||||
};
|
||||
|
||||
struct array {
|
||||
struct value *data;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
struct stack {
|
||||
struct value *stack;
|
||||
ssize_t size;
|
||||
ssize_t sp;
|
||||
};
|
||||
|
||||
struct source;
|
||||
|
||||
struct vtable {
|
||||
int (*readchar)(struct source *);
|
||||
void (*unreadchar)(struct source *);
|
||||
char *(*readline)(struct source *);
|
||||
void (*free)(struct source *);
|
||||
};
|
||||
|
||||
struct source {
|
||||
union {
|
||||
struct {
|
||||
u_char *buf;
|
||||
size_t pos;
|
||||
} string;
|
||||
FILE *stream;
|
||||
} u;
|
||||
struct vtable *vtable;
|
||||
int lastchar;
|
||||
};
|
||||
|
||||
void init_bmachine(bool);
|
||||
void reset_bmachine(struct source *);
|
||||
u_int bmachine_scale(void);
|
||||
void scale_number(BIGNUM *, int);
|
||||
void normalize(struct number *, u_int);
|
||||
void eval(void);
|
||||
void pn(const char *, const struct number *);
|
||||
void pbn(const char *, const BIGNUM *);
|
||||
void negate(struct number *);
|
||||
void split_number(const struct number *, BIGNUM *, BIGNUM *);
|
||||
void bmul_number(struct number *, struct number *,
|
||||
struct number *, u_int scale);
|
||||
|
||||
static __inline u_int
|
||||
max(u_int a, u_int b)
|
||||
{
|
||||
|
||||
return (a > b ? a : b);
|
||||
}
|
555
usr.bin/dc/dc.1
555
usr.bin/dc/dc.1
@ -1,555 +0,0 @@
|
||||
.\" $OpenBSD: dc.1,v 1.27 2012/08/19 12:07:21 jmc Exp $
|
||||
.\"
|
||||
.\" Copyright (C) Caldera International Inc. 2001-2002.
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code and documentation must retain the above
|
||||
.\" copyright notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. 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.
|
||||
.\" 3. All advertising materials mentioning features or use of this software
|
||||
.\" must display the following acknowledgement:
|
||||
.\" This product includes software developed or owned by Caldera
|
||||
.\" International, Inc.
|
||||
.\" 4. Neither the name of Caldera International, Inc. nor the names of other
|
||||
.\" contributors may be used to endorse or promote products derived from
|
||||
.\" this software without specific prior written permission.
|
||||
.\"
|
||||
.\" USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
|
||||
.\" INTERNATIONAL, INC. 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 CALDERA INTERNATIONAL, INC. 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.
|
||||
.\"
|
||||
.Dd September 4, 2019
|
||||
.Dt DC 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm dc
|
||||
.Nd desk calculator
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl hxV
|
||||
.Op Fl e Ar expression
|
||||
.Op Fl f Ar filename
|
||||
.Op Ar filename
|
||||
.Sh DESCRIPTION
|
||||
.Nm
|
||||
is an arbitrary precision arithmetic package.
|
||||
The overall structure of
|
||||
.Nm
|
||||
is
|
||||
a stacking (reverse Polish) calculator i.e.\&
|
||||
numbers are stored on a stack.
|
||||
Adding a number pushes it onto the stack.
|
||||
Arithmetic operations pop arguments off the stack
|
||||
and push the results.
|
||||
See also the
|
||||
.Xr bc 1
|
||||
utility, which is a preprocessor for
|
||||
.Nm
|
||||
providing infix notation and a C-like syntax
|
||||
which implements functions and reasonable control
|
||||
structures for programs.
|
||||
The options are as follows:
|
||||
.Bl -tag -width Ds
|
||||
.It Fl e Ar expr , Fl Fl expression Ar expr
|
||||
Evaluate
|
||||
.Ar expression .
|
||||
If multiple
|
||||
.Fl e
|
||||
options are specified, they will be processed in the order given.
|
||||
.It Fl f Ar filename , Fl Fl file Ar filename
|
||||
Process the content of the given file before further calculations are done.
|
||||
If multiple
|
||||
.Fl f
|
||||
options are specified, they will be processed in the order given.
|
||||
.It Fl h , Fl Fl help
|
||||
Print short usage info.
|
||||
.It Fl V , Fl Fl version
|
||||
Print version info.
|
||||
.It Fl x
|
||||
Enable extended register mode.
|
||||
This mode is used by
|
||||
.Xr bc 1
|
||||
to allow more than 256 registers.
|
||||
See
|
||||
.Sx Registers
|
||||
for a more detailed description.
|
||||
.El
|
||||
.Pp
|
||||
If neither
|
||||
.Ar expression
|
||||
nor
|
||||
.Ar file
|
||||
are specified on the command line,
|
||||
.Nm
|
||||
reads from the standard input.
|
||||
Otherwise
|
||||
.Ar expression
|
||||
and
|
||||
.Ar file
|
||||
are processed and
|
||||
.Nm
|
||||
exits.
|
||||
.Pp
|
||||
Ordinarily,
|
||||
.Nm
|
||||
operates on decimal integers,
|
||||
but one may specify an input base, output base,
|
||||
and a number of fractional digits (scale) to be maintained.
|
||||
Whitespace is ignored, except where it signals the end of a number,
|
||||
end of a line or when a register name is expected.
|
||||
The following constructions are recognized:
|
||||
.Bl -tag -width "number"
|
||||
.It Va number
|
||||
The value of the number is pushed on the stack.
|
||||
A number is an unbroken string of the digits 0\-9 and letters A\-F.
|
||||
It may be preceded by an underscore
|
||||
.Pq Sq _
|
||||
to input a negative number.
|
||||
A number may contain a single decimal point.
|
||||
A number may also contain the characters A\-F, with the values 10\-15.
|
||||
.It Cm "+ - / * % ~ ^"
|
||||
The
|
||||
top two values on the stack are added
|
||||
(+),
|
||||
subtracted
|
||||
(\-),
|
||||
multiplied (*),
|
||||
divided (/),
|
||||
remaindered (%),
|
||||
divided and remaindered (~),
|
||||
or exponentiated (^).
|
||||
The two entries are popped off the stack;
|
||||
the result is pushed on the stack in their place.
|
||||
Any fractional part of an exponent is ignored.
|
||||
.Pp
|
||||
For addition, subtraction, and remainder, the scale of the result is the
|
||||
maximum of scales of the operands.
|
||||
For division the scale of the result is defined
|
||||
by the scale set by the
|
||||
.Ic k
|
||||
operation.
|
||||
For multiplication, the scale is defined by the expression
|
||||
.Sy min(a+b,max(a,b,scale)) ,
|
||||
where
|
||||
.Sy a
|
||||
and
|
||||
.Sy b
|
||||
are the scales of the operands, and
|
||||
.Sy scale
|
||||
is the scale defined by the
|
||||
.Ic k
|
||||
operation.
|
||||
For exponentiation with a non-negative exponent, the scale of the result is
|
||||
.Sy min(a*b,max(scale,a)) ,
|
||||
where
|
||||
.Sy a
|
||||
is the scale of the base, and
|
||||
.Sy b
|
||||
is the
|
||||
.Em value
|
||||
of the exponent.
|
||||
If the exponent is negative, the scale of the result is the scale
|
||||
defined by the
|
||||
.Ic k
|
||||
operation.
|
||||
.Pp
|
||||
In the case of the division and modulus operator (~),
|
||||
the resultant quotient is pushed first followed by the remainder.
|
||||
This is a shorthand for the sequence:
|
||||
.Bd -literal -offset indent -compact
|
||||
x y / x y %
|
||||
.Ed
|
||||
The division and modulus operator is a non-portable extension.
|
||||
.It Ic a
|
||||
Pop the top value from the stack.
|
||||
If that value is a number, compute the integer part of the number modulo 256.
|
||||
If the result is zero, push an empty string.
|
||||
Otherwise push a one character string by interpreting the computed value
|
||||
as an
|
||||
.Tn ASCII
|
||||
character.
|
||||
.Pp
|
||||
If the top value is a string, push a string containing the first character
|
||||
of the original string.
|
||||
If the original string is empty, an empty string is pushed back.
|
||||
The
|
||||
.Ic a
|
||||
operator is a non-portable extension.
|
||||
.It Ic c
|
||||
All values on the stack are popped.
|
||||
.It Ic d
|
||||
The top value on the stack is duplicated.
|
||||
.It Ic e
|
||||
Equivalent to
|
||||
.Ic p ,
|
||||
except that the output is written to the standard error stream.
|
||||
.It Ic f
|
||||
All values on the stack are printed, separated by newlines.
|
||||
.It Ic G
|
||||
The top two numbers are popped from the stack and compared.
|
||||
A one is pushed if the top of the stack is equal to the second number
|
||||
on the stack.
|
||||
A zero is pushed otherwise.
|
||||
This is a non-portable extension.
|
||||
.It Ic I
|
||||
Pushes the input base on the top of the stack.
|
||||
.It Ic i
|
||||
The top value on the stack is popped and used as the
|
||||
base for further input.
|
||||
The initial input base is 10.
|
||||
.It Ic J
|
||||
Pop the top value from the stack.
|
||||
The recursion level is popped by that value and, following that,
|
||||
the input is skipped until the first occurrence of the
|
||||
.Ic M
|
||||
operator.
|
||||
The
|
||||
.Ic J
|
||||
operator is a non-portable extension, used by the
|
||||
.Xr bc 1
|
||||
command.
|
||||
.It Ic K
|
||||
The current scale factor is pushed onto the stack.
|
||||
.It Ic k
|
||||
The top of the stack is popped, and that value is used as
|
||||
a non-negative scale factor:
|
||||
the appropriate number of places
|
||||
are printed on output,
|
||||
and maintained during multiplication, division, and exponentiation.
|
||||
The interaction of scale factor,
|
||||
input base, and output base will be reasonable if all are changed
|
||||
together.
|
||||
.It Ic L Ns Ar x
|
||||
Register
|
||||
.Ar x
|
||||
is treated as a stack and its top value is popped onto the main stack.
|
||||
.It Ic l Ns Ar x
|
||||
The
|
||||
value in register
|
||||
.Ar x
|
||||
is pushed on the stack.
|
||||
The register
|
||||
.Ar x
|
||||
is not altered.
|
||||
Initially, all registers contain the value zero.
|
||||
.It Ic M
|
||||
Mark used by the
|
||||
.Ic J
|
||||
operator.
|
||||
The
|
||||
.Ic M
|
||||
operator is a non-portable extensions, used by the
|
||||
.Xr bc 1
|
||||
command.
|
||||
.It Ic N
|
||||
The top of the stack is replaced by one if the top of the stack
|
||||
is equal to zero.
|
||||
If the top of the stack is unequal to zero, it is replaced by zero.
|
||||
This is a non-portable extension.
|
||||
.It Ic n
|
||||
The top value on the stack is popped and printed without a newline.
|
||||
This is a non-portable extension.
|
||||
.It Ic O
|
||||
Pushes the output base on the top of the stack.
|
||||
.It Ic o
|
||||
The top value on the stack is popped and used as the
|
||||
base for further output.
|
||||
The initial output base is 10.
|
||||
.It Ic P
|
||||
The top of the stack is popped.
|
||||
If the top of the stack is a string, it is printed without a trailing newline.
|
||||
If the top of the stack is a number, it is interpreted as a
|
||||
base 256 number, and each digit of this base 256 number is printed as
|
||||
an
|
||||
.Tn ASCII
|
||||
character, without a trailing newline.
|
||||
.It Ic p
|
||||
The top value on the stack is printed with a trailing newline.
|
||||
The top value remains unchanged.
|
||||
.It Ic Q
|
||||
The top value on the stack is popped and the string execution level is popped
|
||||
by that value.
|
||||
.It Ic q
|
||||
Exits the program.
|
||||
If executing a string, the recursion level is
|
||||
popped by two.
|
||||
.It Ic R
|
||||
The top of the stack is removed (popped).
|
||||
This is a non-portable extension.
|
||||
.It Ic r
|
||||
The top two values on the stack are reversed (swapped).
|
||||
This is a non-portable extension.
|
||||
.It Ic S Ns Ar x
|
||||
Register
|
||||
.Ar x
|
||||
is treated as a stack.
|
||||
The top value of the main stack is popped and pushed on it.
|
||||
.It Ic s Ns Ar x
|
||||
The
|
||||
top of the stack is popped and stored into
|
||||
a register named
|
||||
.Ar x .
|
||||
.It Ic v
|
||||
Replaces the top element on the stack by its square root.
|
||||
The scale of the result is the maximum of the scale of the argument
|
||||
and the current value of scale.
|
||||
.It Ic X
|
||||
Replaces the number on the top of the stack with its scale factor.
|
||||
If the top of the stack is a string, replace it with the integer 0.
|
||||
.It Ic x
|
||||
Treats the top element of the stack as a character string
|
||||
and executes it as a string of
|
||||
.Nm
|
||||
commands.
|
||||
.It Ic Z
|
||||
Replaces the number on the top of the stack with its length.
|
||||
The length of a string is its number of characters.
|
||||
The length of a number is its number of digits, not counting the minus sign
|
||||
and decimal point.
|
||||
.It Ic z
|
||||
The stack level is pushed onto the stack.
|
||||
.It Cm \&[ Ns ... Ns Cm \&]
|
||||
Puts the bracketed
|
||||
.Tn ASCII
|
||||
string onto the top of the stack.
|
||||
If the string includes brackets, these must be properly balanced.
|
||||
The backslash character
|
||||
.Pq Sq \e
|
||||
may be used as an escape character, making it
|
||||
possible to include unbalanced brackets in strings.
|
||||
To include a backslash in a string, use a double backslash.
|
||||
.It Xo
|
||||
.Cm < Ns Va x
|
||||
.Cm > Ns Va x
|
||||
.Cm = Ns Va x
|
||||
.Cm !< Ns Va x
|
||||
.Cm !> Ns Va x
|
||||
.Cm != Ns Va x
|
||||
.Xc
|
||||
The top two elements of the stack are popped and compared.
|
||||
Register
|
||||
.Ar x
|
||||
is executed if they obey the stated
|
||||
relation.
|
||||
.It Xo
|
||||
.Cm < Ns Va x Ns e Ns Va y
|
||||
.Cm > Ns Va x Ns e Ns Va y
|
||||
.Cm = Ns Va x Ns e Ns Va y
|
||||
.Cm !< Ns Va x Ns e Ns Va y
|
||||
.Cm !> Ns Va x Ns e Ns Va y
|
||||
.Cm != Ns Va x Ns e Ns Va y
|
||||
.Xc
|
||||
These operations are variants of the comparison operations above.
|
||||
The first register name is followed by the letter
|
||||
.Sq e
|
||||
and another register name.
|
||||
Register
|
||||
.Ar x
|
||||
will be executed if the relation is true, and register
|
||||
.Ar y
|
||||
will be executed if the relation is false.
|
||||
This is a non-portable extension.
|
||||
.It Ic \&(
|
||||
The top two numbers are popped from the stack and compared.
|
||||
A one is pushed if the top of the stack is less than the second number
|
||||
on the stack.
|
||||
A zero is pushed otherwise.
|
||||
This is a non-portable extension.
|
||||
.It Ic {
|
||||
The top two numbers are popped from the stack and compared.
|
||||
A one is pushed if the top of stack is less than or equal to the
|
||||
second number on the stack.
|
||||
A zero is pushed otherwise.
|
||||
This is a non-portable extension.
|
||||
.It Ic \&!
|
||||
Interprets the rest of the line as a
|
||||
.Ux
|
||||
command.
|
||||
.It Ic \&?
|
||||
A line of input is taken from the input source (usually the terminal)
|
||||
and executed.
|
||||
.It Ic \&: Ns Ar r
|
||||
Pop two values from the stack.
|
||||
The second value on the stack is stored into the array
|
||||
.Ar r
|
||||
indexed by the top of stack.
|
||||
.It Ic \&; Ns Ar r
|
||||
Pop a value from the stack.
|
||||
The value is used as an index into register
|
||||
.Ar r .
|
||||
The value in this register is pushed onto the stack.
|
||||
.Pp
|
||||
Array elements initially have the value zero.
|
||||
Each level of a stacked register has its own array associated with
|
||||
it.
|
||||
The command sequence
|
||||
.Bd -literal -offset indent
|
||||
[first] 0:a [dummy] Sa [second] 0:a 0;a p La 0;a p
|
||||
.Ed
|
||||
.Pp
|
||||
will print
|
||||
.Bd -literal -offset indent
|
||||
second
|
||||
first
|
||||
.Ed
|
||||
.Pp
|
||||
since the string
|
||||
.Ql second
|
||||
is written in an array that is later popped, to reveal the array that
|
||||
stored
|
||||
.Ql first .
|
||||
.It Ic #
|
||||
Skip the rest of the line.
|
||||
This is a non-portable extension.
|
||||
.El
|
||||
.Ss Registers
|
||||
Registers have a single character name
|
||||
.Ar x ,
|
||||
where
|
||||
.Ar x
|
||||
may be any character, including space, tab or any other special character.
|
||||
If extended register mode is enabled using the
|
||||
.Fl x
|
||||
option and the register identifier
|
||||
.Ar x
|
||||
has the value 255, the next two characters are interpreted as a
|
||||
two-byte register index.
|
||||
The set of standard single character registers and the set of extended
|
||||
registers do not overlap.
|
||||
Extended register mode is a non-portable extension.
|
||||
.Sh EXAMPLES
|
||||
An example which prints the first ten values of
|
||||
.Ic n! :
|
||||
.Bd -literal -offset indent
|
||||
[la1+dsa*pla10>y]sy
|
||||
0sa1
|
||||
lyx
|
||||
.Ed
|
||||
.Pp
|
||||
Independent of the current input base, the command
|
||||
.Bd -literal -offset indent
|
||||
Ai
|
||||
.Ed
|
||||
.Pp
|
||||
will reset the input base to decimal 10.
|
||||
.Sh DIAGNOSTICS
|
||||
.Bl -diag
|
||||
.It %c (0%o) is unimplemented
|
||||
an undefined operation was called.
|
||||
.It stack empty
|
||||
for not enough elements on the stack to do what was asked.
|
||||
.It stack register '%c' (0%o) is empty
|
||||
for an
|
||||
.Ar L
|
||||
operation from a stack register that is empty.
|
||||
.It Runtime warning: non-zero scale in exponent
|
||||
for a fractional part of an exponent that is being ignored.
|
||||
.It divide by zero
|
||||
for trying to divide by zero.
|
||||
.It remainder by zero
|
||||
for trying to take a remainder by zero.
|
||||
.It square root of negative number
|
||||
for trying to take the square root of a negative number.
|
||||
.It index too big
|
||||
for an array index that is larger than 2048.
|
||||
.It negative index
|
||||
for a negative array index.
|
||||
.It "input base must be a number between 2 and 16"
|
||||
for trying to set an illegal input base.
|
||||
.It output base must be a number greater than 1
|
||||
for trying to set an illegal output base.
|
||||
.It scale must be a nonnegative number
|
||||
for trying to set a negative or zero scale.
|
||||
.It scale too large
|
||||
for trying to set a scale that is too large.
|
||||
A scale must be representable as a 32-bit unsigned number.
|
||||
.It Q command argument exceeded string execution depth
|
||||
for trying to pop the recursion level more than the current
|
||||
recursion level.
|
||||
.It Q command requires a number >= 1
|
||||
for trying to pop an illegal number of recursion levels.
|
||||
.It recursion too deep
|
||||
for too many levels of nested execution.
|
||||
.Pp
|
||||
The recursion level is increased by one if the
|
||||
.Ar x
|
||||
or
|
||||
.Ar ?\&
|
||||
operation or one of the compare operations resulting in the execution
|
||||
of register is executed.
|
||||
As an exception, the recursion level is not increased if the operation
|
||||
is executed as the last command of a string.
|
||||
For example, the commands
|
||||
.Bd -literal -offset indent
|
||||
[lax]sa
|
||||
1 lax
|
||||
.Ed
|
||||
.Pp
|
||||
will execute an endless loop, while the commands
|
||||
.Bd -literal -offset indent
|
||||
[laxp]sa
|
||||
1 lax
|
||||
.Ed
|
||||
.Pp
|
||||
will terminate because of a too deep recursion level.
|
||||
.It J command argument exceeded string execution depth
|
||||
for trying to pop the recursion level more than the current
|
||||
recursion level.
|
||||
.It mark not found
|
||||
for a failed scan for an occurrence of the
|
||||
.Ic M
|
||||
operator.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr bc 1
|
||||
.Pp
|
||||
.An -nosplit
|
||||
.An L. L. Cherry ,
|
||||
.An R. Morris
|
||||
"DC \- An Interactive Desk Calculator"
|
||||
.Pa /usr/share/doc/usd/05.dc/ .
|
||||
.Sh STANDARDS
|
||||
The arithmetic operations of the
|
||||
.Nm
|
||||
utility are expected to conform to the definition listed in the
|
||||
.Xr bc 1
|
||||
section of the
|
||||
.St -p1003.2
|
||||
specification.
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
command first appeared in
|
||||
.At v1 .
|
||||
A complete rewrite of the
|
||||
.Nm
|
||||
command using the
|
||||
.Xr bn 3
|
||||
big number routines first appeared in
|
||||
.Ox 3.5 .
|
||||
.Sh AUTHORS
|
||||
.An -nosplit
|
||||
The original version of the
|
||||
.Nm
|
||||
command was written by
|
||||
.An Robert Morris
|
||||
and
|
||||
.An Lorinda Cherry .
|
||||
The current version of the
|
||||
.Nm
|
||||
utility was written by
|
||||
.An Otto Moerbeek .
|
154
usr.bin/dc/dc.c
154
usr.bin/dc/dc.c
@ -1,154 +0,0 @@
|
||||
/* $OpenBSD: dc.c,v 1.11 2009/10/27 23:59:37 deraadt Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2003, Otto Moerbeek <otto@drijf.net>
|
||||
* Copyright (c) 2009, Gabor Kovesdan <gabor@FreeBSD.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <capsicum_helpers.h>
|
||||
#include <ctype.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <getopt.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "extern.h"
|
||||
|
||||
#define DC_VER "1.3-FreeBSD"
|
||||
|
||||
static void usage(void);
|
||||
|
||||
extern char *__progname;
|
||||
|
||||
static struct source src;
|
||||
|
||||
static const struct option long_options[] =
|
||||
{
|
||||
{"expression", required_argument, NULL, 'e'},
|
||||
{"file", required_argument, NULL, 'f'},
|
||||
{"help", no_argument, NULL, 'h'},
|
||||
{"version", no_argument, NULL, 'V'}
|
||||
};
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
fprintf(stderr, "usage: %s [-hVx] [-e expression] [file]\n",
|
||||
__progname);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static void
|
||||
procfd(int fd, char *fname) {
|
||||
struct stat st;
|
||||
FILE *file;
|
||||
|
||||
file = fdopen(fd, "r");
|
||||
if (file == NULL)
|
||||
err(1, "cannot open file %s", fname);
|
||||
if (fstat(fileno(file), &st) == -1)
|
||||
err(1, "%s", fname);
|
||||
if (S_ISDIR(st.st_mode)) {
|
||||
errno = EISDIR;
|
||||
err(1, "%s", fname);
|
||||
}
|
||||
src_setstream(&src, file);
|
||||
reset_bmachine(&src);
|
||||
eval();
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int ch, fd;
|
||||
bool extended_regs = false, preproc_done = false;
|
||||
|
||||
/* accept and ignore a single dash to be 4.4BSD dc(1) compatible */
|
||||
while ((ch = getopt_long(argc, argv, "e:f:hVx", long_options, NULL)) != -1) {
|
||||
switch (ch) {
|
||||
case 'e':
|
||||
if (!preproc_done)
|
||||
init_bmachine(extended_regs);
|
||||
src_setstring(&src, optarg);
|
||||
reset_bmachine(&src);
|
||||
eval();
|
||||
preproc_done = true;
|
||||
break;
|
||||
case 'f':
|
||||
if (!preproc_done)
|
||||
init_bmachine(extended_regs);
|
||||
fd = open(optarg, O_RDONLY);
|
||||
if (fd < 0)
|
||||
err(1, "cannot open file %s", optarg);
|
||||
procfd(fd, optarg);
|
||||
preproc_done = true;
|
||||
break;
|
||||
case 'x':
|
||||
extended_regs = true;
|
||||
break;
|
||||
case 'V':
|
||||
fprintf(stderr, "%s (BSD bc) %s\n", __progname, DC_VER);
|
||||
exit(0);
|
||||
break;
|
||||
case '-':
|
||||
break;
|
||||
case 'h':
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (!preproc_done)
|
||||
init_bmachine(extended_regs);
|
||||
(void)setvbuf(stdout, NULL, _IOLBF, 0);
|
||||
(void)setvbuf(stderr, NULL, _IOLBF, 0);
|
||||
|
||||
if (argc > 1)
|
||||
usage();
|
||||
if (argc == 1) {
|
||||
fd = open(argv[0], O_RDONLY);
|
||||
if (fd < 0)
|
||||
err(1, "cannot open file %s", argv[0]);
|
||||
|
||||
if (caph_limit_stream(fd, CAPH_READ) < 0 ||
|
||||
caph_limit_stdio() < 0 ||
|
||||
caph_enter() < 0)
|
||||
err(1, "capsicum");
|
||||
|
||||
procfd(fd, argv[0]);
|
||||
preproc_done = true;
|
||||
}
|
||||
if (preproc_done)
|
||||
return (0);
|
||||
|
||||
if (caph_limit_stdio() < 0 || caph_enter())
|
||||
err(1, "capsicum");
|
||||
src_setstream(&src, stdin);
|
||||
reset_bmachine(&src);
|
||||
eval();
|
||||
|
||||
return (0);
|
||||
}
|
@ -1,63 +0,0 @@
|
||||
/* $OpenBSD: extern.h,v 1.4 2014/12/01 13:13:00 deraadt Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2003, Otto Moerbeek <otto@drijf.net>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "bcode.h"
|
||||
|
||||
|
||||
/* inout.c */
|
||||
void src_setstream(struct source *, FILE *);
|
||||
void src_setstring(struct source *, char *);
|
||||
struct number *readnumber(struct source *, u_int, u_int);
|
||||
void printnumber(FILE *, const struct number *, u_int);
|
||||
char *read_string(struct source *);
|
||||
void print_value(FILE *, const struct value *, const char *, u_int);
|
||||
void print_ascii(FILE *, const struct number *);
|
||||
|
||||
/* mem.c */
|
||||
struct number *new_number(void);
|
||||
void free_number(struct number *);
|
||||
struct number *div_number(struct number *, struct number *, u_int scale);
|
||||
struct number *dup_number(const struct number *);
|
||||
void *bmalloc(size_t);
|
||||
void *breallocarray(void *, size_t, size_t);
|
||||
char *bstrdup(const char *p);
|
||||
void bn_check(int);
|
||||
void bn_checkp(const void *);
|
||||
|
||||
/* stack.c */
|
||||
void stack_init(struct stack *);
|
||||
void stack_free_value(struct value *);
|
||||
struct value *stack_dup_value(const struct value *, struct value *);
|
||||
void stack_swap(struct stack *);
|
||||
size_t stack_size(const struct stack *);
|
||||
void stack_dup(struct stack *);
|
||||
void stack_pushnumber(struct stack *, struct number *);
|
||||
void stack_pushstring(struct stack *stack, char *);
|
||||
void stack_push(struct stack *, struct value *);
|
||||
void stack_set_tos(struct stack *, struct value *);
|
||||
struct value *stack_tos(const struct stack *);
|
||||
struct value *stack_pop(struct stack *);
|
||||
struct number *stack_popnumber(struct stack *);
|
||||
char *stack_popstring(struct stack *);
|
||||
void stack_clear(struct stack *);
|
||||
void stack_print(FILE *, const struct stack *, const char *,
|
||||
u_int base);
|
||||
void frame_assign(struct stack *, size_t, const struct value *);
|
||||
struct value *frame_retrieve(const struct stack *, size_t);
|
||||
/* void frame_free(struct stack *); */
|
@ -1,446 +0,0 @@
|
||||
/* $OpenBSD: inout.c,v 1.18 2014/12/01 13:13:00 deraadt Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2003, Otto Moerbeek <otto@drijf.net>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#include <openssl/ssl.h>
|
||||
#include <ctype.h>
|
||||
#include <err.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "extern.h"
|
||||
|
||||
#define MAX_CHARS_PER_LINE 68
|
||||
|
||||
static int lastchar;
|
||||
static int charcount;
|
||||
|
||||
static int src_getcharstream(struct source *);
|
||||
static void src_ungetcharstream(struct source *);
|
||||
static char *src_getlinestream(struct source *);
|
||||
static int src_getcharstring(struct source *);
|
||||
static void src_ungetcharstring(struct source *);
|
||||
static char *src_getlinestring(struct source *);
|
||||
static void src_freestring(struct source *);
|
||||
static void flushwrap(FILE *);
|
||||
static void putcharwrap(FILE *, int);
|
||||
static void printwrap(FILE *, const char *);
|
||||
static char *get_digit(u_long, int, u_int);
|
||||
|
||||
static struct vtable stream_vtable = {
|
||||
src_getcharstream,
|
||||
src_ungetcharstream,
|
||||
src_getlinestream,
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct vtable string_vtable = {
|
||||
src_getcharstring,
|
||||
src_ungetcharstring,
|
||||
src_getlinestring,
|
||||
src_freestring
|
||||
};
|
||||
|
||||
void
|
||||
src_setstream(struct source *src, FILE *stream)
|
||||
{
|
||||
|
||||
src->u.stream = stream;
|
||||
src->vtable = &stream_vtable;
|
||||
}
|
||||
|
||||
void
|
||||
src_setstring(struct source *src, char *p)
|
||||
{
|
||||
|
||||
src->u.string.buf = (u_char *)p;
|
||||
src->u.string.pos = 0;
|
||||
src->vtable = &string_vtable;
|
||||
}
|
||||
|
||||
static int
|
||||
src_getcharstream(struct source *src)
|
||||
{
|
||||
|
||||
return (src->lastchar = getc(src->u.stream));
|
||||
}
|
||||
|
||||
static void
|
||||
src_ungetcharstream(struct source *src)
|
||||
{
|
||||
|
||||
ungetc(src->lastchar, src->u.stream);
|
||||
}
|
||||
|
||||
static char *
|
||||
src_getlinestream(struct source *src)
|
||||
{
|
||||
char buf[BUFSIZ];
|
||||
|
||||
if (fgets(buf, BUFSIZ, src->u.stream) == NULL)
|
||||
return (bstrdup(""));
|
||||
return bstrdup(buf);
|
||||
}
|
||||
|
||||
static int
|
||||
src_getcharstring(struct source *src)
|
||||
{
|
||||
|
||||
src->lastchar = src->u.string.buf[src->u.string.pos];
|
||||
if (src->lastchar == '\0')
|
||||
return (EOF);
|
||||
else {
|
||||
src->u.string.pos++;
|
||||
return (src->lastchar);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
src_ungetcharstring(struct source *src)
|
||||
{
|
||||
|
||||
if (src->u.string.pos > 0) {
|
||||
if (src->lastchar != '\0')
|
||||
--src->u.string.pos;
|
||||
}
|
||||
}
|
||||
|
||||
static char *
|
||||
src_getlinestring(struct source *src)
|
||||
{
|
||||
char buf[BUFSIZ];
|
||||
int i, ch;
|
||||
|
||||
i = 0;
|
||||
while (i < BUFSIZ-1) {
|
||||
ch = src_getcharstring(src);
|
||||
if (ch == EOF)
|
||||
break;
|
||||
buf[i++] = ch;
|
||||
if (ch == '\n')
|
||||
break;
|
||||
}
|
||||
buf[i] = '\0';
|
||||
return (bstrdup(buf));
|
||||
}
|
||||
|
||||
static void
|
||||
src_freestring(struct source *src)
|
||||
{
|
||||
|
||||
free(src->u.string.buf);
|
||||
}
|
||||
|
||||
static void
|
||||
flushwrap(FILE *f)
|
||||
{
|
||||
|
||||
if (lastchar != -1)
|
||||
putc(lastchar, f);
|
||||
}
|
||||
|
||||
static void
|
||||
putcharwrap(FILE *f, int ch)
|
||||
{
|
||||
|
||||
if (charcount >= MAX_CHARS_PER_LINE) {
|
||||
charcount = 0;
|
||||
fputs("\\\n", f);
|
||||
}
|
||||
if (lastchar != -1) {
|
||||
charcount++;
|
||||
putc(lastchar, f);
|
||||
}
|
||||
lastchar = ch;
|
||||
}
|
||||
|
||||
static void
|
||||
printwrap(FILE *f, const char *p)
|
||||
{
|
||||
char *q;
|
||||
char buf[12];
|
||||
|
||||
q = buf;
|
||||
strlcpy(buf, p, sizeof(buf));
|
||||
while (*q)
|
||||
putcharwrap(f, *q++);
|
||||
}
|
||||
|
||||
struct number *
|
||||
readnumber(struct source *src, u_int base, u_int bscale)
|
||||
{
|
||||
struct number *n;
|
||||
BN_ULONG v;
|
||||
int ch;
|
||||
u_int iscale = 0;
|
||||
bool dot = false, sign = false;
|
||||
|
||||
n = new_number();
|
||||
BN_zero(n->number);
|
||||
|
||||
while ((ch = (*src->vtable->readchar)(src)) != EOF) {
|
||||
|
||||
if ('0' <= ch && ch <= '9')
|
||||
v = ch - '0';
|
||||
else if ('A' <= ch && ch <= 'F')
|
||||
v = ch - 'A' + 10;
|
||||
else if (ch == '_') {
|
||||
sign = true;
|
||||
continue;
|
||||
} else if (ch == '.') {
|
||||
if (dot)
|
||||
break;
|
||||
dot = true;
|
||||
continue;
|
||||
} else {
|
||||
(*src->vtable->unreadchar)(src);
|
||||
break;
|
||||
}
|
||||
if (dot)
|
||||
iscale++;
|
||||
|
||||
bn_check(BN_mul_word(n->number, base));
|
||||
bn_check(BN_add_word(n->number, v));
|
||||
}
|
||||
if (base == 10) {
|
||||
n->scale = iscale;
|
||||
} else {
|
||||
/* At this point, the desired result is n->number / base^iscale*/
|
||||
struct number *quotient, *divisor, *_n;
|
||||
BIGNUM *base_n, *exponent;
|
||||
BN_CTX *ctx;
|
||||
|
||||
ctx = BN_CTX_new();
|
||||
base_n = BN_new();
|
||||
exponent = BN_new();
|
||||
divisor = new_number();
|
||||
BN_zero(base_n);
|
||||
BN_zero(exponent);
|
||||
|
||||
bn_check(BN_add_word(base_n, base));
|
||||
bn_check(BN_add_word(exponent, iscale));
|
||||
bn_check(BN_exp(divisor->number, base_n, exponent, ctx));
|
||||
divisor->scale = 0;
|
||||
quotient = div_number(n, divisor, bscale);
|
||||
_n = n;
|
||||
n = quotient;
|
||||
|
||||
/*
|
||||
* Trim off trailing zeros to yield the smallest scale without
|
||||
* loss of accuracy
|
||||
*/
|
||||
while ( n->scale > 0 &&
|
||||
BN_mod_word(n->number, 10) == 0) {
|
||||
normalize(n, n->scale - 1);
|
||||
}
|
||||
|
||||
free_number(_n);
|
||||
free_number(divisor);
|
||||
BN_CTX_free(ctx);
|
||||
BN_free(base_n);
|
||||
BN_free(exponent);
|
||||
}
|
||||
if (sign)
|
||||
negate(n);
|
||||
return (n);
|
||||
}
|
||||
|
||||
char *
|
||||
read_string(struct source *src)
|
||||
{
|
||||
char *p;
|
||||
int count, ch, i, new_sz, sz;
|
||||
bool escape;
|
||||
|
||||
escape = false;
|
||||
count = 1;
|
||||
i = 0;
|
||||
sz = 15;
|
||||
p = bmalloc(sz + 1);
|
||||
|
||||
while ((ch = (*src->vtable->readchar)(src)) != EOF) {
|
||||
if (!escape) {
|
||||
if (ch == '[')
|
||||
count++;
|
||||
else if (ch == ']')
|
||||
count--;
|
||||
if (count == 0)
|
||||
break;
|
||||
}
|
||||
if (ch == '\\' && !escape)
|
||||
escape = true;
|
||||
else {
|
||||
escape = false;
|
||||
if (i == sz) {
|
||||
new_sz = sz * 2;
|
||||
p = breallocarray(p, 1, new_sz + 1);
|
||||
sz = new_sz;
|
||||
}
|
||||
p[i++] = ch;
|
||||
}
|
||||
}
|
||||
p[i] = '\0';
|
||||
return (p);
|
||||
}
|
||||
|
||||
static char *
|
||||
get_digit(u_long num, int digits, u_int base)
|
||||
{
|
||||
char *p;
|
||||
|
||||
if (base <= 16) {
|
||||
p = bmalloc(2);
|
||||
p[0] = num >= 10 ? num + 'A' - 10 : num + '0';
|
||||
p[1] = '\0';
|
||||
} else {
|
||||
if (asprintf(&p, "%0*lu", digits, num) == -1)
|
||||
err(1, NULL);
|
||||
}
|
||||
return (p);
|
||||
}
|
||||
|
||||
void
|
||||
printnumber(FILE *f, const struct number *b, u_int base)
|
||||
{
|
||||
struct number *fract_part, *int_part;
|
||||
struct stack stack;
|
||||
char *p;
|
||||
char buf[11];
|
||||
size_t sz;
|
||||
unsigned int i;
|
||||
int digits;
|
||||
|
||||
charcount = 0;
|
||||
lastchar = -1;
|
||||
if (BN_is_zero(b->number))
|
||||
putcharwrap(f, '0');
|
||||
|
||||
int_part = new_number();
|
||||
fract_part = new_number();
|
||||
fract_part->scale = b->scale;
|
||||
|
||||
if (base <= 16)
|
||||
digits = 1;
|
||||
else {
|
||||
digits = snprintf(buf, sizeof(buf), "%u", base-1);
|
||||
}
|
||||
split_number(b, int_part->number, fract_part->number);
|
||||
|
||||
i = 0;
|
||||
stack_init(&stack);
|
||||
while (!BN_is_zero(int_part->number)) {
|
||||
BN_ULONG rem = BN_div_word(int_part->number, base);
|
||||
stack_pushstring(&stack, get_digit(rem, digits, base));
|
||||
i++;
|
||||
}
|
||||
sz = i;
|
||||
if (BN_is_negative(b->number))
|
||||
putcharwrap(f, '-');
|
||||
for (i = 0; i < sz; i++) {
|
||||
p = stack_popstring(&stack);
|
||||
if (base > 16)
|
||||
putcharwrap(f, ' ');
|
||||
printwrap(f, p);
|
||||
free(p);
|
||||
}
|
||||
stack_clear(&stack);
|
||||
if (b->scale > 0) {
|
||||
struct number *num_base;
|
||||
BIGNUM *mult, *stop;
|
||||
|
||||
putcharwrap(f, '.');
|
||||
num_base = new_number();
|
||||
bn_check(BN_set_word(num_base->number, base));
|
||||
mult = BN_new();
|
||||
bn_checkp(mult);
|
||||
bn_check(BN_one(mult));
|
||||
stop = BN_new();
|
||||
bn_checkp(stop);
|
||||
bn_check(BN_one(stop));
|
||||
scale_number(stop, b->scale);
|
||||
|
||||
i = 0;
|
||||
while (BN_cmp(mult, stop) < 0) {
|
||||
u_long rem;
|
||||
|
||||
if (i && base > 16)
|
||||
putcharwrap(f, ' ');
|
||||
i = 1;
|
||||
|
||||
bmul_number(fract_part, fract_part, num_base,
|
||||
bmachine_scale());
|
||||
split_number(fract_part, int_part->number, NULL);
|
||||
rem = BN_get_word(int_part->number);
|
||||
p = get_digit(rem, digits, base);
|
||||
int_part->scale = 0;
|
||||
normalize(int_part, fract_part->scale);
|
||||
bn_check(BN_sub(fract_part->number, fract_part->number,
|
||||
int_part->number));
|
||||
printwrap(f, p);
|
||||
free(p);
|
||||
bn_check(BN_mul_word(mult, base));
|
||||
}
|
||||
free_number(num_base);
|
||||
BN_free(mult);
|
||||
BN_free(stop);
|
||||
}
|
||||
flushwrap(f);
|
||||
free_number(int_part);
|
||||
free_number(fract_part);
|
||||
}
|
||||
|
||||
void
|
||||
print_value(FILE *f, const struct value *value, const char *prefix, u_int base)
|
||||
{
|
||||
|
||||
fputs(prefix, f);
|
||||
switch (value->type) {
|
||||
case BCODE_NONE:
|
||||
if (value->array != NULL)
|
||||
fputs("<array>", f);
|
||||
break;
|
||||
case BCODE_NUMBER:
|
||||
printnumber(f, value->u.num, base);
|
||||
break;
|
||||
case BCODE_STRING:
|
||||
fputs(value->u.string, f);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
print_ascii(FILE *f, const struct number *n)
|
||||
{
|
||||
BIGNUM *v;
|
||||
int ch, i, numbits;
|
||||
|
||||
v = BN_dup(n->number);
|
||||
bn_checkp(v);
|
||||
|
||||
if (BN_is_negative(v))
|
||||
BN_set_negative(v, 0);
|
||||
|
||||
numbits = BN_num_bytes(v) * 8;
|
||||
while (numbits > 0) {
|
||||
ch = 0;
|
||||
for (i = 0; i < 8; i++)
|
||||
ch |= BN_is_bit_set(v, numbits-i-1) << (7 - i);
|
||||
putc(ch, f);
|
||||
numbits -= 8;
|
||||
}
|
||||
BN_free(v);
|
||||
}
|
140
usr.bin/dc/mem.c
140
usr.bin/dc/mem.c
@ -1,140 +0,0 @@
|
||||
/* $OpenBSD: mem.c,v 1.6 2014/12/01 13:13:00 deraadt Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2003, Otto Moerbeek <otto@drijf.net>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "extern.h"
|
||||
|
||||
struct number *
|
||||
new_number(void)
|
||||
{
|
||||
struct number *n;
|
||||
|
||||
n = bmalloc(sizeof(*n));
|
||||
n->scale = 0;
|
||||
n->number = BN_new();
|
||||
if (n->number == NULL)
|
||||
err(1, NULL);
|
||||
return (n);
|
||||
}
|
||||
|
||||
void
|
||||
free_number(struct number *n)
|
||||
{
|
||||
|
||||
BN_free(n->number);
|
||||
free(n);
|
||||
}
|
||||
|
||||
/*
|
||||
* Divide dividend by divisor, returning the result. Retain bscale places of
|
||||
* precision.
|
||||
* The result must be freed when no longer in use
|
||||
*/
|
||||
struct number *
|
||||
div_number(struct number *dividend, struct number *divisor, u_int bscale)
|
||||
{
|
||||
struct number *quotient;
|
||||
BN_CTX *ctx;
|
||||
u_int scale;
|
||||
|
||||
quotient = new_number();
|
||||
quotient->scale = bscale;
|
||||
scale = max(divisor->scale, dividend->scale);
|
||||
|
||||
if (BN_is_zero(divisor->number))
|
||||
warnx("divide by zero");
|
||||
else {
|
||||
normalize(divisor, scale);
|
||||
normalize(dividend, scale + quotient->scale);
|
||||
|
||||
ctx = BN_CTX_new();
|
||||
bn_checkp(ctx);
|
||||
bn_check(BN_div(quotient->number, NULL, dividend->number,
|
||||
divisor->number, ctx));
|
||||
BN_CTX_free(ctx);
|
||||
}
|
||||
return (quotient);
|
||||
}
|
||||
|
||||
struct number *
|
||||
dup_number(const struct number *a)
|
||||
{
|
||||
struct number *n;
|
||||
|
||||
n = bmalloc(sizeof(*n));
|
||||
n->scale = a->scale;
|
||||
n->number = BN_dup(a->number);
|
||||
bn_checkp(n->number);
|
||||
return (n);
|
||||
}
|
||||
|
||||
void *
|
||||
bmalloc(size_t sz)
|
||||
{
|
||||
void *p;
|
||||
|
||||
p = malloc(sz);
|
||||
if (p == NULL)
|
||||
err(1, NULL);
|
||||
return (p);
|
||||
}
|
||||
|
||||
void *
|
||||
breallocarray(void *p, size_t nmemb, size_t size)
|
||||
{
|
||||
void *q;
|
||||
|
||||
q = reallocarray(p, nmemb, size);
|
||||
if (q == NULL)
|
||||
err(1, NULL);
|
||||
return (q);
|
||||
}
|
||||
|
||||
char *
|
||||
bstrdup(const char *p)
|
||||
{
|
||||
char *q;
|
||||
|
||||
q = strdup(p);
|
||||
if (q == NULL)
|
||||
err(1, NULL);
|
||||
return (q);
|
||||
}
|
||||
|
||||
void
|
||||
bn_check(int x) \
|
||||
{
|
||||
|
||||
if (x == 0)
|
||||
err(1, "big number failure %lx", ERR_get_error());
|
||||
}
|
||||
|
||||
void
|
||||
bn_checkp(const void *p) \
|
||||
{
|
||||
|
||||
if (p == NULL)
|
||||
err(1, "allocation failure %lx", ERR_get_error());
|
||||
}
|
@ -1,370 +0,0 @@
|
||||
/* $OpenBSD: stack.c,v 1.13 2014/12/01 13:13:00 deraadt Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2003, Otto Moerbeek <otto@drijf.net>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#include <err.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "extern.h"
|
||||
|
||||
static __inline bool stack_empty(const struct stack *);
|
||||
static void stack_grow(struct stack *);
|
||||
static struct array *array_new(void);
|
||||
static __inline void array_free(struct array *);
|
||||
static struct array *array_dup(const struct array *);
|
||||
static __inline void array_grow(struct array *, size_t);
|
||||
static __inline void array_assign(struct array *, size_t, const struct value *);
|
||||
static __inline struct value *array_retrieve(const struct array *, size_t);
|
||||
|
||||
void
|
||||
stack_init(struct stack *stack)
|
||||
{
|
||||
|
||||
stack->size = 0;
|
||||
stack->sp = -1;
|
||||
stack->stack = NULL;
|
||||
}
|
||||
|
||||
static __inline bool
|
||||
stack_empty(const struct stack *stack)
|
||||
{
|
||||
bool empty = stack->sp == -1;
|
||||
|
||||
if (empty)
|
||||
warnx("stack empty");
|
||||
return empty;
|
||||
}
|
||||
|
||||
/* Clear number or string, but leave value itself */
|
||||
void
|
||||
stack_free_value(struct value *v)
|
||||
{
|
||||
|
||||
switch (v->type) {
|
||||
case BCODE_NONE:
|
||||
break;
|
||||
case BCODE_NUMBER:
|
||||
free_number(v->u.num);
|
||||
break;
|
||||
case BCODE_STRING:
|
||||
free(v->u.string);
|
||||
break;
|
||||
}
|
||||
array_free(v->array);
|
||||
v->array = NULL;
|
||||
}
|
||||
|
||||
/* Copy number or string content into already allocated target */
|
||||
struct value *
|
||||
stack_dup_value(const struct value *a, struct value *copy)
|
||||
{
|
||||
|
||||
copy->type = a->type;
|
||||
|
||||
switch (a->type) {
|
||||
case BCODE_NONE:
|
||||
break;
|
||||
case BCODE_NUMBER:
|
||||
copy->u.num = dup_number(a->u.num);
|
||||
break;
|
||||
case BCODE_STRING:
|
||||
copy->u.string = strdup(a->u.string);
|
||||
if (copy->u.string == NULL)
|
||||
err(1, NULL);
|
||||
break;
|
||||
}
|
||||
|
||||
copy->array = a->array == NULL ? NULL : array_dup(a->array);
|
||||
|
||||
return (copy);
|
||||
}
|
||||
|
||||
size_t
|
||||
stack_size(const struct stack *stack)
|
||||
{
|
||||
|
||||
return (stack->sp + 1);
|
||||
}
|
||||
|
||||
void
|
||||
stack_dup(struct stack *stack)
|
||||
{
|
||||
struct value *value;
|
||||
struct value copy;
|
||||
|
||||
value = stack_tos(stack);
|
||||
if (value == NULL) {
|
||||
warnx("stack empty");
|
||||
return;
|
||||
}
|
||||
stack_push(stack, stack_dup_value(value, ©));
|
||||
}
|
||||
|
||||
void
|
||||
stack_swap(struct stack *stack)
|
||||
{
|
||||
struct value copy;
|
||||
|
||||
if (stack->sp < 1) {
|
||||
warnx("stack empty");
|
||||
return;
|
||||
}
|
||||
copy = stack->stack[stack->sp];
|
||||
stack->stack[stack->sp] = stack->stack[stack->sp-1];
|
||||
stack->stack[stack->sp-1] = copy;
|
||||
}
|
||||
|
||||
static void
|
||||
stack_grow(struct stack *stack)
|
||||
{
|
||||
size_t new_size;
|
||||
|
||||
if (++stack->sp == stack->size) {
|
||||
new_size = stack->size * 2 + 1;
|
||||
stack->stack = breallocarray(stack->stack,
|
||||
new_size, sizeof(*stack->stack));
|
||||
stack->size = new_size;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
stack_pushnumber(struct stack *stack, struct number *b)
|
||||
{
|
||||
|
||||
stack_grow(stack);
|
||||
stack->stack[stack->sp].type = BCODE_NUMBER;
|
||||
stack->stack[stack->sp].u.num = b;
|
||||
stack->stack[stack->sp].array = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
stack_pushstring(struct stack *stack, char *string)
|
||||
{
|
||||
|
||||
stack_grow(stack);
|
||||
stack->stack[stack->sp].type = BCODE_STRING;
|
||||
stack->stack[stack->sp].u.string = string;
|
||||
stack->stack[stack->sp].array = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
stack_push(struct stack *stack, struct value *v)
|
||||
{
|
||||
|
||||
switch (v->type) {
|
||||
case BCODE_NONE:
|
||||
stack_grow(stack);
|
||||
stack->stack[stack->sp].type = BCODE_NONE;
|
||||
break;
|
||||
case BCODE_NUMBER:
|
||||
stack_pushnumber(stack, v->u.num);
|
||||
break;
|
||||
case BCODE_STRING:
|
||||
stack_pushstring(stack, v->u.string);
|
||||
break;
|
||||
}
|
||||
stack->stack[stack->sp].array = v->array == NULL ?
|
||||
NULL : array_dup(v->array);
|
||||
}
|
||||
|
||||
struct value *
|
||||
stack_tos(const struct stack *stack)
|
||||
{
|
||||
|
||||
if (stack->sp == -1)
|
||||
return (NULL);
|
||||
return &stack->stack[stack->sp];
|
||||
}
|
||||
|
||||
void
|
||||
stack_set_tos(struct stack *stack, struct value *v)
|
||||
{
|
||||
|
||||
if (stack->sp == -1)
|
||||
stack_push(stack, v);
|
||||
else {
|
||||
stack_free_value(&stack->stack[stack->sp]);
|
||||
stack->stack[stack->sp] = *v;
|
||||
stack->stack[stack->sp].array = v->array == NULL ?
|
||||
NULL : array_dup(v->array);
|
||||
}
|
||||
}
|
||||
|
||||
struct value *
|
||||
stack_pop(struct stack *stack)
|
||||
{
|
||||
|
||||
if (stack_empty(stack))
|
||||
return (NULL);
|
||||
return &stack->stack[stack->sp--];
|
||||
}
|
||||
|
||||
struct number *
|
||||
stack_popnumber(struct stack *stack)
|
||||
{
|
||||
|
||||
if (stack_empty(stack))
|
||||
return (NULL);
|
||||
array_free(stack->stack[stack->sp].array);
|
||||
stack->stack[stack->sp].array = NULL;
|
||||
if (stack->stack[stack->sp].type != BCODE_NUMBER) {
|
||||
warnx("not a number"); /* XXX remove */
|
||||
return (NULL);
|
||||
}
|
||||
return stack->stack[stack->sp--].u.num;
|
||||
}
|
||||
|
||||
char *
|
||||
stack_popstring(struct stack *stack)
|
||||
{
|
||||
|
||||
if (stack_empty(stack))
|
||||
return (NULL);
|
||||
array_free(stack->stack[stack->sp].array);
|
||||
stack->stack[stack->sp].array = NULL;
|
||||
if (stack->stack[stack->sp].type != BCODE_STRING) {
|
||||
warnx("not a string"); /* XXX remove */
|
||||
return (NULL);
|
||||
}
|
||||
return stack->stack[stack->sp--].u.string;
|
||||
}
|
||||
|
||||
void
|
||||
stack_clear(struct stack *stack)
|
||||
{
|
||||
|
||||
while (stack->sp >= 0)
|
||||
stack_free_value(&stack->stack[stack->sp--]);
|
||||
free(stack->stack);
|
||||
stack_init(stack);
|
||||
}
|
||||
|
||||
void
|
||||
stack_print(FILE *f, const struct stack *stack, const char *prefix, u_int base)
|
||||
{
|
||||
ssize_t i;
|
||||
|
||||
for (i = stack->sp; i >= 0; i--) {
|
||||
print_value(f, &stack->stack[i], prefix, base);
|
||||
putc('\n', f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static struct array *
|
||||
array_new(void)
|
||||
{
|
||||
struct array *a;
|
||||
|
||||
a = bmalloc(sizeof(*a));
|
||||
a->data = NULL;
|
||||
a->size = 0;
|
||||
return a;
|
||||
}
|
||||
|
||||
static __inline void
|
||||
array_free(struct array *a)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (a == NULL)
|
||||
return;
|
||||
for (i = 0; i < a->size; i++)
|
||||
stack_free_value(&a->data[i]);
|
||||
free(a->data);
|
||||
free(a);
|
||||
}
|
||||
|
||||
static struct array *
|
||||
array_dup(const struct array *a)
|
||||
{
|
||||
struct array *n;
|
||||
size_t i;
|
||||
|
||||
if (a == NULL)
|
||||
return (NULL);
|
||||
n = array_new();
|
||||
array_grow(n, a->size);
|
||||
for (i = 0; i < a->size; i++)
|
||||
stack_dup_value(&a->data[i], &n->data[i]);
|
||||
return (n);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
array_grow(struct array *array, size_t newsize)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
array->data = breallocarray(array->data, newsize, sizeof(*array->data));
|
||||
for (i = array->size; i < newsize; i++) {
|
||||
array->data[i].type = BCODE_NONE;
|
||||
array->data[i].array = NULL;
|
||||
}
|
||||
array->size = newsize;
|
||||
}
|
||||
|
||||
static __inline void
|
||||
array_assign(struct array *array, size_t i, const struct value *v)
|
||||
{
|
||||
|
||||
if (i >= array->size)
|
||||
array_grow(array, i + 1);
|
||||
stack_free_value(&array->data[i]);
|
||||
array->data[i] = *v;
|
||||
}
|
||||
|
||||
static __inline struct value *
|
||||
array_retrieve(const struct array *array, size_t i)
|
||||
{
|
||||
|
||||
if (i >= array->size)
|
||||
return (NULL);
|
||||
return &array->data[i];
|
||||
}
|
||||
|
||||
void
|
||||
frame_assign(struct stack *stack, size_t i, const struct value *v)
|
||||
{
|
||||
struct array *a;
|
||||
struct value n;
|
||||
|
||||
if (stack->sp == -1) {
|
||||
n.type = BCODE_NONE;
|
||||
n.array = NULL;
|
||||
stack_push(stack, &n);
|
||||
}
|
||||
|
||||
a = stack->stack[stack->sp].array;
|
||||
if (a == NULL)
|
||||
a = stack->stack[stack->sp].array = array_new();
|
||||
array_assign(a, i, v);
|
||||
}
|
||||
|
||||
struct value *
|
||||
frame_retrieve(const struct stack *stack, size_t i)
|
||||
{
|
||||
struct array *a;
|
||||
|
||||
if (stack->sp == -1)
|
||||
return (NULL);
|
||||
a = stack->stack[stack->sp].array;
|
||||
if (a == NULL)
|
||||
a = stack->stack[stack->sp].array = array_new();
|
||||
return array_retrieve(a, i);
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
PACKAGE= tests
|
||||
|
||||
ATF_TESTS_SH= inout
|
||||
ATF_TESTS_SH+= bcode
|
||||
|
||||
.include <bsd.test.mk>
|
@ -1,142 +0,0 @@
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
#
|
||||
# Copyright (c) 2017 Alan Somers
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. 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 AUTHOR 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 AUTHOR 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.
|
||||
#
|
||||
|
||||
atf_test_case bmod
|
||||
bmod_head()
|
||||
{
|
||||
atf_set "descr" "Tests the remainder % operator"
|
||||
}
|
||||
bmod_body()
|
||||
{
|
||||
cat > input.dc << EOF
|
||||
0 3 % p # basic usage
|
||||
1 3 % p
|
||||
2 3 % p
|
||||
3 3 % p
|
||||
4 3 % p
|
||||
_1 3 % p # negative dividends work like a remainder, not a modulo
|
||||
1 _3 % p # negative divisors use the divisor's absolute value
|
||||
1k # fractional remainders
|
||||
5 3 % p
|
||||
6 5 % p
|
||||
5.4 3 % p
|
||||
_.1 3 % p
|
||||
1.1 _3 % p
|
||||
1 .3 % p
|
||||
EOF
|
||||
dc input.dc > output.txt
|
||||
cat > expect.txt << EOF
|
||||
0
|
||||
1
|
||||
2
|
||||
0
|
||||
1
|
||||
-1
|
||||
1
|
||||
2
|
||||
1
|
||||
2.4
|
||||
-.1
|
||||
1.1
|
||||
.1
|
||||
EOF
|
||||
atf_check cmp expect.txt output.txt
|
||||
}
|
||||
|
||||
atf_test_case bmod_by_zero
|
||||
bmod_by_zero_head()
|
||||
{
|
||||
atf_set "descr" "remaindering by zero should print a warning"
|
||||
}
|
||||
bmod_by_zero_body()
|
||||
{
|
||||
atf_check -e match:"remainder by zero" dc -e '1 0 %'
|
||||
}
|
||||
|
||||
atf_test_case bdivmod
|
||||
bdivmod_head()
|
||||
{
|
||||
atf_set "descr" "Tests the divide and modulo ~ operator"
|
||||
}
|
||||
bdivmod_body()
|
||||
{
|
||||
cat > input.dc << EOF
|
||||
0 3 ~ n32Pp # basic usage
|
||||
1 3 ~ n32Pp
|
||||
2 3 ~ n32Pp
|
||||
3 3 ~ n32Pp
|
||||
4 3 ~ n32Pp
|
||||
_1 3 ~ n32Pp # negative dividends work like a remainder, not a modulo
|
||||
_4 3 ~ n32Pp # sign of quotient and divisor must agree
|
||||
1 _3 ~ n32Pp # negative divisors use the divisor's absolute value
|
||||
1k # fractional remainders
|
||||
5 3 ~ n32Pp
|
||||
6 5 ~ n32Pp
|
||||
5.4 3 ~ n32Pp
|
||||
_.1 3 ~ n32Pp
|
||||
1.1 _3 ~ n32Pp
|
||||
1 .3 ~ n32Pp
|
||||
4k
|
||||
.01 .003 ~ n32Pp # divmod quotient always has scale=0
|
||||
EOF
|
||||
dc input.dc > output.txt
|
||||
cat > expect.txt << EOF
|
||||
0 0
|
||||
1 0
|
||||
2 0
|
||||
0 1
|
||||
1 1
|
||||
-1 0
|
||||
-1 -1
|
||||
1 0
|
||||
2 1.6
|
||||
1 1.2
|
||||
2.4 1.8
|
||||
-.1 0.0
|
||||
1.1 -.3
|
||||
.1 3.3
|
||||
.001 3.3333
|
||||
EOF
|
||||
atf_check cmp expect.txt output.txt
|
||||
}
|
||||
|
||||
atf_test_case bdivmod_by_zero
|
||||
bdivmod_by_zero_head()
|
||||
{
|
||||
atf_set "descr" "divmodding by zero should print a warning"
|
||||
}
|
||||
bdivmod_by_zero_body()
|
||||
{
|
||||
atf_check -e match:"divide by zero" dc -e '1 0 ~'
|
||||
}
|
||||
|
||||
atf_init_test_cases()
|
||||
{
|
||||
atf_add_test_case bmod
|
||||
atf_add_test_case bmod_by_zero
|
||||
atf_add_test_case bdivmod
|
||||
atf_add_test_case bdivmod_by_zero
|
||||
}
|
@ -1,100 +0,0 @@
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
#
|
||||
# Copyright (c) 2017 Alan Somers
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. 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 AUTHOR 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 AUTHOR 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.
|
||||
#
|
||||
|
||||
atf_test_case base16_input
|
||||
base16_input_head()
|
||||
{
|
||||
atf_set "descr" "Input hexadecimal numbers"
|
||||
}
|
||||
base16_input_body()
|
||||
{
|
||||
cat > input.dc << EOF
|
||||
4k # set scale to 4 decimal places
|
||||
16i # switch to base 16
|
||||
0 p
|
||||
10 p
|
||||
1 p
|
||||
1. p # The '.' should have no effect
|
||||
1.0 p # Unlike with decimal, should not change the result's scale
|
||||
.8 p # Can input fractions
|
||||
# Check that we can input fractions that need more scale in base 10 than in 16
|
||||
# See PR 206230
|
||||
.1 p
|
||||
.10 p # Result should be .0625, with scale=4
|
||||
.01 p # Result should be truncated to scale=4
|
||||
8k # Increase scale to 8 places
|
||||
.01 p # Result should be exact again
|
||||
0.1 p # Leading zeros are ignored
|
||||
00.1 p # Leading zeros are ignored
|
||||
EOF
|
||||
dc input.dc > output.txt
|
||||
cat > expect.txt << EOF
|
||||
0
|
||||
16
|
||||
1
|
||||
1
|
||||
1
|
||||
.5
|
||||
.0625
|
||||
.0625
|
||||
.0039
|
||||
.00390625
|
||||
.0625
|
||||
.0625
|
||||
EOF
|
||||
atf_check cmp expect.txt output.txt
|
||||
}
|
||||
|
||||
atf_test_case base3_input
|
||||
base3_input_head()
|
||||
{
|
||||
atf_set "descr" "Input ternary numbers"
|
||||
}
|
||||
base3_input_body()
|
||||
{
|
||||
cat > input.dc << EOF
|
||||
4k # 4 digits of precision
|
||||
3i # Base 3 input
|
||||
0 p
|
||||
1 p
|
||||
10 p
|
||||
.1 p # Repeating fractions get truncated
|
||||
EOF
|
||||
dc input.dc > output.txt
|
||||
cat > expect.txt << EOF
|
||||
0
|
||||
1
|
||||
3
|
||||
.3333
|
||||
EOF
|
||||
atf_check cmp expect.txt output.txt
|
||||
}
|
||||
|
||||
atf_init_test_cases()
|
||||
{
|
||||
atf_add_test_case base16_input
|
||||
atf_add_test_case base3_input
|
||||
}
|
Loading…
Reference in New Issue
Block a user