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) 06/05/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 242