xref: /csrg-svn/usr.bin/pascal/src/cset.c (revision 1884)
1750Speter /* Copyright (c) 1979 Regents of the University of California */
2750Speter 
3*1884Speter static	char sccsid[] = "@(#)cset.c 1.3 12/12/80";
4750Speter 
5750Speter #include "whoami.h"
6750Speter #include "0.h"
7750Speter #include "tree.h"
8750Speter #include "opcode.h"
9750Speter #include "objfmt.h"
10750Speter #include "pc.h"
11750Speter #include "pcops.h"
12750Speter 
13750Speter /*
14750Speter  *	rummage through a `constant' set (i.e. anything within [ ]'s) tree
15750Speter  *	and decide if this is a compile time constant set or a runtime set.
16750Speter  *	this information is returned in a structure passed from the caller.
17750Speter  *	while rummaging, this also reorders the tree so that all ranges
18750Speter  *	preceed all singletons.
19750Speter  */
20750Speter bool
21750Speter precset( r , settype , csetp )
22750Speter 	int		*r;
23750Speter 	struct nl	*settype;
24750Speter 	struct csetstr	*csetp;
25750Speter {
26750Speter 	register int		*e;
27750Speter 	register struct nl	*t;
28750Speter 	register struct nl	*exptype;
29750Speter 	register int		*el;
30750Speter 	register int		*pairp;
31750Speter 	register int		*singp;
32750Speter 	int			*ip;
33750Speter 	long			lower;
34750Speter 	long			upper;
35750Speter 	long			rangeupper;
36750Speter 	bool			setofint;
37750Speter 
38750Speter 	csetp -> csettype = NIL;
39750Speter 	csetp -> paircnt = 0;
40750Speter 	csetp -> singcnt = 0;
41750Speter 	csetp -> comptime = TRUE;
42750Speter 	setofint = FALSE;
43750Speter 	if ( settype != NIL ) {
44750Speter 	    if ( settype -> class == SET ) {
45750Speter 		    /*
46750Speter 		     *	the easy case, we are told the type of the set.
47750Speter 		     */
48750Speter 		exptype = settype -> type;
49750Speter 	    } else {
50750Speter 		    /*
51750Speter 		     *	we are told the type, but it's not a set
52750Speter 		     *	supposedly possible if someone tries
53750Speter 		     *	e.g string context [1,2] = 'abc'
54750Speter 		     */
55750Speter 		error("Constant set involved in non set context");
56750Speter 		return csetp -> comptime;
57750Speter 	    }
58750Speter 	} else {
59750Speter 		/*
60750Speter 		 * So far we have no indication
61750Speter 		 * of what the set type should be.
62750Speter 		 * We "look ahead" and try to infer
63750Speter 		 * The type of the constant set
64750Speter 		 * by evaluating one of its members.
65750Speter 		 */
66750Speter 	    e = r[2];
67750Speter 	    if (e == NIL) {
68750Speter 		    /*
691552Speter 		     *	tentative for [], return type of `intset'
70750Speter 		     */
711552Speter 		settype = lookup( intset );
721552Speter 		if ( settype == NIL ) {
731552Speter 		    panic( "empty set" );
741552Speter 		}
751552Speter 		settype = settype -> type;
761552Speter 		if ( settype == NIL ) {
771552Speter 		    return csetp -> comptime;
781552Speter 		}
791552Speter 		if ( isnta( settype , "t" ) ) {
801552Speter 		    error("Set default type \"intset\" is not a set");
811552Speter 		    return csetp -> comptime;
821552Speter 		}
831552Speter 		csetp -> csettype = settype;
84750Speter 		return csetp -> comptime;
85750Speter 	    }
86750Speter 	    e = e[1];
87750Speter 	    if (e == NIL) {
88750Speter 		return csetp -> comptime;
89750Speter 	    }
90750Speter 	    if (e[0] == T_RANG) {
91750Speter 		    e = e[1];
92750Speter 	    }
93750Speter 	    codeoff();
94750Speter 	    t = rvalue(e, NIL , RREQ );
95750Speter 	    codeon();
96750Speter 	    if (t == NIL) {
97750Speter 		return csetp -> comptime;
98750Speter 	    }
99750Speter 		/*
100750Speter 		 * The type of the set, settype, is
101750Speter 		 * deemed to be a set of the base type
102750Speter 		 * of t, which we call exptype.  If,
103750Speter 		 * however, this would involve a
104750Speter 		 * "set of integer", we cop out
105750Speter 		 * and use "intset"'s current scoped
106750Speter 		 * type instead.
107750Speter 		 */
108750Speter 	    if (isa(t, "r")) {
109750Speter 		    error("Sets may not have 'real' elements");
110750Speter 		    return csetp -> comptime;
111750Speter 	    }
112750Speter 	    if (isnta(t, "bcsi")) {
113750Speter 		    error("Set elements must be scalars, not %ss", nameof(t));
114750Speter 		    return csetp -> comptime;
115750Speter 	    }
116750Speter 	    if (isa(t, "i")) {
117750Speter 		    settype = lookup(intset);
118750Speter 		    if (settype == NIL)
119750Speter 			    panic("intset");
120750Speter 		    settype = settype->type;
121750Speter 		    if (settype == NIL)
122750Speter 			    return csetp -> comptime;
123750Speter 		    if (isnta(settype, "t")) {
124750Speter 			    error("Set default type \"intset\" is not a set");
125750Speter 			    return csetp -> comptime;
126750Speter 		    }
127750Speter 		    exptype = settype->type;
128750Speter 			/*
129750Speter 			 *	say we are doing an intset
130750Speter 			 *	but, if we get out of range errors for intset
131750Speter 			 *	we punt constructing the set at	compile time.
132750Speter 			 */
133750Speter 		    setofint = TRUE;
134750Speter 	    } else {
135750Speter 			exptype = t->type;
136750Speter 			if (exptype == NIL)
137750Speter 				return csetp -> comptime;
138750Speter 			if (exptype->class != RANGE)
139750Speter 				exptype = exptype->type;
140750Speter 			settype = defnl(0, SET, exptype, 0);
141750Speter 	    }
142750Speter 	}
143750Speter 	csetp -> csettype = settype;
144750Speter 	setran( exptype );
145750Speter 	lower = set.lwrb;
146750Speter 	upper = set.lwrb + set.uprbp;
147750Speter 	pairp = NIL;
148750Speter 	singp = NIL;
149750Speter 	codeoff();
150750Speter 	while ( el = r[2] ) {
151750Speter 		e = el[1];
152750Speter 		if (e == NIL) {
153750Speter 			    /*
154750Speter 			     *	don't hang this one anywhere.
155750Speter 			     */
156750Speter 			csetp -> csettype = NIL;
157750Speter 			r[2] = el[2];
158750Speter 			continue;
159750Speter 		}
160750Speter 		if (e[0] == T_RANG) {
161750Speter 			if ( csetp -> comptime && constval( e[2] ) ) {
162750Speter 			    t = con.ctype;
163750Speter 			    if ( ((long)con.crval) < lower || ((long)con.crval) > upper ) {
164750Speter 				if ( setofint ) {
165750Speter 				    csetp -> comptime = FALSE;
166750Speter 				} else {
167750Speter 				    error("Range upper bound of %d out of set bounds" , ((long)con.crval) );
168750Speter 				    csetp -> csettype = NIL;
169750Speter 				}
170750Speter 			    }
171750Speter 			    rangeupper = ((long)con.crval);
172750Speter 			} else {
173750Speter 			    csetp -> comptime = FALSE;
174750Speter 			    t = rvalue(e[2], NIL , RREQ );
175750Speter 			    if (t == NIL) {
176750Speter 				    rvalue(e[1], NIL , RREQ );
177750Speter 				    goto pairhang;
178750Speter 			    }
179750Speter 			}
180750Speter 			if (incompat(t, exptype, e[2])) {
181750Speter 				cerror("Upper bound of element type clashed with set type in constant set");
182750Speter 			}
183750Speter 			if ( csetp -> comptime && constval( e[1] ) ) {
184750Speter 			    t = con.ctype;
185750Speter 			    if ( ((long)con.crval) < lower || ((long)con.crval) > upper ) {
186750Speter 				if ( setofint ) {
187750Speter 				    csetp -> comptime = FALSE;
188750Speter 				} else {
189750Speter 				    error("Range lower bound of %d out of set bounds" , ((long)con.crval) );
190750Speter 				    csetp -> csettype = NIL;
191750Speter 				}
192750Speter 			    }
193750Speter 			} else {
194750Speter 			    csetp -> comptime = FALSE;
195750Speter 			    t = rvalue(e[1], NIL , RREQ );
196750Speter 			    if (t == NIL) {
197750Speter 				    goto pairhang;
198750Speter 			    }
199750Speter 			}
200750Speter 			if (incompat(t, exptype, e[1])) {
201750Speter 				cerror("Lower bound of element type clashed with set type in constant set");
202750Speter 			}
203750Speter pairhang:
204750Speter 			    /*
205750Speter 			     *	remove this range from the tree list and
206750Speter 			     *	hang it on the pairs list.
207750Speter 			     */
208750Speter 			ip = el[2];
209750Speter 			el[2] = pairp;
210750Speter 			pairp = r[2];
211750Speter 			r[2] = ip;
212750Speter 			csetp -> paircnt++;
213750Speter 		} else {
214750Speter 			if ( csetp -> comptime && constval( e ) ) {
215750Speter 			    t = con.ctype;
216750Speter 			    if ( ((long)con.crval) < lower || ((long)con.crval) > upper ) {
217750Speter 				if ( setofint ) {
218750Speter 				    csetp -> comptime = FALSE;
219750Speter 				} else {
220750Speter 				    error("Value of %d out of set bounds" , ((long)con.crval) );
221750Speter 				    csetp -> csettype = NIL;
222750Speter 				}
223750Speter 			    }
224750Speter 			} else {
225750Speter 			    csetp -> comptime = FALSE;
226750Speter 			    t = rvalue((int *) e, NLNIL , RREQ );
227750Speter 			    if (t == NIL) {
228750Speter 				    goto singhang;
229750Speter 			    }
230750Speter 			}
231750Speter 			if (incompat(t, exptype, e)) {
232750Speter 				cerror("Element type clashed with set type in constant set");
233750Speter 			}
234750Speter singhang:
235750Speter 			    /*
236750Speter 			     *	take this expression off the tree list and
237750Speter 			     *	hang it on the list of singletons.
238750Speter 			     */
239750Speter 			ip = el[2];
240750Speter 			el[2] = singp;
241750Speter 			singp = r[2];
242750Speter 			r[2] = ip;
243750Speter 			csetp -> singcnt++;
244750Speter 		}
245750Speter 	}
246750Speter 	codeon();
247750Speter #	ifdef PC
248750Speter 	    if ( pairp != NIL ) {
249750Speter 		for ( el = pairp ; el[2] != NIL ; el = el[2] ) /* void */;
250750Speter 		el[2] = singp;
251750Speter 		r[2] = pairp;
252750Speter 	    } else {
253750Speter 		r[2] = singp;
254750Speter 	    }
255750Speter #	endif PC
256750Speter #	ifdef OBJ
257750Speter 	    if ( singp != NIL ) {
258750Speter 		for ( el = singp ; el[2] != NIL ; el = el[2] ) /* void */;
259750Speter 		el[2] = pairp;
260750Speter 		r[2] = singp;
261750Speter 	    } else {
262750Speter 		r[2] = pairp;
263750Speter 	    }
264750Speter #	endif OBJ
265750Speter 	if ( csetp -> csettype == NIL ) {
266750Speter 	    csetp -> comptime = TRUE;
267750Speter 	}
268750Speter 	return csetp -> comptime;
269750Speter }
270750Speter 
271750Speter #define	BITSPERLONG	( sizeof( long ) * BITSPERBYTE )
272750Speter     /*
273750Speter      *	mask[i] has the low i bits turned off.
274750Speter      */
275750Speter long	mask[] = {
276750Speter 		    0xffffffff , 0xfffffffe , 0xfffffffc , 0xfffffff8 ,
277750Speter 		    0xfffffff0 , 0xffffffe0 , 0xffffffc0 , 0xffffff80 ,
278750Speter 		    0xffffff00 , 0xfffffe00 , 0xfffffc00 , 0xfffff800 ,
279750Speter 		    0xfffff000 , 0xffffe000 , 0xffffc000 , 0xffff8000 ,
280750Speter 		    0xffff0000 , 0xfffe0000 , 0xfffc0000 , 0xfff80000 ,
281750Speter 		    0xfff00000 , 0xffe00000 , 0xffc00000 , 0xff800000 ,
282750Speter 		    0xff000000 , 0xfe000000 , 0xfc000000 , 0xf8000000 ,
283750Speter 		    0xf0000000 , 0xe0000000 , 0xc0000000 , 0x80000000 ,
284750Speter 		    0x00000000
285750Speter 		 };
286750Speter     /*
287750Speter      *	given a csetstr, either
288750Speter      *	    put out a compile time constant set and an lvalue to it.
289750Speter      *	or
290750Speter      *	    put out rvalues for the singletons and the pairs
291750Speter      *	    and counts of each.
292750Speter      */
293750Speter postcset( r , csetp )
294750Speter     int			*r;
295750Speter     struct csetstr	*csetp;
296750Speter     {
297750Speter 	register int	*el;
298750Speter 	register int	*e;
299750Speter 	int		lower;
300750Speter 	int		upper;
301750Speter 	int		lowerdiv;
302750Speter 	int		lowermod;
303750Speter 	int		upperdiv;
304750Speter 	int		uppermod;
305750Speter 	int		label;
306750Speter 	long		*lp;
307750Speter 	long		*limit;
308750Speter 	long		tempset[ ( MAXSET / BITSPERLONG ) + 1 ];
309750Speter 	long		temp;
310750Speter 	char		labelname[ BUFSIZ ];
311750Speter 
312750Speter 	if ( csetp -> comptime ) {
313750Speter 	    setran( ( csetp -> csettype ) -> type );
314750Speter 	    limit = &tempset[ ( set.uprbp / BITSPERLONG ) + 1 ];
315750Speter 	    for ( lp = &tempset[0] ; lp < limit ; lp++ ) {
316750Speter 		*lp = 0;
317750Speter 	    }
318750Speter 	    for ( el = r[2] ; el != NIL ; el = el[2] ) {
319750Speter 		e = el[1];
320750Speter 		if ( e[0] == T_RANG ) {
321750Speter 		    constval( e[1] );
322750Speter 		    lower = (long) con.crval;
323750Speter 		    constval( e[2] );
324750Speter 		    upper = (long) con.crval;
325750Speter 		    if ( upper < lower ) {
326750Speter 			continue;
327750Speter 		    }
328750Speter 		    lowerdiv = ( lower - set.lwrb ) / BITSPERLONG;
329750Speter 		    lowermod = ( lower - set.lwrb ) % BITSPERLONG;
330750Speter 		    upperdiv = ( upper - set.lwrb ) / BITSPERLONG;
331750Speter 		    uppermod = ( upper - set.lwrb ) % BITSPERLONG;
332750Speter 		    temp = mask[ lowermod ];
333750Speter 		    if ( lowerdiv == upperdiv ) {
334750Speter 			temp &= ~mask[ uppermod + 1 ];
335750Speter 		    }
336750Speter 		    tempset[ lowerdiv ] |= temp;
337750Speter 		    limit = &tempset[ upperdiv-1 ];
338750Speter 		    for ( lp = &tempset[ lowerdiv+1 ] ; lp <= limit ; lp++ ) {
339750Speter 			*lp |= ~0;
340750Speter 		    }
341750Speter 		    if ( lowerdiv != upperdiv ) {
342750Speter 			tempset[ upperdiv ] |= ~mask[ uppermod + 1 ];
343750Speter 		    }
344750Speter 		} else {
345750Speter 		    constval( e );
346750Speter 		    lowerdiv = ( ((long)con.crval) - set.lwrb ) / BITSPERLONG;
347750Speter 		    lowermod = ( ((long)con.crval) - set.lwrb ) % BITSPERLONG;
348750Speter 		    tempset[ lowerdiv ] |= ( 1 << lowermod );
349750Speter 		}
350750Speter 	    }
351750Speter 	    if ( cgenflg )
352750Speter 		return;
353750Speter #	    ifdef PC
354750Speter 		putprintf( "	.data" , 0 );
355750Speter 		putprintf( "	.align 2" , 0 );
356750Speter 		label = getlab();
357750Speter 		putlab( label );
358750Speter 		lp = &( tempset[0] );
359750Speter 		limit = &tempset[ ( set.uprbp / BITSPERLONG ) + 1 ];
360750Speter 		while ( lp < limit ) {
361750Speter 		    putprintf( "	.long	0x%x" , 1 , *lp ++ );
362750Speter 		    for ( temp = 2 ; ( temp <= 8 ) && lp < limit ; temp ++ ) {
363750Speter 			putprintf( ",0x%x" , 1 , *lp++ );
364750Speter 		    }
365750Speter 		    putprintf( "" , 0 );
366750Speter 		}
367750Speter 		putprintf( "	.text" , 0 );
368750Speter 		sprintf( labelname , PREFIXFORMAT , LABELPREFIX , label );
369750Speter 		putleaf( P2ICON , 0 , 0 , P2PTR | P2STRTY , labelname );
370750Speter #	    endif PC
371750Speter #	    ifdef OBJ
372750Speter 		put( 2, O_CON, (set.uprbp / BITSPERLONG + 1) *
373750Speter 				 (BITSPERLONG / BITSPERBYTE));
374750Speter 		lp = &( tempset[0] );
375750Speter 		limit = &tempset[ ( set.uprbp / BITSPERLONG ) + 1 ];
376750Speter 		while ( lp < limit ) {
377750Speter 		    put( 2, O_CASE4, *lp ++);
378750Speter 		}
379750Speter #	    endif OBJ
380750Speter 	} else {
381750Speter #	    ifdef PC
382750Speter 		putleaf( P2ICON , csetp -> paircnt , 0 , P2INT , 0 );
383750Speter 		putop( P2LISTOP , P2INT );
384750Speter 		putleaf( P2ICON , csetp -> singcnt , 0 , P2INT , 0 );
385750Speter 		putop( P2LISTOP , P2INT );
386750Speter 		for ( el = r[2] ; el != NIL ; el = el[2] ) {
387750Speter 		    e = el[1];
388750Speter 		    if ( e[0] == T_RANG ) {
389750Speter 			rvalue( e[2] , NIL , RREQ );
390750Speter 			putop( P2LISTOP , P2INT );
391750Speter 			rvalue( e[1] , NIL , RREQ );
392750Speter 			putop( P2LISTOP , P2INT );
393750Speter 		    } else {
394750Speter 			rvalue( e , NIL , RREQ );
395750Speter 			putop( P2LISTOP , P2INT );
396750Speter 		    }
397750Speter 		}
398750Speter #	    endif PC
399750Speter #	    ifdef OBJ
400750Speter 		for ( el = r[2] ; el != NIL ; el = el[2] ) {
401750Speter 		    e = el[1];
402750Speter 		    if ( e[0] == T_RANG ) {
403*1884Speter 			stkrval( e[1] , NIL , RREQ );
404750Speter 			stkrval( e[2] , NIL , RREQ );
405750Speter 		    } else {
406750Speter 			stkrval( e , NIL , RREQ );
407750Speter 		    }
408750Speter 		}
409750Speter 		put( 2 , O_CON24 , csetp -> singcnt );
410750Speter 		put( 2 , O_CON24 , csetp -> paircnt );
411750Speter #	    endif OBJ
412750Speter 	}
413750Speter }
414