1ab52e991SDaniel Eischen# 2*4d846d26SWarner Losh# SPDX-License-Identifier: BSD-2-Clause 3f0cfa1b1SPedro F. Giffuni# 4ab52e991SDaniel Eischen# Copyright (C) 2006 Daniel M. Eischen. All rights reserved. 5ab52e991SDaniel Eischen# 6ab52e991SDaniel Eischen# Redistribution and use in source and binary forms, with or without 7ab52e991SDaniel Eischen# modification, are permitted provided that the following conditions 8ab52e991SDaniel Eischen# are met: 9ab52e991SDaniel Eischen# 1. Redistributions of source code must retain the above copyright 10ab52e991SDaniel Eischen# notice, this list of conditions and the following disclaimer. 11ab52e991SDaniel Eischen# 2. Redistributions in binary form must reproduce the above copyright 12ab52e991SDaniel Eischen# notice, this list of conditions and the following disclaimer in the 13ab52e991SDaniel Eischen# documentation and/or other materials provided with the distribution. 14ab52e991SDaniel Eischen# 15ab52e991SDaniel Eischen# THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16ab52e991SDaniel Eischen# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17ab52e991SDaniel Eischen# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18ab52e991SDaniel Eischen# ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 19ab52e991SDaniel Eischen# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20ab52e991SDaniel Eischen# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21ab52e991SDaniel Eischen# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22ab52e991SDaniel Eischen# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23ab52e991SDaniel Eischen# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24ab52e991SDaniel Eischen# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25ab52e991SDaniel Eischen# SUCH DAMAGE. 26ab52e991SDaniel Eischen# 27ab52e991SDaniel Eischen# 28ab52e991SDaniel Eischen 29ab52e991SDaniel Eischen# 30ab52e991SDaniel Eischen# Make a list of all the library versions listed in the master file. 31ab52e991SDaniel Eischen# 32ab52e991SDaniel Eischen# versions[] - array indexed by version name, contains number 33ab52e991SDaniel Eischen# of symbols (+ 1) found for each version. 34ab52e991SDaniel Eischen# successors[] - array index by version name, contains successor 35ab52e991SDaniel Eischen# version name. 36ab52e991SDaniel Eischen# symbols[][] - array index by [version name, symbol index], contains 37ab52e991SDaniel Eischen# names of symbols defined for each version. 3891fb7b9bSYaroslav Tykhiy# names[] - array index is symbol name and value is its first version seen, 3939d5a8ffSYaroslav Tykhiy# used to check for duplicate symbols and warn about them. 40ab52e991SDaniel Eischen# 41ab52e991SDaniel EischenBEGIN { 42ab52e991SDaniel Eischen brackets = 0; 4391fb7b9bSYaroslav Tykhiy errors = warns = 0; 44ab52e991SDaniel Eischen version_count = 0; 45ab52e991SDaniel Eischen current_version = ""; 46ab52e991SDaniel Eischen stderr = "/dev/stderr"; 47ab52e991SDaniel Eischen while (getline < vfile) { 48ab52e991SDaniel Eischen # Strip comments. 49ab52e991SDaniel Eischen sub("#.*$", "", $0); 50ab52e991SDaniel Eischen 5139d5a8ffSYaroslav Tykhiy # Strip leading and trailing whitespace. 5239d5a8ffSYaroslav Tykhiy sub("^[ \t]+", "", $0); 5339d5a8ffSYaroslav Tykhiy sub("[ \t]+$", "", $0); 54ab52e991SDaniel Eischen 5539d5a8ffSYaroslav Tykhiy if (/^[a-zA-Z0-9._]+[ \t]*{$/) { 5639d5a8ffSYaroslav Tykhiy # Strip brace. 5739d5a8ffSYaroslav Tykhiy sub("{", "", $1); 58ab52e991SDaniel Eischen brackets++; 59ab52e991SDaniel Eischen symver = $1; 60ab52e991SDaniel Eischen versions[symver] = 1; 61ab52e991SDaniel Eischen successors[symver] = ""; 626f91e7a3SDaniel Eischen generated[symver] = 0; 63ab52e991SDaniel Eischen version_count++; 64ab52e991SDaniel Eischen } 6539d5a8ffSYaroslav Tykhiy else if (/^}[ \t]*[a-zA-Z0-9._]+[ \t]*;$/) { 6639d5a8ffSYaroslav Tykhiy v = $1 != "}" ? $1 : $2; 6739d5a8ffSYaroslav Tykhiy # Strip brace. 6839d5a8ffSYaroslav Tykhiy sub("}", "", v); 69ab52e991SDaniel Eischen # Strip semicolon. 7039d5a8ffSYaroslav Tykhiy sub(";", "", v); 7139d5a8ffSYaroslav Tykhiy if (symver == "") { 72ab52e991SDaniel Eischen printf("File %s: Unmatched bracket.\n", 73ab52e991SDaniel Eischen vfile) > stderr; 7439d5a8ffSYaroslav Tykhiy errors++; 7539d5a8ffSYaroslav Tykhiy } 7639d5a8ffSYaroslav Tykhiy else if (versions[v] != 1) { 7739d5a8ffSYaroslav Tykhiy printf("File %s: `%s' has unknown " \ 7839d5a8ffSYaroslav Tykhiy "successor `%s'.\n", 7939d5a8ffSYaroslav Tykhiy vfile, symver, v) > stderr; 8039d5a8ffSYaroslav Tykhiy errors++; 8139d5a8ffSYaroslav Tykhiy } 8239d5a8ffSYaroslav Tykhiy else 8339d5a8ffSYaroslav Tykhiy successors[symver] = v; 8439d5a8ffSYaroslav Tykhiy brackets--; 8539d5a8ffSYaroslav Tykhiy } 8639d5a8ffSYaroslav Tykhiy else if (/^}[ \t]*;$/) { 8739d5a8ffSYaroslav Tykhiy if (symver == "") { 8839d5a8ffSYaroslav Tykhiy printf("File %s: Unmatched bracket.\n", 8939d5a8ffSYaroslav Tykhiy vfile) > stderr; 9039d5a8ffSYaroslav Tykhiy errors++; 9139d5a8ffSYaroslav Tykhiy } 92ab52e991SDaniel Eischen # No successor 93ab52e991SDaniel Eischen brackets--; 94ab52e991SDaniel Eischen } 9539d5a8ffSYaroslav Tykhiy else if (/^}$/) { 9639d5a8ffSYaroslav Tykhiy printf("File %s: Missing final semicolon.\n", 97ab52e991SDaniel Eischen vfile) > stderr; 9839d5a8ffSYaroslav Tykhiy errors++; 99ab52e991SDaniel Eischen } 100ab52e991SDaniel Eischen else if (/^$/) 101ab52e991SDaniel Eischen ; # Ignore blank lines. 10239d5a8ffSYaroslav Tykhiy else { 10339d5a8ffSYaroslav Tykhiy printf("File %s: Unknown directive: `%s'.\n", 104ab52e991SDaniel Eischen vfile, $0) > stderr; 10539d5a8ffSYaroslav Tykhiy errors++; 10639d5a8ffSYaroslav Tykhiy } 107ab52e991SDaniel Eischen } 108ab52e991SDaniel Eischen brackets = 0; 109ab52e991SDaniel Eischen} 110ab52e991SDaniel Eischen 11139d5a8ffSYaroslav Tykhiy{ 11239d5a8ffSYaroslav Tykhiy # Set meaningful filename for diagnostics. 11339d5a8ffSYaroslav Tykhiy filename = FILENAME != "" ? FILENAME : "<stdin>"; 11439d5a8ffSYaroslav Tykhiy 115ab52e991SDaniel Eischen # Delete comments, preceding and trailing whitespace, then 116ab52e991SDaniel Eischen # consume blank lines. 117ab52e991SDaniel Eischen sub("#.*$", "", $0); 118ab52e991SDaniel Eischen sub("^[ \t]+", "", $0); 119ab52e991SDaniel Eischen sub("[ \t]+$", "", $0); 120ab52e991SDaniel Eischen if ($0 == "") 121ab52e991SDaniel Eischen next; 122ab52e991SDaniel Eischen} 123ab52e991SDaniel Eischen 12439d5a8ffSYaroslav Tykhiy/^[a-zA-Z0-9._]+[ \t]*{$/ { 125ab52e991SDaniel Eischen # Strip bracket from version name. 126ab52e991SDaniel Eischen sub("{", "", $1); 12739d5a8ffSYaroslav Tykhiy if (current_version != "") { 128ab52e991SDaniel Eischen printf("File %s, line %d: Illegal nesting detected.\n", 12939d5a8ffSYaroslav Tykhiy filename, FNR) > stderr; 13039d5a8ffSYaroslav Tykhiy errors++; 13139d5a8ffSYaroslav Tykhiy } 132ab52e991SDaniel Eischen else if (versions[$1] == 0) { 133ab52e991SDaniel Eischen printf("File %s, line %d: Undefined " \ 13439d5a8ffSYaroslav Tykhiy "library version `%s'.\n", filename, FNR, $1) > stderr; 13539d5a8ffSYaroslav Tykhiy errors++; 136ab52e991SDaniel Eischen # Remove this entry from the versions. 137ab52e991SDaniel Eischen delete versions[$1]; 138ab52e991SDaniel Eischen } 139ab52e991SDaniel Eischen else 140ab52e991SDaniel Eischen current_version = $1; 141ab52e991SDaniel Eischen brackets++; 142ab52e991SDaniel Eischen next; 143ab52e991SDaniel Eischen} 144ab52e991SDaniel Eischen 14539d5a8ffSYaroslav Tykhiy/^[a-zA-Z0-9._]+[ \t]*;$/ { 14639d5a8ffSYaroslav Tykhiy # Strip semicolon. 14739d5a8ffSYaroslav Tykhiy sub(";", "", $1); 148ab52e991SDaniel Eischen if (current_version != "") { 149ab52e991SDaniel Eischen count = versions[current_version]; 150ab52e991SDaniel Eischen versions[current_version]++; 151ab52e991SDaniel Eischen symbols[current_version, count] = $1; 15291fb7b9bSYaroslav Tykhiy if ($1 in names && names[$1] != current_version) { 15391fb7b9bSYaroslav Tykhiy # 15491fb7b9bSYaroslav Tykhiy # A graver case when a dup symbol appears under 15591fb7b9bSYaroslav Tykhiy # different versions in the map. That can result 15691fb7b9bSYaroslav Tykhiy # in subtle problems with the library later. 15791fb7b9bSYaroslav Tykhiy # 15891fb7b9bSYaroslav Tykhiy printf("File %s, line %d: Duplicated symbol `%s' " \ 15991fb7b9bSYaroslav Tykhiy "in version `%s', first seen in `%s'. " \ 16039d5a8ffSYaroslav Tykhiy "Did you forget to move it to ObsoleteVersions?\n", 16191fb7b9bSYaroslav Tykhiy filename, FNR, $1, 16291fb7b9bSYaroslav Tykhiy current_version, names[$1]) > stderr; 16339d5a8ffSYaroslav Tykhiy errors++; 16439d5a8ffSYaroslav Tykhiy } 16591fb7b9bSYaroslav Tykhiy else if (names[$1] == current_version) { 16691fb7b9bSYaroslav Tykhiy # 16791fb7b9bSYaroslav Tykhiy # A harmless case: a dup symbol with the same version. 16891fb7b9bSYaroslav Tykhiy # 16991fb7b9bSYaroslav Tykhiy printf("File %s, line %d: warning: " \ 17091fb7b9bSYaroslav Tykhiy "Duplicated symbol `%s' in version `%s'.\n", 17191fb7b9bSYaroslav Tykhiy filename, FNR, $1, current_version) > stderr; 17291fb7b9bSYaroslav Tykhiy warns++; 17391fb7b9bSYaroslav Tykhiy } 17491fb7b9bSYaroslav Tykhiy else 17591fb7b9bSYaroslav Tykhiy names[$1] = current_version; 17639d5a8ffSYaroslav Tykhiy } 17739d5a8ffSYaroslav Tykhiy else { 17839d5a8ffSYaroslav Tykhiy printf("File %s, line %d: Symbol `%s' outside version scope.\n", 17939d5a8ffSYaroslav Tykhiy filename, FNR, $1) > stderr; 18039d5a8ffSYaroslav Tykhiy errors++; 181ab52e991SDaniel Eischen } 182ab52e991SDaniel Eischen next; 183ab52e991SDaniel Eischen} 184ab52e991SDaniel Eischen 18539d5a8ffSYaroslav Tykhiy/^}[ \t]*;$/ { 186ab52e991SDaniel Eischen brackets--; 187ab52e991SDaniel Eischen if (brackets < 0) { 188ab52e991SDaniel Eischen printf("File %s, line %d: Unmatched bracket.\n", 18939d5a8ffSYaroslav Tykhiy filename, FNR, $1) > stderr; 19039d5a8ffSYaroslav Tykhiy errors++; 191ab52e991SDaniel Eischen brackets = 0; # Reset 192ab52e991SDaniel Eischen } 193ab52e991SDaniel Eischen current_version = ""; 194ab52e991SDaniel Eischen next; 195ab52e991SDaniel Eischen} 196ab52e991SDaniel Eischen 197ab52e991SDaniel Eischen 19839d5a8ffSYaroslav Tykhiy{ 19939d5a8ffSYaroslav Tykhiy printf("File %s, line %d: Unknown directive: `%s'.\n", 20039d5a8ffSYaroslav Tykhiy filename, FNR, $0) > stderr; 20139d5a8ffSYaroslav Tykhiy errors++; 202ab52e991SDaniel Eischen} 203ab52e991SDaniel Eischen 2046f91e7a3SDaniel Eischenfunction print_version(v) 2056f91e7a3SDaniel Eischen{ 2066f91e7a3SDaniel Eischen # This function is recursive, so return if this version 2076f91e7a3SDaniel Eischen # has already been printed. Otherwise, if there is an 2086f91e7a3SDaniel Eischen # ancestral version, recursively print its symbols before 2096f91e7a3SDaniel Eischen # printing the symbols for this version. 2106f91e7a3SDaniel Eischen # 2116f91e7a3SDaniel Eischen if (generated[v] == 1) 2126f91e7a3SDaniel Eischen return; 2136f91e7a3SDaniel Eischen if (successors[v] != "") 2146f91e7a3SDaniel Eischen print_version(successors[v]); 2156f91e7a3SDaniel Eischen 216ab52e991SDaniel Eischen printf("%s {\n", v); 217ab52e991SDaniel Eischen 218ab52e991SDaniel Eischen # The version count is always one more that actual, 219ab52e991SDaniel Eischen # so the loop ranges from 1 to n-1. 220ab52e991SDaniel Eischen # 221ab52e991SDaniel Eischen for (i = 1; i < versions[v]; i++) { 222ab52e991SDaniel Eischen if (i == 1) 223ab52e991SDaniel Eischen printf("global:\n"); 22439d5a8ffSYaroslav Tykhiy printf("\t%s;\n", symbols[v, i]); 225ab52e991SDaniel Eischen } 2269f408248SAlexander Kabaev 2279f408248SAlexander Kabaev version_count--; 2289f408248SAlexander Kabaev if (version_count == 0) { 229ab52e991SDaniel Eischen printf("local:\n"); 230ab52e991SDaniel Eischen printf("\t*;\n"); 231ab52e991SDaniel Eischen } 2329f408248SAlexander Kabaev if (successors[v] == "") 2339f408248SAlexander Kabaev printf("};\n"); 234ab52e991SDaniel Eischen else 235ab52e991SDaniel Eischen printf("} %s;\n", successors[v]); 2366f91e7a3SDaniel Eischen printf("\n"); 2376f91e7a3SDaniel Eischen 2386f91e7a3SDaniel Eischen generated[v] = 1; 2396f91e7a3SDaniel Eischen } 24039d5a8ffSYaroslav Tykhiy 2416f91e7a3SDaniel EischenEND { 24239d5a8ffSYaroslav Tykhiy if (errors) { 24391fb7b9bSYaroslav Tykhiy printf("%d error(s) total.\n", errors) > stderr; 24439d5a8ffSYaroslav Tykhiy exit(1); 24539d5a8ffSYaroslav Tykhiy } 24639d5a8ffSYaroslav Tykhiy # OK, no errors. 2476f91e7a3SDaniel Eischen for (v in versions) { 2486f91e7a3SDaniel Eischen print_version(v); 249ab52e991SDaniel Eischen } 250ab52e991SDaniel Eischen} 251