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