From: Nick Bowler Date: Sun, 8 Jan 2023 05:32:22 +0000 (-0500) Subject: Add a helper macro to use the new gen-options packed format. X-Git-Url: https://git.draconx.ca/gitweb/dxcommon.git/commitdiff_plain/e599119f0492b01f1f21a8cce8d695c314dab3b1 Add a helper macro to use the new gen-options packed format. Abstract some of the boilerplate into a new macro. The gen-options.awk is augmented to also give the packed format width as a power of two (8/16/32/64). Other than that we can use all the existing definitions to make this common code in a new "xtra.h" header file. --- diff --git a/scripts/gen-options.awk b/scripts/gen-options.awk index a93c47c..80adcb4 100755 --- a/scripts/gen-options.awk +++ b/scripts/gen-options.awk @@ -82,7 +82,9 @@ # # * the object-like macro LOPT_PACK_BITS expands to an integer constant # expression, suitable for use in #if directives, that specifies the -# minimum number of bits required by the encoding. +# minimum number of bits required by the encoding. LOPT_PACK_BITS2 +# is the same, but rounded up to the next power of two greater than +# or equal to 8. # # * the object-like macro LOPTS_PACKED_INITIALIZER expands to a # comma-separated sequence of integer constant expressions, suitable @@ -358,17 +360,18 @@ END { # Currently, this only works if none of the options use action specifications # (as these would require encoding user-specified pointer expressions and # arbitrary int values). -function output_packed_macros(i, tmp, accum, max) +function output_packed_macros(i, tmp, accum, max, totalbits) { - print "\n#define LOPT_PACK_BITS (LOPT_SC_BITS + LOPT_HA_BITS + LOPT_LS_BITS)"; + print ""; # determine number of bits to encode offsets in SOPT_STRING max = length(sopt_string); - accum = 0; + totalbits = accum = 0; for (i = 1; i <= max; i *= 2) { accum++; } print "#define LOPT_SC_BITS " accum; + totalbits += accum; # determine number of bits to encode has_arg values max = 0; @@ -377,7 +380,9 @@ function output_packed_macros(i, tmp, accum, max) if (tmp > max) max = tmp; } - print "#define LOPT_HA_BITS " (max > 1 ? 2 : max > 0 ? 1 : 0); + accum = (max > 1 ? 2 : max > 0 ? 1 : 0); + print "#define LOPT_HA_BITS " accum; + totalbits += accum; # determine number of bits to encode offsets in lopt_strings max = 0; @@ -391,6 +396,12 @@ function output_packed_macros(i, tmp, accum, max) accum++; } print "#define LOPT_LS_BITS " accum; + totalbits += accum; + + print "#define LOPT_PACK_BITS " totalbits; + for (i = 8; i < totalbits; i *= 2) + ; + print "#define LOPT_PACK_BITS2 " i; # Now emit the packed initializer macro print "\n#define LOPTS_PACKED_INITIALIZER \\"; diff --git a/src/xtra.h b/src/xtra.h new file mode 100644 index 0000000..4de8df5 --- /dev/null +++ b/src/xtra.h @@ -0,0 +1,42 @@ +/* + * 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