xref: /csrg-svn/old/pcc/mip/pftn.c (revision 31000)
1 #ifndef lint
2 static char *sccsid ="@(#)pftn.c	1.15 (Berkeley) 05/01/87";
3 #endif lint
4 
5 # include "pass1.h"
6 
7 unsigned int offsz;
8 
9 struct symtab *schain[MAXSCOPES];	/* sym chains for clearst */
10 int chaintop;				/* highest active entry */
11 
12 struct instk {
13 	int in_sz;   /* size of array element */
14 	int in_x;    /* current index for structure member in structure initializations */
15 	int in_n;    /* number of initializations seen */
16 	int in_s;    /* sizoff */
17 	int in_d;    /* dimoff */
18 	TWORD in_t;    /* type */
19 	int in_id;   /* stab index */
20 	int in_fl;   /* flag which says if this level is controlled by {} */
21 	OFFSZ in_off;  /* offset of the beginning of this level */
22 	}
23 instack[10],
24 *pstk;
25 
26 	/* defines used for getting things off of the initialization stack */
27 
28 
29 struct symtab *relook();
30 
31 
32 int ddebug = 0;
33 
34 struct symtab * mknonuniq();
35 
36 defid( q, class ) register NODE *q; register int class; {
37 	register struct symtab *p;
38 	int idp;
39 	register TWORD type;
40 	TWORD stp;
41 	register int scl;
42 	int dsym, ddef;
43 	int slev, temp;
44 	int changed;
45 
46 	if( q == NIL ) return;  /* an error was detected */
47 
48 	if( q < node || q >= &node[TREESZ] ) cerror( "defid call" );
49 
50 	idp = q->tn.rval;
51 
52 	if( idp < 0 ) cerror( "tyreduce" );
53 	p = &stab[idp];
54 #ifdef LINT
55 	if (pflag) {
56 		register int	i;
57 
58 #ifndef FLEXNAMES
59 		for (i = 0; i < 8; ++i)
60 #else /* FLEXNAMES */
61 		for (i = 0; ; ++i)
62 #endif /* FLEXNAMES */
63 			if (p->sname[i] == '\0')
64 				break;
65 			else if (p->sname[i] == '$') {
66 #ifndef FLEXNAMES
67 				werror( "nonportable identifier (uses $): %.8s",
68 #else /* FLEXNAMES */
69 				werror( "nonportable identifier (uses $): %s",
70 #endif /* FLEXNAMES */
71 					p->sname);
72 				break;
73 			}
74 	}
75 #endif /* LINT */
76 
77 # ifndef BUG1
78 	if( ddebug ){
79 #ifndef FLEXNAMES
80 		printf( "defid( %.8s (%d), ", p->sname, idp );
81 #else
82 		printf( "defid( %s (%d), ", p->sname, idp );
83 #endif
84 		tprint( q->in.type );
85 		printf( ", %s, (%d,%d) ), level %d\n", scnames(class), q->fn.cdim, q->fn.csiz, blevel );
86 		}
87 # endif
88 
89 	fixtype( q, class );
90 
91 	type = q->in.type;
92 	class = fixclass( class, type );
93 
94 	stp = p->stype;
95 	slev = p->slevel;
96 
97 # ifndef BUG1
98 	if( ddebug ){
99 		printf( "	modified to " );
100 		tprint( type );
101 		printf( ", %s\n", scnames(class) );
102 		printf( "	previous def'n: " );
103 		tprint( stp );
104 		printf( ", %s, (%d,%d) ), level %d\n", scnames(p->sclass), p->dimoff, p->sizoff, slev );
105 		}
106 # endif
107 
108 	if( stp == FTN && p->sclass == SNULL )goto enter;
109 		/* name encountered as function, not yet defined */
110 	if( stp == UNDEF|| stp == FARG ){
111 		if( blevel==1 && stp!=FARG ) switch( class ){
112 
113 		default:
114 #ifndef FLEXNAMES
115 			if(!(class&FIELD)) uerror( "declared argument %.8s is missing", p->sname );
116 #else
117 			if(!(class&FIELD)) uerror( "declared argument %s is missing", p->sname );
118 #endif
119 		case MOS:
120 		case STNAME:
121 		case MOU:
122 		case UNAME:
123 		case MOE:
124 		case ENAME:
125 		case TYPEDEF:
126 			;
127 			}
128 		goto enter;
129 		}
130 
131 	if( type != stp ) goto mismatch;
132 	/* test (and possibly adjust) dimensions */
133 	dsym = p->dimoff;
134 	ddef = q->fn.cdim;
135 	changed = 0;
136 	for( temp=type; temp&TMASK; temp = DECREF(temp) ){
137 		if( ISARY(temp) ){
138 			if (dimtab[dsym] == 0) {
139 				dimtab[dsym] = dimtab[ddef];
140 				changed = 1;
141 				}
142 			else if (dimtab[ddef]!=0&&dimtab[dsym]!=dimtab[ddef]) {
143 				goto mismatch;
144 				}
145 			++dsym;
146 			++ddef;
147 			}
148 		}
149 
150 	if (changed) {
151 		FIXDEF(p);
152 		}
153 
154 	/* check that redeclarations are to the same structure */
155 	if( (temp==STRTY||temp==UNIONTY||temp==ENUMTY) && p->sizoff != q->fn.csiz
156 		 && class!=STNAME && class!=UNAME && class!=ENAME ){
157 		goto mismatch;
158 		}
159 
160 	scl = ( p->sclass );
161 
162 # ifndef BUG1
163 	if( ddebug ){
164 		printf( "	previous class: %s\n", scnames(scl) );
165 		}
166 # endif
167 
168 	if( class&FIELD ){
169 		/* redefinition */
170 		if( !falloc( p, class&FLDSIZ, 1, NIL ) ) {
171 			/* successful allocation */
172 			psave( idp );
173 			return;
174 			}
175 		/* blew it: resume at end of switch... */
176 		}
177 
178 	else switch( class ){
179 
180 	case EXTERN:
181 		switch( scl ){
182 		case STATIC:
183 		case USTATIC:
184 			if( slev==0 ) return;
185 			break;
186 		case EXTDEF:
187 		case EXTERN:
188 		case FORTRAN:
189 		case UFORTRAN:
190 			return;
191 			}
192 		break;
193 
194 	case STATIC:
195 		if( scl==USTATIC || (scl==EXTERN && blevel==0) ){
196 			p->sclass = STATIC;
197 			if( ISFTN(type) ) curftn = idp;
198 			return;
199 			}
200 		break;
201 
202 	case USTATIC:
203 		if( scl==STATIC || scl==USTATIC ) return;
204 		break;
205 
206 	case LABEL:
207 		if( scl == ULABEL ){
208 			p->sclass = LABEL;
209 			deflab( p->offset );
210 			return;
211 			}
212 		break;
213 
214 	case TYPEDEF:
215 		if( scl == class ) return;
216 		break;
217 
218 	case UFORTRAN:
219 		if( scl == UFORTRAN || scl == FORTRAN ) return;
220 		break;
221 
222 	case FORTRAN:
223 		if( scl == UFORTRAN ){
224 			p->sclass = FORTRAN;
225 			if( ISFTN(type) ) curftn = idp;
226 			return;
227 			}
228 		break;
229 
230 	case MOU:
231 	case MOS:
232 		if( scl == class ) {
233 			if( oalloc( p, &strucoff ) ) break;
234 			if( class == MOU ) strucoff = 0;
235 			psave( idp );
236 			return;
237 			}
238 		break;
239 
240 	case MOE:
241 		if( scl == class ){
242 			if( p->offset!= strucoff++ ) break;
243 			psave( idp );
244 			}
245 		break;
246 
247 	case EXTDEF:
248 		if( scl == EXTERN ) {
249 			p->sclass = EXTDEF;
250 			if( ISFTN(type) ) curftn = idp;
251 			return;
252 			}
253 		break;
254 
255 	case STNAME:
256 	case UNAME:
257 	case ENAME:
258 		if( scl != class ) break;
259 		if( dimtab[p->sizoff] == 0 ) return;  /* previous entry just a mention */
260 		break;
261 
262 	case ULABEL:
263 		if( scl == LABEL || scl == ULABEL ) return;
264 	case PARAM:
265 	case AUTO:
266 	case REGISTER:
267 		;  /* mismatch.. */
268 
269 		}
270 
271 	mismatch:
272 	/* allow nonunique structure/union member names */
273 
274 	if( class==MOU || class==MOS || class & FIELD ){/* make a new entry */
275 		register int *memp;
276 		p->sflags |= SNONUNIQ;  /* old entry is nonunique */
277 		/* determine if name has occurred in this structure/union */
278 		if (paramno > 0) for( memp = &paramstk[paramno-1];
279 			/* while */ *memp>=0 && stab[*memp].sclass != STNAME
280 				&& stab[*memp].sclass != UNAME;
281 			/* iterate */ --memp){ char *cname, *oname;
282 			if( stab[*memp].sflags & SNONUNIQ ){int k;
283 				cname=p->sname;
284 				oname=stab[*memp].sname;
285 #ifndef FLEXNAMES
286 				for(k=1; k<=NCHNAM; ++k){
287 					if(*cname++ != *oname)goto diff;
288 					if(!*oname++)break;
289 					}
290 #else
291 				if (cname != oname) goto diff;
292 #endif
293 				uerror("redeclaration of: %s",p->sname);
294 				break;
295 				diff: continue;
296 				}
297 			}
298 		p = mknonuniq( &idp ); /* update p and idp to new entry */
299 		goto enter;
300 		}
301 	if( blevel > slev && class != EXTERN && class != FORTRAN &&
302 		class != UFORTRAN && !( class == LABEL && slev >= 2 ) ){
303 		q->tn.rval = idp = hide( p );
304 		p = &stab[idp];
305 		goto enter;
306 		}
307 #ifndef FLEXNAMES
308 	uerror( "redeclaration of %.8s", p->sname );
309 #else
310 	uerror( "redeclaration of %s", p->sname );
311 #endif
312 	if( class==EXTDEF && ISFTN(type) ) curftn = idp;
313 	return;
314 
315 	enter:  /* make a new entry */
316 
317 # ifndef BUG1
318 	if( ddebug ) printf( "	new entry made\n" );
319 # endif
320 	if( type == UNDEF ) uerror("void type for %s",p->sname);
321 	p->stype = type;
322 	p->sclass = class;
323 	p->slevel = blevel;
324 	p->offset = NOOFFSET;
325 	p->suse = lineno;
326 	if( class == STNAME || class == UNAME || class == ENAME ) {
327 		p->sizoff = curdim;
328 		dstash( 0 );  /* size */
329 		dstash( -1 ); /* index to members of str or union */
330 		dstash( ALSTRUCT );  /* alignment */
331 		dstash( idp );
332 		}
333 	else {
334 		switch( BTYPE(type) ){
335 		case STRTY:
336 		case UNIONTY:
337 		case ENUMTY:
338 			p->sizoff = q->fn.csiz;
339 			break;
340 		default:
341 			p->sizoff = BTYPE(type);
342 			}
343 		}
344 
345 	/* copy dimensions */
346 
347 	p->dimoff = q->fn.cdim;
348 
349 	/* allocate offsets */
350 	if( class&FIELD ){
351 		falloc( p, class&FLDSIZ, 0, NIL );  /* new entry */
352 		psave( idp );
353 		}
354 	else switch( class ){
355 
356 	case AUTO:
357 		oalloc( p, &autooff );
358 		break;
359 	case STATIC:
360 	case EXTDEF:
361 		p->offset = getlab();
362 		if( ISFTN(type) ) curftn = idp;
363 		break;
364 	case ULABEL:
365 	case LABEL:
366 		p->offset = getlab();
367 		p->slevel = 2;
368 		if( class == LABEL ){
369 			locctr( PROG );
370 			deflab( p->offset );
371 			}
372 		break;
373 
374 	case EXTERN:
375 	case UFORTRAN:
376 	case FORTRAN:
377 		p->offset = getlab();
378 		p->slevel = 0;
379 		break;
380 	case MOU:
381 	case MOS:
382 		oalloc( p, &strucoff );
383 		if( class == MOU ) strucoff = 0;
384 		psave( idp );
385 		break;
386 
387 	case MOE:
388 		p->offset = strucoff++;
389 		psave( idp );
390 		break;
391 	case REGISTER:
392 		p->offset = regvar--;
393 		if( blevel == 1 ) p->sflags |= SSET;
394 		if( regvar < minrvar ) minrvar = regvar;
395 		break;
396 		}
397 
398 	{
399 		register int l = p->slevel;
400 
401 		if( l >= MAXSCOPES )
402 			cerror( "scopes nested too deep" );
403 
404 		p->snext = schain[l];
405 		schain[l] = p;
406 		if( l >= chaintop )
407 			chaintop = l + 1;
408 		}
409 
410 	/* user-supplied routine to fix up new definitions */
411 
412 	FIXDEF(p);
413 
414 # ifndef BUG1
415 	if( ddebug ) printf( "	dimoff, sizoff, offset: %d, %d, %d\n", p->dimoff, p->sizoff, p->offset );
416 # endif
417 
418 	}
419 
420 psave( i ){
421 	if( paramno >= PARAMSZ ){
422 		cerror( "parameter stack overflow");
423 		}
424 	paramstk[ paramno++ ] = i;
425 	}
426 
427 ftnend(){ /* end of function */
428 	if( retlab != NOLAB ){ /* inside a real function */
429 		efcode();
430 		}
431 	checkst(0);
432 	retstat = 0;
433 	tcheck();
434 	curclass = SNULL;
435 	brklab = contlab = retlab = NOLAB;
436 	flostat = 0;
437 	if( nerrors == 0 ){
438 		if( psavbc != & asavbc[0] ) cerror("bcsave error");
439 		if( paramno != 0 ) cerror("parameter reset error");
440 		if( swx != 0 ) cerror( "switch error");
441 		}
442 	psavbc = &asavbc[0];
443 	paramno = 0;
444 	autooff = AUTOINIT;
445 	minrvar = regvar = MAXRVAR;
446 	reached = 1;
447 	swx = 0;
448 	swp = swtab;
449 	locctr(DATA);
450 	}
451 
452 dclargs(){
453 	register i, j;
454 	register struct symtab *p;
455 	register NODE *q;
456 	argoff = ARGINIT;
457 # ifndef BUG1
458 	if( ddebug > 2) printf("dclargs()\n");
459 # endif
460 	for( i=0; i<paramno; ++i ){
461 		if( (j = paramstk[i]) < 0 ) continue;
462 		p = &stab[j];
463 # ifndef BUG1
464 		if( ddebug > 2 ){
465 			printf("\t%s (%d) ",p->sname, j);
466 			tprint(p->stype);
467 			printf("\n");
468 			}
469 # endif
470 		if( p->stype == FARG ) {
471 			q = block(FREE,NIL,NIL,INT,0,INT);
472 			q->tn.rval = j;
473 			defid( q, PARAM );
474 			}
475 		FIXARG(p); /* local arg hook, eg. for sym. debugger */
476 		oalloc( p, &argoff );  /* always set aside space, even for register arguments */
477 		}
478 	cendarg();
479 	locctr(PROG);
480 	defalign(ALINT);
481 	ftnno = getlab();
482 	bfcode( paramstk, paramno );
483 	paramno = 0;
484 	}
485 
486 NODE *
487 rstruct( idn, soru ){ /* reference to a structure or union, with no definition */
488 	register struct symtab *p;
489 	register NODE *q;
490 	p = &stab[idn];
491 	switch( p->stype ){
492 
493 	case UNDEF:
494 	def:
495 		q = block( FREE, NIL, NIL, 0, 0, 0 );
496 		q->tn.rval = idn;
497 		q->in.type = (soru&INSTRUCT) ? STRTY : ( (soru&INUNION) ? UNIONTY : ENUMTY );
498 		defid( q, (soru&INSTRUCT) ? STNAME : ( (soru&INUNION) ? UNAME : ENAME ) );
499 		break;
500 
501 	case STRTY:
502 		if( soru & INSTRUCT ) break;
503 		goto def;
504 
505 	case UNIONTY:
506 		if( soru & INUNION ) break;
507 		goto def;
508 
509 	case ENUMTY:
510 		if( !(soru&(INUNION|INSTRUCT)) ) break;
511 		goto def;
512 
513 		}
514 	stwart = instruct;
515 	return( mkty( p->stype, 0, p->sizoff ) );
516 	}
517 
518 moedef( idn ){
519 	register NODE *q;
520 
521 	q = block( FREE, NIL, NIL, MOETY, 0, 0 );
522 	q->tn.rval = idn;
523 	if( idn>=0 ) defid( q, MOE );
524 	}
525 
526 bstruct( idn, soru ){ /* begining of structure or union declaration */
527 	register NODE *q;
528 
529 	psave( instruct );
530 	psave( curclass );
531 	psave( strucoff );
532 	strucoff = 0;
533 	instruct = soru;
534 	q = block( FREE, NIL, NIL, 0, 0, 0 );
535 	q->tn.rval = idn;
536 	if( instruct==INSTRUCT ){
537 		curclass = MOS;
538 		q->in.type = STRTY;
539 		if( idn >= 0 ) defid( q, STNAME );
540 		}
541 	else if( instruct == INUNION ) {
542 		curclass = MOU;
543 		q->in.type = UNIONTY;
544 		if( idn >= 0 ) defid( q, UNAME );
545 		}
546 	else { /* enum */
547 		curclass = MOE;
548 		q->in.type = ENUMTY;
549 		if( idn >= 0 ) defid( q, ENAME );
550 		}
551 	psave( idn = q->tn.rval );
552 	/* the "real" definition is where the members are seen */
553 	if ( idn >= 0 ) stab[idn].suse = lineno;
554 	return( paramno-4 );
555 	}
556 
557 NODE *
558 dclstruct( oparam ){
559 	register struct symtab *p;
560 	register i, al, sa, j, sz, szindex;
561 	register TWORD temp;
562 	register high, low;
563 
564 	/* paramstack contains:
565 		paramstack[ oparam ] = previous instruct
566 		paramstack[ oparam+1 ] = previous class
567 		paramstk[ oparam+2 ] = previous strucoff
568 		paramstk[ oparam+3 ] = structure name
569 
570 		paramstk[ oparam+4, ... ]  = member stab indices
571 
572 		*/
573 
574 
575 	if( (i=paramstk[oparam+3]) < 0 ){
576 		szindex = curdim;
577 		dstash( 0 );  /* size */
578 		dstash( -1 );  /* index to member names */
579 		dstash( ALSTRUCT );  /* alignment */
580 		dstash( -lineno );	/* name of structure */
581 		}
582 	else {
583 		szindex = stab[i].sizoff;
584 		}
585 
586 # ifndef BUG1
587 	if( ddebug ){
588 #ifndef FLEXNAMES
589 		printf( "dclstruct( %.8s ), szindex = %d\n", (i>=0)? stab[i].sname : "??", szindex );
590 #else
591 		printf( "dclstruct( %s ), szindex = %d\n", (i>=0)? stab[i].sname : "??", szindex );
592 #endif
593 		}
594 # endif
595 	temp = (instruct&INSTRUCT)?STRTY:((instruct&INUNION)?UNIONTY:ENUMTY);
596 	stwart = instruct = paramstk[ oparam ];
597 	curclass = paramstk[ oparam+1 ];
598 	dimtab[ szindex+1 ] = curdim;
599 	al = ALSTRUCT;
600 
601 	high = low = 0;
602 
603 	for( i = oparam+4;  i< paramno; ++i ){
604 		dstash( j=paramstk[i] );
605 		if( j<0 || j>= SYMTSZ ) cerror( "gummy structure member" );
606 		p = &stab[j];
607 		if( temp == ENUMTY ){
608 			if( p->offset < low ) low = p->offset;
609 			if( p->offset > high ) high = p->offset;
610 			p->sizoff = szindex;
611 			continue;
612 			}
613 		sa = talign( p->stype, p->sizoff );
614 		if( p->sclass & FIELD ){
615 			sz = p->sclass&FLDSIZ;
616 			}
617 		else {
618 			sz = tsize( p->stype, p->dimoff, p->sizoff );
619 			}
620 		if( sz == 0 ){
621 #ifndef FLEXNAMES
622 			werror( "illegal zero sized structure member: %.8s", p->sname );
623 #else
624 			werror( "illegal zero sized structure member: %s", p->sname );
625 #endif
626 			}
627 		if( sz > strucoff ) strucoff = sz;  /* for use with unions */
628 		SETOFF( al, sa );
629 		/* set al, the alignment, to the lcm of the alignments of the members */
630 		}
631 	dstash( -1 );  /* endmarker */
632 	SETOFF( strucoff, al );
633 
634 	if( temp == ENUMTY ){
635 		register TWORD ty;
636 
637 # ifdef ENUMSIZE
638 		ty = ENUMSIZE(high,low);
639 # else
640 		if( (char)high == high && (char)low == low ) ty = ctype( CHAR );
641 		else if( (short)high == high && (short)low == low ) ty = ctype( SHORT );
642 		else ty = ctype(INT);
643 #endif
644 		strucoff = tsize( ty, 0, (int)ty );
645 		dimtab[ szindex+2 ] = al = talign( ty, (int)ty );
646 		}
647 
648 	if( strucoff == 0 ) uerror( "zero sized structure" );
649 	dimtab[ szindex ] = strucoff;
650 	dimtab[ szindex+2 ] = al;
651 	dimtab[ szindex+3 ] = paramstk[ oparam+3 ];  /* name index */
652 
653 	FIXSTRUCT( szindex, oparam ); /* local hook, eg. for sym debugger */
654 # ifndef BUG1
655 	if( ddebug>1 ){
656 		printf( "\tdimtab[%d,%d,%d] = %d,%d,%d\n", szindex,szindex+1,szindex+2,
657 				dimtab[szindex],dimtab[szindex+1],dimtab[szindex+2] );
658 		for( i = dimtab[szindex+1]; dimtab[i] >= 0; ++i ){
659 #ifndef FLEXNAMES
660 			printf( "\tmember %.8s(%d)\n", stab[dimtab[i]].sname, dimtab[i] );
661 #else
662 			printf( "\tmember %s(%d)\n", stab[dimtab[i]].sname, dimtab[i] );
663 #endif
664 			}
665 		}
666 # endif
667 
668 	strucoff = paramstk[ oparam+2 ];
669 	paramno = oparam;
670 
671 	return( mkty( temp, 0, szindex ) );
672 	}
673 
674 	/* VARARGS */
675 yyerror( s ) char *s; { /* error printing routine in parser */
676 
677 	uerror( s );
678 
679 	}
680 
681 yyaccpt(){
682 	ftnend();
683 	}
684 
685 ftnarg( idn ) {
686 	switch( stab[idn].stype ){
687 
688 	case UNDEF:
689 		/* this parameter, entered at scan */
690 		break;
691 	case FARG:
692 #ifndef FLEXNAMES
693 		uerror("redeclaration of formal parameter, %.8s",
694 #else
695 		uerror("redeclaration of formal parameter, %s",
696 #endif
697 			stab[idn].sname);
698 		/* fall thru */
699 	case FTN:
700 		/* the name of this function matches parm */
701 		/* fall thru */
702 	default:
703 		idn = hide( &stab[idn]);
704 		break;
705 	case TNULL:
706 		/* unused entry, fill it */
707 		;
708 		}
709 	stab[idn].stype = FARG;
710 	stab[idn].sclass = PARAM;
711 	psave( idn );
712 	}
713 
714 talign( ty, s) register unsigned ty; register s; {
715 	/* compute the alignment of an object with type ty, sizeoff index s */
716 
717 	register i;
718 	if( s<0 && ty!=INT && ty!=CHAR && ty!=SHORT && ty!=UNSIGNED && ty!=UCHAR && ty!=USHORT
719 #ifdef LONGFIELDS
720 		&& ty!=LONG && ty!=ULONG
721 #endif
722 					){
723 		return( fldal( ty ) );
724 		}
725 
726 	for( i=0; i<=(SZINT-BTSHIFT-1); i+=TSHIFT ){
727 		switch( (ty>>i)&TMASK ){
728 
729 		case FTN:
730 			cerror( "compiler takes alignment of function");
731 		case PTR:
732 			return( ALPOINT );
733 		case ARY:
734 			continue;
735 		case 0:
736 			break;
737 			}
738 		}
739 
740 	switch( BTYPE(ty) ){
741 
742 	case UNIONTY:
743 	case ENUMTY:
744 	case STRTY:
745 		return( (unsigned int) dimtab[ s+2 ] );
746 	case CHAR:
747 	case UCHAR:
748 		return( ALCHAR );
749 	case FLOAT:
750 		return( ALFLOAT );
751 	case DOUBLE:
752 		return( ALDOUBLE );
753 	case LONG:
754 	case ULONG:
755 		return( ALLONG );
756 	case SHORT:
757 	case USHORT:
758 		return( ALSHORT );
759 	default:
760 		return( ALINT );
761 		}
762 	}
763 
764 OFFSZ
765 tsize( ty, d, s )  TWORD ty; {
766 	/* compute the size associated with type ty,
767 	    dimoff d, and sizoff s */
768 	/* BETTER NOT BE CALLED WHEN t, d, and s REFER TO A BIT FIELD... */
769 
770 	int i;
771 	OFFSZ mult;
772 
773 	mult = 1;
774 
775 	for( i=0; i<=(SZINT-BTSHIFT-1); i+=TSHIFT ){
776 		switch( (ty>>i)&TMASK ){
777 
778 		case FTN:
779 			cerror( "compiler takes size of function");
780 		case PTR:
781 			return( SZPOINT * mult );
782 		case ARY:
783 			mult *= (unsigned int) dimtab[ d++ ];
784 			continue;
785 		case 0:
786 			break;
787 
788 			}
789 		}
790 
791 	if( dimtab[s]==0 ) {
792 		if( ty == STRTY )
793 			uerror( "undefined structure" );
794 		else
795 			uerror( "unknown size");
796 		return( SZINT );
797 		}
798 	return( (unsigned int) dimtab[ s ] * mult );
799 	}
800 
801 inforce( n ) OFFSZ n; {  /* force inoff to have the value n */
802 	/* inoff is updated to have the value n */
803 	OFFSZ wb;
804 	register rest;
805 	/* rest is used to do a lot of conversion to ints... */
806 
807 	if( inoff == n ) return;
808 	if( inoff > n ) {
809 		cerror( "initialization alignment error");
810 		}
811 
812 	wb = inoff;
813 	SETOFF( wb, SZINT );
814 
815 	/* wb now has the next higher word boundary */
816 
817 	if( wb >= n ){ /* in the same word */
818 		rest = n - inoff;
819 		vfdzero( rest );
820 		return;
821 		}
822 
823 	/* otherwise, extend inoff to be word aligned */
824 
825 	rest = wb - inoff;
826 	vfdzero( rest );
827 
828 	/* now, skip full words until near to n */
829 
830 	rest = (n-inoff)/SZINT;
831 	zecode( rest );
832 
833 	/* now, the remainder of the last word */
834 
835 	rest = n-inoff;
836 	vfdzero( rest );
837 	if( inoff != n ) cerror( "inoff error");
838 
839 	}
840 
841 vfdalign( n ){ /* make inoff have the offset the next alignment of n */
842 	OFFSZ m;
843 
844 	m = inoff;
845 	SETOFF( m, n );
846 	inforce( m );
847 	}
848 
849 
850 int idebug = 0;
851 
852 int ibseen = 0;  /* the number of } constructions which have been filled */
853 
854 int ifull = 0; /* 1 if all initializers have been seen */
855 
856 int iclass;  /* storage class of thing being initialized */
857 
858 int ilocctr = 0;  /* location counter for current initialization */
859 
860 beginit(curid){
861 	/* beginning of initilization; set location ctr and set type */
862 	register struct symtab *p;
863 
864 # ifndef BUG1
865 	if( idebug >= 3 ) printf( "beginit(), curid = %d\n", curid );
866 # endif
867 
868 	p = &stab[curid];
869 
870 	iclass = p->sclass;
871 	if( curclass == EXTERN || curclass == FORTRAN ) iclass = EXTERN;
872 	switch( iclass ){
873 
874 	case UNAME:
875 	case EXTERN:
876 		return;
877 	case AUTO:
878 	case REGISTER:
879 		break;
880 	case EXTDEF:
881 	case STATIC:
882 		ilocctr = ISARY(p->stype)?ADATA:DATA;
883 		locctr( ilocctr );
884 		defalign( talign( p->stype, p->sizoff ) );
885 		defnam( p );
886 
887 		}
888 
889 	inoff = 0;
890 	ibseen = 0;
891 	ifull = 0;
892 
893 	pstk = 0;
894 
895 	instk( curid, p->stype, p->dimoff, p->sizoff, inoff );
896 
897 	}
898 
899 instk( id, t, d, s, off ) OFFSZ off; TWORD t; {
900 	/* make a new entry on the parameter stack to initialize id */
901 
902 	register struct symtab *p;
903 
904 	for(;;){
905 # ifndef BUG1
906 		if( idebug ) printf( "instk((%d, %o,%d,%d, %d)\n", id, t, d, s, off );
907 # endif
908 
909 		/* save information on the stack */
910 
911 		if( !pstk ) pstk = instack;
912 		else ++pstk;
913 
914 		pstk->in_fl = 0;	/* { flag */
915 		pstk->in_id =  id ;
916 		pstk->in_t =  t ;
917 		pstk->in_d =  d ;
918 		pstk->in_s =  s ;
919 		pstk->in_n = 0;  /* number seen */
920 		pstk->in_x =  t==STRTY ?dimtab[s+1] : 0 ;
921 		pstk->in_off =  off;   /* offset at the beginning of this element */
922 		/* if t is an array, DECREF(t) can't be a field */
923 		/* INS_sz has size of array elements, and -size for fields */
924 		if( ISARY(t) ){
925 			pstk->in_sz = tsize( DECREF(t), d+1, s );
926 			}
927 		else if( stab[id].sclass & FIELD ){
928 			pstk->in_sz = - ( stab[id].sclass & FLDSIZ );
929 			}
930 		else {
931 			pstk->in_sz = 0;
932 			}
933 
934 		if( (iclass==AUTO || iclass == REGISTER ) &&
935 			(ISARY(t) || t==STRTY) ) uerror( "no automatic aggregate initialization" );
936 
937 		/* now, if this is not a scalar, put on another element */
938 
939 		if( ISARY(t) ){
940 			t = DECREF(t);
941 			++d;
942 			continue;
943 			}
944 		else if( t == STRTY ){
945 			if( dimtab[pstk->in_s] == 0 ){
946 				uerror( "can't initialize undefined structure" );
947 				iclass = -1;
948 				return;
949 				}
950 			id = dimtab[pstk->in_x];
951 			p = &stab[id];
952 			if( p->sclass != MOS && !(p->sclass&FIELD) ) cerror( "insane structure member list" );
953 			t = p->stype;
954 			d = p->dimoff;
955 			s = p->sizoff;
956 			off += p->offset;
957 			continue;
958 			}
959 		else return;
960 		}
961 	}
962 
963 NODE *
964 getstr(){ /* decide if the string is external or an initializer, and get the contents accordingly */
965 
966 	register l, temp;
967 	register NODE *p;
968 
969 	if( (iclass==EXTDEF||iclass==STATIC) && (pstk->in_t == CHAR || pstk->in_t == UCHAR) &&
970 			pstk!=instack && ISARY( pstk[-1].in_t ) ){
971 		/* treat "abc" as { 'a', 'b', 'c', 0 } */
972 		strflg = 1;
973 		ilbrace();  /* simulate { */
974 		inforce( pstk->in_off );
975 		/* if the array is inflexible (not top level), pass in the size and
976 			be prepared to throw away unwanted initializers */
977 		lxstr((pstk-1)!=instack?dimtab[(pstk-1)->in_d]:0);  /* get the contents */
978 		irbrace();  /* simulate } */
979 		return( NIL );
980 		}
981 	else { /* make a label, and get the contents and stash them away */
982 		if( iclass != SNULL ){ /* initializing */
983 			/* fill out previous word, to permit pointer */
984 			vfdalign( ALPOINT );
985 			}
986 		temp = locctr( blevel==0?ISTRNG:STRNG ); /* set up location counter */
987 		deflab( l = getlab() );
988 		strflg = 0;
989 		lxstr(0); /* get the contents */
990 		locctr( blevel==0?ilocctr:temp );
991 		p = buildtree( STRING, NIL, NIL );
992 		p->tn.rval = -l;
993 		return(p);
994 		}
995 	}
996 
997 putbyte( v ){ /* simulate byte v appearing in a list of integer values */
998 	register NODE *p;
999 	p = bcon(v);
1000 	incode( p, SZCHAR );
1001 	tfree( p );
1002 	gotscal();
1003 	}
1004 
1005 endinit(){
1006 	register TWORD t;
1007 	register d, s, n, d1;
1008 
1009 # ifndef BUG1
1010 	if( idebug ) printf( "endinit(), inoff = %d\n", inoff );
1011 # endif
1012 
1013 	switch( iclass ){
1014 
1015 	case EXTERN:
1016 	case AUTO:
1017 	case REGISTER:
1018 	case -1:
1019 		return;
1020 		}
1021 
1022 	pstk = instack;
1023 
1024 	t = pstk->in_t;
1025 	d = pstk->in_d;
1026 	s = pstk->in_s;
1027 	n = pstk->in_n;
1028 
1029 	if( ISARY(t) ){
1030 		d1 = dimtab[d];
1031 
1032 		vfdalign( pstk->in_sz );  /* fill out part of the last element, if needed */
1033 		n = inoff/pstk->in_sz;  /* real number of initializers */
1034 		if( d1 >= n ){
1035 			/* once again, t is an array, so no fields */
1036 			inforce( tsize( t, d, s ) );
1037 			n = d1;
1038 			}
1039 		if( d1!=0 && d1!=n ) uerror( "too many initializers");
1040 		if( n==0 ) werror( "empty array declaration");
1041 		dimtab[d] = n;
1042 		if( d1==0 ) FIXDEF(&stab[pstk->in_id]);
1043 		}
1044 
1045 	else if( t == STRTY || t == UNIONTY ){
1046 		/* clearly not fields either */
1047 		inforce( tsize( t, d, s ) );
1048 		}
1049 	else if( n > 1 ) uerror( "bad scalar initialization");
1050 	/* this will never be called with a field element... */
1051 	else inforce( tsize(t,d,s) );
1052 
1053 	paramno = 0;
1054 	vfdalign( AL_INIT );
1055 	inoff = 0;
1056 	iclass = SNULL;
1057 
1058 	}
1059 
1060 doinit( p ) register NODE *p; {
1061 
1062 	/* take care of generating a value for the initializer p */
1063 	/* inoff has the current offset (last bit written)
1064 		in the current word being generated */
1065 
1066 	register sz, d, s;
1067 	register TWORD t;
1068 	int o;
1069 
1070 	/* note: size of an individual initializer is assumed to fit into an int */
1071 
1072 	if( iclass < 0 || pstk == 0 ) goto leave;
1073 	if( iclass == EXTERN || iclass == UNAME ){
1074 		uerror( "cannot initialize extern or union" );
1075 		iclass = -1;
1076 		goto leave;
1077 		}
1078 
1079 	if( iclass == AUTO || iclass == REGISTER ){
1080 		/* do the initialization and get out, without regard
1081 		    for filing out the variable with zeros, etc. */
1082 		bccode();
1083 		idname = pstk->in_id;
1084 		p = buildtree( ASSIGN, buildtree( NAME, NIL, NIL ), p );
1085 		ecomp(p);
1086 		return;
1087 		}
1088 
1089 	if( p == NIL ) return;  /* for throwing away strings that have been turned into lists */
1090 
1091 	if( ifull ){
1092 		uerror( "too many initializers" );
1093 		iclass = -1;
1094 		goto leave;
1095 		}
1096 	if( ibseen ){
1097 		uerror( "} expected");
1098 		goto leave;
1099 		}
1100 
1101 # ifndef BUG1
1102 	if( idebug > 1 ) printf( "doinit(%o)\n", p );
1103 # endif
1104 
1105 	t = pstk->in_t;  /* type required */
1106 	d = pstk->in_d;
1107 	s = pstk->in_s;
1108 	if( pstk->in_sz < 0 ){  /* bit field */
1109 		sz = -pstk->in_sz;
1110 		}
1111 	else {
1112 		sz = tsize( t, d, s );
1113 		}
1114 
1115 	inforce( pstk->in_off );
1116 
1117 	p = buildtree( ASSIGN, block( NAME, NIL,NIL, t, d, s ), p );
1118 #ifdef LINT
1119 	ecode(p);
1120 #endif
1121 	p->in.left->in.op = FREE;
1122 	p->in.left = p->in.right;
1123 	p->in.right = NIL;
1124 	p->in.left = optim( p->in.left );
1125 	o = p->in.left->in.op;
1126 	if( o == UNARY AND ){
1127 		o = p->in.left->in.op = FREE;
1128 		p->in.left = p->in.left->in.left;
1129 		}
1130 	p->in.op = INIT;
1131 
1132 	if( sz < SZINT ){ /* special case: bit fields, etc. */
1133 		if( o != ICON ) uerror( "illegal initialization" );
1134 		else incode( p->in.left, sz );
1135 		}
1136 	else if( o == FCON ){
1137 		fincode( p->in.left->fpn.fval, sz );
1138 		}
1139 	else if( o == DCON ){
1140 		fincode( p->in.left->dpn.dval, sz );
1141 		}
1142 	else {
1143 		p = optim(p);
1144 		if( p->in.left->in.op != ICON ) uerror( "illegal initialization" );
1145 		else cinit( p, sz );
1146 		}
1147 
1148 	gotscal();
1149 
1150 	leave:
1151 	tfree(p);
1152 	}
1153 
1154 gotscal(){
1155 	register t, ix;
1156 	register n, id;
1157 	struct symtab *p;
1158 	OFFSZ temp;
1159 
1160 	for( ; pstk > instack; ) {
1161 
1162 		if( pstk->in_fl ) ++ibseen;
1163 
1164 		--pstk;
1165 
1166 		t = pstk->in_t;
1167 
1168 		if( t == STRTY ){
1169 			ix = ++pstk->in_x;
1170 			if( (id=dimtab[ix]) < 0 ) continue;
1171 
1172 			/* otherwise, put next element on the stack */
1173 
1174 			p = &stab[id];
1175 			instk( id, p->stype, p->dimoff, p->sizoff, p->offset+pstk->in_off );
1176 			return;
1177 			}
1178 		else if( ISARY(t) ){
1179 			n = ++pstk->in_n;
1180 			if( n >= dimtab[pstk->in_d] && pstk > instack ) continue;
1181 
1182 			/* put the new element onto the stack */
1183 
1184 			temp = pstk->in_sz;
1185 			instk( pstk->in_id, (TWORD)DECREF(pstk->in_t), pstk->in_d+1, pstk->in_s,
1186 				pstk->in_off+n*temp );
1187 			return;
1188 			}
1189 
1190 		}
1191 	ifull = 1;
1192 	}
1193 
1194 ilbrace(){ /* process an initializer's left brace */
1195 	register t;
1196 	struct instk *temp;
1197 
1198 	temp = pstk;
1199 
1200 	for( ; pstk > instack; --pstk ){
1201 
1202 		t = pstk->in_t;
1203 		if( t != STRTY && !ISARY(t) ) continue; /* not an aggregate */
1204 		if( pstk->in_fl ){ /* already associated with a { */
1205 			if( pstk->in_n ) uerror( "illegal {");
1206 			continue;
1207 			}
1208 
1209 		/* we have one ... */
1210 		pstk->in_fl = 1;
1211 		break;
1212 		}
1213 
1214 	/* cannot find one */
1215 	/* ignore such right braces */
1216 
1217 	pstk = temp;
1218 	}
1219 
1220 irbrace(){
1221 	/* called when a '}' is seen */
1222 
1223 # ifndef BUG1
1224 	if( idebug ) printf( "irbrace(): paramno = %d on entry\n", paramno );
1225 # endif
1226 
1227 	if( ibseen ) {
1228 		--ibseen;
1229 		return;
1230 		}
1231 
1232 	for( ; pstk > instack; --pstk ){
1233 		if( !pstk->in_fl ) continue;
1234 
1235 		/* we have one now */
1236 
1237 		pstk->in_fl = 0;  /* cancel { */
1238 		gotscal();  /* take it away... */
1239 		return;
1240 		}
1241 
1242 	/* these right braces match ignored left braces: throw out */
1243 	ifull = 1;
1244 
1245 	}
1246 
1247 upoff( size, alignment, poff ) register alignment, *poff; {
1248 	/* update the offset pointed to by poff; return the
1249 	/* offset of a value of size `size', alignment `alignment',
1250 	/* given that off is increasing */
1251 
1252 	register off;
1253 
1254 	off = *poff;
1255 	SETOFF( off, alignment );
1256 	if( (offsz-off) <  size ){
1257 		if( instruct!=INSTRUCT )cerror("too many local variables");
1258 		else cerror("Structure too large");
1259 		}
1260 	*poff = off+size;
1261 	return( off );
1262 	}
1263 
1264 oalloc( p, poff ) register struct symtab *p; register *poff; {
1265 	/* allocate p with offset *poff, and update *poff */
1266 	register al, off, tsz;
1267 	int noff;
1268 
1269 	al = talign( p->stype, p->sizoff );
1270 	noff = off = *poff;
1271 	tsz = tsize( p->stype, p->dimoff, p->sizoff );
1272 #ifdef BACKAUTO
1273 	if( p->sclass == AUTO ){
1274 		if( (offsz-off) < tsz ) cerror("too many local variables");
1275 		noff = off + tsz;
1276 		SETOFF( noff, al );
1277 		off = -noff;
1278 		}
1279 	else
1280 #endif
1281 		if( p->sclass == PARAM && ( tsz < SZINT ) ){
1282 			off = upoff( SZINT, ALINT, &noff );
1283 # ifndef RTOLBYTES
1284 			off = noff - tsz;
1285 #endif
1286 			}
1287 		else
1288 		{
1289 		off = upoff( tsz, al, &noff );
1290 		}
1291 
1292 	if( p->sclass != REGISTER ){ /* in case we are allocating stack space for register arguments */
1293 		if( p->offset == NOOFFSET ) p->offset = off;
1294 		else if( off != p->offset ) return(1);
1295 		}
1296 
1297 	*poff = noff;
1298 	return(0);
1299 	}
1300 
1301 falloc( p, w, new, pty )  register struct symtab *p; NODE *pty; {
1302 	/* allocate a field of width w */
1303 	/* new is 0 if new entry, 1 if redefinition, -1 if alignment */
1304 
1305 	register al,sz,type;
1306 
1307 	type = (new<0)? pty->in.type : p->stype;
1308 
1309 	/* this must be fixed to use the current type in alignments */
1310 	switch( new<0?pty->in.type:p->stype ){
1311 
1312 	case ENUMTY:
1313 		{
1314 			int s;
1315 			s = new<0 ? pty->fn.csiz : p->sizoff;
1316 			al = dimtab[s+2];
1317 			sz = dimtab[s];
1318 			break;
1319 			}
1320 
1321 	case CHAR:
1322 	case UCHAR:
1323 		al = ALCHAR;
1324 		sz = SZCHAR;
1325 		break;
1326 
1327 	case SHORT:
1328 	case USHORT:
1329 		al = ALSHORT;
1330 		sz = SZSHORT;
1331 		break;
1332 
1333 	case INT:
1334 	case UNSIGNED:
1335 		al = ALINT;
1336 		sz = SZINT;
1337 		break;
1338 #ifdef LONGFIELDS
1339 
1340 	case LONG:
1341 	case ULONG:
1342 		al = ALLONG;
1343 		sz = SZLONG;
1344 		break;
1345 #endif
1346 
1347 	default:
1348 		if( new < 0 ) {
1349 			uerror( "illegal field type" );
1350 			al = ALINT;
1351 			}
1352 		else {
1353 			al = fldal( p->stype );
1354 			sz =SZINT;
1355 			}
1356 		}
1357 
1358 	if( w > sz ) {
1359 		uerror( "field too big");
1360 		w = sz;
1361 		}
1362 
1363 	if( w == 0 ){ /* align only */
1364 		SETOFF( strucoff, al );
1365 		if( new >= 0 ) uerror( "zero size field");
1366 		return(0);
1367 		}
1368 
1369 	if( strucoff%al + w > sz ) SETOFF( strucoff, al );
1370 	if( new < 0 ) {
1371 		if( (offsz-strucoff) < w )
1372 			cerror("structure too large");
1373 		strucoff += w;  /* we know it will fit */
1374 		return(0);
1375 		}
1376 
1377 	/* establish the field */
1378 
1379 	if( new == 1 ) { /* previous definition */
1380 		if( p->offset != strucoff || p->sclass != (FIELD|w) ) return(1);
1381 		}
1382 	p->offset = strucoff;
1383 	if( (offsz-strucoff) < w ) cerror("structure too large");
1384 	strucoff += w;
1385 	p->stype = type;
1386 	fldty( p );
1387 	return(0);
1388 	}
1389 
1390 nidcl( p ) NODE *p; { /* handle unitialized declarations */
1391 	/* assumed to be not functions */
1392 	register class;
1393 	register commflag;  /* flag for labelled common declarations */
1394 
1395 	commflag = 0;
1396 
1397 	/* compute class */
1398 	if( (class=curclass) == SNULL ){
1399 		if( blevel > 1 ) class = AUTO;
1400 		else if( blevel != 0 || instruct ) cerror( "nidcl error" );
1401 		else { /* blevel = 0 */
1402 			class = noinit();
1403 			if( class == EXTERN ) commflag = 1;
1404 			}
1405 		}
1406 #ifdef LCOMM
1407 	/* hack so stab will come at as LCSYM rather than STSYM */
1408 	if (class == STATIC) {
1409 		extern int stabLCSYM;
1410 		stabLCSYM = 1;
1411 	}
1412 #endif
1413 
1414 	defid( p, class );
1415 
1416 #ifndef LCOMM
1417 	if( class==EXTDEF || class==STATIC )
1418 #else
1419 	if (class==STATIC) {
1420 		register struct symtab *s = &stab[p->tn.rval];
1421 		extern int stabLCSYM;
1422 		int sz = tsize(s->stype, s->dimoff, s->sizoff)/SZCHAR;
1423 
1424 		stabLCSYM = 0;
1425 		if (sz % sizeof (int))
1426 			sz += sizeof (int) - (sz % sizeof (int));
1427 		if (s->slevel > 1)
1428 			printf("	.lcomm	L%d,%d\n", s->offset, sz);
1429 		else
1430 			printf("	.lcomm	%s,%d\n", exname(s->sname), sz);
1431 	}else if (class == EXTDEF)
1432 #endif
1433 		{
1434 		/* simulate initialization by 0 */
1435 		beginit(p->tn.rval);
1436 		endinit();
1437 		}
1438 	if( commflag ) commdec( p->tn.rval );
1439 	}
1440 
1441 TWORD
1442 types( t1, t2, t3 ) TWORD t1, t2, t3; {
1443 	/* return a basic type from basic types t1, t2, and t3 */
1444 
1445 	TWORD t[3], noun, adj, unsg;
1446 	register i;
1447 
1448 	t[0] = t1;
1449 	t[1] = t2;
1450 	t[2] = t3;
1451 
1452 	unsg = INT;  /* INT or UNSIGNED */
1453 	noun = UNDEF;  /* INT, CHAR, or FLOAT */
1454 	adj = INT;  /* INT, LONG, or SHORT */
1455 
1456 	for( i=0; i<3; ++i ){
1457 		switch( t[i] ){
1458 
1459 		default:
1460 		bad:
1461 			uerror( "illegal type combination" );
1462 			return( INT );
1463 
1464 		case UNDEF:
1465 			continue;
1466 
1467 		case UNSIGNED:
1468 			if( unsg != INT ) goto bad;
1469 			unsg = UNSIGNED;
1470 			continue;
1471 
1472 		case LONG:
1473 		case SHORT:
1474 			if( adj != INT ) goto bad;
1475 			adj = t[i];
1476 			continue;
1477 
1478 		case INT:
1479 		case CHAR:
1480 		case FLOAT:
1481 			if( noun != UNDEF ) goto bad;
1482 			noun = t[i];
1483 			continue;
1484 			}
1485 		}
1486 
1487 	/* now, construct final type */
1488 	if( noun == UNDEF ) noun = INT;
1489 	else if( noun == FLOAT ){
1490 		if( unsg != INT || adj == SHORT ) goto bad;
1491 		return( adj==LONG ? DOUBLE : FLOAT );
1492 		}
1493 	else if( noun == CHAR && adj != INT ) goto bad;
1494 
1495 	/* now, noun is INT or CHAR */
1496 	if( adj != INT ) noun = adj;
1497 	if( unsg == UNSIGNED ) return( noun + (UNSIGNED-INT) );
1498 	else return( noun );
1499 	}
1500 
1501 NODE *
1502 tymerge( typ, idp ) NODE *typ, *idp; {
1503 	/* merge type typ with identifier idp  */
1504 
1505 	register unsigned t;
1506 	register i;
1507 	extern int eprint();
1508 
1509 	if( typ->in.op != TYPE ) cerror( "tymerge: arg 1" );
1510 	if(idp == NIL ) return( NIL );
1511 
1512 # ifndef BUG1
1513 	if( ddebug > 2 ) fwalk( idp, eprint, 0 );
1514 # endif
1515 
1516 	idp->in.type = typ->in.type;
1517 	idp->fn.cdim = curdim;
1518 	tyreduce( idp );
1519 	idp->fn.csiz = typ->fn.csiz;
1520 
1521 	for( t=typ->in.type, i=typ->fn.cdim; t&TMASK; t = DECREF(t) ){
1522 		if( ISARY(t) ) dstash( dimtab[i++] );
1523 		}
1524 
1525 	/* now idp is a single node: fix up type */
1526 
1527 	idp->in.type = ctype( idp->in.type );
1528 
1529 	if( (t = BTYPE(idp->in.type)) != STRTY && t != UNIONTY && t != ENUMTY ){
1530 		idp->fn.csiz = t;  /* in case ctype has rewritten things */
1531 		}
1532 
1533 	return( idp );
1534 	}
1535 
1536 tyreduce( p ) register NODE *p; {
1537 
1538 	/* build a type, and stash away dimensions, from a parse tree of the declaration */
1539 	/* the type is build top down, the dimensions bottom up */
1540 	register o, temp;
1541 	register unsigned t;
1542 
1543 	o = p->in.op;
1544 	p->in.op = FREE;
1545 
1546 	if( o == NAME ) return;
1547 
1548 	t = INCREF( p->in.type );
1549 	if( o == UNARY CALL ) t += (FTN-PTR);
1550 	else if( o == LB ){
1551 		t += (ARY-PTR);
1552 		temp = p->in.right->tn.lval;
1553 		p->in.right->in.op = FREE;
1554 		if( ( temp == 0 ) & ( p->in.left->tn.op == LB ) )
1555 			uerror( "Null dimension" );
1556 		}
1557 
1558 	p->in.left->in.type = t;
1559 	tyreduce( p->in.left );
1560 
1561 	if( o == LB ) dstash( temp );
1562 
1563 	p->tn.rval = p->in.left->tn.rval;
1564 	p->in.type = p->in.left->in.type;
1565 
1566 	}
1567 
1568 fixtype( p, class ) register NODE *p; {
1569 	register unsigned t, type;
1570 	register mod1, mod2;
1571 	/* fix up the types, and check for legality */
1572 
1573 	if( (type = p->in.type) == UNDEF ) return;
1574 	if( mod2 = (type&TMASK) ){
1575 		t = DECREF(type);
1576 		while( mod1=mod2, mod2 = (t&TMASK) ){
1577 			if( mod1 == ARY && mod2 == FTN ){
1578 				uerror( "array of functions is illegal" );
1579 				type = 0;
1580 				}
1581 			else if( mod1 == FTN && ( mod2 == ARY || mod2 == FTN ) ){
1582 				uerror( "function returns illegal type" );
1583 				type = 0;
1584 				}
1585 			t = DECREF(t);
1586 			}
1587 		}
1588 
1589 	/* detect function arguments, watching out for structure declarations */
1590 	/* for example, beware of f(x) struct [ int a[10]; } *x; { ... } */
1591 	/* the danger is that "a" will be converted to a pointer */
1592 
1593 	if( class==SNULL && blevel==1 && !(instruct&(INSTRUCT|INUNION)) ) class = PARAM;
1594 	if( class == PARAM || ( class==REGISTER && blevel==1 ) ){
1595 		if( type == FLOAT ) type = DOUBLE;
1596 		else if( ISARY(type) ){
1597 			++p->fn.cdim;
1598 			type += (PTR-ARY);
1599 			}
1600 		else if( ISFTN(type) ){
1601 			werror( "a function is declared as an argument" );
1602 			type = INCREF(type);
1603 			}
1604 
1605 		}
1606 
1607 	if( instruct && ISFTN(type) ){
1608 		uerror( "function illegal in structure or union" );
1609 		type = INCREF(type);
1610 		}
1611 	p->in.type = type;
1612 	}
1613 
1614 uclass( class ) register class; {
1615 	/* give undefined version of class */
1616 	if( class == SNULL ) return( EXTERN );
1617 	else if( class == STATIC ) return( USTATIC );
1618 	else if( class == FORTRAN ) return( UFORTRAN );
1619 	else return( class );
1620 	}
1621 
1622 fixclass( class, type ) TWORD type; {
1623 
1624 	/* first, fix null class */
1625 
1626 	if( class == SNULL ){
1627 		if( instruct&INSTRUCT ) class = MOS;
1628 		else if( instruct&INUNION ) class = MOU;
1629 		else if( blevel == 0 ) class = EXTDEF;
1630 		else if( blevel == 1 ) class = PARAM;
1631 		else class = AUTO;
1632 
1633 		}
1634 
1635 	/* now, do general checking */
1636 
1637 	if( ISFTN( type ) ){
1638 		switch( class ) {
1639 		default:
1640 			uerror( "function has illegal storage class" );
1641 		case AUTO:
1642 			class = EXTERN;
1643 		case EXTERN:
1644 		case EXTDEF:
1645 		case FORTRAN:
1646 		case TYPEDEF:
1647 		case STATIC:
1648 		case UFORTRAN:
1649 		case USTATIC:
1650 			;
1651 			}
1652 		}
1653 
1654 	if( class&FIELD ){
1655 		if( !(instruct&INSTRUCT) ) uerror( "illegal use of field" );
1656 		return( class );
1657 		}
1658 
1659 	switch( class ){
1660 
1661 	case MOU:
1662 		if( !(instruct&INUNION) ) uerror( "illegal class" );
1663 		return( class );
1664 
1665 	case MOS:
1666 		if( !(instruct&INSTRUCT) ) uerror( "illegal class" );
1667 		return( class );
1668 
1669 	case MOE:
1670 		if( instruct & (INSTRUCT|INUNION) ) uerror( "illegal class" );
1671 		return( class );
1672 
1673 	case REGISTER:
1674 		if( blevel == 0 ) uerror( "illegal register declaration" );
1675 		else if( regvar >= MINRVAR && cisreg( type ) ) return( class );
1676 		if( blevel == 1 ) return( PARAM );
1677 		else return( AUTO );
1678 
1679 	case AUTO:
1680 	case LABEL:
1681 	case ULABEL:
1682 		if( blevel < 2 ) uerror( "illegal class" );
1683 		return( class );
1684 
1685 	case PARAM:
1686 		if( blevel != 1 ) uerror( "illegal class" );
1687 		return( class );
1688 
1689 	case UFORTRAN:
1690 	case FORTRAN:
1691 # ifdef NOFORTRAN
1692 			NOFORTRAN;    /* a condition which can regulate the FORTRAN usage */
1693 # endif
1694 		if( !ISFTN(type) ) uerror( "fortran declaration must apply to function" );
1695 		else {
1696 			type = DECREF(type);
1697 			if( ISFTN(type) || ISARY(type) || ISPTR(type) ) {
1698 				uerror( "fortran function has wrong type" );
1699 				}
1700 			}
1701 	case EXTERN:
1702 	case STATIC:
1703 	case EXTDEF:
1704 	case TYPEDEF:
1705 	case USTATIC:
1706 		if( blevel == 1 ){
1707 			uerror( "illegal class" );
1708 			return( PARAM );
1709 			}
1710 	case STNAME:
1711 	case UNAME:
1712 	case ENAME:
1713 		return( class );
1714 
1715 	default:
1716 		cerror( "illegal class: %d", class );
1717 		/* NOTREACHED */
1718 
1719 		}
1720 	}
1721 
1722 struct symtab *
1723 mknonuniq(idindex) int *idindex; {/* locate a symbol table entry for */
1724 	/* an occurrence of a nonunique structure member name */
1725 	/* or field */
1726 	register i;
1727 	register struct symtab * sp;
1728 	char *p,*q;
1729 
1730 	sp = & stab[ i= *idindex ]; /* position search at old entry */
1731 	while( sp->stype != TNULL ){ /* locate unused entry */
1732 		if( ++i >= SYMTSZ ){/* wrap around symbol table */
1733 			i = 0;
1734 			sp = stab;
1735 			}
1736 		else ++sp;
1737 		if( i == *idindex ) cerror("Symbol table full");
1738 		}
1739 	sp->sflags = SNONUNIQ | SMOS;
1740 	p = sp->sname;
1741 	q = stab[*idindex].sname; /* old entry name */
1742 #ifdef FLEXNAMES
1743 	sp->sname = stab[*idindex].sname;
1744 #endif
1745 # ifndef BUG1
1746 	if( ddebug ){
1747 		printf("\tnonunique entry for %s from %d to %d\n",
1748 			q, *idindex, i );
1749 		}
1750 # endif
1751 	*idindex = i;
1752 #ifndef FLEXNAMES
1753 	for( i=1; i<=NCHNAM; ++i ){ /* copy name */
1754 		if( *p++ = *q /* assign */ ) ++q;
1755 		}
1756 #endif
1757 	return ( sp );
1758 	}
1759 
1760 lookup( name, s) char *name; {
1761 	/* look up name: must agree with s w.r.t. STAG, SMOS and SHIDDEN */
1762 
1763 	register char *p, *q;
1764 	int i, j, ii;
1765 	register struct symtab *sp;
1766 
1767 	/* compute initial hash index */
1768 # ifndef BUG1
1769 	if( ddebug > 2 ){
1770 		printf( "lookup( %s, %d ), stwart=%d, instruct=%d\n", name, s, stwart, instruct );
1771 		}
1772 # endif
1773 
1774 	i = 0;
1775 #ifndef FLEXNAMES
1776 	for( p=name, j=0; *p != '\0'; ++p ){
1777 		i += *p;
1778 		if( ++j >= NCHNAM ) break;
1779 		}
1780 #else
1781 	i = (int)name;
1782 #endif
1783 	i = i%SYMTSZ;
1784 	sp = &stab[ii=i];
1785 
1786 	for(;;){ /* look for name */
1787 
1788 		if( sp->stype == TNULL ){ /* empty slot */
1789 			sp->sflags = s;  /* set STAG, SMOS if needed, turn off all others */
1790 #ifndef FLEXNAMES
1791 			p = sp->sname;
1792 			for( j=0; j<NCHNAM; ++j ) if( *p++ = *name ) ++name;
1793 #else
1794 			sp->sname = name;
1795 #endif
1796 			sp->stype = UNDEF;
1797 			sp->sclass = SNULL;
1798 			return( i );
1799 			}
1800 		if( (sp->sflags & (STAG|SMOS|SHIDDEN)) != s ) goto next;
1801 		p = sp->sname;
1802 		q = name;
1803 #ifndef FLEXNAMES
1804 		for( j=0; j<NCHNAM;++j ){
1805 			if( *p++ != *q ) goto next;
1806 			if( !*q++ ) break;
1807 			}
1808 		return( i );
1809 #else
1810 		if (p == q)
1811 			return ( i );
1812 #endif
1813 	next:
1814 		if( ++i >= SYMTSZ ){
1815 			i = 0;
1816 			sp = stab;
1817 			}
1818 		else ++sp;
1819 		if( i == ii ) cerror( "symbol table full" );
1820 		}
1821 	}
1822 
1823 #ifndef checkst
1824 /* if not debugging, make checkst a macro */
1825 checkst(lev){
1826 	register int s, i, j;
1827 	register struct symtab *p, *q;
1828 
1829 	for( i=0, p=stab; i<SYMTSZ; ++i, ++p ){
1830 		if( p->stype == TNULL ) continue;
1831 		j = lookup( p->sname, p->sflags&(SMOS|STAG) );
1832 		if( j != i ){
1833 			q = &stab[j];
1834 			if( q->stype == UNDEF ||
1835 			    q->slevel <= p->slevel ){
1836 #ifndef FLEXNAMES
1837 				cerror( "check error: %.8s", q->sname );
1838 #else
1839 				cerror( "check error: %s", q->sname );
1840 #endif
1841 				}
1842 			}
1843 #ifndef FLEXNAMES
1844 		else if( p->slevel > lev ) cerror( "%.8s check at level %d", p->sname, lev );
1845 #else
1846 		else if( p->slevel > lev ) cerror( "%s check at level %d", p->sname, lev );
1847 #endif
1848 		}
1849 	}
1850 #endif
1851 
1852 struct symtab *
1853 relook(p) register struct symtab *p; {  /* look up p again, and see where it lies */
1854 
1855 	register struct symtab *q;
1856 
1857 	/* I'm not sure that this handles towers of several hidden definitions in all cases */
1858 	q = &stab[lookup( p->sname, p->sflags&(STAG|SMOS|SHIDDEN) )];
1859 	/* make relook always point to either p or an empty cell */
1860 	if( q->stype == UNDEF ){
1861 		q->stype = TNULL;
1862 		return(q);
1863 		}
1864 	while( q != p ){
1865 		if( q->stype == TNULL ) break;
1866 		if( ++q >= &stab[SYMTSZ] ) q=stab;
1867 		}
1868 	return(q);
1869 	}
1870 
1871 clearst( lev ) register int lev; {
1872 	register struct symtab *p, *q;
1873 	register int temp;
1874 	struct symtab *clist = 0;
1875 
1876 	temp = lineno;
1877 	aobeg();
1878 
1879 	/* step 1: remove entries */
1880 	while( chaintop-1 > lev ){
1881 		register int type;
1882 
1883 		p = schain[--chaintop];
1884 		schain[chaintop] = 0;
1885 		for( ; p; p = q ){
1886 			q = p->snext;
1887 			type = p->stype;
1888 			if( p->stype == TNULL || p->slevel <= lev )
1889 				cerror( "schain botch" );
1890 			lineno = p->suse < 0 ? -p->suse : p->suse;
1891 			if( p->stype==UNDEF || ( p->sclass==ULABEL && lev<2 ) ){
1892 				lineno = temp;
1893 #ifndef FLEXNAMES
1894 				uerror( "%.8s undefined", p->sname );
1895 #else
1896 				uerror( "%s undefined", p->sname );
1897 #endif
1898 				}
1899 			else aocode(p);
1900 # ifndef BUG1
1901 			if( ddebug ){
1902 #ifndef FLEXNAMES
1903 				printf( "removing %.8s", p->sname );
1904 #else
1905 				printf( "removing %s", p->sname );
1906 #endif
1907 				printf( " from stab[%d], flags %o level %d\n",
1908 					p-stab, p->sflags, p->slevel);
1909 				}
1910 # endif
1911 			if( p->sflags & SHIDES )unhide( p );
1912 			p->stype = TNULL;
1913 			p->snext = clist;
1914 			clist = p;
1915 			}
1916 		}
1917 
1918 	/* step 2: fix any mishashed entries */
1919 	p = clist;
1920 	while( p ){
1921 		register struct symtab *r, *next;
1922 
1923 		q = p;
1924 		next = p->snext;
1925 		for(;;){
1926 			if( ++q >= &stab[SYMTSZ] )q = stab;
1927 			if( q == p || q->stype == TNULL )break;
1928 			if( (r = relook(q)) != q ) {
1929 				*r = *q;
1930 				q->stype = TNULL;
1931 				}
1932 			}
1933 		p = next;
1934 		}
1935 
1936 	lineno = temp;
1937 	aoend();
1938 	}
1939 
1940 hide( p ) register struct symtab *p; {
1941 	register struct symtab *q;
1942 	for( q=p+1; ; ++q ){
1943 		if( q >= &stab[SYMTSZ] ) q = stab;
1944 		if( q == p ) cerror( "symbol table full" );
1945 		if( q->stype == TNULL ) break;
1946 		}
1947 	*q = *p;
1948 	p->sflags |= SHIDDEN;
1949 	q->sflags = (p->sflags&(SMOS|STAG)) | SHIDES;
1950 #ifndef FLEXNAMES
1951 	if( hflag ) werror( "%.8s redefinition hides earlier one", p->sname );
1952 #else
1953 	if( hflag ) werror( "%s redefinition hides earlier one", p->sname );
1954 #endif
1955 # ifndef BUG1
1956 	if( ddebug ) printf( "	%d hidden in %d\n", p-stab, q-stab );
1957 # endif
1958 	return( idname = q-stab );
1959 	}
1960 
1961 unhide( p ) register struct symtab *p; {
1962 	register struct symtab *q;
1963 	register s, j;
1964 
1965 	s = p->sflags & (SMOS|STAG);
1966 	q = p;
1967 
1968 	for(;;){
1969 
1970 		if( q == stab ) q = &stab[SYMTSZ-1];
1971 		else --q;
1972 
1973 		if( q == p ) break;
1974 
1975 		if( (q->sflags&(SMOS|STAG)) == s ){
1976 #ifndef FLEXNAMES
1977 			for( j =0; j<NCHNAM; ++j ) if( p->sname[j] != q->sname[j] ) break;
1978 			if( j == NCHNAM ){ /* found the name */
1979 #else
1980 			if (p->sname == q->sname) {
1981 #endif
1982 				q->sflags &= ~SHIDDEN;
1983 # ifndef BUG1
1984 				if( ddebug ) printf( "unhide uncovered %d from %d\n", q-stab,p-stab);
1985 # endif
1986 				return;
1987 				}
1988 			}
1989 
1990 		}
1991 	cerror( "unhide fails" );
1992 	}
1993