xref: /original-bsd/old/pcc/mip/pftn.c (revision 54dff0c1)
1442524f6Sralph #ifndef lint
2*54dff0c1Sbostic static char *sccsid ="@(#)pftn.c	1.29 (Berkeley) 06/18/90";
3442524f6Sralph #endif lint
4442524f6Sralph 
5ed50c01bSralph # include "pass1.h"
695513c10Slinton 
795513c10Slinton unsigned int offsz;
895513c10Slinton 
92f906f46Smckusick struct symtab *schain[MAXSCOPES];	/* sym chains for clearst */
102f906f46Smckusick int chaintop;				/* highest active entry */
112f906f46Smckusick 
1295513c10Slinton struct instk {
1395513c10Slinton 	int in_sz;   /* size of array element */
1495513c10Slinton 	int in_x;    /* current index for structure member in structure initializations */
1595513c10Slinton 	int in_n;    /* number of initializations seen */
1695513c10Slinton 	int in_s;    /* sizoff */
1795513c10Slinton 	int in_d;    /* dimoff */
1895513c10Slinton 	TWORD in_t;    /* type */
1995513c10Slinton 	int in_id;   /* stab index */
2095513c10Slinton 	int in_fl;   /* flag which says if this level is controlled by {} */
2195513c10Slinton 	OFFSZ in_off;  /* offset of the beginning of this level */
2295513c10Slinton 	}
2395513c10Slinton instack[10],
2495513c10Slinton *pstk;
2595513c10Slinton 
2695513c10Slinton 	/* defines used for getting things off of the initialization stack */
2795513c10Slinton 
2895513c10Slinton 
2995513c10Slinton struct symtab *relook();
3095513c10Slinton 
3195513c10Slinton 
3295513c10Slinton int ddebug = 0;
3395513c10Slinton 
3495513c10Slinton struct symtab * mknonuniq();
3595513c10Slinton 
defid(q,class)362f906f46Smckusick defid( q, class ) register NODE *q; register int class; {
3795513c10Slinton 	register struct symtab *p;
3895513c10Slinton 	int idp;
392f906f46Smckusick 	register TWORD type;
4095513c10Slinton 	TWORD stp;
412f906f46Smckusick 	register int scl;
4295513c10Slinton 	int dsym, ddef;
4395513c10Slinton 	int slev, temp;
4476f37e67Slinton 	int changed;
4595513c10Slinton 
4695513c10Slinton 	if( q == NIL ) return;  /* an error was detected */
4795513c10Slinton 
4895513c10Slinton 	if( q < node || q >= &node[TREESZ] ) cerror( "defid call" );
4995513c10Slinton 
5095513c10Slinton 	idp = q->tn.rval;
5195513c10Slinton 
5295513c10Slinton 	if( idp < 0 ) cerror( "tyreduce" );
5395513c10Slinton 	p = &stab[idp];
5495513c10Slinton 
5595513c10Slinton # ifndef BUG1
5695513c10Slinton 	if( ddebug ){
5795513c10Slinton #ifndef FLEXNAMES
5895513c10Slinton 		printf( "defid( %.8s (%d), ", p->sname, idp );
5995513c10Slinton #else
6095513c10Slinton 		printf( "defid( %s (%d), ", p->sname, idp );
6195513c10Slinton #endif
6295513c10Slinton 		tprint( q->in.type );
6395513c10Slinton 		printf( ", %s, (%d,%d) ), level %d\n", scnames(class), q->fn.cdim, q->fn.csiz, blevel );
6495513c10Slinton 		}
6595513c10Slinton # endif
6695513c10Slinton 
6795513c10Slinton 	fixtype( q, class );
6895513c10Slinton 
6995513c10Slinton 	type = q->in.type;
7095513c10Slinton 	class = fixclass( class, type );
7195513c10Slinton 
7295513c10Slinton 	stp = p->stype;
7395513c10Slinton 	slev = p->slevel;
7495513c10Slinton 
7595513c10Slinton # ifndef BUG1
7695513c10Slinton 	if( ddebug ){
7795513c10Slinton 		printf( "	modified to " );
7895513c10Slinton 		tprint( type );
7995513c10Slinton 		printf( ", %s\n", scnames(class) );
8095513c10Slinton 		printf( "	previous def'n: " );
8195513c10Slinton 		tprint( stp );
8295513c10Slinton 		printf( ", %s, (%d,%d) ), level %d\n", scnames(p->sclass), p->dimoff, p->sizoff, slev );
8395513c10Slinton 		}
8495513c10Slinton # endif
8595513c10Slinton 
8695513c10Slinton 	if( stp == FTN && p->sclass == SNULL )goto enter;
8795513c10Slinton 	if( blevel==1 && stp!=FARG ) switch( class ){
8895513c10Slinton 
8995513c10Slinton 		default:
9095513c10Slinton #ifndef FLEXNAMES
9195513c10Slinton 			if(!(class&FIELD)) uerror( "declared argument %.8s is missing", p->sname );
9295513c10Slinton #else
9395513c10Slinton 			if(!(class&FIELD)) uerror( "declared argument %s is missing", p->sname );
9495513c10Slinton #endif
9595513c10Slinton 		case MOS:
9695513c10Slinton 		case STNAME:
9795513c10Slinton 		case MOU:
9895513c10Slinton 		case UNAME:
9995513c10Slinton 		case MOE:
10095513c10Slinton 		case ENAME:
10195513c10Slinton 		case TYPEDEF:
10295513c10Slinton 			;
10395513c10Slinton 			}
1045a6549aeSdonn 	if( stp == UNDEF|| stp == FARG ) goto enter;
10595513c10Slinton 
10695513c10Slinton 	if( type != stp ) goto mismatch;
1073acd5f49Sdonn 	if( blevel > slev && (class == AUTO || class == REGISTER) )
1083acd5f49Sdonn 		/* new scope */
1093acd5f49Sdonn 		goto mismatch;
1103acd5f49Sdonn 
11195513c10Slinton 	/* test (and possibly adjust) dimensions */
11295513c10Slinton 	dsym = p->dimoff;
11395513c10Slinton 	ddef = q->fn.cdim;
11476f37e67Slinton 	changed = 0;
11595513c10Slinton 	for( temp=type; temp&TMASK; temp = DECREF(temp) ){
11695513c10Slinton 		if( ISARY(temp) ){
11776f37e67Slinton 			if (dimtab[dsym] == 0) {
11876f37e67Slinton 				dimtab[dsym] = dimtab[ddef];
11976f37e67Slinton 				changed = 1;
12076f37e67Slinton 				}
12195513c10Slinton 			else if (dimtab[ddef]!=0&&dimtab[dsym]!=dimtab[ddef]) {
12295513c10Slinton 				goto mismatch;
12395513c10Slinton 				}
12495513c10Slinton 			++dsym;
12595513c10Slinton 			++ddef;
12695513c10Slinton 			}
12795513c10Slinton 		}
12895513c10Slinton 
12976f37e67Slinton 	if (changed) {
13076f37e67Slinton 		FIXDEF(p);
13176f37e67Slinton 		}
13276f37e67Slinton 
13395513c10Slinton 	/* check that redeclarations are to the same structure */
13495513c10Slinton 	if( (temp==STRTY||temp==UNIONTY||temp==ENUMTY) && p->sizoff != q->fn.csiz
13595513c10Slinton 		 && class!=STNAME && class!=UNAME && class!=ENAME ){
13695513c10Slinton 		goto mismatch;
13795513c10Slinton 		}
13895513c10Slinton 
13995513c10Slinton 	scl = ( p->sclass );
14095513c10Slinton 
14195513c10Slinton # ifndef BUG1
14295513c10Slinton 	if( ddebug ){
14395513c10Slinton 		printf( "	previous class: %s\n", scnames(scl) );
14495513c10Slinton 		}
14595513c10Slinton # endif
14695513c10Slinton 
14795513c10Slinton 	if( class&FIELD ){
14895513c10Slinton 		/* redefinition */
14995513c10Slinton 		if( !falloc( p, class&FLDSIZ, 1, NIL ) ) {
15095513c10Slinton 			/* successful allocation */
15195513c10Slinton 			psave( idp );
15295513c10Slinton 			return;
15395513c10Slinton 			}
15495513c10Slinton 		/* blew it: resume at end of switch... */
15595513c10Slinton 		}
15695513c10Slinton 
15795513c10Slinton 	else switch( class ){
15895513c10Slinton 
15995513c10Slinton 	case EXTERN:
16095513c10Slinton 		switch( scl ){
16195513c10Slinton 		case STATIC:
16295513c10Slinton 		case USTATIC:
16395513c10Slinton 			if( slev==0 ) return;
16495513c10Slinton 			break;
16595513c10Slinton 		case EXTDEF:
16695513c10Slinton 		case EXTERN:
16795513c10Slinton 		case FORTRAN:
16895513c10Slinton 		case UFORTRAN:
16995513c10Slinton 			return;
17095513c10Slinton 			}
17195513c10Slinton 		break;
17295513c10Slinton 
17395513c10Slinton 	case STATIC:
17495513c10Slinton 		if( scl==USTATIC || (scl==EXTERN && blevel==0) ){
17595513c10Slinton 			p->sclass = STATIC;
17695513c10Slinton 			if( ISFTN(type) ) curftn = idp;
17795513c10Slinton 			return;
17895513c10Slinton 			}
17995513c10Slinton 		break;
18095513c10Slinton 
18195513c10Slinton 	case USTATIC:
18295513c10Slinton 		if( scl==STATIC || scl==USTATIC ) return;
18395513c10Slinton 		break;
18495513c10Slinton 
18595513c10Slinton 	case LABEL:
18695513c10Slinton 		if( scl == ULABEL ){
18795513c10Slinton 			p->sclass = LABEL;
18895513c10Slinton 			deflab( p->offset );
18995513c10Slinton 			return;
19095513c10Slinton 			}
19195513c10Slinton 		break;
19295513c10Slinton 
19395513c10Slinton 	case TYPEDEF:
19495513c10Slinton 		if( scl == class ) return;
19595513c10Slinton 		break;
19695513c10Slinton 
19795513c10Slinton 	case UFORTRAN:
19895513c10Slinton 		if( scl == UFORTRAN || scl == FORTRAN ) return;
19995513c10Slinton 		break;
20095513c10Slinton 
20195513c10Slinton 	case FORTRAN:
20295513c10Slinton 		if( scl == UFORTRAN ){
20395513c10Slinton 			p->sclass = FORTRAN;
20495513c10Slinton 			if( ISFTN(type) ) curftn = idp;
20595513c10Slinton 			return;
20695513c10Slinton 			}
20795513c10Slinton 		break;
20895513c10Slinton 
20995513c10Slinton 	case MOU:
21095513c10Slinton 	case MOS:
21195513c10Slinton 		if( scl == class ) {
21295513c10Slinton 			if( oalloc( p, &strucoff ) ) break;
21395513c10Slinton 			if( class == MOU ) strucoff = 0;
21495513c10Slinton 			psave( idp );
21595513c10Slinton 			return;
21695513c10Slinton 			}
21795513c10Slinton 		break;
21895513c10Slinton 
21995513c10Slinton 	case MOE:
22095513c10Slinton 		break;
22195513c10Slinton 
22295513c10Slinton 	case EXTDEF:
22395513c10Slinton 		if( scl == EXTERN ) {
22495513c10Slinton 			p->sclass = EXTDEF;
22595513c10Slinton 			if( ISFTN(type) ) curftn = idp;
22695513c10Slinton 			return;
22795513c10Slinton 			}
22895513c10Slinton 		break;
22995513c10Slinton 
23095513c10Slinton 	case STNAME:
23195513c10Slinton 	case UNAME:
23295513c10Slinton 	case ENAME:
23395513c10Slinton 		if( scl != class ) break;
23495513c10Slinton 		if( dimtab[p->sizoff] == 0 ) return;  /* previous entry just a mention */
23595513c10Slinton 		break;
23695513c10Slinton 
23795513c10Slinton 	case ULABEL:
23895513c10Slinton 		if( scl == LABEL || scl == ULABEL ) return;
23995513c10Slinton 	case PARAM:
24095513c10Slinton 	case AUTO:
24195513c10Slinton 	case REGISTER:
24295513c10Slinton 		;  /* mismatch.. */
24395513c10Slinton 
24495513c10Slinton 		}
24595513c10Slinton 
24695513c10Slinton 	mismatch:
24795513c10Slinton 	/* allow nonunique structure/union member names */
24895513c10Slinton 
24995513c10Slinton 	if( class==MOU || class==MOS || class & FIELD ){/* make a new entry */
2502f906f46Smckusick 		register int *memp;
25195513c10Slinton 		p->sflags |= SNONUNIQ;  /* old entry is nonunique */
25295513c10Slinton 		/* determine if name has occurred in this structure/union */
2539a304896Sralph 		if (paramno > 0) for( memp = &paramstk[paramno-1];
25495513c10Slinton 			/* while */ *memp>=0 && stab[*memp].sclass != STNAME
25595513c10Slinton 				&& stab[*memp].sclass != UNAME;
25695513c10Slinton 			/* iterate */ --memp){ char *cname, *oname;
2575a6549aeSdonn 			if( stab[*memp].sflags & SNONUNIQ ){
25895513c10Slinton 				cname=p->sname;
25995513c10Slinton 				oname=stab[*memp].sname;
26095513c10Slinton #ifndef FLEXNAMES
2615a6549aeSdonn 				for(temp=1; temp<=NCHNAM; ++temp){
26295513c10Slinton 					if(*cname++ != *oname)goto diff;
26395513c10Slinton 					if(!*oname++)break;
26495513c10Slinton 					}
26595513c10Slinton #else
26695513c10Slinton 				if (cname != oname) goto diff;
26795513c10Slinton #endif
26895513c10Slinton 				uerror("redeclaration of: %s",p->sname);
26995513c10Slinton 				break;
27095513c10Slinton 				diff: continue;
27195513c10Slinton 				}
27295513c10Slinton 			}
27395513c10Slinton 		p = mknonuniq( &idp ); /* update p and idp to new entry */
27495513c10Slinton 		goto enter;
27595513c10Slinton 		}
27695513c10Slinton 	if( blevel > slev && class != EXTERN && class != FORTRAN &&
27795513c10Slinton 		class != UFORTRAN && !( class == LABEL && slev >= 2 ) ){
27895513c10Slinton 		q->tn.rval = idp = hide( p );
27995513c10Slinton 		p = &stab[idp];
28095513c10Slinton 		goto enter;
28195513c10Slinton 		}
28295513c10Slinton #ifndef FLEXNAMES
28395513c10Slinton 	uerror( "redeclaration of %.8s", p->sname );
28495513c10Slinton #else
28595513c10Slinton 	uerror( "redeclaration of %s", p->sname );
28695513c10Slinton #endif
28795513c10Slinton 	if( class==EXTDEF && ISFTN(type) ) curftn = idp;
28895513c10Slinton 	return;
28995513c10Slinton 
29095513c10Slinton 	enter:  /* make a new entry */
29195513c10Slinton 
29295513c10Slinton # ifndef BUG1
29395513c10Slinton 	if( ddebug ) printf( "	new entry made\n" );
29495513c10Slinton # endif
29595513c10Slinton 	if( type == UNDEF ) uerror("void type for %s",p->sname);
29695513c10Slinton 	p->stype = type;
29795513c10Slinton 	p->sclass = class;
29895513c10Slinton 	p->slevel = blevel;
29995513c10Slinton 	p->offset = NOOFFSET;
30095513c10Slinton 	p->suse = lineno;
30195513c10Slinton 	if( class == STNAME || class == UNAME || class == ENAME ) {
30295513c10Slinton 		p->sizoff = curdim;
30395513c10Slinton 		dstash( 0 );  /* size */
30495513c10Slinton 		dstash( -1 ); /* index to members of str or union */
30595513c10Slinton 		dstash( ALSTRUCT );  /* alignment */
30695513c10Slinton 		dstash( idp );
30795513c10Slinton 		}
30895513c10Slinton 	else {
30995513c10Slinton 		switch( BTYPE(type) ){
31095513c10Slinton 		case STRTY:
31195513c10Slinton 		case UNIONTY:
31295513c10Slinton 		case ENUMTY:
31395513c10Slinton 			p->sizoff = q->fn.csiz;
31495513c10Slinton 			break;
31595513c10Slinton 		default:
31695513c10Slinton 			p->sizoff = BTYPE(type);
31795513c10Slinton 			}
31895513c10Slinton 		}
31995513c10Slinton 
32095513c10Slinton 	/* copy dimensions */
32195513c10Slinton 
32295513c10Slinton 	p->dimoff = q->fn.cdim;
32395513c10Slinton 
32495513c10Slinton 	/* allocate offsets */
32595513c10Slinton 	if( class&FIELD ){
3265a6549aeSdonn 		(void) falloc( p, class&FLDSIZ, 0, NIL );  /* new entry */
32795513c10Slinton 		psave( idp );
32895513c10Slinton 		}
32995513c10Slinton 	else switch( class ){
33095513c10Slinton 
33195513c10Slinton 	case AUTO:
3325a6549aeSdonn 		(void) oalloc( p, &autooff );
33395513c10Slinton 		break;
33495513c10Slinton 	case STATIC:
33595513c10Slinton 	case EXTDEF:
33695513c10Slinton 		p->offset = getlab();
33795513c10Slinton 		if( ISFTN(type) ) curftn = idp;
33895513c10Slinton 		break;
33995513c10Slinton 	case ULABEL:
34095513c10Slinton 	case LABEL:
34195513c10Slinton 		p->offset = getlab();
34295513c10Slinton 		p->slevel = 2;
34395513c10Slinton 		if( class == LABEL ){
3445a6549aeSdonn 			(void) locctr( PROG );
34595513c10Slinton 			deflab( p->offset );
34695513c10Slinton 			}
34795513c10Slinton 		break;
34895513c10Slinton 
34995513c10Slinton 	case EXTERN:
35095513c10Slinton 	case UFORTRAN:
35195513c10Slinton 	case FORTRAN:
35295513c10Slinton 		p->offset = getlab();
35395513c10Slinton 		p->slevel = 0;
35495513c10Slinton 		break;
35595513c10Slinton 	case MOU:
35695513c10Slinton 	case MOS:
3575a6549aeSdonn 		(void) oalloc( p, &strucoff );
35895513c10Slinton 		if( class == MOU ) strucoff = 0;
35995513c10Slinton 		psave( idp );
36095513c10Slinton 		break;
36195513c10Slinton 
36295513c10Slinton 	case MOE:
36395513c10Slinton 		p->offset = strucoff++;
36495513c10Slinton 		psave( idp );
36595513c10Slinton 		break;
36695513c10Slinton 	case REGISTER:
36795513c10Slinton 		p->offset = regvar--;
36895513c10Slinton 		if( blevel == 1 ) p->sflags |= SSET;
36995513c10Slinton 		if( regvar < minrvar ) minrvar = regvar;
37095513c10Slinton 		break;
37195513c10Slinton 		}
37295513c10Slinton 
3732f906f46Smckusick 	{
3742f906f46Smckusick 		register int l = p->slevel;
3752f906f46Smckusick 
3762f906f46Smckusick 		if( l >= MAXSCOPES )
3772f906f46Smckusick 			cerror( "scopes nested too deep" );
3782f906f46Smckusick 
3792f906f46Smckusick 		p->snext = schain[l];
3802f906f46Smckusick 		schain[l] = p;
3812f906f46Smckusick 		if( l >= chaintop )
3822f906f46Smckusick 			chaintop = l + 1;
3832f906f46Smckusick 		}
3842f906f46Smckusick 
38595513c10Slinton 	/* user-supplied routine to fix up new definitions */
38695513c10Slinton 
38795513c10Slinton 	FIXDEF(p);
38895513c10Slinton 
38995513c10Slinton # ifndef BUG1
39095513c10Slinton 	if( ddebug ) printf( "	dimoff, sizoff, offset: %d, %d, %d\n", p->dimoff, p->sizoff, p->offset );
39195513c10Slinton # endif
39295513c10Slinton 
39395513c10Slinton 	}
39495513c10Slinton 
psave(i)39595513c10Slinton psave( i ){
39695513c10Slinton 	if( paramno >= PARAMSZ ){
39795513c10Slinton 		cerror( "parameter stack overflow");
39895513c10Slinton 		}
39995513c10Slinton 	paramstk[ paramno++ ] = i;
40095513c10Slinton 	}
40195513c10Slinton 
ftnend()40295513c10Slinton ftnend(){ /* end of function */
403bac0bd58Sdonn 	if( retlab != NOLAB && nerrors == 0 ){ /* inside a real function */
40495513c10Slinton 		efcode();
40595513c10Slinton 		}
40695513c10Slinton 	checkst(0);
40795513c10Slinton 	retstat = 0;
40895513c10Slinton 	tcheck();
40995513c10Slinton 	curclass = SNULL;
41095513c10Slinton 	brklab = contlab = retlab = NOLAB;
41195513c10Slinton 	flostat = 0;
41295513c10Slinton 	if( nerrors == 0 ){
41395513c10Slinton 		if( psavbc != & asavbc[0] ) cerror("bcsave error");
41495513c10Slinton 		if( paramno != 0 ) cerror("parameter reset error");
41595513c10Slinton 		if( swx != 0 ) cerror( "switch error");
41695513c10Slinton 		}
41795513c10Slinton 	psavbc = &asavbc[0];
41895513c10Slinton 	paramno = 0;
41995513c10Slinton 	autooff = AUTOINIT;
42095513c10Slinton 	minrvar = regvar = MAXRVAR;
42195513c10Slinton 	reached = 1;
42295513c10Slinton 	swx = 0;
42395513c10Slinton 	swp = swtab;
4245a6549aeSdonn 	(void) locctr(DATA);
42595513c10Slinton 	}
42695513c10Slinton 
dclargs()42795513c10Slinton dclargs(){
42895513c10Slinton 	register i, j;
42995513c10Slinton 	register struct symtab *p;
43095513c10Slinton 	register NODE *q;
43195513c10Slinton 	argoff = ARGINIT;
43295513c10Slinton # ifndef BUG1
43395513c10Slinton 	if( ddebug > 2) printf("dclargs()\n");
43495513c10Slinton # endif
43595513c10Slinton 	for( i=0; i<paramno; ++i ){
43695513c10Slinton 		if( (j = paramstk[i]) < 0 ) continue;
43795513c10Slinton 		p = &stab[j];
43895513c10Slinton # ifndef BUG1
43995513c10Slinton 		if( ddebug > 2 ){
44095513c10Slinton 			printf("\t%s (%d) ",p->sname, j);
44195513c10Slinton 			tprint(p->stype);
44295513c10Slinton 			printf("\n");
44395513c10Slinton 			}
44495513c10Slinton # endif
44595513c10Slinton 		if( p->stype == FARG ) {
44695513c10Slinton 			q = block(FREE,NIL,NIL,INT,0,INT);
44795513c10Slinton 			q->tn.rval = j;
44895513c10Slinton 			defid( q, PARAM );
44995513c10Slinton 			}
45095513c10Slinton 		FIXARG(p); /* local arg hook, eg. for sym. debugger */
45195513c10Slinton 		oalloc( p, &argoff );  /* always set aside space, even for register arguments */
45295513c10Slinton 		}
45395513c10Slinton 	cendarg();
4545a6549aeSdonn 	(void) locctr(PROG);
45595513c10Slinton 	defalign(ALINT);
45695513c10Slinton 	ftnno = getlab();
45795513c10Slinton 	bfcode( paramstk, paramno );
45895513c10Slinton 	paramno = 0;
45995513c10Slinton 	}
46095513c10Slinton 
46195513c10Slinton NODE *
rstruct(idn,soru)46295513c10Slinton rstruct( idn, soru ){ /* reference to a structure or union, with no definition */
46395513c10Slinton 	register struct symtab *p;
46495513c10Slinton 	register NODE *q;
46595513c10Slinton 	p = &stab[idn];
46695513c10Slinton 	switch( p->stype ){
46795513c10Slinton 
46895513c10Slinton 	case UNDEF:
46995513c10Slinton 	def:
47095513c10Slinton 		q = block( FREE, NIL, NIL, 0, 0, 0 );
47195513c10Slinton 		q->tn.rval = idn;
47295513c10Slinton 		q->in.type = (soru&INSTRUCT) ? STRTY : ( (soru&INUNION) ? UNIONTY : ENUMTY );
47395513c10Slinton 		defid( q, (soru&INSTRUCT) ? STNAME : ( (soru&INUNION) ? UNAME : ENAME ) );
47495513c10Slinton 		break;
47595513c10Slinton 
47695513c10Slinton 	case STRTY:
47795513c10Slinton 		if( soru & INSTRUCT ) break;
47895513c10Slinton 		goto def;
47995513c10Slinton 
48095513c10Slinton 	case UNIONTY:
48195513c10Slinton 		if( soru & INUNION ) break;
48295513c10Slinton 		goto def;
48395513c10Slinton 
48495513c10Slinton 	case ENUMTY:
48595513c10Slinton 		if( !(soru&(INUNION|INSTRUCT)) ) break;
48695513c10Slinton 		goto def;
48795513c10Slinton 
48895513c10Slinton 		}
48995513c10Slinton 	stwart = instruct;
49095513c10Slinton 	return( mkty( p->stype, 0, p->sizoff ) );
49195513c10Slinton 	}
49295513c10Slinton 
moedef(idn)49395513c10Slinton moedef( idn ){
49495513c10Slinton 	register NODE *q;
49595513c10Slinton 
49695513c10Slinton 	q = block( FREE, NIL, NIL, MOETY, 0, 0 );
49795513c10Slinton 	q->tn.rval = idn;
49895513c10Slinton 	if( idn>=0 ) defid( q, MOE );
49995513c10Slinton 	}
50095513c10Slinton 
bstruct(idn,soru)50195513c10Slinton bstruct( idn, soru ){ /* begining of structure or union declaration */
50295513c10Slinton 	register NODE *q;
50395513c10Slinton 
50495513c10Slinton 	psave( instruct );
50595513c10Slinton 	psave( curclass );
50695513c10Slinton 	psave( strucoff );
50795513c10Slinton 	strucoff = 0;
50895513c10Slinton 	instruct = soru;
50995513c10Slinton 	q = block( FREE, NIL, NIL, 0, 0, 0 );
51095513c10Slinton 	q->tn.rval = idn;
51195513c10Slinton 	if( instruct==INSTRUCT ){
51295513c10Slinton 		curclass = MOS;
51395513c10Slinton 		q->in.type = STRTY;
51495513c10Slinton 		if( idn >= 0 ) defid( q, STNAME );
51595513c10Slinton 		}
51695513c10Slinton 	else if( instruct == INUNION ) {
51795513c10Slinton 		curclass = MOU;
51895513c10Slinton 		q->in.type = UNIONTY;
51995513c10Slinton 		if( idn >= 0 ) defid( q, UNAME );
52095513c10Slinton 		}
52195513c10Slinton 	else { /* enum */
52295513c10Slinton 		curclass = MOE;
52395513c10Slinton 		q->in.type = ENUMTY;
52495513c10Slinton 		if( idn >= 0 ) defid( q, ENAME );
52595513c10Slinton 		}
52695513c10Slinton 	psave( idn = q->tn.rval );
52795513c10Slinton 	/* the "real" definition is where the members are seen */
52895513c10Slinton 	if ( idn >= 0 ) stab[idn].suse = lineno;
52995513c10Slinton 	return( paramno-4 );
53095513c10Slinton 	}
53195513c10Slinton 
53295513c10Slinton NODE *
dclstruct(oparam)53395513c10Slinton dclstruct( oparam ){
53495513c10Slinton 	register struct symtab *p;
53595513c10Slinton 	register i, al, sa, j, sz, szindex;
53695513c10Slinton 	register TWORD temp;
53795513c10Slinton 	register high, low;
53895513c10Slinton 
5395a6549aeSdonn 	/* paramstk contains:
5405a6549aeSdonn 		paramstk[ oparam ] = previous instruct
5415a6549aeSdonn 		paramstk[ oparam+1 ] = previous class
54295513c10Slinton 		paramstk[ oparam+2 ] = previous strucoff
54395513c10Slinton 		paramstk[ oparam+3 ] = structure name
54495513c10Slinton 
54595513c10Slinton 		paramstk[ oparam+4, ... ]  = member stab indices
54695513c10Slinton 
54795513c10Slinton 		*/
54895513c10Slinton 
54995513c10Slinton 
55095513c10Slinton 	if( (i=paramstk[oparam+3]) < 0 ){
55195513c10Slinton 		szindex = curdim;
55295513c10Slinton 		dstash( 0 );  /* size */
55395513c10Slinton 		dstash( -1 );  /* index to member names */
55495513c10Slinton 		dstash( ALSTRUCT );  /* alignment */
55595513c10Slinton 		dstash( -lineno );	/* name of structure */
55695513c10Slinton 		}
55795513c10Slinton 	else {
55895513c10Slinton 		szindex = stab[i].sizoff;
55995513c10Slinton 		}
56095513c10Slinton 
56195513c10Slinton # ifndef BUG1
56295513c10Slinton 	if( ddebug ){
56395513c10Slinton #ifndef FLEXNAMES
56495513c10Slinton 		printf( "dclstruct( %.8s ), szindex = %d\n", (i>=0)? stab[i].sname : "??", szindex );
56595513c10Slinton #else
56695513c10Slinton 		printf( "dclstruct( %s ), szindex = %d\n", (i>=0)? stab[i].sname : "??", szindex );
56795513c10Slinton #endif
56895513c10Slinton 		}
56995513c10Slinton # endif
57095513c10Slinton 	temp = (instruct&INSTRUCT)?STRTY:((instruct&INUNION)?UNIONTY:ENUMTY);
57195513c10Slinton 	stwart = instruct = paramstk[ oparam ];
57295513c10Slinton 	curclass = paramstk[ oparam+1 ];
57395513c10Slinton 	dimtab[ szindex+1 ] = curdim;
57495513c10Slinton 	al = ALSTRUCT;
57595513c10Slinton 
57695513c10Slinton 	high = low = 0;
57795513c10Slinton 
57895513c10Slinton 	for( i = oparam+4;  i< paramno; ++i ){
57995513c10Slinton 		dstash( j=paramstk[i] );
58095513c10Slinton 		if( j<0 || j>= SYMTSZ ) cerror( "gummy structure member" );
58195513c10Slinton 		p = &stab[j];
58295513c10Slinton 		if( temp == ENUMTY ){
58395513c10Slinton 			if( p->offset < low ) low = p->offset;
58495513c10Slinton 			if( p->offset > high ) high = p->offset;
58595513c10Slinton 			p->sizoff = szindex;
58695513c10Slinton 			continue;
58795513c10Slinton 			}
58895513c10Slinton 		sa = talign( p->stype, p->sizoff );
58995513c10Slinton 		if( p->sclass & FIELD ){
59095513c10Slinton 			sz = p->sclass&FLDSIZ;
59195513c10Slinton 			}
59295513c10Slinton 		else {
59395513c10Slinton 			sz = tsize( p->stype, p->dimoff, p->sizoff );
59495513c10Slinton 			}
59595513c10Slinton 		if( sz == 0 ){
59695513c10Slinton #ifndef FLEXNAMES
59795513c10Slinton 			werror( "illegal zero sized structure member: %.8s", p->sname );
59895513c10Slinton #else
59995513c10Slinton 			werror( "illegal zero sized structure member: %s", p->sname );
60095513c10Slinton #endif
60195513c10Slinton 			}
60295513c10Slinton 		if( sz > strucoff ) strucoff = sz;  /* for use with unions */
60395513c10Slinton 		SETOFF( al, sa );
60495513c10Slinton 		/* set al, the alignment, to the lcm of the alignments of the members */
60595513c10Slinton 		}
60695513c10Slinton 	dstash( -1 );  /* endmarker */
60795513c10Slinton 	SETOFF( strucoff, al );
60895513c10Slinton 
60995513c10Slinton 	if( temp == ENUMTY ){
61095513c10Slinton 		register TWORD ty;
61195513c10Slinton 
61295513c10Slinton # ifdef ENUMSIZE
61395513c10Slinton 		ty = ENUMSIZE(high,low);
61495513c10Slinton # else
61595513c10Slinton 		if( (char)high == high && (char)low == low ) ty = ctype( CHAR );
61695513c10Slinton 		else if( (short)high == high && (short)low == low ) ty = ctype( SHORT );
61795513c10Slinton 		else ty = ctype(INT);
61895513c10Slinton #endif
61995513c10Slinton 		strucoff = tsize( ty, 0, (int)ty );
62095513c10Slinton 		dimtab[ szindex+2 ] = al = talign( ty, (int)ty );
62195513c10Slinton 		}
62295513c10Slinton 
62395513c10Slinton 	if( strucoff == 0 ) uerror( "zero sized structure" );
62495513c10Slinton 	dimtab[ szindex ] = strucoff;
62595513c10Slinton 	dimtab[ szindex+2 ] = al;
62695513c10Slinton 	dimtab[ szindex+3 ] = paramstk[ oparam+3 ];  /* name index */
62795513c10Slinton 
62895513c10Slinton 	FIXSTRUCT( szindex, oparam ); /* local hook, eg. for sym debugger */
62995513c10Slinton # ifndef BUG1
63095513c10Slinton 	if( ddebug>1 ){
63195513c10Slinton 		printf( "\tdimtab[%d,%d,%d] = %d,%d,%d\n", szindex,szindex+1,szindex+2,
63295513c10Slinton 				dimtab[szindex],dimtab[szindex+1],dimtab[szindex+2] );
63395513c10Slinton 		for( i = dimtab[szindex+1]; dimtab[i] >= 0; ++i ){
63495513c10Slinton #ifndef FLEXNAMES
63595513c10Slinton 			printf( "\tmember %.8s(%d)\n", stab[dimtab[i]].sname, dimtab[i] );
63695513c10Slinton #else
63795513c10Slinton 			printf( "\tmember %s(%d)\n", stab[dimtab[i]].sname, dimtab[i] );
63895513c10Slinton #endif
63995513c10Slinton 			}
64095513c10Slinton 		}
64195513c10Slinton # endif
64295513c10Slinton 
64395513c10Slinton 	strucoff = paramstk[ oparam+2 ];
64495513c10Slinton 	paramno = oparam;
64595513c10Slinton 
64695513c10Slinton 	return( mkty( temp, 0, szindex ) );
64795513c10Slinton 	}
64895513c10Slinton 
64995513c10Slinton 	/* VARARGS */
yyerror(s)65095513c10Slinton yyerror( s ) char *s; { /* error printing routine in parser */
65195513c10Slinton 
65295513c10Slinton 	uerror( s );
65395513c10Slinton 
65495513c10Slinton 	}
65595513c10Slinton 
yyaccpt()65695513c10Slinton yyaccpt(){
65795513c10Slinton 	ftnend();
65895513c10Slinton 	}
65995513c10Slinton 
ftnarg(idn)66095513c10Slinton ftnarg( idn ) {
66195513c10Slinton 	switch( stab[idn].stype ){
66295513c10Slinton 
66395513c10Slinton 	case UNDEF:
66495513c10Slinton 		/* this parameter, entered at scan */
66595513c10Slinton 		break;
66695513c10Slinton 	case FARG:
66795513c10Slinton #ifndef FLEXNAMES
66895513c10Slinton 		uerror("redeclaration of formal parameter, %.8s",
66995513c10Slinton #else
67095513c10Slinton 		uerror("redeclaration of formal parameter, %s",
67195513c10Slinton #endif
67295513c10Slinton 			stab[idn].sname);
67395513c10Slinton 		/* fall thru */
67495513c10Slinton 	case FTN:
67595513c10Slinton 		/* the name of this function matches parm */
67695513c10Slinton 		/* fall thru */
67795513c10Slinton 	default:
67895513c10Slinton 		idn = hide( &stab[idn]);
67995513c10Slinton 		break;
68095513c10Slinton 	case TNULL:
68195513c10Slinton 		/* unused entry, fill it */
68295513c10Slinton 		;
68395513c10Slinton 		}
68495513c10Slinton 	stab[idn].stype = FARG;
68595513c10Slinton 	stab[idn].sclass = PARAM;
68695513c10Slinton 	psave( idn );
68795513c10Slinton 	}
68895513c10Slinton 
talign(ty,s)68995513c10Slinton talign( ty, s) register unsigned ty; register s; {
69095513c10Slinton 	/* compute the alignment of an object with type ty, sizeoff index s */
69195513c10Slinton 
69295513c10Slinton 	register i;
69395513c10Slinton 	if( s<0 && ty!=INT && ty!=CHAR && ty!=SHORT && ty!=UNSIGNED && ty!=UCHAR && ty!=USHORT
69495513c10Slinton #ifdef LONGFIELDS
69595513c10Slinton 		&& ty!=LONG && ty!=ULONG
69695513c10Slinton #endif
69795513c10Slinton 					){
69895513c10Slinton 		return( fldal( ty ) );
69995513c10Slinton 		}
70095513c10Slinton 
70195513c10Slinton 	for( i=0; i<=(SZINT-BTSHIFT-1); i+=TSHIFT ){
70295513c10Slinton 		switch( (ty>>i)&TMASK ){
70395513c10Slinton 
70495513c10Slinton 		case FTN:
7058ad063b4Smckusick 			uerror( "can't assign to function" );
7068ad063b4Smckusick 			return( ALCHAR );
70795513c10Slinton 		case PTR:
70895513c10Slinton 			return( ALPOINT );
70995513c10Slinton 		case ARY:
71095513c10Slinton 			continue;
71195513c10Slinton 		case 0:
71295513c10Slinton 			break;
71395513c10Slinton 			}
71495513c10Slinton 		}
71595513c10Slinton 
71695513c10Slinton 	switch( BTYPE(ty) ){
71795513c10Slinton 
71895513c10Slinton 	case UNIONTY:
71995513c10Slinton 	case ENUMTY:
72095513c10Slinton 	case STRTY:
72195513c10Slinton 		return( (unsigned int) dimtab[ s+2 ] );
72295513c10Slinton 	case CHAR:
72395513c10Slinton 	case UCHAR:
72495513c10Slinton 		return( ALCHAR );
72595513c10Slinton 	case FLOAT:
72695513c10Slinton 		return( ALFLOAT );
72795513c10Slinton 	case DOUBLE:
72895513c10Slinton 		return( ALDOUBLE );
72995513c10Slinton 	case LONG:
73095513c10Slinton 	case ULONG:
73195513c10Slinton 		return( ALLONG );
73295513c10Slinton 	case SHORT:
73395513c10Slinton 	case USHORT:
73495513c10Slinton 		return( ALSHORT );
73595513c10Slinton 	default:
73695513c10Slinton 		return( ALINT );
73795513c10Slinton 		}
73895513c10Slinton 	}
73995513c10Slinton 
74095513c10Slinton OFFSZ
tsize(ty,d,s)74195513c10Slinton tsize( ty, d, s )  TWORD ty; {
74295513c10Slinton 	/* compute the size associated with type ty,
74395513c10Slinton 	    dimoff d, and sizoff s */
74495513c10Slinton 	/* BETTER NOT BE CALLED WHEN t, d, and s REFER TO A BIT FIELD... */
74595513c10Slinton 
74695513c10Slinton 	int i;
74795513c10Slinton 	OFFSZ mult;
74895513c10Slinton 
74995513c10Slinton 	mult = 1;
75095513c10Slinton 
75195513c10Slinton 	for( i=0; i<=(SZINT-BTSHIFT-1); i+=TSHIFT ){
75295513c10Slinton 		switch( (ty>>i)&TMASK ){
75395513c10Slinton 
75495513c10Slinton 		case FTN:
75558e25b8bSdonn 			/* cerror( "compiler takes size of function"); */
75658e25b8bSdonn 			uerror( "can't take size of function" );
75758e25b8bSdonn 			return( SZCHAR );
75895513c10Slinton 		case PTR:
75995513c10Slinton 			return( SZPOINT * mult );
76095513c10Slinton 		case ARY:
76195513c10Slinton 			mult *= (unsigned int) dimtab[ d++ ];
76295513c10Slinton 			continue;
76395513c10Slinton 		case 0:
76495513c10Slinton 			break;
76595513c10Slinton 
76695513c10Slinton 			}
76795513c10Slinton 		}
76895513c10Slinton 
76995513c10Slinton 	if( dimtab[s]==0 ) {
77056d94415Sdonn 		if( ty == STRTY )
77156d94415Sdonn 			uerror( "undefined structure" );
77256d94415Sdonn 		else
77395513c10Slinton 			uerror( "unknown size");
77495513c10Slinton 		return( SZINT );
77595513c10Slinton 		}
77695513c10Slinton 	return( (unsigned int) dimtab[ s ] * mult );
77795513c10Slinton 	}
77895513c10Slinton 
inforce(n)77995513c10Slinton inforce( n ) OFFSZ n; {  /* force inoff to have the value n */
78095513c10Slinton 	/* inoff is updated to have the value n */
78195513c10Slinton 	OFFSZ wb;
78295513c10Slinton 	register rest;
78395513c10Slinton 	/* rest is used to do a lot of conversion to ints... */
78495513c10Slinton 
78595513c10Slinton 	if( inoff == n ) return;
78695513c10Slinton 	if( inoff > n ) {
78795513c10Slinton 		cerror( "initialization alignment error");
78895513c10Slinton 		}
78995513c10Slinton 
79095513c10Slinton 	wb = inoff;
79195513c10Slinton 	SETOFF( wb, SZINT );
79295513c10Slinton 
79395513c10Slinton 	/* wb now has the next higher word boundary */
79495513c10Slinton 
79595513c10Slinton 	if( wb >= n ){ /* in the same word */
79695513c10Slinton 		rest = n - inoff;
79795513c10Slinton 		vfdzero( rest );
79895513c10Slinton 		return;
79995513c10Slinton 		}
80095513c10Slinton 
80195513c10Slinton 	/* otherwise, extend inoff to be word aligned */
80295513c10Slinton 
80395513c10Slinton 	rest = wb - inoff;
80495513c10Slinton 	vfdzero( rest );
80595513c10Slinton 
80695513c10Slinton 	/* now, skip full words until near to n */
80795513c10Slinton 
80895513c10Slinton 	rest = (n-inoff)/SZINT;
80995513c10Slinton 	zecode( rest );
81095513c10Slinton 
81195513c10Slinton 	/* now, the remainder of the last word */
81295513c10Slinton 
81395513c10Slinton 	rest = n-inoff;
81495513c10Slinton 	vfdzero( rest );
81595513c10Slinton 	if( inoff != n ) cerror( "inoff error");
81695513c10Slinton 
81795513c10Slinton 	}
81895513c10Slinton 
vfdalign(n)81995513c10Slinton vfdalign( n ){ /* make inoff have the offset the next alignment of n */
82095513c10Slinton 	OFFSZ m;
82195513c10Slinton 
82295513c10Slinton 	m = inoff;
82395513c10Slinton 	SETOFF( m, n );
82495513c10Slinton 	inforce( m );
82595513c10Slinton 	}
82695513c10Slinton 
82795513c10Slinton 
82895513c10Slinton int idebug = 0;
82995513c10Slinton 
83095513c10Slinton int ibseen = 0;  /* the number of } constructions which have been filled */
83195513c10Slinton 
832cd7b1b55Sdonn int ifull = 0; /* 1 if all initializers have been seen */
833cd7b1b55Sdonn 
83495513c10Slinton int iclass;  /* storage class of thing being initialized */
83595513c10Slinton 
83695513c10Slinton int ilocctr = 0;  /* location counter for current initialization */
83795513c10Slinton 
beginit(curid)83895513c10Slinton beginit(curid){
83995513c10Slinton 	/* beginning of initilization; set location ctr and set type */
84095513c10Slinton 	register struct symtab *p;
84195513c10Slinton 
84295513c10Slinton # ifndef BUG1
84395513c10Slinton 	if( idebug >= 3 ) printf( "beginit(), curid = %d\n", curid );
84495513c10Slinton # endif
84595513c10Slinton 
84695513c10Slinton 	p = &stab[curid];
84795513c10Slinton 
84895513c10Slinton 	iclass = p->sclass;
84995513c10Slinton 	if( curclass == EXTERN || curclass == FORTRAN ) iclass = EXTERN;
85095513c10Slinton 	switch( iclass ){
85195513c10Slinton 
85295513c10Slinton 	case UNAME:
85395513c10Slinton 	case EXTERN:
85495513c10Slinton 		return;
85595513c10Slinton 	case AUTO:
85695513c10Slinton 	case REGISTER:
85795513c10Slinton 		break;
85895513c10Slinton 	case EXTDEF:
85995513c10Slinton 	case STATIC:
86095513c10Slinton 		ilocctr = ISARY(p->stype)?ADATA:DATA;
861bac0bd58Sdonn 		if( nerrors == 0 ){
8625a6549aeSdonn 			(void) locctr( ilocctr );
86395513c10Slinton 			defalign( talign( p->stype, p->sizoff ) );
86495513c10Slinton 			defnam( p );
865bac0bd58Sdonn 			}
86695513c10Slinton 
86795513c10Slinton 		}
86895513c10Slinton 
86995513c10Slinton 	inoff = 0;
87095513c10Slinton 	ibseen = 0;
871cd7b1b55Sdonn 	ifull = 0;
87295513c10Slinton 
87395513c10Slinton 	pstk = 0;
87495513c10Slinton 
87595513c10Slinton 	instk( curid, p->stype, p->dimoff, p->sizoff, inoff );
87695513c10Slinton 
87795513c10Slinton 	}
87895513c10Slinton 
instk(id,t,d,s,off)87995513c10Slinton instk( id, t, d, s, off ) OFFSZ off; TWORD t; {
88095513c10Slinton 	/* make a new entry on the parameter stack to initialize id */
88195513c10Slinton 
88295513c10Slinton 	register struct symtab *p;
88395513c10Slinton 
88495513c10Slinton 	for(;;){
88595513c10Slinton # ifndef BUG1
88695513c10Slinton 		if( idebug ) printf( "instk((%d, %o,%d,%d, %d)\n", id, t, d, s, off );
88795513c10Slinton # endif
88895513c10Slinton 
88995513c10Slinton 		/* save information on the stack */
89095513c10Slinton 
89195513c10Slinton 		if( !pstk ) pstk = instack;
89295513c10Slinton 		else ++pstk;
89395513c10Slinton 
89495513c10Slinton 		pstk->in_fl = 0;	/* { flag */
89595513c10Slinton 		pstk->in_id =  id ;
89695513c10Slinton 		pstk->in_t =  t ;
89795513c10Slinton 		pstk->in_d =  d ;
89895513c10Slinton 		pstk->in_s =  s ;
89995513c10Slinton 		pstk->in_n = 0;  /* number seen */
90095513c10Slinton 		pstk->in_x =  t==STRTY ?dimtab[s+1] : 0 ;
90195513c10Slinton 		pstk->in_off =  off;   /* offset at the beginning of this element */
90295513c10Slinton 		/* if t is an array, DECREF(t) can't be a field */
90395513c10Slinton 		/* INS_sz has size of array elements, and -size for fields */
90495513c10Slinton 		if( ISARY(t) ){
90595513c10Slinton 			pstk->in_sz = tsize( DECREF(t), d+1, s );
90695513c10Slinton 			}
90795513c10Slinton 		else if( stab[id].sclass & FIELD ){
90895513c10Slinton 			pstk->in_sz = - ( stab[id].sclass & FLDSIZ );
90995513c10Slinton 			}
91095513c10Slinton 		else {
91195513c10Slinton 			pstk->in_sz = 0;
91295513c10Slinton 			}
91395513c10Slinton 
91495513c10Slinton 		if( (iclass==AUTO || iclass == REGISTER ) &&
91595513c10Slinton 			(ISARY(t) || t==STRTY) ) uerror( "no automatic aggregate initialization" );
91695513c10Slinton 
91795513c10Slinton 		/* now, if this is not a scalar, put on another element */
91895513c10Slinton 
91995513c10Slinton 		if( ISARY(t) ){
92095513c10Slinton 			t = DECREF(t);
92195513c10Slinton 			++d;
92295513c10Slinton 			continue;
92395513c10Slinton 			}
92495513c10Slinton 		else if( t == STRTY ){
92556d94415Sdonn 			if( dimtab[pstk->in_s] == 0 ){
92656d94415Sdonn 				uerror( "can't initialize undefined structure" );
92756d94415Sdonn 				iclass = -1;
92856d94415Sdonn 				return;
92956d94415Sdonn 				}
93095513c10Slinton 			id = dimtab[pstk->in_x];
93195513c10Slinton 			p = &stab[id];
93295513c10Slinton 			if( p->sclass != MOS && !(p->sclass&FIELD) ) cerror( "insane structure member list" );
93395513c10Slinton 			t = p->stype;
93495513c10Slinton 			d = p->dimoff;
93595513c10Slinton 			s = p->sizoff;
93695513c10Slinton 			off += p->offset;
93795513c10Slinton 			continue;
93895513c10Slinton 			}
93995513c10Slinton 		else return;
94095513c10Slinton 		}
94195513c10Slinton 	}
94295513c10Slinton 
94395513c10Slinton NODE *
getstr()94495513c10Slinton getstr(){ /* decide if the string is external or an initializer, and get the contents accordingly */
94595513c10Slinton 
94695513c10Slinton 	register l, temp;
94795513c10Slinton 	register NODE *p;
94895513c10Slinton 
94995513c10Slinton 	if( (iclass==EXTDEF||iclass==STATIC) && (pstk->in_t == CHAR || pstk->in_t == UCHAR) &&
95095513c10Slinton 			pstk!=instack && ISARY( pstk[-1].in_t ) ){
95195513c10Slinton 		/* treat "abc" as { 'a', 'b', 'c', 0 } */
95295513c10Slinton 		strflg = 1;
95395513c10Slinton 		ilbrace();  /* simulate { */
95495513c10Slinton 		inforce( pstk->in_off );
95595513c10Slinton 		/* if the array is inflexible (not top level), pass in the size and
95695513c10Slinton 			be prepared to throw away unwanted initializers */
95795513c10Slinton 		lxstr((pstk-1)!=instack?dimtab[(pstk-1)->in_d]:0);  /* get the contents */
95895513c10Slinton 		irbrace();  /* simulate } */
95995513c10Slinton 		return( NIL );
96095513c10Slinton 		}
96195513c10Slinton 	else { /* make a label, and get the contents and stash them away */
96295513c10Slinton 		if( iclass != SNULL ){ /* initializing */
96395513c10Slinton 			/* fill out previous word, to permit pointer */
96495513c10Slinton 			vfdalign( ALPOINT );
96595513c10Slinton 			}
96695513c10Slinton 		temp = locctr( blevel==0?ISTRNG:STRNG ); /* set up location counter */
96795513c10Slinton 		deflab( l = getlab() );
96895513c10Slinton 		strflg = 0;
96995513c10Slinton 		lxstr(0); /* get the contents */
9705a6549aeSdonn 		(void) locctr( blevel==0?ilocctr:temp );
97195513c10Slinton 		p = buildtree( STRING, NIL, NIL );
97295513c10Slinton 		p->tn.rval = -l;
97395513c10Slinton 		return(p);
97495513c10Slinton 		}
97595513c10Slinton 	}
97695513c10Slinton 
putbyte(v)97795513c10Slinton putbyte( v ){ /* simulate byte v appearing in a list of integer values */
97895513c10Slinton 	register NODE *p;
97995513c10Slinton 	p = bcon(v);
98095513c10Slinton 	incode( p, SZCHAR );
98195513c10Slinton 	tfree( p );
98295513c10Slinton 	gotscal();
98395513c10Slinton 	}
98495513c10Slinton 
endinit()98595513c10Slinton endinit(){
98695513c10Slinton 	register TWORD t;
98795513c10Slinton 	register d, s, n, d1;
98895513c10Slinton 
98995513c10Slinton # ifndef BUG1
99095513c10Slinton 	if( idebug ) printf( "endinit(), inoff = %d\n", inoff );
99195513c10Slinton # endif
99295513c10Slinton 
99395513c10Slinton 	switch( iclass ){
99495513c10Slinton 
99595513c10Slinton 	case EXTERN:
99695513c10Slinton 	case AUTO:
99795513c10Slinton 	case REGISTER:
99856d94415Sdonn 	case -1:
99995513c10Slinton 		return;
100095513c10Slinton 		}
100195513c10Slinton 
100295513c10Slinton 	pstk = instack;
100395513c10Slinton 
100495513c10Slinton 	t = pstk->in_t;
100595513c10Slinton 	d = pstk->in_d;
100695513c10Slinton 	s = pstk->in_s;
100795513c10Slinton 	n = pstk->in_n;
100895513c10Slinton 
100995513c10Slinton 	if( ISARY(t) ){
101095513c10Slinton 		d1 = dimtab[d];
101195513c10Slinton 
101295513c10Slinton 		vfdalign( pstk->in_sz );  /* fill out part of the last element, if needed */
101395513c10Slinton 		n = inoff/pstk->in_sz;  /* real number of initializers */
101495513c10Slinton 		if( d1 >= n ){
101595513c10Slinton 			/* once again, t is an array, so no fields */
101695513c10Slinton 			inforce( tsize( t, d, s ) );
101795513c10Slinton 			n = d1;
101895513c10Slinton 			}
101995513c10Slinton 		if( d1!=0 && d1!=n ) uerror( "too many initializers");
102095513c10Slinton 		if( n==0 ) werror( "empty array declaration");
102195513c10Slinton 		dimtab[d] = n;
1022b705736cSlinton 		if( d1==0 ) FIXDEF(&stab[pstk->in_id]);
102395513c10Slinton 		}
102495513c10Slinton 
102595513c10Slinton 	else if( t == STRTY || t == UNIONTY ){
102695513c10Slinton 		/* clearly not fields either */
102795513c10Slinton 		inforce( tsize( t, d, s ) );
102895513c10Slinton 		}
102995513c10Slinton 	else if( n > 1 ) uerror( "bad scalar initialization");
103095513c10Slinton 	/* this will never be called with a field element... */
103195513c10Slinton 	else inforce( tsize(t,d,s) );
103295513c10Slinton 
103395513c10Slinton 	paramno = 0;
103495513c10Slinton 	vfdalign( AL_INIT );
103595513c10Slinton 	inoff = 0;
103695513c10Slinton 	iclass = SNULL;
103795513c10Slinton 
103895513c10Slinton 	}
103995513c10Slinton 
fixinit()1040522b2d2aSdonn fixinit(){
1041522b2d2aSdonn 	/* called from the grammar if we must punt during initialization */
1042522b2d2aSdonn 	/* stolen from endinit() */
1043522b2d2aSdonn 	pstk = instack;
1044522b2d2aSdonn 	paramno = 0;
1045522b2d2aSdonn 	vfdalign( AL_INIT );
1046522b2d2aSdonn 	inoff = 0;
1047522b2d2aSdonn 	iclass = SNULL;
1048522b2d2aSdonn 	}
1049522b2d2aSdonn 
doinit(p)105095513c10Slinton doinit( p ) register NODE *p; {
105195513c10Slinton 
105295513c10Slinton 	/* take care of generating a value for the initializer p */
105395513c10Slinton 	/* inoff has the current offset (last bit written)
105495513c10Slinton 		in the current word being generated */
105595513c10Slinton 
105695513c10Slinton 	register sz, d, s;
105795513c10Slinton 	register TWORD t;
1058442524f6Sralph 	int o;
105995513c10Slinton 
106095513c10Slinton 	/* note: size of an individual initializer is assumed to fit into an int */
106195513c10Slinton 
1062bac0bd58Sdonn 	if( iclass < 0 ) goto leave;
106395513c10Slinton 	if( iclass == EXTERN || iclass == UNAME ){
106495513c10Slinton 		uerror( "cannot initialize extern or union" );
106595513c10Slinton 		iclass = -1;
106695513c10Slinton 		goto leave;
106795513c10Slinton 		}
106895513c10Slinton 
106995513c10Slinton 	if( iclass == AUTO || iclass == REGISTER ){
107095513c10Slinton 		/* do the initialization and get out, without regard
107195513c10Slinton 		    for filing out the variable with zeros, etc. */
107295513c10Slinton 		bccode();
107395513c10Slinton 		idname = pstk->in_id;
107495513c10Slinton 		p = buildtree( ASSIGN, buildtree( NAME, NIL, NIL ), p );
107595513c10Slinton 		ecomp(p);
107695513c10Slinton 		return;
107795513c10Slinton 		}
107895513c10Slinton 
107995513c10Slinton 	if( p == NIL ) return;  /* for throwing away strings that have been turned into lists */
108095513c10Slinton 
1081cd7b1b55Sdonn 	if( ifull ){
1082cd7b1b55Sdonn 		uerror( "too many initializers" );
1083cd7b1b55Sdonn 		iclass = -1;
1084cd7b1b55Sdonn 		goto leave;
1085cd7b1b55Sdonn 		}
108695513c10Slinton 	if( ibseen ){
108795513c10Slinton 		uerror( "} expected");
108895513c10Slinton 		goto leave;
108995513c10Slinton 		}
109095513c10Slinton 
109195513c10Slinton # ifndef BUG1
109295513c10Slinton 	if( idebug > 1 ) printf( "doinit(%o)\n", p );
109395513c10Slinton # endif
109495513c10Slinton 
109595513c10Slinton 	t = pstk->in_t;  /* type required */
109695513c10Slinton 	d = pstk->in_d;
109795513c10Slinton 	s = pstk->in_s;
109895513c10Slinton 	if( pstk->in_sz < 0 ){  /* bit field */
109995513c10Slinton 		sz = -pstk->in_sz;
110095513c10Slinton 		}
110195513c10Slinton 	else {
110295513c10Slinton 		sz = tsize( t, d, s );
110395513c10Slinton 		}
110495513c10Slinton 
110595513c10Slinton 	inforce( pstk->in_off );
110695513c10Slinton 
110795513c10Slinton 	p = buildtree( ASSIGN, block( NAME, NIL,NIL, t, d, s ), p );
1108d72678f3Sdonn #ifdef LINT
1109d72678f3Sdonn 	/* force lint to treat this like an assignment */
1110d72678f3Sdonn 	ecode(p);
1111d72678f3Sdonn #endif
111295513c10Slinton 	p->in.left->in.op = FREE;
111395513c10Slinton 	p->in.left = p->in.right;
111495513c10Slinton 	p->in.right = NIL;
111595513c10Slinton 	p->in.left = optim( p->in.left );
1116442524f6Sralph 	o = p->in.left->in.op;
1117442524f6Sralph 	if( o == UNARY AND ){
1118442524f6Sralph 		o = p->in.left->in.op = FREE;
111995513c10Slinton 		p->in.left = p->in.left->in.left;
112095513c10Slinton 		}
112195513c10Slinton 	p->in.op = INIT;
112295513c10Slinton 
112395513c10Slinton 	if( sz < SZINT ){ /* special case: bit fields, etc. */
11240cdaaa16Sdonn 		if( o != ICON || p->in.left->tn.rval != NONAME )
11250cdaaa16Sdonn 			uerror( "illegal initialization" );
112695513c10Slinton 		else incode( p->in.left, sz );
112795513c10Slinton 		}
1128442524f6Sralph 	else if( o == FCON ){
1129442524f6Sralph 		fincode( p->in.left->fpn.fval, sz );
1130442524f6Sralph 		}
1131442524f6Sralph 	else if( o == DCON ){
1132442524f6Sralph 		fincode( p->in.left->dpn.dval, sz );
113395513c10Slinton 		}
113495513c10Slinton 	else {
11356bbea3b4Sralph 		p = optim(p);
11366bbea3b4Sralph 		if( p->in.left->in.op != ICON ) uerror( "illegal initialization" );
11376bbea3b4Sralph 		else cinit( p, sz );
113895513c10Slinton 		}
113995513c10Slinton 
114095513c10Slinton 	gotscal();
114195513c10Slinton 
114295513c10Slinton 	leave:
114395513c10Slinton 	tfree(p);
114495513c10Slinton 	}
114595513c10Slinton 
gotscal()114695513c10Slinton gotscal(){
114795513c10Slinton 	register t, ix;
114895513c10Slinton 	register n, id;
114995513c10Slinton 	struct symtab *p;
115095513c10Slinton 	OFFSZ temp;
115195513c10Slinton 
115295513c10Slinton 	for( ; pstk > instack; ) {
115395513c10Slinton 
115495513c10Slinton 		if( pstk->in_fl ) ++ibseen;
115595513c10Slinton 
115695513c10Slinton 		--pstk;
115795513c10Slinton 
115895513c10Slinton 		t = pstk->in_t;
115995513c10Slinton 
116095513c10Slinton 		if( t == STRTY ){
116195513c10Slinton 			ix = ++pstk->in_x;
116295513c10Slinton 			if( (id=dimtab[ix]) < 0 ) continue;
116395513c10Slinton 
116495513c10Slinton 			/* otherwise, put next element on the stack */
116595513c10Slinton 
116695513c10Slinton 			p = &stab[id];
116795513c10Slinton 			instk( id, p->stype, p->dimoff, p->sizoff, p->offset+pstk->in_off );
116895513c10Slinton 			return;
116995513c10Slinton 			}
117095513c10Slinton 		else if( ISARY(t) ){
117195513c10Slinton 			n = ++pstk->in_n;
117295513c10Slinton 			if( n >= dimtab[pstk->in_d] && pstk > instack ) continue;
117395513c10Slinton 
117495513c10Slinton 			/* put the new element onto the stack */
117595513c10Slinton 
117695513c10Slinton 			temp = pstk->in_sz;
117795513c10Slinton 			instk( pstk->in_id, (TWORD)DECREF(pstk->in_t), pstk->in_d+1, pstk->in_s,
117895513c10Slinton 				pstk->in_off+n*temp );
117995513c10Slinton 			return;
118095513c10Slinton 			}
118195513c10Slinton 
118295513c10Slinton 		}
1183cd7b1b55Sdonn 	ifull = 1;
118495513c10Slinton 	}
118595513c10Slinton 
ilbrace()118695513c10Slinton ilbrace(){ /* process an initializer's left brace */
118795513c10Slinton 	register t;
118895513c10Slinton 	struct instk *temp;
118995513c10Slinton 
119095513c10Slinton 	temp = pstk;
119195513c10Slinton 
119295513c10Slinton 	for( ; pstk > instack; --pstk ){
119395513c10Slinton 
119495513c10Slinton 		t = pstk->in_t;
119595513c10Slinton 		if( t != STRTY && !ISARY(t) ) continue; /* not an aggregate */
119695513c10Slinton 		if( pstk->in_fl ){ /* already associated with a { */
119795513c10Slinton 			if( pstk->in_n ) uerror( "illegal {");
119895513c10Slinton 			continue;
119995513c10Slinton 			}
120095513c10Slinton 
120195513c10Slinton 		/* we have one ... */
120295513c10Slinton 		pstk->in_fl = 1;
120395513c10Slinton 		break;
120495513c10Slinton 		}
120595513c10Slinton 
120695513c10Slinton 	/* cannot find one */
120795513c10Slinton 	/* ignore such right braces */
120895513c10Slinton 
120995513c10Slinton 	pstk = temp;
121095513c10Slinton 	}
121195513c10Slinton 
irbrace()121295513c10Slinton irbrace(){
121395513c10Slinton 	/* called when a '}' is seen */
121495513c10Slinton 
121595513c10Slinton # ifndef BUG1
121695513c10Slinton 	if( idebug ) printf( "irbrace(): paramno = %d on entry\n", paramno );
121795513c10Slinton # endif
121895513c10Slinton 
121995513c10Slinton 	if( ibseen ) {
122095513c10Slinton 		--ibseen;
122195513c10Slinton 		return;
122295513c10Slinton 		}
122395513c10Slinton 
122495513c10Slinton 	for( ; pstk > instack; --pstk ){
122595513c10Slinton 		if( !pstk->in_fl ) continue;
122695513c10Slinton 
122795513c10Slinton 		/* we have one now */
122895513c10Slinton 
122995513c10Slinton 		pstk->in_fl = 0;  /* cancel { */
123095513c10Slinton 		gotscal();  /* take it away... */
123195513c10Slinton 		return;
123295513c10Slinton 		}
123395513c10Slinton 
123495513c10Slinton 	/* these right braces match ignored left braces: throw out */
1235cd7b1b55Sdonn 	ifull = 1;
123695513c10Slinton 
123795513c10Slinton 	}
123895513c10Slinton 
upoff(size,alignment,poff)123995513c10Slinton upoff( size, alignment, poff ) register alignment, *poff; {
124095513c10Slinton 	/* update the offset pointed to by poff; return the
124195513c10Slinton 	/* offset of a value of size `size', alignment `alignment',
124295513c10Slinton 	/* given that off is increasing */
124395513c10Slinton 
124495513c10Slinton 	register off;
124595513c10Slinton 
124695513c10Slinton 	off = *poff;
124795513c10Slinton 	SETOFF( off, alignment );
124895513c10Slinton 	if( (offsz-off) <  size ){
124995513c10Slinton 		if( instruct!=INSTRUCT )cerror("too many local variables");
125095513c10Slinton 		else cerror("Structure too large");
125195513c10Slinton 		}
125295513c10Slinton 	*poff = off+size;
125395513c10Slinton 	return( off );
125495513c10Slinton 	}
125595513c10Slinton 
oalloc(p,poff)125695513c10Slinton oalloc( p, poff ) register struct symtab *p; register *poff; {
125795513c10Slinton 	/* allocate p with offset *poff, and update *poff */
125895513c10Slinton 	register al, off, tsz;
125995513c10Slinton 	int noff;
126095513c10Slinton 
126195513c10Slinton 	al = talign( p->stype, p->sizoff );
126295513c10Slinton 	noff = off = *poff;
126395513c10Slinton 	tsz = tsize( p->stype, p->dimoff, p->sizoff );
126495513c10Slinton #ifdef BACKAUTO
126595513c10Slinton 	if( p->sclass == AUTO ){
126695513c10Slinton 		if( (offsz-off) < tsz ) cerror("too many local variables");
126795513c10Slinton 		noff = off + tsz;
126895513c10Slinton 		SETOFF( noff, al );
126995513c10Slinton 		off = -noff;
127095513c10Slinton 		}
127195513c10Slinton 	else
127295513c10Slinton #endif
127395513c10Slinton 		if( p->sclass == PARAM && ( tsz < SZINT ) ){
127495513c10Slinton 			off = upoff( SZINT, ALINT, &noff );
127595513c10Slinton # ifndef RTOLBYTES
127695513c10Slinton 			off = noff - tsz;
127795513c10Slinton #endif
127895513c10Slinton 			}
127995513c10Slinton 		else
128095513c10Slinton 		{
128195513c10Slinton 		off = upoff( tsz, al, &noff );
128295513c10Slinton 		}
128395513c10Slinton 
128495513c10Slinton 	if( p->sclass != REGISTER ){ /* in case we are allocating stack space for register arguments */
128595513c10Slinton 		if( p->offset == NOOFFSET ) p->offset = off;
128695513c10Slinton 		else if( off != p->offset ) return(1);
128795513c10Slinton 		}
128895513c10Slinton 
128995513c10Slinton 	*poff = noff;
129095513c10Slinton 	return(0);
129195513c10Slinton 	}
129295513c10Slinton 
falloc(p,w,new,pty)129395513c10Slinton falloc( p, w, new, pty )  register struct symtab *p; NODE *pty; {
129495513c10Slinton 	/* allocate a field of width w */
129595513c10Slinton 	/* new is 0 if new entry, 1 if redefinition, -1 if alignment */
129695513c10Slinton 
129795513c10Slinton 	register al,sz,type;
129895513c10Slinton 
129995513c10Slinton 	type = (new<0)? pty->in.type : p->stype;
130095513c10Slinton 
130195513c10Slinton 	/* this must be fixed to use the current type in alignments */
130295513c10Slinton 	switch( new<0?pty->in.type:p->stype ){
130395513c10Slinton 
130495513c10Slinton 	case ENUMTY:
130595513c10Slinton 		{
130695513c10Slinton 			int s;
130795513c10Slinton 			s = new<0 ? pty->fn.csiz : p->sizoff;
130895513c10Slinton 			al = dimtab[s+2];
130995513c10Slinton 			sz = dimtab[s];
131095513c10Slinton 			break;
131195513c10Slinton 			}
131295513c10Slinton 
131395513c10Slinton 	case CHAR:
131495513c10Slinton 	case UCHAR:
131595513c10Slinton 		al = ALCHAR;
131695513c10Slinton 		sz = SZCHAR;
131795513c10Slinton 		break;
131895513c10Slinton 
131995513c10Slinton 	case SHORT:
132095513c10Slinton 	case USHORT:
132195513c10Slinton 		al = ALSHORT;
132295513c10Slinton 		sz = SZSHORT;
132395513c10Slinton 		break;
132495513c10Slinton 
132595513c10Slinton 	case INT:
132695513c10Slinton 	case UNSIGNED:
132795513c10Slinton 		al = ALINT;
132895513c10Slinton 		sz = SZINT;
132995513c10Slinton 		break;
133095513c10Slinton #ifdef LONGFIELDS
133195513c10Slinton 
133295513c10Slinton 	case LONG:
133395513c10Slinton 	case ULONG:
133495513c10Slinton 		al = ALLONG;
133595513c10Slinton 		sz = SZLONG;
133695513c10Slinton 		break;
133795513c10Slinton #endif
133895513c10Slinton 
133995513c10Slinton 	default:
134095513c10Slinton 		if( new < 0 ) {
134195513c10Slinton 			uerror( "illegal field type" );
134295513c10Slinton 			al = ALINT;
134395513c10Slinton 			}
134495513c10Slinton 		else {
134595513c10Slinton 			al = fldal( p->stype );
134695513c10Slinton 			sz =SZINT;
134795513c10Slinton 			}
134895513c10Slinton 		}
134995513c10Slinton 
135095513c10Slinton 	if( w > sz ) {
135195513c10Slinton 		uerror( "field too big");
135295513c10Slinton 		w = sz;
135395513c10Slinton 		}
135495513c10Slinton 
135595513c10Slinton 	if( w == 0 ){ /* align only */
135695513c10Slinton 		SETOFF( strucoff, al );
135795513c10Slinton 		if( new >= 0 ) uerror( "zero size field");
135895513c10Slinton 		return(0);
135995513c10Slinton 		}
136095513c10Slinton 
136195513c10Slinton 	if( strucoff%al + w > sz ) SETOFF( strucoff, al );
136295513c10Slinton 	if( new < 0 ) {
136395513c10Slinton 		if( (offsz-strucoff) < w )
136495513c10Slinton 			cerror("structure too large");
136595513c10Slinton 		strucoff += w;  /* we know it will fit */
136695513c10Slinton 		return(0);
136795513c10Slinton 		}
136895513c10Slinton 
136995513c10Slinton 	/* establish the field */
137095513c10Slinton 
137195513c10Slinton 	if( new == 1 ) { /* previous definition */
137295513c10Slinton 		if( p->offset != strucoff || p->sclass != (FIELD|w) ) return(1);
137395513c10Slinton 		}
137495513c10Slinton 	p->offset = strucoff;
137595513c10Slinton 	if( (offsz-strucoff) < w ) cerror("structure too large");
137695513c10Slinton 	strucoff += w;
137795513c10Slinton 	p->stype = type;
137895513c10Slinton 	fldty( p );
137995513c10Slinton 	return(0);
138095513c10Slinton 	}
138195513c10Slinton 
nidcl(p)138295513c10Slinton nidcl( p ) NODE *p; { /* handle unitialized declarations */
138395513c10Slinton 	/* assumed to be not functions */
138495513c10Slinton 	register class;
138595513c10Slinton 	register commflag;  /* flag for labelled common declarations */
138695513c10Slinton 
138795513c10Slinton 	commflag = 0;
138895513c10Slinton 
138995513c10Slinton 	/* compute class */
139095513c10Slinton 	if( (class=curclass) == SNULL ){
139195513c10Slinton 		if( blevel > 1 ) class = AUTO;
139295513c10Slinton 		else if( blevel != 0 || instruct ) cerror( "nidcl error" );
139395513c10Slinton 		else { /* blevel = 0 */
139495513c10Slinton 			class = noinit();
139595513c10Slinton 			if( class == EXTERN ) commflag = 1;
139695513c10Slinton 			}
139795513c10Slinton 		}
139895513c10Slinton #ifdef LCOMM
13995a6549aeSdonn 	/* hack so stab will come out as LCSYM rather than STSYM */
140095513c10Slinton 	if (class == STATIC) {
140195513c10Slinton 		extern int stabLCSYM;
140295513c10Slinton 		stabLCSYM = 1;
140395513c10Slinton 	}
140495513c10Slinton #endif
140595513c10Slinton 
140695513c10Slinton 	defid( p, class );
140795513c10Slinton 
1408d86759a8Sdonn 	/* if an array is not initialized, no empty dimension */
1409c065a4dbSdonn 	if( class!=EXTERN && class!=TYPEDEF &&
1410c065a4dbSdonn 	    ISARY(p->in.type) && dimtab[p->fn.cdim]==0 )
1411d86759a8Sdonn 		uerror("null storage definition");
1412d86759a8Sdonn 
141395513c10Slinton #ifndef LCOMM
14142f906f46Smckusick 	if( class==EXTDEF || class==STATIC )
141595513c10Slinton #else
141695513c10Slinton 	if (class==STATIC) {
141795513c10Slinton 		register struct symtab *s = &stab[p->tn.rval];
141895513c10Slinton 		extern int stabLCSYM;
141995513c10Slinton 		int sz = tsize(s->stype, s->dimoff, s->sizoff)/SZCHAR;
142095513c10Slinton 
142195513c10Slinton 		stabLCSYM = 0;
142295513c10Slinton 		if (sz % sizeof (int))
142395513c10Slinton 			sz += sizeof (int) - (sz % sizeof (int));
142495513c10Slinton 		if (s->slevel > 1)
142595513c10Slinton 			printf("	.lcomm	L%d,%d\n", s->offset, sz);
142695513c10Slinton 		else
142795513c10Slinton 			printf("	.lcomm	%s,%d\n", exname(s->sname), sz);
14282f906f46Smckusick 	}else if (class == EXTDEF)
142995513c10Slinton #endif
14302f906f46Smckusick 		{
143195513c10Slinton 		/* simulate initialization by 0 */
143295513c10Slinton 		beginit(p->tn.rval);
143395513c10Slinton 		endinit();
143495513c10Slinton 		}
143595513c10Slinton 	if( commflag ) commdec( p->tn.rval );
143695513c10Slinton 	}
143795513c10Slinton 
143895513c10Slinton TWORD
types(t1,t2,t3)143995513c10Slinton types( t1, t2, t3 ) TWORD t1, t2, t3; {
144095513c10Slinton 	/* return a basic type from basic types t1, t2, and t3 */
144195513c10Slinton 
144295513c10Slinton 	TWORD t[3], noun, adj, unsg;
144395513c10Slinton 	register i;
144495513c10Slinton 
144595513c10Slinton 	t[0] = t1;
144695513c10Slinton 	t[1] = t2;
144795513c10Slinton 	t[2] = t3;
144895513c10Slinton 
144995513c10Slinton 	unsg = INT;  /* INT or UNSIGNED */
145095513c10Slinton 	noun = UNDEF;  /* INT, CHAR, or FLOAT */
145195513c10Slinton 	adj = INT;  /* INT, LONG, or SHORT */
145295513c10Slinton 
145395513c10Slinton 	for( i=0; i<3; ++i ){
145495513c10Slinton 		switch( t[i] ){
145595513c10Slinton 
145695513c10Slinton 		default:
145795513c10Slinton 		bad:
145895513c10Slinton 			uerror( "illegal type combination" );
145995513c10Slinton 			return( INT );
146095513c10Slinton 
146195513c10Slinton 		case UNDEF:
146295513c10Slinton 			continue;
146395513c10Slinton 
146495513c10Slinton 		case UNSIGNED:
146595513c10Slinton 			if( unsg != INT ) goto bad;
146695513c10Slinton 			unsg = UNSIGNED;
146795513c10Slinton 			continue;
146895513c10Slinton 
146995513c10Slinton 		case LONG:
147095513c10Slinton 		case SHORT:
147195513c10Slinton 			if( adj != INT ) goto bad;
147295513c10Slinton 			adj = t[i];
147395513c10Slinton 			continue;
147495513c10Slinton 
147595513c10Slinton 		case INT:
147695513c10Slinton 		case CHAR:
147795513c10Slinton 		case FLOAT:
147895513c10Slinton 			if( noun != UNDEF ) goto bad;
147995513c10Slinton 			noun = t[i];
148095513c10Slinton 			continue;
148195513c10Slinton 			}
148295513c10Slinton 		}
148395513c10Slinton 
148495513c10Slinton 	/* now, construct final type */
148595513c10Slinton 	if( noun == UNDEF ) noun = INT;
148695513c10Slinton 	else if( noun == FLOAT ){
148795513c10Slinton 		if( unsg != INT || adj == SHORT ) goto bad;
148895513c10Slinton 		return( adj==LONG ? DOUBLE : FLOAT );
148995513c10Slinton 		}
149095513c10Slinton 	else if( noun == CHAR && adj != INT ) goto bad;
149195513c10Slinton 
149295513c10Slinton 	/* now, noun is INT or CHAR */
149395513c10Slinton 	if( adj != INT ) noun = adj;
149495513c10Slinton 	if( unsg == UNSIGNED ) return( noun + (UNSIGNED-INT) );
149595513c10Slinton 	else return( noun );
149695513c10Slinton 	}
149795513c10Slinton 
149895513c10Slinton NODE *
tymerge(typ,idp)149995513c10Slinton tymerge( typ, idp ) NODE *typ, *idp; {
150095513c10Slinton 	/* merge type typ with identifier idp  */
150195513c10Slinton 
150295513c10Slinton 	register unsigned t;
150395513c10Slinton 	register i;
150495513c10Slinton 	extern int eprint();
150595513c10Slinton 
150695513c10Slinton 	if( typ->in.op != TYPE ) cerror( "tymerge: arg 1" );
150795513c10Slinton 	if(idp == NIL ) return( NIL );
150895513c10Slinton 
150995513c10Slinton # ifndef BUG1
151095513c10Slinton 	if( ddebug > 2 ) fwalk( idp, eprint, 0 );
151195513c10Slinton # endif
151295513c10Slinton 
151395513c10Slinton 	idp->in.type = typ->in.type;
151495513c10Slinton 	idp->fn.cdim = curdim;
151595513c10Slinton 	tyreduce( idp );
151695513c10Slinton 	idp->fn.csiz = typ->fn.csiz;
151795513c10Slinton 
151895513c10Slinton 	for( t=typ->in.type, i=typ->fn.cdim; t&TMASK; t = DECREF(t) ){
151995513c10Slinton 		if( ISARY(t) ) dstash( dimtab[i++] );
152095513c10Slinton 		}
152195513c10Slinton 
152295513c10Slinton 	/* now idp is a single node: fix up type */
152395513c10Slinton 
152495513c10Slinton 	idp->in.type = ctype( idp->in.type );
152595513c10Slinton 
152695513c10Slinton 	if( (t = BTYPE(idp->in.type)) != STRTY && t != UNIONTY && t != ENUMTY ){
152795513c10Slinton 		idp->fn.csiz = t;  /* in case ctype has rewritten things */
152895513c10Slinton 		}
152995513c10Slinton 
153095513c10Slinton 	return( idp );
153195513c10Slinton 	}
153295513c10Slinton 
tyreduce(p)153395513c10Slinton tyreduce( p ) register NODE *p; {
153495513c10Slinton 
153595513c10Slinton 	/* build a type, and stash away dimensions, from a parse tree of the declaration */
153695513c10Slinton 	/* the type is build top down, the dimensions bottom up */
153795513c10Slinton 	register o, temp;
153895513c10Slinton 	register unsigned t;
153995513c10Slinton 
154095513c10Slinton 	o = p->in.op;
154195513c10Slinton 	p->in.op = FREE;
154295513c10Slinton 
154395513c10Slinton 	if( o == NAME ) return;
154495513c10Slinton 
154595513c10Slinton 	t = INCREF( p->in.type );
154695513c10Slinton 	if( o == UNARY CALL ) t += (FTN-PTR);
154795513c10Slinton 	else if( o == LB ){
154895513c10Slinton 		t += (ARY-PTR);
154995513c10Slinton 		temp = p->in.right->tn.lval;
155095513c10Slinton 		p->in.right->in.op = FREE;
1551d86759a8Sdonn 		if( temp == 0 && p->in.left->tn.op == LB )
1552d86759a8Sdonn 			uerror( "null dimension" );
155395513c10Slinton 		}
155495513c10Slinton 
155595513c10Slinton 	p->in.left->in.type = t;
155695513c10Slinton 	tyreduce( p->in.left );
155795513c10Slinton 
155895513c10Slinton 	if( o == LB ) dstash( temp );
155995513c10Slinton 
156095513c10Slinton 	p->tn.rval = p->in.left->tn.rval;
156195513c10Slinton 	p->in.type = p->in.left->in.type;
156295513c10Slinton 
156395513c10Slinton 	}
156495513c10Slinton 
fixtype(p,class)156595513c10Slinton fixtype( p, class ) register NODE *p; {
156695513c10Slinton 	register unsigned t, type;
156795513c10Slinton 	register mod1, mod2;
156895513c10Slinton 	/* fix up the types, and check for legality */
156995513c10Slinton 
157095513c10Slinton 	if( (type = p->in.type) == UNDEF ) return;
157195513c10Slinton 	if( mod2 = (type&TMASK) ){
157295513c10Slinton 		t = DECREF(type);
157395513c10Slinton 		while( mod1=mod2, mod2 = (t&TMASK) ){
157495513c10Slinton 			if( mod1 == ARY && mod2 == FTN ){
157595513c10Slinton 				uerror( "array of functions is illegal" );
157695513c10Slinton 				type = 0;
157795513c10Slinton 				}
157895513c10Slinton 			else if( mod1 == FTN && ( mod2 == ARY || mod2 == FTN ) ){
157995513c10Slinton 				uerror( "function returns illegal type" );
158095513c10Slinton 				type = 0;
158195513c10Slinton 				}
158295513c10Slinton 			t = DECREF(t);
158395513c10Slinton 			}
158495513c10Slinton 		}
158595513c10Slinton 
158695513c10Slinton 	/* detect function arguments, watching out for structure declarations */
1587d86759a8Sdonn 	/* for example, beware of f(x) struct { int a[10]; } *x; { ... } */
158895513c10Slinton 	/* the danger is that "a" will be converted to a pointer */
158995513c10Slinton 
1590d86759a8Sdonn 	if( class==SNULL && blevel==1 && !(instruct&(INSTRUCT|INUNION)) )
1591d86759a8Sdonn 		class = PARAM;
159295513c10Slinton 	if( class == PARAM || ( class==REGISTER && blevel==1 ) ){
159395513c10Slinton 		if( type == FLOAT ) type = DOUBLE;
159495513c10Slinton 		else if( ISARY(type) ){
1595d86759a8Sdonn #ifdef LINT
1596d86759a8Sdonn 			if( hflag && dimtab[p->fn.cdim]!=0 )
1597d86759a8Sdonn 				werror("array[%d] type changed to pointer",
1598d86759a8Sdonn 					dimtab[p->fn.cdim]);
1599d86759a8Sdonn #endif
160095513c10Slinton 			++p->fn.cdim;
160195513c10Slinton 			type += (PTR-ARY);
160295513c10Slinton 			}
160395513c10Slinton 		else if( ISFTN(type) ){
160495513c10Slinton 			werror( "a function is declared as an argument" );
160595513c10Slinton 			type = INCREF(type);
160695513c10Slinton 			}
160795513c10Slinton 
160895513c10Slinton 		}
160995513c10Slinton 
161095513c10Slinton 	if( instruct && ISFTN(type) ){
161195513c10Slinton 		uerror( "function illegal in structure or union" );
161295513c10Slinton 		type = INCREF(type);
161395513c10Slinton 		}
161495513c10Slinton 	p->in.type = type;
161595513c10Slinton 	}
161695513c10Slinton 
uclass(class)161795513c10Slinton uclass( class ) register class; {
161895513c10Slinton 	/* give undefined version of class */
161995513c10Slinton 	if( class == SNULL ) return( EXTERN );
162095513c10Slinton 	else if( class == STATIC ) return( USTATIC );
162195513c10Slinton 	else if( class == FORTRAN ) return( UFORTRAN );
162295513c10Slinton 	else return( class );
162395513c10Slinton 	}
162495513c10Slinton 
fixclass(class,type)162595513c10Slinton fixclass( class, type ) TWORD type; {
162695513c10Slinton 
162795513c10Slinton 	/* first, fix null class */
162895513c10Slinton 
162995513c10Slinton 	if( class == SNULL ){
163095513c10Slinton 		if( instruct&INSTRUCT ) class = MOS;
163195513c10Slinton 		else if( instruct&INUNION ) class = MOU;
163295513c10Slinton 		else if( blevel == 0 ) class = EXTDEF;
163395513c10Slinton 		else if( blevel == 1 ) class = PARAM;
163495513c10Slinton 		else class = AUTO;
163595513c10Slinton 
163695513c10Slinton 		}
163795513c10Slinton 
163895513c10Slinton 	/* now, do general checking */
163995513c10Slinton 
164095513c10Slinton 	if( ISFTN( type ) ){
164195513c10Slinton 		switch( class ) {
164295513c10Slinton 		default:
164395513c10Slinton 			uerror( "function has illegal storage class" );
164495513c10Slinton 		case AUTO:
164595513c10Slinton 			class = EXTERN;
164695513c10Slinton 		case EXTERN:
164795513c10Slinton 		case EXTDEF:
164895513c10Slinton 		case FORTRAN:
164995513c10Slinton 		case TYPEDEF:
165095513c10Slinton 		case STATIC:
165195513c10Slinton 		case UFORTRAN:
165295513c10Slinton 		case USTATIC:
165395513c10Slinton 			;
165495513c10Slinton 			}
165595513c10Slinton 		}
165695513c10Slinton 
165795513c10Slinton 	if( class&FIELD ){
165895513c10Slinton 		if( !(instruct&INSTRUCT) ) uerror( "illegal use of field" );
165995513c10Slinton 		return( class );
166095513c10Slinton 		}
166195513c10Slinton 
166295513c10Slinton 	switch( class ){
166395513c10Slinton 
166495513c10Slinton 	case MOU:
166595513c10Slinton 		if( !(instruct&INUNION) ) uerror( "illegal class" );
166695513c10Slinton 		return( class );
166795513c10Slinton 
166895513c10Slinton 	case MOS:
166995513c10Slinton 		if( !(instruct&INSTRUCT) ) uerror( "illegal class" );
167095513c10Slinton 		return( class );
167195513c10Slinton 
167295513c10Slinton 	case MOE:
167395513c10Slinton 		if( instruct & (INSTRUCT|INUNION) ) uerror( "illegal class" );
167495513c10Slinton 		return( class );
167595513c10Slinton 
167695513c10Slinton 	case REGISTER:
167795513c10Slinton 		if( blevel == 0 ) uerror( "illegal register declaration" );
167895513c10Slinton 		else if( regvar >= MINRVAR && cisreg( type ) ) return( class );
167995513c10Slinton 		if( blevel == 1 ) return( PARAM );
168095513c10Slinton 		else return( AUTO );
168195513c10Slinton 
168295513c10Slinton 	case AUTO:
168395513c10Slinton 	case LABEL:
168495513c10Slinton 	case ULABEL:
168595513c10Slinton 		if( blevel < 2 ) uerror( "illegal class" );
168695513c10Slinton 		return( class );
168795513c10Slinton 
168895513c10Slinton 	case PARAM:
168995513c10Slinton 		if( blevel != 1 ) uerror( "illegal class" );
169095513c10Slinton 		return( class );
169195513c10Slinton 
169295513c10Slinton 	case UFORTRAN:
169395513c10Slinton 	case FORTRAN:
169495513c10Slinton # ifdef NOFORTRAN
169595513c10Slinton 			NOFORTRAN;    /* a condition which can regulate the FORTRAN usage */
169695513c10Slinton # endif
169795513c10Slinton 		if( !ISFTN(type) ) uerror( "fortran declaration must apply to function" );
169895513c10Slinton 		else {
169995513c10Slinton 			type = DECREF(type);
170095513c10Slinton 			if( ISFTN(type) || ISARY(type) || ISPTR(type) ) {
170195513c10Slinton 				uerror( "fortran function has wrong type" );
170295513c10Slinton 				}
170395513c10Slinton 			}
170495513c10Slinton 	case EXTERN:
170595513c10Slinton 	case STATIC:
170695513c10Slinton 	case EXTDEF:
170795513c10Slinton 	case TYPEDEF:
170895513c10Slinton 	case USTATIC:
1709c6022034Sralph 		if( blevel == 1 ){
1710c6022034Sralph 			uerror( "illegal class" );
1711c6022034Sralph 			return( PARAM );
1712c6022034Sralph 			}
1713c6022034Sralph 	case STNAME:
1714c6022034Sralph 	case UNAME:
1715c6022034Sralph 	case ENAME:
171695513c10Slinton 		return( class );
171795513c10Slinton 
171895513c10Slinton 	default:
171995513c10Slinton 		cerror( "illegal class: %d", class );
172095513c10Slinton 		/* NOTREACHED */
172195513c10Slinton 
172295513c10Slinton 		}
172395513c10Slinton 	}
172495513c10Slinton 
172595513c10Slinton struct symtab *
mknonuniq(idindex)172695513c10Slinton mknonuniq(idindex) int *idindex; {/* locate a symbol table entry for */
172795513c10Slinton 	/* an occurrence of a nonunique structure member name */
172895513c10Slinton 	/* or field */
172995513c10Slinton 	register i;
173095513c10Slinton 	register struct symtab * sp;
17315a6549aeSdonn 	char *q;
173295513c10Slinton 
173395513c10Slinton 	sp = & stab[ i= *idindex ]; /* position search at old entry */
173495513c10Slinton 	while( sp->stype != TNULL ){ /* locate unused entry */
173595513c10Slinton 		if( ++i >= SYMTSZ ){/* wrap around symbol table */
173695513c10Slinton 			i = 0;
173795513c10Slinton 			sp = stab;
173895513c10Slinton 			}
173995513c10Slinton 		else ++sp;
174095513c10Slinton 		if( i == *idindex ) cerror("Symbol table full");
174195513c10Slinton 		}
174295513c10Slinton 	sp->sflags = SNONUNIQ | SMOS;
174395513c10Slinton 	q = stab[*idindex].sname; /* old entry name */
174495513c10Slinton #ifdef FLEXNAMES
174595513c10Slinton 	sp->sname = stab[*idindex].sname;
174695513c10Slinton #endif
174795513c10Slinton # ifndef BUG1
174895513c10Slinton 	if( ddebug ){
174995513c10Slinton 		printf("\tnonunique entry for %s from %d to %d\n",
175095513c10Slinton 			q, *idindex, i );
175195513c10Slinton 		}
175295513c10Slinton # endif
175395513c10Slinton 	*idindex = i;
175495513c10Slinton #ifndef FLEXNAMES
17555a6549aeSdonn 	{
17565a6549aeSdonn 		char *p = sp->sname;
17575a6549aeSdonn 		for( i=1; i<=NCHNAM; ++i ) /* copy name */
175895513c10Slinton 			if( *p++ = *q /* assign */ ) ++q;
175995513c10Slinton 		}
176095513c10Slinton #endif
176195513c10Slinton 	return ( sp );
176295513c10Slinton 	}
176395513c10Slinton 
lookup(name,s)176495513c10Slinton lookup( name, s) char *name; {
176595513c10Slinton 	/* look up name: must agree with s w.r.t. STAG, SMOS and SHIDDEN */
176695513c10Slinton 
176795513c10Slinton 	register char *p, *q;
17685a6549aeSdonn 	int i, ii;
17695a6549aeSdonn #ifndef FLEXNAMES
17705a6549aeSdonn 	int j;
17715a6549aeSdonn #endif
177295513c10Slinton 	register struct symtab *sp;
177395513c10Slinton 
177495513c10Slinton 	/* compute initial hash index */
177595513c10Slinton # ifndef BUG1
177695513c10Slinton 	if( ddebug > 2 ){
177795513c10Slinton 		printf( "lookup( %s, %d ), stwart=%d, instruct=%d\n", name, s, stwart, instruct );
177895513c10Slinton 		}
177995513c10Slinton # endif
178095513c10Slinton 
178195513c10Slinton 	i = 0;
178295513c10Slinton #ifndef FLEXNAMES
178395513c10Slinton 	for( p=name, j=0; *p != '\0'; ++p ){
178495513c10Slinton 		i += *p;
178595513c10Slinton 		if( ++j >= NCHNAM ) break;
178695513c10Slinton 		}
178795513c10Slinton #else
178895513c10Slinton 	i = (int)name;
178995513c10Slinton #endif
179095513c10Slinton 	i = i%SYMTSZ;
179195513c10Slinton 	sp = &stab[ii=i];
179295513c10Slinton 
179395513c10Slinton 	for(;;){ /* look for name */
179495513c10Slinton 
179595513c10Slinton 		if( sp->stype == TNULL ){ /* empty slot */
179695513c10Slinton 			sp->sflags = s;  /* set STAG, SMOS if needed, turn off all others */
179795513c10Slinton #ifndef FLEXNAMES
179895513c10Slinton 			p = sp->sname;
179995513c10Slinton 			for( j=0; j<NCHNAM; ++j ) if( *p++ = *name ) ++name;
180095513c10Slinton #else
180195513c10Slinton 			sp->sname = name;
180295513c10Slinton #endif
180395513c10Slinton 			sp->stype = UNDEF;
180495513c10Slinton 			sp->sclass = SNULL;
180595513c10Slinton 			return( i );
180695513c10Slinton 			}
180795513c10Slinton 		if( (sp->sflags & (STAG|SMOS|SHIDDEN)) != s ) goto next;
180895513c10Slinton 		p = sp->sname;
180995513c10Slinton 		q = name;
181095513c10Slinton #ifndef FLEXNAMES
181195513c10Slinton 		for( j=0; j<NCHNAM;++j ){
181295513c10Slinton 			if( *p++ != *q ) goto next;
181395513c10Slinton 			if( !*q++ ) break;
181495513c10Slinton 			}
181595513c10Slinton 		return( i );
181695513c10Slinton #else
181795513c10Slinton 		if (p == q)
181895513c10Slinton 			return ( i );
181995513c10Slinton #endif
182095513c10Slinton 	next:
182195513c10Slinton 		if( ++i >= SYMTSZ ){
182295513c10Slinton 			i = 0;
182395513c10Slinton 			sp = stab;
182495513c10Slinton 			}
182595513c10Slinton 		else ++sp;
182695513c10Slinton 		if( i == ii ) cerror( "symbol table full" );
182795513c10Slinton 		}
182895513c10Slinton 	}
182995513c10Slinton 
183095513c10Slinton #ifndef checkst
183195513c10Slinton /* if not debugging, make checkst a macro */
checkst(lev)183295513c10Slinton checkst(lev){
183395513c10Slinton 	register int s, i, j;
183495513c10Slinton 	register struct symtab *p, *q;
183595513c10Slinton 
183695513c10Slinton 	for( i=0, p=stab; i<SYMTSZ; ++i, ++p ){
183795513c10Slinton 		if( p->stype == TNULL ) continue;
183895513c10Slinton 		j = lookup( p->sname, p->sflags&(SMOS|STAG) );
183995513c10Slinton 		if( j != i ){
184095513c10Slinton 			q = &stab[j];
184195513c10Slinton 			if( q->stype == UNDEF ||
184295513c10Slinton 			    q->slevel <= p->slevel ){
184395513c10Slinton #ifndef FLEXNAMES
184495513c10Slinton 				cerror( "check error: %.8s", q->sname );
184595513c10Slinton #else
184695513c10Slinton 				cerror( "check error: %s", q->sname );
184795513c10Slinton #endif
184895513c10Slinton 				}
184995513c10Slinton 			}
185095513c10Slinton #ifndef FLEXNAMES
185195513c10Slinton 		else if( p->slevel > lev ) cerror( "%.8s check at level %d", p->sname, lev );
185295513c10Slinton #else
185395513c10Slinton 		else if( p->slevel > lev ) cerror( "%s check at level %d", p->sname, lev );
185495513c10Slinton #endif
185595513c10Slinton 		}
185695513c10Slinton 	}
185795513c10Slinton #endif
185895513c10Slinton 
185995513c10Slinton struct symtab *
relook(p)186095513c10Slinton relook(p) register struct symtab *p; {  /* look up p again, and see where it lies */
186195513c10Slinton 
186295513c10Slinton 	register struct symtab *q;
186395513c10Slinton 
186495513c10Slinton 	/* I'm not sure that this handles towers of several hidden definitions in all cases */
186595513c10Slinton 	q = &stab[lookup( p->sname, p->sflags&(STAG|SMOS|SHIDDEN) )];
186695513c10Slinton 	/* make relook always point to either p or an empty cell */
186795513c10Slinton 	if( q->stype == UNDEF ){
186895513c10Slinton 		q->stype = TNULL;
186995513c10Slinton 		return(q);
187095513c10Slinton 		}
187195513c10Slinton 	while( q != p ){
187295513c10Slinton 		if( q->stype == TNULL ) break;
187395513c10Slinton 		if( ++q >= &stab[SYMTSZ] ) q=stab;
187495513c10Slinton 		}
187595513c10Slinton 	return(q);
187695513c10Slinton 	}
187795513c10Slinton 
clearst(lev)18782f906f46Smckusick clearst( lev ) register int lev; {
18792f906f46Smckusick 	register struct symtab *p, *q;
18802f906f46Smckusick 	register int temp;
18812f906f46Smckusick 	struct symtab *clist = 0;
188295513c10Slinton 
188395513c10Slinton 	temp = lineno;
188495513c10Slinton 	aobeg();
188595513c10Slinton 
18862f906f46Smckusick 	/* step 1: remove entries */
18872f906f46Smckusick 	while( chaintop-1 > lev ){
18882f906f46Smckusick 		p = schain[--chaintop];
18892f906f46Smckusick 		schain[chaintop] = 0;
18902f906f46Smckusick 		for( ; p; p = q ){
18912f906f46Smckusick 			q = p->snext;
18922f906f46Smckusick 			if( p->stype == TNULL || p->slevel <= lev )
18932f906f46Smckusick 				cerror( "schain botch" );
18942f906f46Smckusick 			lineno = p->suse < 0 ? -p->suse : p->suse;
189595513c10Slinton 			if( p->stype==UNDEF || ( p->sclass==ULABEL && lev<2 ) ){
189695513c10Slinton 				lineno = temp;
189795513c10Slinton #ifndef FLEXNAMES
189895513c10Slinton 				uerror( "%.8s undefined", p->sname );
189995513c10Slinton #else
190095513c10Slinton 				uerror( "%s undefined", p->sname );
190195513c10Slinton #endif
190295513c10Slinton 				}
190395513c10Slinton 			else aocode(p);
190495513c10Slinton # ifndef BUG1
19052f906f46Smckusick 			if( ddebug ){
190695513c10Slinton #ifndef FLEXNAMES
19072f906f46Smckusick 				printf( "removing %.8s", p->sname );
190895513c10Slinton #else
19092f906f46Smckusick 				printf( "removing %s", p->sname );
191095513c10Slinton #endif
19112f906f46Smckusick 				printf( " from stab[%d], flags %o level %d\n",
19122f906f46Smckusick 					p-stab, p->sflags, p->slevel);
19132f906f46Smckusick 				}
191495513c10Slinton # endif
191595513c10Slinton 			if( p->sflags & SHIDES )unhide( p );
191695513c10Slinton 			p->stype = TNULL;
19172f906f46Smckusick 			p->snext = clist;
19182f906f46Smckusick 			clist = p;
191995513c10Slinton 			}
192095513c10Slinton 		}
19212f906f46Smckusick 
19222f906f46Smckusick 	/* step 2: fix any mishashed entries */
19232f906f46Smckusick 	p = clist;
19242f906f46Smckusick 	while( p ){
1925f9db0fcbSdonn 		register struct symtab *next, **t, *r;
19262f906f46Smckusick 
19272f906f46Smckusick 		q = p;
1928cd7b1b55Sdonn 		next = p->snext;
19292f906f46Smckusick 		for(;;){
19302f906f46Smckusick 			if( ++q >= &stab[SYMTSZ] )q = stab;
19312f906f46Smckusick 			if( q == p || q->stype == TNULL )break;
19322f906f46Smckusick 			if( (r = relook(q)) != q ) {
1933883c0895Sdonn 				/* move q in schain list */
1934f9db0fcbSdonn 				t = &schain[q->slevel];
1935f9db0fcbSdonn 				while( *t && *t != q )
1936f9db0fcbSdonn 					t = &(*t)->snext;
1937f9db0fcbSdonn 				if( *t )
1938f9db0fcbSdonn 					*t = r;
1939f9db0fcbSdonn 				else
19400950f3d7Sdonn 					cerror("schain botch 2");
19412f906f46Smckusick 				*r = *q;
194269748699Sdonn 				q->stype = TNULL;
194395513c10Slinton 				}
19442f906f46Smckusick 			}
1945cd7b1b55Sdonn 		p = next;
19462f906f46Smckusick 		}
19472f906f46Smckusick 
194895513c10Slinton 	lineno = temp;
194995513c10Slinton 	aoend();
195095513c10Slinton 	}
195195513c10Slinton 
hide(p)195295513c10Slinton hide( p ) register struct symtab *p; {
195395513c10Slinton 	register struct symtab *q;
195495513c10Slinton 	for( q=p+1; ; ++q ){
195595513c10Slinton 		if( q >= &stab[SYMTSZ] ) q = stab;
195695513c10Slinton 		if( q == p ) cerror( "symbol table full" );
195795513c10Slinton 		if( q->stype == TNULL ) break;
195895513c10Slinton 		}
19592f906f46Smckusick 	*q = *p;
196095513c10Slinton 	p->sflags |= SHIDDEN;
196195513c10Slinton 	q->sflags = (p->sflags&(SMOS|STAG)) | SHIDES;
196295513c10Slinton #ifndef FLEXNAMES
196395513c10Slinton 	if( hflag ) werror( "%.8s redefinition hides earlier one", p->sname );
196495513c10Slinton #else
196595513c10Slinton 	if( hflag ) werror( "%s redefinition hides earlier one", p->sname );
196695513c10Slinton #endif
196795513c10Slinton # ifndef BUG1
196895513c10Slinton 	if( ddebug ) printf( "	%d hidden in %d\n", p-stab, q-stab );
196995513c10Slinton # endif
197095513c10Slinton 	return( idname = q-stab );
197195513c10Slinton 	}
197295513c10Slinton 
unhide(p)197395513c10Slinton unhide( p ) register struct symtab *p; {
197495513c10Slinton 	register struct symtab *q;
19755a6549aeSdonn 	register s;
197695513c10Slinton 
197795513c10Slinton 	s = p->sflags & (SMOS|STAG);
197895513c10Slinton 	q = p;
197995513c10Slinton 
198095513c10Slinton 	for(;;){
198195513c10Slinton 
198295513c10Slinton 		if( q == stab ) q = &stab[SYMTSZ-1];
198395513c10Slinton 		else --q;
198495513c10Slinton 
198595513c10Slinton 		if( q == p ) break;
198695513c10Slinton 
198795513c10Slinton 		if( (q->sflags&(SMOS|STAG)) == s ){
198895513c10Slinton #ifndef FLEXNAMES
19895a6549aeSdonn 			register j;
199095513c10Slinton 			for( j =0; j<NCHNAM; ++j ) if( p->sname[j] != q->sname[j] ) break;
199195513c10Slinton 			if( j == NCHNAM ){ /* found the name */
199295513c10Slinton #else
199395513c10Slinton 			if (p->sname == q->sname) {
199495513c10Slinton #endif
199595513c10Slinton 				q->sflags &= ~SHIDDEN;
199695513c10Slinton # ifndef BUG1
199795513c10Slinton 				if( ddebug ) printf( "unhide uncovered %d from %d\n", q-stab,p-stab);
199895513c10Slinton # endif
199995513c10Slinton 				return;
200095513c10Slinton 				}
200195513c10Slinton 			}
200295513c10Slinton 
200395513c10Slinton 		}
200495513c10Slinton 	cerror( "unhide fails" );
200595513c10Slinton 	}
2006