Blame bin/autoscan.in

Packit 47b4ca
#! @PERL@ -w
Packit 47b4ca
# -*- perl -*-
Packit 47b4ca
# @configure_input@
Packit 47b4ca
Packit 47b4ca
# autoscan - Create configure.scan (a preliminary configure.ac) for a package.
Packit 47b4ca
# Copyright (C) 1994, 1999-2012 Free Software Foundation, Inc.
Packit 47b4ca
Packit 47b4ca
# This program is free software: you can redistribute it and/or modify
Packit 47b4ca
# it under the terms of the GNU General Public License as published by
Packit 47b4ca
# the Free Software Foundation, either version 3 of the License, or
Packit 47b4ca
# (at your option) any later version.
Packit 47b4ca
Packit 47b4ca
# This program is distributed in the hope that it will be useful,
Packit 47b4ca
# but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 47b4ca
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 47b4ca
# GNU General Public License for more details.
Packit 47b4ca
Packit 47b4ca
# You should have received a copy of the GNU General Public License
Packit 47b4ca
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
Packit 47b4ca
Packit 47b4ca
# Written by David MacKenzie <djm@gnu.ai.mit.edu>.
Packit 47b4ca
Packit 47b4ca
eval 'case $# in 0) exec @PERL@ -S "$0";; *) exec @PERL@ -S "$0" "$@";; esac'
Packit 47b4ca
    if 0;
Packit 47b4ca
Packit 47b4ca
BEGIN
Packit 47b4ca
{
Packit 47b4ca
  my $pkgdatadir = $ENV{'autom4te_perllibdir'} || '@pkgdatadir@';
Packit 47b4ca
  unshift @INC, $pkgdatadir;
Packit 47b4ca
Packit 47b4ca
  # Override SHELL.  On DJGPP SHELL may not be set to a shell
Packit 47b4ca
  # that can handle redirection and quote arguments correctly,
Packit 47b4ca
  # e.g.: COMMAND.COM.  For DJGPP always use the shell that configure
Packit 47b4ca
  # has detected.
Packit 47b4ca
  $ENV{'SHELL'} = '@SHELL@' if ($^O eq 'dos');
Packit 47b4ca
}
Packit 47b4ca
Packit 47b4ca
use Autom4te::ChannelDefs;
Packit 47b4ca
use Autom4te::Configure_ac;
Packit 47b4ca
use Autom4te::General;
Packit 47b4ca
use Autom4te::FileUtils;
Packit 47b4ca
use Autom4te::XFile;
Packit 47b4ca
use File::Basename;
Packit 47b4ca
use File::Find;
Packit 47b4ca
use strict;
Packit 47b4ca
Packit 47b4ca
use vars qw(@cfiles @makefiles @shfiles @subdirs %printed);
Packit 47b4ca
Packit 47b4ca
# The kind of the words we are looking for.
Packit 47b4ca
my @kinds = qw (function header identifier program
Packit 47b4ca
		makevar librarie);
Packit 47b4ca
Packit 47b4ca
# For each kind, the default macro.
Packit 47b4ca
my %generic_macro =
Packit 47b4ca
  (
Packit 47b4ca
   'function'   => 'AC_CHECK_FUNCS',
Packit 47b4ca
   'header'     => 'AC_CHECK_HEADERS',
Packit 47b4ca
   'identifier' => 'AC_CHECK_TYPES',
Packit 47b4ca
   'program'    => 'AC_CHECK_PROGS',
Packit 47b4ca
   'library'    => 'AC_CHECK_LIB'
Packit 47b4ca
  );
Packit 47b4ca
Packit 47b4ca
my %kind_comment =
Packit 47b4ca
  (
Packit 47b4ca
   'function'   => 'Checks for library functions.',
Packit 47b4ca
   'header'     => 'Checks for header files.',
Packit 47b4ca
   'identifier' => 'Checks for typedefs, structures, and compiler characteristics.',
Packit 47b4ca
   'program'    => 'Checks for programs.',
Packit 47b4ca
  );
