1749Speter /* Copyright (c) 1979 Regents of the University of California */ 2749Speter 3*10381Speter static char sccsid[] = "@(#)conv.c 1.2.1.2 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 /* 212*10381Speter * pc uses precheck() and postcheck(). 213749Speter */ 214*10381Speter 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 ) { 24410380Speter putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) 24510380Speter , p -> range[0] != 0 ? name1 : name2 ); 246749Speter } 247749Speter break; 248749Speter case SCAL: 249749Speter /* 250749Speter * how could a scalar ever be out of range? 251749Speter */ 252749Speter break; 253749Speter default: 254749Speter panic( "precheck" ); 255749Speter break; 256749Speter } 257749Speter } 258749Speter 259749Speter /* 260749Speter * if type p requires a range check, 261749Speter * then put out the rest of the arguments of to the checking function 262749Speter * a call to which was started by precheck. 263749Speter * the first argument is what is being rangechecked (put out by rvalue), 264749Speter * the second argument is the lower bound of the range, 265749Speter * the third argument is the upper bound of the range. 266749Speter */ 26710380Speter postcheck( p ) 26810380Speter struct nl *p; 26910380Speter { 270749Speter 27110380Speter if ( opt( 't' ) == 0 ) { 27210380Speter return; 27310380Speter } 27410380Speter if ( p == NIL ) { 27510380Speter return; 27610380Speter } 27710380Speter if ( p -> class == TYPE ) { 27810380Speter p = p -> type; 27910380Speter } 28010380Speter switch ( p -> class ) { 28110380Speter case RANGE: 28210380Speter if ( p != nl + T4INT ) { 28310380Speter if (p -> range[0] != 0 ) { 28410380Speter putleaf( P2ICON , p -> range[0] , 0 , P2INT , 0 ); 28510380Speter putop( P2LISTOP , P2INT ); 28610380Speter } 28710380Speter putleaf( P2ICON , p -> range[1] , 0 , P2INT , 0 ); 288749Speter putop( P2LISTOP , P2INT ); 28910380Speter putop( P2CALL , P2INT ); 290749Speter } 29110380Speter break; 29210380Speter case SCAL: 29310380Speter break; 29410380Speter default: 29510380Speter panic( "postcheck" ); 29610380Speter break; 29710380Speter } 298749Speter } 299749Speter #endif PC 300749Speter 301749Speter #ifdef DEBUG 302749Speter conv(dub) 303749Speter int *dub; 304749Speter { 305749Speter int newfp[2]; 306749Speter double *dp = dub; 307749Speter long *lp = dub; 308749Speter register int exp; 309749Speter long mant; 310749Speter 311749Speter newfp[0] = dub[0] & 0100000; 312749Speter newfp[1] = 0; 313749Speter if (*dp == 0.0) 314749Speter goto ret; 315749Speter exp = ((dub[0] >> 7) & 0377) - 0200; 316749Speter if (exp < 0) { 317749Speter newfp[1] = 1; 318749Speter exp = -exp; 319749Speter } 320749Speter if (exp > 63) 321749Speter exp = 63; 322749Speter dub[0] &= ~0177600; 323749Speter dub[0] |= 0200; 324749Speter mant = *lp; 325749Speter mant <<= 8; 326749Speter if (newfp[0]) 327749Speter mant = -mant; 328749Speter newfp[0] |= (mant >> 17) & 077777; 329749Speter newfp[1] |= (((int) (mant >> 1)) & 0177400) | (exp << 1); 330749Speter ret: 331749Speter dub[0] = newfp[0]; 332749Speter dub[1] = newfp[1]; 333749Speter } 334749Speter #endif 335