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