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