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
75int nerrors = 0;  /* number of errors */
76extern char *ftitle;
77int lineno;
78int savstringsz, newattrsz, nodesszcnt;
79
80int warniserr = 0;
81
82#ifndef WHERE
83#define	WHERE(ch) fprintf(stderr, "%s, line %d: ", ftitle, lineno);
84#endif
85
86static void
87incerr(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 */
98void
99uerror(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 */
114void
115cerror(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 */
138void
139u8error(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
153int wdebug;
154#endif
155
156/*
157 * warning
158 */
159void
160werror(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
179struct Warning {
180	char *flag;
181	char warn;
182	char err;
183	char *fmt;
184};
185
186/*
187 * conditional warnings
188 */
189struct 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 */
232int
233Wset(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 */
250void
251Wflags(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 */
300void
301warner(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
329static NODE *freelink;
330int usednodes;
331
332#ifndef LANG_F77
333NODE *
334talloc(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 */
362NODE *
363tcopy(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 */
384void
385tcheck(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 */
404void
405tfree(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 */
415NODE *
416nfree(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
458int cdope(int);
459#define coptype(o)	(cdope(o)&TYFLG)
460#else
461#define coptype(o)	(dope[o]&TYFLG)
462#endif
463#endif
464
465void
466fwalk(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
492void
493walkf(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
507int dope[DSIZE];
508char *opst[DSIZE];
509
510struct 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
572void
573mkdope(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 */
586void
587tprint(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 */
651struct 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
662static char *allocpole;
663static size_t allocleft;
664size_t permallocsize, tmpallocsize, lostmem;
665
666void *
667permalloc(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
692void *
693tmpcalloc(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 */
705char *
706tmpstrdup(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)
726struct xalloc {
727	struct xalloc *next;
728	union {
729		struct balloc b; /* for initial alignment */
730		char elm[MAXSZ];
731	} u;
732} *tapole, *tmpole;
733int uselem = NELEM; /* next unused element */
734
735void *
736tmpalloc(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
771void
772tmpfree(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 */
795void
796markset(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 */
806void
807markfree(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 */
829char *
830newstring(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 */
851void
852flist(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 */
864void
865listf(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 */
877NODE *
878listarg(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 */
896TWORD
897enunsign(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 */
907TWORD
908deunsign(TWORD t)
909{
910	if (BTYPE(t) >= CHAR && BTYPE(t) <= ULONGLONG)
911		t &= ~1;
912	return t;
913}
914
915/*
916 * Attribute functions.
917 */
918struct attr *
919attr_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 */
936struct attr *
937attr_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 */
953struct attr *
954attr_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 */
966struct attr *
967attr_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 */
976struct attr *
977attr_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
985void *
986xmalloc(int size)
987{
988	void *rv;
989
990	if ((rv = malloc(size)) == NULL)
991		cerror("out of memory!");
992	return rv;
993}
994
995void *
996xstrdup(char *s)
997{
998	void *rv;
999
1000	if ((rv = strdup(s)) == NULL)
1001		cerror("out of memory!");
1002	return rv;
1003}
1004
1005void *
1006xcalloc(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