xref: /csrg-svn/usr.bin/pascal/src/case.c (revision 746)
1*746Speter /* Copyright (c) 1979 Regents of the University of California */
2*746Speter 
3*746Speter static	char sccsid[] = "@(#)case.c 1.1 08/27/80";
4*746Speter 
5*746Speter #include "whoami.h"
6*746Speter #include "0.h"
7*746Speter #include "tree.h"
8*746Speter #include "opcode.h"
9*746Speter 
10*746Speter /*
11*746Speter  * The structure used to
12*746Speter  * hold information about
13*746Speter  * each case label.
14*746Speter  */
15*746Speter struct ct {
16*746Speter 	long	clong;
17*746Speter 	int	cline;
18*746Speter };
19*746Speter 
20*746Speter #ifdef OBJ
21*746Speter /*
22*746Speter  * Caseop generates the
23*746Speter  * pascal case statement code
24*746Speter  */
25*746Speter caseop(r)
26*746Speter 	int *r;
27*746Speter {
28*746Speter 	register struct nl *p;
29*746Speter 	register struct ct *ctab;
30*746Speter 	register *cs;
31*746Speter 	int *cl;
32*746Speter 	double low, high;
33*746Speter 	short *brtab;
34*746Speter 	char *brtab0;
35*746Speter 	char *csend;
36*746Speter 	int w, i, j, m, n;
37*746Speter 	int nr, goc;
38*746Speter 
39*746Speter 	goc = gocnt;
40*746Speter 	/*
41*746Speter 	 * Obtain selector attributes:
42*746Speter 	 *	p	type
43*746Speter 	 *	w	width
44*746Speter 	 *	low	lwb(p)
45*746Speter 	 *	high	upb(p)
46*746Speter 	 */
47*746Speter 	p = rvalue((int *) r[2], NLNIL , RREQ );
48*746Speter 	if (p != NIL) {
49*746Speter 		if (isnta(p, "bcsi")) {
50*746Speter 			error("Case selectors cannot be %ss", nameof(p));
51*746Speter 			p = NIL;
52*746Speter 		} else {
53*746Speter 			cl = p;
54*746Speter 			if (p->class != RANGE)
55*746Speter 				cl = p->type;
56*746Speter 			if (cl == NIL)
57*746Speter 				p = NIL;
58*746Speter 			else {
59*746Speter 				w = width(p);
60*746Speter #ifdef DEBUG
61*746Speter 				if (hp21mx)
62*746Speter 					w = 2;
63*746Speter #endif
64*746Speter 				low = cl->range[0];
65*746Speter 				high = cl->range[1];
66*746Speter 			}
67*746Speter 		}
68*746Speter 	}
69*746Speter 	/*
70*746Speter 	 * Count # of cases
71*746Speter 	 */
72*746Speter 	n = 0;
73*746Speter 	for (cl = r[3]; cl != NIL; cl = cl[2]) {
74*746Speter 		cs = cl[1];
75*746Speter 		if (cs == NIL)
76*746Speter 			continue;
77*746Speter 		for (cs = cs[2]; cs != NIL; cs = cs[2])
78*746Speter 			n++;
79*746Speter 	}
80*746Speter 	/*
81*746Speter 	 * Allocate case table space
82*746Speter 	 */
83*746Speter 	ctab = i = malloc(n * sizeof *ctab);
84*746Speter 	if (i == -1) {
85*746Speter 		error("Ran out of memory (case)");
86*746Speter 		pexit(DIED);
87*746Speter 	}
88*746Speter 	/*
89*746Speter 	 * Check the legality of the
90*746Speter 	 * labels and count the number
91*746Speter 	 * of good labels
92*746Speter 	 */
93*746Speter 	m = 0;
94*746Speter 	for (cl = r[3]; cl != NIL; cl = cl[2]) {
95*746Speter 		cs = cl[1];
96*746Speter 		if (cs == NIL)
97*746Speter 			continue;
98*746Speter 		line = cs[1];
99*746Speter 		for (cs = cs[2]; cs != NIL; cs = cs[2]) {
100*746Speter 			gconst(cs[1]);
101*746Speter 			if (p == NIL || con.ctype == NIL)
102*746Speter 				continue;
103*746Speter 			if (incompat(con.ctype, p, NIL )) {
104*746Speter 				cerror("Case label type clashed with case selector expression type");
105*746Speter 				continue;
106*746Speter 			}
107*746Speter 			if (con.crval < low || con.crval > high) {
108*746Speter 				error("Case label out of range");
109*746Speter 				continue;
110*746Speter 			}
111*746Speter 			ctab[m].clong = con.crval;
112*746Speter 			ctab[m].cline = line;
113*746Speter 			m++;
114*746Speter 		}
115*746Speter 	}
116*746Speter 
117*746Speter 	/*
118*746Speter 	 * Check for duplicate labels
119*746Speter 	 */
120*746Speter 	for (i = 0; i < m; i++)
121*746Speter 		for (j = 0; j < m; j++)
122*746Speter 			if (ctab[i].clong == ctab[j].clong) {
123*746Speter 				if (i == j)
124*746Speter 					continue;
125*746Speter 				if (j < i)
126*746Speter 					break;
127*746Speter 				error("Multiply defined label in case, lines %d and %d", ctab[i].cline, ctab[j].cline);
128*746Speter 			}
129*746Speter 	/*
130*746Speter 	 * Put out case operator and
131*746Speter 	 * leave space for the
132*746Speter 	 * branch table
133*746Speter 	 */
134*746Speter 	if (p != NIL) {
135*746Speter 		put(2, O_CASE1OP + (w >> 1), n);
136*746Speter 		brtab = brtab0 = lc;
137*746Speter 		putspace(n * 2);
138*746Speter 		put(1, O_CASEBEG);
139*746Speter 		for (i=0; i<m; i++)
140*746Speter 			put( 2 , O_CASE1 + (w >> 1), ctab[i].clong);
141*746Speter 		put(1, O_CASEEND);
142*746Speter 	}
143*746Speter 	csend = getlab();
144*746Speter 	put(2, O_TRA, csend);
145*746Speter 	/*
146*746Speter 	 * Free the case
147*746Speter 	 * table space.
148*746Speter 	 */
149*746Speter 	free(ctab);
150*746Speter 	/*
151*746Speter 	 * Generate code for each
152*746Speter 	 * statement. Patch branch
153*746Speter 	 * table to beginning of each
154*746Speter 	 * statement and follow each
155*746Speter 	 * statement with a branch back
156*746Speter 	 * to the TRA above.
157*746Speter 	 */
158*746Speter 	nr = 1;
159*746Speter 	for (cl = r[3]; cl != NIL; cl = cl[2]) {
160*746Speter 		cs = cl[1];
161*746Speter 		if (cs == NIL)
162*746Speter 			continue;
163*746Speter 		if (p != NIL)
164*746Speter 			for (cs = cs[2]; cs != NIL; cs = cs[2]) {
165*746Speter 				patchfil(brtab - 1, lc - brtab0, 1);
166*746Speter 				brtab++;
167*746Speter 			}
168*746Speter 		cs = cl[1];
169*746Speter 		putcnt();
170*746Speter 		level++;
171*746Speter 		statement(cs[3]);
172*746Speter 		nr &= noreach;
173*746Speter 		noreach = 0;
174*746Speter 		put(2, O_TRA, csend);
175*746Speter 		level--;
176*746Speter 		if (gotos[cbn])
177*746Speter 			ungoto();
178*746Speter 	}
179*746Speter 	/*
180*746Speter 	 * Patch the termination branch
181*746Speter 	 */
182*746Speter 	patch(csend);
183*746Speter 	noreach = nr;
184*746Speter 	if (goc != gocnt)
185*746Speter 		putcnt();
186*746Speter }
187*746Speter #endif OBJ
188