X-Git-Url: https://git.draconx.ca/gitweb/cdecl99.git/blobdiff_plain/88c05279e142ff97db82c30f4f3936b1ea5eb22a..a5676c4a2d61a6732e0b144e45339d0e666c2f20:/test/declgen.c diff --git a/test/declgen.c b/test/declgen.c index c59e86c..0e76348 100644 --- a/test/declgen.c +++ b/test/declgen.c @@ -29,6 +29,48 @@ #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 @@ -61,14 +103,10 @@ char *gen_identifier(struct test_rng *rng) */ 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: @@ -94,16 +132,11 @@ struct cdecl_declspec *gen_qualifiers(struct test_rng *rng, bool restrictqual) */ 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; @@ -121,17 +154,10 @@ struct cdecl_declspec *gen_storspecs(struct test_rng *rng, bool registeronly) 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; @@ -157,8 +183,11 @@ retry: 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: @@ -277,26 +306,26 @@ static uintmax_t gen_uintmax(struct test_rng *rng) */ 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. */ @@ -309,11 +338,8 @@ static void gen_function(struct test_rng *rng, struct cdecl_declarator *d) 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) @@ -329,18 +355,9 @@ static void gen_function(struct test_rng *rng, struct cdecl_declarator *d) 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; } @@ -357,31 +374,19 @@ struct cdecl_declarator *gen_declarators(struct test_rng *rng) 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: