1*763Speter /* Copyright (c) 1979 Regents of the University of California */ 2*763Speter 3*763Speter static char sccsid[] = "@(#)pccaseop.c 1.1 08/27/80"; 4*763Speter 5*763Speter #include "whoami.h" 6*763Speter #ifdef PC 7*763Speter /* 8*763Speter * and the rest of the file 9*763Speter */ 10*763Speter #include "0.h" 11*763Speter #include "tree.h" 12*763Speter #include "objfmt.h" 13*763Speter #include "pcops.h" 14*763Speter #include "pc.h" 15*763Speter /* 16*763Speter * tcase [0] T_CASE 17*763Speter * [1] lineof "case" 18*763Speter * [2] expression 19*763Speter * [3] list of cased statements 20*763Speter * cstat [0] T_CSTAT 21*763Speter * [1] lineof ":" 22*763Speter * [2] constant list 23*763Speter * [3] statement 24*763Speter */ 25*763Speter 26*763Speter struct ct { 27*763Speter long clong; 28*763Speter int cline; 29*763Speter }; 30*763Speter 31*763Speter pccaseop( tcase ) 32*763Speter int *tcase; 33*763Speter { 34*763Speter struct nl *exprtype; 35*763Speter struct nl *rangetype; 36*763Speter long low; 37*763Speter long high; 38*763Speter long exproff; 39*763Speter long exprctype; 40*763Speter long count; 41*763Speter long *cstatlp; 42*763Speter long *cstatp; 43*763Speter struct ct *ctab; 44*763Speter long endlabel; 45*763Speter long nextlabel; 46*763Speter long firsttime; 47*763Speter long *casep; 48*763Speter long i; 49*763Speter long nr; 50*763Speter long goc; 51*763Speter 52*763Speter goc = gocnt; 53*763Speter /* 54*763Speter * find out the type of the case expression 55*763Speter */ 56*763Speter line = tcase[1]; 57*763Speter codeoff(); 58*763Speter exprtype = rvalue( (int *) tcase[2] , NIL , RREQ ); 59*763Speter codeon(); 60*763Speter if ( exprtype != NIL ) { 61*763Speter if ( isnta( exprtype , "bcsi" ) ) { 62*763Speter error("Case selectors cannot be %ss" , nameof( exprtype ) ); 63*763Speter exprtype = NIL; 64*763Speter } else { 65*763Speter if ( exprtype -> class != RANGE ) { 66*763Speter rangetype = exprtype -> type; 67*763Speter } else { 68*763Speter rangetype = exprtype; 69*763Speter } 70*763Speter if ( rangetype == NIL ) { 71*763Speter exprtype = NIL; 72*763Speter } else { 73*763Speter low = rangetype -> range[0]; 74*763Speter high = rangetype -> range[1]; 75*763Speter } 76*763Speter } 77*763Speter } 78*763Speter if ( exprtype != NIL ) { 79*763Speter /* 80*763Speter * allocate temporary for case expression 81*763Speter */ 82*763Speter sizes[cbn].om_off -= sizeof( long ); 83*763Speter exproff = sizes[cbn].om_off; 84*763Speter putlbracket( ftnno , -sizes[cbn].om_off ); 85*763Speter if ( sizes[cbn].om_off < sizes[cbn].om_max ) { 86*763Speter sizes[cbn].om_max = sizes[cbn].om_off; 87*763Speter } 88*763Speter /* 89*763Speter * compute and save the expression 90*763Speter */ 91*763Speter exprctype = p2type( exprtype ); 92*763Speter putRV( 0 , cbn , exproff , P2INT ); 93*763Speter rvalue( (int *) tcase[2] , NIL , RREQ ); 94*763Speter putop( P2ASSIGN , exprctype ); 95*763Speter putdot( filename , line ); 96*763Speter } 97*763Speter /* 98*763Speter * count the number of cases 99*763Speter * and allocate table for cases and lines 100*763Speter */ 101*763Speter count = 0; 102*763Speter for ( cstatlp = tcase[3] ; cstatlp != NIL ; cstatlp = cstatlp[2] ) { 103*763Speter cstatp = cstatlp[1]; 104*763Speter if ( cstatp == NIL ) { 105*763Speter continue; 106*763Speter } 107*763Speter for ( casep = cstatp[2] ; casep != NIL ; casep = casep[2] ) { 108*763Speter count++; 109*763Speter } 110*763Speter } 111*763Speter ctab = (struct ct *) malloc( count * sizeof( struct ct ) ); 112*763Speter if ( ctab == (struct ct *) -1 ) { 113*763Speter error("Ran out of memory (case)"); 114*763Speter pexit( DIED ); 115*763Speter } 116*763Speter /* 117*763Speter * generate code for each case 118*763Speter */ 119*763Speter endlabel = getlab(); 120*763Speter nextlabel = getlab(); 121*763Speter count = 0; 122*763Speter nr = 1; 123*763Speter for ( cstatlp = tcase[3] ; cstatlp != NIL ; cstatlp = cstatlp[2] ) { 124*763Speter cstatp = cstatlp[1]; 125*763Speter if ( cstatp == NIL ) { 126*763Speter continue; 127*763Speter } 128*763Speter line = cstatp[1]; 129*763Speter putlab( nextlabel ); 130*763Speter nextlabel = getlab(); 131*763Speter /* 132*763Speter * if it's not any of these, then go to next 133*763Speter */ 134*763Speter firsttime = 1; 135*763Speter for ( casep = cstatp[2] ; casep != NIL ; casep = casep[2] ) { 136*763Speter gconst( casep[1] ); 137*763Speter if( exprtype == NIL || con.ctype == NIL ) { 138*763Speter continue; 139*763Speter } 140*763Speter if ( incompat( con.ctype , exprtype , NIL ) ) { 141*763Speter cerror("Case label type clashed with case selector expression type"); 142*763Speter continue; 143*763Speter } 144*763Speter if ( con.crval < low || con.crval > high ) { 145*763Speter error("Case label out of range"); 146*763Speter continue; 147*763Speter } 148*763Speter ctab[ count ].clong = con.crval; 149*763Speter ctab[ count ].cline = line; 150*763Speter /* 151*763Speter * check for duplicates 152*763Speter */ 153*763Speter for ( i = 0 ; i < count ; i++ ) { 154*763Speter if ( ctab[ i ].clong == con.crval ) { 155*763Speter error("Multiply defined label in case, lines %d and %d" 156*763Speter , ctab[ i ].cline , line ); 157*763Speter } 158*763Speter } 159*763Speter putRV( 0 , cbn , exproff , exprctype , 0 ); 160*763Speter putleaf( P2ICON , ctab[ count ].clong , 0 , exprctype , 0 ); 161*763Speter putop( P2EQ , exprctype ); 162*763Speter if ( ! firsttime ) { 163*763Speter /* 164*763Speter * note the use of !! to get short circuiting 165*763Speter */ 166*763Speter putop( P2OROR , P2CHAR ); 167*763Speter } 168*763Speter firsttime = 0; 169*763Speter } 170*763Speter putleaf( P2ICON , nextlabel , 0 , P2INT , 0 ); 171*763Speter putop( P2CBRANCH , P2INT ); 172*763Speter putdot( filename , line ); 173*763Speter /* 174*763Speter * if we get here, we must be in this case 175*763Speter */ 176*763Speter putcnt(); 177*763Speter level++; 178*763Speter statement( cstatp[3] ); 179*763Speter nr &= noreach; 180*763Speter noreach = 0; 181*763Speter putjbr( endlabel ); 182*763Speter level--; 183*763Speter if (gotos[cbn]) { 184*763Speter ungoto(); 185*763Speter } 186*763Speter } 187*763Speter /* 188*763Speter * default action is to call error 189*763Speter */ 190*763Speter putlab( nextlabel ); 191*763Speter putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) , "_ERROR" ); 192*763Speter putleaf( P2ICON , ECASE , 0 , P2INT , 0 ); 193*763Speter putRV( 0 , cbn , exproff , P2INT ); 194*763Speter putop( P2LISTOP , P2INT ); 195*763Speter putop( P2CALL , P2INT ); 196*763Speter putdot( filename , line ); 197*763Speter putlab( endlabel ); 198*763Speter noreach = nr; 199*763Speter if ( goc != gocnt ) { 200*763Speter putcnt(); 201*763Speter } 202*763Speter } 203*763Speter 204*763Speter #endif PC 205