640 number_to_scaled_string is duplicated in several commands
[unleashed.git] / usr / src / cmd / dc / dc.c
blob772201157cd6171a47992a5c8576424713b950b7
1 /*
2 * CDDL HEADER START
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.
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.
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]
20 * CDDL HEADER END
23 * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
30 #pragma ident "%Z%%M% %I% %E% SMI"
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>
42 #define LASTFUN 026
43 long longest = 0, maxsize = 0, active = 0;
44 int lall = 0, lrel = 0, lcopy = 0, lmore = 0, lbytes = 0;
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.
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.
62 #if __STDC__
63 int
64 ctoint(char c)
65 #else
66 int
67 ctoint(unsigned char c)
68 #endif
70 int i;
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);
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
82 void commnds(void) __NORETURN;
84 int
85 main(int argc, char **argv)
87 (void) setlocale(LC_ALL, "");
88 (void) textdomain(TEXT_DOMAIN);
90 init(argc, argv);
91 commnds();
92 /* NOTREACHED */
95 void
96 commnds(void)
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 */
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;
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;
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;
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;
210 if ((c = sbackc(p)) < 0) {
211 error(gettext("sqrt of neg number\n"));
213 if (k < savk)
214 n = savk;
215 else {
216 n = k * 2 - savk;
217 savk = k;
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);
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);
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;
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;
298 } else
299 if (c < 10)
300 n -= 1;
302 release(p);
303 q = salloc(1);
304 if (n >= 100) {
305 sputc(q, n%100);
306 n /= 100;
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);
318 * POSIX.2
319 * input base must be between 2 and 16
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);
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);
358 if (n != 1) {
359 while (sfbeg(q) == 0)
360 l = l * 100 + sbackc(q);
365 * POSIX.2
366 * Check that output base is less than or equal
367 * BC_BASE_MAX.
369 if (l > BC_BASE_MAX)
370 error(gettext("output base is too large\n"));
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;
386 * POSIX.2
387 * Line length is 70 characters,
388 * including newline.
390 ll = 70;
391 release(q);
392 continue;
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;
412 * POSIX.2
413 * Line length is 70 characters including newline
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--;
434 sputc(p, c);
435 if (c == '[')
436 n++;
438 pushp(p);
439 continue;
440 case 'k':
441 p = pop();
442 EMPTY;
443 p = scalint(p);
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.
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"));
458 scalev = 1;
459 while (c < BC_SCALE_MAX && sfbeg(q) == 0)
460 c = (c * (scalev *= 100)) + sbackc(q);
462 if (c > BC_SCALE_MAX)
463 error(gettext("scale factor is too large\n"));
464 release(q);
466 rewind(p);
467 k = sfeof(p) ? 0 : sgetc(p);
468 release(scalptr);
469 scalptr = p;
470 continue;
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");
494 rewind(p);
495 if ((c = sgetc(p)) < 0) {
496 error(gettext("neg Q\n"));
498 release(p);
499 while (c-- > 0) {
500 if (readptr == &readstk[0]) {
501 error("readstk?\n");
503 if (*readptr != 0)
504 release(*readptr);
505 readptr--;
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--);
526 continue;
527 case 'p':
528 if (stkptr == &stack[0])
529 printf(gettext("empty stack\n"));
530 else {
531 print(*stkptr);
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;
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);
557 continue;
558 case 'S':
559 if (stkptr == &stack[0]) {
560 error(gettext("save: args\n"));
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);
576 release(p);
577 p = q;
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"));
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));
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;
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");
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);
628 pushp(p);
629 continue;
630 case ':':
631 p = pop();
632 EMPTY;
633 q = scalint(p);
634 fsfile(q);
637 * POSIX.2
638 * Make sure index is between 0 and BC_DIM_MAX-1
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);
647 if (c >= BC_DIM_MAX)
648 error(gettext("index is too large\n"));
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;
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;
679 case ';':
680 p = pop();
681 EMPTY;
682 q = scalint(p);
683 fsfile(q);
686 * POSIX.2
687 * Make sure index is between 0 and BC_DIM_MAX-1
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);
696 if (c >= BC_DIM_MAX)
697 error(gettext("index is too large\n"));
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;
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"));
731 } else
732 readptr++;
733 *readptr = p;
734 if (p != 0)
735 rewind(p);
736 else {
737 if ((c = readc()) != '\n')
738 unreadc(c);
740 continue;
741 case '?':
742 if (++readptr == &readstk[RDSKSZ]) {
743 error(gettext("nesting depth\n"));
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());
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);
776 struct blk *
777 dcdiv(struct blk *ddivd, struct blk *ddivr)
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;
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);
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;
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;
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;
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;
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);
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;
862 salterc(divd, d);
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);
874 if (--offset >= 0) {
875 divd->wt--;
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;
891 if (divcarry != 0) {
892 salterc(p, dig - 1);
893 salterc(divd, -1);
894 ps = add(divr, divd);
895 release(divd);
896 divd = ps;
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;
908 salterc(p, d);
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;
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;
926 ddone:
927 if (remsign < 0)
928 chsign(divd);
929 if (divr != ddivr)
930 release(divr);
931 rem = divd;
932 return (p);
936 dscale(void)
938 struct blk *dd, *dr, *r;
939 int c;
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);
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);
964 c = k-skd+skr;
965 if (c < 0)
966 r = removr(dd, -c);
967 else {
968 r = add0(dd, c);
969 irem = 0;
971 arg1 = r;
972 arg2 = dr;
973 savk = k;
974 return (0);
977 struct blk *
978 removr(struct blk *p, int n)
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;
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);
1010 irem = q;
1011 return (s);
1013 if (neg < 0) {
1014 chsign(r);
1015 chsign(q);
1016 irem = q;
1017 return (r);
1019 irem = q;
1020 return (r);
1023 struct blk *
1024 sqrt(struct blk *p)
1026 struct blk *r, *q, *s, *t;
1027 int c, n, nn;
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;
1070 release(t);
1071 release(q);
1072 release(p);
1073 return (r);
1076 struct blk *
1077 exp(struct blk *base, struct blk *ex)
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);
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;
1105 t = copy(p, length(p));
1106 cp = mult(p, t);
1107 release(p);
1108 release(t);
1109 p = cp;
1111 if (temp != 0) {
1112 if ((c = length(base)) == 0) {
1113 goto edone;
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);
1126 edone:
1127 release(p);
1128 release(e);
1129 return (r);
1132 void
1133 init(int argc, char **argv)
1135 struct sym *sp;
1136 char *dcmalloc();
1137 struct stat tsb;
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;
1149 svargc--;
1150 svargv++;
1153 ifile = 1;
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);
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);
1170 } else {
1171 printf(gettext("invalid file type: %s\n"), \
1172 svargv[1]);
1173 exit(1);
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);
1186 * POSIX.2
1187 * default line length is 70 characters including newline
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++;
1212 sptr->next = 0;
1213 sfree = &symlst[0];
1216 void
1217 onintr(int sig)
1220 signal(sig, onintr);
1221 while (readptr != &readstk[0]) {
1222 if (*readptr != 0)
1223 release(*readptr);
1224 readptr--;
1226 curfile = stdin;
1227 commnds();
1230 void
1231 pushp(struct blk *p)
1233 if (stkptr == stkend)
1234 printf(gettext("out of stack space\n"));
1235 else {
1236 stkerr = 0;
1237 *++stkptr = p;
1241 struct blk *
1242 pop(void)
1244 if (stkptr == stack) {
1245 stkerr = 1;
1246 return (0);
1248 return (*stkptr--);
1251 struct blk *
1252 readin(void)
1254 struct blk *p, *q;
1255 int dp, dpct;
1256 int c;
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++;
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);
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++;
1310 q = scale(p, dpct);
1311 return (q);
1316 * returns pointer to struct with ct 0's & p
1318 struct blk *
1319 add0(struct blk *p, int ct)
1321 struct blk *q, *t;
1323 q = salloc(length(p) + (ct + 1) / 2);
1324 while (ct > 1) {
1325 sputc(q, 0);
1326 ct -= 2;
1328 rewind(p);
1329 while (sfeof(p) == 0) {
1330 sputc(q, sgetc(p));
1332 release(p);
1333 if (ct == 1) {
1334 t = mult(tenptr, q);
1335 release(q);
1336 return (t);
1338 return (q);
1341 struct blk *
1342 mult(struct blk *p, struct blk *q)
1344 struct blk *mp, *mq, *mr;
1345 int sign, offset, carry;
1346 int cq, cp, mt, mcr;
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;
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;
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);
1383 offset++;
1384 if (carry != 0) {
1385 mcr = sfeof(mr) ? 0 : slookc(mr);
1386 salterc(mr, mcr + carry);
1389 if (sign < 0) {
1390 chsign(mr);
1392 if (mp != p)
1393 release(mp);
1394 if (mq != q)
1395 release(mq);
1396 return (mr);
1399 void
1400 chsign(struct blk *p)
1402 int carry;
1403 char ct;
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;
1414 salterc(p, ct);
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);
1425 } else {
1426 fsfile(p);
1427 ct = sbackc(p);
1428 if (ct == 0)
1429 truncate(p);
1433 char
1434 readc(void)
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;
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;
1453 if (curfile != stdin) {
1454 fclose(curfile);
1455 curfile = stdin;
1456 goto loop;
1458 exit(0);
1461 void
1462 unreadc(char c)
1465 if ((readptr != &readstk[0]) && (*readptr != 0)) {
1466 sungetc(*readptr, c);
1467 } else
1468 ungetc(c, curfile);
1471 void
1472 binop(char c)
1474 struct blk *r;
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;
1487 release(arg1);
1488 release(arg2);
1489 sputc(r, savk);
1490 pushp(r);
1493 void
1494 print(struct blk *hptr)
1496 struct blk *p, *q, *dec;
1497 int sc; /* scale */
1498 int dig, dout, ct;
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));
1507 printf("\n");
1508 return;
1511 fsfile(hptr);
1512 sc = sbackc(hptr); /* read scale off end of blk */
1513 if (sfbeg(hptr) != 0) {
1514 printf("0\n");
1515 return;
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('-');
1525 if ((obase == 0) || (obase == -1)) {
1526 oneot(p, sc, 'd');
1527 return;
1529 if (obase == 1) {
1530 oneot(p, sc, '1');
1531 return;
1533 if (obase == 10) {
1534 tenot(p, sc);
1535 return;
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, ' ');
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;
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");
1578 struct blk *
1579 getdec(struct blk *p, int sc)
1581 int cc;
1582 struct blk *q, *t, *s;
1584 rewind(p);
1585 if (length(p) * 2 < sc) {
1586 q = copy(p, length(p));
1587 return (q);
1589 q = salloc(length(p));
1590 while (sc >= 1) {
1591 sputc(q, sgetc(p));
1592 sc -= 2;
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);
1608 return (q);
1611 void
1612 tenot(struct blk *p, int sc)
1614 int c, f;
1616 fsfile(p);
1618 f = 0;
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.
1626 while ((sfbeg(p) == 0) && ((p->rd-p->beg-1)*2 >= sc)) {
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.
1633 c = sbackc(p);
1636 * POSIX.2
1637 * as we output digits, we have to watch the line length (ll)
1638 * which should include a '\' and a newline.
1640 if (c < 10) {
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).
1646 if (f == 1) {
1647 CHECKEND;
1648 printf("0");
1649 count--;
1652 CHECKEND;
1653 printf("%d", c);
1654 count--;
1655 } else {
1656 CHECKEND;
1657 printf("%d", c / 10);
1658 count--;
1660 CHECKEND;
1661 printf("%d", c % 10);
1662 count--;
1664 f = 1;
1667 if (sc == 0) {
1669 * no scaling factor, so we must have exited loop because we
1670 * ran out of numbers.
1672 printf("\n");
1673 release(p);
1674 return;
1677 if ((p->rd - p->beg) * 2 > sc) {
1678 c = sbackc(p);
1680 CHECKEND;
1681 printf("%d", c / 10);
1682 count--;
1684 CHECKEND;
1685 printf(".");
1686 count--;
1688 CHECKEND;
1689 printf("%d", c % 10);
1690 count--;
1692 sc--;
1693 } else {
1694 CHECKEND;
1695 printf(".");
1696 count--;
1699 if (sc > (p->rd - p->beg) * 2) {
1700 while (sc > (p->rd - p->beg) * 2) {
1701 CHECKEND;
1702 printf("0");
1703 count--;
1705 sc--;
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--;
1717 CHECKEND;
1718 printf("%d", c);
1719 count--;
1720 } else {
1721 CHECKEND;
1722 printf("%d", c / 10);
1723 count--;
1725 CHECKEND;
1726 printf("%d", c % 10);
1727 count--;
1729 sc -= 2;
1732 if (sc == 1) { /* just in case the scaling factor was odd */
1733 CHECKEND;
1734 printf("%d", sbackc(p) / 10);
1737 printf("\n");
1738 release(p);
1741 void
1742 oneot(struct blk *p, int sc, char ch)
1744 struct blk *q;
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);
1755 release(q);
1756 printf("\n");
1759 void
1760 hexot(struct blk *p, int flg)
1762 int c;
1764 rewind(p);
1765 if (sfeof(p) != 0) {
1766 sputc(strptr, '0');
1767 release(p);
1768 return;
1770 c = sgetc(p);
1771 release(p);
1772 if (c >= 16) {
1773 printf(gettext("hex digit > 16"));
1774 return;
1776 sputc(strptr, c < 10 ? c + '0' : c - 10 + 'A');
1779 void
1780 bigot(struct blk *p, int flg)
1782 struct blk *t, *q;
1783 int l;
1784 int neg;
1786 if (flg == 1)
1787 t = salloc(0);
1788 else {
1789 t = strptr;
1790 l = length(strptr) + fw - 1;
1792 neg = 0;
1793 if (length(p) != 0) {
1794 fsfile(p);
1795 if (sbackc(p) < 0) {
1796 neg = 1;
1797 chsign(p);
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);
1808 release(p);
1809 if (flg == 1) {
1810 l = fw1 - length(t);
1811 if (neg != 0) {
1812 l--;
1813 sputc(strptr, '-');
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, '-');
1832 struct blk *
1833 add(struct blk *a1, struct blk *a2)
1835 struct blk *p;
1836 int carry, n;
1837 int size;
1838 int c, n1, n2;
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);
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);
1869 fsfile(p);
1870 if (sfbeg(p) == 0 && sbackc(p) == -1) {
1871 while ((c = sbackc(p)) == 99) {
1872 if (c == EOF)
1873 break;
1875 sgetc(p);
1876 salterc(p, -1);
1877 truncate(p);
1879 return (p);
1883 eqk(void) {
1884 struct blk *p, *q;
1885 int skp, skq;
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);
1906 arg1 = p;
1907 arg2 = q;
1908 return (0);
1911 struct blk *
1912 removc(struct blk *p, int n)
1914 struct blk *q, *r;
1916 rewind(p);
1917 while (n > 1) {
1918 sgetc(p);
1919 n -= 2;
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;
1930 release(p);
1931 return (q);
1934 struct blk *
1935 scalint(struct blk *p)
1937 int n;
1939 n = sunputc(p);
1940 p = removc(p, n);
1941 return (p);
1944 struct blk *
1945 scale(struct blk *p, int n)
1947 struct blk *q, *s, *t;
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);
1963 subt(void)
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);
1978 command(void)
1980 int c;
1981 char line[100], *sl;
1982 void (*savint)();
1983 pid_t pid, rpid;
1984 int retcode;
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);
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);
2012 cond(char c)
2014 struct blk *p;
2015 int cc;
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);
2027 load();
2028 return (1);
2029 } else {
2030 if (c == '=') {
2031 release(p);
2032 readc();
2033 return (0);
2036 if (c == NE) {
2037 release(p);
2038 load();
2039 return (1);
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);
2049 load();
2050 return (1);
2053 void
2054 load(void)
2056 int c;
2057 struct blk *p, *q, *t, *s;
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);
2075 pushp(q);
2076 } else {
2077 q = copy(p, length(p));
2078 pushp(q);
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);
2097 log2(long n)
2099 int i;
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);
2111 struct blk *
2112 salloc(int size)
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");
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);
2141 struct blk *
2142 morehd(void)
2144 struct blk *h, *kk;
2145 char *dcmalloc();
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");
2155 kk = h;
2156 while (h < hfree + (HEADSZ/BLK))
2157 (h++)->rd = (char *)++kk;
2158 (--h)->rd = 0;
2159 return (hfree);
2162 struct blk *
2163 copy(struct blk *hptr, int size)
2165 struct blk *hdr;
2166 unsigned sz;
2167 char *ptr;
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");
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);
2199 void
2200 sdump(char *s1, struct blk *hptr)
2202 char *p;
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);
2215 void
2216 seekc(struct blk *hptr, int n)
2218 char *nn, *p;
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");
2236 hptr->beg = p;
2237 hptr->wt = hptr->last = hptr->rd = p + n;
2238 return;
2240 hptr->rd = nn;
2241 if (nn > hptr->wt)
2242 hptr->wt = nn;
2245 void
2246 salterwd(struct wblk *hptr, struct blk *n)
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;
2255 void
2256 more(struct blk *hptr)
2258 unsigned size;
2259 char *p;
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");
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;
2284 void
2285 ospace(char *s)
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();
2294 #define G1 gettext("array %o elt %d odd\n")
2295 #define G2 gettext("tmps %o p %o\n")
2296 void
2297 garbage(char *s)
2299 int i;
2300 struct blk *p, *q;
2301 struct sym *tmps;
2302 int ct;
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);
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);
2337 redef(q);
2340 tmps = tmps->next;
2341 } while (tmps != 0);
2347 void
2348 redef(struct blk *p)
2350 int offset;
2351 char *newp;
2352 char *dcmalloc();
2354 if ((int)p->beg & 01) {
2355 printf(gettext("odd ptr %o hdr %o\n"), p->beg, p);
2356 ospace("redef-bad");
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;
2372 void
2373 release(struct blk *p)
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;
2384 struct blk *
2385 getwd(struct blk *p)
2387 struct wblk *wp;
2389 wp = (struct wblk *)p;
2390 if (wp->rdw == wp->wtw)
2391 return (NULL);
2392 return (*wp->rdw++);
2395 void
2396 putwd(struct blk *p, struct blk *c)
2398 struct wblk *wp;
2400 wp = (struct wblk *)p;
2401 if (wp->wtw == wp->lastw)
2402 more(p);
2403 *wp->wtw++ = c;
2406 struct blk *
2407 lookwd(struct blk *p)
2409 struct wblk *wp;
2411 wp = (struct wblk *)p;
2412 if (wp->rdw == wp->wtw)
2413 return (NULL);
2414 return (*wp->rdw);
2417 char *
2418 nalloc(char *p, unsigned int nbytes)
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);
2430 char *
2431 dcmalloc(int size)
2433 return (malloc(size ? size : 1));