xref: /original-bsd/old/pcc/mip/cgram.y (revision 627c8e0e)
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 *
mkty(t,d,s)824 mkty( t, d, s ) unsigned t; {
825 	return( block( TYPE, NIL, NIL, t, d, s ) );
826 	}
827 
828 NODE *
bdty(op,p,v)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 
dstash(n)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 
savebc()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 
resetbc(mask)873 resetbc(mask){
874 
875 	swx = *--psavbc;
876 	flostat = *--psavbc | (flostat&mask);
877 	contlab = *--psavbc;
878 	brklab = *--psavbc;
879 
880 	}
881 
addcase(p)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 
adddef()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 
swstart()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 
swend()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