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