xref: /csrg-svn/usr.bin/pascal/src/conv.c (revision 14728)
1749Speter /* Copyright (c) 1979 Regents of the University of California */
2749Speter 
3*14728Sthien #ifndef lint
4*14728Sthien static char sccsid[] = "@(#)conv.c 1.5 08/19/83";
5*14728Sthien #endif
6749Speter 
7749Speter #include "whoami.h"
8749Speter #ifdef PI
9749Speter #include "0.h"
10749Speter #include "opcode.h"
11749Speter #ifdef PC
12749Speter #   include	"pcops.h"
13749Speter #endif PC
14*14728Sthien #include "tree_ty.h"
15749Speter 
16*14728Sthien #ifndef PC
17749Speter #ifndef PI0
18749Speter /*
19749Speter  * Convert a p1 into a p2.
20749Speter  * Mostly used for different
21749Speter  * length integers and "to real" conversions.
22749Speter  */
23749Speter convert(p1, p2)
24749Speter 	struct nl *p1, *p2;
25749Speter {
26*14728Sthien 	if (p1 == NLNIL || p2 == NLNIL)
27749Speter 		return;
28749Speter 	switch (width(p1) - width(p2)) {
29749Speter 		case -7:
30749Speter 		case -6:
31*14728Sthien 			(void) put(1, O_STOD);
32749Speter 			return;
33749Speter 		case -4:
34*14728Sthien 			(void) put(1, O_ITOD);
35749Speter 			return;
36749Speter 		case -3:
37749Speter 		case -2:
38*14728Sthien 			(void) put(1, O_STOI);
39749Speter 			return;
40749Speter 		case -1:
41749Speter 		case 0:
42749Speter 		case 1:
43749Speter 			return;
44749Speter 		case 2:
45749Speter 		case 3:
46*14728Sthien 			(void) put(1, O_ITOS);
47749Speter 			return;
48749Speter 		default:
49749Speter 			panic("convert");
50749Speter 	}
51749Speter }
52*14728Sthien #endif
53*14728Sthien #endif PC
54749Speter 
55749Speter /*
56749Speter  * Compat tells whether
57749Speter  * p1 and p2 are compatible
58749Speter  * types for an assignment like
59749Speter  * context, i.e. value parameters,
60749Speter  * indicies for 'in', etc.
61749Speter  */
62749Speter compat(p1, p2, t)
63749Speter 	struct nl *p1, *p2;
64*14728Sthien 	struct tnode *t;
65749Speter {
66749Speter 	register c1, c2;
67749Speter 
68749Speter 	c1 = classify(p1);
69749Speter 	if (c1 == NIL)
70749Speter 		return (NIL);
71749Speter 	c2 = classify(p2);
72749Speter 	if (c2 == NIL)
73749Speter 		return (NIL);
74749Speter 	switch (c1) {
75749Speter 		case TBOOL:
76749Speter 		case TCHAR:
77749Speter 			if (c1 == c2)
78749Speter 				return (1);
79749Speter 			break;
80749Speter 		case TINT:
81749Speter 			if (c2 == TINT)
82749Speter 				return (1);
83749Speter 		case TDOUBLE:
84749Speter 			if (c2 == TDOUBLE)
85749Speter 				return (1);
86749Speter #ifndef PI0
87*14728Sthien 			if (c2 == TINT && divflg == FALSE && t != TR_NIL ) {
88*14728Sthien 				divchk= TRUE;
89749Speter 				c1 = classify(rvalue(t, NLNIL , RREQ ));
90*14728Sthien 				divchk = FALSE;
91749Speter 				if (c1 == TINT) {
92749Speter 					error("Type clash: real is incompatible with integer");
93749Speter 					cerror("This resulted because you used '/' which always returns real rather");
94749Speter 					cerror("than 'div' which divides integers and returns integers");
95*14728Sthien 					divflg = TRUE;
96749Speter 					return (NIL);
97749Speter 				}
98749Speter 			}
99749Speter #endif
100749Speter 			break;
101749Speter 		case TSCAL:
102749Speter 			if (c2 != TSCAL)
103749Speter 				break;
104749Speter 			if (scalar(p1) != scalar(p2)) {
105749Speter 				derror("Type clash: non-identical scalar types");
106749Speter 				return (NIL);
107749Speter 			}
108749Speter 			return (1);
109749Speter 		case TSTR:
110749Speter 			if (c2 != TSTR)
111749Speter 				break;
112749Speter 			if (width(p1) != width(p2)) {
113749Speter 				derror("Type clash: unequal length strings");
114749Speter 				return (NIL);
115749Speter 			}
116749Speter 			return (1);
117749Speter 		case TNIL:
118749Speter 			if (c2 != TPTR)
119749Speter 				break;
120749Speter 			return (1);
121749Speter 		case TFILE:
122749Speter 			if (c1 != c2)
123749Speter 				break;
124749Speter 			derror("Type clash: files not allowed in this context");
125749Speter 			return (NIL);
126749Speter 		default:
127749Speter 			if (c1 != c2)
128749Speter 				break;
129749Speter 			if (p1 != p2) {
130749Speter 				derror("Type clash: non-identical %s types", clnames[c1]);
131749Speter 				return (NIL);
132749Speter 			}
133749Speter 			if (p1->nl_flags & NFILES) {
134749Speter 				derror("Type clash: %ss with file components not allowed in this context", clnames[c1]);
135749Speter 				return (NIL);
136749Speter 			}
137749Speter 			return (1);
138749Speter 	}
139749Speter 	derror("Type clash: %s is incompatible with %s", clnames[c1], clnames[c2]);
140749Speter 	return (NIL);
141749Speter }
142749Speter 
143749Speter #ifndef PI0
144*14728Sthien #ifndef PC
145749Speter /*
146749Speter  * Rangechk generates code to
147749Speter  * check if the type p on top
148749Speter  * of the stack is in range for
149749Speter  * assignment to a variable
150749Speter  * of type q.
151749Speter  */
152749Speter rangechk(p, q)
153749Speter 	struct nl *p, *q;
154749Speter {
155749Speter 	register struct nl *rp;
156*14728Sthien #ifdef OBJ
157749Speter 	register op;
158749Speter 	int wq, wrp;
159*14728Sthien #endif
160749Speter 
161749Speter 	if (opt('t') == 0)
162749Speter 		return;
163749Speter 	rp = p;
164749Speter 	if (rp == NIL)
165749Speter 		return;
166749Speter 	if (q == NIL)
167749Speter 		return;
168749Speter #	ifdef OBJ
169749Speter 	    /*
170749Speter 	     * When op is 1 we are checking length
171749Speter 	     * 4 numbers against length 2 bounds,
172749Speter 	     * and adding it to the opcode forces
173749Speter 	     * generation of appropriate tests.
174749Speter 	     */
175749Speter 	    op = 0;
176749Speter 	    wq = width(q);
177749Speter 	    wrp = width(rp);
178749Speter 	    op = wq != wrp && (wq == 4 || wrp == 4);
179749Speter 	    if (rp->class == TYPE)
180749Speter 		    rp = rp->type;
181749Speter 	    switch (rp->class) {
182749Speter 	    case RANGE:
183749Speter 		    if (rp->range[0] != 0) {
184749Speter #    		    ifndef DEBUG
185749Speter 			    if (wrp <= 2)
186*14728Sthien 				    (void) put(3, O_RANG2+op, ( short ) rp->range[0],
187749Speter 						     ( short ) rp->range[1]);
188749Speter 			    else if (rp != nl+T4INT)
189*14728Sthien 				    (void) put(3, O_RANG4+op, rp->range[0], rp->range[1] );
190749Speter #    		    else
191749Speter 			    if (!hp21mx) {
192749Speter 				    if (wrp <= 2)
193*14728Sthien 					    (void) put(3, O_RANG2+op,( short ) rp->range[0],
194749Speter 							    ( short ) rp->range[1]);
195749Speter 				    else if (rp != nl+T4INT)
196*14728Sthien 					    (void) put(3, O_RANG4+op,rp->range[0],
197749Speter 							     rp->range[1]);
198749Speter 			    } else
199749Speter 				    if (rp != nl+T2INT && rp != nl+T4INT)
200*14728Sthien 					    (void) put(3, O_RANG2+op,( short ) rp->range[0],
201749Speter 							    ( short ) rp->range[1]);
202749Speter #    		    endif
203749Speter 			break;
204749Speter 		    }
205749Speter 		    /*
206749Speter 		     * Range whose lower bounds are
207749Speter 		     * zero can be treated as scalars.
208749Speter 		     */
209749Speter 	    case SCAL:
210749Speter 		    if (wrp <= 2)
211*14728Sthien 			    (void) put(2, O_RSNG2+op, ( short ) rp->range[1]);
212749Speter 		    else
213*14728Sthien 			    (void) put( 2 , O_RSNG4+op, rp->range[1]);
214749Speter 		    break;
215749Speter 	    default:
216749Speter 		    panic("rangechk");
217749Speter 	    }
218749Speter #	endif OBJ
219749Speter #	ifdef PC
220749Speter 		/*
22110381Speter 		 *	pc uses precheck() and postcheck().
222749Speter 		 */
22310381Speter 	    panic("rangechk()");
224749Speter #	endif PC
225749Speter }
226749Speter #endif
227749Speter #endif
228*14728Sthien #endif
229749Speter 
230749Speter #ifdef PC
231749Speter     /*
232749Speter      *	if type p requires a range check,
233749Speter      *	    then put out the name of the checking function
234749Speter      *	for the beginning of a function call which is completed by postcheck.
235749Speter      *  (name1 is for a full check; name2 assumes a lower bound of zero)
236749Speter      */
237749Speter precheck( p , name1 , name2 )
238749Speter     struct nl	*p;
239749Speter     char	*name1 , *name2;
240749Speter     {
241749Speter 
242749Speter 	if ( opt( 't' ) == 0 ) {
243749Speter 	    return;
244749Speter 	}
245749Speter 	if ( p == NIL ) {
246749Speter 	    return;
247749Speter 	}
248749Speter 	if ( p -> class == TYPE ) {
249749Speter 	    p = p -> type;
250749Speter 	}
251749Speter 	switch ( p -> class ) {
252749Speter 	    case RANGE:
253749Speter 		if ( p != nl + T4INT ) {
25410382Speter 		    putleaf( P2ICON , 0 , 0 ,
25510382Speter 			    ADDTYPE( P2FTN | P2INT , P2PTR ),
25610382Speter 			    p -> range[0] != 0 ? name1 : name2 );
257749Speter 		}
258749Speter 		break;
259749Speter 	    case SCAL:
260749Speter 		    /*
261749Speter 		     *	how could a scalar ever be out of range?
262749Speter 		     */
263749Speter 		break;
264749Speter 	    default:
265749Speter 		panic( "precheck" );
266749Speter 		break;
267749Speter 	}
268749Speter     }
269749Speter 
270749Speter     /*
271749Speter      *	if type p requires a range check,
272749Speter      *	    then put out the rest of the arguments of to the checking function
273749Speter      *	a call to which was started by precheck.
274749Speter      *	the first argument is what is being rangechecked (put out by rvalue),
275749Speter      *	the second argument is the lower bound of the range,
276749Speter      *	the third argument is the upper bound of the range.
277749Speter      */
27810382Speter postcheck(need, have)
27910382Speter     struct nl	*need;
28010382Speter     struct nl	*have;
28110382Speter {
282749Speter 
28310382Speter     if ( opt( 't' ) == 0 ) {
28410382Speter 	return;
28510382Speter     }
28610382Speter     if ( need == NIL ) {
28710382Speter 	return;
28810382Speter     }
28910382Speter     if ( need -> class == TYPE ) {
29010382Speter 	need = need -> type;
29110382Speter     }
29210382Speter     switch ( need -> class ) {
29310382Speter 	case RANGE:
29410382Speter 	    if ( need != nl + T4INT ) {
29510382Speter 		sconv(p2type(have), P2INT);
29610382Speter 		if (need -> range[0] != 0 ) {
297*14728Sthien 		    putleaf( P2ICON , (int) need -> range[0] , 0 , P2INT ,
298*14728Sthien 							(char *) 0 );
299749Speter 		    putop( P2LISTOP , P2INT );
300749Speter 		}
301*14728Sthien 		putleaf( P2ICON , (int) need -> range[1] , 0 , P2INT ,
302*14728Sthien 				(char *) 0 );
30310382Speter 		putop( P2LISTOP , P2INT );
30410382Speter 		putop( P2CALL , P2INT );
30510382Speter 		sconv(P2INT, p2type(have));
30610382Speter 	    }
30710382Speter 	    break;
30810382Speter 	case SCAL:
30910382Speter 	    break;
31010382Speter 	default:
31110382Speter 	    panic( "postcheck" );
31210382Speter 	    break;
313749Speter     }
31410382Speter }
315749Speter #endif PC
316749Speter 
317749Speter #ifdef DEBUG
318749Speter conv(dub)
319749Speter 	int *dub;
320749Speter {
321749Speter 	int newfp[2];
322*14728Sthien 	double *dp = ((double *) dub);
323*14728Sthien 	long *lp = ((long *) dub);
324749Speter 	register int exp;
325749Speter 	long mant;
326749Speter 
327749Speter 	newfp[0] = dub[0] & 0100000;
328749Speter 	newfp[1] = 0;
329749Speter 	if (*dp == 0.0)
330749Speter 		goto ret;
331749Speter 	exp = ((dub[0] >> 7) & 0377) - 0200;
332749Speter 	if (exp < 0) {
333749Speter 		newfp[1] = 1;
334749Speter 		exp = -exp;
335749Speter 	}
336749Speter 	if (exp > 63)
337749Speter 		exp = 63;
338749Speter 	dub[0] &= ~0177600;
339749Speter 	dub[0] |= 0200;
340749Speter 	mant = *lp;
341749Speter 	mant <<= 8;
342749Speter 	if (newfp[0])
343749Speter 		mant = -mant;
344749Speter 	newfp[0] |= (mant >> 17) & 077777;
345749Speter 	newfp[1] |= (((int) (mant >> 1)) & 0177400) | (exp << 1);
346749Speter ret:
347749Speter 	dub[0] = newfp[0];
348749Speter 	dub[1] = newfp[1];
349749Speter }
350749Speter #endif
351