version_gen.awk revision 156772
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 156772 2006-03-16 15:12:26Z deischen $
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			version_count++;
57		}
58		else if (/^[ \t]*} *[a-zA-Z0-9._]+ *;/) {
59			# Strip semicolon.
60			gsub(";", "", $2);
61			if (symver == "")
62				printf("Unmatched bracket.\n");
63			else if (versions[$2] != 1)
64				printf("File %s: %s has unknown " \
65				    "successor %s\n", vfile, symver, $2);
66			else
67				successors[symver] = $2;
68			brackets--;
69		}
70		else if (/^[ \t]*};/) {
71			if (symver == "")
72				printf("File %s: Unmatched bracket.\n",
73				    vfile) > stderr;
74			# No successor
75			brackets--;
76		}
77		else if (/^[ \t]*}/) {
78			printf("File %s: Missing ending semi-colon.\n",
79			    vfile) > stderr;
80		}
81		else if (/^$/)
82			;  # Ignore blank lines.
83		else
84			printf("File %s: Unknown directive: %s\n",
85			    vfile, $0) > stderr;
86	}
87	brackets = 0;
88}
89
90/.*/ {
91	# Delete comments, preceding and trailing whitespace, then
92	# consume blank lines.
93	sub("#.*$", "", $0);
94	sub("^[ \t]+", "", $0);
95	sub("[ \t]+$", "", $0);
96	if ($0 == "")
97		next;
98}
99
100/^[a-zA-Z0-9._]+ +{$/ {
101	# Strip bracket from version name.
102	sub("{", "", $1);
103	if (current_version != "")
104		printf("File %s, line %d: Illegal nesting detected.\n",
105		    FILENAME, FNR) > stderr;
106	else if (versions[$1] == 0) {
107		printf("File %s, line %d: Undefined " \
108		    "library version %s\n", FILENAME, FNR, $1) > stderr;
109		# Remove this entry from the versions.
110		delete versions[$1];
111	}
112	else
113		current_version = $1;
114	brackets++;
115	next;
116}
117
118/^[a-zA-Z0-9._]+ *;$/ {
119	if (current_version != "") {
120		count = versions[current_version];
121		versions[current_version]++;
122		symbols[current_version, count] = $1;
123	}
124	next;
125}
126
127/^} *;$/ {
128	brackets--;
129	if (brackets < 0) {
130		printf("File %s, line %d: Unmatched bracket.\n",
131		    FILENAME, FNR, $1) > stderr;
132		brackets = 0;	# Reset
133	}
134	current_version = "";
135	next;
136}
137
138
139/.*/ {
140	printf("File %s, line %d: Unknown directive: '%s'\n",
141	    FILENAME, FNR, $0) > stderr;
142}
143
144END {
145	for (v in versions) {
146		printf("\n");
147		printf("%s {\n", v);
148
149		# The version count is always one more that actual,
150		# so the loop ranges from 1 to n-1.
151		#
152		for (i = 1; i < versions[v]; i++) {
153			if (i == 1)
154				printf("global:\n");
155			printf("\t%s\n", symbols[v, i]);
156		}
157		if (successors[v] == "") {
158			# This version succeeds no other version.
159			printf("local:\n");
160			printf("\t*;\n");
161			printf("};\n");
162		}
163		else
164			printf("} %s;\n", successors[v]);
165	}
166}
167