xref: /csrg-svn/usr.bin/pascal/src/var.c (revision 781)
1*781Speter /* Copyright (c) 1979 Regents of the University of California */
2*781Speter 
3*781Speter static	char sccsid[] = "@(#)var.c 1.1 08/27/80";
4*781Speter 
5*781Speter #include "whoami.h"
6*781Speter #include "0.h"
7*781Speter #include "align.h"
8*781Speter #ifdef PC
9*781Speter #   include	"pc.h"
10*781Speter #   include	"pcops.h"
11*781Speter #   include	"iorec.h"
12*781Speter #endif PC
13*781Speter 
14*781Speter /*
15*781Speter  * Declare variables of a var part.  DPOFF1 is
16*781Speter  * the local variable storage for all prog/proc/func
17*781Speter  * modules aside from the block mark.  The total size
18*781Speter  * of all the local variables is entered into the
19*781Speter  * size array.
20*781Speter  */
21*781Speter varbeg()
22*781Speter {
23*781Speter 
24*781Speter /* PC allows for multiple declaration
25*781Speter  * parts except when the "standard"
26*781Speter  * option has been specified.
27*781Speter  * If routine segment is being compiled,
28*781Speter  * do level one processing.
29*781Speter  */
30*781Speter 
31*781Speter #ifndef PI1
32*781Speter if (!progseen)
33*781Speter 	level1();
34*781Speter #ifdef PC
35*781Speter     if (opt('s')) {
36*781Speter 	if (parts & VPRT){
37*781Speter 		standard();
38*781Speter 		error("All variables must be declared in one var part");
39*781Speter 	}
40*781Speter     }
41*781Speter #else
42*781Speter 	if (parts & VPRT)
43*781Speter 		error("All variables must be declared in one var part");
44*781Speter #endif PC
45*781Speter 
46*781Speter 	parts |= VPRT;
47*781Speter #endif
48*781Speter     /*
49*781Speter      *  #ifndef PI0
50*781Speter      *      sizes[cbn].om_max = sizes[cbn].om_off = -DPOFF1;
51*781Speter      *  #endif
52*781Speter      */
53*781Speter 	forechain = NIL;
54*781Speter #ifdef PI0
55*781Speter 	send(REVVBEG);
56*781Speter #endif
57*781Speter }
58*781Speter 
59*781Speter var(vline, vidl, vtype)
60*781Speter #ifdef PI0
61*781Speter 	int vline, *vidl, *vtype;
62*781Speter {
63*781Speter 	register struct nl *np;
64*781Speter 	register int *vl;
65*781Speter 
66*781Speter 	np = gtype(vtype);
67*781Speter 	line = vline;
68*781Speter 	for (vl = vidl; vl != NIL; vl = vl[2]) {
69*781Speter 		}
70*781Speter 	}
71*781Speter 	send(REVVAR, vline, vidl, vtype);
72*781Speter }
73*781Speter #else
74*781Speter 	int vline;
75*781Speter 	register int *vidl;
76*781Speter 	int *vtype;
77*781Speter {
78*781Speter 	register struct nl *np;
79*781Speter 	register struct om *op;
80*781Speter 	long w;
81*781Speter 	int o2;
82*781Speter 	int *ovidl = vidl;
83*781Speter 
84*781Speter 	np = gtype(vtype);
85*781Speter 	line = vline;
86*781Speter 	    /*
87*781Speter 	     * widths are evened out
88*781Speter 	     */
89*781Speter 	w = (lwidth(np) + 1) &~ 1;
90*781Speter 	op = &sizes[cbn];
91*781Speter 	for (; vidl != NIL; vidl = vidl[2]) {
92*781Speter #		ifdef OBJ
93*781Speter 		    op -> om_off = roundup( op -> om_off - w , align( np ) );
94*781Speter 		    o2 = op -> om_off;
95*781Speter #		endif OBJ
96*781Speter #		ifdef PC
97*781Speter 		    if ( cbn == 1 ) {
98*781Speter 				/*
99*781Speter 				 * global variables are not accessed off the fp
100*781Speter 				 * but rather by their names.
101*781Speter 				 */
102*781Speter 			    o2 = 0;
103*781Speter 		    } else {
104*781Speter 				/*
105*781Speter 				 * locals are aligned, too.
106*781Speter 				 */
107*781Speter 			    op -> om_off = roundup( op -> om_off - w
108*781Speter 							, align( np ) );
109*781Speter 			    o2 = op -> om_off;
110*781Speter 		    }
111*781Speter #		endif PC
112*781Speter 		enter(defnl(vidl[1], VAR, np, o2));
113*781Speter 		if ( np -> nl_flags & NFILES ) {
114*781Speter 		    dfiles[ cbn ] = TRUE;
115*781Speter 		}
116*781Speter #		ifdef PC
117*781Speter 		    if ( cbn == 1 ) {
118*781Speter 			putprintf( "	.data" , 0 );
119*781Speter 			putprintf( "	.comm	" , 1 );
120*781Speter 			putprintf( EXTFORMAT , 1 , vidl[1] );
121*781Speter 			putprintf( ",%d" , 0 , w );
122*781Speter 			putprintf( "	.text" , 0 );
123*781Speter 		    }
124*781Speter 		    stabvar( vidl[1] , p2type( np ) , cbn , o2 , w );
125*781Speter #		endif PC
126*781Speter 	}
127*781Speter #	ifdef PTREE
128*781Speter 	    {
129*781Speter 		pPointer	*Vars;
130*781Speter 		pPointer	Var = VarDecl( ovidl , vtype );
131*781Speter 
132*781Speter 		pSeize( PorFHeader[ nesting ] );
133*781Speter 		Vars = &( pDEF( PorFHeader[ nesting ] ).PorFVars );
134*781Speter 		*Vars = ListAppend( *Vars , Var );
135*781Speter 		pRelease( PorFHeader[ nesting ] );
136*781Speter 	    }
137*781Speter #	endif
138*781Speter }
139*781Speter #endif
140*781Speter 
141*781Speter varend()
142*781Speter {
143*781Speter 
144*781Speter 	foredecl();
145*781Speter #ifndef PI0
146*781Speter 	sizes[cbn].om_max = sizes[cbn].om_off;
147*781Speter #else
148*781Speter 	send(REVVEND);
149*781Speter #endif
150*781Speter }
151*781Speter 
152*781Speter /*
153*781Speter  * Evening
154*781Speter  */
155*781Speter even(w)
156*781Speter 	register int w;
157*781Speter {
158*781Speter 	if (w < 0)
159*781Speter 		return (w & ~1);
160*781Speter 	return ((w+1) & ~1);
161*781Speter }
162*781Speter 
163*781Speter /*
164*781Speter  * Find the width of a type in bytes.
165*781Speter  */
166*781Speter width(np)
167*781Speter 	struct nl *np;
168*781Speter {
169*781Speter 
170*781Speter 	return (lwidth(np));
171*781Speter }
172*781Speter 
173*781Speter long
174*781Speter lwidth(np)
175*781Speter 	struct nl *np;
176*781Speter {
177*781Speter 	register struct nl *p;
178*781Speter 	long w;
179*781Speter 
180*781Speter 	p = np;
181*781Speter 	if (p == NIL)
182*781Speter 		return (0);
183*781Speter loop:
184*781Speter 	switch (p->class) {
185*781Speter 		case TYPE:
186*781Speter 			switch (nloff(p)) {
187*781Speter 				case TNIL:
188*781Speter 					return (2);
189*781Speter 				case TSTR:
190*781Speter 				case TSET:
191*781Speter 					panic("width");
192*781Speter 				default:
193*781Speter 					p = p->type;
194*781Speter 					goto loop;
195*781Speter 			}
196*781Speter 		case ARRAY:
197*781Speter 			return (aryconst(p, 0));
198*781Speter 		case PTR:
199*781Speter 			return ( sizeof ( int * ) );
200*781Speter 		case FILET:
201*781Speter #			ifdef OBJ
202*781Speter 			    return ( sizeof ( int * ) );
203*781Speter #			endif OBJ
204*781Speter #			ifdef PC
205*781Speter 			    return ( sizeof(struct iorec)
206*781Speter 				    + lwidth( p -> type ) );
207*781Speter #			endif PC
208*781Speter 		case RANGE:
209*781Speter 			if (p->type == nl+TDOUBLE)
210*781Speter #ifdef DEBUG
211*781Speter 				return (hp21mx ? 4 : 8);
212*781Speter #else
213*781Speter 				return (8);
214*781Speter #endif
215*781Speter 		case SCAL:
216*781Speter 			return (bytes(p->range[0], p->range[1]));
217*781Speter 		case SET:
218*781Speter 			setran(p->type);
219*781Speter 			return roundup( ( set.uprbp >> 3 ) + 1 , A_SET );
220*781Speter 		case STR:
221*781Speter 		case RECORD:
222*781Speter 			return ( p->value[NL_OFFS] );
223*781Speter 		default:
224*781Speter 			panic("wclass");
225*781Speter 	}
226*781Speter }
227*781Speter 
228*781Speter     /*
229*781Speter      *	round up x to a multiple of y
230*781Speter      *	for computing offsets of aligned things.
231*781Speter      *	y had better be positive.
232*781Speter      *	rounding is in the direction of x.
233*781Speter      */
234*781Speter long
235*781Speter roundup( x , y )
236*781Speter     long		x;
237*781Speter     register long	y;
238*781Speter     {
239*781Speter 
240*781Speter 	if ( y == 0 ) {
241*781Speter 	    return 0;
242*781Speter 	}
243*781Speter 	if ( x >= 0 ) {
244*781Speter 		return ( ( ( x + ( y - 1 ) ) / y ) * y );
245*781Speter 	} else {
246*781Speter 		return ( ( ( x - ( y - 1 ) ) / y ) * y );
247*781Speter 	}
248*781Speter     }
249*781Speter 
250*781Speter     /*
251*781Speter      *	alignment of an object using the c alignment scheme
252*781Speter      */
253*781Speter int
254*781Speter align( np )
255*781Speter     struct nl	*np;
256*781Speter     {
257*781Speter 	register struct nl *p;
258*781Speter 
259*781Speter 	p = np;
260*781Speter 	if ( p == NIL ) {
261*781Speter 	    return 0;
262*781Speter 	}
263*781Speter alignit:
264*781Speter 	switch ( p -> class ) {
265*781Speter 	    case TYPE:
266*781Speter 		    switch ( nloff( p ) ) {
267*781Speter 			case TNIL:
268*781Speter 				return A_POINT;
269*781Speter 			case TSTR:
270*781Speter 				return A_CHAR;
271*781Speter 			case TSET:
272*781Speter 				return A_SET;
273*781Speter 			default:
274*781Speter 				p = p -> type;
275*781Speter 				goto alignit;
276*781Speter 		    }
277*781Speter 	    case ARRAY:
278*781Speter 			/*
279*781Speter 			 * arrays are aligned as their component types
280*781Speter 			 */
281*781Speter 		    p = p -> type;
282*781Speter 		    goto alignit;
283*781Speter 	    case PTR:
284*781Speter 		    return A_POINT;
285*781Speter 	    case FILET:
286*781Speter 		    return A_FILET;
287*781Speter 	    case RANGE:
288*781Speter 		    if ( p -> type == nl+TDOUBLE ) {
289*781Speter 			return A_DOUBLE;
290*781Speter 		    }
291*781Speter 		    /* else, fall through */
292*781Speter 	    case SCAL:
293*781Speter 		    switch ( bytes( p -> range[0] , p -> range[1] ) ) {
294*781Speter 			case 4:
295*781Speter 			    return A_LONG;
296*781Speter 			case 2:
297*781Speter 			    return A_SHORT;
298*781Speter 			case 1:
299*781Speter 			    return A_CHAR;
300*781Speter 			default:
301*781Speter 			    panic( "align: scal" );
302*781Speter 		    }
303*781Speter 	    case SET:
304*781Speter 		    return A_SET;
305*781Speter 	    case STR:
306*781Speter 		    return A_CHAR;
307*781Speter 	    case RECORD:
308*781Speter 			/*
309*781Speter 			 * follow chain through all fields in record,
310*781Speter 			 * taking max of alignments of types of fields.
311*781Speter 			 * short circuit out if i reach the maximum alignment.
312*781Speter 			 * this is pretty likely, as A_MAX is only 4.
313*781Speter 			 */
314*781Speter 		    {
315*781Speter 			register long recalign;
316*781Speter 			register long fieldalign;
317*781Speter 
318*781Speter 			recalign = A_MIN;
319*781Speter 			p = p -> chain;
320*781Speter 			while ( ( p != NIL ) && ( recalign < A_MAX ) ) {
321*781Speter 			    fieldalign = align( p -> type );
322*781Speter 			    if ( fieldalign > recalign ) {
323*781Speter 				recalign = fieldalign;
324*781Speter 			    }
325*781Speter 			    p = p -> chain;
326*781Speter 			}
327*781Speter 			return recalign;
328*781Speter 		    }
329*781Speter 	    default:
330*781Speter 		    panic( "align" );
331*781Speter 	}
332*781Speter     }
333*781Speter 
334*781Speter /*
335*781Speter  * Return the width of an element
336*781Speter  * of a n time subscripted np.
337*781Speter  */
338*781Speter long aryconst(np, n)
339*781Speter 	struct nl *np;
340*781Speter 	int n;
341*781Speter {
342*781Speter 	register struct nl *p;
343*781Speter 	long s, d;
344*781Speter 
345*781Speter 	if ((p = np) == NIL)
346*781Speter 		return (NIL);
347*781Speter 	if (p->class != ARRAY)
348*781Speter 		panic("ary");
349*781Speter 	s = lwidth(p->type);
350*781Speter 	/*
351*781Speter 	 * Arrays of anything but characters are word aligned.
352*781Speter 	 */
353*781Speter 	if (s & 1)
354*781Speter 		if (s != 1)
355*781Speter 			s++;
356*781Speter 	/*
357*781Speter 	 * Skip the first n subscripts
358*781Speter 	 */
359*781Speter 	while (n >= 0) {
360*781Speter 		p = p->chain;
361*781Speter 		n--;
362*781Speter 	}
363*781Speter 	/*
364*781Speter 	 * Sum across remaining subscripts.
365*781Speter 	 */
366*781Speter 	while (p != NIL) {
367*781Speter 		if (p->class != RANGE && p->class != SCAL)
368*781Speter 			panic("aryran");
369*781Speter 		d = p->range[1] - p->range[0] + 1;
370*781Speter 		s *= d;
371*781Speter 		p = p->chain;
372*781Speter 	}
373*781Speter 	return (s);
374*781Speter }
375*781Speter 
376*781Speter /*
377*781Speter  * Find the lower bound of a set, and also its size in bits.
378*781Speter  */
379*781Speter setran(q)
380*781Speter 	struct nl *q;
381*781Speter {
382*781Speter 	register lb, ub;
383*781Speter 	register struct nl *p;
384*781Speter 
385*781Speter 	p = q;
386*781Speter 	if (p == NIL)
387*781Speter 		return (NIL);
388*781Speter 	lb = p->range[0];
389*781Speter 	ub = p->range[1];
390*781Speter 	if (p->class != RANGE && p->class != SCAL)
391*781Speter 		panic("setran");
392*781Speter 	set.lwrb = lb;
393*781Speter 	/* set.(upperbound prime) = number of bits - 1; */
394*781Speter 	set.uprbp = ub-lb;
395*781Speter }
396*781Speter 
397*781Speter /*
398*781Speter  * Return the number of bytes required to hold an arithmetic quantity
399*781Speter  */
400*781Speter bytes(lb, ub)
401*781Speter 	long lb, ub;
402*781Speter {
403*781Speter 
404*781Speter #ifndef DEBUG
405*781Speter 	if (lb < -32768 || ub > 32767)
406*781Speter 		return (4);
407*781Speter 	else if (lb < -128 || ub > 127)
408*781Speter 		return (2);
409*781Speter #else
410*781Speter 	if (!hp21mx && (lb < -32768 || ub > 32767))
411*781Speter 		return (4);
412*781Speter 	if (lb < -128 || ub > 127)
413*781Speter 		return (2);
414*781Speter #endif
415*781Speter 	else
416*781Speter 		return (1);
417*781Speter }
418