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