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