X-Git-Url: https://git.draconx.ca/gitweb/cdecl99.git/blobdiff_plain/846e987e42c15064fa078e0b708872f7938ceb09..568c39ad1836f8cf87ccc1b2ba577b6f6ba37e25:/test/randomdecl.c diff --git a/test/randomdecl.c b/test/randomdecl.c new file mode 100644 index 0000000..12728cc --- /dev/null +++ b/test/randomdecl.c @@ -0,0 +1,133 @@ +/* + * Generate random C declarations for testing. + * Copyright © 2011 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 + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "declgen.h" +#include "test.h" + +#define PROGNAME "randomdecl" +static const char *progname = PROGNAME; +static const char sopts[] = "s:n:VH"; +static const struct option lopts[] = { + { "seed", 1, NULL, 's' }, + { "count", 1, NULL, 'n' }, + { "version", 0, NULL, 'V' }, + { "help", 0, NULL, 'H' }, + { 0 } +}; + +static void print_version() +{ + puts(PROGNAME " (" PACKAGE_NAME ") " PACKAGE_VERSION); + puts("Copyright (C) 2011 Nick Bowler."); + puts("License GPLv3+: GNU GPL version 3 or later ."); + puts("This is free software: you are free to change and redistribute it."); + puts("There is NO WARRANTY, to the extent permitted by law."); +} + +static void print_usage(FILE *f) +{ + fprintf(f, "Usage: %s [options]\n", progname); +} + +static void print_help(void) +{ + print_usage(stdout); + puts("Detailed help coming soon."); +} + +static struct cdecl *random_decl(struct gen_rng *rng) +{ + struct cdecl *decl; + unsigned flags = 0; + + decl = malloc_nofail(sizeof *decl); + *decl = (struct cdecl) { 0 }; + + decl->declarators = gen_declarators(rng); + if (decl->declarators->type != CDECL_DECL_FUNCTION) + flags |= GEN_NO_FUNCTION; + if (cdecl_is_abstract(decl->declarators)) + flags |= GEN_NO_STORAGE | GEN_NO_FUNCTION; + if (decl->declarators->type == CDECL_DECL_ARRAY + || decl->declarators->type == CDECL_DECL_IDENT) + flags |= GEN_NO_VOID; + + decl->specifiers = gen_declspecs(rng, flags); + return decl; +} + +int main(int argc, char **argv) +{ + const char *seed = "", *count_str = NULL; + struct gen_rng *rng; + struct cdecl *decl; + unsigned long count = 0; + int opt; + + if (argc > 0) + progname = argv[0]; + + while ((opt = getopt_long(argc, argv, sopts, lopts, NULL)) != -1) { + switch (opt) { + case 's': + seed = optarg; + break; + case 'n': + count_str = optarg; + break; + case 'V': + print_version(); + return EXIT_SUCCESS; + case 'H': + print_help(); + return EXIT_SUCCESS; + default: + print_usage(stderr); + return EXIT_FAILURE; + } + } + + if (count_str && !strict_strtoul(&count, count_str, 0)) { + fprintf(stderr, "%s: invalid count: %s\n", progname, count_str); + return EXIT_FAILURE; + } + + rng = gen_alloc_rng(seed); + if (!rng) + return EXIT_FAILURE; + + for (unsigned long i = 0; !count || i < count; i++) { + decl = random_decl(rng); + if (!decl) + return EXIT_FAILURE; + + test_print_decl(decl); + } + + return EXIT_SUCCESS; +}