xref: /csrg-svn/usr.bin/pascal/src/conv.c (revision 22160)
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