summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLubomir Rintel <lkundrak@v3.sk>2010-05-25 21:15:16 +0200
committerLubomir Rintel <lkundrak@v3.sk>2013-10-29 16:30:52 +0100
commita971aeabb4caf06339d9c53265b034d3cd9349bd (patch)
tree028409a225d3fae4ac56b615d79f0ea1d333cff7
parent34f2fd6c579bf4d59f08820711ff8a3e2bf20429 (diff)
downloaddev86-a971aeabb4caf06339d9c53265b034d3cd9349bd.tar.gz
Add support for K&R-style anonymous structures and unions
-rw-r--r--bcc/declare.c44
-rw-r--r--bcc/express.c13
-rw-r--r--bcc/proto.h8
-rw-r--r--bcc/table.c38
4 files changed, 100 insertions, 3 deletions
diff --git a/bcc/declare.c b/bcc/declare.c
index 0820c4b..a92c545 100644
--- a/bcc/declare.c
+++ b/bcc/declare.c
@@ -2,6 +2,9 @@
/* Copyright (C) 1992 Bruce Evans */
+#ifndef VERY_SMALL_MEMORY
+#include <stdio.h>
+#endif
#include "bcc.h"
#include "align.h"
#include "byteord.h"
@@ -26,6 +29,10 @@ PRIVATE char gvar2name[2 + NAMESIZE]; /* space for structure keys and .. */
PRIVATE struct typestruct *gvartype; /* type of last identifier declared */
PRIVATE bool_t initlistflag; /* remembers whether initializer is a list */
+#ifndef VERY_SMALL_MEMORY
+PRIVATE int anons = 0; /* number of anonymous structures/unions seen */
+#endif
+
FORWARD struct typestruct *chainprefix P((struct typestruct *pretype,
struct typestruct *sufftype));
FORWARD void declaf P((void));
@@ -219,7 +226,12 @@ PRIVATE void declarator()
{
rdeclarator();
if (gvartype->constructor == STRUCTU && gvartype->typesize == 0 &&
+/* We don't do the anonymous union/structure trickery on low mem machines */
+#ifdef VERY_SMALL_MEMORY
gvarsc != TYPEDEFDECL && gvarsc != EXTERNDECL)
+#else
+ gvarsc != TYPEDEFDECL && gvarsc != EXTERNDECL && gvarsc != NULLDECL)
+#endif
error("undefined structure");
}
@@ -328,10 +340,21 @@ struct typelist **ptypelist;
if (gvarsc != NULLDECL)
error("illegal type name");
basetype = gvartype;
+
+#ifndef VERY_SMALL_MEMORY
+ if (sym == SEMICOLON || sym == EOFSYM) {
+ /* Generate a fake structure if none specified... */
+ anonstruct ();
+ /* ....and pretend it was regularly present in source */
+ goto anonstr;
+ }
+#endif
+
while (sym != SEMICOLON && sym != EOFSYM)
{
gvartype = basetype;
declarator();
+anonstr:
fieldwidth = -1;
if (sym == COLON)
{
@@ -1189,3 +1212,24 @@ PUBLIC struct typestruct *typename()
gvartype = ogvartype;
return type;
}
+
+#ifndef VERY_SMALL_MEMORY
+PUBLIC int lastanon()
+{
+ return anons;
+}
+
+PUBLIC void anonname(name, i)
+char *name;
+int i;
+{
+ if (i == 0xfff)
+ fatalerror("Too many anonymous structs/unions");
+ sprintf (name, "__an%03x", i);
+}
+
+PUBLIC void anonstruct()
+{
+ anonname (gvarname, anons++);
+}
+#endif
diff --git a/bcc/express.c b/bcc/express.c
index 9533d91..f57db0a 100644
--- a/bcc/express.c
+++ b/bcc/express.c
@@ -285,9 +285,16 @@ bool_pt seenlp;
nodeptr = node(INDIRECTOP, nodeptr, NULLNODE);
case STRUCELTOP:
nextsym();
- gs2name[0] = nodeptr->nodetype->structkey[0];
- gs2name[1] = nodeptr->nodetype->structkey[1];
- if ((gsymptr = findlorg(gs2name)) == NULL)
+/* On memory constrained systems we save space that would be needed to keep */
+/* track of anonymous structure members by not implementing lookup in them */
+/* at all. */
+#ifdef VERY_SMALL_MEMORY
+ gs2name[0] = nodeptr->nodetype->structkey[0];
+ gs2name[1] = nodeptr->nodetype->structkey[1];
+ if ((gsymptr = findlorg(gs2name)) == NULL)
+#else
+ if ((gsymptr = findstrm(nodeptr->nodetype, gs2name)) == NULL)
+#endif
{
error("undefined structure element");
gsymptr = addglb(gs2name, itype);
diff --git a/bcc/proto.h b/bcc/proto.h
index 3b44a56..baee0c3 100644
--- a/bcc/proto.h
+++ b/bcc/proto.h
@@ -119,6 +119,11 @@ void rbracket P((void));
void rparen P((void));
void semicolon P((void));
struct typestruct *typename P((void));
+#ifndef VERY_SMALL_MEMORY
+int lastanon P((void));
+void anonname P((char *name, int i));
+void anonstruct P((void));
+#endif
/* express.c */
struct nodestruct *assignment_exp P((void));
@@ -355,6 +360,9 @@ void outofmemoryerror P((char *message));
void *qmalloc P((unsigned size));
void swapsym P((struct symstruct *sym1, struct symstruct *sym2));
void syminit P((void));
+#ifndef VERY_SMALL_MEMORY
+struct symstruct *findstrm P((struct typestruct *type, char *name));
+#endif
/* type.c */
struct typestruct *addstruct P((char *structname));
diff --git a/bcc/table.c b/bcc/table.c
index 166c143..e863fb5 100644
--- a/bcc/table.c
+++ b/bcc/table.c
@@ -691,3 +691,41 @@ PUBLIC void syminit()
addkeyword(kwptr->kwname, kwptr->kwcode);
constemplate.type = itype;
}
+
+#ifndef VERY_SMALL_MEMORY
+PUBLIC struct symstruct *findstrm(type, name)
+struct typestruct *type;
+char *name;
+{
+ struct symstruct *symptr;
+ int i;
+ char anon[2 + NAMESIZE];
+ struct typelist *tl;
+
+ /* Look for a struct member named as given */
+ name[0] = type->structkey[0];
+ name[1] = type->structkey[1];
+ if ((symptr = findlorg(name)) != NULL)
+ return symptr;
+
+ /* No match? Fine, let's see if there are any anynymous structures
+ * or unions that we could recurse into */
+ for (i = 0; i < lastanon(); i++)
+ {
+ anon[0] = type->structkey[0];
+ anon[1] = type->structkey[1];
+ anonname(&anon[2], i);
+ if ((symptr = findlorg(anon)) != NULL)
+ {
+ /* Found an anonymous struture */
+ if (!(symptr->type->constructor & STRUCTU))
+ error("Anonymous structure not a structure?!");
+ /* Look for the member */
+ strcpy(&anon[2], &name[2]);
+ if ((symptr = findstrm(symptr->type, anon)) != NULL)
+ return symptr;
+ }
+ }
+ return NULL;
+}
+#endif