1746Speter /* Copyright (c) 1979 Regents of the University of California */ 2746Speter 3*3072Smckusic static char sccsid[] = "@(#)case.c 1.3 03/08/81"; 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; 37*3072Smckusic int goc; 38*3072Smckusic bool nr; 39746Speter 40746Speter goc = gocnt; 41746Speter /* 42746Speter * Obtain selector attributes: 43746Speter * p type 44746Speter * w width 45746Speter * low lwb(p) 46746Speter * high upb(p) 47746Speter */ 48746Speter p = rvalue((int *) r[2], NLNIL , RREQ ); 49746Speter if (p != NIL) { 50746Speter if (isnta(p, "bcsi")) { 51746Speter error("Case selectors cannot be %ss", nameof(p)); 52746Speter p = NIL; 53746Speter } else { 54746Speter cl = p; 55746Speter if (p->class != RANGE) 56746Speter cl = p->type; 57746Speter if (cl == NIL) 58746Speter p = NIL; 59746Speter else { 60746Speter w = width(p); 61746Speter #ifdef DEBUG 62746Speter if (hp21mx) 63746Speter w = 2; 64746Speter #endif 65746Speter low = cl->range[0]; 66746Speter high = cl->range[1]; 67746Speter } 68746Speter } 69746Speter } 70746Speter /* 71746Speter * Count # of cases 72746Speter */ 73746Speter n = 0; 74746Speter for (cl = r[3]; cl != NIL; cl = cl[2]) { 75746Speter cs = cl[1]; 76746Speter if (cs == NIL) 77746Speter continue; 78746Speter for (cs = cs[2]; cs != NIL; cs = cs[2]) 79746Speter n++; 80746Speter } 81746Speter /* 82746Speter * Allocate case table space 83746Speter */ 84746Speter ctab = i = malloc(n * sizeof *ctab); 851832Speter if (i == 0) { 86746Speter error("Ran out of memory (case)"); 87746Speter pexit(DIED); 88746Speter } 89746Speter /* 90746Speter * Check the legality of the 91746Speter * labels and count the number 92746Speter * of good labels 93746Speter */ 94746Speter m = 0; 95746Speter for (cl = r[3]; cl != NIL; cl = cl[2]) { 96746Speter cs = cl[1]; 97746Speter if (cs == NIL) 98746Speter continue; 99746Speter line = cs[1]; 100746Speter for (cs = cs[2]; cs != NIL; cs = cs[2]) { 101746Speter gconst(cs[1]); 102746Speter if (p == NIL || con.ctype == NIL) 103746Speter continue; 104746Speter if (incompat(con.ctype, p, NIL )) { 105746Speter cerror("Case label type clashed with case selector expression type"); 106746Speter continue; 107746Speter } 108746Speter if (con.crval < low || con.crval > high) { 109746Speter error("Case label out of range"); 110746Speter continue; 111746Speter } 112746Speter ctab[m].clong = con.crval; 113746Speter ctab[m].cline = line; 114746Speter m++; 115746Speter } 116746Speter } 117746Speter 118746Speter /* 119746Speter * Check for duplicate labels 120746Speter */ 121746Speter for (i = 0; i < m; i++) 122746Speter for (j = 0; j < m; j++) 123746Speter if (ctab[i].clong == ctab[j].clong) { 124746Speter if (i == j) 125746Speter continue; 126746Speter if (j < i) 127746Speter break; 128746Speter error("Multiply defined label in case, lines %d and %d", ctab[i].cline, ctab[j].cline); 129746Speter } 130746Speter /* 131746Speter * Put out case operator and 132746Speter * leave space for the 133746Speter * branch table 134746Speter */ 135746Speter if (p != NIL) { 136746Speter put(2, O_CASE1OP + (w >> 1), n); 137746Speter brtab = brtab0 = lc; 138746Speter putspace(n * 2); 139746Speter put(1, O_CASEBEG); 140746Speter for (i=0; i<m; i++) 141*3072Smckusic if (w <= 2) 142*3072Smckusic put(2 ,O_CASE1 + (w >> 1), (int)ctab[i].clong); 143*3072Smckusic else 144*3072Smckusic put(2 ,O_CASE4, ctab[i].clong); 145746Speter put(1, O_CASEEND); 146746Speter } 147746Speter csend = getlab(); 148746Speter put(2, O_TRA, csend); 149746Speter /* 150746Speter * Free the case 151746Speter * table space. 152746Speter */ 153746Speter free(ctab); 154746Speter /* 155746Speter * Generate code for each 156746Speter * statement. Patch branch 157746Speter * table to beginning of each 158746Speter * statement and follow each 159746Speter * statement with a branch back 160746Speter * to the TRA above. 161746Speter */ 162*3072Smckusic nr = TRUE; 163746Speter for (cl = r[3]; cl != NIL; cl = cl[2]) { 164746Speter cs = cl[1]; 165746Speter if (cs == NIL) 166746Speter continue; 167746Speter if (p != NIL) 168746Speter for (cs = cs[2]; cs != NIL; cs = cs[2]) { 169*3072Smckusic patchfil(brtab - 1, (long)(lc - brtab0), 1); 170746Speter brtab++; 171746Speter } 172746Speter cs = cl[1]; 173746Speter putcnt(); 174746Speter level++; 175746Speter statement(cs[3]); 176*3072Smckusic nr = (noreach && nr); 177746Speter noreach = 0; 178746Speter put(2, O_TRA, csend); 179746Speter level--; 180746Speter if (gotos[cbn]) 181746Speter ungoto(); 182746Speter } 183746Speter /* 184746Speter * Patch the termination branch 185746Speter */ 186746Speter patch(csend); 187746Speter noreach = nr; 188746Speter if (goc != gocnt) 189746Speter putcnt(); 190746Speter } 191746Speter #endif OBJ 192