1749Speter /* Copyright (c) 1979 Regents of the University of California */ 2749Speter 314728Sthien #ifndef lint 4*18454Sralph static char sccsid[] = "@(#)conv.c 2.2 03/20/85"; 514728Sthien #endif 6749Speter 7749Speter #include "whoami.h" 8749Speter #ifdef PI 9749Speter #include "0.h" 10749Speter #include "opcode.h" 11749Speter #ifdef PC 12*18454Sralph # include <pcc.h> 13749Speter #endif PC 1414728Sthien #include "tree_ty.h" 15749Speter 1614728Sthien #ifndef PC 17749Speter #ifndef PI0 18749Speter /* 19749Speter * Convert a p1 into a p2. 20749Speter * Mostly used for different 21749Speter * length integers and "to real" conversions. 22749Speter */ 23749Speter convert(p1, p2) 24749Speter struct nl *p1, *p2; 25749Speter { 2614728Sthien if (p1 == NLNIL || p2 == NLNIL) 27749Speter return; 28749Speter switch (width(p1) - width(p2)) { 29749Speter case -7: 30749Speter case -6: 3114728Sthien (void) put(1, O_STOD); 32749Speter return; 33749Speter case -4: 3414728Sthien (void) put(1, O_ITOD); 35749Speter return; 36749Speter case -3: 37749Speter case -2: 3814728Sthien (void) put(1, O_STOI); 39749Speter return; 40749Speter case -1: 41749Speter case 0: 42749Speter case 1: 43749Speter return; 44749Speter case 2: 45749Speter case 3: 4614728Sthien (void) put(1, O_ITOS); 47749Speter return; 48749Speter default: 49749Speter panic("convert"); 50749Speter } 51749Speter } 5214728Sthien #endif 5314728Sthien #endif PC 54749Speter 55749Speter /* 56749Speter * Compat tells whether 57749Speter * p1 and p2 are compatible 58749Speter * types for an assignment like 59749Speter * context, i.e. value parameters, 60749Speter * indicies for 'in', etc. 61749Speter */ 62749Speter compat(p1, p2, t) 63749Speter struct nl *p1, *p2; 6414728Sthien struct tnode *t; 65749Speter { 66749Speter register c1, c2; 67749Speter 68749Speter c1 = classify(p1); 69749Speter if (c1 == NIL) 70749Speter return (NIL); 71749Speter c2 = classify(p2); 72749Speter if (c2 == NIL) 73749Speter return (NIL); 74749Speter switch (c1) { 75749Speter case TBOOL: 76749Speter case TCHAR: 77749Speter if (c1 == c2) 78749Speter return (1); 79749Speter break; 80749Speter case TINT: 81749Speter if (c2 == TINT) 82749Speter return (1); 83749Speter case TDOUBLE: 84749Speter if (c2 == TDOUBLE) 85749Speter return (1); 86749Speter #ifndef PI0 8714728Sthien if (c2 == TINT && divflg == FALSE && t != TR_NIL ) { 8814728Sthien divchk= TRUE; 89749Speter c1 = classify(rvalue(t, NLNIL , RREQ )); 9014728Sthien divchk = FALSE; 91749Speter if (c1 == TINT) { 92749Speter error("Type clash: real is incompatible with integer"); 93749Speter cerror("This resulted because you used '/' which always returns real rather"); 94749Speter cerror("than 'div' which divides integers and returns integers"); 9514728Sthien divflg = TRUE; 96749Speter return (NIL); 97749Speter } 98749Speter } 99749Speter #endif 100749Speter break; 101749Speter case TSCAL: 102749Speter if (c2 != TSCAL) 103749Speter break; 104749Speter if (scalar(p1) != scalar(p2)) { 105749Speter derror("Type clash: non-identical scalar types"); 106749Speter return (NIL); 107749Speter } 108749Speter return (1); 109749Speter case TSTR: 110749Speter if (c2 != TSTR) 111749Speter break; 112749Speter if (width(p1) != width(p2)) { 113749Speter derror("Type clash: unequal length strings"); 114749Speter return (NIL); 115749Speter } 116749Speter return (1); 117749Speter case TNIL: 118749Speter if (c2 != TPTR) 119749Speter break; 120749Speter return (1); 121749Speter case TFILE: 122749Speter if (c1 != c2) 123749Speter break; 124749Speter derror("Type clash: files not allowed in this context"); 125749Speter return (NIL); 126749Speter default: 127749Speter if (c1 != c2) 128749Speter break; 129749Speter if (p1 != p2) { 130749Speter derror("Type clash: non-identical %s types", clnames[c1]); 131749Speter return (NIL); 132749Speter } 133749Speter if (p1->nl_flags & NFILES) { 134749Speter derror("Type clash: %ss with file components not allowed in this context", clnames[c1]); 135749Speter return (NIL); 136749Speter } 137749Speter return (1); 138749Speter } 139749Speter derror("Type clash: %s is incompatible with %s", clnames[c1], clnames[c2]); 140749Speter return (NIL); 141749Speter } 142749Speter 143749Speter #ifndef PI0 14414728Sthien #ifndef PC 145749Speter /* 146749Speter * Rangechk generates code to 147749Speter * check if the type p on top 148749Speter * of the stack is in range for 149749Speter * assignment to a variable 150749Speter * of type q. 151749Speter */ 152749Speter rangechk(p, q) 153749Speter struct nl *p, *q; 154749Speter { 155749Speter register struct nl *rp; 15614728Sthien #ifdef OBJ 157749Speter register op; 158749Speter int wq, wrp; 15914728Sthien #endif 160749Speter 161749Speter if (opt('t') == 0) 162749Speter return; 163749Speter rp = p; 164749Speter if (rp == NIL) 165749Speter return; 166749Speter if (q == NIL) 167749Speter return; 168749Speter # ifdef OBJ 169749Speter /* 170749Speter * When op is 1 we are checking length 171749Speter * 4 numbers against length 2 bounds, 172749Speter * and adding it to the opcode forces 173749Speter * generation of appropriate tests. 174749Speter */ 175749Speter op = 0; 176749Speter wq = width(q); 177749Speter wrp = width(rp); 178749Speter op = wq != wrp && (wq == 4 || wrp == 4); 17915962Smckusick if (rp->class == TYPE || rp->class == CRANGE) 180749Speter rp = rp->type; 181749Speter switch (rp->class) { 182749Speter case RANGE: 183749Speter if (rp->range[0] != 0) { 184749Speter # ifndef DEBUG 185749Speter if (wrp <= 2) 18614728Sthien (void) put(3, O_RANG2+op, ( short ) rp->range[0], 187749Speter ( short ) rp->range[1]); 188749Speter else if (rp != nl+T4INT) 18914728Sthien (void) put(3, O_RANG4+op, rp->range[0], rp->range[1] ); 190749Speter # else 191749Speter if (!hp21mx) { 192749Speter if (wrp <= 2) 19314728Sthien (void) put(3, O_RANG2+op,( short ) rp->range[0], 194749Speter ( short ) rp->range[1]); 195749Speter else if (rp != nl+T4INT) 19614728Sthien (void) put(3, O_RANG4+op,rp->range[0], 197749Speter rp->range[1]); 198749Speter } else 199749Speter if (rp != nl+T2INT && rp != nl+T4INT) 20014728Sthien (void) put(3, O_RANG2+op,( short ) rp->range[0], 201749Speter ( short ) rp->range[1]); 202749Speter # endif 203749Speter break; 204749Speter } 205749Speter /* 206749Speter * Range whose lower bounds are 207749Speter * zero can be treated as scalars. 208749Speter */ 209749Speter case SCAL: 210749Speter if (wrp <= 2) 21114728Sthien (void) put(2, O_RSNG2+op, ( short ) rp->range[1]); 212749Speter else 21314728Sthien (void) put( 2 , O_RSNG4+op, rp->range[1]); 214749Speter break; 215749Speter default: 216749Speter panic("rangechk"); 217749Speter } 218749Speter # endif OBJ 219749Speter # ifdef PC 220749Speter /* 22110381Speter * pc uses precheck() and postcheck(). 222749Speter */ 22310381Speter panic("rangechk()"); 224749Speter # endif PC 225749Speter } 226749Speter #endif 227749Speter #endif 22814728Sthien #endif 229749Speter 230749Speter #ifdef PC 231749Speter /* 232749Speter * if type p requires a range check, 233749Speter * then put out the name of the checking function 234749Speter * for the beginning of a function call which is completed by postcheck. 235749Speter * (name1 is for a full check; name2 assumes a lower bound of zero) 236749Speter */ 237749Speter precheck( p , name1 , name2 ) 238749Speter struct nl *p; 239749Speter char *name1 , *name2; 240749Speter { 241749Speter 242749Speter if ( opt( 't' ) == 0 ) { 243749Speter return; 244749Speter } 245749Speter if ( p == NIL ) { 246749Speter return; 247749Speter } 248749Speter if ( p -> class == TYPE ) { 249749Speter p = p -> type; 250749Speter } 251749Speter switch ( p -> class ) { 25215962Smckusick case CRANGE: 253*18454Sralph putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) 25415962Smckusick , name1); 25515962Smckusick break; 256749Speter case RANGE: 257749Speter if ( p != nl + T4INT ) { 258*18454Sralph putleaf( PCC_ICON , 0 , 0 , 259*18454Sralph PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ), 26010382Speter p -> range[0] != 0 ? name1 : name2 ); 261749Speter } 262749Speter break; 263749Speter case SCAL: 264749Speter /* 265749Speter * how could a scalar ever be out of range? 266749Speter */ 267749Speter break; 268749Speter default: 269749Speter panic( "precheck" ); 270749Speter break; 271749Speter } 272749Speter } 273749Speter 274749Speter /* 275749Speter * if type p requires a range check, 276749Speter * then put out the rest of the arguments of to the checking function 277749Speter * a call to which was started by precheck. 278749Speter * the first argument is what is being rangechecked (put out by rvalue), 279749Speter * the second argument is the lower bound of the range, 280749Speter * the third argument is the upper bound of the range. 281749Speter */ 28210382Speter postcheck(need, have) 28310382Speter struct nl *need; 28410382Speter struct nl *have; 28510382Speter { 28615962Smckusick struct nl *p; 287749Speter 28810382Speter if ( opt( 't' ) == 0 ) { 28910382Speter return; 29010382Speter } 29110382Speter if ( need == NIL ) { 29210382Speter return; 29310382Speter } 29410382Speter if ( need -> class == TYPE ) { 29510382Speter need = need -> type; 29610382Speter } 29710382Speter switch ( need -> class ) { 29810382Speter case RANGE: 29910382Speter if ( need != nl + T4INT ) { 300*18454Sralph sconv(p2type(have), PCCT_INT); 30110382Speter if (need -> range[0] != 0 ) { 302*18454Sralph putleaf( PCC_ICON , (int) need -> range[0] , 0 , PCCT_INT , 30314728Sthien (char *) 0 ); 304*18454Sralph putop( PCC_CM , PCCT_INT ); 305749Speter } 306*18454Sralph putleaf( PCC_ICON , (int) need -> range[1] , 0 , PCCT_INT , 30714728Sthien (char *) 0 ); 308*18454Sralph putop( PCC_CM , PCCT_INT ); 309*18454Sralph putop( PCC_CALL , PCCT_INT ); 310*18454Sralph sconv(PCCT_INT, p2type(have)); 31110382Speter } 31210382Speter break; 31315962Smckusick case CRANGE: 314*18454Sralph sconv(p2type(have), PCCT_INT); 31515962Smckusick p = need->nptr[0]; 31615962Smckusick putRV(p->symbol, (p->nl_block & 037), p->value[0], 31715962Smckusick p->extra_flags, p2type( p ) ); 318*18454Sralph putop( PCC_CM , PCCT_INT ); 31915962Smckusick p = need->nptr[1]; 32015962Smckusick putRV(p->symbol, (p->nl_block & 037), p->value[0], 32115962Smckusick p->extra_flags, p2type( p ) ); 322*18454Sralph putop( PCC_CM , PCCT_INT ); 323*18454Sralph putop( PCC_CALL , PCCT_INT ); 324*18454Sralph sconv(PCCT_INT, p2type(have)); 32515962Smckusick break; 32610382Speter case SCAL: 32710382Speter break; 32810382Speter default: 32910382Speter panic( "postcheck" ); 33010382Speter break; 331749Speter } 33210382Speter } 333749Speter #endif PC 334749Speter 335749Speter #ifdef DEBUG 336749Speter conv(dub) 337749Speter int *dub; 338749Speter { 339749Speter int newfp[2]; 34014728Sthien double *dp = ((double *) dub); 34114728Sthien long *lp = ((long *) dub); 342749Speter register int exp; 343749Speter long mant; 344749Speter 345749Speter newfp[0] = dub[0] & 0100000; 346749Speter newfp[1] = 0; 347749Speter if (*dp == 0.0) 348749Speter goto ret; 349749Speter exp = ((dub[0] >> 7) & 0377) - 0200; 350749Speter if (exp < 0) { 351749Speter newfp[1] = 1; 352749Speter exp = -exp; 353749Speter } 354749Speter if (exp > 63) 355749Speter exp = 63; 356749Speter dub[0] &= ~0177600; 357749Speter dub[0] |= 0200; 358749Speter mant = *lp; 359749Speter mant <<= 8; 360749Speter if (newfp[0]) 361749Speter mant = -mant; 362749Speter newfp[0] |= (mant >> 17) & 077777; 363749Speter newfp[1] |= (((int) (mant >> 1)) & 0177400) | (exp << 1); 364749Speter ret: 365749Speter dub[0] = newfp[0]; 366749Speter dub[1] = newfp[1]; 367749Speter } 368749Speter #endif 369