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