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