--- /dev/null
+_info
+.depends
--- /dev/null
+CFLAGS=-O3 -Wall -Wstrict-prototypes -Wold-style-definition -Wmissing-prototypes -Wmissing-declarations -Werror -I.
+
+ALL=$(patsubst %/test, %, $(wildcard */test))
+ALL_DEPENDS=$(patsubst %, %/.depends, $(ALL))
+
+default: test-all
+
+test-all: $(ALL_DEPENDS)
+ @$(MAKE) `for f in $(ALL); do echo test-$$f test-$$f; while read d; do echo test-$$d test-$$f; done < $$f/.depends; done | tsort`
+
+$(ALL_DEPENDS): %/.depends: %/_info
+ @$< depends > $@ || ( rm -f $@; exit 1 )
+
+test-%: FORCE run_tests
+ @echo Testing $*...
+ @if ./run_tests $* | grep ^'not ok'; then exit 1; else exit 0; fi
+
+FORCE:
+
+run_tests: run_tests.o tap/tap.o talloc/talloc.o
+
+clean:
+ rm -f run_tests run_tests.o
--- /dev/null
+#include <stdio.h>
+#include <string.h>
+#include "config.h"
+
+/**
+ * build_assert - routines for build-time assertions
+ *
+ * This code provides routines which will cause compilation to fail should some
+ * assertion be untrue: such failures are preferable to run-time assertions,
+ * but much more limited since they can only depends on compile-time constants.
+ *
+ * These assertions are most useful when two parts of the code must be kept in
+ * sync: it is better to avoid such cases if possible, but seconds best is to
+ * detect invalid changes at build time.
+ *
+ * For example, a tricky piece of code might rely on a certain element being at
+ * the start of the structure. To ensure that future changes don't break it,
+ * you would catch such changes in your code like so:
+ *
+ * Example:
+ * char *foo_string(struct foo *foo)
+ * {
+ * // This trick requires that the string be first in the structure
+ * BUILD_ASSERT(offsetof(struct foo, string) == 0);
+ * return (char *)foo;
+ * }
+ */
+int main(int argc, char *argv[])
+{
+ if (argc != 2)
+ return 1;
+
+ if (strcmp(argv[1], "depends") == 0)
+ /* Nothing. */
+ return 0;
+
+ return 1;
+}
--- /dev/null
+#ifndef CCAN_BUILD_ASSERT_H
+#define CCAN_BUILD_ASSERT_H
+
+/**
+ * BUILD_ASSERT - assert a build-time dependency.
+ * @cond: the compile-time condition which must be true.
+ *
+ * Your compile will fail if the condition isn't true, or can't be evaluated
+ * by the compiler. This can only be used within a function.
+ *
+ * Example:
+ * char *foo_to_char(struct foo *foo)
+ * {
+ * // This code needs string to be at start of foo.
+ * BUILD_ASSERT(offsetof(struct foo, string) == 0);
+ * return (char *)foo;
+ * }
+ */
+#define BUILD_ASSERT(cond) \
+ do { (void) sizeof(char [1 - 2*!(cond)]); } while(0)
+
+/**
+ * EXPR_BUILD_ASSERT - assert a build-time dependency, as an expression.
+ * @cond: the compile-time condition which must be true.
+ *
+ * Your compile will fail if the condition isn't true, or can't be evaluated
+ * by the compiler. This can be used in an expression: its value is "0".
+ *
+ * Example:
+ * #define foo_to_char(foo) \
+ * ((char *)(foo) \
+ * + EXPR_BUILD_ASSERT(offsetof(struct foo, string) == 0))
+ */
+#define EXPR_BUILD_ASSERT(cond) \
+ (sizeof(char [1 - 2*!(cond)]) - 1)
+
+#endif /* CCAN_BUILD_ASSERT_H */
--- /dev/null
+#include "build_assert/build_assert.h"
+
+int main(int argc, char *argv[])
+{
+#ifdef FAIL
+ return EXPR_BUILD_ASSERT(1 == 0);
+#else
+ return 0;
+#endif
+}
--- /dev/null
+#include "build_assert/build_assert.h"
+
+int main(int argc, char *argv[])
+{
+#ifdef FAIL
+ BUILD_ASSERT(1 == 0);
+#endif
+ return 0;
+}
--- /dev/null
+#include "build_assert/build_assert.h"
+
+int main(int argc, char *argv[])
+{
+ BUILD_ASSERT(1 == 1);
+ return 0;
+}
--- /dev/null
+#include "build_assert/build_assert.h"
+#include "tap/tap.h"
+
+int main(int argc, char *argv[])
+{
+ plan_tests(1);
+ ok1(EXPR_BUILD_ASSERT(1 == 1) == 0);
+ return exit_status();
+}
--- /dev/null
+#include <stdio.h>
+#include <string.h>
+#include "config.h"
+
+/**
+ * check_type - routines for compile time type checking
+ *
+ * C has fairly weak typing: ints get automatically converted to longs, signed
+ * to unsigned, etc. There are some cases where this is best avoided, and
+ * these macros provide methods for evoking warnings (or build errors) when
+ * a precise type isn't used.
+ *
+ * On compilers which don't support typeof() these routines are less effective,
+ * since they have to use sizeof() which can only distiguish between types of
+ * different size.
+ */
+int main(int argc, char *argv[])
+{
+ if (argc != 2)
+ return 1;
+
+ if (strcmp(argv[1], "depends") == 0) {
+#if !HAVE_TYPEOF
+ printf("build_assert\n");
+#endif
+ return 0;
+ }
+
+ return 1;
+}
--- /dev/null
+#ifndef CCAN_CHECK_TYPE_H
+#define CCAN_CHECK_TYPE_H
+#include "config.h"
+
+/**
+ * check_type - issue a warning or build failure if type is not correct.
+ * @expr: the expression whose type we should check (not evaluated).
+ * @type: the exact type we expect the expression to be.
+ *
+ * This macro is usually used within other macros to try to ensure that a macro
+ * argument is of the expected type. No type promotion of the expression is
+ * done: an unsigned int is not the same as an int!
+ *
+ * check_type() always evaluates to 1.
+ *
+ * If your compiler does not support typeof, then the best we can do is fail
+ * to compile if the sizes of the types are unequal (a less complete check).
+ *
+ * Example:
+ * // They should always pass a 64-bit value to _set_some_value!
+ * #define set_some_value(expr) \
+ * _set_some_value((check_type((expr), uint64_t), (expr)))
+ */
+
+/**
+ * check_types_match - issue a warning or build failure if types are not same.
+ * @expr1: the first expression (not evaluated).
+ * @expr2: the second expression (not evaluated).
+ *
+ * This macro is usually used within other macros to try to ensure that
+ * arguments are of identical types. No type promotion of the expressions is
+ * done: an unsigned int is not the same as an int!
+ *
+ * check_types_match() always evaluates to 1.
+ *
+ * If your compiler does not support typeof, then the best we can do is fail
+ * to compile if the sizes of the types are unequal (a less complete check).
+ *
+ * Example:
+ * // Do subtraction to get to enclosing type, but make sure that
+ * // pointer is of correct type for that member.
+ * #define container_of(mbr_ptr, encl_type, mbr) \
+ * (check_types_match((mbr_ptr), &((encl_type *)0)->mbr), \
+ * ((encl_type *) \
+ * ((char *)(mbr_ptr) - offsetof(enclosing_type, mbr))))
+ */
+#if HAVE_TYPEOF
+#define check_type(expr, type) \
+ ((typeof(expr) *)0 != (type *)0)
+
+#define check_types_match(expr1, expr2) \
+ ((typeof(expr1) *)0 != (typeof(expr2) *)0)
+#else
+#include "build_assert/build_assert.h"
+/* Without typeof, we can only test the sizes. */
+#define check_type(expr, type) \
+ EXPR_BUILD_ASSERT(sizeof(expr) == sizeof(type))
+
+#define check_types_match(expr1, expr2) \
+ EXPR_BUILD_ASSERT(sizeof(expr1) == sizeof(expr2))
+#endif /* HAVE_TYPEOF */
+
+#endif /* CCAN_CHECK_TYPE_H */
--- /dev/null
+#include "check_type/check_type.h"
+
+int main(int argc, char *argv[])
+{
+#ifdef FAIL
+ check_type(argc, char);
+#endif
+ return 0;
+}
--- /dev/null
+#include "check_type/check_type.h"
+
+int main(int argc, char *argv[])
+{
+#ifdef FAIL
+#if HAVE_TYPEOF
+ check_type(argc, unsigned int);
+#else
+ /* This doesn't work without typeof, so just fail */
+#error "Fail without typeof"
+#endif
+#endif
+ return 0;
+}
--- /dev/null
+#include "check_type/check_type.h"
+
+int main(int argc, char *argv[])
+{
+ unsigned char x = argc;
+#ifdef FAIL
+ check_types_match(argc, x);
+#endif
+ return x;
+}
--- /dev/null
+#include "check_type/check_type.h"
+#include "tap/tap.h"
+
+int main(int argc, char *argv[])
+{
+ int x = 0, y = 0;
+
+ plan_tests(9);
+
+ ok1(check_type(argc, int) == 0);
+ ok1(check_type(&argc, int *) == 0);
+ ok1(check_types_match(argc, argc) == 0);
+ ok1(check_types_match(argc, x) == 0);
+ ok1(check_types_match(&argc, &x) == 0);
+
+ ok1(check_type(x++, int) == 0);
+ ok(x == 0, "check_type does not evaluate expression");
+ ok1(check_types_match(x++, y++) == 0);
+ ok(x == 0 && y == 0, "check_types_match does not evaluate expressions");
+
+ return 0;
+}
--- /dev/null
+/* Simple config.h for gcc. */
+#define HAVE_TYPEOF 1
+#define HAVE_STATEMENT_EXPR 1
--- /dev/null
+#include <stdio.h>
+#include <string.h>
+#include "config.h"
+
+/**
+ * container_of - routine for upcasting
+ *
+ * It is often convenient to create code where the caller registers a pointer
+ * to a generic structure and a callback. The callback might know that the
+ * pointer points to within a larger structure, and container_of gives a
+ * convenient and fairly type-safe way of returning to the enclosing structure.
+ *
+ * This idiom is an alternative to providing a void * pointer for every
+ * callback.
+ *
+ * Example:
+ * struct info
+ * {
+ * int my_stuff;
+ * struct timer timer;
+ * };
+ *
+ * static void my_timer_callback(struct timer *timer)
+ * {
+ * struct info *info = container_of(timer, struct info, timer);
+ * printf("my_stuff is %u\n", info->my_stuff);
+ * }
+ *
+ * int main()
+ * {
+ * struct info info = { .my_stuff = 1 };
+ *
+ * register_timer(&info.timer);
+ * ...
+ */
+int main(int argc, char *argv[])
+{
+ if (argc != 2)
+ return 1;
+
+ if (strcmp(argv[1], "depends") == 0) {
+ printf("check_type\n");
+ return 0;
+ }
+
+ return 1;
+}
--- /dev/null
+#ifndef CCAN_CONTAINER_OF_H
+#define CCAN_CONTAINER_OF_H
+#include <stddef.h>
+
+#include "config.h"
+#include "check_type/check_type.h"
+
+#define container_of(member_ptr, containing_type, member) \
+ ((containing_type *) \
+ ((char *)(member_ptr) - offsetof(containing_type, member)) \
+ - check_types_match(*(member_ptr), ((containing_type *)0)->member))
+
+
+#endif /* CCAN_CONTAINER_OF_H */
--- /dev/null
+#include "container_of/container_of.h"
+#include <stdlib.h>
+
+struct foo {
+ int a;
+ char b;
+};
+
+int main(int argc, char *argv[])
+{
+ struct foo foo = { .a = 1, .b = 2 };
+ int *intp = &foo.a;
+ char *p;
+
+#ifdef FAIL
+ p = container_of(intp, struct foo, a);
+#else
+ p = (char *)intp;
+#endif
+ return p == NULL;
+}
--- /dev/null
+#include "container_of/container_of.h"
+#include <stdlib.h>
+
+struct foo {
+ int a;
+ char b;
+};
+
+int main(int argc, char *argv[])
+{
+ struct foo foo = { .a = 1, .b = 2 }, *foop;
+ int *intp = &foo.a;
+
+#ifdef FAIL
+ foop = container_of(intp, struct foo, b);
+#else
+ foop = NULL;
+#endif
+ return intp == NULL;
+}
--- /dev/null
+#include "container_of/container_of.h"
+#include "tap/tap.h"
+
+struct foo {
+ int a;
+ char b;
+};
+
+int main(int argc, char *argv[])
+{
+ struct foo foo = { .a = 1, .b = 2 };
+ int *intp = &foo.a;
+ char *charp = &foo.b;
+
+ plan_tests(2);
+ ok1(container_of(intp, struct foo, a) == &foo);
+ ok1(container_of(charp, struct foo, b) == &foo);
+ return exit_status();
+}
--- /dev/null
+#include <err.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <assert.h>
+#include <unistd.h>
+#include "tap/tap.h"
+#include "talloc/talloc.h"
+#include "string/string.h"
+
+#define CFLAGS "-O3 -Wall -Wundef -Wstrict-prototypes -Wold-style-definition -Wmissing-prototypes -Wmissing-declarations -Werror -I."
+
+/* FIXME: Use build bug later. */
+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+
+static struct test *tests = NULL;
+static struct obj *objs = NULL;
+static int verbose;
+
+struct test_type
+{
+ const char *name;
+ void (*testfn)(struct test_type *t, const char *name);
+};
+
+struct test
+{
+ struct test *next;
+ struct test_type *type;
+ char *name;
+};
+
+struct obj
+{
+ struct obj *next;
+ char *name;
+};
+
+static char *output_name(const char *name)
+{
+ char *ret;
+
+ assert(strends(name, ".c"));
+
+ ret = talloc_strdup(name, name);
+ ret[strlen(ret) - 2] = '\0';
+ return ret;
+}
+
+static char *obj_list(void)
+{
+ char *list = talloc_strdup(objs, "");
+ struct obj *i;
+
+ for (i = objs; i; i = i->next)
+ list = talloc_asprintf_append(list, "%s ", i->name);
+
+ /* FIXME */
+ list = talloc_asprintf_append(list, "tap/tap.o");
+ return list;
+}
+
+static void compile_objs(void)
+{
+ struct obj *i;
+
+ for (i = objs; i; i = i->next) {
+ char *cmd = talloc_asprintf(i, "gcc " CFLAGS " -o %s.o -c %s%s",
+ output_name(i->name), i->name,
+ verbose ? "" : "> /dev/null 2>&1");
+ ok(system(cmd) == 0, "%s", cmd);
+ }
+}
+
+static void cleanup_objs(void)
+{
+ struct obj *i;
+
+ for (i = objs; i; i = i->next)
+ unlink(talloc_asprintf(i, "%s.o", output_name(i->name)));
+}
+
+static void add_test(const char *testdir, const char *name, struct test_type *t)
+{
+ struct test *test = talloc(testdir, struct test);
+
+ test->next = tests;
+ test->type = t;
+ test->name = talloc_asprintf(test, "%s/%s", testdir, name);
+ tests = test;
+}
+
+static void add_obj(const char *testdir, const char *name)
+{
+ struct obj *obj = talloc(testdir, struct obj);
+
+ obj->next = objs;
+ obj->name = talloc_asprintf(obj, "%s/%s", testdir, name);
+ objs = obj;
+}
+
+static int build(const char *name, int fail)
+{
+ const char *cmd;
+ int ret;
+
+ cmd = talloc_asprintf(name, "gcc " CFLAGS " %s -o %s %s %s%s",
+ fail ? "-DFAIL" : "",
+ output_name(name), name, obj_list(),
+ verbose ? "" : "> /dev/null 2>&1");
+
+ if (verbose)
+ fprintf(stderr, "Running %s\n", cmd);
+
+ ret = system(cmd);
+ if (ret == -1)
+ diag("cmd '%s' failed to execute", cmd);
+
+ return ret;
+}
+
+static void compile_ok(struct test_type *t, const char *name)
+{
+ ok(build(name, 0) == 0, "%s %s", t->name, name);
+}
+
+static void compile_fail(struct test_type *t, const char *name)
+{
+ if (build(name, 0) != 0)
+ fail("non-FAIL build %s", name);
+ else
+ ok(build(name, 1) > 0, "%s %s", t->name, name);
+}
+
+static void run(const char *name)
+{
+ if (system(output_name(name)) == -1)
+ fail("running %s had error %m", name);
+}
+
+static void cleanup(const char *name)
+{
+ unlink(output_name(name));
+}
+
+static struct test_type test_types[] = {
+ { "compile_ok", compile_ok },
+ { "compile_fail", compile_fail },
+ { "run", compile_ok },
+};
+
+int main(int argc, char *argv[])
+{
+ DIR *dir;
+ struct dirent *d;
+ char *testdir;
+ struct test *test;
+ unsigned int num_tests = 0, num_objs = 0;
+
+ if (argc > 1 && streq(argv[1], "--verbose")) {
+ verbose = 1;
+ argc--;
+ argv++;
+ }
+
+ if (argc != 2)
+ errx(1, "Usage: run_tests [--verbose] <dir>");
+
+ testdir = talloc_asprintf(NULL, "%s/test", argv[1]);
+ dir = opendir(testdir);
+ if (!dir)
+ err(1, "Opening '%s'", testdir);
+
+ while ((d = readdir(dir)) != NULL) {
+ unsigned int i;
+ if (d->d_name[0] == '.' || !strends(d->d_name, ".c"))
+ continue;
+
+ for (i = 0; i < ARRAY_SIZE(test_types); i++) {
+ if (strstarts(d->d_name, test_types[i].name)) {
+ add_test(testdir, d->d_name, &test_types[i]);
+ num_tests++;
+ break;
+ }
+ }
+ if (i == ARRAY_SIZE(test_types)) {
+ add_obj(testdir, d->d_name);
+ num_objs++;
+ }
+ }
+
+ plan_tests(num_tests + num_objs);
+ /* First all the extra object compilations. */
+ compile_objs();
+
+ /* Do all the test compilations. */
+ for (test = tests; test; test = test->next)
+ test->type->testfn(test->type, test->name);
+
+ cleanup_objs();
+
+ /* Now run all the ones which wanted to run. */
+ for (test = tests; test; test = test->next) {
+ if (streq(test->type->name, "run"))
+ run(test->name);
+ cleanup(test->name);
+ }
+
+ exit(exit_status());
+}
--- /dev/null
+#! /bin/sh
+
+# First, test normal config.
+if ! make -s; then
+ echo Normal config failed.
+ exit 1
+fi
+
+# Now, remove one HAVE_ at a time.
+cp config.h original-config.h
+trap "mv original-config.h config.h && rm -f .newconfig" EXIT
+
+while grep -q '1$' config.h; do
+ tr '\012' @ < config.h | sed 's/1@/0@/' | tr @ '\012' > .newconfig
+ diff -u config.h .newconfig
+ mv .newconfig config.h
+ if ! make -s; then
+ echo Failed config:
+ cat config.h
+ exit 1
+ fi
+done