Packit 47b4ca
Packit 47b4ca
# $USED{KIND}{ITEM} is the list of locations where the ITEM (of KIND) was used
Packit 47b4ca
# in the user package.
Packit 47b4ca
# For instance $USED{function}{alloca} is the list of `file:line' where
Packit 47b4ca
# `alloca (...)' appears.
Packit 47b4ca
my %used = ();
Packit 47b4ca
Packit 47b4ca
# $MACRO{KIND}{ITEM} is the list of macros to use to test ITEM.
Packit 47b4ca
# Initialized from lib/autoscan/*.  E.g., $MACRO{function}{alloca} contains
Packit 47b4ca
# the singleton AC_FUNC_ALLOCA.  Some require several checks.
Packit 47b4ca
my %macro = ();
Packit 47b4ca
Packit 47b4ca
# $NEEDED_MACROS{MACRO} is an array of locations requiring MACRO.
Packit 47b4ca
# E.g., $NEEDED_MACROS{AC_FUNC_ALLOC} the list of `file:line' containing
Packit 47b4ca
# `alloca (...)'.
Packit 47b4ca
my %needed_macros =
Packit 47b4ca
  (
Packit 47b4ca
   'AC_PREREQ' => [$me],
Packit 47b4ca
  );
Packit 47b4ca
Packit 47b4ca
my $configure_scan = 'configure.scan';
Packit 47b4ca
my $log;
Packit 47b4ca
Packit 47b4ca
# Autoconf and lib files.
Packit 47b4ca
my $autom4te = $ENV{'AUTOM4TE'} || '@bindir@/@autom4te-name@';
Packit 47b4ca
my $autoconf = "$autom4te --language=autoconf";
Packit 47b4ca
my @prepend_include;
Packit 47b4ca
my @include = ('@pkgdatadir@');
Packit 47b4ca
Packit 47b4ca
# $help
Packit 47b4ca
# -----
Packit 47b4ca
$help = "Usage: $0 [OPTION]... [SRCDIR]
Packit 47b4ca
Packit 47b4ca
Examine source files in the directory tree rooted at SRCDIR, or the
Packit 47b4ca
current directory if none is given.  Search the source files for
Packit 47b4ca
common portability problems, check for incompleteness of
Packit 47b4ca
`configure.ac', and create a file `$configure_scan' which is a
Packit 47b4ca
preliminary `configure.ac' for that package.
Packit 47b4ca
Packit 47b4ca
  -h, --help          print this help, then exit
Packit 47b4ca
  -V, --version       print version number, then exit
Packit 47b4ca
  -v, --verbose       verbosely report processing
Packit 47b4ca
  -d, --debug         don't remove temporary files
Packit 47b4ca
Packit 47b4ca
Library directories:
Packit 47b4ca
  -B, --prepend-include=DIR  prepend directory DIR to search path
Packit 47b4ca
  -I, --include=DIR          append directory DIR to search path
Packit 47b4ca
Packit 47b4ca
Report bugs to <bug-autoconf\@gnu.org>.
Packit 47b4ca
GNU Autoconf home page: <http://www.gnu.org/software/autoconf/>.
Packit 47b4ca
General help using GNU software: <http://www.gnu.org/gethelp/>.
Packit 47b4ca
";
Packit 47b4ca
Packit 47b4ca
# $version
Packit 47b4ca
# --------
Packit 47b4ca
$version = "autoscan (@PACKAGE_NAME@) @VERSION@
Packit 47b4ca
Copyright (C) @RELEASE_YEAR@ Free Software Foundation, Inc.
Packit 47b4ca
License GPLv3+/Autoconf: GNU GPL version 3 or later
Packit 47b4ca
<http://gnu.org/licenses/gpl.html>, <http://gnu.org/licenses/exceptions.html>
Packit 47b4ca
This is free software: you are free to change and redistribute it.
Packit 47b4ca
There is NO WARRANTY, to the extent permitted by law.
Packit 47b4ca
Packit 47b4ca
Written by David J. MacKenzie and Akim Demaille.
Packit 47b4ca
";
Packit 47b4ca
Packit 47b4ca
Packit 47b4ca
Packit 47b4ca
Packit 47b4ca
## ------------------------ ##
Packit 47b4ca
## Command line interface.  ##
Packit 47b4ca
## ------------------------ ##
Packit 47b4ca
Packit 47b4ca
# parse_args ()
Packit 47b4ca
# -------------
Packit 47b4ca
# Process any command line arguments.
Packit 47b4ca
sub parse_args ()
Packit 47b4ca
{
Packit 47b4ca
  getopt ('I|include=s' => \@include,
Packit 47b4ca
	  'B|prepend-include=s' => \@prepend_include);
Packit 47b4ca
Packit 47b4ca
  die "$me: too many arguments
Packit 47b4ca
Try `$me --help' for more information.\n"
Packit 47b4ca
    if @ARGV > 1;
Packit 47b4ca
Packit 47b4ca
  my $srcdir = $ARGV[0] || ".";
Packit 47b4ca
Packit 47b4ca
  verb "srcdir = $srcdir";
Packit 47b4ca
  chdir $srcdir || error "cannot cd to $srcdir: $!";
