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