|
|
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: uplevel(); ! 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: default: ! 496: cerror("bad while loop code gen value"); ! 497: /*NOTREACHED*/ ! 498: case LL_TOP: /* test at loop top */ ! 499: deflab(contlab); ! 500: if ($4->in.op == ICON && $4->tn.lval) { ! 501: flostat = FLOOP; ! 502: tfree($4); ! 503: } else { ! 504: $4->ln.lineno = $<lineno>1; ! 505: ecomp(buildtree(CBRANCH, $4, ! 506: bcon(brklab))); ! 507: } ! 508: break; ! 509: case LL_BOT: /* test at loop bottom */ ! 510: if ($4->in.op == ICON && $4->tn.lval) { ! 511: flostat = FLOOP; ! 512: tfree($4); ! 513: deflab(contlab); ! 514: } else { ! 515: branch(contlab); ! 516: deflab($<intval>$ = getlab()); ! 517: } ! 518: break; ! 519: case LL_DUP: /* dup. test at top & bottom */ ! 520: if ($4->in.op == ICON && $4->tn.lval) { ! 521: flostat = FLOOP; ! 522: tfree($4); ! 523: deflab($<intval>$ = contlab); ! 524: } else { ! 525: register NODE *sav; ! 526: extern NODE *treecpy(); ! 527: sav = treecpy($4); ! 528: ecomp(buildtree(CBRANCH,$4, ! 529: bcon(brklab))); ! 530: $4 = sav; ! 531: deflab($<intval>$ = getlab()); ! 532: } ! 533: break; ! 534: } ! 535: } ! 536: statement ! 537: { ! 538: switch (wloop_level) { ! 539: default: ! 540: cerror("bad while loop code gen. value"); ! 541: /*NOTREACHED*/ ! 542: case LL_TOP: /* test at loop top */ ! 543: branch(contlab); ! 544: break; ! 545: case LL_BOT: /* test at loop bottom */ ! 546: if (flostat & FLOOP) ! 547: branch(contlab); ! 548: else { ! 549: reached = 1; ! 550: deflab(contlab); ! 551: ecomp(buildtree(CBRANCH, ! 552: buildtree(NOT, $4, NIL), ! 553: bcon($<intval>6))); ! 554: } ! 555: break; ! 556: case LL_DUP: /* dup. test at top & bottom */ ! 557: if (flostat & FLOOP) ! 558: branch(contlab); ! 559: else { ! 560: if (flostat & FCONT) { ! 561: reached = 1; ! 562: deflab(contlab); ! 563: } ! 564: ecomp(buildtree(CBRANCH, ! 565: buildtree(NOT, $4, NIL), ! 566: bcon($<intval>6))); ! 567: } ! 568: break; ! 569: } ! 570: if ((flostat & FBRK) || !(flostat & FLOOP)) ! 571: reached = 1; ! 572: else ! 573: reached = 0; ! 574: deflab(brklab); ! 575: resetbc(0); ! 576: #ifdef M32B ! 577: whdepth--; ! 578: #endif ! 579: } ! 580: | doprefix statement WHILE LP e RP SM ! 581: { deflab( contlab ); ! 582: if( flostat & FCONT ) reached = 1; ! 583: $5->ln.lineno = $<lineno>3; ! 584: ecomp( buildtree(CBRANCH, ! 585: buildtree(NOT, $5, NIL), bcon($1))); ! 586: deflab( brklab ); ! 587: reached = 1; ! 588: resetbc(0); ! 589: #ifdef M32B ! 590: whdepth--; ! 591: #endif ! 592: } ! 593: | FOR LP .e SM ! 594: { ! 595: #ifdef M32B ! 596: fordepth++; ! 597: #endif ! 598: } ! 599: .e SM ! 600: { ! 601: if ($3) { ! 602: $3->ln.lineno = $<lineno>1; ! 603: ecomp($3); ! 604: } else if (!reached) ! 605: werror("loop not entered at top"); ! 606: savebc(); ! 607: contlab = getlab(); ! 608: brklab = getlab(); ! 609: reached = 1; ! 610: switch (floop_level) { ! 611: default: ! 612: cerror("bad for loop code gen. value"); ! 613: /*NOTREACHED*/ ! 614: case LL_TOP: /* test at loop top */ ! 615: deflab($<intval>$ = getlab()); ! 616: if (!$6) ! 617: flostat |= FLOOP; ! 618: else if ($6->in.op == ICON && $6->tn.lval) { ! 619: flostat |= FLOOP; ! 620: tfree($6); ! 621: $6 = (NODE *)0; ! 622: } else { ! 623: if (!$3) ! 624: $6->ln.lineno = $<lineno>1; ! 625: ecomp(buildtree(CBRANCH, $6, ! 626: bcon(brklab))); ! 627: } ! 628: break; ! 629: case LL_BOT: /* test at loop bottom */ ! 630: if (!$6) ! 631: flostat |= FLOOP; ! 632: else if ($6->in.op == ICON && $6->tn.lval) { ! 633: flostat |= FLOOP; ! 634: tfree($6); ! 635: $6 = (NODE *)0; ! 636: } else ! 637: branch($<intval>1 = getlab()); ! 638: deflab($<intval>$ = getlab()); ! 639: break; ! 640: case LL_DUP: /* dup. test at top & bottom */ ! 641: if (!$6) ! 642: flostat |= FLOOP; ! 643: else if ($6->in.op == ICON && $6->tn.lval) { ! 644: flostat |= FLOOP; ! 645: tfree($6); ! 646: $6 = (NODE *)0; ! 647: } else { ! 648: register NODE *sav; ! 649: extern NODE *treecpy(); ! 650: sav = treecpy($6); ! 651: ecomp(buildtree(CBRANCH, $6, ! 652: bcon(brklab))); ! 653: $6 = sav; ! 654: } ! 655: deflab($<intval>$ = getlab()); ! 656: break; ! 657: } ! 658: } ! 659: .e RP statement ! 660: { ! 661: if (flostat & FCONT) { ! 662: deflab(contlab); ! 663: reached = 1; ! 664: } ! 665: if ($9) ! 666: $9->ln.lineno = lineno, ecomp($9); ! 667: switch (floop_level) { ! 668: default: ! 669: cerror("bad for loop code gen. value"); ! 670: /*NOTREACHED*/ ! 671: case LL_TOP: /* test at loop top */ ! 672: branch($<intval>8); ! 673: break; ! 674: case LL_BOT: /* test at loop bottom */ ! 675: if ($6) ! 676: deflab($<intval>1); ! 677: /*FALLTHROUGH*/ ! 678: case LL_DUP: /* dup. test at top & bottom */ ! 679: if ($6) { ! 680: ecomp(buildtree(CBRANCH, ! 681: buildtree(NOT, $6, NIL), ! 682: bcon($<intval>8))); ! 683: } else ! 684: branch($<intval>8); ! 685: break; ! 686: } ! 687: deflab(brklab); ! 688: if ((flostat & FBRK) || !(flostat & FLOOP)) ! 689: reached = 1; ! 690: else ! 691: reached = 0; ! 692: resetbc(0); ! 693: #ifdef M32B ! 694: fordepth--; ! 695: #endif ! 696: } ! 697: | switchpart statement ! 698: { if( reached ) branch( brklab ); ! 699: deflab( $1 ); ! 700: swend(); ! 701: deflab(brklab); ! 702: if( (flostat&FBRK) || !(flostat&FDEF) ) reached=1; ! 703: resetbc(FCONT); ! 704: #ifdef M32B ! 705: brdepth--; ! 706: #endif ! 707: } ! 708: | BREAK SM ! 709: { if( brklab == NOLAB ) uerror( "illegal break"); ! 710: else if(reached) { ! 711: slineno = $<lineno>1; dbline(); ! 712: branch( brklab ); ! 713: } ! 714: flostat |= FBRK; ! 715: if( brkflag ) goto rch; ! 716: reached = 0; ! 717: } ! 718: | CONTINUE SM ! 719: { if( contlab == NOLAB ) uerror( "illegal continue"); ! 720: else { ! 721: slineno = $<lineno>1; dbline(); ! 722: branch( contlab ); ! 723: } ! 724: flostat |= FCONT; ! 725: goto rch; ! 726: } ! 727: | RETURN SM ! 728: { retstat |= NRETVAL; ! 729: slineno = $<lineno>1; dbline(); ! 730: branch( retlab ); ! 731: rch: ! 732: if( !reached ) werror( "statement not reached"); ! 733: reached = 0; ! 734: } ! 735: | RETURN e SM ! 736: { register NODE *temp; ! 737: TWORD indtype(); ! 738: idname = curftn; ! 739: temp = buildtree( NAME, NIL, NIL ); ! 740: temp->in.type = DECREF(temp->in.type); ! 741: if(temp->in.type == (FTN|VOID)) ! 742: uerror( ! 743: "void function %s cannot return value", ! 744: stab[idname].sname); ! 745: temp->tn.op = RNODE; ! 746: $2 = makety( $2, temp->fn.type, ! 747: temp->fn.cdim, temp->fn.csiz ); ! 748: temp->in.type = indtype( temp->in.type ); ! 749: temp = buildtree( ASSIGN, temp, $2 ); ! 750: temp->ln.lineno = $<lineno>1; ! 751: ecomp( temp ); ! 752: retstat |= RETVAL; ! 753: branch( retlab ); ! 754: reached = 0; ! 755: } ! 756: | GOTO NAME SM ! 757: { register NODE *q; ! 758: q = block( FREE, NIL, NIL, INT|ARY, 0, INT ); ! 759: q->tn.rval = idname = $2; ! 760: defid( q, ULABEL ); ! 761: stab[idname].suse = -lineno; ! 762: slineno = $<lineno>1; dbline(); ! 763: branch( stab[idname].offset ); ! 764: goto rch; ! 765: } ! 766: | SM ! 767: | error SM ! 768: | error RC ! 769: | label statement ! 770: ; ! 771: label: NAME COLON ! 772: { register NODE *q; ! 773: q = block( FREE, NIL, NIL, INT|ARY, 0, LABEL ); ! 774: q->tn.rval = $1; ! 775: defid( q, LABEL ); ! 776: reached = 1; ! 777: } ! 778: | CASE e COLON ! 779: { addcase($2); ! 780: reached = 1; ! 781: } ! 782: | DEFAULT COLON ! 783: { reached = 1; ! 784: adddef(); ! 785: flostat |= FDEF; ! 786: } ! 787: ; ! 788: doprefix: DO ! 789: { savebc(); ! 790: if( !reached ) werror( "loop not entered at top"); ! 791: brklab = getlab(); ! 792: contlab = getlab(); ! 793: deflab( $$ = getlab() ); ! 794: reached = 1; ! 795: #ifdef M32B ! 796: whdepth++; ! 797: #endif ! 798: } ! 799: ; ! 800: ifprefix: IF LP e RP ! 801: { $3->ln.lineno = $<lineno>1; ! 802: ecomp(buildtree(CBRANCH, $3, bcon($$=getlab()))) ; ! 803: reached = 1; ! 804: #ifdef M32B ! 805: brdepth++; ! 806: #endif ! 807: } ! 808: ; ! 809: ifelprefix: ifprefix statement ELSE ! 810: { if( reached ) branch( $$ = getlab() ); ! 811: else $$ = NOLAB; ! 812: deflab( $1 ); ! 813: reached = 1; ! 814: } ! 815: ; ! 816: ! 817: switchpart: SWITCH LP e RP ! 818: { register NODE *temp; ! 819: savebc(); ! 820: temp = block( SNODE, NIL, NIL, INT, 0, INT ); ! 821: temp = buildtree( ASSIGN, temp, $3 ); ! 822: #ifdef M32B ! 823: temp = setswreg( temp ); ! 824: #endif ! 825: brklab = getlab(); ! 826: temp->ln.lineno = $<lineno>1; ! 827: ecomp( temp ); ! 828: branch( $$ = getlab() ); ! 829: swstart(); ! 830: reached = 0; ! 831: #ifdef M32B ! 832: brdepth++; ! 833: #endif ! 834: } ! 835: ; ! 836: /* EXPRESSIONS */ ! 837: con_e: { $<intval>$=instruct; stwart=instruct=0; } e ! 838: %prec CM ! 839: { $$ = icons( $2 ); instruct=$<intval>1; } ! 840: ; ! 841: .e: e ! 842: | ! 843: { $$ = 0; } ! 844: ; ! 845: elist: e ! 846: %prec CM ! 847: | elist CM e ! 848: { goto bop; } ! 849: ; ! 850: ! 851: e: e RELOP e ! 852: { ! 853: preconf: ! 854: if( yychar==RELOP || yychar==EQUOP || yychar==AND ! 855: || yychar==OR || yychar==ER ){ ! 856: precplaint: ! 857: if( hflag ) werror( ! 858: "precedence confusion possible: parenthesize!" ! 859: ); ! 860: } ! 861: bop: ! 862: $$ = buildtree( $2, $1, $3 ); ! 863: } ! 864: | e CM e ! 865: { $2 = COMOP; ! 866: goto bop; ! 867: } ! 868: | e DIVOP e ! 869: { goto bop; } ! 870: | e PLUS e ! 871: { if(yychar==SHIFTOP) goto precplaint; else goto bop; } ! 872: | e MINUS e ! 873: { if(yychar==SHIFTOP ) goto precplaint; else goto bop; } ! 874: | e SHIFTOP e ! 875: { if(yychar==PLUS||yychar==MINUS) goto precplaint; else goto bop; } ! 876: | e MUL e ! 877: { goto bop; } ! 878: | e EQUOP e ! 879: { goto preconf; } ! 880: | e AND e ! 881: { if( yychar==RELOP||yychar==EQUOP ) goto preconf; else goto bop; } ! 882: | e OR e ! 883: { if(yychar==RELOP||yychar==EQUOP) goto preconf; else goto bop; } ! 884: | e ER e ! 885: { if(yychar==RELOP||yychar==EQUOP) goto preconf; else goto bop; } ! 886: | e ANDAND e ! 887: { goto bop; } ! 888: | e OROR e ! 889: { goto bop; } ! 890: | e MUL ASSIGN e ! 891: { abop: ! 892: $$ = buildtree( ASG $2, $1, $4 ); ! 893: } ! 894: | e DIVOP ASSIGN e ! 895: { goto abop; } ! 896: | e PLUS ASSIGN e ! 897: { goto abop; } ! 898: | e MINUS ASSIGN e ! 899: { goto abop; } ! 900: | e SHIFTOP ASSIGN e ! 901: { goto abop; } ! 902: | e AND ASSIGN e ! 903: { goto abop; } ! 904: | e OR ASSIGN e ! 905: { goto abop; } ! 906: | e ER ASSIGN e ! 907: { goto abop; } ! 908: | e QUEST e COLON e ! 909: { $$=buildtree(QUEST, $1, buildtree( COLON, $3, $5 ) ); ! 910: } ! 911: | e ASOP e ! 912: { werror( "old-fashioned assignment operator" ); ! 913: goto bop; } ! 914: | e ASSIGN e ! 915: { goto bop; } ! 916: | term ! 917: ; ! 918: ! 919: term: term INCOP ! 920: { $$ = buildtree( $2, $1, bcon(1) ); } ! 921: | MUL term ! 922: { ubop: ! 923: $$ = buildtree( UNARY $1, $2, NIL ); ! 924: } ! 925: | AND term ! 926: { ! 927: #ifdef M32B ! 928: myand($2); ! 929: #endif ! 930: if( ISFTN($2->in.type) || ISARY($2->in.type) ){ ! 931: werror( "& before array or function: ignored" ); ! 932: $$ = $2; ! 933: } ! 934: else goto ubop; ! 935: } ! 936: | MINUS term ! 937: { goto ubop; } ! 938: | UNOP term ! 939: { ! 940: $$ = buildtree( $1, $2, NIL ); ! 941: } ! 942: | INCOP term ! 943: { $$ = buildtree( $1==INCR ? ASG PLUS : ASG MINUS, ! 944: $2, ! 945: bcon(1) ); ! 946: } ! 947: | SIZEOF term ! 948: { $$ = doszof( $2 ); } ! 949: | LP cast_type RP term %prec INCOP ! 950: { $$ = buildtree( CAST, $2, $4 ); ! 951: $$->in.left->in.op = FREE; ! 952: $$->in.op = FREE; ! 953: $$ = $$->in.right; ! 954: } ! 955: | SIZEOF LP cast_type RP %prec SIZEOF ! 956: { $$ = doszof( $3 ); } ! 957: | term LB e RB ! 958: { $$ = buildtree( LB, $1, $3 ); } ! 959: | term LB e COLON e RB ! 960: { $$ = xicolon( $1, $3, $5 ); } ! 961: | funct_idn RP ! 962: { $$=buildtree(UNARY CALL,$1,NIL); ! 963: } ! 964: | funct_idn elist RP ! 965: { $$=buildtree(CALL,$1,$2); } ! 966: | term STROP NAME ! 967: { if( $2 == DOT ){ ! 968: if( notlval( $1 ) )werror( ! 969: "structure reference must be addressable" ! 970: ); ! 971: $1 = buildtree( UNARY AND, $1, NIL ); ! 972: } ! 973: idname = $3; ! 974: $$ = buildtree( STREF, $1, ! 975: buildtree( NAME, NIL, NIL ) ); ! 976: } ! 977: | NAME ! 978: { idname = $1; ! 979: /* recognize identifiers in initializations */ ! 980: if( blevel==0 && stab[idname].stype == UNDEF ) { ! 981: register NODE *q; ! 982: werror( "undeclared initializer name %s", ! 983: stab[idname].sname ); ! 984: q = block( FREE, NIL, NIL, INT, 0, INT ); ! 985: q->tn.rval = idname; ! 986: defid( q, EXTERN ); ! 987: } ! 988: $$=buildtree(NAME,NIL,NIL); ! 989: stab[$1].suse = -lineno; ! 990: } ! 991: | ICON ! 992: { $$=bcon(0); ! 993: $$->tn.lval = lastcon; ! 994: $$->tn.rval = NONAME; ! 995: if( $1 ) $$->fn.csiz = $$->in.type = ctype(LONG); ! 996: } ! 997: | FCON ! 998: { $$=buildtree(FCON,NIL,NIL); ! 999: $$->fpn.dval = dcon; ! 1000: } ! 1001: | STRING ! 1002: { $$ = getstr(); } ! 1003: | LP e RP ! 1004: { $$=$2; } ! 1005: ; ! 1006: ! 1007: cast_type: type null_decl ! 1008: { ! 1009: $$ = tymerge( $1, $2 ); ! 1010: $$->in.op = NAME; ! 1011: $1->in.op = FREE; ! 1012: } ! 1013: ; ! 1014: ! 1015: null_decl: /* EMPTY */ ! 1016: { $$ = bdty( NAME, NIL, -1 ); } ! 1017: | LP RP ! 1018: { $$ = bdty( UNARY CALL, bdty(NAME,NIL,-1),0); } ! 1019: | LP null_decl RP LP RP ! 1020: { $$ = bdty( UNARY CALL, $2, 0 ); } ! 1021: | MUL null_decl ! 1022: { goto umul; } ! 1023: | null_decl LB RB ! 1024: { goto uary; } ! 1025: | null_decl LB con_e RB ! 1026: { goto bary; } ! 1027: | LP null_decl RP ! 1028: { $$ = $2; } ! 1029: ; ! 1030: ! 1031: funct_idn: NAME LP ! 1032: { if( stab[$1].stype == UNDEF ){ ! 1033: register NODE *q; ! 1034: q = block( FREE, NIL, NIL, FTN|INT, 0, INT ); ! 1035: q->tn.rval = $1; ! 1036: defid( q, EXTERN ); ! 1037: } ! 1038: idname = $1; ! 1039: $$=buildtree(NAME,NIL,NIL); ! 1040: stab[idname].suse = -lineno; ! 1041: } ! 1042: | term LP ! 1043: ; ! 1044: %% ! 1045: ! 1046: NODE * ! 1047: mkty( t, d, s ) unsigned t; { ! 1048: return( block( TYPE, NIL, NIL, t, d, s ) ); ! 1049: } ! 1050: ! 1051: NODE * ! 1052: bdty( op, p, v ) NODE *p; { ! 1053: register NODE *q; ! 1054: ! 1055: q = block( op, p, NIL, INT, 0, INT ); ! 1056: ! 1057: switch( op ){ ! 1058: ! 1059: case UNARY MUL: ! 1060: case UNARY CALL: ! 1061: break; ! 1062: ! 1063: case LB: ! 1064: q->in.right = bcon(v); ! 1065: break; ! 1066: ! 1067: case NAME: ! 1068: q->tn.rval = v; ! 1069: break; ! 1070: ! 1071: default: ! 1072: cerror( "bad bdty" ); ! 1073: } ! 1074: ! 1075: return( q ); ! 1076: } ! 1077: int dimtabsz; ! 1078: allodimtab() ! 1079: { ! 1080: if(!dimtabsz) ! 1081: dimtab = (int *) malloc((dimtabsz = DIMTABSZ)*sizeof(int)); ! 1082: else { ! 1083: dimtabsz *= 3; ! 1084: dimtab = (int *) realloc((char *)dimtab, dimtabsz*sizeof(int)); ! 1085: } ! 1086: if(!dimtab) ! 1087: cerror("dimension table overflow"); ! 1088: } ! 1089: ! 1090: dstash( n ){ /* put n into the dimension table */ ! 1091: if( curdim >= dimtabsz-1 ){ ! 1092: allodimtab(); ! 1093: } ! 1094: dimtab[ curdim++ ] = n; ! 1095: } ! 1096: ! 1097: savebc() { ! 1098: if( psavbc > & asavbc[BCSZ-4 ] ){ ! 1099: cerror( "whiles, fors, etc. too deeply nested"); ! 1100: } ! 1101: *psavbc++ = brklab; ! 1102: *psavbc++ = contlab; ! 1103: *psavbc++ = flostat; ! 1104: *psavbc++ = swx; ! 1105: #ifdef M32B ! 1106: *psavbc++ = swregno; ! 1107: #endif ! 1108: flostat = 0; ! 1109: } ! 1110: ! 1111: resetbc(mask){ ! 1112: ! 1113: #ifdef M32B ! 1114: swregno = *--psavbc; ! 1115: #endif ! 1116: swx = *--psavbc; ! 1117: flostat = *--psavbc | (flostat&mask); ! 1118: contlab = *--psavbc; ! 1119: brklab = *--psavbc; ! 1120: ! 1121: } ! 1122: ! 1123: addcase(p) NODE *p; { /* add case to switch */ ! 1124: ! 1125: p = optim( p ); /* change enum to ints */ ! 1126: if( p->in.op != ICON || p->tn.rval != NONAME){ ! 1127: uerror( "non-constant case expression"); ! 1128: return; ! 1129: } ! 1130: if( swp == swtab ){ ! 1131: uerror( "case not in switch"); ! 1132: return; ! 1133: } ! 1134: if( swp >= &swtab[SWITSZ] ){ ! 1135: cerror( "switch table overflow"); ! 1136: } ! 1137: swp->sval = p->tn.lval; ! 1138: deflab( swp->slab = getlab() ); ! 1139: ++swp; ! 1140: tfree(p); ! 1141: } ! 1142: ! 1143: adddef(){ /* add default case to switch */ ! 1144: if( swtab[swx].slab >= 0 ){ ! 1145: uerror( "duplicate default in switch"); ! 1146: return; ! 1147: } ! 1148: if( swp == swtab ){ ! 1149: uerror( "default not inside switch"); ! 1150: return; ! 1151: } ! 1152: deflab( swtab[swx].slab = getlab() ); ! 1153: } ! 1154: ! 1155: swstart(){ ! 1156: /* begin a switch block */ ! 1157: if( swp >= &swtab[SWITSZ] ){ ! 1158: cerror( "switch table overflow"); ! 1159: } ! 1160: swx = swp - swtab; ! 1161: swp->slab = -1; ! 1162: ++swp; ! 1163: } ! 1164: ! 1165: swend(){ /* end a switch block */ ! 1166: ! 1167: register struct sw *swbeg, *p, *q, *r, *r1; ! 1168: CONSZ temp; ! 1169: int tempi; ! 1170: ! 1171: swbeg = &swtab[swx+1]; ! 1172: ! 1173: /* sort */ ! 1174: ! 1175: r1 = swbeg; ! 1176: r = swp-1; ! 1177: ! 1178: while( swbeg < r ){ ! 1179: /* bubble largest to end */ ! 1180: for( q=swbeg; q<r; ++q ){ ! 1181: if( q->sval > (q+1)->sval ){ ! 1182: /* swap */ ! 1183: r1 = q+1; ! 1184: temp = q->sval; ! 1185: q->sval = r1->sval; ! 1186: r1->sval = temp; ! 1187: tempi = q->slab; ! 1188: q->slab = r1->slab; ! 1189: r1->slab = tempi; ! 1190: } ! 1191: } ! 1192: r = r1; ! 1193: r1 = swbeg; ! 1194: } ! 1195: ! 1196: /* it is now sorted */ ! 1197: ! 1198: for( p = swbeg+1; p<swp; ++p ){ ! 1199: if( p->sval == (p-1)->sval ){ ! 1200: uerror( "duplicate case in switch, %d", tempi=p->sval ); ! 1201: return; ! 1202: } ! 1203: } ! 1204: ! 1205: reached = 1; ! 1206: genswitch( swbeg-1, (int)(swp-swbeg) ); ! 1207: swp = swbeg-1; ! 1208: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.