]> git.draconx.ca Git - cdecl99.git/blobdiff - src/parse-decl.c
libcdecl: Combine identifier and struct allocation.
[cdecl99.git] / src / parse-decl.c
index a6204a18a00c32b524d9bc5dc89cff67cc5b7905..8516a3acab732e26388cb6e40c1ff8fadab4dc69 100644 (file)
 #include "scan.h"
 #include "errmsg.h"
 
+/*
+ * Allocate a "parse item", which is a union of several parse tree
+ * structure types, together with a string buffer.  The s_sz argument
+ * specifies the size of the string (including its terminator), which
+ * may be zero.
+ *
+ * The union's declarator member is pre-initialized to a valid "identifier"
+ * declarator, which shares several interesting offsets with the "declspec"
+ * structure for an "identifier" type specifier.
+ */
+struct parse_item *cdecl__alloc_item(size_t s_sz)
+{
+       struct parse_item *ret;
+
+       ret = malloc(offsetof(struct parse_item, s) + s_sz);
+       if (!ret) {
+               cdecl__errmsg(CDECL__ENOMEM);
+               return NULL;
+       }
+
+       ret->u.declarator.child   = NULL;
+       ret->u.declarator.type    = CDECL_DECL_IDENT;
+       ret->u.declarator.u.ident = ret->s;
+
+       return ret;
+}
+
 /*
  * We can represent type specifiers as a bitmap, which gives us a finite
  * list of acceptable bitmap values according to the C standard.  However,
@@ -173,22 +200,30 @@ static bool valid_declspecs(struct cdecl *decl, bool top)
 
 static struct cdecl_declarator *reduce_function(struct cdecl *param)
 {
-       struct cdecl_declspec   *spec = param->specifiers;
-       struct cdecl_declarator *decl = param->declarators;
-       struct cdecl_declarator *last;
+       struct cdecl_declarator *d, **p = &param->declarators;
+       struct parse_item *spec = (void *)param->specifiers;
 
-       for (last = decl; last && last->type != CDECL_DECL_NULL;)
-               last = last->child;
+       while ((d = *p)->child)
+               p = &d->child;
 
-       if (!last)
+       if (d->type != CDECL_DECL_NULL)
                return NULL;
 
-       last->type = CDECL_DECL_IDENT;
-       last->u.ident = spec->ident;
-       free(param);
-       free(spec);
+       /*
+        * The child and u.ident members of cdecl_declarator are expected
+        * to be located at identical offsets as, respectively, the next
+        * and ident members within cdecl_declspec, so the expectation is
+        * that the compiler can elide both assignments.
+        */
+       spec->u.declarator.child = (void *)spec->u.declspec.next;
+       spec->u.declarator.u.ident = spec->u.declspec.ident;
+       spec->u.declarator.type = CDECL_DECL_IDENT;
+       *p = &spec->u.declarator;
 
-       return decl;
+       free(d);
+       d = param->declarators;
+       free(param);
+       return d;
 }
 
 static bool function_is_reducible(struct cdecl_declarator *d)