1746Speter /* Copyright (c) 1979 Regents of the University of California */ 2746Speter 3*1832Speter static char sccsid[] = "@(#)case.c 1.2 11/24/80"; 4746Speter 5746Speter #include "whoami.h" 6746Speter #include "0.h" 7746Speter #include "tree.h" 8746Speter #include "opcode.h" 9746Speter 10746Speter /* 11746Speter * The structure used to 12746Speter * hold information about 13746Speter * each case label. 14746Speter */ 15746Speter struct ct { 16746Speter long clong; 17746Speter int cline; 18746Speter }; 19746Speter 20746Speter #ifdef OBJ 21746Speter /* 22746Speter * Caseop generates the 23746Speter * pascal case statement code 24746Speter */ 25746Speter caseop(r) 26746Speter int *r; 27746Speter { 28746Speter register struct nl *p; 29746Speter register struct ct *ctab; 30746Speter register *cs; 31746Speter int *cl; 32746Speter double low, high; 33746Speter short *brtab; 34746Speter char *brtab0; 35746Speter char *csend; 36746Speter int w, i, j, m, n; 37746Speter int nr, goc; 38746Speter 39746Speter goc = gocnt; 40746Speter /* 41746Speter * Obtain selector attributes: 42746Speter * p type 43746Speter * w width 44746Speter * low lwb(p) 45746Speter * high upb(p) 46746Speter */ 47746Speter p = rvalue((int *) r[2], NLNIL , RREQ ); 48746Speter if (p != NIL) { 49746Speter if (isnta(p, "bcsi")) { 50746Speter error("Case selectors cannot be %ss", nameof(p)); 51746Speter p = NIL; 52746Speter } else { 53746Speter cl = p; 54746Speter if (p->class != RANGE) 55746Speter cl = p->type; 56746Speter if (cl == NIL) 57746Speter p = NIL; 58746Speter else { 59746Speter w = width(p); 60746Speter #ifdef DEBUG 61746Speter if (hp21mx) 62746Speter w = 2; 63746Speter #endif 64746Speter low = cl->range[0]; 65746Speter high = cl->range[1]; 66746Speter } 67746Speter } 68746Speter } 69746Speter /* 70746Speter * Count # of cases 71746Speter */ 72746Speter n = 0; 73746Speter for (cl = r[3]; cl != NIL; cl = cl[2]) { 74746Speter cs = cl[1]; 75746Speter if (cs == NIL) 76746Speter continue; 77746Speter for (cs = cs[2]; cs != NIL; cs = cs[2]) 78746Speter n++; 79746Speter } 80746Speter /* 81746Speter * Allocate case table space 82746Speter */ 83746Speter ctab = i = malloc(n * sizeof *ctab); 84*1832Speter if (i == 0) { 85746Speter error("Ran out of memory (case)"); 86746Speter pexit(DIED); 87746Speter } 88746Speter /* 89746Speter * Check the legality of the 90746Speter * labels and count the number 91746Speter * of good labels 92746Speter */ 93746Speter m = 0; 94746Speter for (cl = r[3]; cl != NIL; cl = cl[2]) { 95746Speter cs = cl[1]; 96746Speter if (cs == NIL) 97746Speter continue; 98746Speter line = cs[1]; 99746Speter for (cs = cs[2]; cs != NIL; cs = cs[2]) { 100746Speter gconst(cs[1]); 101746Speter if (p == NIL || con.ctype == NIL) 102746Speter continue; 103746Speter if (incompat(con.ctype, p, NIL )) { 104746Speter cerror("Case label type clashed with case selector expression type"); 105746Speter continue; 106746Speter } 107746Speter if (con.crval < low || con.crval > high) { 108746Speter error("Case label out of range"); 109746Speter continue; 110746Speter } 111746Speter ctab[m].clong = con.crval; 112746Speter ctab[m].cline = line; 113746Speter m++; 114746Speter } 115746Speter } 116746Speter 117746Speter /* 118746Speter * Check for duplicate labels 119746Speter */ 120746Speter for (i = 0; i < m; i++) 121746Speter for (j = 0; j < m; j++) 122746Speter if (ctab[i].clong == ctab[j].clong) { 123746Speter if (i == j) 124746Speter continue; 125746Speter if (j < i) 126746Speter break; 127746Speter error("Multiply defined label in case, lines %d and %d", ctab[i].cline, ctab[j].cline); 128746Speter } 129746Speter /* 130746Speter * Put out case operator and 131746Speter * leave space for the 132746Speter * branch table 133746Speter */ 134746Speter if (p != NIL) { 135746Speter put(2, O_CASE1OP + (w >> 1), n); 136746Speter brtab = brtab0 = lc; 137746Speter putspace(n * 2); 138746Speter put(1, O_CASEBEG); 139746Speter for (i=0; i<m; i++) 140746Speter put( 2 , O_CASE1 + (w >> 1), ctab[i].clong); 141746Speter put(1, O_CASEEND); 142746Speter } 143746Speter csend = getlab(); 144746Speter put(2, O_TRA, csend); 145746Speter /* 146746Speter * Free the case 147746Speter * table space. 148746Speter */ 149746Speter free(ctab); 150746Speter /* 151746Speter * Generate code for each 152746Speter * statement. Patch branch 153746Speter * table to beginning of each 154746Speter * statement and follow each 155746Speter * statement with a branch back 156746Speter * to the TRA above. 157746Speter */ 158746Speter nr = 1; 159746Speter for (cl = r[3]; cl != NIL; cl = cl[2]) { 160746Speter cs = cl[1]; 161746Speter if (cs == NIL) 162746Speter continue; 163746Speter if (p != NIL) 164746Speter for (cs = cs[2]; cs != NIL; cs = cs[2]) { 165746Speter patchfil(brtab - 1, lc - brtab0, 1); 166746Speter brtab++; 167746Speter } 168746Speter cs = cl[1]; 169746Speter putcnt(); 170746Speter level++; 171746Speter statement(cs[3]); 172746Speter nr &= noreach; 173746Speter noreach = 0; 174746Speter put(2, O_TRA, csend); 175746Speter level--; 176746Speter if (gotos[cbn]) 177746Speter ungoto(); 178746Speter } 179746Speter /* 180746Speter * Patch the termination branch 181746Speter */ 182746Speter patch(csend); 183746Speter noreach = nr; 184746Speter if (goc != gocnt) 185746Speter putcnt(); 186746Speter } 187746Speter #endif OBJ 188