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