Files
hdf5/bin/make_vers
Scot Breitenfeld cbff0315f3 Default versioned API functions to earliest version for older API settings (#6280)
When a global API version is set (e.g., H5_USE_16_API), functions
introduced after that version now default to their earliest version
(version 1) instead of the latest. This prevents breakage when an
application uses an older API setting but calls functions that were
later versioned.
2026-04-07 11:06:32 -05:00

725 lines
28 KiB
Perl
Executable File

#!/usr/bin/env perl
require 5.003;
use warnings;
# Global settings
# Supported version strings. "16" = HDF5 1.6.0, "200" = HDF5 2.0.0, etc.
#
# Note that the scheme changed with 2.0.0, when we went to semantic versioning.
# We use 200 instead of 20 so that HDF5 11.0.0 will get 1100 instead of 110,
# which would conflict with HDF5 1.10.
#
# Also, note that this scheme started at the 1.6/1.8 transition, so earlier
# versions of the API aren't versioned.
@versions = ("16", "18", "110", "112", "114", "200");
# Number of spaces to indent preprocessor commands inside ifdefs
$indent = 2;
# Global hash of functions ==> # symbol versions parsed from H5vers.txt
$functions = {};
# Global hash of functions ==> versioned function params parsed from H5vers.txt
$func_params = {};
# Global hash of typedefs ==> # symbol versions parsed from H5vers.txt
$typedefs = {};
# Hash of API versions to a hash of (API call name --> symbol version)
#
# There is one hash for each version in @versions and the (API call name
# --> symbol version) hash maps an API name like H5Dopen to the symbol version
# (e.g. H5Dopen --> 1 or 2).
#
# So...
#
# 200 --> {H5Dopen --> 2, H5Iregister_type --> 2, etc.}
my %api_vers_to_function_vers;
foreach my $key (@versions) {
$api_vers_to_function_vers{$key} = {};
}
# Hash of API versions to a hash of (typedef name --> symbol version)
my %api_vers_to_type_vers;
foreach my $key (@versions) {
$api_vers_to_type_vers{$key} = {};
}
#
# Copyright by The HDF Group.
# All rights reserved.
#
# This file is part of HDF5. The full HDF5 copyright notice, including
# terms governing use, modification, and redistribution, is contained in
# the LICENSE file, which can be found at the root of the source code
# distribution tree, or in https://www.hdfgroup.org/licenses.
# If you do not have access to either file, you may request a copy from
# help@hdfgroup.org.
#
# Create public symbol version headers
#
# Read in the public symbol version description text file and create the
# appropriate headers needed by the library.
#
##############################################################################
# Print the copyright into an open file
#
sub print_copyright ($) {
my $fh = shift;
print $fh "/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n";
print $fh " * Copyright by The HDF Group. *\n";
print $fh " * All rights reserved. *\n";
print $fh " * *\n";
print $fh " * This file is part of HDF5. The full HDF5 copyright notice, including *\n";
print $fh " * terms governing use, modification, and redistribution, is contained in *\n";
print $fh " * the LICENSE file, which can be found at the root of the source code *\n";
print $fh " * distribution tree, or in https://www.hdfgroup.org/licenses. *\n";
print $fh " * If you do not have access to either file, you may request a copy from *\n";
print $fh " * help\@hdfgroup.org. *\n";
print $fh " * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */\n";
}
##############################################################################
# Print the "do not change this file" warning
#
sub print_warning ($) {
my $fh = shift;
print $fh "\n/* Generated automatically by bin/make_vers -- do not edit */\n";
print $fh "/* Add new versioned symbols to H5vers.txt file */\n\n";
}
##############################################################################
# Print start of ifdef's to prevent a file from being re-included
#
sub print_startprotect ($$) {
my ($fh, $file) = @_;
# Clip off the ".h" part of the name
$file =~ s/(\w*)\.h/$1/;
# Print the ifdef info
print $fh "\n#ifndef ${file}_H\n";
print $fh "#define ${file}_H\n";
}
##############################################################################
# Print check for conflicting version macro settings
#
sub print_checkoptions ($) {
my $fh = shift; # File handle for output file
# Print the option checking
print $fh "\n\n/* Issue error if contradicting macros have been defined. */\n";
print $fh "/* (Can't use an older (deprecated) API version if deprecated symbols have been disabled) */\n";
# Print the #ifdef
print $fh "#if (";
for my $i (0 .. $#versions - 1) {
print $fh "defined(H5_USE_", $versions[$i], "_API)";
# -2 because we're ignoring the last version in the array, and the
# last version we DO write out can't have an || after it
if ($i < @versions - 2) {
print $fh " || ";
}
}
print $fh ") && defined(H5_NO_DEPRECATED_SYMBOLS)\n";
# Print the error for bad API version chosen
print $fh ' ' x $indent, "#error \"Can't choose old API versions when deprecated APIs are disabled\"\n";
# Print the #endif
print $fh "#endif /* (";
for my $i (0 .. $#versions - 1) {
print $fh "defined(H5_USE_", $versions[$i], "_API)";
if ($i < @versions - 2) {
print $fh " || ";
}
}
print $fh ") && defined(H5_NO_DEPRECATED_SYMBOLS) */\n";
}
##############################################################################
# Print "global" API version macro settings
#
sub print_globalapidefvers ($) {
my $fh = shift; # File handle for output file
# Print the descriptive comment
print $fh "\n\n/* If a particular default \"global\" version of the library's interfaces is\n";
print $fh " * chosen, set the corresponding version macro for API symbols.\n";
print $fh " *\n";
print $fh " */\n";
for my $api_vers (@versions) {
# Print API version ifdef
print $fh "\n#if defined(H5_USE_", $api_vers, "_API_DEFAULT) && !defined(H5_USE_", $api_vers, "_API)\n";
# Print API version definition
print $fh " " x $indent, "#define H5_USE_", $api_vers, "_API 1\n";
# Print API version endif
print $fh "#endif /* H5_USE_", $api_vers, "_API_DEFAULT && !H5_USE_", $api_vers, "_API */\n";
}
}
##############################################################################
# Print "global" API symbol version macro settings
#
sub print_globalapisymbolvers ($) {
my $fh = shift; # File handle for output file
# Print the descriptive comment
print $fh "\n\n/* If a particular \"global\" version of the library's interfaces is chosen,\n";
print $fh " * set the versions for the API symbols affected.\n";
print $fh " *\n";
print $fh " * Note: If an application has already chosen a particular version for an\n";
print $fh " * API symbol, the individual API version macro takes priority.\n";
print $fh " */\n";
# Loop over supported older library APIs and define the appropriate macros
foreach my $api_vers (@versions) {
# Print API version ifdef
print $fh "\n#ifdef H5_USE_", $api_vers, "_API\n";
# Print the version macro info for each function that is defined for
# this API version
print $fh "\n/*************/\n";
print $fh "/* Functions */\n";
print $fh "/*************/\n";
for $name (sort keys %{$api_vers_to_function_vers{$api_vers}}) {
print $fh "\n#if !defined(", $name, "_vers)\n";
print $fh " " x $indent, "#define ", $name, "_vers $api_vers_to_function_vers{$api_vers}{$name}\n";
print $fh "#endif /* !defined(", $name, "_vers) */\n";
}
# Print the version macro info for each typedef that is defined for
# this API version
print $fh "\n/************/\n";
print $fh "/* Typedefs */\n";
print $fh "/************/\n";
for $name (sort keys %{$api_vers_to_type_vers{$api_vers}}) {
print $fh "\n#if !defined(", $name, "_t_vers)\n";
print $fh " " x $indent, "#define ", $name, "_t_vers $api_vers_to_type_vers{$api_vers}{$name}\n";
print $fh "#endif /* !defined(", $name, "_t_vers) */\n";
}
# Print API version endif
print $fh "\n#endif /* H5_USE_", $api_vers, "_API */\n";
}
}
##############################################################################
# Print "default" API version macro settings
#
sub print_defaultapivers ($) {
my $fh = shift; # File handle for output file
my $curr_name; # Current API function
# Print the descriptive comment
print $fh "\n\n/* Choose the correct version of each API symbol, defaulting to the latest\n";
print $fh " * version of each. The \"best\" name for API parameters/data structures\n";
print $fh " * that have changed definitions is also set. An error is issued for\n";
print $fh " * specifying an invalid API version.\n";
print $fh " */\n";
# Loop over function names that are versioned and set up the version macros
print $fh "\n/*************/\n";
print $fh "/* Functions */\n";
print $fh "/*************/\n";
for $curr_name (sort keys %functions) {
my $curr_vers_name; # Name of version macro for current function
my $curr_vers; # Version of function
my @param_list; # Typedefs for the function parameters
# Set up variables for later use
$curr_vers_name = $curr_name . "_vers";
$curr_vers = $functions{$curr_name};
# Split up parameter info
@param_list = split(/\s*,\s*/, $func_params{$curr_name});
#print "print_defaultapivers: param_list=(@param_list)\n";
# Set up default/latest version name mapping
print $fh "\n#if !defined($curr_vers_name) || $curr_vers_name == $curr_vers\n";
print $fh " " x $indent, "#ifndef $curr_vers_name\n";
print $fh " " x ($indent * 2), "#define $curr_vers_name $curr_vers\n";
print $fh " " x $indent, "#endif /* $curr_vers_name */\n";
print $fh " " x $indent, "#define $curr_name $curr_name$curr_vers\n";
# Print function's dependent parameter types
foreach (sort (@param_list)) {
print $fh " " x $indent, "#define ${_}_t $_${curr_vers}_t\n";
}
# Loop to print earlier version name mappings
$curr_vers--;
while($curr_vers > 0) {
print $fh "#elif $curr_vers_name == $curr_vers\n";
print $fh " " x $indent, "#define $curr_name $curr_name$curr_vers\n";
# Print function's dependent parameter types
foreach (sort (@param_list)) {
print $fh " " x $indent, "#define ${_}_t $_${curr_vers}_t\n";
}
$curr_vers--;
}
# Finish up with error for unknown version and endif
print $fh "#else /* $curr_vers_name */\n";
print $fh " " x $indent, "#error \"$curr_vers_name set to invalid value\"\n";
print $fh "#endif /* $curr_vers_name */\n";
}
# Loop over typedefs that are versioned and set up the version macros
print $fh "\n/************/\n";
print $fh "/* Typedefs */\n";
print $fh "/************/\n";
for $curr_name (sort keys %typedefs) {
my $curr_vers_name; # Name of version macro for current function
my $curr_vers; # Version of function
# Set up variables for later use
$curr_vers_name = $curr_name . "_t_vers";
$curr_vers = $typedefs{$curr_name};
# Set up default/latest version name mapping
print $fh "\n#if !defined($curr_vers_name) || $curr_vers_name == $curr_vers\n";
print $fh " " x $indent, "#ifndef $curr_vers_name\n";
print $fh " " x ($indent * 2), "#define $curr_vers_name $curr_vers\n";
print $fh " " x $indent, "#endif /* $curr_vers_name */\n";
print $fh " " x $indent, "#define ${curr_name}_t $curr_name${curr_vers}_t\n";
# Loop to print earlier version name mappings
$curr_vers--;
while ($curr_vers > 0) {
print $fh "#elif $curr_vers_name == $curr_vers\n";
print $fh " " x $indent, "#define ${curr_name}_t $curr_name${curr_vers}_t\n";
$curr_vers--;
}
# Finish up with error for unknown version and endif
print $fh "#else /* $curr_vers_name */\n";
print $fh " " x $indent, "#error \"$curr_vers_name set to invalid value\"\n";
print $fh "#endif /* $curr_vers_name */\n\n";
}
}
##############################################################################
# Print end of ifdef's to prevent a file from being re-included
#
sub print_endprotect ($$) {
my ($fh, $file) = @_;
# Clip off the ".h" part of the name
$file =~ s/(\w*)\.h/$1/;
# Print the endif info
print $fh "#endif /* ${file}_H */\n\n";
}
##############################################################################
# Validate a line from H5vers.txt
#
sub validate_line {
my $name = $_[0];
my $params = $_[1];
my $vers = $_[2];
my @vers_list; # Version strings ("v18", etc.)
my %sym_versions; # Versions already seen (for duplicate checks)
# Check if the name already exists in the list of symbols
if (exists ($functions{$name}) || exists($typedefs{$name})) {
die "duplicated symbol: $name";
}
# Check for no version info given
if ($vers eq "") {
die "no version information: $name";
}
# Separate the versions on commas (produces string elements like "v18")
@vers_list = split (/\s*,\s*/, $vers);
# Check for invalid version data
foreach (@vers_list) {
# Note: v111 is allowed because H5O functions were prematurely versioned
# in HDF5 1.10. Because users were affected by this, the versioning
# was rescinded but the H5O version 2 functions were kept to be
# called directly. Now that the version macros are added in 1.12,
# along with a 3rd version of the H5O functions, the H5O function
# version for default api=v110 should be version 1 to work correctly
# with 1.10 applications that were using unversioned H5O functions,
# and the H5O function version should be version 3 for default api=v112
# (the default api version for 1.12). Allowing a v111 entry allows
# a version 2 that is never accessed via the H5O function macros.
if (!( $_ =~ /v1[02468]/ || $_ =~ /v11[02468]/ || $_ =~ /v111/ || $_ =~ /v200/ )) {
die "bad version information: $name";
}
# Make sure we didn't specify duplicate versions on this line
if (exists($sym_versions{$_})) {
die "duplicate version information: $name";
}
# Store the versions for the function in a local hash table, indexed by the version
# (this is only used to check for duplicates)
$sym_versions{$_}=$_;
}
}
##############################################################################
# Parse a meaningful line (not a comment or blank line) into the appropriate
# data structure
#
sub parse_line ($) {
my $line = shift; # Get the line to parse
# Parse API function lines
#print "line=$line";
if ($line =~ /^\s*FUNCTION:/ || $line =~ /^\s*TYPEDEF:/) {
my $name; # The name of the function
my $params; # Typedefs for function parameters
my $vers_string; # The version info for the function
my @vers_list; # Version info, as a list (e.g., "112", "200", etc.
my $line_type; # Type of line we are parsing
# Determine the type of the line to parse
if ($line =~ /^\s*FUNCTION:/) {
$line_type = 1;
# Get the function's name & version info
($name, $params, $vers_string) = ($line =~ /^\s*FUNCTION:\s*(\w*);\s*(.*?)\s*;\s*(.*?)\s*$/);
#print "parse_line: name='$name', params='$params', vers_string='$vers_string'\n";
}
elsif ($line =~ /^\s*TYPEDEF:/) {
$line_type = 2;
# Get the typedefs's name & version info
($name, $vers_string) = ($line =~ /^\s*TYPEDEF:\s*(\w*);\s*(.*?)\s*$/);
#print "parse_line: name='$name', vers_string='$vers_string'\n";
} else {
die "unknown line type: $line";
}
#print "parse_line: line_type='$line_type'\n";
validate_line($name, $params, $vers_string);
# Split the version info and strip off the leading "v"
@vers_list = split(/\s*,\s*/, $vers_string);
@vers_list = map { substr($_, 1) } @vers_list;
#print "parse_line: vers_list=(@vers_list)\n";
# Parse the version list into the hashes of version and type info
my $curr_sym_number = 1;
foreach my $vers (@vers_list) {
foreach my $hash_vers (@versions) {
if ($vers > $hash_vers) {
next;
} else {
if ($line_type == 1) {
$api_vers_to_function_vers{$hash_vers}{$name} = $curr_sym_number;
} else {
$api_vers_to_type_vers{$hash_vers}{$name} = $curr_sym_number;
}
}
}
$curr_sym_number++;
}
# For API versions earlier than the function's introduction,
# default to the earliest version (version 1) for maximum compatibility
my $intro_vers = $vers_list[0];
foreach my $hash_vers (@versions) {
if ($hash_vers < $intro_vers) {
if ($line_type == 1) {
$api_vers_to_function_vers{$hash_vers}{$name} = 1;
} else {
$api_vers_to_type_vers{$hash_vers}{$name} = 1;
}
}
}
# Store the number of symbol versions in a hash table, indexed by the name
if ($line_type == 1) {
$functions{$name} = $#vers_list + 1;
# Store the function's parameter types for later
$func_params{$name} = $params;
} elsif ($line_type == 2) {
$typedefs{$name} = $#vers_list + 1;
}
#print "\n";
}
# Unknown keyword
else {
die "unknown keyword: $line";
}
}
##############################################################################
# Create the generated portion of the public header file
#
sub create_public ($) {
my $prefix = shift; # Get the prefix for the generated file
my $file = "H5version.h"; # Name of file to generate
my $name; # Name of function
# Rename previous file
# rename "${prefix}${file}", "${prefix}${file}~" or die "unable to make backup";
# Open new header file
open HEADER, ">${prefix}${file}" or die "unable to modify source";
# Create file contents
print_copyright(*HEADER);
print_warning(*HEADER);
print_startprotect(*HEADER, $file);
print_globalapidefvers(*HEADER);
print_checkoptions(*HEADER);
print_globalapisymbolvers(*HEADER);
print_defaultapivers(*HEADER);
print_endprotect(*HEADER, $file);
# Close header file
close HEADER;
}
##############################################################################
# Create the generated CMake file for Doxygen PREDEFINED macros
#
sub create_doxygen_cmake ($) {
my $prefix = shift; # Get the prefix for the source file (e.g., "src/")
my $file = "H5version_doxygen.cmake"; # Name of file to generate
# Output to doxygen directory (relative to src/)
my $doxygen_dir = $prefix;
$doxygen_dir =~ s/src\/?$/docs\/doxygen\//; # Replace "src/" with "docs/doxygen/"
# Create doxygen directory if it doesn't exist
if ($doxygen_dir ne "" && ! -d $doxygen_dir) {
mkdir $doxygen_dir or die "unable to create directory: $doxygen_dir";
}
# Open new cmake file in doxygen directory
open CMAKE, ">${doxygen_dir}${file}" or die "unable to create doxygen cmake file: ${doxygen_dir}${file}";
# Create file contents
print CMAKE "# Generated automatically by bin/make_vers -- do not edit\n";
print CMAKE "# Add new versioned symbols to H5vers.txt file\n";
print CMAKE "#\n";
print CMAKE "# Doxygen PREDEFINED entries for versioned APIs\n";
print CMAKE "# These macros tell Doxygen which version each API name maps to,\n";
print CMAKE "# preventing \"multiple \@param documentation sections\" warnings\n";
print CMAKE "\n";
print CMAKE "list (APPEND _doxygen_predefined_entries\n";
# Add function version macros (sorted for consistency)
for my $name (sort keys %functions) {
my $vers = $functions{$name};
print CMAKE " \"$name=$name$vers\"\n";
}
print CMAKE ")\n";
# Close cmake file
close CMAKE;
}
##############################################################################
# Create the generated test file for verifying API version defaulting
#
sub create_test ($) {
my $prefix = shift; # Get the prefix for the source file (e.g., "src/")
my $file = "tapi_version_default.c";
# Output to test directory (relative to src/)
my $test_dir = $prefix;
$test_dir =~ s/src\/?$/test\//;
# Validate the substitution succeeded
if ($test_dir eq $prefix && $prefix ne "") {
die "create_test: prefix '$prefix' does not end in 'src/' -- cannot derive test directory";
}
# Create test directory if it doesn't exist
if ($test_dir ne "" && ! -d $test_dir) {
mkdir $test_dir or die "unable to create directory: $test_dir";
}
# Open new test file
open TEST, ">${test_dir}${file}" or die "unable to create test file: ${test_dir}${file}";
# Print copyright and warning
print_copyright(*TEST);
print_warning(*TEST);
# Print test description
print TEST "/*\n";
print TEST " * Purpose: Tests that versioned API function macros default to the earliest\n";
print TEST " * version for functions introduced after the configured global API\n";
print TEST " * version. For example, with H5_USE_16_API, H5Sencode (introduced\n";
print TEST " * in v1.8) should map to H5Sencode1, not H5Sencode2.\n";
print TEST " *\n";
print TEST " * This test is compiled multiple times with different\n";
print TEST " * -DH5_USE_*_API and -DTEST_API_VERSION=* flags to verify each\n";
print TEST " * API version level.\n";
print TEST " */\n";
# Emit preamble that clears all global API version defaults.
# When the project is configured with a default API version (e.g.,
# HDF5_DEFAULT_API_VERSION=v16), H5pubconf.h defines H5_USE_16_API_DEFAULT,
# which causes H5version.h to activate H5_USE_16_API. If the test also
# defines -DH5_USE_200_API, both blocks would be active and the earliest
# one wins (setting everything to version 1). To isolate each test to
# exactly one API version, we include H5pubconf.h first (setting its
# include guard), then #undef all API version macros, and re-establish
# only the version under test before including the rest of the headers.
print TEST "/* Include config header first to set its include guard */\n";
print TEST "#include \"H5pubconf.h\"\n\n";
print TEST "/* Clear all API version macros that may have been set by the\n";
print TEST " * global default configuration, so only the version under test\n";
print TEST " * is active when H5version.h is processed.\n";
print TEST " */\n";
foreach my $api_vers (@versions) {
print TEST "#undef H5_USE_${api_vers}_API_DEFAULT\n";
print TEST "#undef H5_USE_${api_vers}_API\n";
}
print TEST "\n";
print TEST "/* Re-establish only the API version under test */\n";
my $first_preamble = 1;
foreach my $api_vers (@versions) {
if ($first_preamble) {
print TEST "#if TEST_API_VERSION == $api_vers\n";
$first_preamble = 0;
}
else {
print TEST "#elif TEST_API_VERSION == $api_vers\n";
}
print TEST " #define H5_USE_${api_vers}_API 1\n";
}
print TEST "#else\n";
print TEST " #error \"TEST_API_VERSION not set to a valid value\"\n";
print TEST "#endif\n\n";
print TEST "#include \"h5test.h\"\n\n";
# Print CHECK_VERS macro for functions
print TEST "/*\n";
print TEST " * Helper macro: check that a _vers macro equals an expected value.\n";
print TEST " */\n";
print TEST "#define CHECK_VERS(func_name, expected) \\\n";
print TEST " do { \\\n";
print TEST " if (func_name##_vers != (expected)) { \\\n";
print TEST " fprintf(stderr, \"FAIL: %s_vers = %d, expected %d\\n\", \\\n";
print TEST " #func_name, func_name##_vers, (expected)); \\\n";
print TEST " nerrors++; \\\n";
print TEST " } \\\n";
print TEST " } while (0)\n\n";
# Print CHECK_VERS_T macro for typedefs
print TEST "#define CHECK_VERS_T(type_name, expected) \\\n";
print TEST " do { \\\n";
print TEST " if (type_name##_t_vers != (expected)) { \\\n";
print TEST " fprintf(stderr, \"FAIL: %s_t_vers = %d, expected %d\\n\", \\\n";
print TEST " #type_name, type_name##_t_vers, (expected)); \\\n";
print TEST " nerrors++; \\\n";
print TEST " } \\\n";
print TEST " } while (0)\n\n";
# Print main function
print TEST "int\n";
print TEST "main(void)\n";
print TEST "{\n";
print TEST " int nerrors = 0;\n\n";
print TEST " TESTING(\"API version defaulting for versioned functions\");\n\n";
# Generate test sections for each API version
my $first = 1;
foreach my $api_vers (@versions) {
if ($first) {
print TEST "#if TEST_API_VERSION == $api_vers\n";
$first = 0;
}
else {
print TEST "#elif TEST_API_VERSION == $api_vers\n";
}
print TEST " printf(\"Configured with H5_USE_${api_vers}_API\\n\");\n\n";
# Print checks for all functions at this API version
for my $name (sort keys %{$api_vers_to_function_vers{$api_vers}}) {
my $expected = $api_vers_to_function_vers{$api_vers}{$name};
print TEST " CHECK_VERS($name, $expected);\n";
}
print TEST "\n";
# Print checks for all typedefs at this API version
for my $name (sort keys %{$api_vers_to_type_vers{$api_vers}}) {
my $expected = $api_vers_to_type_vers{$api_vers}{$name};
print TEST " CHECK_VERS_T($name, $expected);\n";
}
print TEST "\n";
}
# Close the #if/#elif chain
print TEST "#else\n";
print TEST "#error \"TEST_API_VERSION not set to a valid value\"\n";
print TEST "#endif\n\n";
# Print result checking and return
print TEST " if (nerrors) {\n";
print TEST " H5_FAILED();\n";
print TEST " fprintf(stderr, \" %d version check%s failed\\n\", nerrors, nerrors > 1 ? \"s\" : \"\");\n";
print TEST " return 1;\n";
print TEST " }\n\n";
print TEST " PASSED();\n";
print TEST " return 0;\n";
print TEST "}\n";
# Close test file
close TEST;
}
##############################################################################
# Read symbol version file (given as command-line argument) in and process it
# into internal data structures, then create header files.
#
for $file (@ARGV) {
my $prefix; # Local prefix for generated files
#print "file = '$file'\n";
# Check for directory prefix on input file
if ($file =~ /\//) {
($prefix) = ($file =~ /(^.*\/)/);
}
else {
$prefix = "";
}
#print "prefix = '$prefix'\n";
# Read in the entire file
open SOURCE, $file or die "$file: $!\n";
while ( defined ($line = <SOURCE>) ) {
# Skip blank lines and those lines whose first character is a '#'
if (!($line =~ /(^\s*#.*$)|(^\s*$)/)) {
# Construct data structures for later printing
parse_line($line);
}
}
close SOURCE;
# Create header files
print "Generating 'H5version.h'\n";
create_public($prefix);
print "Generating 'docs/doxygen/H5version_doxygen.cmake'\n";
create_doxygen_cmake($prefix);
print "Generating 'test/tapi_version_default.c'\n";
create_test($prefix);
}