#!/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; }