xref: /csrg-svn/usr.bin/pascal/src/var.c (revision 8681)
1781Speter /* Copyright (c) 1979 Regents of the University of California */
2781Speter 
3*8681Speter static char sccsid[] = "@(#)var.c 1.13 10/19/82";
4781Speter 
5781Speter #include "whoami.h"
6781Speter #include "0.h"
7781Speter #include "align.h"
82075Smckusic #include "iorec.h"
9781Speter #ifdef PC
10781Speter #   include	"pc.h"
11781Speter #   include	"pcops.h"
12781Speter #endif PC
13781Speter 
14781Speter /*
15781Speter  * Declare variables of a var part.  DPOFF1 is
16781Speter  * the local variable storage for all prog/proc/func
17781Speter  * modules aside from the block mark.  The total size
18781Speter  * of all the local variables is entered into the
19781Speter  * size array.
20781Speter  */
217951Speter varbeg( lineofyvar , r )
227951Speter     int	lineofyvar;
23781Speter {
247951Speter     static bool	var_order = FALSE;
257951Speter     static bool	var_seen = FALSE;
26781Speter 
27837Speter /* this allows for multiple declaration
28781Speter  * parts except when the "standard"
29781Speter  * option has been specified.
30781Speter  * If routine segment is being compiled,
31781Speter  * do level one processing.
32781Speter  */
33781Speter 
34781Speter #ifndef PI1
35837Speter 	if (!progseen)
36837Speter 		level1();
377951Speter 	line = lineofyvar;
38837Speter 	if ( parts[ cbn ] & RPRT ) {
39837Speter 	    if ( opt( 's' ) ) {
40781Speter 		standard();
417951Speter 		error("Variable declarations should precede routine declarations");
42837Speter 	    } else {
437951Speter 		if ( !var_order ) {
447951Speter 		    var_order = TRUE;
457951Speter 		    warning();
467951Speter 		    error("Variable declarations should precede routine declarations");
477951Speter 		}
48837Speter 	    }
49781Speter 	}
50837Speter 	if ( parts[ cbn ] & VPRT ) {
51837Speter 	    if ( opt( 's' ) ) {
52837Speter 		standard();
537951Speter 		error("All variables should be declared in one var part");
54837Speter 	    } else {
557951Speter 		if ( !var_seen ) {
567951Speter 		    var_seen = TRUE;
577951Speter 		    warning();
587951Speter 		    error("All variables should be declared in one var part");
597951Speter 		}
60837Speter 	    }
61837Speter 	}
62837Speter 	parts[ cbn ] |= VPRT;
63781Speter #endif
64781Speter     /*
65781Speter      *  #ifndef PI0
663229Smckusic      *      sizes[cbn].om_max = sizes[cbn].curtmps.om_off = -DPOFF1;
67781Speter      *  #endif
68781Speter      */
69781Speter 	forechain = NIL;
70781Speter #ifdef PI0
71781Speter 	send(REVVBEG);
72781Speter #endif
73781Speter }
74781Speter 
75781Speter var(vline, vidl, vtype)
76781Speter #ifdef PI0
77781Speter 	int vline, *vidl, *vtype;
78781Speter {
79781Speter 	register struct nl *np;
80781Speter 	register int *vl;
81781Speter 
82781Speter 	np = gtype(vtype);
83781Speter 	line = vline;
84781Speter 	for (vl = vidl; vl != NIL; vl = vl[2]) {
85781Speter 		}
86781Speter 	}
87781Speter 	send(REVVAR, vline, vidl, vtype);
88781Speter }
89781Speter #else
90781Speter 	int vline;
91781Speter 	register int *vidl;
92781Speter 	int *vtype;
93781Speter {
94781Speter 	register struct nl *np;
95781Speter 	register struct om *op;
96781Speter 	long w;
97781Speter 	int o2;
98781Speter 	int *ovidl = vidl;
993836Speter 	struct nl	*vp;
100781Speter 
101781Speter 	np = gtype(vtype);
102781Speter 	line = vline;
1033949Speter 	w = lwidth(np);
104781Speter 	op = &sizes[cbn];
105781Speter 	for (; vidl != NIL; vidl = vidl[2]) {
106781Speter #		ifdef OBJ
1073235Smckusic 		    op->curtmps.om_off =
1083235Smckusic 			roundup((int)(op->curtmps.om_off-w), (long)align(np));
1093235Smckusic 		    o2 = op -> curtmps.om_off;
110781Speter #		endif OBJ
111781Speter #		ifdef PC
112781Speter 		    if ( cbn == 1 ) {
113781Speter 				/*
114781Speter 				 * global variables are not accessed off the fp
115781Speter 				 * but rather by their names.
116781Speter 				 */
117781Speter 			    o2 = 0;
118781Speter 		    } else {
119781Speter 				/*
120781Speter 				 * locals are aligned, too.
121781Speter 				 */
1223229Smckusic 			    op->curtmps.om_off =
1233229Smckusic 				roundup((int)(op->curtmps.om_off - w),
1243082Smckusic 				(long)align(np));
1253229Smckusic 			    o2 = op -> curtmps.om_off;
126781Speter 		    }
127781Speter #		endif PC
1283836Speter 		vp = enter(defnl(vidl[1], VAR, np, o2));
129781Speter 		if ( np -> nl_flags & NFILES ) {
130781Speter 		    dfiles[ cbn ] = TRUE;
131781Speter 		}
132781Speter #		ifdef PC
133781Speter 		    if ( cbn == 1 ) {
134781Speter 			putprintf( "	.data" , 0 );
1353949Speter 			putprintf( "	.align	%d" , 0 , dotalign(align(np)));
136781Speter 			putprintf( "	.comm	" , 1 );
137781Speter 			putprintf( EXTFORMAT , 1 , vidl[1] );
138781Speter 			putprintf( ",%d" , 0 , w );
139781Speter 			putprintf( "	.text" , 0 );
1402165Speter 			stabgvar( vidl[1] , p2type( np ) , o2 , w , line );
1413836Speter 			vp -> extra_flags |= NGLOBAL;
1423836Speter 		    } else {
1433836Speter 			vp -> extra_flags |= NLOCAL;
144781Speter 		    }
145781Speter #		endif PC
146781Speter 	}
147781Speter #	ifdef PTREE
148781Speter 	    {
149781Speter 		pPointer	*Vars;
150781Speter 		pPointer	Var = VarDecl( ovidl , vtype );
151781Speter 
152781Speter 		pSeize( PorFHeader[ nesting ] );
153781Speter 		Vars = &( pDEF( PorFHeader[ nesting ] ).PorFVars );
154781Speter 		*Vars = ListAppend( *Vars , Var );
155781Speter 		pRelease( PorFHeader[ nesting ] );
156781Speter 	    }
157781Speter #	endif
158781Speter }
159781Speter #endif
160781Speter 
161781Speter varend()
162781Speter {
163781Speter 
164781Speter 	foredecl();
165781Speter #ifndef PI0
1663229Smckusic 	sizes[cbn].om_max = sizes[cbn].curtmps.om_off;
167781Speter #else
168781Speter 	send(REVVEND);
169781Speter #endif
170781Speter }
171781Speter 
172781Speter /*
173781Speter  * Evening
174781Speter  */
1753082Smckusic long
1763082Smckusic leven(w)
1773082Smckusic 	register long w;
1783082Smckusic {
1793082Smckusic 	if (w < 0)
1803082Smckusic 		return (w & 0xfffffffe);
1813082Smckusic 	return ((w+1) & 0xfffffffe);
1823082Smckusic }
1833082Smckusic 
1843082Smckusic int
185781Speter even(w)
186781Speter 	register int w;
187781Speter {
1883082Smckusic 	return leven((long)w);
189781Speter }
190781Speter 
191781Speter /*
192781Speter  * Find the width of a type in bytes.
193781Speter  */
194781Speter width(np)
195781Speter 	struct nl *np;
196781Speter {
197781Speter 
198781Speter 	return (lwidth(np));
199781Speter }
200781Speter 
201781Speter long
202781Speter lwidth(np)
203781Speter 	struct nl *np;
204781Speter {
205781Speter 	register struct nl *p;
206781Speter 	long w;
207781Speter 
208781Speter 	p = np;
209781Speter 	if (p == NIL)
210781Speter 		return (0);
211781Speter loop:
212781Speter 	switch (p->class) {
213781Speter 		case TYPE:
214781Speter 			switch (nloff(p)) {
215781Speter 				case TNIL:
216781Speter 					return (2);
217781Speter 				case TSTR:
218781Speter 				case TSET:
219781Speter 					panic("width");
220781Speter 				default:
221781Speter 					p = p->type;
222781Speter 					goto loop;
223781Speter 			}
224781Speter 		case ARRAY:
225781Speter 			return (aryconst(p, 0));
226781Speter 		case PTR:
227781Speter 			return ( sizeof ( int * ) );
228781Speter 		case FILET:
2292075Smckusic 			return ( sizeof(struct iorec) + lwidth( p -> type ) );
230781Speter 		case RANGE:
231781Speter 			if (p->type == nl+TDOUBLE)
232781Speter #ifdef DEBUG
233781Speter 				return (hp21mx ? 4 : 8);
234781Speter #else
235781Speter 				return (8);
236781Speter #endif
237781Speter 		case SCAL:
238781Speter 			return (bytes(p->range[0], p->range[1]));
239781Speter 		case SET:
240781Speter 			setran(p->type);
2413082Smckusic 			return roundup((int)((set.uprbp >> 3) + 1),
2423082Smckusic 				(long)(A_SET));
243781Speter 		case STR:
244781Speter 		case RECORD:
245781Speter 			return ( p->value[NL_OFFS] );
246781Speter 		default:
247781Speter 			panic("wclass");
248781Speter 	}
249781Speter }
250781Speter 
251781Speter     /*
252781Speter      *	round up x to a multiple of y
253781Speter      *	for computing offsets of aligned things.
254781Speter      *	y had better be positive.
255781Speter      *	rounding is in the direction of x.
256781Speter      */
257781Speter long
258781Speter roundup( x , y )
2593082Smckusic     int			x;
260781Speter     register long	y;
261781Speter     {
262781Speter 
263781Speter 	if ( y == 0 ) {
2644030Smckusic 	    return x;
265781Speter 	}
266781Speter 	if ( x >= 0 ) {
267781Speter 		return ( ( ( x + ( y - 1 ) ) / y ) * y );
268781Speter 	} else {
269781Speter 		return ( ( ( x - ( y - 1 ) ) / y ) * y );
270781Speter 	}
271781Speter     }
272781Speter 
273781Speter     /*
274781Speter      *	alignment of an object using the c alignment scheme
275781Speter      */
276781Speter int
277781Speter align( np )
278781Speter     struct nl	*np;
279781Speter     {
280781Speter 	register struct nl *p;
281781Speter 
282781Speter 	p = np;
283781Speter 	if ( p == NIL ) {
284781Speter 	    return 0;
285781Speter 	}
286781Speter alignit:
287781Speter 	switch ( p -> class ) {
288781Speter 	    case TYPE:
289781Speter 		    switch ( nloff( p ) ) {
290781Speter 			case TNIL:
291781Speter 				return A_POINT;
292781Speter 			case TSTR:
293781Speter 				return A_CHAR;
294781Speter 			case TSET:
295781Speter 				return A_SET;
296781Speter 			default:
297781Speter 				p = p -> type;
298781Speter 				goto alignit;
299781Speter 		    }
300781Speter 	    case ARRAY:
301781Speter 			/*
302781Speter 			 * arrays are aligned as their component types
303781Speter 			 */
304781Speter 		    p = p -> type;
305781Speter 		    goto alignit;
306781Speter 	    case PTR:
307781Speter 		    return A_POINT;
308781Speter 	    case FILET:
309781Speter 		    return A_FILET;
310781Speter 	    case RANGE:
311781Speter 		    if ( p -> type == nl+TDOUBLE ) {
312781Speter 			return A_DOUBLE;
313781Speter 		    }
314781Speter 		    /* else, fall through */
315781Speter 	    case SCAL:
316781Speter 		    switch ( bytes( p -> range[0] , p -> range[1] ) ) {
317781Speter 			case 4:
318781Speter 			    return A_LONG;
319781Speter 			case 2:
320781Speter 			    return A_SHORT;
321781Speter 			case 1:
322781Speter 			    return A_CHAR;
323781Speter 			default:
324781Speter 			    panic( "align: scal" );
325781Speter 		    }
326781Speter 	    case SET:
327781Speter 		    return A_SET;
328781Speter 	    case STR:
329781Speter 		    return A_CHAR;
330781Speter 	    case RECORD:
331781Speter 			/*
332*8681Speter 			 * the alignment of a record is in its align_info field
333*8681Speter 			 * why don't we use this for the rest of the namelist?
334781Speter 			 */
335*8681Speter 		    return p -> align_info;
336781Speter 	    default:
337781Speter 		    panic( "align" );
338781Speter 	}
339781Speter     }
340781Speter 
3413949Speter     /*
3423949Speter      *	given an alignment, return power of two for .align pseudo-op
3433949Speter      */
3443949Speter dotalign( alignment )
3453949Speter     int	alignment;
3463949Speter {
3473949Speter 
3483949Speter     switch ( alignment ) {
3493949Speter 	case A_CHAR:		/*
3503949Speter 				 * also
3513949Speter 				 *	A_STRUCT
3523949Speter 				 */
3533949Speter 		return 0;
3543949Speter 	case A_SHORT:
3553949Speter 		return 1;
3563949Speter 	case A_LONG:		/*
3573949Speter 				 * also
3583949Speter 				 *	A_POINT, A_INT, A_FLOAT, A_DOUBLE,
3593949Speter 				 *	A_STACK, A_FILET, A_SET
3603949Speter 				 */
3613949Speter 		return 2;
3623949Speter     }
3633949Speter }
3643949Speter 
365781Speter /*
366781Speter  * Return the width of an element
367781Speter  * of a n time subscripted np.
368781Speter  */
369781Speter long aryconst(np, n)
370781Speter 	struct nl *np;
371781Speter 	int n;
372781Speter {
373781Speter 	register struct nl *p;
374781Speter 	long s, d;
375781Speter 
376781Speter 	if ((p = np) == NIL)
377781Speter 		return (NIL);
378781Speter 	if (p->class != ARRAY)
379781Speter 		panic("ary");
380781Speter 	s = lwidth(p->type);
381781Speter 	/*
382781Speter 	 * Arrays of anything but characters are word aligned.
383781Speter 	 */
384781Speter 	if (s & 1)
385781Speter 		if (s != 1)
386781Speter 			s++;
387781Speter 	/*
388781Speter 	 * Skip the first n subscripts
389781Speter 	 */
390781Speter 	while (n >= 0) {
391781Speter 		p = p->chain;
392781Speter 		n--;
393781Speter 	}
394781Speter 	/*
395781Speter 	 * Sum across remaining subscripts.
396781Speter 	 */
397781Speter 	while (p != NIL) {
398781Speter 		if (p->class != RANGE && p->class != SCAL)
399781Speter 			panic("aryran");
400781Speter 		d = p->range[1] - p->range[0] + 1;
401781Speter 		s *= d;
402781Speter 		p = p->chain;
403781Speter 	}
404781Speter 	return (s);
405781Speter }
406781Speter 
407781Speter /*
408781Speter  * Find the lower bound of a set, and also its size in bits.
409781Speter  */
410781Speter setran(q)
411781Speter 	struct nl *q;
412781Speter {
413781Speter 	register lb, ub;
414781Speter 	register struct nl *p;
415781Speter 
416781Speter 	p = q;
417781Speter 	if (p == NIL)
418781Speter 		return (NIL);
419781Speter 	lb = p->range[0];
420781Speter 	ub = p->range[1];
421781Speter 	if (p->class != RANGE && p->class != SCAL)
422781Speter 		panic("setran");
423781Speter 	set.lwrb = lb;
424781Speter 	/* set.(upperbound prime) = number of bits - 1; */
425781Speter 	set.uprbp = ub-lb;
426781Speter }
427781Speter 
428781Speter /*
429781Speter  * Return the number of bytes required to hold an arithmetic quantity
430781Speter  */
431781Speter bytes(lb, ub)
432781Speter 	long lb, ub;
433781Speter {
434781Speter 
435781Speter #ifndef DEBUG
436781Speter 	if (lb < -32768 || ub > 32767)
437781Speter 		return (4);
438781Speter 	else if (lb < -128 || ub > 127)
439781Speter 		return (2);
440781Speter #else
441781Speter 	if (!hp21mx && (lb < -32768 || ub > 32767))
442781Speter 		return (4);
443781Speter 	if (lb < -128 || ub > 127)
444781Speter 		return (2);
445781Speter #endif
446781Speter 	else
447781Speter 		return (1);
448781Speter }
449