locales: Rename zh_han* to zh_Han* (capitalize)
[dragonfly.git] / share / mk / version_gen.awk
1 #
2 # Copyright (C) 2006 Daniel M. Eischen.  All rights reserved.
3
4 # Redistribution and use in source and binary forms, with or without
5 # modification, are permitted provided that the following conditions
6 # are met:
7 # 1. Redistributions of source code must retain the above copyright
8 #    notice, this list of conditions and the following disclaimer.
9 # 2. Redistributions in binary form must reproduce the above copyright
10 #    notice, this list of conditions and the following disclaimer in the
11 #    documentation and/or other materials provided with the distribution.
12
13 # THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 # ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
17 # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 # SUCH DAMAGE.
24 #
25 # $FreeBSD$
26 #
27
28 #
29 # Make a list of all the library versions listed in the master file.
30 #
31 #   versions[] - array indexed by version name, contains number
32 #                of symbols (+ 1) found for each version.
33 #   successors[] - array index by version name, contains successor
34 #                  version name.
35 #   symbols[][] - array index by [version name, symbol index], contains
36 #                 names of symbols defined for each version.
37 #   names[] - array index is symbol name and value is its first version seen,
38 #             used to check for duplicate symbols and warn about them.
39 #
40 BEGIN {
41         brackets = 0;
42         errors = warns = 0;
43         version_count = 0;
44         current_version = "";
45         stderr = "/dev/stderr";
46         while (getline < vfile) {
47                 # Strip comments.
48                 sub("#.*$", "", $0);
49
50                 # Strip leading and trailing whitespace.
51                 sub("^[ \t]+", "", $0);
52                 sub("[ \t]+$", "", $0);
53
54                 if (/^[a-zA-Z0-9._]+[ \t]*{$/) {
55                         # Strip brace.
56                         sub("{", "", $1);
57                         brackets++;
58                         symver = $1;
59                         versions[symver] = 1;
60                         successors[symver] = "";
61                         generated[symver] = 0;
62                         version_count++;
63                 }
64                 else if (/^}[ \t]*[a-zA-Z0-9._]+[ \t]*;$/) {
65                         v = $1 != "}" ? $1 : $2;
66                         # Strip brace.
67                         sub("}", "", v);
68                         # Strip semicolon.
69                         sub(";", "", v);
70                         if (symver == "") {
71                                 printf("File %s: Unmatched bracket.\n",
72                                 vfile) > stderr;
73                                 errors++;
74                         }
75                         else if (versions[v] != 1) {
76                                 printf("File %s: `%s' has unknown " \
77                                     "successor `%s'.\n",
78                                     vfile, symver, v) > stderr;
79                                 errors++;
80                         }
81                         else
82                                 successors[symver] = v;
83                         brackets--;
84                 }
85                 else if (/^}[ \t]*;$/) {
86                         if (symver == "") {
87                                 printf("File %s: Unmatched bracket.\n",
88                                     vfile) > stderr;
89                                 errors++;
90                         }
91                         # No successor
92                         brackets--;
93                 }
94                 else if (/^}$/) {
95                         printf("File %s: Missing final semicolon.\n",
96                             vfile) > stderr;
97                         errors++;
98                 }
99                 else if (/^$/)
100                         ;  # Ignore blank lines.
101                 else {
102                         printf("File %s: Unknown directive: `%s'.\n",
103                             vfile, $0) > stderr;
104                         errors++;
105                 }
106         }
107         brackets = 0;
108 }
109
110 {
111         # Set meaningful filename for diagnostics.
112         filename = FILENAME != "" ? FILENAME : "<stdin>";
113
114         # Delete comments, preceding and trailing whitespace, then
115         # consume blank lines.
116         sub("#.*$", "", $0);
117         sub("^[ \t]+", "", $0);
118         sub("[ \t]+$", "", $0);
119         if ($0 == "")
120                 next;
121 }
122
123 /^[a-zA-Z0-9._]+[ \t]*{$/ {
124         # Strip bracket from version name.
125         sub("{", "", $1);
126         if (current_version != "") {
127                 printf("File %s, line %d: Illegal nesting detected.\n",
128                     filename, FNR) > stderr;
129                 errors++;
130         }
131         else if (versions[$1] == 0) {
132                 printf("File %s, line %d: Undefined " \
133                     "library version `%s'.\n", filename, FNR, $1) > stderr;
134                 errors++;
135                 # Remove this entry from the versions.
136                 delete versions[$1];
137         }
138         else
139                 current_version = $1;
140         brackets++;
141         next;
142 }
143
144 /^[a-zA-Z0-9._]+[ \t]*;$/ {
145         # Strip semicolon.
146         sub(";", "", $1);
147         if (current_version != "") {
148                 count = versions[current_version];
149                 versions[current_version]++;
150                 symbols[current_version, count] = $1;
151                 if ($1 in names && names[$1] != current_version) {
152                         #
153                         # A graver case when a dup symbol appears under
154                         # different versions in the map.  That can result
155                         # in subtle problems with the library later.
156                         #
157                         printf("File %s, line %d: Duplicated symbol `%s' " \
158                             "in version `%s', first seen in `%s'. " \
159                             "Did you forget to move it to ObsoleteVersions?\n",
160                             filename, FNR, $1,
161                             current_version, names[$1]) > stderr;
162                         errors++;
163                 }
164                 else if (names[$1] == current_version) {
165                         #
166                         # A harmless case: a dup symbol with the same version.
167                         #
168                         printf("File %s, line %d: warning: " \
169                             "Duplicated symbol `%s' in version `%s'.\n",
170                             filename, FNR, $1, current_version) > stderr;
171                         warns++;
172                 }
173                 else
174                         names[$1] = current_version;
175         }
176         else {
177                 printf("File %s, line %d: Symbol `%s' outside version scope.\n",
178                     filename, FNR, $1) > stderr;
179                 errors++;
180         }
181         next;
182 }
183
184 /^}[ \t]*;$/ {
185         brackets--;
186         if (brackets < 0) {
187                 printf("File %s, line %d: Unmatched bracket.\n",
188                     filename, FNR, $1) > stderr;
189                 errors++;
190                 brackets = 0;   # Reset
191         }
192         current_version = "";
193         next;
194 }
195
196
197 {
198         printf("File %s, line %d: Unknown directive: `%s'.\n",
199             filename, FNR, $0) > stderr;
200         errors++;
201 }
202
203 function print_version(v)
204 {
205         # This function is recursive, so return if this version
206         # has already been printed.  Otherwise, if there is an
207         # ancestral version, recursively print its symbols before
208         # printing the symbols for this version.
209         #
210         if (generated[v] == 1)
211                 return;
212         if (successors[v] != "")
213                 print_version(successors[v]);
214
215         printf("%s {\n", v);
216
217         # The version count is always one more that actual,
218         # so the loop ranges from 1 to n-1.
219         #
220         for (i = 1; i < versions[v]; i++) {
221                 if (i == 1)
222                         printf("global:\n");
223                 printf("\t%s;\n", symbols[v, i]);
224         }
225
226         version_count--;
227         if (version_count == 0) {
228                 printf("local:\n");
229                 printf("\t*;\n");
230         }
231         if (successors[v] == "")
232                 printf("};\n");
233         else
234                 printf("} %s;\n", successors[v]);
235         printf("\n");
236
237         generated[v] = 1;
238     }
239
240 END {
241         if (errors) {
242                 printf("%d error(s) total.\n", errors) > stderr;
243                 exit(1);
244         }
245         # OK, no errors.
246         for (v in versions) {
247                 print_version(v);
248         }
249 }