Ok, In 15 years of writing C code I have never seen code like this, and I don't know how it works. It centers around some C99 code where somehow multiple lines of code get resolved to an integer value. It comes from libplist, specifically here. Ok, it starts on line 394, where a uint64_t member of a struct, is assigned the result of a macro UINT_TO_HOST
data->intval = UINT_TO_HOST(&data->intval, size);
UINT_TO_HOST is a macro that takes a pointer to an unsigned integer, and the size in btes of the integer. the macro defines a union to a set of pointers of different uint sizes, then sets the address to the uint pointer passed to the macro. It then proceeds to align the uint in memory, in order to properly byte swap it with another macro. UINT_TO_HOST is defined on line 172
#define UINT_TO_HOST(x, n) \
({ \
union plist_uint_ptr __up; \
__up.src = x; \
(n == 8 ? be64toh( get_unaligned(__up.u64ptr) ) : \
(n == 4 ? be32toh( get_unaligned(__up.u32ptr) ) : \
(n == 3 ? uint24_from_be( __up ) : \
(n == 2 ? be16toh( get_unaligned(__up.u16ptr) ) : \
*__up.u8ptr )))); \
})
get unaligned does a trick with a struct and the gcc attribute packed, which returns the pointer value aligned in memory based on the type.
#define get_unaligned(ptr) \
({ \
struct __attribute__((packed)) { \
typeof(*(ptr)) __v; \
} *__p = (void *) (ptr); \
__p->__v; \
})
be64toh simply does some in place masking and shifting.
#define be64toh(x) ((((x) & 0xFF00000000000000ull) >> 56) \
| (((x) & 0x00FF000000000000ull) >> 40) \
| (((x) & 0x0000FF0000000000ull) >> 24) \
| (((x) & 0x000000FF00000000ull) >> 8) \
| (((x) & 0x00000000FF000000ull) << 8) \
| (((x) & 0x0000000000FF0000ull) << 24) \
| (((x) & 0x000000000000FF00ull) << 40) \
| (((x) & 0x00000000000000FFull) << 56))
The question is how does UINT_TO_HOST actually return a value into data->intval, since UINT_TO_HOST basically gets resolved to 3 lines of code inside a set of curly braces {}. The same thing appears to happen inside of get_unaligned, where presumably the last statement
__p->_v;
Is what gets returned. What is this feature called, and can anyone point to some documentation on this 'feature'?