xref: /csrg-svn/usr.bin/pascal/src/conv.c (revision 749)
1*749Speter /* Copyright (c) 1979 Regents of the University of California */
2*749Speter 
3*749Speter static	char sccsid[] = "@(#)conv.c 1.1 08/27/80";
4*749Speter 
5*749Speter #include "whoami.h"
6*749Speter #ifdef PI
7*749Speter #include "0.h"
8*749Speter #include "opcode.h"
9*749Speter #ifdef PC
10*749Speter #   include	"pcops.h"
11*749Speter #endif PC
12*749Speter 
13*749Speter #ifndef PI0
14*749Speter /*
15*749Speter  * Convert a p1 into a p2.
16*749Speter  * Mostly used for different
17*749Speter  * length integers and "to real" conversions.
18*749Speter  */
19*749Speter convert(p1, p2)
20*749Speter 	struct nl *p1, *p2;
21*749Speter {
22*749Speter 	if (p1 == NIL || p2 == NIL)
23*749Speter 		return;
24*749Speter 	switch (width(p1) - width(p2)) {
25*749Speter 		case -7:
26*749Speter 		case -6:
27*749Speter 			put1(O_STOD);
28*749Speter 			return;
29*749Speter 		case -4:
30*749Speter 			put1(O_ITOD);
31*749Speter 			return;
32*749Speter 		case -3:
33*749Speter 		case -2:
34*749Speter 			put1(O_STOI);
35*749Speter 			return;
36*749Speter 		case -1:
37*749Speter 		case 0:
38*749Speter 		case 1:
39*749Speter 			return;
40*749Speter 		case 2:
41*749Speter 		case 3:
42*749Speter 			put1(O_ITOS);
43*749Speter 			return;
44*749Speter 		default:
45*749Speter 			panic("convert");
46*749Speter 	}
47*749Speter }
48*749Speter #endif
49*749Speter 
50*749Speter /*
51*749Speter  * Compat tells whether
52*749Speter  * p1 and p2 are compatible
53*749Speter  * types for an assignment like
54*749Speter  * context, i.e. value parameters,
55*749Speter  * indicies for 'in', etc.
56*749Speter  */
57*749Speter compat(p1, p2, t)
58*749Speter 	struct nl *p1, *p2;
59*749Speter {
60*749Speter 	register c1, c2;
61*749Speter 
62*749Speter 	c1 = classify(p1);
63*749Speter 	if (c1 == NIL)
64*749Speter 		return (NIL);
65*749Speter 	c2 = classify(p2);
66*749Speter 	if (c2 == NIL)
67*749Speter 		return (NIL);
68*749Speter 	switch (c1) {
69*749Speter 		case TBOOL:
70*749Speter 		case TCHAR:
71*749Speter 			if (c1 == c2)
72*749Speter 				return (1);
73*749Speter 			break;
74*749Speter 		case TINT:
75*749Speter 			if (c2 == TINT)
76*749Speter 				return (1);
77*749Speter 		case TDOUBLE:
78*749Speter 			if (c2 == TDOUBLE)
79*749Speter 				return (1);
80*749Speter #ifndef PI0
81*749Speter 			if (c2 == TINT && divflg == 0 && t != NIL ) {
82*749Speter 				divchk= 1;
83*749Speter 				c1 = classify(rvalue(t, NLNIL , RREQ ));
84*749Speter 				divchk = NIL;
85*749Speter 				if (c1 == TINT) {
86*749Speter 					error("Type clash: real is incompatible with integer");
87*749Speter 					cerror("This resulted because you used '/' which always returns real rather");
88*749Speter 					cerror("than 'div' which divides integers and returns integers");
89*749Speter 					divflg = 1;
90*749Speter 					return (NIL);
91*749Speter 				}
92*749Speter 			}
93*749Speter #endif
94*749Speter 			break;
95*749Speter 		case TSCAL:
96*749Speter 			if (c2 != TSCAL)
97*749Speter 				break;
98*749Speter 			if (scalar(p1) != scalar(p2)) {
99*749Speter 				derror("Type clash: non-identical scalar types");
100*749Speter 				return (NIL);
101*749Speter 			}
102*749Speter 			return (1);
103*749Speter 		case TSTR:
104*749Speter 			if (c2 != TSTR)
105*749Speter 				break;
106*749Speter 			if (width(p1) != width(p2)) {
107*749Speter 				derror("Type clash: unequal length strings");
108*749Speter 				return (NIL);
109*749Speter 			}
110*749Speter 			return (1);
111*749Speter 		case TNIL:
112*749Speter 			if (c2 != TPTR)
113*749Speter 				break;
114*749Speter 			return (1);
115*749Speter 		case TFILE:
116*749Speter 			if (c1 != c2)
117*749Speter 				break;
118*749Speter 			derror("Type clash: files not allowed in this context");
119*749Speter 			return (NIL);
120*749Speter 		default:
121*749Speter 			if (c1 != c2)
122*749Speter 				break;
123*749Speter 			if (p1 != p2) {
124*749Speter 				derror("Type clash: non-identical %s types", clnames[c1]);
125*749Speter 				return (NIL);
126*749Speter 			}
127*749Speter 			if (p1->nl_flags & NFILES) {
128*749Speter 				derror("Type clash: %ss with file components not allowed in this context", clnames[c1]);
129*749Speter 				return (NIL);
130*749Speter 			}
131*749Speter 			return (1);
132*749Speter 	}
133*749Speter 	derror("Type clash: %s is incompatible with %s", clnames[c1], clnames[c2]);
134*749Speter 	return (NIL);
135*749Speter }
136*749Speter 
137*749Speter #ifndef PI0
138*749Speter /*
139*749Speter  * Rangechk generates code to
140*749Speter  * check if the type p on top
141*749Speter  * of the stack is in range for
142*749Speter  * assignment to a variable
143*749Speter  * of type q.
144*749Speter  */
145*749Speter rangechk(p, q)
146*749Speter 	struct nl *p, *q;
147*749Speter {
148*749Speter 	register struct nl *rp;
149*749Speter 	register op;
150*749Speter 	int wq, wrp;
151*749Speter 
152*749Speter 	if (opt('t') == 0)
153*749Speter 		return;
154*749Speter 	rp = p;
155*749Speter 	if (rp == NIL)
156*749Speter 		return;
157*749Speter 	if (q == NIL)
158*749Speter 		return;
159*749Speter #	ifdef OBJ
160*749Speter 	    /*
161*749Speter 	     * When op is 1 we are checking length
162*749Speter 	     * 4 numbers against length 2 bounds,
163*749Speter 	     * and adding it to the opcode forces
164*749Speter 	     * generation of appropriate tests.
165*749Speter 	     */
166*749Speter 	    op = 0;
167*749Speter 	    wq = width(q);
168*749Speter 	    wrp = width(rp);
169*749Speter 	    op = wq != wrp && (wq == 4 || wrp == 4);
170*749Speter 	    if (rp->class == TYPE)
171*749Speter 		    rp = rp->type;
172*749Speter 	    switch (rp->class) {
173*749Speter 	    case RANGE:
174*749Speter 		    if (rp->range[0] != 0) {
175*749Speter #    		    ifndef DEBUG
176*749Speter 			    if (wrp <= 2)
177*749Speter 				    put(3, O_RANG2+op, ( short ) rp->range[0],
178*749Speter 						     ( short ) rp->range[1]);
179*749Speter 			    else if (rp != nl+T4INT)
180*749Speter 				    put(3, O_RANG4+op, rp->range[0], rp->range[1] );
181*749Speter #    		    else
182*749Speter 			    if (!hp21mx) {
183*749Speter 				    if (wrp <= 2)
184*749Speter 					    put(3, O_RANG2+op,( short ) rp->range[0],
185*749Speter 							    ( short ) rp->range[1]);
186*749Speter 				    else if (rp != nl+T4INT)
187*749Speter 					    put(3, O_RANG4+op,rp->range[0],
188*749Speter 							     rp->range[1]);
189*749Speter 			    } else
190*749Speter 				    if (rp != nl+T2INT && rp != nl+T4INT)
191*749Speter 					    put(3, O_RANG2+op,( short ) rp->range[0],
192*749Speter 							    ( short ) rp->range[1]);
193*749Speter #    		    endif
194*749Speter 			break;
195*749Speter 		    }
196*749Speter 		    /*
197*749Speter 		     * Range whose lower bounds are
198*749Speter 		     * zero can be treated as scalars.
199*749Speter 		     */
200*749Speter 	    case SCAL:
201*749Speter 		    if (wrp <= 2)
202*749Speter 			    put(2, O_RSNG2+op, ( short ) rp->range[1]);
203*749Speter 		    else
204*749Speter 			    put( 2 , O_RSNG4+op, rp->range[1]);
205*749Speter 		    break;
206*749Speter 	    default:
207*749Speter 		    panic("rangechk");
208*749Speter 	    }
209*749Speter #	endif OBJ
210*749Speter #	ifdef PC
211*749Speter 		/*
212*749Speter 		 * what i want to do is make this and some other stuff
213*749Speter 		 * arguments to a function call, which will do the rangecheck,
214*749Speter 		 * and return the value of the current expression, or abort
215*749Speter 		 * if the rangecheck fails.
216*749Speter 		 * probably i need one rangecheck routine to return each c-type
217*749Speter 		 * of value.
218*749Speter 		 * also, i haven't figured out what the `other stuff' is.
219*749Speter 		 */
220*749Speter 	    putprintf( "#	call rangecheck" , 0 );
221*749Speter #	endif PC
222*749Speter }
223*749Speter #endif
224*749Speter #endif
225*749Speter 
226*749Speter #ifdef PC
227*749Speter     /*
228*749Speter      *	if type p requires a range check,
229*749Speter      *	    then put out the name of the checking function
230*749Speter      *	for the beginning of a function call which is completed by postcheck.
231*749Speter      *  (name1 is for a full check; name2 assumes a lower bound of zero)
232*749Speter      */
233*749Speter precheck( p , name1 , name2 )
234*749Speter     struct nl	*p;
235*749Speter     char	*name1 , *name2;
236*749Speter     {
237*749Speter 
238*749Speter 	if ( opt( 't' ) == 0 ) {
239*749Speter 	    return;
240*749Speter 	}
241*749Speter 	if ( p == NIL ) {
242*749Speter 	    return;
243*749Speter 	}
244*749Speter 	if ( p -> class == TYPE ) {
245*749Speter 	    p = p -> type;
246*749Speter 	}
247*749Speter 	switch ( p -> class ) {
248*749Speter 	    case RANGE:
249*749Speter 		if ( p != nl + T4INT ) {
250*749Speter 		    putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR )
251*749Speter 			    , p -> range[0] != 0 ? name1 : name2 );
252*749Speter 		}
253*749Speter 		break;
254*749Speter 	    case SCAL:
255*749Speter 		    /*
256*749Speter 		     *	how could a scalar ever be out of range?
257*749Speter 		     */
258*749Speter 		break;
259*749Speter 	    default:
260*749Speter 		panic( "precheck" );
261*749Speter 		break;
262*749Speter 	}
263*749Speter     }
264*749Speter 
265*749Speter     /*
266*749Speter      *	if type p requires a range check,
267*749Speter      *	    then put out the rest of the arguments of to the checking function
268*749Speter      *	a call to which was started by precheck.
269*749Speter      *	the first argument is what is being rangechecked (put out by rvalue),
270*749Speter      *	the second argument is the lower bound of the range,
271*749Speter      *	the third argument is the upper bound of the range.
272*749Speter      */
273*749Speter postcheck( p )
274*749Speter     struct nl	*p;
275*749Speter     {
276*749Speter 
277*749Speter 	if ( opt( 't' ) == 0 ) {
278*749Speter 	    return;
279*749Speter 	}
280*749Speter 	if ( p == NIL ) {
281*749Speter 	    return;
282*749Speter 	}
283*749Speter 	if ( p -> class == TYPE ) {
284*749Speter 	    p = p -> type;
285*749Speter 	}
286*749Speter 	switch ( p -> class ) {
287*749Speter 	    case RANGE:
288*749Speter 		if ( p != nl + T4INT ) {
289*749Speter 		    if (p -> range[0] != 0 ) {
290*749Speter 			putleaf( P2ICON , p -> range[0] , 0 , P2INT , 0 );
291*749Speter 			putop( P2LISTOP , P2INT );
292*749Speter 		    }
293*749Speter 		    putleaf( P2ICON , p -> range[1] , 0 , P2INT , 0 );
294*749Speter 		    putop( P2LISTOP , P2INT );
295*749Speter 		    putop( P2CALL , P2INT );
296*749Speter 		}
297*749Speter 		break;
298*749Speter 	    case SCAL:
299*749Speter 		break;
300*749Speter 	    default:
301*749Speter 		panic( "postcheck" );
302*749Speter 		break;
303*749Speter 	}
304*749Speter     }
305*749Speter #endif PC
306*749Speter 
307*749Speter #ifdef DEBUG
308*749Speter conv(dub)
309*749Speter 	int *dub;
310*749Speter {
311*749Speter 	int newfp[2];
312*749Speter 	double *dp = dub;
313*749Speter 	long *lp = dub;
314*749Speter 	register int exp;
315*749Speter 	long mant;
316*749Speter 
317*749Speter 	newfp[0] = dub[0] & 0100000;
318*749Speter 	newfp[1] = 0;
319*749Speter 	if (*dp == 0.0)
320*749Speter 		goto ret;
321*749Speter 	exp = ((dub[0] >> 7) & 0377) - 0200;
322*749Speter 	if (exp < 0) {
323*749Speter 		newfp[1] = 1;
324*749Speter 		exp = -exp;
325*749Speter 	}
326*749Speter 	if (exp > 63)
327*749Speter 		exp = 63;
328*749Speter 	dub[0] &= ~0177600;
329*749Speter 	dub[0] |= 0200;
330*749Speter 	mant = *lp;
331*749Speter 	mant <<= 8;
332*749Speter 	if (newfp[0])
333*749Speter 		mant = -mant;
334*749Speter 	newfp[0] |= (mant >> 17) & 077777;
335*749Speter 	newfp[1] |= (((int) (mant >> 1)) & 0177400) | (exp << 1);
336*749Speter ret:
337*749Speter 	dub[0] = newfp[0];
338*749Speter 	dub[1] = newfp[1];
339*749Speter }
340*749Speter #endif
341