|
|
1.1 ! root 1: /* @(#) cgram.y: 1.2 2/9/84 */ ! 2: %{ ! 3: static char SCCSID[] = "@(#) cgram.y: 2.1 83/08/02"; ! 4: %} ! 5: %term NAME 2 ! 6: %term STRING 3 ! 7: %term ICON 4 ! 8: %term FCON 5 ! 9: %term PLUS 6 ! 10: %term MINUS 8 ! 11: %term MUL 11 ! 12: %term AND 14 ! 13: %term OR 17 ! 14: %term ER 19 ! 15: %term QUEST 21 ! 16: %term COLON 22 ! 17: %term ANDAND 23 ! 18: %term OROR 24 ! 19: ! 20: /* special interfaces for yacc alone */ ! 21: /* These serve as abbreviations of 2 or more ops: ! 22: ASOP =, = ops ! 23: RELOP LE,LT,GE,GT ! 24: EQUOP EQ,NE ! 25: DIVOP DIV,MOD ! 26: SHIFTOP LS,RS ! 27: ICOP ICR,DECR ! 28: UNOP NOT,COMPL ! 29: STROP DOT,STREF ! 30: ! 31: */ ! 32: %term ASOP 25 ! 33: %term RELOP 26 ! 34: %term EQUOP 27 ! 35: %term DIVOP 28 ! 36: %term SHIFTOP 29 ! 37: %term INCOP 30 ! 38: %term UNOP 31 ! 39: %term STROP 32 ! 40: ! 41: /* reserved words, etc */ ! 42: %term TYPE 33 ! 43: %term CLASS 34 ! 44: %term STRUCT 35 ! 45: %term RETURN 36 ! 46: %term GOTO 37 ! 47: %term IF 38 ! 48: %term ELSE 39 ! 49: %term SWITCH 40 ! 50: %term BREAK 41 ! 51: %term CONTINUE 42 ! 52: %term WHILE 43 ! 53: %term DO 44 ! 54: %term FOR 45 ! 55: %term DEFAULT 46 ! 56: %term CASE 47 ! 57: %term SIZEOF 48 ! 58: %term ENUM 49 ! 59: ! 60: /* little symbols, etc. */ ! 61: /* namely, ! 62: ! 63: LP ( ! 64: RP ) ! 65: ! 66: LC { ! 67: RC } ! 68: ! 69: LB [ ! 70: RB ] ! 71: ! 72: CM , ! 73: SM ; ! 74: ! 75: */ ! 76: ! 77: %term LP 50 ! 78: %term RP 51 ! 79: %term LC 52 ! 80: %term RC 53 ! 81: %term LB 54 ! 82: %term RB 55 ! 83: %term CM 56 ! 84: %term SM 57 ! 85: %term ASSIGN 58 ! 86: %term ASM 59 ! 87: ! 88: /* at last count, there were 7 shift/reduce, 1 reduce/reduce conflicts ! 89: /* these involved: ! 90: if/else ! 91: recognizing functions in various contexts, including declarations ! 92: error recovery ! 93: */ ! 94: ! 95: %left CM ! 96: %right ASOP ASSIGN ! 97: %right QUEST COLON ! 98: %left OROR ! 99: %left ANDAND ! 100: %left OR ! 101: %left ER ! 102: %left AND ! 103: %left EQUOP ! 104: %left RELOP ! 105: %left SHIFTOP ! 106: %left PLUS MINUS ! 107: %left MUL DIVOP ! 108: %right UNOP ! 109: %right INCOP SIZEOF ! 110: %left LB LP STROP ! 111: %{ ! 112: # include "mfile1.h" ! 113: %} ! 114: ! 115: /* define types */ ! 116: %start ext_def_list ! 117: ! 118: %type <intval> con_e ifelprefix ifprefix doprefix switchpart ! 119: enum_head str_head name_lp ! 120: %type <nodep> e .e term attributes oattributes type enum_dcl struct_dcl ! 121: cast_type null_decl funct_idn declarator fdeclarator ! 122: nfdeclarator elist ! 123: ! 124: %token <intval> CLASS NAME STRUCT RELOP CM DIVOP PLUS MINUS SHIFTOP MUL AND OR ! 125: ER ANDAND OROR ASSIGN STROP INCOP UNOP ICON ! 126: %token <nodep> TYPE ! 127: ! 128: %% ! 129: ! 130: %{ ! 131: extern int wloop_level; /* specifies while loop code generation */ ! 132: extern int floop_level; /* specifies for loop code generation */ ! 133: static int fake = 0; ! 134: static char fakename[NCHNAM+1]; ! 135: %} ! 136: ! 137: ext_def_list: ext_def_list external_def ! 138: | /* EMPTY */ ! 139: { ! 140: #ifndef LINT ! 141: beg_file(); ! 142: #endif ! 143: ftnend(); ! 144: } ! 145: ; ! 146: external_def: data_def ! 147: { curclass = SNULL; blevel = 0; } ! 148: | error ! 149: { curclass = SNULL; blevel = 0; } ! 150: | ASM SM ! 151: { asmout(); curclass = SNULL; blevel = 0; } ! 152: ; ! 153: data_def: oattributes SM ! 154: { $1->in.op = FREE; } ! 155: | oattributes init_dcl_list SM ! 156: { $1->in.op = FREE; } ! 157: | oattributes fdeclarator ! 158: { defid( tymerge($1,$2), ! 159: curclass==STATIC?STATIC:EXTDEF ); } ! 160: function_body ! 161: { ! 162: if( blevel ) cerror( "function level error" ); ! 163: if( reached ) retstat |= NRETVAL; ! 164: $1->in.op = FREE; ! 165: ftnend(); ! 166: } ! 167: ; ! 168: ! 169: function_body: arg_dcl_list compoundstmt ! 170: { regvar = 0; } /* clear out arguments */ ! 171: ; ! 172: ! 173: arg_dcl_list: arg_dcl_list attributes declarator_list SM ! 174: { curclass = SNULL; $2->in.op = FREE; } ! 175: | arg_dcl_list attributes SM ! 176: /* to permit structs in decl. lists */ ! 177: { curclass = SNULL; $2->in.op = FREE; } ! 178: | /* EMPTY */ { blevel = 1; } ! 179: ; ! 180: ! 181: stmt_list: stmt_list statement ! 182: | /* EMPTY */ ! 183: { bccode(); ! 184: locctr(PROG); ! 185: } ! 186: ; ! 187: ! 188: dcl_stat_list : dcl_stat_list attributes SM ! 189: { $2->in.op = FREE; } ! 190: | dcl_stat_list attributes init_dcl_list SM ! 191: { $2->in.op = FREE; } ! 192: | /* EMPTY */ ! 193: ; ! 194: ! 195: oattributes: attributes ! 196: | /* empty */ ! 197: { $$ = mkty(INT,0,INT); curclass = SNULL; } ! 198: ; ! 199: attributes: class type ! 200: { $$ = $2; } ! 201: | type class ! 202: | class ! 203: { $$ = mkty(INT,0,INT); } ! 204: | type ! 205: { curclass = SNULL ; } ! 206: | type class type ! 207: { $1->in.type = types( $1->in.type, $3->in.type, ! 208: UNDEF ); ! 209: $3->in.op = FREE; ! 210: } ! 211: ; ! 212: ! 213: class: CLASS ! 214: { curclass = $1; } ! 215: ; ! 216: ! 217: type: TYPE ! 218: | TYPE TYPE ! 219: { $1->in.type = types( $1->in.type, $2->in.type, UNDEF ); ! 220: $2->in.op = FREE; ! 221: } ! 222: | TYPE TYPE TYPE ! 223: { $1->in.type = types( $1->in.type, $2->in.type, $3->in.type ); ! 224: $2->in.op = $3->in.op = FREE; ! 225: } ! 226: | struct_dcl ! 227: | enum_dcl ! 228: ; ! 229: ! 230: enum_dcl: enum_head LC moe_list optcomma RC ! 231: { $$ = dclstruct($1); } ! 232: | ENUM NAME ! 233: { $$ = rstruct($2,0); stwart = instruct; } ! 234: ; ! 235: ! 236: enum_head: ENUM ! 237: { $$ = bstruct(-1,0); stwart = SEENAME; } ! 238: | ENUM NAME ! 239: { $$ = bstruct($2,0); stwart = SEENAME; } ! 240: ; ! 241: ! 242: moe_list: moe ! 243: | moe_list CM moe ! 244: ; ! 245: ! 246: moe: NAME ! 247: { moedef( $1 ); } ! 248: | NAME ASSIGN con_e ! 249: { strucoff = $3; moedef( $1 ); } ! 250: ; ! 251: ! 252: struct_dcl: str_head LC type_dcl_list optsemi RC ! 253: { $$ = dclstruct($1); } ! 254: | STRUCT NAME ! 255: { $$ = rstruct($2,$1); } ! 256: ; ! 257: ! 258: str_head: STRUCT ! 259: { $$ = bstruct(-1,$1); stwart=0; } ! 260: | STRUCT NAME ! 261: { $$ = bstruct($2,$1); stwart=0; } ! 262: ; ! 263: ! 264: type_dcl_list: type_declaration ! 265: | type_dcl_list SM type_declaration ! 266: ; ! 267: ! 268: type_declaration: type declarator_list ! 269: { curclass = SNULL; stwart=0; $1->in.op = FREE; } ! 270: | type ! 271: { if( curclass != MOU ){ ! 272: curclass = SNULL; ! 273: } ! 274: else { ! 275: sprintf( fakename, "$%dFAKE", fake++ ); ! 276: defid( tymerge($1, bdty(NAME,NIL, ! 277: lookup( fakename, SMOS ))), curclass ); ! 278: werror("union member must be named"); ! 279: } ! 280: stwart = 0; ! 281: $1->in.op = FREE; ! 282: } ! 283: ; ! 284: ! 285: ! 286: declarator_list: declarator ! 287: { defid( tymerge($<nodep>0,$1), curclass); ! 288: stwart = instruct; } ! 289: | declarator_list CM {$<nodep>$=$<nodep>0;} declarator ! 290: { defid( tymerge($<nodep>0,$4), curclass); ! 291: stwart = instruct; } ! 292: ; ! 293: declarator: nfdeclarator ! 294: | nfdeclarator COLON con_e ! 295: %prec CM ! 296: { if( !(instruct&INSTRUCT) ) ! 297: uerror( "field outside of structure" ); ! 298: if( $3<0 || $3 >= FIELD ){ ! 299: uerror( "illegal field size" ); ! 300: $3 = 1; ! 301: } ! 302: defid( tymerge($<nodep>0,$1), FIELD|$3 ); ! 303: $$ = NIL; ! 304: } ! 305: | COLON con_e ! 306: %prec CM ! 307: { if( !(instruct&INSTRUCT) ) ! 308: uerror( "field outside of structure" ); ! 309: /* alignment or hole */ ! 310: falloc( stab, $2, -1, $<nodep>0 ); ! 311: $$ = NIL; ! 312: } ! 313: | error ! 314: { $$ = NIL; } ! 315: ; ! 316: ! 317: /* int (a)(); is not a function --- sorry! */ ! 318: nfdeclarator: MUL nfdeclarator ! 319: { umul: ! 320: $$ = bdty( UNARY MUL, $2, 0 ); } ! 321: | nfdeclarator LP RP ! 322: { uftn: ! 323: $$ = bdty( UNARY CALL, $1, 0 ); } ! 324: | nfdeclarator LB RB ! 325: { uary: ! 326: $$ = bdty( LB, $1, 0 ); } ! 327: | nfdeclarator LB con_e RB ! 328: { bary: ! 329: if( (int)$3 <= 0 ) ! 330: werror( "zero or negative subscript" ); ! 331: $$ = bdty( LB, $1, $3 ); } ! 332: | NAME ! 333: { $$ = bdty( NAME, NIL, $1 ); } ! 334: | LP nfdeclarator RP ! 335: { $$=$2; } ! 336: ; ! 337: fdeclarator: MUL fdeclarator ! 338: { goto umul; } ! 339: | fdeclarator LP RP ! 340: { goto uftn; } ! 341: | fdeclarator LB RB ! 342: { goto uary; } ! 343: | fdeclarator LB con_e RB ! 344: { goto bary; } ! 345: | LP fdeclarator RP ! 346: { $$ = $2; } ! 347: | name_lp ! 348: { if (paramno) ! 349: uerror("arg list in declaration"); } ! 350: name_list RP ! 351: { ! 352: if( blevel!=0 ) ! 353: uerror( ! 354: "function declaration in bad context"); ! 355: $$ = bdty( UNARY CALL, bdty(NAME,NIL,$1), 0 ); ! 356: stwart = 0; ! 357: } ! 358: | name_lp ! 359: { if (paramno) ! 360: uerror("arg list in declaration"); } ! 361: RP ! 362: { ! 363: $$ = bdty( UNARY CALL, bdty(NAME,NIL,$1), 0 ); ! 364: stwart = 0; ! 365: } ! 366: ; ! 367: ! 368: name_lp: NAME LP ! 369: { ! 370: /* turn off typedefs for argument names */ ! 371: stwart = SEENAME; ! 372: if( stab[$1].sclass == SNULL ) ! 373: stab[$1].stype = FTN; ! 374: } ! 375: ; ! 376: ! 377: name_list: NAME ! 378: { ftnarg( $1 ); stwart = SEENAME; } ! 379: | name_list CM NAME ! 380: { ftnarg( $3 ); stwart = SEENAME; } ! 381: | error ! 382: ; ! 383: /* always preceeded by attributes: thus the $<nodep>0's */ ! 384: init_dcl_list: init_declarator ! 385: %prec CM ! 386: | init_dcl_list CM {$<nodep>$=$<nodep>0;} init_declarator ! 387: ; ! 388: /* always preceeded by attributes */ ! 389: xnfdeclarator: nfdeclarator ! 390: { defid( $1 = tymerge($<nodep>0,$1), curclass); ! 391: beginit($1->tn.rval); ! 392: } ! 393: | error ! 394: ; ! 395: /* always preceeded by attributes */ ! 396: init_declarator: nfdeclarator ! 397: { nidcl( tymerge($<nodep>0,$1) ); } ! 398: | fdeclarator ! 399: { defid( tymerge($<nodep>0,$1), uclass(curclass) ); ! 400: } ! 401: | xnfdeclarator ASSIGN e ! 402: %prec CM ! 403: { doinit( $3 ); ! 404: endinit(); } ! 405: | xnfdeclarator ASSIGN LC init_list optcomma RC ! 406: { endinit(); } ! 407: | error ! 408: ; ! 409: ! 410: init_list: initializer ! 411: %prec CM ! 412: | init_list CM initializer ! 413: ; ! 414: initializer: e ! 415: %prec CM ! 416: { doinit( $1 ); } ! 417: | ibrace init_list optcomma RC ! 418: { irbrace(); } ! 419: ; ! 420: ! 421: optcomma : /* empty */ ! 422: | CM ! 423: ; ! 424: ! 425: optsemi : /* empty */ ! 426: | SM ! 427: ; ! 428: ! 429: ibrace : LC ! 430: { ilbrace(); } ! 431: ; ! 432: ! 433: /* STATEMENTS */ ! 434: ! 435: compoundstmt: begin dcl_stat_list stmt_list RC ! 436: { ! 437: clearst(blevel); ! 438: if (--blevel == 1) ! 439: { ! 440: clearst(blevel); ! 441: blevel = 0; ! 442: } ! 443: checkst(blevel); ! 444: autooff = *--psavbc; ! 445: regvar = *--psavbc; ! 446: } ! 447: ; ! 448: ! 449: begin: LC ! 450: { if( blevel == 1 ) dclargs(); ! 451: ++blevel; ! 452: if( psavbc > &asavbc[BCSZ-2] ) ! 453: cerror( "nesting too deep" ); ! 454: *psavbc++ = regvar; ! 455: *psavbc++ = autooff; ! 456: } ! 457: ; ! 458: ! 459: statement: e SM ! 460: { ecomp( $1 ); } ! 461: | ASM SM ! 462: { asmout(); } ! 463: | compoundstmt ! 464: | ifprefix statement ! 465: { deflab($1); ! 466: reached = 1; ! 467: #ifdef M32B ! 468: brdepth--; ! 469: #endif ! 470: } ! 471: | ifelprefix statement ! 472: { if( $1 != NOLAB ){ ! 473: deflab( $1 ); ! 474: reached = 1; ! 475: } ! 476: #ifdef M32B ! 477: brdepth--; ! 478: #endif ! 479: } ! 480: | WHILE ! 481: { ! 482: #ifdef M32B ! 483: whdepth++; ! 484: #endif ! 485: } ! 486: LP e RP ! 487: { ! 488: savebc(); ! 489: if (!reached) ! 490: werror("loop not entered at top"); ! 491: reached = 1; ! 492: brklab = getlab(); ! 493: contlab = getlab(); ! 494: switch (wloop_level) ! 495: { ! 496: default: ! 497: cerror("bad while loop code gen value"); ! 498: /*NOTREACHED*/ ! 499: case LL_TOP: /* test at loop top */ ! 500: deflab(contlab); ! 501: if ($4->in.op == ICON && ! 502: $4->tn.lval != 0) ! 503: { ! 504: flostat = FLOOP; ! 505: tfree($4); ! 506: } ! 507: else ! 508: ecomp(buildtree(CBRANCH, $4, ! 509: bcon(brklab))); ! 510: break; ! 511: case LL_BOT: /* test at loop bottom */ ! 512: if ($4->in.op == ICON && ! 513: $4->tn.lval != 0) ! 514: { ! 515: flostat = FLOOP; ! 516: tfree($4); ! 517: deflab(contlab); ! 518: } ! 519: else ! 520: { ! 521: branch(contlab); ! 522: deflab($<intval>$ = getlab()); ! 523: } ! 524: break; ! 525: case LL_DUP: /* dup. test at top & bottom */ ! 526: if ($4->in.op == ICON && ! 527: $4->tn.lval != 0) ! 528: { ! 529: flostat = FLOOP; ! 530: tfree($4); ! 531: deflab($<intval>$ = contlab); ! 532: } ! 533: else ! 534: { ! 535: #ifndef LINT ! 536: /* don't rotate loops for lint */ ! 537: register NODE *sav; ! 538: extern NODE *treecpy(); ! 539: ! 540: sav = treecpy($4); ! 541: ecomp(buildtree(CBRANCH,$4, ! 542: bcon(brklab))); ! 543: $4 = sav; ! 544: #endif ! 545: deflab($<intval>$ = getlab()); ! 546: } ! 547: break; ! 548: } ! 549: } ! 550: statement ! 551: { ! 552: switch (wloop_level) ! 553: { ! 554: default: ! 555: cerror("bad while loop code gen. value"); ! 556: /*NOTREACHED*/ ! 557: case LL_TOP: /* test at loop top */ ! 558: branch(contlab); ! 559: break; ! 560: case LL_BOT: /* test at loop bottom */ ! 561: if (flostat & FLOOP) ! 562: branch(contlab); ! 563: else ! 564: { ! 565: reached = 1; ! 566: deflab(contlab); ! 567: ecomp(buildtree(CBRANCH, ! 568: buildtree(NOT, $4, NIL), ! 569: bcon($<intval>6))); ! 570: } ! 571: break; ! 572: case LL_DUP: /* dup. test at top & bottom */ ! 573: if (flostat & FLOOP) ! 574: branch(contlab); ! 575: else ! 576: { ! 577: if (flostat & FCONT) ! 578: { ! 579: reached = 1; ! 580: deflab(contlab); ! 581: } ! 582: ecomp(buildtree(CBRANCH, ! 583: buildtree(NOT, $4, NIL), ! 584: bcon($<intval>6))); ! 585: } ! 586: break; ! 587: } ! 588: if ((flostat & FBRK) || !(flostat & FLOOP)) ! 589: reached = 1; ! 590: else ! 591: reached = 0; ! 592: deflab(brklab); ! 593: resetbc(0); ! 594: #ifdef M32B ! 595: whdepth--; ! 596: #endif ! 597: } ! 598: | doprefix statement WHILE LP e RP SM ! 599: { deflab( contlab ); ! 600: if( flostat & FCONT ) reached = 1; ! 601: ecomp( buildtree( CBRANCH, ! 602: buildtree( NOT, $5, NIL ), bcon( $1 ) ) ); ! 603: deflab( brklab ); ! 604: reached = 1; ! 605: resetbc(0); ! 606: #ifdef M32B ! 607: whdepth--; ! 608: #endif ! 609: } ! 610: | FOR LP .e SM ! 611: { ! 612: #ifdef M32B ! 613: fordepth++; ! 614: #endif ! 615: } ! 616: .e SM ! 617: { ! 618: if ($3) ! 619: ecomp($3); ! 620: else if (!reached) ! 621: werror("loop not entered at top"); ! 622: savebc(); ! 623: contlab = getlab(); ! 624: brklab = getlab(); ! 625: reached = 1; ! 626: switch (floop_level) ! 627: { ! 628: default: ! 629: cerror("bad for loop code gen. value"); ! 630: /*NOTREACHED*/ ! 631: case LL_TOP: /* test at loop top */ ! 632: deflab($<intval>$ = getlab()); ! 633: if (!$6) ! 634: flostat |= FLOOP; ! 635: else if ($6->in.op == ICON && ! 636: $6->tn.lval != 0) ! 637: { ! 638: flostat |= FLOOP; ! 639: tfree($6); ! 640: $6 = (NODE *)0; ! 641: } ! 642: else ! 643: ecomp(buildtree(CBRANCH, $6, ! 644: bcon(brklab))); ! 645: break; ! 646: case LL_BOT: /* test at loop bottom */ ! 647: if (!$6) ! 648: flostat |= FLOOP; ! 649: else if ($6->in.op == ICON && ! 650: $6->tn.lval != 0) ! 651: { ! 652: flostat |= FLOOP; ! 653: tfree($6); ! 654: $6 = (NODE *)0; ! 655: } ! 656: else ! 657: branch($<intval>1 = getlab()); ! 658: deflab($<intval>$ = getlab()); ! 659: break; ! 660: case LL_DUP: /* dup. test at top & bottom */ ! 661: if (!$6) ! 662: flostat |= FLOOP; ! 663: else if ($6->in.op == ICON && ! 664: $6->tn.lval != 0) ! 665: { ! 666: flostat |= FLOOP; ! 667: tfree($6); ! 668: $6 = (NODE *)0; ! 669: } ! 670: else ! 671: { ! 672: #ifndef LINT ! 673: /* don't rotate loops for lint */ ! 674: register NODE *sav; ! 675: extern NODE *treecpy(); ! 676: ! 677: sav = treecpy($6); ! 678: ecomp(buildtree(CBRANCH, $6, ! 679: bcon(brklab))); ! 680: $6 = sav; ! 681: #endif ! 682: } ! 683: deflab($<intval>$ = getlab()); ! 684: break; ! 685: } ! 686: } ! 687: .e RP statement ! 688: { ! 689: if (flostat & FCONT) ! 690: { ! 691: deflab(contlab); ! 692: reached = 1; ! 693: } ! 694: if ($9) ! 695: ecomp($9); ! 696: switch (floop_level) ! 697: { ! 698: default: ! 699: cerror("bad for loop code gen. value"); ! 700: /*NOTREACHED*/ ! 701: case LL_TOP: /* test at loop top */ ! 702: branch($<intval>8); ! 703: break; ! 704: case LL_BOT: /* test at loop bottom */ ! 705: if ($6) ! 706: deflab($<intval>1); ! 707: /*FALLTHROUGH*/ ! 708: case LL_DUP: /* dup. test at top & bottom */ ! 709: if ($6) ! 710: { ! 711: ecomp(buildtree(CBRANCH, ! 712: buildtree(NOT, $6, NIL), ! 713: bcon($<intval>8))); ! 714: } ! 715: else ! 716: branch($<intval>8); ! 717: break; ! 718: } ! 719: deflab(brklab); ! 720: if ((flostat & FBRK) || !(flostat & FLOOP)) ! 721: reached = 1; ! 722: else ! 723: reached = 0; ! 724: resetbc(0); ! 725: #ifdef M32B ! 726: fordepth--; ! 727: #endif ! 728: } ! 729: | switchpart statement ! 730: { if( reached ) branch( brklab ); ! 731: deflab( $1 ); ! 732: swend(); ! 733: deflab(brklab); ! 734: if( (flostat&FBRK) || !(flostat&FDEF) ) reached=1; ! 735: resetbc(FCONT); ! 736: #ifdef M32B ! 737: brdepth--; ! 738: #endif ! 739: } ! 740: | BREAK SM ! 741: { if( brklab == NOLAB ) uerror( "illegal break"); ! 742: else if(reached) branch( brklab ); ! 743: flostat |= FBRK; ! 744: if( brkflag ) goto rch; ! 745: reached = 0; ! 746: } ! 747: | CONTINUE SM ! 748: { if( contlab == NOLAB ) uerror( "illegal continue"); ! 749: else branch( contlab ); ! 750: flostat |= FCONT; ! 751: goto rch; ! 752: } ! 753: | RETURN SM ! 754: { retstat |= NRETVAL; ! 755: branch( retlab ); ! 756: rch: ! 757: if( !reached ) werror( "statement not reached"); ! 758: reached = 0; ! 759: } ! 760: | RETURN e SM ! 761: { register NODE *temp; ! 762: TWORD indtype(); ! 763: idname = curftn; ! 764: temp = buildtree( NAME, NIL, NIL ); ! 765: temp->in.type = DECREF(temp->in.type); ! 766: if(temp->in.type == (FTN|VOID)) ! 767: uerror( ! 768: "void function %s cannot return value", ! 769: stab[idname].sname); ! 770: temp->tn.op = RNODE; ! 771: $2 = makety( $2, temp->fn.type, ! 772: temp->fn.cdim, temp->fn.csiz ); ! 773: temp->in.type = indtype( temp->in.type ); ! 774: temp = buildtree( ASSIGN, temp, $2 ); ! 775: ecomp( temp ); ! 776: retstat |= RETVAL; ! 777: branch( retlab ); ! 778: reached = 0; ! 779: } ! 780: | GOTO NAME SM ! 781: { register NODE *q; ! 782: q = block( FREE, NIL, NIL, INT|ARY, 0, INT ); ! 783: q->tn.rval = idname = $2; ! 784: defid( q, ULABEL ); ! 785: stab[idname].suse = -lineno; ! 786: branch( stab[idname].offset ); ! 787: goto rch; ! 788: } ! 789: | SM ! 790: | error SM ! 791: | error RC ! 792: | label statement ! 793: ; ! 794: label: NAME COLON ! 795: { register NODE *q; ! 796: q = block( FREE, NIL, NIL, INT|ARY, 0, LABEL ); ! 797: q->tn.rval = $1; ! 798: defid( q, LABEL ); ! 799: reached = 1; ! 800: } ! 801: | CASE e COLON ! 802: { addcase($2); ! 803: reached = 1; ! 804: } ! 805: | DEFAULT COLON ! 806: { reached = 1; ! 807: adddef(); ! 808: flostat |= FDEF; ! 809: } ! 810: ; ! 811: doprefix: DO ! 812: { savebc(); ! 813: if( !reached ) werror( "loop not entered at top"); ! 814: brklab = getlab(); ! 815: contlab = getlab(); ! 816: deflab( $$ = getlab() ); ! 817: reached = 1; ! 818: #ifdef M32B ! 819: whdepth++; ! 820: #endif ! 821: } ! 822: ; ! 823: ifprefix: IF LP e RP ! 824: { ecomp( buildtree( CBRANCH, $3, bcon( $$=getlab()) ) ) ; ! 825: reached = 1; ! 826: #ifdef M32B ! 827: brdepth++; ! 828: #endif ! 829: } ! 830: ; ! 831: ifelprefix: ifprefix statement ELSE ! 832: { if( reached ) branch( $$ = getlab() ); ! 833: else $$ = NOLAB; ! 834: deflab( $1 ); ! 835: reached = 1; ! 836: } ! 837: ; ! 838: ! 839: switchpart: SWITCH LP e RP ! 840: { register NODE *temp; ! 841: savebc(); ! 842: temp = block( SNODE, NIL, NIL, INT, 0, INT ); ! 843: temp = buildtree( ASSIGN, temp, $3 ); ! 844: #ifdef M32B ! 845: temp = setswreg( temp ); ! 846: #endif ! 847: brklab = getlab(); ! 848: ecomp( temp ); ! 849: branch( $$ = getlab() ); ! 850: swstart(); ! 851: reached = 0; ! 852: #ifdef M32B ! 853: brdepth++; ! 854: #endif ! 855: } ! 856: ; ! 857: /* EXPRESSIONS */ ! 858: con_e: { $<intval>$=instruct; stwart=instruct=0; } e ! 859: %prec CM ! 860: { $$ = icons( $2 ); instruct=$<intval>1; } ! 861: ; ! 862: .e: e ! 863: | ! 864: { $$=0; } ! 865: ; ! 866: elist: e ! 867: %prec CM ! 868: | elist CM e ! 869: { goto bop; } ! 870: ; ! 871: ! 872: e: e RELOP e ! 873: { ! 874: preconf: ! 875: if( yychar==RELOP || yychar==EQUOP || yychar==AND ! 876: || yychar==OR || yychar==ER ){ ! 877: precplaint: ! 878: if( hflag ) werror( ! 879: "precedence confusion possible: parenthesize!" ! 880: ); ! 881: } ! 882: bop: ! 883: $$ = buildtree( $2, $1, $3 ); ! 884: } ! 885: | e CM e ! 886: { $2 = COMOP; ! 887: goto bop; ! 888: } ! 889: | e DIVOP e ! 890: { goto bop; } ! 891: | e PLUS e ! 892: { if(yychar==SHIFTOP) goto precplaint; else goto bop; } ! 893: | e MINUS e ! 894: { if(yychar==SHIFTOP ) goto precplaint; else goto bop; } ! 895: | e SHIFTOP e ! 896: { if(yychar==PLUS||yychar==MINUS) goto precplaint; else goto bop; } ! 897: | e MUL e ! 898: { goto bop; } ! 899: | e EQUOP e ! 900: { goto preconf; } ! 901: | e AND e ! 902: { if( yychar==RELOP||yychar==EQUOP ) goto preconf; else goto bop; } ! 903: | e OR e ! 904: { if(yychar==RELOP||yychar==EQUOP) goto preconf; else goto bop; } ! 905: | e ER e ! 906: { if(yychar==RELOP||yychar==EQUOP) goto preconf; else goto bop; } ! 907: | e ANDAND e ! 908: { goto bop; } ! 909: | e OROR e ! 910: { goto bop; } ! 911: | e MUL ASSIGN e ! 912: { abop: ! 913: $$ = buildtree( ASG $2, $1, $4 ); ! 914: } ! 915: | e DIVOP ASSIGN e ! 916: { goto abop; } ! 917: | e PLUS ASSIGN e ! 918: { goto abop; } ! 919: | e MINUS ASSIGN e ! 920: { goto abop; } ! 921: | e SHIFTOP ASSIGN e ! 922: { goto abop; } ! 923: | e AND ASSIGN e ! 924: { goto abop; } ! 925: | e OR ASSIGN e ! 926: { goto abop; } ! 927: | e ER ASSIGN e ! 928: { goto abop; } ! 929: | e QUEST e COLON e ! 930: { $$=buildtree(QUEST, $1, buildtree( COLON, $3, $5 ) ); ! 931: } ! 932: | e ASOP e ! 933: { werror( "old-fashioned assignment operator" ); ! 934: goto bop; } ! 935: | e ASSIGN e ! 936: { goto bop; } ! 937: | term ! 938: ; ! 939: ! 940: term: term INCOP ! 941: { $$ = buildtree( $2, $1, bcon(1) ); } ! 942: | MUL term ! 943: { ubop: ! 944: $$ = buildtree( UNARY $1, $2, NIL ); ! 945: } ! 946: | AND term ! 947: { ! 948: #ifdef M32B ! 949: myand($2); ! 950: #endif ! 951: if( ISFTN($2->in.type) || ISARY($2->in.type) ){ ! 952: werror( "& before array or function: ignored" ); ! 953: $$ = $2; ! 954: } ! 955: else goto ubop; ! 956: } ! 957: | MINUS term ! 958: { goto ubop; } ! 959: | UNOP term ! 960: { ! 961: $$ = buildtree( $1, $2, NIL ); ! 962: } ! 963: | INCOP term ! 964: { $$ = buildtree( $1==INCR ? ASG PLUS : ASG MINUS, ! 965: $2, ! 966: bcon(1) ); ! 967: } ! 968: | SIZEOF term ! 969: { $$ = doszof( $2 ); } ! 970: | LP cast_type RP term %prec INCOP ! 971: { $$ = buildtree( CAST, $2, $4 ); ! 972: $$->in.left->in.op = FREE; ! 973: $$->in.op = FREE; ! 974: $$ = $$->in.right; ! 975: } ! 976: | SIZEOF LP cast_type RP %prec SIZEOF ! 977: { $$ = doszof( $3 ); } ! 978: | term LB e RB ! 979: { $$ = buildtree( LB, $1, $3 ); } ! 980: | term LB e COLON e RB ! 981: { $$ = xicolon( $1, $3, $5 ); } ! 982: | funct_idn RP ! 983: { $$=buildtree(UNARY CALL,$1,NIL); } ! 984: | funct_idn elist RP ! 985: { $$=buildtree(CALL,$1,$2); } ! 986: | term STROP NAME ! 987: { if( $2 == DOT ){ ! 988: if( notlval( $1 ) )uerror( ! 989: "structure reference must be addressable" ! 990: ); ! 991: $1 = buildtree( UNARY AND, $1, NIL ); ! 992: } ! 993: idname = $3; ! 994: $$ = buildtree( STREF, $1, ! 995: buildtree( NAME, NIL, NIL ) ); ! 996: } ! 997: | NAME ! 998: { idname = $1; ! 999: /* recognize identifiers in initializations */ ! 1000: if( blevel==0 && stab[idname].stype == UNDEF ) { ! 1001: register NODE *q; ! 1002: werror( "undeclared initializer name %s", ! 1003: stab[idname].sname ); ! 1004: q = block( FREE, NIL, NIL, INT, 0, INT ); ! 1005: q->tn.rval = idname; ! 1006: defid( q, EXTERN ); ! 1007: } ! 1008: $$=buildtree(NAME,NIL,NIL); ! 1009: stab[$1].suse = -lineno; ! 1010: } ! 1011: | ICON ! 1012: { $$=bcon(0); ! 1013: $$->tn.lval = lastcon; ! 1014: $$->tn.rval = NONAME; ! 1015: if( $1 ) $$->fn.csiz = $$->in.type = ctype(LONG); ! 1016: } ! 1017: | FCON ! 1018: { $$=buildtree(FCON,NIL,NIL); ! 1019: $$->fpn.dval = dcon; ! 1020: } ! 1021: | STRING ! 1022: { $$ = getstr(); /* get string contents */ } ! 1023: | LP e RP ! 1024: { $$=$2; } ! 1025: ; ! 1026: ! 1027: cast_type: type null_decl ! 1028: { ! 1029: $$ = tymerge( $1, $2 ); ! 1030: $$->in.op = NAME; ! 1031: $1->in.op = FREE; ! 1032: } ! 1033: ; ! 1034: ! 1035: null_decl: /* EMPTY */ ! 1036: { $$ = bdty( NAME, NIL, -1 ); } ! 1037: | LP RP ! 1038: { $$ = bdty( UNARY CALL, bdty(NAME,NIL,-1),0); } ! 1039: | LP null_decl RP LP RP ! 1040: { $$ = bdty( UNARY CALL, $2, 0 ); } ! 1041: | MUL null_decl ! 1042: { goto umul; } ! 1043: | null_decl LB RB ! 1044: { goto uary; } ! 1045: | null_decl LB con_e RB ! 1046: { goto bary; } ! 1047: | LP null_decl RP ! 1048: { $$ = $2; } ! 1049: ; ! 1050: ! 1051: funct_idn: NAME LP ! 1052: { if( stab[$1].stype == UNDEF ){ ! 1053: register NODE *q; ! 1054: q = block( FREE, NIL, NIL, FTN|INT, 0, INT ); ! 1055: q->tn.rval = $1; ! 1056: defid( q, EXTERN ); ! 1057: } ! 1058: idname = $1; ! 1059: $$=buildtree(NAME,NIL,NIL); ! 1060: stab[idname].suse = -lineno; ! 1061: } ! 1062: | term LP ! 1063: ; ! 1064: %% ! 1065: ! 1066: NODE * ! 1067: mkty( t, d, s ) unsigned t; { ! 1068: return( block( TYPE, NIL, NIL, t, d, s ) ); ! 1069: } ! 1070: ! 1071: NODE * ! 1072: bdty( op, p, v ) NODE *p; { ! 1073: register NODE *q; ! 1074: ! 1075: q = block( op, p, NIL, INT, 0, INT ); ! 1076: ! 1077: switch( op ){ ! 1078: ! 1079: case UNARY MUL: ! 1080: case UNARY CALL: ! 1081: break; ! 1082: ! 1083: case LB: ! 1084: q->in.right = bcon(v); ! 1085: break; ! 1086: ! 1087: case NAME: ! 1088: q->tn.rval = v; ! 1089: break; ! 1090: ! 1091: default: ! 1092: cerror( "bad bdty" ); ! 1093: } ! 1094: ! 1095: return( q ); ! 1096: } ! 1097: ! 1098: dstash( n ){ /* put n into the dimension table */ ! 1099: if( curdim >= DIMTABSZ-1 ){ ! 1100: cerror( "dimension table overflow"); ! 1101: } ! 1102: dimtab[ curdim++ ] = n; ! 1103: } ! 1104: ! 1105: savebc() { ! 1106: if( psavbc > & asavbc[BCSZ-4 ] ){ ! 1107: cerror( "whiles, fors, etc. too deeply nested"); ! 1108: } ! 1109: *psavbc++ = brklab; ! 1110: *psavbc++ = contlab; ! 1111: *psavbc++ = flostat; ! 1112: *psavbc++ = swx; ! 1113: #ifdef M32B ! 1114: *psavbc++ = swregno; ! 1115: #endif ! 1116: flostat = 0; ! 1117: } ! 1118: ! 1119: resetbc(mask){ ! 1120: ! 1121: #ifdef M32B ! 1122: swregno = *--psavbc; ! 1123: #endif ! 1124: swx = *--psavbc; ! 1125: flostat = *--psavbc | (flostat&mask); ! 1126: contlab = *--psavbc; ! 1127: brklab = *--psavbc; ! 1128: ! 1129: } ! 1130: ! 1131: addcase(p) NODE *p; { /* add case to switch */ ! 1132: ! 1133: p = optim( p ); /* change enum to ints */ ! 1134: if( p->in.op != ICON ){ ! 1135: uerror( "non-constant case expression"); ! 1136: return; ! 1137: } ! 1138: if( swp == swtab ){ ! 1139: uerror( "case not in switch"); ! 1140: return; ! 1141: } ! 1142: if( swp >= &swtab[SWITSZ] ){ ! 1143: cerror( "switch table overflow"); ! 1144: } ! 1145: swp->sval = p->tn.lval; ! 1146: deflab( swp->slab = getlab() ); ! 1147: ++swp; ! 1148: tfree(p); ! 1149: } ! 1150: ! 1151: adddef(){ /* add default case to switch */ ! 1152: if( swtab[swx].slab >= 0 ){ ! 1153: uerror( "duplicate default in switch"); ! 1154: return; ! 1155: } ! 1156: if( swp == swtab ){ ! 1157: uerror( "default not inside switch"); ! 1158: return; ! 1159: } ! 1160: deflab( swtab[swx].slab = getlab() ); ! 1161: } ! 1162: ! 1163: swstart(){ ! 1164: /* begin a switch block */ ! 1165: if( swp >= &swtab[SWITSZ] ){ ! 1166: cerror( "switch table overflow"); ! 1167: } ! 1168: swx = swp - swtab; ! 1169: swp->slab = -1; ! 1170: ++swp; ! 1171: } ! 1172: ! 1173: swend(){ /* end a switch block */ ! 1174: ! 1175: register struct sw *swbeg, *p, *q, *r, *r1; ! 1176: CONSZ temp; ! 1177: int tempi; ! 1178: ! 1179: swbeg = &swtab[swx+1]; ! 1180: ! 1181: /* sort */ ! 1182: ! 1183: r1 = swbeg; ! 1184: r = swp-1; ! 1185: ! 1186: while( swbeg < r ){ ! 1187: /* bubble largest to end */ ! 1188: for( q=swbeg; q<r; ++q ){ ! 1189: if( q->sval > (q+1)->sval ){ ! 1190: /* swap */ ! 1191: r1 = q+1; ! 1192: temp = q->sval; ! 1193: q->sval = r1->sval; ! 1194: r1->sval = temp; ! 1195: tempi = q->slab; ! 1196: q->slab = r1->slab; ! 1197: r1->slab = tempi; ! 1198: } ! 1199: } ! 1200: r = r1; ! 1201: r1 = swbeg; ! 1202: } ! 1203: ! 1204: /* it is now sorted */ ! 1205: ! 1206: for( p = swbeg+1; p<swp; ++p ){ ! 1207: if( p->sval == (p-1)->sval ){ ! 1208: uerror( "duplicate case in switch, %d", tempi=p->sval ); ! 1209: return; ! 1210: } ! 1211: } ! 1212: ! 1213: reached = 1; ! 1214: genswitch( swbeg-1, (int)(swp-swbeg) ); ! 1215: swp = swbeg-1; ! 1216: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.