X-Git-Url: https://git.draconx.ca/gitweb/cdecl99.git/blobdiff_plain/9628bd06223d7e1730574ca0c93d76b1d39856b4..425ed781f7a27bc415e13a1901899e2c7b11e4c8:/test/declgen.c diff --git a/test/declgen.c b/test/declgen.c index ac9d23e..4fb39cb 100644 --- a/test/declgen.c +++ b/test/declgen.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -178,6 +179,10 @@ retry: case CDECL_TYPE_IDENT: assert(!specs->next); specs->ident = gen_identifier(rng); + break; + default: + /* Nothing to be done. */ + ; } return specs; @@ -264,6 +269,20 @@ gen_declspecs(struct gen_rng *rng, unsigned flags) return gen_randomize_specs(rng, s); } +static uintmax_t gen_uintmax(struct gen_rng *rng) +{ + unsigned char tmp; + uintmax_t ret = 0; + + for (size_t i = 0; i < sizeof ret; i++) { + tmp = gsl_rng_uniform_int(rng->rng, UCHAR_MAX+1); + ret <<= CHAR_BIT; + ret |= tmp; + } + + return ret; +} + /* * Generate a random array declarator, selecting one of four possibilities * uniformly at random. @@ -274,19 +293,21 @@ static void gen_array(struct gen_rng *rng, struct cdecl_declarator *d) d->u.array = (struct cdecl_array){0}; switch (gsl_rng_uniform_int(rng->rng, 4)) { - case '0': + case 0: d->u.array.vla = malloc_nofail(1); d->u.array.vla[0] = 0; break; - case '1': + case 1: d->u.array.vla = gen_identifier(rng); break; - case '2': + case 2: d->u.array.length = 0; break; - case '3': - d->u.array.length = gsl_rng_uniform_int(rng->rng, -1); + case 3: + d->u.array.length = gen_uintmax(rng); break; + default: + assert(0); } } @@ -316,6 +337,24 @@ static void gen_function(struct gen_rng *rng, struct cdecl_declarator *d) if (d->u.function.parameters) { d->u.function.variadic = gsl_rng_uniform(rng->rng) < 0.5; + } else if (gsl_rng_uniform(rng->rng) < 0.5) { + 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, + }; + + d->u.function.parameters = param; } } @@ -363,6 +402,12 @@ struct cdecl_declarator *gen_declarators(struct gen_rng *rng) break; case 2: gen_function(rng, d); + if (p && p->type == CDECL_DECL_POINTER) { + struct cdecl_pointer *ptr = &p->u.pointer; + + gen_free_declspecs(ptr->qualifiers); + ptr->qualifiers = gen_qualifiers(rng, false); + } limit = 1; break; default: @@ -390,11 +435,74 @@ struct gen_rng *gen_alloc_rng(const char *seed_str) return NULL; } - rng = malloc(sizeof *rng); - if (rng) { - rng->rng = gsl_rng_alloc(gsl_rng_mt19937); - gsl_rng_set(rng->rng, seed); - } + rng = malloc_nofail(sizeof *rng); + rng->rng = gsl_rng_alloc(gsl_rng_mt19937); + gsl_rng_set(rng->rng, seed); return rng; } + +void gen_free_rng(struct gen_rng *rng) +{ + if (rng) + gsl_rng_free(rng->rng); + free(rng); +} + +static void gen_free_parameters(struct cdecl *x) +{ + struct cdecl *p; + + while (x) { + p = x->next; + + gen_free_declspecs(x->specifiers); + gen_free_declarators(x->declarators); + free(x); + + x = p; + } +} + +void gen_free_declspecs(struct cdecl_declspec *x) +{ + struct cdecl_declspec *p; + + while (x) { + p = x->next; + free(x->ident); + free(x); + x = p; + } +} + +void gen_free_declarators(struct cdecl_declarator *x) +{ + struct cdecl_declarator *p; + + while (x) { + p = x->child; + + switch (x->type) { + case CDECL_DECL_NULL: + break; + case CDECL_DECL_IDENT: + free(x->u.ident); + break; + case CDECL_DECL_POINTER: + gen_free_declspecs(x->u.pointer.qualifiers); + break; + case CDECL_DECL_ARRAY: + free(x->u.array.vla); + break; + case CDECL_DECL_FUNCTION: + gen_free_parameters(x->u.function.parameters); + break; + default: + assert(0); + } + + free(x); + x = p; + } +}