1*22160Sdist /* 2*22160Sdist * Copyright (c) 1980 Regents of the University of California. 3*22160Sdist * All rights reserved. The Berkeley software License Agreement 4*22160Sdist * specifies the terms and conditions for redistribution. 5*22160Sdist */ 6749Speter 714728Sthien #ifndef lint 8*22160Sdist static char sccsid[] = "@(#)conv.c 5.1 (Berkeley) 06/05/85"; 9*22160Sdist #endif not lint 10749Speter 11749Speter #include "whoami.h" 12749Speter #ifdef PI 13749Speter #include "0.h" 14749Speter #include "opcode.h" 15749Speter #ifdef PC 1618454Sralph # include <pcc.h> 17749Speter #endif PC 1814728Sthien #include "tree_ty.h" 19749Speter 2014728Sthien #ifndef PC 21749Speter #ifndef PI0 22749Speter /* 23749Speter * Convert a p1 into a p2. 24749Speter * Mostly used for different 25749Speter * length integers and "to real" conversions. 26749Speter */ 27749Speter convert(p1, p2) 28749Speter struct nl *p1, *p2; 29749Speter { 3014728Sthien if (p1 == NLNIL || p2 == NLNIL) 31749Speter return; 32749Speter switch (width(p1) - width(p2)) { 33749Speter case -7: 34749Speter case -6: 3514728Sthien (void) put(1, O_STOD); 36749Speter return; 37749Speter case -4: 3814728Sthien (void) put(1, O_ITOD); 39749Speter return; 40749Speter case -3: 41749Speter case -2: 4214728Sthien (void) put(1, O_STOI); 43749Speter return; 44749Speter case -1: 45749Speter case 0: 46749Speter case 1: 47749Speter return; 48749Speter case 2: 49749Speter case 3: 5014728Sthien (void) put(1, O_ITOS); 51749Speter return; 52749Speter default: 53749Speter panic("convert"); 54749Speter } 55749Speter } 5614728Sthien #endif 5714728Sthien #endif PC 58749Speter 59749Speter /* 60749Speter * Compat tells whether 61749Speter * p1 and p2 are compatible 62749Speter * types for an assignment like 63749Speter * context, i.e. value parameters, 64749Speter * indicies for 'in', etc. 65749Speter */ 66749Speter compat(p1, p2, t) 67749Speter struct nl *p1, *p2; 6814728Sthien struct tnode *t; 69749Speter { 70749Speter register c1, c2; 71749Speter 72749Speter c1 = classify(p1); 73749Speter if (c1 == NIL) 74749Speter return (NIL); 75749Speter c2 = classify(p2); 76749Speter if (c2 == NIL) 77749Speter return (NIL); 78749Speter switch (c1) { 79749Speter case TBOOL: 80749Speter case TCHAR: 81749Speter if (c1 == c2) 82749Speter return (1); 83749Speter break; 84749Speter case TINT: 85749Speter if (c2 == TINT) 86749Speter return (1); 87749Speter case TDOUBLE: 88749Speter if (c2 == TDOUBLE) 89749Speter return (1); 90749Speter #ifndef PI0 9114728Sthien if (c2 == TINT && divflg == FALSE && t != TR_NIL ) { 9214728Sthien divchk= TRUE; 93749Speter c1 = classify(rvalue(t, NLNIL , RREQ )); 9414728Sthien divchk = FALSE; 95749Speter if (c1 == TINT) { 96749Speter error("Type clash: real is incompatible with integer"); 97749Speter cerror("This resulted because you used '/' which always returns real rather"); 98749Speter cerror("than 'div' which divides integers and returns integers"); 9914728Sthien divflg = TRUE; 100749Speter return (NIL); 101749Speter } 102749Speter } 103749Speter #endif 104749Speter break; 105749Speter case TSCAL: 106749Speter if (c2 != TSCAL) 107749Speter break; 108749Speter if (scalar(p1) != scalar(p2)) { 109749Speter derror("Type clash: non-identical scalar types"); 110749Speter return (NIL); 111749Speter } 112749Speter return (1); 113749Speter case TSTR: 114749Speter if (c2 != TSTR) 115749Speter break; 116749Speter if (width(p1) != width(p2)) { 117749Speter derror("Type clash: unequal length strings"); 118749Speter return (NIL); 119749Speter } 120749Speter return (1); 121749Speter case TNIL: 122749Speter if (c2 != TPTR) 123749Speter break; 124749Speter return (1); 125749Speter case TFILE: 126749Speter if (c1 != c2) 127749Speter break; 128749Speter derror("Type clash: files not allowed in this context"); 129749Speter return (NIL); 130749Speter default: 131749Speter if (c1 != c2) 132749Speter break; 133749Speter if (p1 != p2) { 134749Speter derror("Type clash: non-identical %s types", clnames[c1]); 135749Speter return (NIL); 136749Speter } 137749Speter if (p1->nl_flags & NFILES) { 138749Speter derror("Type clash: %ss with file components not allowed in this context", clnames[c1]); 139749Speter return (NIL); 140749Speter } 141749Speter return (1); 142749Speter } 143749Speter derror("Type clash: %s is incompatible with %s", clnames[c1], clnames[c2]); 144749Speter return (NIL); 145749Speter } 146749Speter 147749Speter #ifndef PI0 14814728Sthien #ifndef PC 149749Speter /* 150749Speter * Rangechk generates code to 151749Speter * check if the type p on top 152749Speter * of the stack is in range for 153749Speter * assignment to a variable 154749Speter * of type q. 155749Speter */ 156749Speter rangechk(p, q) 157749Speter struct nl *p, *q; 158749Speter { 159749Speter register struct nl *rp; 16014728Sthien #ifdef OBJ 161749Speter register op; 162749Speter int wq, wrp; 16314728Sthien #endif 164749Speter 165749Speter if (opt('t') == 0) 166749Speter return; 167749Speter rp = p; 168749Speter if (rp == NIL) 169749Speter return; 170749Speter if (q == NIL) 171749Speter return; 172749Speter # ifdef OBJ 173749Speter /* 174749Speter * When op is 1 we are checking length 175749Speter * 4 numbers against length 2 bounds, 176749Speter * and adding it to the opcode forces 177749Speter * generation of appropriate tests. 178749Speter */ 179749Speter op = 0; 180749Speter wq = width(q); 181749Speter wrp = width(rp); 182749Speter op = wq != wrp && (wq == 4 || wrp == 4); 18315962Smckusick if (rp->class == TYPE || rp->class == CRANGE) 184749Speter rp = rp->type; 185749Speter switch (rp->class) { 186749Speter case RANGE: 187749Speter if (rp->range[0] != 0) { 188749Speter # ifndef DEBUG 189749Speter if (wrp <= 2) 19014728Sthien (void) put(3, O_RANG2+op, ( short ) rp->range[0], 191749Speter ( short ) rp->range[1]); 192749Speter else if (rp != nl+T4INT) 19314728Sthien (void) put(3, O_RANG4+op, rp->range[0], rp->range[1] ); 194749Speter # else 195749Speter if (!hp21mx) { 196749Speter if (wrp <= 2) 19714728Sthien (void) put(3, O_RANG2+op,( short ) rp->range[0], 198749Speter ( short ) rp->range[1]); 199749Speter else if (rp != nl+T4INT) 20014728Sthien (void) put(3, O_RANG4+op,rp->range[0], 201749Speter rp->range[1]); 202749Speter } else 203749Speter if (rp != nl+T2INT && rp != nl+T4INT) 20414728Sthien (void) put(3, O_RANG2+op,( short ) rp->range[0], 205749Speter ( short ) rp->range[1]); 206749Speter # endif 207749Speter break; 208749Speter } 209749Speter /* 210749Speter * Range whose lower bounds are 211749Speter * zero can be treated as scalars. 212749Speter */ 213749Speter case SCAL: 214749Speter if (wrp <= 2) 21514728Sthien (void) put(2, O_RSNG2+op, ( short ) rp->range[1]); 216749Speter else 21714728Sthien (void) put( 2 , O_RSNG4+op, rp->range[1]); 218749Speter break; 219749Speter default: 220749Speter panic("rangechk"); 221749Speter } 222749Speter # endif OBJ 223749Speter # ifdef PC 224749Speter /* 22510381Speter * pc uses precheck() and postcheck(). 226749Speter */ 22710381Speter panic("rangechk()"); 228749Speter # endif PC 229749Speter } 230749Speter #endif 231749Speter #endif 23214728Sthien #endif 233749Speter 234749Speter #ifdef PC 235749Speter /* 236749Speter * if type p requires a range check, 237749Speter * then put out the name of the checking function 238749Speter * for the beginning of a function call which is completed by postcheck. 239749Speter * (name1 is for a full check; name2 assumes a lower bound of zero) 240749Speter */ 241749Speter precheck( p , name1 , name2 ) 242749Speter struct nl *p; 243749Speter char *name1 , *name2; 244749Speter { 245749Speter 246749Speter if ( opt( 't' ) == 0 ) { 247749Speter return; 248749Speter } 249749Speter if ( p == NIL ) { 250749Speter return; 251749Speter } 252749Speter if ( p -> class == TYPE ) { 253749Speter p = p -> type; 254749Speter } 255749Speter switch ( p -> class ) { 25615962Smckusick case CRANGE: 25718454Sralph putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) 25815962Smckusick , name1); 25915962Smckusick break; 260749Speter case RANGE: 261749Speter if ( p != nl + T4INT ) { 26218454Sralph putleaf( PCC_ICON , 0 , 0 , 26318454Sralph PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ), 26410382Speter p -> range[0] != 0 ? name1 : name2 ); 265749Speter } 266749Speter break; 267749Speter case SCAL: 268749Speter /* 269749Speter * how could a scalar ever be out of range? 270749Speter */ 271749Speter break; 272749Speter default: 273749Speter panic( "precheck" ); 274749Speter break; 275749Speter } 276749Speter } 277749Speter 278749Speter /* 279749Speter * if type p requires a range check, 280749Speter * then put out the rest of the arguments of to the checking function 281749Speter * a call to which was started by precheck. 282749Speter * the first argument is what is being rangechecked (put out by rvalue), 283749Speter * the second argument is the lower bound of the range, 284749Speter * the third argument is the upper bound of the range. 285749Speter */ 28610382Speter postcheck(need, have) 28710382Speter struct nl *need; 28810382Speter struct nl *have; 28910382Speter { 29015962Smckusick struct nl *p; 291749Speter 29210382Speter if ( opt( 't' ) == 0 ) { 29310382Speter return; 29410382Speter } 29510382Speter if ( need == NIL ) { 29610382Speter return; 29710382Speter } 29810382Speter if ( need -> class == TYPE ) { 29910382Speter need = need -> type; 30010382Speter } 30110382Speter switch ( need -> class ) { 30210382Speter case RANGE: 30310382Speter if ( need != nl + T4INT ) { 30418454Sralph sconv(p2type(have), PCCT_INT); 30510382Speter if (need -> range[0] != 0 ) { 30618454Sralph putleaf( PCC_ICON , (int) need -> range[0] , 0 , PCCT_INT , 30714728Sthien (char *) 0 ); 30818454Sralph putop( PCC_CM , PCCT_INT ); 309749Speter } 31018454Sralph putleaf( PCC_ICON , (int) need -> range[1] , 0 , PCCT_INT , 31114728Sthien (char *) 0 ); 31218454Sralph putop( PCC_CM , PCCT_INT ); 31318454Sralph putop( PCC_CALL , PCCT_INT ); 31418454Sralph sconv(PCCT_INT, p2type(have)); 31510382Speter } 31610382Speter break; 31715962Smckusick case CRANGE: 31818454Sralph sconv(p2type(have), PCCT_INT); 31915962Smckusick p = need->nptr[0]; 32015962Smckusick putRV(p->symbol, (p->nl_block & 037), p->value[0], 32115962Smckusick p->extra_flags, p2type( p ) ); 32218454Sralph putop( PCC_CM , PCCT_INT ); 32315962Smckusick p = need->nptr[1]; 32415962Smckusick putRV(p->symbol, (p->nl_block & 037), p->value[0], 32515962Smckusick p->extra_flags, p2type( p ) ); 32618454Sralph putop( PCC_CM , PCCT_INT ); 32718454Sralph putop( PCC_CALL , PCCT_INT ); 32818454Sralph sconv(PCCT_INT, p2type(have)); 32915962Smckusick break; 33010382Speter case SCAL: 33110382Speter break; 33210382Speter default: 33310382Speter panic( "postcheck" ); 33410382Speter break; 335749Speter } 33610382Speter } 337749Speter #endif PC 338749Speter 339749Speter #ifdef DEBUG 340749Speter conv(dub) 341749Speter int *dub; 342749Speter { 343749Speter int newfp[2]; 34414728Sthien double *dp = ((double *) dub); 34514728Sthien long *lp = ((long *) dub); 346749Speter register int exp; 347749Speter long mant; 348749Speter 349749Speter newfp[0] = dub[0] & 0100000; 350749Speter newfp[1] = 0; 351749Speter if (*dp == 0.0) 352749Speter goto ret; 353749Speter exp = ((dub[0] >> 7) & 0377) - 0200; 354749Speter if (exp < 0) { 355749Speter newfp[1] = 1; 356749Speter exp = -exp; 357749Speter } 358749Speter if (exp > 63) 359749Speter exp = 63; 360749Speter dub[0] &= ~0177600; 361749Speter dub[0] |= 0200; 362749Speter mant = *lp; 363749Speter mant <<= 8; 364749Speter if (newfp[0]) 365749Speter mant = -mant; 366749Speter newfp[0] |= (mant >> 17) & 077777; 367749Speter newfp[1] |= (((int) (mant >> 1)) & 0177400) | (exp << 1); 368749Speter ret: 369749Speter dub[0] = newfp[0]; 370749Speter dub[1] = newfp[1]; 371749Speter } 372749Speter #endif 373