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 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 25 /* All Rights Reserved */ 26 27 28 /* 29 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 30 * Use is subject to license terms. 31 */ 32 33 %{ 34 #ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.9 */ 35 %} 36 %{ 37 #include <stdio.h> 38 #include <stdarg.h> 39 #include <limits.h> 40 #include <libintl.h> 41 #include <locale.h> 42 #include <signal.h> 43 44 static int *getout(int); 45 static int *bundle(int, ...); 46 static void usage(void); 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, $2); 107 rcrs = crs; 108 output(""); 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 yylex() 482 { 483 int c, ch; 484 485 restart: 486 c = getch(); 487 peekc = -1; 488 while (c == ' ' || c == '\t') 489 c = getch(); 490 if (c == '\\') { 491 (void) getch(); 492 goto restart; 493 } 494 if (c <= 'z' && c >= 'a') { 495 /* look ahead to look for reserved words */ 496 peekc = getch(); 497 if (peekc >= 'a' && peekc <= 'z') { 498 /* must be reserved word */ 499 if (c == 'i' && peekc == 'f') { 500 c = _IF; 501 goto skip; 502 } 503 if (c == 'w' && peekc == 'h') { 504 c = _WHILE; 505 goto skip; 506 } 507 if (c == 'f' && peekc == 'o') { 508 c = _FOR; 509 goto skip; 510 } 511 if (c == 's' && peekc == 'q') { 512 c = SQRT; 513 goto skip; 514 } 515 if (c == 'r' && peekc == 'e') { 516 c = _RETURN; 517 goto skip; 518 } 519 if (c == 'b' && peekc == 'r') { 520 c = _BREAK; 521 goto skip; 522 } 523 if (c == 'd' && peekc == 'e') { 524 c = _DEFINE; 525 goto skip; 526 } 527 if (c == 's' && peekc == 'c') { 528 c = SCALE; 529 goto skip; 530 } 531 if (c == 'b' && peekc == 'a') { 532 c = BASE; 533 goto skip; 534 } 535 if (c == 'i' && peekc == 'b') { 536 c = BASE; 537 goto skip; 538 } 539 if (c == 'o' && peekc == 'b') { 540 c = OBASE; 541 goto skip; 542 } 543 if (c == 'd' && peekc == 'i') { 544 c = FFF; 545 goto skip; 546 } 547 if (c == 'a' && peekc == 'u') { 548 c = _AUTO; 549 goto skip; 550 } 551 if (c == 'l' && peekc == 'e') { 552 c = LENGTH; 553 goto skip; 554 } 555 if (c == 'q' && peekc == 'u') { 556 getout(0); 557 } 558 /* could not be found */ 559 return (error); 560 561 skip: /* skip over rest of word */ 562 peekc = -1; 563 while ((ch = getch()) >= 'a' && ch <= 'z') 564 ; 565 peekc = ch; 566 return (c); 567 } 568 569 /* usual case; just one single letter */ 570 571 yylval.cptr = letr[c-'a']; 572 return (LETTER); 573 } 574 575 if (c >= '0' && c <= '9' || c >= 'A' && c <= 'F') { 576 yylval.cc = c; 577 return (DIGIT); 578 } 579 580 switch (c) { 581 case '.': 582 return (DOT); 583 584 case '=': 585 switch ((peekc = getch())) { 586 case '=': 587 c = EQ; 588 goto gotit; 589 590 case '+': 591 c = EQPL; 592 goto gotit; 593 594 case '-': 595 c = EQMI; 596 goto gotit; 597 598 case '*': 599 c = EQMUL; 600 goto gotit; 601 602 case '/': 603 c = EQDIV; 604 goto gotit; 605 606 case '%': 607 c = EQREM; 608 goto gotit; 609 610 case '^': 611 c = EQEXP; 612 goto gotit; 613 614 default: 615 return ('='); 616 gotit: 617 peekc = -1; 618 return (c); 619 } 620 621 case '+': 622 return (cpeek('+', INCR, '=', EQPL, '+')); 623 624 case '-': 625 return (cpeek('-', DECR, '=', EQMI, '-')); 626 627 case '*': 628 return (cpeek('=', EQMUL, '\0', 0, '*')); 629 630 case '%': 631 return (cpeek('=', EQREM, '\0', 0, '%')); 632 633 case '^': 634 return (cpeek('=', EQEXP, '\0', 0, '^')); 635 636 case '<': 637 return (cpeek('=', LE, '\0', 0, '<')); 638 639 case '>': 640 return (cpeek('=', GE, '\0', 0, '>')); 641 642 case '!': 643 return (cpeek('=', NE, '\0', 0, '!')); 644 645 case '/': 646 if ((peekc = getch()) == '=') { 647 peekc = -1; 648 return (EQDIV); 649 } 650 if (peekc == '*') { 651 peekc = -1; 652 while ((getch() != '*') || ((peekc = getch()) != '/')) 653 ; 654 peekc = -1; 655 goto restart; 656 } 657 else 658 return (c); 659 660 case '"': 661 yylval.cptr = str; 662 while ((c = getch()) != '"') { 663 *str++ = c; 664 if (str >= &string[STRING_SIZE-1]) { 665 yyerror("string space exceeded"); 666 getout(1); 667 } 668 } 669 *str++ = '\0'; 670 return (QSTR); 671 672 default: 673 return (c); 674 } 675 } 676 677 cpeek(c1, yes1, c2, yes2, none) 678 char c1, c2, none; 679 { 680 int r; 681 682 peekc = getch(); 683 if (peekc == c1) 684 r = yes1; 685 else if (peekc == c2) 686 r = yes2; 687 else 688 return (none); 689 peekc = -1; 690 return (r); 691 } 692 693 getch() 694 { 695 int ch; 696 char mbuf[LINE_MAX]; 697 698 loop: 699 ch = (peekc < 0) ? getc(in) : peekc; 700 peekc = -1; 701 if (ch != EOF) 702 return (ch); 703 704 if (++ifile >= sargc) { 705 if (ifile >= sargc+1) 706 getout(0); 707 in = stdin; 708 ln = 0; 709 goto loop; 710 } 711 712 (void) fclose(in); 713 if ((in = fopen(sargv[ifile], "r")) != NULL) { 714 ln = 0; 715 ss = sargv[ifile]; 716 goto loop; 717 } 718 (void) snprintf(mbuf, sizeof (mbuf), "can't open input file %s", 719 sargv[ifile]); 720 ln = -1; 721 ss = "command line"; 722 yyerror(mbuf); 723 getout(1); 724 /*NOTREACHED*/ 725 } 726 727 #define b_sp_max 5000 728 int b_space[b_sp_max]; 729 int *b_sp_nxt = { b_space }; 730 731 int bdebug = 0; 732 733 static int * 734 bundle(int i, ...) 735 { 736 va_list ap; 737 int *q; 738 739 va_start(ap, i); 740 q = b_sp_nxt; 741 if (bdebug) 742 printf("bundle %d elements at %o\n", i, q); 743 while (i-- > 0) { 744 if (b_sp_nxt >= & b_space[b_sp_max]) 745 yyerror("bundling space exceeded"); 746 *b_sp_nxt++ = va_arg(ap, int); 747 } 748 * b_sp_nxt++ = 0; 749 yyval.iptr = q; 750 va_end(ap); 751 return (q); 752 } 753 754 routput(p) 755 int *p; 756 { 757 if (bdebug) printf("routput(%o)\n", p); 758 if (p >= &b_space[0] && p < &b_space[b_sp_max]) { 759 /* part of a bundle */ 760 while (*p != 0) 761 routput(*p++); 762 } 763 else 764 printf((char *)p); /* character string */ 765 } 766 767 output(p) 768 int *p; 769 { 770 routput(p); 771 b_sp_nxt = & b_space[0]; 772 printf("\n"); 773 (void) fflush(stdout); 774 cp = cary; 775 crs = rcrs; 776 } 777 778 conout(p, s) 779 int *p; 780 char *s; 781 { 782 printf("["); 783 routput(p); 784 printf("]s%s\n", s); 785 (void) fflush(stdout); 786 lev--; 787 } 788 789 yyerror(s) 790 char *s; 791 { 792 if (ifile >= sargc) 793 ss = "teletype"; 794 795 if (ss == 0 || *ss == 0) 796 (void) fprintf(stderr, gettext("%s on line %d\n"), s, ln+1); 797 else 798 (void) fprintf(stderr, gettext("%s on line %d, %s\n"), 799 s, ln+1, ss); 800 (void) fflush(stderr); 801 802 cp = cary; 803 crs = rcrs; 804 bindx = 0; 805 lev = 0; 806 b_sp_nxt = &b_space[0]; 807 } 808 809 checkbuffer() 810 { 811 /* Do not exceed the last char in input line buffer */ 812 if (cp >= cpend) { 813 yyerror("line too long\n"); 814 getout(1); 815 } 816 } 817 818 pp(s) 819 int *s; 820 { 821 /* puts the relevant stuff on pre and post for the letter s */ 822 823 (void) bundle(3, "S", s, pre); 824 pre = yyval.iptr; 825 (void) bundle(4, post, "L", s, "s."); 826 post = yyval.iptr; 827 } 828 829 tp(s) 830 int *s; 831 { /* same as pp, but for temps */ 832 bundle(3, "0S", s, pre); 833 pre = yyval.iptr; 834 bundle(4, post, "L", s, "s."); 835 post = yyval.iptr; 836 } 837 838 yyinit(argc, argv) 839 int argc; 840 char *argv[]; 841 { 842 char mbuf[LINE_MAX]; 843 844 (void) signal(SIGINT, SIG_IGN); /* ignore all interrupts */ 845 846 sargv = argv; 847 sargc = argc; 848 if (sargc == 0) 849 in = stdin; 850 else if ((in = fopen(sargv[0], "r")) == NULL) { 851 (void) snprintf(mbuf, sizeof (mbuf), "can't open input file %s", 852 sargv[0]); 853 ln = -1; 854 ss = "command line"; 855 yyerror(mbuf); 856 getout(1); 857 } 858 ifile = 0; 859 ln = 0; 860 ss = sargv[0]; 861 } 862 863 static int * 864 getout(code) 865 int code; 866 { 867 printf("q"); 868 (void) fflush(stdout); 869 exit(code); 870 } 871 872 int * 873 getf(p) 874 char *p; 875 { 876 return ((int *) &funtab[2*(*p -0141)]); 877 } 878 879 int * 880 geta(p) 881 char *p; 882 { 883 return ((int *) &atab[2*(*p - 0141)]); 884 } 885 886 main(argc, argv) 887 int argc; 888 char *argv[]; 889 { 890 int p[2]; 891 int cflag = 0; 892 int lflag = 0; 893 int flag = 0; 894 char **av; 895 int filecounter = 0; 896 897 (void) setlocale(LC_ALL, ""); 898 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ 899 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */ 900 #endif 901 (void) textdomain(TEXT_DOMAIN); 902 903 while ((flag = getopt(argc, argv, "dcl")) != EOF) { 904 switch (flag) { 905 case 'd': 906 case 'c': 907 cflag++; 908 break; 909 910 case 'l': 911 lflag++; 912 break; 913 914 default: 915 fflush(stdout); 916 usage(); 917 break; 918 } 919 } 920 921 argc -= optind; 922 av = &argv[optind]; 923 924 /* 925 * argc is the count of arguments, which should be filenames, 926 * remaining in argv. av is a pointer to the first of the 927 * remaining arguments. 928 */ 929 930 for (filecounter = 0; filecounter < argc; filecounter++) { 931 if ((strlen(av[filecounter])) >= PATH_MAX) { 932 (void) fprintf(stderr, 933 gettext("File argument too long\n")); 934 exit(2); 935 } 936 } 937 938 if (lflag) { 939 /* 940 * if the user wants to include the math library, prepend 941 * the math library filename to the argument list by 942 * overwriting the last option (there must be at least one 943 * supplied option if this is being done). 944 */ 945 av = &argv[optind-1]; 946 av[0] = "/usr/lib/lib.b"; 947 argc++; 948 } 949 950 if (cflag) { 951 yyinit(argc, av); 952 yyparse(); 953 exit(0); 954 } 955 956 pipe(p); 957 if (fork() == 0) { 958 (void) close(1); 959 dup(p[1]); 960 (void) close(p[0]); 961 (void) close(p[1]); 962 yyinit(argc, av); 963 yyparse(); 964 exit(0); 965 } 966 (void) close(0); 967 dup(p[0]); 968 (void) close(p[0]); 969 (void) close(p[1]); 970 #ifdef XPG6 971 execl("/usr/xpg6/bin/dc", "dc", "-", 0); 972 #else 973 execl("/usr/bin/dc", "dc", "-", 0); 974 #endif 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