]> git.draconx.ca Git - cdecl99.git/blob - test/randomdecl.c
12728ccb7fa09d0aafe87712bb0b44cf04d2949c
[cdecl99.git] / test / randomdecl.c
1 /*
2  *  Generate random C declarations for testing.
3  *  Copyright © 2011 Nick Bowler
4  *
5  *  This program is free software: you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation, either version 3 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18
19 #include <config.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <assert.h>
24 #include <stdbool.h>
25 #include <errno.h>
26 #include <getopt.h>
27 #include <cdecl.h>
28
29 #include "declgen.h"
30 #include "test.h"
31
32 #define PROGNAME "randomdecl"
33 static const char *progname = PROGNAME;
34 static const char sopts[] = "s:n:VH";
35 static const struct option lopts[] = {
36         { "seed",    1, NULL, 's' },
37         { "count",   1, NULL, 'n' },
38         { "version", 0, NULL, 'V' },
39         { "help",    0, NULL, 'H' },
40         { 0 }
41 };
42
43 static void print_version()
44 {
45         puts(PROGNAME " (" PACKAGE_NAME ") " PACKAGE_VERSION);
46         puts("Copyright (C) 2011 Nick Bowler.");
47         puts("License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.");
48         puts("This is free software: you are free to change and redistribute it.");
49         puts("There is NO WARRANTY, to the extent permitted by law.");
50 }
51
52 static void print_usage(FILE *f)
53 {
54         fprintf(f, "Usage: %s [options]\n", progname);
55 }
56
57 static void print_help(void)
58 {
59         print_usage(stdout);
60         puts("Detailed help coming soon.");
61 }
62
63 static struct cdecl *random_decl(struct gen_rng *rng)
64 {
65         struct cdecl *decl;
66         unsigned flags = 0;
67
68         decl = malloc_nofail(sizeof *decl);
69         *decl = (struct cdecl) { 0 };
70
71         decl->declarators = gen_declarators(rng);
72         if (decl->declarators->type != CDECL_DECL_FUNCTION)
73                 flags |= GEN_NO_FUNCTION;
74         if (cdecl_is_abstract(decl->declarators))
75                 flags |= GEN_NO_STORAGE | GEN_NO_FUNCTION;
76         if (decl->declarators->type == CDECL_DECL_ARRAY
77             || decl->declarators->type == CDECL_DECL_IDENT)
78                 flags |= GEN_NO_VOID;
79
80         decl->specifiers = gen_declspecs(rng, flags);
81         return decl;
82 }
83
84 int main(int argc, char **argv)
85 {
86         const char *seed = "", *count_str = NULL;
87         struct gen_rng *rng;
88         struct cdecl *decl;
89         unsigned long count = 0;
90         int opt;
91
92         if (argc > 0)
93                 progname = argv[0];
94
95         while ((opt = getopt_long(argc, argv, sopts, lopts, NULL)) != -1) {
96                 switch (opt) {
97                 case 's':
98                         seed = optarg;
99                         break;
100                 case 'n':
101                         count_str = optarg;
102                         break;
103                 case 'V':
104                         print_version();
105                         return EXIT_SUCCESS;
106                 case 'H':
107                         print_help();
108                         return EXIT_SUCCESS;
109                 default:
110                         print_usage(stderr);
111                         return EXIT_FAILURE;
112                 }
113         }
114
115         if (count_str && !strict_strtoul(&count, count_str, 0)) {
116                 fprintf(stderr, "%s: invalid count: %s\n", progname, count_str);
117                 return EXIT_FAILURE;
118         }
119
120         rng = gen_alloc_rng(seed);
121         if (!rng)
122                 return EXIT_FAILURE;
123
124         for (unsigned long i = 0; !count || i < count; i++) {
125                 decl = random_decl(rng);
126                 if (!decl)
127                         return EXIT_FAILURE;
128
129                 test_print_decl(decl);
130         }
131
132         return EXIT_SUCCESS;
133 }