new copyright; att/bsd/shared
[unix-history] / usr / src / usr.bin / pascal / src / var.c
CommitLineData
0fc6e47b
KB
1/*-
2 * Copyright (c) 1980 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * %sccs.include.redist.c%
252367af 6 */
c7f21b42 7
72fbef68 8#ifndef lint
0fc6e47b
KB
9static char sccsid[] = "@(#)var.c 5.5 (Berkeley) %G%";
10#endif /* not lint */
c7f21b42
PK
11
12#include "whoami.h"
13#include "0.h"
82ebacca 14#include "objfmt.h"
c7f21b42 15#include "align.h"
4c1835f7 16#include "iorec.h"
c7f21b42
PK
17#ifdef PC
18# include "pc.h"
c7f21b42 19#endif PC
f763caa4 20#include "tmps.h"
72fbef68 21#include "tree_ty.h"
c7f21b42
PK
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 */
72fbef68 30/*ARGSUSED*/
7204688c
PK
31varbeg( lineofyvar , r )
32 int lineofyvar;
c7f21b42 33{
7204688c
PK
34 static bool var_order = FALSE;
35 static bool var_seen = FALSE;
c7f21b42 36
af97bcfa 37/* this allows for multiple declaration
c7f21b42
PK
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
af97bcfa
PK
45 if (!progseen)
46 level1();
7204688c 47 line = lineofyvar;
af97bcfa
PK
48 if ( parts[ cbn ] & RPRT ) {
49 if ( opt( 's' ) ) {
c7f21b42 50 standard();
7204688c 51 error("Variable declarations should precede routine declarations");
af97bcfa 52 } else {
7204688c
PK
53 if ( !var_order ) {
54 var_order = TRUE;
55 warning();
56 error("Variable declarations should precede routine declarations");
57 }
af97bcfa 58 }
c7f21b42 59 }
af97bcfa
PK
60 if ( parts[ cbn ] & VPRT ) {
61 if ( opt( 's' ) ) {
62 standard();
7204688c 63 error("All variables should be declared in one var part");
af97bcfa 64 } else {
7204688c
PK
65 if ( !var_seen ) {
66 var_seen = TRUE;
67 warning();
68 error("All variables should be declared in one var part");
69 }
af97bcfa 70 }
af97bcfa
PK
71 }
72 parts[ cbn ] |= VPRT;
c7f21b42
PK
73#endif
74 /*
75 * #ifndef PI0
ddb1d555 76 * sizes[cbn].om_max = sizes[cbn].curtmps.om_off = -DPOFF1;
c7f21b42
PK
77 * #endif
78 */
79 forechain = NIL;
80#ifdef PI0
81 send(REVVBEG);
82#endif
83}
84
85var(vline, vidl, vtype)
86#ifdef PI0
72fbef68
RT
87 int vline;
88 struct tnode *vidl, *vtype;
c7f21b42
PK
89{
90 register struct nl *np;
72fbef68 91 register struct tnode *vl;
c7f21b42
PK
92
93 np = gtype(vtype);
94 line = vline;
72fbef68
RT
95 /* why is this here? */
96 for (vl = vidl; vl != TR_NIL; vl = vl->list_node.next) {
c7f21b42
PK
97 }
98 }
99 send(REVVAR, vline, vidl, vtype);
100}
101#else
102 int vline;
72fbef68
RT
103 register struct tnode *vidl;
104 struct tnode *vtype;
c7f21b42
PK
105{
106 register struct nl *np;
107 register struct om *op;
108 long w;
109 int o2;
72fbef68 110#ifdef PC
1f43951f 111 struct nl *vp;
72fbef68 112#endif
c7f21b42
PK
113
114 np = gtype(vtype);
115 line = vline;
4a4b0cfc 116 w = lwidth(np);
c7f21b42 117 op = &sizes[cbn];
72fbef68 118 for (; vidl != TR_NIL; vidl = vidl->list_node.next) {
c7f21b42 119# ifdef OBJ
f8d06e69
KM
120 op->curtmps.om_off =
121 roundup((int)(op->curtmps.om_off-w), (long)align(np));
122 o2 = op -> curtmps.om_off;
c7f21b42
PK
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 */
ddb1d555
KM
135 op->curtmps.om_off =
136 roundup((int)(op->curtmps.om_off - w),
6cbd3a07 137 (long)align(np));
ddb1d555 138 o2 = op -> curtmps.om_off;
c7f21b42
PK
139 }
140# endif PC
72fbef68
RT
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
cb5423b7 146 if ( np != NLNIL && (np -> nl_flags & NFILES) ) {
c7f21b42
PK
147 dfiles[ cbn ] = TRUE;
148 }
149# ifdef PC
150 if ( cbn == 1 ) {
151 putprintf( " .data" , 0 );
82ebacca 152 aligndot(align(np));
c7f21b42 153 putprintf( " .comm " , 1 );
72fbef68
RT
154 putprintf( EXTFORMAT , 1 , (int) vidl->list_node.list );
155 putprintf( ",%d" , 0 , (int) w );
c7f21b42 156 putprintf( " .text" , 0 );
8c8b6ab8 157 stabgvar( vp , w , line );
1f43951f
PK
158 vp -> extra_flags |= NGLOBAL;
159 } else {
160 vp -> extra_flags |= NLOCAL;
c7f21b42 161 }
c7f21b42
PK
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
178varend()
179{
180
181 foredecl();
182#ifndef PI0
ddb1d555 183 sizes[cbn].om_max = sizes[cbn].curtmps.om_off;
c7f21b42
PK
184#else
185 send(REVVEND);
186#endif
187}
188
c7f21b42
PK
189/*
190 * Find the width of a type in bytes.
191 */
192width(np)
193 struct nl *np;
194{
195
196 return (lwidth(np));
197}
198
199long
200lwidth(np)
201 struct nl *np;
202{
203 register struct nl *p;
c7f21b42
PK
204
205 p = np;
206 if (p == NIL)
207 return (0);
208loop:
209 switch (p->class) {
72fbef68
RT
210 default:
211 panic("wclass");
c7f21b42
PK
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:
4c1835f7 228 return ( sizeof(struct iorec) + lwidth( p -> type ) );
9965cdc3
KM
229 case CRANGE:
230 p = p->type;
231 goto loop;
c7f21b42
PK
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);
e7a4b007
KM
243 /*
244 * Sets are some multiple of longs
245 */
6cbd3a07 246 return roundup((int)((set.uprbp >> 3) + 1),
e7a4b007 247 (long)(sizeof(long)));
c7f21b42
PK
248 case STR:
249 case RECORD:
250 return ( p->value[NL_OFFS] );
c7f21b42
PK
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 */
260long
261roundup( x , y )
6cbd3a07 262 int x;
c7f21b42
PK
263 register long y;
264 {
265
266 if ( y == 0 ) {
9a322285 267 return x;
c7f21b42
PK
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 */
279int
280align( np )
281 struct nl *np;
282 {
283 register struct nl *p;
e7a4b007 284 long elementalign;
c7f21b42
PK
285
286 p = np;
287 if ( p == NIL ) {
288 return 0;
289 }
290alignit:
291 switch ( p -> class ) {
72fbef68
RT
292 default:
293 panic( "align" );
c7f21b42
PK
294 case TYPE:
295 switch ( nloff( p ) ) {
296 case TNIL:
297 return A_POINT;
298 case TSTR:
82ebacca 299 return A_STRUCT;
c7f21b42
PK
300 case TSET:
301 return A_SET;
302 default:
303 p = p -> type;
304 goto alignit;
305 }
306 case ARRAY:
307 /*
e7a4b007 308 * arrays are structures, since they can get
82ebacca 309 * assigned form/to as structure assignments.
e7a4b007 310 * preserve internal alignment if it is greater.
c7f21b42 311 */
e7a4b007
KM
312 elementalign = align(p -> type);
313 return elementalign > A_STRUCT ? elementalign : A_STRUCT;
c7f21b42
PK
314 case PTR:
315 return A_POINT;
316 case FILET:
317 return A_FILET;
9965cdc3 318 case CRANGE:
c7f21b42
PK
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:
82ebacca
PK
338 /*
339 * arrays of chars are structs
340 */
341 return A_STRUCT;
c7f21b42
PK
342 case RECORD:
343 /*
d25ca1ea
PK
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?
c7f21b42 346 */
d25ca1ea 347 return p -> align_info;
c7f21b42
PK
348 }
349 }
350
82ebacca 351#ifdef PC
4a4b0cfc 352 /*
82ebacca 353 * output an alignment pseudo-op.
4a4b0cfc 354 */
82ebacca 355aligndot(alignment)
4a4b0cfc 356 int alignment;
d374dfc8 357#if defined(vax) || defined(tahoe)
4a4b0cfc 358{
82ebacca
PK
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;
4a4b0cfc
PK
369 }
370}
d374dfc8 371#endif vax || tahoe
82ebacca
PK
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
c7f21b42
PK
385/*
386 * Return the width of an element
387 * of a n time subscripted np.
388 */
389long 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");
9965cdc3
KM
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);
c7f21b42
PK
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 */
436setran(q)
437 struct nl *q;
438{
439 register lb, ub;
440 register struct nl *p;
441
442 p = q;
443 if (p == NIL)
72fbef68 444 return;
c7f21b42
PK
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 */
457bytes(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}