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