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