xref: /original-bsd/usr.bin/dc/dc.c (revision a76afa45)
1 #ifndef lint
2 static char sccsid[] = "@(#)dc.c	4.6	(Berkeley)	05/11/89";
3 #endif not lint
4 
5 #include <paths.h>
6 #include <sys/signal.h>
7 #include <stdio.h>
8 #include "dc.h"
9 
10 main(argc,argv)
11 int argc;
12 char *argv[];
13 {
14 	init(argc,argv);
15 	commnds();
16 }
17 commnds(){
18 	register int c;
19 	register struct blk *p,*q;
20 	long l;
21 	int sign;
22 	struct blk **ptr,*s,*t;
23 	struct sym *sp;
24 	int sk,sk1,sk2;
25 	int n,d;
26 
27 	while(1){
28 		if(((c = readc())>='0' && c <= '9')|| (c>='A' && c <='F') || c == '.'){
29 			unreadc(c);
30 			p = readin();
31 			pushp(p);
32 			continue;
33 		}
34 		switch(c){
35 		case ' ':
36 		case '\n':
37 		case 0377:
38 		case EOF:
39 			continue;
40 		case 'Y':
41 			sdump("stk",*stkptr);
42 			printf("all %ld rel %ld headmor %ld\n",all,rel,headmor);
43 			printf("nbytes %ld\n",nbytes);
44 			continue;
45 		case '_':
46 			p = readin();
47 			savk = sunputc(p);
48 			chsign(p);
49 			sputc(p,savk);
50 			pushp(p);
51 			continue;
52 		case '-':
53 			subt();
54 			continue;
55 		case '+':
56 			if(eqk() != 0)continue;
57 			binop('+');
58 			continue;
59 		case '*':
60 			arg1 = pop();
61 			EMPTY;
62 			arg2 = pop();
63 			EMPTYR(arg1);
64 			sk1 = sunputc(arg1);
65 			sk2 = sunputc(arg2);
66 			binop('*');
67 			p = pop();
68 			sunputc(p);
69 			savk = n = sk1+sk2;
70 			if(n>k && n>sk1 && n>sk2){
71 				sk = sk1;
72 				if(sk<sk2)sk = sk2;
73 				if(sk<k)sk = k;
74 				p = removc(p,n-sk);
75 				savk = sk;
76 			}
77 			sputc(p,savk);
78 			pushp(p);
79 			continue;
80 		case '/':
81 casediv:
82 			if(dscale() != 0)continue;
83 			binop('/');
84 			if(irem != 0)release(irem);
85 			release(rem);
86 			continue;
87 		case '%':
88 			if(dscale() != 0)continue;
89 			binop('/');
90 			p = pop();
91 			release(p);
92 			if(irem == 0){
93 				sputc(rem,skr+k);
94 				pushp(rem);
95 				continue;
96 			}
97 			p = add0(rem,skd-(skr+k));
98 			q = add(p,irem);
99 			release(p);
100 			release(irem);
101 			sputc(q,skd);
102 			pushp(q);
103 			continue;
104 		case 'v':
105 			p = pop();
106 			EMPTY;
107 			savk = sunputc(p);
108 			if(length(p) == 0){
109 				sputc(p,savk);
110 				pushp(p);
111 				continue;
112 			}
113 			if((c = sbackc(p))<0){
114 				error("sqrt of neg number\n");
115 			}
116 			if(k<savk)n = savk;
117 			else{
118 				n = k*2-savk;
119 				savk = k;
120 			}
121 			arg1 = add0(p,n);
122 			arg2 = sqrt(arg1);
123 			sputc(arg2,savk);
124 			pushp(arg2);
125 			continue;
126 		case '^':
127 			neg = 0;
128 			arg1 = pop();
129 			EMPTY;
130 			if(sunputc(arg1) != 0)error("exp not an integer\n");
131 			arg2 = pop();
132 			EMPTYR(arg1);
133 			if(sfbeg(arg1) == 0 && sbackc(arg1)<0){
134 				neg++;
135 				chsign(arg1);
136 			}
137 			if(length(arg1)>=3){
138 				error("exp too big\n");
139 			}
140 			savk = sunputc(arg2);
141 			p = exp(arg2,arg1);
142 			release(arg2);
143 			rewind(arg1);
144 			c = sgetc(arg1);
145 			if(sfeof(arg1) == 0)
146 				c = sgetc(arg1)*100 + c;
147 			d = c*savk;
148 			release(arg1);
149 			if(neg == 0){
150 				if(k>=savk)n = k;
151 				else n = savk;
152 				if(n<d){
153 					q = removc(p,d-n);
154 					sputc(q,n);
155 					pushp(q);
156 				}
157 				else {
158 					sputc(p,d);
159 					pushp(p);
160 				}
161 			}
162 			else {
163 				sputc(p,d);
164 				pushp(p);
165 			}
166 			if(neg == 0)continue;
167 			p = pop();
168 			q = salloc(2);
169 			sputc(q,1);
170 			sputc(q,0);
171 			pushp(q);
172 			pushp(p);
173 			goto casediv;
174 		case 'z':
175 			p = salloc(2);
176 			n = stkptr - stkbeg;
177 			if(n >= 100){
178 				sputc(p,n/100);
179 				n %= 100;
180 			}
181 			sputc(p,n);
182 			sputc(p,0);
183 			pushp(p);
184 			continue;
185 		case 'Z':
186 			p = pop();
187 			EMPTY;
188 			n = (length(p)-1)<<1;
189 			fsfile(p);
190 			sbackc(p);
191 			if(sfbeg(p) == 0){
192 				if((c = sbackc(p))<0){
193 					n -= 2;
194 					if(sfbeg(p) == 1)n += 1;
195 					else {
196 						if((c = sbackc(p)) == 0)n += 1;
197 						else if(c > 90)n -= 1;
198 					}
199 				}
200 				else if(c < 10) n -= 1;
201 			}
202 			release(p);
203 			q = salloc(1);
204 			if(n >= 100){
205 				sputc(q,n%100);
206 				n /= 100;
207 			}
208 			sputc(q,n);
209 			sputc(q,0);
210 			pushp(q);
211 			continue;
212 		case 'i':
213 			p = pop();
214 			EMPTY;
215 			p = scalint(p);
216 			release(inbas);
217 			inbas = p;
218 			continue;
219 		case 'I':
220 			p = copy(inbas,length(inbas)+1);
221 			sputc(p,0);
222 			pushp(p);
223 			continue;
224 		case 'o':
225 			p = pop();
226 			EMPTY;
227 			p = scalint(p);
228 			sign = 0;
229 			n = length(p);
230 			q = copy(p,n);
231 			fsfile(q);
232 			l = c = sbackc(q);
233 			if(n != 1){
234 				if(c<0){
235 					sign = 1;
236 					chsign(q);
237 					n = length(q);
238 					fsfile(q);
239 					l = c = sbackc(q);
240 				}
241 				if(n != 1){
242 					while(sfbeg(q) == 0)l = l*100+sbackc(q);
243 				}
244 			}
245 			logo = log2(l);
246 			obase = l;
247 			release(basptr);
248 			if(sign == 1)obase = -l;
249 			basptr = p;
250 			outdit = bigot;
251 			if(n == 1 && sign == 0){
252 				if(c <= 16){
253 					outdit = hexot;
254 					fw = 1;
255 					fw1 = 0;
256 					ll = 70;
257 					release(q);
258 					continue;
259 				}
260 			}
261 			n = 0;
262 			if(sign == 1)n++;
263 			p = salloc(1);
264 			sputc(p,-1);
265 			t = add(p,q);
266 			n += length(t)*2;
267 			fsfile(t);
268 			if((c = sbackc(t))>9)n++;
269 			release(t);
270 			release(q);
271 			release(p);
272 			fw = n;
273 			fw1 = n-1;
274 			ll = 70;
275 			if(fw>=ll)continue;
276 			ll = (70/fw)*fw;
277 			continue;
278 		case 'O':
279 			p = copy(basptr,length(basptr)+1);
280 			sputc(p,0);
281 			pushp(p);
282 			continue;
283 		case '[':
284 			n = 0;
285 			p = salloc(0);
286 			while(1){
287 				if((c = readc()) == ']'){
288 					if(n == 0)break;
289 					n--;
290 				}
291 				sputc(p,c);
292 				if(c == '[')n++;
293 			}
294 			pushp(p);
295 			continue;
296 		case 'k':
297 			p = pop();
298 			EMPTY;
299 			p = scalint(p);
300 			if(length(p)>1){
301 				error("scale too big\n");
302 			}
303 			rewind(p);
304 			k = sfeof(p)?0:sgetc(p);
305 			release(scalptr);
306 			scalptr = p;
307 			continue;
308 		case 'K':
309 			p = copy(scalptr,length(scalptr)+1);
310 			sputc(p,0);
311 			pushp(p);
312 			continue;
313 		case 'X':
314 			p = pop();
315 			EMPTY;
316 			fsfile(p);
317 			n = sbackc(p);
318 			release(p);
319 			p = salloc(2);
320 			sputc(p,n);
321 			sputc(p,0);
322 			pushp(p);
323 			continue;
324 		case 'Q':
325 			p = pop();
326 			EMPTY;
327 			if(length(p)>2){
328 				error("Q?\n");
329 			}
330 			rewind(p);
331 			if((c =  sgetc(p))<0){
332 				error("neg Q\n");
333 			}
334 			release(p);
335 			while(c-- > 0){
336 				if(readptr == &readstk[0]){
337 					error("readstk?\n");
338 				}
339 				if(*readptr != 0)release(*readptr);
340 				readptr--;
341 			}
342 			continue;
343 		case 'q':
344 			if(readptr <= &readstk[1])exit(0);
345 			if(*readptr != 0)release(*readptr);
346 			readptr--;
347 			if(*readptr != 0)release(*readptr);
348 			readptr--;
349 			continue;
350 		case 'f':
351 			if(stkptr == &stack[0])printf("empty stack\n");
352 			else {
353 				for(ptr = stkptr; ptr > &stack[0];){
354 					print(*ptr--);
355 				}
356 			}
357 			continue;
358 		case 'p':
359 			if(stkptr == &stack[0])printf("empty stack\n");
360 			else{
361 				print(*stkptr);
362 			}
363 			continue;
364 		case 'P':
365 			p = pop();
366 			EMPTY;
367 			sputc(p,0);
368 			printf("%s",p->beg);
369 			release(p);
370 			continue;
371 		case 'd':
372 			if(stkptr == &stack[0]){
373 				printf("empty stack\n");
374 				continue;
375 			}
376 			q = *stkptr;
377 			n = length(q);
378 			p = copy(*stkptr,n);
379 			pushp(p);
380 			continue;
381 		case 'c':
382 			while(stkerr == 0){
383 				p = pop();
384 				if(stkerr == 0)release(p);
385 			}
386 			continue;
387 		case 'S':
388 			if(stkptr == &stack[0]){
389 				error("save: args\n");
390 			}
391 			c = readc() & 0377;
392 			sptr = stable[c];
393 			sp = stable[c] = sfree;
394 			sfree = sfree->next;
395 			if(sfree == 0)goto sempty;
396 			sp->next = sptr;
397 			p = pop();
398 			EMPTY;
399 			if(c >= ARRAYST){
400 				q = copy(p,PTRSZ);
401 				for(n = 0;n < PTRSZ-1;n++)sputc(q,0);
402 				release(p);
403 				p = q;
404 			}
405 			sp->val = p;
406 			continue;
407 sempty:
408 			error("symbol table overflow\n");
409 		case 's':
410 			if(stkptr == &stack[0]){
411 				error("save:args\n");
412 			}
413 			c = readc() & 0377;
414 			sptr = stable[c];
415 			if(sptr != 0){
416 				p = sptr->val;
417 				if(c >= ARRAYST){
418 					rewind(p);
419 					while(sfeof(p) == 0)release(getwd(p));
420 				}
421 				release(p);
422 			}
423 			else{
424 				sptr = stable[c] = sfree;
425 				sfree = sfree->next;
426 				if(sfree == 0)goto sempty;
427 				sptr->next = 0;
428 			}
429 			p = pop();
430 			sptr->val = p;
431 			continue;
432 		case 'l':
433 			load();
434 			continue;
435 		case 'L':
436 			c = readc() & 0377;
437 			sptr = stable[c];
438 			if(sptr == 0){
439 				error("L?\n");
440 			}
441 			stable[c] = sptr->next;
442 			sptr->next = sfree;
443 			sfree = sptr;
444 			p = sptr->val;
445 			if(c >= ARRAYST){
446 				rewind(p);
447 				while(sfeof(p) == 0){
448 					q = getwd(p);
449 					if(q != 0)release(q);
450 				}
451 			}
452 			pushp(p);
453 			continue;
454 		case ':':
455 			p = pop();
456 			EMPTY;
457 			q = scalint(p);
458 			fsfile(q);
459 			c = 0;
460 			if((sfbeg(q) == 0) && ((c = sbackc(q))<0)){
461 				error("neg index\n");
462 			}
463 			if(length(q)>2){
464 				error("index too big\n");
465 			}
466 			if(sfbeg(q) == 0)c = c*100+sbackc(q);
467 			if(c >= MAXIND){
468 				error("index too big\n");
469 			}
470 			release(q);
471 			n = readc() & 0377;
472 			sptr = stable[n];
473 			if(sptr == 0){
474 				sptr = stable[n] = sfree;
475 				sfree = sfree->next;
476 				if(sfree == 0)goto sempty;
477 				sptr->next = 0;
478 				p = salloc((c+PTRSZ)*PTRSZ);
479 				zero(p);
480 			}
481 			else{
482 				p = sptr->val;
483 				if(length(p)-PTRSZ < c*PTRSZ){
484 					q = copy(p,(c+PTRSZ)*PTRSZ);
485 					release(p);
486 					p = q;
487 				}
488 			}
489 			seekc(p,c*PTRSZ);
490 			q = lookwd(p);
491 			if (q!=NULL) release(q);
492 			s = pop();
493 			EMPTY;
494 			salterwd(p,s);
495 			sptr->val = p;
496 			continue;
497 		case ';':
498 			p = pop();
499 			EMPTY;
500 			q = scalint(p);
501 			fsfile(q);
502 			c = 0;
503 			if((sfbeg(q) == 0) && ((c = sbackc(q))<0)){
504 				error("neg index\n");
505 			}
506 			if(length(q)>2){
507 				error("index too big\n");
508 			}
509 			if(sfbeg(q) == 0)c = c*100+sbackc(q);
510 			if(c >= MAXIND){
511 				error("index too big\n");
512 			}
513 			release(q);
514 			n = readc() & 0377;
515 			sptr = stable[n];
516 			if(sptr != 0){
517 				p = sptr->val;
518 				if(length(p)-PTRSZ >= c*PTRSZ){
519 					seekc(p,c*PTRSZ);
520 					s = getwd(p);
521 					if(s != 0){
522 						q = copy(s,length(s));
523 						pushp(q);
524 						continue;
525 					}
526 				}
527 			}
528 			q = salloc(PTRSZ);
529 			putwd(q, (struct blk *)0);
530 			pushp(q);
531 			continue;
532 		case 'x':
533 execute:
534 			p = pop();
535 			EMPTY;
536 			if((readptr != &readstk[0]) && (*readptr != 0)){
537 				if((*readptr)->rd == (*readptr)->wt)
538 					release(*readptr);
539 				else{
540 					if(readptr++ == &readstk[RDSKSZ]){
541 						error("nesting depth\n");
542 					}
543 				}
544 			}
545 			else readptr++;
546 			*readptr = p;
547 			if(p != 0)rewind(p);
548 			else{
549 				if((c = readc()) != '\n')unreadc(c);
550 			}
551 			continue;
552 		case '?':
553 			if(++readptr == &readstk[RDSKSZ]){
554 				error("nesting depth\n");
555 			}
556 			*readptr = 0;
557 			fsave = curfile;
558 			curfile = stdin;
559 			while((c = readc()) == '!')command();
560 			p = salloc(0);
561 			sputc(p,c);
562 			while((c = readc()) != '\n'){
563 				sputc(p,c);
564 				if(c == '\\')sputc(p,readc());
565 			}
566 			curfile = fsave;
567 			*readptr = p;
568 			continue;
569 		case '!':
570 			if(command() == 1)goto execute;
571 			continue;
572 		case '<':
573 		case '>':
574 		case '=':
575 			if(cond(c) == 1)goto execute;
576 			continue;
577 		default:
578 			printf("%o is unimplemented\n",c);
579 		}
580 	}
581 }
582 struct blk *
583 div(ddivd,ddivr)
584 struct blk *ddivd,*ddivr;
585 {
586 	int divsign,remsign,offset,divcarry;
587 	int carry, dig,magic,d,dd;
588 	long c,td,cc;
589 	struct blk *ps;
590 	register struct blk *p,*divd,*divr;
591 
592 	rem = 0;
593 	p = salloc(0);
594 	if(length(ddivr) == 0){
595 		pushp(ddivr);
596 		printf("divide by 0\n");
597 		return((struct blk *)1);
598 	}
599 	divsign = remsign = 0;
600 	divr = ddivr;
601 	fsfile(divr);
602 	if(sbackc(divr) == -1){
603 		divr = copy(ddivr,length(ddivr));
604 		chsign(divr);
605 		divsign = ~divsign;
606 	}
607 	divd = copy(ddivd,length(ddivd));
608 	fsfile(divd);
609 	if(sfbeg(divd) == 0 && sbackc(divd) == -1){
610 		chsign(divd);
611 		divsign = ~divsign;
612 		remsign = ~remsign;
613 	}
614 	offset = length(divd) - length(divr);
615 	if(offset < 0)goto ddone;
616 	seekc(p,offset+1);
617 	sputc(divd,0);
618 	magic = 0;
619 	fsfile(divr);
620 	c = sbackc(divr);
621 	if(c<10)magic++;
622 	c = c*100 + (sfbeg(divr)?0:sbackc(divr));
623 	if(magic>0){
624 		c = (c*100 +(sfbeg(divr)?0:sbackc(divr)))*2;
625 		c /= 25;
626 	}
627 	while(offset >= 0){
628 		fsfile(divd);
629 		td = sbackc(divd)*100;
630 		dd = sfbeg(divd)?0:sbackc(divd);
631 		td = (td+dd)*100;
632 		dd = sfbeg(divd)?0:sbackc(divd);
633 		td = td+dd;
634 		cc = c;
635 		if(offset == 0)td += 1;
636 		else cc += 1;
637 		if(magic != 0)td = td<<3;
638 		dig = td/cc;
639 		rewind(divr);
640 		rewind(divxyz);
641 		carry = 0;
642 		while(sfeof(divr) == 0){
643 			d = sgetc(divr)*dig+carry;
644 			carry = d / 100;
645 			salterc(divxyz,d%100);
646 		}
647 		salterc(divxyz,carry);
648 		rewind(divxyz);
649 		seekc(divd,offset);
650 		carry = 0;
651 		while(sfeof(divd) == 0){
652 			d = slookc(divd);
653 			d = d-(sfeof(divxyz)?0:sgetc(divxyz))-carry;
654 			carry = 0;
655 			if(d < 0){
656 				d += 100;
657 				carry = 1;
658 			}
659 			salterc(divd,d);
660 		}
661 		divcarry = carry;
662 		sbackc(p);
663 		salterc(p,dig);
664 		sbackc(p);
665 		if(--offset >= 0){
666 			if(d > 0){
667 				sbackc(divd);
668 				dd=sbackc(divd);
669 				salterc(divd,dd+100);
670 			}
671 			divd->wt--;
672 		}
673 	}
674 	if(divcarry != 0){
675 		salterc(p,dig-1);
676 		salterc(divd,-1);
677 		ps = add(divr,divd);
678 		release(divd);
679 		divd = ps;
680 	}
681 
682 	rewind(p);
683 	divcarry = 0;
684 	while(sfeof(p) == 0){
685 		d = slookc(p)+divcarry;
686 		divcarry = 0;
687 		if(d >= 100){
688 			d -= 100;
689 			divcarry = 1;
690 		}
691 		salterc(p,d);
692 	}
693 	if(divcarry != 0)salterc(p,divcarry);
694 	fsfile(p);
695 	while(sfbeg(p) == 0){
696 		if(sbackc(p) == 0)truncate(p);
697 		else break;
698 	}
699 	if(divsign < 0)chsign(p);
700 	fsfile(divd);
701 	while(sfbeg(divd) == 0){
702 		if(sbackc(divd) == 0)truncate(divd);
703 		else break;
704 	}
705 ddone:
706 	if(remsign<0)chsign(divd);
707 	if(divr != ddivr)release(divr);
708 	rem = divd;
709 	return(p);
710 }
711 dscale(){
712 	register struct blk *dd,*dr;
713 	register struct blk *r;
714 	int c;
715 
716 	dr = pop();
717 	EMPTYS;
718 	dd = pop();
719 	EMPTYSR(dr);
720 	fsfile(dd);
721 	skd = sunputc(dd);
722 	fsfile(dr);
723 	skr = sunputc(dr);
724 	if(sfbeg(dr) == 1 || (sfbeg(dr) == 0 && sbackc(dr) == 0)){
725 		sputc(dr,skr);
726 		pushp(dr);
727 		errorrt("divide by 0\n");
728 	}
729 	c = k-skd+skr;
730 	if(c < 0)r = removr(dd,-c);
731 	else {
732 		r = add0(dd,c);
733 		irem = 0;
734 	}
735 	arg1 = r;
736 	arg2 = dr;
737 	savk = k;
738 	return(0);
739 }
740 struct blk *
741 removr(p,n)
742 struct blk *p;
743 {
744 	int nn;
745 	register struct blk *q,*s,*r;
746 
747 	rewind(p);
748 	nn = (n+1)/2;
749 	q = salloc(nn);
750 	while(n>1){
751 		sputc(q,sgetc(p));
752 		n -= 2;
753 	}
754 	r = salloc(2);
755 	while(sfeof(p) == 0)sputc(r,sgetc(p));
756 	release(p);
757 	if(n == 1){
758 		s = div(r,tenptr);
759 		release(r);
760 		rewind(rem);
761 		if(sfeof(rem) == 0)sputc(q,sgetc(rem));
762 		release(rem);
763 		irem = q;
764 		return(s);
765 	}
766 	irem = q;
767 	return(r);
768 }
769 struct blk *
770 sqrt(p)
771 struct blk *p;
772 {
773 	struct blk *t;
774 	struct blk *r,*q,*s;
775 	int c,n,nn;
776 
777 	n = length(p);
778 	fsfile(p);
779 	c = sbackc(p);
780 	if((n&1) != 1)c = c*100+(sfbeg(p)?0:sbackc(p));
781 	n = (n+1)>>1;
782 	r = salloc(n);
783 	zero(r);
784 	seekc(r,n);
785 	nn=1;
786 	while((c -= nn)>=0)nn+=2;
787 	c=(nn+1)>>1;
788 	fsfile(r);
789 	sbackc(r);
790 	if(c>=100){
791 		c -= 100;
792 		salterc(r,c);
793 		sputc(r,1);
794 	}
795 	else salterc(r,c);
796 	while(1){
797 		q = div(p,r);
798 		s = add(q,r);
799 		release(q);
800 		release(rem);
801 		q = div(s,sqtemp);
802 		release(s);
803 		release(rem);
804 		s = copy(r,length(r));
805 		chsign(s);
806 		t = add(s,q);
807 		release(s);
808 		fsfile(t);
809 		nn = sfbeg(t)?0:sbackc(t);
810 		if(nn>=0)break;
811 		release(r);
812 		release(t);
813 		r = q;
814 	}
815 	release(t);
816 	release(q);
817 	release(p);
818 	return(r);
819 }
820 struct blk *
821 exp(base,ex)
822 struct blk *base,*ex;
823 {
824 	register struct blk *r,*e,*p;
825 	struct blk *e1,*t,*cp;
826 	int temp,c,n;
827 	r = salloc(1);
828 	sputc(r,1);
829 	p = copy(base,length(base));
830 	e = copy(ex,length(ex));
831 	fsfile(e);
832 	if(sfbeg(e) != 0)goto edone;
833 	temp=0;
834 	c = sbackc(e);
835 	if(c<0){
836 		temp++;
837 		chsign(e);
838 	}
839 	while(length(e) != 0){
840 		e1=div(e,sqtemp);
841 		release(e);
842 		e = e1;
843 		n = length(rem);
844 		release(rem);
845 		if(n != 0){
846 			e1=mult(p,r);
847 			release(r);
848 			r = e1;
849 		}
850 		t = copy(p,length(p));
851 		cp = mult(p,t);
852 		release(p);
853 		release(t);
854 		p = cp;
855 	}
856 	if(temp != 0){
857 		if((c = length(base)) == 0){
858 			goto edone;
859 		}
860 		if(c>1)create(r);
861 		else{
862 			rewind(base);
863 			if((c = sgetc(base))<=1){
864 				create(r);
865 				sputc(r,c);
866 			}
867 			else create(r);
868 		}
869 	}
870 edone:
871 	release(p);
872 	release(e);
873 	return(r);
874 }
875 init(argc,argv)
876 int argc;
877 char *argv[];
878 {
879 	register struct sym *sp;
880 
881 	if (signal(SIGINT, SIG_IGN) != SIG_IGN)
882 		signal(SIGINT,onintr);
883 	setbuf(stdout,(char *)NULL);
884 	svargc = --argc;
885 	svargv = argv;
886 	while(svargc>0 && svargv[1][0] == '-'){
887 		switch(svargv[1][1]){
888 		default:
889 			dbg=1;
890 		}
891 		svargc--;
892 		svargv++;
893 	}
894 	ifile=1;
895 	if(svargc<=0)curfile = stdin;
896 	else if((curfile = fopen(svargv[1],"r")) == NULL){
897 		printf("can't open file %s\n",svargv[1]);
898 		exit(1);
899 		}
900 	scalptr = salloc(1);
901 	sputc(scalptr,0);
902 	basptr = salloc(1);
903 	sputc(basptr,10);
904 	obase=10;
905 	log10=log2(10L);
906 	ll=70;
907 	fw=1;
908 	fw1=0;
909 	tenptr = salloc(1);
910 	sputc(tenptr,10);
911 	obase=10;
912 	inbas = salloc(1);
913 	sputc(inbas,10);
914 	sqtemp = salloc(1);
915 	sputc(sqtemp,2);
916 	chptr = salloc(0);
917 	strptr = salloc(0);
918 	divxyz = salloc(0);
919 	stkbeg = stkptr = &stack[0];
920 	stkend = &stack[STKSZ];
921 	stkerr = 0;
922 	readptr = &readstk[0];
923 	k=0;
924 	sp = sptr = &symlst[0];
925 	while(sptr < &symlst[TBLSZ-1]){
926 		sptr->next = ++sp;
927 		sptr++;
928 	}
929 	sptr->next=0;
930 	sfree = &symlst[0];
931 	return;
932 }
933 onintr(){
934 
935 	signal(SIGINT,onintr);
936 	while(readptr != &readstk[0]){
937 		if(*readptr != 0){release(*readptr);}
938 		readptr--;
939 	}
940 	curfile = stdin;
941 	commnds();
942 }
943 pushp(p)
944 struct blk *p;
945 {
946 	if(stkptr == stkend){
947 		printf("out of stack space\n");
948 		return;
949 	}
950 	stkerr=0;
951 	*++stkptr = p;
952 	return;
953 }
954 struct blk *
955 pop(){
956 	if(stkptr == stack){
957 		stkerr=1;
958 		return(0);
959 	}
960 	return(*stkptr--);
961 }
962 struct blk *
963 readin(){
964 	register struct blk *p,*q;
965 	int dp,dpct;
966 	register int c;
967 
968 	dp = dpct=0;
969 	p = salloc(0);
970 	while(1){
971 		c = readc();
972 		switch(c){
973 		case '.':
974 			if(dp != 0){
975 				unreadc(c);
976 				break;
977 			}
978 			dp++;
979 			continue;
980 		case '\\':
981 			readc();
982 			continue;
983 		default:
984 			if(c >= 'A' && c <= 'F')c = c - 'A' + 10;
985 			else if(c >= '0' && c <= '9')c -= '0';
986 			else goto gotnum;
987 			if(dp != 0){
988 				if(dpct >= 99)continue;
989 				dpct++;
990 			}
991 			create(chptr);
992 			if(c != 0)sputc(chptr,c);
993 			q = mult(p,inbas);
994 			release(p);
995 			p = add(chptr,q);
996 			release(q);
997 		}
998 	}
999 gotnum:
1000 	unreadc(c);
1001 	if(dp == 0){
1002 		sputc(p,0);
1003 		return(p);
1004 	}
1005 	else{
1006 		q = scale(p,dpct);
1007 		return(q);
1008 	}
1009 }
1010 struct blk *
1011 add0(p,ct)
1012 int ct;
1013 struct blk *p;
1014 {
1015 		/* returns pointer to struct with ct 0's & p */
1016 	register struct blk *q,*t;
1017 
1018 	q = salloc(length(p)+(ct+1)/2);
1019 	while(ct>1){
1020 		sputc(q,0);
1021 		ct -= 2;
1022 	}
1023 	rewind(p);
1024 	while(sfeof(p) == 0){
1025 		sputc(q,sgetc(p));
1026 	}
1027 	release(p);
1028 	if(ct == 1){
1029 		t = mult(tenptr,q);
1030 		release(q);
1031 		return(t);
1032 	}
1033 	return(q);
1034 }
1035 struct blk *
1036 mult(p,q)
1037 struct blk *p,*q;
1038 {
1039 	register struct blk *mp,*mq,*mr;
1040 	int sign,offset,carry;
1041 	int cq,cp,mt,mcr;
1042 
1043 	offset = sign = 0;
1044 	fsfile(p);
1045 	mp = p;
1046 	if(sfbeg(p) == 0){
1047 		if(sbackc(p)<0){
1048 			mp = copy(p,length(p));
1049 			chsign(mp);
1050 			sign = ~sign;
1051 		}
1052 	}
1053 	fsfile(q);
1054 	mq = q;
1055 	if(sfbeg(q) == 0){
1056 		if(sbackc(q)<0){
1057 			mq = copy(q,length(q));
1058 			chsign(mq);
1059 			sign = ~sign;
1060 		}
1061 	}
1062 	mr = salloc(length(mp)+length(mq));
1063 	zero(mr);
1064 	rewind(mq);
1065 	while(sfeof(mq) == 0){
1066 		cq = sgetc(mq);
1067 		rewind(mp);
1068 		rewind(mr);
1069 		mr->rd += offset;
1070 		carry=0;
1071 		while(sfeof(mp) == 0){
1072 			cp = sgetc(mp);
1073 			mcr = sfeof(mr)?0:slookc(mr);
1074 			mt = cp*cq + carry + mcr;
1075 			carry = mt/100;
1076 			salterc(mr,mt%100);
1077 		}
1078 		offset++;
1079 		if(carry != 0){
1080 			mcr = sfeof(mr)?0:slookc(mr);
1081 			salterc(mr,mcr+carry);
1082 		}
1083 	}
1084 	if(sign < 0){
1085 		chsign(mr);
1086 	}
1087 	if(mp != p)release(mp);
1088 	if(mq != q)release(mq);
1089 	return(mr);
1090 }
1091 chsign(p)
1092 struct blk *p;
1093 {
1094 	register int carry;
1095 	register char ct;
1096 
1097 	carry=0;
1098 	rewind(p);
1099 	while(sfeof(p) == 0){
1100 		ct=100-slookc(p)-carry;
1101 		carry=1;
1102 		if(ct>=100){
1103 			ct -= 100;
1104 			carry=0;
1105 		}
1106 		salterc(p,ct);
1107 	}
1108 	if(carry != 0){
1109 		sputc(p,-1);
1110 		fsfile(p);
1111 		sbackc(p);
1112 		ct = sbackc(p);
1113 		if(ct == 99){
1114 			truncate(p);
1115 			sputc(p,-1);
1116 		}
1117 	}
1118 	else{
1119 		fsfile(p);
1120 		ct = sbackc(p);
1121 		if(ct == 0)truncate(p);
1122 	}
1123 	return;
1124 }
1125 readc(){
1126 loop:
1127 	if((readptr != &readstk[0]) && (*readptr != 0)){
1128 		if(sfeof(*readptr) == 0)return(lastchar = sgetc(*readptr));
1129 		release(*readptr);
1130 		readptr--;
1131 		goto loop;
1132 	}
1133 	lastchar = getc(curfile);
1134 	if(lastchar != EOF)return(lastchar);
1135 	if(readptr != &readptr[0]){
1136 		readptr--;
1137 		if(*readptr == 0)curfile = stdin;
1138 		goto loop;
1139 	}
1140 	if(curfile != stdin){
1141 		fclose(curfile);
1142 		curfile = stdin;
1143 		goto loop;
1144 	}
1145 	exit(0);
1146 }
1147 unreadc(c)
1148 char c;
1149 {
1150 
1151 	if((readptr != &readstk[0]) && (*readptr != 0)){
1152 		sungetc(*readptr,c);
1153 	}
1154 	else ungetc(c,curfile);
1155 	return;
1156 }
1157 binop(c)
1158 char c;
1159 {
1160 	register struct blk *r;
1161 
1162 	switch(c){
1163 	case '+':
1164 		r = add(arg1,arg2);
1165 		break;
1166 	case '*':
1167 		r = mult(arg1,arg2);
1168 		break;
1169 	case '/':
1170 		r = div(arg1,arg2);
1171 		break;
1172 	}
1173 	release(arg1);
1174 	release(arg2);
1175 	sputc(r,savk);
1176 	pushp(r);
1177 	return;
1178 }
1179 print(hptr)
1180 struct blk *hptr;
1181 {
1182 	int sc;
1183 	register struct blk *p,*q,*dec;
1184 	int dig,dout,ct;
1185 
1186 	rewind(hptr);
1187 	while(sfeof(hptr) == 0){
1188 		if(sgetc(hptr)>99){
1189 			rewind(hptr);
1190 			while(sfeof(hptr) == 0){
1191 				printf("%c",sgetc(hptr));
1192 			}
1193 			printf("\n");
1194 			return;
1195 		}
1196 	}
1197 	fsfile(hptr);
1198 	sc = sbackc(hptr);
1199 	if(sfbeg(hptr) != 0){
1200 		printf("0\n");
1201 		return;
1202 	}
1203 	count = ll;
1204 	p = copy(hptr,length(hptr));
1205 	sunputc(p);
1206 	fsfile(p);
1207 	if(sbackc(p)<0){
1208 		chsign(p);
1209 		OUTC('-');
1210 	}
1211 	if((obase == 0) || (obase == -1)){
1212 		oneot(p,sc,'d');
1213 		return;
1214 	}
1215 	if(obase == 1){
1216 		oneot(p,sc,'1');
1217 		return;
1218 	}
1219 	if(obase == 10){
1220 		tenot(p,sc);
1221 		return;
1222 	}
1223 	create(strptr);
1224 	dig = log10*sc;
1225 	dout = ((dig/10) + dig) /logo;
1226 	dec = getdec(p,sc);
1227 	p = removc(p,sc);
1228 	while(length(p) != 0){
1229 		q = div(p,basptr);
1230 		release(p);
1231 		p = q;
1232 		(*outdit)(rem,0);
1233 	}
1234 	release(p);
1235 	fsfile(strptr);
1236 	while(sfbeg(strptr) == 0)OUTC(sbackc(strptr));
1237 	if(sc == 0){
1238 		release(dec);
1239 		printf("\n");
1240 		return;
1241 	}
1242 	create(strptr);
1243 	OUTC('.');
1244 	ct=0;
1245 	do{
1246 		q = mult(basptr,dec);
1247 		release(dec);
1248 		dec = getdec(q,sc);
1249 		p = removc(q,sc);
1250 		(*outdit)(p,1);
1251 	}while(++ct < dout);
1252 	release(dec);
1253 	rewind(strptr);
1254 	while(sfeof(strptr) == 0)OUTC(sgetc(strptr));
1255 	printf("\n");
1256 	return;
1257 }
1258 
1259 struct blk *
1260 getdec(p,sc)
1261 struct blk *p;
1262 {
1263 	int cc;
1264 	register struct blk *q,*t,*s;
1265 
1266 	rewind(p);
1267 	if(length(p)*2 < sc){
1268 		q = copy(p,length(p));
1269 		return(q);
1270 	}
1271 	q = salloc(length(p));
1272 	while(sc >= 1){
1273 		sputc(q,sgetc(p));
1274 		sc -= 2;
1275 	}
1276 	if(sc != 0){
1277 		t = mult(q,tenptr);
1278 		s = salloc(cc = length(q));
1279 		release(q);
1280 		rewind(t);
1281 		while(cc-- > 0)sputc(s,sgetc(t));
1282 		sputc(s,0);
1283 		release(t);
1284 		t = div(s,tenptr);
1285 		release(s);
1286 		release(rem);
1287 		return(t);
1288 	}
1289 	return(q);
1290 }
1291 tenot(p,sc)
1292 struct blk *p;
1293 {
1294 	register int c,f;
1295 
1296 	fsfile(p);
1297 	f=0;
1298 	while((sfbeg(p) == 0) && ((p->rd-p->beg-1)*2 >= sc)){
1299 		c = sbackc(p);
1300 		if((c<10) && (f == 1))printf("0%d",c);
1301 		else printf("%d",c);
1302 		f=1;
1303 		TEST2;
1304 	}
1305 	if(sc == 0){
1306 		printf("\n");
1307 		release(p);
1308 		return;
1309 	}
1310 	if((p->rd-p->beg)*2 > sc){
1311 		c = sbackc(p);
1312 		printf("%d.",c/10);
1313 		TEST2;
1314 		OUTC(c%10 +'0');
1315 		sc--;
1316 	}
1317 	else {
1318 		OUTC('.');
1319 	}
1320 	if(sc > (p->rd-p->beg)*2){
1321 		while(sc>(p->rd-p->beg)*2){
1322 			OUTC('0');
1323 			sc--;
1324 		}
1325 	}
1326 	while(sc > 1){
1327 		c = sbackc(p);
1328 		if(c<10)printf("0%d",c);
1329 		else printf("%d",c);
1330 		sc -= 2;
1331 		TEST2;
1332 	}
1333 	if(sc == 1){
1334 		OUTC(sbackc(p)/10 +'0');
1335 	}
1336 	printf("\n");
1337 	release(p);
1338 	return;
1339 }
1340 oneot(p,sc,ch)
1341 struct blk *p;
1342 char ch;
1343 {
1344 	register struct blk *q;
1345 
1346 	q = removc(p,sc);
1347 	create(strptr);
1348 	sputc(strptr,-1);
1349 	while(length(q)>0){
1350 		p = add(strptr,q);
1351 		release(q);
1352 		q = p;
1353 		OUTC(ch);
1354 	}
1355 	release(q);
1356 	printf("\n");
1357 	return;
1358 }
1359 hexot(p,flg)
1360 struct blk *p;
1361 {
1362 	register int c;
1363 	rewind(p);
1364 	if(sfeof(p) != 0){
1365 		sputc(strptr,'0');
1366 		release(p);
1367 		return;
1368 	}
1369 	c = sgetc(p);
1370 	release(p);
1371 	if(c >= 16){
1372 		printf("hex digit > 16");
1373 		return;
1374 	}
1375 	sputc(strptr,c<10?c+'0':c-10+'A');
1376 	return;
1377 }
1378 bigot(p,flg)
1379 struct blk *p;
1380 {
1381 	register struct blk *t,*q;
1382 	register int l;
1383 	int neg;
1384 
1385 	if(flg == 1)t = salloc(0);
1386 	else{
1387 		t = strptr;
1388 		l = length(strptr)+fw-1;
1389 	}
1390 	neg=0;
1391 	if(length(p) != 0){
1392 		fsfile(p);
1393 		if(sbackc(p)<0){
1394 			neg=1;
1395 			chsign(p);
1396 		}
1397 		while(length(p) != 0){
1398 			q = div(p,tenptr);
1399 			release(p);
1400 			p = q;
1401 			rewind(rem);
1402 			sputc(t,sfeof(rem)?'0':sgetc(rem)+'0');
1403 			release(rem);
1404 		}
1405 	}
1406 	release(p);
1407 	if(flg == 1){
1408 		l = fw1-length(t);
1409 		if(neg != 0){
1410 			l--;
1411 			sputc(strptr,'-');
1412 		}
1413 		fsfile(t);
1414 		while(l-- > 0)sputc(strptr,'0');
1415 		while(sfbeg(t) == 0)sputc(strptr,sbackc(t));
1416 		release(t);
1417 	}
1418 	else{
1419 		l -= length(strptr);
1420 		while(l-- > 0)sputc(strptr,'0');
1421 		if(neg != 0){
1422 			sunputc(strptr);
1423 			sputc(strptr,'-');
1424 		}
1425 	}
1426 	sputc(strptr,' ');
1427 	return;
1428 }
1429 struct blk *
1430 add(a1,a2)
1431 struct blk *a1,*a2;
1432 {
1433 	register struct blk *p;
1434 	register int carry,n;
1435 	int size;
1436 	int c,n1,n2;
1437 
1438 	size = length(a1)>length(a2)?length(a1):length(a2);
1439 	p = salloc(size);
1440 	rewind(a1);
1441 	rewind(a2);
1442 	carry=0;
1443 	while(--size >= 0){
1444 		n1 = sfeof(a1)?0:sgetc(a1);
1445 		n2 = sfeof(a2)?0:sgetc(a2);
1446 		n = n1 + n2 + carry;
1447 		if(n>=100){
1448 			carry=1;
1449 			n -= 100;
1450 		}
1451 		else if(n<0){
1452 			carry = -1;
1453 			n += 100;
1454 		}
1455 		else carry = 0;
1456 		sputc(p,n);
1457 	}
1458 	if(carry != 0)sputc(p,carry);
1459 	fsfile(p);
1460 	if(sfbeg(p) == 0){
1461 		while(sfbeg(p) == 0 && (c = sbackc(p)) == 0);
1462 		if(c != 0)salterc(p,c);
1463 		truncate(p);
1464 	}
1465 	fsfile(p);
1466 	if(sfbeg(p) == 0 && sbackc(p) == -1){
1467 		while((c = sbackc(p)) == 99){
1468 			if(c == EOF)break;
1469 		}
1470 		sgetc(p);
1471 		salterc(p,-1);
1472 		truncate(p);
1473 	}
1474 	return(p);
1475 }
1476 eqk(){
1477 	register struct blk *p,*q;
1478 	register int skp;
1479 	int skq;
1480 
1481 	p = pop();
1482 	EMPTYS;
1483 	q = pop();
1484 	EMPTYSR(p);
1485 	skp = sunputc(p);
1486 	skq = sunputc(q);
1487 	if(skp == skq){
1488 		arg1=p;
1489 		arg2=q;
1490 		savk = skp;
1491 		return(0);
1492 	}
1493 	else if(skp < skq){
1494 		savk = skq;
1495 		p = add0(p,skq-skp);
1496 	}
1497 	else {
1498 		savk = skp;
1499 		q = add0(q,skp-skq);
1500 	}
1501 	arg1=p;
1502 	arg2=q;
1503 	return(0);
1504 }
1505 struct blk *
1506 removc(p,n)
1507 struct blk *p;
1508 {
1509 	register struct blk *q,*r;
1510 
1511 	rewind(p);
1512 	while(n>1){
1513 		sgetc(p);
1514 		n -= 2;
1515 	}
1516 	q = salloc(2);
1517 	while(sfeof(p) == 0)sputc(q,sgetc(p));
1518 	if(n == 1){
1519 		r = div(q,tenptr);
1520 		release(q);
1521 		release(rem);
1522 		q = r;
1523 	}
1524 	release(p);
1525 	return(q);
1526 }
1527 struct blk *
1528 scalint(p)
1529 struct blk *p;
1530 {
1531 	register int n;
1532 	n = sunputc(p);
1533 	p = removc(p,n);
1534 	return(p);
1535 }
1536 struct blk *
1537 scale(p,n)
1538 struct blk *p;
1539 {
1540 	register struct blk *q,*s,*t;
1541 
1542 	t = add0(p,n);
1543 	q = salloc(1);
1544 	sputc(q,n);
1545 	s = exp(inbas,q);
1546 	release(q);
1547 	q = div(t,s);
1548 	release(t);
1549 	release(s);
1550 	release(rem);
1551 	sputc(q,n);
1552 	return(q);
1553 }
1554 subt(){
1555 	arg1=pop();
1556 	EMPTYS;
1557 	savk = sunputc(arg1);
1558 	chsign(arg1);
1559 	sputc(arg1,savk);
1560 	pushp(arg1);
1561 	if(eqk() != 0)return(1);
1562 	binop('+');
1563 	return(0);
1564 }
1565 command(){
1566 	int c;
1567 	char line[100],*sl;
1568 	register (*savint)(),pid,rpid;
1569 	int retcode;
1570 
1571 	switch(c = readc()){
1572 	case '<':
1573 		return(cond(NL));
1574 	case '>':
1575 		return(cond(NG));
1576 	case '=':
1577 		return(cond(NE));
1578 	default:
1579 		sl = line;
1580 		*sl++ = c;
1581 		while((c = readc()) != '\n')*sl++ = c;
1582 		*sl = 0;
1583 		if((pid = fork()) == 0){
1584 			execl(_PATH_BSHELL,"sh","-c",line,0);
1585 			exit(0100);
1586 		}
1587 		savint = signal(SIGINT, SIG_IGN);
1588 		while((rpid = wait(&retcode)) != pid && rpid != -1);
1589 		signal(SIGINT,savint);
1590 		printf("!\n");
1591 		return(0);
1592 	}
1593 }
1594 cond(c)
1595 char c;
1596 {
1597 	register struct blk *p;
1598 	register char cc;
1599 
1600 	if(subt() != 0)return(1);
1601 	p = pop();
1602 	sunputc(p);
1603 	if(length(p) == 0){
1604 		release(p);
1605 		if(c == '<' || c == '>' || c == NE){
1606 			readc();
1607 			return(0);
1608 		}
1609 		load();
1610 		return(1);
1611 	}
1612 	else {
1613 		if(c == '='){
1614 			release(p);
1615 			readc();
1616 			return(0);
1617 		}
1618 	}
1619 	if(c == NE){
1620 		release(p);
1621 		load();
1622 		return(1);
1623 	}
1624 	fsfile(p);
1625 	cc = sbackc(p);
1626 	release(p);
1627 	if((cc<0 && (c == '<' || c == NG)) ||
1628 		(cc >0) && (c == '>' || c == NL)){
1629 		readc();
1630 		return(0);
1631 	}
1632 	load();
1633 	return(1);
1634 }
1635 load(){
1636 	register int c;
1637 	register struct blk *p,*q;
1638 	struct blk *t,*s;
1639 	c = readc() & 0377;
1640 	sptr = stable[c];
1641 	if(sptr != 0){
1642 		p = sptr->val;
1643 		if(c >= ARRAYST){
1644 			q = salloc(length(p));
1645 			rewind(p);
1646 			while(sfeof(p) == 0){
1647 				s = getwd(p);
1648 				if(s == 0){putwd(q, (struct blk *)NULL);}
1649 				else{
1650 					t = copy(s,length(s));
1651 					putwd(q,t);
1652 				}
1653 			}
1654 			pushp(q);
1655 		}
1656 		else{
1657 			q = copy(p,length(p));
1658 			pushp(q);
1659 		}
1660 	}
1661 	else{
1662 		q = salloc(1);
1663 		sputc(q,0);
1664 		pushp(q);
1665 	}
1666 	return;
1667 }
1668 log2(n)
1669 long n;
1670 {
1671 	register int i;
1672 
1673 	if(n == 0)return(0);
1674 	i=31;
1675 	if(n<0)return(i);
1676 	while((n= n<<1) >0)i--;
1677 	return(--i);
1678 }
1679 
1680 struct blk *
1681 salloc(size)
1682 int size;
1683 {
1684 	register struct blk *hdr;
1685 	register char *ptr;
1686 	all++;
1687 	nbytes += size;
1688 	ptr = malloc((unsigned)size);
1689 	if(ptr == 0){
1690 		garbage("salloc");
1691 		if((ptr = malloc((unsigned)size)) == 0)
1692 			ospace("salloc");
1693 	}
1694 	if((hdr = hfree) == 0)hdr = morehd();
1695 	hfree = (struct blk *)hdr->rd;
1696 	hdr->rd = hdr->wt = hdr->beg = ptr;
1697 	hdr->last = ptr+size;
1698 	return(hdr);
1699 }
1700 struct blk *
1701 morehd(){
1702 	register struct blk *h,*kk;
1703 	headmor++;
1704 	nbytes += HEADSZ;
1705 	hfree = h = (struct blk *)malloc(HEADSZ);
1706 	if(hfree == 0){
1707 		garbage("morehd");
1708 		if((hfree = h = (struct blk *)malloc(HEADSZ)) == 0)
1709 			ospace("headers");
1710 	}
1711 	kk = h;
1712 	while(h<hfree+(HEADSZ/BLK))(h++)->rd = (char *)++kk;
1713 	(--h)->rd=0;
1714 	return(hfree);
1715 }
1716 /*
1717 sunputc(hptr)
1718 struct blk *hptr;
1719 {
1720 	hptr->wt--;
1721 	hptr->rd = hptr->wt;
1722 	return(*hptr->wt);
1723 }
1724 */
1725 struct blk *
1726 copy(hptr,size)
1727 struct blk *hptr;
1728 int size;
1729 {
1730 	register struct blk *hdr;
1731 	register unsigned sz;
1732 	register char *ptr;
1733 
1734 	all++;
1735 	nbytes += size;
1736 	sz = length(hptr);
1737 	ptr = nalloc(hptr->beg, (unsigned)size);
1738 	if(ptr == 0){
1739 		garbage("copy");
1740 		if((ptr = nalloc(hptr->beg, (unsigned)size)) == NULL){
1741 			printf("copy size %d\n",size);
1742 			ospace("copy");
1743 		}
1744 	}
1745 	if((hdr = hfree) == 0)hdr = morehd();
1746 	hfree = (struct blk *)hdr->rd;
1747 	hdr->rd = hdr->beg = ptr;
1748 	hdr->last = ptr+size;
1749 	hdr->wt = ptr+sz;
1750 	ptr = hdr->wt;
1751 	while(ptr<hdr->last)*ptr++ = '\0';
1752 	return(hdr);
1753 }
1754 sdump(s1,hptr)
1755 char *s1;
1756 struct blk *hptr;
1757 {
1758 	char *p;
1759 	printf("%s %o rd %o wt %o beg %o last %o\n",s1,hptr,hptr->rd,hptr->wt,hptr->beg,hptr->last);
1760 	p = hptr->beg;
1761 	while(p < hptr->wt)printf("%d ",*p++);
1762 	printf("\n");
1763 }
1764 seekc(hptr,n)
1765 struct blk *hptr;
1766 {
1767 	register char *nn,*p;
1768 
1769 	nn = hptr->beg+n;
1770 	if(nn > hptr->last){
1771 		nbytes += nn - hptr->last;
1772 		p = realloc(hptr->beg, (unsigned)n);
1773 		if(p == 0){
1774 			hptr->beg = realloc(hptr->beg, (unsigned)(hptr->last-hptr->beg));
1775 			garbage("seekc");
1776 			if((p = realloc(hptr->beg, (unsigned)n)) == 0)
1777 				ospace("seekc");
1778 		}
1779 		hptr->beg = p;
1780 		hptr->wt = hptr->last = hptr->rd = p+n;
1781 		return;
1782 	}
1783 	hptr->rd = nn;
1784 	if(nn>hptr->wt)hptr->wt = nn;
1785 	return;
1786 }
1787 salterwd(hptr,n)
1788 struct wblk *hptr;
1789 struct blk *n;
1790 {
1791 	if(hptr->rdw == hptr->lastw)more(hptr);
1792 	*hptr->rdw++ = n;
1793 	if(hptr->rdw > hptr->wtw)hptr->wtw = hptr->rdw;
1794 	return;
1795 }
1796 more(hptr)
1797 struct blk *hptr;
1798 {
1799 	register unsigned size;
1800 	register char *p;
1801 
1802 	if((size=(hptr->last-hptr->beg)*2) == 0)size=1;
1803 	nbytes += size/2;
1804 	p = realloc(hptr->beg, (unsigned)size);
1805 	if(p == 0){
1806 		hptr->beg = realloc(hptr->beg, (unsigned)(hptr->last-hptr->beg));
1807 		garbage("more");
1808 		if((p = realloc(hptr->beg,(unsigned)size)) == 0)
1809 			ospace("more");
1810 	}
1811 	hptr->rd = hptr->rd-hptr->beg+p;
1812 	hptr->wt = hptr->wt-hptr->beg+p;
1813 	hptr->beg = p;
1814 	hptr->last = p+size;
1815 	return;
1816 }
1817 ospace(s)
1818 char *s;
1819 {
1820 	printf("out of space: %s\n",s);
1821 	printf("all %ld rel %ld headmor %ld\n",all,rel,headmor);
1822 	printf("nbytes %ld\n",nbytes);
1823 	sdump("stk",*stkptr);
1824 	abort();
1825 }
1826 garbage(s)
1827 char *s;
1828 {
1829 	int i;
1830 	struct blk *p, *q;
1831 	struct sym *tmps;
1832 	int ct;
1833 
1834 /*	printf("got to garbage %s\n",s);	*/
1835 	for(i=0;i<TBLSZ;i++){
1836 		tmps = stable[i];
1837 		if(tmps != 0){
1838 			if(i < ARRAYST){
1839 				do {
1840 					p = tmps->val;
1841 					if(((int)p->beg & 01)  != 0){
1842 						printf("string %o\n",i);
1843 						sdump("odd beg",p);
1844 					}
1845 					redef(p);
1846 					tmps = tmps->next;
1847 				} while(tmps != 0);
1848 				continue;
1849 			}
1850 			else {
1851 				do {
1852 					p = tmps->val;
1853 					rewind(p);
1854 					ct = 0;
1855 					while((q = getwd(p)) != NULL){
1856 						ct++;
1857 						if(q != 0){
1858 							if(((int)q->beg & 01) != 0){
1859 								printf("array %o elt %d odd\n",i-ARRAYST,ct);
1860 printf("tmps %o p %o\n",tmps,p);
1861 								sdump("elt",q);
1862 							}
1863 							redef(q);
1864 						}
1865 					}
1866 					tmps = tmps->next;
1867 				} while(tmps != 0);
1868 			}
1869 		}
1870 	}
1871 }
1872 redef(p)
1873 struct blk *p;
1874 {
1875 	register offset;
1876 	register char *newp;
1877 
1878 	if ((int)p->beg&01) {
1879 		printf("odd ptr %o hdr %o\n",p->beg,p);
1880 		ospace("redef-bad");
1881 	}
1882 	newp = realloc(p->beg, (unsigned)(p->last-p->beg));
1883 	if(newp == NULL)ospace("redef");
1884 	offset = newp - p->beg;
1885 	p->beg = newp;
1886 	p->rd += offset;
1887 	p->wt += offset;
1888 	p->last += offset;
1889 }
1890 
1891 release(p)
1892 register struct blk *p;
1893 {
1894 	rel++;
1895 	nbytes -= p->last - p->beg;
1896 	p->rd = (char *)hfree;
1897 	hfree = p;
1898 	free(p->beg);
1899 }
1900 
1901 struct blk *
1902 getwd(p)
1903 struct blk *p;
1904 {
1905 	register struct wblk *wp;
1906 
1907 	wp = (struct wblk *)p;
1908 	if (wp->rdw == wp->wtw)
1909 		return(NULL);
1910 	return(*wp->rdw++);
1911 }
1912 
1913 putwd(p, c)
1914 struct blk *p, *c;
1915 {
1916 	register struct wblk *wp;
1917 
1918 	wp = (struct wblk *)p;
1919 	if (wp->wtw == wp->lastw)
1920 		more(p);
1921 	*wp->wtw++ = c;
1922 }
1923 
1924 struct blk *
1925 lookwd(p)
1926 struct blk *p;
1927 {
1928 	register struct wblk *wp;
1929 
1930 	wp = (struct wblk *)p;
1931 	if (wp->rdw == wp->wtw)
1932 		return(NULL);
1933 	return(*wp->rdw);
1934 }
1935 char *
1936 nalloc(p,nbytes)
1937 register char *p;
1938 unsigned nbytes;
1939 {
1940 	char *malloc();
1941 	register char *q, *r;
1942 	q = r = malloc(nbytes);
1943 	if(q==0)
1944 		return(0);
1945 	while(nbytes--)
1946 		*q++ = *p++;
1947 	return(r);
1948 }
1949