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