--- /dev/null
+/*
+ * Copyright © 2023 Nick Bowler
+ *
+ * License WTFPL2: Do What The Fuck You Want To Public License, version 2.
+ * This is free software: you are free to do what the fuck you want to.
+ * There is NO WARRANTY, to the extent permitted by law.
+ */
+
+#ifndef DX_XTRA_H_
+#define DX_XTRA_H_
+
+#define XTRA_PASTE(a, b) a ## b
+#define XTRA_PASTE2(a, b) XTRA_PASTE(a, b)
+
+#define XTRA_ARRAYSIZE(a) (sizeof (a) / sizeof (a)[0])
+
+/*
+ * This macro may be used to simplify construction of a 'struct option'
+ * array from the packed format produced by gen-options.awk.
+ *
+ * Expanding this in a function will
+ *
+ * (1) declare a constant array with static storage duration that
+ * contains the packed representation, and
+ * (2) declare an array of struct option of suitable length, with
+ * the given name, and
+ * (3) emit code to fill the struct option array from the packed
+ * representation.
+ *
+ * The uint_leastXX_t typedefs must be in scope in order to use this macro.
+ */
+#define XTRA_PACKED_LOPTS(name) \
+ static const XTRA_PASTE2(uint_least, XTRA_PASTE2(LOPT_PACK_BITS2, _t)) \
+ name##_packed[] = { LOPTS_PACKED_INITIALIZER }; \
+ struct option name[XTRA_ARRAYSIZE(name##_packed) + 1] = {0}; \
+ do { \
+ unsigned i; \
+ for (i = 0; i < XTRA_ARRAYSIZE(name##_packed); i++) \
+ LOPT_UNPACK(name[i], name##_packed[i]); \
+ } while (0)
+
+#endif