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