2 * Generate random C declarations for testing.
3 * Copyright © 2012, 2020, 2022-2024 Nick Bowler
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.
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.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <https://www.gnu.org/licenses/>.
31 #define PROGNAME "randomdecl"
34 static const char sopts[] = "s:n:ECVH";
35 static const struct option lopts[] = {
36 { "seed", 1, NULL, 's' },
37 { "count", 1, NULL, 'n' },
38 { "cdecl", 0, NULL, 'C' },
39 { "english", 0, NULL, 'E' },
40 { "version", 0, NULL, 'V' },
41 { "help", 0, NULL, 'H' },
50 static void print_usage(FILE *f)
52 fprintf(f, "Usage: %s [options]\n", progname);
55 static void print_help(void)
57 const struct option *opt;
60 puts("Generate random C declarations for testing.\n");
61 test_print_options(lopts);
64 static struct cdecl *random_decl(struct test_rng *rng)
69 decl = malloc_nofail(sizeof *decl);
72 decl->declarators = gen_declarators(rng);
73 if (decl->declarators->type != CDECL_DECL_FUNCTION)
74 flags |= GEN_NO_FUNCTION;
75 if (cdecl_is_abstract(decl->declarators))
76 flags |= GEN_NO_STORAGE | GEN_NO_FUNCTION;
77 if (decl->declarators->type == CDECL_DECL_ARRAY
78 || decl->declarators->type == CDECL_DECL_IDENT)
81 decl->specifiers = gen_declspecs(rng, flags);
86 print_decl(struct cdecl *decl, size_t func(char *, size_t, struct cdecl *))
88 static size_t printbuf_size;
89 static char *printbuf;
92 rc = func(printbuf, printbuf_size, decl);
93 if (rc >= printbuf_size) {
94 printbuf_size = rc + 1;
95 printbuf = realloc_nofail(printbuf, printbuf_size);
99 printf("%s\n", printbuf);
102 int main(int argc, char **argv)
104 const char *seed = "", *count_str = NULL;
105 unsigned long i, count = 0;
106 int opt, mode = MODE_CDECL;
107 struct test_rng *rng;
113 while ((opt = getopt_long(argc, argv, sopts, lopts, NULL)) != -1) {
128 test_print_version(PROGNAME);
139 if (count_str && !test_strtoul(&count, count_str)) {
140 print_error("invalid count: %s", count_str);
144 rng = test_rng_alloc(seed);
148 for (i = 0; !count || i < count; i++) {
149 decl = random_decl(rng);
151 if (mode == MODE_ENGLISH) {
152 print_decl(decl, cdecl_explain);
154 print_decl(decl, cdecl_declare);
157 gen_free_declspecs(decl->specifiers);
158 gen_free_declarators(decl->declarators);