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