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