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