1*48116Sbostic /*- 2*48116Sbostic * Copyright (c) 1980 The Regents of the University of California. 3*48116Sbostic * All rights reserved. 4*48116Sbostic * 5*48116Sbostic * %sccs.include.redist.c% 622160Sdist */ 7749Speter 814728Sthien #ifndef lint 9*48116Sbostic static char sccsid[] = "@(#)conv.c 5.2 (Berkeley) 04/16/91"; 10*48116Sbostic #endif /* not lint */ 11749Speter 12749Speter #include "whoami.h" 13749Speter #ifdef PI 14749Speter #include "0.h" 15749Speter #include "opcode.h" 16749Speter #ifdef PC 1718454Sralph # include <pcc.h> 18749Speter #endif PC 1914728Sthien #include "tree_ty.h" 20749Speter 2114728Sthien #ifndef PC 22749Speter #ifndef PI0 23749Speter /* 24749Speter * Convert a p1 into a p2. 25749Speter * Mostly used for different 26749Speter * length integers and "to real" conversions. 27749Speter */ 28749Speter convert(p1, p2) 29749Speter struct nl *p1, *p2; 30749Speter { 3114728Sthien if (p1 == NLNIL || p2 == NLNIL) 32749Speter return; 33749Speter switch (width(p1) - width(p2)) { 34749Speter case -7: 35749Speter case -6: 3614728Sthien (void) put(1, O_STOD); 37749Speter return; 38749Speter case -4: 3914728Sthien (void) put(1, O_ITOD); 40749Speter return; 41749Speter case -3: 42749Speter case -2: 4314728Sthien (void) put(1, O_STOI); 44749Speter return; 45749Speter case -1: 46749Speter case 0: 47749Speter case 1: 48749Speter return; 49749Speter case 2: 50749Speter case 3: 5114728Sthien (void) put(1, O_ITOS); 52749Speter return; 53749Speter default: 54749Speter panic("convert"); 55749Speter } 56749Speter } 5714728Sthien #endif 5814728Sthien #endif PC 59749Speter 60749Speter /* 61749Speter * Compat tells whether 62749Speter * p1 and p2 are compatible 63749Speter * types for an assignment like 64749Speter * context, i.e. value parameters, 65749Speter * indicies for 'in', etc. 66749Speter */ 67749Speter compat(p1, p2, t) 68749Speter struct nl *p1, *p2; 6914728Sthien struct tnode *t; 70749Speter { 71749Speter register c1, c2; 72749Speter 73749Speter c1 = classify(p1); 74749Speter if (c1 == NIL) 75749Speter return (NIL); 76749Speter c2 = classify(p2); 77749Speter if (c2 == NIL) 78749Speter return (NIL); 79749Speter switch (c1) { 80749Speter case TBOOL: 81749Speter case TCHAR: 82749Speter if (c1 == c2) 83749Speter return (1); 84749Speter break; 85749Speter case TINT: 86749Speter if (c2 == TINT) 87749Speter return (1); 88749Speter case TDOUBLE: 89749Speter if (c2 == TDOUBLE) 90749Speter return (1); 91749Speter #ifndef PI0 9214728Sthien if (c2 == TINT && divflg == FALSE && t != TR_NIL ) { 9314728Sthien divchk= TRUE; 94749Speter c1 = classify(rvalue(t, NLNIL , RREQ )); 9514728Sthien divchk = FALSE; 96749Speter if (c1 == TINT) { 97749Speter error("Type clash: real is incompatible with integer"); 98749Speter cerror("This resulted because you used '/' which always returns real rather"); 99749Speter cerror("than 'div' which divides integers and returns integers"); 10014728Sthien divflg = TRUE; 101749Speter return (NIL); 102749Speter } 103749Speter } 104749Speter #endif 105749Speter break; 106749Speter case TSCAL: 107749Speter if (c2 != TSCAL) 108749Speter break; 109749Speter if (scalar(p1) != scalar(p2)) { 110749Speter derror("Type clash: non-identical scalar types"); 111749Speter return (NIL); 112749Speter } 113749Speter return (1); 114749Speter case TSTR: 115749Speter if (c2 != TSTR) 116749Speter break; 117749Speter if (width(p1) != width(p2)) { 118749Speter derror("Type clash: unequal length strings"); 119749Speter return (NIL); 120749Speter } 121749Speter return (1); 122749Speter case TNIL: 123749Speter if (c2 != TPTR) 124749Speter break; 125749Speter return (1); 126749Speter case TFILE: 127749Speter if (c1 != c2) 128749Speter break; 129749Speter derror("Type clash: files not allowed in this context"); 130749Speter return (NIL); 131749Speter default: 132749Speter if (c1 != c2) 133749Speter break; 134749Speter if (p1 != p2) { 135749Speter derror("Type clash: non-identical %s types", clnames[c1]); 136749Speter return (NIL); 137749Speter } 138749Speter if (p1->nl_flags & NFILES) { 139749Speter derror("Type clash: %ss with file components not allowed in this context", clnames[c1]); 140749Speter return (NIL); 141749Speter } 142749Speter return (1); 143749Speter } 144749Speter derror("Type clash: %s is incompatible with %s", clnames[c1], clnames[c2]); 145749Speter return (NIL); 146749Speter } 147749Speter 148749Speter #ifndef PI0 14914728Sthien #ifndef PC 150749Speter /* 151749Speter * Rangechk generates code to 152749Speter * check if the type p on top 153749Speter * of the stack is in range for 154749Speter * assignment to a variable 155749Speter * of type q. 156749Speter */ 157749Speter rangechk(p, q) 158749Speter struct nl *p, *q; 159749Speter { 160749Speter register struct nl *rp; 16114728Sthien #ifdef OBJ 162749Speter register op; 163749Speter int wq, wrp; 16414728Sthien #endif 165749Speter 166749Speter if (opt('t') == 0) 167749Speter return; 168749Speter rp = p; 169749Speter if (rp == NIL) 170749Speter return; 171749Speter if (q == NIL) 172749Speter return; 173749Speter # ifdef OBJ 174749Speter /* 175749Speter * When op is 1 we are checking length 176749Speter * 4 numbers against length 2 bounds, 177749Speter * and adding it to the opcode forces 178749Speter * generation of appropriate tests. 179749Speter */ 180749Speter op = 0; 181749Speter wq = width(q); 182749Speter wrp = width(rp); 183749Speter op = wq != wrp && (wq == 4 || wrp == 4); 18415962Smckusick if (rp->class == TYPE || rp->class == CRANGE) 185749Speter rp = rp->type; 186749Speter switch (rp->class) { 187749Speter case RANGE: 188749Speter if (rp->range[0] != 0) { 189749Speter # ifndef DEBUG 190749Speter if (wrp <= 2) 19114728Sthien (void) put(3, O_RANG2+op, ( short ) rp->range[0], 192749Speter ( short ) rp->range[1]); 193749Speter else if (rp != nl+T4INT) 19414728Sthien (void) put(3, O_RANG4+op, rp->range[0], rp->range[1] ); 195749Speter # else 196749Speter if (!hp21mx) { 197749Speter if (wrp <= 2) 19814728Sthien (void) put(3, O_RANG2+op,( short ) rp->range[0], 199749Speter ( short ) rp->range[1]); 200749Speter else if (rp != nl+T4INT) 20114728Sthien (void) put(3, O_RANG4+op,rp->range[0], 202749Speter rp->range[1]); 203749Speter } else 204749Speter if (rp != nl+T2INT && rp != nl+T4INT) 20514728Sthien (void) put(3, O_RANG2+op,( short ) rp->range[0], 206749Speter ( short ) rp->range[1]); 207749Speter # endif 208749Speter break; 209749Speter } 210749Speter /* 211749Speter * Range whose lower bounds are 212749Speter * zero can be treated as scalars. 213749Speter */ 214749Speter case SCAL: 215749Speter if (wrp <= 2) 21614728Sthien (void) put(2, O_RSNG2+op, ( short ) rp->range[1]); 217749Speter else 21814728Sthien (void) put( 2 , O_RSNG4+op, rp->range[1]); 219749Speter break; 220749Speter default: 221749Speter panic("rangechk"); 222749Speter } 223749Speter # endif OBJ 224749Speter # ifdef PC 225749Speter /* 22610381Speter * pc uses precheck() and postcheck(). 227749Speter */ 22810381Speter panic("rangechk()"); 229749Speter # endif PC 230749Speter } 231749Speter #endif 232749Speter #endif 23314728Sthien #endif 234749Speter 235749Speter #ifdef PC 236749Speter /* 237749Speter * if type p requires a range check, 238749Speter * then put out the name of the checking function 239749Speter * for the beginning of a function call which is completed by postcheck. 240749Speter * (name1 is for a full check; name2 assumes a lower bound of zero) 241749Speter */ 242749Speter precheck( p , name1 , name2 ) 243749Speter struct nl *p; 244749Speter char *name1 , *name2; 245749Speter { 246749Speter 247749Speter if ( opt( 't' ) == 0 ) { 248749Speter return; 249749Speter } 250749Speter if ( p == NIL ) { 251749Speter return; 252749Speter } 253749Speter if ( p -> class == TYPE ) { 254749Speter p = p -> type; 255749Speter } 256749Speter switch ( p -> class ) { 25715962Smckusick case CRANGE: 25818454Sralph putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) 25915962Smckusick , name1); 26015962Smckusick break; 261749Speter case RANGE: 262749Speter if ( p != nl + T4INT ) { 26318454Sralph putleaf( PCC_ICON , 0 , 0 , 26418454Sralph PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ), 26510382Speter p -> range[0] != 0 ? name1 : name2 ); 266749Speter } 267749Speter break; 268749Speter case SCAL: 269749Speter /* 270749Speter * how could a scalar ever be out of range? 271749Speter */ 272749Speter break; 273749Speter default: 274749Speter panic( "precheck" ); 275749Speter break; 276749Speter } 277749Speter } 278749Speter 279749Speter /* 280749Speter * if type p requires a range check, 281749Speter * then put out the rest of the arguments of to the checking function 282749Speter * a call to which was started by precheck. 283749Speter * the first argument is what is being rangechecked (put out by rvalue), 284749Speter * the second argument is the lower bound of the range, 285749Speter * the third argument is the upper bound of the range. 286749Speter */ 28710382Speter postcheck(need, have) 28810382Speter struct nl *need; 28910382Speter struct nl *have; 29010382Speter { 29115962Smckusick struct nl *p; 292749Speter 29310382Speter if ( opt( 't' ) == 0 ) { 29410382Speter return; 29510382Speter } 29610382Speter if ( need == NIL ) { 29710382Speter return; 29810382Speter } 29910382Speter if ( need -> class == TYPE ) { 30010382Speter need = need -> type; 30110382Speter } 30210382Speter switch ( need -> class ) { 30310382Speter case RANGE: 30410382Speter if ( need != nl + T4INT ) { 30518454Sralph sconv(p2type(have), PCCT_INT); 30610382Speter if (need -> range[0] != 0 ) { 30718454Sralph putleaf( PCC_ICON , (int) need -> range[0] , 0 , PCCT_INT , 30814728Sthien (char *) 0 ); 30918454Sralph putop( PCC_CM , PCCT_INT ); 310749Speter } 31118454Sralph putleaf( PCC_ICON , (int) need -> range[1] , 0 , PCCT_INT , 31214728Sthien (char *) 0 ); 31318454Sralph putop( PCC_CM , PCCT_INT ); 31418454Sralph putop( PCC_CALL , PCCT_INT ); 31518454Sralph sconv(PCCT_INT, p2type(have)); 31610382Speter } 31710382Speter break; 31815962Smckusick case CRANGE: 31918454Sralph sconv(p2type(have), PCCT_INT); 32015962Smckusick p = need->nptr[0]; 32115962Smckusick putRV(p->symbol, (p->nl_block & 037), p->value[0], 32215962Smckusick p->extra_flags, p2type( p ) ); 32318454Sralph putop( PCC_CM , PCCT_INT ); 32415962Smckusick p = need->nptr[1]; 32515962Smckusick putRV(p->symbol, (p->nl_block & 037), p->value[0], 32615962Smckusick p->extra_flags, p2type( p ) ); 32718454Sralph putop( PCC_CM , PCCT_INT ); 32818454Sralph putop( PCC_CALL , PCCT_INT ); 32918454Sralph sconv(PCCT_INT, p2type(have)); 33015962Smckusick break; 33110382Speter case SCAL: 33210382Speter break; 33310382Speter default: 33410382Speter panic( "postcheck" ); 33510382Speter break; 336749Speter } 33710382Speter } 338749Speter #endif PC 339749Speter 340749Speter #ifdef DEBUG 341749Speter conv(dub) 342749Speter int *dub; 343749Speter { 344749Speter int newfp[2]; 34514728Sthien double *dp = ((double *) dub); 34614728Sthien long *lp = ((long *) dub); 347749Speter register int exp; 348749Speter long mant; 349749Speter 350749Speter newfp[0] = dub[0] & 0100000; 351749Speter newfp[1] = 0; 352749Speter if (*dp == 0.0) 353749Speter goto ret; 354749Speter exp = ((dub[0] >> 7) & 0377) - 0200; 355749Speter if (exp < 0) { 356749Speter newfp[1] = 1; 357749Speter exp = -exp; 358749Speter } 359749Speter if (exp > 63) 360749Speter exp = 63; 361749Speter dub[0] &= ~0177600; 362749Speter dub[0] |= 0200; 363749Speter mant = *lp; 364749Speter mant <<= 8; 365749Speter if (newfp[0]) 366749Speter mant = -mant; 367749Speter newfp[0] |= (mant >> 17) & 077777; 368749Speter newfp[1] |= (((int) (mant >> 1)) & 0177400) | (exp << 1); 369749Speter ret: 370749Speter dub[0] = newfp[0]; 371749Speter dub[1] = newfp[1]; 372749Speter } 373749Speter #endif 374