xref: /netbsd/external/bsd/pcc/dist/pcc/cc/ccom/pftn.c (revision 852486b6)
1 /*	Id: pftn.c,v 1.379 2014/07/02 15:31:41 ragge Exp 	*/
2 /*	$NetBSD: pftn.c,v 1.9 2014/07/24 20:12:50 plunky Exp $	*/
3 /*
4  * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 /*
28  * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
29  *
30  * Redistribution and use in source and binary forms, with or without
31  * modification, are permitted provided that the following conditions
32  * are met:
33  *
34  * Redistributions of source code and documentation must retain the above
35  * copyright notice, this list of conditions and the following disclaimer.
36  * Redistributions in binary form must reproduce the above copyright
37  * notice, this list of conditionsand the following disclaimer in the
38  * documentation and/or other materials provided with the distribution.
39  * All advertising materials mentioning features or use of this software
40  * must display the following acknowledgement:
41  * 	This product includes software developed or owned by Caldera
42  *	International, Inc.
43  * Neither the name of Caldera International, Inc. nor the names of other
44  * contributors may be used to endorse or promote products derived from
45  * this software without specific prior written permission.
46  *
47  * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
48  * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
49  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
50  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
51  * DISCLAIMED.  IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE
52  * FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55  * HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT,
56  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
57  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
58  * POSSIBILITY OF SUCH DAMAGE.
59  */
60 
61 /*
62  * Many changes from the 32V sources, among them:
63  * - New symbol table manager (moved to another file).
64  * - Prototype saving/checks.
65  */
66 
67 # include "pass1.h"
68 #include "unicode.h"
69 
70 #include "cgram.h"
71 
72 struct symtab *cftnsp;
73 int arglistcnt, dimfuncnt;	/* statistics */
74 int symtabcnt, suedefcnt;	/* statistics */
75 int autooff,		/* the next unused automatic offset */
76     maxautooff,		/* highest used automatic offset in function */
77     argoff;		/* the next unused argument offset */
78 int retlab = NOLAB;	/* return label for subroutine */
79 int brklab;
80 int contlab;
81 int flostat;
82 int blevel;
83 int reached, prolab;
84 
85 struct params;
86 
87 #define MKTY(p, t, d, s) r = talloc(); *r = *p; \
88 	r = argcast(r, t, d, s); *p = *r; nfree(r);
89 
90 /*
91  * Linked list stack while reading in structs.
92  */
93 struct rstack {
94 	struct	rstack *rnext;
95 	int	rsou;
96 	int	rstr;
97 	struct	symtab *rsym;
98 	struct	symtab *rb;
99 	struct	attr *ap;
100 	int	flags;
101 #define	LASTELM	1
102 } *rpole;
103 
104 /*
105  * Linked list for parameter (and struct elements) declaration.
106  */
107 static struct params {
108 	struct params *prev;
109 	struct symtab *sym;
110 } *lparam;
111 static int nparams;
112 
113 /* defines used for getting things off of the initialization stack */
114 
115 NODE *arrstk[10];
116 int arrstkp;
117 static int intcompare;
118 NODE *parlink;
119 
120 void fixtype(NODE *p, int class);
121 int fixclass(int class, TWORD type);
122 static void dynalloc(struct symtab *p, int *poff);
123 static void evalidx(struct symtab *p);
124 int isdyn(struct symtab *p);
125 void inforce(OFFSZ n);
126 void vfdalign(int n);
127 static void ssave(struct symtab *);
128 #ifdef PCC_DEBUG
129 static void alprint(union arglist *al, int in);
130 #endif
131 static void lcommadd(struct symtab *sp);
132 static NODE *mkcmplx(NODE *p, TWORD dt);
133 extern int fun_inline;
134 
135 void
136 defid(NODE *q, int class)
137 {
138 	defid2(q, class, 0);
139 }
140 
141 /*
142  * Declaration of an identifier.  Handles redeclarations, hiding,
143  * incomplete types and forward declarations.
144  *
145  * q is a TYPE node setup after parsing with n_type, n_df and n_ap.
146  * n_sp is a pointer to the not-yet initalized symbol table entry
147  * unless it's a redeclaration or supposed to hide a variable.
148  */
149 
150 void
151 defid2(NODE *q, int class, char *astr)
152 {
153 	struct attr *ap;
154 	struct symtab *p;
155 	TWORD type, qual;
156 	TWORD stp, stq;
157 	int scl;
158 	union dimfun *dsym, *ddef;
159 	int slev, temp, changed;
160 
161 	if (q == NIL)
162 		return;  /* an error was detected */
163 
164 #ifdef GCC_COMPAT
165 	gcc_modefix(q);
166 #endif
167 	p = q->n_sp;
168 
169 	if (p->sname == NULL)
170 		cerror("defining null identifier");
171 
172 #ifdef PCC_DEBUG
173 	if (ddebug) {
174 		printf("defid(%s '%s'(%p), ", p->sname, p->soname , p);
175 		tprint(q->n_type, q->n_qual);
176 		printf(", %s, (%p)), level %d\n\t", scnames(class),
177 		    q->n_df, blevel);
178 #ifdef GCC_COMPAT
179 		dump_attr(q->n_ap);
180 #endif
181 	}
182 #endif
183 
184 	fixtype(q, class);
185 
186 	type = q->n_type;
187 	qual = q->n_qual;
188 	class = fixclass(class, type);
189 
190 	stp = p->stype;
191 	stq = p->squal;
192 	slev = p->slevel;
193 
194 #ifdef PCC_DEBUG
195 	if (ddebug) {
196 		printf("	modified to ");
197 		tprint(type, qual);
198 		printf(", %s\n", scnames(class));
199 		printf("	previous def'n: ");
200 		tprint(stp, stq);
201 		printf(", %s, (%p,%p)), level %d\n",
202 		    scnames(p->sclass), p->sdf, p->sap, slev);
203 	}
204 #endif
205 
206 	if (blevel == 1) {
207 		switch (class) {
208 		default:
209 			if (!(class&FIELD) && !ISFTN(type))
210 				uerror("declared argument %s missing",
211 				    p->sname );
212 			break;
213 		case MOS:
214 		case MOU:
215 			cerror("field5");
216 		case TYPEDEF:
217 		case PARAM:
218 			break;
219 		}
220 	}
221 
222 	if (stp == UNDEF)
223 		goto enter; /* New symbol */
224 
225 	if (type != stp)
226 		goto mismatch;
227 
228 	if (blevel > slev && (class == AUTO || class == REGISTER))
229 		/* new scope */
230 		goto mismatch;
231 
232 	/*
233 	 * test (and possibly adjust) dimensions.
234 	 * also check that prototypes are correct.
235 	 */
236 	dsym = p->sdf;
237 	ddef = q->n_df;
238 	changed = 0;
239 	for (temp = type; temp & TMASK; temp = DECREF(temp)) {
240 		if (ISARY(temp)) {
241 			if (dsym->ddim == NOOFFSET) {
242 				dsym->ddim = ddef->ddim;
243 				changed = 1;
244 			} else if (ddef->ddim != NOOFFSET &&
245 			    dsym->ddim!=ddef->ddim) {
246 				goto mismatch;
247 			}
248 			++dsym;
249 			++ddef;
250 		} else if (ISFTN(temp)) {
251 			/* add a late-defined prototype here */
252 			if (!oldstyle && dsym->dfun == NULL)
253 				dsym->dfun = ddef->dfun;
254 			if (!oldstyle && ddef->dfun != NULL &&
255 			    chkftn(dsym->dfun, ddef->dfun))
256 				uerror("declaration doesn't match prototype");
257 			dsym++, ddef++;
258 		}
259 	}
260 #ifdef STABS
261 	if (changed && gflag)
262 		stabs_chgsym(p); /* symbol changed */
263 #endif
264 
265 	/* check that redeclarations are to the same structure */
266 	if (temp == STRTY || temp == UNIONTY) {
267 		if (strmemb(p->sap) != strmemb(q->n_ap))
268 			goto mismatch;
269 	}
270 
271 	scl = p->sclass;
272 
273 #ifdef PCC_DEBUG
274 	if (ddebug)
275 		printf("	previous class: %s\n", scnames(scl));
276 #endif
277 
278 	/*
279 	 * Its allowed to add attributes to existing declarations.
280 	 * Be careful though not to trash existing attributes.
281 	 * XXX - code below is probably not correct.
282 	 */
283 	if (p->sap && p->sap->atype <= ATTR_MAX) {
284 		/* nothing special, just overwrite */
285 		p->sap = q->n_ap;
286 	} else {
287 		if (p->slevel == blevel) {
288 			for (ap = q->n_ap; ap; ap = ap->next) {
289 				if (ap->atype > ATTR_MAX)
290 					p->sap = attr_add(p->sap, attr_dup(ap, 3));
291 			}
292 		} else
293 			p->sap = q->n_ap;
294 	}
295 
296 	if (class & FIELD)
297 		cerror("field1");
298 	switch(class) {
299 
300 	case EXTERN:
301 		if (astr)
302 			p->soname = astr;
303 		switch( scl ){
304 		case STATIC:
305 		case USTATIC:
306 			if( slev==0 )
307 				goto done;
308 			break;
309 		case EXTDEF:
310 		case EXTERN:
311 			goto done;
312 		case SNULL:
313 			if (p->sflags & SINLINE) {
314 				p->sclass = EXTDEF;
315 				inline_ref(p);
316 				goto done;
317 			}
318 			break;
319 		}
320 		break;
321 
322 	case STATIC:
323 		if (astr)
324 			p->soname = astr;
325 		if (scl==USTATIC || (scl==EXTERN && blevel==0)) {
326 			p->sclass = STATIC;
327 			goto done;
328 		}
329 		if (changed || (scl == STATIC && blevel == slev))
330 			goto done; /* identical redeclaration */
331 		break;
332 
333 	case USTATIC:
334 		if (scl==STATIC || scl==USTATIC)
335 			goto done;
336 		break;
337 
338 	case TYPEDEF:
339 		if (scl == class)
340 			goto done;
341 		break;
342 
343 	case MOU:
344 	case MOS:
345 		cerror("field6");
346 
347 	case EXTDEF:
348 		switch (scl) {
349 		case EXTERN:
350 			p->sclass = EXTDEF;
351 			goto done;
352 		case USTATIC:
353 			p->sclass = STATIC;
354 			goto done;
355 		case SNULL:
356 #ifdef GCC_COMPAT
357 			/*
358 			 * Handle redeclarations of inlined functions.
359 			 * This is allowed if the previous declaration is of
360 			 * type gnu_inline.
361 			 */
362 			if (attr_find(p->sap, GCC_ATYP_GNU_INLINE))
363 				goto done;
364 #endif
365 			break;
366 		}
367 		break;
368 
369 	case AUTO:
370 	case REGISTER:
371 		break;  /* mismatch.. */
372 	case SNULL:
373 		if (fun_inline && ISFTN(type)) {
374 			if (scl == EXTERN) {
375 				p->sclass = EXTDEF;
376 				inline_ref(p);
377 			}
378 			goto done;
379 		}
380 		break;
381 	}
382 
383 	mismatch:
384 
385 	/*
386 	 * Only allowed for automatic variables.
387 	 */
388 	if ((blevel == 2 && slev == 1) || blevel <= slev || class == EXTERN) {
389 		uerror("redeclaration of %s", p->sname);
390 		return;
391 	}
392 	q->n_sp = p = hide(p);
393 
394 	enter:  /* make a new entry */
395 
396 #ifdef PCC_DEBUG
397 	if(ddebug)
398 		printf("	new entry made\n");
399 #endif
400 	p->stype = type;
401 	p->squal = qual;
402 	p->sclass = (char)class;
403 	p->slevel = (char)blevel;
404 	p->soffset = NOOFFSET;
405 	if (q->n_ap)
406 		p->sap = attr_add(q->n_ap, p->sap);
407 
408 	/* copy dimensions */
409 	p->sdf = q->n_df;
410 	/* Do not save param info for old-style functions */
411 	if (ISFTN(type) && oldstyle)
412 		p->sdf->dfun = NULL;
413 
414 	if (arrstkp)
415 		evalidx(p);
416 
417 	/* allocate offsets */
418 	if (class&FIELD) {
419 		cerror("field2");  /* new entry */
420 	} else switch (class) {
421 
422 	case REGISTER:
423 		if (astr != NULL)
424 			werror("no register assignment (yet)");
425 		p->sclass = class = AUTO;
426 		/* FALLTHROUGH */
427 	case AUTO:
428 		if (isdyn(p)) {
429 			p->sflags |= SDYNARRAY;
430 			dynalloc(p, &autooff);
431 		} else
432 			oalloc(p, &autooff);
433 		break;
434 
435 	case PARAM:
436 		if (q->n_type != FARG)
437 			oalloc(p, &argoff);
438 		break;
439 
440 	case STATIC:
441 	case EXTDEF:
442 	case EXTERN:
443 		p->soffset = getlab();
444 		/* FALLTHROUGH */
445 	case USTATIC:
446 		if (astr)
447 			p->soname = astr;
448 		break;
449 
450 	case MOU:
451 	case MOS:
452 		cerror("field7");
453 	case SNULL:
454 #ifdef notdef
455 		if (fun_inline) {
456 			p->slevel = 1;
457 			p->soffset = getlab();
458 		}
459 #endif
460 		break;
461 	}
462 
463 #ifdef STABS
464 	if (gflag && p->stype != FARG)
465 		stabs_newsym(p);
466 #endif
467 
468 done:
469 	fixdef(p);	/* Leave last word to target */
470 #ifndef HAVE_WEAKREF
471 	{
472 		struct attr *at;
473 
474 		/* Refer renamed function */
475 		if ((at = attr_find(p->sap, GCC_ATYP_WEAKREF)))
476 			p->soname = at->sarg(0);
477 	}
478 #endif
479 #ifdef PCC_DEBUG
480 	if (ddebug) {
481 		printf( "	sdf, offset: %p, %d\n\t",
482 		    p->sdf, p->soffset);
483 #ifdef GCC_COMPAT
484 		dump_attr(p->sap);
485 #endif
486 	}
487 #endif
488 }
489 
490 void
491 ssave(struct symtab *sym)
492 {
493 	struct params *p;
494 
495 	p = tmpalloc(sizeof(struct params));
496 	p->prev = lparam;
497 	p->sym = sym;
498 	lparam = p;
499 }
500 
501 /*
502  * end of function
503  */
504 void
505 ftnend(void)
506 {
507 #ifdef GCC_COMPAT
508 	struct attr *gc, *gd;
509 #endif
510 	extern int *mkclabs(void);
511 	extern NODE *cftnod;
512 	extern struct savbc *savbc;
513 	extern struct swdef *swpole;
514 	extern int tvaloff;
515 	char *c;
516 
517 	if (retlab != NOLAB && nerrors == 0) { /* inside a real function */
518 		plabel(retlab);
519 		if (cftnod)
520 			ecomp(buildtree(FORCE, cftnod, NIL));
521 		efcode(); /* struct return handled here */
522 		if ((c = cftnsp->soname) == NULL)
523 			c = addname(exname(cftnsp->sname));
524 		SETOFF(maxautooff, ALCHAR);
525 		send_passt(IP_EPILOG, maxautooff/SZCHAR, c,
526 		    cftnsp->stype, cftnsp->sclass == EXTDEF,
527 		    retlab, tvaloff, mkclabs());
528 	}
529 
530 	cftnod = NIL;
531 	tcheck();
532 	brklab = contlab = retlab = NOLAB;
533 	flostat = 0;
534 	if (nerrors == 0) {
535 		if (savbc != NULL)
536 			cerror("bcsave error");
537 		if (lparam != NULL)
538 			cerror("parameter reset error");
539 		if (swpole != NULL)
540 			cerror("switch error");
541 	}
542 #ifdef GCC_COMPAT
543 	if (cftnsp) {
544 		gc = attr_find(cftnsp->sap, GCC_ATYP_CONSTRUCTOR);
545 		gd = attr_find(cftnsp->sap, GCC_ATYP_DESTRUCTOR);
546 		if (gc || gd) {
547 			struct symtab sts = *cftnsp;
548 			NODE *p;
549 			sts.stype = INCREF(sts.stype);
550 			p = nametree(&sts);
551 			p->n_op = ICON;
552 			if (gc) {
553 				locctr(CTORS, NULL);
554 				inval(0, SZPOINT(0), p);
555 			}
556 			if (gd) {
557 				locctr(DTORS, NULL);
558 				inval(0, SZPOINT(0), p);
559 			}
560 			tfree(p);
561 		}
562 	}
563 #endif
564 	savbc = NULL;
565 	lparam = NULL;
566 	cftnsp = NULL;
567 	maxautooff = autooff = AUTOINIT;
568 	reached = 1;
569 
570 	if (isinlining)
571 		inline_end();
572 	inline_prtout();
573 
574 	tmpfree(); /* Release memory resources */
575 }
576 
577 static struct symtab nulsym = {
578 	NULL, 0, 0, 0, 0, "null", "null", INT, 0, NULL, NULL
579 };
580 
581 void
582 dclargs(void)
583 {
584 	union dimfun *df;
585 	union arglist *al, *al2, *alb;
586 	struct params *a;
587 	struct symtab *p, **parr = NULL; /* XXX gcc */
588 	int i;
589 
590 	/*
591 	 * Deal with fun(void) properly.
592 	 */
593 	if (nparams == 1 && lparam->sym && lparam->sym->stype == VOID)
594 		goto done;
595 
596 	/*
597 	 * Generate a list for bfcode().
598 	 * Parameters were pushed in reverse order.
599 	 */
600 	if (nparams != 0)
601 		parr = tmpalloc(sizeof(struct symtab *) * nparams);
602 
603 	if (nparams)
604 	    for (a = lparam, i = 0; a != NULL; a = a->prev) {
605 		p = a->sym;
606 		parr[i++] = p;
607 		if (p == NULL) {
608 			uerror("parameter %d name missing", i);
609 			p = &nulsym; /* empty symtab */
610 		}
611 		if (p->stype == FARG)
612 			p->stype = INT;
613 		if (ISARY(p->stype)) {
614 			p->stype += (PTR-ARY);
615 			p->sdf++;
616 		} else if (ISFTN(p->stype)) {
617 			werror("function declared as argument");
618 			p->stype = INCREF(p->stype);
619 		}
620 #ifdef STABS
621 		if (gflag)
622 			stabs_newsym(p);
623 #endif
624 	}
625 	if (oldstyle && (df = cftnsp->sdf) && (al = df->dfun)) {
626 		/*
627 		 * Check against prototype of oldstyle function.
628 		 */
629 		alb = al2 = tmpalloc(sizeof(union arglist) * nparams * 3 + 1);
630 		for (i = 0; i < nparams; i++) {
631 			TWORD type = parr[i]->stype;
632 			(al2++)->type = type;
633 			if (ISSOU(BTYPE(type)))
634 				(al2++)->sap = parr[i]->sap;
635 			while (!ISFTN(type) && !ISARY(type) && type > BTMASK)
636 				type = DECREF(type);
637 			if (type > BTMASK)
638 				(al2++)->df = parr[i]->sdf;
639 		}
640 		al2->type = TNULL;
641 		intcompare = 1;
642 		if (chkftn(al, alb))
643 			uerror("function doesn't match prototype");
644 		intcompare = 0;
645 
646 	}
647 
648 	if (oldstyle && nparams) {
649 		/* Must recalculate offset for oldstyle args here */
650 		argoff = ARGINIT;
651 		for (i = 0; i < nparams; i++) {
652 			parr[i]->soffset = NOOFFSET;
653 			oalloc(parr[i], &argoff);
654 		}
655 	}
656 
657 done:	autooff = AUTOINIT;
658 
659 	plabel(prolab); /* after prolog, used in optimization */
660 	retlab = getlab();
661 	bfcode(parr, nparams);
662 	if (fun_inline && (xinline
663 #ifdef GCC_COMPAT
664  || attr_find(cftnsp->sap, GCC_ATYP_ALW_INL)
665 #endif
666 		))
667 		inline_args(parr, nparams);
668 	plabel(getlab()); /* used when spilling */
669 	if (parlink)
670 		ecomp(parlink);
671 	parlink = NIL;
672 	lparam = NULL;
673 	nparams = 0;
674 	symclear(1);	/* In case of function pointer args */
675 }
676 
677 /*
678  * basic attributes for structs and enums
679  */
680 static struct attr *
681 seattr(void)
682 {
683 	return attr_add(attr_new(ATTR_ALIGNED, 4), attr_new(ATTR_STRUCT, 2));
684 }
685 
686 /*
687  * Struct/union/enum symtab construction.
688  */
689 static void
690 defstr(struct symtab *sp, int class)
691 {
692 	sp->sclass = (char)class;
693 	if (class == STNAME)
694 		sp->stype = STRTY;
695 	else if (class == UNAME)
696 		sp->stype = UNIONTY;
697 	else if (class == ENAME)
698 		sp->stype = ENUMTY;
699 }
700 
701 /*
702  * Declare a struct/union/enum tag.
703  * If not found, create a new tag with UNDEF type.
704  */
705 static struct symtab *
706 deftag(char *name, int class)
707 {
708 	struct symtab *sp;
709 
710 	if ((sp = lookup(name, STAGNAME))->sap == NULL) {
711 		/* New tag */
712 		defstr(sp, class);
713 	} else if (sp->sclass != class)
714 		uerror("tag %s redeclared", name);
715 	return sp;
716 }
717 
718 /*
719  * reference to a structure or union, with no definition
720  */
721 NODE *
722 rstruct(char *tag, int soru)
723 {
724 	struct symtab *sp;
725 
726 	sp = deftag(tag, soru);
727 	if (sp->sap == NULL)
728 		sp->sap = seattr();
729 	return mkty(sp->stype, 0, sp->sap);
730 }
731 
732 static int enumlow, enumhigh;
733 int enummer;
734 
735 /*
736  * Declare a member of enum.
737  */
738 void
739 moedef(char *name)
740 {
741 	struct symtab *sp;
742 
743 	sp = lookup(name, SNORMAL);
744 	if (sp->stype == UNDEF || (sp->slevel < blevel)) {
745 		if (sp->stype != UNDEF)
746 			sp = hide(sp);
747 		sp->stype = INT; /* always */
748 		sp->sclass = MOE;
749 		sp->soffset = enummer;
750 	} else
751 		uerror("%s redeclared", name);
752 	if (enummer < enumlow)
753 		enumlow = enummer;
754 	if (enummer > enumhigh)
755 		enumhigh = enummer;
756 	enummer++;
757 }
758 
759 /*
760  * Declare an enum tag.  Complain if already defined.
761  */
762 struct symtab *
763 enumhd(char *name)
764 {
765 	struct attr *ap;
766 	struct symtab *sp;
767 
768 	enummer = enumlow = enumhigh = 0;
769 	if (name == NULL)
770 		return NULL;
771 
772 	sp = deftag(name, ENAME);
773 	if (sp->stype != ENUMTY) {
774 		if (sp->slevel == blevel)
775 			uerror("%s redeclared", name);
776 		sp = hide(sp);
777 		defstr(sp, ENAME);
778 	}
779 	if (sp->sap == NULL)
780 		ap = sp->sap = attr_new(ATTR_STRUCT, 4);
781 	else
782 		ap = attr_find(sp->sap, ATTR_STRUCT);
783 	ap->amlist = sp;
784 	return sp;
785 }
786 
787 /*
788  * finish declaration of an enum
789  */
790 NODE *
791 enumdcl(struct symtab *sp)
792 {
793 	NODE *p;
794 	TWORD t;
795 
796 #ifdef ENUMSIZE
797 	t = ENUMSIZE(enumhigh, enumlow);
798 #else
799 	t = ctype(enumlow < 0 ? INT : UNSIGNED);
800 #ifdef notdef
801 	if (enumhigh <= MAX_CHAR && enumlow >= MIN_CHAR)
802 		t = ctype(CHAR);
803 	else if (enumhigh <= MAX_SHORT && enumlow >= MIN_SHORT)
804 		t = ctype(SHORT);
805 	else
806 		t = ctype(INT);
807 #endif
808 #endif
809 
810 	if (sp)
811 		sp->stype = t;
812 	p = mkty(t, 0, 0);
813 	p->n_sp = sp;
814 	return p;
815 }
816 
817 /*
818  * Handle reference to an enum
819  */
820 NODE *
821 enumref(char *name)
822 {
823 	struct symtab *sp;
824 	NODE *p;
825 
826 	sp = lookup(name, STAGNAME);
827 
828 #ifdef notdef
829 	/*
830 	 * 6.7.2.3 Clause 2:
831 	 * "A type specifier of the form 'enum identifier' without an
832 	 *  enumerator list shall only appear after the type it specifies
833 	 *  is complete."
834 	 */
835 	if (sp->sclass != ENAME)
836 		uerror("enum %s undeclared", name);
837 #endif
838 	if (sp->sclass == SNULL) {
839 		/* declare existence of enum */
840 		sp = enumhd(name);
841 		sp->stype = ENUMTY;
842 	}
843 
844 	p = mkty(sp->stype, 0, sp->sap);
845 	p->n_sp = sp;
846 	return p;
847 }
848 
849 /*
850  * begining of structure or union declaration
851  * It's an error if this routine is called twice with the same struct.
852  */
853 struct rstack *
854 bstruct(char *name, int soru, NODE *gp)
855 {
856 	struct rstack *r;
857 	struct symtab *sp;
858 	struct attr *ap, *gap;
859 
860 #ifdef GCC_COMPAT
861 	gap = gp ? gcc_attr_parse(gp) : NULL;
862 #else
863 	gap = NULL;
864 #endif
865 
866 	if (name != NULL) {
867 		sp = deftag(name, soru);
868 		if (sp->sap == NULL)
869 			sp->sap = seattr();
870 		ap = attr_find(sp->sap, ATTR_ALIGNED);
871 		if (ap->iarg(0) != 0) {
872 			if (sp->slevel < blevel) {
873 				sp = hide(sp);
874 				defstr(sp, soru);
875 				sp->sap = seattr();
876 			} else
877 				uerror("%s redeclared", name);
878 		}
879 		gap = sp->sap = attr_add(sp->sap, gap);
880 	} else {
881 		gap = attr_add(seattr(), gap);
882 		sp = NULL;
883 	}
884 
885 	r = tmpcalloc(sizeof(struct rstack));
886 	r->rsou = soru;
887 	r->rsym = sp;
888 	r->rb = NULL;
889 	r->ap = gap;
890 	r->rnext = rpole;
891 	rpole = r;
892 
893 	return r;
894 }
895 
896 /*
897  * Called after a struct is declared to restore the environment.
898  * - If ALSTRUCT is defined, this will be the struct alignment and the
899  *   struct size will be a multiple of ALSTRUCT, otherwise it will use
900  *   the alignment of the largest struct member.
901  */
902 NODE *
903 dclstruct(struct rstack *r)
904 {
905 	NODE *n;
906 	struct attr *aps, *apb;
907 	struct symtab *sp;
908 	int al, sa, sz;
909 
910 	apb = attr_find(r->ap, ATTR_ALIGNED);
911 	aps = attr_find(r->ap, ATTR_STRUCT);
912 	aps->amlist = r->rb;
913 
914 #ifdef ALSTRUCT
915 	al = ALSTRUCT;
916 #else
917 	al = ALCHAR;
918 #endif
919 
920 	/*
921 	 * extract size and alignment, calculate offsets
922 	 */
923 	for (sp = r->rb; sp; sp = sp->snext) {
924 		sa = talign(sp->stype, sp->sap);
925 		if (sp->sclass & FIELD)
926 			sz = sp->sclass&FLDSIZ;
927 		else
928 			sz = (int)tsize(sp->stype, sp->sdf, sp->sap);
929 		if (sz > rpole->rstr)
930 			rpole->rstr = sz;  /* for use with unions */
931 		/*
932 		 * set al, the alignment, to the lcm of the alignments
933 		 * of the members.
934 		 */
935 		SETOFF(al, sa);
936 	}
937 
938 	SETOFF(rpole->rstr, al);
939 
940 	aps->amsize = rpole->rstr;
941 	apb->iarg(0) = al;
942 
943 #ifdef PCC_DEBUG
944 	if (ddebug) {
945 		printf("dclstruct(%s): size=%d, align=%d\n",
946 		    r->rsym ? r->rsym->sname : "??",
947 		    aps->amsize, apb->iarg(0));
948 	}
949 	if (ddebug>1) {
950 		printf("\tsize %d align %d link %p\n",
951 		    aps->amsize, apb->iarg(0), aps->amlist);
952 		for (sp = aps->amlist; sp != NULL; sp = sp->snext) {
953 			printf("\tmember %s(%p)\n", sp->sname, sp);
954 		}
955 	}
956 #endif
957 
958 #ifdef STABS
959 	if (gflag)
960 		stabs_struct(r->rsym, r->ap);
961 #endif
962 
963 	rpole = r->rnext;
964 	n = mkty(r->rsou == STNAME ? STRTY : UNIONTY, 0, r->ap);
965 	n->n_sp = r->rsym;
966 
967 	n->n_qual |= 1; /* definition place XXX used by attributes */
968 	return n;
969 }
970 
971 /*
972  * Add a new member to the current struct or union being declared.
973  */
974 void
975 soumemb(NODE *n, char *name, int class)
976 {
977 	struct symtab *sp, *lsp;
978 	int incomp, tsz, al;
979 	TWORD t;
980 
981 	if (rpole == NULL)
982 		cerror("soumemb");
983 
984 	/* check if tag name exists */
985 	lsp = NULL;
986 	for (sp = rpole->rb; sp != NULL; lsp = sp, sp = sp->snext)
987 		if (*name != '*' && sp->sname == name)
988 			uerror("redeclaration of %s", name);
989 
990 	sp = getsymtab(name, SMOSNAME);
991 	if (rpole->rb == NULL)
992 		rpole->rb = sp;
993 	else
994 		lsp->snext = sp;
995 
996 	n->n_sp = sp;
997 	sp->stype = n->n_type;
998 	sp->squal = n->n_qual;
999 	sp->slevel = blevel;
1000 	sp->sap = n->n_ap;
1001 	sp->sdf = n->n_df;
1002 
1003 	if (class & FIELD) {
1004 		sp->sclass = (char)class;
1005 		falloc(sp, class&FLDSIZ, NIL);
1006 	} else if (rpole->rsou == STNAME || rpole->rsou == UNAME) {
1007 		sp->sclass = rpole->rsou == STNAME ? MOS : MOU;
1008 		if (sp->sclass == MOU)
1009 			rpole->rstr = 0;
1010 		al = talign(sp->stype, sp->sap);
1011 		tsz = (int)tsize(sp->stype, sp->sdf, sp->sap);
1012 		sp->soffset = upoff(tsz, al, &rpole->rstr);
1013 	}
1014 
1015 	/*
1016 	 * 6.7.2.1 clause 16:
1017 	 * "...the last member of a structure with more than one
1018 	 *  named member may have incomplete array type;"
1019 	 */
1020 	if (ISARY(sp->stype) && sp->sdf->ddim == NOOFFSET)
1021 		incomp = 1;
1022 	else
1023 		incomp = 0;
1024 	if ((rpole->flags & LASTELM) || (rpole->rb == sp && incomp == 1))
1025 		uerror("incomplete array in struct");
1026 	if (incomp == 1)
1027 		rpole->flags |= LASTELM;
1028 
1029 	/*
1030 	 * 6.7.2.1 clause 2:
1031 	 * "...such a structure shall not be a member of a structure
1032 	 *  or an element of an array."
1033 	 */
1034 	t = sp->stype;
1035 	if (rpole->rsou != STNAME || BTYPE(t) != STRTY)
1036 		return; /* not for unions */
1037 	while (ISARY(t))
1038 		t = DECREF(t);
1039 	if (ISPTR(t))
1040 		return;
1041 
1042 	if ((lsp = strmemb(sp->sap)) != NULL) {
1043 		for (; lsp->snext; lsp = lsp->snext)
1044 			;
1045 		if (ISARY(lsp->stype) && lsp->snext &&
1046 		    lsp->sdf->ddim == NOOFFSET)
1047 			uerror("incomplete struct in struct");
1048 	}
1049 }
1050 
1051 /*
1052  * error printing routine in parser
1053  */
1054 void
1055 yyerror(char *s)
1056 {
1057 	uerror(s);
1058 }
1059 
1060 void yyaccpt(void);
1061 void
1062 yyaccpt(void)
1063 {
1064 	ftnend();
1065 }
1066 
1067 /*
1068  * p is top of type list given to tymerge later.
1069  * Find correct CALL node and declare parameters from there.
1070  */
1071 void
1072 ftnarg(NODE *p)
1073 {
1074 	NODE *q;
1075 
1076 #ifdef PCC_DEBUG
1077 	if (ddebug > 2)
1078 		printf("ftnarg(%p)\n", p);
1079 #endif
1080 	/*
1081 	 * Push argument symtab entries onto param stack in reverse order,
1082 	 * due to the nature of the stack it will be reclaimed correct.
1083 	 */
1084 	for (; p->n_op != NAME; p = p->n_left) {
1085 		if (p->n_op == UCALL && p->n_left->n_op == NAME)
1086 			return;	/* Nothing to enter */
1087 		if (p->n_op == CALL && p->n_left->n_op == NAME)
1088 			break;
1089 	}
1090 
1091 	p = p->n_right;
1092 	while (p->n_op == CM) {
1093 		q = p->n_right;
1094 		if (q->n_op != ELLIPSIS) {
1095 			ssave(q->n_sp);
1096 			nparams++;
1097 #ifdef PCC_DEBUG
1098 			if (ddebug > 2)
1099 				printf("	saving sym %s (%p) from (%p)\n",
1100 				    q->n_sp->sname, q->n_sp, q);
1101 #endif
1102 		}
1103 		p = p->n_left;
1104 	}
1105 	ssave(p->n_sp);
1106 	if (p->n_type != VOID)
1107 		nparams++;
1108 
1109 #ifdef PCC_DEBUG
1110 	if (ddebug > 2)
1111 		printf("	saving sym %s (%p) from (%p)\n",
1112 		    nparams ? p->n_sp->sname : "<noname>", p->n_sp, p);
1113 #endif
1114 }
1115 
1116 /*
1117  * compute the alignment of an object with type ty, sizeoff index s
1118  */
1119 int
1120 talign(unsigned int ty, struct attr *apl)
1121 {
1122 	struct attr *al;
1123 	int a;
1124 
1125 	for (; ty > BTMASK; ty = DECREF(ty)) {
1126 		switch (ty & TMASK) {
1127 		case PTR:
1128 			return(ALPOINT);
1129 		case ARY:
1130 			continue;
1131 		case FTN:
1132 			cerror("compiler takes alignment of function");
1133 		}
1134 	}
1135 
1136 	/* check for alignment attribute */
1137 	if ((al = attr_find(apl, ATTR_ALIGNED))) {
1138 		if ((a = al->iarg(0)) == 0) {
1139 			uerror("no alignment");
1140 			a = ALINT;
1141 		}
1142 		return a;
1143 	}
1144 
1145 #ifndef NO_COMPLEX
1146 	if (ISITY(ty))
1147 		ty -= (FIMAG-FLOAT);
1148 #endif
1149 	ty = BTYPE(ty);
1150 	if (ty >= CHAR && ty <= ULONGLONG && ISUNSIGNED(ty))
1151 		ty = DEUNSIGN(ty);
1152 
1153 	switch (ty) {
1154 	case BOOL: a = ALBOOL; break;
1155 	case CHAR: a = ALCHAR; break;
1156 	case SHORT: a = ALSHORT; break;
1157 	case INT: a = ALINT; break;
1158 	case LONG: a = ALLONG; break;
1159 	case LONGLONG: a = ALLONGLONG; break;
1160 	case FLOAT: a = ALFLOAT; break;
1161 	case DOUBLE: a = ALDOUBLE; break;
1162 	case LDOUBLE: a = ALLDOUBLE; break;
1163 	default:
1164 		uerror("no alignment");
1165 		a = ALINT;
1166 	}
1167 	return a;
1168 }
1169 
1170 short sztable[] = { 0, SZBOOL, SZCHAR, SZCHAR, SZSHORT, SZSHORT, SZINT, SZINT,
1171 	SZLONG, SZLONG, SZLONGLONG, SZLONGLONG, SZFLOAT, SZDOUBLE, SZLDOUBLE };
1172 
1173 /* compute the size associated with type ty,
1174  *  dimoff d, and sizoff s */
1175 /* BETTER NOT BE CALLED WHEN t, d, and s REFER TO A BIT FIELD... */
1176 OFFSZ
1177 tsize(TWORD ty, union dimfun *d, struct attr *apl)
1178 {
1179 	struct attr *ap, *ap2;
1180 	OFFSZ mult, sz;
1181 
1182 	mult = 1;
1183 
1184 	for (; ty > BTMASK; ty = DECREF(ty)) {
1185 		switch (ty & TMASK) {
1186 
1187 		case FTN:
1188 			uerror( "cannot take size of function");
1189 		case PTR:
1190 			return( SZPOINT(ty) * mult );
1191 		case ARY:
1192 			if (d->ddim == NOOFFSET)
1193 				return 0;
1194 			if (d->ddim < 0)
1195 				cerror("tsize: dynarray");
1196 			mult *= d->ddim;
1197 			d++;
1198 		}
1199 	}
1200 
1201 #ifndef NO_COMPLEX
1202 	if (ISITY(ty))
1203 		ty -= (FIMAG-FLOAT);
1204 #endif
1205 
1206 	if (ty == VOID)
1207 		ty = CHAR;
1208 	if (ty <= LDOUBLE)
1209 		sz = sztable[ty];
1210 	else if (ISSOU(ty)) {
1211 		if ((ap = strattr(apl)) == NULL ||
1212 		    (ap2 = attr_find(apl, ATTR_ALIGNED)) == NULL ||
1213 		    (ap2->iarg(0) == 0)) {
1214 			uerror("unknown structure/union/enum");
1215 			sz = SZINT;
1216 		} else
1217 			sz = ap->amsize;
1218 	} else {
1219 		uerror("unknown type");
1220 		sz = SZINT;
1221 	}
1222 
1223 	return((unsigned int)sz * mult);
1224 }
1225 
1226 /*
1227  * Save string (and print it out).  If wide then wide string.
1228  */
1229 NODE *
1230 strend(int wide, char *str)
1231 {
1232 	struct symtab *sp;
1233 	NODE *p;
1234 
1235 	/* If an identical string is already emitted, just forget this one */
1236 	if (wide) {
1237 		/* Do not save wide strings, at least not now */
1238 		sp = getsymtab(str, SSTRING|STEMP);
1239 	} else {
1240 		str = addstring(str);	/* enter string in string table */
1241 		sp = lookup(str, SSTRING);	/* check for existence */
1242 	}
1243 
1244 	if (sp->soffset == 0) { /* No string */
1245 		char *wr;
1246 		int i;
1247 
1248 		sp->sclass = STATIC;
1249 		sp->slevel = 1;
1250 		sp->soffset = getlab();
1251 		sp->squal = (CON >> TSHIFT);
1252 		sp->sdf = permalloc(sizeof(union dimfun));
1253 		if (wide) {
1254 			sp->stype = WCHAR_TYPE+ARY;
1255 		} else {
1256 			if (xuchar) {
1257 				sp->stype = UCHAR+ARY;
1258 			} else {
1259 				sp->stype = CHAR+ARY;
1260 			}
1261 		}
1262 		if (wide) {
1263 			for (wr = sp->sname, i = 1; *wr; i++)
1264 				u82cp(&wr);
1265 			sp->sdf->ddim = i;
1266 			inwstring(sp);
1267 		} else {
1268 			sp->sdf->ddim = strlen(sp->sname)+1;
1269 			instring(sp);
1270 		}
1271 	}
1272 
1273 	p = block(NAME, NIL, NIL, sp->stype, sp->sdf, sp->sap);
1274 	p->n_sp = sp;
1275 	return(clocal(p));
1276 }
1277 
1278 /*
1279  * Print out a wide string by calling ninval().
1280  */
1281 void
1282 inwstring(struct symtab *sp)
1283 {
1284 	char *s = sp->sname;
1285 	NODE *p;
1286 
1287 	locctr(STRNG, sp);
1288 	defloc(sp);
1289 	p = xbcon(0, NULL, WCHAR_TYPE);
1290 	do {
1291 		p->n_lval=u82cp(&s);
1292 		inval(0, tsize(WCHAR_TYPE, NULL, NULL), p);
1293 	} while (s[-1] != 0);
1294 	nfree(p);
1295 }
1296 
1297 #ifndef MYINSTRING
1298 /*
1299  * Print out a string of characters.
1300  * Assume that the assembler understands C-style escape
1301  * sequences.
1302  * Do not break UTF-8 sequences between lines and ensure
1303  * the code path is 8-bit clean.
1304  */
1305 void
1306 instring(struct symtab *sp)
1307 {
1308 	char *s = sp->sname;
1309 
1310 	locctr(STRNG, sp);
1311 	defloc(sp);
1312 
1313 	char line[70], *t = line;
1314 	printf("\t.ascii \"");
1315 	while(s[0] != 0) {
1316 		unsigned int c=(unsigned char)*s++;
1317 		if(c<' ') t+=sprintf(t,"\\%03o",c);
1318 		else if(c=='\\') *t++='\\', *t++='\\';
1319 		else if(c=='\"') *t++='\\', *t++='\"';
1320 		else if(c=='\'') *t++='\\', *t++='\'';
1321 		else {
1322 			*t++=c;
1323 			int sz=u8len(&s[-1]);
1324 			int i;
1325 			for(i=1;i<sz;i++) *t++=*s++;
1326 		}
1327 		if(t>=&line[60]) {
1328 			fwrite(line, 1, t-&line[0], stdout);
1329 			printf("\"\n\t.ascii \"");
1330 			t = line;
1331 		}
1332 	}
1333 	fwrite(line, 1, t-&line[0], stdout);
1334 	printf("\\0\"\n");
1335 }
1336 #endif
1337 
1338 /*
1339  * update the offset pointed to by poff; return the
1340  * offset of a value of size `size', alignment `alignment',
1341  * given that off is increasing
1342  */
1343 int
1344 upoff(int size, int alignment, int *poff)
1345 {
1346 	int off;
1347 
1348 	off = *poff;
1349 	SETOFF(off, alignment);
1350 	if (off < 0)
1351 		cerror("structure or stack overgrown"); /* wrapped */
1352 	*poff = off+size;
1353 	return (off);
1354 }
1355 
1356 /*
1357  * allocate p with offset *poff, and update *poff
1358  */
1359 int
1360 oalloc(struct symtab *p, int *poff )
1361 {
1362 	int al, off, tsz;
1363 	int noff;
1364 
1365 	/*
1366 	 * Only generate tempnodes if we are optimizing,
1367 	 * and only for integers, floats or pointers,
1368 	 * and not if the type on this level is volatile.
1369 	 */
1370 	if (xtemps && ((p->sclass == AUTO) || (p->sclass == REGISTER)) &&
1371 	    (p->stype < STRTY || ISPTR(p->stype)) &&
1372 	    !(cqual(p->stype, p->squal) & VOL) && cisreg(p->stype)) {
1373 		NODE *tn = tempnode(0, p->stype, p->sdf, p->sap);
1374 		p->soffset = regno(tn);
1375 		p->sflags |= STNODE;
1376 		nfree(tn);
1377 		return 0;
1378 	}
1379 
1380 	al = talign(p->stype, p->sap);
1381 	noff = off = *poff;
1382 	tsz = (int)tsize(p->stype, p->sdf, p->sap);
1383 #ifdef BACKAUTO
1384 	if (p->sclass == AUTO) {
1385 		noff = off + tsz;
1386 		if (noff < 0)
1387 			cerror("stack overflow");
1388 		SETOFF(noff, al);
1389 		off = -noff;
1390 	} else
1391 #endif
1392 	if (p->sclass == PARAM && (p->stype == CHAR || p->stype == UCHAR ||
1393 	    p->stype == SHORT || p->stype == USHORT || p->stype == BOOL)) {
1394 		off = upoff(SZINT, ALINT, &noff);
1395 #if TARGET_ENDIAN == TARGET_BE
1396 		off = noff - tsz;
1397 #endif
1398 	} else {
1399 		off = upoff(tsz, al, &noff);
1400 	}
1401 
1402 	if (p->sclass != REGISTER) {
1403 	/* in case we are allocating stack space for register arguments */
1404 		if (p->soffset == NOOFFSET)
1405 			p->soffset = off;
1406 		else if(off != p->soffset)
1407 			return(1);
1408 	}
1409 
1410 	*poff = noff;
1411 	return(0);
1412 }
1413 
1414 /*
1415  * Delay emission of code generated in argument headers.
1416  */
1417 static void
1418 edelay(NODE *p)
1419 {
1420 	if (blevel == 1) {
1421 		/* Delay until after declarations */
1422 		if (parlink == NULL)
1423 			parlink = p;
1424 		else
1425 			parlink = block(COMOP, parlink, p, 0, 0, 0);
1426 	} else
1427 		ecomp(p);
1428 }
1429 
1430 /*
1431  * Traverse through the array args, evaluate them and put the
1432  * resulting temp numbers in the dim fields.
1433  */
1434 static void
1435 evalidx(struct symtab *sp)
1436 {
1437 	union dimfun *df;
1438 	NODE *p;
1439 	TWORD t;
1440 	int astkp = 0;
1441 
1442 	if (arrstk[0] == NIL)
1443 		astkp++; /* for parameter arrays */
1444 
1445 	if (isdyn(sp))
1446 		sp->sflags |= SDYNARRAY;
1447 
1448 	df = sp->sdf;
1449 	for (t = sp->stype; t > BTMASK; t = DECREF(t)) {
1450 		if (!ISARY(t))
1451 			continue;
1452 		if (df->ddim == -1) {
1453 			p = tempnode(0, INT, 0, 0);
1454 			df->ddim = -regno(p);
1455 			edelay(buildtree(ASSIGN, p, arrstk[astkp++]));
1456 		}
1457 		df++;
1458 	}
1459 	arrstkp = 0;
1460 }
1461 
1462 /*
1463  * Return 1 if dynamic array, 0 otherwise.
1464  */
1465 int
1466 isdyn(struct symtab *sp)
1467 {
1468 	union dimfun *df = sp->sdf;
1469 	TWORD t;
1470 
1471 	for (t = sp->stype; t > BTMASK; t = DECREF(t)) {
1472 		if (!ISARY(t))
1473 			return 0;
1474 		if (df->ddim < 0 && df->ddim != NOOFFSET)
1475 			return 1;
1476 		df++;
1477 	}
1478 	return 0;
1479 }
1480 
1481 /*
1482  * Allocate space on the stack for dynamic arrays (or at least keep track
1483  * of the index).
1484  * Strategy is as follows:
1485  * - first entry is a pointer to the dynamic datatype.
1486  * - if it's a one-dimensional array this will be the only entry used.
1487  * - if it's a multi-dimensional array the following (numdim-1) integers
1488  *   will contain the sizes to multiply the indexes with.
1489  * - code to write the dimension sizes this will be generated here.
1490  * - code to allocate space on the stack will be generated here.
1491  */
1492 static void
1493 dynalloc(struct symtab *p, int *poff)
1494 {
1495 	union dimfun *df;
1496 	NODE *n, *tn, *pol;
1497 	TWORD t;
1498 
1499 	/*
1500 	 * The pointer to the array is not necessarily stored in a
1501 	 * TEMP node, but if it is, its number is in the soffset field;
1502 	 */
1503 	t = p->stype;
1504 	p->sflags |= STNODE;
1505 	p->stype = INCREF(p->stype); /* Make this an indirect pointer */
1506 	tn = tempnode(0, p->stype, p->sdf, p->sap);
1507 	p->soffset = regno(tn);
1508 
1509 	df = p->sdf;
1510 
1511 	pol = bcon(1);
1512 	for (; t > BTMASK; t = DECREF(t)) {
1513 		if (!ISARY(t))
1514 			break;
1515 		if (df->ddim < 0)
1516 			n = tempnode(-df->ddim, INT, 0, 0);
1517 		else
1518 			n = bcon(df->ddim);
1519 
1520 		pol = buildtree(MUL, pol, n);
1521 		df++;
1522 	}
1523 	/* Create stack gap */
1524 	spalloc(tn, pol, tsize(t, 0, p->sap));
1525 }
1526 
1527 /*
1528  * allocate a field of width w
1529  * new is 0 if new entry, 1 if redefinition, -1 if alignment
1530  */
1531 int
1532 falloc(struct symtab *p, int w, NODE *pty)
1533 {
1534 	TWORD otype, type;
1535 	int al,sz;
1536 
1537 	otype = type = p ? p->stype : pty->n_type;
1538 
1539 	if (type == BOOL)
1540 		type = BOOL_TYPE;
1541 	if (!ISINTEGER(type)) {
1542 		uerror("illegal field type");
1543 		type = INT;
1544 	}
1545 
1546 	al = talign(type, NULL);
1547 	sz = tsize(type, NULL, NULL);
1548 
1549 	if (w > sz) {
1550 		uerror("field too big");
1551 		w = sz;
1552 	}
1553 
1554 	if (w == 0) { /* align only */
1555 		SETOFF(rpole->rstr, al);
1556 		if (p != NULL)
1557 			uerror("zero size field");
1558 		return(0);
1559 	}
1560 
1561 	if (rpole->rstr%al + w > sz)
1562 		SETOFF(rpole->rstr, al);
1563 	if (p == NULL) {
1564 		rpole->rstr += w;  /* we know it will fit */
1565 		return(0);
1566 	}
1567 
1568 	/* establish the field */
1569 
1570 	p->soffset = rpole->rstr;
1571 	rpole->rstr += w;
1572 	p->stype = otype;
1573 	fldty(p);
1574 	return(0);
1575 }
1576 
1577 /*
1578  * Check if this symbol should be a common or must be handled in data seg.
1579  */
1580 static void
1581 commchk(struct symtab *sp)
1582 {
1583 	if ((sp->sflags & STLS)
1584 #ifdef GCC_COMPAT
1585 		|| attr_find(sp->sap, GCC_ATYP_SECTION)
1586 #endif
1587 	    ) {
1588 		/* TLS handled in data segment */
1589 		if (sp->sclass == EXTERN)
1590 			sp->sclass = EXTDEF;
1591 		beginit(sp);
1592 		endinit(1);
1593 	} else {
1594 		symdirec(sp);
1595 		defzero(sp);
1596 	}
1597 }
1598 
1599 void
1600 nidcl(NODE *p, int class)
1601 {
1602 	nidcl2(p, class, 0);
1603 }
1604 
1605 /*
1606  * handle unitialized declarations assumed to be not functions:
1607  * int a;
1608  * extern int a;
1609  * static int a;
1610  */
1611 void
1612 nidcl2(NODE *p, int class, char *astr)
1613 {
1614 	struct symtab *sp;
1615 	int commflag = 0;
1616 
1617 	/* compute class */
1618 	if (class == SNULL) {
1619 		if (blevel > 1)
1620 			class = AUTO;
1621 		else if (blevel != 0 || rpole)
1622 			cerror( "nidcl error" );
1623 		else /* blevel = 0 */
1624 			commflag = 1, class = EXTERN;
1625 	}
1626 
1627 	defid2(p, class, astr);
1628 
1629 	sp = p->n_sp;
1630 	/* check if forward decl */
1631 	if (ISARY(sp->stype) && sp->sdf->ddim == NOOFFSET)
1632 		return;
1633 
1634 	if (sp->sflags & SASG)
1635 		return; /* already initialized */
1636 
1637 	switch (class) {
1638 	case EXTDEF:
1639 		/* simulate initialization by 0 */
1640 		simpleinit(p->n_sp, bcon(0));
1641 		break;
1642 	case EXTERN:
1643 		if (commflag)
1644 			lcommadd(p->n_sp);
1645 		else
1646 			extdec(p->n_sp);
1647 		break;
1648 	case STATIC:
1649 		if (blevel == 0)
1650 			lcommadd(p->n_sp);
1651 		else
1652 			commchk(p->n_sp);
1653 		break;
1654 	}
1655 }
1656 
1657 struct lcd {
1658 	SLIST_ENTRY(lcd) next;
1659 	struct symtab *sp;
1660 };
1661 
1662 static SLIST_HEAD(, lcd) lhead = { NULL, &lhead.q_forw};
1663 
1664 /*
1665  * Add a local common statement to the printout list.
1666  */
1667 void
1668 lcommadd(struct symtab *sp)
1669 {
1670 	struct lcd *lc, *lcp;
1671 
1672 	lcp = NULL;
1673 	SLIST_FOREACH(lc, &lhead, next) {
1674 		if (lc->sp == sp)
1675 			return; /* already exists */
1676 		if (lc->sp == NULL && lcp == NULL)
1677 			lcp = lc;
1678 	}
1679 	if (lcp == NULL) {
1680 		lc = permalloc(sizeof(struct lcd));
1681 		lc->sp = sp;
1682 		SLIST_INSERT_LAST(&lhead, lc, next);
1683 	} else
1684 		lcp->sp = sp;
1685 }
1686 
1687 /*
1688  * Delete a local common statement.
1689  */
1690 void
1691 lcommdel(struct symtab *sp)
1692 {
1693 	struct lcd *lc;
1694 
1695 	SLIST_FOREACH(lc, &lhead, next) {
1696 		if (lc->sp == sp) {
1697 			lc->sp = NULL;
1698 			return;
1699 		}
1700 	}
1701 }
1702 
1703 /*
1704  * Print out the remaining common statements.
1705  */
1706 void
1707 lcommprint(void)
1708 {
1709 	struct lcd *lc;
1710 
1711 	SLIST_FOREACH(lc, &lhead, next) {
1712 		if (lc->sp != NULL)
1713 			commchk(lc->sp);
1714 	}
1715 }
1716 
1717 /*
1718  * Merge given types to a single node.
1719  * Any type can end up here.
1720  * p is the old node, q is the old (if any).
1721  * CLASS is AUTO, EXTERN, REGISTER, STATIC or TYPEDEF.
1722  * QUALIFIER is VOL or CON
1723  * TYPE is CHAR, SHORT, INT, LONG, SIGNED, UNSIGNED, VOID, BOOL, FLOAT,
1724  * 	DOUBLE, STRTY, UNIONTY.
1725  */
1726 struct typctx {
1727 	int class, qual, sig, uns, cmplx, imag, err;
1728 	TWORD type;
1729 	NODE *saved;
1730 	struct attr *pre, *post;
1731 };
1732 
1733 static void
1734 typwalk(NODE *p, void *arg)
1735 {
1736 	struct typctx *tc = arg;
1737 
1738 #define	cmop(x,y) block(CM, x, y, INT, 0, 0)
1739 	switch (p->n_op) {
1740 	case ATTRIB:
1741 #ifdef GCC_COMPAT
1742 		if (tc->saved && (tc->saved->n_qual & 1)) {
1743 			tc->post = attr_add(tc->post,gcc_attr_parse(p->n_left));
1744 		} else {
1745 			tc->pre = attr_add(tc->pre, gcc_attr_parse(p->n_left));
1746 		}
1747 		p->n_left = bcon(0); /* For tfree() */
1748 #else
1749 		uerror("gcc type attribute used");
1750 #endif
1751 		break;
1752 	case CLASS:
1753 		if (p->n_type == 0)
1754 			break;	/* inline hack */
1755 		if (tc->class)
1756 			tc->err = 1; /* max 1 class */
1757 		tc->class = p->n_type;
1758 		break;
1759 
1760 	case QUALIFIER:
1761 		if (p->n_qual == 0 && tc->saved && !ISPTR(tc->saved->n_type))
1762 			uerror("invalid use of 'restrict'");
1763 		tc->qual |= p->n_qual >> TSHIFT;
1764 		break;
1765 
1766 	case TYPE:
1767 		if (p->n_sp != NULL || ISSOU(p->n_type)) {
1768 			/* typedef, enum or struct/union */
1769 			if (tc->saved || tc->type)
1770 				tc->err = 1;
1771 #ifdef GCC_COMPAT
1772 			if (ISSOU(p->n_type) && p->n_left) {
1773 				if (tc->post)
1774 					cerror("typwalk");
1775 				tc->post = gcc_attr_parse(p->n_left);
1776 			}
1777 #endif
1778 			tc->saved = ccopy(p);
1779 			break;
1780 		}
1781 
1782 		switch (p->n_type) {
1783 		case BOOL:
1784 		case CHAR:
1785 		case FLOAT:
1786 		case VOID:
1787 			if (tc->type)
1788 				tc->err = 1;
1789 			tc->type = p->n_type;
1790 			break;
1791 		case DOUBLE:
1792 			if (tc->type == 0)
1793 				tc->type = DOUBLE;
1794 			else if (tc->type == LONG)
1795 				tc->type = LDOUBLE;
1796 			else
1797 				tc->err = 1;
1798 			break;
1799 		case SHORT:
1800 			if (tc->type == 0 || tc->type == INT)
1801 				tc->type = SHORT;
1802 			else
1803 				tc->err = 1;
1804 			break;
1805 		case INT:
1806 			if (tc->type == SHORT || tc->type == LONG ||
1807 			    tc->type == LONGLONG)
1808 				break;
1809 			else if (tc->type == 0)
1810 				tc->type = INT;
1811 			else
1812 				tc->err = 1;
1813 			break;
1814 		case LONG:
1815 			if (tc->type == 0)
1816 				tc->type = LONG;
1817 			else if (tc->type == INT)
1818 				break;
1819 			else if (tc->type == LONG)
1820 				tc->type = LONGLONG;
1821 			else if (tc->type == DOUBLE)
1822 				tc->type = LDOUBLE;
1823 			else
1824 				tc->err = 1;
1825 			break;
1826 		case SIGNED:
1827 			if (tc->sig || tc->uns)
1828 				tc->err = 1;
1829 			tc->sig = 1;
1830 			break;
1831 		case UNSIGNED:
1832 			if (tc->sig || tc->uns)
1833 				tc->err = 1;
1834 			tc->uns = 1;
1835 			break;
1836 		case COMPLEX:
1837 			tc->cmplx = 1;
1838 			break;
1839 		case IMAG:
1840 			tc->imag = 1;
1841 			break;
1842 		default:
1843 			cerror("typwalk");
1844 		}
1845 	}
1846 
1847 }
1848 
1849 NODE *
1850 typenode(NODE *p)
1851 {
1852 	struct symtab *sp;
1853 	struct typctx tc;
1854 	NODE *q;
1855 	char *c;
1856 
1857 	memset(&tc, 0, sizeof(struct typctx));
1858 
1859 	flist(p, typwalk, &tc);
1860 	tfree(p);
1861 
1862 	if (tc.err)
1863 		goto bad;
1864 
1865 	if (tc.cmplx || tc.imag) {
1866 		if (tc.type == 0)
1867 			tc.type = DOUBLE;
1868 		if ((tc.cmplx && tc.imag) || tc.sig || tc.uns ||
1869 		    !ISFTY(tc.type))
1870 			goto bad;
1871 		if (tc.cmplx) {
1872 			c = tc.type == DOUBLE ? "0d" :
1873 			    tc.type == FLOAT ? "0f" : "0l";
1874 			sp = lookup(addname(c), 0);
1875 			tc.type = STRTY;
1876 			tc.saved = mkty(tc.type, sp->sdf, sp->sap);
1877 			tc.saved->n_sp = sp;
1878 			tc.type = 0;
1879 		} else
1880 			tc.type += (FIMAG-FLOAT);
1881 	}
1882 
1883 	if (tc.saved && tc.type)
1884 		goto bad;
1885 	if (tc.sig || tc.uns) {
1886 		if (tc.type == 0)
1887 			tc.type = tc.sig ? INT : UNSIGNED;
1888 		if (tc.type > ULONGLONG)
1889 			goto bad;
1890 		if (tc.uns)
1891 			tc.type = ENUNSIGN(tc.type);
1892 	}
1893 
1894 	if (xuchar && tc.type == CHAR && tc.sig == 0)
1895 		tc.type = UCHAR;
1896 
1897 #ifdef GCC_COMPAT
1898 	if (pragma_packed) {
1899 		q = bdty(CALL, bdty(NAME, "packed"), bcon(pragma_packed));
1900 		tc.post = attr_add(tc.post, gcc_attr_parse(q));
1901 	}
1902 	if (pragma_aligned) {
1903 		/* Deal with relevant pragmas */
1904 		q = bdty(CALL, bdty(NAME, "aligned"), bcon(pragma_aligned));
1905 		tc.post = attr_add(tc.post, gcc_attr_parse(q));
1906 	}
1907 	pragma_aligned = pragma_packed = 0;
1908 #endif
1909 	if ((q = tc.saved) == NULL) {
1910 		TWORD t;
1911 		if ((t = BTYPE(tc.type)) > LDOUBLE && t != VOID &&
1912 		    t != BOOL && !(t >= FIMAG && t <= LIMAG))
1913 			cerror("typenode2 t %x", tc.type);
1914 		if (t == UNDEF) {
1915 			t = INT;
1916 			MODTYPE(tc.type, INT);
1917 		}
1918 		q =  mkty(tc.type, 0, 0);
1919 	}
1920 	q->n_ap = attr_add(q->n_ap, tc.post);
1921 	q->n_qual = tc.qual;
1922 	q->n_lval = tc.class;
1923 #ifdef GCC_COMPAT
1924 	if (tc.post) {
1925 		/* Can only occur for TYPEDEF, STRUCT or UNION */
1926 		if (tc.saved == NULL)
1927 			cerror("typenode");
1928 		if (tc.saved->n_sp) /* trailer attributes for structs */
1929 			tc.saved->n_sp->sap = q->n_ap;
1930 	}
1931 	if (tc.pre)
1932 		q->n_ap = attr_add(q->n_ap, tc.pre);
1933 	gcc_tcattrfix(q);
1934 #endif
1935 	return q;
1936 
1937 bad:	uerror("illegal type combination");
1938 	return mkty(INT, 0, 0);
1939 }
1940 
1941 struct tylnk {
1942 	struct tylnk *next;
1943 	union dimfun df;
1944 };
1945 
1946 /*
1947  * Retrieve all CM-separated argument types, sizes and dimensions and
1948  * put them in an array.
1949  * XXX - can only check first type level, side effects?
1950  */
1951 static union arglist *
1952 arglist(NODE *n)
1953 {
1954 	union arglist *al;
1955 	NODE *w = n, **ap;
1956 	int num, cnt, i, j, k;
1957 	TWORD ty;
1958 
1959 #ifdef PCC_DEBUG
1960 	if (pdebug) {
1961 		printf("arglist %p\n", n);
1962 		fwalk(n, eprint, 0);
1963 	}
1964 #endif
1965 	/* First: how much to allocate */
1966 	for (num = cnt = 0, w = n; w->n_op == CM; w = w->n_left) {
1967 		cnt++;	/* Number of levels */
1968 		num++;	/* At least one per step */
1969 		if (w->n_right->n_op == ELLIPSIS)
1970 			continue;
1971 		ty = w->n_right->n_type;
1972 		if (ty == ENUMTY) {
1973 			uerror("arg %d enum undeclared", cnt);
1974 			ty = w->n_right->n_type = INT;
1975 		}
1976 		if (BTYPE(ty) == STRTY || BTYPE(ty) == UNIONTY)
1977 			num++;
1978 		while (!ISFTN(ty) && !ISARY(ty) && ty > BTMASK)
1979 			ty = DECREF(ty);
1980 		if (ty > BTMASK)
1981 			num++;
1982 	}
1983 	cnt++;
1984 	ty = w->n_type;
1985 	if (ty == ENUMTY) {
1986 		uerror("arg %d enum undeclared", cnt);
1987 		ty = w->n_type = INT;
1988 	}
1989 	if (BTYPE(ty) == STRTY || BTYPE(ty) == UNIONTY)
1990 		num++;
1991 	while (!ISFTN(ty) && !ISARY(ty) && ty > BTMASK)
1992 		ty = DECREF(ty);
1993 	if (ty > BTMASK)
1994 		num++;
1995 	num += 2; /* TEND + last arg type */
1996 
1997 	/* Second: Create list to work on */
1998 	ap = tmpalloc(sizeof(NODE *) * cnt);
1999 	al = permalloc(sizeof(union arglist) * num);
2000 	arglistcnt += num;
2001 
2002 	for (w = n, i = 0; w->n_op == CM; w = w->n_left)
2003 		ap[i++] = w->n_right;
2004 	ap[i] = w;
2005 
2006 	/* Third: Create actual arg list */
2007 	for (k = 0, j = i; j >= 0; j--) {
2008 		if (ap[j]->n_op == ELLIPSIS) {
2009 			al[k++].type = TELLIPSIS;
2010 			ap[j]->n_op = ICON; /* for tfree() */
2011 			continue;
2012 		}
2013 		/* Convert arrays to pointers */
2014 		if (ISARY(ap[j]->n_type)) {
2015 			ap[j]->n_type += (PTR-ARY);
2016 			ap[j]->n_df++;
2017 		}
2018 		/* Convert (silently) functions to pointers */
2019 		if (ISFTN(ap[j]->n_type))
2020 			ap[j]->n_type = INCREF(ap[j]->n_type);
2021 		ty = ap[j]->n_type;
2022 #ifdef GCC_COMPAT
2023 		if (ty == UNIONTY &&
2024 		    attr_find(ap[j]->n_ap, GCC_ATYP_TRANSP_UNION)){
2025 			/* transparent unions must have compatible types
2026 			 * shortcut here: if pointers, set void *,
2027 			 * otherwise btype.
2028 			 */
2029 			struct symtab *sp = strmemb(ap[j]->n_ap);
2030 			ty = ISPTR(sp->stype) ? PTR|VOID : sp->stype;
2031 		}
2032 #endif
2033 		al[k++].type = ty;
2034 		if (BTYPE(ty) == STRTY || BTYPE(ty) == UNIONTY)
2035 			al[k++].sap = ap[j]->n_ap;
2036 		while (!ISFTN(ty) && !ISARY(ty) && ty > BTMASK)
2037 			ty = DECREF(ty);
2038 		if (ty > BTMASK)
2039 			al[k++].df = ap[j]->n_df;
2040 	}
2041 	al[k++].type = TNULL;
2042 	if (k > num)
2043 		cerror("arglist: k%d > num%d", k, num);
2044 	tfree(n);
2045 #ifdef PCC_DEBUG
2046 	if (pdebug)
2047 		alprint(al, 0);
2048 #endif
2049 	return al;
2050 }
2051 
2052 static void
2053 tylkadd(union dimfun dim, struct tylnk **tylkp, int *ntdim)
2054 {
2055 	(*tylkp)->next = tmpalloc(sizeof(struct tylnk));
2056 	*tylkp = (*tylkp)->next;
2057 	(*tylkp)->next = NULL;
2058 	(*tylkp)->df = dim;
2059 	(*ntdim)++;
2060 }
2061 
2062 /*
2063  * build a type, and stash away dimensions,
2064  * from a parse tree of the declaration
2065  * the type is build top down, the dimensions bottom up
2066  */
2067 static void
2068 tyreduce(NODE *p, struct tylnk **tylkp, int *ntdim)
2069 {
2070 	union dimfun dim;
2071 	NODE *r = NULL;
2072 	int o;
2073 	TWORD t, q;
2074 
2075 	o = p->n_op;
2076 	if (o == NAME) {
2077 		p->n_qual = DECQAL(p->n_qual);
2078 		return;
2079 	}
2080 
2081 	t = INCREF(p->n_type);
2082 	q = p->n_qual;
2083 	switch (o) {
2084 	case CALL:
2085 		t += (FTN-PTR);
2086 		dim.dfun = arglist(p->n_right);
2087 		break;
2088 	case UCALL:
2089 		t += (FTN-PTR);
2090 		dim.dfun = NULL;
2091 		break;
2092 	case LB:
2093 		t += (ARY-PTR);
2094 		if (p->n_right->n_op != ICON) {
2095 			r = p->n_right;
2096 			o = RB;
2097 		} else {
2098 			dim.ddim = (int)p->n_right->n_lval;
2099 			nfree(p->n_right);
2100 #ifdef notdef
2101 	/* XXX - check dimensions at usage time */
2102 			if (dim.ddim == NOOFFSET && p->n_left->n_op == LB)
2103 				uerror("null dimension");
2104 #endif
2105 		}
2106 		break;
2107 	}
2108 
2109 	p->n_left->n_type = t;
2110 	p->n_left->n_qual = INCQAL(q) | p->n_left->n_qual;
2111 	tyreduce(p->n_left, tylkp, ntdim);
2112 
2113 	if (o == LB || o == UCALL || o == CALL)
2114 		tylkadd(dim, tylkp, ntdim);
2115 	if (o == RB) {
2116 		dim.ddim = -1;
2117 		tylkadd(dim, tylkp, ntdim);
2118 		arrstk[arrstkp++] = r;
2119 	}
2120 
2121 	p->n_sp = p->n_left->n_sp;
2122 	p->n_type = p->n_left->n_type;
2123 	p->n_qual = p->n_left->n_qual;
2124 }
2125 
2126 /*
2127  * merge type typ with identifier idp.
2128  * idp is returned as a NAME node with correct types,
2129  * typ is untouched since multiple declarations uses it.
2130  * typ has type attributes, idp can never carry such attributes
2131  * so on return just a pointer to the typ attributes is returned.
2132  */
2133 NODE *
2134 tymerge(NODE *typ, NODE *idp)
2135 {
2136 	TWORD t;
2137 	NODE *p;
2138 	union dimfun *j;
2139 	struct tylnk *base, tylnk, *tylkp;
2140 	struct attr *bap;
2141 	int ntdim, i;
2142 
2143 #ifdef PCC_DEBUG
2144 	if (ddebug > 2) {
2145 		printf("tymerge(%p,%p)\n", typ, idp);
2146 		fwalk(typ, eprint, 0);
2147 		fwalk(idp, eprint, 0);
2148 	}
2149 #endif
2150 
2151 	if (typ->n_op != TYPE)
2152 		cerror("tymerge: arg 1");
2153 
2154 	bap = typ->n_ap;
2155 
2156 	idp->n_type = typ->n_type;
2157 	idp->n_qual |= typ->n_qual;
2158 
2159 	tylkp = &tylnk;
2160 	tylkp->next = NULL;
2161 	ntdim = 0;
2162 
2163 	tyreduce(idp, &tylkp, &ntdim);
2164 
2165 	for (t = typ->n_type, j = typ->n_df; t&TMASK; t = DECREF(t))
2166 		if (ISARY(t) || ISFTN(t))
2167 			tylkadd(*j++, &tylkp, &ntdim);
2168 
2169 	if (ntdim) {
2170 		union dimfun *a = permalloc(sizeof(union dimfun) * ntdim);
2171 		dimfuncnt += ntdim;
2172 		for (i = 0, base = tylnk.next; base; base = base->next, i++)
2173 			a[i] = base->df;
2174 		idp->n_df = a;
2175 	} else
2176 		idp->n_df = NULL;
2177 
2178 	/* now idp is a single node: fix up type */
2179 	if ((t = ctype(idp->n_type)) != idp->n_type)
2180 		idp->n_type = t;
2181 
2182 	if (idp->n_op != NAME) {
2183 		for (p = idp->n_left; p->n_op != NAME; p = p->n_left)
2184 			nfree(p);
2185 		nfree(p);
2186 		idp->n_op = NAME;
2187 	}
2188 	/* carefully not destroy any type attributes */
2189 	if (idp->n_ap != NULL) {
2190 		struct attr *ap = idp->n_ap;
2191 		while (ap->next)
2192 			ap = ap->next;
2193 		ap->next = bap;
2194 	} else
2195 		idp->n_ap = bap;
2196 
2197 	return(idp);
2198 }
2199 
2200 static NODE *
2201 argcast(NODE *p, TWORD t, union dimfun *d, struct attr *ap)
2202 {
2203 	NODE *u, *r = talloc();
2204 
2205 	r->n_op = NAME;
2206 	r->n_type = t;
2207 	r->n_qual = 0; /* XXX */
2208 	r->n_df = d;
2209 	r->n_ap = ap;
2210 
2211 	u = buildtree(CAST, r, p);
2212 	nfree(u->n_left);
2213 	r = u->n_right;
2214 	nfree(u);
2215 	return r;
2216 }
2217 
2218 #ifdef PCC_DEBUG
2219 /*
2220  * Print a prototype.
2221  */
2222 static void
2223 alprint(union arglist *al, int in)
2224 {
2225 	TWORD t;
2226 	int i = 0, j;
2227 
2228 	for (; al->type != TNULL; al++) {
2229 		for (j = in; j > 0; j--)
2230 			printf("  ");
2231 		printf("arg %d: ", i++);
2232 		t = al->type;
2233 		tprint(t, 0);
2234 		while (t > BTMASK) {
2235 			if (ISARY(t)) {
2236 				al++;
2237 				printf(" dim %d ", al->df->ddim);
2238 			} else if (ISFTN(t)) {
2239 				al++;
2240 				if (al->df->dfun) {
2241 					printf("\n");
2242 					alprint(al->df->dfun, in+1);
2243 				}
2244 			}
2245 			t = DECREF(t);
2246 		}
2247 		if (ISSOU(t)) {
2248 			al++;
2249 			printf(" (size %d align %d)", (int)tsize(t, 0, al->sap),
2250 			    (int)talign(t, al->sap));
2251 		}
2252 		printf("\n");
2253 	}
2254 	if (in == 0)
2255 		printf("end arglist\n");
2256 }
2257 #endif
2258 
2259 int
2260 suemeq(struct attr *s1, struct attr *s2)
2261 {
2262 
2263 	return (strmemb(s1) == strmemb(s2));
2264 }
2265 
2266 /*
2267  * Sanity-check old-style args.
2268  */
2269 static NODE *
2270 oldarg(NODE *p)
2271 {
2272 	if (p->n_op == TYPE)
2273 		uerror("type is not an argument");
2274 	if (p->n_type == FLOAT)
2275 		return cast(p, DOUBLE, p->n_qual);
2276 	return p;
2277 }
2278 
2279 /*
2280  * Do prototype checking and add conversions before calling a function.
2281  * Argument f is function and a is a CM-separated list of arguments.
2282  * Returns a merged node (via buildtree() of function and arguments.
2283  */
2284 NODE *
2285 doacall(struct symtab *sp, NODE *f, NODE *a)
2286 {
2287 	NODE *w, *r;
2288 	union arglist *al;
2289 	struct ap {
2290 		struct ap *next;
2291 		NODE *node;
2292 	} *at, *apole = NULL;
2293 	int argidx/* , hasarray = 0*/;
2294 	TWORD type, arrt;
2295 
2296 #ifdef PCC_DEBUG
2297 	if (ddebug) {
2298 		printf("doacall.\n");
2299 		fwalk(f, eprint, 0);
2300 		if (a)
2301 			fwalk(a, eprint, 0);
2302 	}
2303 #endif
2304 
2305 	/* First let MD code do something */
2306 	calldec(f, a);
2307 /* XXX XXX hack */
2308 	if ((f->n_op == CALL) &&
2309 	    f->n_left->n_op == ADDROF &&
2310 	    f->n_left->n_left->n_op == NAME &&
2311 	    (f->n_left->n_left->n_type & 0x7e0) == 0x4c0)
2312 		goto build;
2313 /* XXX XXX hack */
2314 
2315 	/* Check for undefined or late defined enums */
2316 	if (BTYPE(f->n_type) == ENUMTY) {
2317 		/* not-yet check if declared enum */
2318 		struct symtab *sq = strmemb(f->n_ap);
2319 		if (sq->stype != ENUMTY)
2320 			MODTYPE(f->n_type, sq->stype);
2321 		if (BTYPE(f->n_type) == ENUMTY)
2322 			uerror("enum %s not declared", sq->sname);
2323 	}
2324 
2325 	/*
2326 	 * Do some basic checks.
2327 	 */
2328 	if (f->n_df == NULL || (al = f->n_df[0].dfun) == NULL) {
2329 		/*
2330 		 * Handle non-prototype declarations.
2331 		 */
2332 		if (f->n_op == NAME && f->n_sp != NULL) {
2333 			if (strncmp(f->n_sp->sname, "__builtin", 9) != 0 &&
2334 			    (f->n_sp->sflags & SINSYS) == 0)
2335 				warner(Wmissing_prototypes, f->n_sp->sname);
2336 		} else
2337 			warner(Wmissing_prototypes, "<pointer>");
2338 
2339 		/* floats must be cast to double */
2340 		if (a == NULL)
2341 			goto build;
2342 		if (a->n_op != CM) {
2343 			a = oldarg(a);
2344 		} else {
2345 			for (w = a; w->n_left->n_op == CM; w = w->n_left)
2346 				w->n_right = oldarg(w->n_right);
2347 			w->n_left = oldarg(w->n_left);
2348 			w->n_right = oldarg(w->n_right);
2349 		}
2350 		goto build;
2351 	}
2352 	if (al->type == VOID) {
2353 		if (a != NULL)
2354 			uerror("function takes no arguments");
2355 		goto build; /* void function */
2356 	} else {
2357 		if (a == NULL) {
2358 			uerror("function needs arguments");
2359 			goto build;
2360 		}
2361 	}
2362 #ifdef PCC_DEBUG
2363 	if (pdebug) {
2364 		printf("arglist for %s\n",
2365 		    f->n_sp != NULL ? f->n_sp->sname : "function pointer");
2366 		alprint(al, 0);
2367 	}
2368 #endif
2369 
2370 	/*
2371 	 * Create a list of pointers to the nodes given as arg.
2372 	 */
2373 	for (w = a; w->n_op == CM; w = w->n_left) {
2374 		at = tmpalloc(sizeof(struct ap));
2375 		at->node = w->n_right;
2376 		at->next = apole;
2377 		apole = at;
2378 	}
2379 	at = tmpalloc(sizeof(struct ap));
2380 	at->node = w;
2381 	at->next = apole;
2382 	apole = at;
2383 
2384 	/*
2385 	 * Do the typechecking by walking up the list.
2386 	 */
2387 	argidx = 1;
2388 	while (al->type != TNULL) {
2389 		if (al->type == TELLIPSIS) {
2390 			/* convert the rest of float to double */
2391 			for (; apole; apole = apole->next) {
2392 				if (apole->node->n_type != FLOAT)
2393 					continue;
2394 				MKTY(apole->node, DOUBLE, 0, 0);
2395 			}
2396 			goto build;
2397 		}
2398 		if (apole == NULL) {
2399 			uerror("too few arguments to function");
2400 			goto build;
2401 		}
2402 /* al = prototyp, apole = argument till ftn */
2403 /* type = argumentets typ, arrt = prototypens typ */
2404 		type = apole->node->n_type;
2405 		arrt = al->type;
2406 #if 0
2407 		if ((hasarray = ISARY(arrt)))
2408 			arrt += (PTR-ARY);
2409 #endif
2410 		/* Taking addresses of arrays are meaningless in expressions */
2411 		/* but people tend to do that and also use in prototypes */
2412 		/* this is mostly a problem with typedefs */
2413 		if (ISARY(type)) {
2414 			if (ISPTR(arrt) && ISARY(DECREF(arrt)))
2415 				type = INCREF(type);
2416 			else
2417 				type += (PTR-ARY);
2418 		} else if (ISPTR(type) && !ISARY(DECREF(type)) &&
2419 		    ISPTR(arrt) && ISARY(DECREF(arrt))) {
2420 			type += (ARY-PTR);
2421 			type = INCREF(type);
2422 		}
2423 
2424 		/* Check structs */
2425 		if (type <= BTMASK && arrt <= BTMASK) {
2426 			if (type != arrt) {
2427 				if (ISSOU(BTYPE(type)) || ISSOU(BTYPE(arrt))) {
2428 incomp:					uerror("incompatible types for arg %d",
2429 					    argidx);
2430 				} else {
2431 					MKTY(apole->node, arrt, 0, 0)
2432 				}
2433 #ifndef NO_COMPLEX
2434 			} else if (type == STRTY &&
2435 			    attr_find(apole->node->n_ap, ATTR_COMPLEX) &&
2436 			    attr_find(al[1].sap, ATTR_COMPLEX)) {
2437 				/* Both are complex */
2438 				if (strmemb(apole->node->n_ap)->stype !=
2439 				    strmemb(al[1].sap)->stype) {
2440 					/* must convert to correct type */
2441 					w = talloc();
2442 					*w = *apole->node;
2443 					w = mkcmplx(w,
2444 					    strmemb(al[1].sap)->stype);
2445 					*apole->node = *w;
2446 					nfree(w);
2447 				}
2448 				goto out;
2449 #endif
2450 			} else if (ISSOU(BTYPE(type))) {
2451 				if (!suemeq(apole->node->n_ap, al[1].sap))
2452 					goto incomp;
2453 			}
2454 			goto out;
2455 		}
2456 
2457 		/* XXX should (recusively) check return type and arg list of
2458 		   func ptr arg XXX */
2459 		if (ISFTN(DECREF(arrt)) && ISFTN(type))
2460 			type = INCREF(type);
2461 
2462 		/* Hereafter its only pointers (or arrays) left */
2463 		/* Check for struct/union intermixing with other types */
2464 		if (((type <= BTMASK) && ISSOU(BTYPE(type))) ||
2465 		    ((arrt <= BTMASK) && ISSOU(BTYPE(arrt))))
2466 			goto incomp;
2467 
2468 		/* Check for struct/union compatibility */
2469 		if (type == arrt) {
2470 			if (ISSOU(BTYPE(type))) {
2471 				if (suemeq(apole->node->n_ap, al[1].sap))
2472 					goto out;
2473 			} else
2474 				goto out;
2475 		}
2476 		if (BTYPE(arrt) == VOID && type > BTMASK)
2477 			goto skip; /* void *f = some pointer */
2478 		if (arrt > BTMASK && BTYPE(type) == VOID)
2479 			goto skip; /* some *f = void pointer */
2480 		if (apole->node->n_op == ICON && apole->node->n_lval == 0)
2481 			goto skip; /* Anything assigned a zero */
2482 
2483 		if ((type & ~BTMASK) == (arrt & ~BTMASK)) {
2484 			/* do not complain for pointers with signedness */
2485 			if ((DEUNSIGN(BTYPE(type)) == DEUNSIGN(BTYPE(arrt))) &&
2486 			    (BTYPE(type) != BTYPE(arrt))) {
2487 				warner(Wpointer_sign, NULL);
2488 				goto skip;
2489 			}
2490 		}
2491 
2492 		werror("implicit conversion of argument %d due to prototype",
2493 		    argidx);
2494 
2495 skip:		if (ISSOU(BTYPE(arrt))) {
2496 			MKTY(apole->node, arrt, 0, al[1].sap)
2497 		} else {
2498 			MKTY(apole->node, arrt, 0, 0)
2499 		}
2500 
2501 out:		al++;
2502 		if (ISSOU(BTYPE(arrt)))
2503 			al++;
2504 #if 0
2505 		while (arrt > BTMASK && !ISFTN(arrt))
2506 			arrt = DECREF(arrt);
2507 		if (ISFTN(arrt) || hasarray)
2508 			al++;
2509 #else
2510 		while (arrt > BTMASK) {
2511 			if (ISARY(arrt) || ISFTN(arrt)) {
2512 				al++;
2513 				break;
2514 			}
2515 			arrt = DECREF(arrt);
2516 		}
2517 #endif
2518 		apole = apole->next;
2519 		argidx++;
2520 	}
2521 	if (apole != NULL)
2522 		uerror("too many arguments to function");
2523 
2524 build:	if (sp != NULL && (sp->sflags & SINLINE) && (w = inlinetree(sp, f, a)))
2525 		return w;
2526 	return buildtree(a == NIL ? UCALL : CALL, f, a);
2527 }
2528 
2529 static int
2530 chk2(TWORD type, union dimfun *dsym, union dimfun *ddef)
2531 {
2532 	while (type > BTMASK) {
2533 		switch (type & TMASK) {
2534 		case ARY:
2535 			/* may be declared without dimension */
2536 			if (dsym->ddim == NOOFFSET)
2537 				dsym->ddim = ddef->ddim;
2538 			if (dsym->ddim < 0 && ddef->ddim < 0)
2539 				; /* dynamic arrays as arguments */
2540 			else if (ddef->ddim > 0 && dsym->ddim != ddef->ddim)
2541 				return 1;
2542 			dsym++, ddef++;
2543 			break;
2544 		case FTN:
2545 			/* old-style function headers with function pointers
2546 			 * will most likely not have a prototype.
2547 			 * This is not considered an error.  */
2548 			if (ddef->dfun == NULL) {
2549 #ifdef notyet
2550 				werror("declaration not a prototype");
2551 #endif
2552 			} else if (chkftn(dsym->dfun, ddef->dfun))
2553 				return 1;
2554 			dsym++, ddef++;
2555 			break;
2556 		}
2557 		type = DECREF(type);
2558 	}
2559 	return 0;
2560 }
2561 
2562 /*
2563  * Compare two function argument lists to see if they match.
2564  */
2565 int
2566 chkftn(union arglist *usym, union arglist *udef)
2567 {
2568 	TWORD t2;
2569 	int ty, tyn;
2570 
2571 	if (usym == NULL)
2572 		return 0;
2573 	if (cftnsp != NULL && udef == NULL && usym->type == VOID)
2574 		return 0; /* foo() { function with foo(void); prototype */
2575 	if (udef == NULL && usym->type != TNULL)
2576 		return 1;
2577 	while (usym->type != TNULL) {
2578 		if (usym->type == udef->type)
2579 			goto done;
2580 		/*
2581 		 * If an old-style declaration, then all types smaller than
2582 		 * int are given as int parameters.
2583 		 */
2584 		if (intcompare) {
2585 			ty = BTYPE(usym->type);
2586 			tyn = BTYPE(udef->type);
2587 			if (ty == tyn || ty != INT)
2588 				return 1;
2589 			if (tyn == CHAR || tyn == UCHAR ||
2590 			    tyn == SHORT || tyn == USHORT)
2591 				goto done;
2592 			return 1;
2593 		} else
2594 			return 1;
2595 
2596 done:		ty = BTYPE(usym->type);
2597 		t2 = usym->type;
2598 		if (ISSOU(ty)) {
2599 			usym++, udef++;
2600 			if (suemeq(usym->sap, udef->sap) == 0)
2601 				return 1;
2602 		}
2603 
2604 		while (!ISFTN(t2) && !ISARY(t2) && t2 > BTMASK)
2605 			t2 = DECREF(t2);
2606 		if (t2 > BTMASK) {
2607 			usym++, udef++;
2608 			if (chk2(t2, usym->df, udef->df))
2609 				return 1;
2610 		}
2611 		usym++, udef++;
2612 	}
2613 	if (usym->type != udef->type)
2614 		return 1;
2615 	return 0;
2616 }
2617 
2618 void
2619 fixtype(NODE *p, int class)
2620 {
2621 	unsigned int t, type;
2622 	int mod1, mod2;
2623 	/* fix up the types, and check for legality */
2624 
2625 	/* forward declared enums */
2626 	if (BTYPE(p->n_sp->stype) == ENUMTY) {
2627 		MODTYPE(p->n_sp->stype, strmemb(p->n_sp->sap)->stype);
2628 	}
2629 
2630 	if( (type = p->n_type) == UNDEF ) return;
2631 	if ((mod2 = (type&TMASK))) {
2632 		t = DECREF(type);
2633 		while( mod1=mod2, mod2 = (t&TMASK) ){
2634 			if( mod1 == ARY && mod2 == FTN ){
2635 				uerror( "array of functions is illegal" );
2636 				type = 0;
2637 				}
2638 			else if( mod1 == FTN && ( mod2 == ARY || mod2 == FTN ) ){
2639 				uerror( "function returns illegal type" );
2640 				type = 0;
2641 				}
2642 			t = DECREF(t);
2643 			}
2644 		}
2645 
2646 	/* detect function arguments, watching out for structure declarations */
2647 	if (rpole && ISFTN(type)) {
2648 		uerror("function illegal in structure or union");
2649 		type = INCREF(type);
2650 	}
2651 	p->n_type = type;
2652 }
2653 
2654 /*
2655  * give undefined version of class
2656  */
2657 int
2658 uclass(int class)
2659 {
2660 	if (class == SNULL)
2661 		return(EXTERN);
2662 	else if (class == STATIC)
2663 		return(USTATIC);
2664 	else
2665 		return(class);
2666 }
2667 
2668 int
2669 fixclass(int class, TWORD type)
2670 {
2671 	extern int fun_inline;
2672 
2673 	/* first, fix null class */
2674 	if (class == SNULL) {
2675 		if (fun_inline && ISFTN(type))
2676 			return SNULL;
2677 		if (rpole)
2678 			cerror("field8");
2679 		else if (blevel == 0)
2680 			class = EXTDEF;
2681 		else
2682 			class = AUTO;
2683 	}
2684 
2685 	/* now, do general checking */
2686 
2687 	if( ISFTN( type ) ){
2688 		switch( class ) {
2689 		default:
2690 			uerror( "function has illegal storage class" );
2691 		case AUTO:
2692 			class = EXTERN;
2693 		case EXTERN:
2694 		case EXTDEF:
2695 		case TYPEDEF:
2696 		case STATIC:
2697 		case USTATIC:
2698 			;
2699 			}
2700 		}
2701 
2702 	if (class & FIELD) {
2703 		cerror("field3");
2704 	}
2705 
2706 	switch (class) {
2707 
2708 	case MOS:
2709 	case MOU:
2710 		cerror("field4");
2711 
2712 	case REGISTER:
2713 		if (blevel == 0)
2714 			uerror("illegal register declaration");
2715 		if (blevel == 1)
2716 			return(PARAM);
2717 		else
2718 			return(REGISTER);
2719 
2720 	case AUTO:
2721 		if( blevel < 2 ) uerror( "illegal ULABEL class" );
2722 		return( class );
2723 
2724 	case EXTERN:
2725 	case STATIC:
2726 	case EXTDEF:
2727 	case TYPEDEF:
2728 	case USTATIC:
2729 	case PARAM:
2730 		return( class );
2731 
2732 	default:
2733 		cerror( "illegal class: %d", class );
2734 		/* NOTREACHED */
2735 
2736 	}
2737 	return 0; /* XXX */
2738 }
2739 
2740 /*
2741  * Generates a goto statement; sets up label number etc.
2742  */
2743 void
2744 gotolabel(char *name)
2745 {
2746 	struct symtab *s = lookup(name, SLBLNAME);
2747 
2748 	if (s->soffset == 0) {
2749 		s->soffset = -getlab();
2750 		s->sclass = STATIC;
2751 	}
2752 	branch(s->soffset < 0 ? -s->soffset : s->soffset);
2753 }
2754 
2755 /*
2756  * Sets a label for gotos.
2757  */
2758 void
2759 deflabel(char *name, NODE *p)
2760 {
2761 	struct symtab *s = lookup(name, SLBLNAME);
2762 
2763 #ifdef GCC_COMPAT
2764 	s->sap = gcc_attr_parse(p);
2765 #endif
2766 	if (s->soffset > 0)
2767 		uerror("label '%s' redefined", name);
2768 	if (s->soffset == 0) {
2769 		s->soffset = getlab();
2770 		s->sclass = STATIC;
2771 	}
2772 	if (s->soffset < 0)
2773 		s->soffset = -s->soffset;
2774 	plabel( s->soffset);
2775 }
2776 
2777 struct symtab *
2778 getsymtab(char *name, int flags)
2779 {
2780 	struct symtab *s;
2781 
2782 	if (flags & STEMP) {
2783 		s = tmpalloc(sizeof(struct symtab));
2784 	} else {
2785 		s = permalloc(sizeof(struct symtab));
2786 		symtabcnt++;
2787 	}
2788 	s->sname = name;
2789 	s->soname = NULL;
2790 	s->snext = NULL;
2791 	s->stype = UNDEF;
2792 	s->squal = 0;
2793 	s->sclass = SNULL;
2794 	s->sflags = (short)(flags & SMASK);
2795 	s->soffset = 0;
2796 	s->slevel = (char)blevel;
2797 	s->sdf = NULL;
2798 	s->sap = NULL;
2799 	return s;
2800 }
2801 
2802 int
2803 fldchk(int sz)
2804 {
2805 	if (rpole->rsou != STNAME && rpole->rsou != UNAME)
2806 		uerror("field outside of structure");
2807 	if (sz < 0 || sz >= FIELD) {
2808 		uerror("illegal field size");
2809 		return 1;
2810 	}
2811 	return 0;
2812 }
2813 
2814 #ifdef PCC_DEBUG
2815 static char *
2816 ccnames[] = { /* names of storage classes */
2817 	"SNULL",
2818 	"AUTO",
2819 	"EXTERN",
2820 	"STATIC",
2821 	"REGISTER",
2822 	"EXTDEF",
2823 	"LABEL",
2824 	"ULABEL",
2825 	"MOS",
2826 	"PARAM",
2827 	"STNAME",
2828 	"MOU",
2829 	"UNAME",
2830 	"TYPEDEF",
2831 	"FORTRAN",
2832 	"ENAME",
2833 	"MOE",
2834 	"UFORTRAN",
2835 	"USTATIC",
2836 	};
2837 
2838 char *
2839 scnames(int c)
2840 {
2841 	/* return the name for storage class c */
2842 	static char buf[12];
2843 	if( c&FIELD ){
2844 		snprintf( buf, sizeof(buf), "FIELD[%d]", c&FLDSIZ );
2845 		return( buf );
2846 		}
2847 	return( ccnames[c] );
2848 	}
2849 #endif
2850 
2851 #ifdef os_openbsd
2852 static char *stack_chk_fail = "__stack_smash_handler";
2853 static char *stack_chk_guard = "__guard";
2854 #else
2855 static char *stack_chk_fail = "__stack_chk_fail";
2856 static char *stack_chk_guard = "__stack_chk_guard";
2857 #endif
2858 static char *stack_chk_canary = "__stack_chk_canary";
2859 
2860 void
2861 sspinit(void)
2862 {
2863 	NODE *p;
2864 
2865 	p = block(NAME, NIL, NIL, FTN+VOID, 0, 0);
2866 	p->n_sp = lookup(stack_chk_fail, SNORMAL);
2867 	defid(p, EXTERN);
2868 	nfree(p);
2869 
2870 	p = block(NAME, NIL, NIL, INT, 0, 0);
2871 	p->n_sp = lookup(stack_chk_guard, SNORMAL);
2872 	defid(p, EXTERN);
2873 	nfree(p);
2874 }
2875 
2876 void
2877 sspstart(void)
2878 {
2879 	NODE *p, *q;
2880 
2881 	q = block(NAME, NIL, NIL, INT, 0, 0);
2882  	q->n_sp = lookup(stack_chk_guard, SNORMAL);
2883 	q = clocal(q);
2884 
2885 	p = block(REG, NIL, NIL, INCREF(INT), 0, 0);
2886 	p->n_lval = 0;
2887 	p->n_rval = FPREG;
2888 	p = cast(p, INT, 0);
2889 	q = buildtree(ER, p, q);
2890 
2891 	p = block(NAME, NIL, NIL, INT, 0, 0);
2892 	p->n_qual = VOL >> TSHIFT;
2893 	p->n_sp = lookup(stack_chk_canary, SNORMAL);
2894 	defid(p, AUTO);
2895 	p = clocal(p);
2896 	ecomp(buildtree(ASSIGN, p, q));
2897 }
2898 
2899 void
2900 sspend(void)
2901 {
2902 	NODE *p, *q;
2903 	TWORD t;
2904 	int lab;
2905 
2906 	if (retlab != NOLAB) {
2907 		plabel(retlab);
2908 		retlab = getlab();
2909 	}
2910 
2911 	t = DECREF(cftnsp->stype);
2912 	if (t == BOOL)
2913 		t = BOOL_TYPE;
2914 
2915 	p = block(NAME, NIL, NIL, INT, 0, 0);
2916 	p->n_sp = lookup(stack_chk_canary, SNORMAL);
2917 	p = clocal(p);
2918 
2919 	q = block(REG, NIL, NIL, INCREF(INT), 0, 0);
2920 	q->n_lval = 0;
2921 	q->n_rval = FPREG;
2922 	q = cast(q, INT, 0);
2923 	q = buildtree(ER, p, q);
2924 
2925 	p = block(NAME, NIL, NIL, INT, 0, 0);
2926 	p->n_sp = lookup(stack_chk_guard, SNORMAL);
2927 	p = clocal(p);
2928 
2929 	lab = getlab();
2930 	cbranch(buildtree(EQ, p, q), bcon(lab));
2931 
2932 	p = block(NAME, NIL, NIL, FTN+VOID, 0, 0);
2933 	p->n_sp = lookup(stack_chk_fail, SNORMAL);
2934 	p = clocal(p);
2935 
2936 	q = eve(bdty(STRING, cftnsp->sname, 0));
2937 	ecomp(buildtree(CALL, p, q));
2938 
2939 	plabel(lab);
2940 }
2941 
2942 /*
2943  * Allocate on the permanent heap for inlines, otherwise temporary heap.
2944  */
2945 void *
2946 blkalloc(int size)
2947 {
2948 	return isinlining || blevel < 2 ?  permalloc(size) : tmpalloc(size);
2949 }
2950 
2951 /*
2952  * Allocate on the permanent heap for inlines, otherwise temporary heap.
2953  */
2954 void *
2955 inlalloc(int size)
2956 {
2957 	return isinlining ?  permalloc(size) : tmpalloc(size);
2958 }
2959 
2960 struct attr *
2961 attr_new(int type, int nelem)
2962 {
2963 	struct attr *ap;
2964 	int sz;
2965 
2966 	sz = sizeof(struct attr) + nelem * sizeof(union aarg);
2967 
2968 	ap = memset(blkalloc(sz), 0, sz);
2969 	ap->atype = type;
2970 	return ap;
2971 }
2972 
2973 /*
2974  * Add attribute list new before old and return new.
2975  */
2976 struct attr *
2977 attr_add(struct attr *old, struct attr *new)
2978 {
2979 	struct attr *ap;
2980 
2981 	if (new == NULL)
2982 		return old; /* nothing to add */
2983 
2984 	for (ap = new; ap->next; ap = ap->next)
2985 		;
2986 	ap->next = old;
2987 	return new;
2988 }
2989 
2990 /*
2991  * Search for attribute type in list ap.  Return entry or NULL.
2992  */
2993 struct attr *
2994 attr_find(struct attr *ap, int type)
2995 {
2996 
2997 	for (; ap && ap->atype != type; ap = ap->next)
2998 		;
2999 	return ap;
3000 }
3001 
3002 /*
3003  * Copy an attribute struct.
3004  * Return destination.
3005  */
3006 struct attr *
3007 attr_copy(struct attr *aps, struct attr *apd, int n)
3008 {
3009 	int sz = sizeof(struct attr) + n * sizeof(union aarg);
3010 	return memcpy(apd, aps, sz);
3011 }
3012 
3013 /*
3014  * Duplicate an attribute, like strdup.
3015  */
3016 struct attr *
3017 attr_dup(struct attr *ap, int n)
3018 {
3019 	int sz = sizeof(struct attr) + n * sizeof(union aarg);
3020 	ap = memcpy(blkalloc(sz), ap, sz);
3021 	ap->next = NULL;
3022 	return ap;
3023 }
3024 
3025 /*
3026  * Fetch pointer to first member in a struct list.
3027  */
3028 struct symtab *
3029 strmemb(struct attr *ap)
3030 {
3031 
3032 	if ((ap = attr_find(ap, ATTR_STRUCT)) == NULL)
3033 		cerror("strmemb");
3034 	return ap->amlist;
3035 }
3036 
3037 #ifndef NO_COMPLEX
3038 
3039 static char *real, *imag;
3040 static struct symtab *cxsp[3], *cxmul[3], *cxdiv[3];
3041 static char *cxnmul[] = { "__mulsc3", "__muldc3", "__mulxc3" };
3042 static char *cxndiv[] = { "__divsc3", "__divdc3", "__divxc3" };
3043 /*
3044  * As complex numbers internally are handled as structs, create
3045  * these by hand-crafting them.
3046  */
3047 void
3048 complinit(void)
3049 {
3050 	struct attr *ap;
3051 	struct rstack *rp;
3052 	NODE *p, *q;
3053 	char *n[] = { "0f", "0d", "0l" };
3054 	int i, d_debug;
3055 
3056 	d_debug = ddebug;
3057 	ddebug = 0;
3058 	real = addname("__real");
3059 	imag = addname("__imag");
3060 	p = block(NAME, NIL, NIL, FLOAT, 0, 0);
3061 	for (i = 0; i < 3; i++) {
3062 		p->n_type = FLOAT+i;
3063 		rpole = rp = bstruct(NULL, STNAME, NULL);
3064 		soumemb(p, real, 0);
3065 		soumemb(p, imag, 0);
3066 		q = dclstruct(rp);
3067 		cxsp[i] = q->n_sp = lookup(addname(n[i]), 0);
3068 		defid(q, TYPEDEF);
3069 		ap = attr_new(ATTR_COMPLEX, 0);
3070 		q->n_sp->sap = attr_add(q->n_sp->sap, ap);
3071 		nfree(q);
3072 	}
3073 	/* create function declarations for external ops */
3074 	for (i = 0; i < 3; i++) {
3075 		cxnmul[i] = addname(cxnmul[i]);
3076 		p->n_sp = cxmul[i] = lookup(cxnmul[i], 0);
3077 		p->n_type = FTN|STRTY;
3078 		p->n_ap = cxsp[i]->sap;
3079 		p->n_df = cxsp[i]->sdf;
3080 		defid2(p, EXTERN, 0);
3081 		cxmul[i]->sdf = permalloc(sizeof(union dimfun));
3082 		cxmul[i]->sdf->dfun = NULL;
3083 		cxndiv[i] = addname(cxndiv[i]);
3084 		p->n_sp = cxdiv[i] = lookup(cxndiv[i], 0);
3085 		p->n_type = FTN|STRTY;
3086 		p->n_ap = cxsp[i]->sap;
3087 		p->n_df = cxsp[i]->sdf;
3088 		defid2(p, EXTERN, 0);
3089 		cxdiv[i]->sdf = permalloc(sizeof(union dimfun));
3090 		cxdiv[i]->sdf->dfun = NULL;
3091 	}
3092 	nfree(p);
3093 	ddebug = d_debug;
3094 }
3095 
3096 /*
3097  * Return the highest real floating point type.
3098  * Known that at least one type is complex or imaginary.
3099  */
3100 static TWORD
3101 maxtyp(NODE *l, NODE *r)
3102 {
3103 	TWORD tl, tr, t;
3104 
3105 	tl = ANYCX(l) ? strmemb(l->n_ap)->stype : l->n_type;
3106 	tr = ANYCX(r) ? strmemb(r->n_ap)->stype : r->n_type;
3107 	if (ISITY(tl))
3108 		tl -= (FIMAG - FLOAT);
3109 	if (ISITY(tr))
3110 		tr -= (FIMAG - FLOAT);
3111 	t = tl > tr ? tl : tr;
3112 	if (!ISFTY(t))
3113 		cerror("maxtyp");
3114 	return t;
3115 }
3116 
3117 /*
3118  * Fetch space on stack for complex struct.
3119  */
3120 static NODE *
3121 cxstore(TWORD t)
3122 {
3123 	struct symtab s;
3124 
3125 	s = *cxsp[t - FLOAT];
3126 	s.sclass = AUTO;
3127 	s.soffset = NOOFFSET;
3128 	oalloc(&s, &autooff);
3129 	return nametree(&s);
3130 }
3131 
3132 #define	comop(x,y) buildtree(COMOP, x, y)
3133 
3134 /*
3135  * Convert node p to complex type dt.
3136  */
3137 static NODE *
3138 mkcmplx(NODE *p, TWORD dt)
3139 {
3140 	NODE *q, *r, *i, *t;
3141 
3142 	if (!ANYCX(p)) {
3143 		/* Not complex, convert to complex on stack */
3144 		q = cxstore(dt);
3145 		if (ISITY(p->n_type)) {
3146 			p->n_type = p->n_type - FIMAG + FLOAT;
3147 			r = bcon(0);
3148 			i = p;
3149 		} else {
3150 			r = p;
3151 			i = bcon(0);
3152 		}
3153 		p = buildtree(ASSIGN, structref(ccopy(q), DOT, real), r);
3154 		p = comop(p, buildtree(ASSIGN, structref(ccopy(q), DOT, imag), i));
3155 		p = comop(p, q);
3156 	} else {
3157 		if (strmemb(p->n_ap)->stype != dt) {
3158 			q = cxstore(dt);
3159 			p = buildtree(ADDROF, p, NIL);
3160 			t = tempnode(0, p->n_type, p->n_df, p->n_ap);
3161 			p = buildtree(ASSIGN, ccopy(t), p);
3162 			p = comop(p, buildtree(ASSIGN,
3163 			    structref(ccopy(q), DOT, real),
3164 			    structref(ccopy(t), STREF, real)));
3165 			p = comop(p, buildtree(ASSIGN,
3166 			    structref(ccopy(q), DOT, imag),
3167 			    structref(t, STREF, imag)));
3168 			p = comop(p, q);
3169 		}
3170 	}
3171 	return p;
3172 }
3173 
3174 static NODE *
3175 cxasg(NODE *l, NODE *r)
3176 {
3177 	TWORD tl, tr;
3178 
3179 	tl = strattr(l->n_ap) ? strmemb(l->n_ap)->stype : 0;
3180 	tr = strattr(r->n_ap) ? strmemb(r->n_ap)->stype : 0;
3181 
3182 	if (ANYCX(l) && ANYCX(r) && tl != tr) {
3183 		/* different types in structs */
3184 		r = mkcmplx(r, tl);
3185 	} else if (!ANYCX(l))
3186 		r = structref(r, DOT, ISITY(l->n_type) ? imag : real);
3187 	else if (!ANYCX(r))
3188 		r = mkcmplx(r, tl);
3189 	return buildtree(ASSIGN, l, r);
3190 }
3191 
3192 /*
3193  * Fixup complex operations.
3194  * At least one operand is complex.
3195  */
3196 NODE *
3197 cxop(int op, NODE *l, NODE *r)
3198 {
3199 	TWORD mxtyp;
3200 	NODE *p, *q;
3201 	NODE *ltemp, *rtemp;
3202 	NODE *real_l, *imag_l;
3203 	NODE *real_r, *imag_r;
3204 
3205 	if (op == ASSIGN)
3206 		return cxasg(l, r);
3207 
3208 	mxtyp = maxtyp(l, r);
3209 	l = mkcmplx(l, mxtyp);
3210 	if (op != UMINUS)
3211 		r = mkcmplx(r, mxtyp);
3212 
3213 
3214 	/* put a pointer to left and right elements in a TEMP */
3215 	l = buildtree(ADDROF, l, NIL);
3216 	ltemp = tempnode(0, l->n_type, l->n_df, l->n_ap);
3217 	l = buildtree(ASSIGN, ccopy(ltemp), l);
3218 
3219 	if (op != UMINUS) {
3220 		r = buildtree(ADDROF, r, NIL);
3221 		rtemp = tempnode(0, r->n_type, r->n_df, r->n_ap);
3222 		r = buildtree(ASSIGN, ccopy(rtemp), r);
3223 
3224 		p = comop(l, r);
3225 	} else
3226 		p = l;
3227 
3228 	/* create the four trees needed for calculation */
3229 	real_l = structref(ccopy(ltemp), STREF, real);
3230 	imag_l = structref(ltemp, STREF, imag);
3231 	if (op != UMINUS) {
3232 		real_r = structref(ccopy(rtemp), STREF, real);
3233 		imag_r = structref(rtemp, STREF, imag);
3234 	}
3235 
3236 	/* get storage on stack for the result */
3237 	q = cxstore(mxtyp);
3238 
3239 	switch (op) {
3240 	case NE:
3241 	case EQ:
3242 		tfree(q);
3243 		p = buildtree(op, comop(p, real_l), real_r);
3244 		q = buildtree(op, imag_l, imag_r);
3245 		p = buildtree(op == EQ ? ANDAND : OROR, p, q);
3246 		return p;
3247 
3248 	case ANDAND:
3249 	case OROR: /* go via EQ to get INT of it */
3250 		tfree(q);
3251 		p = buildtree(NE, comop(p, real_l), bcon(0)); /* gets INT */
3252 		q = buildtree(NE, imag_l, bcon(0));
3253 		p = buildtree(OR, p, q);
3254 
3255 		q = buildtree(NE, real_r, bcon(0));
3256 		q = buildtree(OR, q, buildtree(NE, imag_r, bcon(0)));
3257 
3258 		p = buildtree(op, p, q);
3259 		return p;
3260 
3261 	case UMINUS:
3262 		p = comop(p, buildtree(ASSIGN, structref(ccopy(q), DOT, real),
3263 		    buildtree(op, real_l, NIL)));
3264 		p = comop(p, buildtree(ASSIGN, structref(ccopy(q), DOT, imag),
3265 		    buildtree(op, imag_l, NIL)));
3266 		break;
3267 
3268 	case PLUS:
3269 	case MINUS:
3270 		p = comop(p, buildtree(ASSIGN, structref(ccopy(q), DOT, real),
3271 		    buildtree(op, real_l, real_r)));
3272 		p = comop(p, buildtree(ASSIGN, structref(ccopy(q), DOT, imag),
3273 		    buildtree(op, imag_l, imag_r)));
3274 		break;
3275 
3276 	case MUL:
3277 	case DIV:
3278 		/* Complex mul is "complex" */
3279 		/* (u+iv)*(x+iy)=((u*x)-(v*y))+i(v*x+y*u) */
3280 		/* Complex div is even more "complex" */
3281 		/* (u+iv)/(x+iy)=(u*x+v*y)/(x*x+y*y)+i((v*x-u*y)/(x*x+y*y)) */
3282 		/* but we need to do it via a subroutine */
3283 		tfree(q);
3284 		p = buildtree(CM, comop(p, real_l), imag_l);
3285 		p = buildtree(CM, p, real_r);
3286 		p = buildtree(CM, p, imag_r);
3287 		q = nametree(op == DIV ?
3288 		    cxdiv[mxtyp-FLOAT] : cxmul[mxtyp-FLOAT]);
3289 		return buildtree(CALL, q, p);
3290 		break;
3291 	default:
3292 		uerror("illegal operator %s", copst(op));
3293 	}
3294 	return comop(p, q);
3295 }
3296 
3297 /*
3298  * Fixup imaginary operations.
3299  * At least one operand is imaginary, none is complex.
3300  */
3301 NODE *
3302 imop(int op, NODE *l, NODE *r)
3303 {
3304 	NODE *p, *q;
3305 	TWORD mxtyp;
3306 	int li, ri;
3307 
3308 	li = ri = 0;
3309 	if (ISITY(l->n_type))
3310 		li = 1, l->n_type = l->n_type - (FIMAG-FLOAT);
3311 	if (ISITY(r->n_type))
3312 		ri = 1, r->n_type = r->n_type - (FIMAG-FLOAT);
3313 
3314 	mxtyp = maxtyp(l, r);
3315 	switch (op) {
3316 	case ASSIGN:
3317 		/* if both are imag, store value, otherwise store 0.0 */
3318 		if (!(li && ri)) {
3319 			tfree(r);
3320 			r = bcon(0);
3321 		}
3322 		p = buildtree(ASSIGN, l, r);
3323 		p->n_type += (FIMAG-FLOAT);
3324 		break;
3325 
3326 	case PLUS:
3327 		if (li && ri) {
3328 			p = buildtree(PLUS, l, r);
3329 			p->n_type += (FIMAG-FLOAT);
3330 		} else {
3331 			/* If one is imaginary and one is real, make complex */
3332 			if (li)
3333 				q = l, l = r, r = q; /* switch */
3334 			q = cxstore(mxtyp);
3335 			p = buildtree(ASSIGN,
3336 			    structref(ccopy(q), DOT, real), l);
3337 			p = comop(p, buildtree(ASSIGN,
3338 			    structref(ccopy(q), DOT, imag), r));
3339 			p = comop(p, q);
3340 		}
3341 		break;
3342 
3343 	case MINUS:
3344 		if (li && ri) {
3345 			p = buildtree(MINUS, l, r);
3346 			p->n_type += (FIMAG-FLOAT);
3347 		} else if (li) {
3348 			q = cxstore(mxtyp);
3349 			p = buildtree(ASSIGN, structref(ccopy(q), DOT, real),
3350 			    buildtree(UMINUS, r, NIL));
3351 			p = comop(p, buildtree(ASSIGN,
3352 			    structref(ccopy(q), DOT, imag), l));
3353 			p = comop(p, q);
3354 		} else /* if (ri) */ {
3355 			q = cxstore(mxtyp);
3356 			p = buildtree(ASSIGN,
3357 			    structref(ccopy(q), DOT, real), l);
3358 			p = comop(p, buildtree(ASSIGN,
3359 			    structref(ccopy(q), DOT, imag),
3360 			    buildtree(UMINUS, r, NIL)));
3361 			p = comop(p, q);
3362 		}
3363 		break;
3364 
3365 	case MUL:
3366 		p = buildtree(MUL, l, r);
3367 		if (li && ri)
3368 			p = buildtree(UMINUS, p, NIL);
3369 		if (li ^ ri)
3370 			p->n_type += (FIMAG-FLOAT);
3371 		break;
3372 
3373 	case DIV:
3374 		p = buildtree(DIV, l, r);
3375 		if (ri && !li)
3376 			p = buildtree(UMINUS, p, NIL);
3377 		if (li ^ ri)
3378 			p->n_type += (FIMAG-FLOAT);
3379 		break;
3380 
3381 	case EQ:
3382 	case NE:
3383 	case LT:
3384 	case LE:
3385 	case GT:
3386 	case GE:
3387 		if (li ^ ri) { /* always 0 */
3388 			tfree(l);
3389 			tfree(r);
3390 			p = bcon(0);
3391 		} else
3392 			p = buildtree(op, l, r);
3393 		break;
3394 
3395 	default:
3396 		cerror("imop");
3397 		p = NULL;
3398 	}
3399 	return p;
3400 }
3401 
3402 NODE *
3403 cxelem(int op, NODE *p)
3404 {
3405 
3406 	if (ANYCX(p)) {
3407 		p = structref(p, DOT, op == XREAL ? real : imag);
3408 	} else if (op == XIMAG) {
3409 		/* XXX  sanitycheck? */
3410 		tfree(p);
3411 		p = bcon(0);
3412 	}
3413 	return p;
3414 }
3415 
3416 NODE *
3417 cxconj(NODE *p)
3418 {
3419 	NODE *q, *r;
3420 
3421 	/* XXX side effects? */
3422 	q = cxstore(strmemb(p->n_ap)->stype);
3423 	r = buildtree(ASSIGN, structref(ccopy(q), DOT, real),
3424 	    structref(ccopy(p), DOT, real));
3425 	r = comop(r, buildtree(ASSIGN, structref(ccopy(q), DOT, imag),
3426 	    buildtree(UMINUS, structref(p, DOT, imag), NIL)));
3427 	return comop(r, q);
3428 }
3429 
3430 /*
3431  * Prepare for return.
3432  * There may be implicit casts to other types.
3433  */
3434 NODE *
3435 cxret(NODE *p, NODE *q)
3436 {
3437 	if (ANYCX(q)) { /* Return complex type */
3438 		p = mkcmplx(p, strmemb(q->n_ap)->stype);
3439 	} else if (ISFTY(q->n_type) || ISITY(q->n_type)) { /* real or imag */
3440 		p = structref(p, DOT, ISFTY(q->n_type) ? real : imag);
3441 		if (p->n_type != q->n_type)
3442 			p = cast(p, q->n_type, 0);
3443 	} else
3444 		cerror("cxred failing type");
3445 	return p;
3446 }
3447 
3448 /*
3449  * either p1 or p2 is complex, so fixup the remaining type accordingly.
3450  */
3451 NODE *
3452 cxcast(NODE *p1, NODE *p2)
3453 {
3454 	if (ANYCX(p1) && ANYCX(p2)) {
3455 		if (p1->n_type != p2->n_type)
3456 			p2 = mkcmplx(p2, p1->n_type);
3457 	} else if (ANYCX(p1)) {
3458 		p2 = mkcmplx(p2, p1->n_type);
3459 	} else /* if (ANYCX(p2)) */ {
3460 		p2 = cast(structref(p2, DOT, real), p1->n_type, 0);
3461 	}
3462 	nfree(p1);
3463 	return p2;
3464 }
3465 #endif
3466