#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <limits.h>
#include <errno.h>
#include <assert.h>
#include <stdbool.h>
case CDECL_TYPE_IDENT:
assert(!specs->next);
specs->ident = gen_identifier(rng);
+ break;
+ default:
+ /* Nothing to be done. */
+ ;
}
return specs;
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.
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);
}
}
.declarators = gen_declarators(rng),
};
- if (param->declarators->type == CDECL_DECL_ARRAY
- || param->declarators->type == CDECL_DECL_IDENT)
+ if (param->declarators->type != CDECL_DECL_POINTER
+ && param->declarators->type != CDECL_DECL_FUNCTION)
flags |= GEN_NO_VOID;
param->specifiers = gen_declspecs(rng, flags);
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;
}
}
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:
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;
+ }
+}