]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/dc.c
cwfs: fix listen filedescriptor leaks
[plan9front.git] / sys / src / cmd / dc.c
1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4
5 typedef void*   pointer;
6 #pragma varargck        type    "lx"    pointer
7
8 #define FATAL 0
9 #define NFATAL 1
10 #define BLK sizeof(Blk)
11 #define PTRSZ sizeof(int*)
12 #define TBLSZ 256                       /* 1<<BI2BY */
13
14 #define HEADSZ 1024
15 #define STKSZ 100
16 #define RDSKSZ 100
17 #define ARRAYST 221
18 #define MAXIND 2048
19
20 #define NL 1
21 #define NG 2
22 #define NE 3
23
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);\
38                                 *(p)->wt++ = c; }
39 #define salterc(p,c)    {if((p)->rd==(p)->last)more(p);\
40                                 *(p)->rd++ = c;\
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;)\
45                                 *pp++='\0'
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); }
54
55 #define LASTFUN 026
56
57 typedef struct  Blk     Blk;
58 struct  Blk
59 {
60         char    *rd;
61         char    *wt;
62         char    *beg;
63         char    *last;
64 };
65 typedef struct  Sym     Sym;
66 struct  Sym
67 {
68         Sym     *next;
69         Blk     *val;
70 };
71 typedef struct  Wblk    Wblk;
72 struct  Wblk
73 {
74         Blk     **rdw;
75         Blk     **wtw;
76         Blk     **begw;
77         Blk     **lastw;
78 };
79
80 Biobuf  *curfile, *fsave;
81 Blk     *arg1, *arg2;
82 uchar   savk;
83 int     dbg;
84 int     ifile;
85 Blk     *scalptr, *basptr, *tenptr, *inbas;
86 Blk     *sqtemp, *chptr, *strptr, *divxyz;
87 Blk     *stack[STKSZ];
88 Blk     **stkptr,**stkbeg;
89 Blk     **stkend;
90 Blk     *hfree;
91 int     stkerr;
92 int     lastchar;
93 Blk     *readstk[RDSKSZ];
94 Blk     **readptr;
95 Blk     *rem;
96 int     k;
97 Blk     *irem;
98 int     skd,skr;
99 int     neg;
100 Sym     symlst[TBLSZ];
101 Sym     *stable[TBLSZ];
102 Sym     *sptr, *sfree;
103 long    rel;
104 long    nbytes;
105 long    all;
106 long    headmor;
107 long    obase;
108 int     fw,fw1,ll;
109 void    (*outdit)(Blk *p, int flg);
110 int     logo;
111 int     logten;
112 int     count;
113 char    *pp;
114 char    *dummy;
115 long    longest, maxsize, active;
116 int     lall, lrel, lcopy, lmore, lbytes;
117 int     inside;
118 Biobuf  bin;
119 Biobuf  bout;
120
121 void    main(int argc, char *argv[]);
122 void    commnds(void);
123 Blk*    readin(void);
124 Blk*    div(Blk *ddivd, Blk *ddivr);
125 int     dscale(void);
126 Blk*    removr(Blk *p, int n);
127 Blk*    dcsqrt(Blk *p);
128 void    init(int argc, char *argv[]);
129 void    onintr(void);
130 void    pushp(Blk *p);
131 Blk*    pop(void);
132 Blk*    readin(void);
133 Blk*    add0(Blk *p, int ct);
134 Blk*    mult(Blk *p, Blk *q);
135 void    chsign(Blk *p);
136 int     readc(void);
137 void    unreadc(char c);
138 void    binop(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);
147 int     eqk(void);
148 Blk*    removc(Blk *p, int n);
149 Blk*    scalint(Blk *p);
150 Blk*    scale(Blk *p, int n);
151 int     subt(void);
152 int     command(void);
153 int     cond(char c);
154 void    load(void);
155 int     log2(long n);
156 Blk*    salloc(int size);
157 Blk*    morehd(void);
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);
168 Blk*    lookwd(Blk *p);
169 int     getstk(void);
170
171 /********debug only**/
172 void
173 tpr(char *cp, Blk *bp)
174 {
175         print("%s-> ", cp);
176         print("beg: %lx rd: %lx wt: %lx last: %lx\n", bp->beg, bp->rd,
177                 bp->wt, bp->last);
178         for (cp = bp->beg; cp != bp->wt; cp++) {
179                 print("%d", *cp);
180                 if (cp != bp->wt-1)
181                         print("/");
182         }
183         print("\n");
184 }
185 /************/
186
187 void
188 main(int argc, char *argv[])
189 {
190         Binit(&bin, 0, OREAD);
191         Binit(&bout, 1, OWRITE);
192         init(argc,argv);
193         commnds();
194         exits(0);
195 }
196
197 void
198 commnds(void)
199 {
200         Blk *p, *q, **ptr, *s, *t;
201         long l;
202         Sym *sp;
203         int sk, sk1, sk2, c, sign, n, d;
204
205         while(1) {
206                 Bflush(&bout);
207                 if(((c = readc())>='0' && c <= '9') ||
208                     (c>='A' && c <='F') || c == '.') {
209                         unreadc(c);
210                         p = readin();
211                         pushp(p);
212                         continue;
213                 }
214                 switch(c) {
215                 case ' ':
216                 case '\t':
217                 case '\n':
218                 case -1:
219                         continue;
220                 case 'Y':
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,
225                                 active, maxsize);
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;
229                         continue;
230                 case '_':
231                         p = readin();
232                         savk = sunputc(p);
233                         chsign(p);
234                         sputc(p,savk);
235                         pushp(p);
236                         continue;
237                 case '-':
238                         subt();
239                         continue;
240                 case '+':
241                         if(eqk() != 0)
242                                 continue;
243                         binop('+');
244                         continue;
245                 case '*':
246                         arg1 = pop();
247                         EMPTY;
248                         arg2 = pop();
249                         EMPTYR(arg1);
250                         sk1 = sunputc(arg1);
251                         sk2 = sunputc(arg2);
252                         savk = sk1+sk2;
253                         binop('*');
254                         p = pop();
255                         if(savk>k && savk>sk1 && savk>sk2) {
256                                 sclobber(p);
257                                 sk = sk1;
258                                 if(sk<sk2)
259                                         sk = sk2;
260                                 if(sk<k)
261                                         sk = k;
262                                 p = removc(p,savk-sk);
263                                 savk = sk;
264                                 sputc(p,savk);
265                         }
266                         pushp(p);
267                         continue;
268                 case '/':
269                 casediv:
270                         if(dscale() != 0)
271                                 continue;
272                         binop('/');
273                         if(irem != 0)
274                                 release(irem);
275                         release(rem);
276                         continue;
277                 case '%':
278                         if(dscale() != 0)
279                                 continue;
280                         binop('/');
281                         p = pop();
282                         release(p);
283                         if(irem == 0) {
284                                 sputc(rem,skr+k);
285                                 pushp(rem);
286                                 continue;
287                         }
288                         p = add0(rem,skd-(skr+k));
289                         q = add(p,irem);
290                         release(p);
291                         release(irem);
292                         sputc(q,skd);
293                         pushp(q);
294                         continue;
295                 case 'v':
296                         p = pop();
297                         EMPTY;
298                         savk = sunputc(p);
299                         if(length(p) == 0) {
300                                 sputc(p,savk);
301                                 pushp(p);
302                                 continue;
303                         }
304                         if(sbackc(p)<0) {
305                                 error("sqrt of neg number\n");
306                         }
307                         if(k<savk)
308                                 n = savk;
309                         else {
310                                 n = k*2-savk;
311                                 savk = k;
312                         }
313                         arg1 = add0(p,n);
314                         arg2 = dcsqrt(arg1);
315                         sputc(arg2,savk);
316                         pushp(arg2);
317                         continue;
318
319                 case '^':
320                         neg = 0;
321                         arg1 = pop();
322                         EMPTY;
323                         if(sunputc(arg1) != 0)
324                                 error("exp not an integer\n");
325                         arg2 = pop();
326                         EMPTYR(arg1);
327                         if(sfbeg(arg1) == 0 && sbackc(arg1)<0) {
328                                 neg++;
329                                 chsign(arg1);
330                         }
331                         if(length(arg1)>=3) {
332                                 error("exp too big\n");
333                         }
334                         savk = sunputc(arg2);
335                         p = dcexp(arg2,arg1);
336                         release(arg2);
337                         rewind(arg1);
338                         c = sgetc(arg1);
339                         if(c == -1)
340                                 c = 0;
341                         else
342                         if(sfeof(arg1) == 0)
343                                 c = sgetc(arg1)*100 + c;
344                         d = c*savk;
345                         release(arg1);
346                 /*      if(neg == 0) {          removed to fix -exp bug*/
347                                 if(k>=savk)
348                                         n = k;
349                                 else
350                                         n = savk;
351                                 if(n<d) {
352                                         q = removc(p,d-n);
353                                         sputc(q,n);
354                                         pushp(q);
355                                 } else {
356                                         sputc(p,d);
357                                         pushp(p);
358                                 }
359                 /*      } else { this is disaster for exp <-127 */
360                 /*              sputc(p,d);             */
361                 /*              pushp(p);               */
362                 /*      }                               */
363                         if(neg == 0)
364                                 continue;
365                         p = pop();
366                         q = salloc(2);
367                         sputc(q,1);
368                         sputc(q,0);
369                         pushp(q);
370                         pushp(p);
371                         goto casediv;
372                 case 'z':
373                         p = salloc(2);
374                         n = stkptr - stkbeg;
375                         if(n >= 100) {
376                                 sputc(p,n/100);
377                                 n %= 100;
378                         }
379                         sputc(p,n);
380                         sputc(p,0);
381                         pushp(p);
382                         continue;
383                 case 'Z':
384                         p = pop();
385                         EMPTY;
386                         n = (length(p)-1)<<1;
387                         fsfile(p);
388                         backc(p);
389                         if(sfbeg(p) == 0) {
390                                 if((c = sbackc(p))<0) {
391                                         n -= 2;
392                                         if(sfbeg(p) == 1)
393                                                 n++;
394                                         else {
395                                                 if((c = sbackc(p)) == 0)
396                                                         n++;
397                                                 else
398                                                 if(c > 90)
399                                                         n--;
400                                         }
401                                 } else
402                                 if(c < 10)
403                                         n--;
404                         }
405                         release(p);
406                         q = salloc(1);
407                         if(n >= 100) {
408                                 sputc(q,n%100);
409                                 n /= 100;
410                         }
411                         sputc(q,n);
412                         sputc(q,0);
413                         pushp(q);
414                         continue;
415                 case 'i':
416                         p = pop();
417                         EMPTY;
418                         p = scalint(p);
419                         release(inbas);
420                         inbas = p;
421                         continue;
422                 case 'I':
423                         p = copy(inbas,length(inbas)+1);
424                         sputc(p,0);
425                         pushp(p);
426                         continue;
427                 case 'o':
428                         p = pop();
429                         EMPTY;
430                         p = scalint(p);
431                         sign = 0;
432                         n = length(p);
433                         q = copy(p,n);
434                         fsfile(q);
435                         l = c = sbackc(q);
436                         if(n != 1) {
437                                 if(c<0) {
438                                         sign = 1;
439                                         chsign(q);
440                                         n = length(q);
441                                         fsfile(q);
442                                         l = c = sbackc(q);
443                                 }
444                                 if(n != 1) {
445                                         while(sfbeg(q) == 0)
446                                                 l = l*100+sbackc(q);
447                                 }
448                         }
449                         logo = log2(l);
450                         obase = l;
451                         release(basptr);
452                         if(sign == 1)
453                                 obase = -l;
454                         basptr = p;
455                         outdit = bigot;
456                         if(n == 1 && sign == 0) {
457                                 if(c <= 16) {
458                                         outdit = hexot;
459                                         fw = 1;
460                                         fw1 = 0;
461                                         ll = 70;
462                                         release(q);
463                                         continue;
464                                 }
465                         }
466                         n = 0;
467                         if(sign == 1)
468                                 n++;
469                         p = salloc(1);
470                         sputc(p,-1);
471                         t = add(p,q);
472                         n += length(t)*2;
473                         fsfile(t);
474                         if(sbackc(t)>9)
475                                 n++;
476                         release(t);
477                         release(q);
478                         release(p);
479                         fw = n;
480                         fw1 = n-1;
481                         ll = 70;
482                         if(fw>=ll)
483                                 continue;
484                         ll = (70/fw)*fw;
485                         continue;
486                 case 'O':
487                         p = copy(basptr,length(basptr)+1);
488                         sputc(p,0);
489                         pushp(p);
490                         continue;
491                 case '[':
492                         n = 0;
493                         p = salloc(0);
494                         for(;;) {
495                                 if((c = readc()) == ']') {
496                                         if(n == 0)
497                                                 break;
498                                         n--;
499                                 }
500                                 sputc(p,c);
501                                 if(c == '[')
502                                         n++;
503                         }
504                         pushp(p);
505                         continue;
506                 case 'k':
507                         p = pop();
508                         EMPTY;
509                         p = scalint(p);
510                         if(length(p)>1) {
511                                 error("scale too big\n");
512                         }
513                         rewind(p);
514                         k = 0;
515                         if(!sfeof(p))
516                                 k = sgetc(p);
517                         release(scalptr);
518                         scalptr = p;
519                         continue;
520                 case 'K':
521                         p = copy(scalptr,length(scalptr)+1);
522                         sputc(p,0);
523                         pushp(p);
524                         continue;
525                 case 'X':
526                         p = pop();
527                         EMPTY;
528                         fsfile(p);
529                         n = sbackc(p);
530                         release(p);
531                         p = salloc(2);
532                         sputc(p,n);
533                         sputc(p,0);
534                         pushp(p);
535                         continue;
536                 case 'Q':
537                         p = pop();
538                         EMPTY;
539                         if(length(p)>2) {
540                                 error("Q?\n");
541                         }
542                         rewind(p);
543                         if((c =  sgetc(p))<0) {
544                                 error("neg Q\n");
545                         }
546                         release(p);
547                         while(c-- > 0) {
548                                 if(readptr == &readstk[0]) {
549                                         error("readstk?\n");
550                                 }
551                                 if(*readptr != 0)
552                                         release(*readptr);
553                                 readptr--;
554                         }
555                         continue;
556                 case 'q':
557                         if(readptr <= &readstk[1])
558                                 exits(0);
559                         if(*readptr != 0)
560                                 release(*readptr);
561                         readptr--;
562                         if(*readptr != 0)
563                                 release(*readptr);
564                         readptr--;
565                         continue;
566                 case 'f':
567                         if(stkptr == &stack[0])
568                                 Bprint(&bout,"empty stack\n");
569                         else {
570                                 for(ptr = stkptr; ptr > &stack[0];) {
571                                         dcprint(*ptr--);
572                                 }
573                         }
574                         continue;
575                 case 'p':
576                         if(stkptr == &stack[0])
577                                 Bprint(&bout,"empty stack\n");
578                         else {
579                                 dcprint(*stkptr);
580                         }
581                         continue;
582                 case 'P':
583                         p = pop();
584                         EMPTY;
585                         sputc(p,0);
586                         Bprint(&bout,"%s",p->beg);
587                         release(p);
588                         continue;
589                 case 'd':
590                         if(stkptr == &stack[0]) {
591                                 Bprint(&bout,"empty stack\n");
592                                 continue;
593                         }
594                         q = *stkptr;
595                         n = length(q);
596                         p = copy(*stkptr,n);
597                         pushp(p);
598                         continue;
599                 case 'c':
600                         while(stkerr == 0) {
601                                 p = pop();
602                                 if(stkerr == 0)
603                                         release(p);
604                         }
605                         continue;
606                 case 'S':
607                         if(stkptr == &stack[0]) {
608                                 error("save: args\n");
609                         }
610                         c = getstk() & 0377;
611                         sptr = stable[c];
612                         sp = stable[c] = sfree;
613                         sfree = sfree->next;
614                         if(sfree == 0)
615                                 goto sempty;
616                         sp->next = sptr;
617                         p = pop();
618                         EMPTY;
619                         if(c >= ARRAYST) {
620                                 q = copy(p,length(p)+PTRSZ);
621                                 for(n = 0;n < PTRSZ;n++) {
622                                         sputc(q,0);
623                                 }
624                                 release(p);
625                                 p = q;
626                         }
627                         sp->val = p;
628                         continue;
629                 sempty:
630                         error("symbol table overflow\n");
631                 case 's':
632                         if(stkptr == &stack[0]) {
633                                 error("save:args\n");
634                         }
635                         c = getstk() & 0377;
636                         sptr = stable[c];
637                         if(sptr != 0) {
638                                 p = sptr->val;
639                                 if(c >= ARRAYST) {
640                                         rewind(p);
641                                         while(sfeof(p) == 0)
642                                                 release(dcgetwd(p));
643                                 }
644                                 release(p);
645                         } else {
646                                 sptr = stable[c] = sfree;
647                                 sfree = sfree->next;
648                                 if(sfree == 0)
649                                         goto sempty;
650                                 sptr->next = 0;
651                         }
652                         p = pop();
653                         sptr->val = p;
654                         continue;
655                 case 'l':
656                         load();
657                         continue;
658                 case 'L':
659                         c = getstk() & 0377;
660                         sptr = stable[c];
661                         if(sptr == 0) {
662                                 error("L?\n");
663                         }
664                         stable[c] = sptr->next;
665                         sptr->next = sfree;
666                         sfree = sptr;
667                         p = sptr->val;
668                         if(c >= ARRAYST) {
669                                 rewind(p);
670                                 while(sfeof(p) == 0) {
671                                         q = dcgetwd(p);
672                                         if(q != 0)
673                                                 release(q);
674                                 }
675                         }
676                         pushp(p);
677                         continue;
678                 case ':':
679                         p = pop();
680                         EMPTY;
681                         q = scalint(p);
682                         fsfile(q);
683                         c = 0;
684                         if((sfbeg(q) == 0) && ((c = sbackc(q))<0)) {
685                                 error("neg index\n");
686                         }
687                         if(length(q)>2) {
688                                 error("index too big\n");
689                         }
690                         if(sfbeg(q) == 0)
691                                 c = c*100+sbackc(q);
692                         if(c >= MAXIND) {
693                                 error("index too big\n");
694                         }
695                         release(q);
696                         n = getstk() & 0377;
697                         sptr = stable[n];
698                         if(sptr == 0) {
699                                 sptr = stable[n] = sfree;
700                                 sfree = sfree->next;
701                                 if(sfree == 0)
702                                         goto sempty;
703                                 sptr->next = 0;
704                                 p = salloc((c+PTRSZ)*PTRSZ);
705                                 zero(p);
706                         } else {
707                                 p = sptr->val;
708                                 if(length(p)-PTRSZ < c*PTRSZ) {
709                                         q = copy(p,(c+PTRSZ)*PTRSZ);
710                                         release(p);
711                                         p = q;
712                                 }
713                         }
714                         seekc(p,c*PTRSZ);
715                         q = lookwd(p);
716                         if(q!=0)
717                                 release(q);
718                         s = pop();
719                         EMPTY;
720                         salterwd(p, s);
721                         sptr->val = p;
722                         continue;
723                 case ';':
724                         p = pop();
725                         EMPTY;
726                         q = scalint(p);
727                         fsfile(q);
728                         c = 0;
729                         if((sfbeg(q) == 0) && ((c = sbackc(q))<0)) {
730                                 error("neg index\n");
731                         }
732                         if(length(q)>2) {
733                                 error("index too big\n");
734                         }
735                         if(sfbeg(q) == 0)
736                                 c = c*100+sbackc(q);
737                         if(c >= MAXIND) {
738                                 error("index too big\n");
739                         }
740                         release(q);
741                         n = getstk() & 0377;
742                         sptr = stable[n];
743                         if(sptr != 0){
744                                 p = sptr->val;
745                                 if(length(p)-PTRSZ >= c*PTRSZ) {
746                                         seekc(p,c*PTRSZ);
747                                         s = dcgetwd(p);
748                                         if(s != 0) {
749                                                 q = copy(s,length(s));
750                                                 pushp(q);
751                                                 continue;
752                                         }
753                                 }
754                         }
755                         q = salloc(1);  /*so uninitialized array elt prints as 0*/
756                         sputc(q, 0);
757                         pushp(q);
758                         continue;
759                 case 'x':
760                 execute:
761                         p = pop();
762                         EMPTY;
763                         if((readptr != &readstk[0]) && (*readptr != 0)) {
764                                 if((*readptr)->rd == (*readptr)->wt)
765                                         release(*readptr);
766                                 else {
767                                         if(readptr++ == &readstk[RDSKSZ]) {
768                                                 error("nesting depth\n");
769                                         }
770                                 }
771                         } else
772                                 readptr++;
773                         *readptr = p;
774                         if(p != 0)
775                                 rewind(p);
776                         else {
777                                 if((c = readc()) != '\n')
778                                         unreadc(c);
779                         }
780                         continue;
781                 case '?':
782                         if(++readptr == &readstk[RDSKSZ]) {
783                                 error("nesting depth\n");
784                         }
785                         *readptr = 0;
786                         fsave = curfile;
787                         curfile = &bin;
788                         while((c = readc()) == '!')
789                                 command();
790                         p = salloc(0);
791                         sputc(p,c);
792                         while((c = readc()) != '\n') {
793                                 sputc(p,c);
794                                 if(c == '\\')
795                                         sputc(p,readc());
796                         }
797                         curfile = fsave;
798                         *readptr = p;
799                         continue;
800                 case '!':
801                         if(command() == 1)
802                                 goto execute;
803                         continue;
804                 case '<':
805                 case '>':
806                 case '=':
807                         if(cond(c) == 1)
808                                 goto execute;
809                         continue;
810                 default:
811                         Bprint(&bout,"%o is unimplemented\n",c);
812                 }
813         }
814 }
815
816 Blk*
817 div(Blk *ddivd, Blk *ddivr)
818 {
819         int divsign, remsign, offset, divcarry,
820                 carry, dig, magic, d, dd, under, first;
821         long c, td, cc;
822         Blk *ps, *px, *p, *divd, *divr;
823
824         dig = 0;
825         under = 0;
826         divcarry = 0;
827         rem = 0;
828         p = salloc(0);
829         if(length(ddivr) == 0) {
830                 pushp(ddivr);
831                 Bprint(&bout,"divide by 0\n");
832                 return(p);
833         }
834         divsign = remsign = first = 0;
835         divr = ddivr;
836         fsfile(divr);
837         if(sbackc(divr) == -1) {
838                 divr = copy(ddivr,length(ddivr));
839                 chsign(divr);
840                 divsign = ~divsign;
841         }
842         divd = copy(ddivd,length(ddivd));
843         fsfile(divd);
844         if(sfbeg(divd) == 0 && sbackc(divd) == -1) {
845                 chsign(divd);
846                 divsign = ~divsign;
847                 remsign = ~remsign;
848         }
849         offset = length(divd) - length(divr);
850         if(offset < 0)
851                 goto ddone;
852         seekc(p,offset+1);
853         sputc(divd,0);
854         magic = 0;
855         fsfile(divr);
856         c = sbackc(divr);
857         if(c < 10)
858                 magic++;
859         c = c * 100 + (sfbeg(divr)?0:sbackc(divr));
860         if(magic>0){
861                 c = (c * 100 +(sfbeg(divr)?0:sbackc(divr)))*2;
862                 c /= 25;
863         }
864         while(offset >= 0) {
865                 first++;
866                 fsfile(divd);
867                 td = sbackc(divd) * 100;
868                 dd = sfbeg(divd)?0:sbackc(divd);
869                 td = (td + dd) * 100;
870                 dd = sfbeg(divd)?0:sbackc(divd);
871                 td = td + dd;
872                 cc = c;
873                 if(offset == 0)
874                         td++;
875                 else
876                         cc++;
877                 if(magic != 0)
878                         td = td<<3;
879                 dig = td/cc;
880                 under=0;
881                 if(td%cc < 8  && dig > 0 && magic) {
882                         dig--;
883                         under=1;
884                 }
885                 rewind(divr);
886                 rewind(divxyz);
887                 carry = 0;
888                 while(sfeof(divr) == 0) {
889                         d = sgetc(divr)*dig+carry;
890                         carry = d / 100;
891                         salterc(divxyz,d%100);
892                 }
893                 salterc(divxyz,carry);
894                 rewind(divxyz);
895                 seekc(divd,offset);
896                 carry = 0;
897                 while(sfeof(divd) == 0) {
898                         d = slookc(divd);
899                         d = d-(sfeof(divxyz)?0:sgetc(divxyz))-carry;
900                         carry = 0;
901                         if(d < 0) {
902                                 d += 100;
903                                 carry = 1;
904                         }
905                         salterc(divd,d);
906                 }
907                 divcarry = carry;
908                 backc(p);
909                 salterc(p,dig);
910                 backc(p);
911                 fsfile(divd);
912                 d=sbackc(divd);
913                 if((d != 0) && /*!divcarry*/ (offset != 0)) {
914                         d = sbackc(divd) + 100;
915                         salterc(divd,d);
916                 }
917                 if(--offset >= 0)
918                         divd->wt--;
919         }
920         if(under) {     /* undershot last - adjust*/
921                 px = copy(divr,length(divr));   /*11/88 don't corrupt ddivr*/
922                 chsign(px);
923                 ps = add(px,divd);
924                 fsfile(ps);
925                 if(length(ps) > 0 && sbackc(ps) < 0) {
926                         release(ps);    /*only adjust in really undershot*/
927                 } else {
928                         release(divd);
929                         salterc(p, dig+1);
930                         divd=ps;
931                 }
932         }
933         if(divcarry != 0) {
934                 salterc(p,dig-1);
935                 salterc(divd,-1);
936                 ps = add(divr,divd);
937                 release(divd);
938                 divd = ps;
939         }
940
941         rewind(p);
942         divcarry = 0;
943         while(sfeof(p) == 0){
944                 d = slookc(p)+divcarry;
945                 divcarry = 0;
946                 if(d >= 100){
947                         d -= 100;
948                         divcarry = 1;
949                 }
950                 salterc(p,d);
951         }
952         if(divcarry != 0)salterc(p,divcarry);
953         fsfile(p);
954         while(sfbeg(p) == 0) {
955                 if(sbackc(p) != 0)
956                         break;
957                 truncate(p);
958         }
959         if(divsign < 0)
960                 chsign(p);
961         fsfile(divd);
962         while(sfbeg(divd) == 0) {
963                 if(sbackc(divd) != 0)
964                         break;
965                 truncate(divd);
966         }
967 ddone:
968         if(remsign<0)
969                 chsign(divd);
970         if(divr != ddivr)
971                 release(divr);
972         rem = divd;
973         return(p);
974 }
975
976 int
977 dscale(void)
978 {
979         Blk *dd, *dr, *r;
980         int c;
981
982         dr = pop();
983         EMPTYS;
984         dd = pop();
985         EMPTYSR(dr);
986         fsfile(dd);
987         skd = sunputc(dd);
988         fsfile(dr);
989         skr = sunputc(dr);
990         if(sfbeg(dr) == 1 || (sfbeg(dr) == 0 && sbackc(dr) == 0)) {
991                 sputc(dr,skr);
992                 pushp(dr);
993                 Bprint(&bout,"divide by 0\n");
994                 return(1);
995         }
996         if(sfbeg(dd) == 1 || (sfbeg(dd) == 0 && sbackc(dd) == 0)) {
997                 sputc(dd,skd);
998                 pushp(dd);
999                 return(1);
1000         }
1001         c = k-skd+skr;
1002         if(c < 0)
1003                 r = removr(dd,-c);
1004         else {
1005                 r = add0(dd,c);
1006                 irem = 0;
1007         }
1008         arg1 = r;
1009         arg2 = dr;
1010         savk = k;
1011         return(0);
1012 }
1013
1014 Blk*
1015 removr(Blk *p, int n)
1016 {
1017         int nn, neg;
1018         Blk *q, *s, *r;
1019
1020         fsfile(p);
1021         neg = sbackc(p);
1022         if(neg < 0)
1023                 chsign(p);
1024         rewind(p);
1025         nn = (n+1)/2;
1026         q = salloc(nn);
1027         while(n>1) {
1028                 sputc(q,sgetc(p));
1029                 n -= 2;
1030         }
1031         r = salloc(2);
1032         while(sfeof(p) == 0)
1033                 sputc(r,sgetc(p));
1034         release(p);
1035         if(n == 1){
1036                 s = div(r,tenptr);
1037                 release(r);
1038                 rewind(rem);
1039                 if(sfeof(rem) == 0)
1040                         sputc(q,sgetc(rem));
1041                 release(rem);
1042                 if(neg < 0){
1043                         chsign(s);
1044                         chsign(q);
1045                         irem = q;
1046                         return(s);
1047                 }
1048                 irem = q;
1049                 return(s);
1050         }
1051         if(neg < 0) {
1052                 chsign(r);
1053                 chsign(q);
1054                 irem = q;
1055                 return(r);
1056         }
1057         irem = q;
1058         return(r);
1059 }
1060
1061 Blk*
1062 dcsqrt(Blk *p)
1063 {
1064         Blk *t, *r, *q, *s;
1065         int c, n, nn;
1066
1067         n = length(p);
1068         fsfile(p);
1069         c = sbackc(p);
1070         if((n&1) != 1)
1071                 c = c*100+(sfbeg(p)?0:sbackc(p));
1072         n = (n+1)>>1;
1073         r = salloc(n);
1074         zero(r);
1075         seekc(r,n);
1076         nn=1;
1077         while((c -= nn)>=0)
1078                 nn+=2;
1079         c=(nn+1)>>1;
1080         fsfile(r);
1081         backc(r);
1082         if(c>=100) {
1083                 c -= 100;
1084                 salterc(r,c);
1085                 sputc(r,1);
1086         } else
1087                 salterc(r,c);
1088         for(;;){
1089                 q = div(p,r);
1090                 s = add(q,r);
1091                 release(q);
1092                 release(rem);
1093                 q = div(s,sqtemp);
1094                 release(s);
1095                 release(rem);
1096                 s = copy(r,length(r));
1097                 chsign(s);
1098                 t = add(s,q);
1099                 release(s);
1100                 fsfile(t);
1101                 nn = sfbeg(t)?0:sbackc(t);
1102                 if(nn>=0)
1103                         break;
1104                 release(r);
1105                 release(t);
1106                 r = q;
1107         }
1108         release(t);
1109         release(q);
1110         release(p);
1111         return(r);
1112 }
1113
1114 Blk*
1115 dcexp(Blk *base, Blk *ex)
1116 {
1117         Blk *r, *e, *p, *e1, *t, *cp;
1118         int temp, c, n;
1119
1120         r = salloc(1);
1121         sputc(r,1);
1122         p = copy(base,length(base));
1123         e = copy(ex,length(ex));
1124         fsfile(e);
1125         if(sfbeg(e) != 0)
1126                 goto edone;
1127         temp=0;
1128         c = sbackc(e);
1129         if(c<0) {
1130                 temp++;
1131                 chsign(e);
1132         }
1133         while(length(e) != 0) {
1134                 e1=div(e,sqtemp);
1135                 release(e);
1136                 e = e1;
1137                 n = length(rem);
1138                 release(rem);
1139                 if(n != 0) {
1140                         e1=mult(p,r);
1141                         release(r);
1142                         r = e1;
1143                 }
1144                 t = copy(p,length(p));
1145                 cp = mult(p,t);
1146                 release(p);
1147                 release(t);
1148                 p = cp;
1149         }
1150         if(temp != 0) {
1151                 if((c = length(base)) == 0) {
1152                         goto edone;
1153                 }
1154                 if(c>1)
1155                         create(r);
1156                 else {
1157                         rewind(base);
1158                         if((c = sgetc(base))<=1) {
1159                                 create(r);
1160                                 sputc(r,c);
1161                         } else
1162                                 create(r);
1163                 }
1164         }
1165 edone:
1166         release(p);
1167         release(e);
1168         return(r);
1169 }
1170
1171 void
1172 init(int argc, char *argv[])
1173 {
1174         Sym *sp;
1175         Dir *d;
1176
1177         ARGBEGIN {
1178         default:
1179                 dbg = 1;
1180                 break;
1181         } ARGEND
1182         ifile = 1;
1183         curfile = &bin;
1184         if(*argv){
1185                 d = dirstat(*argv);
1186                 if(d == nil) {
1187                         fprint(2, "dc: can't open file %s\n", *argv);
1188                         exits("open");
1189                 }
1190                 if(d->mode & DMDIR) {
1191                         fprint(2, "dc: file %s is a directory\n", *argv);
1192                         exits("open");
1193                 }
1194                 free(d);
1195                 if((curfile = Bopen(*argv, OREAD)) == 0) {
1196                         fprint(2,"dc: can't open file %s\n", *argv);
1197                         exits("open");
1198                 }
1199         }
1200 /*      dummy = malloc(0);  /* prepare for garbage-collection */
1201         scalptr = salloc(1);
1202         sputc(scalptr,0);
1203         basptr = salloc(1);
1204         sputc(basptr,10);
1205         obase=10;
1206         logten=log2(10L);
1207         ll=70;
1208         fw=1;
1209         fw1=0;
1210         tenptr = salloc(1);
1211         sputc(tenptr,10);
1212         obase=10;
1213         inbas = salloc(1);
1214         sputc(inbas,10);
1215         sqtemp = salloc(1);
1216         sputc(sqtemp,2);
1217         chptr = salloc(0);
1218         strptr = salloc(0);
1219         divxyz = salloc(0);
1220         stkbeg = stkptr = &stack[0];
1221         stkend = &stack[STKSZ-1];
1222         stkerr = 0;
1223         readptr = &readstk[0];
1224         k=0;
1225         sp = sptr = &symlst[0];
1226         while(sptr < &symlst[TBLSZ-1]) {
1227                 sptr->next = ++sp;
1228                 sptr++;
1229         }
1230         sptr->next=0;
1231         sfree = &symlst[0];
1232 }
1233
1234 void
1235 pushp(Blk *p)
1236 {
1237         if(stkptr == stkend) {
1238                 Bprint(&bout,"out of stack space\n");
1239                 return;
1240         }
1241         stkerr=0;
1242         *++stkptr = p;
1243         return;
1244 }
1245
1246 Blk*
1247 pop(void)
1248 {
1249         if(stkptr == stack) {
1250                 stkerr=1;
1251                 return(0);
1252         }
1253         return(*stkptr--);
1254 }
1255
1256 Blk*
1257 readin(void)
1258 {
1259         Blk *p, *q;
1260         int dp, dpct, c;
1261
1262         dp = dpct=0;
1263         p = salloc(0);
1264         for(;;){
1265                 c = readc();
1266                 switch(c) {
1267                 case '.':
1268                         if(dp != 0)
1269                                 goto gotnum;
1270                         dp++;
1271                         continue;
1272                 case '\\':
1273                         readc();
1274                         continue;
1275                 default:
1276                         if(c >= 'A' && c <= 'F')
1277                                 c = c - 'A' + 10;
1278                         else
1279                         if(c >= '0' && c <= '9')
1280                                 c -= '0';
1281                         else
1282                                 goto gotnum;
1283                         if(dp != 0) {
1284                                 if(dpct >= 99)
1285                                         continue;
1286                                 dpct++;
1287                         }
1288                         create(chptr);
1289                         if(c != 0)
1290                                 sputc(chptr,c);
1291                         q = mult(p,inbas);
1292                         release(p);
1293                         p = add(chptr,q);
1294                         release(q);
1295                 }
1296         }
1297 gotnum:
1298         unreadc(c);
1299         if(dp == 0) {
1300                 sputc(p,0);
1301                 return(p);
1302         } else {
1303                 q = scale(p,dpct);
1304                 return(q);
1305         }
1306 }
1307
1308 /*
1309  * returns pointer to struct with ct 0's & p
1310  */
1311 Blk*
1312 add0(Blk *p, int ct)
1313 {
1314         Blk *q, *t;
1315
1316         q = salloc(length(p)+(ct+1)/2);
1317         while(ct>1) {
1318                 sputc(q,0);
1319                 ct -= 2;
1320         }
1321         rewind(p);
1322         while(sfeof(p) == 0) {
1323                 sputc(q,sgetc(p));
1324         }
1325         release(p);
1326         if(ct == 1) {
1327                 t = mult(tenptr,q);
1328                 release(q);
1329                 return(t);
1330         }
1331         return(q);
1332 }
1333
1334 Blk*
1335 mult(Blk *p, Blk *q)
1336 {
1337         Blk *mp, *mq, *mr;
1338         int sign, offset, carry;
1339         int cq, cp, mt, mcr;
1340
1341         offset = sign = 0;
1342         fsfile(p);
1343         mp = p;
1344         if(sfbeg(p) == 0) {
1345                 if(sbackc(p)<0) {
1346                         mp = copy(p,length(p));
1347                         chsign(mp);
1348                         sign = ~sign;
1349                 }
1350         }
1351         fsfile(q);
1352         mq = q;
1353         if(sfbeg(q) == 0){
1354                 if(sbackc(q)<0) {
1355                         mq = copy(q,length(q));
1356                         chsign(mq);
1357                         sign = ~sign;
1358                 }
1359         }
1360         mr = salloc(length(mp)+length(mq));
1361         zero(mr);
1362         rewind(mq);
1363         while(sfeof(mq) == 0) {
1364                 cq = sgetc(mq);
1365                 rewind(mp);
1366                 rewind(mr);
1367                 mr->rd += offset;
1368                 carry=0;
1369                 while(sfeof(mp) == 0) {
1370                         cp = sgetc(mp);
1371                         mcr = sfeof(mr)?0:slookc(mr);
1372                         mt = cp*cq + carry + mcr;
1373                         carry = mt/100;
1374                         salterc(mr,mt%100);
1375                 }
1376                 offset++;
1377                 if(carry != 0) {
1378                         mcr = sfeof(mr)?0:slookc(mr);
1379                         salterc(mr,mcr+carry);
1380                 }
1381         }
1382         if(sign < 0) {
1383                 chsign(mr);
1384         }
1385         if(mp != p)
1386                 release(mp);
1387         if(mq != q)
1388                 release(mq);
1389         return(mr);
1390 }
1391
1392 void
1393 chsign(Blk *p)
1394 {
1395         int carry;
1396         char ct;
1397
1398         carry=0;
1399         rewind(p);
1400         while(sfeof(p) == 0) {
1401                 ct=100-slookc(p)-carry;
1402                 carry=1;
1403                 if(ct>=100) {
1404                         ct -= 100;
1405                         carry=0;
1406                 }
1407                 salterc(p,ct);
1408         }
1409         if(carry != 0) {
1410                 sputc(p,-1);
1411                 fsfile(p);
1412                 backc(p);
1413                 ct = sbackc(p);
1414                 if(ct == 99 /*&& !sfbeg(p)*/) {
1415                         truncate(p);
1416                         sputc(p,-1);
1417                 }
1418         } else{
1419                 fsfile(p);
1420                 ct = sbackc(p);
1421                 if(ct == 0)
1422                         truncate(p);
1423         }
1424         return;
1425 }
1426
1427 int
1428 readc(void)
1429 {
1430 loop:
1431         if((readptr != &readstk[0]) && (*readptr != 0)) {
1432                 if(sfeof(*readptr) == 0)
1433                         return(lastchar = sgetc(*readptr));
1434                 release(*readptr);
1435                 readptr--;
1436                 goto loop;
1437         }
1438         lastchar = Bgetc(curfile);
1439         if(lastchar != -1)
1440                 return(lastchar);
1441         if(readptr != &readptr[0]) {
1442                 readptr--;
1443                 if(*readptr == 0)
1444                         curfile = &bin;
1445                 goto loop;
1446         }
1447         if(curfile != &bin) {
1448                 Bterm(curfile);
1449                 curfile = &bin;
1450                 goto loop;
1451         }
1452         exits(0);
1453         return 0;       /* shut up ken */
1454 }
1455
1456 void
1457 unreadc(char c)
1458 {
1459
1460         if((readptr != &readstk[0]) && (*readptr != 0)) {
1461                 sungetc(*readptr,c);
1462         } else
1463                 Bungetc(curfile);
1464         return;
1465 }
1466
1467 void
1468 binop(char c)
1469 {
1470         Blk *r;
1471
1472         r = 0;
1473         switch(c) {
1474         case '+':
1475                 r = add(arg1,arg2);
1476                 break;
1477         case '*':
1478                 r = mult(arg1,arg2);
1479                 break;
1480         case '/':
1481                 r = div(arg1,arg2);
1482                 break;
1483         }
1484         release(arg1);
1485         release(arg2);
1486         sputc(r,savk);
1487         pushp(r);
1488 }
1489
1490 void
1491 dcprint(Blk *hptr)
1492 {
1493         Blk *p, *q, *dec;
1494         int dig, dout, ct, sc;
1495
1496         rewind(hptr);
1497         while(sfeof(hptr) == 0) {
1498                 if(sgetc(hptr)>99) {
1499                         rewind(hptr);
1500                         while(sfeof(hptr) == 0) {
1501                                 Bprint(&bout,"%c",sgetc(hptr));
1502                         }
1503                         Bprint(&bout,"\n");
1504                         return;
1505                 }
1506         }
1507         fsfile(hptr);
1508         sc = sbackc(hptr);
1509         if(sfbeg(hptr) != 0) {
1510                 Bprint(&bout,"0\n");
1511                 return;
1512         }
1513         count = ll;
1514         p = copy(hptr,length(hptr));
1515         sclobber(p);
1516         fsfile(p);
1517         if(sbackc(p)<0) {
1518                 chsign(p);
1519                 OUTC('-');
1520         }
1521         if((obase == 0) || (obase == -1)) {
1522                 oneot(p,sc,'d');
1523                 return;
1524         }
1525         if(obase == 1) {
1526                 oneot(p,sc,'1');
1527                 return;
1528         }
1529         if(obase == 10) {
1530                 tenot(p,sc);
1531                 return;
1532         }
1533         /* sleazy hack to scale top of stack - divide by 1 */
1534         pushp(p);
1535         sputc(p, sc);
1536         p=salloc(0);
1537         create(p);
1538         sputc(p, 1);
1539         sputc(p, 0);
1540         pushp(p);
1541         if(dscale() != 0)
1542                 return;
1543         p = div(arg1, arg2);
1544         release(arg1);
1545         release(arg2);
1546         sc = savk;
1547
1548         create(strptr);
1549         dig = logten*sc;
1550         dout = ((dig/10) + dig) / logo;
1551         dec = getdec(p,sc);
1552         p = removc(p,sc);
1553         while(length(p) != 0) {
1554                 q = div(p,basptr);
1555                 release(p);
1556                 p = q;
1557                 (*outdit)(rem,0);
1558         }
1559         release(p);
1560         fsfile(strptr);
1561         while(sfbeg(strptr) == 0)
1562                 OUTC(sbackc(strptr));
1563         if(sc == 0) {
1564                 release(dec);
1565                 Bprint(&bout,"\n");
1566                 return;
1567         }
1568         create(strptr);
1569         OUTC('.');
1570         ct=0;
1571         do {
1572                 q = mult(basptr,dec);
1573                 release(dec);
1574                 dec = getdec(q,sc);
1575                 p = removc(q,sc);
1576                 (*outdit)(p,1);
1577         } while(++ct < dout);
1578         release(dec);
1579         rewind(strptr);
1580         while(sfeof(strptr) == 0)
1581                 OUTC(sgetc(strptr));
1582         Bprint(&bout,"\n");
1583 }
1584
1585 Blk*
1586 getdec(Blk *p, int sc)
1587 {
1588         int cc;
1589         Blk *q, *t, *s;
1590
1591         rewind(p);
1592         if(length(p)*2 < sc) {
1593                 q = copy(p,length(p));
1594                 return(q);
1595         }
1596         q = salloc(length(p));
1597         while(sc >= 1) {
1598                 sputc(q,sgetc(p));
1599                 sc -= 2;
1600         }
1601         if(sc != 0) {
1602                 t = mult(q,tenptr);
1603                 s = salloc(cc = length(q));
1604                 release(q);
1605                 rewind(t);
1606                 while(cc-- > 0)
1607                         sputc(s,sgetc(t));
1608                 sputc(s,0);
1609                 release(t);
1610                 t = div(s,tenptr);
1611                 release(s);
1612                 release(rem);
1613                 return(t);
1614         }
1615         return(q);
1616 }
1617
1618 void
1619 tenot(Blk *p, int sc)
1620 {
1621         int c, f;
1622
1623         fsfile(p);
1624         f=0;
1625         while((sfbeg(p) == 0) && ((p->rd-p->beg-1)*2 >= sc)) {
1626                 c = sbackc(p);
1627                 if((c<10) && (f == 1))
1628                         Bprint(&bout,"0%d",c);
1629                 else
1630                         Bprint(&bout,"%d",c);
1631                 f=1;
1632                 TEST2;
1633         }
1634         if(sc == 0) {
1635                 Bprint(&bout,"\n");
1636                 release(p);
1637                 return;
1638         }
1639         if((p->rd-p->beg)*2 > sc) {
1640                 c = sbackc(p);
1641                 Bprint(&bout,"%d.",c/10);
1642                 TEST2;
1643                 OUTC(c%10 +'0');
1644                 sc--;
1645         } else {
1646                 OUTC('.');
1647         }
1648         while(sc>(p->rd-p->beg)*2) {
1649                 OUTC('0');
1650                 sc--;
1651         }
1652         while(sc > 1) {
1653                 c = sbackc(p);
1654                 if(c<10)
1655                         Bprint(&bout,"0%d",c);
1656                 else
1657                         Bprint(&bout,"%d",c);
1658                 sc -= 2;
1659                 TEST2;
1660         }
1661         if(sc == 1) {
1662                 OUTC(sbackc(p)/10 +'0');
1663         }
1664         Bprint(&bout,"\n");
1665         release(p);
1666 }
1667
1668 void
1669 oneot(Blk *p, int sc, char ch)
1670 {
1671         Blk *q;
1672
1673         q = removc(p,sc);
1674         create(strptr);
1675         sputc(strptr,-1);
1676         while(length(q)>0) {
1677                 p = add(strptr,q);
1678                 release(q);
1679                 q = p;
1680                 OUTC(ch);
1681         }
1682         release(q);
1683         Bprint(&bout,"\n");
1684 }
1685
1686 void
1687 hexot(Blk *p, int flg)
1688 {
1689         int c;
1690
1691         USED(flg);
1692         rewind(p);
1693         if(sfeof(p) != 0) {
1694                 sputc(strptr,'0');
1695                 release(p);
1696                 return;
1697         }
1698         c = sgetc(p);
1699         release(p);
1700         if(c >= 16) {
1701                 Bprint(&bout,"hex digit > 16");
1702                 return;
1703         }
1704         sputc(strptr,c<10?c+'0':c-10+'a');
1705 }
1706
1707 void
1708 bigot(Blk *p, int flg)
1709 {
1710         Blk *t, *q;
1711         int neg, l;
1712
1713         if(flg == 1) {
1714                 t = salloc(0);
1715                 l = 0;
1716         } else {
1717                 t = strptr;
1718                 l = length(strptr)+fw-1;
1719         }
1720         neg=0;
1721         if(length(p) != 0) {
1722                 fsfile(p);
1723                 if(sbackc(p)<0) {
1724                         neg=1;
1725                         chsign(p);
1726                 }
1727                 while(length(p) != 0) {
1728                         q = div(p,tenptr);
1729                         release(p);
1730                         p = q;
1731                         rewind(rem);
1732                         sputc(t,sfeof(rem)?'0':sgetc(rem)+'0');
1733                         release(rem);
1734                 }
1735         }
1736         release(p);
1737         if(flg == 1) {
1738                 l = fw1-length(t);
1739                 if(neg != 0) {
1740                         l--;
1741                         sputc(strptr,'-');
1742                 }
1743                 fsfile(t);
1744                 while(l-- > 0)
1745                         sputc(strptr,'0');
1746                 while(sfbeg(t) == 0)
1747                         sputc(strptr,sbackc(t));
1748                 release(t);
1749         } else {
1750                 l -= length(strptr);
1751                 while(l-- > 0)
1752                         sputc(strptr,'0');
1753                 if(neg != 0) {
1754                         sclobber(strptr);
1755                         sputc(strptr,'-');
1756                 }
1757         }
1758         sputc(strptr,' ');
1759 }
1760
1761 Blk*
1762 add(Blk *a1, Blk *a2)
1763 {
1764         Blk *p;
1765         int carry, n, size, c, n1, n2;
1766
1767         size = length(a1)>length(a2)?length(a1):length(a2);
1768         p = salloc(size);
1769         rewind(a1);
1770         rewind(a2);
1771         carry=0;
1772         while(--size >= 0) {
1773                 n1 = sfeof(a1)?0:sgetc(a1);
1774                 n2 = sfeof(a2)?0:sgetc(a2);
1775                 n = n1 + n2 + carry;
1776                 if(n>=100) {
1777                         carry=1;
1778                         n -= 100;
1779                 } else
1780                 if(n<0) {
1781                         carry = -1;
1782                         n += 100;
1783                 } else
1784                         carry = 0;
1785                 sputc(p,n);
1786         }
1787         if(carry != 0)
1788                 sputc(p,carry);
1789         fsfile(p);
1790         if(sfbeg(p) == 0) {
1791                 c = 0;
1792                 while(sfbeg(p) == 0 && (c = sbackc(p)) == 0)
1793                         ;
1794                 if(c != 0)
1795                         salterc(p,c);
1796                 truncate(p);
1797         }
1798         fsfile(p);
1799         if(sfbeg(p) == 0 && sbackc(p) == -1) {
1800                 while((c = sbackc(p)) == 99) {
1801                         if(c == -1)
1802                                 break;
1803                 }
1804                 skipc(p);
1805                 salterc(p,-1);
1806                 truncate(p);
1807         }
1808         return(p);
1809 }
1810
1811 int
1812 eqk(void)
1813 {
1814         Blk *p, *q;
1815         int skp, skq;
1816
1817         p = pop();
1818         EMPTYS;
1819         q = pop();
1820         EMPTYSR(p);
1821         skp = sunputc(p);
1822         skq = sunputc(q);
1823         if(skp == skq) {
1824                 arg1=p;
1825                 arg2=q;
1826                 savk = skp;
1827                 return(0);
1828         }
1829         if(skp < skq) {
1830                 savk = skq;
1831                 p = add0(p,skq-skp);
1832         } else {
1833                 savk = skp;
1834                 q = add0(q,skp-skq);
1835         }
1836         arg1=p;
1837         arg2=q;
1838         return(0);
1839 }
1840
1841 Blk*
1842 removc(Blk *p, int n)
1843 {
1844         Blk *q, *r;
1845
1846         rewind(p);
1847         while(n>1) {
1848                 skipc(p);
1849                 n -= 2;
1850         }
1851         q = salloc(2);
1852         while(sfeof(p) == 0)
1853                 sputc(q,sgetc(p));
1854         if(n == 1) {
1855                 r = div(q,tenptr);
1856                 release(q);
1857                 release(rem);
1858                 q = r;
1859         }
1860         release(p);
1861         return(q);
1862 }
1863
1864 Blk*
1865 scalint(Blk *p)
1866 {
1867         int n;
1868
1869         n = sunputc(p);
1870         p = removc(p,n);
1871         return(p);
1872 }
1873
1874 Blk*
1875 scale(Blk *p, int n)
1876 {
1877         Blk *q, *s, *t;
1878
1879         t = add0(p,n);
1880         q = salloc(1);
1881         sputc(q,n);
1882         s = dcexp(inbas,q);
1883         release(q);
1884         q = div(t,s);
1885         release(t);
1886         release(s);
1887         release(rem);
1888         sputc(q,n);
1889         return(q);
1890 }
1891
1892 int
1893 subt(void)
1894 {
1895         arg1=pop();
1896         EMPTYS;
1897         savk = sunputc(arg1);
1898         chsign(arg1);
1899         sputc(arg1,savk);
1900         pushp(arg1);
1901         if(eqk() != 0)
1902                 return(1);
1903         binop('+');
1904         return(0);
1905 }
1906
1907 int
1908 command(void)
1909 {
1910         char line[100], *sl;
1911         int pid, p, c;
1912
1913         switch(c = readc()) {
1914         case '<':
1915                 return(cond(NL));
1916         case '>':
1917                 return(cond(NG));
1918         case '=':
1919                 return(cond(NE));
1920         default:
1921                 sl = line;
1922                 *sl++ = c;
1923                 while((c = readc()) != '\n')
1924                         *sl++ = c;
1925                 *sl = 0;
1926                 if((pid = fork()) == 0) {
1927                         execl("/bin/rc","rc","-c",line,nil);
1928                         exits("shell");
1929                 }
1930                 for(;;) {
1931                         if((p = waitpid()) < 0)
1932                                 break;
1933                         if(p== pid)
1934                                 break;
1935                 }
1936                 Bprint(&bout,"!\n");
1937                 return(0);
1938         }
1939 }
1940
1941 int
1942 cond(char c)
1943 {
1944         Blk *p;
1945         int cc;
1946
1947         if(subt() != 0)
1948                 return(1);
1949         p = pop();
1950         sclobber(p);
1951         if(length(p) == 0) {
1952                 release(p);
1953                 if(c == '<' || c == '>' || c == NE) {
1954                         getstk();
1955                         return(0);
1956                 }
1957                 load();
1958                 return(1);
1959         }
1960         if(c == '='){
1961                 release(p);
1962                 getstk();
1963                 return(0);
1964         }
1965         if(c == NE) {
1966                 release(p);
1967                 load();
1968                 return(1);
1969         }
1970         fsfile(p);
1971         cc = sbackc(p);
1972         release(p);
1973         if((cc<0 && (c == '<' || c == NG)) ||
1974            (cc >0) && (c == '>' || c == NL)) {
1975                 getstk();
1976                 return(0);
1977         }
1978         load();
1979         return(1);
1980 }
1981
1982 void
1983 load(void)
1984 {
1985         int c;
1986         Blk *p, *q, *t, *s;
1987
1988         c = getstk() & 0377;
1989         sptr = stable[c];
1990         if(sptr != 0) {
1991                 p = sptr->val;
1992                 if(c >= ARRAYST) {
1993                         q = salloc(length(p));
1994                         rewind(p);
1995                         while(sfeof(p) == 0) {
1996                                 s = dcgetwd(p);
1997                                 if(s == 0) {
1998                                         putwd(q, (Blk*)0);
1999                                 } else {
2000                                         t = copy(s,length(s));
2001                                         putwd(q,t);
2002                                 }
2003                         }
2004                         pushp(q);
2005                 } else {
2006                         q = copy(p,length(p));
2007                         pushp(q);
2008                 }
2009         } else {
2010                 q = salloc(1);
2011                 if(c <= LASTFUN) {
2012                         Bprint(&bout,"function %c undefined\n",c+'a'-1);
2013                         sputc(q,'c');
2014                         sputc(q,'0');
2015                         sputc(q,' ');
2016                         sputc(q,'1');
2017                         sputc(q,'Q');
2018                 }
2019                 else
2020                         sputc(q,0);
2021                 pushp(q);
2022         }
2023 }
2024
2025 int
2026 log2(long n)
2027 {
2028         int i;
2029
2030         if(n == 0)
2031                 return(0);
2032         i=31;
2033         if(n<0)
2034                 return(i);
2035         while((n <<= 1) > 0)
2036                 i--;
2037         return i-1;
2038 }
2039
2040 Blk*
2041 salloc(int size)
2042 {
2043         Blk *hdr;
2044         char *ptr;
2045
2046         all++;
2047         lall++;
2048         if(all - rel > active)
2049                 active = all - rel;
2050         nbytes += size;
2051         lbytes += size;
2052         if(nbytes >maxsize)
2053                 maxsize = nbytes;
2054         if(size > longest)
2055                 longest = size;
2056         ptr = malloc((unsigned)size);
2057         if(ptr == 0){
2058                 garbage("salloc");
2059                 if((ptr = malloc((unsigned)size)) == 0)
2060                         ospace("salloc");
2061         }
2062         if((hdr = hfree) == 0)
2063                 hdr = morehd();
2064         hfree = (Blk *)hdr->rd;
2065         hdr->rd = hdr->wt = hdr->beg = ptr;
2066         hdr->last = ptr+size;
2067         return(hdr);
2068 }
2069
2070 Blk*
2071 morehd(void)
2072 {
2073         Blk *h, *kk;
2074
2075         headmor++;
2076         nbytes += HEADSZ;
2077         hfree = h = (Blk *)malloc(HEADSZ);
2078         if(hfree == 0) {
2079                 garbage("morehd");
2080                 if((hfree = h = (Blk*)malloc(HEADSZ)) == 0)
2081                         ospace("headers");
2082         }
2083         kk = h;
2084         while(h<hfree+(HEADSZ/BLK))
2085                 (h++)->rd = (char*)++kk;
2086         (h-1)->rd=0;
2087         return(hfree);
2088 }
2089
2090 Blk*
2091 copy(Blk *hptr, int size)
2092 {
2093         Blk *hdr;
2094         unsigned sz;
2095         char *ptr;
2096
2097         all++;
2098         lall++;
2099         lcopy++;
2100         nbytes += size;
2101         lbytes += size;
2102         if(size > longest)
2103                 longest = size;
2104         if(size > maxsize)
2105                 maxsize = size;
2106         sz = length(hptr);
2107         ptr = malloc(size);
2108         if(ptr == 0) {
2109                 Bprint(&bout,"copy size %d\n",size);
2110                 ospace("copy");
2111         }
2112         memmove(ptr, hptr->beg, sz);
2113         if (size-sz > 0)
2114                 memset(ptr+sz, 0, size-sz);
2115         if((hdr = hfree) == 0)
2116                 hdr = morehd();
2117         hfree = (Blk *)hdr->rd;
2118         hdr->rd = hdr->beg = ptr;
2119         hdr->last = ptr+size;
2120         hdr->wt = ptr+sz;
2121         ptr = hdr->wt;
2122         while(ptr<hdr->last)
2123                 *ptr++ = '\0';
2124         return(hdr);
2125 }
2126
2127 void
2128 sdump(char *s1, Blk *hptr)
2129 {
2130         char *p;
2131
2132         if(hptr == nil) {
2133                 Bprint(&bout, "%s no block\n", s1);
2134                 return;
2135         }
2136         Bprint(&bout,"%s %lx rd %lx wt %lx beg %lx last %lx\n",
2137                 s1,hptr,hptr->rd,hptr->wt,hptr->beg,hptr->last);
2138         p = hptr->beg;
2139         while(p < hptr->wt)
2140                 Bprint(&bout,"%d ",*p++);
2141         Bprint(&bout,"\n");
2142 }
2143
2144 void
2145 seekc(Blk *hptr, int n)
2146 {
2147         char *nn,*p;
2148
2149         nn = hptr->beg+n;
2150         if(nn > hptr->last) {
2151                 nbytes += nn - hptr->last;
2152                 if(nbytes > maxsize)
2153                         maxsize = nbytes;
2154                 lbytes += nn - hptr->last;
2155                 if(n > longest)
2156                         longest = n;
2157 /*              free(hptr->beg); /**/
2158                 p = realloc(hptr->beg, n);
2159                 if(p == 0) {
2160 /*                      hptr->beg = realloc(hptr->beg, hptr->last-hptr->beg);
2161 **                      garbage("seekc");
2162 **                      if((p = realloc(hptr->beg, n)) == 0)
2163 */                              ospace("seekc");
2164                 }
2165                 hptr->beg = p;
2166                 hptr->wt = hptr->last = hptr->rd = p+n;
2167                 return;
2168         }
2169         hptr->rd = nn;
2170         if(nn>hptr->wt)
2171                 hptr->wt = nn;
2172 }
2173
2174 void
2175 salterwd(Blk *ahptr, Blk *n)
2176 {
2177         Wblk *hptr;
2178
2179         hptr = (Wblk*)ahptr;
2180         if(hptr->rdw == hptr->lastw)
2181                 more(ahptr);
2182         *hptr->rdw++ = n;
2183         if(hptr->rdw > hptr->wtw)
2184                 hptr->wtw = hptr->rdw;
2185 }
2186
2187 void
2188 more(Blk *hptr)
2189 {
2190         unsigned size;
2191         char *p;
2192
2193         if((size=(hptr->last-hptr->beg)*2) == 0)
2194                 size=2;
2195         nbytes += size/2;
2196         if(nbytes > maxsize)
2197                 maxsize = nbytes;
2198         if(size > longest)
2199                 longest = size;
2200         lbytes += size/2;
2201         lmore++;
2202 /*      free(hptr->beg);/**/
2203         p = realloc(hptr->beg, size);
2204
2205         if(p == 0) {
2206 /*              hptr->beg = realloc(hptr->beg, (hptr->last-hptr->beg));
2207 **              garbage("more");
2208 **              if((p = realloc(hptr->beg,size)) == 0)
2209 */                      ospace("more");
2210         }
2211         hptr->rd = p + (hptr->rd - hptr->beg);
2212         hptr->wt = p + (hptr->wt - hptr->beg);
2213         hptr->beg = p;
2214         hptr->last = p+size;
2215 }
2216
2217 void
2218 ospace(char *s)
2219 {
2220         Bprint(&bout,"out of space: %s\n",s);
2221         Bprint(&bout,"all %ld rel %ld headmor %ld\n",all,rel,headmor);
2222         Bprint(&bout,"nbytes %ld\n",nbytes);
2223         sdump("stk",*stkptr);
2224         abort();
2225 }
2226
2227 void
2228 garbage(char *s)
2229 {
2230         USED(s);
2231 }
2232
2233 void
2234 release(Blk *p)
2235 {
2236         rel++;
2237         lrel++;
2238         nbytes -= p->last - p->beg;
2239         p->rd = (char*)hfree;
2240         hfree = p;
2241         free(p->beg);
2242 }
2243
2244 Blk*
2245 dcgetwd(Blk *p)
2246 {
2247         Wblk *wp;
2248
2249         wp = (Wblk*)p;
2250         if(wp->rdw == wp->wtw)
2251                 return(0);
2252         return(*wp->rdw++);
2253 }
2254
2255 void
2256 putwd(Blk *p, Blk *c)
2257 {
2258         Wblk *wp;
2259
2260         wp = (Wblk*)p;
2261         if(wp->wtw == wp->lastw)
2262                 more(p);
2263         *wp->wtw++ = c;
2264 }
2265
2266 Blk*
2267 lookwd(Blk *p)
2268 {
2269         Wblk *wp;
2270
2271         wp = (Wblk*)p;
2272         if(wp->rdw == wp->wtw)
2273                 return(0);
2274         return(*wp->rdw);
2275 }
2276
2277 int
2278 getstk(void)
2279 {
2280         int n;
2281         uchar c;
2282
2283         c = readc();
2284         if(c != '<')
2285                 return c;
2286         n = 0;
2287         while(1) {
2288                 c = readc();
2289                 if(c == '>')
2290                         break;
2291                 n = n*10+c-'0';
2292         }
2293         return n;
2294 }