|
|
1.1 ! root 1: /* cgram.y 4.22 87/12/09 */ ! 2: ! 3: /* ! 4: * Grammar for the C compiler. ! 5: * ! 6: * This grammar requires the definitions of terminals in the file 'pcctokens'. ! 7: * (YACC doesn't have an 'include' mechanism, unfortunately.) ! 8: */ ! 9: ! 10: ! 11: /* at last count, there were 7 shift/reduce, 1 reduce/reduce conflicts ! 12: /* these involved: ! 13: if/else ! 14: recognizing functions in various contexts, including declarations ! 15: error recovery ! 16: */ ! 17: ! 18: %left CM ! 19: %right ASOP ASSIGN ! 20: %right QUEST COLON ! 21: %left OROR ! 22: %left ANDAND ! 23: %left OR ! 24: %left ER ! 25: %left AND ! 26: %left EQUOP ! 27: %left RELOP ! 28: %left SHIFTOP ! 29: %left PLUS MINUS ! 30: %left MUL DIVOP ! 31: %right UNOP ! 32: %right INCOP SIZEOF ! 33: %left LB LP STROP ! 34: %{ ! 35: # include "pass1.h" ! 36: %} ! 37: ! 38: /* define types */ ! 39: %start ext_def_list ! 40: ! 41: %type <intval> con_e ifelprefix ifprefix whprefix forprefix doprefix switchpart ! 42: enum_head str_head name_lp ! 43: %type <nodep> e .e term attributes oattributes type enum_dcl struct_dcl ! 44: cast_type null_decl funct_idn declarator fdeclarator nfdeclarator ! 45: elist ! 46: ! 47: %token <intval> CLASS NAME STRUCT RELOP CM DIVOP PLUS MINUS SHIFTOP MUL AND OR ER ANDAND OROR ! 48: ASSIGN STROP INCOP UNOP ICON ! 49: %token <nodep> TYPE ! 50: ! 51: %% ! 52: ! 53: %{ ! 54: static int fake = 0; ! 55: #ifndef FLEXNAMES ! 56: static char fakename[NCHNAM+1]; ! 57: #else ! 58: static char fakename[24]; ! 59: #endif ! 60: static int nsizeof = 0; ! 61: %} ! 62: ! 63: ext_def_list: ext_def_list external_def ! 64: | ! 65: =ftnend(); ! 66: ; ! 67: external_def: data_def ! 68: ={ curclass = SNULL; blevel = 0; } ! 69: | error ! 70: ={ curclass = SNULL; blevel = 0; } ! 71: ; ! 72: data_def: ! 73: oattributes SM ! 74: ={ $1->in.op = FREE; } ! 75: | oattributes init_dcl_list SM ! 76: ={ $1->in.op = FREE; } ! 77: | oattributes fdeclarator { ! 78: defid( tymerge($1,$2), curclass==STATIC?STATIC:EXTDEF ); ! 79: #ifndef LINT ! 80: if( nerrors == 0 ) ! 81: pfstab(stab[$2->tn.rval].sname); ! 82: #endif ! 83: } function_body ! 84: ={ ! 85: if( blevel ) cerror( "function level error" ); ! 86: if( reached ) retstat |= NRETVAL; ! 87: $1->in.op = FREE; ! 88: ftnend(); ! 89: } ! 90: ; ! 91: ! 92: function_body: arg_dcl_list compoundstmt ! 93: ; ! 94: arg_dcl_list: arg_dcl_list declaration ! 95: | ={ blevel = 1; } ! 96: ; ! 97: ! 98: stmt_list: stmt_list statement ! 99: | /* empty */ ! 100: ={ bccode(); ! 101: (void) locctr(PROG); ! 102: } ! 103: ; ! 104: ! 105: r_dcl_stat_list : dcl_stat_list attributes SM ! 106: ={ $2->in.op = FREE; ! 107: #ifndef LINT ! 108: if( nerrors == 0 ) plcstab(blevel); ! 109: #endif ! 110: } ! 111: | dcl_stat_list attributes init_dcl_list SM ! 112: ={ $2->in.op = FREE; ! 113: #ifndef LINT ! 114: if( nerrors == 0 ) plcstab(blevel); ! 115: #endif ! 116: } ! 117: ; ! 118: ! 119: dcl_stat_list : dcl_stat_list attributes SM ! 120: ={ $2->in.op = FREE; } ! 121: | dcl_stat_list attributes init_dcl_list SM ! 122: ={ $2->in.op = FREE; } ! 123: | /* empty */ ! 124: ; ! 125: declaration: attributes declarator_list SM ! 126: ={ curclass = SNULL; $1->in.op = FREE; } ! 127: | attributes SM ! 128: ={ curclass = SNULL; $1->in.op = FREE; } ! 129: | error SM ! 130: ={ curclass = SNULL; } ! 131: ; ! 132: oattributes: attributes ! 133: | /* VOID */ ! 134: ={ $$ = mkty(INT,0,INT); curclass = SNULL; } ! 135: ; ! 136: attributes: class type ! 137: ={ $$ = $2; } ! 138: | type class ! 139: | class ! 140: ={ $$ = mkty(INT,0,INT); } ! 141: | type ! 142: ={ curclass = SNULL ; } ! 143: | type class type ! 144: ={ $1->in.type = types( $1->in.type, $3->in.type, UNDEF ); ! 145: $3->in.op = FREE; ! 146: } ! 147: ; ! 148: ! 149: ! 150: class: CLASS ! 151: ={ curclass = $1; } ! 152: ; ! 153: ! 154: type: TYPE ! 155: | TYPE TYPE ! 156: ={ $1->in.type = types( $1->in.type, $2->in.type, UNDEF ); ! 157: $2->in.op = FREE; ! 158: } ! 159: | TYPE TYPE TYPE ! 160: ={ $1->in.type = types( $1->in.type, $2->in.type, $3->in.type ); ! 161: $2->in.op = $3->in.op = FREE; ! 162: } ! 163: | struct_dcl ! 164: | enum_dcl ! 165: ; ! 166: ! 167: enum_dcl: enum_head LC moe_list optcomma RC ! 168: ={ $$ = dclstruct($1); } ! 169: | ENUM NAME ! 170: ={ $$ = rstruct($2,0); stwart = instruct; } ! 171: ; ! 172: ! 173: enum_head: ENUM ! 174: ={ $$ = bstruct(-1,0); stwart = SEENAME; } ! 175: | ENUM NAME ! 176: ={ $$ = bstruct($2,0); stwart = SEENAME; } ! 177: ; ! 178: ! 179: moe_list: moe ! 180: | moe_list CM moe ! 181: ; ! 182: ! 183: moe: NAME ! 184: ={ moedef( $1 ); } ! 185: | NAME ASSIGN con_e ! 186: ={ strucoff = $3; moedef( $1 ); } ! 187: ; ! 188: ! 189: struct_dcl: str_head LC type_dcl_list optsemi RC ! 190: ={ $$ = dclstruct($1); } ! 191: | STRUCT NAME ! 192: ={ $$ = rstruct($2,$1); } ! 193: ; ! 194: ! 195: str_head: STRUCT ! 196: ={ $$ = bstruct(-1,$1); stwart=0; } ! 197: | STRUCT NAME ! 198: ={ $$ = bstruct($2,$1); stwart=0; } ! 199: ; ! 200: ! 201: type_dcl_list: type_declaration ! 202: | type_dcl_list SM type_declaration ! 203: ; ! 204: ! 205: type_declaration: type declarator_list ! 206: ={ curclass = SNULL; stwart=0; $1->in.op = FREE; } ! 207: | type ! 208: ={ if( curclass != MOU ){ ! 209: curclass = SNULL; ! 210: } ! 211: else { ! 212: sprintf( fakename, "$%dFAKE", fake++ ); ! 213: #ifdef FLEXNAMES ! 214: /* No need to hash this, we won't look it up */ ! 215: defid( tymerge($1, bdty(NAME,NIL,lookup( savestr(fakename), SMOS ))), curclass ); ! 216: #else ! 217: defid( tymerge($1, bdty(NAME,NIL,lookup( fakename, SMOS ))), curclass ); ! 218: #endif ! 219: werror("structure typed union member must be named"); ! 220: } ! 221: stwart = 0; ! 222: $1->in.op = FREE; ! 223: } ! 224: ; ! 225: ! 226: ! 227: declarator_list: declarator ! 228: ={ defid( tymerge($<nodep>0,$1), curclass); stwart = instruct; } ! 229: | declarator_list CM {$<nodep>$=$<nodep>0;} declarator ! 230: ={ defid( tymerge($<nodep>0,$4), curclass); stwart = instruct; } ! 231: ; ! 232: declarator: fdeclarator ! 233: | nfdeclarator ! 234: | nfdeclarator COLON con_e ! 235: %prec CM ! 236: ={ if( !(instruct&INSTRUCT) ) uerror( "field outside of structure" ); ! 237: if( $3<0 || $3 >= FIELD ){ ! 238: uerror( "illegal field size" ); ! 239: $3 = 1; ! 240: } ! 241: defid( tymerge($<nodep>0,$1), FIELD|$3 ); ! 242: $$ = NIL; ! 243: } ! 244: | COLON con_e ! 245: %prec CM ! 246: ={ if( !(instruct&INSTRUCT) ) uerror( "field outside of structure" ); ! 247: (void) falloc( stab, $2, -1, $<nodep>0 ); /* alignment or hole */ ! 248: $$ = NIL; ! 249: } ! 250: | error ! 251: ={ $$ = NIL; } ! 252: ; ! 253: ! 254: /* int (a)(); is not a function --- sorry! */ ! 255: nfdeclarator: MUL nfdeclarator ! 256: ={ umul: ! 257: $$ = bdty( UNARY MUL, $2, 0 ); } ! 258: | nfdeclarator LP RP ! 259: ={ uftn: ! 260: $$ = bdty( UNARY CALL, $1, 0 ); } ! 261: | nfdeclarator LB RB ! 262: ={ uary: ! 263: $$ = bdty( LB, $1, 0 ); } ! 264: | nfdeclarator LB con_e RB ! 265: ={ bary: ! 266: if( (int)$3 <= 0 ) werror( "zero or negative subscript" ); ! 267: $$ = bdty( LB, $1, $3 ); } ! 268: | NAME ! 269: ={ $$ = bdty( NAME, NIL, $1 ); } ! 270: | LP nfdeclarator RP ! 271: ={ $$=$2; } ! 272: ; ! 273: fdeclarator: MUL fdeclarator ! 274: ={ goto umul; } ! 275: | fdeclarator LP RP ! 276: ={ goto uftn; } ! 277: | fdeclarator LB RB ! 278: ={ goto uary; } ! 279: | fdeclarator LB con_e RB ! 280: ={ goto bary; } ! 281: | LP fdeclarator RP ! 282: ={ $$ = $2; } ! 283: | name_lp name_list RP ! 284: ={ ! 285: if( blevel!=0 ) uerror("function declaration in bad context"); ! 286: $$ = bdty( UNARY CALL, bdty(NAME,NIL,$1), 0 ); ! 287: stwart = 0; ! 288: } ! 289: | name_lp RP ! 290: ={ ! 291: $$ = bdty( UNARY CALL, bdty(NAME,NIL,$1), 0 ); ! 292: stwart = 0; ! 293: } ! 294: ; ! 295: ! 296: name_lp: NAME LP ! 297: ={ ! 298: /* turn off typedefs for argument names */ ! 299: stwart = SEENAME; ! 300: if( stab[$1].sclass == SNULL ) ! 301: stab[$1].stype = FTN; ! 302: } ! 303: ; ! 304: ! 305: name_list: NAME ! 306: ={ ftnarg( $1 ); stwart = SEENAME; } ! 307: | name_list CM NAME ! 308: ={ ftnarg( $3 ); stwart = SEENAME; } ! 309: | error ! 310: ; ! 311: /* always preceeded by attributes: thus the $<nodep>0's */ ! 312: init_dcl_list: init_declarator ! 313: %prec CM ! 314: | init_dcl_list CM {$<nodep>$=$<nodep>0;} init_declarator ! 315: ; ! 316: /* always preceeded by attributes */ ! 317: xnfdeclarator: nfdeclarator ! 318: ={ int id; ! 319: ! 320: defid( $1 = tymerge($<nodep>0,$1), curclass); ! 321: id = $1->tn.rval; ! 322: beginit(id); ! 323: if( stab[id].sclass == AUTO || ! 324: stab[id].sclass == REGISTER || ! 325: stab[id].sclass == STATIC ) ! 326: stab[id].suse = -lineno; ! 327: } ! 328: | error ! 329: ; ! 330: /* always preceeded by attributes */ ! 331: init_declarator: nfdeclarator ! 332: ={ nidcl( tymerge($<nodep>0,$1) ); } ! 333: | fdeclarator ! 334: ={ defid( tymerge($<nodep>0,$1), uclass(curclass) ); ! 335: if( paramno > 0 ){ ! 336: uerror( "illegal argument" ); ! 337: paramno = 0; ! 338: } ! 339: } ! 340: | xnfdeclarator optasgn e ! 341: %prec CM ! 342: ={ doinit( $3 ); ! 343: endinit(); } ! 344: | xnfdeclarator optasgn LC init_list optcomma RC ! 345: ={ endinit(); } ! 346: | error ! 347: ={ fixinit(); } ! 348: ; ! 349: ! 350: init_list: initializer ! 351: %prec CM ! 352: | init_list CM initializer ! 353: ; ! 354: initializer: e ! 355: %prec CM ! 356: ={ doinit( $1 ); } ! 357: | ibrace init_list optcomma RC ! 358: ={ irbrace(); } ! 359: ; ! 360: ! 361: optcomma : /* VOID */ ! 362: | CM ! 363: ; ! 364: ! 365: optsemi : /* VOID */ ! 366: | SM ! 367: ; ! 368: ! 369: optasgn : /* uncomment for old-fashioned initializations */ ! 370: /* /* VOID */ ! 371: /* ={ werror( "old-fashioned initialization: use =" ); } ! 372: /* | */ ASSIGN ! 373: ; ! 374: ! 375: ibrace : LC ! 376: ={ ilbrace(); } ! 377: ; ! 378: ! 379: /* STATEMENTS */ ! 380: ! 381: compoundstmt: dcmpstmt ! 382: | cmpstmt ! 383: ; ! 384: ! 385: dcmpstmt: begin r_dcl_stat_list stmt_list RC ! 386: ={ ! 387: #ifndef LINT ! 388: if( nerrors == 0 ) prcstab(blevel); ! 389: #endif ! 390: --blevel; ! 391: if( blevel == 1 ) blevel = 0; ! 392: clearst( blevel ); ! 393: checkst( blevel ); ! 394: autooff = *--psavbc; ! 395: regvar = *--psavbc; ! 396: } ! 397: ; ! 398: ! 399: cmpstmt: begin stmt_list RC ! 400: ={ --blevel; ! 401: if( blevel == 1 ) blevel = 0; ! 402: clearst( blevel ); ! 403: checkst( blevel ); ! 404: autooff = *--psavbc; ! 405: regvar = *--psavbc; ! 406: } ! 407: ; ! 408: ! 409: begin: LC ! 410: ={ if( blevel == 1 ) dclargs(); ! 411: ++blevel; ! 412: if( psavbc > &asavbc[BCSZ-2] ) cerror( "nesting too deep" ); ! 413: *psavbc++ = regvar; ! 414: *psavbc++ = autooff; ! 415: } ! 416: ; ! 417: ! 418: statement: e SM ! 419: ={ ecomp( $1 ); } ! 420: | compoundstmt ! 421: | ifprefix statement ! 422: ={ deflab($1); ! 423: reached = 1; ! 424: } ! 425: | ifelprefix statement ! 426: ={ if( $1 != NOLAB ){ ! 427: deflab( $1 ); ! 428: reached = 1; ! 429: } ! 430: } ! 431: | whprefix statement ! 432: ={ branch( contlab ); ! 433: deflab( brklab ); ! 434: if( (flostat&FBRK) || !(flostat&FLOOP)) reached = 1; ! 435: else reached = 0; ! 436: resetbc(0); ! 437: } ! 438: | doprefix statement WHILE LP e RP SM ! 439: ={ deflab( contlab ); ! 440: if( flostat & FCONT ) reached = 1; ! 441: ecomp( buildtree( CBRANCH, buildtree( NOT, $5, NIL ), bcon( $1 ) ) ); ! 442: deflab( brklab ); ! 443: reached = 1; ! 444: resetbc(0); ! 445: } ! 446: | forprefix .e RP statement ! 447: ={ deflab( contlab ); ! 448: if( flostat&FCONT ) reached = 1; ! 449: if( $2 ) ecomp( $2 ); ! 450: branch( $1 ); ! 451: deflab( brklab ); ! 452: if( (flostat&FBRK) || !(flostat&FLOOP) ) reached = 1; ! 453: else reached = 0; ! 454: resetbc(0); ! 455: } ! 456: | switchpart statement ! 457: ={ if( reached ) branch( brklab ); ! 458: deflab( $1 ); ! 459: swend(); ! 460: deflab(brklab); ! 461: if( (flostat&FBRK) || !(flostat&FDEF) ) reached = 1; ! 462: resetbc(FCONT); ! 463: } ! 464: | BREAK SM ! 465: ={ if( brklab == NOLAB ) uerror( "illegal break"); ! 466: else if(reached) branch( brklab ); ! 467: flostat |= FBRK; ! 468: if( brkflag ) goto rch; ! 469: reached = 0; ! 470: } ! 471: | CONTINUE SM ! 472: ={ if( contlab == NOLAB ) uerror( "illegal continue"); ! 473: else branch( contlab ); ! 474: flostat |= FCONT; ! 475: goto rch; ! 476: } ! 477: | RETURN SM ! 478: ={ retstat |= NRETVAL; ! 479: branch( retlab ); ! 480: rch: ! 481: if( !reached ) werror( "statement not reached"); ! 482: reached = 0; ! 483: } ! 484: | RETURN e SM ! 485: ={ register NODE *temp; ! 486: idname = curftn; ! 487: temp = buildtree( NAME, NIL, NIL ); ! 488: if(temp->in.type == TVOID) ! 489: uerror("void function %s cannot return value", ! 490: stab[idname].sname); ! 491: temp->in.type = DECREF( temp->in.type ); ! 492: temp = buildtree( RETURN, temp, $2 ); ! 493: /* now, we have the type of the RHS correct */ ! 494: temp->in.left->in.op = FREE; ! 495: temp->in.op = FREE; ! 496: ecomp( buildtree( FORCE, temp->in.right, NIL ) ); ! 497: retstat |= RETVAL; ! 498: branch( retlab ); ! 499: reached = 0; ! 500: } ! 501: | GOTO NAME SM ! 502: ={ register NODE *q; ! 503: q = block( FREE, NIL, NIL, INT|ARY, 0, INT ); ! 504: q->tn.rval = idname = $2; ! 505: defid( q, ULABEL ); ! 506: stab[idname].suse = -lineno; ! 507: branch( stab[idname].offset ); ! 508: goto rch; ! 509: } ! 510: | SM ! 511: | error SM ! 512: | error RC ! 513: | label statement ! 514: ; ! 515: label: NAME COLON ! 516: ={ register NODE *q; ! 517: q = block( FREE, NIL, NIL, INT|ARY, 0, LABEL ); ! 518: q->tn.rval = $1; ! 519: defid( q, LABEL ); ! 520: reached = 1; ! 521: } ! 522: | CASE e COLON ! 523: ={ addcase($2); ! 524: reached = 1; ! 525: } ! 526: | DEFAULT COLON ! 527: ={ reached = 1; ! 528: adddef(); ! 529: flostat |= FDEF; ! 530: } ! 531: ; ! 532: doprefix: DO ! 533: ={ savebc(); ! 534: if( !reached ) werror( "loop not entered at top"); ! 535: brklab = getlab(); ! 536: contlab = getlab(); ! 537: deflab( $$ = getlab() ); ! 538: reached = 1; ! 539: } ! 540: ; ! 541: ifprefix: IF LP e RP ! 542: ={ ecomp( buildtree( CBRANCH, $3, bcon( $$=getlab()) ) ) ; ! 543: reached = 1; ! 544: } ! 545: ; ! 546: ifelprefix: ifprefix statement ELSE ! 547: ={ if( reached ) branch( $$ = getlab() ); ! 548: else $$ = NOLAB; ! 549: deflab( $1 ); ! 550: reached = 1; ! 551: } ! 552: ; ! 553: ! 554: whprefix: WHILE LP e RP ! 555: ={ savebc(); ! 556: if( !reached ) werror( "loop not entered at top"); ! 557: if( $3->in.op == ICON && $3->tn.lval != 0 ) flostat = FLOOP; ! 558: deflab( contlab = getlab() ); ! 559: reached = 1; ! 560: brklab = getlab(); ! 561: if( flostat == FLOOP ) tfree( $3 ); ! 562: else ecomp( buildtree( CBRANCH, $3, bcon( brklab) ) ); ! 563: } ! 564: ; ! 565: forprefix: FOR LP .e SM .e SM ! 566: ={ if( $3 ) ecomp( $3 ); ! 567: else if( !reached ) werror( "loop not entered at top"); ! 568: savebc(); ! 569: contlab = getlab(); ! 570: brklab = getlab(); ! 571: deflab( $$ = getlab() ); ! 572: reached = 1; ! 573: if( $5 ) ecomp( buildtree( CBRANCH, $5, bcon( brklab) ) ); ! 574: else flostat |= FLOOP; ! 575: } ! 576: ; ! 577: switchpart: SWITCH LP e RP ! 578: ={ register NODE *q; ! 579: ! 580: savebc(); ! 581: brklab = getlab(); ! 582: q = $3; ! 583: switch( q->in.type ) { ! 584: case CHAR: case UCHAR: ! 585: case SHORT: case USHORT: ! 586: case INT: case UNSIGNED: ! 587: case MOE: case ENUMTY: ! 588: break; ! 589: default: ! 590: werror("switch expression not type int"); ! 591: q = makety( q, INT, q->fn.cdim, q->fn.csiz ); ! 592: } ! 593: #ifdef LINT ! 594: if( hflag && q->in.op == ICON ) ! 595: werror( "constant switch expression" ); ! 596: #endif ! 597: ecomp( buildtree( FORCE, q, NIL ) ); ! 598: branch( $$ = getlab() ); ! 599: swstart(); ! 600: reached = 0; ! 601: } ! 602: ; ! 603: /* EXPRESSIONS */ ! 604: con_e: { $<intval>$=instruct; stwart=instruct=0; } e ! 605: %prec CM ! 606: ={ $$ = icons( $2 ); instruct=$<intval>1; } ! 607: ; ! 608: .e: e ! 609: | ! 610: ={ $$=0; } ! 611: ; ! 612: elist: e ! 613: %prec CM ! 614: | elist CM e ! 615: ={ goto bop; } ! 616: ; ! 617: ! 618: e: e RELOP e ! 619: ={ ! 620: preconf: ! 621: if( yychar==RELOP||yychar==EQUOP||yychar==AND||yychar==OR||yychar==ER ){ ! 622: precplaint: ! 623: if( hflag ) werror( "precedence confusion possible: parenthesize!" ); ! 624: } ! 625: bop: ! 626: $$ = buildtree( $2, $1, $3 ); ! 627: } ! 628: | e CM e ! 629: ={ $2 = COMOP; ! 630: goto bop; ! 631: } ! 632: | e DIVOP e ! 633: ={ goto bop; } ! 634: | e PLUS e ! 635: ={ if(yychar==SHIFTOP) goto precplaint; else goto bop; } ! 636: | e MINUS e ! 637: ={ if(yychar==SHIFTOP ) goto precplaint; else goto bop; } ! 638: | e SHIFTOP e ! 639: ={ if(yychar==PLUS||yychar==MINUS) goto precplaint; else goto bop; } ! 640: | e MUL e ! 641: ={ goto bop; } ! 642: | e EQUOP e ! 643: ={ goto preconf; } ! 644: | e AND e ! 645: ={ if( yychar==RELOP||yychar==EQUOP ) goto preconf; else goto bop; } ! 646: | e OR e ! 647: ={ if(yychar==RELOP||yychar==EQUOP) goto preconf; else goto bop; } ! 648: | e ER e ! 649: ={ if(yychar==RELOP||yychar==EQUOP) goto preconf; else goto bop; } ! 650: | e ANDAND e ! 651: ={ goto bop; } ! 652: | e OROR e ! 653: ={ goto bop; } ! 654: | e MUL ASSIGN e ! 655: ={ abop: ! 656: $$ = buildtree( ASG $2, $1, $4 ); ! 657: } ! 658: | e DIVOP ASSIGN e ! 659: ={ goto abop; } ! 660: | e PLUS ASSIGN e ! 661: ={ goto abop; } ! 662: | e MINUS ASSIGN e ! 663: ={ goto abop; } ! 664: | e SHIFTOP ASSIGN e ! 665: ={ goto abop; } ! 666: | e AND ASSIGN e ! 667: ={ goto abop; } ! 668: | e OR ASSIGN e ! 669: ={ goto abop; } ! 670: | e ER ASSIGN e ! 671: ={ goto abop; } ! 672: | e QUEST e COLON e ! 673: ={ $$=buildtree(QUEST, $1, buildtree( COLON, $3, $5 ) ); ! 674: } ! 675: | e ASOP e ! 676: ={ werror( "old-fashioned assignment operator" ); goto bop; } ! 677: | e ASSIGN e ! 678: ={ goto bop; } ! 679: | term ! 680: ; ! 681: term: term INCOP ! 682: ={ $$ = buildtree( $2, $1, bcon(1) ); } ! 683: | MUL term ! 684: ={ ubop: ! 685: $$ = buildtree( UNARY $1, $2, NIL ); ! 686: } ! 687: | AND term ! 688: ={ if( ISFTN($2->in.type) || ISARY($2->in.type) ){ ! 689: werror( "& before array or function: ignored" ); ! 690: $$ = $2; ! 691: } ! 692: else if( $2->in.op == UNARY MUL && ! 693: ($2->in.left->in.op == STASG || ! 694: $2->in.left->in.op == STCALL || ! 695: $2->in.left->in.op == UNARY STCALL) ){ ! 696: /* legal trees but not available to users */ ! 697: uerror( "unacceptable operand of &" ); ! 698: goto ubop; ! 699: } ! 700: else goto ubop; ! 701: } ! 702: | MINUS term ! 703: ={ goto ubop; } ! 704: | UNOP term ! 705: ={ ! 706: $$ = buildtree( $1, $2, NIL ); ! 707: } ! 708: | INCOP term ! 709: ={ $$ = buildtree( $1==INCR ? ASG PLUS : ASG MINUS, ! 710: $2, ! 711: bcon(1) ); ! 712: } ! 713: | pushsizeof term %prec SIZEOF ! 714: ={ $$ = doszof( $2 ); --nsizeof; } ! 715: | LP cast_type RP term %prec INCOP ! 716: ={ $$ = buildtree( CAST, $2, $4 ); ! 717: $$->in.left->in.op = FREE; ! 718: $$->in.op = FREE; ! 719: $$ = $$->in.right; ! 720: } ! 721: | pushsizeof LP cast_type RP %prec SIZEOF ! 722: ={ $$ = doszof( $3 ); --nsizeof; } ! 723: | term LB e RB ! 724: ={ $$ = buildtree( UNARY MUL, buildtree( PLUS, $1, $3 ), NIL ); } ! 725: | funct_idn RP ! 726: ={ $$=buildtree(UNARY CALL,$1,NIL); } ! 727: | funct_idn elist RP ! 728: ={ $$=buildtree(CALL,$1,$2); } ! 729: | term STROP NAME ! 730: ={ if( $2 == DOT ){ ! 731: if( notlval( $1 ) && ! 732: !($1->in.op == UNARY MUL && ! 733: ($1->in.left->in.op == STASG || ! 734: $1->in.left->in.op == STCALL || ! 735: $1->in.left->in.op == UNARY STCALL)) ) ! 736: uerror("structure reference must be addressable"); ! 737: $1 = buildtree( UNARY AND, $1, NIL ); ! 738: } ! 739: idname = $3; ! 740: $$ = buildtree( STREF, $1, buildtree( NAME, NIL, NIL ) ); ! 741: } ! 742: | NAME ! 743: ={ idname = $1; ! 744: /* recognize identifiers in initializations */ ! 745: if( blevel==0 && stab[idname].stype == UNDEF ) { ! 746: register NODE *q; ! 747: #ifndef FLEXNAMES ! 748: werror( "undeclared initializer name %.8s", stab[idname].sname ); ! 749: #else ! 750: werror( "undeclared initializer name %s", stab[idname].sname ); ! 751: #endif ! 752: q = block( FREE, NIL, NIL, INT, 0, INT ); ! 753: q->tn.rval = idname; ! 754: defid( q, EXTERN ); ! 755: } ! 756: $$=buildtree(NAME,NIL,NIL); ! 757: if( nsizeof == 0 ) ! 758: stab[$1].suse = -lineno; ! 759: } ! 760: | ICON ! 761: ={ $$=bcon(0); ! 762: $$->tn.lval = lastcon; ! 763: $$->tn.rval = NONAME; ! 764: if( $1 ) $$->fn.csiz = $$->in.type = ctype(LONG); ! 765: } ! 766: | FCON ! 767: ={ $$=buildtree(FCON,NIL,NIL); ! 768: $$->fpn.fval = fcon; ! 769: } ! 770: | DCON ! 771: ={ $$=buildtree(DCON,NIL,NIL); ! 772: $$->dpn.dval = dcon; ! 773: } ! 774: | STRING ! 775: ={ $$ = getstr(); /* get string contents */ } ! 776: | LP e RP ! 777: ={ $$=$2; } ! 778: ; ! 779: ! 780: cast_type: type null_decl ! 781: ={ ! 782: $$ = tymerge( $1, $2 ); ! 783: $$->in.op = NAME; ! 784: $1->in.op = FREE; ! 785: } ! 786: ; ! 787: ! 788: pushsizeof: SIZEOF ! 789: ={ ++nsizeof; } ! 790: ; ! 791: ! 792: null_decl: /* empty */ ! 793: ={ $$ = bdty( NAME, NIL, -1 ); } ! 794: | LP RP ! 795: ={ $$ = bdty( UNARY CALL, bdty(NAME,NIL,-1),0); } ! 796: | LP null_decl RP LP RP ! 797: ={ $$ = bdty( UNARY CALL, $2, 0 ); } ! 798: | MUL null_decl ! 799: ={ goto umul; } ! 800: | null_decl LB RB ! 801: ={ goto uary; } ! 802: | null_decl LB con_e RB ! 803: ={ goto bary; } ! 804: | LP null_decl RP ! 805: ={ $$ = $2; } ! 806: ; ! 807: ! 808: funct_idn: NAME LP ! 809: ={ if( stab[$1].stype == UNDEF ){ ! 810: register NODE *q; ! 811: q = block( FREE, NIL, NIL, FTN|INT, 0, INT ); ! 812: q->tn.rval = $1; ! 813: defid( q, EXTERN ); ! 814: } ! 815: idname = $1; ! 816: $$=buildtree(NAME,NIL,NIL); ! 817: stab[idname].suse = -lineno; ! 818: } ! 819: | term LP ! 820: ; ! 821: %% ! 822: ! 823: NODE * ! 824: mkty( t, d, s ) unsigned t; { ! 825: return( block( TYPE, NIL, NIL, t, d, s ) ); ! 826: } ! 827: ! 828: NODE * ! 829: bdty( op, p, v ) NODE *p; { ! 830: register NODE *q; ! 831: ! 832: q = block( op, p, NIL, INT, 0, INT ); ! 833: ! 834: switch( op ){ ! 835: ! 836: case UNARY MUL: ! 837: case UNARY CALL: ! 838: break; ! 839: ! 840: case LB: ! 841: q->in.right = bcon(v); ! 842: break; ! 843: ! 844: case NAME: ! 845: q->tn.rval = v; ! 846: break; ! 847: ! 848: default: ! 849: cerror( "bad bdty" ); ! 850: } ! 851: ! 852: return( q ); ! 853: } ! 854: ! 855: dstash( n ){ /* put n into the dimension table */ ! 856: if( curdim >= DIMTABSZ-1 ){ ! 857: cerror( "dimension table overflow"); ! 858: } ! 859: dimtab[ curdim++ ] = n; ! 860: } ! 861: ! 862: savebc() { ! 863: if( psavbc > & asavbc[BCSZ-4 ] ){ ! 864: cerror( "whiles, fors, etc. too deeply nested"); ! 865: } ! 866: *psavbc++ = brklab; ! 867: *psavbc++ = contlab; ! 868: *psavbc++ = flostat; ! 869: *psavbc++ = swx; ! 870: flostat = 0; ! 871: } ! 872: ! 873: resetbc(mask){ ! 874: ! 875: swx = *--psavbc; ! 876: flostat = *--psavbc | (flostat&mask); ! 877: contlab = *--psavbc; ! 878: brklab = *--psavbc; ! 879: ! 880: } ! 881: ! 882: addcase(p) NODE *p; { /* add case to switch */ ! 883: ! 884: p = optim( p ); /* change enum to ints */ ! 885: if( p->in.op != ICON || p->tn.rval != NONAME ){ ! 886: uerror( "non-constant case expression"); ! 887: return; ! 888: } ! 889: if( swp == swtab ){ ! 890: uerror( "case not in switch"); ! 891: return; ! 892: } ! 893: if( swp >= &swtab[SWITSZ] ){ ! 894: cerror( "switch table overflow"); ! 895: } ! 896: swp->sval = p->tn.lval; ! 897: deflab( swp->slab = getlab() ); ! 898: ++swp; ! 899: tfree(p); ! 900: } ! 901: ! 902: adddef(){ /* add default case to switch */ ! 903: if( swtab[swx].slab >= 0 ){ ! 904: uerror( "duplicate default in switch"); ! 905: return; ! 906: } ! 907: if( swp == swtab ){ ! 908: uerror( "default not inside switch"); ! 909: return; ! 910: } ! 911: deflab( swtab[swx].slab = getlab() ); ! 912: } ! 913: ! 914: swstart(){ ! 915: /* begin a switch block */ ! 916: if( swp >= &swtab[SWITSZ] ){ ! 917: cerror( "switch table overflow"); ! 918: } ! 919: swx = swp - swtab; ! 920: swp->slab = -1; ! 921: ++swp; ! 922: } ! 923: ! 924: swend(){ /* end a switch block */ ! 925: ! 926: register struct sw *swbeg, *p, *q, *r, *r1; ! 927: CONSZ temp; ! 928: int tempi; ! 929: ! 930: swbeg = &swtab[swx+1]; ! 931: ! 932: /* sort */ ! 933: ! 934: r1 = swbeg; ! 935: r = swp-1; ! 936: ! 937: while( swbeg < r ){ ! 938: /* bubble largest to end */ ! 939: for( q=swbeg; q<r; ++q ){ ! 940: if( q->sval > (q+1)->sval ){ ! 941: /* swap */ ! 942: r1 = q+1; ! 943: temp = q->sval; ! 944: q->sval = r1->sval; ! 945: r1->sval = temp; ! 946: tempi = q->slab; ! 947: q->slab = r1->slab; ! 948: r1->slab = tempi; ! 949: } ! 950: } ! 951: r = r1; ! 952: r1 = swbeg; ! 953: } ! 954: ! 955: /* it is now sorted */ ! 956: ! 957: for( p = swbeg+1; p<swp; ++p ){ ! 958: if( p->sval == (p-1)->sval ){ ! 959: uerror( "duplicate case in switch, %d", p->sval ); ! 960: return; ! 961: } ! 962: } ! 963: ! 964: genswitch( swbeg-1, swp-swbeg ); ! 965: swp = swbeg-1; ! 966: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.