]> git.draconx.ca Git - dxcommon.git/blob - scripts/bake-config.awk
DX_C_ALIGNAS: Work around bash-5 parsing bug.
[dxcommon.git] / scripts / bake-config.awk
1 #!/bin/awk -f
2 #
3 # Copyright © 2023 Nick Bowler
4 #
5 # Usage: bake-config.awk config.h some_header.h
6 #
7 # Looks for #define and #undef lines in config.h to identify configuration
8 # macros, then looks for uses of those macros in some_header.h and substitutes
9 # them accordingly.  The result is a header file that does not directly depend
10 # on config.h, which can be installed normally.
11 #
12 # Presently, two kinds of substitions are made.
13 #
14 # - For a #define in config.h, any occurrence of that macro is substituted with
15 #   its replacement text.
16 #
17 # - For an #undef in config.h, any occurrence of that macro in an #if or #elif
18 #   directive is replaced with a literal 0.
19 #
20 # Almost no attempt is made to understand C syntax so the replacement is very
21 # simplistic, and won't work well in many cases.  Inspect the output!
22 #
23 # License WTFPL2: Do What The Fuck You Want To Public License, version 2.
24 # This is free software: you are free to do what the fuck you want to.
25 # There is NO WARRANTY, to the extent permitted by law.
26
27 BEGIN {
28   filenum = 0;
29   idclass = "[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0-9_]";
30 }
31
32 FNR == 1 { filenum++; }
33 filenum == 1 && $1 == "#define" && $2 !~ /[(]/ {
34   key = $2;
35   $1 = $2 = "";
36   sub(/^ */, "", $0);
37   config[key] = $0 " /* " key " */";
38 }
39
40 # Autoconf comments out #undef lines in config.h, so we're looking for
41 #    /* #undef FOO */
42 filenum == 1 && $2 == "#undef" {
43   undef[$3] = 0 " /* " $3 " */";
44 }
45
46 filenum == 2 {
47   CHANGED = 0;
48   tok = $0;
49
50   # Mark identifier boundaries to avoid replacing substrings.  Use ` as
51   # it is not valid in C code (outside of string/character literals).
52   gsub(idclass"+", "`&`", tok);
53
54   # Replace all occurrences of configuration macros normally.
55   tok = do_replace(tok, config);
56
57   # Replace explicitly undefined configuration macros in #if/#elif
58   if ($0 ~ /^[ \t]*#[ \t]*(el)?if[ \t]/)
59     tok = do_replace(tok, undef);
60
61   if (CHANGED) {
62     gsub(/`/, "", tok);
63     print tok;
64   } else {
65     print $0;
66   }
67 }
68
69 function do_replace(s, config, result, t)
70 {
71   while (match(s, "`" idclass "+`")) {
72     t = substr(s, RSTART+1, RLENGTH-2);
73     if (t in config) {
74       result = result substr(s, 1, RSTART - 1) config[t];
75       CHANGED = 1;
76     } else {
77       result = result substr(s, 1, RSTART + RLENGTH - 1);
78     }
79
80     s = substr(s, RSTART + RLENGTH);
81   }
82
83   return result s;
84 }