1 %{ 2 static char *sccsid = "@(#)bc.y 4.1 (Berkeley) 10/01/80"; 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 int 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, '+' ) ); 410 case '-': return( cpeek( '-', DECR, '-' ) ); 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 return(c); 422 case '"': 423 yylval = str; 424 while((c=getch()) != '"'){*str++ = c; 425 if(str >= &string[999]){yyerror("string space exceeded"); 426 getout(); 427 } 428 } 429 *str++ = '\0'; 430 return(QSTR); 431 default: return( c ); 432 } 433 } 434 435 cpeek( c, yes, no ){ 436 if( (peekc=getch()) != c ) return( no ); 437 else { 438 peekc = -1; 439 return( yes ); 440 } 441 } 442 443 getch(){ 444 int ch; 445 loop: 446 ch = (peekc < 0) ? getc(in) : peekc; 447 peekc = -1; 448 if(ch != EOF)return(ch); 449 if(++ifile > sargc){ 450 if(ifile >= sargc+2)getout(); 451 in = stdin; 452 ln = 0; 453 goto loop; 454 } 455 fclose(in); 456 if((in = fopen(sargv[ifile],"r")) != NULL){ 457 ln = 0; 458 ss = sargv[ifile]; 459 goto loop; 460 } 461 yyerror("cannot open input file"); 462 } 463 # define b_sp_max 3000 464 int b_space [ b_sp_max ]; 465 int * b_sp_nxt = { b_space }; 466 467 int bdebug = 0; 468 bundle(a){ 469 int i, *p, *q; 470 471 p = &a; 472 i = *p++; 473 q = b_sp_nxt; 474 if( bdebug ) printf("bundle %d elements at %o\n",i, q ); 475 while(i-- > 0){ 476 if( b_sp_nxt >= & b_space[b_sp_max] ) yyerror( "bundling space exceeded" ); 477 * b_sp_nxt++ = *p++; 478 } 479 * b_sp_nxt++ = 0; 480 yyval = q; 481 return( q ); 482 } 483 484 routput(p) int *p; { 485 if( bdebug ) printf("routput(%o)\n", p ); 486 if( p >= &b_space[0] && p < &b_space[b_sp_max]){ 487 /* part of a bundle */ 488 while( *p != 0 ) routput( *p++ ); 489 } 490 else printf( p ); /* character string */ 491 } 492 493 output( p ) int *p; { 494 routput( p ); 495 b_sp_nxt = & b_space[0]; 496 printf( "\n" ); 497 fflush(stdout); 498 cp = cary; 499 crs = rcrs; 500 } 501 502 conout( p, s ) int *p; char *s; { 503 printf("["); 504 routput( p ); 505 printf("]s%s\n", s ); 506 fflush(stdout); 507 lev--; 508 } 509 510 yyerror( s ) char *s; { 511 if(ifile > sargc)ss="teletype"; 512 printf("c[%s on line %d, %s]pc\n", s ,ln+1,ss); 513 fflush(stdout); 514 cp = cary; 515 crs = rcrs; 516 bindx = 0; 517 lev = 0; 518 b_sp_nxt = &b_space[0]; 519 } 520 521 pp( s ) char *s; { 522 /* puts the relevant stuff on pre and post for the letter s */ 523 524 bundle(3, "S", s, pre ); 525 pre = yyval; 526 bundle(4, post, "L", s, "s." ); 527 post = yyval; 528 } 529 530 tp( s ) char *s; { /* same as pp, but for temps */ 531 bundle(3, "0S", s, pre ); 532 pre = yyval; 533 bundle(4, post, "L", s, "s." ); 534 post = yyval; 535 } 536 537 yyinit(argc,argv) int argc; char *argv[];{ 538 signal( 2, (int(*)())1 ); /* ignore all interrupts */ 539 sargv=argv; 540 sargc= -- argc; 541 if(sargc == 0)in=stdin; 542 else if((in = fopen(sargv[1],"r")) == NULL) 543 yyerror("cannot open input file"); 544 ifile = 1; 545 ln = 0; 546 ss = sargv[1]; 547 } 548 int *getout(){ 549 printf("q"); 550 fflush(stdout); 551 exit(); 552 } 553 554 int * 555 getf(p) char *p;{ 556 return(&funtab[2*(*p -0141)]); 557 } 558 int * 559 geta(p) char *p;{ 560 return(&atab[2*(*p - 0141)]); 561 } 562 563 main(argc, argv) 564 char **argv; 565 { 566 int p[2]; 567 568 569 if (argc > 1 && *argv[1] == '-') { 570 if((argv[1][1] == 'd')||(argv[1][1] == 'c')){ 571 yyinit(--argc, ++argv); 572 yyparse(); 573 exit(); 574 } 575 if(argv[1][1] != 'l'){ 576 printf("unrecognizable argument\n"); 577 fflush(stdout); 578 exit(); 579 } 580 argv[1] = "/usr/lib/lib.b"; 581 } 582 pipe(p); 583 if (fork()==0) { 584 close(1); 585 dup(p[1]); 586 close(p[0]); 587 close(p[1]); 588 yyinit(argc, argv); 589 yyparse(); 590 exit(); 591 } 592 close(0); 593 dup(p[0]); 594 close(p[0]); 595 close(p[1]); 596 execl("/bin/dc", "dc", "-", 0); 597 execl("/usr/bin/dc", "dc", "-", 0); 598 } 599