mirror of
https://github.com/HDFGroup/hdf5.git
synced 2024-11-27 02:10:55 +08:00
06880aeb4d
Tweak make_vers script so that it indents preprocessor commands inside #ifdefs, is more forgiving and informative about the input file's prefix, and is better parameterized with the global variables at the beginning of the script. When major versions are branched from the trunk, the $max_idx value should be the only value that needs to be changed in the version of the script on the trunk. Changes to H5version.h file are just indention. Tested on: Mac OS X/32 10.6.8 (amazon) (too minor to require h5committest)
506 lines
19 KiB
Perl
Executable File
506 lines
19 KiB
Perl
Executable File
#!/usr/bin/perl -w
|
|
require 5.003;
|
|
|
|
# Global settings
|
|
# (The max_idx parameter is the only thing that needs to be changed when adding
|
|
# support for a new major release. If support for a prior major release
|
|
# is added (like support for 1.4, etc), the min_sup_idx parameter will
|
|
# need to be decremented. - QAK)
|
|
|
|
# Max. library "index" (0 = v1.0, 1 = 1.2, etc)
|
|
$max_idx = 5;
|
|
|
|
# Min. supported previous library version "index" (0 = v1.0, 1 = 1.2, etc)
|
|
$min_sup_idx = 3;
|
|
|
|
# Number of spaces to indent preprocessor commands inside ifdefs
|
|
$indent = 2;
|
|
|
|
#
|
|
# Copyright by The HDF Group.
|
|
# Copyright by the Board of Trustees of the University of Illinois.
|
|
# 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 files COPYING and Copyright.html. COPYING can be found at the root
|
|
# of the source code distribution tree; Copyright.html can be found at the
|
|
# root level of an installed copy of the electronic HDF5 document set and
|
|
# is linked from the top-level documents page. It can also be found at
|
|
# http://hdfgroup.org/HDF5/doc/Copyright.html. 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.
|
|
#
|
|
# Programmer: Quincey Koziol
|
|
# Creation Date: 2007/07/10
|
|
|
|
##############################################################################
|
|
# 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 " * Copyright by the Board of Trustees of the University of Illinois. *\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 files COPYING and Copyright.html. COPYING can be found at the root *\n";
|
|
print $fh " * of the source code distribution tree; Copyright.html can be found at the *\n";
|
|
print $fh " * root level of an installed copy of the electronic HDF5 document set and *\n";
|
|
print $fh " * is linked from the top-level documents page. It can also be found at *\n";
|
|
print $fh " * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *\n";
|
|
print $fh " * access to either file, you may request a copy from 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
|
|
my $curr_idx; # Current API version index
|
|
|
|
# Print the option checking
|
|
print $fh "\n/* Issue error if contradicting macros have been defined. */\n";
|
|
|
|
# Print the #ifdef
|
|
print $fh "#if (";
|
|
for $curr_idx ($min_sup_idx .. ($max_idx - 1)) {
|
|
print $fh "defined(H5_USE_1", ($curr_idx * 2), "_API)";
|
|
if($curr_idx < ($max_idx - 1)) {
|
|
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 $curr_idx ($min_sup_idx .. ($max_idx - 1)) {
|
|
print $fh "defined(H5_USE_1", ($curr_idx * 2), "_API)";
|
|
if($curr_idx < ($max_idx - 1)) {
|
|
print $fh " || ";
|
|
}
|
|
}
|
|
print $fh ") && defined(H5_NO_DEPRECATED_SYMBOLS) */\n";
|
|
}
|
|
|
|
##############################################################################
|
|
# Print "global" API version macro settings
|
|
#
|
|
sub print_globalapivers ($) {
|
|
my $fh = shift; # File handle for output file
|
|
my $curr_idx; # Current API version index
|
|
|
|
# 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";
|
|
|
|
for $curr_idx ($min_sup_idx .. ($max_idx - 1)) {
|
|
# Print API version ifdef
|
|
print $fh "#if defined(H5_USE_1", ($curr_idx * 2), "_API_DEFAULT) && !defined(H5_USE_1", ($curr_idx * 2), "_API)\n";
|
|
# Print API version definition
|
|
print $fh " " x $indent, "#define H5_USE_1", ($curr_idx * 2), "_API 1\n";
|
|
# Print API version endif
|
|
print $fh "#endif /* H5_USE_1", ($curr_idx * 2), "_API_DEFAULT && !H5_USE_1", ($curr_idx * 2), "_API */\n\n";
|
|
}
|
|
|
|
# Loop over supported older library APIs and define the appropriate macros
|
|
for $curr_idx ($min_sup_idx .. ($max_idx - 1)) {
|
|
# Print API version ifdef
|
|
print $fh "\n#ifdef H5_USE_1", ($curr_idx * 2), "_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 %{$func_vers[$curr_idx]}) {
|
|
print $fh "\n#if !defined(", $name, "_vers)\n";
|
|
print $fh " " x $indent, "#define ", $name, "_vers $func_vers[$curr_idx]{$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 %{$type_vers[$curr_idx]}) {
|
|
print $fh "\n#if !defined(", $name, "_t_vers)\n";
|
|
print $fh " " x $indent, "#define ", $name, "_t_vers $type_vers[$curr_idx]{$name}\n";
|
|
print $fh "#endif /* !defined(", $name, "_t_vers) */\n";
|
|
}
|
|
|
|
# Print API version endif
|
|
print $fh "\n#endif /* H5_USE_1", ($curr_idx * 2), "_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";
|
|
}
|
|
|
|
##############################################################################
|
|
# 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\n";
|
|
if($line =~ /^\s*FUNCTION:/ || $line =~ /^\s*TYPEDEF:/) {
|
|
my $name; # The name of the function
|
|
my $params; # Typedefs for function parameters
|
|
my $vers; # The version info for the function
|
|
my @vers_list; # Version info, as a list
|
|
my @vers_nums; # Version info, as a numeric list
|
|
my $num_versions; # Number of versions for function
|
|
my %sym_versions; # Versions for a symbol
|
|
my $last_idx; # The previous version index seen for a function
|
|
my $last_vers; # The previous version # seen for a function
|
|
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) = ($line =~ /^\s*FUNCTION:\s*(\w*);\s*(.*?)\s*;\s*(.*?)\s*$/);
|
|
#print "parse_line: name='$name', params='$params', vers='$vers'\n";
|
|
}
|
|
elsif($line =~ /^\s*TYPEDEF:/) {
|
|
$line_type = 2;
|
|
|
|
# Get the typedefs's name & version info
|
|
($name, $vers) = ($line =~ /^\s*TYPEDEF:\s*(\w*);\s*(.*?)\s*$/);
|
|
#print "parse_line: name='$name', vers='$vers'\n";
|
|
}
|
|
#print "parse_line: line_type='$line_type'\n";
|
|
|
|
|
|
# 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";
|
|
}
|
|
|
|
# Split up version info
|
|
@vers_list = split(/\s*,\s*/, $vers);
|
|
#print "parse_line: vers_list=(@vers_list)\n";
|
|
|
|
# Parse the version list into numbers, checking for invalid input
|
|
foreach(@vers_list) {
|
|
my $vers_idx; # Index of version in array
|
|
|
|
# Do some validation on the input
|
|
if(!( $_ =~ /v1[02468]/ || $_ =~ /v11[02468]/ )) {
|
|
die "bad version information: $name";
|
|
}
|
|
if(exists($sym_versions{$_})) {
|
|
die "duplicate version information: $name";
|
|
}
|
|
|
|
# Store the versions for the function in a local hash table, indexed by the version
|
|
$sym_versions{$_}=$_;
|
|
|
|
#print "parse_line: _=$_\n";
|
|
# Get the index of the version
|
|
($vers_idx) = ($_ =~ /v1(\d+)/);
|
|
$vers_idx /= 2;
|
|
#print "parse_line: vers_idx='$vers_idx'\n";
|
|
push(@vers_nums, $vers_idx);
|
|
}
|
|
#print "parse_line: vers_nums=(@vers_nums)\n";
|
|
|
|
# Check for invalid version info given
|
|
$last_idx = -1;
|
|
$last_vers = 1;
|
|
foreach(sort(@vers_nums)) {
|
|
#print "parse_line: _=$_ last_idx='$last_idx'\n";
|
|
# Update intermediate versions of the library that included the API routine
|
|
if($last_idx >= 0) {
|
|
#print "parse_line: name='$name'\n";
|
|
#print "parse_line: last_vers='$last_vers'\n";
|
|
#print "parse_line: last_idx='$last_idx'\n";
|
|
|
|
# Add the function to the list of API routines available in
|
|
# different versions of the library
|
|
while($last_idx <= $_) {
|
|
if($line_type == 1) {
|
|
$func_vers[$last_idx]{$name} = $last_vers;
|
|
} elsif($line_type == 2) {
|
|
$type_vers[$last_idx]{$name} = $last_vers;
|
|
} else {
|
|
die "unknown line type: $line";
|
|
}
|
|
$last_idx++;
|
|
}
|
|
|
|
# Increment the version # of the function
|
|
$last_vers++;
|
|
}
|
|
|
|
# Keep track of last version index seen
|
|
$last_idx = $_;
|
|
}
|
|
|
|
# Finish updating versions of the library that included the API routine
|
|
if($last_idx >= 0) {
|
|
#print "parse_line: max_idx='$max_idx'\n";
|
|
|
|
# Add the function to the list of API routines available in
|
|
# different versions of the library
|
|
while($last_idx <= $max_idx) {
|
|
if($line_type == 1) {
|
|
$func_vers[$last_idx]{$name} = $last_vers;
|
|
} elsif($line_type == 2) {
|
|
$type_vers[$last_idx]{$name} = $last_vers;
|
|
} else {
|
|
die "unknown line type: $line";
|
|
}
|
|
$last_idx++;
|
|
}
|
|
}
|
|
|
|
# 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;
|
|
} else {
|
|
die "unknown line type: $line";
|
|
}
|
|
}
|
|
# 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_checkoptions(*HEADER);
|
|
print_globalapivers(*HEADER);
|
|
print_defaultapivers(*HEADER);
|
|
print_endprotect(*HEADER, $file);
|
|
|
|
# Close header file
|
|
close HEADER;
|
|
}
|
|
|
|
##############################################################################
|
|
# 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 '", $prefix, "H5version.h'\n";
|
|
create_public($prefix);
|
|
|
|
#for $name (sort keys %functions) {
|
|
# print "functions{$name} = $functions{$name}\n";
|
|
#}
|
|
|
|
#for $i (0 .. $#func_vers) {
|
|
# my $vers_name; # Name of indexed version
|
|
# $vers_name = "v1." . ($i * 2);
|
|
# print "$vers_name functions: ";
|
|
# for $name (sort keys %{$func_vers[$i]}) {
|
|
# print "$name$func_vers[$i]{$name} ";
|
|
# }
|
|
# print "\n";
|
|
#}
|
|
|
|
}
|
|
|