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