/*
* Generate random C declarations for testing.
- * Copyright © 2011 Nick Bowler
+ * Copyright © 2012, 2021-2022 Nick Bowler
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
#include <errno.h>
#include <assert.h>
#include <stdbool.h>
-#include <gsl/gsl_rng.h>
#include "declgen.h"
#include "cdecl.h"
#include "test.h"
-struct gen_rng {
- gsl_rng *rng;
-};
-
/*
* Generate a random identifier. We arbitrarily pick 10 as the largest
* possible. Avoid generating keywords, including the English ones, by
* excluding the letters t, o, a and n. Reserved words are OK.
*/
-char *gen_identifier(struct gen_rng *rng)
+char *gen_identifier(struct test_rng *rng)
{
static const char valid[59] = "_bcdefghijklmpqrsuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
char *str;
size_t n;
- n = gsl_rng_uniform_int(rng->rng, 10)+1;
+ n = test_rng_uniform_int(rng, 10)+1;
str = malloc_nofail(n+1);
/* Exclude 10 digits from the first character. */
- str[0] = valid[gsl_rng_uniform_int(rng->rng, sizeof valid - 10)];
+ str[0] = valid[test_rng_uniform_int(rng, sizeof valid - 10)];
for (size_t i = 1; i < n; i++)
- str[i] = valid[gsl_rng_uniform_int(rng->rng, sizeof valid)];
+ str[i] = valid[test_rng_uniform_int(rng, sizeof valid)];
str[n] = 0;
return str;
* qualifier is chosen uniformly at random from the set of possibilities:
* const, volatile and, if restrictqual is true, restrict.
*/
-struct cdecl_declspec *gen_qualifiers(struct gen_rng *rng, bool restrictqual)
+struct cdecl_declspec *gen_qualifiers(struct test_rng *rng, bool restrictqual)
{
struct cdecl_declspec *s = NULL, *p;
- while (gsl_rng_uniform(rng->rng) < 0.5) {
+ while (test_rng_uniform(rng) < 0.5) {
p = s;
s = malloc_nofail(sizeof *s);
*s = (struct cdecl_declspec) {
.next = p,
};
- switch (gsl_rng_uniform_int(rng->rng, 2+restrictqual)) {
+ switch (test_rng_uniform_int(rng, 2+restrictqual)) {
case 0:
s->type = CDECL_QUAL_CONST;
break;
* Generate random function specifiers. Like qualifiers, function specifiers
* can appear multiple times.
*/
-struct cdecl_declspec *gen_funcspecs(struct gen_rng *rng)
+struct cdecl_declspec *gen_funcspecs(struct test_rng *rng)
{
struct cdecl_declspec *s = NULL, *p;
- while (gsl_rng_uniform(rng->rng) < 0.5) {
+ while (test_rng_uniform(rng) < 0.5) {
p = s;
s = malloc_nofail(sizeof *s);
* true, then the only possible storage-class specifier is "register".
* Otherwise, a specifier type will be selected uniformly at random.
*/
-struct cdecl_declspec *gen_storspecs(struct gen_rng *rng, bool registeronly)
+struct cdecl_declspec *gen_storspecs(struct test_rng *rng, bool registeronly)
{
struct cdecl_declspec *s;
- if (gsl_rng_uniform(rng->rng) < 0.5)
+ if (test_rng_uniform(rng) < 0.5)
return NULL;
s = malloc_nofail(sizeof *s);
if (registeronly)
return s;
- switch (gsl_rng_uniform_int(rng->rng, 5)) {
+ switch (test_rng_uniform_int(rng, 5)) {
case 0: s->type = CDECL_STOR_TYPEDEF; break;
case 1: s->type = CDECL_STOR_REGISTER; break;
case 2: s->type = CDECL_STOR_STATIC; break;
*/
#include "typegen.h"
-struct cdecl_declspec *gen_typespecs(struct gen_rng *rng, bool voidtype)
+struct cdecl_declspec *gen_typespecs(struct test_rng *rng, bool voidtype)
{
struct cdecl_declspec *specs;
retry:
- specs = gen_raw_typespecs(gsl_rng_uniform_int(rng->rng,
- GEN_TOTAL_TYPES));
+ specs = gen_raw_typespecs(test_rng_uniform_int(rng, GEN_TOTAL_TYPES));
switch (specs->type) {
/* void is not always valid, so we might need to pick again. */
}
struct cdecl_declspec *
-gen_randomize_specs(struct gen_rng *rng, struct cdecl_declspec *specs)
+gen_randomize_specs(struct test_rng *rng, struct cdecl_declspec *specs)
{
struct cdecl_declspec **p;
size_t n = 0;
struct cdecl_declspec *tmp;
size_t r;
- r = gsl_rng_uniform_int(rng->rng, n-i);
+ r = test_rng_uniform_int(rng, n-i);
tmp = p[i];
p[i] = p[r+i];
p[r+i] = tmp;
* be generated by this function: use gen_qualifiers directly.
*/
struct cdecl_declspec *
-gen_declspecs(struct gen_rng *rng, unsigned flags)
+gen_declspecs(struct test_rng *rng, unsigned flags)
{
struct cdecl_declspec *s, *p;
return gen_randomize_specs(rng, s);
}
-static uintmax_t gen_uintmax(struct gen_rng *rng)
+static uintmax_t gen_uintmax(struct test_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);
+ tmp = test_rng_uniform_int(rng, UCHAR_MAX+1);
ret <<= CHAR_BIT;
ret |= tmp;
}
* Generate a random array declarator, selecting one of four possibilities
* uniformly at random.
*/
-static void gen_array(struct gen_rng *rng, struct cdecl_declarator *d)
+static void gen_array(struct test_rng *rng, struct cdecl_declarator *d)
{
d->type = CDECL_DECL_ARRAY;
d->u.array = (struct cdecl_array){0};
- switch (gsl_rng_uniform_int(rng->rng, 4)) {
+ switch (test_rng_uniform_int(rng, 4)) {
case 0:
d->u.array.vla = malloc_nofail(1);
d->u.array.vla[0] = 0;
}
/* Generate a function declarator. */
-static void gen_function(struct gen_rng *rng, struct cdecl_declarator *d)
+static void gen_function(struct test_rng *rng, struct cdecl_declarator *d)
{
d->type = CDECL_DECL_FUNCTION;
d->u.function.parameters = NULL;
- while (gsl_rng_uniform(rng->rng) < 0.5) {
+ while (test_rng_uniform(rng) < 0.5) {
unsigned flags = GEN_ONLY_REGISTER | GEN_NO_FUNCTION;
struct cdecl *param;
}
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) {
+ d->u.function.variadic = test_rng_uniform(rng) < 0.5;
+ } else if (test_rng_uniform(rng) < 0.5) {
struct cdecl *param;
/* We will never generate (void) above; do it here. */
* are ultimately terminated by either a null declarator or an identifier,
* selected uniformly at random.
*/
-struct cdecl_declarator *gen_declarators(struct gen_rng *rng)
+struct cdecl_declarator *gen_declarators(struct test_rng *rng)
{
struct cdecl_declarator *d, *p;
unsigned limit = 3;
d = malloc_nofail(sizeof *d);
- if (gsl_rng_uniform(rng->rng) < 0.5) {
+ if (test_rng_uniform(rng) < 0.5) {
*d = (struct cdecl_declarator) {
.type = CDECL_DECL_NULL,
};
};
}
- while (gsl_rng_uniform(rng->rng) < 0.5) {
+ while (test_rng_uniform(rng) < 0.5) {
p = d;
d = malloc_nofail(sizeof *d);
*d = (struct cdecl_declarator) {
.child = p,
};
- switch (gsl_rng_uniform_int(rng->rng, limit)) {
+ switch (test_rng_uniform_int(rng, limit)) {
case 0:
d->type = CDECL_DECL_POINTER;
d->u.pointer = (struct cdecl_pointer) {
return d;
}
-struct gen_rng *gen_alloc_rng(const char *seed_str)
-{
- unsigned long seed;
- struct gen_rng *rng;
- char *end;
-
- errno = 0;
- seed = strtoul(seed_str, &end, 0);
- if (*end != 0) {
- fprintf(stderr, "%s: invalid seed\n", seed_str);
- return NULL;
- } else if (errno != 0) {
- fprintf(stderr, "%s: invalid seed: %s\n",
- seed_str, strerror(errno));
- return NULL;
- }
-
- 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;