diff options
Diffstat (limited to 'include/libHX')
-rw-r--r-- | include/libHX/defs.h | 48 | ||||
-rw-r--r-- | include/libHX/list.h | 18 | ||||
-rw-r--r-- | include/libHX/option.h | 2 |
3 files changed, 42 insertions, 26 deletions
diff --git a/include/libHX/defs.h b/include/libHX/defs.h index bb03f40..9ecdd32 100644 --- a/include/libHX/defs.h +++ b/include/libHX/defs.h @@ -22,6 +22,9 @@ # define containerof(var, type, member) reinterpret_cast<type *>( \ reinterpret_cast<char *>(var) - offsetof(type, member)) # endif +# ifndef static_cast +# define static_cast(T, x) static_cast<T>(x) +# endif template<typename new_type> static __inline__ new_type signed_cast(const char *expr) @@ -91,24 +94,33 @@ static __inline__ new_type signed_cast(unsigned char *expr) ((struct { type x; }){(expr)}.x) # endif # if defined(__GNUC__) && !defined(__clang__) && !defined(const_cast1) -# define __const_cast_strip1(expr) \ - __typeof__(*(union { int z; __typeof__(expr) x; }){0}.x) -# define __const_cast_strip2(expr) \ - __typeof__(**(union { int z; __typeof__(expr) x; }){0}.x) -# define __const_cast_strip3(expr) \ - __typeof__(***(union { int z; __typeof__(expr) x; }){0}.x) -# define const_cast1(new_type, expr) ({ \ - BUILD_BUG_ON(!__builtin_types_compatible_p(__const_cast_strip1(expr), __const_cast_strip1(new_type))); \ - (new_type)(expr); \ - }) -# define const_cast2(new_type, expr) ({ \ - BUILD_BUG_ON(!__builtin_types_compatible_p(__const_cast_strip2(expr), __const_cast_strip2(new_type))); \ - (new_type)(expr); \ - }) -# define const_cast3(new_type, expr) ({ \ - BUILD_BUG_ON(!__builtin_types_compatible_p(__const_cast_strip3(expr), __const_cast_strip3(new_type))); \ - (new_type)(expr); \ - }) + /* + * The idea starts with (in abstract notation) + * typeof deref typeof expr + * To deref something, we need an object, which we can get by + * creating a temporary aggregate, such as a union, of which + * the member is accessed and dereferenced. + * *(union { __typeof__(expr) x; }){init}.x + * union has two nice properties: + * - with an additional dummy member, we do not have to + * initialize x according to its type, which, if expr is + * an array type, may want extra braces. + * - and with that dummy member, we also avoid the ugly + * "literal 0 is implicitly convertible to a pointer". + * Unfortunately, this all requires C99 compound initializers. + * That's ok - gcc and clang only treat it as a warning even + * under strict C89 - and if you still force strict C89 on + * yourself, you have a lot to answer for either way. + */ +# define __const_cast_strip(ptrs, expr) \ + __typeof__(ptrs(union { int z; __typeof__(expr) x; }){0}.x) +# define __const_cast_p(ptrs, new_type, expr) ((new_type)( \ + (expr) + \ + BUILD_BUG_ON_EXPR(!__builtin_types_compatible_p(__const_cast_strip(ptrs, expr), __const_cast_strip(ptrs, new_type))) \ + )) +# define const_cast1(new_type, expr) __const_cast_p(*, new_type, expr) +# define const_cast2(new_type, expr) __const_cast_p(**, new_type, expr) +# define const_cast3(new_type, expr) __const_cast_p(***, new_type, expr) # endif # ifndef signed_cast # define signed_cast(type, expr) ((type)(expr)) diff --git a/include/libHX/list.h b/include/libHX/list.h index a18b17e..3146c22 100644 --- a/include/libHX/list.h +++ b/include/libHX/list.h @@ -63,35 +63,37 @@ static __inline__ bool HXlist_empty(const struct HXlist_head *head) } #define HXlist_for_each(pos, head) \ - for ((pos) = (head)->next; (pos) != (void *)(head); \ + for ((pos) = (head)->next; (pos) != static_cast(void *, (head)); \ (pos) = (pos)->next) #define HXlist_for_each_rev(pos, head) \ - for ((pos) = (head)->prev; (pos) != (void *)(head); \ + for ((pos) = (head)->prev; (pos) != static_cast(void *, (head)); \ (pos) = (pos)->prev) #define HXlist_for_each_safe(pos, n, head) \ - for ((pos) = (head)->next, (n) = (pos)->next; (pos) != (void *)(head); \ + for ((pos) = (head)->next, (n) = (pos)->next; \ + (pos) != static_cast(void *, (head)); \ (pos) = (n), (n) = (pos)->next) #define HXlist_for_each_rev_safe(pos, n, head) \ - for ((pos) = (head)->prev, (n) = (pos)->prev; (pos) != (void *)(head); \ + for ((pos) = (head)->prev, (n) = (pos)->prev; \ + (pos) != static_cast(void *, (head)); \ (pos) = (n), (n) = (pos)->prev) #define HXlist_for_each_entry(pos, head, member) \ for ((pos) = HXlist_entry((head)->next, __typeof__(*(pos)), member); \ - &(pos)->member != (void *)(head); \ + &(pos)->member != static_cast(void *, (head)); \ (pos) = HXlist_entry((pos)->member.next, __typeof__(*(pos)), member)) #define HXlist_for_each_entry_rev(pos, head, member) \ for ((pos) = HXlist_entry((head)->prev, __typeof__(*(pos)), member); \ - &(pos)->member != (void *)(head); \ + &(pos)->member != static_cast(void *, (head)); \ (pos) = HXlist_entry((pos)->member.prev, __typeof__(*(pos)), member)) #define HXlist_for_each_entry_safe(pos, n, head, member) \ for ((pos) = HXlist_entry((head)->next, __typeof__(*(pos)), member), \ (n) = HXlist_entry((pos)->member.next, __typeof__(*(pos)), member); \ - &(pos)->member != (void *)(head); \ + &(pos)->member != static_cast(void *, (head)); \ (pos) = (n), (n) = HXlist_entry((n)->member.next, __typeof__(*(n)), \ member)) @@ -154,7 +156,7 @@ static __inline__ struct HXlist_head * __HXclist_shift(struct HXclist_head *head) { struct HXlist_head *p; - if ((const void *)head == head->list.next) + if (static_cast(const void *, head) == head->list.next) return NULL; p = head->list.next; HXlist_del(p); diff --git a/include/libHX/option.h b/include/libHX/option.h index 3b8187f..d60c3f1 100644 --- a/include/libHX/option.h +++ b/include/libHX/option.h @@ -160,12 +160,14 @@ enum { * %HXOPT_ERR_UNKN: unknown option was encountered * %HXOPT_ERR_VOID: long option takes no value * %HXOPT_ERR_MIS: option requires a value argument + * %HXOPT_ERR_AMBIG: long option abbreviation was ambiguous */ enum { HXOPT_ERR_SUCCESS = 0, HXOPT_ERR_UNKN, HXOPT_ERR_VOID, HXOPT_ERR_MIS, + HXOPT_ERR_AMBIG, }; /** |