1749Speter /* Copyright (c) 1979 Regents of the University of California */ 2749Speter 3*10382Speter static char sccsid[] = "@(#)conv.c 1.4 01/17/83"; 4749Speter 5749Speter #include "whoami.h" 6749Speter #ifdef PI 7749Speter #include "0.h" 8749Speter #include "opcode.h" 9749Speter #ifdef PC 10749Speter # include "pcops.h" 11749Speter #endif PC 12749Speter 13749Speter #ifndef PI0 14749Speter /* 15749Speter * Convert a p1 into a p2. 16749Speter * Mostly used for different 17749Speter * length integers and "to real" conversions. 18749Speter */ 19749Speter convert(p1, p2) 20749Speter struct nl *p1, *p2; 21749Speter { 22749Speter if (p1 == NIL || p2 == NIL) 23749Speter return; 24749Speter switch (width(p1) - width(p2)) { 25749Speter case -7: 26749Speter case -6: 273072Smckusic put(1, O_STOD); 28749Speter return; 29749Speter case -4: 303072Smckusic put(1, O_ITOD); 31749Speter return; 32749Speter case -3: 33749Speter case -2: 343072Smckusic put(1, O_STOI); 35749Speter return; 36749Speter case -1: 37749Speter case 0: 38749Speter case 1: 39749Speter return; 40749Speter case 2: 41749Speter case 3: 423072Smckusic put(1, O_ITOS); 43749Speter return; 44749Speter default: 45749Speter panic("convert"); 46749Speter } 47749Speter } 48749Speter #endif 49749Speter 50749Speter /* 51749Speter * Compat tells whether 52749Speter * p1 and p2 are compatible 53749Speter * types for an assignment like 54749Speter * context, i.e. value parameters, 55749Speter * indicies for 'in', etc. 56749Speter */ 57749Speter compat(p1, p2, t) 58749Speter struct nl *p1, *p2; 59749Speter { 60749Speter register c1, c2; 61749Speter 62749Speter c1 = classify(p1); 63749Speter if (c1 == NIL) 64749Speter return (NIL); 65749Speter c2 = classify(p2); 66749Speter if (c2 == NIL) 67749Speter return (NIL); 68749Speter switch (c1) { 69749Speter case TBOOL: 70749Speter case TCHAR: 71749Speter if (c1 == c2) 72749Speter return (1); 73749Speter break; 74749Speter case TINT: 75749Speter if (c2 == TINT) 76749Speter return (1); 77749Speter case TDOUBLE: 78749Speter if (c2 == TDOUBLE) 79749Speter return (1); 80749Speter #ifndef PI0 81749Speter if (c2 == TINT && divflg == 0 && t != NIL ) { 82749Speter divchk= 1; 83749Speter c1 = classify(rvalue(t, NLNIL , RREQ )); 84749Speter divchk = NIL; 85749Speter if (c1 == TINT) { 86749Speter error("Type clash: real is incompatible with integer"); 87749Speter cerror("This resulted because you used '/' which always returns real rather"); 88749Speter cerror("than 'div' which divides integers and returns integers"); 89749Speter divflg = 1; 90749Speter return (NIL); 91749Speter } 92749Speter } 93749Speter #endif 94749Speter break; 95749Speter case TSCAL: 96749Speter if (c2 != TSCAL) 97749Speter break; 98749Speter if (scalar(p1) != scalar(p2)) { 99749Speter derror("Type clash: non-identical scalar types"); 100749Speter return (NIL); 101749Speter } 102749Speter return (1); 103749Speter case TSTR: 104749Speter if (c2 != TSTR) 105749Speter break; 106749Speter if (width(p1) != width(p2)) { 107749Speter derror("Type clash: unequal length strings"); 108749Speter return (NIL); 109749Speter } 110749Speter return (1); 111749Speter case TNIL: 112749Speter if (c2 != TPTR) 113749Speter break; 114749Speter return (1); 115749Speter case TFILE: 116749Speter if (c1 != c2) 117749Speter break; 118749Speter derror("Type clash: files not allowed in this context"); 119749Speter return (NIL); 120749Speter default: 121749Speter if (c1 != c2) 122749Speter break; 123749Speter if (p1 != p2) { 124749Speter derror("Type clash: non-identical %s types", clnames[c1]); 125749Speter return (NIL); 126749Speter } 127749Speter if (p1->nl_flags & NFILES) { 128749Speter derror("Type clash: %ss with file components not allowed in this context", clnames[c1]); 129749Speter return (NIL); 130749Speter } 131749Speter return (1); 132749Speter } 133749Speter derror("Type clash: %s is incompatible with %s", clnames[c1], clnames[c2]); 134749Speter return (NIL); 135749Speter } 136749Speter 137749Speter #ifndef PI0 138749Speter /* 139749Speter * Rangechk generates code to 140749Speter * check if the type p on top 141749Speter * of the stack is in range for 142749Speter * assignment to a variable 143749Speter * of type q. 144749Speter */ 145749Speter rangechk(p, q) 146749Speter struct nl *p, *q; 147749Speter { 148749Speter register struct nl *rp; 149749Speter register op; 150749Speter int wq, wrp; 151749Speter 152749Speter if (opt('t') == 0) 153749Speter return; 154749Speter rp = p; 155749Speter if (rp == NIL) 156749Speter return; 157749Speter if (q == NIL) 158749Speter return; 159749Speter # ifdef OBJ 160749Speter /* 161749Speter * When op is 1 we are checking length 162749Speter * 4 numbers against length 2 bounds, 163749Speter * and adding it to the opcode forces 164749Speter * generation of appropriate tests. 165749Speter */ 166749Speter op = 0; 167749Speter wq = width(q); 168749Speter wrp = width(rp); 169749Speter op = wq != wrp && (wq == 4 || wrp == 4); 170749Speter if (rp->class == TYPE) 171749Speter rp = rp->type; 172749Speter switch (rp->class) { 173749Speter case RANGE: 174749Speter if (rp->range[0] != 0) { 175749Speter # ifndef DEBUG 176749Speter if (wrp <= 2) 177749Speter put(3, O_RANG2+op, ( short ) rp->range[0], 178749Speter ( short ) rp->range[1]); 179749Speter else if (rp != nl+T4INT) 180749Speter put(3, O_RANG4+op, rp->range[0], rp->range[1] ); 181749Speter # else 182749Speter if (!hp21mx) { 183749Speter if (wrp <= 2) 184749Speter put(3, O_RANG2+op,( short ) rp->range[0], 185749Speter ( short ) rp->range[1]); 186749Speter else if (rp != nl+T4INT) 187749Speter put(3, O_RANG4+op,rp->range[0], 188749Speter rp->range[1]); 189749Speter } else 190749Speter if (rp != nl+T2INT && rp != nl+T4INT) 191749Speter put(3, O_RANG2+op,( short ) rp->range[0], 192749Speter ( short ) rp->range[1]); 193749Speter # endif 194749Speter break; 195749Speter } 196749Speter /* 197749Speter * Range whose lower bounds are 198749Speter * zero can be treated as scalars. 199749Speter */ 200749Speter case SCAL: 201749Speter if (wrp <= 2) 202749Speter put(2, O_RSNG2+op, ( short ) rp->range[1]); 203749Speter else 204749Speter put( 2 , O_RSNG4+op, rp->range[1]); 205749Speter break; 206749Speter default: 207749Speter panic("rangechk"); 208749Speter } 209749Speter # endif OBJ 210749Speter # ifdef PC 211749Speter /* 21210381Speter * pc uses precheck() and postcheck(). 213749Speter */ 21410381Speter panic("rangechk()"); 215749Speter # endif PC 216749Speter } 217749Speter #endif 218749Speter #endif 219749Speter 220749Speter #ifdef PC 221749Speter /* 222749Speter * if type p requires a range check, 223749Speter * then put out the name of the checking function 224749Speter * for the beginning of a function call which is completed by postcheck. 225749Speter * (name1 is for a full check; name2 assumes a lower bound of zero) 226749Speter */ 227749Speter precheck( p , name1 , name2 ) 228749Speter struct nl *p; 229749Speter char *name1 , *name2; 230749Speter { 231749Speter 232749Speter if ( opt( 't' ) == 0 ) { 233749Speter return; 234749Speter } 235749Speter if ( p == NIL ) { 236749Speter return; 237749Speter } 238749Speter if ( p -> class == TYPE ) { 239749Speter p = p -> type; 240749Speter } 241749Speter switch ( p -> class ) { 242749Speter case RANGE: 243749Speter if ( p != nl + T4INT ) { 244*10382Speter putleaf( P2ICON , 0 , 0 , 245*10382Speter ADDTYPE( P2FTN | P2INT , P2PTR ), 246*10382Speter p -> range[0] != 0 ? name1 : name2 ); 247749Speter } 248749Speter break; 249749Speter case SCAL: 250749Speter /* 251749Speter * how could a scalar ever be out of range? 252749Speter */ 253749Speter break; 254749Speter default: 255749Speter panic( "precheck" ); 256749Speter break; 257749Speter } 258749Speter } 259749Speter 260749Speter /* 261749Speter * if type p requires a range check, 262749Speter * then put out the rest of the arguments of to the checking function 263749Speter * a call to which was started by precheck. 264749Speter * the first argument is what is being rangechecked (put out by rvalue), 265749Speter * the second argument is the lower bound of the range, 266749Speter * the third argument is the upper bound of the range. 267749Speter */ 268*10382Speter postcheck(need, have) 269*10382Speter struct nl *need; 270*10382Speter struct nl *have; 271*10382Speter { 272749Speter 273*10382Speter if ( opt( 't' ) == 0 ) { 274*10382Speter return; 275*10382Speter } 276*10382Speter if ( need == NIL ) { 277*10382Speter return; 278*10382Speter } 279*10382Speter if ( need -> class == TYPE ) { 280*10382Speter need = need -> type; 281*10382Speter } 282*10382Speter switch ( need -> class ) { 283*10382Speter case RANGE: 284*10382Speter if ( need != nl + T4INT ) { 285*10382Speter sconv(p2type(have), P2INT); 286*10382Speter if (need -> range[0] != 0 ) { 287*10382Speter putleaf( P2ICON , need -> range[0] , 0 , P2INT , 0 ); 288749Speter putop( P2LISTOP , P2INT ); 289749Speter } 290*10382Speter putleaf( P2ICON , need -> range[1] , 0 , P2INT , 0 ); 291*10382Speter putop( P2LISTOP , P2INT ); 292*10382Speter putop( P2CALL , P2INT ); 293*10382Speter sconv(P2INT, p2type(have)); 294*10382Speter } 295*10382Speter break; 296*10382Speter case SCAL: 297*10382Speter break; 298*10382Speter default: 299*10382Speter panic( "postcheck" ); 300*10382Speter break; 301749Speter } 302*10382Speter } 303749Speter #endif PC 304749Speter 305749Speter #ifdef DEBUG 306749Speter conv(dub) 307749Speter int *dub; 308749Speter { 309749Speter int newfp[2]; 310749Speter double *dp = dub; 311749Speter long *lp = dub; 312749Speter register int exp; 313749Speter long mant; 314749Speter 315749Speter newfp[0] = dub[0] & 0100000; 316749Speter newfp[1] = 0; 317749Speter if (*dp == 0.0) 318749Speter goto ret; 319749Speter exp = ((dub[0] >> 7) & 0377) - 0200; 320749Speter if (exp < 0) { 321749Speter newfp[1] = 1; 322749Speter exp = -exp; 323749Speter } 324749Speter if (exp > 63) 325749Speter exp = 63; 326749Speter dub[0] &= ~0177600; 327749Speter dub[0] |= 0200; 328749Speter mant = *lp; 329749Speter mant <<= 8; 330749Speter if (newfp[0]) 331749Speter mant = -mant; 332749Speter newfp[0] |= (mant >> 17) & 077777; 333749Speter newfp[1] |= (((int) (mant >> 1)) & 0177400) | (exp << 1); 334749Speter ret: 335749Speter dub[0] = newfp[0]; 336749Speter dub[1] = newfp[1]; 337749Speter } 338749Speter #endif 339