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