| dc.c - 9base - revived minimalist port of Plan 9 userland to Unix | |
| git clone git://git.suckless.org/9base | |
| Log | |
| Files | |
| Refs | |
| README | |
| LICENSE | |
| --- | |
| dc.c (36375B) | |
| --- | |
| 1 #include <u.h> | |
| 2 #include <libc.h> | |
| 3 #include <bio.h> | |
| 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(… | |
| 46 #define TEST2 {if((count -= 2) <=0){Bprint(&bout,"\\\n");… | |
| 47 #define EMPTY if(stkerr != 0){Bprint(&bout,"stack empty\n… | |
| 48 #define EMPTYR(x) if(stkerr!=0){pushp(x);Bprint(&bout,"stack empt… | |
| 49 #define EMPTYS if(stkerr != 0){Bprint(&bout,"stack empty\… | |
| 50 #define EMPTYSR(x) if(stkerr !=0){Bprint(&bout,"stack empty\n");p… | |
| 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",al… | |
| 221 Bprint(&bout, "nbytes %ld\n",nbytes); | |
| 222 Bprint(&bout, "longest %ld active %ld maxsize %l… | |
| 223 active, maxsize); | |
| 224 Bprint(&bout, "new all %d rel %d copy %d more %d… | |
| 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<sk2) | |
| 257 sk = sk2; | |
| 258 if(sk<k) | |
| 259 sk = k; | |
| 260 p = removc(p,savk-sk); | |
| 261 savk = sk; | |
| 262 sputc(p,savk); | |
| 263 } | |
| 264 pushp(p); | |
| 265 continue; | |
| 266 case '/': | |
| 267 casediv: | |
| 268 if(dscale() != 0) | |
| 269 continue; | |
| 270 binop('/'); | |
| 271 if(irem != 0) | |
| 272 release(irem); | |
| 273 release(rem); | |
| 274 continue; | |
| 275 case '%': | |
| 276 if(dscale() != 0) | |
| 277 continue; | |
| 278 binop('/'); | |
| 279 p = pop(); | |
| 280 release(p); | |
| 281 if(irem == 0) { | |
| 282 sputc(rem,skr+k); | |
| 283 pushp(rem); | |
| 284 continue; | |
| 285 } | |
| 286 p = add0(rem,skd-(skr+k)); | |
| 287 q = add(p,irem); | |
| 288 release(p); | |
| 289 release(irem); | |
| 290 sputc(q,skd); | |
| 291 pushp(q); | |
| 292 continue; | |
| 293 case 'v': | |
| 294 p = pop(); | |
| 295 EMPTY; | |
| 296 savk = sunputc(p); | |
| 297 if(length(p) == 0) { | |
| 298 sputc(p,savk); | |
| 299 pushp(p); | |
| 300 continue; | |
| 301 } | |
| 302 if(sbackc(p)<0) { | |
| 303 error("sqrt of neg number\n"); | |
| 304 } | |
| 305 if(k<savk) | |
| 306 n = savk; | |
| 307 else { | |
| 308 n = k*2-savk; | |
| 309 savk = k; | |
| 310 } | |
| 311 arg1 = add0(p,n); | |
| 312 arg2 = dcsqrt(arg1); | |
| 313 sputc(arg2,savk); | |
| 314 pushp(arg2); | |
| 315 continue; | |
| 316 | |
| 317 case '^': | |
| 318 neg = 0; | |
| 319 arg1 = pop(); | |
| 320 EMPTY; | |
| 321 if(sunputc(arg1) != 0) | |
| 322 error("exp not an integer\n"); | |
| 323 arg2 = pop(); | |
| 324 EMPTYR(arg1); | |
| 325 if(sfbeg(arg1) == 0 && sbackc(arg1)<0) { | |
| 326 neg++; | |
| 327 chsign(arg1); | |
| 328 } | |
| 329 if(length(arg1)>=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 -… | |
| 345 if(k>=savk) | |
| 346 n = k; | |
| 347 else | |
| 348 n = savk; | |
| 349 if(n<d) { | |
| 350 q = removc(p,d-n); | |
| 351 sputc(q,n); | |
| 352 pushp(q); | |
| 353 } else { | |
| 354 sputc(p,d); | |
| 355 pushp(p); | |
| 356 } | |
| 357 /* } else { this is disaster for exp <-127 */ | |
| 358 /* sputc(p,d); */ | |
| 359 /* pushp(p); */ | |
| 360 /* } */ | |
| 361 if(neg == 0) | |
| 362 continue; | |
| 363 p = pop(); | |
| 364 q = salloc(2); | |
| 365 sputc(q,1); | |
| 366 sputc(q,0); | |
| 367 pushp(q); | |
| 368 pushp(p); | |
| 369 goto casediv; | |
| 370 case 'z': | |
| 371 p = salloc(2); | |
| 372 n = stkptr - stkbeg; | |
| 373 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 e… | |
| 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 corru… | |
| 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 unde… | |
| 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(h<hfree+(HEADSZ/BLK)) | |
| 2083 (h++)->rd = (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(ptr<hdr->last) | |
| 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… | |
| 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 } |