1: %{ 2: static char *sccsid = "@(#)bc.y 4.3.1 (2.11BSD) 1996/10/23"; 3: int *getout(); 4: %} 5: %right '=' 6: %left '+' '-' 7: %left '*' '/' '%' 8: %right '^' 9: %left UMINUS 10: 11: %term LETTER DIGIT SQRT LENGTH _IF FFF EQ 12: %term _WHILE _FOR NE LE GE INCR DECR 13: %term _RETURN _BREAK _DEFINE BASE OBASE SCALE 14: %term EQPL EQMI EQMUL EQDIV EQREM EQEXP 15: %term _AUTO DOT 16: %term QSTR 17: 18: %{ 19: #include <stdio.h> 20: FILE *in; 21: char cary[1000], *cp = { cary }; 22: char string[1000], *str = {string}; 23: int crs = '0'; 24: int rcrs = '0'; /* reset crs */ 25: int bindx = 0; 26: int lev = 0; 27: int ln; 28: char *ss; 29: int bstack[10] = { 0 }; 30: char *numb[15] = { 31: " 0", " 1", " 2", " 3", " 4", " 5", 32: " 6", " 7", " 8", " 9", " 10", " 11", 33: " 12", " 13", " 14" }; 34: int *pre, *post; 35: %} 36: %% 37: start : 38: | start stat tail 39: = output( $2 ); 40: | start def dargs ')' '{' dlist slist '}' 41: ={ bundle( 6,pre, $7, post ,"0",numb[lev],"Q"); 42: conout( $$, $2 ); 43: rcrs = crs; 44: output( "" ); 45: lev = bindx = 0; 46: } 47: ; 48: 49: dlist : tail 50: | dlist _AUTO dlets tail 51: ; 52: 53: stat : e 54: ={ bundle(2, $1, "ps." ); } 55: | 56: ={ bundle(1, "" ); } 57: | QSTR 58: ={ bundle(3,"[",$1,"]P");} 59: | LETTER '=' e 60: ={ bundle(3, $3, "s", $1 ); } 61: | LETTER '[' e ']' '=' e 62: ={ bundle(4, $6, $3, ":", geta($1)); } 63: | LETTER EQOP e 64: ={ bundle(6, "l", $1, $3, $2, "s", $1 ); } 65: | LETTER '[' e ']' EQOP e 66: ={ bundle(8,$3, ";", geta($1), $6, $5, $3, ":", geta($1));} 67: | _BREAK 68: ={ bundle(2, numb[lev-bstack[bindx-1]], "Q" ); } 69: | _RETURN '(' e ')' 70: = bundle(4, $3, post, numb[lev], "Q" ); 71: | _RETURN '(' ')' 72: = bundle(4, "0", post, numb[lev], "Q" ); 73: | _RETURN 74: = bundle(4,"0",post,numb[lev],"Q"); 75: | SCALE '=' e 76: = bundle(2, $3, "k"); 77: | SCALE EQOP e 78: = bundle(4,"K",$3,$2,"k"); 79: | BASE '=' e 80: = bundle(2,$3, "i"); 81: | BASE EQOP e 82: = bundle(4,"I",$3,$2,"i"); 83: | OBASE '=' e 84: = bundle(2,$3,"o"); 85: | OBASE EQOP e 86: = bundle(4,"O",$3,$2,"o"); 87: | '{' slist '}' 88: ={ $$ = $2; } 89: | FFF 90: ={ bundle(1,"fY"); } 91: | error 92: ={ bundle(1,"c"); } 93: | _IF CRS BLEV '(' re ')' stat 94: ={ conout( $7, $2 ); 95: bundle(3, $5, $2, " " ); 96: } 97: | _WHILE CRS '(' re ')' stat BLEV 98: ={ bundle(3, $6, $4, $2 ); 99: conout( $$, $2 ); 100: bundle(3, $4, $2, " " ); 101: } 102: | fprefix CRS re ';' e ')' stat BLEV 103: ={ bundle(5, $7, $5, "s.", $3, $2 ); 104: conout( $$, $2 ); 105: bundle(5, $1, "s.", $3, $2, " " ); 106: } 107: | '~' LETTER '=' e 108: ={ bundle(3,$4,"S",$2); } 109: ; 110: 111: EQOP : EQPL 112: ={ $$ = "+"; } 113: | EQMI 114: ={ $$ = "-"; } 115: | EQMUL 116: ={ $$ = "*"; } 117: | EQDIV 118: ={ $$ = "/"; } 119: | EQREM 120: ={ $$ = "%%"; } 121: | EQEXP 122: ={ $$ = "^"; } 123: ; 124: 125: fprefix : _FOR '(' e ';' 126: ={ $$ = $3; } 127: ; 128: 129: BLEV : 130: ={ --bindx; } 131: ; 132: 133: slist : stat 134: | slist tail stat 135: ={ bundle(2, $1, $3 ); } 136: ; 137: 138: tail : '\n' 139: ={ln++;} 140: | ';' 141: ; 142: 143: re : e EQ e 144: = bundle(3, $1, $3, "=" ); 145: | e '<' e 146: = bundle(3, $1, $3, ">" ); 147: | e '>' e 148: = bundle(3, $1, $3, "<" ); 149: | e NE e 150: = bundle(3, $1, $3, "!=" ); 151: | e GE e 152: = bundle(3, $1, $3, "!>" ); 153: | e LE e 154: = bundle(3, $1, $3, "!<" ); 155: | e 156: = bundle(2, $1, " 0!=" ); 157: ; 158: 159: e : e '+' e 160: = bundle(3, $1, $3, "+" ); 161: | e '-' e 162: = bundle(3, $1, $3, "-" ); 163: | '-' e %prec UMINUS 164: = bundle(3, " 0", $2, "-" ); 165: | e '*' e 166: = bundle(3, $1, $3, "*" ); 167: | e '/' e 168: = bundle(3, $1, $3, "/" ); 169: | e '%' e 170: = bundle(3, $1, $3, "%%" ); 171: | e '^' e 172: = bundle(3, $1, $3, "^" ); 173: | LETTER '[' e ']' 174: ={ bundle(3,$3, ";", geta($1)); } 175: | LETTER INCR 176: = bundle(4, "l", $1, "d1+s", $1 ); 177: | INCR LETTER 178: = bundle(4, "l", $2, "1+ds", $2 ); 179: | DECR LETTER 180: = bundle(4, "l", $2, "1-ds", $2 ); 181: | LETTER DECR 182: = bundle(4, "l", $1, "d1-s", $1 ); 183: | LETTER '[' e ']' INCR 184: = bundle(7,$3,";",geta($1),"d1+",$3,":",geta($1)); 185: | INCR LETTER '[' e ']' 186: = bundle(7,$4,";",geta($2),"1+d",$4,":",geta($2)); 187: | LETTER '[' e ']' DECR 188: = bundle(7,$3,";",geta($1),"d1-",$3,":",geta($1)); 189: | DECR LETTER '[' e ']' 190: = bundle(7,$4,";",geta($2),"1-d",$4,":",geta($2)); 191: | SCALE INCR 192: = bundle(1,"Kd1+k"); 193: | INCR SCALE 194: = bundle(1,"K1+dk"); 195: | SCALE DECR 196: = bundle(1,"Kd1-k"); 197: | DECR SCALE 198: = bundle(1,"K1-dk"); 199: | BASE INCR 200: = bundle(1,"Id1+i"); 201: | INCR BASE 202: = bundle(1,"I1+di"); 203: | BASE DECR 204: = bundle(1,"Id1-i"); 205: | DECR BASE 206: = bundle(1,"I1-di"); 207: | OBASE INCR 208: = bundle(1,"Od1+o"); 209: | INCR OBASE 210: = bundle(1,"O1+do"); 211: | OBASE DECR 212: = bundle(1,"Od1-o"); 213: | DECR OBASE 214: = bundle(1,"O1-do"); 215: | LETTER '(' cargs ')' 216: = bundle(4, $3, "l", getf($1), "x" ); 217: | LETTER '(' ')' 218: = bundle(3, "l", getf($1), "x" ); 219: | cons 220: ={ bundle(2, " ", $1 ); } 221: | DOT cons 222: ={ bundle(2, " .", $2 ); } 223: | cons DOT cons 224: ={ bundle(4, " ", $1, ".", $3 ); } 225: | cons DOT 226: ={ bundle(3, " ", $1, "." ); } 227: | DOT 228: ={ $$ = "l."; } 229: | LETTER 230: = { bundle(2, "l", $1 ); } 231: | LETTER '=' e 232: ={ bundle(3, $3, "ds", $1 ); } 233: | LETTER EQOP e %prec '=' 234: ={ bundle(6, "l", $1, $3, $2, "ds", $1 ); } 235: | LETTER '[' e ']' '=' e 236: = { bundle(5,$6,"d",$3,":",geta($1)); } 237: | LETTER '[' e ']' EQOP e 238: = { bundle(9,$3,";",geta($1),$6,$5,"d",$3,":",geta($1)); } 239: | LENGTH '(' e ')' 240: = bundle(2,$3,"Z"); 241: | SCALE '(' e ')' 242: = bundle(2,$3,"X"); /* must be before '(' e ')' */ 243: | '(' e ')' 244: = { $$ = $2; } 245: | '?' 246: ={ bundle(1, "?" ); } 247: | SQRT '(' e ')' 248: ={ bundle(2, $3, "v" ); } 249: | '~' LETTER 250: ={ bundle(2,"L",$2); } 251: | SCALE '=' e 252: = bundle(2,$3,"dk"); 253: | SCALE EQOP e %prec '=' 254: = bundle(4,"K",$3,$2,"dk"); 255: | BASE '=' e 256: = bundle(2,$3,"di"); 257: | BASE EQOP e %prec '=' 258: = bundle(4,"I",$3,$2,"di"); 259: | OBASE '=' e 260: = bundle(2,$3,"do"); 261: | OBASE EQOP e %prec '=' 262: = bundle(4,"O",$3,$2,"do"); 263: | SCALE 264: = bundle(1,"K"); 265: | BASE 266: = bundle(1,"I"); 267: | OBASE 268: = bundle(1,"O"); 269: ; 270: 271: cargs : eora 272: | cargs ',' eora 273: = bundle(2, $1, $3 ); 274: ; 275: eora: e 276: | LETTER '[' ']' 277: =bundle(2,"l",geta($1)); 278: ; 279: 280: cons : constant 281: ={ *cp++ = '\0'; } 282: 283: constant: 284: '_' 285: ={ $$ = cp; *cp++ = '_'; } 286: | DIGIT 287: ={ $$ = cp; *cp++ = $1; } 288: | constant DIGIT 289: ={ *cp++ = $2; } 290: ; 291: 292: CRS : 293: ={ $$ = cp; *cp++ = crs++; *cp++ = '\0'; 294: if(crs == '[')crs+=3; 295: if(crs == 'a')crs='{'; 296: if(crs >= 0241){yyerror("program too big"); 297: getout(); 298: } 299: bstack[bindx++] = lev++; } 300: ; 301: 302: def : _DEFINE LETTER '(' 303: ={ $$ = getf($2); 304: pre = ""; 305: post = ""; 306: lev = 1; 307: bstack[bindx=0] = 0; 308: } 309: ; 310: 311: dargs : 312: | lora 313: ={ pp( $1 ); } 314: | dargs ',' lora 315: ={ pp( $3 ); } 316: ; 317: 318: dlets : lora 319: ={ tp($1); } 320: | dlets ',' lora 321: ={ tp($3); } 322: ; 323: lora : LETTER 324: | LETTER '[' ']' 325: ={ $$ = geta($1); } 326: ; 327: 328: %% 329: # define error 256 330: 331: int peekc = -1; 332: int sargc; 333: int ifile; 334: char **sargv; 335: 336: char funtab[52] = { 337: 01,0,02,0,03,0,04,0,05,0,06,0,07,0,010,0,011,0,012,0,013,0,014,0,015,0,016,0,017,0, 338: 020,0,021,0,022,0,023,0,024,0,025,0,026,0,027,0,030,0,031,0,032,0 }; 339: char atab[52] = { 340: 0241,0,0242,0,0243,0,0244,0,0245,0,0246,0,0247,0,0250,0,0251,0,0252,0,0253,0, 341: 0254,0,0255,0,0256,0,0257,0,0260,0,0261,0,0262,0,0263,0,0264,0,0265,0,0266,0, 342: 0267,0,0270,0,0271,0,0272,0}; 343: char *letr[26] = { 344: "a","b","c","d","e","f","g","h","i","j", 345: "k","l","m","n","o","p","q","r","s","t", 346: "u","v","w","x","y","z" } ; 347: char *dot = { "." }; 348: yylex(){ 349: int c, ch; 350: restart: 351: c = getch(); 352: peekc = -1; 353: while( c == ' ' || c == '\t' ) c = getch(); 354: if(c == '\\'){ 355: getch(); 356: goto restart; 357: } 358: if( c<= 'z' && c >= 'a' ) { 359: /* look ahead to look for reserved words */ 360: peekc = getch(); 361: if( peekc >= 'a' && peekc <= 'z' ){ /* must be reserved word */ 362: if( c=='i' && peekc=='f' ){ c=_IF; goto skip; } 363: if( c=='w' && peekc=='h' ){ c=_WHILE; goto skip; } 364: if( c=='f' && peekc=='o' ){ c=_FOR; goto skip; } 365: if( c=='s' && peekc=='q' ){ c=SQRT; goto skip; } 366: if( c=='r' && peekc=='e' ){ c=_RETURN; goto skip; } 367: if( c=='b' && peekc=='r' ){ c=_BREAK; goto skip; } 368: if( c=='d' && peekc=='e' ){ c=_DEFINE; goto skip; } 369: if( c=='s' && peekc=='c' ){ c= SCALE; goto skip; } 370: if( c=='b' && peekc=='a' ){ c=BASE; goto skip; } 371: if( c=='i' && peekc == 'b'){ c=BASE; goto skip; } 372: if( c=='o' && peekc=='b' ){ c=OBASE; goto skip; } 373: if( c=='d' && peekc=='i' ){ c=FFF; goto skip; } 374: if( c=='a' && peekc=='u' ){ c=_AUTO; goto skip; } 375: if( c == 'l' && peekc=='e'){ c=LENGTH; goto skip; } 376: if( c == 'q' && peekc == 'u'){getout();} 377: /* could not be found */ 378: return( error ); 379: skip: /* skip over rest of word */ 380: peekc = -1; 381: while( (ch = getch()) >= 'a' && ch <= 'z' ); 382: peekc = ch; 383: return( c ); 384: } 385: 386: /* usual case; just one single letter */ 387: 388: yylval = letr[c-'a']; 389: return( LETTER ); 390: } 391: if( c>= '0' && c <= '9' || c>= 'A' && c<= 'F' ){ 392: yylval = c; 393: return( DIGIT ); 394: } 395: switch( c ){ 396: case '.': return( DOT ); 397: case '=': 398: switch( peekc = getch() ){ 399: case '=': c=EQ; goto gotit; 400: case '+': c=EQPL; goto gotit; 401: case '-': c=EQMI; goto gotit; 402: case '*': c=EQMUL; goto gotit; 403: case '/': c=EQDIV; goto gotit; 404: case '%': c=EQREM; goto gotit; 405: case '^': c=EQEXP; goto gotit; 406: default: return( '=' ); 407: gotit: peekc = -1; return(c); 408: } 409: case '+': return( cpeek( '+', INCR, cpeek( '=', EQPL, '+') ) ); 410: case '-': return( cpeek( '-', DECR, cpeek( '=', EQMI, '-') ) ); 411: case '<': return( cpeek( '=', LE, '<' ) ); 412: case '>': return( cpeek( '=', GE, '>' ) ); 413: case '!': return( cpeek( '=', NE, '!' ) ); 414: case '/': 415: if((peekc = getch()) == '*'){ 416: peekc = -1; 417: while((getch() != '*') || ((peekc = getch()) != '/')); 418: peekc = -1; 419: goto restart; 420: } 421: else if (peekc == '=') { 422: c=EQDIV; 423: goto gotit; 424: } 425: else return(c); 426: case '*': 427: return( cpeek( '=', EQMUL, '*' ) ); 428: case '%': 429: return( cpeek( '=', EQREM, '%' ) ); 430: case '^': 431: return( cpeek( '=', EQEXP, '^' ) ); 432: case '"': 433: yylval = str; 434: while((c=getch()) != '"'){*str++ = c; 435: if(str >= &string[999]){yyerror("string space exceeded"); 436: getout(); 437: } 438: } 439: *str++ = '\0'; 440: return(QSTR); 441: default: return( c ); 442: } 443: } 444: 445: cpeek( c, yes, no ){ 446: if( (peekc=getch()) != c ) return( no ); 447: else { 448: peekc = -1; 449: return( yes ); 450: } 451: } 452: 453: getch(){ 454: int ch; 455: loop: 456: ch = (peekc < 0) ? getc(in) : peekc; 457: peekc = -1; 458: if(ch != EOF)return(ch); 459: if(++ifile > sargc){ 460: if(ifile >= sargc+2)getout(); 461: in = stdin; 462: ln = 0; 463: goto loop; 464: } 465: fclose(in); 466: if((in = fopen(sargv[ifile],"r")) != NULL){ 467: ln = 0; 468: ss = sargv[ifile]; 469: goto loop; 470: } 471: yyerror("cannot open input file"); 472: } 473: # define b_sp_max 3000 474: int b_space [ b_sp_max ]; 475: int * b_sp_nxt = { b_space }; 476: 477: int bdebug = 0; 478: bundle(a){ 479: int i, *p, *q; 480: 481: p = &a; 482: i = *p++; 483: q = b_sp_nxt; 484: if( bdebug ) printf("bundle %d elements at %o\n",i, q ); 485: while(i-- > 0){ 486: if( b_sp_nxt >= & b_space[b_sp_max] ) yyerror( "bundling space exceeded" ); 487: * b_sp_nxt++ = *p++; 488: } 489: * b_sp_nxt++ = 0; 490: yyval = q; 491: return( q ); 492: } 493: 494: routput(p) int *p; { 495: if( bdebug ) printf("routput(%o)\n", p ); 496: if( p >= &b_space[0] && p < &b_space[b_sp_max]){ 497: /* part of a bundle */ 498: while( *p != 0 ) routput( *p++ ); 499: } 500: else printf( p ); /* character string */ 501: } 502: 503: output( p ) int *p; { 504: routput( p ); 505: b_sp_nxt = & b_space[0]; 506: printf( "\n" ); 507: fflush(stdout); 508: cp = cary; 509: crs = rcrs; 510: } 511: 512: conout( p, s ) int *p; char *s; { 513: printf("["); 514: routput( p ); 515: printf("]s%s\n", s ); 516: fflush(stdout); 517: lev--; 518: } 519: 520: yyerror( s ) char *s; { 521: if(ifile > sargc)ss="teletype"; 522: printf("c[%s on line %d, %s]pc\n", s ,ln+1,ss); 523: fflush(stdout); 524: cp = cary; 525: crs = rcrs; 526: bindx = 0; 527: lev = 0; 528: b_sp_nxt = &b_space[0]; 529: } 530: 531: pp( s ) char *s; { 532: /* puts the relevant stuff on pre and post for the letter s */ 533: 534: bundle(3, "S", s, pre ); 535: pre = yyval; 536: bundle(4, post, "L", s, "s." ); 537: post = yyval; 538: } 539: 540: tp( s ) char *s; { /* same as pp, but for temps */ 541: bundle(3, "0S", s, pre ); 542: pre = yyval; 543: bundle(4, post, "L", s, "s." ); 544: post = yyval; 545: } 546: 547: yyinit(argc,argv) int argc; char *argv[];{ 548: signal( 2, (int(*)())1 ); /* ignore all interrupts */ 549: sargv=argv; 550: sargc= -- argc; 551: if(sargc == 0)in=stdin; 552: else if((in = fopen(sargv[1],"r")) == NULL) { 553: yyerror("cannot open input file"); 554: in = stdin; 555: } 556: ifile = 1; 557: ln = 0; 558: ss = sargv[1]; 559: } 560: int *getout(){ 561: printf("q"); 562: fflush(stdout); 563: exit(); 564: } 565: 566: int * 567: getf(p) char *p;{ 568: return(&funtab[2*(*p -0141)]); 569: } 570: int * 571: geta(p) char *p;{ 572: return(&atab[2*(*p - 0141)]); 573: } 574: 575: main(argc, argv) 576: char **argv; 577: { 578: int p[2]; 579: 580: 581: if (argc > 1 && *argv[1] == '-') { 582: if((argv[1][1] == 'd')||(argv[1][1] == 'c')){ 583: yyinit(--argc, ++argv); 584: yyparse(); 585: exit(); 586: } 587: if(argv[1][1] != 'l'){ 588: printf("unrecognizable argument\n"); 589: fflush(stdout); 590: exit(); 591: } 592: argv[1] = "/usr/share/misc/lib.b"; 593: } 594: pipe(p); 595: if (fork()==0) { 596: close(1); 597: dup(p[1]); 598: close(p[0]); 599: close(p[1]); 600: yyinit(argc, argv); 601: yyparse(); 602: exit(); 603: } 604: close(0); 605: dup(p[0]); 606: close(p[0]); 607: close(p[1]); 608: execl("/bin/dc", "dc", "-", 0); 609: execl("/usr/bin/dc", "dc", "-", 0); 610: }