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