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