1746Speter /* Copyright (c) 1979 Regents of the University of California */ 2746Speter 3*14728Sthien #ifndef lint 4*14728Sthien static char sccsid[] = "@(#)case.c 1.4 08/19/83"; 5*14728Sthien #endif 6746Speter 7746Speter #include "whoami.h" 8746Speter #include "0.h" 9746Speter #include "tree.h" 10746Speter #include "opcode.h" 11*14728Sthien #include "tree_ty.h" 12746Speter 13746Speter /* 14746Speter * The structure used to 15746Speter * hold information about 16746Speter * each case label. 17746Speter */ 18746Speter struct ct { 19746Speter long clong; 20746Speter int cline; 21746Speter }; 22746Speter 23746Speter #ifdef OBJ 24746Speter /* 25746Speter * Caseop generates the 26746Speter * pascal case statement code 27746Speter */ 28*14728Sthien caseop(rnode) 29*14728Sthien WHI_CAS *rnode; 30746Speter { 31746Speter register struct nl *p; 32746Speter register struct ct *ctab; 33*14728Sthien register struct tnode *cs; 34*14728Sthien extern char *lc; 35746Speter double low, high; 36746Speter short *brtab; 37746Speter char *brtab0; 38746Speter char *csend; 39*14728Sthien int w, j, m, n; 403072Smckusic int goc; 413072Smckusic bool nr; 42746Speter 43746Speter goc = gocnt; 44746Speter /* 45746Speter * Obtain selector attributes: 46746Speter * p type 47746Speter * w width 48746Speter * low lwb(p) 49746Speter * high upb(p) 50746Speter */ 51*14728Sthien p = rvalue(rnode->expr, NLNIL , RREQ ); 52*14728Sthien 53*14728Sthien { 54*14728Sthien register struct nl *cl; 55*14728Sthien 56*14728Sthien if (p != NLNIL) { 57746Speter if (isnta(p, "bcsi")) { 58746Speter error("Case selectors cannot be %ss", nameof(p)); 59*14728Sthien p = NLNIL; 60746Speter } else { 61746Speter cl = p; 62*14728Sthien if (p->class != (char) RANGE) 63746Speter cl = p->type; 64*14728Sthien if (cl == NLNIL) 65*14728Sthien p = NLNIL; 66746Speter else { 67746Speter w = width(p); 68746Speter #ifdef DEBUG 69746Speter if (hp21mx) 70746Speter w = 2; 71746Speter #endif 72746Speter low = cl->range[0]; 73746Speter high = cl->range[1]; 74746Speter } 75746Speter } 76746Speter } 77*14728Sthien } /* local declaration */ 78*14728Sthien { 79*14728Sthien struct tnode *cl; /* list node */ 80746Speter /* 81746Speter * Count # of cases 82746Speter */ 83746Speter n = 0; 84*14728Sthien for (cl = rnode->stmnt_list; cl != TR_NIL; 85*14728Sthien cl = cl->list_node.next) { 86*14728Sthien cs = cl->list_node.list;; 87*14728Sthien if (cs == TR_NIL) 88746Speter continue; 89*14728Sthien for (cs = cs->c_stmnt.const_list; cs != TR_NIL; 90*14728Sthien cs = cs->list_node.next) 91746Speter n++; 92746Speter } 93*14728Sthien } /* local declaration */ 94746Speter /* 95746Speter * Allocate case table space 96746Speter */ 97*14728Sthien { 98*14728Sthien char *i; 99*14728Sthien i = malloc((unsigned) n * sizeof *ctab); 1001832Speter if (i == 0) { 101746Speter error("Ran out of memory (case)"); 102746Speter pexit(DIED); 103746Speter } 104*14728Sthien ctab = (struct ct *) i; 105*14728Sthien } 106746Speter /* 107746Speter * Check the legality of the 108746Speter * labels and count the number 109746Speter * of good labels 110746Speter */ 111*14728Sthien { 112*14728Sthien register struct tnode *cl; 113746Speter m = 0; 114*14728Sthien for (cl = rnode->stmnt_list; cl != TR_NIL; 115*14728Sthien cl = cl->list_node.next) { 116*14728Sthien cs = cl->list_node.list; 117*14728Sthien if (cs == TR_NIL) 118746Speter continue; 119*14728Sthien line = cs->c_stmnt.line_no; 120*14728Sthien for (cs = cs->c_stmnt.const_list; cs != TR_NIL; 121*14728Sthien cs = cs->list_node.next) { 122*14728Sthien gconst(cs->list_node.list); 123*14728Sthien if (p == NLNIL || con.ctype == NIL) 124746Speter continue; 125*14728Sthien if (incompat(con.ctype, p, TR_NIL )) { 126746Speter cerror("Case label type clashed with case selector expression type"); 127746Speter continue; 128746Speter } 129746Speter if (con.crval < low || con.crval > high) { 130746Speter error("Case label out of range"); 131746Speter continue; 132746Speter } 133746Speter ctab[m].clong = con.crval; 134746Speter ctab[m].cline = line; 135746Speter m++; 136746Speter } 137746Speter } 138*14728Sthien } /* decl of cl */ 139*14728Sthien { 140*14728Sthien register int i; 141746Speter /* 142746Speter * Check for duplicate labels 143746Speter */ 144746Speter for (i = 0; i < m; i++) 145746Speter for (j = 0; j < m; j++) 146746Speter if (ctab[i].clong == ctab[j].clong) { 147746Speter if (i == j) 148746Speter continue; 149746Speter if (j < i) 150746Speter break; 151*14728Sthien error("Multiply defined label in case, lines %d and %d", (char *) ctab[i].cline, (char *) ctab[j].cline); 152746Speter } 153*14728Sthien } 154746Speter /* 155746Speter * Put out case operator and 156746Speter * leave space for the 157746Speter * branch table 158746Speter */ 159*14728Sthien if (p != NLNIL) { 160*14728Sthien (void) put(2, O_CASE1OP + (w >> 1), n); 161*14728Sthien brtab0 = lc; 162*14728Sthien brtab = ((short *) brtab0); 163746Speter putspace(n * 2); 164*14728Sthien (void) put(1, O_CASEBEG); 165*14728Sthien { 166*14728Sthien int i; 167746Speter for (i=0; i<m; i++) 1683072Smckusic if (w <= 2) 169*14728Sthien (void) put(2 ,O_CASE1 + (w >> 1), (int)ctab[i].clong); 1703072Smckusic else 171*14728Sthien (void) put(2 ,O_CASE4, ctab[i].clong); 172*14728Sthien } 173*14728Sthien (void) put(1, O_CASEEND); 174746Speter } 175746Speter csend = getlab(); 176*14728Sthien (void) put(2, O_TRA, csend); 177746Speter /* 178746Speter * Free the case 179746Speter * table space. 180746Speter */ 181*14728Sthien free((char *) ctab); 182746Speter /* 183746Speter * Generate code for each 184746Speter * statement. Patch branch 185746Speter * table to beginning of each 186746Speter * statement and follow each 187746Speter * statement with a branch back 188746Speter * to the TRA above. 189746Speter */ 190*14728Sthien { 191*14728Sthien register struct tnode *cl; 1923072Smckusic nr = TRUE; 193*14728Sthien for (cl = rnode->stmnt_list; cl != TR_NIL; 194*14728Sthien cl = cl->list_node.next) { 195*14728Sthien cs = cl->list_node.list; 196*14728Sthien if (cs == TR_NIL) 197746Speter continue; 198*14728Sthien if (p != NLNIL) 199*14728Sthien for (cs = cs->c_stmnt.const_list; cs != TR_NIL; 200*14728Sthien cs = cs->list_node.next) { 201*14728Sthien #ifdef ADDR16 202*14728Sthien patchfil(((char *) (brtab - 1)), 203*14728Sthien (long)(lc - brtab0), 1); 204*14728Sthien #endif ADDR16 205*14728Sthien #ifdef ADDR32 206*14728Sthien 207*14728Sthien patchfil( ((unsigned long) (brtab - 1)), 208*14728Sthien (long)(lc - brtab0), 1); 209*14728Sthien #endif ADDR32 210746Speter brtab++; 211746Speter } 212*14728Sthien cs = cl->list_node.list; 213746Speter putcnt(); 214746Speter level++; 215*14728Sthien statement(cs->c_stmnt.stmnt); 216*14728Sthien nr = (bool)(noreach && nr); 217*14728Sthien noreach = FALSE; 218*14728Sthien (void) put(2, O_TRA, csend); 219746Speter level--; 220746Speter if (gotos[cbn]) 221746Speter ungoto(); 222746Speter } 223*14728Sthien } /* decl of cl */ 224746Speter /* 225746Speter * Patch the termination branch 226746Speter */ 227*14728Sthien #ifdef ADDR16 228*14728Sthien patch((char *) csend); 229*14728Sthien #endif ADDR16 230*14728Sthien #ifdef ADDR32 231*14728Sthien patch((unsigned long) csend); 232*14728Sthien #endif ADDR32 233746Speter noreach = nr; 234746Speter if (goc != gocnt) 235746Speter putcnt(); 236746Speter } 237746Speter #endif OBJ 238