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