Add bc(1)

This commit is contained in:
Juhani Krekelä 2021-04-18 19:46:51 +03:00
parent 7aafee75c8
commit d493e58131
5 changed files with 1234 additions and 0 deletions

6
bc/COPYING Normal file
View File

@ -0,0 +1,6 @@
bc.1 is derived from Unix 7th edition. See LICENSE.v7
bc.y and lib.b are derived from 4.4BSD. See LICENSE.bsd
yyval.sed is by Gunnar Ritter. See LICENSE.gritter
Additionally, the files have been modified by Gunnar Ritter. See
LICENSE.gritter

222
bc/bc.1 Normal file
View File

@ -0,0 +1,222 @@
.\"
.\" Sccsid @(#)bc.1 1.7 (gritter) 10/11/03
.\" Derived from bc(1), Unix 7th edition:
.\" 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:
.\" Redistributions of source code and documentation must retain the
.\" above copyright notice, this list of conditions and the following
.\" disclaimer.
.\" Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 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.
.\" 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.
.TH BC 1 "10/11/03" "Heirloom Toolchest" "User Commands"
.SH NAME
bc \- arbitrary-precision arithmetic language
.SH SYNOPSIS
\fBbc\fR [\fB\-c\fR] [\fB\-l\fR] [\fIfile\fR ... ]
.SH DESCRIPTION
.I Bc
is an interactive processor for a language which resembles
C but provides unlimited precision arithmetic.
It takes input from any files given, then reads
the standard input.
The
.B \-l
argument stands for the name
of an arbitrary precision math library.
The syntax for
.I bc
programs is as follows;
L means letter a-z,
E means expression, S means statement.
.HP 6
Comments
.br
are enclosed in /* and */.
.HP 6
Names
.br
simple variables: L
.br
array elements: L [ E ]
.br
The words `ibase', `obase', and `scale'
.HP 6
Other operands
.br
arbitrarily long numbers with optional sign and decimal point.
.br
( E )
.br
sqrt ( E )
.br
length ( E ) number of significant decimal digits
.br
scale ( E ) number of digits right of decimal point
.br
L ( E , ... , E )
.HP 6
Operators
.br
+ \- * / % ^
(% is remainder; ^ is power)
.br
++ \-\- (prefix and postfix; apply to names)
.br
== <= >= != < >
.br
= =+ =\- =* =/ =% =^
.br
.HP 6
Statements
.br
E
.br
{ S ; ... ; S }
.br
if ( E ) S
.br
while ( E ) S
.br
for ( E ; E ; E ) S
.br
null statement
.br
break
.br
quit
.HP 6
Function definitions
.br
define L ( L ,..., L ) {
.br
auto L, ... , L
.br
S; ... S
.br
return ( E )
.br
}
.HP 6
Functions in
.B \-l
math library
.br
s(x) sine
.br
c(x) cosine
.br
e(x) exponential
.br
l(x) log
.br
a(x) arctangent
.br
j(n,x) Bessel function
.PP
.DT
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.
Either semicolons or newlines may separate statements.
Assignment to
.I scale
influences the number of digits to be retained on arithmetic
operations in the manner of
.IR dc (1).
Assignments to
.I ibase
or
.I 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
.PP
.nf
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
}
}
.PP
.fi
defines a function to compute an approximate value of
the exponential function and
.PP
.nf
for(i=1; i<=10; i++) e(i)
.fi
.PP
prints approximate values of the exponential function of
the first ten integers.
.PP
.I Bc
is actually a preprocessor for
.IR dc (1),
which it invokes automatically, unless the
.B \-c
(compile only)
option is present.
In this case the
.I dc
input is sent to the standard output instead.
.SH FILES
.ta \w'/usr/5lib/lib.b 'u
/usr/5lib/lib.b mathematical library
.br
dc(1) desk calculator proper
.SH "SEE ALSO"
dc(1)
.br
L. L. Cherry and R. Morris,
.I
BC \- An arbitrary precision desk-calculator language
.SH BUGS
No &&, \(or\|\(or, or ! operators.
.br
.I For
statement must have all three E's.
.br
.I Quit
is interpreted when read, not when executed.

743
bc/bc.y Normal file
View File

@ -0,0 +1,743 @@
%{
/* from 4.4BSD /usr/src/usr.bin/bc/bc.y */
/*-
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* This module is believed to contain source code proprietary to AT&T.
* Use and redistribution is subject to the Berkeley Software License
* Agreement and your Software Agreement with AT&T (Western Electric).
*
* from bc.y 8.1 (Berkeley) 6/6/93
*/
/*
* 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:
* Redistributions of source code and documentation must retain the
* above copyright notice, this list of conditions and the following
* disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 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.
* 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.
*/
#if __GNUC__ >= 3 && __GNUC_MINOR__ >= 4 || __GNUC__ >= 4
#define USED __attribute__ ((used))
#elif defined __GNUC__
#define USED __attribute__ ((unused))
#else
#define USED
#endif
static const char sccsid[] USED = "@(#)bc.sl 1.24 (gritter) 7/3/05";
#include <unistd.h>
#include <signal.h>
#include <limits.h>
#include <inttypes.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
typedef intptr_t YYSTYPE;
#define YYSTYPE YYSTYPE
static int cpeek(int c, int yes, int no);
static int getch(void);
static intptr_t bundle(int a, ...);
static void routput(intptr_t *p);
static void output(intptr_t *p);
static void conout(intptr_t p, intptr_t s);
static void pp(intptr_t);
static void tp(intptr_t);
static void yyinit(int argc, char *argv[]);
static intptr_t *getout(void);
static intptr_t *getf(intptr_t);
static intptr_t *geta(intptr_t);
static void yyerror(const char *);
static void cantopen(const char *);
extern int yylex(void);
#if defined (__GLIBC__) && defined (_IO_getc_unlocked)
#undef getc
#define getc(f) _IO_getc_unlocked(f)
#endif
%}
%right '='
%left '+' '-'
%left '*' '/' '%'
%right '^'
%left UMINUS
%term LETTER DIGIT SQRT LENGTH _IF FFF EQ
%term _WHILE _FOR NE LE GE INCR DECR
%term _RETURN _BREAK _DEFINE BASE OBASE SCALE
%term EQPL EQMI EQMUL EQDIV EQREM EQEXP
%term _AUTO DOT
%term QSTR
%{
#define THIS_BC_STRING_MAX 1000
static FILE *in;
static char cary[LINE_MAX + 1], *cp = { cary };
static char string[THIS_BC_STRING_MAX + 3], *str = {string};
static int crs = '0';
static int rcrs = '0'; /* reset crs */
static int bindx = 0;
static int lev = 0;
static int ln;
static char *ss;
static int bstack[10] = { 0 };
static char *numb[15] = {
" 0", " 1", " 2", " 3", " 4", " 5",
" 6", " 7", " 8", " 9", " 10", " 11",
" 12", " 13", " 14" };
static intptr_t *pre, *post;
%}
%%
start :
| start stat tail
{ output( (intptr_t *)$2 );}
| start def dargs ')' '{' dlist slist '}'
{ bundle( 6,pre, $7, post ,"0",numb[lev],"Q");
conout( $$, $2 );
rcrs = crs;
output( (intptr_t *)"" );
lev = bindx = 0;
}
;
dlist : tail
| dlist _AUTO dlets tail
;
stat : e
{ bundle(2, $1, "ps." ); }
|
{ bundle(1, "" ); }
| QSTR
{ bundle(3,"[",$1,"]P");}
| LETTER '=' e
{ bundle(3, $3, "s", $1 ); }
| LETTER '[' e ']' '=' e
{ bundle(4, $6, $3, ":", geta($1)); }
| LETTER EQOP e
{ bundle(6, "l", $1, $3, $2, "s", $1 ); }
| LETTER '[' e ']' EQOP e
{ bundle(8,$3, ";", geta($1), $6, $5, $3, ":", geta($1));}
| _BREAK
{ bundle(2, numb[lev-bstack[bindx-1]], "Q" ); }
| _RETURN '(' e ')'
{ bundle(4, $3, post, numb[lev], "Q" ); }
| _RETURN '(' ')'
{ bundle(4, "0", post, numb[lev], "Q" ); }
| _RETURN
{ bundle(4,"0",post,numb[lev],"Q"); }
| SCALE '=' e
{ bundle(2, $3, "k"); }
| SCALE EQOP e
{ bundle(4,"K",$3,$2,"k"); }
| BASE '=' e
{ bundle(2,$3, "i"); }
| BASE EQOP e
{ bundle(4,"I",$3,$2,"i"); }
| OBASE '=' e
{ bundle(2,$3,"o"); }
| OBASE EQOP e
{ bundle(4,"O",$3,$2,"o"); }
| '{' slist '}'
{ $$ = $2; }
| FFF
{ bundle(1,"fY"); }
| error
{ bundle(1,"c"); }
| _IF CRS BLEV '(' re ')' stat
{ conout( $7, $2 );
bundle(3, $5, $2, " " );
}
| _WHILE CRS '(' re ')' stat BLEV
{ bundle(3, $6, $4, $2 );
conout( $$, $2 );
bundle(3, $4, $2, " " );
}
| fprefix CRS re ';' e ')' stat BLEV
{ bundle(5, $7, $5, "s.", $3, $2 );
conout( $$, $2 );
bundle(5, $1, "s.", $3, $2, " " );
}
| '~' LETTER '=' e
{ bundle(3,$4,"S",$2); }
;
EQOP : EQPL
{ $$ = (intptr_t)"+"; }
| EQMI
{ $$ = (intptr_t)"-"; }
| EQMUL
{ $$ = (intptr_t)"*"; }
| EQDIV
{ $$ = (intptr_t)"/"; }
| EQREM
{ $$ = (intptr_t)"%%"; }
| EQEXP
{ $$ = (intptr_t)"^"; }
;
fprefix : _FOR '(' e ';'
{ $$ = $3; }
;
BLEV :
{ --bindx; }
;
slist : stat
| slist tail stat
{ bundle(2, $1, $3 ); }
;
tail : '\n'
{ln++;}
| ';'
;
re : e EQ e
{ bundle(3, $1, $3, "=" ); }
| e '<' e
{ bundle(3, $1, $3, ">" ); }
| e '>' e
{ bundle(3, $1, $3, "<" ); }
| e NE e
{ bundle(3, $1, $3, "!=" ); }
| e GE e
{ bundle(3, $1, $3, "!>" ); }
| e LE e
{ bundle(3, $1, $3, "!<" ); }
| e
{ bundle(2, $1, " 0!=" ); }
;
e : e '+' e
{ bundle(3, $1, $3, "+" ); }
| e '-' e
{ bundle(3, $1, $3, "-" ); }
| '-' e %prec UMINUS
{ bundle(3, " 0", $2, "-" ); }
| e '*' e
{ bundle(3, $1, $3, "*" ); }
| e '/' e
{ bundle(3, $1, $3, "/" ); }
| e '%' e
{ bundle(3, $1, $3, "%%" ); }
| e '^' e
{ bundle(3, $1, $3, "^" ); }
| LETTER '[' e ']'
{ bundle(3,$3, ";", geta($1)); }
| LETTER INCR
{ bundle(4, "l", $1, "d1+s", $1 ); }
| INCR LETTER
{ bundle(4, "l", $2, "1+ds", $2 ); }
| DECR LETTER
{ bundle(4, "l", $2, "1-ds", $2 ); }
| LETTER DECR
{ bundle(4, "l", $1, "d1-s", $1 ); }
| LETTER '[' e ']' INCR
{ bundle(7,$3,";",geta($1),"d1+",$3,":",geta($1)); }
| INCR LETTER '[' e ']'
{ bundle(7,$4,";",geta($2),"1+d",$4,":",geta($2)); }
| LETTER '[' e ']' DECR
{ bundle(7,$3,";",geta($1),"d1-",$3,":",geta($1)); }
| DECR LETTER '[' e ']'
{ bundle(7,$4,";",geta($2),"1-d",$4,":",geta($2)); }
| SCALE INCR
{ bundle(1,"Kd1+k"); }
| INCR SCALE
{ bundle(1,"K1+dk"); }
| SCALE DECR
{ bundle(1,"Kd1-k"); }
| DECR SCALE
{ bundle(1,"K1-dk"); }
| BASE INCR
{ bundle(1,"Id1+i"); }
| INCR BASE
{ bundle(1,"I1+di"); }
| BASE DECR
{ bundle(1,"Id1-i"); }
| DECR BASE
{ bundle(1,"I1-di"); }
| OBASE INCR
{ bundle(1,"Od1+o"); }
| INCR OBASE
{ bundle(1,"O1+do"); }
| OBASE DECR
{ bundle(1,"Od1-o"); }
| DECR OBASE
{ bundle(1,"O1-do"); }
| LETTER '(' cargs ')'
{ bundle(4, $3, "l", getf($1), "x" ); }
| LETTER '(' ')'
{ bundle(3, "l", getf($1), "x" ); }
| cons
{ bundle(2, " ", $1 ); }
| DOT cons
{ bundle(2, " .", $2 ); }
| cons DOT cons
{ bundle(4, " ", $1, ".", $3 ); }
| cons DOT
{ bundle(3, " ", $1, "." ); }
| DOT
{ $$ = (intptr_t)"l."; }
| LETTER
{ bundle(2, "l", $1 ); }
| LETTER '=' e
{ bundle(3, $3, "ds", $1 ); }
| LETTER EQOP e %prec '='
{ bundle(6, "l", $1, $3, $2, "ds", $1 ); }
| LETTER '[' e ']' '=' e
{ bundle(5,$6,"d",$3,":",geta($1)); }
| LETTER '[' e ']' EQOP e
{ bundle(9,$3,";",geta($1),$6,$5,"d",$3,":",geta($1)); }
| LENGTH '(' e ')'
{ bundle(2,$3,"Z"); }
| SCALE '(' e ')'
{ bundle(2,$3,"X"); } /* must be before '(' e ')' */
| '(' e ')'
{ $$ = $2; }
| '?'
{ bundle(1, "?" ); }
| SQRT '(' e ')'
{ bundle(2, $3, "v" ); }
| '~' LETTER
{ bundle(2,"L",$2); }
| SCALE '=' e
{ bundle(2,$3,"dk"); }
| SCALE EQOP e %prec '='
{ bundle(4,"K",$3,$2,"dk"); }
| BASE '=' e
{ bundle(2,$3,"di"); }
| BASE EQOP e %prec '='
{ bundle(4,"I",$3,$2,"di"); }
| OBASE '=' e
{ bundle(2,$3,"do"); }
| OBASE EQOP e %prec '='
{ bundle(4,"O",$3,$2,"do"); }
| SCALE
{ bundle(1,"K"); }
| BASE
{ bundle(1,"I"); }
| OBASE
{ bundle(1,"O"); }
;
cargs : eora
| cargs ',' eora
{ bundle(2, $1, $3 ); }
;
eora: e
| LETTER '[' ']'
{bundle(2,"l",geta($1)); }
;
cons : constant
{ *cp++ = '\0'; }
constant:
'_'
{ $$ = (intptr_t)cp; *cp++ = '_'; }
| DIGIT
{ $$ = (intptr_t)cp; *cp++ = $1; }
| constant DIGIT
{ *cp++ = $2; }
;
CRS :
{ $$ = (intptr_t)cp; *cp++ = crs++; *cp++ = '\0';
if(crs == '[')crs+=3;
if(crs == 'a')crs='{';
if(crs >= 0241){yyerror("program too big");
getout();
}
bstack[bindx++] = lev++; }
;
def : _DEFINE LETTER '('
{ $$ = (intptr_t)getf($2);
pre = (intptr_t *)"";
post = (intptr_t *)"";
lev = 1;
bstack[bindx=0] = 0;
}
;
dargs :
| lora
{ pp( $1 ); }
| dargs ',' lora
{ pp( $3 ); }
;
dlets : lora
{ tp($1); }
| dlets ',' lora
{ tp($3); }
;
lora : LETTER
| LETTER '[' ']'
{ $$ = (intptr_t)geta($1); }
;
%%
# define error 256
static int peekc = -1;
static int sargc;
static int ifile;
static char **sargv;
static char funtab[52] = {
01,0,02,0,03,0,04,0,05,0,06,0,07,0,010,0,011,0,012,0,013,0,014,0,015,0,016,0,017,0,
020,0,021,0,022,0,023,0,024,0,025,0,026,0,027,0,030,0,031,0,032,0 };
static char atab[52] = {
0241,0,0242,0,0243,0,0244,0,0245,0,0246,0,0247,0,0250,0,0251,0,0252,0,0253,0,
0254,0,0255,0,0256,0,0257,0,0260,0,0261,0,0262,0,0263,0,0264,0,0265,0,0266,0,
0267,0,0270,0,0271,0,0272,0};
static char *letr[26] = {
"a","b","c","d","e","f","g","h","i","j",
"k","l","m","n","o","p","q","r","s","t",
"u","v","w","x","y","z" } ;
/*static char *dot = { "." };*/
int
yylex(void){
int c, ch;
restart:
c = getch();
peekc = -1;
while( c == ' ' || c == '\t' ) c = getch();
if(c == '\\'){
getch();
goto restart;
}
if( c<= 'z' && c >= 'a' ) {
/* look ahead to look for reserved words */
peekc = getch();
if( peekc >= 'a' && peekc <= 'z' ){ /* must be reserved word */
if( c=='i' && peekc=='f' ){ c=_IF; goto skip; }
if( c=='w' && peekc=='h' ){ c=_WHILE; goto skip; }
if( c=='f' && peekc=='o' ){ c=_FOR; goto skip; }
if( c=='s' && peekc=='q' ){ c=SQRT; goto skip; }
if( c=='r' && peekc=='e' ){ c=_RETURN; goto skip; }
if( c=='b' && peekc=='r' ){ c=_BREAK; goto skip; }
if( c=='d' && peekc=='e' ){ c=_DEFINE; goto skip; }
if( c=='s' && peekc=='c' ){ c= SCALE; goto skip; }
if( c=='b' && peekc=='a' ){ c=BASE; goto skip; }
if( c=='i' && peekc == 'b'){ c=BASE; goto skip; }
if( c=='o' && peekc=='b' ){ c=OBASE; goto skip; }
if( c=='d' && peekc=='i' ){ c=FFF; goto skip; }
if( c=='a' && peekc=='u' ){ c=_AUTO; goto skip; }
if( c == 'l' && peekc=='e'){ c=LENGTH; goto skip; }
if( c == 'q' && peekc == 'u'){getout();}
/* could not be found */
return( error );
skip: /* skip over rest of word */
peekc = -1;
while( (ch = getch()) >= 'a' && ch <= 'z' );
peekc = ch;
return( c );
}
/* usual case; just one single letter */
yylval = (intptr_t)letr[c-'a'];
return( LETTER );
}
if( c>= '0' && c <= '9' || c>= 'A' && c<= 'F' ){
yylval = c;
return( DIGIT );
}
switch( c ){
case '.': return( DOT );
case '=':
switch( peekc = getch() ){
case '=': c=EQ; goto gotit;
case '+': c=EQPL; goto gotit;
case '-': c=EQMI; goto gotit;
case '*': c=EQMUL; goto gotit;
case '/': c=EQDIV; goto gotit;
case '%': c=EQREM; goto gotit;
case '^': c=EQEXP; goto gotit;
default: return( '=' );
gotit: peekc = -1; return(c);
}
case '+': return( cpeek( '+', INCR, cpeek( '=', EQPL, '+') ) );
case '-': return( cpeek( '-', DECR, cpeek( '=', EQMI, '-') ) ) ;
case '<': return( cpeek( '=', LE, '<' ) );
case '>': return( cpeek( '=', GE, '>' ) );
case '!': return( cpeek( '=', NE, '!' ) );
case '/':
if((peekc = getch()) == '*'){
peekc = -1;
while((getch() != '*') || ((peekc = getch()) != '/'));
peekc = -1;
goto restart;
}
else if (peekc == '=') {
c=EQDIV;
goto gotit;
}
else return(c);
case '*':
return( cpeek( '=', EQMUL, '*' ) );
case '%':
return( cpeek( '=', EQREM, '%' ) );
case '^':
return( cpeek( '=', EQEXP, '^' ) );
case '"':
yylval = (intptr_t)str;
while((c=getch()) != '"'){*str++ = c;
if(str >= &string[sizeof string - 1]){yyerror("string space exceeded");
getout();
}
}
*str++ = '\0';
return(QSTR);
default: return( c );
}
}
static int
cpeek(int c, int yes, int no){
if( (peekc=getch()) != c ) return( no );
else {
peekc = -1;
return( yes );
}
}
static int
getch(void){
int ch;
loop:
ch = (peekc < 0) ? getc(in) : peekc;
peekc = -1;
if(ch != EOF)return(ch);
if(++ifile > sargc){
if(ifile >= sargc+2)getout();
in = stdin;
ln = 0;
goto loop;
}
fclose(in);
if((in = fopen(sargv[ifile],"r")) != NULL){
ln = 0;
ss = sargv[ifile];
goto loop;
}
cantopen(sargv[ifile]);
return EOF;
}
# define b_sp_max 3000
static intptr_t b_space [ b_sp_max ];
static intptr_t * b_sp_nxt = { b_space };
static int bdebug = 0;
static intptr_t
bundle(int a, ...){
intptr_t i, *q;
va_list ap;
i = a;
q = b_sp_nxt;
if( bdebug ) printf("bundle %ld elements at %lo\n",(long)i, (long)q );
va_start(ap, a);
while(i-- > 0){
if( b_sp_nxt >= & b_space[b_sp_max] ) yyerror( "bundling space exceeded" );
* b_sp_nxt++ = va_arg(ap, intptr_t);
}
va_end(ap);
* b_sp_nxt++ = 0;
yyval = (intptr_t)q;
return( (intptr_t)q );
}
static void
routput(intptr_t *p) {
if( bdebug ) printf("routput(%lo)\n", (long)p );
if( p >= &b_space[0] && p < &b_space[b_sp_max]){
/* part of a bundle */
while( *p != 0 ) routput( (intptr_t *)*p++ );
}
else printf( (char *)p ); /* character string */
}
static void
output(intptr_t *p) {
routput( p );
b_sp_nxt = & b_space[0];
printf( "\n" );
fflush(stdout);
cp = cary;
crs = rcrs;
}
static void
conout(intptr_t p, intptr_t s) {
printf("[");
routput( (intptr_t *)p );
printf("]s%s\n", (char *)s );
fflush(stdout);
lev--;
}
static void
yyerror(const char *s) {
if(ifile > sargc)ss="teletype";
fprintf(stderr, "%s on line %d, %s\n",
s ,ss?ln+1:0,ss?ss:"command line");
cp = cary;
crs = rcrs;
bindx = 0;
lev = 0;
b_sp_nxt = &b_space[0];
}
static void
cantopen(const char *fn)
{
char spc[280];
char *oss = ss;
ss = 0;
snprintf(spc, sizeof spc, "can't open input file %s", fn);
yyerror(spc);
ss = oss;
}
static void
pp(intptr_t s) {
/* puts the relevant stuff on pre and post for the letter s */
bundle(3, "S", s, pre );
pre = (intptr_t *)yyval;
bundle(4, post, "L", s, "s." );
post = (intptr_t *)yyval;
}
static void
tp(intptr_t s) { /* same as pp, but for temps */
bundle(3, "0S", s, pre );
pre = (intptr_t *)yyval;
bundle(4, post, "L", s, "s." );
post = (intptr_t *)yyval;
}
static void
yyinit(int argc,char **argv) {
signal(SIGINT, SIG_IGN);
sargv=argv;
sargc= -- argc;
if(sargc == 0)in=stdin;
else if((in = fopen(sargv[1],"r")) == NULL) {
cantopen(sargv[1]);
exit(0);
}
ifile = 1;
ln = 0;
ss = sargv[1];
}
static intptr_t *
getout(void){
printf("q");
fflush(stdout);
exit(0);
/*NOTREACHED*/
return(NULL);
}
static intptr_t *
getf(intptr_t p) {
return(intptr_t *)(&funtab[2*(*((char *)p) -0141)]);
}
static intptr_t *
geta(intptr_t p) {
return(intptr_t *)(&atab[2*(*((char *)p) - 0141)]);
}
int
main(int argc, char **argv)
{
extern int yyparse(void);
const char optstring[] = "cdl";
int p[2];
int i;
int cflag = 0, lflag = 0;
#ifdef __GLIBC__
putenv("POSIXLY_CORRECT=1");
#endif
while ((i = getopt(argc, argv, optstring)) != EOF) {
switch (i) {
case 'd':
case 'c':
cflag = 1;
break;
case 'l':
lflag = 1;
break;
default:
exit(2);
}
}
argv += optind - 1, argc -= optind - 1;
if (cflag) {
yyinit(argc, argv);
yyparse();
exit(0);
}
if (lflag) {
*argv-- = LIBB;
argc++;
}
pipe(p);
if (fork()==0) {
close(1);
dup(p[1]);
close(p[0]);
close(p[1]);
yyinit(argc, argv);
yyparse();
exit(0);
}
close(0);
dup(p[0]);
close(p[0]);
close(p[1]);
execl(DC, "dc", "-", NULL);
execl("/usr/5bin/dc", "dc", "-", NULL);
execl("/usr/local/bin/dc", "dc", "-", NULL);
execl("/usr/contrib/bin/dc", "dc", "-", NULL);
execl("/usr/bin/dc", "dc", "-", NULL);
return(1);
}

241
bc/lib.b Normal file
View File

@ -0,0 +1,241 @@
/* from 4.4BSD /usr/src/usr.bin/bc/bc.library */
/*-
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* This module is believed to contain source code proprietary to AT&T.
* Use and redistribution is subject to the Berkeley Software License
* Agreement and your Software Agreement with AT&T (Western Electric).
*
* from bc.library 8.1 (Berkeley) 6/6/93
*/
/*
* 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:
* Redistributions of source code and documentation must retain the
* above copyright notice, this list of conditions and the following
* disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 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.
* 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.
*/
/* Sccsid @(#)lib.b 1.4 (gritter) 8/26/02 */
scale = 20
define e(x){
auto a, b, c, d, e, g, t, w, y
t = scale
scale = t + .434*x + 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
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
if(x <=0) return(1-10^scale)
t = scale
f=1
scale = scale + scale(x) - length(x) + 1
s=scale
while(x > 2){
s = s + (length(x)-scale(x))/2 + 1
if(s>0) scale = s
x = sqrt(x)
f=f*2
}
while(x < .5){
s = s + (length(x)-scale(x))/2 + 1
if(s>0) scale = s
x = sqrt(x)
f=f*2
}
scale = t + length(f) - scale(f) + 1
u = (x-1)/(x+1)
scale = scale + 1.1*length(t) - 1.1*scale(t)
s = u*u
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
return(u*c/d)
}
e=g
}
}
define s(x){
auto a, b, c, s, t, y, p, n, i
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; return(s/1)}
s = s+c
}
}
define c(x){
auto t
t = scale
scale = scale+1
x = s(x+2*a(1))
scale = t
return(x/1)
}
define a(x){
auto a, b, c, d, e, f, g, s, t
if(x==0) return(0)
if(x==1) {
if(scale<52) {
return(.7853981633974483096156608458198757210492923498437764/1)
}
}
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){
scale = t
return(x*c/d)
}
e=g
}
}
define j(n,x){
auto a,b,c,d,e,g,i,s,k,t
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){
scale = t
return(g/1)
}
e=g
}
}

22
bc/yyval.sed Normal file
View File

@ -0,0 +1,22 @@
#
# Sccsid @(#)yyval.sed 1.3 (gritter) 4/27/04
#
# bison has a yacc-compatible yyval, but it is a local variable inside
# yyparse(). Making the variable global is necessary to make bc work
# with a bison-generated parser.
1,2 {
/Bison/ {
:look
/YYSTYPE/ {
a\
YYSTYPE yyval;
:repl
s/^[ ]*YYSTYPE[ ]*yyval;//
n
t
b repl
}
n
b look
}
}