diff --git a/bc/COPYING b/bc/COPYING new file mode 100644 index 0000000..ee1cd26 --- /dev/null +++ b/bc/COPYING @@ -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 diff --git a/bc/bc.1 b/bc/bc.1 new file mode 100644 index 0000000..f0ba3ea --- /dev/null +++ b/bc/bc.1 @@ -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. diff --git a/bc/bc.y b/bc/bc.y new file mode 100644 index 0000000..8da3b60 --- /dev/null +++ b/bc/bc.y @@ -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 +#include +#include +#include +#include +#include +#include +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); +} diff --git a/bc/lib.b b/bc/lib.b new file mode 100644 index 0000000..150b9a6 --- /dev/null +++ b/bc/lib.b @@ -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=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 + } +} diff --git a/bc/yyval.sed b/bc/yyval.sed new file mode 100644 index 0000000..3857dc7 --- /dev/null +++ b/bc/yyval.sed @@ -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 + } +}