xref: /titanic_52/usr/src/cmd/dc/dc.c (revision 7ff178cd8db129d385d3177eb20744d3b6efc59b)
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