1ab52e991SDaniel Eischen# 2*f0cfa1b1SPedro F. Giffuni# SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3*f0cfa1b1SPedro 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# $FreeBSD$ 28ab52e991SDaniel Eischen# 29ab52e991SDaniel Eischen 30ab52e991SDaniel Eischen# 31ab52e991SDaniel Eischen# Make a list of all the library versions listed in the master file. 32ab52e991SDaniel Eischen# 33ab52e991SDaniel Eischen# versions[] - array indexed by version name, contains number 34ab52e991SDaniel Eischen# of symbols (+ 1) found for each version. 35ab52e991SDaniel Eischen# successors[] - array index by version name, contains successor 36ab52e991SDaniel Eischen# version name. 37ab52e991SDaniel Eischen# symbols[][] - array index by [version name, symbol index], contains 38ab52e991SDaniel Eischen# names of symbols defined for each version. 3991fb7b9bSYaroslav Tykhiy# names[] - array index is symbol name and value is its first version seen, 4039d5a8ffSYaroslav Tykhiy# used to check for duplicate symbols and warn about them. 41ab52e991SDaniel Eischen# 42ab52e991SDaniel EischenBEGIN { 43ab52e991SDaniel Eischen brackets = 0; 4491fb7b9bSYaroslav Tykhiy errors = warns = 0; 45ab52e991SDaniel Eischen version_count = 0; 46ab52e991SDaniel Eischen current_version = ""; 47ab52e991SDaniel Eischen stderr = "/dev/stderr"; 48ab52e991SDaniel Eischen while (getline < vfile) { 49ab52e991SDaniel Eischen # Strip comments. 50ab52e991SDaniel Eischen sub("#.*$", "", $0); 51ab52e991SDaniel Eischen 5239d5a8ffSYaroslav Tykhiy # Strip leading and trailing whitespace. 5339d5a8ffSYaroslav Tykhiy sub("^[ \t]+", "", $0); 5439d5a8ffSYaroslav Tykhiy sub("[ \t]+$", "", $0); 55ab52e991SDaniel Eischen 5639d5a8ffSYaroslav Tykhiy if (/^[a-zA-Z0-9._]+[ \t]*{$/) { 5739d5a8ffSYaroslav Tykhiy # Strip brace. 5839d5a8ffSYaroslav Tykhiy sub("{", "", $1); 59ab52e991SDaniel Eischen brackets++; 60ab52e991SDaniel Eischen symver = $1; 61ab52e991SDaniel Eischen versions[symver] = 1; 62ab52e991SDaniel Eischen successors[symver] = ""; 636f91e7a3SDaniel Eischen generated[symver] = 0; 64ab52e991SDaniel Eischen version_count++; 65ab52e991SDaniel Eischen } 6639d5a8ffSYaroslav Tykhiy else if (/^}[ \t]*[a-zA-Z0-9._]+[ \t]*;$/) { 6739d5a8ffSYaroslav Tykhiy v = $1 != "}" ? $1 : $2; 6839d5a8ffSYaroslav Tykhiy # Strip brace. 6939d5a8ffSYaroslav Tykhiy sub("}", "", v); 70ab52e991SDaniel Eischen # Strip semicolon. 7139d5a8ffSYaroslav Tykhiy sub(";", "", v); 7239d5a8ffSYaroslav Tykhiy if (symver == "") { 73ab52e991SDaniel Eischen printf("File %s: Unmatched bracket.\n", 74ab52e991SDaniel Eischen vfile) > stderr; 7539d5a8ffSYaroslav Tykhiy errors++; 7639d5a8ffSYaroslav Tykhiy } 7739d5a8ffSYaroslav Tykhiy else if (versions[v] != 1) { 7839d5a8ffSYaroslav Tykhiy printf("File %s: `%s' has unknown " \ 7939d5a8ffSYaroslav Tykhiy "successor `%s'.\n", 8039d5a8ffSYaroslav Tykhiy vfile, symver, v) > stderr; 8139d5a8ffSYaroslav Tykhiy errors++; 8239d5a8ffSYaroslav Tykhiy } 8339d5a8ffSYaroslav Tykhiy else 8439d5a8ffSYaroslav Tykhiy successors[symver] = v; 8539d5a8ffSYaroslav Tykhiy brackets--; 8639d5a8ffSYaroslav Tykhiy } 8739d5a8ffSYaroslav Tykhiy else if (/^}[ \t]*;$/) { 8839d5a8ffSYaroslav Tykhiy if (symver == "") { 8939d5a8ffSYaroslav Tykhiy printf("File %s: Unmatched bracket.\n", 9039d5a8ffSYaroslav Tykhiy vfile) > stderr; 9139d5a8ffSYaroslav Tykhiy errors++; 9239d5a8ffSYaroslav Tykhiy } 93ab52e991SDaniel Eischen # No successor 94ab52e991SDaniel Eischen brackets--; 95ab52e991SDaniel Eischen } 9639d5a8ffSYaroslav Tykhiy else if (/^}$/) { 9739d5a8ffSYaroslav Tykhiy printf("File %s: Missing final semicolon.\n", 98ab52e991SDaniel Eischen vfile) > stderr; 9939d5a8ffSYaroslav Tykhiy errors++; 100ab52e991SDaniel Eischen } 101ab52e991SDaniel Eischen else if (/^$/) 102ab52e991SDaniel Eischen ; # Ignore blank lines. 10339d5a8ffSYaroslav Tykhiy else { 10439d5a8ffSYaroslav Tykhiy printf("File %s: Unknown directive: `%s'.\n", 105ab52e991SDaniel Eischen vfile, $0) > stderr; 10639d5a8ffSYaroslav Tykhiy errors++; 10739d5a8ffSYaroslav Tykhiy } 108ab52e991SDaniel Eischen } 109ab52e991SDaniel Eischen brackets = 0; 110ab52e991SDaniel Eischen} 111ab52e991SDaniel Eischen 11239d5a8ffSYaroslav Tykhiy{ 11339d5a8ffSYaroslav Tykhiy # Set meaningful filename for diagnostics. 11439d5a8ffSYaroslav Tykhiy filename = FILENAME != "" ? FILENAME : "<stdin>"; 11539d5a8ffSYaroslav Tykhiy 116ab52e991SDaniel Eischen # Delete comments, preceding and trailing whitespace, then 117ab52e991SDaniel Eischen # consume blank lines. 118ab52e991SDaniel Eischen sub("#.*$", "", $0); 119ab52e991SDaniel Eischen sub("^[ \t]+", "", $0); 120ab52e991SDaniel Eischen sub("[ \t]+$", "", $0); 121ab52e991SDaniel Eischen if ($0 == "") 122ab52e991SDaniel Eischen next; 123ab52e991SDaniel Eischen} 124ab52e991SDaniel Eischen 12539d5a8ffSYaroslav Tykhiy/^[a-zA-Z0-9._]+[ \t]*{$/ { 126ab52e991SDaniel Eischen # Strip bracket from version name. 127ab52e991SDaniel Eischen sub("{", "", $1); 12839d5a8ffSYaroslav Tykhiy if (current_version != "") { 129ab52e991SDaniel Eischen printf("File %s, line %d: Illegal nesting detected.\n", 13039d5a8ffSYaroslav Tykhiy filename, FNR) > stderr; 13139d5a8ffSYaroslav Tykhiy errors++; 13239d5a8ffSYaroslav Tykhiy } 133ab52e991SDaniel Eischen else if (versions[$1] == 0) { 134ab52e991SDaniel Eischen printf("File %s, line %d: Undefined " \ 13539d5a8ffSYaroslav Tykhiy "library version `%s'.\n", filename, FNR, $1) > stderr; 13639d5a8ffSYaroslav Tykhiy errors++; 137ab52e991SDaniel Eischen # Remove this entry from the versions. 138ab52e991SDaniel Eischen delete versions[$1]; 139ab52e991SDaniel Eischen } 140ab52e991SDaniel Eischen else 141ab52e991SDaniel Eischen current_version = $1; 142ab52e991SDaniel Eischen brackets++; 143ab52e991SDaniel Eischen next; 144ab52e991SDaniel Eischen} 145ab52e991SDaniel Eischen 14639d5a8ffSYaroslav Tykhiy/^[a-zA-Z0-9._]+[ \t]*;$/ { 14739d5a8ffSYaroslav Tykhiy # Strip semicolon. 14839d5a8ffSYaroslav Tykhiy sub(";", "", $1); 149ab52e991SDaniel Eischen if (current_version != "") { 150ab52e991SDaniel Eischen count = versions[current_version]; 151ab52e991SDaniel Eischen versions[current_version]++; 152ab52e991SDaniel Eischen symbols[current_version, count] = $1; 15391fb7b9bSYaroslav Tykhiy if ($1 in names && names[$1] != current_version) { 15491fb7b9bSYaroslav Tykhiy # 15591fb7b9bSYaroslav Tykhiy # A graver case when a dup symbol appears under 15691fb7b9bSYaroslav Tykhiy # different versions in the map. That can result 15791fb7b9bSYaroslav Tykhiy # in subtle problems with the library later. 15891fb7b9bSYaroslav Tykhiy # 15991fb7b9bSYaroslav Tykhiy printf("File %s, line %d: Duplicated symbol `%s' " \ 16091fb7b9bSYaroslav Tykhiy "in version `%s', first seen in `%s'. " \ 16139d5a8ffSYaroslav Tykhiy "Did you forget to move it to ObsoleteVersions?\n", 16291fb7b9bSYaroslav Tykhiy filename, FNR, $1, 16391fb7b9bSYaroslav Tykhiy current_version, names[$1]) > stderr; 16439d5a8ffSYaroslav Tykhiy errors++; 16539d5a8ffSYaroslav Tykhiy } 16691fb7b9bSYaroslav Tykhiy else if (names[$1] == current_version) { 16791fb7b9bSYaroslav Tykhiy # 16891fb7b9bSYaroslav Tykhiy # A harmless case: a dup symbol with the same version. 16991fb7b9bSYaroslav Tykhiy # 17091fb7b9bSYaroslav Tykhiy printf("File %s, line %d: warning: " \ 17191fb7b9bSYaroslav Tykhiy "Duplicated symbol `%s' in version `%s'.\n", 17291fb7b9bSYaroslav Tykhiy filename, FNR, $1, current_version) > stderr; 17391fb7b9bSYaroslav Tykhiy warns++; 17491fb7b9bSYaroslav Tykhiy } 17591fb7b9bSYaroslav Tykhiy else 17691fb7b9bSYaroslav Tykhiy names[$1] = current_version; 17739d5a8ffSYaroslav Tykhiy } 17839d5a8ffSYaroslav Tykhiy else { 17939d5a8ffSYaroslav Tykhiy printf("File %s, line %d: Symbol `%s' outside version scope.\n", 18039d5a8ffSYaroslav Tykhiy filename, FNR, $1) > stderr; 18139d5a8ffSYaroslav Tykhiy errors++; 182ab52e991SDaniel Eischen } 183ab52e991SDaniel Eischen next; 184ab52e991SDaniel Eischen} 185ab52e991SDaniel Eischen 18639d5a8ffSYaroslav Tykhiy/^}[ \t]*;$/ { 187ab52e991SDaniel Eischen brackets--; 188ab52e991SDaniel Eischen if (brackets < 0) { 189ab52e991SDaniel Eischen printf("File %s, line %d: Unmatched bracket.\n", 19039d5a8ffSYaroslav Tykhiy filename, FNR, $1) > stderr; 19139d5a8ffSYaroslav Tykhiy errors++; 192ab52e991SDaniel Eischen brackets = 0; # Reset 193ab52e991SDaniel Eischen } 194ab52e991SDaniel Eischen current_version = ""; 195ab52e991SDaniel Eischen next; 196ab52e991SDaniel Eischen} 197ab52e991SDaniel Eischen 198ab52e991SDaniel Eischen 19939d5a8ffSYaroslav Tykhiy{ 20039d5a8ffSYaroslav Tykhiy printf("File %s, line %d: Unknown directive: `%s'.\n", 20139d5a8ffSYaroslav Tykhiy filename, FNR, $0) > stderr; 20239d5a8ffSYaroslav Tykhiy errors++; 203ab52e991SDaniel Eischen} 204ab52e991SDaniel Eischen 2056f91e7a3SDaniel Eischenfunction print_version(v) 2066f91e7a3SDaniel Eischen{ 2076f91e7a3SDaniel Eischen # This function is recursive, so return if this version 2086f91e7a3SDaniel Eischen # has already been printed. Otherwise, if there is an 2096f91e7a3SDaniel Eischen # ancestral version, recursively print its symbols before 2106f91e7a3SDaniel Eischen # printing the symbols for this version. 2116f91e7a3SDaniel Eischen # 2126f91e7a3SDaniel Eischen if (generated[v] == 1) 2136f91e7a3SDaniel Eischen return; 2146f91e7a3SDaniel Eischen if (successors[v] != "") 2156f91e7a3SDaniel Eischen print_version(successors[v]); 2166f91e7a3SDaniel Eischen 217ab52e991SDaniel Eischen printf("%s {\n", v); 218ab52e991SDaniel Eischen 219ab52e991SDaniel Eischen # The version count is always one more that actual, 220ab52e991SDaniel Eischen # so the loop ranges from 1 to n-1. 221ab52e991SDaniel Eischen # 222ab52e991SDaniel Eischen for (i = 1; i < versions[v]; i++) { 223ab52e991SDaniel Eischen if (i == 1) 224ab52e991SDaniel Eischen printf("global:\n"); 22539d5a8ffSYaroslav Tykhiy printf("\t%s;\n", symbols[v, i]); 226ab52e991SDaniel Eischen } 2279f408248SAlexander Kabaev 2289f408248SAlexander Kabaev version_count--; 2299f408248SAlexander Kabaev if (version_count == 0) { 230ab52e991SDaniel Eischen printf("local:\n"); 231ab52e991SDaniel Eischen printf("\t*;\n"); 232ab52e991SDaniel Eischen } 2339f408248SAlexander Kabaev if (successors[v] == "") 2349f408248SAlexander Kabaev printf("};\n"); 235ab52e991SDaniel Eischen else 236ab52e991SDaniel Eischen printf("} %s;\n", successors[v]); 2376f91e7a3SDaniel Eischen printf("\n"); 2386f91e7a3SDaniel Eischen 2396f91e7a3SDaniel Eischen generated[v] = 1; 2406f91e7a3SDaniel Eischen } 24139d5a8ffSYaroslav Tykhiy 2426f91e7a3SDaniel EischenEND { 24339d5a8ffSYaroslav Tykhiy if (errors) { 24491fb7b9bSYaroslav Tykhiy printf("%d error(s) total.\n", errors) > stderr; 24539d5a8ffSYaroslav Tykhiy exit(1); 24639d5a8ffSYaroslav Tykhiy } 24739d5a8ffSYaroslav Tykhiy # OK, no errors. 2486f91e7a3SDaniel Eischen for (v in versions) { 2496f91e7a3SDaniel Eischen print_version(v); 250ab52e991SDaniel Eischen } 251ab52e991SDaniel Eischen} 252