From 6fcea8b76c8836873449a6495e52a9a9874af38c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juhani=20Krekel=C3=A4?= Date: Sun, 18 Apr 2021 19:04:40 +0300 Subject: [PATCH] Add dc(1) sources --- LICENSE.bsd | 30 + LICENSE.gritter | 19 + LICENSE.v7 | 31 + dc/COPYING | 5 + dc/dc.1 | 231 ++++++ dc/dc.c | 2061 +++++++++++++++++++++++++++++++++++++++++++++++ dc/dc.h | 203 +++++ 7 files changed, 2580 insertions(+) create mode 100644 LICENSE.bsd create mode 100644 LICENSE.gritter create mode 100644 LICENSE.v7 create mode 100644 dc/COPYING create mode 100644 dc/dc.1 create mode 100644 dc/dc.c create mode 100644 dc/dc.h diff --git a/LICENSE.bsd b/LICENSE.bsd new file mode 100644 index 0000000..b7e4397 --- /dev/null +++ b/LICENSE.bsd @@ -0,0 +1,30 @@ + Copyright (c) 1980, 1993 + The Regents of the University of California. 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 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 by the University of + California, Berkeley and its contributors. + 4. Neither the name of the University nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. diff --git a/LICENSE.gritter b/LICENSE.gritter new file mode 100644 index 0000000..2a32253 --- /dev/null +++ b/LICENSE.gritter @@ -0,0 +1,19 @@ + Copyright (c) 2003 Gunnar Ritter + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute + it freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source distribution. diff --git a/LICENSE.v7 b/LICENSE.v7 new file mode 100644 index 0000000..3a0d583 --- /dev/null +++ b/LICENSE.v7 @@ -0,0 +1,31 @@ + 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. diff --git a/dc/COPYING b/dc/COPYING new file mode 100644 index 0000000..171f1bf --- /dev/null +++ b/dc/COPYING @@ -0,0 +1,5 @@ +dc.1 and dc.h are derived from Unix 7th edition. See LICENSE.v7 +dc.c is derived from 4.4BSD. See LICENSE.bsd + +Additionally, the files have been modified by Gunnar Ritter. See +LICENSE.gritter diff --git a/dc/dc.1 b/dc/dc.1 new file mode 100644 index 0000000..fd9f0ad --- /dev/null +++ b/dc/dc.1 @@ -0,0 +1,231 @@ +.\" +.\" Sccsid @(#)dc.1 1.5 (gritter) 1/11/03 +.\" Derived from dc(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 DC 1 "1/11/03" "Heirloom Toolchest" "User Commands" +.SH NAME +dc \- desk calculator +.SH SYNOPSIS +\fBdc\fR [\fIfile\fR] +.SH DESCRIPTION +.I Dc +is an arbitrary precision arithmetic package. +Ordinarily it operates on decimal integers, +but one may specify an input base, output base, +and a number of fractional digits to be maintained. +The overall structure of +.I dc +is +a stacking (reverse Polish) calculator. +If an argument is given, +input is taken from that file until its end, +then from the standard input. +The following constructions are recognized: +.HP 6 +number +.br +The value of the number is pushed on the stack. +A number is an unbroken string of the digits 0-9. +It may be preceded by an underscore _ to input a +negative number. +Numbers may contain decimal points. +.HP 6 ++ \- / * % ^ +.br +The +top two values on the stack are added +(+), +subtracted +(\-), +multiplied (*), +divided (/), +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. +.TP +.BI s x +The +top of the stack is popped and stored into +a register named +.I x, +where +.I x +may be any character. +If +the +.B s +is capitalized, +.I x +is treated as a stack and the value is pushed on it. +.TP +.BI l x +The +value in register +.I x +is pushed on the stack. +The register +.I x +is not altered. +All registers start with zero value. +If the +.B l +is capitalized, +register +.I x +is treated as a stack and its top value is popped onto the main stack. +.TP +.B d +The +top value on the stack is duplicated. +.TP +.B p +The top value on the stack is printed. +The top value remains unchanged. +.B P +interprets the top of the stack as an ascii string, +removes it, and prints it. +.TP +.B f +All values on the stack and in registers are printed. +.TP +.B q +exits the program. +If executing a string, the recursion level is +popped by two. +If +.B q +is capitalized, +the top value on the stack is popped and the string execution level is popped +by that value. +.TP +.B x +treats the top element of the stack as a character string +and executes it as a string of dc commands. +.TP +.B X +replaces the number on the top of the stack with its scale factor. +.TP +.B "[ ... ]" +puts the bracketed ascii string onto the top of the stack. +.HP 6 +.I "x =x" +.br +The +top two elements of the stack are popped and compared. +Register +.I x +is executed if they obey the stated +relation. +.TP +.B v +replaces the top element on the stack by its square root. +Any existing fractional part of the argument is taken +into account, but otherwise the scale factor is ignored. +.TP +.B ! +interprets the rest of the line as a UNIX command. +.TP +.B c +All values on the stack are popped. +.TP +.B i +The top value on the stack is popped and used as the +number radix for further input. +.B I +pushes the input base on the top of the stack. +.TP +.B o +The top value on the stack is popped and used as the +number radix for further output. +.TP +.SM +.B O +pushes the output base on the top of the stack. +.TP +.B 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. +.TP +.B z +The stack level is pushed onto the stack. +.TP +.SM +.B Z +replaces the number on the top of the stack with its length. +.TP +.B ? +A line of input is taken from the input source (usually the terminal) +and executed. +.TP +.B "; :" +are used by +.I bc +for array operations. +.PP +An example which prints the first ten values of n! is +.nf +.PP +.in +3 +[la1+dsa*pla10>y]sy +.br +0sa1 +.br +lyx +.fi +.SH "SEE ALSO" +bc(1), +which is a preprocessor for +.I dc +providing infix notation and a C-like syntax +which implements functions and reasonable control +structures for programs. +.SH DIAGNOSTICS +`x is unimplemented' where x is an octal number. +.br +`stack empty' for not enough elements on the stack to do what was asked. +.br +`Out of space' when the free list is exhausted (too many digits). +.br +`Out of headers' for too many numbers being kept around. +.br +`Out of pushdown' for too many items on the stack. +.br +`Nesting Depth' for too many levels of nested execution. diff --git a/dc/dc.c b/dc/dc.c new file mode 100644 index 0000000..e9252d1 --- /dev/null +++ b/dc/dc.c @@ -0,0 +1,2061 @@ +/* from 4.4BSD /usr/src/usr.bin/dc/dc.c */ +/*- + * 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 dc.c 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 @(#)dc.c 1.21 (gritter) 12/25/06> */ + +#include +#include +#include +#include +#include +#include "sigset.h" +#include +#include +#include + +#include "dc.h" + +int +main(int argc,char **argv) +{ + init(argc,argv); + commnds(); + /*NOTREACHED*/ + return(0); +} + +void +commnds(void){ + register int c; + register struct blk *p,*q; + long l; + int sign; + struct blk **ptr,*s,*t; + struct sym *sp; + int sk,sk1,sk2; + int n,d; + + while(1){ + if(((c = readc())>='0' && c <= '9')|| (c>='A' && c <='F') || c == '.'){ + unreadc(c); + p = readin(); + pushp(p); + continue; + } + switch(c){ + case ' ': + case '\n': + case 0377: + case EOF: + continue; + case 'Y': + sdump("stk",*stkptr); + printf("all %ld rel %ld headmor %ld\n",all,rel,headmor); + printf("nbytes %ld\n",nbytes); + continue; + case '_': + p = readin(); + savk = sunputc(p); + chsign(p); + sputc(p,savk); + pushp(p); + continue; + case '-': + subt(); + continue; + case '+': + if(eqk() != 0)continue; + binop('+'); + continue; + case '*': + arg1 = pop(); + EMPTY; + arg2 = pop(); + EMPTYR(arg1); + sk1 = sunputc(arg1); + sk2 = sunputc(arg2); + binop('*'); + p = pop(); + sunputc(p); + savk = n = sk1+sk2; + if(n>k && n>sk1 && n>sk2){ + sk = sk1; + if(sk=3){ + error("exp too big\n"); + } + savk = sunputc(arg2); + p = dcexp(arg2,arg1); + release(arg2); + rewind(arg1); + c = sgetc(arg1); + if(sfeof(arg1) == 0) + c = sgetc(arg1)*100 + c; + d = c*savk; + release(arg1); + if(neg == 0){ + if(k>=savk)n = k; + else n = savk; + if(n= 100){ + sputc(p,n/100); + n %= 100; + } + sputc(p,n); + sputc(p,0); + pushp(p); + continue; + case 'Z': + p = pop(); + EMPTY; + n = (length(p)-1)<<1; + fsfile(p); + sbackc(p); + if(sfbeg(p) == 0){ + if((c = sbackc(p))<0){ + n -= 2; + if(sfbeg(p) == 1)n += 1; + else { + if((c = sbackc(p)) == 0)n += 1; + else if(c > 90)n -= 1; + } + } + else if(c < 10) n -= 1; + } + release(p); + q = salloc(1); + if(n >= 100){ + sputc(q,n%100); + n /= 100; + } + sputc(q,n); + sputc(q,0); + pushp(q); + continue; + case 'i': + p = pop(); + EMPTY; + p = scalint(p); + release(inbas); + inbas = p; + continue; + case 'I': + p = copy(inbas,length(inbas)+1); + sputc(p,0); + pushp(p); + continue; + case 'o': + p = pop(); + EMPTY; + p = scalint(p); + sign = 0; + n = length(p); + q = copy(p,n); + fsfile(q); + l = c = sbackc(q); + if(n != 1){ + if(c<0){ + sign = 1; + chsign(q); + n = length(q); + fsfile(q); + l = c = sbackc(q); + } + if(n != 1){ + while(sfbeg(q) == 0)l = l*100+sbackc(q); + } + } + if (l > BC_BASE_MAX) + error("output base is too large\n"); + logo = log_2(l); + obase = l; + release(basptr); + if(sign == 1)obase = (long)-l; + basptr = p; + outdit = (int (*)(struct blk *, int, int))bigot; + if(n == 1 && sign == 0){ + if(c <= 16){ + outdit = (int (*)(struct blk *, int, int))hexot; + fw = 1; + fw1 = 0; + ll = 68; + release(q); + continue; + } + } + n = 0; + if(sign == 1)n++; + p = salloc(1); + sputc(p,-1); + t = add(p,q); + n += length(t)*2; + fsfile(t); + if((c = sbackc(t))>9)n++; + release(t); + release(q); + release(p); + fw = n; + fw1 = n-1; + ll = 68; + if(fw>=ll)continue; + ll = (68/fw)*fw; + continue; + case 'O': + p = copy(basptr,length(basptr)+1); + sputc(p,0); + pushp(p); + continue; + case '[': + n = 0; + p = salloc(0); + while(1){ + if((c = readc()) == ']'){ + if(n == 0)break; + n--; + } + sputc(p,c); + if(c == '[')n++; + } + pushp(p); + continue; + case 'k': + p = pop(); + EMPTY; + p = scalint(p); + if(length(p)>1){ + error("scale too big\n"); + } + rewind(p); + k = sfeof(p)?0:sgetc(p); + release(scalptr); + scalptr = p; + continue; + case 'K': + p = copy(scalptr,length(scalptr)+1); + sputc(p,0); + pushp(p); + continue; + case 'X': + p = pop(); + EMPTY; + fsfile(p); + n = sbackc(p); + release(p); + p = salloc(2); + sputc(p,n); + sputc(p,0); + pushp(p); + continue; + case 'Q': + p = pop(); + EMPTY; + if(length(p)>2){ + error("Q?\n"); + } + rewind(p); + if((c = sgetc(p))<0){ + error("neg Q\n"); + } + release(p); + while(c-- > 0){ + if(readptr == &readstk[0]){ + error("readstk?\n"); + } + if(*readptr != 0)release(*readptr); + readptr--; + } + continue; + case 'q': + if(readptr <= &readstk[1])exit(0); + if(*readptr != 0)release(*readptr); + readptr--; + if(*readptr != 0)release(*readptr); + readptr--; + continue; + case 'f': + if(stkptr == &stack[0])printf("empty stack\n"); + else { + for(ptr = stkptr; ptr > &stack[0];){ + print(*ptr--); + } + } + continue; + case 'p': + if(stkptr == &stack[0])printf("empty stack\n"); + else{ + print(*stkptr); + } + continue; + case 'P': + p = pop(); + EMPTY; + sputc(p,0); + printf("%s",p->beg); + release(p); + continue; + case 'd': + if(stkptr == &stack[0]){ + printf("empty stack\n"); + continue; + } + q = *stkptr; + n = length(q); + p = copy(*stkptr,n); + pushp(p); + continue; + case 'c': + while(stkerr == 0){ + p = pop(); + if(stkerr == 0)release(p); + } + continue; + case 'S': + if(stkptr == &stack[0]){ + error("save: args\n"); + } + c = readc() & 0377; + sptr = stable[c]; + sp = stable[c] = sfree; + sfree = sfree->next; + if(sfree == 0)goto sempty; + sp->next = sptr; + p = pop(); + EMPTY; + if(c >= ARRAYST){ + q = copy(p,length(p)); + for(n = 0;n < PTRSZ;n++)sputc(q,0); + release(p); + p = q; + } + sp->val = p; + continue; +sempty: + error("symbol table overflow\n"); + case 's': + if(stkptr == &stack[0]){ + error("save:args\n"); + } + c = readc() & 0377; + sptr = stable[c]; + if(sptr != 0){ + p = sptr->val; + if(c >= ARRAYST){ + rewind(p); + while(sfeof(p) == 0)release(dcgetwd(p)); + } + release(p); + } + else{ + sptr = stable[c] = sfree; + sfree = sfree->next; + if(sfree == 0)goto sempty; + sptr->next = 0; + } + p = pop(); + sptr->val = p; + continue; + case 'l': + load(); + continue; + case 'L': + c = readc() & 0377; + sptr = stable[c]; + if(sptr == 0){ + error("L?\n"); + } + stable[c] = sptr->next; + sptr->next = sfree; + sfree = sptr; + p = sptr->val; + if(c >= ARRAYST){ + rewind(p); + while(sfeof(p) == 0){ + q = dcgetwd(p); + if(q != 0)release(q); + } + } + pushp(p); + continue; + case ':': + p = pop(); + EMPTY; + q = scalint(p); + fsfile(q); + c = 0; + if((sfbeg(q) == 0) && ((c = sbackc(q))<0)){ + error("neg index\n"); + } + if(length(q)>2){ + error("index too big\n"); + } + if(sfbeg(q) == 0)c = c*100+sbackc(q); + if(c >= BC_DIM_MAX){ + error("index too big\n"); + } + release(q); + n = readc() & 0377; + sptr = stable[n]; + if(sptr == 0){ + sptr = stable[n] = sfree; + sfree = sfree->next; + if(sfree == 0)goto sempty; + sptr->next = 0; + p = salloc((c+PTRSZ)*PTRSZ); + zero(p); + } + else{ + p = sptr->val; + if(length(p)-PTRSZ < c*PTRSZ){ + q = copy(p,(c+PTRSZ)*PTRSZ); + release(p); + p = q; + } + } + seekc(p,c*PTRSZ); + q = lookwd(p); + if (q!=NULL) release(q); + s = pop(); + EMPTY; + salterwd((struct wblk *)p,s); + sptr->val = p; + continue; + case ';': + p = pop(); + EMPTY; + q = scalint(p); + fsfile(q); + c = 0; + if((sfbeg(q) == 0) && ((c = sbackc(q))<0)){ + error("neg index\n"); + } + if(length(q)>2){ + error("index too big\n"); + } + if(sfbeg(q) == 0)c = c*100+sbackc(q); + if(c >= BC_DIM_MAX){ + error("index too big\n"); + } + release(q); + n = readc() & 0377; + sptr = stable[n]; + if(sptr != 0){ + p = sptr->val; + if(length(p)-PTRSZ >= c*PTRSZ){ + seekc(p,c*PTRSZ); + s = dcgetwd(p); + if(s != 0){ + q = copy(s,length(s)); + pushp(q); + continue; + } + } + } + q = salloc(1); + sputc(q, 0); + pushp(q); + continue; + case 'x': +execute: + p = pop(); + EMPTY; + if((readptr != &readstk[0]) && (*readptr != 0)){ + if((*readptr)->rd == (*readptr)->wt) + release(*readptr); + else{ + if(readptr++ == &readstk[RDSKSZ]){ + error("nesting depth\n"); + } + } + } + else readptr++; + *readptr = p; + if(p != 0)rewind(p); + else{ + if((c = readc()) != '\n')unreadc(c); + } + continue; + case '?': + if(++readptr == &readstk[RDSKSZ]){ + error("nesting depth\n"); + } + *readptr = 0; + fsave = curfile; + curfile = stdin; + while((c = readc()) == '!')command(); + p = salloc(0); + sputc(p,c); + while((c = readc()) != '\n'){ + sputc(p,c); + if(c == '\\')sputc(p,readc()); + } + curfile = fsave; + *readptr = p; + continue; + case '!': + if(command() == 1)goto execute; + continue; + case '<': + case '>': + case '=': + if(cond(c) == 1)goto execute; + continue; + default: + printf("%o is unimplemented\n",c); + } + } +} + +struct blk * +div(struct blk *ddivd,struct blk *ddivr) +{ + int divsign,remsign,offset,divcarry = 0; + int carry, dig = 0,magic,d = 0,dd; + long c,td,cc; + struct blk *ps; + register struct blk *p,*divd,*divr; + + rem = 0; + p = salloc(0); + if(length(ddivr) == 0){ + pushp(ddivr); + printf("divide by 0\n"); + return NULL; + } + divsign = remsign = 0; + divr = ddivr; + fsfile(divr); + if(sbackc(divr) == -1){ + divr = copy(ddivr,length(ddivr)); + chsign(divr); + divsign = ~divsign; + } + divd = copy(ddivd,length(ddivd)); + fsfile(divd); + if(sfbeg(divd) == 0 && sbackc(divd) == -1){ + chsign(divd); + divsign = ~divsign; + remsign = ~remsign; + } + offset = length(divd) - length(divr); + if(offset < 0)goto ddone; + seekc(p,offset+1); + sputc(divd,0); + magic = 0; + fsfile(divr); + c = sbackc(divr); + if(c<10)magic++; + c = c*100 + (sfbeg(divr)?0:sbackc(divr)); + if(magic>0){ + c = (c*100 +(sfbeg(divr)?0:sbackc(divr)))*2; + c /= 25; + } + while(offset >= 0){ + fsfile(divd); + td = sbackc(divd)*100; + dd = sfbeg(divd)?0:sbackc(divd); + td = (td+dd)*100; + dd = sfbeg(divd)?0:sbackc(divd); + td = td+dd; + cc = c; + if(offset == 0)td += 1; + else cc += 1; + if(magic != 0)td = td<<3; + dig = td/cc; + rewind(divr); + rewind(divxyz); + carry = 0; + while(sfeof(divr) == 0){ + d = sgetc(divr)*dig+carry; + carry = d / 100; + salterc(divxyz,d%100); + } + salterc(divxyz,carry); + rewind(divxyz); + seekc(divd,offset); + carry = 0; + while(sfeof(divd) == 0){ + d = slookc(divd); + d = d-(sfeof(divxyz)?0:sgetc(divxyz))-carry; + carry = 0; + if(d < 0){ + d += 100; + carry = 1; + } + salterc(divd,d); + } + divcarry = carry; + sbackc(p); + salterc(p,dig); + sbackc(p); + if(--offset >= 0){ + if(d > 0){ + sbackc(divd); + dd=sbackc(divd); + salterc(divd,dd+100); + } + divd->wt--; + } + } + if(divcarry != 0){ + salterc(p,dig-1); + salterc(divd,-1); + ps = add(divr,divd); + release(divd); + divd = ps; + } + + rewind(p); + divcarry = 0; + while(sfeof(p) == 0){ + d = slookc(p)+divcarry; + divcarry = 0; + if(d >= 100){ + d -= 100; + divcarry = 1; + } + salterc(p,d); + } + if(divcarry != 0)salterc(p,divcarry); + fsfile(p); + while(sfbeg(p) == 0){ + if(sbackc(p) == 0)truncate(p); + else break; + } + if(divsign < 0)chsign(p); + fsfile(divd); + while(sfbeg(divd) == 0){ + if(sbackc(divd) == 0)truncate(divd); + else break; + } +ddone: + if(remsign<0)chsign(divd); + if(divr != ddivr)release(divr); + rem = divd; + return(p); +} + +int +dscale(void){ + register struct blk *dd,*dr; + register struct blk *r; + int c; + + dr = pop(); + EMPTYS; + dd = pop(); + EMPTYSR(dr); + fsfile(dd); + skd = sunputc(dd); + fsfile(dr); + skr = sunputc(dr); + if(sfbeg(dr) == 1 || (sfbeg(dr) == 0 && sbackc(dr) == 0)){ + sputc(dr,skr); + pushp(dr); + errorrt("divide by 0\n"); + } + c = k-skd+skr; + if(c < 0)r = removr(dd,-c); + else { + r = add0(dd,c); + irem = 0; + } + arg1 = r; + arg2 = dr; + savk = k; + return(0); +} + +struct blk * +removr(struct blk *p,int n) +{ + int nn; + register struct blk *q,*s,*r; + + rewind(p); + nn = (n+1)/2; + q = salloc(nn); + while(n>1){ + sputc(q,sgetc(p)); + n -= 2; + } + r = salloc(2); + while(sfeof(p) == 0)sputc(r,sgetc(p)); + release(p); + if(n == 1){ + s = dcdiv(r,tenptr); + release(r); + rewind(rem); + if(sfeof(rem) == 0)sputc(q,sgetc(rem)); + release(rem); + irem = q; + return(s); + } + irem = q; + return(r); +} + +struct blk * +sqrt(struct blk *p) +{ + struct blk *t; + struct blk *r,*q,*s; + int c,n,nn; + + n = length(p); + fsfile(p); + c = sbackc(p); + if((n&1) != 1)c = c*100+(sfbeg(p)?0:sbackc(p)); + n = (n+1)>>1; + r = salloc(n); + zero(r); + seekc(r,n); + nn=1; + while((c -= nn)>=0)nn+=2; + c=(nn+1)>>1; + fsfile(r); + sbackc(r); + if(c>=100){ + c -= 100; + salterc(r,c); + sputc(r,1); + } + else salterc(r,c); + while(1){ + q = dcdiv(p,r); + s = add(q,r); + release(q); + release(rem); + q = dcdiv(s,sqtemp); + release(s); + release(rem); + s = copy(r,length(r)); + chsign(s); + t = add(s,q); + release(s); + fsfile(t); + nn = sfbeg(t)?0:sbackc(t); + if(nn>=0)break; + release(r); + release(t); + r = q; + } + release(t); + release(q); + release(p); + return(r); +} + +struct blk * +exp(struct blk *base,struct blk *ex) +{ + register struct blk *r,*e,*p; + struct blk *e1,*t,*cp; + int temp,c,n; + r = salloc(1); + sputc(r,1); + p = copy(base,length(base)); + e = copy(ex,length(ex)); + fsfile(e); + if(sfbeg(e) != 0)goto edone; + temp=0; + c = sbackc(e); + if(c<0){ + temp++; + chsign(e); + } + while(length(e) != 0){ + e1=dcdiv(e,sqtemp); + release(e); + e = e1; + n = length(rem); + release(rem); + if(n != 0){ + e1=mult(p,r); + release(r); + r = e1; + } + t = copy(p,length(p)); + cp = mult(p,t); + release(p); + release(t); + p = cp; + } + if(temp != 0){ + if((c = length(base)) == 0){ + goto edone; + } + if(c>1)create(r); + else{ + rewind(base); + if((c = sgetc(base))<=1){ + create(r); + sputc(r,c); + } + else create(r); + } + } +edone: + release(p); + release(e); + return(r); +} + +void +init(int argc,char **argv) +{ + register struct sym *sp; + + if (sigset(SIGINT, SIG_IGN) != SIG_IGN) + sigset(SIGINT,onintr); + setbuf(stdout,(char *)NULL); + svargc = --argc; + svargv = argv; + while(svargc>0 && svargv[1][0] == '-'){ + switch(svargv[1][1]){ + default: + dbg=1; + } + svargc--; + svargv++; + } + ifile=1; + if(svargc<=0)curfile = stdin; + else if((curfile = fopen(svargv[1],"r")) == NULL){ + printf("can't open file %s\n",svargv[1]); + exit(1); + } + scalptr = salloc(1); + sputc(scalptr,0); + basptr = salloc(1); + sputc(basptr,10); + obase=10; + log_10=log_2(10L); + ll=68; + fw=1; + fw1=0; + tenptr = salloc(1); + sputc(tenptr,10); + obase=10; + inbas = salloc(1); + sputc(inbas,10); + sqtemp = salloc(1); + sputc(sqtemp,2); + chptr = salloc(0); + strptr = salloc(0); + divxyz = salloc(0); + stkbeg = stkptr = &stack[0]; + stkend = &stack[STKSZ]; + stkerr = 0; + readptr = &readstk[0]; + k=0; + sp = sptr = &symlst[0]; + while(sptr < &symlst[TBLSZ]){ + sptr->next = ++sp; + sptr++; + } + sptr->next=0; + sfree = &symlst[0]; + return; +} + +void +onintr(int signum){ + + sigset(SIGINT,onintr); + while(readptr != &readstk[0]){ + if(*readptr != 0){release(*readptr);} + readptr--; + } + curfile = stdin; + commnds(); +} + +void +pushp(struct blk *p) +{ + if(stkptr == stkend){ + printf("out of stack space\n"); + return; + } + stkerr=0; + *++stkptr = p; + return; +} + +struct blk * +pop(void){ + if(stkptr == stack){ + stkerr=1; + return(0); + } + return(*stkptr--); +} + +struct blk * +readin(void){ + register struct blk *p,*q; + int dp,dpct; + register int c; + + dp = dpct=0; + p = salloc(0); + while(1){ + c = readc(); + switch(c){ + case '.': + if(dp != 0){ + unreadc(c); + break; + } + dp++; + continue; + case '\\': + readc(); + continue; + default: + if(c >= 'A' && c <= 'F')c = c - 'A' + 10; + else if(c >= '0' && c <= '9')c -= '0'; + else goto gotnum; + if(dp != 0){ + if(dpct >= 99)continue; + dpct++; + } + create(chptr); + if(c != 0)sputc(chptr,c); + q = mult(p,inbas); + release(p); + p = add(chptr,q); + release(q); + } + } +gotnum: + unreadc(c); + if(dp == 0){ + sputc(p,0); + return(p); + } + else{ + q = scale(p,dpct); + return(q); + } +} + +struct blk * +add0(struct blk *p,int ct) +{ + /* returns pointer to struct with ct 0's & p */ + register struct blk *q,*t; + + q = salloc(length(p)+(ct+1)/2); + while(ct>1){ + sputc(q,0); + ct -= 2; + } + rewind(p); + while(sfeof(p) == 0){ + sputc(q,sgetc(p)); + } + release(p); + if(ct == 1){ + t = mult(tenptr,q); + release(q); + return(t); + } + return(q); +} + +struct blk * +mult(struct blk *p,struct blk *q) +{ + register struct blk *mp,*mq,*mr; + int sign,offset,carry; + int cq,cp,mt,mcr; + + offset = sign = 0; + fsfile(p); + mp = p; + if(sfbeg(p) == 0){ + if(sbackc(p)<0){ + mp = copy(p,length(p)); + chsign(mp); + sign = ~sign; + } + } + fsfile(q); + mq = q; + if(sfbeg(q) == 0){ + if(sbackc(q)<0){ + mq = copy(q,length(q)); + chsign(mq); + sign = ~sign; + } + } + mr = salloc(length(mp)+length(mq)); + zero(mr); + rewind(mq); + while(sfeof(mq) == 0){ + cq = sgetc(mq); + rewind(mp); + rewind(mr); + mr->rd += offset; + carry=0; + while(sfeof(mp) == 0){ + cp = sgetc(mp); + mcr = sfeof(mr)?0:slookc(mr); + mt = cp*cq + carry + mcr; + carry = mt/100; + salterc(mr,mt%100); + } + offset++; + if(carry != 0){ + mcr = sfeof(mr)?0:slookc(mr); + salterc(mr,mcr+carry); + } + } + if(sign < 0){ + chsign(mr); + } + if(mp != p)release(mp); + if(mq != q)release(mq); + return(mr); +} + +void +chsign(struct blk *p) +{ + register int carry; + register char ct; + + carry=0; + rewind(p); + while(sfeof(p) == 0){ + ct=100-slookc(p)-carry; + carry=1; + if(ct>=100){ + ct -= 100; + carry=0; + } + salterc(p,ct); + } + if(carry != 0){ + sputc(p,-1); + fsfile(p); + sbackc(p); + ct = sbackc(p); + if(ct == 99){ + truncate(p); + sputc(p,-1); + } + } + else{ + fsfile(p); + ct = sbackc(p); + if(ct == 0)truncate(p); + } + return; +} + +int +readc(void){ +loop: + if((readptr != &readstk[0]) && (*readptr != 0)){ + if(sfeof(*readptr) == 0)return(lastchar = sgetc(*readptr)); + release(*readptr); + readptr--; + goto loop; + } + lastchar = getc(curfile); + if(lastchar != EOF)return(lastchar); + if(readptr != &readptr[0]){ + readptr--; + if(*readptr == 0)curfile = stdin; + goto loop; + } + if(curfile != stdin){ + fclose(curfile); + curfile = stdin; + goto loop; + } + exit(0); +} + +void +unreadc(char c) +{ + + if((readptr != &readstk[0]) && (*readptr != 0)){ + sungetc(*readptr,c); + } + else ungetc(c,curfile); + return; +} + +void +binop(char c) +{ + register struct blk *r = NULL; + + switch(c){ + case '+': + r = add(arg1,arg2); + break; + case '*': + r = mult(arg1,arg2); + break; + case '/': + r = dcdiv(arg1,arg2); + break; + } + release(arg1); + release(arg2); + sputc(r,savk); + pushp(r); + return; +} + +void +print(struct blk *hptr) +{ + int sc; + register struct blk *p,*q,*dec; + int dig,dout,ct; + + rewind(hptr); + while(sfeof(hptr) == 0){ + if(sgetc(hptr)>99){ + rewind(hptr); + while(sfeof(hptr) == 0){ + printf("%c",sgetc(hptr)); + } + printf("\n"); + return; + } + } + fsfile(hptr); + sc = sbackc(hptr); + if(sfbeg(hptr) != 0){ + printf("0\n"); + return; + } + count = ll; + p = copy(hptr,length(hptr)); + sunputc(p); + fsfile(p); + if(sbackc(p)<0){ + chsign(p); + OUTC('-'); + } + if((obase == 0) || (obase == -1)){ + oneot(p,sc,'d'); + return; + } + if(obase == 1){ + oneot(p,sc,'1'); + return; + } + if(obase == 10){ + tenot(p,sc); + return; + } + create(strptr); + dig = log_10*sc; + dout = ((dig/10) + dig) /logo; + dec = getdec(p,sc); + p = removc(p,sc); + while(length(p) != 0){ + q = dcdiv(p,basptr); + release(p); + p = q; + (*outdit)(rem,0,1); + } + release(p); + fsfile(strptr); + while(sfbeg(strptr) == 0)OUTC(sbackc(strptr)); + if(sc == 0){ + release(dec); + printf("\n"); + return; + } + create(strptr); + OUTC('.'); + ct=0; + do{ + q = mult(basptr,dec); + release(dec); + dec = getdec(q,sc); + p = removc(q,sc); + (*outdit)(p,1,ct+1= 1){ + sputc(q,sgetc(p)); + sc -= 2; + } + if(sc != 0){ + t = mult(q,tenptr); + s = salloc(cc = length(q)); + release(q); + rewind(t); + while(cc-- > 0)sputc(s,sgetc(t)); + sputc(s,0); + release(t); + t = dcdiv(s,tenptr); + release(s); + release(rem); + return(t); + } + return(q); +} + +void +tenot(struct blk *p,int sc) +{ + register int c,f; + char b[3]; + + fsfile(p); + f=0; + while((sfbeg(p) == 0) && ((p->rd-p->beg-1)*2 >= sc)){ + c = sbackc(p); + if((c<10) && (f == 1))snprintf(b, sizeof b, "0%d",c); + else snprintf(b, sizeof b, "%d",c); + f=1; + TEST2(b); + } + if(sc == 0){ + printf("\n"); + release(p); + return; + } + if((p->rd-p->beg)*2 > sc){ + c = sbackc(p); + snprintf(b, sizeof b, "%d.",c/10); + TEST2(b); + OUTC(c%10 +'0'); + sc--; + } + else { + OUTC('.'); + } + if(sc > (p->rd-p->beg)*2){ + while(sc>(p->rd-p->beg)*2){ + OUTC('0'); + sc--; + } + } + while(sc > 1){ + c = sbackc(p); + if(c<10)snprintf(b, sizeof b, "0%d",c); + else snprintf(b, sizeof b, "%d",c); + sc -= 2; + TEST2(b); + } + if(sc == 1){ + OUTC(sbackc(p)/10 +'0'); + } + printf("\n"); + release(p); + return; +} + +void +oneot(struct blk *p,int sc,char ch) +{ + register struct blk *q; + + q = removc(p,sc); + create(strptr); + sputc(strptr,-1); + while(length(q)>0){ + p = add(strptr,q); + release(q); + q = p; + OUTC(ch); + } + release(q); + printf("\n"); + return; +} + +void +hexot(struct blk *p,int flg,int unused) +{ + register int c; + rewind(p); + if(sfeof(p) != 0){ + sputc(strptr,'0'); + release(p); + return; + } + c = sgetc(p); + release(p); + if(c >= 16){ + printf("hex digit > 16"); + return; + } + sputc(strptr,c<10?c+'0':c-10+'A'); + return; +} + +void +bigot(struct blk *p,int flg,int putspc) +{ + register struct blk *t,*q; + register int l = 0; + int neg; + + if(flg == 1)t = salloc(0); + else{ + t = strptr; + l = length(strptr)+fw-1; + } + neg=0; + if(length(p) != 0){ + fsfile(p); + if(sbackc(p)<0){ + neg=1; + chsign(p); + } + while(length(p) != 0){ + q = dcdiv(p,tenptr); + release(p); + p = q; + rewind(rem); + sputc(t,sfeof(rem)?'0':sgetc(rem)+'0'); + release(rem); + } + } + release(p); + if(flg == 1){ + l = fw1-length(t); + if(neg != 0){ + l--; + sputc(strptr,'-'); + } + fsfile(t); + while(l-- > 0)sputc(strptr,'0'); + while(sfbeg(t) == 0)sputc(strptr,sbackc(t)); + release(t); + } + else{ + l -= length(strptr); + while(l-- > 0)sputc(strptr,'0'); + if(neg != 0){ + sunputc(strptr); + sputc(strptr,'-'); + } + } + if (putspc) + sputc(strptr,' '); + return; +} + +struct blk * +add(struct blk *a1,struct blk *a2) +{ + register struct blk *p; + register int carry,n; + int size; + int c = 0,n1,n2; + + size = length(a1)>length(a2)?length(a1):length(a2); + p = salloc(size); + rewind(a1); + rewind(a2); + carry=0; + while(--size >= 0){ + n1 = sfeof(a1)?0:sgetc(a1); + n2 = sfeof(a2)?0:sgetc(a2); + n = n1 + n2 + carry; + if(n>=100){ + carry=1; + n -= 100; + } + else if(n<0){ + carry = -1; + n += 100; + } + else carry = 0; + sputc(p,n); + } + if(carry != 0)sputc(p,carry); + fsfile(p); + if(sfbeg(p) == 0){ + while(sfbeg(p) == 0 && (c = sbackc(p)) == 0); + if(c != 0)salterc(p,c); + truncate(p); + } + fsfile(p); + if(sfbeg(p) == 0 && sbackc(p) == -1){ + while((c = sbackc(p)) == 99){ + if(c == EOF)break; + } + sgetc(p); + salterc(p,-1); + truncate(p); + } + return(p); +} + +int +eqk(void){ + register struct blk *p,*q; + register int skp; + int skq; + + p = pop(); + EMPTYS; + q = pop(); + EMPTYSR(p); + skp = sunputc(p); + skq = sunputc(q); + if(skp == skq){ + arg1=p; + arg2=q; + savk = skp; + return(0); + } + else if(skp < skq){ + savk = skq; + p = add0(p,skq-skp); + } + else { + savk = skp; + q = add0(q,skp-skq); + } + arg1=p; + arg2=q; + return(0); +} + +struct blk * +removc(struct blk *p,int n) +{ + register struct blk *q,*r; + + rewind(p); + while(n>1){ + sgetc(p); + n -= 2; + } + q = salloc(2); + while(sfeof(p) == 0)sputc(q,sgetc(p)); + if(n == 1){ + r = dcdiv(q,tenptr); + release(q); + release(rem); + q = r; + } + release(p); + return(q); +} + +struct blk * +scalint(struct blk *p) +{ + register int n; + n = sunputc(p); + p = removc(p,n); + return(p); +} + +struct blk * +scale(struct blk *p,int n) +{ + register struct blk *q,*s,*t; + + t = add0(p,n); + q = salloc(1); + sputc(q,n); + s = dcexp(inbas,q); + release(q); + q = dcdiv(t,s); + release(t); + release(s); + release(rem); + sputc(q,n); + return(q); +} + +int +subt(void){ + arg1=pop(); + EMPTYS; + savk = sunputc(arg1); + chsign(arg1); + sputc(arg1,savk); + pushp(arg1); + if(eqk() != 0)return(1); + binop('+'); + return(0); +} + +int +command(void){ + int c; + static char *line; + static int linesize; + char *sl; + register void (*savint)(int); + register int pid,rpid; + int retcode; + + switch(c = readc()){ + case '<': + return(cond(NL)); + case '>': + return(cond(NG)); + case '=': + return(cond(NE)); + default: + if (line == 0) + line = srealloc(0, linesize = 10); + sl = line; + *sl++ = c; + while((c = readc()) != '\n') { + if (sl >= &line[linesize-2]) { + int diff = sl - line; + line = srealloc(line, linesize += 10); + sl = &line[diff]; + } + *sl++ = c; + } + *sl = 0; + if((pid = fork()) == 0){ + execl(SHELL,"sh","-c",line,NULL); + exit(0100); + } + savint = sigset(SIGINT, SIG_IGN); + while((rpid = wait(&retcode)) != pid && rpid != -1); + sigset(SIGINT,savint); + printf("!\n"); + return(0); + } +} + +int +cond(char c) +{ + register struct blk *p; + register int cc; + + if(subt() != 0)return(1); + p = pop(); + sunputc(p); + if(length(p) == 0){ + release(p); + if(c == '<' || c == '>' || c == NE){ + readc(); + return(0); + } + load(); + return(1); + } + else { + if(c == '='){ + release(p); + readc(); + return(0); + } + } + if(c == NE){ + release(p); + load(); + return(1); + } + fsfile(p); + cc = sbackc(p); + release(p); + if((cc<0 && (c == '<' || c == NG)) || + (cc >0) && (c == '>' || c == NL)){ + readc(); + return(0); + } + load(); + return(1); +} + +void +load(void){ + register int c; + register struct blk *p,*q; + struct blk *t,*s; + c = readc() & 0377; + sptr = stable[c]; + if(sptr != 0){ + p = sptr->val; + if(c >= ARRAYST){ + q = salloc(length(p)); + rewind(p); + while(sfeof(p) == 0){ + s = dcgetwd(p); + if(s == 0){putwd(q, (struct blk *)NULL);} + else{ + t = copy(s,length(s)); + putwd(q,t); + } + } + pushp(q); + } + else{ + q = copy(p,length(p)); + pushp(q); + } + } + else{ + q = salloc(1); + sputc(q,0); + pushp(q); + } + return; +} + +int +log_2(long n) +{ + register int i; + + if(n == 0)return(0); + i=31; + if(n<0)return(i); + while((n= n<<1) >0)i--; + return(--i); +} + +struct blk * +salloc(int size) +{ + register struct blk *hdr; + register char *ptr; + all++; + nbytes += size; + ptr = malloc((unsigned)(size?size:1)); + if(ptr == 0){ + garbage("salloc"); + if((ptr = malloc((unsigned)(size?size:1))) == 0) + ospace("salloc"); + } + if((hdr = hfree) == 0)hdr = morehd(); + hfree = (struct blk *)hdr->rd; + hdr->rd = hdr->wt = hdr->beg = ptr; + hdr->last = ptr+size; + return(hdr); +} + +struct blk * +morehd(void){ + register struct blk *h,*kk; + headmor++; + nbytes += HEADSZ; + hfree = h = (struct blk *)malloc(HEADSZ); + if(hfree == 0){ + garbage("morehd"); + if((hfree = h = (struct blk *)malloc(HEADSZ)) == 0) + ospace("headers"); + } + kk = h; + while(hrd = (char *)++kk; + (--h)->rd=0; + return(hfree); +} + +/* +sunputc(struct blk *hptr) +{ + hptr->wt--; + hptr->rd = hptr->wt; + return(*hptr->wt); +} +*/ + +struct blk * +copy(struct blk *hptr,int size) +{ + register struct blk *hdr; + register unsigned sz; + register char *ptr; + + all++; + nbytes += size; + sz = length(hptr); + ptr = nalloc(hptr->beg, (unsigned)size); + if(ptr == 0){ + garbage("copy"); + if((ptr = nalloc(hptr->beg, (unsigned)size)) == NULL){ + printf("copy size %d\n",size); + ospace("copy"); + } + } + if((hdr = hfree) == 0)hdr = morehd(); + hfree = (struct blk *)hdr->rd; + hdr->rd = hdr->beg = ptr; + hdr->last = ptr+size; + hdr->wt = ptr+sz; + ptr = hdr->wt; + while(ptrlast)*ptr++ = '\0'; + return(hdr); +} + +void +sdump(char *s1,struct blk *hptr) +{ + char *p; + printf("%s %lo rd %lo wt %lo beg %lo last %lo\n", s1, + (long)(intptr_t)hptr, + (long)(intptr_t)hptr->rd, + (long)(intptr_t)hptr->wt, + (long)(intptr_t)hptr->beg, + (long)(intptr_t)hptr->last); + p = hptr->beg; + while(p < hptr->wt)printf("%d ",*p++); + printf("\n"); +} + +void +seekc(struct blk *hptr,int n) +{ + register char *nn,*p; + + nn = hptr->beg+n; + if(nn > hptr->last){ + nbytes += nn - hptr->last; + /*free(hptr->beg);*/ + p = realloc(hptr->beg, (unsigned)n); + if(p == 0){ + hptr->beg = realloc(hptr->beg, (unsigned)(hptr->last-hptr->beg)); + garbage("seekc"); + if((p = realloc(hptr->beg, (unsigned)n)) == 0) + ospace("seekc"); + } + hptr->beg = p; + hptr->wt = hptr->last = hptr->rd = p+n; + return; + } + hptr->rd = nn; + if(nn>hptr->wt)hptr->wt = nn; + return; +} + +void +salterwd(struct wblk *hptr,struct blk *n) +{ + if(hptr->rdw == hptr->lastw)more((struct blk *)hptr); + *hptr->rdw++ = n; + if(hptr->rdw > hptr->wtw)hptr->wtw = hptr->rdw; + return; +} + +void +more(struct blk *hptr) +{ + register unsigned size; + register char *p; + + if((size=(hptr->last-hptr->beg)*2) == 0)size=1; + nbytes += size/2; + /*free(hptr->beg);*/ + p = realloc(hptr->beg, (unsigned)size); + if(p == 0){ + hptr->beg = realloc(hptr->beg, (unsigned)(hptr->last-hptr->beg)); + garbage("more"); + if((p = realloc(hptr->beg,size)) == 0) + ospace("more"); + } + hptr->rd = hptr->rd-hptr->beg+p; + hptr->wt = hptr->wt-hptr->beg+p; + hptr->beg = p; + hptr->last = p+size; + return; +} + +void +ospace(char *s) +{ + printf("out of space: %s\n",s); + printf("all %ld rel %ld headmor %ld\n",all,rel,headmor); + printf("nbytes %ld\n",nbytes); + sdump("stk",*stkptr); + abort(); +} + +void +garbage(char *s) +{ + int i; + struct blk *p, *q; + struct sym *tmps; + int ct; + +/* printf("got to garbage %s\n",s); */ + for(i=0;ival; + if(((intptr_t)p->beg & 01) != 0){ + printf("string %o\n",i); + sdump("odd beg",p); + } + redef(p); + tmps = tmps->next; + } while(tmps != 0); + continue; + } + else { + do { + p = tmps->val; + rewind(p); + ct = 0; + while((q = dcgetwd(p)) != NULL){ + ct++; + if(q != 0){ + if(((intptr_t)q->beg & 01) != 0){ + printf("array %o elt %d odd\n",i-ARRAYST,ct); +printf("tmps %lo p %lo\n",(long)(intptr_t)tmps,(long)(intptr_t)p); + sdump("elt",q); + } + redef(q); + } + } + tmps = tmps->next; + } while(tmps != 0); + } + } + } +} + +void +redef(struct blk *p) +{ + register int offset; + register char *newp; + + if ((intptr_t)p->beg&01) { + printf("odd ptr %lo hdr %lo\n",(long)(intptr_t)p->beg, + (long)(intptr_t)p); + ospace("redef-bad"); + } + /*free(p->beg);*/ + newp = realloc(p->beg, (unsigned)(p->last-p->beg)); + if(newp == NULL)ospace("redef"); + offset = newp - p->beg; + p->beg = newp; + p->rd += offset; + p->wt += offset; + p->last += offset; +} + +void +release(register struct blk *p) +{ + rel++; + nbytes -= p->last - p->beg; + p->rd = (char *)hfree; + hfree = p; + free(p->beg); +} + +struct blk * +dcgetwd(struct blk *p) +{ + register struct wblk *wp; + + wp = (struct wblk *)p; + if (wp->rdw == wp->wtw) + return(NULL); + return(*wp->rdw++); +} + +void +putwd(struct blk *p, struct blk *c) +{ + register struct wblk *wp; + + wp = (struct wblk *)p; + if (wp->wtw == wp->lastw) + more(p); + *wp->wtw++ = c; +} + +struct blk * +lookwd(struct blk *p) +{ + register struct wblk *wp; + + wp = (struct wblk *)p; + if (wp->rdw == wp->wtw) + return(NULL); + return(*wp->rdw); +} + +char * +nalloc(register char *p,unsigned nbytes) +{ + register char *q, *r; + q = r = malloc(nbytes ? nbytes : 1); + if(q==0) + return(0); + while(nbytes--) + *q++ = *p++; + return(r); +} + +void * +srealloc(void *op, size_t size) +{ + void *np; + + if ((np = realloc(op, size)) == 0) { + write(2, "no memory\n", 10); + _exit(077); + } + return np; +} diff --git a/dc/dc.h b/dc/dc.h new file mode 100644 index 0000000..bc17d6a --- /dev/null +++ b/dc/dc.h @@ -0,0 +1,203 @@ +/* from Unix 7th Edition /usr/src/cmd/dc/dc.h */ +/* + * 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 @(#)dc.h 1.9 (gritter) 2/4/05> */ + +#include +#include + +#define FATAL 0 +#define NFATAL 1 +#define BLK sizeof(struct blk) +#define PTRSZ sizeof(int *) +#define HEADSZ 1024 +#define STKSZ 100 +#define RDSKSZ 100 +#define TBLSZ 256 +#define ARRAYST 0241 +#define NL 1 +#define NG 2 +#define NE 3 +#define length(p) ((p)->wt-(p)->beg) +#define rewind(p) (p)->rd=(p)->beg +#define create(p) (p)->rd = (p)->wt = (p)->beg +#define fsfile(p) (p)->rd = (p)->wt +#define truncate(p) (p)->wt = (p)->rd +#define sfeof(p) (((p)->rd>=(p)->wt)?1:0) +#define sfbeg(p) (((p)->rd==(p)->beg)?1:0) +#define sungetc(p,c) *(--(p)->rd)=c +#ifdef interdata +#define NEGBYTE 0200 +#define MASK (-1 & ~0377) +#define sgetc(p) ( ((p)->rd==(p)->wt) ? EOF :( ((*(p)->rd & NEGBYTE) != 0) ? ( *(p)->rd++ | MASK): *(p)->rd++ )) +#define slookc(p) ( ((p)->rd==(p)->wt) ? EOF :( ((*(p)->rd & NEGBYTE) != 0) ? (*(p)->rd | MASK) : *(p)->rd )) +#define sbackc(p) ( ((p)->rd==(p)->beg) ? EOF :( ((*(--(p)->rd) & NEGBYTE) != 0) ? (*(p)->rd | MASK): *(p)->rd )) +#endif +#ifndef interdata +#define sgetc(p) (((p)->rd==(p)->wt)?EOF:*(p)->rd++) +#define slookc(p) (((p)->rd==(p)->wt)?EOF:*(p)->rd) +#define sbackc(p) (((p)->rd==(p)->beg)?EOF:*(--(p)->rd)) +#endif +#define sputc(p,c) {if((p)->wt==(p)->last)more(p); *(p)->wt++ = c; } +#define salterc(p,c) {if((p)->rd==(p)->last)more(p); *(p)->rd++ = c; if((p)->rd>(p)->wt)(p)->wt=(p)->rd;} +#define sunputc(p) (*( (p)->rd = --(p)->wt)) +#define zero(p) for(pp=(p)->beg;pp<(p)->last;)*pp++='\0' +#define OUTC(x) {int _c = (x); if (_c) {printf("%c",_c); if(--count == 0){printf("\\\n"); count=ll;} } } +#define TEST2(b) { OUTC(b[0] & 0377); OUTC(b[1] & 0377); } +#define EMPTY if(stkerr != 0){printf("stack empty\n"); continue; } +#define EMPTYR(x) if(stkerr!=0){pushp(x);printf("stack empty\n");continue;} +#define EMPTYS if(stkerr != 0){printf("stack empty\n"); return(1);} +#define EMPTYSR(x) if(stkerr !=0){printf("stack empty\n");pushp(x);return(1);} +#define error(p) {printf(p); continue; } +#define errorrt(p) {printf(p); return(1); } +struct blk { + char *rd; + char *wt; + char *beg; + char *last; +}; +struct blk *hfree; +struct blk *arg1, *arg2; +int svargc; +char savk; +char **svargv; +int dbg; +int ifile; +FILE *curfile; +struct blk *scalptr, *basptr, *tenptr, *inbas; +struct blk *sqtemp, *chptr, *strptr, *divxyz; +struct blk *stack[STKSZ]; +struct blk **stkptr,**stkbeg; +struct blk **stkend; +int stkerr; +int lastchar; +struct blk *readstk[RDSKSZ]; +struct blk **readptr; +struct blk *rem; +int k; +struct blk *irem; +int skd,skr; +int neg; +struct sym { + struct sym *next; + struct blk *val; +} symlst[TBLSZ]; +struct sym *stable[TBLSZ]; +struct sym *sptr,*sfree; +struct wblk { + struct blk **rdw; + struct blk **wtw; + struct blk **begw; + struct blk **lastw; +}; +FILE *fsave; +long rel; +long nbytes; +long all; +long headmor; +long obase; +int fw,fw1,ll; +int (*outdit)(struct blk *, int, int); +int logo; +int log_10; +int count; +char *pp; +char *dummy; + +#define div(a, b) dcdiv(a, b) +#define sqrt(a) dcsqrt(a) +#define exp(a, b) dcexp(a, b) +#define getwd(a) dcgetwd(a) +extern void commnds(void); +extern struct blk *div(struct blk *, struct blk *); +extern int dscale(void); +extern struct blk *removr(struct blk *, int); +extern struct blk *sqrt(struct blk *); +extern struct blk *exp(struct blk *, struct blk *); +extern void init(int, char *[]); +extern void onintr(int); +extern void pushp(struct blk *); +extern struct blk *pop(void); +extern struct blk *readin(void); +extern struct blk *add0(struct blk *, int); +extern struct blk *mult(struct blk *, struct blk *); +extern void chsign(struct blk *); +extern int readc(void); +extern void unreadc(char); +extern void binop(char); +extern void print(struct blk *); +extern struct blk *getdec(struct blk *, int); +extern void tenot(struct blk *, int); +extern void oneot(struct blk *, int, char); +extern void hexot(struct blk *, int, int); +extern void bigot(struct blk *, int, int); +extern struct blk *add(struct blk *, struct blk *); +extern int eqk(void); +extern struct blk *removc(struct blk *, int); +extern struct blk *scalint(struct blk *); +extern struct blk *scale(struct blk *, int); +extern int subt(void); +extern int command(void); +extern int cond(char); +extern void load(void); +extern int log_2(long); +extern struct blk *salloc(int); +extern struct blk *morehd(void); +extern struct blk *copy(struct blk *, int); +extern void sdump(char *, struct blk *); +extern void seekc(struct blk *, int); +extern void salterwd(struct wblk *, struct blk *); +extern void more(struct blk *); +extern void ospace(char *); +extern void garbage(char *); +extern void redef(struct blk *); +extern void release(register struct blk *); +extern struct blk *getwd(struct blk *); +extern void putwd(struct blk *, struct blk *); +extern struct blk *lookwd(struct blk *); +extern char *nalloc(register char *, unsigned); +extern void *srealloc(void *, size_t); + +#if defined (__GLIBC__) && defined (_IO_getc_unlocked) +#undef getc +#define getc(f) _IO_getc_unlocked(f) +#endif + +#ifndef BC_BASE_MAX +#define BC_BASE_MAX 99 +#endif +#ifndef BC_DIM_MAX +#define BC_DIM_MAX 2048 +#endif