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 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 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 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 * 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 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 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 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 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 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 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 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 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 866 getout(int code) 867 { 868 printf("q"); 869 (void) fflush(stdout); 870 exit(code); 871 } 872 873 int * 874 getf(char *p) 875 { 876 return ((int *) &funtab[2*(*p -0141)]); 877 } 878 879 int * 880 geta(char *p) 881 { 882 return ((int *) &atab[2*(*p - 0141)]); 883 } 884 885 int 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 978 usage(void) 979 { 980 (void) fprintf(stderr, gettext( 981 "usage: bc [ -c ] [ -l ] [ file ... ]\n")); 982 exit(2); 983 } 984