+# Emit the packed initializer macros. This is used as an array initializer
+# that encodes the following information:
+#
+# - short option character offset
+# - arg value (0, 1 or 2), and
+# - long option string offset
+#
+# as a single integer value for each option, in as few bits as practical.
+#
+# 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)
+{
+ print "\n#define LOPT_PACK_BITS (LOPT_SC_BITS + LOPT_HA_BITS + LOPT_LS_BITS)";
+
+ # determine number of bits to encode offsets in SOPT_STRING
+ max = length(sopt_string);
+ accum = 0;
+ for (i = 1; i <= max; i *= 2) {
+ accum++;
+ }
+ print "#define LOPT_SC_BITS " accum;
+
+ # determine number of bits to encode has_arg values
+ max = 0;
+ for (i in optionspec) {
+ tmp = optionspec[i]; sub(/,.*/, "", tmp);
+ if (tmp > max)
+ max = tmp;
+ }
+ print "#define LOPT_HA_BITS " (max > 1 ? 2 : max > 0 ? 1 : 0);
+
+ # determine number of bits to encode offsets in lopt_strings
+ max = 0;
+ for (i in offsets) {
+ if (offsets[i] > max)
+ max = offsets[i];
+ }
+
+ accum = 0;
+ for (i = 1; i <= max; i *= 2) {
+ accum++;
+ }
+ print "#define LOPT_LS_BITS " accum;
+
+ # Now emit the packed initializer macro
+ print "\n#define LOPTS_PACKED_INITIALIZER \\";
+ accum = "";
+ for (i = 0; i < count; i++) {
+ if (accum)
+ print "\t" accum ", \\";
+
+ tmp = options[i];
+ accum = "("offsets[tmp] "ul" "<<LOPT_HA_BITS)";
+ max = tmp = optionspec[tmp];
+ sub(/,.*/, "", max)
+ accum = "((" accum "|" max ")<<LOPT_SC_BITS)";
+
+ sub(/.*[, ]/, "", tmp);
+ if (tmp ~ /^[']/) {
+ tmp = index(sopt_string, substr(tmp, 2, 1)) - 1;
+ } else {
+ tmp = length(sopt_string);
+ }
+ accum = accum "|" tmp;
+ }
+
+ if (accum)
+ print "\t" accum;
+
+ # Finally, the unpack helper macros
+ tmp = "(x) & ((1ul<<LOPT_SC_BITS)-1)";
+ print "\n#define LOPT_UNPACK_VAL(x) \\"
+ print "\t( SOPT_STRING[" tmp "] \\";
+ print "\t? SOPT_STRING[" tmp "] \\";
+ print "\t: 1u + UCHAR_MAX + ((x)>>(LOPT_SC_BITS+LOPT_HA_BITS)))";
+
+ print "\n#define LOPT_UNPACK_ARG(x) \\";
+ print "\t(((x)>>LOPT_SC_BITS)&((1ul<<LOPT_HA_BITS)-1))";
+
+ print "\n#define LOPT_UNPACK_NAME(x) \\"
+ print "\t(lopt_strings+((x)>>(LOPT_SC_BITS+LOPT_HA_BITS)))";
+
+ print "\n#define LOPT_UNPACK(opt, x) do { \\";
+ print "\t(opt).name = LOPT_UNPACK_NAME(x); \\"
+ print "\t(opt).has_arg = LOPT_UNPACK_ARG(x); \\"
+ print "\t(opt).val = LOPT_UNPACK_VAL(x); \\"
+ print "} while (0)";
+}
+