1 %{
2 /*
3 * CDDL HEADER START
4 *
5 * The contents of this file are subject to the terms of the
6 * Common Development and Distribution License, Version 1.0 only
7 * (the "License"). You may not use this file except in compliance
8 * with the License.
9 *
10 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
11 * or http://www.opensolaris.org/os/licensing.
12 * See the License for the specific language governing permissions
13 * and limitations under the License.
14 *
15 * When distributing Covered Code, include this CDDL HEADER in each
16 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
17 * If applicable, add the following below this CDDL HEADER, with the
18 * fields enclosed by brackets "[]" replaced with your own identifying
19 * information: Portions Copyright [yyyy] [name of copyright owner]
20 *
21 * CDDL HEADER END
22 */
23 %}
24 /*
25 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
26 * Use is subject to license terms.
27 */
28
29 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
30 /* All Rights Reserved */
31
32 %{
33 #include <stdio.h>
34 #include <stdarg.h>
35 #include <limits.h>
36 #include <libintl.h>
37 #include <locale.h>
38 #include <signal.h>
39
40 static void getout(int) __NORETURN;
41 static int *bundle(int, ...);
42 static void usage(void);
43
44 int cpeek(char, int, char, int, char);
45 int yyerror(const char *);
46
47 #define STRING_SIZE (BC_STRING_MAX + 3) /* string plus quotes */
48 /* plus NULL */
49
50 FILE *in;
51 char cary[LINE_MAX+1];
52 char *cp = { cary };
53 char *cpend = &cary[LINE_MAX]; /* last address (not the null char) */
54 char string[STRING_SIZE];
55 char *str = { string };
56 int crs = '0';
57 int rcrs = '0'; /* reset crs */
58 int bindx = 0;
59 int lev = 0; /* current scope level */
60 int ln; /* line number of current file */
61 int *ttp;
62 char *ss; /* current input source */
63 int bstack[10] = { 0 };
64 char *numb[15] = {
65 " 0", " 1", " 2", " 3", " 4", " 5",
66 " 6", " 7", " 8", " 9", " 10", " 11",
67 " 12", " 13", " 14"
68 };
69 int *pre, *post;
70 int interact = 0; /* talking to a tty? */
71 %}
72
73 %union {
74 int *iptr;
75 char *cptr;
76 int cc;
77 }
78 %start start;
79 %type <iptr> stat def slist dlets e
80 %type <iptr> re fprefix cargs eora cons constant lora
81 %right '='
82 %left '+' '-'
83 %left '*' '/' '%'
84 %right '^'
85 %left UMINUS
86
87 %token <cptr> LETTER
88 %type <cptr> EQOP CRS
89 %token <cc> DIGIT SQRT LENGTH _IF FFF EQ
90 %token <cc> _WHILE _FOR NE LE GE INCR DECR
91 %token <cc> _RETURN _BREAK _DEFINE BASE OBASE SCALE
92 %token <cc> EQPL EQMI EQMUL EQDIV EQREM EQEXP
93 %token <cptr> _AUTO DOT
94 %token <cc> QSTR
95
96 %%
97 start :
98 | start stat tail
99 {
100 output($2);
101 }
102 | start def dargs ')' '{' dlist slist '}'
103 {
104 ttp = bundle(6, pre, $7, post, "0", numb[lev], "Q");
105 conout(ttp, (char *)$2);
106 rcrs = crs;
107 output((int *)"");
108 lev = bindx = 0;
109 }
110 ;
111
112 dlist : tail
113 | dlist _AUTO dlets tail
114 ;
115
116 stat : e
117 {
118 bundle(2, $1, "ps.");
119 }
120 |
121 {
122 bundle(1, "");
123 }
124 | QSTR
125 {
126 bundle(3, "[", $1, "]P");
127 }
128 | LETTER '=' e
129 {
130 bundle(3, $3, "s", $1);
131 }
132 | LETTER '[' e ']' '=' e
133 {
134 bundle(4, $6, $3, ":", geta($1));
135 }
136 | LETTER EQOP e
137 {
138 bundle(6, "l", $1, $3, $2, "s", $1);
139 }
140 | LETTER '[' e ']' EQOP e
141 {
142 bundle(8, $3, ";", geta($1), $6, $5, $3, ":", geta($1));
143 }
144 | _BREAK
145 {
146 bundle(2, numb[lev-bstack[bindx-1]], "Q");
147 }
148 | _RETURN '(' e ')'
149 {
150 bundle(4, $3, post, numb[lev], "Q");
151 }
152 | _RETURN '(' ')'
153 {
154 bundle(4, "0", post, numb[lev], "Q");
155 }
156 | _RETURN
157 {
158 bundle(4, "0", post, numb[lev], "Q");
159 }
160 | SCALE '=' e
161 {
162 bundle(2, $3, "k");
163 }
164 | SCALE EQOP e
165 {
166 bundle(4, "K", $3, $2, "k");
167 }
168 | BASE '=' e
169 {
170 bundle(2, $3, "i");
171 }
172 | BASE EQOP e
173 {
174 bundle(4, "I", $3, $2, "i");
175 }
176 | OBASE '=' e
177 {
178 bundle(2, $3, "o");
179 }
180 | OBASE EQOP e
181 {
182 bundle(4, "O", $3, $2, "o");
183 }
184 | '{' slist '}'
185 {
186 $$ = $2;
187 }
188 | FFF
189 {
190 bundle(1, "fY");
191 }
192 | error
193 {
194 bundle(1, "c");
195 }
196 | _IF CRS BLEV '(' re ')' stat
197 {
198 conout($7, $2);
199 bundle(3, $5, $2, " ");
200 }
201 | _WHILE CRS '(' re ')' stat BLEV
202 {
203 bundle(3, $6, $4, $2);
204 conout($$, $2);
205 bundle(3, $4, $2, " ");
206 }
207 | fprefix CRS re ';' e ')' stat BLEV
208 {
209 bundle(5, $7, $5, "s.", $3, $2);
210 conout($$, $2);
211 bundle(5, $1, "s.", $3, $2, " ");
212 }
213 | '~' LETTER '=' e
214 {
215 bundle(3, $4, "S", $2);
216 }
217 ;
218
219 EQOP : EQPL
220 {
221 $$ = "+";
222 }
223 | EQMI
224 {
225 $$ = "-";
226 }
227 | EQMUL
228 {
229 $$ = "*";
230 }
231 | EQDIV
232 {
233 $$ = "/";
234 }
235 | EQREM
236 {
237 $$ = "%%";
238 }
239 | EQEXP
240 {
241 $$ = "^";
242 }
243 ;
244
245 fprefix : _FOR '(' e ';'
246 {
247 $$ = $3;
248 }
249 ;
250
251 BLEV :
252 {
253 --bindx;
254 }
255 ;
256
257 slist : stat
258 | slist tail stat
259 {
260 bundle(2, $1, $3);
261 }
262 ;
263
264 tail : '\n'
265 {
266 ln++;
267 }
268 | ';'
269 ;
270
271 re : e EQ e
272 {
273 $$ = bundle(3, $1, $3, "=");
274 }
275 | e '<' e
276 {
277 bundle(3, $1, $3, ">");
278 }
279 | e '>' e
280 {
281 bundle(3, $1, $3, "<");
282 }
283 | e NE e
284 {
285 bundle(3, $1, $3, "!=");
286 }
287 | e GE e
288 {
289 bundle(3, $1, $3, "!>");
290 }
291 | e LE e
292 {
293 bundle(3, $1, $3, "!<");
294 }
295 | e
296 {
297 bundle(2, $1, " 0!=");
298 }
299 ;
300
301 e : e '+' e
302 {
303 bundle(3, $1, $3, "+");
304 }
305 | e '-' e
306 {
307 bundle(3, $1, $3, "-");
308 }
309 | '-' e %prec UMINUS
310 {
311 bundle(3, " 0", $2, "-");
312 }
313 | e '*' e
314 {
315 bundle(3, $1, $3, "*");
316 }
317 | e '/' e
318 {
319 bundle(3, $1, $3, "/");
320 }
321 | e '%' e
322 {
323 bundle(3, $1, $3, "%%");
324 }
325 | e '^' e
326 {
327 bundle(3, $1, $3, "^");
328 }
329 | LETTER '[' e ']'
330 {
331 bundle(3, $3, ";", geta($1));
332 }
333 | LETTER INCR
334 {
335 bundle(4, "l", $1, "d1+s", $1);
336 }
337 | INCR LETTER
338 {
339 bundle(4, "l", $2, "1+ds", $2);
340 }
341 | DECR LETTER
342 {
343 bundle(4, "l", $2, "1-ds", $2);
344 }
345 | LETTER DECR
346 {
347 bundle(4, "l", $1, "d1-s", $1);
348 }
349 | LETTER '[' e ']' INCR
350 {
351 bundle(7, $3, ";", geta($1), "d1+", $3, ":", geta($1));
352 }
353 | INCR LETTER '[' e ']'
354 {
355 bundle(7, $4, ";", geta($2), "1+d", $4, ":", geta($2));
356 }
357 | LETTER '[' e ']' DECR
358 {
359 bundle(7, $3, ";", geta($1), "d1-", $3, ":", geta($1));
360 }
361 | DECR LETTER '[' e ']'
362 {
363 bundle(7, $4, ";", geta($2), "1-d", $4, ":", geta($2));
364 }
365 | SCALE INCR
366 {
367 bundle(1, "Kd1+k");
368 }
369 | INCR SCALE
370 {
371 bundle(1, "K1+dk");
372 }
373 | SCALE DECR
374 {
375 bundle(1, "Kd1-k");
376 }
377 | DECR SCALE
378 {
379 bundle(1, "K1-dk");
380 }
381 | BASE INCR
382 {
383 bundle(1, "Id1+i");
384 }
385 | INCR BASE
386 {
387 bundle(1, "I1+di");
388 }
389 | BASE DECR
390 {
391 bundle(1, "Id1-i");
392 }
393 | DECR BASE
394 {
395 bundle(1, "I1-di");
396 }
397 | OBASE INCR
398 {
399 bundle(1, "Od1+o");
400 }
401 | INCR OBASE
402 {
403 bundle(1, "O1+do");
404 }
405 | OBASE DECR
406 {
407 bundle(1, "Od1-o");
408 }
409 | DECR OBASE
410 {
411 bundle(1, "O1-do");
412 }
413 | LETTER '(' cargs ')'
414 {
415 bundle(4, $3, "l", getf($1), "x");
416 }
417 | LETTER '(' ')'
418 {
419 bundle(3, "l", getf($1), "x");
420 }
421 | cons
422 {
423 bundle(2, " ", $1);
424 }
425 | DOT cons
426 {
427 bundle(2, " .", $2);
428 }
429 | cons DOT cons
430 {
431 bundle(4, " ", $1, ".", $3);
432 }
433 | cons DOT
434 {
435 bundle(3, " ", $1, ".");
436 }
437 | DOT
438 {
439 $<cptr>$ = "l.";
440 }
441 | LETTER
442 {
443 bundle(2, "l", $1);
444 }
445 | LETTER '=' e
446 {
447 bundle(3, $3, "ds", $1);
448 }
449 | LETTER EQOP e %prec '='
450 {
451 bundle(6, "l", $1, $3, $2, "ds", $1);
452 }
453 | LETTER '[' e ']' '=' e
454 {
455 bundle(5, $6, "d", $3, ":", geta($1));
456 }
457 | LETTER '[' e ']' EQOP e
458 {
459 bundle(9, $3, ";", geta($1), $6, $5, "d", $3, ":",
460 geta($1));
461 }
462 | LENGTH '(' e ')'
463 {
464 bundle(2, $3, "Z");
465 }
466 | SCALE '(' e ')'
467 {
468 bundle(2, $3, "X"); /* must be before '(' e ')' */
469 }
470 | '(' e ')'
471 {
472 $$ = $2;
473 }
474 | '?'
475 {
476 bundle(1, "?");
477 }
478 | SQRT '(' e ')'
479 {
480 bundle(2, $3, "v");
481 }
482 | '~' LETTER
483 {
484 bundle(2, "L", $2);
485 }
486 | SCALE '=' e
487 {
488 bundle(2, $3, "dk");
489 }
490 | SCALE EQOP e %prec '='
491 {
492 bundle(4, "K", $3, $2, "dk");
493 }
494 | BASE '=' e
495 {
496 bundle(2, $3, "di");
497 }
498 | BASE EQOP e %prec '='
499 {
500 bundle(4, "I", $3, $2, "di");
501 }
502 | OBASE '=' e
503 {
504 bundle(2, $3, "do");
505 }
506 | OBASE EQOP e %prec '='
507 {
508 bundle(4, "O", $3, $2, "do");
509 }
510 | SCALE
511 {
512 bundle(1, "K");
513 }
514 | BASE
515 {
516 bundle(1, "I");
517 }
518 | OBASE
519 {
520 bundle(1, "O");
521 }
522 ;
523
524 cargs : eora
525 | cargs ',' eora
526 {
527 bundle(2, $1, $3);
528 }
529 ;
530 eora : e
531 | LETTER '[' ']'
532 {
533 bundle(2, "l", geta($1));
534 }
535 ;
536
537 cons : constant
538 {
539 *cp++ = '\0';
540 }
541
542 constant: '_'
543 {
544 checkbuffer();
545 $<cptr>$ = cp;
546 *cp++ = '_';
547 }
548 | DIGIT
549 {
550 checkbuffer();
551 $<cptr>$ = cp;
552 *cp++ = $1;
553 }
554 | constant DIGIT
555 {
556 checkbuffer();
557 *cp++ = $2;
558 }
559 ;
560
561 CRS :
562 {
563 checkbuffer();
564 $$ = cp;
565 *cp++ = crs++;
566 *cp++ = '\0';
567 if (crs == '[')
568 crs += 3;
569 if (crs == 'a')
570 crs = '{';
571 if (crs >= 0241) {
572 (void) yyerror("program too big");
573 getout(1);
574 }
575 bstack[bindx++] = lev++;
576 }
577 ;
578
579 def : _DEFINE LETTER '('
580 {
581 $$ = getf($2);
582 pre = (int *)"";
583 post = (int *)"";
584 lev = 1;
585 bstack[bindx = 0] = 0;
586 }
587 ;
588
589 dargs : /* empty */
590 | lora
591 {
592 pp($1);
593 }
594 | dargs ',' lora
595 {
596 pp($3);
597 }
598 ;
599
600 dlets : lora
601 {
602 tp($1);
603 }
604 | dlets ',' lora
605 {
606 tp($3);
607 }
608 ;
609
610 lora : LETTER
611 {
612 $<cptr>$ = $1;
613 }
614 | LETTER '[' ']'
615 {
616 $$ = geta($1);
617 }
618 ;
619
620 %%
621 #define error 256
622
623 int peekc = -1;
624 int ifile; /* current index into sargv */
625 int sargc; /* size of sargv[] */
626 char **sargv; /* saved arg list without options */
627
628 char funtab[52] = {
629 01, 0, 02, 0, 03, 0, 04, 0, 05, 0, 06, 0, 07, 0,
630 010, 0, 011, 0, 012, 0, 013, 0, 014, 0, 015, 0, 016, 0, 017, 0,
631 020, 0, 021, 0, 022, 0, 023, 0, 024, 0, 025, 0, 026, 0, 027, 0,
632 030, 0, 031, 0, 032, 0
633 };
634
635 unsigned char atab[52] = {
636 0241, 0, 0242, 0, 0243, 0, 0244, 0, 0245, 0, 0246, 0, 0247, 0, 0250, 0,
637 0251, 0, 0252, 0, 0253, 0, 0254, 0, 0255, 0, 0256, 0, 0257, 0, 0260, 0,
638 0261, 0, 0262, 0, 0263, 0, 0264, 0, 0265, 0, 0266, 0, 0267, 0, 0270, 0,
639 0271, 0, 0272, 0
640 };
641
642 char *letr[26] = {
643 "a", "b", "c", "d", "e", "f", "g", "h", "i", "j",
644 "k", "l", "m", "n", "o", "p", "q", "r", "s", "t",
645 "u", "v", "w", "x", "y", "z"
646 };
647
648 int
yylex(void)649 yylex(void)
650 {
651 int c, ch;
652
653 restart:
654 c = getch();
655 peekc = -1;
656 while (c == ' ' || c == '\t')
657 c = getch();
658 if (c == '\\') {
659 (void) getch();
660 goto restart;
661 }
662 if (c <= 'z' && c >= 'a') {
663 /* look ahead to look for reserved words */
664 peekc = getch();
665 if (peekc >= 'a' && peekc <= 'z') {
666 /* must be reserved word */
667 if (c == 'i' && peekc == 'f') {
668 c = _IF;
669 goto skip;
670 }
671 if (c == 'w' && peekc == 'h') {
672 c = _WHILE;
673 goto skip;
674 }
675 if (c == 'f' && peekc == 'o') {
676 c = _FOR;
677 goto skip;
678 }
679 if (c == 's' && peekc == 'q') {
680 c = SQRT;
681 goto skip;
682 }
683 if (c == 'r' && peekc == 'e') {
684 c = _RETURN;
685 goto skip;
686 }
687 if (c == 'b' && peekc == 'r') {
688 c = _BREAK;
689 goto skip;
690 }
691 if (c == 'd' && peekc == 'e') {
692 c = _DEFINE;
693 goto skip;
694 }
695 if (c == 's' && peekc == 'c') {
696 c = SCALE;
697 goto skip;
698 }
699 if (c == 'b' && peekc == 'a') {
700 c = BASE;
701 goto skip;
702 }
703 if (c == 'i' && peekc == 'b') {
704 c = BASE;
705 goto skip;
706 }
707 if (c == 'o' && peekc == 'b') {
708 c = OBASE;
709 goto skip;
710 }
711 if (c == 'd' && peekc == 'i') {
712 c = FFF;
713 goto skip;
714 }
715 if (c == 'a' && peekc == 'u') {
716 c = _AUTO;
717 goto skip;
718 }
719 if (c == 'l' && peekc == 'e') {
720 c = LENGTH;
721 goto skip;
722 }
723 if (c == 'q' && peekc == 'u') {
724 getout(0);
725 }
726 /* could not be found */
727 return (error);
728
729 skip: /* skip over rest of word */
730 peekc = -1;
731 while ((ch = getch()) >= 'a' && ch <= 'z')
732 ;
733 peekc = ch;
734 return (c);
735 }
736
737 /* usual case; just one single letter */
738
739 yylval.cptr = letr[c-'a'];
740 return (LETTER);
741 }
742
743 if (c >= '0' && c <= '9' || c >= 'A' && c <= 'F') {
744 yylval.cc = c;
745 return (DIGIT);
746 }
747
748 switch (c) {
749 case '.':
750 return (DOT);
751
752 case '=':
753 switch ((peekc = getch())) {
754 case '=':
755 c = EQ;
756 goto gotit;
757
758 case '+':
759 c = EQPL;
760 goto gotit;
761
762 case '-':
763 c = EQMI;
764 goto gotit;
765
766 case '*':
767 c = EQMUL;
768 goto gotit;
769
770 case '/':
771 c = EQDIV;
772 goto gotit;
773
774 case '%':
775 c = EQREM;
776 goto gotit;
777
778 case '^':
779 c = EQEXP;
780 goto gotit;
781
782 default:
783 return ('=');
784 gotit:
785 peekc = -1;
786 return (c);
787 }
788
789 case '+':
790 return (cpeek('+', INCR, '=', EQPL, '+'));
791
792 case '-':
793 return (cpeek('-', DECR, '=', EQMI, '-'));
794
795 case '*':
796 return (cpeek('=', EQMUL, '\0', 0, '*'));
797
798 case '%':
799 return (cpeek('=', EQREM, '\0', 0, '%'));
800
801 case '^':
802 return (cpeek('=', EQEXP, '\0', 0, '^'));
803
804 case '<':
805 return (cpeek('=', LE, '\0', 0, '<'));
806
807 case '>':
808 return (cpeek('=', GE, '\0', 0, '>'));
809
810 case '!':
811 return (cpeek('=', NE, '\0', 0, '!'));
812
813 case '/':
814 if ((peekc = getch()) == '=') {
815 peekc = -1;
816 return (EQDIV);
817 }
818 if (peekc == '*') {
819 peekc = -1;
820 while ((getch() != '*') || ((peekc = getch()) != '/'))
821 ;
822 peekc = -1;
823 goto restart;
824 }
825 else
826 return (c);
827
828 case '"':
829 yylval.cptr = str;
830 while ((c = getch()) != '"') {
831 *str++ = c;
832 if (str >= &string[STRING_SIZE-1]) {
833 (void) yyerror("string space exceeded");
834 getout(1);
835 }
836 }
837 *str++ = '\0';
838 return (QSTR);
839
840 default:
841 return (c);
842 }
843 }
844
845 int
cpeek(char c1,int yes1,char c2,int yes2,char none)846 cpeek(char c1, int yes1, char c2, int yes2, char none)
847 {
848 int r;
849
850 peekc = getch();
851 if (peekc == c1)
852 r = yes1;
853 else if (peekc == c2)
854 r = yes2;
855 else
856 return (none);
857 peekc = -1;
858 return (r);
859 }
860
861
862 int
getch(void)863 getch(void)
864 {
865 int ch;
866 char mbuf[LINE_MAX];
867
868 loop:
869 ch = (peekc < 0) ? getc(in) : peekc;
870 peekc = -1;
871 if (ch != EOF)
872 return (ch);
873
874 if (++ifile >= sargc) {
875 if (ifile >= sargc+1)
876 getout(0);
877 in = stdin;
878 ln = 0;
879 goto loop;
880 }
881
882 (void) fclose(in);
883 if ((in = fopen(sargv[ifile], "r")) != NULL) {
884 ln = 0;
885 ss = sargv[ifile];
886 goto loop;
887 }
888 (void) snprintf(mbuf, sizeof (mbuf), "can't open input file %s",
889 sargv[ifile]);
890 ln = -1;
891 ss = "command line";
892 (void) yyerror(mbuf);
893 getout(1);
894 /*NOTREACHED*/
895 }
896
897 #define b_sp_max 5000
898 int b_space[b_sp_max];
899 int *b_sp_nxt = { b_space };
900
901 int bdebug = 0;
902
903 static int *
bundle(int i,...)904 bundle(int i, ...)
905 {
906 va_list ap;
907 int *q;
908
909 va_start(ap, i);
910 q = b_sp_nxt;
911 if (bdebug)
912 printf("bundle %d elements at %o\n", i, q);
913 while (i-- > 0) {
914 if (b_sp_nxt >= & b_space[b_sp_max])
915 (void) yyerror("bundling space exceeded");
916 *b_sp_nxt++ = va_arg(ap, int);
917 }
918 * b_sp_nxt++ = 0;
919 yyval.iptr = q;
920 va_end(ap);
921 return (q);
922 }
923
924 void
routput(int * p)925 routput(int *p)
926 {
927 if (bdebug) printf("routput(%o)\n", p);
928 if (p >= &b_space[0] && p < &b_space[b_sp_max]) {
929 /* part of a bundle */
930 while (*p != 0)
931 routput((int *)*p++);
932 }
933 else
934 printf((char *)p); /* character string */
935 }
936
937 void
output(int * p)938 output(int *p)
939 {
940 routput(p);
941 b_sp_nxt = & b_space[0];
942 printf("\n");
943 (void) fflush(stdout);
944 cp = cary;
945 crs = rcrs;
946 }
947
948 void
conout(int * p,char * s)949 conout(int *p, char *s)
950 {
951 printf("[");
952 routput(p);
953 printf("]s%s\n", s);
954 (void) fflush(stdout);
955 lev--;
956 }
957
958 int
yyerror(const char * s)959 yyerror(const char *s)
960 {
961 if (ifile >= sargc)
962 ss = "teletype";
963
964 if (ss == 0 || *ss == 0)
965 (void) fprintf(stderr, gettext("%s on line %d\n"), s, ln+1);
966 else
967 (void) fprintf(stderr, gettext("%s on line %d, %s\n"),
968 s, ln+1, ss);
969 (void) fflush(stderr);
970
971 cp = cary;
972 crs = rcrs;
973 bindx = 0;
974 lev = 0;
975 b_sp_nxt = &b_space[0];
976 return (0);
977 }
978
979 void
checkbuffer(void)980 checkbuffer(void)
981 {
982 /* Do not exceed the last char in input line buffer */
983 if (cp >= cpend) {
984 (void) yyerror("line too long\n");
985 getout(1);
986 }
987 }
988
989 void
pp(int * s)990 pp(int *s)
991 {
992 /* puts the relevant stuff on pre and post for the letter s */
993
994 (void) bundle(3, "S", s, pre);
995 pre = yyval.iptr;
996 (void) bundle(4, post, "L", s, "s.");
997 post = yyval.iptr;
998 }
999
1000 void
tp(int * s)1001 tp(int *s)
1002 { /* same as pp, but for temps */
1003 bundle(3, "0S", s, pre);
1004 pre = yyval.iptr;
1005 bundle(4, post, "L", s, "s.");
1006 post = yyval.iptr;
1007 }
1008
1009 void
yyinit(int argc,char ** argv)1010 yyinit(int argc, char **argv)
1011 {
1012 char mbuf[LINE_MAX];
1013
1014 (void) signal(SIGINT, SIG_IGN); /* ignore all interrupts */
1015
1016 sargv = argv;
1017 sargc = argc;
1018 if (sargc == 0)
1019 in = stdin;
1020 else if ((in = fopen(sargv[0], "r")) == NULL) {
1021 (void) snprintf(mbuf, sizeof (mbuf), "can't open input file %s",
1022 sargv[0]);
1023 ln = -1;
1024 ss = "command line";
1025 (void) yyerror(mbuf);
1026 getout(1);
1027 }
1028 ifile = 0;
1029 ln = 0;
1030 ss = sargv[0];
1031 }
1032
1033 static void
getout(int code)1034 getout(int code)
1035 {
1036 printf("q");
1037 (void) fflush(stdout);
1038 exit(code);
1039 }
1040
1041 int *
getf(char * p)1042 getf(char *p)
1043 {
1044 return ((int *) &funtab[2*(*p -0141)]);
1045 }
1046
1047 int *
geta(char * p)1048 geta(char *p)
1049 {
1050 return ((int *) &atab[2*(*p - 0141)]);
1051 }
1052
1053 int
main(int argc,char ** argv)1054 main(int argc, char **argv)
1055 {
1056 int p[2];
1057 int cflag = 0;
1058 int lflag = 0;
1059 int flag = 0;
1060 char **av;
1061 int filecounter = 0;
1062
1063 (void) setlocale(LC_ALL, "");
1064 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
1065 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */
1066 #endif
1067 (void) textdomain(TEXT_DOMAIN);
1068
1069 while ((flag = getopt(argc, argv, "dcl")) != EOF) {
1070 switch (flag) {
1071 case 'd':
1072 case 'c':
1073 cflag++;
1074 break;
1075
1076 case 'l':
1077 lflag++;
1078 break;
1079
1080 default:
1081 fflush(stdout);
1082 usage();
1083 break;
1084 }
1085 }
1086
1087 argc -= optind;
1088 av = &argv[optind];
1089
1090 /*
1091 * argc is the count of arguments, which should be filenames,
1092 * remaining in argv. av is a pointer to the first of the
1093 * remaining arguments.
1094 */
1095
1096 for (filecounter = 0; filecounter < argc; filecounter++) {
1097 if ((strlen(av[filecounter])) >= PATH_MAX) {
1098 (void) fprintf(stderr,
1099 gettext("File argument too long\n"));
1100 exit(2);
1101 }
1102 }
1103
1104 if (lflag) {
1105 /*
1106 * if the user wants to include the math library, prepend
1107 * the math library filename to the argument list by
1108 * overwriting the last option (there must be at least one
1109 * supplied option if this is being done).
1110 */
1111 av = &argv[optind-1];
1112 av[0] = "/usr/lib/lib.b";
1113 argc++;
1114 }
1115
1116 if (cflag) {
1117 yyinit(argc, av);
1118 yyparse();
1119 exit(0);
1120 }
1121
1122 pipe(p);
1123 if (fork() == 0) {
1124 (void) close(1);
1125 dup(p[1]);
1126 (void) close(p[0]);
1127 (void) close(p[1]);
1128 yyinit(argc, av);
1129 yyparse();
1130 exit(0);
1131 }
1132 (void) close(0);
1133 dup(p[0]);
1134 (void) close(p[0]);
1135 (void) close(p[1]);
1136 #ifdef XPG6
1137 execl("/usr/xpg6/bin/dc", "dc", "-", 0);
1138 #else
1139 execl("/usr/bin/dc", "dc", "-", 0);
1140 #endif
1141
1142 return (1);
1143 }
1144
1145 static void
usage(void)1146 usage(void)
1147 {
1148 (void) fprintf(stderr, gettext(
1149 "usage: bc [ -c ] [ -l ] [ file ... ]\n"));
1150 exit(2);
1151 }
1152