/* 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> */ /* Modified by nortti, 2021 */ #define _XOPEN_SOURCE 500 #include #include #include #include #include #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; struct sigaction sa; sigaction(SIGINT, NULL, &sa); if (sa.sa_handler != SIG_IGN){ sa.sa_handler = onintr; sigaction(SIGINT, &sa, NULL); } 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){ 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; struct sigaction sa,savint; 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("/bin/sh","sh","-c",line,NULL); exit(0100); } sa.sa_flags = 0; sigemptyset(&sa.sa_mask); sa.sa_handler = SIG_IGN; sigaction(SIGINT, &sa, &savint); while((rpid = wait(&retcode)) != pid && rpid != -1); sigaction(SIGINT, &savint, NULL); 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; }