version_gen.awk revision 171530
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: head/share/mk/version_gen.awk 171530 2007-07-21 20:52:32Z kan $
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#
38BEGIN {
39	brackets = 0;
40	errors = 0;
41	version_count = 0;
42	current_version = "";
43	stderr = "/dev/stderr";
44	while (getline < vfile) {
45		# Strip comments.
46		sub("#.*$", "", $0);
47
48		# Strip trailing spaces.
49		sub(" *$", "", $0);
50
51		if (/^[ \t]*[a-zA-Z0-9._]+ *{/) {
52			brackets++;
53			symver = $1;
54			versions[symver] = 1;
55			successors[symver] = "";
56			generated[symver] = 0;
57			version_count++;
58		}
59		else if (/^[ \t]*} *[a-zA-Z0-9._]+ *;/) {
60			# Strip semicolon.
61			gsub(";", "", $2);
62			if (symver == "")
63				printf("Unmatched bracket.\n");
64			else if (versions[$2] != 1)
65				printf("File %s: %s has unknown " \
66				    "successor %s\n", vfile, symver, $2);
67			else
68				successors[symver] = $2;
69			brackets--;
70		}
71		else if (/^[ \t]*};/) {
72			if (symver == "")
73				printf("File %s: Unmatched bracket.\n",
74				    vfile) > stderr;
75			# No successor
76			brackets--;
77		}
78		else if (/^[ \t]*}/) {
79			printf("File %s: Missing ending semi-colon.\n",
80			    vfile) > stderr;
81		}
82		else if (/^$/)
83			;  # Ignore blank lines.
84		else
85			printf("File %s: Unknown directive: %s\n",
86			    vfile, $0) > stderr;
87	}
88	brackets = 0;
89}
90
91/.*/ {
92	# Delete comments, preceding and trailing whitespace, then
93	# consume blank lines.
94	sub("#.*$", "", $0);
95	sub("^[ \t]+", "", $0);
96	sub("[ \t]+$", "", $0);
97	if ($0 == "")
98		next;
99}
100
101/^[a-zA-Z0-9._]+ +{$/ {
102	# Strip bracket from version name.
103	sub("{", "", $1);
104	if (current_version != "")
105		printf("File %s, line %d: Illegal nesting detected.\n",
106		    FILENAME, FNR) > stderr;
107	else if (versions[$1] == 0) {
108		printf("File %s, line %d: Undefined " \
109		    "library version %s\n", FILENAME, FNR, $1) > stderr;
110		# Remove this entry from the versions.
111		delete versions[$1];
112	}
113	else
114		current_version = $1;
115	brackets++;
116	next;
117}
118
119/^[a-zA-Z0-9._]+ *;$/ {
120	if (current_version != "") {
121		count = versions[current_version];
122		versions[current_version]++;
123		symbols[current_version, count] = $1;
124	}
125	next;
126}
127
128/^} *;$/ {
129	brackets--;
130	if (brackets < 0) {
131		printf("File %s, line %d: Unmatched bracket.\n",
132		    FILENAME, FNR, $1) > stderr;
133		brackets = 0;	# Reset
134	}
135	current_version = "";
136	next;
137}
138
139
140/.*/ {
141	printf("File %s, line %d: Unknown directive: '%s'\n",
142	    FILENAME, FNR, $0) > stderr;
143}
144
145function print_version(v)
146{
147	# This function is recursive, so return if this version
148	# has already been printed.  Otherwise, if there is an
149	# ancestral version, recursively print its symbols before
150	# printing the symbols for this version.
151	#
152	if (generated[v] == 1)
153		return;
154	if (successors[v] != "")
155		print_version(successors[v]);
156
157	printf("%s {\n", v);
158
159	# The version count is always one more that actual,
160	# so the loop ranges from 1 to n-1.
161	#
162	for (i = 1; i < versions[v]; i++) {
163		if (i == 1)
164			printf("global:\n");
165		printf("\t%s\n", symbols[v, i]);
166	}
167
168	version_count--;
169	if (version_count == 0) {
170		printf("local:\n");
171		printf("\t*;\n");
172	}
173	if (successors[v] == "")
174		printf("};\n");
175	else
176		printf("} %s;\n", successors[v]);
177	printf("\n");
178
179	generated[v] = 1;
180    }
181END {
182	for (v in versions) {
183		print_version(v);
184	}
185}
186