1: %term NAME 2 2: %term STRING 3 3: %term ICON 4 4: %term FCON 5 5: %term PLUS 6 6: %term MINUS 8 7: %term MUL 11 8: %term AND 14 9: %term OR 17 10: %term ER 19 11: %term QUEST 21 12: %term COLON 22 13: %term ANDAND 23 14: %term OROR 24 15: 16: /* special interfaces for yacc alone */ 17: /* These serve as abbreviations of 2 or more ops: 18: ASOP =, = ops 19: RELOP LE,LT,GE,GT 20: EQUOP EQ,NE 21: DIVOP DIV,MOD 22: SHIFTOP LS,RS 23: ICOP ICR,DECR 24: UNOP NOT,COMPL 25: STROP DOT,STREF 26: 27: */ 28: %term ASOP 25 29: %term RELOP 26 30: %term EQUOP 27 31: %term DIVOP 28 32: %term SHIFTOP 29 33: %term INCOP 30 34: %term UNOP 31 35: %term STROP 32 36: 37: /* reserved words, etc */ 38: %term TYPE 33 39: %term CLASS 34 40: %term STRUCT 35 41: %term RETURN 36 42: %term GOTO 37 43: %term IF 38 44: %term ELSE 39 45: %term SWITCH 40 46: %term BREAK 41 47: %term CONTINUE 42 48: %term WHILE 43 49: %term DO 44 50: %term FOR 45 51: %term DEFAULT 46 52: %term CASE 47 53: %term SIZEOF 48 54: %term ENUM 49 55: 56: 57: /* little symbols, etc. */ 58: /* namely, 59: 60: LP ( 61: RP ) 62: 63: LC { 64: RC } 65: 66: LB [ 67: RB ] 68: 69: CM , 70: SM ; 71: 72: */ 73: 74: %term LP 50 75: %term RP 51 76: %term LC 52 77: %term RC 53 78: %term LB 54 79: %term RB 55 80: %term CM 56 81: %term SM 57 82: %term ASSIGN 58 83: 84: /* at last count, there were 7 shift/reduce, 1 reduce/reduce conflicts 85: /* these involved: 86: if/else 87: recognizing functions in various contexts, including declarations 88: error recovery 89: */ 90: 91: %left CM 92: %right ASOP ASSIGN 93: %right QUEST COLON 94: %left OROR 95: %left ANDAND 96: %left OR 97: %left ER 98: %left AND 99: %left EQUOP 100: %left RELOP 101: %left SHIFTOP 102: %left PLUS MINUS 103: %left MUL DIVOP 104: %right UNOP 105: %right INCOP SIZEOF 106: %left LB LP STROP 107: %{ 108: # include "mfile1" 109: %} 110: 111: /* define types */ 112: %start ext_def_list 113: 114: %type <intval> con_e ifelprefix ifprefix whprefix forprefix doprefix switchpart 115: enum_head str_head name_lp 116: %type <nodep> e .e term attributes oattributes type enum_dcl struct_dcl 117: cast_type null_decl funct_idn declarator fdeclarator nfdeclarator 118: elist 119: 120: %token <intval> CLASS NAME STRUCT RELOP CM DIVOP PLUS MINUS SHIFTOP MUL AND OR ER ANDAND OROR 121: ASSIGN STROP INCOP UNOP ICON 122: %token <nodep> TYPE 123: 124: %% 125: 126: %{ 127: static int fake = 0; 128: static char fakename[NCHNAM+1]; 129: %} 130: 131: ext_def_list: ext_def_list external_def 132: | 133: =ftnend(); 134: ; 135: external_def: data_def 136: ={ curclass = SNULL; blevel = 0; } 137: | error 138: ={ curclass = SNULL; blevel = 0; } 139: ; 140: data_def: 141: oattributes SM 142: ={ $1->op = FREE; } 143: | oattributes init_dcl_list SM 144: ={ $1->op = FREE; } 145: | oattributes fdeclarator { 146: defid( tymerge($1,$2), curclass==STATIC?STATIC:EXTDEF ); 147: } function_body 148: ={ 149: if( blevel ) cerror( "function level error" ); 150: if( reached ) retstat |= NRETVAL; 151: $1->op = FREE; 152: ftnend(); 153: } 154: ; 155: 156: function_body: arg_dcl_list compoundstmt 157: ; 158: arg_dcl_list: arg_dcl_list declaration 159: | ={ blevel = 1; } 160: ; 161: 162: stmt_list: stmt_list statement 163: | /* empty */ 164: ={ bccode(); 165: locctr(PROG); 166: } 167: ; 168: 169: dcl_stat_list : dcl_stat_list attributes SM 170: ={ $2->op = FREE; } 171: | dcl_stat_list attributes init_dcl_list SM 172: ={ $2->op = FREE; } 173: | /* empty */ 174: ; 175: declaration: attributes declarator_list SM 176: ={ curclass = SNULL; $1->op = FREE; } 177: | attributes SM 178: ={ curclass = SNULL; $1->op = FREE; } 179: | error SM 180: ={ curclass = SNULL; } 181: ; 182: oattributes: attributes 183: | /* VOID */ 184: ={ $$ = mkty(INT,0,INT); curclass = SNULL; } 185: ; 186: attributes: class type 187: ={ $$ = $2; } 188: | type class 189: | class 190: ={ $$ = mkty(INT,0,INT); } 191: | type 192: ={ curclass = SNULL ; } 193: ; 194: 195: 196: class: CLASS 197: ={ curclass = $1; } 198: ; 199: 200: type: TYPE 201: | TYPE TYPE 202: ={ $1->type = types( $1->type, $2->type, UNDEF ); 203: $2->op = FREE; 204: } 205: | TYPE TYPE TYPE 206: ={ $1->type = types( $1->type, $2->type, $3->type ); 207: $2->op = $3->op = FREE; 208: } 209: | struct_dcl 210: | enum_dcl 211: ; 212: 213: enum_dcl: enum_head LC moe_list optcomma RC 214: ={ $$ = dclstruct($1); } 215: | ENUM NAME 216: ={ $$ = rstruct($2,0); stwart = instruct; } 217: ; 218: 219: enum_head: ENUM 220: ={ $$ = bstruct(-1,0); } 221: | ENUM NAME 222: ={ $$ = bstruct($2,0); } 223: ; 224: 225: moe_list: moe 226: | moe_list CM moe 227: ; 228: 229: moe: NAME 230: ={ moedef( $1 ); } 231: | NAME ASSIGN con_e 232: ={ strucoff = $3; moedef( $1 ); } 233: ; 234: 235: struct_dcl: str_head LC type_dcl_list optsemi RC 236: ={ $$ = dclstruct($1); } 237: | STRUCT NAME 238: ={ $$ = rstruct($2,$1); } 239: ; 240: 241: str_head: STRUCT 242: ={ $$ = bstruct(-1,$1); stwart=0; } 243: | STRUCT NAME 244: ={ $$ = bstruct($2,$1); stwart=0; } 245: ; 246: 247: type_dcl_list: type_declaration 248: | type_dcl_list SM type_declaration 249: ; 250: 251: type_declaration: type declarator_list 252: ={ curclass = SNULL; stwart=0; $1->op = FREE; } 253: | type 254: ={ if( curclass != MOU ){ 255: curclass = SNULL; 256: } 257: else { 258: sprintf( fakename, "$%dFAKE", fake++ ); 259: defid( tymerge($1, bdty(NAME,NIL,lookup( fakename, SMOS ))), curclass ); 260: } 261: stwart = 0; 262: $1->op = FREE; 263: } 264: ; 265: 266: 267: declarator_list: declarator 268: ={ defid( tymerge($<nodep>0,$1), curclass); stwart = instruct; } 269: | declarator_list CM {$<nodep>$=$<nodep>0;} declarator 270: ={ defid( tymerge($<nodep>0,$4), curclass); stwart = instruct; } 271: ; 272: declarator: fdeclarator 273: | nfdeclarator 274: | nfdeclarator COLON con_e 275: %prec CM 276: ={ if( !(instruct&INSTRUCT) ) uerror( "field outside of structure" ); 277: if( $3<0 || $3 >= FIELD ){ 278: uerror( "illegal field size" ); 279: $3 = 1; 280: } 281: defid( tymerge($<nodep>0,$1), FIELD|$3 ); 282: $$ = NIL; 283: } 284: | COLON con_e 285: %prec CM 286: ={ if( !(instruct&INSTRUCT) ) uerror( "field outside of structure" ); 287: falloc( stab, $2, -1, $<nodep>0 ); /* alignment or hole */ 288: $$ = NIL; 289: } 290: | error 291: ={ $$ = NIL; } 292: ; 293: 294: /* int (a)(); is not a function --- sorry! */ 295: nfdeclarator: MUL nfdeclarator 296: ={ umul: 297: $$ = bdty( UNARY MUL, $2, 0 ); } 298: | nfdeclarator LP RP 299: ={ uftn: 300: $$ = bdty( UNARY CALL, $1, 0 ); } 301: | nfdeclarator LB RB 302: ={ uary: 303: $$ = bdty( LB, $1, 0 ); } 304: | nfdeclarator LB con_e RB 305: ={ bary: 306: if( (int)$3 <= 0 ) werror( "zero or negative subscript" ); 307: $$ = bdty( LB, $1, $3 ); } 308: | NAME 309: ={ $$ = bdty( NAME, NIL, $1 ); } 310: | LP nfdeclarator RP 311: ={ $$=$2; } 312: ; 313: fdeclarator: MUL fdeclarator 314: ={ goto umul; } 315: | fdeclarator LP RP 316: ={ goto uftn; } 317: | fdeclarator LB RB 318: ={ goto uary; } 319: | fdeclarator LB con_e RB 320: ={ goto bary; } 321: | LP fdeclarator RP 322: ={ $$ = $2; } 323: | name_lp name_list RP 324: ={ 325: if( blevel!=0 ) uerror("function declaration in bad context"); 326: $$ = bdty( UNARY CALL, bdty(NAME,NIL,$1), 0 ); 327: stwart = 0; 328: } 329: | name_lp RP 330: ={ 331: $$ = bdty( UNARY CALL, bdty(NAME,NIL,$1), 0 ); 332: stwart = 0; 333: } 334: ; 335: 336: name_lp: NAME LP 337: ={ 338: /* turn off typedefs for argument names */ 339: stwart = SEENAME; 340: } 341: ; 342: 343: name_list: NAME 344: ={ ftnarg( $1 ); stwart = SEENAME; } 345: | name_list CM NAME 346: ={ ftnarg( $3 ); stwart = SEENAME; } 347: ; 348: /* always preceeded by attributes: thus the $<nodep>0's */ 349: init_dcl_list: init_declarator 350: %prec CM 351: | init_dcl_list CM {$<nodep>$=$<nodep>0;} init_declarator 352: ; 353: /* always preceeded by attributes */ 354: xnfdeclarator: nfdeclarator 355: ={ defid( $1 = tymerge($<nodep>0,$1), curclass); 356: beginit($1->rval); 357: } 358: | error 359: ; 360: /* always preceeded by attributes */ 361: init_declarator: nfdeclarator 362: ={ nidcl( tymerge($<nodep>0,$1) ); } 363: | fdeclarator 364: ={ defid( tymerge($<nodep>0,$1), uclass(curclass) ); 365: } 366: | xnfdeclarator optasgn e 367: %prec CM 368: ={ doinit( $3 ); 369: endinit(); } 370: | xnfdeclarator optasgn LC init_list optcomma RC 371: ={ endinit(); } 372: ; 373: 374: init_list: initializer 375: %prec CM 376: | init_list CM initializer 377: ; 378: initializer: e 379: %prec CM 380: ={ doinit( $1 ); } 381: | ibrace init_list optcomma RC 382: ={ irbrace(); } 383: ; 384: 385: optcomma : /* VOID */ 386: | CM 387: ; 388: 389: optsemi : /* VOID */ 390: | SM 391: ; 392: 393: optasgn : /* VOID */ 394: ={ werror( "old-fashioned initialization: use =" ); } 395: | ASSIGN 396: ; 397: 398: ibrace : LC 399: ={ ilbrace(); } 400: ; 401: 402: /* STATEMENTS */ 403: 404: compoundstmt: begin dcl_stat_list stmt_list RC 405: ={ --blevel; 406: if( blevel == 1 ) blevel = 0; 407: clearst( blevel ); 408: checkst( blevel ); 409: autooff = *--psavbc; 410: regvar = *--psavbc; 411: } 412: ; 413: 414: begin: LC 415: ={ if( blevel == 1 ) dclargs(); 416: ++blevel; 417: if( psavbc > &asavbc[BCSZ-2] ) cerror( "nesting too deep" ); 418: *psavbc++ = regvar; 419: *psavbc++ = autooff; 420: } 421: ; 422: 423: statement: e SM 424: ={ ecomp( $1 ); } 425: | compoundstmt 426: | ifprefix statement 427: ={ deflab($1); 428: reached = 1; 429: } 430: | ifelprefix statement 431: ={ if( $1 != NOLAB ){ 432: deflab( $1 ); 433: reached = 1; 434: } 435: } 436: | whprefix statement 437: ={ branch( contlab ); 438: deflab( brklab ); 439: if( (flostat&FBRK) || !(flostat&FLOOP)) reached = 1; 440: else reached = 0; 441: resetbc(0); 442: } 443: | doprefix statement WHILE LP e RP SM 444: ={ deflab( contlab ); 445: if( flostat & FCONT ) reached = 1; 446: ecomp( buildtree( CBRANCH, buildtree( NOT, $5, NIL ), bcon( $1 ) ) ); 447: deflab( brklab ); 448: reached = 1; 449: resetbc(0); 450: } 451: | forprefix .e RP statement 452: ={ deflab( contlab ); 453: if( flostat&FCONT ) reached = 1; 454: if( $2 ) ecomp( $2 ); 455: branch( $1 ); 456: deflab( brklab ); 457: if( (flostat&FBRK) || !(flostat&FLOOP) ) reached = 1; 458: else reached = 0; 459: resetbc(0); 460: } 461: | switchpart statement 462: ={ if( reached ) branch( brklab ); 463: deflab( $1 ); 464: swend(); 465: deflab(brklab); 466: if( (flostat&FBRK) || !(flostat&FDEF) ) reached = 1; 467: resetbc(FCONT); 468: } 469: | BREAK SM 470: ={ if( brklab == NOLAB ) uerror( "illegal break"); 471: else if(reached) branch( brklab ); 472: flostat |= FBRK; 473: if( brkflag ) goto rch; 474: reached = 0; 475: } 476: | CONTINUE SM 477: ={ if( contlab == NOLAB ) uerror( "illegal continue"); 478: else branch( contlab ); 479: flostat |= FCONT; 480: goto rch; 481: } 482: | RETURN SM 483: ={ retstat |= NRETVAL; 484: branch( retlab ); 485: rch: 486: if( !reached ) werror( "statement not reached"); 487: reached = 0; 488: } 489: | RETURN e SM 490: ={ register NODE *temp; 491: idname = curftn; 492: temp = buildtree( NAME, NIL, NIL ); 493: temp->type = DECREF( temp->type ); 494: temp = buildtree( RETURN, temp, $2 ); 495: /* now, we have the type of the RHS correct */ 496: temp->left->op = FREE; 497: temp->op = FREE; 498: ecomp( buildtree( FORCE, temp->right, NIL ) ); 499: retstat |= RETVAL; 500: branch( retlab ); 501: reached = 0; 502: } 503: | GOTO NAME SM 504: ={ register NODE *q; 505: q = block( FREE, NIL, NIL, INT|ARY, 0, INT ); 506: q->rval = idname = $2; 507: defid( q, ULABEL ); 508: stab[idname].suse = -lineno; 509: branch( stab[idname].offset ); 510: goto rch; 511: } 512: | SM 513: | error SM 514: | error RC 515: | label statement 516: ; 517: label: NAME COLON 518: ={ register NODE *q; 519: q = block( FREE, NIL, NIL, INT|ARY, 0, LABEL ); 520: q->rval = $1; 521: defid( q, LABEL ); 522: reached = 1; 523: } 524: | CASE e COLON 525: ={ addcase($2); 526: reached = 1; 527: } 528: | DEFAULT COLON 529: ={ reached = 1; 530: adddef(); 531: flostat |= FDEF; 532: } 533: ; 534: doprefix: DO 535: ={ savebc(); 536: if( !reached ) werror( "loop not entered at top"); 537: brklab = getlab(); 538: contlab = getlab(); 539: deflab( $$ = getlab() ); 540: reached = 1; 541: } 542: ; 543: ifprefix: IF LP e RP 544: ={ ecomp( buildtree( CBRANCH, $3, bcon( $$=getlab()) ) ) ; 545: reached = 1; 546: } 547: ; 548: ifelprefix: ifprefix statement ELSE 549: ={ if( reached ) branch( $$ = getlab() ); 550: else $$ = NOLAB; 551: deflab( $1 ); 552: reached = 1; 553: } 554: ; 555: 556: whprefix: WHILE LP e RP 557: ={ savebc(); 558: if( !reached ) werror( "loop not entered at top"); 559: if( $3->op == ICON && $3->lval != 0 ) flostat = FLOOP; 560: deflab( contlab = getlab() ); 561: reached = 1; 562: brklab = getlab(); 563: if( flostat == FLOOP ) tfree( $3 ); 564: else ecomp( buildtree( CBRANCH, $3, bcon( brklab) ) ); 565: } 566: ; 567: forprefix: FOR LP .e SM .e SM 568: ={ if( $3 ) ecomp( $3 ); 569: else if( !reached ) werror( "loop not entered at top"); 570: savebc(); 571: contlab = getlab(); 572: brklab = getlab(); 573: deflab( $$ = getlab() ); 574: reached = 1; 575: if( $5 ) ecomp( buildtree( CBRANCH, $5, bcon( brklab) ) ); 576: else flostat |= FLOOP; 577: } 578: ; 579: switchpart: SWITCH LP e RP 580: ={ savebc(); 581: brklab = getlab(); 582: ecomp( buildtree( FORCE, $3, 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->type) || ISARY($2->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: $$->left->op = FREE; 695: $$->op = FREE; 696: $$ = $$->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: $1 = buildtree( UNARY AND, $1, NIL ); 709: } 710: idname = $3; 711: $$ = buildtree( STREF, $1, buildtree( NAME, NIL, NIL ) ); 712: } 713: | NAME 714: ={ idname = $1; 715: /* recognize identifiers in initializations */ 716: if( blevel==0 && stab[idname].stype == UNDEF ) { 717: register NODE *q; 718: werror( "undeclared initializer name %.8s", stab[idname].sname ); 719: q = block( FREE, NIL, NIL, INT, 0, INT ); 720: q->rval = idname; 721: defid( q, EXTERN ); 722: } 723: $$=buildtree(NAME,NIL,NIL); 724: stab[$1].suse = -lineno; 725: } 726: | ICON 727: ={ $$=bcon(0); 728: $$->lval = lastcon; 729: $$->rval = NONAME; 730: if( $1 ) $$->csiz = $$->type = ctype(LONG); 731: } 732: | FCON 733: ={ $$=buildtree(FCON,NIL,NIL); 734: $$->dval = dcon; 735: } 736: | STRING 737: ={ $$ = getstr(); /* get string contents */ } 738: | LP e RP 739: ={ $$=$2; } 740: ; 741: 742: cast_type: type null_decl 743: ={ 744: $$ = tymerge( $1, $2 ); 745: $$->op = NAME; 746: $1->op = FREE; 747: } 748: ; 749: 750: null_decl: /* empty */ 751: ={ $$ = bdty( NAME, NIL, -1 ); } 752: | LP RP 753: ={ $$ = bdty( UNARY CALL, bdty(NAME,NIL,-1),0); } 754: | LP null_decl RP LP RP 755: ={ $$ = bdty( UNARY CALL, $2, 0 ); } 756: | MUL null_decl 757: ={ goto umul; } 758: | null_decl LB RB 759: ={ goto uary; } 760: | null_decl LB con_e RB 761: ={ goto bary; } 762: | LP null_decl RP 763: ={ $$ = $2; } 764: ; 765: 766: funct_idn: NAME LP 767: ={ if( stab[$1].stype == UNDEF ){ 768: register NODE *q; 769: q = block( FREE, NIL, NIL, FTN|INT, 0, INT ); 770: q->rval = $1; 771: defid( q, EXTERN ); 772: } 773: idname = $1; 774: $$=buildtree(NAME,NIL,NIL); 775: stab[idname].suse = -lineno; 776: } 777: | term LP 778: ; 779: %% 780: 781: NODE * 782: mkty( t, d, s ) unsigned t; { 783: return( block( TYPE, NIL, NIL, t, d, s ) ); 784: } 785: 786: NODE * 787: bdty( op, p, v ) NODE *p; { 788: register NODE *q; 789: 790: q = block( op, p, NIL, INT, 0, INT ); 791: 792: switch( op ){ 793: 794: case UNARY MUL: 795: case UNARY CALL: 796: break; 797: 798: case LB: 799: q->right = bcon(v); 800: break; 801: 802: case NAME: 803: q->rval = v; 804: break; 805: 806: default: 807: cerror( "bad bdty" ); 808: } 809: 810: return( q ); 811: } 812: 813: dstash( n ){ /* put n into the dimension table */ 814: if( curdim >= DIMTABSZ-1 ){ 815: cerror( "dimension table overflow"); 816: } 817: dimtab[ curdim++ ] = n; 818: } 819: 820: savebc() { 821: if( psavbc > & asavbc[BCSZ-4 ] ){ 822: cerror( "whiles, fors, etc. too deeply nested"); 823: } 824: *psavbc++ = brklab; 825: *psavbc++ = contlab; 826: *psavbc++ = flostat; 827: *psavbc++ = swx; 828: flostat = 0; 829: } 830: 831: resetbc(mask){ 832: 833: swx = *--psavbc; 834: flostat = *--psavbc | (flostat&mask); 835: contlab = *--psavbc; 836: brklab = *--psavbc; 837: 838: } 839: 840: addcase(p) NODE *p; { /* add case to switch */ 841: 842: p = optim( p ); /* change enum to ints */ 843: if( p->op != ICON ){ 844: uerror( "non-constant case expression"); 845: return; 846: } 847: if( swp == swtab ){ 848: uerror( "case not in switch"); 849: return; 850: } 851: if( swp >= &swtab[SWITSZ] ){ 852: cerror( "switch table overflow"); 853: } 854: swp->sval = p->lval; 855: deflab( swp->slab = getlab() ); 856: ++swp; 857: tfree(p); 858: } 859: 860: adddef(){ /* add default case to switch */ 861: if( swtab[swx].slab >= 0 ){ 862: uerror( "duplicate default in switch"); 863: return; 864: } 865: if( swp == swtab ){ 866: uerror( "default not inside switch"); 867: return; 868: } 869: deflab( swtab[swx].slab = getlab() ); 870: } 871: 872: swstart(){ 873: /* begin a switch block */ 874: if( swp >= &swtab[SWITSZ] ){ 875: cerror( "switch table overflow"); 876: } 877: swx = swp - swtab; 878: swp->slab = -1; 879: ++swp; 880: } 881: 882: swend(){ /* end a switch block */ 883: 884: register struct sw *swbeg, *p, *q, *r, *r1; 885: CONSZ temp; 886: int tempi; 887: 888: swbeg = &swtab[swx+1]; 889: 890: /* sort */ 891: 892: r1 = swbeg; 893: r = swp-1; 894: 895: while( swbeg < r ){ 896: /* bubble largest to end */ 897: for( q=swbeg; q<r; ++q ){ 898: if( q->sval > (q+1)->sval ){ 899: /* swap */ 900: r1 = q+1; 901: temp = q->sval; 902: q->sval = r1->sval; 903: r1->sval = temp; 904: tempi = q->slab; 905: q->slab = r1->slab; 906: r1->slab = tempi; 907: } 908: } 909: r = r1; 910: r1 = swbeg; 911: } 912: 913: /* it is now sorted */ 914: 915: for( p = swbeg+1; p<swp; ++p ){ 916: if( p->sval == (p-1)->sval ){ 917: uerror( "duplicate case in switch, %d", tempi=p->sval ); 918: return; 919: } 920: } 921: 922: genswitch( swbeg-1, swp-swbeg ); 923: swp = swbeg-1; 924: }