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