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

Defined functions

_addcase defined in line 849; used 1 times
_adddef defined in line 869; used 1 times
_bdty defined in line 795; used 16 times
_dstash defined in line 822; used 12 times
_mkty defined in line 788; used 7 times
_resetbc defined in line 840; used 4 times
_savebc defined in line 829; used 4 times
_swend defined in line 891; used 1 times
_swstart defined in line 881; used 1 times
Last modified: 1985-08-25
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2067
Valid CSS Valid XHTML 1.0 Strict