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