2003-01-16 Roland McGrath <roland@redhat.com>
[kopensolaris-gnu/glibc.git] / scripts / merge-abilist.awk
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
14
15 /^[^| ]/ {
16   if (NF < 2 && config == "") {
17     print "BAD LINE:", $0 > "/dev/stderr";
18     exit 2;
19   }
20
21   if (NF < 2) {
22     current = $1 ":" config;
23   }
24   else {
25     # Filter out the old stanzas from the config we are merging in.
26     # That way, if a set disappears from the .symlist file for this
27     # config, the old stanza doesn't stay in the merged output tagged
28     # for this config.  (Disappearing sets might happen during development,
29     # and between releases could happen on a soname change).
30     nc = 0;
31     for (i = 2; i <= NF; ++i)
32       if ($i != config)
33         c[nc++] = $i;
34     if (nc == 0)
35       current = "";
36     else {
37       current = $1 ":" c[0];
38       for (i = 1; i < nc; ++i)
39         current = current "," $1 ":" c[i];
40     }
41   }
42
43   next;
44 }
45
46 /^\| / {
47   if (NF < 3) {
48     print "BAD LINE:", $0 > "/dev/stderr";
49     exit 2;
50   }
51
52   nc = 0;
53   for (i = 3; i <= NF; ++i)
54     if ($i != config)
55       c[nc++] = $i;
56   for (i = 0; i < nc; ++i)
57     current = current "," $2 ":" c[i];
58
59   next;
60 }
61
62 {
63   if (current == "") next;
64
65   ns = split(seen[$0], s, ",");
66   nc = split(current, c, ",");
67   for (i = 1; i <= nc; ++i) {
68     # Sorted insert.
69     for (j = 1; j <= ns; ++j) {
70       if (c[i] < s[j]) {
71         for (k = ns; k >= j; --k)
72           s[k + 1] = s[k];
73         s[j] = c[i];
74         ++ns;
75         break;
76       }
77     }
78     if (j >= ns)
79       s[++ns] = c[i];
80   }
81
82   seen[$0] = s[1];
83   for (i = 2; i <= ns; ++i)
84     seen[$0] = seen[$0] "," s[i];
85
86   next;
87 }
88
89 END {
90   for (line in seen) {
91     if (seen[line] in stanzas)
92       stanzas[seen[line]] = stanzas[seen[line]] "\n" line;
93     else
94       stanzas[seen[line]] = line;
95   }
96
97   ns = split("", s);
98   for (configs in stanzas) {
99     # Sorted insert.
100     for (j = 1; j <= ns; ++j)
101       if (configs < s[j]) {
102         for (k = ns; k >= j; --k)
103           s[k + 1] = s[k];
104         s[j] = configs;
105         ++ns;
106         break;
107       }
108     if (j >= ns)
109       s[++ns] = configs;
110   }
111
112   # S[1..NS] is now a sorted list of stanza identifiers.
113   # STANZAS[ID] contains the lines for that stanza.
114   # All we have to do is pretty-print the stanza ID,
115   # and then print the sorted list.
116
117   for (i = 1; i <= ns; ++i) {
118     # S[I] is a sorted, comma-separated list of SET:CONFIG pairs.
119     # All we have to do is pretty-print them.
120     nc = split(s[i], c, ",");
121     lastvers = "";
122     for (j = 1; j <= nc; ++j) {
123       split(c[j], temp, ":");
124       version = temp[1];
125       conf = temp[2];
126       if (version != lastvers)
127         printf "%s%s", (lastvers != "" ? "\n| " : ""), version;
128       printf " %s", conf;
129       lastvers = version;
130     }
131     print "";
132     outpipe = "sort";
133     print stanzas[s[i]] | outpipe;
134     close(outpipe);
135   }
136 }