1749Speter /* Copyright (c) 1979 Regents of the University of California */ 2749Speter 3*10380Speter static char sccsid[] = "@(#)conv.c 1.2.1.1 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 /* 212749Speter * what i want to do is make this and some other stuff 213749Speter * arguments to a function call, which will do the rangecheck, 214749Speter * and return the value of the current expression, or abort 215749Speter * if the rangecheck fails. 216749Speter * probably i need one rangecheck routine to return each c-type 217749Speter * of value. 218749Speter * also, i haven't figured out what the `other stuff' is. 219749Speter */ 220749Speter putprintf( "# call rangecheck" , 0 ); 221749Speter # endif PC 222749Speter } 223749Speter #endif 224749Speter #endif 225749Speter 226749Speter #ifdef PC 227749Speter /* 228749Speter * if type p requires a range check, 229749Speter * then put out the name of the checking function 230749Speter * for the beginning of a function call which is completed by postcheck. 231749Speter * (name1 is for a full check; name2 assumes a lower bound of zero) 232749Speter */ 233749Speter precheck( p , name1 , name2 ) 234749Speter struct nl *p; 235749Speter char *name1 , *name2; 236749Speter { 237749Speter 238749Speter if ( opt( 't' ) == 0 ) { 239749Speter return; 240749Speter } 241749Speter if ( p == NIL ) { 242749Speter return; 243749Speter } 244749Speter if ( p -> class == TYPE ) { 245749Speter p = p -> type; 246749Speter } 247749Speter switch ( p -> class ) { 248749Speter case RANGE: 249749Speter if ( p != nl + T4INT ) { 250*10380Speter putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) 251*10380Speter , p -> range[0] != 0 ? name1 : name2 ); 252749Speter } 253749Speter break; 254749Speter case SCAL: 255749Speter /* 256749Speter * how could a scalar ever be out of range? 257749Speter */ 258749Speter break; 259749Speter default: 260749Speter panic( "precheck" ); 261749Speter break; 262749Speter } 263749Speter } 264749Speter 265749Speter /* 266749Speter * if type p requires a range check, 267749Speter * then put out the rest of the arguments of to the checking function 268749Speter * a call to which was started by precheck. 269749Speter * the first argument is what is being rangechecked (put out by rvalue), 270749Speter * the second argument is the lower bound of the range, 271749Speter * the third argument is the upper bound of the range. 272749Speter */ 273*10380Speter postcheck( p ) 274*10380Speter struct nl *p; 275*10380Speter { 276749Speter 277*10380Speter if ( opt( 't' ) == 0 ) { 278*10380Speter return; 279*10380Speter } 280*10380Speter if ( p == NIL ) { 281*10380Speter return; 282*10380Speter } 283*10380Speter if ( p -> class == TYPE ) { 284*10380Speter p = p -> type; 285*10380Speter } 286*10380Speter switch ( p -> class ) { 287*10380Speter case RANGE: 288*10380Speter if ( p != nl + T4INT ) { 289*10380Speter if (p -> range[0] != 0 ) { 290*10380Speter putleaf( P2ICON , p -> range[0] , 0 , P2INT , 0 ); 291*10380Speter putop( P2LISTOP , P2INT ); 292*10380Speter } 293*10380Speter putleaf( P2ICON , p -> range[1] , 0 , P2INT , 0 ); 294749Speter putop( P2LISTOP , P2INT ); 295*10380Speter putop( P2CALL , P2INT ); 296749Speter } 297*10380Speter break; 298*10380Speter case SCAL: 299*10380Speter break; 300*10380Speter default: 301*10380Speter panic( "postcheck" ); 302*10380Speter break; 303*10380Speter } 304749Speter } 305749Speter #endif PC 306749Speter 307749Speter #ifdef DEBUG 308749Speter conv(dub) 309749Speter int *dub; 310749Speter { 311749Speter int newfp[2]; 312749Speter double *dp = dub; 313749Speter long *lp = dub; 314749Speter register int exp; 315749Speter long mant; 316749Speter 317749Speter newfp[0] = dub[0] & 0100000; 318749Speter newfp[1] = 0; 319749Speter if (*dp == 0.0) 320749Speter goto ret; 321749Speter exp = ((dub[0] >> 7) & 0377) - 0200; 322749Speter if (exp < 0) { 323749Speter newfp[1] = 1; 324749Speter exp = -exp; 325749Speter } 326749Speter if (exp > 63) 327749Speter exp = 63; 328749Speter dub[0] &= ~0177600; 329749Speter dub[0] |= 0200; 330749Speter mant = *lp; 331749Speter mant <<= 8; 332749Speter if (newfp[0]) 333749Speter mant = -mant; 334749Speter newfp[0] |= (mant >> 17) & 077777; 335749Speter newfp[1] |= (((int) (mant >> 1)) & 0177400) | (exp << 1); 336749Speter ret: 337749Speter dub[0] = newfp[0]; 338749Speter dub[1] = newfp[1]; 339749Speter } 340749Speter #endif 341