xref: /csrg-svn/usr.bin/pascal/src/var.c (revision 22201)
1*22201Sdist /*
2*22201Sdist  * Copyright (c) 1980 Regents of the University of California.
3*22201Sdist  * All rights reserved.  The Berkeley software License Agreement
4*22201Sdist  * specifies the terms and conditions for redistribution.
5*22201Sdist  */
6781Speter 
718351Smckusick #ifndef lint
8*22201Sdist static char sccsid[] = "@(#)var.c	5.1 (Berkeley) 06/05/85";
9*22201Sdist #endif not lint
10781Speter 
11781Speter #include "whoami.h"
12781Speter #include "0.h"
1310664Speter #include "objfmt.h"
14781Speter #include "align.h"
152075Smckusic #include "iorec.h"
16781Speter #ifdef PC
17781Speter #   include	"pc.h"
18781Speter #endif PC
1911336Speter #include "tmps.h"
2018351Smckusick #include "tree_ty.h"
21781Speter 
22781Speter /*
23781Speter  * Declare variables of a var part.  DPOFF1 is
24781Speter  * the local variable storage for all prog/proc/func
25781Speter  * modules aside from the block mark.  The total size
26781Speter  * of all the local variables is entered into the
27781Speter  * size array.
28781Speter  */
2918351Smckusick /*ARGSUSED*/
307951Speter varbeg( lineofyvar , r )
317951Speter     int	lineofyvar;
32781Speter {
337951Speter     static bool	var_order = FALSE;
347951Speter     static bool	var_seen = FALSE;
35781Speter 
36837Speter /* this allows for multiple declaration
37781Speter  * parts except when the "standard"
38781Speter  * option has been specified.
39781Speter  * If routine segment is being compiled,
40781Speter  * do level one processing.
41781Speter  */
42781Speter 
43781Speter #ifndef PI1
44837Speter 	if (!progseen)
45837Speter 		level1();
467951Speter 	line = lineofyvar;
47837Speter 	if ( parts[ cbn ] & RPRT ) {
48837Speter 	    if ( opt( 's' ) ) {
49781Speter 		standard();
507951Speter 		error("Variable declarations should precede routine declarations");
51837Speter 	    } else {
527951Speter 		if ( !var_order ) {
537951Speter 		    var_order = TRUE;
547951Speter 		    warning();
557951Speter 		    error("Variable declarations should precede routine declarations");
567951Speter 		}
57837Speter 	    }
58781Speter 	}
59837Speter 	if ( parts[ cbn ] & VPRT ) {
60837Speter 	    if ( opt( 's' ) ) {
61837Speter 		standard();
627951Speter 		error("All variables should be declared in one var part");
63837Speter 	    } else {
647951Speter 		if ( !var_seen ) {
657951Speter 		    var_seen = TRUE;
667951Speter 		    warning();
677951Speter 		    error("All variables should be declared in one var part");
687951Speter 		}
69837Speter 	    }
70837Speter 	}
71837Speter 	parts[ cbn ] |= VPRT;
72781Speter #endif
73781Speter     /*
74781Speter      *  #ifndef PI0
753229Smckusic      *      sizes[cbn].om_max = sizes[cbn].curtmps.om_off = -DPOFF1;
76781Speter      *  #endif
77781Speter      */
78781Speter 	forechain = NIL;
79781Speter #ifdef PI0
80781Speter 	send(REVVBEG);
81781Speter #endif
82781Speter }
83781Speter 
84781Speter var(vline, vidl, vtype)
85781Speter #ifdef PI0
8618351Smckusick 	int vline;
8718351Smckusick 	struct tnode *vidl, *vtype;
88781Speter {
89781Speter 	register struct nl *np;
9018351Smckusick 	register struct tnode *vl;
91781Speter 
92781Speter 	np = gtype(vtype);
93781Speter 	line = vline;
9418351Smckusick 	/* why is this here? */
9518351Smckusick 	for (vl = vidl; vl != TR_NIL; vl = vl->list_node.next) {
96781Speter 		}
97781Speter 	}
98781Speter 	send(REVVAR, vline, vidl, vtype);
99781Speter }
100781Speter #else
101781Speter 	int vline;
10218351Smckusick 	register struct tnode *vidl;
10318351Smckusick 	struct tnode *vtype;
104781Speter {
105781Speter 	register struct nl *np;
106781Speter 	register struct om *op;
107781Speter 	long w;
108781Speter 	int o2;
10918351Smckusick #ifdef PC
1103836Speter 	struct nl	*vp;
11118351Smckusick #endif
112781Speter 
113781Speter 	np = gtype(vtype);
114781Speter 	line = vline;
1153949Speter 	w = lwidth(np);
116781Speter 	op = &sizes[cbn];
11718351Smckusick 	for (; vidl != TR_NIL; vidl = vidl->list_node.next) {
118781Speter #		ifdef OBJ
1193235Smckusic 		    op->curtmps.om_off =
1203235Smckusic 			roundup((int)(op->curtmps.om_off-w), (long)align(np));
1213235Smckusic 		    o2 = op -> curtmps.om_off;
122781Speter #		endif OBJ
123781Speter #		ifdef PC
124781Speter 		    if ( cbn == 1 ) {
125781Speter 				/*
126781Speter 				 * global variables are not accessed off the fp
127781Speter 				 * but rather by their names.
128781Speter 				 */
129781Speter 			    o2 = 0;
130781Speter 		    } else {
131781Speter 				/*
132781Speter 				 * locals are aligned, too.
133781Speter 				 */
1343229Smckusic 			    op->curtmps.om_off =
1353229Smckusic 				roundup((int)(op->curtmps.om_off - w),
1363082Smckusic 				(long)align(np));
1373229Smckusic 			    o2 = op -> curtmps.om_off;
138781Speter 		    }
139781Speter #		endif PC
14018351Smckusick #		ifdef PC
14118351Smckusick 		vp = enter(defnl((char *) vidl->list_node.list, VAR, np, o2));
14218351Smckusick #		else
14318351Smckusick 		(void) enter(defnl((char *) vidl->list_node.list, VAR, np, o2));
14418351Smckusick #		endif
145781Speter 		if ( np -> nl_flags & NFILES ) {
146781Speter 		    dfiles[ cbn ] = TRUE;
147781Speter 		}
148781Speter #		ifdef PC
149781Speter 		    if ( cbn == 1 ) {
150781Speter 			putprintf( "	.data" , 0 );
15110664Speter 			aligndot(align(np));
152781Speter 			putprintf( "	.comm	" , 1 );
15318351Smckusick 			putprintf( EXTFORMAT , 1 , (int) vidl->list_node.list );
15418351Smckusick 			putprintf( ",%d" , 0 , (int) w );
155781Speter 			putprintf( "	.text" , 0 );
15618351Smckusick 			stabgvar( vp , w , line );
1573836Speter 			vp -> extra_flags |= NGLOBAL;
1583836Speter 		    } else {
1593836Speter 			vp -> extra_flags |= NLOCAL;
160781Speter 		    }
161781Speter #		endif PC
162781Speter 	}
163781Speter #	ifdef PTREE
164781Speter 	    {
165781Speter 		pPointer	*Vars;
166781Speter 		pPointer	Var = VarDecl( ovidl , vtype );
167781Speter 
168781Speter 		pSeize( PorFHeader[ nesting ] );
169781Speter 		Vars = &( pDEF( PorFHeader[ nesting ] ).PorFVars );
170781Speter 		*Vars = ListAppend( *Vars , Var );
171781Speter 		pRelease( PorFHeader[ nesting ] );
172781Speter 	    }
173781Speter #	endif
174781Speter }
175781Speter #endif
176781Speter 
177781Speter varend()
178781Speter {
179781Speter 
180781Speter 	foredecl();
181781Speter #ifndef PI0
1823229Smckusic 	sizes[cbn].om_max = sizes[cbn].curtmps.om_off;
183781Speter #else
184781Speter 	send(REVVEND);
185781Speter #endif
186781Speter }
187781Speter 
188781Speter /*
189781Speter  * Evening
190781Speter  */
1913082Smckusic long
1923082Smckusic leven(w)
1933082Smckusic 	register long w;
1943082Smckusic {
1953082Smckusic 	if (w < 0)
1963082Smckusic 		return (w & 0xfffffffe);
1973082Smckusic 	return ((w+1) & 0xfffffffe);
1983082Smckusic }
1993082Smckusic 
20018351Smckusick #ifndef PC
2013082Smckusic int
202781Speter even(w)
203781Speter 	register int w;
204781Speter {
2053082Smckusic 	return leven((long)w);
206781Speter }
20718351Smckusick #endif
208781Speter 
209781Speter /*
210781Speter  * Find the width of a type in bytes.
211781Speter  */
212781Speter width(np)
213781Speter 	struct nl *np;
214781Speter {
215781Speter 
216781Speter 	return (lwidth(np));
217781Speter }
218781Speter 
219781Speter long
220781Speter lwidth(np)
221781Speter 	struct nl *np;
222781Speter {
223781Speter 	register struct nl *p;
224781Speter 
225781Speter 	p = np;
226781Speter 	if (p == NIL)
227781Speter 		return (0);
228781Speter loop:
229781Speter 	switch (p->class) {
23018351Smckusick 		default:
23118351Smckusick 			panic("wclass");
232781Speter 		case TYPE:
233781Speter 			switch (nloff(p)) {
234781Speter 				case TNIL:
235781Speter 					return (2);
236781Speter 				case TSTR:
237781Speter 				case TSET:
238781Speter 					panic("width");
239781Speter 				default:
240781Speter 					p = p->type;
241781Speter 					goto loop;
242781Speter 			}
243781Speter 		case ARRAY:
244781Speter 			return (aryconst(p, 0));
245781Speter 		case PTR:
246781Speter 			return ( sizeof ( int * ) );
247781Speter 		case FILET:
2482075Smckusic 			return ( sizeof(struct iorec) + lwidth( p -> type ) );
24918351Smckusick 		case CRANGE:
25018351Smckusick 			p = p->type;
25118351Smckusick 			goto loop;
252781Speter 		case RANGE:
253781Speter 			if (p->type == nl+TDOUBLE)
254781Speter #ifdef DEBUG
255781Speter 				return (hp21mx ? 4 : 8);
256781Speter #else
257781Speter 				return (8);
258781Speter #endif
259781Speter 		case SCAL:
260781Speter 			return (bytes(p->range[0], p->range[1]));
261781Speter 		case SET:
262781Speter 			setran(p->type);
26311822Smckusick 			/*
26411822Smckusick 			 * Sets are some multiple of longs
26511822Smckusick 			 */
2663082Smckusic 			return roundup((int)((set.uprbp >> 3) + 1),
26711822Smckusick 				(long)(sizeof(long)));
268781Speter 		case STR:
269781Speter 		case RECORD:
270781Speter 			return ( p->value[NL_OFFS] );
271781Speter 	}
272781Speter }
273781Speter 
274781Speter     /*
275781Speter      *	round up x to a multiple of y
276781Speter      *	for computing offsets of aligned things.
277781Speter      *	y had better be positive.
278781Speter      *	rounding is in the direction of x.
279781Speter      */
280781Speter long
281781Speter roundup( x , y )
2823082Smckusic     int			x;
283781Speter     register long	y;
284781Speter     {
285781Speter 
286781Speter 	if ( y == 0 ) {
2874030Smckusic 	    return x;
288781Speter 	}
289781Speter 	if ( x >= 0 ) {
290781Speter 		return ( ( ( x + ( y - 1 ) ) / y ) * y );
291781Speter 	} else {
292781Speter 		return ( ( ( x - ( y - 1 ) ) / y ) * y );
293781Speter 	}
294781Speter     }
295781Speter 
296781Speter     /*
297781Speter      *	alignment of an object using the c alignment scheme
298781Speter      */
299781Speter int
300781Speter align( np )
301781Speter     struct nl	*np;
302781Speter     {
303781Speter 	register struct nl *p;
30411822Smckusick 	long elementalign;
305781Speter 
306781Speter 	p = np;
307781Speter 	if ( p == NIL ) {
308781Speter 	    return 0;
309781Speter 	}
310781Speter alignit:
311781Speter 	switch ( p -> class ) {
31218351Smckusick 	    default:
31318351Smckusick 		    panic( "align" );
314781Speter 	    case TYPE:
315781Speter 		    switch ( nloff( p ) ) {
316781Speter 			case TNIL:
317781Speter 				return A_POINT;
318781Speter 			case TSTR:
31910664Speter 				return A_STRUCT;
320781Speter 			case TSET:
321781Speter 				return A_SET;
322781Speter 			default:
323781Speter 				p = p -> type;
324781Speter 				goto alignit;
325781Speter 		    }
326781Speter 	    case ARRAY:
327781Speter 			/*
32811822Smckusick 			 * arrays are structures, since they can get
32910664Speter 			 * assigned form/to as structure assignments.
33011822Smckusick 			 * preserve internal alignment if it is greater.
331781Speter 			 */
33211822Smckusick 		    elementalign = align(p -> type);
33311822Smckusick 		    return elementalign > A_STRUCT ? elementalign : A_STRUCT;
334781Speter 	    case PTR:
335781Speter 		    return A_POINT;
336781Speter 	    case FILET:
337781Speter 		    return A_FILET;
33818351Smckusick 	    case CRANGE:
339781Speter 	    case RANGE:
340781Speter 		    if ( p -> type == nl+TDOUBLE ) {
341781Speter 			return A_DOUBLE;
342781Speter 		    }
343781Speter 		    /* else, fall through */
344781Speter 	    case SCAL:
345781Speter 		    switch ( bytes( p -> range[0] , p -> range[1] ) ) {
346781Speter 			case 4:
347781Speter 			    return A_LONG;
348781Speter 			case 2:
349781Speter 			    return A_SHORT;
350781Speter 			case 1:
351781Speter 			    return A_CHAR;
352781Speter 			default:
353781Speter 			    panic( "align: scal" );
354781Speter 		    }
355781Speter 	    case SET:
356781Speter 		    return A_SET;
357781Speter 	    case STR:
35810664Speter 			/*
35910664Speter 			 * arrays of chars are structs
36010664Speter 			 */
36110664Speter 		    return A_STRUCT;
362781Speter 	    case RECORD:
363781Speter 			/*
3648681Speter 			 * the alignment of a record is in its align_info field
3658681Speter 			 * why don't we use this for the rest of the namelist?
366781Speter 			 */
3678681Speter 		    return p -> align_info;
368781Speter 	}
369781Speter     }
370781Speter 
37110664Speter #ifdef PC
3723949Speter     /*
37310664Speter      *	output an alignment pseudo-op.
3743949Speter      */
37510664Speter aligndot(alignment)
3763949Speter     int	alignment;
37710664Speter #ifdef vax
3783949Speter {
37910664Speter     switch (alignment) {
38010664Speter 	case 1:
38110664Speter 	    return;
38210664Speter 	case 2:
38310664Speter 	    putprintf("	.align 1", 0);
38410664Speter 	    return;
38510664Speter 	default:
38610664Speter 	case 4:
38710664Speter 	    putprintf("	.align 2", 0);
38810664Speter 	    return;
3893949Speter     }
3903949Speter }
39110664Speter #endif vax
39210664Speter #ifdef mc68000
39310664Speter {
39410664Speter     switch (alignment) {
39510664Speter 	case 1:
39610664Speter 	    return;
39710664Speter 	default:
39810664Speter 	    putprintf("	.even", 0);
39910664Speter 	    return;
40010664Speter     }
40110664Speter }
40210664Speter #endif mc68000
40310664Speter #endif PC
40410664Speter 
405781Speter /*
406781Speter  * Return the width of an element
407781Speter  * of a n time subscripted np.
408781Speter  */
409781Speter long aryconst(np, n)
410781Speter 	struct nl *np;
411781Speter 	int n;
412781Speter {
413781Speter 	register struct nl *p;
414781Speter 	long s, d;
415781Speter 
416781Speter 	if ((p = np) == NIL)
417781Speter 		return (NIL);
418781Speter 	if (p->class != ARRAY)
419781Speter 		panic("ary");
42018351Smckusick 	/*
42118351Smckusick 	 * If it is a conformant array, we cannot find the width from
42218351Smckusick 	 * the type.
42318351Smckusick 	 */
42418351Smckusick 	if (p->chain->class == CRANGE)
42518351Smckusick 		return (NIL);
426781Speter 	s = lwidth(p->type);
427781Speter 	/*
428781Speter 	 * Arrays of anything but characters are word aligned.
429781Speter 	 */
430781Speter 	if (s & 1)
431781Speter 		if (s != 1)
432781Speter 			s++;
433781Speter 	/*
434781Speter 	 * Skip the first n subscripts
435781Speter 	 */
436781Speter 	while (n >= 0) {
437781Speter 		p = p->chain;
438781Speter 		n--;
439781Speter 	}
440781Speter 	/*
441781Speter 	 * Sum across remaining subscripts.
442781Speter 	 */
443781Speter 	while (p != NIL) {
444781Speter 		if (p->class != RANGE && p->class != SCAL)
445781Speter 			panic("aryran");
446781Speter 		d = p->range[1] - p->range[0] + 1;
447781Speter 		s *= d;
448781Speter 		p = p->chain;
449781Speter 	}
450781Speter 	return (s);
451781Speter }
452781Speter 
453781Speter /*
454781Speter  * Find the lower bound of a set, and also its size in bits.
455781Speter  */
456781Speter setran(q)
457781Speter 	struct nl *q;
458781Speter {
459781Speter 	register lb, ub;
460781Speter 	register struct nl *p;
461781Speter 
462781Speter 	p = q;
463781Speter 	if (p == NIL)
46418351Smckusick 		return;
465781Speter 	lb = p->range[0];
466781Speter 	ub = p->range[1];
467781Speter 	if (p->class != RANGE && p->class != SCAL)
468781Speter 		panic("setran");
469781Speter 	set.lwrb = lb;
470781Speter 	/* set.(upperbound prime) = number of bits - 1; */
471781Speter 	set.uprbp = ub-lb;
472781Speter }
473781Speter 
474781Speter /*
475781Speter  * Return the number of bytes required to hold an arithmetic quantity
476781Speter  */
477781Speter bytes(lb, ub)
478781Speter 	long lb, ub;
479781Speter {
480781Speter 
481781Speter #ifndef DEBUG
482781Speter 	if (lb < -32768 || ub > 32767)
483781Speter 		return (4);
484781Speter 	else if (lb < -128 || ub > 127)
485781Speter 		return (2);
486781Speter #else
487781Speter 	if (!hp21mx && (lb < -32768 || ub > 32767))
488781Speter 		return (4);
489781Speter 	if (lb < -128 || ub > 127)
490781Speter 		return (2);
491781Speter #endif
492781Speter 	else
493781Speter 		return (1);
494781Speter }
495