]> git.draconx.ca Git - cdecl99.git/blobdiff - test/randomdecl.c
Add a tool to generate random declarations.
[cdecl99.git] / test / randomdecl.c
diff --git a/test/randomdecl.c b/test/randomdecl.c
new file mode 100644 (file)
index 0000000..12728cc
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <stdbool.h>
+#include <errno.h>
+#include <getopt.h>
+#include <cdecl.h>
+
+#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 <http://gnu.org/licenses/gpl.html>.");
+       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;
+}