xref: /csrg-svn/old/pcc/mip/pftn.c (revision 32823)
117746Sralph #ifndef lint
2*32823Sdonn static char *sccsid ="@(#)pftn.c	1.25 (Berkeley) 12/10/87";
317746Sralph #endif lint
417746Sralph 
518398Sralph # include "pass1.h"
613939Slinton 
713939Slinton unsigned int offsz;
813939Slinton 
924405Smckusick struct symtab *schain[MAXSCOPES];	/* sym chains for clearst */
1024405Smckusick int chaintop;				/* highest active entry */
1124405Smckusick 
1213939Slinton struct instk {
1313939Slinton 	int in_sz;   /* size of array element */
1413939Slinton 	int in_x;    /* current index for structure member in structure initializations */
1513939Slinton 	int in_n;    /* number of initializations seen */
1613939Slinton 	int in_s;    /* sizoff */
1713939Slinton 	int in_d;    /* dimoff */
1813939Slinton 	TWORD in_t;    /* type */
1913939Slinton 	int in_id;   /* stab index */
2013939Slinton 	int in_fl;   /* flag which says if this level is controlled by {} */
2113939Slinton 	OFFSZ in_off;  /* offset of the beginning of this level */
2213939Slinton 	}
2313939Slinton instack[10],
2413939Slinton *pstk;
2513939Slinton 
2613939Slinton 	/* defines used for getting things off of the initialization stack */
2713939Slinton 
2813939Slinton 
2913939Slinton struct symtab *relook();
3013939Slinton 
3113939Slinton 
3213939Slinton int ddebug = 0;
3313939Slinton 
3413939Slinton struct symtab * mknonuniq();
3513939Slinton 
3624405Smckusick defid( q, class ) register NODE *q; register int class; {
3713939Slinton 	register struct symtab *p;
3813939Slinton 	int idp;
3924405Smckusick 	register TWORD type;
4013939Slinton 	TWORD stp;
4124405Smckusick 	register int scl;
4213939Slinton 	int dsym, ddef;
4313939Slinton 	int slev, temp;
4413940Slinton 	int changed;
4513939Slinton 
4613939Slinton 	if( q == NIL ) return;  /* an error was detected */
4713939Slinton 
4813939Slinton 	if( q < node || q >= &node[TREESZ] ) cerror( "defid call" );
4913939Slinton 
5013939Slinton 	idp = q->tn.rval;
5113939Slinton 
5213939Slinton 	if( idp < 0 ) cerror( "tyreduce" );
5313939Slinton 	p = &stab[idp];
5413939Slinton 
5513939Slinton # ifndef BUG1
5613939Slinton 	if( ddebug ){
5713939Slinton #ifndef FLEXNAMES
5813939Slinton 		printf( "defid( %.8s (%d), ", p->sname, idp );
5913939Slinton #else
6013939Slinton 		printf( "defid( %s (%d), ", p->sname, idp );
6113939Slinton #endif
6213939Slinton 		tprint( q->in.type );
6313939Slinton 		printf( ", %s, (%d,%d) ), level %d\n", scnames(class), q->fn.cdim, q->fn.csiz, blevel );
6413939Slinton 		}
6513939Slinton # endif
6613939Slinton 
6713939Slinton 	fixtype( q, class );
6813939Slinton 
6913939Slinton 	type = q->in.type;
7013939Slinton 	class = fixclass( class, type );
7113939Slinton 
7213939Slinton 	stp = p->stype;
7313939Slinton 	slev = p->slevel;
7413939Slinton 
7513939Slinton # ifndef BUG1
7613939Slinton 	if( ddebug ){
7713939Slinton 		printf( "	modified to " );
7813939Slinton 		tprint( type );
7913939Slinton 		printf( ", %s\n", scnames(class) );
8013939Slinton 		printf( "	previous def'n: " );
8113939Slinton 		tprint( stp );
8213939Slinton 		printf( ", %s, (%d,%d) ), level %d\n", scnames(p->sclass), p->dimoff, p->sizoff, slev );
8313939Slinton 		}
8413939Slinton # endif
8513939Slinton 
8613939Slinton 	if( stp == FTN && p->sclass == SNULL )goto enter;
8732817Sdonn 	if( blevel==1 && stp!=FARG ) switch( class ){
8813939Slinton 
8913939Slinton 		default:
9013939Slinton #ifndef FLEXNAMES
9113939Slinton 			if(!(class&FIELD)) uerror( "declared argument %.8s is missing", p->sname );
9213939Slinton #else
9313939Slinton 			if(!(class&FIELD)) uerror( "declared argument %s is missing", p->sname );
9413939Slinton #endif
9513939Slinton 		case MOS:
9613939Slinton 		case STNAME:
9713939Slinton 		case MOU:
9813939Slinton 		case UNAME:
9913939Slinton 		case MOE:
10013939Slinton 		case ENAME:
10113939Slinton 		case TYPEDEF:
10213939Slinton 			;
10313939Slinton 			}
10432817Sdonn 	if( stp == UNDEF|| stp == FARG ) goto enter;
10513939Slinton 
10613939Slinton 	if( type != stp ) goto mismatch;
10732821Sdonn 	if( blevel > slev && (class == AUTO || class == REGISTER) )
10832821Sdonn 		/* new scope */
10932821Sdonn 		goto mismatch;
11032821Sdonn 
11113939Slinton 	/* test (and possibly adjust) dimensions */
11213939Slinton 	dsym = p->dimoff;
11313939Slinton 	ddef = q->fn.cdim;
11413940Slinton 	changed = 0;
11513939Slinton 	for( temp=type; temp&TMASK; temp = DECREF(temp) ){
11613939Slinton 		if( ISARY(temp) ){
11713940Slinton 			if (dimtab[dsym] == 0) {
11813940Slinton 				dimtab[dsym] = dimtab[ddef];
11913940Slinton 				changed = 1;
12013940Slinton 				}
12113940Slinton 			else if (dimtab[ddef]!=0&&dimtab[dsym]!=dimtab[ddef]) {
12213939Slinton 				goto mismatch;
12313939Slinton 				}
12413939Slinton 			++dsym;
12513939Slinton 			++ddef;
12613939Slinton 			}
12713939Slinton 		}
12813939Slinton 
12913940Slinton 	if (changed) {
13013940Slinton 		FIXDEF(p);
13113940Slinton 		}
13213940Slinton 
13313939Slinton 	/* check that redeclarations are to the same structure */
13413939Slinton 	if( (temp==STRTY||temp==UNIONTY||temp==ENUMTY) && p->sizoff != q->fn.csiz
13513939Slinton 		 && class!=STNAME && class!=UNAME && class!=ENAME ){
13613939Slinton 		goto mismatch;
13713939Slinton 		}
13813939Slinton 
13913939Slinton 	scl = ( p->sclass );
14013939Slinton 
14113939Slinton # ifndef BUG1
14213939Slinton 	if( ddebug ){
14313939Slinton 		printf( "	previous class: %s\n", scnames(scl) );
14413939Slinton 		}
14513939Slinton # endif
14613939Slinton 
14713939Slinton 	if( class&FIELD ){
14813939Slinton 		/* redefinition */
14913939Slinton 		if( !falloc( p, class&FLDSIZ, 1, NIL ) ) {
15013939Slinton 			/* successful allocation */
15113939Slinton 			psave( idp );
15213939Slinton 			return;
15313939Slinton 			}
15413939Slinton 		/* blew it: resume at end of switch... */
15513939Slinton 		}
15613939Slinton 
15713939Slinton 	else switch( class ){
15813939Slinton 
15913939Slinton 	case EXTERN:
16013939Slinton 		switch( scl ){
16113939Slinton 		case STATIC:
16213939Slinton 		case USTATIC:
16313939Slinton 			if( slev==0 ) return;
16413939Slinton 			break;
16513939Slinton 		case EXTDEF:
16613939Slinton 		case EXTERN:
16713939Slinton 		case FORTRAN:
16813939Slinton 		case UFORTRAN:
16913939Slinton 			return;
17013939Slinton 			}
17113939Slinton 		break;
17213939Slinton 
17313939Slinton 	case STATIC:
17413939Slinton 		if( scl==USTATIC || (scl==EXTERN && blevel==0) ){
17513939Slinton 			p->sclass = STATIC;
17613939Slinton 			if( ISFTN(type) ) curftn = idp;
17713939Slinton 			return;
17813939Slinton 			}
17913939Slinton 		break;
18013939Slinton 
18113939Slinton 	case USTATIC:
18213939Slinton 		if( scl==STATIC || scl==USTATIC ) return;
18313939Slinton 		break;
18413939Slinton 
18513939Slinton 	case LABEL:
18613939Slinton 		if( scl == ULABEL ){
18713939Slinton 			p->sclass = LABEL;
18813939Slinton 			deflab( p->offset );
18913939Slinton 			return;
19013939Slinton 			}
19113939Slinton 		break;
19213939Slinton 
19313939Slinton 	case TYPEDEF:
19413939Slinton 		if( scl == class ) return;
19513939Slinton 		break;
19613939Slinton 
19713939Slinton 	case UFORTRAN:
19813939Slinton 		if( scl == UFORTRAN || scl == FORTRAN ) return;
19913939Slinton 		break;
20013939Slinton 
20113939Slinton 	case FORTRAN:
20213939Slinton 		if( scl == UFORTRAN ){
20313939Slinton 			p->sclass = FORTRAN;
20413939Slinton 			if( ISFTN(type) ) curftn = idp;
20513939Slinton 			return;
20613939Slinton 			}
20713939Slinton 		break;
20813939Slinton 
20913939Slinton 	case MOU:
21013939Slinton 	case MOS:
21113939Slinton 		if( scl == class ) {
21213939Slinton 			if( oalloc( p, &strucoff ) ) break;
21313939Slinton 			if( class == MOU ) strucoff = 0;
21413939Slinton 			psave( idp );
21513939Slinton 			return;
21613939Slinton 			}
21713939Slinton 		break;
21813939Slinton 
21913939Slinton 	case MOE:
22013939Slinton 		if( scl == class ){
22113939Slinton 			if( p->offset!= strucoff++ ) break;
22213939Slinton 			psave( idp );
22313939Slinton 			}
22413939Slinton 		break;
22513939Slinton 
22613939Slinton 	case EXTDEF:
22713939Slinton 		if( scl == EXTERN ) {
22813939Slinton 			p->sclass = EXTDEF;
22913939Slinton 			if( ISFTN(type) ) curftn = idp;
23013939Slinton 			return;
23113939Slinton 			}
23213939Slinton 		break;
23313939Slinton 
23413939Slinton 	case STNAME:
23513939Slinton 	case UNAME:
23613939Slinton 	case ENAME:
23713939Slinton 		if( scl != class ) break;
23813939Slinton 		if( dimtab[p->sizoff] == 0 ) return;  /* previous entry just a mention */
23913939Slinton 		break;
24013939Slinton 
24113939Slinton 	case ULABEL:
24213939Slinton 		if( scl == LABEL || scl == ULABEL ) return;
24313939Slinton 	case PARAM:
24413939Slinton 	case AUTO:
24513939Slinton 	case REGISTER:
24613939Slinton 		;  /* mismatch.. */
24713939Slinton 
24813939Slinton 		}
24913939Slinton 
25013939Slinton 	mismatch:
25113939Slinton 	/* allow nonunique structure/union member names */
25213939Slinton 
25313939Slinton 	if( class==MOU || class==MOS || class & FIELD ){/* make a new entry */
25424405Smckusick 		register int *memp;
25513939Slinton 		p->sflags |= SNONUNIQ;  /* old entry is nonunique */
25613939Slinton 		/* determine if name has occurred in this structure/union */
25717981Sralph 		if (paramno > 0) for( memp = &paramstk[paramno-1];
25813939Slinton 			/* while */ *memp>=0 && stab[*memp].sclass != STNAME
25913939Slinton 				&& stab[*memp].sclass != UNAME;
26017981Sralph 			/* iterate */ --memp){ char *cname, *oname;
26132817Sdonn 			if( stab[*memp].sflags & SNONUNIQ ){
26213939Slinton 				cname=p->sname;
26313939Slinton 				oname=stab[*memp].sname;
26413939Slinton #ifndef FLEXNAMES
26532817Sdonn 				for(temp=1; temp<=NCHNAM; ++temp){
26613939Slinton 					if(*cname++ != *oname)goto diff;
26713939Slinton 					if(!*oname++)break;
26813939Slinton 					}
26913939Slinton #else
27013939Slinton 				if (cname != oname) goto diff;
27113939Slinton #endif
27213939Slinton 				uerror("redeclaration of: %s",p->sname);
27313939Slinton 				break;
27413939Slinton 				diff: continue;
27513939Slinton 				}
27613939Slinton 			}
27713939Slinton 		p = mknonuniq( &idp ); /* update p and idp to new entry */
27813939Slinton 		goto enter;
27913939Slinton 		}
28013939Slinton 	if( blevel > slev && class != EXTERN && class != FORTRAN &&
28113939Slinton 		class != UFORTRAN && !( class == LABEL && slev >= 2 ) ){
28213939Slinton 		q->tn.rval = idp = hide( p );
28313939Slinton 		p = &stab[idp];
28413939Slinton 		goto enter;
28513939Slinton 		}
28613939Slinton #ifndef FLEXNAMES
28713939Slinton 	uerror( "redeclaration of %.8s", p->sname );
28813939Slinton #else
28913939Slinton 	uerror( "redeclaration of %s", p->sname );
29013939Slinton #endif
29113939Slinton 	if( class==EXTDEF && ISFTN(type) ) curftn = idp;
29213939Slinton 	return;
29313939Slinton 
29413939Slinton 	enter:  /* make a new entry */
29513939Slinton 
29613939Slinton # ifndef BUG1
29713939Slinton 	if( ddebug ) printf( "	new entry made\n" );
29813939Slinton # endif
29913939Slinton 	if( type == UNDEF ) uerror("void type for %s",p->sname);
30013939Slinton 	p->stype = type;
30113939Slinton 	p->sclass = class;
30213939Slinton 	p->slevel = blevel;
30313939Slinton 	p->offset = NOOFFSET;
30413939Slinton 	p->suse = lineno;
30513939Slinton 	if( class == STNAME || class == UNAME || class == ENAME ) {
30613939Slinton 		p->sizoff = curdim;
30713939Slinton 		dstash( 0 );  /* size */
30813939Slinton 		dstash( -1 ); /* index to members of str or union */
30913939Slinton 		dstash( ALSTRUCT );  /* alignment */
31013939Slinton 		dstash( idp );
31113939Slinton 		}
31213939Slinton 	else {
31313939Slinton 		switch( BTYPE(type) ){
31413939Slinton 		case STRTY:
31513939Slinton 		case UNIONTY:
31613939Slinton 		case ENUMTY:
31713939Slinton 			p->sizoff = q->fn.csiz;
31813939Slinton 			break;
31913939Slinton 		default:
32013939Slinton 			p->sizoff = BTYPE(type);
32113939Slinton 			}
32213939Slinton 		}
32313939Slinton 
32413939Slinton 	/* copy dimensions */
32513939Slinton 
32613939Slinton 	p->dimoff = q->fn.cdim;
32713939Slinton 
32813939Slinton 	/* allocate offsets */
32913939Slinton 	if( class&FIELD ){
33032817Sdonn 		(void) falloc( p, class&FLDSIZ, 0, NIL );  /* new entry */
33113939Slinton 		psave( idp );
33213939Slinton 		}
33313939Slinton 	else switch( class ){
33413939Slinton 
33513939Slinton 	case AUTO:
33632817Sdonn 		(void) oalloc( p, &autooff );
33713939Slinton 		break;
33813939Slinton 	case STATIC:
33913939Slinton 	case EXTDEF:
34013939Slinton 		p->offset = getlab();
34113939Slinton 		if( ISFTN(type) ) curftn = idp;
34213939Slinton 		break;
34313939Slinton 	case ULABEL:
34413939Slinton 	case LABEL:
34513939Slinton 		p->offset = getlab();
34613939Slinton 		p->slevel = 2;
34713939Slinton 		if( class == LABEL ){
34832817Sdonn 			(void) locctr( PROG );
34913939Slinton 			deflab( p->offset );
35013939Slinton 			}
35113939Slinton 		break;
35213939Slinton 
35313939Slinton 	case EXTERN:
35413939Slinton 	case UFORTRAN:
35513939Slinton 	case FORTRAN:
35613939Slinton 		p->offset = getlab();
35713939Slinton 		p->slevel = 0;
35813939Slinton 		break;
35913939Slinton 	case MOU:
36013939Slinton 	case MOS:
36132817Sdonn 		(void) oalloc( p, &strucoff );
36213939Slinton 		if( class == MOU ) strucoff = 0;
36313939Slinton 		psave( idp );
36413939Slinton 		break;
36513939Slinton 
36613939Slinton 	case MOE:
36713939Slinton 		p->offset = strucoff++;
36813939Slinton 		psave( idp );
36913939Slinton 		break;
37013939Slinton 	case REGISTER:
37113939Slinton 		p->offset = regvar--;
37213939Slinton 		if( blevel == 1 ) p->sflags |= SSET;
37313939Slinton 		if( regvar < minrvar ) minrvar = regvar;
37413939Slinton 		break;
37513939Slinton 		}
37613939Slinton 
37724405Smckusick 	{
37824405Smckusick 		register int l = p->slevel;
37924405Smckusick 
38024405Smckusick 		if( l >= MAXSCOPES )
38124405Smckusick 			cerror( "scopes nested too deep" );
38224405Smckusick 
38324405Smckusick 		p->snext = schain[l];
38424405Smckusick 		schain[l] = p;
38524405Smckusick 		if( l >= chaintop )
38624405Smckusick 			chaintop = l + 1;
38724405Smckusick 		}
38824405Smckusick 
38913939Slinton 	/* user-supplied routine to fix up new definitions */
39013939Slinton 
39113939Slinton 	FIXDEF(p);
39213939Slinton 
39313939Slinton # ifndef BUG1
39413939Slinton 	if( ddebug ) printf( "	dimoff, sizoff, offset: %d, %d, %d\n", p->dimoff, p->sizoff, p->offset );
39513939Slinton # endif
39613939Slinton 
39713939Slinton 	}
39813939Slinton 
39913939Slinton psave( i ){
40013939Slinton 	if( paramno >= PARAMSZ ){
40113939Slinton 		cerror( "parameter stack overflow");
40213939Slinton 		}
40313939Slinton 	paramstk[ paramno++ ] = i;
40413939Slinton 	}
40513939Slinton 
40613939Slinton ftnend(){ /* end of function */
40732814Sdonn 	if( retlab != NOLAB && nerrors == 0 ){ /* inside a real function */
40813939Slinton 		efcode();
40913939Slinton 		}
41013939Slinton 	checkst(0);
41113939Slinton 	retstat = 0;
41213939Slinton 	tcheck();
41313939Slinton 	curclass = SNULL;
41413939Slinton 	brklab = contlab = retlab = NOLAB;
41513939Slinton 	flostat = 0;
41613939Slinton 	if( nerrors == 0 ){
41713939Slinton 		if( psavbc != & asavbc[0] ) cerror("bcsave error");
41813939Slinton 		if( paramno != 0 ) cerror("parameter reset error");
41913939Slinton 		if( swx != 0 ) cerror( "switch error");
42013939Slinton 		}
42113939Slinton 	psavbc = &asavbc[0];
42213939Slinton 	paramno = 0;
42313939Slinton 	autooff = AUTOINIT;
42413939Slinton 	minrvar = regvar = MAXRVAR;
42513939Slinton 	reached = 1;
42613939Slinton 	swx = 0;
42713939Slinton 	swp = swtab;
42832817Sdonn 	(void) locctr(DATA);
42913939Slinton 	}
43013939Slinton 
43113939Slinton dclargs(){
43213939Slinton 	register i, j;
43313939Slinton 	register struct symtab *p;
43413939Slinton 	register NODE *q;
43513939Slinton 	argoff = ARGINIT;
43613939Slinton # ifndef BUG1
43713939Slinton 	if( ddebug > 2) printf("dclargs()\n");
43813939Slinton # endif
43913939Slinton 	for( i=0; i<paramno; ++i ){
44013939Slinton 		if( (j = paramstk[i]) < 0 ) continue;
44113939Slinton 		p = &stab[j];
44213939Slinton # ifndef BUG1
44313939Slinton 		if( ddebug > 2 ){
44413939Slinton 			printf("\t%s (%d) ",p->sname, j);
44513939Slinton 			tprint(p->stype);
44613939Slinton 			printf("\n");
44713939Slinton 			}
44813939Slinton # endif
44913939Slinton 		if( p->stype == FARG ) {
45013939Slinton 			q = block(FREE,NIL,NIL,INT,0,INT);
45113939Slinton 			q->tn.rval = j;
45213939Slinton 			defid( q, PARAM );
45313939Slinton 			}
45413939Slinton 		FIXARG(p); /* local arg hook, eg. for sym. debugger */
45513939Slinton 		oalloc( p, &argoff );  /* always set aside space, even for register arguments */
45613939Slinton 		}
45713939Slinton 	cendarg();
45832817Sdonn 	(void) locctr(PROG);
45913939Slinton 	defalign(ALINT);
46013939Slinton 	ftnno = getlab();
46113939Slinton 	bfcode( paramstk, paramno );
46213939Slinton 	paramno = 0;
46313939Slinton 	}
46413939Slinton 
46513939Slinton NODE *
46613939Slinton rstruct( idn, soru ){ /* reference to a structure or union, with no definition */
46713939Slinton 	register struct symtab *p;
46813939Slinton 	register NODE *q;
46913939Slinton 	p = &stab[idn];
47013939Slinton 	switch( p->stype ){
47113939Slinton 
47213939Slinton 	case UNDEF:
47313939Slinton 	def:
47413939Slinton 		q = block( FREE, NIL, NIL, 0, 0, 0 );
47513939Slinton 		q->tn.rval = idn;
47613939Slinton 		q->in.type = (soru&INSTRUCT) ? STRTY : ( (soru&INUNION) ? UNIONTY : ENUMTY );
47713939Slinton 		defid( q, (soru&INSTRUCT) ? STNAME : ( (soru&INUNION) ? UNAME : ENAME ) );
47813939Slinton 		break;
47913939Slinton 
48013939Slinton 	case STRTY:
48113939Slinton 		if( soru & INSTRUCT ) break;
48213939Slinton 		goto def;
48313939Slinton 
48413939Slinton 	case UNIONTY:
48513939Slinton 		if( soru & INUNION ) break;
48613939Slinton 		goto def;
48713939Slinton 
48813939Slinton 	case ENUMTY:
48913939Slinton 		if( !(soru&(INUNION|INSTRUCT)) ) break;
49013939Slinton 		goto def;
49113939Slinton 
49213939Slinton 		}
49313939Slinton 	stwart = instruct;
49413939Slinton 	return( mkty( p->stype, 0, p->sizoff ) );
49513939Slinton 	}
49613939Slinton 
49713939Slinton moedef( idn ){
49813939Slinton 	register NODE *q;
49913939Slinton 
50013939Slinton 	q = block( FREE, NIL, NIL, MOETY, 0, 0 );
50113939Slinton 	q->tn.rval = idn;
50213939Slinton 	if( idn>=0 ) defid( q, MOE );
50313939Slinton 	}
50413939Slinton 
50513939Slinton bstruct( idn, soru ){ /* begining of structure or union declaration */
50613939Slinton 	register NODE *q;
50713939Slinton 
50813939Slinton 	psave( instruct );
50913939Slinton 	psave( curclass );
51013939Slinton 	psave( strucoff );
51113939Slinton 	strucoff = 0;
51213939Slinton 	instruct = soru;
51313939Slinton 	q = block( FREE, NIL, NIL, 0, 0, 0 );
51413939Slinton 	q->tn.rval = idn;
51513939Slinton 	if( instruct==INSTRUCT ){
51613939Slinton 		curclass = MOS;
51713939Slinton 		q->in.type = STRTY;
51813939Slinton 		if( idn >= 0 ) defid( q, STNAME );
51913939Slinton 		}
52013939Slinton 	else if( instruct == INUNION ) {
52113939Slinton 		curclass = MOU;
52213939Slinton 		q->in.type = UNIONTY;
52313939Slinton 		if( idn >= 0 ) defid( q, UNAME );
52413939Slinton 		}
52513939Slinton 	else { /* enum */
52613939Slinton 		curclass = MOE;
52713939Slinton 		q->in.type = ENUMTY;
52813939Slinton 		if( idn >= 0 ) defid( q, ENAME );
52913939Slinton 		}
53013939Slinton 	psave( idn = q->tn.rval );
53113939Slinton 	/* the "real" definition is where the members are seen */
53213939Slinton 	if ( idn >= 0 ) stab[idn].suse = lineno;
53313939Slinton 	return( paramno-4 );
53413939Slinton 	}
53513939Slinton 
53613939Slinton NODE *
53713939Slinton dclstruct( oparam ){
53813939Slinton 	register struct symtab *p;
53913939Slinton 	register i, al, sa, j, sz, szindex;
54013939Slinton 	register TWORD temp;
54113939Slinton 	register high, low;
54213939Slinton 
54332817Sdonn 	/* paramstk contains:
54432817Sdonn 		paramstk[ oparam ] = previous instruct
54532817Sdonn 		paramstk[ oparam+1 ] = previous class
54613939Slinton 		paramstk[ oparam+2 ] = previous strucoff
54713939Slinton 		paramstk[ oparam+3 ] = structure name
54813939Slinton 
54913939Slinton 		paramstk[ oparam+4, ... ]  = member stab indices
55013939Slinton 
55113939Slinton 		*/
55213939Slinton 
55313939Slinton 
55413939Slinton 	if( (i=paramstk[oparam+3]) < 0 ){
55513939Slinton 		szindex = curdim;
55613939Slinton 		dstash( 0 );  /* size */
55713939Slinton 		dstash( -1 );  /* index to member names */
55813939Slinton 		dstash( ALSTRUCT );  /* alignment */
55913939Slinton 		dstash( -lineno );	/* name of structure */
56013939Slinton 		}
56113939Slinton 	else {
56213939Slinton 		szindex = stab[i].sizoff;
56313939Slinton 		}
56413939Slinton 
56513939Slinton # ifndef BUG1
56613939Slinton 	if( ddebug ){
56713939Slinton #ifndef FLEXNAMES
56813939Slinton 		printf( "dclstruct( %.8s ), szindex = %d\n", (i>=0)? stab[i].sname : "??", szindex );
56913939Slinton #else
57013939Slinton 		printf( "dclstruct( %s ), szindex = %d\n", (i>=0)? stab[i].sname : "??", szindex );
57113939Slinton #endif
57213939Slinton 		}
57313939Slinton # endif
57413939Slinton 	temp = (instruct&INSTRUCT)?STRTY:((instruct&INUNION)?UNIONTY:ENUMTY);
57513939Slinton 	stwart = instruct = paramstk[ oparam ];
57613939Slinton 	curclass = paramstk[ oparam+1 ];
57713939Slinton 	dimtab[ szindex+1 ] = curdim;
57813939Slinton 	al = ALSTRUCT;
57913939Slinton 
58013939Slinton 	high = low = 0;
58113939Slinton 
58213939Slinton 	for( i = oparam+4;  i< paramno; ++i ){
58313939Slinton 		dstash( j=paramstk[i] );
58413939Slinton 		if( j<0 || j>= SYMTSZ ) cerror( "gummy structure member" );
58513939Slinton 		p = &stab[j];
58613939Slinton 		if( temp == ENUMTY ){
58713939Slinton 			if( p->offset < low ) low = p->offset;
58813939Slinton 			if( p->offset > high ) high = p->offset;
58913939Slinton 			p->sizoff = szindex;
59013939Slinton 			continue;
59113939Slinton 			}
59213939Slinton 		sa = talign( p->stype, p->sizoff );
59313939Slinton 		if( p->sclass & FIELD ){
59413939Slinton 			sz = p->sclass&FLDSIZ;
59513939Slinton 			}
59613939Slinton 		else {
59713939Slinton 			sz = tsize( p->stype, p->dimoff, p->sizoff );
59813939Slinton 			}
59913939Slinton 		if( sz == 0 ){
60013939Slinton #ifndef FLEXNAMES
60113939Slinton 			werror( "illegal zero sized structure member: %.8s", p->sname );
60213939Slinton #else
60313939Slinton 			werror( "illegal zero sized structure member: %s", p->sname );
60413939Slinton #endif
60513939Slinton 			}
60613939Slinton 		if( sz > strucoff ) strucoff = sz;  /* for use with unions */
60713939Slinton 		SETOFF( al, sa );
60813939Slinton 		/* set al, the alignment, to the lcm of the alignments of the members */
60913939Slinton 		}
61013939Slinton 	dstash( -1 );  /* endmarker */
61113939Slinton 	SETOFF( strucoff, al );
61213939Slinton 
61313939Slinton 	if( temp == ENUMTY ){
61413939Slinton 		register TWORD ty;
61513939Slinton 
61613939Slinton # ifdef ENUMSIZE
61713939Slinton 		ty = ENUMSIZE(high,low);
61813939Slinton # else
61913939Slinton 		if( (char)high == high && (char)low == low ) ty = ctype( CHAR );
62013939Slinton 		else if( (short)high == high && (short)low == low ) ty = ctype( SHORT );
62113939Slinton 		else ty = ctype(INT);
62213939Slinton #endif
62313939Slinton 		strucoff = tsize( ty, 0, (int)ty );
62413939Slinton 		dimtab[ szindex+2 ] = al = talign( ty, (int)ty );
62513939Slinton 		}
62613939Slinton 
62713939Slinton 	if( strucoff == 0 ) uerror( "zero sized structure" );
62813939Slinton 	dimtab[ szindex ] = strucoff;
62913939Slinton 	dimtab[ szindex+2 ] = al;
63013939Slinton 	dimtab[ szindex+3 ] = paramstk[ oparam+3 ];  /* name index */
63113939Slinton 
63213939Slinton 	FIXSTRUCT( szindex, oparam ); /* local hook, eg. for sym debugger */
63313939Slinton # ifndef BUG1
63413939Slinton 	if( ddebug>1 ){
63513939Slinton 		printf( "\tdimtab[%d,%d,%d] = %d,%d,%d\n", szindex,szindex+1,szindex+2,
63613939Slinton 				dimtab[szindex],dimtab[szindex+1],dimtab[szindex+2] );
63713939Slinton 		for( i = dimtab[szindex+1]; dimtab[i] >= 0; ++i ){
63813939Slinton #ifndef FLEXNAMES
63913939Slinton 			printf( "\tmember %.8s(%d)\n", stab[dimtab[i]].sname, dimtab[i] );
64013939Slinton #else
64113939Slinton 			printf( "\tmember %s(%d)\n", stab[dimtab[i]].sname, dimtab[i] );
64213939Slinton #endif
64313939Slinton 			}
64413939Slinton 		}
64513939Slinton # endif
64613939Slinton 
64713939Slinton 	strucoff = paramstk[ oparam+2 ];
64813939Slinton 	paramno = oparam;
64913939Slinton 
65013939Slinton 	return( mkty( temp, 0, szindex ) );
65113939Slinton 	}
65213939Slinton 
65313939Slinton 	/* VARARGS */
65413939Slinton yyerror( s ) char *s; { /* error printing routine in parser */
65513939Slinton 
65613939Slinton 	uerror( s );
65713939Slinton 
65813939Slinton 	}
65913939Slinton 
66013939Slinton yyaccpt(){
66113939Slinton 	ftnend();
66213939Slinton 	}
66313939Slinton 
66413939Slinton ftnarg( idn ) {
66513939Slinton 	switch( stab[idn].stype ){
66613939Slinton 
66713939Slinton 	case UNDEF:
66813939Slinton 		/* this parameter, entered at scan */
66913939Slinton 		break;
67013939Slinton 	case FARG:
67113939Slinton #ifndef FLEXNAMES
67213939Slinton 		uerror("redeclaration of formal parameter, %.8s",
67313939Slinton #else
67413939Slinton 		uerror("redeclaration of formal parameter, %s",
67513939Slinton #endif
67613939Slinton 			stab[idn].sname);
67713939Slinton 		/* fall thru */
67813939Slinton 	case FTN:
67913939Slinton 		/* the name of this function matches parm */
68013939Slinton 		/* fall thru */
68113939Slinton 	default:
68213939Slinton 		idn = hide( &stab[idn]);
68313939Slinton 		break;
68413939Slinton 	case TNULL:
68513939Slinton 		/* unused entry, fill it */
68613939Slinton 		;
68713939Slinton 		}
68813939Slinton 	stab[idn].stype = FARG;
68913939Slinton 	stab[idn].sclass = PARAM;
69013939Slinton 	psave( idn );
69113939Slinton 	}
69213939Slinton 
69313939Slinton talign( ty, s) register unsigned ty; register s; {
69413939Slinton 	/* compute the alignment of an object with type ty, sizeoff index s */
69513939Slinton 
69613939Slinton 	register i;
69713939Slinton 	if( s<0 && ty!=INT && ty!=CHAR && ty!=SHORT && ty!=UNSIGNED && ty!=UCHAR && ty!=USHORT
69813939Slinton #ifdef LONGFIELDS
69913939Slinton 		&& ty!=LONG && ty!=ULONG
70013939Slinton #endif
70113939Slinton 					){
70213939Slinton 		return( fldal( ty ) );
70313939Slinton 		}
70413939Slinton 
70513939Slinton 	for( i=0; i<=(SZINT-BTSHIFT-1); i+=TSHIFT ){
70613939Slinton 		switch( (ty>>i)&TMASK ){
70713939Slinton 
70813939Slinton 		case FTN:
70913939Slinton 			cerror( "compiler takes alignment of function");
71013939Slinton 		case PTR:
71113939Slinton 			return( ALPOINT );
71213939Slinton 		case ARY:
71313939Slinton 			continue;
71413939Slinton 		case 0:
71513939Slinton 			break;
71613939Slinton 			}
71713939Slinton 		}
71813939Slinton 
71913939Slinton 	switch( BTYPE(ty) ){
72013939Slinton 
72113939Slinton 	case UNIONTY:
72213939Slinton 	case ENUMTY:
72313939Slinton 	case STRTY:
72413939Slinton 		return( (unsigned int) dimtab[ s+2 ] );
72513939Slinton 	case CHAR:
72613939Slinton 	case UCHAR:
72713939Slinton 		return( ALCHAR );
72813939Slinton 	case FLOAT:
72913939Slinton 		return( ALFLOAT );
73013939Slinton 	case DOUBLE:
73113939Slinton 		return( ALDOUBLE );
73213939Slinton 	case LONG:
73313939Slinton 	case ULONG:
73413939Slinton 		return( ALLONG );
73513939Slinton 	case SHORT:
73613939Slinton 	case USHORT:
73713939Slinton 		return( ALSHORT );
73813939Slinton 	default:
73913939Slinton 		return( ALINT );
74013939Slinton 		}
74113939Slinton 	}
74213939Slinton 
74313939Slinton OFFSZ
74413939Slinton tsize( ty, d, s )  TWORD ty; {
74513939Slinton 	/* compute the size associated with type ty,
74613939Slinton 	    dimoff d, and sizoff s */
74713939Slinton 	/* BETTER NOT BE CALLED WHEN t, d, and s REFER TO A BIT FIELD... */
74813939Slinton 
74913939Slinton 	int i;
75013939Slinton 	OFFSZ mult;
75113939Slinton 
75213939Slinton 	mult = 1;
75313939Slinton 
75413939Slinton 	for( i=0; i<=(SZINT-BTSHIFT-1); i+=TSHIFT ){
75513939Slinton 		switch( (ty>>i)&TMASK ){
75613939Slinton 
75713939Slinton 		case FTN:
75832819Sdonn 			/* cerror( "compiler takes size of function"); */
75932819Sdonn 			uerror( "can't take size of function" );
76032819Sdonn 			return( SZCHAR );
76113939Slinton 		case PTR:
76213939Slinton 			return( SZPOINT * mult );
76313939Slinton 		case ARY:
76413939Slinton 			mult *= (unsigned int) dimtab[ d++ ];
76513939Slinton 			continue;
76613939Slinton 		case 0:
76713939Slinton 			break;
76813939Slinton 
76913939Slinton 			}
77013939Slinton 		}
77113939Slinton 
77213939Slinton 	if( dimtab[s]==0 ) {
77325749Sdonn 		if( ty == STRTY )
77425749Sdonn 			uerror( "undefined structure" );
77525749Sdonn 		else
77625749Sdonn 			uerror( "unknown size");
77713939Slinton 		return( SZINT );
77813939Slinton 		}
77913939Slinton 	return( (unsigned int) dimtab[ s ] * mult );
78013939Slinton 	}
78113939Slinton 
78213939Slinton inforce( n ) OFFSZ n; {  /* force inoff to have the value n */
78313939Slinton 	/* inoff is updated to have the value n */
78413939Slinton 	OFFSZ wb;
78513939Slinton 	register rest;
78613939Slinton 	/* rest is used to do a lot of conversion to ints... */
78713939Slinton 
78813939Slinton 	if( inoff == n ) return;
78913939Slinton 	if( inoff > n ) {
79013939Slinton 		cerror( "initialization alignment error");
79113939Slinton 		}
79213939Slinton 
79313939Slinton 	wb = inoff;
79413939Slinton 	SETOFF( wb, SZINT );
79513939Slinton 
79613939Slinton 	/* wb now has the next higher word boundary */
79713939Slinton 
79813939Slinton 	if( wb >= n ){ /* in the same word */
79913939Slinton 		rest = n - inoff;
80013939Slinton 		vfdzero( rest );
80113939Slinton 		return;
80213939Slinton 		}
80313939Slinton 
80413939Slinton 	/* otherwise, extend inoff to be word aligned */
80513939Slinton 
80613939Slinton 	rest = wb - inoff;
80713939Slinton 	vfdzero( rest );
80813939Slinton 
80913939Slinton 	/* now, skip full words until near to n */
81013939Slinton 
81113939Slinton 	rest = (n-inoff)/SZINT;
81213939Slinton 	zecode( rest );
81313939Slinton 
81413939Slinton 	/* now, the remainder of the last word */
81513939Slinton 
81613939Slinton 	rest = n-inoff;
81713939Slinton 	vfdzero( rest );
81813939Slinton 	if( inoff != n ) cerror( "inoff error");
81913939Slinton 
82013939Slinton 	}
82113939Slinton 
82213939Slinton vfdalign( n ){ /* make inoff have the offset the next alignment of n */
82313939Slinton 	OFFSZ m;
82413939Slinton 
82513939Slinton 	m = inoff;
82613939Slinton 	SETOFF( m, n );
82713939Slinton 	inforce( m );
82813939Slinton 	}
82913939Slinton 
83013939Slinton 
83113939Slinton int idebug = 0;
83213939Slinton 
83313939Slinton int ibseen = 0;  /* the number of } constructions which have been filled */
83413939Slinton 
83527247Sdonn int ifull = 0; /* 1 if all initializers have been seen */
83627247Sdonn 
83713939Slinton int iclass;  /* storage class of thing being initialized */
83813939Slinton 
83913939Slinton int ilocctr = 0;  /* location counter for current initialization */
84013939Slinton 
84113939Slinton beginit(curid){
84213939Slinton 	/* beginning of initilization; set location ctr and set type */
84313939Slinton 	register struct symtab *p;
84413939Slinton 
84513939Slinton # ifndef BUG1
84613939Slinton 	if( idebug >= 3 ) printf( "beginit(), curid = %d\n", curid );
84713939Slinton # endif
84813939Slinton 
84913939Slinton 	p = &stab[curid];
85013939Slinton 
85113939Slinton 	iclass = p->sclass;
85213939Slinton 	if( curclass == EXTERN || curclass == FORTRAN ) iclass = EXTERN;
85313939Slinton 	switch( iclass ){
85413939Slinton 
85513939Slinton 	case UNAME:
85613939Slinton 	case EXTERN:
85713939Slinton 		return;
85813939Slinton 	case AUTO:
85913939Slinton 	case REGISTER:
86013939Slinton 		break;
86113939Slinton 	case EXTDEF:
86213939Slinton 	case STATIC:
86313939Slinton 		ilocctr = ISARY(p->stype)?ADATA:DATA;
86432814Sdonn 		if( nerrors == 0 ){
86532817Sdonn 			(void) locctr( ilocctr );
86632814Sdonn 			defalign( talign( p->stype, p->sizoff ) );
86732814Sdonn 			defnam( p );
86832814Sdonn 			}
86913939Slinton 
87013939Slinton 		}
87113939Slinton 
87213939Slinton 	inoff = 0;
87313939Slinton 	ibseen = 0;
87427247Sdonn 	ifull = 0;
87513939Slinton 
87613939Slinton 	pstk = 0;
87713939Slinton 
87813939Slinton 	instk( curid, p->stype, p->dimoff, p->sizoff, inoff );
87913939Slinton 
88013939Slinton 	}
88113939Slinton 
88213939Slinton instk( id, t, d, s, off ) OFFSZ off; TWORD t; {
88313939Slinton 	/* make a new entry on the parameter stack to initialize id */
88413939Slinton 
88513939Slinton 	register struct symtab *p;
88613939Slinton 
88713939Slinton 	for(;;){
88813939Slinton # ifndef BUG1
88913939Slinton 		if( idebug ) printf( "instk((%d, %o,%d,%d, %d)\n", id, t, d, s, off );
89013939Slinton # endif
89113939Slinton 
89213939Slinton 		/* save information on the stack */
89313939Slinton 
89413939Slinton 		if( !pstk ) pstk = instack;
89513939Slinton 		else ++pstk;
89613939Slinton 
89713939Slinton 		pstk->in_fl = 0;	/* { flag */
89813939Slinton 		pstk->in_id =  id ;
89913939Slinton 		pstk->in_t =  t ;
90013939Slinton 		pstk->in_d =  d ;
90113939Slinton 		pstk->in_s =  s ;
90213939Slinton 		pstk->in_n = 0;  /* number seen */
90313939Slinton 		pstk->in_x =  t==STRTY ?dimtab[s+1] : 0 ;
90413939Slinton 		pstk->in_off =  off;   /* offset at the beginning of this element */
90513939Slinton 		/* if t is an array, DECREF(t) can't be a field */
90613939Slinton 		/* INS_sz has size of array elements, and -size for fields */
90713939Slinton 		if( ISARY(t) ){
90813939Slinton 			pstk->in_sz = tsize( DECREF(t), d+1, s );
90913939Slinton 			}
91013939Slinton 		else if( stab[id].sclass & FIELD ){
91113939Slinton 			pstk->in_sz = - ( stab[id].sclass & FLDSIZ );
91213939Slinton 			}
91313939Slinton 		else {
91413939Slinton 			pstk->in_sz = 0;
91513939Slinton 			}
91613939Slinton 
91713939Slinton 		if( (iclass==AUTO || iclass == REGISTER ) &&
91813939Slinton 			(ISARY(t) || t==STRTY) ) uerror( "no automatic aggregate initialization" );
91913939Slinton 
92013939Slinton 		/* now, if this is not a scalar, put on another element */
92113939Slinton 
92213939Slinton 		if( ISARY(t) ){
92313939Slinton 			t = DECREF(t);
92413939Slinton 			++d;
92513939Slinton 			continue;
92613939Slinton 			}
92713939Slinton 		else if( t == STRTY ){
92825749Sdonn 			if( dimtab[pstk->in_s] == 0 ){
92925749Sdonn 				uerror( "can't initialize undefined structure" );
93025749Sdonn 				iclass = -1;
93125749Sdonn 				return;
93225749Sdonn 				}
93313939Slinton 			id = dimtab[pstk->in_x];
93413939Slinton 			p = &stab[id];
93513939Slinton 			if( p->sclass != MOS && !(p->sclass&FIELD) ) cerror( "insane structure member list" );
93613939Slinton 			t = p->stype;
93713939Slinton 			d = p->dimoff;
93813939Slinton 			s = p->sizoff;
93913939Slinton 			off += p->offset;
94013939Slinton 			continue;
94113939Slinton 			}
94213939Slinton 		else return;
94313939Slinton 		}
94413939Slinton 	}
94513939Slinton 
94613939Slinton NODE *
94713939Slinton getstr(){ /* decide if the string is external or an initializer, and get the contents accordingly */
94813939Slinton 
94913939Slinton 	register l, temp;
95013939Slinton 	register NODE *p;
95113939Slinton 
95213939Slinton 	if( (iclass==EXTDEF||iclass==STATIC) && (pstk->in_t == CHAR || pstk->in_t == UCHAR) &&
95313939Slinton 			pstk!=instack && ISARY( pstk[-1].in_t ) ){
95413939Slinton 		/* treat "abc" as { 'a', 'b', 'c', 0 } */
95513939Slinton 		strflg = 1;
95613939Slinton 		ilbrace();  /* simulate { */
95713939Slinton 		inforce( pstk->in_off );
95813939Slinton 		/* if the array is inflexible (not top level), pass in the size and
95913939Slinton 			be prepared to throw away unwanted initializers */
96013939Slinton 		lxstr((pstk-1)!=instack?dimtab[(pstk-1)->in_d]:0);  /* get the contents */
96113939Slinton 		irbrace();  /* simulate } */
96213939Slinton 		return( NIL );
96313939Slinton 		}
96413939Slinton 	else { /* make a label, and get the contents and stash them away */
96513939Slinton 		if( iclass != SNULL ){ /* initializing */
96613939Slinton 			/* fill out previous word, to permit pointer */
96713939Slinton 			vfdalign( ALPOINT );
96813939Slinton 			}
96913939Slinton 		temp = locctr( blevel==0?ISTRNG:STRNG ); /* set up location counter */
97013939Slinton 		deflab( l = getlab() );
97113939Slinton 		strflg = 0;
97213939Slinton 		lxstr(0); /* get the contents */
97332817Sdonn 		(void) locctr( blevel==0?ilocctr:temp );
97413939Slinton 		p = buildtree( STRING, NIL, NIL );
97513939Slinton 		p->tn.rval = -l;
97613939Slinton 		return(p);
97713939Slinton 		}
97813939Slinton 	}
97913939Slinton 
98013939Slinton putbyte( v ){ /* simulate byte v appearing in a list of integer values */
98113939Slinton 	register NODE *p;
98213939Slinton 	p = bcon(v);
98313939Slinton 	incode( p, SZCHAR );
98413939Slinton 	tfree( p );
98513939Slinton 	gotscal();
98613939Slinton 	}
98713939Slinton 
98813939Slinton endinit(){
98913939Slinton 	register TWORD t;
99013939Slinton 	register d, s, n, d1;
99113939Slinton 
99213939Slinton # ifndef BUG1
99313939Slinton 	if( idebug ) printf( "endinit(), inoff = %d\n", inoff );
99413939Slinton # endif
99513939Slinton 
99613939Slinton 	switch( iclass ){
99713939Slinton 
99813939Slinton 	case EXTERN:
99913939Slinton 	case AUTO:
100013939Slinton 	case REGISTER:
100125749Sdonn 	case -1:
100213939Slinton 		return;
100313939Slinton 		}
100413939Slinton 
100513939Slinton 	pstk = instack;
100613939Slinton 
100713939Slinton 	t = pstk->in_t;
100813939Slinton 	d = pstk->in_d;
100913939Slinton 	s = pstk->in_s;
101013939Slinton 	n = pstk->in_n;
101113939Slinton 
101213939Slinton 	if( ISARY(t) ){
101313939Slinton 		d1 = dimtab[d];
101413939Slinton 
101513939Slinton 		vfdalign( pstk->in_sz );  /* fill out part of the last element, if needed */
101613939Slinton 		n = inoff/pstk->in_sz;  /* real number of initializers */
101713939Slinton 		if( d1 >= n ){
101813939Slinton 			/* once again, t is an array, so no fields */
101913939Slinton 			inforce( tsize( t, d, s ) );
102013939Slinton 			n = d1;
102113939Slinton 			}
102213939Slinton 		if( d1!=0 && d1!=n ) uerror( "too many initializers");
102313939Slinton 		if( n==0 ) werror( "empty array declaration");
102413939Slinton 		dimtab[d] = n;
102513942Slinton 		if( d1==0 ) FIXDEF(&stab[pstk->in_id]);
102613939Slinton 		}
102713939Slinton 
102813939Slinton 	else if( t == STRTY || t == UNIONTY ){
102913939Slinton 		/* clearly not fields either */
103013939Slinton 		inforce( tsize( t, d, s ) );
103113939Slinton 		}
103213939Slinton 	else if( n > 1 ) uerror( "bad scalar initialization");
103313939Slinton 	/* this will never be called with a field element... */
103413939Slinton 	else inforce( tsize(t,d,s) );
103513939Slinton 
103613939Slinton 	paramno = 0;
103713939Slinton 	vfdalign( AL_INIT );
103813939Slinton 	inoff = 0;
103913939Slinton 	iclass = SNULL;
104013939Slinton 
104113939Slinton 	}
104213939Slinton 
104332818Sdonn fixinit(){
104432818Sdonn 	/* called from the grammar if we must punt during initialization */
104532818Sdonn 	/* stolen from endinit() */
104632818Sdonn 	pstk = instack;
104732818Sdonn 	paramno = 0;
104832818Sdonn 	vfdalign( AL_INIT );
104932818Sdonn 	inoff = 0;
105032818Sdonn 	iclass = SNULL;
105132818Sdonn 	}
105232818Sdonn 
105313939Slinton doinit( p ) register NODE *p; {
105413939Slinton 
105513939Slinton 	/* take care of generating a value for the initializer p */
105613939Slinton 	/* inoff has the current offset (last bit written)
105713939Slinton 		in the current word being generated */
105813939Slinton 
105913939Slinton 	register sz, d, s;
106013939Slinton 	register TWORD t;
106117746Sralph 	int o;
106213939Slinton 
106313939Slinton 	/* note: size of an individual initializer is assumed to fit into an int */
106413939Slinton 
106532814Sdonn 	if( iclass < 0 ) goto leave;
106613939Slinton 	if( iclass == EXTERN || iclass == UNAME ){
106713939Slinton 		uerror( "cannot initialize extern or union" );
106813939Slinton 		iclass = -1;
106913939Slinton 		goto leave;
107013939Slinton 		}
107113939Slinton 
107213939Slinton 	if( iclass == AUTO || iclass == REGISTER ){
107313939Slinton 		/* do the initialization and get out, without regard
107413939Slinton 		    for filing out the variable with zeros, etc. */
107513939Slinton 		bccode();
107613939Slinton 		idname = pstk->in_id;
107713939Slinton 		p = buildtree( ASSIGN, buildtree( NAME, NIL, NIL ), p );
107813939Slinton 		ecomp(p);
107913939Slinton 		return;
108013939Slinton 		}
108113939Slinton 
108213939Slinton 	if( p == NIL ) return;  /* for throwing away strings that have been turned into lists */
108313939Slinton 
108427247Sdonn 	if( ifull ){
108527247Sdonn 		uerror( "too many initializers" );
108627247Sdonn 		iclass = -1;
108727247Sdonn 		goto leave;
108827247Sdonn 		}
108913939Slinton 	if( ibseen ){
109013939Slinton 		uerror( "} expected");
109113939Slinton 		goto leave;
109213939Slinton 		}
109313939Slinton 
109413939Slinton # ifndef BUG1
109513939Slinton 	if( idebug > 1 ) printf( "doinit(%o)\n", p );
109613939Slinton # endif
109713939Slinton 
109813939Slinton 	t = pstk->in_t;  /* type required */
109913939Slinton 	d = pstk->in_d;
110013939Slinton 	s = pstk->in_s;
110113939Slinton 	if( pstk->in_sz < 0 ){  /* bit field */
110213939Slinton 		sz = -pstk->in_sz;
110313939Slinton 		}
110413939Slinton 	else {
110513939Slinton 		sz = tsize( t, d, s );
110613939Slinton 		}
110713939Slinton 
110813939Slinton 	inforce( pstk->in_off );
110913939Slinton 
111013939Slinton 	p = buildtree( ASSIGN, block( NAME, NIL,NIL, t, d, s ), p );
111113939Slinton 	p->in.left->in.op = FREE;
111213939Slinton 	p->in.left = p->in.right;
111313939Slinton 	p->in.right = NIL;
111413939Slinton 	p->in.left = optim( p->in.left );
111517746Sralph 	o = p->in.left->in.op;
111617746Sralph 	if( o == UNARY AND ){
111717746Sralph 		o = p->in.left->in.op = FREE;
111813939Slinton 		p->in.left = p->in.left->in.left;
111913939Slinton 		}
112013939Slinton 	p->in.op = INIT;
112113939Slinton 
112213939Slinton 	if( sz < SZINT ){ /* special case: bit fields, etc. */
112332815Sdonn 		if( o != ICON || p->in.left->tn.rval != NONAME )
112432815Sdonn 			uerror( "illegal initialization" );
112513939Slinton 		else incode( p->in.left, sz );
112613939Slinton 		}
112717746Sralph 	else if( o == FCON ){
112817746Sralph 		fincode( p->in.left->fpn.fval, sz );
112913939Slinton 		}
113017746Sralph 	else if( o == DCON ){
113117746Sralph 		fincode( p->in.left->dpn.dval, sz );
113217746Sralph 		}
113313939Slinton 	else {
113416178Sralph 		p = optim(p);
113516178Sralph 		if( p->in.left->in.op != ICON ) uerror( "illegal initialization" );
113616178Sralph 		else cinit( p, sz );
113713939Slinton 		}
113813939Slinton 
113913939Slinton 	gotscal();
114013939Slinton 
114113939Slinton 	leave:
114213939Slinton 	tfree(p);
114313939Slinton 	}
114413939Slinton 
114513939Slinton gotscal(){
114613939Slinton 	register t, ix;
114713939Slinton 	register n, id;
114813939Slinton 	struct symtab *p;
114913939Slinton 	OFFSZ temp;
115013939Slinton 
115113939Slinton 	for( ; pstk > instack; ) {
115213939Slinton 
115313939Slinton 		if( pstk->in_fl ) ++ibseen;
115413939Slinton 
115513939Slinton 		--pstk;
115613939Slinton 
115713939Slinton 		t = pstk->in_t;
115813939Slinton 
115913939Slinton 		if( t == STRTY ){
116013939Slinton 			ix = ++pstk->in_x;
116113939Slinton 			if( (id=dimtab[ix]) < 0 ) continue;
116213939Slinton 
116313939Slinton 			/* otherwise, put next element on the stack */
116413939Slinton 
116513939Slinton 			p = &stab[id];
116613939Slinton 			instk( id, p->stype, p->dimoff, p->sizoff, p->offset+pstk->in_off );
116713939Slinton 			return;
116813939Slinton 			}
116913939Slinton 		else if( ISARY(t) ){
117013939Slinton 			n = ++pstk->in_n;
117113939Slinton 			if( n >= dimtab[pstk->in_d] && pstk > instack ) continue;
117213939Slinton 
117313939Slinton 			/* put the new element onto the stack */
117413939Slinton 
117513939Slinton 			temp = pstk->in_sz;
117613939Slinton 			instk( pstk->in_id, (TWORD)DECREF(pstk->in_t), pstk->in_d+1, pstk->in_s,
117713939Slinton 				pstk->in_off+n*temp );
117813939Slinton 			return;
117913939Slinton 			}
118013939Slinton 
118113939Slinton 		}
118227247Sdonn 	ifull = 1;
118313939Slinton 	}
118413939Slinton 
118513939Slinton ilbrace(){ /* process an initializer's left brace */
118613939Slinton 	register t;
118713939Slinton 	struct instk *temp;
118813939Slinton 
118913939Slinton 	temp = pstk;
119013939Slinton 
119113939Slinton 	for( ; pstk > instack; --pstk ){
119213939Slinton 
119313939Slinton 		t = pstk->in_t;
119413939Slinton 		if( t != STRTY && !ISARY(t) ) continue; /* not an aggregate */
119513939Slinton 		if( pstk->in_fl ){ /* already associated with a { */
119613939Slinton 			if( pstk->in_n ) uerror( "illegal {");
119713939Slinton 			continue;
119813939Slinton 			}
119913939Slinton 
120013939Slinton 		/* we have one ... */
120113939Slinton 		pstk->in_fl = 1;
120213939Slinton 		break;
120313939Slinton 		}
120413939Slinton 
120513939Slinton 	/* cannot find one */
120613939Slinton 	/* ignore such right braces */
120713939Slinton 
120813939Slinton 	pstk = temp;
120913939Slinton 	}
121013939Slinton 
121113939Slinton irbrace(){
121213939Slinton 	/* called when a '}' is seen */
121313939Slinton 
121413939Slinton # ifndef BUG1
121513939Slinton 	if( idebug ) printf( "irbrace(): paramno = %d on entry\n", paramno );
121613939Slinton # endif
121713939Slinton 
121813939Slinton 	if( ibseen ) {
121913939Slinton 		--ibseen;
122013939Slinton 		return;
122113939Slinton 		}
122213939Slinton 
122313939Slinton 	for( ; pstk > instack; --pstk ){
122413939Slinton 		if( !pstk->in_fl ) continue;
122513939Slinton 
122613939Slinton 		/* we have one now */
122713939Slinton 
122813939Slinton 		pstk->in_fl = 0;  /* cancel { */
122913939Slinton 		gotscal();  /* take it away... */
123013939Slinton 		return;
123113939Slinton 		}
123213939Slinton 
123313939Slinton 	/* these right braces match ignored left braces: throw out */
123427247Sdonn 	ifull = 1;
123513939Slinton 
123613939Slinton 	}
123713939Slinton 
123813939Slinton upoff( size, alignment, poff ) register alignment, *poff; {
123913939Slinton 	/* update the offset pointed to by poff; return the
124013939Slinton 	/* offset of a value of size `size', alignment `alignment',
124113939Slinton 	/* given that off is increasing */
124213939Slinton 
124313939Slinton 	register off;
124413939Slinton 
124513939Slinton 	off = *poff;
124613939Slinton 	SETOFF( off, alignment );
124713939Slinton 	if( (offsz-off) <  size ){
124813939Slinton 		if( instruct!=INSTRUCT )cerror("too many local variables");
124913939Slinton 		else cerror("Structure too large");
125013939Slinton 		}
125113939Slinton 	*poff = off+size;
125213939Slinton 	return( off );
125313939Slinton 	}
125413939Slinton 
125513939Slinton oalloc( p, poff ) register struct symtab *p; register *poff; {
125613939Slinton 	/* allocate p with offset *poff, and update *poff */
125713939Slinton 	register al, off, tsz;
125813939Slinton 	int noff;
125913939Slinton 
126013939Slinton 	al = talign( p->stype, p->sizoff );
126113939Slinton 	noff = off = *poff;
126213939Slinton 	tsz = tsize( p->stype, p->dimoff, p->sizoff );
126313939Slinton #ifdef BACKAUTO
126413939Slinton 	if( p->sclass == AUTO ){
126513939Slinton 		if( (offsz-off) < tsz ) cerror("too many local variables");
126613939Slinton 		noff = off + tsz;
126713939Slinton 		SETOFF( noff, al );
126813939Slinton 		off = -noff;
126913939Slinton 		}
127013939Slinton 	else
127113939Slinton #endif
127213939Slinton 		if( p->sclass == PARAM && ( tsz < SZINT ) ){
127313939Slinton 			off = upoff( SZINT, ALINT, &noff );
127413939Slinton # ifndef RTOLBYTES
127513939Slinton 			off = noff - tsz;
127613939Slinton #endif
127713939Slinton 			}
127813939Slinton 		else
127913939Slinton 		{
128013939Slinton 		off = upoff( tsz, al, &noff );
128113939Slinton 		}
128213939Slinton 
128313939Slinton 	if( p->sclass != REGISTER ){ /* in case we are allocating stack space for register arguments */
128413939Slinton 		if( p->offset == NOOFFSET ) p->offset = off;
128513939Slinton 		else if( off != p->offset ) return(1);
128613939Slinton 		}
128713939Slinton 
128813939Slinton 	*poff = noff;
128913939Slinton 	return(0);
129013939Slinton 	}
129113939Slinton 
129213939Slinton falloc( p, w, new, pty )  register struct symtab *p; NODE *pty; {
129313939Slinton 	/* allocate a field of width w */
129413939Slinton 	/* new is 0 if new entry, 1 if redefinition, -1 if alignment */
129513939Slinton 
129613939Slinton 	register al,sz,type;
129713939Slinton 
129813939Slinton 	type = (new<0)? pty->in.type : p->stype;
129913939Slinton 
130013939Slinton 	/* this must be fixed to use the current type in alignments */
130113939Slinton 	switch( new<0?pty->in.type:p->stype ){
130213939Slinton 
130313939Slinton 	case ENUMTY:
130413939Slinton 		{
130513939Slinton 			int s;
130613939Slinton 			s = new<0 ? pty->fn.csiz : p->sizoff;
130713939Slinton 			al = dimtab[s+2];
130813939Slinton 			sz = dimtab[s];
130913939Slinton 			break;
131013939Slinton 			}
131113939Slinton 
131213939Slinton 	case CHAR:
131313939Slinton 	case UCHAR:
131413939Slinton 		al = ALCHAR;
131513939Slinton 		sz = SZCHAR;
131613939Slinton 		break;
131713939Slinton 
131813939Slinton 	case SHORT:
131913939Slinton 	case USHORT:
132013939Slinton 		al = ALSHORT;
132113939Slinton 		sz = SZSHORT;
132213939Slinton 		break;
132313939Slinton 
132413939Slinton 	case INT:
132513939Slinton 	case UNSIGNED:
132613939Slinton 		al = ALINT;
132713939Slinton 		sz = SZINT;
132813939Slinton 		break;
132913939Slinton #ifdef LONGFIELDS
133013939Slinton 
133113939Slinton 	case LONG:
133213939Slinton 	case ULONG:
133313939Slinton 		al = ALLONG;
133413939Slinton 		sz = SZLONG;
133513939Slinton 		break;
133613939Slinton #endif
133713939Slinton 
133813939Slinton 	default:
133913939Slinton 		if( new < 0 ) {
134013939Slinton 			uerror( "illegal field type" );
134113939Slinton 			al = ALINT;
134213939Slinton 			}
134313939Slinton 		else {
134413939Slinton 			al = fldal( p->stype );
134513939Slinton 			sz =SZINT;
134613939Slinton 			}
134713939Slinton 		}
134813939Slinton 
134913939Slinton 	if( w > sz ) {
135013939Slinton 		uerror( "field too big");
135113939Slinton 		w = sz;
135213939Slinton 		}
135313939Slinton 
135413939Slinton 	if( w == 0 ){ /* align only */
135513939Slinton 		SETOFF( strucoff, al );
135613939Slinton 		if( new >= 0 ) uerror( "zero size field");
135713939Slinton 		return(0);
135813939Slinton 		}
135913939Slinton 
136013939Slinton 	if( strucoff%al + w > sz ) SETOFF( strucoff, al );
136113939Slinton 	if( new < 0 ) {
136213939Slinton 		if( (offsz-strucoff) < w )
136313939Slinton 			cerror("structure too large");
136413939Slinton 		strucoff += w;  /* we know it will fit */
136513939Slinton 		return(0);
136613939Slinton 		}
136713939Slinton 
136813939Slinton 	/* establish the field */
136913939Slinton 
137013939Slinton 	if( new == 1 ) { /* previous definition */
137113939Slinton 		if( p->offset != strucoff || p->sclass != (FIELD|w) ) return(1);
137213939Slinton 		}
137313939Slinton 	p->offset = strucoff;
137413939Slinton 	if( (offsz-strucoff) < w ) cerror("structure too large");
137513939Slinton 	strucoff += w;
137613939Slinton 	p->stype = type;
137713939Slinton 	fldty( p );
137813939Slinton 	return(0);
137913939Slinton 	}
138013939Slinton 
138113939Slinton nidcl( p ) NODE *p; { /* handle unitialized declarations */
138213939Slinton 	/* assumed to be not functions */
138313939Slinton 	register class;
138413939Slinton 	register commflag;  /* flag for labelled common declarations */
138513939Slinton 
138613939Slinton 	commflag = 0;
138713939Slinton 
138813939Slinton 	/* compute class */
138913939Slinton 	if( (class=curclass) == SNULL ){
139013939Slinton 		if( blevel > 1 ) class = AUTO;
139113939Slinton 		else if( blevel != 0 || instruct ) cerror( "nidcl error" );
139213939Slinton 		else { /* blevel = 0 */
139313939Slinton 			class = noinit();
139413939Slinton 			if( class == EXTERN ) commflag = 1;
139513939Slinton 			}
139613939Slinton 		}
139713939Slinton #ifdef LCOMM
139832817Sdonn 	/* hack so stab will come out as LCSYM rather than STSYM */
139913939Slinton 	if (class == STATIC) {
140013939Slinton 		extern int stabLCSYM;
140113939Slinton 		stabLCSYM = 1;
140213939Slinton 	}
140313939Slinton #endif
140413939Slinton 
140513939Slinton 	defid( p, class );
140613939Slinton 
140732816Sdonn 	/* if an array is not initialized, no empty dimension */
140832820Sdonn 	if( class!=EXTERN && class!=TYPEDEF &&
140932820Sdonn 	    ISARY(p->in.type) && dimtab[p->fn.cdim]==0 )
141032816Sdonn 		uerror("null storage definition");
141132816Sdonn 
141213939Slinton #ifndef LCOMM
141324405Smckusick 	if( class==EXTDEF || class==STATIC )
141413939Slinton #else
141513939Slinton 	if (class==STATIC) {
141613939Slinton 		register struct symtab *s = &stab[p->tn.rval];
141713939Slinton 		extern int stabLCSYM;
141813939Slinton 		int sz = tsize(s->stype, s->dimoff, s->sizoff)/SZCHAR;
141913939Slinton 
142013939Slinton 		stabLCSYM = 0;
142113939Slinton 		if (sz % sizeof (int))
142213939Slinton 			sz += sizeof (int) - (sz % sizeof (int));
142313939Slinton 		if (s->slevel > 1)
142413939Slinton 			printf("	.lcomm	L%d,%d\n", s->offset, sz);
142513939Slinton 		else
142613939Slinton 			printf("	.lcomm	%s,%d\n", exname(s->sname), sz);
142724405Smckusick 	}else if (class == EXTDEF)
142813939Slinton #endif
142924405Smckusick 		{
143013939Slinton 		/* simulate initialization by 0 */
143113939Slinton 		beginit(p->tn.rval);
143213939Slinton 		endinit();
143313939Slinton 		}
143413939Slinton 	if( commflag ) commdec( p->tn.rval );
143513939Slinton 	}
143613939Slinton 
143713939Slinton TWORD
143813939Slinton types( t1, t2, t3 ) TWORD t1, t2, t3; {
143913939Slinton 	/* return a basic type from basic types t1, t2, and t3 */
144013939Slinton 
144113939Slinton 	TWORD t[3], noun, adj, unsg;
144213939Slinton 	register i;
144313939Slinton 
144413939Slinton 	t[0] = t1;
144513939Slinton 	t[1] = t2;
144613939Slinton 	t[2] = t3;
144713939Slinton 
144813939Slinton 	unsg = INT;  /* INT or UNSIGNED */
144913939Slinton 	noun = UNDEF;  /* INT, CHAR, or FLOAT */
145013939Slinton 	adj = INT;  /* INT, LONG, or SHORT */
145113939Slinton 
145213939Slinton 	for( i=0; i<3; ++i ){
145313939Slinton 		switch( t[i] ){
145413939Slinton 
145513939Slinton 		default:
145613939Slinton 		bad:
145713939Slinton 			uerror( "illegal type combination" );
145813939Slinton 			return( INT );
145913939Slinton 
146013939Slinton 		case UNDEF:
146113939Slinton 			continue;
146213939Slinton 
146313939Slinton 		case UNSIGNED:
146413939Slinton 			if( unsg != INT ) goto bad;
146513939Slinton 			unsg = UNSIGNED;
146613939Slinton 			continue;
146713939Slinton 
146813939Slinton 		case LONG:
146913939Slinton 		case SHORT:
147013939Slinton 			if( adj != INT ) goto bad;
147113939Slinton 			adj = t[i];
147213939Slinton 			continue;
147313939Slinton 
147413939Slinton 		case INT:
147513939Slinton 		case CHAR:
147613939Slinton 		case FLOAT:
147713939Slinton 			if( noun != UNDEF ) goto bad;
147813939Slinton 			noun = t[i];
147913939Slinton 			continue;
148013939Slinton 			}
148113939Slinton 		}
148213939Slinton 
148313939Slinton 	/* now, construct final type */
148413939Slinton 	if( noun == UNDEF ) noun = INT;
148513939Slinton 	else if( noun == FLOAT ){
148613939Slinton 		if( unsg != INT || adj == SHORT ) goto bad;
148713939Slinton 		return( adj==LONG ? DOUBLE : FLOAT );
148813939Slinton 		}
148913939Slinton 	else if( noun == CHAR && adj != INT ) goto bad;
149013939Slinton 
149113939Slinton 	/* now, noun is INT or CHAR */
149213939Slinton 	if( adj != INT ) noun = adj;
149313939Slinton 	if( unsg == UNSIGNED ) return( noun + (UNSIGNED-INT) );
149413939Slinton 	else return( noun );
149513939Slinton 	}
149613939Slinton 
149713939Slinton NODE *
149813939Slinton tymerge( typ, idp ) NODE *typ, *idp; {
149913939Slinton 	/* merge type typ with identifier idp  */
150013939Slinton 
150113939Slinton 	register unsigned t;
150213939Slinton 	register i;
150313939Slinton 	extern int eprint();
150413939Slinton 
150513939Slinton 	if( typ->in.op != TYPE ) cerror( "tymerge: arg 1" );
150613939Slinton 	if(idp == NIL ) return( NIL );
150713939Slinton 
150813939Slinton # ifndef BUG1
150913939Slinton 	if( ddebug > 2 ) fwalk( idp, eprint, 0 );
151013939Slinton # endif
151113939Slinton 
151213939Slinton 	idp->in.type = typ->in.type;
151313939Slinton 	idp->fn.cdim = curdim;
151413939Slinton 	tyreduce( idp );
151513939Slinton 	idp->fn.csiz = typ->fn.csiz;
151613939Slinton 
151713939Slinton 	for( t=typ->in.type, i=typ->fn.cdim; t&TMASK; t = DECREF(t) ){
151813939Slinton 		if( ISARY(t) ) dstash( dimtab[i++] );
151913939Slinton 		}
152013939Slinton 
152113939Slinton 	/* now idp is a single node: fix up type */
152213939Slinton 
152313939Slinton 	idp->in.type = ctype( idp->in.type );
152413939Slinton 
152513939Slinton 	if( (t = BTYPE(idp->in.type)) != STRTY && t != UNIONTY && t != ENUMTY ){
152613939Slinton 		idp->fn.csiz = t;  /* in case ctype has rewritten things */
152713939Slinton 		}
152813939Slinton 
152913939Slinton 	return( idp );
153013939Slinton 	}
153113939Slinton 
153213939Slinton tyreduce( p ) register NODE *p; {
153313939Slinton 
153413939Slinton 	/* build a type, and stash away dimensions, from a parse tree of the declaration */
153513939Slinton 	/* the type is build top down, the dimensions bottom up */
153613939Slinton 	register o, temp;
153713939Slinton 	register unsigned t;
153813939Slinton 
153913939Slinton 	o = p->in.op;
154013939Slinton 	p->in.op = FREE;
154113939Slinton 
154213939Slinton 	if( o == NAME ) return;
154313939Slinton 
154413939Slinton 	t = INCREF( p->in.type );
154513939Slinton 	if( o == UNARY CALL ) t += (FTN-PTR);
154613939Slinton 	else if( o == LB ){
154713939Slinton 		t += (ARY-PTR);
154813939Slinton 		temp = p->in.right->tn.lval;
154913939Slinton 		p->in.right->in.op = FREE;
155032816Sdonn 		if( temp == 0 && p->in.left->tn.op == LB )
155132816Sdonn 			uerror( "null dimension" );
155213939Slinton 		}
155313939Slinton 
155413939Slinton 	p->in.left->in.type = t;
155513939Slinton 	tyreduce( p->in.left );
155613939Slinton 
155713939Slinton 	if( o == LB ) dstash( temp );
155813939Slinton 
155913939Slinton 	p->tn.rval = p->in.left->tn.rval;
156013939Slinton 	p->in.type = p->in.left->in.type;
156113939Slinton 
156213939Slinton 	}
156313939Slinton 
156413939Slinton fixtype( p, class ) register NODE *p; {
156513939Slinton 	register unsigned t, type;
156613939Slinton 	register mod1, mod2;
156713939Slinton 	/* fix up the types, and check for legality */
156813939Slinton 
156913939Slinton 	if( (type = p->in.type) == UNDEF ) return;
157013939Slinton 	if( mod2 = (type&TMASK) ){
157113939Slinton 		t = DECREF(type);
157213939Slinton 		while( mod1=mod2, mod2 = (t&TMASK) ){
157313939Slinton 			if( mod1 == ARY && mod2 == FTN ){
157413939Slinton 				uerror( "array of functions is illegal" );
157513939Slinton 				type = 0;
157613939Slinton 				}
157713939Slinton 			else if( mod1 == FTN && ( mod2 == ARY || mod2 == FTN ) ){
157813939Slinton 				uerror( "function returns illegal type" );
157913939Slinton 				type = 0;
158013939Slinton 				}
158113939Slinton 			t = DECREF(t);
158213939Slinton 			}
158313939Slinton 		}
158413939Slinton 
158513939Slinton 	/* detect function arguments, watching out for structure declarations */
158632816Sdonn 	/* for example, beware of f(x) struct { int a[10]; } *x; { ... } */
158713939Slinton 	/* the danger is that "a" will be converted to a pointer */
158813939Slinton 
158932816Sdonn 	if( class==SNULL && blevel==1 && !(instruct&(INSTRUCT|INUNION)) )
159032816Sdonn 		class = PARAM;
159113939Slinton 	if( class == PARAM || ( class==REGISTER && blevel==1 ) ){
159213939Slinton 		if( type == FLOAT ) type = DOUBLE;
159313939Slinton 		else if( ISARY(type) ){
159432816Sdonn #ifdef LINT
159532816Sdonn 			if( hflag && dimtab[p->fn.cdim]!=0 )
159632816Sdonn 				werror("array[%d] type changed to pointer",
159732816Sdonn 					dimtab[p->fn.cdim]);
159832816Sdonn #endif
159913939Slinton 			++p->fn.cdim;
160013939Slinton 			type += (PTR-ARY);
160113939Slinton 			}
160213939Slinton 		else if( ISFTN(type) ){
160313939Slinton 			werror( "a function is declared as an argument" );
160413939Slinton 			type = INCREF(type);
160513939Slinton 			}
160613939Slinton 
160713939Slinton 		}
160813939Slinton 
160913939Slinton 	if( instruct && ISFTN(type) ){
161013939Slinton 		uerror( "function illegal in structure or union" );
161113939Slinton 		type = INCREF(type);
161213939Slinton 		}
161313939Slinton 	p->in.type = type;
161413939Slinton 	}
161513939Slinton 
161613939Slinton uclass( class ) register class; {
161713939Slinton 	/* give undefined version of class */
161813939Slinton 	if( class == SNULL ) return( EXTERN );
161913939Slinton 	else if( class == STATIC ) return( USTATIC );
162013939Slinton 	else if( class == FORTRAN ) return( UFORTRAN );
162113939Slinton 	else return( class );
162213939Slinton 	}
162313939Slinton 
162413939Slinton fixclass( class, type ) TWORD type; {
162513939Slinton 
162613939Slinton 	/* first, fix null class */
162713939Slinton 
162813939Slinton 	if( class == SNULL ){
162913939Slinton 		if( instruct&INSTRUCT ) class = MOS;
163013939Slinton 		else if( instruct&INUNION ) class = MOU;
163113939Slinton 		else if( blevel == 0 ) class = EXTDEF;
163213939Slinton 		else if( blevel == 1 ) class = PARAM;
163313939Slinton 		else class = AUTO;
163413939Slinton 
163513939Slinton 		}
163613939Slinton 
163713939Slinton 	/* now, do general checking */
163813939Slinton 
163913939Slinton 	if( ISFTN( type ) ){
164013939Slinton 		switch( class ) {
164113939Slinton 		default:
164213939Slinton 			uerror( "function has illegal storage class" );
164313939Slinton 		case AUTO:
164413939Slinton 			class = EXTERN;
164513939Slinton 		case EXTERN:
164613939Slinton 		case EXTDEF:
164713939Slinton 		case FORTRAN:
164813939Slinton 		case TYPEDEF:
164913939Slinton 		case STATIC:
165013939Slinton 		case UFORTRAN:
165113939Slinton 		case USTATIC:
165213939Slinton 			;
165313939Slinton 			}
165413939Slinton 		}
165513939Slinton 
165613939Slinton 	if( class&FIELD ){
165713939Slinton 		if( !(instruct&INSTRUCT) ) uerror( "illegal use of field" );
165813939Slinton 		return( class );
165913939Slinton 		}
166013939Slinton 
166113939Slinton 	switch( class ){
166213939Slinton 
166313939Slinton 	case MOU:
166413939Slinton 		if( !(instruct&INUNION) ) uerror( "illegal class" );
166513939Slinton 		return( class );
166613939Slinton 
166713939Slinton 	case MOS:
166813939Slinton 		if( !(instruct&INSTRUCT) ) uerror( "illegal class" );
166913939Slinton 		return( class );
167013939Slinton 
167113939Slinton 	case MOE:
167213939Slinton 		if( instruct & (INSTRUCT|INUNION) ) uerror( "illegal class" );
167313939Slinton 		return( class );
167413939Slinton 
167513939Slinton 	case REGISTER:
167613939Slinton 		if( blevel == 0 ) uerror( "illegal register declaration" );
167713939Slinton 		else if( regvar >= MINRVAR && cisreg( type ) ) return( class );
167813939Slinton 		if( blevel == 1 ) return( PARAM );
167913939Slinton 		else return( AUTO );
168013939Slinton 
168113939Slinton 	case AUTO:
168213939Slinton 	case LABEL:
168313939Slinton 	case ULABEL:
168413939Slinton 		if( blevel < 2 ) uerror( "illegal class" );
168513939Slinton 		return( class );
168613939Slinton 
168713939Slinton 	case PARAM:
168813939Slinton 		if( blevel != 1 ) uerror( "illegal class" );
168913939Slinton 		return( class );
169013939Slinton 
169113939Slinton 	case UFORTRAN:
169213939Slinton 	case FORTRAN:
169313939Slinton # ifdef NOFORTRAN
169413939Slinton 			NOFORTRAN;    /* a condition which can regulate the FORTRAN usage */
169513939Slinton # endif
169613939Slinton 		if( !ISFTN(type) ) uerror( "fortran declaration must apply to function" );
169713939Slinton 		else {
169813939Slinton 			type = DECREF(type);
169913939Slinton 			if( ISFTN(type) || ISARY(type) || ISPTR(type) ) {
170013939Slinton 				uerror( "fortran function has wrong type" );
170113939Slinton 				}
170213939Slinton 			}
170313939Slinton 	case EXTERN:
170413939Slinton 	case STATIC:
170513939Slinton 	case EXTDEF:
170613939Slinton 	case TYPEDEF:
170713939Slinton 	case USTATIC:
170817151Sralph 		if( blevel == 1 ){
170917151Sralph 			uerror( "illegal class" );
171017151Sralph 			return( PARAM );
171117151Sralph 			}
171217151Sralph 	case STNAME:
171317151Sralph 	case UNAME:
171417151Sralph 	case ENAME:
171513939Slinton 		return( class );
171613939Slinton 
171713939Slinton 	default:
171813939Slinton 		cerror( "illegal class: %d", class );
171913939Slinton 		/* NOTREACHED */
172013939Slinton 
172113939Slinton 		}
172213939Slinton 	}
172313939Slinton 
172413939Slinton struct symtab *
172513939Slinton mknonuniq(idindex) int *idindex; {/* locate a symbol table entry for */
172613939Slinton 	/* an occurrence of a nonunique structure member name */
172713939Slinton 	/* or field */
172813939Slinton 	register i;
172913939Slinton 	register struct symtab * sp;
173032817Sdonn 	char *q;
173113939Slinton 
173213939Slinton 	sp = & stab[ i= *idindex ]; /* position search at old entry */
173313939Slinton 	while( sp->stype != TNULL ){ /* locate unused entry */
173413939Slinton 		if( ++i >= SYMTSZ ){/* wrap around symbol table */
173513939Slinton 			i = 0;
173613939Slinton 			sp = stab;
173713939Slinton 			}
173813939Slinton 		else ++sp;
173913939Slinton 		if( i == *idindex ) cerror("Symbol table full");
174013939Slinton 		}
174113939Slinton 	sp->sflags = SNONUNIQ | SMOS;
174213939Slinton 	q = stab[*idindex].sname; /* old entry name */
174313939Slinton #ifdef FLEXNAMES
174413939Slinton 	sp->sname = stab[*idindex].sname;
174513939Slinton #endif
174613939Slinton # ifndef BUG1
174713939Slinton 	if( ddebug ){
174813939Slinton 		printf("\tnonunique entry for %s from %d to %d\n",
174913939Slinton 			q, *idindex, i );
175013939Slinton 		}
175113939Slinton # endif
175213939Slinton 	*idindex = i;
175313939Slinton #ifndef FLEXNAMES
175432817Sdonn 	{
175532817Sdonn 		char *p = sp->sname;
175632817Sdonn 		for( i=1; i<=NCHNAM; ++i ) /* copy name */
175732817Sdonn 			if( *p++ = *q /* assign */ ) ++q;
175813939Slinton 		}
175913939Slinton #endif
176013939Slinton 	return ( sp );
176113939Slinton 	}
176213939Slinton 
176313939Slinton lookup( name, s) char *name; {
176413939Slinton 	/* look up name: must agree with s w.r.t. STAG, SMOS and SHIDDEN */
176513939Slinton 
176613939Slinton 	register char *p, *q;
176732817Sdonn 	int i, ii;
176832817Sdonn #ifndef FLEXNAMES
176932817Sdonn 	int j;
177032817Sdonn #endif
177113939Slinton 	register struct symtab *sp;
177213939Slinton 
177313939Slinton 	/* compute initial hash index */
177413939Slinton # ifndef BUG1
177513939Slinton 	if( ddebug > 2 ){
177613939Slinton 		printf( "lookup( %s, %d ), stwart=%d, instruct=%d\n", name, s, stwart, instruct );
177713939Slinton 		}
177813939Slinton # endif
177913939Slinton 
178013939Slinton 	i = 0;
178113939Slinton #ifndef FLEXNAMES
178213939Slinton 	for( p=name, j=0; *p != '\0'; ++p ){
178313939Slinton 		i += *p;
178413939Slinton 		if( ++j >= NCHNAM ) break;
178513939Slinton 		}
178613939Slinton #else
178713939Slinton 	i = (int)name;
178813939Slinton #endif
178913939Slinton 	i = i%SYMTSZ;
179013939Slinton 	sp = &stab[ii=i];
179113939Slinton 
179213939Slinton 	for(;;){ /* look for name */
179313939Slinton 
179413939Slinton 		if( sp->stype == TNULL ){ /* empty slot */
179513939Slinton 			sp->sflags = s;  /* set STAG, SMOS if needed, turn off all others */
179613939Slinton #ifndef FLEXNAMES
179713939Slinton 			p = sp->sname;
179813939Slinton 			for( j=0; j<NCHNAM; ++j ) if( *p++ = *name ) ++name;
179913939Slinton #else
180013939Slinton 			sp->sname = name;
180113939Slinton #endif
180213939Slinton 			sp->stype = UNDEF;
180313939Slinton 			sp->sclass = SNULL;
180413939Slinton 			return( i );
180513939Slinton 			}
180613939Slinton 		if( (sp->sflags & (STAG|SMOS|SHIDDEN)) != s ) goto next;
180713939Slinton 		p = sp->sname;
180813939Slinton 		q = name;
180913939Slinton #ifndef FLEXNAMES
181013939Slinton 		for( j=0; j<NCHNAM;++j ){
181113939Slinton 			if( *p++ != *q ) goto next;
181213939Slinton 			if( !*q++ ) break;
181313939Slinton 			}
181413939Slinton 		return( i );
181513939Slinton #else
181613939Slinton 		if (p == q)
181713939Slinton 			return ( i );
181813939Slinton #endif
181913939Slinton 	next:
182013939Slinton 		if( ++i >= SYMTSZ ){
182113939Slinton 			i = 0;
182213939Slinton 			sp = stab;
182313939Slinton 			}
182413939Slinton 		else ++sp;
182513939Slinton 		if( i == ii ) cerror( "symbol table full" );
182613939Slinton 		}
182713939Slinton 	}
182813939Slinton 
182913939Slinton #ifndef checkst
183013939Slinton /* if not debugging, make checkst a macro */
183113939Slinton checkst(lev){
183213939Slinton 	register int s, i, j;
183313939Slinton 	register struct symtab *p, *q;
183413939Slinton 
183513939Slinton 	for( i=0, p=stab; i<SYMTSZ; ++i, ++p ){
183613939Slinton 		if( p->stype == TNULL ) continue;
183713939Slinton 		j = lookup( p->sname, p->sflags&(SMOS|STAG) );
183813939Slinton 		if( j != i ){
183913939Slinton 			q = &stab[j];
184013939Slinton 			if( q->stype == UNDEF ||
184113939Slinton 			    q->slevel <= p->slevel ){
184213939Slinton #ifndef FLEXNAMES
184313939Slinton 				cerror( "check error: %.8s", q->sname );
184413939Slinton #else
184513939Slinton 				cerror( "check error: %s", q->sname );
184613939Slinton #endif
184713939Slinton 				}
184813939Slinton 			}
184913939Slinton #ifndef FLEXNAMES
185013939Slinton 		else if( p->slevel > lev ) cerror( "%.8s check at level %d", p->sname, lev );
185113939Slinton #else
185213939Slinton 		else if( p->slevel > lev ) cerror( "%s check at level %d", p->sname, lev );
185313939Slinton #endif
185413939Slinton 		}
185513939Slinton 	}
185613939Slinton #endif
185713939Slinton 
185813939Slinton struct symtab *
185913939Slinton relook(p) register struct symtab *p; {  /* look up p again, and see where it lies */
186013939Slinton 
186113939Slinton 	register struct symtab *q;
186213939Slinton 
186313939Slinton 	/* I'm not sure that this handles towers of several hidden definitions in all cases */
186413939Slinton 	q = &stab[lookup( p->sname, p->sflags&(STAG|SMOS|SHIDDEN) )];
186513939Slinton 	/* make relook always point to either p or an empty cell */
186613939Slinton 	if( q->stype == UNDEF ){
186713939Slinton 		q->stype = TNULL;
186813939Slinton 		return(q);
186913939Slinton 		}
187013939Slinton 	while( q != p ){
187113939Slinton 		if( q->stype == TNULL ) break;
187213939Slinton 		if( ++q >= &stab[SYMTSZ] ) q=stab;
187313939Slinton 		}
187413939Slinton 	return(q);
187513939Slinton 	}
187613939Slinton 
187724405Smckusick clearst( lev ) register int lev; {
187824405Smckusick 	register struct symtab *p, *q;
187924405Smckusick 	register int temp;
188024405Smckusick 	struct symtab *clist = 0;
188113939Slinton 
188213939Slinton 	temp = lineno;
188313939Slinton 	aobeg();
188413939Slinton 
188524405Smckusick 	/* step 1: remove entries */
188624405Smckusick 	while( chaintop-1 > lev ){
188724405Smckusick 		p = schain[--chaintop];
188824405Smckusick 		schain[chaintop] = 0;
188924405Smckusick 		for( ; p; p = q ){
189024405Smckusick 			q = p->snext;
189124405Smckusick 			if( p->stype == TNULL || p->slevel <= lev )
189224405Smckusick 				cerror( "schain botch" );
189324405Smckusick 			lineno = p->suse < 0 ? -p->suse : p->suse;
189424405Smckusick 			if( p->stype==UNDEF || ( p->sclass==ULABEL && lev<2 ) ){
189513939Slinton 				lineno = temp;
189613939Slinton #ifndef FLEXNAMES
189713939Slinton 				uerror( "%.8s undefined", p->sname );
189813939Slinton #else
189913939Slinton 				uerror( "%s undefined", p->sname );
190013939Slinton #endif
190113939Slinton 				}
190213939Slinton 			else aocode(p);
190313939Slinton # ifndef BUG1
190424405Smckusick 			if( ddebug ){
190513939Slinton #ifndef FLEXNAMES
190624405Smckusick 				printf( "removing %.8s", p->sname );
190713939Slinton #else
190824405Smckusick 				printf( "removing %s", p->sname );
190913939Slinton #endif
191024405Smckusick 				printf( " from stab[%d], flags %o level %d\n",
191124405Smckusick 					p-stab, p->sflags, p->slevel);
191224405Smckusick 				}
191313939Slinton # endif
191424405Smckusick 			if( p->sflags & SHIDES )unhide( p );
191513939Slinton 			p->stype = TNULL;
191624405Smckusick 			p->snext = clist;
191724405Smckusick 			clist = p;
191813939Slinton 			}
191924405Smckusick 		}
192024405Smckusick 
192124405Smckusick 	/* step 2: fix any mishashed entries */
192224405Smckusick 	p = clist;
192324405Smckusick 	while( p ){
1924*32823Sdonn 		register struct symtab *r, *next, *t;
192524405Smckusick 
192624405Smckusick 		q = p;
192727247Sdonn 		next = p->snext;
192824405Smckusick 		for(;;){
192924405Smckusick 			if( ++q >= &stab[SYMTSZ] )q = stab;
193024405Smckusick 			if( q == p || q->stype == TNULL )break;
193124405Smckusick 			if( (r = relook(q)) != q ) {
193232822Sdonn 				/* move q in schain list */
1933*32823Sdonn 				if( !(t = schain[q->slevel]) )
1934*32823Sdonn 					cerror("schain botch 2");
1935*32823Sdonn 				if( t == q )
1936*32823Sdonn 					schain[q->slevel] = r;
1937*32823Sdonn 				else {
1938*32823Sdonn 					while( t->snext && t->snext != q )
1939*32823Sdonn 						t = t->snext;
1940*32823Sdonn 					if( !t->snext )
1941*32823Sdonn 						cerror("schain botch 3");
1942*32823Sdonn 					t->snext = r;
1943*32823Sdonn 					}
194432822Sdonn 				/* are we guaranteed r isn't in clist too? */
194524405Smckusick 				*r = *q;
194626822Sdonn 				q->stype = TNULL;
194713939Slinton 				}
194813939Slinton 			}
194927247Sdonn 		p = next;
195013939Slinton 		}
195124405Smckusick 
195213939Slinton 	lineno = temp;
195313939Slinton 	aoend();
195413939Slinton 	}
195513939Slinton 
195613939Slinton hide( p ) register struct symtab *p; {
195713939Slinton 	register struct symtab *q;
195813939Slinton 	for( q=p+1; ; ++q ){
195913939Slinton 		if( q >= &stab[SYMTSZ] ) q = stab;
196013939Slinton 		if( q == p ) cerror( "symbol table full" );
196113939Slinton 		if( q->stype == TNULL ) break;
196213939Slinton 		}
196324405Smckusick 	*q = *p;
196413939Slinton 	p->sflags |= SHIDDEN;
196513939Slinton 	q->sflags = (p->sflags&(SMOS|STAG)) | SHIDES;
196613939Slinton #ifndef FLEXNAMES
196713939Slinton 	if( hflag ) werror( "%.8s redefinition hides earlier one", p->sname );
196813939Slinton #else
196913939Slinton 	if( hflag ) werror( "%s redefinition hides earlier one", p->sname );
197013939Slinton #endif
197113939Slinton # ifndef BUG1
197213939Slinton 	if( ddebug ) printf( "	%d hidden in %d\n", p-stab, q-stab );
197313939Slinton # endif
197413939Slinton 	return( idname = q-stab );
197513939Slinton 	}
197613939Slinton 
197713939Slinton unhide( p ) register struct symtab *p; {
197813939Slinton 	register struct symtab *q;
197932817Sdonn 	register s;
198013939Slinton 
198113939Slinton 	s = p->sflags & (SMOS|STAG);
198213939Slinton 	q = p;
198313939Slinton 
198413939Slinton 	for(;;){
198513939Slinton 
198613939Slinton 		if( q == stab ) q = &stab[SYMTSZ-1];
198713939Slinton 		else --q;
198813939Slinton 
198913939Slinton 		if( q == p ) break;
199013939Slinton 
199113939Slinton 		if( (q->sflags&(SMOS|STAG)) == s ){
199213939Slinton #ifndef FLEXNAMES
199332817Sdonn 			register j;
199413939Slinton 			for( j =0; j<NCHNAM; ++j ) if( p->sname[j] != q->sname[j] ) break;
199513939Slinton 			if( j == NCHNAM ){ /* found the name */
199613939Slinton #else
199713939Slinton 			if (p->sname == q->sname) {
199813939Slinton #endif
199913939Slinton 				q->sflags &= ~SHIDDEN;
200013939Slinton # ifndef BUG1
200113939Slinton 				if( ddebug ) printf( "unhide uncovered %d from %d\n", q-stab,p-stab);
200213939Slinton # endif
200313939Slinton 				return;
200413939Slinton 				}
200513939Slinton 			}
200613939Slinton 
200713939Slinton 		}
200813939Slinton 	cerror( "unhide fails" );
200913939Slinton 	}
2010