|
|
1.1 ! root 1: /* Copyright (c) 1979 Regents of the University of California */ ! 2: ! 3: static char sccsid[] = "@(#)case.c 1.3 3/8/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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.