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