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