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