AM_CPPFLAGS = -I$(top_srcdir)/src $(STUB_INCLUDES)
EXTRA_DIST = scripts/fix-gnulib.pl scripts/fix-ltdl.pl \
- scripts/gen-options.awk scripts/gen-strtab.awk \
- scripts/gen-tree.awk scripts/join.awk scripts/pe-subsys.awk \
- src/copysym.h src/help.h src/pack.h src/tap.h t/getopt/getopt.h \
- t/nls/gettext.h t/nls/mbswidth.h tests/data/gnulib.mk
+ scripts/bake-config.awk scripts/gen-options.awk \
+ scripts/gen-strtab.awk scripts/gen-tree.awk scripts/join.awk \
+ scripts/pe-subsys.awk src/copysym.h src/help.h src/pack.h \
+ src/tap.h t/getopt/getopt.h t/nls/gettext.h t/nls/mbswidth.h \
+ tests/data/gnulib.mk
check_LIBRARIES = t/libdummy.a t/libempty.a
--- /dev/null
+#!/bin/awk -f
+#
+# Copyright © 2023 Nick Bowler
+#
+# Usage: bake-config.awk config.h some_header.h
+#
+# Looks for #define and #undef lines in config.h to identify configuration
+# macros, then looks for uses of those macros in some_header.h and substitutes
+# them accordingly. The result is a header file that does not directly depend
+# on config.h, which can be installed normally.
+#
+# Presently, two kinds of substitions are made.
+#
+# - For a #define in config.h, any occurrence of that macro is substituted with
+# its replacement text.
+#
+# - For an #undef in config.h, any occurrence of that macro in an #if or #elif
+# directive is replaced with a literal 0.
+#
+# Almost no attempt is made to understand C syntax so the replacement is very
+# simplistic, and won't work well in many cases. Inspect the output!
+#
+# 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.
+
+BEGIN {
+ filenum = 0;
+ idclass = "[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0-9_]";
+}
+
+FNR == 1 { filenum++; }
+filenum == 1 && $1 == "#define" && $2 !~ /[(]/ {
+ key = $2;
+ $1 = $2 = "";
+ sub(/^ */, "", $0);
+ config[key] = $0 " /* " key " */";
+}
+
+# Autoconf comments out #undef lines in config.h, so we're looking for
+# /* #undef FOO */
+filenum == 1 && $2 == "#undef" {
+ undef[$3] = 0 " /* " $3 " */";
+}
+
+filenum == 2 {
+ CHANGED = 0;
+ tok = $0;
+
+ # Mark identifier boundaries to avoid replacing substrings. Use ` as
+ # it is not valid in C code (outside of string/character literals).
+ gsub(idclass"+", "`&`", tok);
+
+ # Replace all occurrences of configuration macros normally.
+ tok = do_replace(tok, config);
+
+ # Replace explicitly undefined configuration macros in #if/#elif
+ if ($0 ~ /^[ \t]*#[ \t]*(el)?if[ \t]/)
+ tok = do_replace(tok, undef);
+
+ if (CHANGED) {
+ gsub(/`/, "", tok);
+ print tok;
+ } else {
+ print $0;
+ }
+}
+
+function do_replace(s, config, result, t)
+{
+ while (match(s, "`" idclass "+`")) {
+ t = substr(s, RSTART+1, RLENGTH-2);
+ if (t in config) {
+ result = result substr(s, 1, RSTART - 1) config[t];
+ CHANGED = 1;
+ } else {
+ result = result substr(s, 1, RSTART + RLENGTH - 1);
+ }
+
+ s = substr(s, RSTART + RLENGTH);
+ }
+
+ return result s;
+}
AT_BANNER([Script tests])
+AT_SETUP([bake-config.awk])
+AT_KEYWORDS([bake-config awk script scripts])
+
+AT_DATA([cfg.h],
+[[#define hello world
+/* #undef HAVE_STUFF */
+#define HAVE_OTHER_STUFF 1
+/* #undef HAVE_CRAZY_STUFF */
+]])
+
+AT_DATA([lib.h],
+[[#if HAVE_STUFF
+# define foo hello__
+#elif HAVE_CRAZY_STUFF
+# define foo hello
+#elif HAVE_OTHER_STUFF
+# define foo __hello
+#endif
+]])
+
+AT_CHECK([$AWK -f "$srcdir/scripts/bake-config.awk" cfg.h lib.h], [0],
+[[#if 0 /* HAVE_STUFF */
+# define foo hello__
+#elif 0 /* HAVE_CRAZY_STUFF */
+# define foo world /* hello */
+#elif 1 /* HAVE_OTHER_STUFF */
+# define foo __hello
+#endif
+]])
+
+AT_CLEANUP
+
m4_define([TEST_GEN_OPTIONS],
[AT_KEYWORDS([gen-options awk script scripts])dnl
AT_DATA([m4_default([$2], [options.def])], [$1])