libc/nls: Sync with FreeBSD.
[dragonfly.git] / share / mk / version_gen.awk
blob93fbc4fc9129b0a64a2112f85d8be4619189cfb8
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.
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.
25 # $FreeBSD$
29 # Make a list of all the library versions listed in the master file.
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.
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);
50 # Strip leading and trailing whitespace.
51 sub("^[ \t]+", "", $0);
52 sub("[ \t]+$", "", $0);
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++;
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++;
75 else if (versions[v] != 1) {
76 printf("File %s: `%s' has unknown " \
77 "successor `%s'.\n",
78 vfile, symver, v) > stderr;
79 errors++;
81 else
82 successors[symver] = v;
83 brackets--;
85 else if (/^}[ \t]*;$/) {
86 if (symver == "") {
87 printf("File %s: Unmatched bracket.\n",
88 vfile) > stderr;
89 errors++;
91 # No successor
92 brackets--;
94 else if (/^}$/) {
95 printf("File %s: Missing final semicolon.\n",
96 vfile) > stderr;
97 errors++;
99 else if (/^$/)
100 ; # Ignore blank lines.
101 else {
102 printf("File %s: Unknown directive: `%s'.\n",
103 vfile, $0) > stderr;
104 errors++;
107 brackets = 0;
111 # Set meaningful filename for diagnostics.
112 filename = FILENAME != "" ? FILENAME : "<stdin>";
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;
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++;
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];
138 else
139 current_version = $1;
140 brackets++;
141 next;
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) {
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.
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++;
164 else if (names[$1] == current_version) {
166 # A harmless case: a dup symbol with the same version.
168 printf("File %s, line %d: warning: " \
169 "Duplicated symbol `%s' in version `%s'.\n",
170 filename, FNR, $1, current_version) > stderr;
171 warns++;
173 else
174 names[$1] = current_version;
176 else {
177 printf("File %s, line %d: Symbol `%s' outside version scope.\n",
178 filename, FNR, $1) > stderr;
179 errors++;
181 next;
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
192 current_version = "";
193 next;
198 printf("File %s, line %d: Unknown directive: `%s'.\n",
199 filename, FNR, $0) > stderr;
200 errors++;
203 function print_version(v)
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.
210 if (generated[v] == 1)
211 return;
212 if (successors[v] != "")
213 print_version(successors[v]);
215 printf("%s {\n", v);
217 # The version count is always one more that actual,
218 # so the loop ranges from 1 to n-1.
220 for (i = 1; i < versions[v]; i++) {
221 if (i == 1)
222 printf("global:\n");
223 printf("\t%s;\n", symbols[v, i]);
226 version_count--;
227 if (version_count == 0) {
228 printf("local:\n");
229 printf("\t*;\n");
231 if (successors[v] == "")
232 printf("};\n");
233 else
234 printf("} %s;\n", successors[v]);
235 printf("\n");
237 generated[v] = 1;
240 END {
241 if (errors) {
242 printf("%d error(s) total.\n", errors) > stderr;
243 exit(1);
245 # OK, no errors.
246 for (v in versions) {
247 print_version(v);