1: /*
2: * Copyright (c) 1980 Regents of the University of California.
3: * All rights reserved. The Berkeley software License Agreement
4: * specifies the terms and conditions for redistribution.
5: */
6:
7: #ifndef lint
8: static char sccsid[] = "@(#)case.c 5.2 (Berkeley) 6/5/85";
9: #endif not lint
10:
11: #include "whoami.h"
12: #include "0.h"
13: #include "tree.h"
14: #include "opcode.h"
15: #include "tree_ty.h"
16:
17: /*
18: * The structure used to
19: * hold information about
20: * each case label.
21: */
22: struct ct {
23: long clong;
24: int cline;
25: };
26:
27: #ifdef OBJ
28: /*
29: * Caseop generates the
30: * pascal case statement code
31: */
32: caseop(rnode)
33: WHI_CAS *rnode;
34: {
35: register struct nl *p;
36: register struct ct *ctab;
37: register struct tnode *cs;
38: extern char *lc;
39: double low, high;
40: short *brtab;
41: char *brtab0;
42: char *csend;
43: int w, j, m, n;
44: int goc;
45: bool nr;
46:
47: goc = gocnt;
48: /*
49: * Obtain selector attributes:
50: * p type
51: * w width
52: * low lwb(p)
53: * high upb(p)
54: */
55: p = rvalue(rnode->expr, NLNIL , RREQ );
56:
57: {
58: register struct nl *cl;
59:
60: if (p != NLNIL) {
61: if (isnta(p, "bcsi")) {
62: error("Case selectors cannot be %ss", nameof(p));
63: p = NLNIL;
64: } else {
65: cl = p;
66: if (p->class != (char) RANGE)
67: cl = p->type;
68: if (cl == NLNIL)
69: p = NLNIL;
70: else {
71: w = width(p);
72: #ifdef DEBUG
73: if (hp21mx)
74: w = 2;
75: #endif
76: low = cl->range[0];
77: high = cl->range[1];
78: }
79: }
80: }
81: } /* local declaration */
82: {
83: struct tnode *cl; /* list node */
84: /*
85: * Count # of cases
86: */
87: n = 0;
88: for (cl = rnode->stmnt_list; cl != TR_NIL;
89: cl = cl->list_node.next) {
90: cs = cl->list_node.list;;
91: if (cs == TR_NIL)
92: continue;
93: for (cs = cs->c_stmnt.const_list; cs != TR_NIL;
94: cs = cs->list_node.next)
95: n++;
96: }
97: } /* local declaration */
98: /*
99: * Allocate case table space
100: */
101: {
102: char *i;
103: i = malloc((unsigned) n * sizeof *ctab);
104: if (i == 0) {
105: error("Ran out of memory (case)");
106: pexit(DIED);
107: }
108: ctab = (struct ct *) i;
109: }
110: /*
111: * Check the legality of the
112: * labels and count the number
113: * of good labels
114: */
115: {
116: register struct tnode *cl;
117: m = 0;
118: for (cl = rnode->stmnt_list; cl != TR_NIL;
119: cl = cl->list_node.next) {
120: cs = cl->list_node.list;
121: if (cs == TR_NIL)
122: continue;
123: line = cs->c_stmnt.line_no;
124: for (cs = cs->c_stmnt.const_list; cs != TR_NIL;
125: cs = cs->list_node.next) {
126: gconst(cs->list_node.list);
127: if (p == NLNIL || con.ctype == NIL)
128: continue;
129: if (incompat(con.ctype, p, TR_NIL )) {
130: cerror("Case label type clashed with case selector expression type");
131: continue;
132: }
133: if (con.crval < low || con.crval > high) {
134: error("Case label out of range");
135: continue;
136: }
137: ctab[m].clong = con.crval;
138: ctab[m].cline = line;
139: m++;
140: }
141: }
142: } /* decl of cl */
143: {
144: register int i;
145: /*
146: * Check for duplicate labels
147: */
148: for (i = 0; i < m; i++)
149: for (j = 0; j < m; j++)
150: if (ctab[i].clong == ctab[j].clong) {
151: if (i == j)
152: continue;
153: if (j < i)
154: break;
155: error("Multiply defined label in case, lines %d and %d", (char *) ctab[i].cline, (char *) ctab[j].cline);
156: }
157: }
158: /*
159: * Put out case operator and
160: * leave space for the
161: * branch table
162: */
163: if (p != NLNIL) {
164: (void) put(2, O_CASE1OP + (w >> 1), n);
165: brtab0 = lc;
166: brtab = ((short *) brtab0);
167: putspace(n * 2);
168: (void) put(1, O_CASEBEG);
169: {
170: int i;
171: for (i=0; i<m; i++)
172: if (w <= 2)
173: (void) put(2 ,O_CASE1 + (w >> 1), (int)ctab[i].clong);
174: else
175: (void) put(2 ,O_CASE4, ctab[i].clong);
176: }
177: (void) put(1, O_CASEEND);
178: }
179: csend = getlab();
180: (void) put(2, O_TRA, csend);
181: /*
182: * Free the case
183: * table space.
184: */
185: free((char *) ctab);
186: /*
187: * Generate code for each
188: * statement. Patch branch
189: * table to beginning of each
190: * statement and follow each
191: * statement with a branch back
192: * to the TRA above.
193: */
194: {
195: register struct tnode *cl;
196: nr = TRUE;
197: for (cl = rnode->stmnt_list; cl != TR_NIL;
198: cl = cl->list_node.next) {
199: cs = cl->list_node.list;
200: if (cs == TR_NIL)
201: continue;
202: if (p != NLNIL)
203: for (cs = cs->c_stmnt.const_list; cs != TR_NIL;
204: cs = cs->list_node.next) {
205: #ifdef ADDR16
206: patchfil(((char *) (brtab - 1)),
207: (long)(lc - brtab0), 1);
208: #endif ADDR16
209: #ifdef ADDR32
210:
211: patchfil( ((unsigned long) (brtab - 1)),
212: (long)(lc - brtab0), 1);
213: #endif ADDR32
214: brtab++;
215: }
216: cs = cl->list_node.list;
217: putcnt();
218: level++;
219: statement(cs->c_stmnt.stmnt);
220: nr = (bool)(noreach && nr);
221: noreach = FALSE;
222: (void) put(2, O_TRA, csend);
223: level--;
224: if (gotos[cbn])
225: ungoto();
226: }
227: } /* decl of cl */
228: /*
229: * Patch the termination branch
230: */
231: #ifdef ADDR16
232: patch((char *) csend);
233: #endif ADDR16
234: #ifdef ADDR32
235: patch((unsigned long) csend);
236: #endif ADDR32
237: noreach = nr;
238: if (goc != gocnt)
239: putcnt();
240: }
241: #endif OBJ
Defined functions
Defined variables
sccsid
defined in line
8;
never used
Defined struct's
ct
defined in line
22; used 4 times