X-Git-Url: https://git.draconx.ca/gitweb/dxcommon.git/blobdiff_plain/262d3eaea39294df3f6172b28213e927e2f3b424..d4f7fab64222a7d3ce15e86c5c7b32f7cdd3ce93:/scripts/bake-config.awk diff --git a/scripts/bake-config.awk b/scripts/bake-config.awk new file mode 100755 index 0000000..56e2151 --- /dev/null +++ b/scripts/bake-config.awk @@ -0,0 +1,84 @@ +#!/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; +}