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