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