xref: /csrg-svn/usr.bin/pascal/src/conv.c (revision 10382)
1749Speter /* Copyright (c) 1979 Regents of the University of California */
2749Speter 
3*10382Speter static char sccsid[] = "@(#)conv.c 1.4 01/17/83";
4749Speter 
5749Speter #include "whoami.h"
6749Speter #ifdef PI
7749Speter #include "0.h"
8749Speter #include "opcode.h"
9749Speter #ifdef PC
10749Speter #   include	"pcops.h"
11749Speter #endif PC
12749Speter 
13749Speter #ifndef PI0
14749Speter /*
15749Speter  * Convert a p1 into a p2.
16749Speter  * Mostly used for different
17749Speter  * length integers and "to real" conversions.
18749Speter  */
19749Speter convert(p1, p2)
20749Speter 	struct nl *p1, *p2;
21749Speter {
22749Speter 	if (p1 == NIL || p2 == NIL)
23749Speter 		return;
24749Speter 	switch (width(p1) - width(p2)) {
25749Speter 		case -7:
26749Speter 		case -6:
273072Smckusic 			put(1, O_STOD);
28749Speter 			return;
29749Speter 		case -4:
303072Smckusic 			put(1, O_ITOD);
31749Speter 			return;
32749Speter 		case -3:
33749Speter 		case -2:
343072Smckusic 			put(1, O_STOI);
35749Speter 			return;
36749Speter 		case -1:
37749Speter 		case 0:
38749Speter 		case 1:
39749Speter 			return;
40749Speter 		case 2:
41749Speter 		case 3:
423072Smckusic 			put(1, O_ITOS);
43749Speter 			return;
44749Speter 		default:
45749Speter 			panic("convert");
46749Speter 	}
47749Speter }
48749Speter #endif
49749Speter 
50749Speter /*
51749Speter  * Compat tells whether
52749Speter  * p1 and p2 are compatible
53749Speter  * types for an assignment like
54749Speter  * context, i.e. value parameters,
55749Speter  * indicies for 'in', etc.
56749Speter  */
57749Speter compat(p1, p2, t)
58749Speter 	struct nl *p1, *p2;
59749Speter {
60749Speter 	register c1, c2;
61749Speter 
62749Speter 	c1 = classify(p1);
63749Speter 	if (c1 == NIL)
64749Speter 		return (NIL);
65749Speter 	c2 = classify(p2);
66749Speter 	if (c2 == NIL)
67749Speter 		return (NIL);
68749Speter 	switch (c1) {
69749Speter 		case TBOOL:
70749Speter 		case TCHAR:
71749Speter 			if (c1 == c2)
72749Speter 				return (1);
73749Speter 			break;
74749Speter 		case TINT:
75749Speter 			if (c2 == TINT)
76749Speter 				return (1);
77749Speter 		case TDOUBLE:
78749Speter 			if (c2 == TDOUBLE)
79749Speter 				return (1);
80749Speter #ifndef PI0
81749Speter 			if (c2 == TINT && divflg == 0 && t != NIL ) {
82749Speter 				divchk= 1;
83749Speter 				c1 = classify(rvalue(t, NLNIL , RREQ ));
84749Speter 				divchk = NIL;
85749Speter 				if (c1 == TINT) {
86749Speter 					error("Type clash: real is incompatible with integer");
87749Speter 					cerror("This resulted because you used '/' which always returns real rather");
88749Speter 					cerror("than 'div' which divides integers and returns integers");
89749Speter 					divflg = 1;
90749Speter 					return (NIL);
91749Speter 				}
92749Speter 			}
93749Speter #endif
94749Speter 			break;
95749Speter 		case TSCAL:
96749Speter 			if (c2 != TSCAL)
97749Speter 				break;
98749Speter 			if (scalar(p1) != scalar(p2)) {
99749Speter 				derror("Type clash: non-identical scalar types");
100749Speter 				return (NIL);
101749Speter 			}
102749Speter 			return (1);
103749Speter 		case TSTR:
104749Speter 			if (c2 != TSTR)
105749Speter 				break;
106749Speter 			if (width(p1) != width(p2)) {
107749Speter 				derror("Type clash: unequal length strings");
108749Speter 				return (NIL);
109749Speter 			}
110749Speter 			return (1);
111749Speter 		case TNIL:
112749Speter 			if (c2 != TPTR)
113749Speter 				break;
114749Speter 			return (1);
115749Speter 		case TFILE:
116749Speter 			if (c1 != c2)
117749Speter 				break;
118749Speter 			derror("Type clash: files not allowed in this context");
119749Speter 			return (NIL);
120749Speter 		default:
121749Speter 			if (c1 != c2)
122749Speter 				break;
123749Speter 			if (p1 != p2) {
124749Speter 				derror("Type clash: non-identical %s types", clnames[c1]);
125749Speter 				return (NIL);
126749Speter 			}
127749Speter 			if (p1->nl_flags & NFILES) {
128749Speter 				derror("Type clash: %ss with file components not allowed in this context", clnames[c1]);
129749Speter 				return (NIL);
130749Speter 			}
131749Speter 			return (1);
132749Speter 	}
133749Speter 	derror("Type clash: %s is incompatible with %s", clnames[c1], clnames[c2]);
134749Speter 	return (NIL);
135749Speter }
136749Speter 
137749Speter #ifndef PI0
138749Speter /*
139749Speter  * Rangechk generates code to
140749Speter  * check if the type p on top
141749Speter  * of the stack is in range for
142749Speter  * assignment to a variable
143749Speter  * of type q.
144749Speter  */
145749Speter rangechk(p, q)
146749Speter 	struct nl *p, *q;
147749Speter {
148749Speter 	register struct nl *rp;
149749Speter 	register op;
150749Speter 	int wq, wrp;
151749Speter 
152749Speter 	if (opt('t') == 0)
153749Speter 		return;
154749Speter 	rp = p;
155749Speter 	if (rp == NIL)
156749Speter 		return;
157749Speter 	if (q == NIL)
158749Speter 		return;
159749Speter #	ifdef OBJ
160749Speter 	    /*
161749Speter 	     * When op is 1 we are checking length
162749Speter 	     * 4 numbers against length 2 bounds,
163749Speter 	     * and adding it to the opcode forces
164749Speter 	     * generation of appropriate tests.
165749Speter 	     */
166749Speter 	    op = 0;
167749Speter 	    wq = width(q);
168749Speter 	    wrp = width(rp);
169749Speter 	    op = wq != wrp && (wq == 4 || wrp == 4);
170749Speter 	    if (rp->class == TYPE)
171749Speter 		    rp = rp->type;
172749Speter 	    switch (rp->class) {
173749Speter 	    case RANGE:
174749Speter 		    if (rp->range[0] != 0) {
175749Speter #    		    ifndef DEBUG
176749Speter 			    if (wrp <= 2)
177749Speter 				    put(3, O_RANG2+op, ( short ) rp->range[0],
178749Speter 						     ( short ) rp->range[1]);
179749Speter 			    else if (rp != nl+T4INT)
180749Speter 				    put(3, O_RANG4+op, rp->range[0], rp->range[1] );
181749Speter #    		    else
182749Speter 			    if (!hp21mx) {
183749Speter 				    if (wrp <= 2)
184749Speter 					    put(3, O_RANG2+op,( short ) rp->range[0],
185749Speter 							    ( short ) rp->range[1]);
186749Speter 				    else if (rp != nl+T4INT)
187749Speter 					    put(3, O_RANG4+op,rp->range[0],
188749Speter 							     rp->range[1]);
189749Speter 			    } else
190749Speter 				    if (rp != nl+T2INT && rp != nl+T4INT)
191749Speter 					    put(3, O_RANG2+op,( short ) rp->range[0],
192749Speter 							    ( short ) rp->range[1]);
193749Speter #    		    endif
194749Speter 			break;
195749Speter 		    }
196749Speter 		    /*
197749Speter 		     * Range whose lower bounds are
198749Speter 		     * zero can be treated as scalars.
199749Speter 		     */
200749Speter 	    case SCAL:
201749Speter 		    if (wrp <= 2)
202749Speter 			    put(2, O_RSNG2+op, ( short ) rp->range[1]);
203749Speter 		    else
204749Speter 			    put( 2 , O_RSNG4+op, rp->range[1]);
205749Speter 		    break;
206749Speter 	    default:
207749Speter 		    panic("rangechk");
208749Speter 	    }
209749Speter #	endif OBJ
210749Speter #	ifdef PC
211749Speter 		/*
21210381Speter 		 *	pc uses precheck() and postcheck().
213749Speter 		 */
21410381Speter 	    panic("rangechk()");
215749Speter #	endif PC
216749Speter }
217749Speter #endif
218749Speter #endif
219749Speter 
220749Speter #ifdef PC
221749Speter     /*
222749Speter      *	if type p requires a range check,
223749Speter      *	    then put out the name of the checking function
224749Speter      *	for the beginning of a function call which is completed by postcheck.
225749Speter      *  (name1 is for a full check; name2 assumes a lower bound of zero)
226749Speter      */
227749Speter precheck( p , name1 , name2 )
228749Speter     struct nl	*p;
229749Speter     char	*name1 , *name2;
230749Speter     {
231749Speter 
232749Speter 	if ( opt( 't' ) == 0 ) {
233749Speter 	    return;
234749Speter 	}
235749Speter 	if ( p == NIL ) {
236749Speter 	    return;
237749Speter 	}
238749Speter 	if ( p -> class == TYPE ) {
239749Speter 	    p = p -> type;
240749Speter 	}
241749Speter 	switch ( p -> class ) {
242749Speter 	    case RANGE:
243749Speter 		if ( p != nl + T4INT ) {
244*10382Speter 		    putleaf( P2ICON , 0 , 0 ,
245*10382Speter 			    ADDTYPE( P2FTN | P2INT , P2PTR ),
246*10382Speter 			    p -> range[0] != 0 ? name1 : name2 );
247749Speter 		}
248749Speter 		break;
249749Speter 	    case SCAL:
250749Speter 		    /*
251749Speter 		     *	how could a scalar ever be out of range?
252749Speter 		     */
253749Speter 		break;
254749Speter 	    default:
255749Speter 		panic( "precheck" );
256749Speter 		break;
257749Speter 	}
258749Speter     }
259749Speter 
260749Speter     /*
261749Speter      *	if type p requires a range check,
262749Speter      *	    then put out the rest of the arguments of to the checking function
263749Speter      *	a call to which was started by precheck.
264749Speter      *	the first argument is what is being rangechecked (put out by rvalue),
265749Speter      *	the second argument is the lower bound of the range,
266749Speter      *	the third argument is the upper bound of the range.
267749Speter      */
268*10382Speter postcheck(need, have)
269*10382Speter     struct nl	*need;
270*10382Speter     struct nl	*have;
271*10382Speter {
272749Speter 
273*10382Speter     if ( opt( 't' ) == 0 ) {
274*10382Speter 	return;
275*10382Speter     }
276*10382Speter     if ( need == NIL ) {
277*10382Speter 	return;
278*10382Speter     }
279*10382Speter     if ( need -> class == TYPE ) {
280*10382Speter 	need = need -> type;
281*10382Speter     }
282*10382Speter     switch ( need -> class ) {
283*10382Speter 	case RANGE:
284*10382Speter 	    if ( need != nl + T4INT ) {
285*10382Speter 		sconv(p2type(have), P2INT);
286*10382Speter 		if (need -> range[0] != 0 ) {
287*10382Speter 		    putleaf( P2ICON , need -> range[0] , 0 , P2INT , 0 );
288749Speter 		    putop( P2LISTOP , P2INT );
289749Speter 		}
290*10382Speter 		putleaf( P2ICON , need -> range[1] , 0 , P2INT , 0 );
291*10382Speter 		putop( P2LISTOP , P2INT );
292*10382Speter 		putop( P2CALL , P2INT );
293*10382Speter 		sconv(P2INT, p2type(have));
294*10382Speter 	    }
295*10382Speter 	    break;
296*10382Speter 	case SCAL:
297*10382Speter 	    break;
298*10382Speter 	default:
299*10382Speter 	    panic( "postcheck" );
300*10382Speter 	    break;
301749Speter     }
302*10382Speter }
303749Speter #endif PC
304749Speter 
305749Speter #ifdef DEBUG
306749Speter conv(dub)
307749Speter 	int *dub;
308749Speter {
309749Speter 	int newfp[2];
310749Speter 	double *dp = dub;
311749Speter 	long *lp = dub;
312749Speter 	register int exp;
313749Speter 	long mant;
314749Speter 
315749Speter 	newfp[0] = dub[0] & 0100000;
316749Speter 	newfp[1] = 0;
317749Speter 	if (*dp == 0.0)
318749Speter 		goto ret;
319749Speter 	exp = ((dub[0] >> 7) & 0377) - 0200;
320749Speter 	if (exp < 0) {
321749Speter 		newfp[1] = 1;
322749Speter 		exp = -exp;
323749Speter 	}
324749Speter 	if (exp > 63)
325749Speter 		exp = 63;
326749Speter 	dub[0] &= ~0177600;
327749Speter 	dub[0] |= 0200;
328749Speter 	mant = *lp;
329749Speter 	mant <<= 8;
330749Speter 	if (newfp[0])
331749Speter 		mant = -mant;
332749Speter 	newfp[0] |= (mant >> 17) & 077777;
333749Speter 	newfp[1] |= (((int) (mant >> 1)) & 0177400) | (exp << 1);
334749Speter ret:
335749Speter 	dub[0] = newfp[0];
336749Speter 	dub[1] = newfp[1];
337749Speter }
338749Speter #endif
339