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

Defined functions

_addcase defined in line 840; used 1 times
_adddef defined in line 860; used 1 times
_bdty defined in line 786; used 14 times
_dstash defined in line 813; used 20 times
_mkty defined in line 779; used 8 times
_resetbc defined in line 831; used 4 times
_savebc defined in line 820; used 4 times
_swend defined in line 882; used 1 times
_swstart defined in line 872; used 1 times
Last modified: 1982-08-28
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1037
Valid CSS Valid XHTML 1.0 Strict