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