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