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