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