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