Home | History | Annotate | Download | only in dc
      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);