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 void yyerror(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 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 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 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 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 void
yyerror(char * s)959 yyerror(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 }
977
978 void
checkbuffer(void)979 checkbuffer(void)
980 {
981 /* Do not exceed the last char in input line buffer */
982 if (cp >= cpend) {
983 yyerror("line too long\n");
984 getout(1);
985 }
986 }
987
988 void
pp(int * s)989 pp(int *s)
990 {
991 /* puts the relevant stuff on pre and post for the letter s */
992
993 (void) bundle(3, "S", s, pre);
994 pre = yyval.iptr;
995 (void) bundle(4, post, "L", s, "s.");
996 post = yyval.iptr;
997 }
998
999 void
tp(int * s)1000 tp(int *s)
1001 { /* same as pp, but for temps */
1002 bundle(3, "0S", s, pre);
1003 pre = yyval.iptr;
1004 bundle(4, post, "L", s, "s.");
1005 post = yyval.iptr;
1006 }
1007
1008 void
yyinit(int argc,char ** argv)1009 yyinit(int argc, char **argv)
1010 {
1011 char mbuf[LINE_MAX];
1012
1013 (void) signal(SIGINT, SIG_IGN); /* ignore all interrupts */
1014
1015 sargv = argv;
1016 sargc = argc;
1017 if (sargc == 0)
1018 in = stdin;
1019 else if ((in = fopen(sargv[0], "r")) == NULL) {
1020 (void) snprintf(mbuf, sizeof (mbuf), "can't open input file %s",
1021 sargv[0]);
1022 ln = -1;
1023 ss = "command line";
1024 yyerror(mbuf);
1025 getout(1);
1026 }
1027 ifile = 0;
1028 ln = 0;
1029 ss = sargv[0];
1030 }
1031
1032 static void
getout(int code)1033 getout(int code)
1034 {
1035 printf("q");
1036 (void) fflush(stdout);
1037 exit(code);
1038 }
1039
1040 int *
getf(char * p)1041 getf(char *p)
1042 {
1043 return ((int *) &funtab[2*(*p -0141)]);
1044 }
1045
1046 int *
geta(char * p)1047 geta(char *p)
1048 {
1049 return ((int *) &atab[2*(*p - 0141)]);
1050 }
1051
1052 int
main(int argc,char ** argv)1053 main(int argc, char **argv)
1054 {
1055 int p[2];
1056 int cflag = 0;
1057 int lflag = 0;
1058 int flag = 0;
1059 char **av;
1060 int filecounter = 0;
1061
1062 (void) setlocale(LC_ALL, "");
1063 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
1064 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */
1065 #endif
1066 (void) textdomain(TEXT_DOMAIN);
1067
1068 while ((flag = getopt(argc, argv, "dcl")) != EOF) {
1069 switch (flag) {
1070 case 'd':
1071 case 'c':
1072 cflag++;
1073 break;
1074
1075 case 'l':
1076 lflag++;
1077 break;
1078
1079 default:
1080 fflush(stdout);
1081 usage();
1082 break;
1083 }
1084 }
1085
1086 argc -= optind;
1087 av = &argv[optind];
1088
1089 /*
1090 * argc is the count of arguments, which should be filenames,
1091 * remaining in argv. av is a pointer to the first of the
1092 * remaining arguments.
1093 */
1094
1095 for (filecounter = 0; filecounter < argc; filecounter++) {
1096 if ((strlen(av[filecounter])) >= PATH_MAX) {
1097 (void) fprintf(stderr,
1098 gettext("File argument too long\n"));
1099 exit(2);
1100 }
1101 }
1102
1103 if (lflag) {
1104 /*
1105 * if the user wants to include the math library, prepend
1106 * the math library filename to the argument list by
1107 * overwriting the last option (there must be at least one
1108 * supplied option if this is being done).
1109 */
1110 av = &argv[optind-1];
1111 av[0] = "/usr/lib/lib.b";
1112 argc++;
1113 }
1114
1115 if (cflag) {
1116 yyinit(argc, av);
1117 yyparse();
1118 exit(0);
1119 }
1120
1121 pipe(p);
1122 if (fork() == 0) {
1123 (void) close(1);
1124 dup(p[1]);
1125 (void) close(p[0]);
1126 (void) close(p[1]);
1127 yyinit(argc, av);
1128 yyparse();
1129 exit(0);
1130 }
1131 (void) close(0);
1132 dup(p[0]);
1133 (void) close(p[0]);
1134 (void) close(p[1]);
1135 #ifdef XPG6
1136 execl("/usr/xpg6/bin/dc", "dc", "-", 0);
1137 #else
1138 execl("/usr/bin/dc", "dc", "-", 0);
1139 #endif
1140
1141 return (1);
1142 }
1143
1144 static void
usage(void)1145 usage(void)
1146 {
1147 (void) fprintf(stderr, gettext(
1148 "usage: bc [ -c ] [ -l ] [ file ... ]\n"));
1149 exit(2);
1150 }
1151