#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,
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 = ¶m->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)