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