#!/usr/bin/perl -w #use strict; use vars qw($top %used_defines %set_defines); use File::Find; use Getopt::Long; use Config; # # Do a perl check for version >= 5.005. See 'gpt-translate-interpreter' should you # need to alter the invocation path to a valid perl interpreter in the GPT front-end # programs. # if ( ! ( defined eval "require 5.005" ) ) { die "GPT requires at least Perl version 5.005"; } my $gpath = $ENV{GPT_LOCATION}; if (!defined($gpath)) { $gpath = $ENV{GLOBUS_LOCATION}; } if (!defined($gpath)) { die "GPT_LOCATION or GLOBUS_LOCATION needs to be set before running this script" } @INC = ("$gpath/lib/perl", "$gpath/lib/perl/$Config{'archname'}", @INC); if ( ! ( defined eval "require Grid::GPT::GPTObject" ) ) { die("$gpath does not appear to hold a valid GPT installation\n"); } require Pod::Usage; $top = "."; my ($config, $disable_undefs); my $verbose = 0; my ($help, $man, $version); # sub pod2usage { # my $ex = shift; # print "gpt_undefines [-srcdir=PATH -config -disable-undefs -verbose -help] headers containing defines\n"; # exit $ex; # } GetOptions( 'srcdir=s' => \$top, 'config' => \$config, 'disable-undefs' => \$disable_undefs, 'verbose=i' => \$verbose, 'help' => \$help,'version' => \$version) or Pod::Usage::pod2usage(1); Pod::Usage::pod2usage(0) if $help; require Grid::GPT::GPTIdentity; Grid::GPT::GPTIdentity::print_gpt_version() if defined $version; for my $h (@ARGV) { scan_for_def_cmds($h, 1); } find(\&globus_sh, $top); my $word; if (defined($config)) { for $word (sort keys %used_defines) { next if (defined($set_defines{$word})); print "#ifndef $word\n"; print "#undef $word\n"; print "#endif\n"; } } else { for $word (sort keys %used_defines) { next if (defined($set_defines{$word})); print "$word :\n"; for (sort keys %{$used_defines{$word}}) { print "\t$_\n"; } print "\n\n"; } } sub globus_sh { if (! -f "$_") { return; } if (! -T "$_") { return; } if (!/\.[Cch]$/) { return; } if (/config\.h/) { return; } my $file = $_; scan_for_def_cmds($file); $_ = $file; } sub scan_for_def_cmds { my ($file, $just_defines) = @_; open (FILE,"<$file"); my $line_continuation = "no"; my $isifdef = "no"; while () { my $macro_buffer; # process a line continuation if ($line_continuation eq "yes") { $macro_buffer .= $_; $line_continuation = "no"; } # scan for #if?def's if (/^\s*\#if/) { if (m!\\$!) { $line_continuation = "yes"; } $macro_buffer = $_; $isifdef = "yes"; next if defined($just_defines); } # scan for #define's if (/^\s*\#def/) { if (m!\\$!) { $line_continuation = "yes"; } $macro_buffer = $_; $isifdef = "no"; } # scan for #undef's including those commented out if (m!^/\*\s*\#undef! and ! defined($disable_undefs)) { # remove comment so that line doesn't get stripped s!^/\*!!; if (m!\\$!) { $line_continuation = "yes"; } $macro_buffer = $_; $isifdef = "no"; } if (defined($macro_buffer)) { # print $macro_buffer; my $keywrds = { if =>1, defined =>1, ifdef =>1, ifndef =>1, define =>1, 0 => 1, 1 => 1 }; # print $macro_buffer; # Remove comments for the buffer $macro_buffer =~ s!/\*.+$!!g; # print $macro_buffer; # extract all of the words out of the buffer while ($macro_buffer =~ m/(\w+)/g) { my $word = $1; # skip C keywords next if (defined($keywrds->{$word})); # decide which hash to put the word in. my $wordlist = \%set_defines; $wordlist = \%used_defines if ($isifdef eq "yes"); # create the has if it doesn't exist if (!defined($wordlist->{$word})) { $wordlist->{$word} = {}; } # fill in the hash entry my $fullname = $file; if (defined($File::Find::name)) { $fullname = $File::Find::name; $fullname =~ s!$top!!; } $wordlist->{$word}->{$fullname} = 1; } } } close FILE; } =head1 NAME B - Generate a list of preprocessor macros that are not defined. =head1 SYNOPSIS gpt_undefines [-srcdir=PATH -config -disable-undefs -verbose -help] headers containing defines =head1 DESCRIPTION B Generates a list of preprocessor macros that are not defined internally in the source code. Macros that are defined in the header files listed during B's invocation will also be excluded. =head1 OPTIONS =over 4 =item -srcdir=PATH Use PATH as the directory containing the source code. Source code in the entire directory tree will be scanned. Default PATH is the directory B was invoked in. =item -config Prints the list out in a format that can be pasted into an installable header file. =item -disable-undefs Do not count commented out undefines as a define. This technique is used by autoconf to indicate a negative test result. Example: /* #undef HAVE_TCP_FASTACK */ =back =head1 Managing Autoconf defines. By default the defines tested for by the configure script are stored in a file called B. This file should never be installed. to add autoconf defines to config.h simply add the define in the following format to the file acconfig.h: #undef AUTOCONF_DEFINE acconfig.h is tranformed into a config.h.in by the script B. Then the configure script transform it into config.h. A problem occurs when the autoconf defines are used in installed header files. In this case the defines should be put in an installable header file using the following format: #ifndef AUTOCONF_DEFINE #undef AUTOCONF_DEFINE #endif =head1 SEE ALSO autoconf(1) autoheader(1) =head1 AUTHOR Michael Bletzinger Embletzin.ncsa.uiuc.eduE and Eric Blau Eeblau.ncsa.uiuc.eduE =cut