X-Git-Url: http://git.ozlabs.org/?p=ccan;a=blobdiff_plain;f=tools%2Fconfigurator%2Fconfigurator.c;h=56880fb1875b066a6eddc3b99954ca65b0158cec;hp=4445139c90fcfabd01989956e1e60cd8cc958e36;hb=d1d29462c77d909b8e7a6b960bcc71c9422e0f8f;hpb=1f4312c3320f353a18ab4aec4b8ae725fc25c911 diff --git a/tools/configurator/configurator.c b/tools/configurator/configurator.c index 4445139c..56880fb1 100644 --- a/tools/configurator/configurator.c +++ b/tools/configurator/configurator.c @@ -20,10 +20,11 @@ static int verbose; enum test_style { - EXECUTE, - OUTSIDE_MAIN, - DEFINES_FUNC, - INSIDE_MAIN + OUTSIDE_MAIN = 0x1, + DEFINES_FUNC = 0x2, + INSIDE_MAIN = 0x4, + DEFINES_EVERYTHING = 0x8, + EXECUTE = 0x8000 }; struct test { @@ -38,19 +39,30 @@ struct test { static struct test tests[] = { { "HAVE_ALIGNOF", INSIDE_MAIN, NULL, "return __alignof__(double) > 0 ? 0 : 1;" }, + { "HAVE_ASPRINTF", DEFINES_FUNC, NULL, + "#define _GNU_SOURCE\n" + "#include \n" + "static char *func(int x) {" + " char *p;\n" + " if (asprintf(&p, \"%u\", x) == -1) p = NULL;" + " return p;\n" + "}" }, { "HAVE_ATTRIBUTE_COLD", DEFINES_FUNC, NULL, "static int __attribute__((cold)) func(int x) { return x; }" }, { "HAVE_ATTRIBUTE_CONST", DEFINES_FUNC, NULL, "static int __attribute__((const)) func(int x) { return x; }" }, { "HAVE_ATTRIBUTE_MAY_ALIAS", OUTSIDE_MAIN, NULL, "typedef short __attribute__((__may_alias__)) short_a;" }, + { "HAVE_ATTRIBUTE_NORETURN", DEFINES_FUNC, NULL, + "#include \n" + "static void __attribute__((noreturn)) func(int x) { exit(x); }" }, { "HAVE_ATTRIBUTE_PRINTF", DEFINES_FUNC, NULL, "static void __attribute__((format(__printf__, 1, 2))) func(const char *fmt, ...) { }" }, { "HAVE_ATTRIBUTE_UNUSED", OUTSIDE_MAIN, NULL, "static int __attribute__((unused)) func(int x) { return x; }" }, { "HAVE_ATTRIBUTE_USED", OUTSIDE_MAIN, NULL, "static int __attribute__((used)) func(int x) { return x; }" }, - { "HAVE_BIG_ENDIAN", EXECUTE, NULL, + { "HAVE_BIG_ENDIAN", INSIDE_MAIN|EXECUTE, NULL, "union { int i; char c[sizeof(int)]; } u;\n" "u.i = 0x01020304;\n" "return u.c[0] == 0x01 && u.c[1] == 0x02 && u.c[2] == 0x03 && u.c[3] == 0x04 ? 0 : 1;" }, @@ -90,7 +102,7 @@ static struct test tests[] = { { "HAVE_GETPAGESIZE", DEFINES_FUNC, NULL, "#include \n" "static int func(void) { return getpagesize(); }" }, - { "HAVE_LITTLE_ENDIAN", EXECUTE, NULL, + { "HAVE_LITTLE_ENDIAN", INSIDE_MAIN|EXECUTE, NULL, "union { int i; char c[sizeof(int)]; } u;\n" "u.i = 0x01020304;\n" "return u.c[0] == 0x04 && u.c[1] == 0x03 && u.c[2] == 0x02 && u.c[3] == 0x01 ? 0 : 1;" }, @@ -100,12 +112,22 @@ static struct test tests[] = { " return mmap(0, 65536, PROT_READ, MAP_SHARED, fd, 0);\n" "}" }, { "HAVE_NESTED_FUNCTIONS", DEFINES_FUNC, NULL, - "static int func(int val) {\n" + "void (*func(int val))(int);\n" + "void (*func(int val))(int) {\n" " auto void add(int val2);\n" " void add(int val2) { val += val2; }\n" - " add(7);\n" - " return val;\n" - "}" }, + " return add;\n" + "}\n" }, + { "HAVE_STACK_GROWS_UPWARDS", DEFINES_EVERYTHING|EXECUTE, NULL, + "static long nest(const void *base, unsigned int i)\n" + "{\n" + " if (i == 0)\n" + " return (const char *)&i - (const char *)base;\n" + " return nest(base, i-1);\n" + "}\n" + "int main(int argc, char *argv[]) {\n" + " return (nest(&argc, argc) > 0) ? 0 : 1\n;" + "}\n" }, { "HAVE_STATEMENT_EXPR", INSIDE_MAIN, NULL, "return ({ int x = argc; x == argc ? 0 : 1; });" }, { "HAVE_TYPEOF", INSIDE_MAIN, NULL, @@ -242,8 +264,7 @@ static bool run_test(const char *cmd, struct test *test) err(1, "creating %s", INPUT_FILE); fprintf(outf, "%s", PRE_BOILERPLATE); - switch (test->style) { - case EXECUTE: + switch (test->style & ~EXECUTE) { case INSIDE_MAIN: fprintf(outf, "%s", MAIN_START_BOILERPLATE); fprintf(outf, "%s", test->fragment); @@ -262,6 +283,12 @@ static bool run_test(const char *cmd, struct test *test) fprintf(outf, "%s", MAIN_BODY_BOILERPLATE); fprintf(outf, "%s", MAIN_END_BOILERPLATE); break; + case DEFINES_EVERYTHING: + fprintf(outf, "%s", test->fragment); + break; + default: + abort(); + } fclose(outf); @@ -274,7 +301,7 @@ static bool run_test(const char *cmd, struct test *test) printf("Compile %s for %s, status %i: %s\n", status ? "fail" : "warning", test->name, status, output); - if (test->style == EXECUTE) + if (test->style & EXECUTE) errx(1, "Test for %s did not compile:\n%s", test->name, output); test->answer = false; @@ -283,9 +310,9 @@ static bool run_test(const char *cmd, struct test *test) /* Compile succeeded. */ free(output); /* We run INSIDE_MAIN tests for sanity checking. */ - if (test->style == EXECUTE || test->style == INSIDE_MAIN) { + if ((test->style & EXECUTE) || (test->style & INSIDE_MAIN)) { output = run("./" OUTPUT_FILE, &status); - if (test->style == INSIDE_MAIN && status != 0) + if (!(test->style & EXECUTE) && status != 0) errx(1, "Test for %s failed with %i:\n%s", test->name, status, output); if (verbose && status) @@ -334,10 +361,14 @@ int main(int argc, char *argv[]) unlink(INPUT_FILE); cmd[strlen(cmd) - strlen(" -o " OUTPUT_FILE " " INPUT_FILE)] = '\0'; - printf("/* Generated by CCAN configurator */\n"); + printf("/* Generated by CCAN configurator */\n" + "#ifndef CCAN_CONFIG_H\n" + "#define CCAN_CONFIG_H\n"); + printf("#define _GNU_SOURCE /* Always use GNU extensions. */\n"); printf("#define CCAN_COMPILER \"%s\"\n", argv[1]); printf("#define CCAN_CFLAGS \"%s\"\n\n", cmd + strlen(argv[1]) + 1); for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) printf("#define %s %u\n", tests[i].name, tests[i].answer); + printf("#endif /* CCAN_CONFIG_H */\n"); return 0; }