1156772Sdeischen# 2156772Sdeischen# Copyright (C) 2006 Daniel M. Eischen. All rights reserved. 3156772Sdeischen# 4156772Sdeischen# Redistribution and use in source and binary forms, with or without 5156772Sdeischen# modification, are permitted provided that the following conditions 6156772Sdeischen# are met: 7156772Sdeischen# 1. Redistributions of source code must retain the above copyright 8156772Sdeischen# notice, this list of conditions and the following disclaimer. 9156772Sdeischen# 2. Redistributions in binary form must reproduce the above copyright 10156772Sdeischen# notice, this list of conditions and the following disclaimer in the 11156772Sdeischen# documentation and/or other materials provided with the distribution. 12156772Sdeischen# 13156772Sdeischen# THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14156772Sdeischen# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15156772Sdeischen# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16156772Sdeischen# ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 17156772Sdeischen# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18156772Sdeischen# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19156772Sdeischen# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20156772Sdeischen# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21156772Sdeischen# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22156772Sdeischen# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23156772Sdeischen# SUCH DAMAGE. 24156772Sdeischen# 25156772Sdeischen# $FreeBSD$ 26156772Sdeischen# 27156772Sdeischen 28156772Sdeischen# 29156772Sdeischen# Make a list of all the library versions listed in the master file. 30156772Sdeischen# 31156772Sdeischen# versions[] - array indexed by version name, contains number 32156772Sdeischen# of symbols (+ 1) found for each version. 33156772Sdeischen# successors[] - array index by version name, contains successor 34156772Sdeischen# version name. 35156772Sdeischen# symbols[][] - array index by [version name, symbol index], contains 36156772Sdeischen# names of symbols defined for each version. 37172747Syar# names[] - array index is symbol name and value is its first version seen, 38172729Syar# used to check for duplicate symbols and warn about them. 39156772Sdeischen# 40156772SdeischenBEGIN { 41156772Sdeischen brackets = 0; 42172747Syar errors = warns = 0; 43156772Sdeischen version_count = 0; 44156772Sdeischen current_version = ""; 45156772Sdeischen stderr = "/dev/stderr"; 46156772Sdeischen while (getline < vfile) { 47156772Sdeischen # Strip comments. 48156772Sdeischen sub("#.*$", "", $0); 49156772Sdeischen 50172729Syar # Strip leading and trailing whitespace. 51172729Syar sub("^[ \t]+", "", $0); 52172729Syar sub("[ \t]+$", "", $0); 53156772Sdeischen 54172729Syar if (/^[a-zA-Z0-9._]+[ \t]*{$/) { 55172729Syar # Strip brace. 56172729Syar sub("{", "", $1); 57156772Sdeischen brackets++; 58156772Sdeischen symver = $1; 59156772Sdeischen versions[symver] = 1; 60156772Sdeischen successors[symver] = ""; 61168963Sdeischen generated[symver] = 0; 62156772Sdeischen version_count++; 63156772Sdeischen } 64172729Syar else if (/^}[ \t]*[a-zA-Z0-9._]+[ \t]*;$/) { 65172729Syar v = $1 != "}" ? $1 : $2; 66172729Syar # Strip brace. 67172729Syar sub("}", "", v); 68156772Sdeischen # Strip semicolon. 69172729Syar sub(";", "", v); 70172729Syar if (symver == "") { 71172729Syar printf("File %s: Unmatched bracket.\n", 72172729Syar vfile) > stderr; 73172729Syar errors++; 74172729Syar } 75172729Syar else if (versions[v] != 1) { 76172729Syar printf("File %s: `%s' has unknown " \ 77172729Syar "successor `%s'.\n", 78172729Syar vfile, symver, v) > stderr; 79172729Syar errors++; 80172729Syar } 81156772Sdeischen else 82172729Syar successors[symver] = v; 83156772Sdeischen brackets--; 84156772Sdeischen } 85172729Syar else if (/^}[ \t]*;$/) { 86172729Syar if (symver == "") { 87156772Sdeischen printf("File %s: Unmatched bracket.\n", 88156772Sdeischen vfile) > stderr; 89172729Syar errors++; 90172729Syar } 91156772Sdeischen # No successor 92156772Sdeischen brackets--; 93156772Sdeischen } 94172729Syar else if (/^}$/) { 95172729Syar printf("File %s: Missing final semicolon.\n", 96156772Sdeischen vfile) > stderr; 97172729Syar errors++; 98156772Sdeischen } 99156772Sdeischen else if (/^$/) 100156772Sdeischen ; # Ignore blank lines. 101172729Syar else { 102172729Syar printf("File %s: Unknown directive: `%s'.\n", 103156772Sdeischen vfile, $0) > stderr; 104172729Syar errors++; 105172729Syar } 106156772Sdeischen } 107156772Sdeischen brackets = 0; 108156772Sdeischen} 109156772Sdeischen 110172729Syar{ 111172729Syar # Set meaningful filename for diagnostics. 112172729Syar filename = FILENAME != "" ? FILENAME : "<stdin>"; 113172729Syar 114156772Sdeischen # Delete comments, preceding and trailing whitespace, then 115156772Sdeischen # consume blank lines. 116156772Sdeischen sub("#.*$", "", $0); 117156772Sdeischen sub("^[ \t]+", "", $0); 118156772Sdeischen sub("[ \t]+$", "", $0); 119156772Sdeischen if ($0 == "") 120156772Sdeischen next; 121156772Sdeischen} 122156772Sdeischen 123172729Syar/^[a-zA-Z0-9._]+[ \t]*{$/ { 124156772Sdeischen # Strip bracket from version name. 125156772Sdeischen sub("{", "", $1); 126172729Syar if (current_version != "") { 127156772Sdeischen printf("File %s, line %d: Illegal nesting detected.\n", 128172729Syar filename, FNR) > stderr; 129172729Syar errors++; 130172729Syar } 131156772Sdeischen else if (versions[$1] == 0) { 132156772Sdeischen printf("File %s, line %d: Undefined " \ 133172729Syar "library version `%s'.\n", filename, FNR, $1) > stderr; 134172729Syar errors++; 135156772Sdeischen # Remove this entry from the versions. 136156772Sdeischen delete versions[$1]; 137156772Sdeischen } 138156772Sdeischen else 139156772Sdeischen current_version = $1; 140156772Sdeischen brackets++; 141156772Sdeischen next; 142156772Sdeischen} 143156772Sdeischen 144172729Syar/^[a-zA-Z0-9._]+[ \t]*;$/ { 145172729Syar # Strip semicolon. 146172729Syar sub(";", "", $1); 147156772Sdeischen if (current_version != "") { 148156772Sdeischen count = versions[current_version]; 149156772Sdeischen versions[current_version]++; 150156772Sdeischen symbols[current_version, count] = $1; 151172747Syar if ($1 in names && names[$1] != current_version) { 152172747Syar # 153172747Syar # A graver case when a dup symbol appears under 154172747Syar # different versions in the map. That can result 155172747Syar # in subtle problems with the library later. 156172747Syar # 157172747Syar printf("File %s, line %d: Duplicated symbol `%s' " \ 158172747Syar "in version `%s', first seen in `%s'. " \ 159172729Syar "Did you forget to move it to ObsoleteVersions?\n", 160172747Syar filename, FNR, $1, 161172747Syar current_version, names[$1]) > stderr; 162172729Syar errors++; 163172729Syar } 164172747Syar else if (names[$1] == current_version) { 165172747Syar # 166172747Syar # A harmless case: a dup symbol with the same version. 167172747Syar # 168172747Syar printf("File %s, line %d: warning: " \ 169172747Syar "Duplicated symbol `%s' in version `%s'.\n", 170172747Syar filename, FNR, $1, current_version) > stderr; 171172747Syar warns++; 172172747Syar } 173172747Syar else 174172747Syar names[$1] = current_version; 175156772Sdeischen } 176172729Syar else { 177172729Syar printf("File %s, line %d: Symbol `%s' outside version scope.\n", 178172729Syar filename, FNR, $1) > stderr; 179172729Syar errors++; 180172729Syar } 181156772Sdeischen next; 182156772Sdeischen} 183156772Sdeischen 184172729Syar/^}[ \t]*;$/ { 185156772Sdeischen brackets--; 186156772Sdeischen if (brackets < 0) { 187156772Sdeischen printf("File %s, line %d: Unmatched bracket.\n", 188172729Syar filename, FNR, $1) > stderr; 189172729Syar errors++; 190156772Sdeischen brackets = 0; # Reset 191156772Sdeischen } 192156772Sdeischen current_version = ""; 193156772Sdeischen next; 194156772Sdeischen} 195156772Sdeischen 196156772Sdeischen 197172729Syar{ 198172729Syar printf("File %s, line %d: Unknown directive: `%s'.\n", 199172729Syar filename, FNR, $0) > stderr; 200172729Syar errors++; 201156772Sdeischen} 202156772Sdeischen 203168963Sdeischenfunction print_version(v) 204168963Sdeischen{ 205168963Sdeischen # This function is recursive, so return if this version 206168963Sdeischen # has already been printed. Otherwise, if there is an 207168963Sdeischen # ancestral version, recursively print its symbols before 208168963Sdeischen # printing the symbols for this version. 209168963Sdeischen # 210168963Sdeischen if (generated[v] == 1) 211168963Sdeischen return; 212168963Sdeischen if (successors[v] != "") 213168963Sdeischen print_version(successors[v]); 214168963Sdeischen 215168963Sdeischen printf("%s {\n", v); 216168963Sdeischen 217168963Sdeischen # The version count is always one more that actual, 218168963Sdeischen # so the loop ranges from 1 to n-1. 219168963Sdeischen # 220168963Sdeischen for (i = 1; i < versions[v]; i++) { 221168963Sdeischen if (i == 1) 222168963Sdeischen printf("global:\n"); 223172729Syar printf("\t%s;\n", symbols[v, i]); 224168963Sdeischen } 225171530Skan 226171530Skan version_count--; 227171530Skan if (version_count == 0) { 228168963Sdeischen printf("local:\n"); 229168963Sdeischen printf("\t*;\n"); 230171530Skan } 231171530Skan if (successors[v] == "") 232168963Sdeischen printf("};\n"); 233168963Sdeischen else 234168963Sdeischen printf("} %s;\n", successors[v]); 235168963Sdeischen printf("\n"); 236168963Sdeischen 237168963Sdeischen generated[v] = 1; 238168963Sdeischen } 239172729Syar 240156772SdeischenEND { 241172729Syar if (errors) { 242172747Syar printf("%d error(s) total.\n", errors) > stderr; 243172729Syar exit(1); 244172729Syar } 245172729Syar # OK, no errors. 246156772Sdeischen for (v in versions) { 247168963Sdeischen print_version(v); 248156772Sdeischen } 249156772Sdeischen} 250