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