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
ctoint(char c)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
main(int argc,char ** argv)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
commnds(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 *
dcdiv(struct blk * ddivd,struct blk * ddivr)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
dscale(void)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 *
removr(struct blk * p,int n)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 *
sqrt(struct blk * p)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 *
exp(struct blk * base,struct blk * ex)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
init(int argc,char ** argv)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
onintr(int sig)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
pushp(struct blk * p)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 *
pop(void)1242 pop(void)
1243 {
1244 if (stkptr == stack) {
1245 stkerr = 1;
1246 return (0);
1247 }
1248 return (*stkptr--);
1249 }
1250
1251 struct blk *
readin(void)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 *
add0(struct blk * p,int ct)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 *
mult(struct blk * p,struct blk * q)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
chsign(struct blk * p)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
readc(void)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
unreadc(char c)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
binop(char c)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
print(struct blk * hptr)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 *
getdec(struct blk * p,int sc)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
tenot(struct blk * p,int sc)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
oneot(struct blk * p,int sc,char ch)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
hexot(struct blk * p,int flg)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
bigot(struct blk * p,int flg)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 *
add(struct blk * a1,struct blk * a2)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
eqk(void)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 *
removc(struct blk * p,int n)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 *
scalint(struct blk * p)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 *
scale(struct blk * p,int n)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
subt(void)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
command(void)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
cond(char c)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
load(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
log2(long n)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 *
salloc(int size)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 *
morehd(void)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 *
copy(struct blk * hptr,int size)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
sdump(char * s1,struct blk * hptr)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
seekc(struct blk * hptr,int n)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
salterwd(struct wblk * hptr,struct blk * n)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
more(struct blk * hptr)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
ospace(char * s)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
garbage(char * s)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
redef(struct blk * p)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
release(struct blk * p)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 *
getwd(struct blk * p)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
putwd(struct blk * p,struct blk * c)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 *
lookwd(struct blk * p)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 *
nalloc(char * p,unsigned int nbytes)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 *
dcmalloc(int size)2431 dcmalloc(int size)
2432 {
2433 return (malloc(size ? size : 1));
2434 }
2435