extern const char *program_name;
+#define __ARRAY_SIZE_NOCHECK(ARRAY) (sizeof(ARRAY) / sizeof((ARRAY)[0]))
+#ifdef __GNUC__
+/* return 0 for array types, 1 otherwise */
+#define __ARRAY_CHECK(ARRAY) \
+ !__builtin_types_compatible_p(typeof(ARRAY), typeof(&ARRAY[0]))
+
+/* compile-time fail if not array */
+#define __ARRAY_FAIL(ARRAY) (sizeof(char[-2*!__ARRAY_CHECK(ARRAY)]))
+#define __ARRAY_SIZE(ARRAY) \
+ __builtin_choose_expr(__ARRAY_CHECK(ARRAY), \
+ __ARRAY_SIZE_NOCHECK(ARRAY), __ARRAY_FAIL(ARRAY))
+#else
+#define __ARRAY_SIZE(ARRAY) __ARRAY_SIZE_NOCHECK(ARRAY)
+#endif
+
/* Returns the number of elements in ARRAY. */
-#define ARRAY_SIZE(ARRAY) (sizeof ARRAY / sizeof *ARRAY)
+#define ARRAY_SIZE(ARRAY) __ARRAY_SIZE(ARRAY)
/* Returns X / Y, rounding up. X must be nonnegative to round correctly. */
#define DIV_ROUND_UP(X, Y) (((X) + ((Y) - 1)) / (Y))
* that that OBJECT points to, assigns the address of the outer object to
* OBJECT, which must be an lvalue.
*
- * Evaluates to 1. */
+ * Evaluates to (void) 0 as the result is not to be used. */
#define ASSIGN_CONTAINER(OBJECT, POINTER, MEMBER) \
- ((OBJECT) = OBJECT_CONTAINING(POINTER, OBJECT, MEMBER), 1)
+ ((OBJECT) = OBJECT_CONTAINING(POINTER, OBJECT, MEMBER), (void) 0)
+
+/* Given ATTR, and TYPE, cast the ATTR to TYPE by first casting ATTR to
+ * (void *). This is to suppress the alignment warning issued by clang. */
+#define ALIGNED_CAST(TYPE, ATTR) ((TYPE) (void *) (ATTR))
#ifdef __cplusplus
extern "C" {
set_program_name__(name, VERSION, __DATE__, __TIME__)
const char *get_subprogram_name(void);
-void set_subprogram_name(const char *name);
+void set_subprogram_name(const char *format, ...) PRINTF_FORMAT(1, 2);
const char *get_program_version(void);
void ovs_print_version(uint8_t min_ofp, uint8_t max_ofp);