xref: /netbsd-src/external/bsd/pcc/dist/pcc/mip/common.c (revision 41b9722a1abf231082724f766574d77aa46a5bdd)
1 /*	Id: common.c,v 1.122 2015/09/30 20:04:30 ragge Exp 	*/
2 /*	$NetBSD: common.c,v 1.7 2016/02/09 20:37:32 plunky Exp $	*/
3 /*
4  * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 /*
29  * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
30  *
31  * Redistribution and use in source and binary forms, with or without
32  * modification, are permitted provided that the following conditions
33  * are met:
34  *
35  * Redistributions of source code and documentation must retain the above
36  * copyright notice, this list of conditions and the following disclaimer.
37  * Redistributions in binary form must reproduce the above copyright
38  * notice, this list of conditionsand the following disclaimer in the
39  * documentation and/or other materials provided with the distribution.
40  * All advertising materials mentioning features or use of this software
41  * must display the following acknowledgement:
42  * 	This product includes software developed or owned by Caldera
43  *	International, Inc.
44  * Neither the name of Caldera International, Inc. nor the names of other
45  * contributors may be used to endorse or promote products derived from
46  * this software without specific prior written permission.
47  *
48  * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
49  * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
50  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
51  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
52  * DISCLAIMED.  IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE
53  * FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56  * HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT,
57  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
58  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
59  * POSSIBILITY OF SUCH DAMAGE.
60  */
61 
62 #include <stdarg.h>
63 #include <stddef.h>
64 #include <stdlib.h>
65 #include <stdio.h>
66 #include <string.h>
67 
68 #include "pass2.h"
69 #include "unicode.h"
70 
71 # ifndef EXIT
72 # define EXIT exit
73 # endif
74 
75 int nerrors = 0;  /* number of errors */
76 extern char *ftitle;
77 int lineno;
78 int savstringsz, newattrsz, nodesszcnt;
79 
80 int warniserr = 0;
81 
82 #ifndef WHERE
83 #define	WHERE(ch) fprintf(stderr, "%s, line %d: ", ftitle, lineno);
84 #endif
85 
86 static void
incerr(void)87 incerr(void)
88 {
89 	if (++nerrors > 30)
90 		cerror("too many errors");
91 }
92 
93 /*
94  * nonfatal error message
95  * the routine where is different for pass 1 and pass 2;
96  * it tells where the error took place
97  */
98 void
uerror(const char * s,...)99 uerror(const char *s, ...)
100 {
101 	va_list ap;
102 
103 	va_start(ap, s);
104 	WHERE('u');
105 	vfprintf(stderr, s, ap);
106 	fprintf(stderr, "\n");
107 	va_end(ap);
108 	incerr();
109 }
110 
111 /*
112  * compiler error: die
113  */
114 void
cerror(const char * s,...)115 cerror(const char *s, ...)
116 {
117 	va_list ap;
118 
119 	va_start(ap, s);
120 	WHERE('c');
121 
122 	/* give the compiler the benefit of the doubt */
123 	if (nerrors && nerrors <= 30) {
124 		fprintf(stderr,
125 		    "cannot recover from earlier errors: goodbye!\n");
126 	} else {
127 		fprintf(stderr, "compiler error: ");
128 		vfprintf(stderr, s, ap);
129 		fprintf(stderr, "\n");
130 	}
131 	va_end(ap);
132 	EXIT(1);
133 }
134 
135 /*
136  * warning
137  */
138 void
u8error(const char * s,...)139 u8error(const char *s, ...)
140 {
141 	va_list ap;
142 	va_start(ap, s);
143 	WHERE('w');
144 	fprintf(stderr, "warning: ");
145 	vfprintf(stderr, s, ap);
146 	fprintf(stderr, "\n");
147 	va_end(ap);
148 	if (warniserr)
149 		incerr();
150 }
151 
152 #ifdef MKEXT
153 int wdebug;
154 #endif
155 
156 /*
157  * warning
158  */
159 void
werror(const char * s,...)160 werror(const char *s, ...)
161 {
162 	extern int wdebug;
163 	va_list ap;
164 
165 	if (wdebug)
166 		return;
167 	va_start(ap, s);
168 	WHERE('w');
169 	fprintf(stderr, "warning: ");
170 	vfprintf(stderr, s, ap);
171 	fprintf(stderr, "\n");
172 	va_end(ap);
173 	if (warniserr)
174 		incerr();
175 }
176 
177 #ifndef MKEXT
178 
179 struct Warning {
180 	char *flag;
181 	char warn;
182 	char err;
183 	char *fmt;
184 };
185 
186 /*
187  * conditional warnings
188  */
189 struct Warning Warnings[] = {
190 	{
191 		"truncate", 0, 0,
192 		"conversion from '%s' to '%s' may alter its value"
193 	}, {
194 		"strict-prototypes", 0, 0,
195 		"function declaration isn't a prototype"
196 	}, {
197 		"missing-prototypes", 0, 0,
198 		"no previous prototype for `%s'"
199 	}, {
200 		"implicit-int", 0, 0,
201 		"return type defaults to `int'",
202 	}, {
203 		"implicit-function-declaration", 0, 0,
204 		"implicit declaration of function '%s'"
205 	}, {
206 		"shadow", 0, 0,
207 		"declaration of '%s' shadows a %s declaration"
208 	}, {
209 		"pointer-sign", 0, 0,
210 		"illegal pointer combination"
211 	}, {
212 		"sign-compare", 0, 0,
213 		"comparison between signed and unsigned"
214 	}, {
215 		"unknown-pragmas", 0, 0,
216 		"ignoring #pragma %s %s"
217 	}, {
218 		"unreachable-code", 0, 0,
219 		"statement not reached"
220 	}, {
221 		"deprecated-declarations", 1, 0,
222 		"`%s' is deprecated"
223 	}, {
224 		"attributes", 1, 0,
225 		"unsupported attribute `%s'"
226 	}, {	NULL	}
227 };
228 
229 /*
230  * set the warn/err status of a conditional warning
231  */
232 int
Wset(char * str,int warn,int err)233 Wset(char *str, int warn, int err)
234 {
235 	struct Warning *w = Warnings;
236 
237 	for (w = Warnings; w->flag; w++) {
238 		if (strcmp(w->flag, str) == 0) {
239 			w->warn = warn;
240 			w->err = err;
241 			return 0;
242 		}
243 	}
244 	return 1;
245 }
246 
247 /*
248  * handle a conditional warning flag.
249  */
250 void
Wflags(char * str)251 Wflags(char *str)
252 {
253 	struct Warning *w;
254 	int isset, iserr;
255 
256 	/* handle -Werror specially */
257 	if (strcmp("error", str) == 0) {
258 		for (w = Warnings; w->flag; w++)
259 			w->err = 1;
260 
261 		warniserr = 1;
262 		return;
263 	}
264 
265 	isset = 1;
266 	if (strncmp("no-", str, 3) == 0) {
267 		str += 3;
268 		isset = 0;
269 	}
270 
271 	iserr = 0;
272 	if (strncmp("error=", str, 6) == 0) {
273 		str += 6;
274 		iserr = 1;
275 	}
276 
277 	for (w = Warnings; w->flag; w++) {
278 		if (strcmp(w->flag, str) != 0)
279 			continue;
280 
281 		if (isset) {
282 			if (iserr)
283 				w->err = 1;
284 			w->warn = 1;
285 		} else if (iserr) {
286 			w->err = 0;
287 		} else {
288 			w->warn = 0;
289 		}
290 
291 		return;
292 	}
293 
294 	fprintf(stderr, "unrecognised warning option '%s'\n", str);
295 }
296 
297 /*
298  * emit a conditional warning
299  */
300 void
warner(int type,...)301 warner(int type, ...)
302 {
303 	va_list ap;
304 	char *t;
305 #ifndef PASS2
306 	extern int issyshdr;
307 
308 	if (issyshdr && type == Wtruncate)
309 		return; /* Too many false positives */
310 #endif
311 
312 	if (Warnings[type].warn == 0)
313 		return; /* no warning */
314 	if (Warnings[type].err) {
315 		t = "error";
316 		incerr();
317 	} else
318 		t = "warning";
319 
320 	va_start(ap, type);
321 	fprintf(stderr, "%s:%d: %s: ", ftitle, lineno, t);
322 	vfprintf(stderr, Warnings[type].fmt, ap);
323 	fprintf(stderr, "\n");
324 	va_end(ap);
325 }
326 #endif /* MKEXT */
327 
328 #ifndef MKEXT
329 static NODE *freelink;
330 int usednodes;
331 
332 #ifndef LANG_F77
333 NODE *
talloc(void)334 talloc(void)
335 {
336 	register NODE *p;
337 
338 	usednodes++;
339 
340 	if (freelink != NULL) {
341 		p = freelink;
342 		freelink = p->n_left;
343 		if (p->n_op != FREE)
344 			cerror("node not FREE: %p", p);
345 		if (ndebug)
346 			printf("alloc node %p from freelist\n", p);
347 		return p;
348 	}
349 
350 	p = permalloc(sizeof(NODE));
351 	nodesszcnt += sizeof(NODE);
352 	p->n_op = FREE;
353 	if (ndebug)
354 		printf("alloc node %p from memory\n", p);
355 	return p;
356 }
357 #endif
358 
359 /*
360  * make a fresh copy of p
361  */
362 NODE *
tcopy(NODE * p)363 tcopy(NODE *p)
364 {
365 	NODE *q;
366 
367 	q = talloc();
368 	*q = *p;
369 
370 	switch (optype(q->n_op)) {
371 	case BITYPE:
372 		q->n_right = tcopy(p->n_right);
373 	case UTYPE:
374 		q->n_left = tcopy(p->n_left);
375 	}
376 
377 	return(q);
378 }
379 
380 #ifndef LANG_F77
381 /*
382  * ensure that all nodes have been freed
383  */
384 void
tcheck(void)385 tcheck(void)
386 {
387 #ifdef LANG_CXX
388 	extern int inlnodecnt;
389 #else
390 #define	inlnodecnt 0
391 #endif
392 
393 	if (nerrors)
394 		return;
395 
396 	if ((usednodes - inlnodecnt) != 0)
397 		cerror("usednodes == %d, inlnodecnt %d", usednodes, inlnodecnt);
398 }
399 #endif
400 
401 /*
402  * free the tree p
403  */
404 void
tfree(NODE * p)405 tfree(NODE *p)
406 {
407 	if (p->n_op != FREE)
408 		walkf(p, (void (*)(NODE *, void *))nfree, 0);
409 }
410 
411 /*
412  * Free a node, and return its left descendant.
413  * It is up to the caller to know whether the return value is usable.
414  */
415 NODE *
nfree(NODE * p)416 nfree(NODE *p)
417 {
418 	NODE *l;
419 #ifdef PCC_DEBUG_NODES
420 	NODE *q;
421 #endif
422 
423 	if (p == NULL)
424 		cerror("freeing blank node!");
425 
426 	l = p->n_left;
427 	if (p->n_op == FREE)
428 		cerror("freeing FREE node", p);
429 #ifdef PCC_DEBUG_NODES
430 	q = freelink;
431 	while (q != NULL) {
432 		if (q == p)
433 			cerror("freeing free node %p", p);
434 		q = q->n_left;
435 	}
436 #endif
437 
438 	if (ndebug)
439 		printf("freeing node %p\n", p);
440 	p->n_op = FREE;
441 	p->n_left = freelink;
442 	freelink = p;
443 	usednodes--;
444 	return l;
445 }
446 #endif
447 
448 #ifdef LANG_F77
449 #define OPTYPE(x) optype(x)
450 #else
451 #define OPTYPE(x) coptype(x)
452 #endif
453 
454 #ifdef MKEXT
455 #define coptype(o)	(dope[o]&TYFLG)
456 #else
457 #ifndef PASS2
458 int cdope(int);
459 #define coptype(o)	(cdope(o)&TYFLG)
460 #else
461 #define coptype(o)	(dope[o]&TYFLG)
462 #endif
463 #endif
464 
465 void
fwalk(NODE * t,void (* f)(NODE *,int,int *,int *),int down)466 fwalk(NODE *t, void (*f)(NODE *, int, int *, int *), int down)
467 {
468 
469 	int down1, down2;
470 
471 	more:
472 	down1 = down2 = 0;
473 
474 	(*f)(t, down, &down1, &down2);
475 
476 	switch (OPTYPE( t->n_op )) {
477 
478 	case BITYPE:
479 		fwalk( t->n_left, f, down1 );
480 		t = t->n_right;
481 		down = down2;
482 		goto more;
483 
484 	case UTYPE:
485 		t = t->n_left;
486 		down = down1;
487 		goto more;
488 
489 	}
490 }
491 
492 void
walkf(NODE * t,void (* f)(NODE *,void *),void * arg)493 walkf(NODE *t, void (*f)(NODE *, void *), void *arg)
494 {
495 	int opty;
496 
497 
498 	opty = OPTYPE(t->n_op);
499 
500 	if (opty != LTYPE)
501 		walkf( t->n_left, f, arg );
502 	if (opty == BITYPE)
503 		walkf( t->n_right, f, arg );
504 	(*f)(t, arg);
505 }
506 
507 int dope[DSIZE];
508 char *opst[DSIZE];
509 
510 struct dopest {
511 	int dopeop;
512 	char opst[8];
513 	int dopeval;
514 } indope[] = {
515 	{ NAME, "NAME", LTYPE, },
516 	{ REG, "REG", LTYPE, },
517 	{ OREG, "OREG", LTYPE, },
518 	{ TEMP, "TEMP", LTYPE, },
519 	{ ICON, "ICON", LTYPE, },
520 	{ FCON, "FCON", LTYPE, },
521 	{ CCODES, "CCODES", LTYPE, },
522 	{ UMINUS, "U-", UTYPE, },
523 	{ UMUL, "U*", UTYPE, },
524 	{ FUNARG, "FUNARG", UTYPE, },
525 	{ UCALL, "UCALL", UTYPE|CALLFLG, },
526 	{ UFORTCALL, "UFCALL", UTYPE|CALLFLG, },
527 	{ COMPL, "~", UTYPE, },
528 	{ FORCE, "FORCE", UTYPE, },
529 	{ XARG, "XARG", UTYPE, },
530 	{ XASM, "XASM", BITYPE, },
531 	{ SCONV, "SCONV", UTYPE, },
532 	{ PCONV, "PCONV", UTYPE, },
533 	{ PLUS, "+", BITYPE|FLOFLG|SIMPFLG|COMMFLG, },
534 	{ MINUS, "-", BITYPE|FLOFLG|SIMPFLG, },
535 	{ MUL, "*", BITYPE|FLOFLG|MULFLG, },
536 	{ AND, "&", BITYPE|SIMPFLG|COMMFLG, },
537 	{ CM, ",", BITYPE, },
538 	{ ASSIGN, "=", BITYPE|ASGFLG, },
539 	{ DIV, "/", BITYPE|FLOFLG|MULFLG|DIVFLG, },
540 	{ MOD, "%", BITYPE|DIVFLG, },
541 	{ LS, "<<", BITYPE|SHFFLG, },
542 	{ RS, ">>", BITYPE|SHFFLG, },
543 	{ OR, "|", BITYPE|COMMFLG|SIMPFLG, },
544 	{ ER, "^", BITYPE|COMMFLG|SIMPFLG, },
545 	{ CALL, "CALL", BITYPE|CALLFLG, },
546 	{ FORTCALL, "FCALL", BITYPE|CALLFLG, },
547 	{ EQ, "==", BITYPE|LOGFLG, },
548 	{ NE, "!=", BITYPE|LOGFLG, },
549 	{ LE, "<=", BITYPE|LOGFLG, },
550 	{ LT, "<", BITYPE|LOGFLG, },
551 	{ GE, ">=", BITYPE|LOGFLG, },
552 	{ GT, ">", BITYPE|LOGFLG, },
553 	{ UGT, "UGT", BITYPE|LOGFLG, },
554 	{ UGE, "UGE", BITYPE|LOGFLG, },
555 	{ ULT, "ULT", BITYPE|LOGFLG, },
556 	{ ULE, "ULE", BITYPE|LOGFLG, },
557 	{ CBRANCH, "CBRANCH", BITYPE, },
558 	{ FLD, "FLD", UTYPE, },
559 	{ PMCONV, "PMCONV", BITYPE, },
560 	{ PVCONV, "PVCONV", BITYPE, },
561 	{ RETURN, "RETURN", BITYPE|ASGFLG|ASGOPFLG, },
562 	{ GOTO, "GOTO", UTYPE, },
563 	{ STASG, "STASG", BITYPE|ASGFLG, },
564 	{ STARG, "STARG", UTYPE, },
565 	{ STCALL, "STCALL", BITYPE|CALLFLG, },
566 	{ USTCALL, "USTCALL", UTYPE|CALLFLG, },
567 	{ ADDROF, "U&", UTYPE, },
568 
569 	{ -1,	"",	0 },
570 };
571 
572 void
mkdope(void)573 mkdope(void)
574 {
575 	struct dopest *q;
576 
577 	for( q = indope; q->dopeop >= 0; ++q ){
578 		dope[q->dopeop] = q->dopeval;
579 		opst[q->dopeop] = q->opst;
580 	}
581 }
582 
583 /*
584  * output a nice description of the type of t
585  */
586 void
tprint(TWORD t,TWORD q)587 tprint(TWORD t, TWORD q)
588 {
589 	static char * tnames[BTMASK+1] = {
590 		"undef",
591 		"bool",
592 		"char",
593 		"uchar",
594 		"short",
595 		"ushort",
596 		"int",
597 		"unsigned",
598 		"long",
599 		"ulong",
600 		"longlong",
601 		"ulonglong",
602 		"float",
603 		"double",
604 		"ldouble",
605 		"strty",
606 		"unionty",
607 		"enumty",
608 		"moety",
609 		"void",
610 		"signed", /* pass1 */
611 		"farg", /* pass1 */
612 		"fimag", /* pass1 */
613 		"dimag", /* pass1 */
614 		"limag", /* pass1 */
615 		"fcomplex", /* pass1 */
616 		"dcomplex", /* pass1 */
617 		"lcomplex", /* pass1 */
618 		"enumty", /* pass1 */
619 		"?", "?", "?"
620 		};
621 
622 	for(;; t = DECREF(t), q = DECREF(q)) {
623 		if (ISCON(q))
624 			putchar('C');
625 		if (ISVOL(q))
626 			putchar('V');
627 
628 		if (ISPTR(t))
629 			printf("PTR ");
630 		else if (ISFTN(t))
631 			printf("FTN ");
632 		else if (ISARY(t))
633 			printf("ARY ");
634 		else {
635 			printf("%s%s%s", ISCON(q << TSHIFT) ? "const " : "",
636 			    ISVOL(q << TSHIFT) ? "volatile " : "", tnames[t]);
637 			return;
638 		}
639 	}
640 }
641 
642 /*
643  * Memory allocation routines.
644  * Memory are allocated from the system in MEMCHUNKSZ blocks.
645  * permalloc() returns a bunch of memory that is never freed.
646  * Memory allocated through tmpalloc() will be released the
647  * next time a function is ended (via tmpfree()).
648  */
649 
650 #define	MEMCHUNKSZ 8192	/* 8k per allocation */
651 struct balloc {
652 	char a1;
653 	union {
654 		long long l;
655 		long double d;
656 	} a2;
657 };
658 
659 #define	ALIGNMENT offsetof(struct balloc, a2)
660 #define	ROUNDUP(x) (((x) + ((ALIGNMENT)-1)) & ~((ALIGNMENT)-1))
661 
662 static char *allocpole;
663 static size_t allocleft;
664 size_t permallocsize, tmpallocsize, lostmem;
665 
666 void *
permalloc(size_t size)667 permalloc(size_t size)
668 {
669 	void *rv;
670 
671 	if (size > MEMCHUNKSZ) {
672 		if ((rv = malloc(size)) == NULL)
673 			cerror("permalloc: missing %d bytes", size);
674 		return rv;
675 	}
676 	if (size == 0)
677 		cerror("permalloc2");
678 	if (allocleft < size) {
679 		/* loses unused bytes */
680 		lostmem += allocleft;
681 		if ((allocpole = malloc(MEMCHUNKSZ)) == NULL)
682 			cerror("permalloc: out of memory");
683 		allocleft = MEMCHUNKSZ;
684 	}
685 	size = ROUNDUP(size);
686 	rv = &allocpole[MEMCHUNKSZ-allocleft];
687 	allocleft -= size;
688 	permallocsize += size;
689 	return rv;
690 }
691 
692 void *
tmpcalloc(size_t size)693 tmpcalloc(size_t size)
694 {
695 	void *rv;
696 
697 	rv = tmpalloc(size);
698 	memset(rv, 0, size);
699 	return rv;
700 }
701 
702 /*
703  * Duplicate a string onto the temporary heap.
704  */
705 char *
tmpstrdup(char * str)706 tmpstrdup(char *str)
707 {
708 	size_t len;
709 
710 	len = strlen(str) + 1;
711 	return memcpy(tmpalloc(len), str, len);
712 }
713 
714 /*
715  * Allocation routines for temporary memory.
716  */
717 #if 0
718 #define	ALLDEBUG(x)	printf x
719 #else
720 #define	ALLDEBUG(x)
721 #endif
722 
723 #define	NELEM	((MEMCHUNKSZ-ROUNDUP(sizeof(struct xalloc *)))/ALIGNMENT)
724 #define	ELEMSZ	(ALIGNMENT)
725 #define	MAXSZ	(NELEM*ELEMSZ)
726 struct xalloc {
727 	struct xalloc *next;
728 	union {
729 		struct balloc b; /* for initial alignment */
730 		char elm[MAXSZ];
731 	} u;
732 } *tapole, *tmpole;
733 int uselem = NELEM; /* next unused element */
734 
735 void *
tmpalloc(size_t size)736 tmpalloc(size_t size)
737 {
738 	struct xalloc *xp;
739 	void *rv;
740 	size_t nelem;
741 
742 	nelem = ROUNDUP(size)/ELEMSZ;
743 	ALLDEBUG(("tmpalloc(%ld,%ld) %zd (%zd) ", ELEMSZ, NELEM, size, nelem));
744 	if (nelem > NELEM/2) {
745 		size += ROUNDUP(sizeof(struct xalloc *));
746 		if ((xp = malloc(size)) == NULL)
747 			cerror("out of memory");
748 		ALLDEBUG(("XMEM! (%zd,%p) ", size, xp));
749 		xp->next = tmpole;
750 		tmpole = xp;
751 		ALLDEBUG(("rv %p\n", &xp->u.elm[0]));
752 		return &xp->u.elm[0];
753 	}
754 	if (nelem + uselem >= NELEM) {
755 		ALLDEBUG(("MOREMEM! "));
756 		/* alloc more */
757 		if ((xp = malloc(sizeof(struct xalloc))) == NULL)
758 			cerror("out of memory");
759 		xp->next = tapole;
760 		tapole = xp;
761 		uselem = 0;
762 	} else
763 		xp = tapole;
764 	rv = &xp->u.elm[uselem * ELEMSZ];
765 	ALLDEBUG(("elemno %d ", uselem));
766 	uselem += nelem;
767 	ALLDEBUG(("new %d rv %p\n", uselem, rv));
768 	return rv;
769 }
770 
771 void
tmpfree(void)772 tmpfree(void)
773 {
774 	struct xalloc *x1;
775 
776 	while (tmpole) {
777 		x1 = tmpole;
778 		tmpole = tmpole->next;
779 		ALLDEBUG(("XMEM! free %p\n", x1));
780 		free(x1);
781 	}
782 	while (tapole && tapole->next) {
783 		x1 = tapole;
784 		tapole = tapole->next;
785 		ALLDEBUG(("MOREMEM! free %p\n", x1));
786 		free(x1);
787 	}
788 	if (tapole)
789 		uselem = 0;
790 }
791 
792 /*
793  * Set a mark for later removal from the temp heap.
794  */
795 void
markset(struct mark * m)796 markset(struct mark *m)
797 {
798 	m->tmsav = tmpole;
799 	m->tasav = tapole;
800 	m->elem = uselem;
801 }
802 
803 /*
804  * Remove everything on tmp heap from a mark.
805  */
806 void
markfree(struct mark * m)807 markfree(struct mark *m)
808 {
809 	struct xalloc *x1;
810 
811 	while (tmpole != m->tmsav) {
812 		x1 = tmpole;
813 		tmpole = tmpole->next;
814 		free(x1);
815 	}
816 	while (tapole != m->tasav) {
817 		x1 = tapole;
818 		tapole = tapole->next;
819 		free(x1);
820 	}
821 	uselem = m->elem;
822 }
823 
824 /*
825  * Allocate space on the permanent stack for a string of length len+1
826  * and copy it there.
827  * Return the new address.
828  */
829 char *
newstring(char * s,size_t len)830 newstring(char *s, size_t len)
831 {
832 	char *u, *c;
833 
834 	len++;
835 	savstringsz += len;
836 	if (allocleft < len) {
837 		u = c = permalloc(len);
838 	} else {
839 		u = c = &allocpole[MEMCHUNKSZ-allocleft];
840 		allocleft -= ROUNDUP(len);
841 		permallocsize += ROUNDUP(len);
842 	}
843 	while (len--)
844 		*c++ = *s++;
845 	return u;
846 }
847 
848 /*
849  * Do a preorder walk of the CM list p and apply function f on each element.
850  */
851 void
flist(NODE * p,void (* f)(NODE *,void *),void * arg)852 flist(NODE *p, void (*f)(NODE *, void *), void *arg)
853 {
854 	if (p->n_op == CM) {
855 		(*f)(p->n_right, arg);
856 		flist(p->n_left, f, arg);
857 	} else
858 		(*f)(p, arg);
859 }
860 
861 /*
862  * The same as flist but postorder.
863  */
864 void
listf(NODE * p,void (* f)(NODE *))865 listf(NODE *p, void (*f)(NODE *))
866 {
867 	if (p->n_op == CM) {
868 		listf(p->n_left, f);
869 		(*f)(p->n_right);
870 	} else
871 		(*f)(p);
872 }
873 
874 /*
875  * Get list argument number n from list, or NIL if out of list.
876  */
877 NODE *
listarg(NODE * p,int n,int * cnt)878 listarg(NODE *p, int n, int *cnt)
879 {
880 	NODE *r;
881 
882 	if (p->n_op == CM) {
883 		r = listarg(p->n_left, n, cnt);
884 		if (n == ++(*cnt))
885 			r = p->n_right;
886 	} else {
887 		*cnt = 0;
888 		r = n == 0 ? p : NIL;
889 	}
890 	return r;
891 }
892 
893 /*
894  * Make a type unsigned, if possible.
895  */
896 TWORD
enunsign(TWORD t)897 enunsign(TWORD t)
898 {
899 	if (BTYPE(t) >= CHAR && BTYPE(t) <= ULONGLONG)
900 		t |= 1;
901 	return t;
902 }
903 
904 /*
905  * Make a type signed, if possible.
906  */
907 TWORD
deunsign(TWORD t)908 deunsign(TWORD t)
909 {
910 	if (BTYPE(t) >= CHAR && BTYPE(t) <= ULONGLONG)
911 		t &= ~1;
912 	return t;
913 }
914 
915 /*
916  * Attribute functions.
917  */
918 struct attr *
attr_new(int type,int nelem)919 attr_new(int type, int nelem)
920 {
921 	struct attr *ap;
922 	int sz;
923 
924 	sz = sizeof(struct attr) + nelem * sizeof(union aarg);
925 
926 	ap = memset(permalloc(sz), 0, sz);
927 	newattrsz += sz;
928 	ap->atype = type;
929 	ap->sz = nelem;
930 	return ap;
931 }
932 
933 /*
934  * Add attribute list new before old and return new.
935  */
936 struct attr *
attr_add(struct attr * old,struct attr * new)937 attr_add(struct attr *old, struct attr *new)
938 {
939 	struct attr *ap;
940 
941 	if (new == NULL)
942 		return old; /* nothing to add */
943 
944 	for (ap = new; ap->next; ap = ap->next)
945 		;
946 	ap->next = old;
947 	return new;
948 }
949 
950 /*
951  * Search for attribute type in list ap.  Return entry or NULL.
952  */
953 struct attr *
attr_find(struct attr * ap,int type)954 attr_find(struct attr *ap, int type)
955 {
956 
957 	for (; ap && ap->atype != type; ap = ap->next)
958 		;
959 	return ap;
960 }
961 
962 /*
963  * Copy an attribute struct.
964  * Return destination.
965  */
966 struct attr *
attr_copy(struct attr * aps,struct attr * apd,int n)967 attr_copy(struct attr *aps, struct attr *apd, int n)
968 {
969 	int sz = sizeof(struct attr) + n * sizeof(union aarg);
970 	return memcpy(apd, aps, sz);
971 }
972 
973 /*
974  * Duplicate an attribute, like strdup.
975  */
976 struct attr *
attr_dup(struct attr * ap)977 attr_dup(struct attr *ap)
978 {
979 	int sz = sizeof(struct attr) + ap->sz * sizeof(union aarg);
980 	ap = memcpy(permalloc(sz), ap, sz);
981 	ap->next = NULL;
982 	return ap;
983 }
984 
985 void *
xmalloc(int size)986 xmalloc(int size)
987 {
988 	void *rv;
989 
990 	if ((rv = malloc(size)) == NULL)
991 		cerror("out of memory!");
992 	return rv;
993 }
994 
995 void *
xstrdup(char * s)996 xstrdup(char *s)
997 {
998 	void *rv;
999 
1000 	if ((rv = strdup(s)) == NULL)
1001 		cerror("out of memory!");
1002 	return rv;
1003 }
1004 
1005 void *
xcalloc(int a,int b)1006 xcalloc(int a, int b)
1007 {
1008 	void *rv;
1009 
1010 	if ((rv = calloc(a, b)) == NULL)
1011 		cerror("out of memory!");
1012 	return rv;
1013 }
1014