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