[BZ #4344]
[glibc/history.git] / scripts / merge-abilist.awk
blob91999d922174709f029cbd759a580ed84fe1dbb2
1 # awk script to merge a config-specific .symlist file with others.
2 # The input files should be existing .abilist files, and a .symlist
3 # file. This must be run with awk -v config=REGEXP to specify a
4 # regexp matching configuration tuples for which the .symlist input
5 # defines an ABI. The result merges all duplicate occurrences of any
6 # symbol into a stanza listing the regexps matching configurations
7 # that contain it and giving associated versions.
8 # The merged file contains stanzas in the form:
9 # GLIBC_x.y regexp...
10 # | GLIBC_x.y.z regexp...
11 # | GLIBC_m.n regexp...
12 # function F
13 # variable D 0x4
15 BEGIN { current = "UNSET" }
17 /^[^| ]/ {
18 if (NF < 2 && config == "") {
19 print FILENAME ":" FNR ": BAD SET LINE:", $0 > "/dev/stderr";
20 exit 2;
23 if (NF < 2) {
24 current = $1 ":" config;
26 else {
27 # Filter out the old stanzas from the config we are merging in.
28 # That way, if a set disappears from the .symlist file for this
29 # config, the old stanza doesn't stay in the merged output tagged
30 # for this config. (Disappearing sets might happen during development,
31 # and between releases could happen on a soname change).
32 nc = 0;
33 for (i = 2; i <= NF; ++i)
34 if ($i != config)
35 c[nc++] = $i;
36 if (nc == 0)
37 current = "";
38 else {
39 current = $1 ":" c[0];
40 for (i = 1; i < nc; ++i)
41 current = current "," $1 ":" c[i];
45 next;
48 /^\| / {
49 if (NF < 3 || current == "UNSET") {
50 print FILENAME ":" FNR ": BAD | LINE:", $0 > "/dev/stderr";
51 exit 2;
54 nc = 0;
55 for (i = 3; i <= NF; ++i)
56 if ($i != config)
57 c[nc++] = $i;
58 for (i = 0; i < nc; ++i)
59 current = current "," $2 ":" c[i];
61 next;
65 if (current == "") next;
66 if (current == "UNSET") {
67 print FILENAME ":" FNR ": IGNORED LINE:", $0 > "/dev/stderr";
68 next;
71 ns = split(seen[$0], s, ",");
72 nc = split(current, c, ",");
73 for (i = 1; i <= nc; ++i) {
74 if (c[i] == "")
75 continue;
76 # Sorted insert.
77 for (j = 1; j <= ns; ++j) {
78 if (c[i] == s[j])
79 break;
80 if (c[i] < s[j]) {
81 for (k = ns; k >= j; --k)
82 s[k + 1] = s[k];
83 s[j] = c[i];
84 ++ns;
85 break;
88 if (j > ns)
89 s[++ns] = c[i];
92 seen[$0] = s[1];
93 for (i = 2; i <= ns; ++i)
94 seen[$0] = seen[$0] "," s[i];
96 next;
99 END {
100 for (line in seen) {
101 if (seen[line] in stanzas)
102 stanzas[seen[line]] = stanzas[seen[line]] "\n" line;
103 else
104 stanzas[seen[line]] = line;
107 ns = split("", s);
108 for (configs in stanzas) {
109 # Sorted insert.
110 for (j = 1; j <= ns; ++j) {
111 if (configs == s[j])
112 break;
113 if (configs < s[j]) {
114 for (k = ns; k >= j; --k)
115 s[k + 1] = s[k];
116 s[j] = configs;
117 ++ns;
118 break;
121 if (j > ns)
122 s[++ns] = configs;
125 # S[1..NS] is now a sorted list of stanza identifiers.
126 # STANZAS[ID] contains the lines for that stanza.
127 # All we have to do is pretty-print the stanza ID,
128 # and then print the sorted list.
130 for (i = 1; i <= ns; ++i) {
131 # S[I] is a sorted, comma-separated list of SET:CONFIG pairs.
132 # All we have to do is pretty-print them.
133 nc = split(s[i], c, ",");
134 lastvers = lastconf = "";
135 for (j = 1; j <= nc; ++j) {
136 split(c[j], temp, ":");
137 version = temp[1];
138 conf = temp[2];
139 if (version != lastvers)
140 printf "%s%s", (lastvers != "" ? "\n| " : ""), version;
141 # Hack: if CONF is foo.*/bar and LASTCONF was foo.*,
142 # then we can omit the foo.*/bar since foo.* matches already.
143 # Note we don't update LASTCONF, so foo.*/baz next time will match too.
144 else if ((slash = index(conf, ".*/")) > 0 && \
145 substr(conf, 1, slash + 2 - 1) == lastconf)
146 continue;
147 printf " %s", conf;
148 lastvers = version;
149 lastconf = conf;
151 print "";
152 outpipe = "sort";
153 print stanzas[s[i]] | outpipe;
154 close(outpipe);