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);
   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