148116Sbostic /*-
2*62205Sbostic * Copyright (c) 1980, 1993
3*62205Sbostic * The Regents of the University of California. All rights reserved.
448116Sbostic *
548116Sbostic * %sccs.include.redist.c%
622160Sdist */
7749Speter
814728Sthien #ifndef lint
9*62205Sbostic static char sccsid[] = "@(#)conv.c 8.1 (Berkeley) 06/06/93";
1048116Sbostic #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
conv(dub)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