#include "cdecl.h"
#include "test.h"
+/*
+ * Return a newly-allocated null declarator. The child member is set by the
+ * argument; other members are initialized to zero.
+ */
+struct cdecl_declarator *new_declarator(struct cdecl_declarator *child)
+{
+ struct cdecl_declarator *d, init = { child, CDECL_DECL_NULL };
+
+ d = malloc_nofail(sizeof *d);
+ *d = init;
+
+ return d;
+}
+
+/*
+ * Return a newly-allocated void specifier. The next member is set by the
+ * argument; other members are initialized to zero.
+ */
+struct cdecl_declspec *new_specifier(struct cdecl_declspec *next)
+{
+ struct cdecl_declspec *d, init = { next, CDECL_TYPE_VOID };
+
+ d = malloc_nofail(sizeof *d);
+ *d = init;
+
+ return d;
+}
+
+/*
+ * Return a newly-allocated declaration. The next member is set by the
+ * argument; other members are initialized to zero.
+ */
+struct cdecl *new_cdecl(struct cdecl *next)
+{
+ struct cdecl *d, init = { next };
+
+ d = malloc_nofail(sizeof *d);
+ *d = init;
+
+ return d;
+}
+
/*
* Generate a random identifier. We arbitrarily pick 10 as the largest
* possible. Avoid generating keywords, including the English ones, by
*/
struct cdecl_declspec *gen_qualifiers(struct test_rng *rng, bool restrictqual)
{
- struct cdecl_declspec *s = NULL, *p;
+ struct cdecl_declspec *s = NULL;
while (test_rng_uniform(rng) < 0.5) {
- p = s;
- s = malloc_nofail(sizeof *s);
- *s = (struct cdecl_declspec) {
- .next = p,
- };
+ s = new_specifier(s);
switch (test_rng_uniform_int(rng, 2+restrictqual)) {
case 0:
*/
struct cdecl_declspec *gen_funcspecs(struct test_rng *rng)
{
- struct cdecl_declspec *s = NULL, *p;
+ struct cdecl_declspec *s = NULL;
while (test_rng_uniform(rng) < 0.5) {
- p = s;
- s = malloc_nofail(sizeof *s);
-
- *s = (struct cdecl_declspec) {
- .type = CDECL_FUNC_INLINE,
- .next = p,
- };
+ s = new_specifier(s);
+ s->type = CDECL_FUNC_INLINE;
}
return s;
if (test_rng_uniform(rng) < 0.5)
return NULL;
- s = malloc_nofail(sizeof *s);
- *s = (struct cdecl_declspec) {
- .type = CDECL_STOR_REGISTER,
- };
-
- if (registeronly)
- return s;
-
- switch (test_rng_uniform_int(rng, 5)) {
- case 0: s->type = CDECL_STOR_TYPEDEF; break;
- case 1: s->type = CDECL_STOR_REGISTER; break;
+ s = new_specifier(NULL);
+ switch (test_rng_uniform_int(rng, registeronly ? 1 : 5)) {
+ case 0: s->type = CDECL_STOR_REGISTER; break;
+ case 1: s->type = CDECL_STOR_TYPEDEF; break;
case 2: s->type = CDECL_STOR_STATIC; break;
case 3: s->type = CDECL_STOR_AUTO; break;
case 4: s->type = CDECL_STOR_EXTERN; break;
switch (specs->type) {
/* void is not always valid, so we might need to pick again. */
case CDECL_TYPE_VOID:
- if (!voidtype)
+ if (!voidtype) {
+ assert(!specs->next);
+ free(specs);
goto retry;
+ }
break;
/* A few kinds of type specifiers need identifiers to go with them. */
case CDECL_TYPE_STRUCT:
*/
static void gen_array(struct test_rng *rng, struct cdecl_declarator *d)
{
- d->type = CDECL_DECL_ARRAY;
- d->u.array = (struct cdecl_array){0};
+ struct cdecl_array tmp = {0};
switch (test_rng_uniform_int(rng, 4)) {
case 0:
- d->u.array.vla = malloc_nofail(1);
- d->u.array.vla[0] = 0;
+ tmp.vla = malloc_nofail(1);
+ tmp.vla[0] = 0;
break;
case 1:
- d->u.array.vla = gen_identifier(rng);
+ tmp.vla = gen_identifier(rng);
break;
case 2:
- d->u.array.length = 0;
- break;
+ tmp.length = gen_uintmax(rng);
case 3:
- d->u.array.length = gen_uintmax(rng);
break;
default:
assert(0);
}
+
+ d->type = CDECL_DECL_ARRAY;
+ d->u.array = tmp;
}
/* Generate a function declarator. */
unsigned flags = GEN_ONLY_REGISTER | GEN_NO_FUNCTION;
struct cdecl *param;
- param = malloc_nofail(sizeof *param);
- *param = (struct cdecl) {
- .next = d->u.function.parameters,
- .declarators = gen_declarators(rng),
- };
+ param = new_cdecl(d->u.function.parameters);
+ param->declarators = gen_declarators(rng);
if (param->declarators->type != CDECL_DECL_POINTER
&& param->declarators->type != CDECL_DECL_FUNCTION)
struct cdecl *param;
/* We will never generate (void) above; do it here. */
- param = malloc_nofail(sizeof *param);
- *param = (struct cdecl) { 0 };
-
- param->declarators = malloc_nofail(sizeof *param->declarators);
- *param->declarators = (struct cdecl_declarator) {
- .type = CDECL_DECL_NULL,
- };
-
- param->specifiers = malloc_nofail(sizeof *param->specifiers);
- *param->specifiers = (struct cdecl_declspec) {
- .type = CDECL_TYPE_VOID,
- };
+ param = new_cdecl(NULL);
+ param->declarators = new_declarator(NULL);
+ param->specifiers = new_specifier(NULL);
d->u.function.parameters = param;
}
struct cdecl_declarator *d, *p;
unsigned limit = 3;
- d = malloc_nofail(sizeof *d);
+ d = new_declarator(NULL);
if (test_rng_uniform(rng) < 0.5) {
- *d = (struct cdecl_declarator) {
- .type = CDECL_DECL_NULL,
- };
- } else {
- *d = (struct cdecl_declarator) {
- .type = CDECL_DECL_IDENT,
- .u.ident = gen_identifier(rng),
- };
+ d->type = CDECL_DECL_IDENT;
+ d->u.ident = gen_identifier(rng);
}
while (test_rng_uniform(rng) < 0.5) {
- p = d;
- d = malloc_nofail(sizeof *d);
- *d = (struct cdecl_declarator) {
- .child = p,
- };
+ d = new_declarator((p = d));
switch (test_rng_uniform_int(rng, limit)) {
case 0:
d->type = CDECL_DECL_POINTER;
- d->u.pointer = (struct cdecl_pointer) {
- .qualifiers = gen_qualifiers(rng, true),
- };
+ d->u.pointer.qualifiers = gen_qualifiers(rng, true);
limit = 3;
break;
case 1: