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: }