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