summaryrefslogtreecommitdiff
path: root/usr.bin
diff options
context:
space:
mode:
authorAnders Magnusson <ragge@cvs.openbsd.org>2007-12-09 18:47:08 +0000
committerAnders Magnusson <ragge@cvs.openbsd.org>2007-12-09 18:47:08 +0000
commit141ed79e7b891bd8643f6883644a07efa7b87ff4 (patch)
treea36c46be164c032885ffe23451cb0ec8a4a0642f /usr.bin
parentee92e58dd8ce869be29af6a3c970f6e5f9916bde (diff)
Updates from master repo:
- Rewrite typenode() so that const/volatile can be handled better. - Give target code the opportunity to handle string symbols.
Diffstat (limited to 'usr.bin')
-rw-r--r--usr.bin/pcc/ccom/pftn.c267
1 files changed, 123 insertions, 144 deletions
diff --git a/usr.bin/pcc/ccom/pftn.c b/usr.bin/pcc/ccom/pftn.c
index a602e7322d9..0e68d40b469 100644
--- a/usr.bin/pcc/ccom/pftn.c
+++ b/usr.bin/pcc/ccom/pftn.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pftn.c,v 1.8 2007/11/18 17:39:55 ragge Exp $ */
+/* $OpenBSD: pftn.c,v 1.9 2007/12/09 18:47:07 ragge Exp $ */
/*
* Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
* All rights reserved.
@@ -748,6 +748,7 @@ enumhd(char *name)
NODE *
enumdcl(struct symtab *sp)
{
+ NODE *p;
TWORD t;
#ifdef ENUMSIZE
@@ -764,7 +765,9 @@ enumdcl(struct symtab *sp)
sp->stype = t;
sp->ssue = MKSUE(t);
}
- return mkty(t, 0, MKSUE(t));
+ p = mkty(t, 0, MKSUE(t));
+ p->n_sp = sp;
+ return p;
}
/*
@@ -774,12 +777,15 @@ NODE *
enumref(char *name)
{
struct symtab *sp;
+ NODE *p;
sp = lookup(name, STAGNAME);
if (sp->sclass != ENAME)
uerror("enum %s undeclared", name);
- return mkty(sp->stype, 0, sp->ssue);
+ p = mkty(sp->stype, 0, sp->ssue);
+ p->n_sp = sp;
+ return p;
}
/*
@@ -1169,7 +1175,7 @@ wstrend(char *str)
}
p->n_df->ddim = (i+1) * ((MKSUE(WCHAR_TYPE))->suesize/SZCHAR);
p->n_sp = sp;
- return(p);
+ return(clocal(p));
}
/*
@@ -1218,7 +1224,7 @@ strend(char *str)
}
p->n_df->ddim = i+1;
p->n_sp = s;
- return(p);
+ return(clocal(p));
}
/*
@@ -1598,162 +1604,135 @@ lcommprint(void)
}
/*
- * Merges a type tree into one type. Returns one type node with merged types
- * and class stored in the su field. Frees all other nodes.
- * XXX - classes in typedefs?
+ * Merge given types to a single node.
+ * Any type can end up here.
+ * p is the old node, q is the old (if any).
+ * CLASS is AUTO, EXTERN, REGISTER, STATIC or TYPEDEF.
+ * QUALIFIER is VOL or CON
+ * TYPE is CHAR, SHORT, INT, LONG, SIGNED, UNSIGNED, VOID, BOOL, FLOAT,
+ * DOUBLE, STRTY, UNIONTY.
*/
NODE *
typenode(NODE *p)
{
- NODE *l, *sp = NULL;
- int class = 0, adj, noun, sign;
- TWORD qual = 0;
-
- adj = INT; /* INT, LONG or SHORT */
- noun = UNDEF; /* INT, CHAR or FLOAT */
- sign = 0; /* 0, SIGNED or UNSIGNED */
-
- /* Remove initial QUALIFIERs */
- if (p && p->n_op == QUALIFIER) {
- qual = p->n_type;
- l = p->n_left;
- nfree(p);
- p = l;
- }
+ NODE *q, *saved;
+ TWORD type;
+ int class, qual;
+ int sig, uns;
- /* Handle initial classes special */
- if (p && p->n_op == CLASS) {
- class = p->n_type;
- l = p->n_left;
- nfree(p);
- p = l;
- }
+ type = class = qual = sig = uns = 0;
+ saved = NIL;
- /* Remove more QUALIFIERs */
- if (p && p->n_op == QUALIFIER) {
- qual |= p->n_type;
- l = p->n_left;
- nfree(p);
- p = l;
- }
-
-ag: if (p && p->n_op == TYPE) {
- if (p->n_left == NIL) {
-#ifdef CHAR_UNSIGNED
- if (p->n_type == CHAR)
- p->n_type = UCHAR;
-#endif
- if (p->n_type == SIGNED)
- p->n_type = INT;
-uni: p->n_lval = class;
- p->n_qual = qual >> TSHIFT;
- return p;
- } else if (p->n_left->n_op == QUALIFIER) {
- qual |= p->n_left->n_type;
- l = p->n_left;
- p->n_left = l->n_left;
- nfree(l);
- goto ag;
- } else if (ISSTR(p->n_type)) {
- /* Save node; needed for return */
- sp = p;
- p = p->n_left;
- }
- }
+ if (strunem != 0)
+ class = strunem;
- while (p != NIL) {
- if (p->n_op == QUALIFIER) {
- qual |= p->n_type;
- goto next;
- }
- if (p->n_op == CLASS) {
- if (class != 0)
- uerror("too many storage classes");
+ for (q = p; p; p = p->n_left) {
+ switch (p->n_op) {
+ case CLASS:
+ if (class)
+ goto bad; /* max 1 class */
class = p->n_type;
- goto next;
- }
- if (p->n_op != TYPE)
- cerror("typenode got notype %d", p->n_op);
- switch (p->n_type) {
- case UCHAR:
- case USHORT: /* may come from typedef */
- if (sign != 0 || adj != INT)
- goto bad;
- noun = p->n_type;
break;
- case SIGNED:
- case UNSIGNED:
- if (sign != 0)
- goto bad;
- sign = p->n_type;
+
+ case QUALIFIER:
+ qual |= p->n_type >> TSHIFT;
break;
- case LONG:
- if (adj == LONG) {
- adj = LONGLONG;
+
+ case TYPE:
+ if (p->n_sp != NULL || ISSOU(p->n_type)) {
+ /* typedef, enum or struct/union */
+ if (saved || type)
+ goto bad;
+ saved = p;
break;
- }
- /* FALLTHROUGH */
- case SHORT:
- if (adj != INT)
+ } else if ((p->n_type == SIGNED && uns) ||
+ (p->n_type == UNSIGNED && sig))
goto bad;
- adj = p->n_type;
- break;
- case INT:
- case CHAR:
- case FLOAT:
- case DOUBLE:
- if (noun != UNDEF)
- goto bad;
- noun = p->n_type;
- break;
- case VOID:
- if (noun != UNDEF || adj != INT)
- goto bad;
- adj = noun = VOID;
- break;
- case STRTY:
- case UNIONTY:
- break;
- default:
- goto bad;
+
+ switch (p->n_type) {
+ case BOOL:
+ case CHAR:
+ case FLOAT:
+ case VOID:
+ if (type)
+ goto bad;
+ type = p->n_type;
+ break;
+ case DOUBLE:
+ if (type == 0)
+ type = DOUBLE;
+ else if (type == LONG)
+ type = LDOUBLE;
+ else
+ goto bad;
+ break;
+ case SHORT:
+ if (type == 0 || type == INT)
+ type = SHORT;
+ else
+ goto bad;
+ break;
+ case INT:
+ if (type == SHORT || type == LONG ||
+ type == LONGLONG)
+ break;
+ else if (type == 0)
+ type = INT;
+ else
+ goto bad;
+ break;
+ case LONG:
+ if (type == 0)
+ type = LONG;
+ else if (type == INT)
+ break;
+ else if (type == LONG)
+ type = LONGLONG;
+ else if (type == DOUBLE)
+ type = LDOUBLE;
+ else
+ goto bad;
+ break;
+ case SIGNED:
+ if (sig || uns)
+ goto bad;
+ sig = 1;
+ break;
+ case UNSIGNED:
+ if (sig || uns)
+ goto bad;
+ uns = 1;
+ break;
+ default:
+ cerror("typenode");
+ }
}
- next:
- l = p->n_left;
- nfree(p);
- p = l;
}
-
- if (sp) {
- p = sp;
- goto uni;
+ if (saved && type)
+ goto bad;
+ if (sig || uns) {
+ if (type == 0)
+ type = sig ? INT : UNSIGNED;
+ if (type > ULONGLONG)
+ goto bad;
+ if (uns)
+ type = ENUNSIGN(type);
}
-
#ifdef CHAR_UNSIGNED
- if (noun == CHAR && sign == 0)
- sign = UNSIGNED;
+ if (type == CHAR && sig == 0)
+ type = UCHAR;
#endif
- if (noun == UNDEF) {
- noun = INT;
- } else if (noun == FLOAT) {
- if (sign != 0 || adj == SHORT)
- goto bad;
- noun = (adj == LONG ? DOUBLE : FLOAT);
- } else if (noun == DOUBLE) {
- if (sign != 0 || adj == SHORT)
- goto bad;
- noun = (adj == LONG ? LDOUBLE : DOUBLE);
- } else if (noun == CHAR && adj != INT)
- goto bad;
- if (adj != INT && (noun != DOUBLE && noun != LDOUBLE))
- noun = adj;
- if (sign == UNSIGNED)
- noun += (UNSIGNED-INT);
+ /* free the chain */
+ while (q) {
+ p = q->n_left;
+ if (q != saved)
+ nfree(q);
+ q = p;
+ }
- p = block(TYPE, NIL, NIL, noun, 0, 0);
- p->n_qual = qual >> TSHIFT;
- if (strunem != 0)
- class = strunem;
+ p = (saved ? saved : block(TYPE, NIL, NIL, type, 0, 0));
+ p->n_qual = qual;
p->n_lval = class;
return p;
@@ -1800,7 +1779,7 @@ tymerge(NODE *typ, NODE *idp)
#endif
idp->n_type = typ->n_type;
- idp->n_qual = (typ->n_qual << TSHIFT) | idp->n_qual; /* XXX ??? */
+ idp->n_qual = typ->n_qual;
tylkp = &tylnk;
tylkp->next = NULL;
@@ -1825,7 +1804,7 @@ tymerge(NODE *typ, NODE *idp)
/* now idp is a single node: fix up type */
idp->n_type = ctype(idp->n_type);
- idp->n_qual = DECQAL(idp->n_qual);
+// idp->n_qual = DECQAL(idp->n_qual);
/* in case ctype has rewritten things */
if ((t = BTYPE(idp->n_type)) != STRTY && t != UNIONTY)