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