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