Packit 47b4ca
}
Packit 47b4ca
Packit 47b4ca
Packit 47b4ca
# init_tables ()
Packit 47b4ca
# --------------
Packit 47b4ca
# Put values in the tables of what to do with each token.
Packit 47b4ca
sub init_tables ()
Packit 47b4ca
{
Packit 47b4ca
  # The data file format supports only one line of macros per function.
Packit 47b4ca
  # If more than that is required for a common portability problem,
Packit 47b4ca
  # a new Autoconf macro should probably be written for that case,
Packit 47b4ca
  # instead of duplicating the code in lots of configure.ac files.
Packit 47b4ca
  my $file = find_file ("autoscan/autoscan.list",
Packit 47b4ca
			reverse (@prepend_include), @include);
Packit 47b4ca
  my $table = new Autom4te::XFile "< " . open_quote ($file);
Packit 47b4ca
  my $tables_are_consistent = 1;
Packit 47b4ca
Packit 47b4ca
  while ($_ = $table->getline)
Packit 47b4ca
    {
Packit 47b4ca
      # Ignore blank lines and comments.
Packit 47b4ca
      next
Packit 47b4ca
	if /^\s*$/ || /^\s*\#/;
Packit 47b4ca
Packit 47b4ca
      # '<kind>: <word> <macro invocation>' or...
Packit 47b4ca
      # '<kind>: <word> warn: <message>'.
Packit 47b4ca
      if (/^(\S+):\s+(\S+)\s+(\S.*)$/)
Packit 47b4ca
	{
Packit 47b4ca
	  my ($kind, $word, $macro) = ($1, $2, $3);
Packit 47b4ca
	  error "$file:$.: invalid kind: $_"
Packit 47b4ca
	    unless grep { $_ eq $kind } @kinds;
Packit 47b4ca
	  push @{$macro{$kind}{$word}}, $macro;
Packit 47b4ca
	}
Packit 47b4ca
      else
Packit 47b4ca
	{
Packit 47b4ca
	  error "$file:$.: invalid definition: $_";
Packit 47b4ca
	}
Packit 47b4ca
    }
Packit 47b4ca
Packit 47b4ca
  if ($debug)
Packit 47b4ca
    {
Packit 47b4ca
      foreach my $kind (@kinds)
Packit 47b4ca
	{
Packit 47b4ca
	  foreach my $word (sort keys %{$macro{$kind}})
Packit 47b4ca
	    {
Packit 47b4ca
	      print "$kind: $word: @{$macro{$kind}{$word}}\n";
Packit 47b4ca
	    }
Packit 47b4ca
	}
Packit 47b4ca
Packit 47b4ca
    }
Packit 47b4ca
}
Packit 47b4ca
Packit 47b4ca
Packit 47b4ca
# used ($KIND, $WORD, [$WHERE])
Packit 47b4ca
# -----------------------------
Packit 47b4ca
# $WORD is used as a $KIND.
Packit 47b4ca
sub used ($$;$)
Packit 47b4ca
{
Packit 47b4ca
  my ($kind, $word, $where) = @_;
Packit 47b4ca
  $where ||= "$File::Find::name:$.";
Packit 47b4ca
  if (
Packit 47b4ca
      # Check for all the libraries.  But `-links' is certainly a
Packit 47b4ca
      # `find' argument, and `-le', a `test' argument.
Packit 47b4ca
      ($kind eq 'library' && $word !~ /^(e|inks)$/)
Packit 47b4ca
      # Other than libraries are to be checked only if listed in
Packit 47b4ca
      # the Autoscan library files.
Packit 47b4ca
      || defined $macro{$kind}{$word}
Packit 47b4ca
     )
Packit 47b4ca
    {
Packit 47b4ca
      push (@{$used{$kind}{$word}}, $where);
Packit 47b4ca
    }
Packit 47b4ca
}
Packit 47b4ca
Packit 47b4ca
Packit 47b4ca
Packit 47b4ca
## ----------------------- ##
Packit 47b4ca
## Scanning source files.  ##
Packit 47b4ca
## ----------------------- ##
Packit 47b4ca
Packit 47b4ca
Packit 47b4ca
# scan_c_file ($FILE-NAME)
Packit 47b4ca
# ------------------------
Packit 47b4ca
sub scan_c_file ($)
Packit 47b4ca
{
Packit 47b4ca
  my ($file_name) = @_;
Packit 47b4ca
  push @cfiles, $File::Find::name;
Packit 47b4ca
Packit 47b4ca
  # Nonzero if in a multiline comment.
Packit 47b4ca
  my $in_comment = 0;
Packit 47b4ca
Packit 47b4ca
  my $file = new Autom4te::XFile "< " . open_quote ($file_name);
Packit 47b4ca
Packit 47b4ca
  while ($_ = $file->getline)
Packit 47b4ca
    {
Packit 47b4ca
      # Strip out comments.
Packit 47b4ca
      if ($in_comment && s,^.*?\*/,,)
Packit 47b4ca
	{
Packit 47b4ca
	  $in_comment = 0;
Packit 47b4ca
	}
Packit 47b4ca
      # The whole line is inside a comment.
Packit 47b4ca
      next if $in_comment;
Packit 47b4ca
      # All on one line.
Packit 47b4ca
      s,/\*.*?\*/,,g;
Packit 47b4ca
Packit 47b4ca
      # Starting on this line.
Packit 47b4ca
      if (s,/\*.*$,,)
Packit 47b4ca
	{
Packit 47b4ca
	  $in_comment = 1;
Packit 47b4ca
	}
Packit 47b4ca
Packit 47b4ca
      # Preprocessor directives.
Packit 47b4ca
      if (s/^\s*\#\s*//)
Packit 47b4ca
	{
Packit 47b4ca
	  if (/^include\s*<([^>]*)>/)
Packit 47b4ca
	    {
Packit 47b4ca
	      used ('header', $1);
Packit 47b4ca
	    }
Packit 47b4ca
	  if (s/^(if|ifdef|ifndef|elif)\s+//)
Packit 47b4ca
	    {
Packit 47b4ca
	      foreach my $word (split (/\W+/))
Packit 47b4ca
		{
Packit 47b4ca
		  used ('identifier', $word)
Packit 47b4ca
		    unless $word eq 'defined' || $word !~ /^[a-zA-Z_]/;
Packit 47b4ca
		}
Packit 47b4ca
	    }
Packit 47b4ca
	  # Ignore other preprocessor directives.
Packit 47b4ca
	  next;
Packit 47b4ca
	}
Packit 47b4ca
Packit 47b4ca
      # Remove string and character constants.
Packit 47b4ca
      s,\"[^\"]*\",,g;
Packit 47b4ca
      s,\'[^\']*\',,g;
Packit 47b4ca
Packit 47b4ca
      # Tokens in the code.
Packit 47b4ca
      # Maybe we should ignore function definitions (in column 0)?
Packit 47b4ca
      while (s/\b([a-zA-Z_]\w*)\s*\(/ /)
Packit 47b4ca
	{
Packit 47b4ca
	  used ('function', $1);
Packit 47b4ca
	}
Packit 47b4ca
      while (s/\b([a-zA-Z_]\w*)\b/ /)
Packit 47b4ca
	{
Packit 47b4ca
	  used ('identifier', $1);
Packit 47b4ca
	}
Packit 47b4ca
    }
Packit 47b4ca
Packit 47b4ca
  $file->close;
Packit 47b4ca
}
Packit 47b4ca
Packit 47b4ca
Packit 47b4ca
# scan_makefile($MAKEFILE-NAME)
Packit 47b4ca
# -----------------------------
Packit 47b4ca
sub scan_makefile ($)
Packit 47b4ca
{
Packit 47b4ca
  my ($file_name) = @_;
Packit 47b4ca
  push @makefiles, $File::Find::name;
Packit 47b4ca
Packit 47b4ca
  my $file = new Autom4te::XFile "< " . open_quote ($file_name);
Packit 47b4ca
Packit 47b4ca
  while ($_ = $file->getline)
Packit 47b4ca
    {
Packit 47b4ca
      # Strip out comments.
Packit 47b4ca
      s/#.*//;
Packit 47b4ca
Packit 47b4ca
      # Variable assignments.
Packit 47b4ca
      while (s/\b([a-zA-Z_]\w*)\s*=/ /)
Packit 47b4ca
	{
Packit 47b4ca
	  used ('makevar', $1);
Packit 47b4ca
	}
Packit 47b4ca
      # Be sure to catch a whole word.  For instance `lex$U.$(OBJEXT)'
Packit 47b4ca
      # is a single token.  Otherwise we might believe `lex' is needed.
Packit 47b4ca
      foreach my $word (split (/\s+/))
Packit 47b4ca
	{
Packit 47b4ca
	  # Libraries.
Packit 47b4ca
	  if ($word =~ /^-l([a-zA-Z_]\w*)$/)
Packit 47b4ca
	    {
Packit 47b4ca
	      used ('library', $1);
Packit 47b4ca
	    }
Packit 47b4ca
	  # Tokens in the code.
Packit 47b4ca
	  # We allow some additional characters, e.g., `+', since
Packit 47b4ca
	  # autoscan/programs includes `c++'.
Packit 47b4ca
	  if ($word =~ /^[a-zA-Z_][\w+]*$/)
Packit 47b4ca
	    {
Packit 47b4ca
	      used ('program', $word);
Packit 47b4ca
	    }
Packit 47b4ca
	}
Packit 47b4ca
    }
Packit 47b4ca
Packit 47b4ca
  $file->close;
Packit 47b4ca
}
Packit 47b4ca
Packit 47b4ca
Packit 47b4ca
# scan_sh_file($SHELL-SCRIPT-NAME)
Packit 47b4ca
# --------------------------------
Packit 47b4ca
sub scan_sh_file ($)
Packit 47b4ca
{
Packit 47b4ca
  my ($file_name) = @_;
Packit 47b4ca
  push @shfiles, $File::Find::name;
Packit 47b4ca
Packit 47b4ca
  my $file = new Autom4te::XFile "< " . open_quote ($file_name);
Packit 47b4ca
Packit 47b4ca
  while ($_ = $file->getline)
Packit 47b4ca
    {
Packit 47b4ca
      # Strip out comments and variable references.
Packit 47b4ca
      s/#.*//;
Packit Service f3add8
      s/\${[^\}]*}//g;
Packit 47b4ca
      s/@[^@]*@//g;
Packit 47b4ca
Packit 47b4ca
      # Tokens in the code.
Packit 47b4ca
      while (s/\b([a-zA-Z_]\w*)\b/ /)
Packit 47b4ca
	{
Packit 47b4ca
	  used ('program', $1);
Packit 47b4ca
	}
Packit 47b4ca
    }
Packit 47b4ca
Packit 47b4ca
  $file->close;
Packit 47b4ca
}
Packit 47b4ca
Packit 47b4ca
Packit 47b4ca
# scan_file ()
Packit 47b4ca
# ------------
Packit 47b4ca
# Called by &find on each file.  $_ contains the current file name with
Packit 47b4ca
# the current directory of the walk through.
Packit 47b4ca
sub scan_file ()
Packit 47b4ca
{
Packit 47b4ca
  # Wanted only if there is no corresponding FILE.in.
Packit 47b4ca
  return
Packit 47b4ca
    if -f "$_.in";
Packit 47b4ca
Packit 47b4ca
  # Save $_ as Find::File requires it to be preserved.
Packit 47b4ca
  local $_ = $_;
Packit 47b4ca
Packit 47b4ca
  # Strip a useless leading `./'.
Packit 47b4ca
  $File::Find::name =~ s,^\./,,;
Packit 47b4ca
Packit 47b4ca
  if ($_ ne '.' and -d $_ and
Packit 47b4ca
      -f "$_/configure.in"  ||
Packit 47b4ca
      -f "$_/configure.ac"  ||
Packit 47b4ca
      -f "$_/configure.gnu" ||
Packit 47b4ca
      -f "$_/configure")
Packit 47b4ca
    {
Packit 47b4ca
      $File::Find::prune = 1;
Packit 47b4ca
      push @subdirs, $File::Find::name;
Packit 47b4ca
    }
Packit 47b4ca
  if (/\.[chlym](\.in)?$/)
Packit 47b4ca
    {
Packit 47b4ca
      used 'program', 'cc', $File::Find::name;
Packit 47b4ca
      scan_c_file ($_);
Packit 47b4ca
    }
Packit 47b4ca
  elsif (/\.(cc|cpp|cxx|CC|C|hh|hpp|hxx|HH|H|yy|ypp|ll|lpp)(\.in)?$/)
Packit 47b4ca
    {
Packit 47b4ca
      used 'program', 'c++', $File::Find::name;
Packit 47b4ca
      scan_c_file ($_);
Packit 47b4ca
    }
Packit 47b4ca
  elsif ((/^((?:GNUm|M|m)akefile)(\.in)?$/ && ! -f "$1.am")
Packit 47b4ca
	 || /^(?:GNUm|M|m)akefile(\.am)?$/)
Packit 47b4ca
    {
Packit 47b4ca
      scan_makefile ($_);
Packit 47b4ca
    }
Packit 47b4ca
  elsif (/\.sh(\.in)?$/)
Packit 47b4ca
    {
Packit 47b4ca
      scan_sh_file ($_);
Packit 47b4ca
    }
Packit 47b4ca
}
Packit 47b4ca
Packit 47b4ca
Packit 47b4ca
# scan_files ()
Packit 47b4ca
# -------------
Packit 47b4ca
# Read through the files and collect lists of tokens in them
Packit 47b4ca
# that might create nonportabilities.
Packit 47b4ca
sub scan_files ()
Packit 47b4ca
{
Packit 47b4ca
  find (\&scan_file, '.');
Packit 47b4ca
Packit 47b4ca
  if ($verbose)
Packit 47b4ca
    {
Packit 47b4ca
      print "cfiles: @cfiles\n";
Packit 47b4ca
      print "makefiles: @makefiles\n";
Packit 47b4ca
      print "shfiles: @shfiles\n";
Packit 47b4ca
Packit 47b4ca
      foreach my $kind (@kinds)
Packit 47b4ca
	{
Packit 47b4ca
	  print "\n$kind:\n";
Packit 47b4ca
	  foreach my $word (sort keys %{$used{$kind}})
Packit 47b4ca
	    {
Packit 47b4ca
	      print "$word: @{$used{$kind}{$word}}\n";
Packit 47b4ca
	    }
Packit 47b4ca
	}
Packit 47b4ca
    }
Packit 47b4ca
}
Packit 47b4ca
Packit 47b4ca
Packit 47b4ca
## ----------------------- ##
Packit 47b4ca
## Output configure.scan.  ##
Packit 47b4ca
## ----------------------- ##
Packit 47b4ca
Packit 47b4ca
Packit 47b4ca
# output_kind ($FILE, $KIND)
Packit 47b4ca
# --------------------------
Packit 47b4ca
sub output_kind ($$)
Packit 47b4ca
{
Packit 47b4ca
  my ($file, $kind) = @_;
Packit 47b4ca
  # Lists of words to be checked with the generic macro.
Packit 47b4ca
  my @have;
Packit 47b4ca
Packit 47b4ca
  print $file "\n# $kind_comment{$kind}\n"
Packit 47b4ca
    if exists $kind_comment{$kind};
Packit 47b4ca
  foreach my $word (sort keys %{$used{$kind}})
Packit 47b4ca
    {
Packit 47b4ca
      # Output the needed macro invocations in $configure_scan if not
Packit 47b4ca
      # already printed, and remember these macros are needed.
Packit 47b4ca
      foreach my $macro (@{$macro{$kind}{$word}})
Packit 47b4ca
	{
Packit 47b4ca
	  if ($macro =~ /^warn:\s+(.*)/)
Packit 47b4ca
	    {
Packit 47b4ca
	      my $message = $1;
Packit 47b4ca
	      foreach my $location (@{$used{$kind}{$word}})
Packit 47b4ca
		{
Packit 47b4ca
		  warn "$location: warning: $message\n";
Packit 47b4ca
		}
Packit 47b4ca
	    }
Packit 47b4ca
	  elsif (exists $generic_macro{$kind}
Packit 47b4ca
	      && $macro eq $generic_macro{$kind})
Packit 47b4ca
	    {
Packit 47b4ca
	      push (@have, $word);
Packit 47b4ca
	      push (@{$needed_macros{"$generic_macro{$kind}([$word])"}},
Packit 47b4ca
		    @{$used{$kind}{$word}});
Packit 47b4ca
	    }
Packit 47b4ca
	  else
Packit 47b4ca
	    {
Packit 47b4ca
	      if (! $printed{$macro})
Packit 47b4ca
		{
Packit 47b4ca
		  print $file "$macro\n";
Packit 47b4ca
		  $printed{$macro} = 1;
Packit 47b4ca
		}
Packit 47b4ca
	      push (@{$needed_macros{$macro}},
Packit 47b4ca
		    @{$used{$kind}{$word}});
Packit 47b4ca
	    }
Packit 47b4ca
	}
Packit 47b4ca
    }
Packit 47b4ca
  print $file "$generic_macro{$kind}([" . join(' ', sort(@have)) . "])\n"
Packit 47b4ca
    if @have;
Packit 47b4ca
}
Packit 47b4ca
Packit 47b4ca
Packit 47b4ca
# output_libraries ($FILE)
Packit 47b4ca
# ------------------------
Packit 47b4ca
sub output_libraries ($)
Packit 47b4ca
{
Packit 47b4ca
  my ($file) = @_;
Packit 47b4ca
Packit 47b4ca
  print $file "\n# Checks for libraries.\n";
Packit 47b4ca
  foreach my $word (sort keys %{$used{'library'}})
Packit 47b4ca
    {
Packit 47b4ca
      print $file "# FIXME: Replace `main' with a function in `-l$word':\n";
Packit 47b4ca
      print $file "AC_CHECK_LIB([$word], [main])\n";
Packit 47b4ca
    }
Packit 47b4ca
}
Packit 47b4ca
Packit 47b4ca
Packit 47b4ca
# output ($CONFIGURE_SCAN)
Packit 47b4ca
# ------------------------
Packit 47b4ca
# Print a proto configure.ac.
Packit 47b4ca
sub output ($)
Packit 47b4ca
{
Packit 47b4ca
  my $configure_scan = shift;
Packit 47b4ca
  my %unique_makefiles;
Packit 47b4ca
Packit 47b4ca
  my $file = new Autom4te::XFile "> " . open_quote ($configure_scan);
Packit 47b4ca
Packit 47b4ca
  print $file
Packit 47b4ca
    ("#                                               -*- Autoconf -*-\n" .
Packit 47b4ca
     "# Process this file with autoconf to produce a configure script.\n" .
Packit 47b4ca
     "\n" .
Packit 47b4ca
     "AC_PREREQ([@VERSION@])\n" .
Packit 47b4ca
     "AC_INIT([FULL-PACKAGE-NAME], [VERSION], [BUG-REPORT-ADDRESS])\n");
Packit 47b4ca
  if (defined $cfiles[0])
Packit 47b4ca
    {
Packit 47b4ca
      print $file "AC_CONFIG_SRCDIR([$cfiles[0]])\n";
Packit 47b4ca
      print $file "AC_CONFIG_HEADERS([config.h])\n";
Packit 47b4ca
    }
Packit 47b4ca
Packit 47b4ca
  output_kind ($file, 'program');
Packit 47b4ca
  output_kind ($file, 'makevar');
Packit 47b4ca
  output_libraries ($file);
Packit 47b4ca
  output_kind ($file, 'header');
Packit 47b4ca
  output_kind ($file, 'identifier');
Packit 47b4ca
  output_kind ($file, 'function');
Packit 47b4ca
Packit 47b4ca
  print $file "\n";
Packit 47b4ca
  if (@makefiles)
Packit 47b4ca
    {
Packit 47b4ca
      # Change DIR/Makefile.in to DIR/Makefile.
Packit 47b4ca
      foreach my $m (@makefiles)
Packit 47b4ca
	{
Packit 47b4ca
	  $m =~ s/\.(?:in|am)$//;
Packit 47b4ca
	  $unique_makefiles{$m}++;
Packit 47b4ca
	}
Packit 47b4ca
      print $file ("AC_CONFIG_FILES([",
Packit 47b4ca
		   join ("\n                 ",
Packit 47b4ca
			 sort keys %unique_makefiles), "])\n");
Packit 47b4ca
    }
Packit 47b4ca
  if (@subdirs)
Packit 47b4ca
    {
Packit 47b4ca
      print $file ("AC_CONFIG_SUBDIRS([",
Packit 47b4ca
		   join ("\n                   ",
Packit 47b4ca
			 sort @subdirs), "])\n");
Packit 47b4ca
    }
Packit 47b4ca
  print $file "AC_OUTPUT\n";
Packit 47b4ca
Packit 47b4ca
  $file->close;
Packit 47b4ca
}
Packit 47b4ca
Packit 47b4ca
Packit 47b4ca
Packit 47b4ca
## --------------------------------------- ##
Packit 47b4ca
## Checking the accuracy of configure.ac.  ##
Packit 47b4ca
## --------------------------------------- ##
Packit 47b4ca
Packit 47b4ca
Packit 47b4ca
# &check_configure_ac ($CONFIGURE_AC)
Packit 47b4ca
# -----------------------------------
Packit 47b4ca
# Use autoconf to check if all the suggested macros are included
Packit 47b4ca
# in CONFIGURE_AC.
Packit 47b4ca
sub check_configure_ac ($)
Packit 47b4ca
{
Packit 47b4ca
  my ($configure_ac) = @_;
Packit 47b4ca
Packit 47b4ca
  # Find what needed macros are invoked in CONFIGURE_AC.
Packit 47b4ca
  # I'd be very happy if someone could explain to me why sort (uniq ...)
Packit 47b4ca
  # doesn't work properly: I need `uniq (sort ...)'.  --akim
Packit 47b4ca
  my $trace_option =
Packit 47b4ca
    join (' --trace=', '',
Packit 47b4ca
	  uniq (sort (map { s/\(.*//; $_ } keys %needed_macros)));
Packit 47b4ca
Packit 47b4ca
  verb "running: $autoconf $trace_option $configure_ac";
Packit 47b4ca
  my $traces =
Packit 47b4ca
    new Autom4te::XFile "$autoconf $trace_option $configure_ac |";
Packit 47b4ca
Packit 47b4ca
  while ($_ = $traces->getline)
Packit 47b4ca
    {
Packit 47b4ca
      chomp;
Packit 47b4ca
      my ($file, $line, $macro, @args) = split (/:/, $_);
Packit 47b4ca
      if ($macro =~ /^AC_CHECK_(HEADER|FUNC|TYPE|MEMBER)S$/)
Packit 47b4ca
	{
Packit 47b4ca
	  # To be rigorous, we should distinguish between space and comma
Packit 47b4ca
	  # separated macros.  But there is no point.
Packit 47b4ca
	  foreach my $word (split (/\s|,/, $args[0]))
Packit 47b4ca
	    {
Packit 47b4ca
	      # AC_CHECK_MEMBERS wants `struct' or `union'.
Packit 47b4ca
	      if ($macro eq "AC_CHECK_MEMBERS"
Packit 47b4ca
		  && $word =~ /^stat.st_/)
Packit 47b4ca
		{
Packit 47b4ca
		  $word = "struct " . $word;
Packit 47b4ca
		}
Packit 47b4ca
	      delete $needed_macros{"$macro([$word])"};
Packit 47b4ca
	    }
Packit 47b4ca
	}
Packit 47b4ca
      else
Packit 47b4ca
	{
Packit 47b4ca
	  delete $needed_macros{$macro};
Packit 47b4ca
	}
Packit 47b4ca
    }
Packit 47b4ca
Packit 47b4ca
  $traces->close;
Packit 47b4ca
Packit 47b4ca
  # Report the missing macros.
Packit 47b4ca
  foreach my $macro (sort keys %needed_macros)
Packit 47b4ca
    {
Packit 47b4ca
      warn ("$configure_ac: warning: missing $macro wanted by: "
Packit 47b4ca
	    . (${$needed_macros{$macro}}[0])
Packit 47b4ca
	    . "\n");
Packit 47b4ca
      print $log "$me: warning: missing $macro wanted by: \n";
Packit 47b4ca
      foreach my $need (@{$needed_macros{$macro}})
Packit 47b4ca
	{
Packit 47b4ca
	  print $log "\t$need\n";
Packit 47b4ca
	}
Packit 47b4ca
    }
Packit 47b4ca
}
Packit 47b4ca
Packit 47b4ca
Packit 47b4ca
## -------------- ##
Packit 47b4ca
## Main program.  ##
Packit 47b4ca
## -------------- ##
Packit 47b4ca
Packit 47b4ca
parse_args;
Packit 47b4ca
$log = new Autom4te::XFile "> " . open_quote ("$me.log");
Packit 47b4ca
Packit 47b4ca
$autoconf .= " --debug" if $debug;
Packit 47b4ca
$autoconf .= " --verbose" if $verbose;
Packit 47b4ca
$autoconf .= join (' --include=', '', map { shell_quote ($_) } @include);
Packit 47b4ca
$autoconf .= join (' --prepend-include=', '', map { shell_quote ($_) } @prepend_include);
Packit 47b4ca
Packit 47b4ca
my $configure_ac = find_configure_ac;
Packit 47b4ca
init_tables;
Packit 47b4ca
scan_files;
Packit 47b4ca
output ('configure.scan');
Packit 47b4ca
if (-f $configure_ac)
Packit 47b4ca
  {
Packit 47b4ca
    check_configure_ac ($configure_ac);
Packit 47b4ca
  }
Packit 47b4ca
# This close is really needed.  For some reason, probably best named
Packit 47b4ca
# a bug, it seems that the dtor of $LOG is not called automatically
Packit 47b4ca
# at END.  It results in a truncated file.
Packit 47b4ca
$log->close;
Packit 47b4ca
exit 0;
Packit 47b4ca
Packit 47b4ca
### Setup "GNU" style for perl-mode and cperl-mode.
Packit 47b4ca
## Local Variables:
Packit 47b4ca
## perl-indent-level: 2
Packit 47b4ca
## perl-continued-statement-offset: 2
Packit 47b4ca
## perl-continued-brace-offset: 0
Packit 47b4ca
## perl-brace-offset: 0
Packit 47b4ca
## perl-brace-imaginary-offset: 0
Packit 47b4ca
## perl-label-offset: -2
Packit 47b4ca
## cperl-indent-level: 2
Packit 47b4ca
## cperl-brace-offset: 0
Packit 47b4ca
## cperl-continued-brace-offset: 0
Packit 47b4ca
## cperl-label-offset: -2
Packit 47b4ca
## cperl-extra-newline-before-brace: t
Packit 47b4ca
## cperl-merge-trailing-else: nil
Packit 47b4ca
## cperl-continued-statement-offset: 2
Packit 47b4ca
## End: