|
|
1.1 root 1: /* @(#) cgram.y: 1.2 2/9/84 */
2: %{
3: static char SCCSID[] = "@(#) cgram.y: 2.1 83/08/02";
4: %}
5: %term NAME 2
6: %term STRING 3
7: %term ICON 4
8: %term FCON 5
9: %term PLUS 6
10: %term MINUS 8
11: %term MUL 11
12: %term AND 14
13: %term OR 17
14: %term ER 19
15: %term QUEST 21
16: %term COLON 22
17: %term ANDAND 23
18: %term OROR 24
19:
20: /* special interfaces for yacc alone */
21: /* These serve as abbreviations of 2 or more ops:
22: ASOP =, = ops
23: RELOP LE,LT,GE,GT
24: EQUOP EQ,NE
25: DIVOP DIV,MOD
26: SHIFTOP LS,RS
27: ICOP ICR,DECR
28: UNOP NOT,COMPL
29: STROP DOT,STREF
30:
31: */
32: %term ASOP 25
33: %term RELOP 26
34: %term EQUOP 27
35: %term DIVOP 28
36: %term SHIFTOP 29
37: %term INCOP 30
38: %term UNOP 31
39: %term STROP 32
40:
41: /* reserved words, etc */
42: %term TYPE 33
43: %term CLASS 34
44: %term STRUCT 35
45: %term RETURN 36
46: %term GOTO 37
47: %term IF 38
48: %term ELSE 39
49: %term SWITCH 40
50: %term BREAK 41
51: %term CONTINUE 42
52: %term WHILE 43
53: %term DO 44
54: %term FOR 45
55: %term DEFAULT 46
56: %term CASE 47
57: %term SIZEOF 48
58: %term ENUM 49
59:
60: /* little symbols, etc. */
61: /* namely,
62:
63: LP (
64: RP )
65:
66: LC {
67: RC }
68:
69: LB [
70: RB ]
71:
72: CM ,
73: SM ;
74:
75: */
76:
77: %term LP 50
78: %term RP 51
79: %term LC 52
80: %term RC 53
81: %term LB 54
82: %term RB 55
83: %term CM 56
84: %term SM 57
85: %term ASSIGN 58
86: %term ASM 59
87:
88: /* at last count, there were 7 shift/reduce, 1 reduce/reduce conflicts
89: /* these involved:
90: if/else
91: recognizing functions in various contexts, including declarations
92: error recovery
93: */
94:
95: %left CM
96: %right ASOP ASSIGN
97: %right QUEST COLON
98: %left OROR
99: %left ANDAND
100: %left OR
101: %left ER
102: %left AND
103: %left EQUOP
104: %left RELOP
105: %left SHIFTOP
106: %left PLUS MINUS
107: %left MUL DIVOP
108: %right UNOP
109: %right INCOP SIZEOF
110: %left LB LP STROP
111: %{
112: # include "mfile1.h"
113: %}
114:
115: /* define types */
116: %start ext_def_list
117:
118: %type <intval> con_e ifelprefix ifprefix doprefix switchpart
119: enum_head str_head name_lp
120: %type <nodep> e .e term attributes oattributes type enum_dcl struct_dcl
121: cast_type null_decl funct_idn declarator fdeclarator
122: nfdeclarator elist
123:
124: %token <intval> CLASS NAME STRUCT RELOP CM DIVOP PLUS MINUS SHIFTOP MUL AND OR
125: ER ANDAND OROR ASSIGN STROP INCOP UNOP ICON
126: %token <nodep> TYPE
127:
128: %%
129:
130: %{
131: extern int wloop_level; /* specifies while loop code generation */
132: extern int floop_level; /* specifies for loop code generation */
133: static int fake = 0;
134: static char fakename[NCHNAM+1];
135: %}
136:
137: ext_def_list: ext_def_list external_def
138: | /* EMPTY */
139: {
140: #ifndef LINT
141: beg_file();
142: #endif
143: ftnend();
144: }
145: ;
146: external_def: data_def
147: { curclass = SNULL; blevel = 0; }
148: | error
149: { curclass = SNULL; blevel = 0; }
150: | ASM SM
151: { asmout(); curclass = SNULL; blevel = 0; }
152: ;
153: data_def: oattributes SM
154: { $1->in.op = FREE; }
155: | oattributes init_dcl_list SM
156: { $1->in.op = FREE; }
157: | oattributes fdeclarator
158: { defid( tymerge($1,$2),
159: curclass==STATIC?STATIC:EXTDEF ); }
160: function_body
161: {
162: if( blevel ) cerror( "function level error" );
163: if( reached ) retstat |= NRETVAL;
164: $1->in.op = FREE;
165: ftnend();
166: }
167: ;
168:
169: function_body: arg_dcl_list compoundstmt
170: { regvar = 0; } /* clear out arguments */
171: ;
172:
173: arg_dcl_list: arg_dcl_list attributes declarator_list SM
174: { curclass = SNULL; $2->in.op = FREE; }
175: | arg_dcl_list attributes SM
176: /* to permit structs in decl. lists */
177: { curclass = SNULL; $2->in.op = FREE; }
178: | /* EMPTY */ { blevel = 1; }
179: ;
180:
181: stmt_list: stmt_list statement
182: | /* EMPTY */
183: { bccode();
184: locctr(PROG);
185: }
186: ;
187:
188: dcl_stat_list : dcl_stat_list attributes SM
189: { $2->in.op = FREE; }
190: | dcl_stat_list attributes init_dcl_list SM
191: { $2->in.op = FREE; }
192: | /* EMPTY */
193: ;
194:
195: oattributes: attributes
196: | /* empty */
197: { $$ = mkty(INT,0,INT); curclass = SNULL; }
198: ;
199: attributes: class type
200: { $$ = $2; }
201: | type class
202: | class
203: { $$ = mkty(INT,0,INT); }
204: | type
205: { curclass = SNULL ; }
206: | type class type
207: { $1->in.type = types( $1->in.type, $3->in.type,
208: UNDEF );
209: $3->in.op = FREE;
210: }
211: ;
212:
213: class: CLASS
214: { curclass = $1; }
215: ;
216:
217: type: TYPE
218: | TYPE TYPE
219: { $1->in.type = types( $1->in.type, $2->in.type, UNDEF );
220: $2->in.op = FREE;
221: }
222: | TYPE TYPE TYPE
223: { $1->in.type = types( $1->in.type, $2->in.type, $3->in.type );
224: $2->in.op = $3->in.op = FREE;
225: }
226: | struct_dcl
227: | enum_dcl
228: ;
229:
230: enum_dcl: enum_head LC moe_list optcomma RC
231: { $$ = dclstruct($1); }
232: | ENUM NAME
233: { $$ = rstruct($2,0); stwart = instruct; }
234: ;
235:
236: enum_head: ENUM
237: { $$ = bstruct(-1,0); stwart = SEENAME; }
238: | ENUM NAME
239: { $$ = bstruct($2,0); stwart = SEENAME; }
240: ;
241:
242: moe_list: moe
243: | moe_list CM moe
244: ;
245:
246: moe: NAME
247: { moedef( $1 ); }
248: | NAME ASSIGN con_e
249: { strucoff = $3; moedef( $1 ); }
250: ;
251:
252: struct_dcl: str_head LC type_dcl_list optsemi RC
253: { $$ = dclstruct($1); }
254: | STRUCT NAME
255: { $$ = rstruct($2,$1); }
256: ;
257:
258: str_head: STRUCT
259: { $$ = bstruct(-1,$1); stwart=0; }
260: | STRUCT NAME
261: { $$ = bstruct($2,$1); stwart=0; }
262: ;
263:
264: type_dcl_list: type_declaration
265: | type_dcl_list SM type_declaration
266: ;
267:
268: type_declaration: type declarator_list
269: { curclass = SNULL; stwart=0; $1->in.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,
277: lookup( fakename, SMOS ))), curclass );
278: werror("union member must be named");
279: }
280: stwart = 0;
281: $1->in.op = FREE;
282: }
283: ;
284:
285:
286: declarator_list: declarator
287: { defid( tymerge($<nodep>0,$1), curclass);
288: stwart = instruct; }
289: | declarator_list CM {$<nodep>$=$<nodep>0;} declarator
290: { defid( tymerge($<nodep>0,$4), curclass);
291: stwart = instruct; }
292: ;
293: declarator: nfdeclarator
294: | nfdeclarator COLON con_e
295: %prec CM
296: { if( !(instruct&INSTRUCT) )
297: uerror( "field outside of structure" );
298: if( $3<0 || $3 >= FIELD ){
299: uerror( "illegal field size" );
300: $3 = 1;
301: }
302: defid( tymerge($<nodep>0,$1), FIELD|$3 );
303: $$ = NIL;
304: }
305: | COLON con_e
306: %prec CM
307: { if( !(instruct&INSTRUCT) )
308: uerror( "field outside of structure" );
309: /* alignment or hole */
310: falloc( stab, $2, -1, $<nodep>0 );
311: $$ = NIL;
312: }
313: | error
314: { $$ = NIL; }
315: ;
316:
317: /* int (a)(); is not a function --- sorry! */
318: nfdeclarator: MUL nfdeclarator
319: { umul:
320: $$ = bdty( UNARY MUL, $2, 0 ); }
321: | nfdeclarator LP RP
322: { uftn:
323: $$ = bdty( UNARY CALL, $1, 0 ); }
324: | nfdeclarator LB RB
325: { uary:
326: $$ = bdty( LB, $1, 0 ); }
327: | nfdeclarator LB con_e RB
328: { bary:
329: if( (int)$3 <= 0 )
330: werror( "zero or negative subscript" );
331: $$ = bdty( LB, $1, $3 ); }
332: | NAME
333: { $$ = bdty( NAME, NIL, $1 ); }
334: | LP nfdeclarator RP
335: { $$=$2; }
336: ;
337: fdeclarator: MUL fdeclarator
338: { goto umul; }
339: | fdeclarator LP RP
340: { goto uftn; }
341: | fdeclarator LB RB
342: { goto uary; }
343: | fdeclarator LB con_e RB
344: { goto bary; }
345: | LP fdeclarator RP
346: { $$ = $2; }
347: | name_lp
348: { if (paramno)
349: uerror("arg list in declaration"); }
350: name_list RP
351: {
352: if( blevel!=0 )
353: uerror(
354: "function declaration in bad context");
355: $$ = bdty( UNARY CALL, bdty(NAME,NIL,$1), 0 );
356: stwart = 0;
357: }
358: | name_lp
359: { if (paramno)
360: uerror("arg list in declaration"); }
361: RP
362: {
363: $$ = bdty( UNARY CALL, bdty(NAME,NIL,$1), 0 );
364: stwart = 0;
365: }
366: ;
367:
368: name_lp: NAME LP
369: {
370: /* turn off typedefs for argument names */
371: stwart = SEENAME;
372: if( stab[$1].sclass == SNULL )
373: stab[$1].stype = FTN;
374: }
375: ;
376:
377: name_list: NAME
378: { ftnarg( $1 ); stwart = SEENAME; }
379: | name_list CM NAME
380: { ftnarg( $3 ); stwart = SEENAME; }
381: | error
382: ;
383: /* always preceeded by attributes: thus the $<nodep>0's */
384: init_dcl_list: init_declarator
385: %prec CM
386: | init_dcl_list CM {$<nodep>$=$<nodep>0;} init_declarator
387: ;
388: /* always preceeded by attributes */
389: xnfdeclarator: nfdeclarator
390: { defid( $1 = tymerge($<nodep>0,$1), curclass);
391: beginit($1->tn.rval);
392: }
393: | error
394: ;
395: /* always preceeded by attributes */
396: init_declarator: nfdeclarator
397: { nidcl( tymerge($<nodep>0,$1) ); }
398: | fdeclarator
399: { defid( tymerge($<nodep>0,$1), uclass(curclass) );
400: }
401: | xnfdeclarator ASSIGN e
402: %prec CM
403: { doinit( $3 );
404: endinit(); }
405: | xnfdeclarator ASSIGN LC init_list optcomma RC
406: { endinit(); }
407: | error
408: ;
409:
410: init_list: initializer
411: %prec CM
412: | init_list CM initializer
413: ;
414: initializer: e
415: %prec CM
416: { doinit( $1 ); }
417: | ibrace init_list optcomma RC
418: { irbrace(); }
419: ;
420:
421: optcomma : /* empty */
422: | CM
423: ;
424:
425: optsemi : /* empty */
426: | SM
427: ;
428:
429: ibrace : LC
430: { ilbrace(); }
431: ;
432:
433: /* STATEMENTS */
434:
435: compoundstmt: begin dcl_stat_list stmt_list RC
436: {
437: clearst(blevel);
438: if (--blevel == 1)
439: {
440: clearst(blevel);
441: blevel = 0;
442: }
443: checkst(blevel);
444: autooff = *--psavbc;
445: regvar = *--psavbc;
446: }
447: ;
448:
449: begin: LC
450: { if( blevel == 1 ) dclargs();
451: ++blevel;
452: if( psavbc > &asavbc[BCSZ-2] )
453: cerror( "nesting too deep" );
454: *psavbc++ = regvar;
455: *psavbc++ = autooff;
456: }
457: ;
458:
459: statement: e SM
460: { ecomp( $1 ); }
461: | ASM SM
462: { asmout(); }
463: | compoundstmt
464: | ifprefix statement
465: { deflab($1);
466: reached = 1;
467: #ifdef M32B
468: brdepth--;
469: #endif
470: }
471: | ifelprefix statement
472: { if( $1 != NOLAB ){
473: deflab( $1 );
474: reached = 1;
475: }
476: #ifdef M32B
477: brdepth--;
478: #endif
479: }
480: | WHILE
481: {
482: #ifdef M32B
483: whdepth++;
484: #endif
485: }
486: LP e RP
487: {
488: savebc();
489: if (!reached)
490: werror("loop not entered at top");
491: reached = 1;
492: brklab = getlab();
493: contlab = getlab();
494: switch (wloop_level)
495: {
496: default:
497: cerror("bad while loop code gen value");
498: /*NOTREACHED*/
499: case LL_TOP: /* test at loop top */
500: deflab(contlab);
501: if ($4->in.op == ICON &&
502: $4->tn.lval != 0)
503: {
504: flostat = FLOOP;
505: tfree($4);
506: }
507: else
508: ecomp(buildtree(CBRANCH, $4,
509: bcon(brklab)));
510: break;
511: case LL_BOT: /* test at loop bottom */
512: if ($4->in.op == ICON &&
513: $4->tn.lval != 0)
514: {
515: flostat = FLOOP;
516: tfree($4);
517: deflab(contlab);
518: }
519: else
520: {
521: branch(contlab);
522: deflab($<intval>$ = getlab());
523: }
524: break;
525: case LL_DUP: /* dup. test at top & bottom */
526: if ($4->in.op == ICON &&
527: $4->tn.lval != 0)
528: {
529: flostat = FLOOP;
530: tfree($4);
531: deflab($<intval>$ = contlab);
532: }
533: else
534: {
535: #ifndef LINT
536: /* don't rotate loops for lint */
537: register NODE *sav;
538: extern NODE *treecpy();
539:
540: sav = treecpy($4);
541: ecomp(buildtree(CBRANCH,$4,
542: bcon(brklab)));
543: $4 = sav;
544: #endif
545: deflab($<intval>$ = getlab());
546: }
547: break;
548: }
549: }
550: statement
551: {
552: switch (wloop_level)
553: {
554: default:
555: cerror("bad while loop code gen. value");
556: /*NOTREACHED*/
557: case LL_TOP: /* test at loop top */
558: branch(contlab);
559: break;
560: case LL_BOT: /* test at loop bottom */
561: if (flostat & FLOOP)
562: branch(contlab);
563: else
564: {
565: reached = 1;
566: deflab(contlab);
567: ecomp(buildtree(CBRANCH,
568: buildtree(NOT, $4, NIL),
569: bcon($<intval>6)));
570: }
571: break;
572: case LL_DUP: /* dup. test at top & bottom */
573: if (flostat & FLOOP)
574: branch(contlab);
575: else
576: {
577: if (flostat & FCONT)
578: {
579: reached = 1;
580: deflab(contlab);
581: }
582: ecomp(buildtree(CBRANCH,
583: buildtree(NOT, $4, NIL),
584: bcon($<intval>6)));
585: }
586: break;
587: }
588: if ((flostat & FBRK) || !(flostat & FLOOP))
589: reached = 1;
590: else
591: reached = 0;
592: deflab(brklab);
593: resetbc(0);
594: #ifdef M32B
595: whdepth--;
596: #endif
597: }
598: | doprefix statement WHILE LP e RP SM
599: { deflab( contlab );
600: if( flostat & FCONT ) reached = 1;
601: ecomp( buildtree( CBRANCH,
602: buildtree( NOT, $5, NIL ), bcon( $1 ) ) );
603: deflab( brklab );
604: reached = 1;
605: resetbc(0);
606: #ifdef M32B
607: whdepth--;
608: #endif
609: }
610: | FOR LP .e SM
611: {
612: #ifdef M32B
613: fordepth++;
614: #endif
615: }
616: .e SM
617: {
618: if ($3)
619: ecomp($3);
620: else if (!reached)
621: werror("loop not entered at top");
622: savebc();
623: contlab = getlab();
624: brklab = getlab();
625: reached = 1;
626: switch (floop_level)
627: {
628: default:
629: cerror("bad for loop code gen. value");
630: /*NOTREACHED*/
631: case LL_TOP: /* test at loop top */
632: deflab($<intval>$ = getlab());
633: if (!$6)
634: flostat |= FLOOP;
635: else if ($6->in.op == ICON &&
636: $6->tn.lval != 0)
637: {
638: flostat |= FLOOP;
639: tfree($6);
640: $6 = (NODE *)0;
641: }
642: else
643: ecomp(buildtree(CBRANCH, $6,
644: bcon(brklab)));
645: break;
646: case LL_BOT: /* test at loop bottom */
647: if (!$6)
648: flostat |= FLOOP;
649: else if ($6->in.op == ICON &&
650: $6->tn.lval != 0)
651: {
652: flostat |= FLOOP;
653: tfree($6);
654: $6 = (NODE *)0;
655: }
656: else
657: branch($<intval>1 = getlab());
658: deflab($<intval>$ = getlab());
659: break;
660: case LL_DUP: /* dup. test at top & bottom */
661: if (!$6)
662: flostat |= FLOOP;
663: else if ($6->in.op == ICON &&
664: $6->tn.lval != 0)
665: {
666: flostat |= FLOOP;
667: tfree($6);
668: $6 = (NODE *)0;
669: }
670: else
671: {
672: #ifndef LINT
673: /* don't rotate loops for lint */
674: register NODE *sav;
675: extern NODE *treecpy();
676:
677: sav = treecpy($6);
678: ecomp(buildtree(CBRANCH, $6,
679: bcon(brklab)));
680: $6 = sav;
681: #endif
682: }
683: deflab($<intval>$ = getlab());
684: break;
685: }
686: }
687: .e RP statement
688: {
689: if (flostat & FCONT)
690: {
691: deflab(contlab);
692: reached = 1;
693: }
694: if ($9)
695: ecomp($9);
696: switch (floop_level)
697: {
698: default:
699: cerror("bad for loop code gen. value");
700: /*NOTREACHED*/
701: case LL_TOP: /* test at loop top */
702: branch($<intval>8);
703: break;
704: case LL_BOT: /* test at loop bottom */
705: if ($6)
706: deflab($<intval>1);
707: /*FALLTHROUGH*/
708: case LL_DUP: /* dup. test at top & bottom */
709: if ($6)
710: {
711: ecomp(buildtree(CBRANCH,
712: buildtree(NOT, $6, NIL),
713: bcon($<intval>8)));
714: }
715: else
716: branch($<intval>8);
717: break;
718: }
719: deflab(brklab);
720: if ((flostat & FBRK) || !(flostat & FLOOP))
721: reached = 1;
722: else
723: reached = 0;
724: resetbc(0);
725: #ifdef M32B
726: fordepth--;
727: #endif
728: }
729: | switchpart statement
730: { if( reached ) branch( brklab );
731: deflab( $1 );
732: swend();
733: deflab(brklab);
734: if( (flostat&FBRK) || !(flostat&FDEF) ) reached=1;
735: resetbc(FCONT);
736: #ifdef M32B
737: brdepth--;
738: #endif
739: }
740: | BREAK SM
741: { if( brklab == NOLAB ) uerror( "illegal break");
742: else if(reached) branch( brklab );
743: flostat |= FBRK;
744: if( brkflag ) goto rch;
745: reached = 0;
746: }
747: | CONTINUE SM
748: { if( contlab == NOLAB ) uerror( "illegal continue");
749: else branch( contlab );
750: flostat |= FCONT;
751: goto rch;
752: }
753: | RETURN SM
754: { retstat |= NRETVAL;
755: branch( retlab );
756: rch:
757: if( !reached ) werror( "statement not reached");
758: reached = 0;
759: }
760: | RETURN e SM
761: { register NODE *temp;
762: TWORD indtype();
763: idname = curftn;
764: temp = buildtree( NAME, NIL, NIL );
765: temp->in.type = DECREF(temp->in.type);
766: if(temp->in.type == (FTN|VOID))
767: uerror(
768: "void function %s cannot return value",
769: stab[idname].sname);
770: temp->tn.op = RNODE;
771: $2 = makety( $2, temp->fn.type,
772: temp->fn.cdim, temp->fn.csiz );
773: temp->in.type = indtype( temp->in.type );
774: temp = buildtree( ASSIGN, temp, $2 );
775: ecomp( temp );
776: retstat |= RETVAL;
777: branch( retlab );
778: reached = 0;
779: }
780: | GOTO NAME SM
781: { register NODE *q;
782: q = block( FREE, NIL, NIL, INT|ARY, 0, INT );
783: q->tn.rval = idname = $2;
784: defid( q, ULABEL );
785: stab[idname].suse = -lineno;
786: branch( stab[idname].offset );
787: goto rch;
788: }
789: | SM
790: | error SM
791: | error RC
792: | label statement
793: ;
794: label: NAME COLON
795: { register NODE *q;
796: q = block( FREE, NIL, NIL, INT|ARY, 0, LABEL );
797: q->tn.rval = $1;
798: defid( q, LABEL );
799: reached = 1;
800: }
801: | CASE e COLON
802: { addcase($2);
803: reached = 1;
804: }
805: | DEFAULT COLON
806: { reached = 1;
807: adddef();
808: flostat |= FDEF;
809: }
810: ;
811: doprefix: DO
812: { savebc();
813: if( !reached ) werror( "loop not entered at top");
814: brklab = getlab();
815: contlab = getlab();
816: deflab( $$ = getlab() );
817: reached = 1;
818: #ifdef M32B
819: whdepth++;
820: #endif
821: }
822: ;
823: ifprefix: IF LP e RP
824: { ecomp( buildtree( CBRANCH, $3, bcon( $$=getlab()) ) ) ;
825: reached = 1;
826: #ifdef M32B
827: brdepth++;
828: #endif
829: }
830: ;
831: ifelprefix: ifprefix statement ELSE
832: { if( reached ) branch( $$ = getlab() );
833: else $$ = NOLAB;
834: deflab( $1 );
835: reached = 1;
836: }
837: ;
838:
839: switchpart: SWITCH LP e RP
840: { register NODE *temp;
841: savebc();
842: temp = block( SNODE, NIL, NIL, INT, 0, INT );
843: temp = buildtree( ASSIGN, temp, $3 );
844: #ifdef M32B
845: temp = setswreg( temp );
846: #endif
847: brklab = getlab();
848: ecomp( temp );
849: branch( $$ = getlab() );
850: swstart();
851: reached = 0;
852: #ifdef M32B
853: brdepth++;
854: #endif
855: }
856: ;
857: /* EXPRESSIONS */
858: con_e: { $<intval>$=instruct; stwart=instruct=0; } e
859: %prec CM
860: { $$ = icons( $2 ); instruct=$<intval>1; }
861: ;
862: .e: e
863: |
864: { $$=0; }
865: ;
866: elist: e
867: %prec CM
868: | elist CM e
869: { goto bop; }
870: ;
871:
872: e: e RELOP e
873: {
874: preconf:
875: if( yychar==RELOP || yychar==EQUOP || yychar==AND
876: || yychar==OR || yychar==ER ){
877: precplaint:
878: if( hflag ) werror(
879: "precedence confusion possible: parenthesize!"
880: );
881: }
882: bop:
883: $$ = buildtree( $2, $1, $3 );
884: }
885: | e CM e
886: { $2 = COMOP;
887: goto bop;
888: }
889: | e DIVOP e
890: { goto bop; }
891: | e PLUS e
892: { if(yychar==SHIFTOP) goto precplaint; else goto bop; }
893: | e MINUS e
894: { if(yychar==SHIFTOP ) goto precplaint; else goto bop; }
895: | e SHIFTOP e
896: { if(yychar==PLUS||yychar==MINUS) goto precplaint; else goto bop; }
897: | e MUL e
898: { goto bop; }
899: | e EQUOP e
900: { goto preconf; }
901: | e AND e
902: { if( yychar==RELOP||yychar==EQUOP ) goto preconf; else goto bop; }
903: | e OR e
904: { if(yychar==RELOP||yychar==EQUOP) goto preconf; else goto bop; }
905: | e ER e
906: { if(yychar==RELOP||yychar==EQUOP) goto preconf; else goto bop; }
907: | e ANDAND e
908: { goto bop; }
909: | e OROR e
910: { goto bop; }
911: | e MUL ASSIGN e
912: { abop:
913: $$ = buildtree( ASG $2, $1, $4 );
914: }
915: | e DIVOP ASSIGN e
916: { goto abop; }
917: | e PLUS ASSIGN e
918: { goto abop; }
919: | e MINUS ASSIGN e
920: { goto abop; }
921: | e SHIFTOP ASSIGN e
922: { goto abop; }
923: | e AND ASSIGN e
924: { goto abop; }
925: | e OR ASSIGN e
926: { goto abop; }
927: | e ER ASSIGN e
928: { goto abop; }
929: | e QUEST e COLON e
930: { $$=buildtree(QUEST, $1, buildtree( COLON, $3, $5 ) );
931: }
932: | e ASOP e
933: { werror( "old-fashioned assignment operator" );
934: goto bop; }
935: | e ASSIGN e
936: { goto bop; }
937: | term
938: ;
939:
940: term: term INCOP
941: { $$ = buildtree( $2, $1, bcon(1) ); }
942: | MUL term
943: { ubop:
944: $$ = buildtree( UNARY $1, $2, NIL );
945: }
946: | AND term
947: {
948: #ifdef M32B
949: myand($2);
950: #endif
951: if( ISFTN($2->in.type) || ISARY($2->in.type) ){
952: werror( "& before array or function: ignored" );
953: $$ = $2;
954: }
955: else goto ubop;
956: }
957: | MINUS term
958: { goto ubop; }
959: | UNOP term
960: {
961: $$ = buildtree( $1, $2, NIL );
962: }
963: | INCOP term
964: { $$ = buildtree( $1==INCR ? ASG PLUS : ASG MINUS,
965: $2,
966: bcon(1) );
967: }
968: | SIZEOF term
969: { $$ = doszof( $2 ); }
970: | LP cast_type RP term %prec INCOP
971: { $$ = buildtree( CAST, $2, $4 );
972: $$->in.left->in.op = FREE;
973: $$->in.op = FREE;
974: $$ = $$->in.right;
975: }
976: | SIZEOF LP cast_type RP %prec SIZEOF
977: { $$ = doszof( $3 ); }
978: | term LB e RB
979: { $$ = buildtree( LB, $1, $3 ); }
980: | term LB e COLON e RB
981: { $$ = xicolon( $1, $3, $5 ); }
982: | funct_idn RP
983: { $$=buildtree(UNARY CALL,$1,NIL); }
984: | funct_idn elist RP
985: { $$=buildtree(CALL,$1,$2); }
986: | term STROP NAME
987: { if( $2 == DOT ){
988: if( notlval( $1 ) )uerror(
989: "structure reference must be addressable"
990: );
991: $1 = buildtree( UNARY AND, $1, NIL );
992: }
993: idname = $3;
994: $$ = buildtree( STREF, $1,
995: buildtree( NAME, NIL, NIL ) );
996: }
997: | NAME
998: { idname = $1;
999: /* recognize identifiers in initializations */
1000: if( blevel==0 && stab[idname].stype == UNDEF ) {
1001: register NODE *q;
1002: werror( "undeclared initializer name %s",
1003: stab[idname].sname );
1004: q = block( FREE, NIL, NIL, INT, 0, INT );
1005: q->tn.rval = idname;
1006: defid( q, EXTERN );
1007: }
1008: $$=buildtree(NAME,NIL,NIL);
1009: stab[$1].suse = -lineno;
1010: }
1011: | ICON
1012: { $$=bcon(0);
1013: $$->tn.lval = lastcon;
1014: $$->tn.rval = NONAME;
1015: if( $1 ) $$->fn.csiz = $$->in.type = ctype(LONG);
1016: }
1017: | FCON
1018: { $$=buildtree(FCON,NIL,NIL);
1019: $$->fpn.dval = dcon;
1020: }
1021: | STRING
1022: { $$ = getstr(); /* get string contents */ }
1023: | LP e RP
1024: { $$=$2; }
1025: ;
1026:
1027: cast_type: type null_decl
1028: {
1029: $$ = tymerge( $1, $2 );
1030: $$->in.op = NAME;
1031: $1->in.op = FREE;
1032: }
1033: ;
1034:
1035: null_decl: /* EMPTY */
1036: { $$ = bdty( NAME, NIL, -1 ); }
1037: | LP RP
1038: { $$ = bdty( UNARY CALL, bdty(NAME,NIL,-1),0); }
1039: | LP null_decl RP LP RP
1040: { $$ = bdty( UNARY CALL, $2, 0 ); }
1041: | MUL null_decl
1042: { goto umul; }
1043: | null_decl LB RB
1044: { goto uary; }
1045: | null_decl LB con_e RB
1046: { goto bary; }
1047: | LP null_decl RP
1048: { $$ = $2; }
1049: ;
1050:
1051: funct_idn: NAME LP
1052: { if( stab[$1].stype == UNDEF ){
1053: register NODE *q;
1054: q = block( FREE, NIL, NIL, FTN|INT, 0, INT );
1055: q->tn.rval = $1;
1056: defid( q, EXTERN );
1057: }
1058: idname = $1;
1059: $$=buildtree(NAME,NIL,NIL);
1060: stab[idname].suse = -lineno;
1061: }
1062: | term LP
1063: ;
1064: %%
1065:
1066: NODE *
1067: mkty( t, d, s ) unsigned t; {
1068: return( block( TYPE, NIL, NIL, t, d, s ) );
1069: }
1070:
1071: NODE *
1072: bdty( op, p, v ) NODE *p; {
1073: register NODE *q;
1074:
1075: q = block( op, p, NIL, INT, 0, INT );
1076:
1077: switch( op ){
1078:
1079: case UNARY MUL:
1080: case UNARY CALL:
1081: break;
1082:
1083: case LB:
1084: q->in.right = bcon(v);
1085: break;
1086:
1087: case NAME:
1088: q->tn.rval = v;
1089: break;
1090:
1091: default:
1092: cerror( "bad bdty" );
1093: }
1094:
1095: return( q );
1096: }
1097:
1098: dstash( n ){ /* put n into the dimension table */
1099: if( curdim >= DIMTABSZ-1 ){
1100: cerror( "dimension table overflow");
1101: }
1102: dimtab[ curdim++ ] = n;
1103: }
1104:
1105: savebc() {
1106: if( psavbc > & asavbc[BCSZ-4 ] ){
1107: cerror( "whiles, fors, etc. too deeply nested");
1108: }
1109: *psavbc++ = brklab;
1110: *psavbc++ = contlab;
1111: *psavbc++ = flostat;
1112: *psavbc++ = swx;
1113: #ifdef M32B
1114: *psavbc++ = swregno;
1115: #endif
1116: flostat = 0;
1117: }
1118:
1119: resetbc(mask){
1120:
1121: #ifdef M32B
1122: swregno = *--psavbc;
1123: #endif
1124: swx = *--psavbc;
1125: flostat = *--psavbc | (flostat&mask);
1126: contlab = *--psavbc;
1127: brklab = *--psavbc;
1128:
1129: }
1130:
1131: addcase(p) NODE *p; { /* add case to switch */
1132:
1133: p = optim( p ); /* change enum to ints */
1134: if( p->in.op != ICON ){
1135: uerror( "non-constant case expression");
1136: return;
1137: }
1138: if( swp == swtab ){
1139: uerror( "case not in switch");
1140: return;
1141: }
1142: if( swp >= &swtab[SWITSZ] ){
1143: cerror( "switch table overflow");
1144: }
1145: swp->sval = p->tn.lval;
1146: deflab( swp->slab = getlab() );
1147: ++swp;
1148: tfree(p);
1149: }
1150:
1151: adddef(){ /* add default case to switch */
1152: if( swtab[swx].slab >= 0 ){
1153: uerror( "duplicate default in switch");
1154: return;
1155: }
1156: if( swp == swtab ){
1157: uerror( "default not inside switch");
1158: return;
1159: }
1160: deflab( swtab[swx].slab = getlab() );
1161: }
1162:
1163: swstart(){
1164: /* begin a switch block */
1165: if( swp >= &swtab[SWITSZ] ){
1166: cerror( "switch table overflow");
1167: }
1168: swx = swp - swtab;
1169: swp->slab = -1;
1170: ++swp;
1171: }
1172:
1173: swend(){ /* end a switch block */
1174:
1175: register struct sw *swbeg, *p, *q, *r, *r1;
1176: CONSZ temp;
1177: int tempi;
1178:
1179: swbeg = &swtab[swx+1];
1180:
1181: /* sort */
1182:
1183: r1 = swbeg;
1184: r = swp-1;
1185:
1186: while( swbeg < r ){
1187: /* bubble largest to end */
1188: for( q=swbeg; q<r; ++q ){
1189: if( q->sval > (q+1)->sval ){
1190: /* swap */
1191: r1 = q+1;
1192: temp = q->sval;
1193: q->sval = r1->sval;
1194: r1->sval = temp;
1195: tempi = q->slab;
1196: q->slab = r1->slab;
1197: r1->slab = tempi;
1198: }
1199: }
1200: r = r1;
1201: r1 = swbeg;
1202: }
1203:
1204: /* it is now sorted */
1205:
1206: for( p = swbeg+1; p<swp; ++p ){
1207: if( p->sval == (p-1)->sval ){
1208: uerror( "duplicate case in switch, %d", tempi=p->sval );
1209: return;
1210: }
1211: }
1212:
1213: reached = 1;
1214: genswitch( swbeg-1, (int)(swp-swbeg) );
1215: swp = swbeg-1;
1216: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.