6 #pragma varargck type "lx" pointer
10 #define BLK sizeof(Blk)
11 #define PTRSZ sizeof(int*)
12 #define TBLSZ 256 /* 1<<BI2BY */
24 #define length(p) ((p)->wt-(p)->beg)
25 #define rewind(p) (p)->rd=(p)->beg
26 #define create(p) (p)->rd = (p)->wt = (p)->beg
27 #define fsfile(p) (p)->rd = (p)->wt
28 #define truncate(p) (p)->wt = (p)->rd
29 #define sfeof(p) (((p)->rd==(p)->wt)?1:0)
30 #define sfbeg(p) (((p)->rd==(p)->beg)?1:0)
31 #define sungetc(p,c) *(--(p)->rd)=c
32 #define sgetc(p) (((p)->rd==(p)->wt)?-1:*(p)->rd++)
33 #define skipc(p) {if((p)->rd<(p)->wt)(p)->rd++;}
34 #define slookc(p) (((p)->rd==(p)->wt)?-1:*(p)->rd)
35 #define sbackc(p) (((p)->rd==(p)->beg)?-1:*(--(p)->rd))
36 #define backc(p) {if((p)->rd>(p)->beg) --(p)->rd;}
37 #define sputc(p,c) {if((p)->wt==(p)->last)more(p);\
39 #define salterc(p,c) {if((p)->rd==(p)->last)more(p);\
41 if((p)->rd>(p)->wt)(p)->wt=(p)->rd;}
42 #define sunputc(p) (*((p)->rd = --(p)->wt))
43 #define sclobber(p) ((p)->rd = --(p)->wt)
44 #define zero(p) for(pp=(p)->beg;pp<(p)->last;)\
46 #define OUTC(x) {Bputc(&bout,x); if(--count == 0){Bprint(&bout,"\\\n"); count=ll;} }
47 #define TEST2 {if((count -= 2) <=0){Bprint(&bout,"\\\n");count=ll;}}
48 #define EMPTY if(stkerr != 0){Bprint(&bout,"stack empty\n"); continue; }
49 #define EMPTYR(x) if(stkerr!=0){pushp(x);Bprint(&bout,"stack empty\n");continue;}
50 #define EMPTYS if(stkerr != 0){Bprint(&bout,"stack empty\n"); return(1);}
51 #define EMPTYSR(x) if(stkerr !=0){Bprint(&bout,"stack empty\n");pushp(x);return(1);}
52 #define error(p) {Bprint(&bout,p); continue; }
53 #define errorrt(p) {Bprint(&bout,p); return(1); }
57 typedef struct Blk Blk;
65 typedef struct Sym Sym;
71 typedef struct Wblk Wblk;
80 Biobuf *curfile, *fsave;
85 Blk *scalptr, *basptr, *tenptr, *inbas;
86 Blk *sqtemp, *chptr, *strptr, *divxyz;
88 Blk **stkptr,**stkbeg;
109 void (*outdit)(Blk *p, int flg);
115 long longest, maxsize, active;
116 int lall, lrel, lcopy, lmore, lbytes;
121 void main(int argc, char *argv[]);
124 Blk* div(Blk *ddivd, Blk *ddivr);
126 Blk* removr(Blk *p, int n);
128 void init(int argc, char *argv[]);
133 Blk* add0(Blk *p, int ct);
134 Blk* mult(Blk *p, Blk *q);
137 void unreadc(char c);
139 void dcprint(Blk *hptr);
140 Blk* dcexp(Blk *base, Blk *ex);
141 Blk* getdec(Blk *p, int sc);
142 void tenot(Blk *p, int sc);
143 void oneot(Blk *p, int sc, char ch);
144 void hexot(Blk *p, int flg);
145 void bigot(Blk *p, int flg);
146 Blk* add(Blk *a1, Blk *a2);
148 Blk* removc(Blk *p, int n);
149 Blk* scalint(Blk *p);
150 Blk* scale(Blk *p, int n);
156 Blk* salloc(int size);
158 Blk* copy(Blk *hptr, int size);
159 void sdump(char *s1, Blk *hptr);
160 void seekc(Blk *hptr, int n);
161 void salterwd(Blk *hptr, Blk *n);
162 void more(Blk *hptr);
163 void ospace(char *s);
164 void garbage(char *s);
165 void release(Blk *p);
166 Blk* dcgetwd(Blk *p);
167 void putwd(Blk *p, Blk *c);
171 /********debug only**/
173 tpr(char *cp, Blk *bp)
176 print("beg: %lx rd: %lx wt: %lx last: %lx\n", bp->beg, bp->rd,
178 for (cp = bp->beg; cp != bp->wt; cp++) {
188 main(int argc, char *argv[])
190 Binit(&bin, 0, OREAD);
191 Binit(&bout, 1, OWRITE);
200 Blk *p, *q, **ptr, *s, *t;
203 int sk, sk1, sk2, c, sign, n, d;
207 if(((c = readc())>='0' && c <= '9') ||
208 (c>='A' && c <='F') || c == '.') {
221 sdump("stk",*stkptr);
222 Bprint(&bout, "all %ld rel %ld headmor %ld\n",all,rel,headmor);
223 Bprint(&bout, "nbytes %ld\n",nbytes);
224 Bprint(&bout, "longest %ld active %ld maxsize %ld\n", longest,
226 Bprint(&bout, "new all %d rel %d copy %d more %d lbytes %d\n",
227 lall, lrel, lcopy, lmore, lbytes);
228 lall = lrel = lcopy = lmore = lbytes = 0;
255 if(savk>k && savk>sk1 && savk>sk2) {
262 p = removc(p,savk-sk);
288 p = add0(rem,skd-(skr+k));
305 error("sqrt of neg number\n");
323 if(sunputc(arg1) != 0)
324 error("exp not an integer\n");
327 if(sfbeg(arg1) == 0 && sbackc(arg1)<0) {
331 if(length(arg1)>=5) {
332 error("exp too big\n");
334 savk = sunputc(arg2);
335 p = dcexp(arg2,arg1);
343 c = sgetc(arg1)*100 + c;
346 /* if(neg == 0) { removed to fix -exp bug*/
359 /* } else { this is disaster for exp <-127 */
386 n = (length(p)-1)<<1;
390 if((c = sbackc(p))<0) {
395 if((c = sbackc(p)) == 0)
423 p = copy(inbas,length(inbas)+1);
456 if(n == 1 && sign == 0) {
487 p = copy(basptr,length(basptr)+1);
495 if((c = readc()) == ']') {
511 error("scale too big\n");
521 p = copy(scalptr,length(scalptr)+1);
543 if((c = sgetc(p))<0) {
548 if(readptr == &readstk[0]) {
557 if(readptr <= &readstk[1])
567 if(stkptr == &stack[0])
568 Bprint(&bout,"empty stack\n");
570 for(ptr = stkptr; ptr > &stack[0];) {
576 if(stkptr == &stack[0])
577 Bprint(&bout,"empty stack\n");
586 Bprint(&bout,"%s",p->beg);
590 if(stkptr == &stack[0]) {
591 Bprint(&bout,"empty stack\n");
607 if(stkptr == &stack[0]) {
608 error("save: args\n");
612 sp = stable[c] = sfree;
620 q = copy(p,length(p)+PTRSZ);
621 for(n = 0;n < PTRSZ;n++) {
630 error("symbol table overflow\n");
632 if(stkptr == &stack[0]) {
633 error("save:args\n");
641 while(sfeof(p) == 0) {
649 sptr = stable[c] = sfree;
667 stable[c] = sptr->next;
673 while(sfeof(p) == 0) {
687 if((sfbeg(q) == 0) && ((c = sbackc(q))<0)) {
688 error("neg index\n");
691 error("index too big\n");
696 error("index too big\n");
702 sptr = stable[n] = sfree;
707 p = salloc((c+PTRSZ)*PTRSZ);
711 if(length(p)-PTRSZ < c*PTRSZ) {
712 q = copy(p,(c+PTRSZ)*PTRSZ);
732 if((sfbeg(q) == 0) && ((c = sbackc(q))<0)) {
733 error("neg index\n");
736 error("index too big\n");
741 error("index too big\n");
748 if(length(p)-PTRSZ >= c*PTRSZ) {
752 q = copy(s,length(s));
758 q = salloc(1); /*so uninitialized array elt prints as 0*/
766 if((readptr != &readstk[0]) && (*readptr != 0)) {
767 if((*readptr)->rd == (*readptr)->wt)
770 if(readptr++ == &readstk[RDSKSZ]) {
771 error("nesting depth\n");
780 if((c = readc()) != '\n')
785 if(++readptr == &readstk[RDSKSZ]) {
786 error("nesting depth\n");
791 while((c = readc()) == '!')
795 while((c = readc()) != '\n') {
814 Bprint(&bout,"%o is unimplemented\n",c);
820 div(Blk *ddivd, Blk *ddivr)
822 int divsign, remsign, offset, divcarry,
823 carry, dig, magic, d, dd, under, first;
825 Blk *ps, *px, *p, *divd, *divr;
832 if(length(ddivr) == 0) {
834 Bprint(&bout,"divide by 0\n");
837 divsign = remsign = first = 0;
840 if(sbackc(divr) == -1) {
841 divr = copy(ddivr,length(ddivr));
845 divd = copy(ddivd,length(ddivd));
847 if(sfbeg(divd) == 0 && sbackc(divd) == -1) {
852 offset = length(divd) - length(divr);
862 c = c * 100 + (sfbeg(divr)?0:sbackc(divr));
864 c = (c * 100 +(sfbeg(divr)?0:sbackc(divr)))*2;
870 td = sbackc(divd) * 100;
871 dd = sfbeg(divd)?0:sbackc(divd);
872 td = (td + dd) * 100;
873 dd = sfbeg(divd)?0:sbackc(divd);
884 if(td%cc < 8 && dig > 0 && magic) {
891 while(sfeof(divr) == 0) {
892 d = sgetc(divr)*dig+carry;
894 salterc(divxyz,d%100);
896 salterc(divxyz,carry);
900 while(sfeof(divd) == 0) {
902 d = d-(sfeof(divxyz)?0:sgetc(divxyz))-carry;
916 if((d != 0) && /*!divcarry*/ (offset != 0)) {
917 d = sbackc(divd) + 100;
923 if(under) { /* undershot last - adjust*/
924 px = copy(divr,length(divr)); /*11/88 don't corrupt ddivr*/
928 if(length(ps) > 0 && sbackc(ps) < 0) {
929 release(ps); /*only adjust in really undershot*/
946 while(sfeof(p) == 0){
947 d = slookc(p)+divcarry;
955 if(divcarry != 0)salterc(p,divcarry);
957 while(sfbeg(p) == 0) {
965 while(sfbeg(divd) == 0) {
966 if(sbackc(divd) != 0)
993 if(sfbeg(dr) == 1 || (sfbeg(dr) == 0 && sbackc(dr) == 0)) {
996 Bprint(&bout,"divide by 0\n");
999 if(sfbeg(dd) == 1 || (sfbeg(dd) == 0 && sbackc(dd) == 0)) {
1018 removr(Blk *p, int n)
1035 while(sfeof(p) == 0)
1043 sputc(q,sgetc(rem));
1074 c = c*100+(sfbeg(p)?0:sbackc(p));
1099 s = copy(r,length(r));
1104 nn = sfbeg(t)?0:sbackc(t);
1118 dcexp(Blk *base, Blk *ex)
1120 Blk *r, *e, *p, *e1, *t, *cp;
1125 p = copy(base,length(base));
1126 e = copy(ex,length(ex));
1136 while(length(e) != 0) {
1147 t = copy(p,length(p));
1154 if((c = length(base)) == 0) {
1161 if((c = sgetc(base))<=1) {
1175 init(int argc, char *argv[])
1190 fprint(2, "dc: can't open file %s\n", *argv);
1193 if(d->mode & DMDIR) {
1194 fprint(2, "dc: file %s is a directory\n", *argv);
1198 if((curfile = Bopen(*argv, OREAD)) == 0) {
1199 fprint(2,"dc: can't open file %s\n", *argv);
1203 /* dummy = malloc(0); /* prepare for garbage-collection */
1204 scalptr = salloc(1);
1223 stkbeg = stkptr = &stack[0];
1224 stkend = &stack[STKSZ-1];
1226 readptr = &readstk[0];
1228 sp = sptr = &symlst[0];
1229 while(sptr < &symlst[TBLSZ-1]) {
1240 if(stkptr == stkend) {
1241 Bprint(&bout,"out of stack space\n");
1252 if(stkptr == stack) {
1279 if(c >= 'A' && c <= 'F')
1282 if(c >= '0' && c <= '9')
1312 * returns pointer to struct with ct 0's & p
1315 add0(Blk *p, int ct)
1319 q = salloc(length(p)+(ct+1)/2);
1325 while(sfeof(p) == 0) {
1338 mult(Blk *p, Blk *q)
1341 int sign, offset, carry;
1342 int cq, cp, mt, mcr;
1349 mp = copy(p,length(p));
1358 mq = copy(q,length(q));
1363 mr = salloc(length(mp)+length(mq));
1366 while(sfeof(mq) == 0) {
1372 while(sfeof(mp) == 0) {
1374 mcr = sfeof(mr)?0:slookc(mr);
1375 mt = cp*cq + carry + mcr;
1381 mcr = sfeof(mr)?0:slookc(mr);
1382 salterc(mr,mcr+carry);
1403 while(sfeof(p) == 0) {
1404 ct=100-slookc(p)-carry;
1417 if(ct == 99 /*&& !sfbeg(p)*/) {
1434 if((readptr != &readstk[0]) && (*readptr != 0)) {
1435 if(sfeof(*readptr) == 0)
1436 return(lastchar = sgetc(*readptr));
1441 lastchar = Bgetc(curfile);
1444 if(readptr != &readptr[0]) {
1450 if(curfile != &bin) {
1456 return 0; /* shut up ken */
1463 if((readptr != &readstk[0]) && (*readptr != 0)) {
1464 sungetc(*readptr,c);
1481 r = mult(arg1,arg2);
1497 int dig, dout, ct, sc;
1500 while(sfeof(hptr) == 0) {
1501 if(sgetc(hptr)>99) {
1503 while(sfeof(hptr) == 0) {
1504 Bprint(&bout,"%c",sgetc(hptr));
1512 if(sfbeg(hptr) != 0) {
1513 Bprint(&bout,"0\n");
1517 p = copy(hptr,length(hptr));
1524 if((obase == 0) || (obase == -1)) {
1536 /* sleazy hack to scale top of stack - divide by 1 */
1546 p = div(arg1, arg2);
1553 dout = ((dig/10) + dig) / logo;
1556 while(length(p) != 0) {
1564 while(sfbeg(strptr) == 0)
1565 OUTC(sbackc(strptr));
1575 q = mult(basptr,dec);
1580 } while(++ct < dout);
1583 while(sfeof(strptr) == 0)
1584 OUTC(sgetc(strptr));
1589 getdec(Blk *p, int sc)
1595 if(length(p)*2 < sc) {
1596 q = copy(p,length(p));
1599 q = salloc(length(p));
1606 s = salloc(cc = length(q));
1622 tenot(Blk *p, int sc)
1628 while((sfbeg(p) == 0) && ((p->rd-p->beg-1)*2 >= sc)) {
1630 if((c<10) && (f == 1))
1631 Bprint(&bout,"0%d",c);
1633 Bprint(&bout,"%d",c);
1642 if((p->rd-p->beg)*2 > sc) {
1644 Bprint(&bout,"%d.",c/10);
1651 while(sc>(p->rd-p->beg)*2) {
1658 Bprint(&bout,"0%d",c);
1660 Bprint(&bout,"%d",c);
1665 OUTC(sbackc(p)/10 +'0');
1672 oneot(Blk *p, int sc, char ch)
1679 while(length(q)>0) {
1690 hexot(Blk *p, int flg)
1704 Bprint(&bout,"hex digit > 16");
1707 sputc(strptr,c<10?c+'0':c-10+'a');
1711 bigot(Blk *p, int flg)
1721 l = length(strptr)+fw-1;
1724 if(length(p) != 0) {
1730 while(length(p) != 0) {
1735 sputc(t,sfeof(rem)?'0':sgetc(rem)+'0');
1749 while(sfbeg(t) == 0)
1750 sputc(strptr,sbackc(t));
1753 l -= length(strptr);
1765 add(Blk *a1, Blk *a2)
1768 int carry, n, size, c, n1, n2;
1770 size = length(a1)>length(a2)?length(a1):length(a2);
1775 while(--size >= 0) {
1776 n1 = sfeof(a1)?0:sgetc(a1);
1777 n2 = sfeof(a2)?0:sgetc(a2);
1778 n = n1 + n2 + carry;
1795 while(sfbeg(p) == 0 && (c = sbackc(p)) == 0)
1802 if(sfbeg(p) == 0 && sbackc(p) == -1) {
1803 while((c = sbackc(p)) == 99) {
1834 p = add0(p,skq-skp);
1837 q = add0(q,skp-skq);
1845 removc(Blk *p, int n)
1855 while(sfeof(p) == 0)
1878 scale(Blk *p, int n)
1900 savk = sunputc(arg1);
1913 char line[100], *sl;
1916 switch(c = readc()) {
1926 while((c = readc()) != '\n')
1927 if(sl-line < sizeof(line)-1)
1930 if((pid = fork()) == 0) {
1931 execl("/bin/rc","rc","-c",line,nil);
1935 if((p = waitpid()) < 0)
1940 Bprint(&bout,"!\n");
1955 if(length(p) == 0) {
1957 if(c == '<' || c == '>' || c == NE) {
1977 if((cc<0 && (c == '<' || c == NG)) ||
1978 (cc >0) && (c == '>' || c == NL)) {
1992 c = getstk() & 0377;
1997 q = salloc(length(p));
1999 while(sfeof(p) == 0) {
2004 t = copy(s,length(s));
2010 q = copy(p,length(p));
2016 Bprint(&bout,"function %c undefined\n",c+'a'-1);
2039 while((n <<= 1) > 0)
2052 if(all - rel > active)
2060 ptr = malloc((unsigned)size);
2063 if((ptr = malloc((unsigned)size)) == 0)
2066 if((hdr = hfree) == 0)
2068 hfree = (Blk *)hdr->rd;
2069 hdr->rd = hdr->wt = hdr->beg = ptr;
2070 hdr->last = ptr+size;
2081 hfree = h = (Blk *)malloc(HEADSZ);
2084 if((hfree = h = (Blk*)malloc(HEADSZ)) == 0)
2088 while(h<hfree+(HEADSZ/BLK))
2089 (h++)->rd = (char*)++kk;
2095 copy(Blk *hptr, int size)
2113 Bprint(&bout,"copy size %d\n",size);
2116 memmove(ptr, hptr->beg, sz);
2118 memset(ptr+sz, 0, size-sz);
2119 if((hdr = hfree) == 0)
2121 hfree = (Blk *)hdr->rd;
2122 hdr->rd = hdr->beg = ptr;
2123 hdr->last = ptr+size;
2126 while(ptr<hdr->last)
2132 sdump(char *s1, Blk *hptr)
2137 Bprint(&bout, "%s no block\n", s1);
2140 Bprint(&bout,"%s %lx rd %lx wt %lx beg %lx last %lx\n",
2141 s1,hptr,hptr->rd,hptr->wt,hptr->beg,hptr->last);
2144 Bprint(&bout,"%d ",*p++);
2149 seekc(Blk *hptr, int n)
2154 if(nn > hptr->last) {
2155 nbytes += nn - hptr->last;
2156 if(nbytes > maxsize)
2158 lbytes += nn - hptr->last;
2161 /* free(hptr->beg); /**/
2162 p = realloc(hptr->beg, n);
2164 /* hptr->beg = realloc(hptr->beg, hptr->last-hptr->beg);
2165 ** garbage("seekc");
2166 ** if((p = realloc(hptr->beg, n)) == 0)
2170 hptr->wt = hptr->last = hptr->rd = p+n;
2179 salterwd(Blk *ahptr, Blk *n)
2183 hptr = (Wblk*)ahptr;
2184 if(hptr->rdw == hptr->lastw)
2187 if(hptr->rdw > hptr->wtw)
2188 hptr->wtw = hptr->rdw;
2197 if((size=(hptr->last-hptr->beg)*2) == 0)
2200 if(nbytes > maxsize)
2206 /* free(hptr->beg);/**/
2207 p = realloc(hptr->beg, size);
2210 /* hptr->beg = realloc(hptr->beg, (hptr->last-hptr->beg));
2212 ** if((p = realloc(hptr->beg,size)) == 0)
2215 hptr->rd = p + (hptr->rd - hptr->beg);
2216 hptr->wt = p + (hptr->wt - hptr->beg);
2218 hptr->last = p+size;
2224 Bprint(&bout,"out of space: %s\n",s);
2225 Bprint(&bout,"all %ld rel %ld headmor %ld\n",all,rel,headmor);
2226 Bprint(&bout,"nbytes %ld\n",nbytes);
2227 sdump("stk",*stkptr);
2242 nbytes -= p->last - p->beg;
2243 p->rd = (char*)hfree;
2254 if(wp->rdw == wp->wtw)
2260 putwd(Blk *p, Blk *c)
2265 if(wp->wtw == wp->lastw)
2276 if(wp->rdw == wp->wtw)