Home | History | Annotate | Line # | Download | only in mip
      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 (at) ludd.luth.se).
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     26  */
     27 
     28 /*
     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
     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
     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
    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
    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
    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
    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
    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
    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 *
    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 *
    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
    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
    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 *
    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
    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
    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
    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
    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 *
    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 *
    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 *
    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 *
    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
    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
    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
    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 *
    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
    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
    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 *
    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
    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
    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 *
    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 *
    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 *
    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 *
    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 *
    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 *
    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 *
    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 *
   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