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