|
|
1.1 root 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 *
824: mkty( t, d, s ) unsigned t; {
825: return( block( TYPE, NIL, NIL, t, d, s ) );
826: }
827:
828: NODE *
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:
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:
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:
873: resetbc(mask){
874:
875: swx = *--psavbc;
876: flostat = *--psavbc | (flostat&mask);
877: contlab = *--psavbc;
878: brklab = *--psavbc;
879:
880: }
881:
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:
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:
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:
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.