xref: /original-bsd/old/pcc/mip/cgram.y (revision 2602db28)
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