return 0;
}
+ if (strcmp(argv[1], "testdepends") == 0) {
+ printf("ccan/build_assert\n");
+ return 0;
+ }
+
return 1;
}
#define TCON(decls) struct { decls; } _tcon[1]
#endif
+/**
+ * TCON_WRAP - declare a wrapper type containing a base type and type canaries
+ * @basetype: the base type to wrap
+ * @decls: the semi-colon separated list of type canaries.
+ *
+ * This expands to a new type which includes the given base type, and
+ * also type canaries, similar to those created with TCON.
+ *
+ * The embedded base type value can be accessed using tcon_unwrap().
+ *
+ * Differences from using TCON()
+ * - The wrapper type will take either the size of the base type, or
+ * the size of a single pointer, whichever is greater (regardless of
+ * compiler)
+ * - A TCON_WRAP type may be included in another structure, and need
+ * not be the last element.
+ *
+ * A type of "void *" will allow tcon_check() to pass on any (pointer) type.
+ *
+ * Example:
+ * // Simply typesafe linked list.
+ * struct list_head {
+ * struct list_head *prev, *next;
+ * };
+ *
+ * typedef TCON_WRAP(struct list_head, char *canary) string_list_t;
+ *
+ * // More complex: mapping from one type to another.
+ * struct map {
+ * void *contents;
+ * };
+ *
+ * typedef TCON_WRAP(struct map, char *charp_canary; int int_canary)
+ * int_to_string_map_t;
+ */
+#define TCON_WRAP(basetype, decls) \
+ union { \
+ basetype _base; \
+ struct { \
+ decls; \
+ } *_tcon; \
+ }
+
+/**
+ * TCON_WRAP_INIT - an initializer for a variable declared with TCON_WRAP
+ * @...: Initializer for the base type (treated as variadic so commas
+ * can be included)
+ *
+ * Converts converts an initializer suitable for a base type into one
+ * suitable for that type wrapped with TCON_WRAP.
+ *
+ * Example:
+ * TCON_WRAP(int, char *canary) canaried_int = TCON_WRAP_INIT(17);
+ */
+#define TCON_WRAP_INIT(...) \
+ { ._base = __VA_ARGS__, }
+
+/**
+ * tcon_unwrap - Access the base type of a TCON_WRAP
+ * @ptr: pointer to an object declared with TCON_WRAP
+ *
+ * tcon_unwrap() returns a pointer to the base type of the TCON_WRAP()
+ * object pointer to by @ptr.
+ *
+ * Example:
+ * TCON_WRAP(int, char *canary) canaried_int;
+ *
+ * *tcon_unwrap(&canaried_int) = 17;
+ */
+#define tcon_unwrap(ptr) (&((ptr)->_base))
+
/**
* tcon_check - typecheck a typed container
* @x: the structure containing the TCON.
--- /dev/null
+#include <ccan/tcon/tcon.h>
+#include <stdlib.h>
+
+struct container {
+ void *p;
+};
+
+int main(int argc, char *argv[])
+{
+ TCON_WRAP(struct container,
+ int *tc1; char *tc2) icon;
+#ifdef FAIL
+#if !HAVE_TYPEOF
+#error We cannot detect type problems without HAVE_TYPEOF
+#endif
+ char *
+#else
+ int *
+#endif
+ x;
+
+ tcon_unwrap(&icon)->p = NULL;
+ x = tcon_cast(&icon, tc1, tcon_unwrap(&icon)->p);
+ return x != NULL ? 0 : 1;
+}
--- /dev/null
+#include <ccan/tcon/tcon.h>
+#include <stdlib.h>
+
+struct container {
+ void *p;
+};
+
+int main(int argc, char *argv[])
+{
+ TCON_WRAP(struct container, int *canary) icon;
+#ifdef FAIL
+ char *
+#else
+ int *
+#endif
+ x = NULL;
+
+ tcon_unwrap(tcon_check(&icon, canary, x))->p = x;
+ return 0;
+}
int main(int argc, char *argv[])
{
struct void_container vcon;
+ TCON_WRAP(struct container, void *canary) vconw;
tcon_check(&vcon, canary, NULL)->raw.p = NULL;
tcon_check(&vcon, canary, argv[0])->raw.p = NULL;
tcon_check(&vcon, canary, main)->raw.p = NULL;
+
+ tcon_unwrap(tcon_check(&vconw, canary, NULL))->p = NULL;
+ tcon_unwrap(tcon_check(&vconw, canary, argv[0]))->p = NULL;
+ tcon_unwrap(tcon_check(&vconw, canary, main))->p = NULL;
+
return 0;
}
#include <ccan/tcon/tcon.h>
+#include <ccan/build_assert/build_assert.h>
#include <stdlib.h>
struct container {
{
struct int_container icon;
struct charp_and_int_container cicon;
+ TCON_WRAP(struct container, int tc) iconw;
+ TCON_WRAP(struct container, int tc1; char *tc2) ciconw;
tcon_check(&icon, tc, 7)->raw.p = NULL;
tcon_check(&cicon, tc1, 7)->raw.p = argv[0];
tcon_check(&cicon, tc2, argv[0])->raw.p = argv[0];
+
+ tcon_unwrap(tcon_check(&iconw, tc, 7))->p = NULL;
+ tcon_unwrap(tcon_check(&ciconw, tc1, 7))->p = argv[0];
+ tcon_unwrap(tcon_check(&ciconw, tc2, argv[0]))->p = argv[0];
+
+ BUILD_ASSERT(sizeof(iconw) == sizeof(struct container));
+ BUILD_ASSERT(sizeof(ciconw) == sizeof(struct container));
+
return 0;
}
--- /dev/null
+#include <ccan/tcon/tcon.h>
+#include <ccan/tap/tap.h>
+#include <stdlib.h>
+
+typedef TCON_WRAP(int, char *canary) canaried_int;
+
+int main(int argc, char *argv[])
+{
+ canaried_int ci = TCON_WRAP_INIT(0);
+
+ plan_tests(2);
+
+ ok1(*tcon_unwrap(&ci) == 0);
+ *tcon_unwrap(&ci) = 17;
+ ok1(*tcon_unwrap(&ci) == 17);
+
+ return exit_status();
+}