1 /* $Id: common.c,v 1.93 2011/01/22 22:08:23 ragge Exp $ */
3 * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
30 * Redistribution and use in source and binary forms, with or without
31 * modification, are permitted provided that the following conditions
34 * Redistributions of source code and documentation must retain the above
35 * copyright notice, this list of conditions and the following disclaimer.
36 * Redistributions in binary form must reproduce the above copyright
37 * notice, this list of conditionsand the following disclaimer in the
38 * documentation and/or other materials provided with the distribution.
39 * All advertising materials mentioning features or use of this software
40 * must display the following acknowledgement:
41 * This product includes software developed or owned by Caldera
43 * Neither the name of Caldera International, Inc. nor the names of other
44 * contributors may be used to endorse or promote products derived from
45 * this software without specific prior written permission.
47 * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
48 * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
49 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
50 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
51 * DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE
52 * FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55 * HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT,
56 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
57 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
58 * POSSIBILITY OF SUCH DAMAGE.
72 int nerrors
= 0; /* number of errors */
79 #define WHERE(ch) fprintf(stderr, "%s, line %d: ", ftitle, lineno);
86 cerror("too many errors");
90 * nonfatal error message
91 * the routine where is different for pass 1 and pass 2;
92 * it tells where the error took place
101 vfprintf(stderr
, s
, ap
);
102 fprintf(stderr
, "\n");
108 * compiler error: die
118 /* give the compiler the benefit of the doubt */
119 if (nerrors
&& nerrors
<= 30) {
121 "cannot recover from earlier errors: goodbye!\n");
123 fprintf(stderr
, "compiler error: ");
124 vfprintf(stderr
, s
, ap
);
125 fprintf(stderr
, "\n");
141 fprintf(stderr
, "warning: ");
142 vfprintf(stderr
, s
, ap
);
143 fprintf(stderr
, "\n");
151 bittype warnary
[(NUMW
/NUMBITS
)+1], werrary
[(NUMW
/NUMBITS
)+1];
153 static char *warntxt
[] = {
154 "conversion to '%s' from '%s' may alter its value",
155 "function declaration isn't a prototype", /* Wstrict_prototypes */
156 "no previous prototype for `%s'", /* Wmissing_prototypes */
157 "return type defaults to `int'", /* Wimplicit_int */
158 /* Wimplicit_function_declaration */
159 "implicit declaration of function '%s'",
160 "declaration of '%s' shadows a %s declaration", /* Wshadow */
161 "illegal pointer combination", /* Wpointer_sign */
162 "comparison between signed and unsigned", /* Wsign_compare */
163 "ignoring #pragma %s %s", /* Wunknown_pragmas */
164 "statement not reached", /* Wunreachable_code */
168 "truncate", "strict-prototypes", "missing-prototypes",
169 "implicit-int", "implicit-function-declaration", "shadow",
170 "pointer-sign", "sign-compare", "unknown-pragmas",
175 * "emulate" the gcc warning flags.
182 if (strncmp("no-", str
, 3) == 0) {
187 if (strcmp(str
, "error") == 0) {
189 for (i
= 0; i
< NUMW
; i
++)
193 for (i
= 0; i
< NUMW
; i
++) {
194 if (strcmp(flagstr
[i
], str
) != 0)
199 BITCLEAR(warnary
, i
);
202 fprintf(stderr
, "unrecognised warning option '%s'\n", str
);
206 * Deal with gcc warnings.
209 warner(int type
, ...)
214 if (TESTBIT(warnary
, type
) == 0)
215 return; /* no warning */
216 if (TESTBIT(werrary
, type
)) {
223 fprintf(stderr
, "%s:%d: %s: ", ftitle
, lineno
, w
);
224 vfprintf(stderr
, warntxt
[type
], ap
);
225 fprintf(stderr
, "\n");
231 static NODE
*freelink
;
232 static int usednodes
;
242 if (freelink
!= NULL
) {
246 cerror("node not FREE: %p", p
);
248 printf("alloc node %p from freelist\n", p
);
252 p
= permalloc(sizeof(NODE
));
255 printf("alloc node %p from memory\n", p
);
261 * make a fresh copy of p
271 switch (optype(q
->n_op
)) {
273 q
->n_right
= tcopy(p
->n_right
);
275 q
->n_left
= tcopy(p
->n_left
);
283 * ensure that all nodes have been freed
288 extern int inlnodecnt
;
293 if ((usednodes
- inlnodecnt
) != 0)
294 cerror("usednodes == %d, inlnodecnt %d", usednodes
, inlnodecnt
);
305 walkf(p
, (void (*)(NODE
*, void *))nfree
, 0);
309 * Free a node, and return its left descendant.
310 * It is up to the caller to know whether the return value is usable.
316 #ifdef PCC_DEBUG_NODES
321 cerror("freeing blank node!");
325 cerror("freeing FREE node", p
);
326 #ifdef PCC_DEBUG_NODES
330 cerror("freeing free node %p", p
);
336 printf("freeing node %p\n", p
);
346 #define OPTYPE(x) optype(x)
348 #define OPTYPE(x) coptype(x)
352 #define coptype(o) (dope[o]&TYFLG)
355 #define coptype(o) (cdope(o)&TYFLG)
359 fwalk(NODE
*t
, void (*f
)(NODE
*, int, int *, int *), int down
)
367 (*f
)(t
, down
, &down1
, &down2
);
369 switch (OPTYPE( t
->n_op
)) {
372 fwalk( t
->n_left
, f
, down1
);
386 walkf(NODE
*t
, void (*f
)(NODE
*, void *), void *arg
)
391 opty
= OPTYPE(t
->n_op
);
394 walkf( t
->n_left
, f
, arg
);
396 walkf( t
->n_right
, f
, arg
);
408 { NAME
, "NAME", LTYPE
, },
409 { REG
, "REG", LTYPE
, },
410 { OREG
, "OREG", LTYPE
, },
411 { TEMP
, "TEMP", LTYPE
, },
412 { ICON
, "ICON", LTYPE
, },
413 { FCON
, "FCON", LTYPE
, },
414 { CCODES
, "CCODES", LTYPE
, },
415 { UMINUS
, "U-", UTYPE
, },
416 { UMUL
, "U*", UTYPE
, },
417 { FUNARG
, "FUNARG", UTYPE
, },
418 { UCALL
, "UCALL", UTYPE
|CALLFLG
, },
419 { UFORTCALL
, "UFCALL", UTYPE
|CALLFLG
, },
420 { COMPL
, "~", UTYPE
, },
421 { FORCE
, "FORCE", UTYPE
, },
422 { XARG
, "XARG", UTYPE
, },
423 { XASM
, "XASM", BITYPE
, },
424 { SCONV
, "SCONV", UTYPE
, },
425 { PCONV
, "PCONV", UTYPE
, },
426 { PLUS
, "+", BITYPE
|FLOFLG
|SIMPFLG
|COMMFLG
, },
427 { MINUS
, "-", BITYPE
|FLOFLG
|SIMPFLG
, },
428 { MUL
, "*", BITYPE
|FLOFLG
|MULFLG
, },
429 { AND
, "&", BITYPE
|SIMPFLG
|COMMFLG
, },
430 { CM
, ",", BITYPE
, },
431 { ASSIGN
, "=", BITYPE
|ASGFLG
, },
432 { DIV
, "/", BITYPE
|FLOFLG
|MULFLG
|DIVFLG
, },
433 { MOD
, "%", BITYPE
|DIVFLG
, },
434 { LS
, "<<", BITYPE
|SHFFLG
, },
435 { RS
, ">>", BITYPE
|SHFFLG
, },
436 { OR
, "|", BITYPE
|COMMFLG
|SIMPFLG
, },
437 { ER
, "^", BITYPE
|COMMFLG
|SIMPFLG
, },
438 { STREF
, "->", BITYPE
, },
439 { CALL
, "CALL", BITYPE
|CALLFLG
, },
440 { FORTCALL
, "FCALL", BITYPE
|CALLFLG
, },
441 { EQ
, "==", BITYPE
|LOGFLG
, },
442 { NE
, "!=", BITYPE
|LOGFLG
, },
443 { LE
, "<=", BITYPE
|LOGFLG
, },
444 { LT
, "<", BITYPE
|LOGFLG
, },
445 { GE
, ">=", BITYPE
|LOGFLG
, },
446 { GT
, ">", BITYPE
|LOGFLG
, },
447 { UGT
, "UGT", BITYPE
|LOGFLG
, },
448 { UGE
, "UGE", BITYPE
|LOGFLG
, },
449 { ULT
, "ULT", BITYPE
|LOGFLG
, },
450 { ULE
, "ULE", BITYPE
|LOGFLG
, },
451 { CBRANCH
, "CBRANCH", BITYPE
, },
452 { FLD
, "FLD", UTYPE
, },
453 { PMCONV
, "PMCONV", BITYPE
, },
454 { PVCONV
, "PVCONV", BITYPE
, },
455 { RETURN
, "RETURN", BITYPE
|ASGFLG
|ASGOPFLG
, },
456 { GOTO
, "GOTO", UTYPE
, },
457 { STASG
, "STASG", BITYPE
|ASGFLG
, },
458 { STARG
, "STARG", UTYPE
, },
459 { STCALL
, "STCALL", BITYPE
|CALLFLG
, },
460 { USTCALL
, "USTCALL", UTYPE
|CALLFLG
, },
461 { ADDROF
, "U&", UTYPE
, },
471 for( q
= indope
; q
->dopeop
>= 0; ++q
){
472 dope
[q
->dopeop
] = q
->dopeval
;
473 opst
[q
->dopeop
] = q
->opst
;
478 * output a nice description of the type of t
481 tprint(FILE *fp
, TWORD t
, TWORD q
)
483 static char * tnames
[] = {
504 "signed", /* pass1 */
509 "fcomplex", /* pass1 */
510 "dcomplex", /* pass1 */
511 "lcomplex", /* pass1 */
512 "enumty", /* pass1 */
516 for(;; t
= DECREF(t
), q
= DECREF(q
)) {
529 fprintf(fp
, "%s%s%s", ISCON(q
<< TSHIFT
) ? "const " : "",
530 ISVOL(q
<< TSHIFT
) ? "volatile " : "", tnames
[t
]);
537 * Memory allocation routines.
538 * Memory are allocated from the system in MEMCHUNKSZ blocks.
539 * permalloc() returns a bunch of memory that is never freed.
540 * Memory allocated through tmpalloc() will be released the
541 * next time a function is ended (via tmpfree()).
544 #define MEMCHUNKSZ 8192 /* 8k per allocation */
553 #define ALIGNMENT ((long)&((struct balloc *)0)->a2)
554 #define ROUNDUP(x) (((x) + ((ALIGNMENT)-1)) & ~((ALIGNMENT)-1))
556 static char *allocpole
;
557 static int allocleft
;
558 int permallocsize
, tmpallocsize
, lostmem
;
565 if (size
> MEMCHUNKSZ
) {
566 if ((rv
= malloc(size
)) == NULL
)
567 cerror("permalloc: missing %d bytes", size
);
571 cerror("permalloc2");
572 if (allocleft
< size
) {
573 /* looses unused bytes */
574 lostmem
+= allocleft
;
575 if ((allocpole
= malloc(MEMCHUNKSZ
)) == NULL
)
576 cerror("permalloc: out of memory");
577 allocleft
= MEMCHUNKSZ
;
579 size
= ROUNDUP(size
);
580 rv
= &allocpole
[MEMCHUNKSZ
-allocleft
];
582 permallocsize
+= size
;
597 * Duplicate a string onto the temporary heap.
604 len
= strlen(str
) + 1;
605 return memcpy(tmpalloc(len
), str
, len
);
609 * Allocation routines for temporary memory.
612 #define ALLDEBUG(x) printf x
617 #define NELEM ((MEMCHUNKSZ-ROUNDUP(sizeof(struct xalloc *)))/ALIGNMENT)
618 #define ELEMSZ (ALIGNMENT)
619 #define MAXSZ (NELEM*ELEMSZ)
623 struct balloc b
; /* for initial alignment */
627 int uselem
= NELEM
; /* next unused element */
636 nelem
= ROUNDUP(size
)/ELEMSZ
;
637 ALLDEBUG(("tmpalloc(%ld,%ld) %d (%zd) ", ELEMSZ
, NELEM
, size
, nelem
));
638 if (nelem
> NELEM
/2) {
639 xp
= malloc(size
+ ROUNDUP(sizeof(struct xalloc
*)));
641 cerror("out of memory");
642 ALLDEBUG(("XMEM! (%ld,%p) ",
643 size
+ ROUNDUP(sizeof(struct xalloc
*)), xp
));
646 ALLDEBUG(("rv %p\n", &xp
->u
.elm
[0]));
647 return &xp
->u
.elm
[0];
649 if (nelem
+ uselem
>= NELEM
) {
650 ALLDEBUG(("MOREMEM! "));
652 if ((xp
= malloc(sizeof(struct xalloc
))) == NULL
)
653 cerror("out of memory");
659 rv
= &xp
->u
.elm
[uselem
* ELEMSZ
];
660 ALLDEBUG(("elemno %d ", uselem
));
662 ALLDEBUG(("new %d rv %p\n", uselem
, rv
));
673 tmpole
= tmpole
->next
;
674 ALLDEBUG(("XMEM! free %p\n", x1
));
677 while (tapole
&& tapole
->next
) {
679 tapole
= tapole
->next
;
680 ALLDEBUG(("MOREMEM! free %p\n", x1
));
688 * Set a mark for later removal from the temp heap.
691 markset(struct mark
*m
)
699 * Remove everything on tmp heap from a mark.
702 markfree(struct mark
*m
)
706 while (tmpole
!= m
->tmsav
) {
708 tmpole
= tmpole
->next
;
711 while (tapole
!= m
->tasav
) {
713 tapole
= tapole
->next
;
720 * Allocate space on the permanent stack for a string of length len+1
722 * Return the new address.
725 newstring(char *s
, int len
)
730 if (allocleft
< len
) {
731 u
= c
= permalloc(len
);
733 u
= c
= &allocpole
[MEMCHUNKSZ
-allocleft
];
734 allocleft
-= ROUNDUP(len
+1);
742 * Do a preorder walk of the CM list p and apply function f on each element.
745 flist(NODE
*p
, void (*f
)(NODE
*, void *), void *arg
)
748 (*f
)(p
->n_right
, arg
);
749 flist(p
->n_left
, f
, arg
);
755 * The same as flist but postorder.
758 listf(NODE
*p
, void (*f
)(NODE
*))
768 * Get list argument number n from list, or NIL if out of list.
771 listarg(NODE
*p
, int n
, int *cnt
)
776 r
= listarg(p
->n_left
, n
, cnt
);
781 r
= n
== 0 ? p
: NIL
;