<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;"># autoconf -- create `configure' using m4 macros
# Copyright (C) 2001, 2002, 2003, 2004, 2006, 2007 Free Software
# Foundation, Inc.

# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.

package Autom4te::General;

=head1 NAME

Autom4te::General - general support functions for Autoconf and Automake

=head1 SYNOPSIS

  use Autom4te::General

=head1 DESCRIPTION

This perl module provides various general purpose support functions
used in several executables of the Autoconf and Automake packages.

=cut

use 5.005_03;
use Exporter;
use Autom4te::ChannelDefs;
use Autom4te::Channels;
use File::Basename;
use File::Path ();
use File::stat;
use IO::File;
use Carp;
use strict;

use vars qw (@ISA @EXPORT);

@ISA = qw (Exporter);

# Variables we define and export.
my @export_vars =
  qw ($debug $force $help $me $tmp $verbose $version);

# Functions we define and export.
my @export_subs =
  qw (&amp;debug
      &amp;getopt &amp;shell_quote &amp;mktmpdir
      &amp;uniq);

# Functions we forward (coming from modules we use).
my @export_forward_subs =
  qw (&amp;basename &amp;dirname &amp;fileparse);

@EXPORT = (@export_vars, @export_subs, @export_forward_subs);


# Variable we share with the main package.  Be sure to have a single
# copy of them: using `my' together with multiple inclusion of this
# package would introduce several copies.

=head2 Global Variables

=over 4

=item C&lt;$debug&gt;

Set this variable to 1 if debug messages should be enabled.  Debug
messages are meant for developpers only, or when tracking down an
incorrect execution.

=cut

use vars qw ($debug);
$debug = 0;

=item C&lt;$force&gt;

Set this variable to 1 to recreate all the files, or to consider all
the output files are obsolete.

=cut

use vars qw ($force);
$force = undef;

=item C&lt;$help&gt;

Set to the help message associated to the option C&lt;--help&gt;.

=cut

use vars qw ($help);
$help = undef;

=item C&lt;$me&gt;

The name of this application, as should be used in diagostic messages.

=cut

use vars qw ($me);
$me = basename ($0);

=item C&lt;$tmp&gt;

The name of the temporary directory created by C&lt;mktmpdir&gt;.  Left
C&lt;undef&gt; otherwise.

=cut

# Our tmp dir.
use vars qw ($tmp);
$tmp = undef;

=item C&lt;$verbose&gt;

Enable verbosity messages.  These messages are meant for ordinary
users, and typically make explicit the steps being performed.

=cut

use vars qw ($verbose);
$verbose = 0;

=item C&lt;$version&gt;

Set to the version message associated to the option C&lt;--version&gt;.

=cut

use vars qw ($version);
$version = undef;

=back

=cut



## ----- ##
## END.  ##
## ----- ##

=head2 Functions

=over 4

=item C&lt;END&gt;

Filter Perl's exit codes, delete any temporary directory (unless
C&lt;$debug&gt;), and exit nonzero whenever closing C&lt;STDOUT&gt; fails.

=cut

# END
# ---
sub END
{
  # $? contains the exit status we will return.
  # It was set using one of the following ways:
  #
  #  1) normal termination
  #     this sets $? = 0
  #  2) calling `exit (n)'
  #     this sets $? = n
  #  3) calling die or friends (croak, confess...):
  #     a) when $! is non-0
  #        this set $? = $!
  #     b) when $! is 0 but $? is not
  #        this sets $? = ($? &gt;&gt; 8)   (i.e., the exit code of the
  #        last program executed)
  #     c) when both $! and $? are 0
  #        this sets $? = 255
  #
  # Cases 1), 2), and 3b) are fine, but we prefer $? = 1 for 3a) and 3c).
  my $status = $?;
  $status = 1 if ($! &amp;&amp; $! == $?) || $? == 255;
  # (Note that we cannot safely distinguish calls to `exit (n)'
  # from calls to die when `$! = n'.  It's not big deal because
  # we only call `exit (0)' or `exit (1)'.)

  if (!$debug &amp;&amp; defined $tmp &amp;&amp; -d $tmp)
    {
      local $SIG{__WARN__} = sub { $status = 1; warn $_[0] };
      File::Path::rmtree $tmp;
    }

  # This is required if the code might send any output to stdout
  # E.g., even --version or --help.  So it's best to do it unconditionally.
  if (! close STDOUT)
    {
      print STDERR "$me: closing standard output: $!\n";
      $? = 1;
      return;
    }

  $? = $status;
}


## ----------- ##
## Functions.  ##
## ----------- ##


=item C&lt;debug (@message)&gt;

If the debug mode is enabled (C&lt;$debug&gt; and C&lt;$verbose&gt;), report the
C&lt;@message&gt; on C&lt;STDERR&gt;, signed with the name of the program.

=cut

# &amp;debug(@MESSAGE)
# ----------------
# Messages displayed only if $DEBUG and $VERBOSE.
sub debug (@)
{
  print STDERR "$me: ", @_, "\n"
    if $verbose &amp;&amp; $debug;
}


=item C&lt;getopt (%option)&gt;

Wrapper around C&lt;Getopt::Long&gt;.  In addition to the user C&lt;option&gt;s,
support C&lt;-h&gt;/C&lt;--help&gt;, C&lt;-V&gt;/C&lt;--version&gt;, C&lt;-v&gt;/C&lt;--verbose&gt;,
C&lt;-d&gt;/C&lt;--debug&gt;, C&lt;-f&gt;/C&lt;--force&gt;.  Conform to the GNU Coding
Standards for error messages.  Try to work around a weird behavior
from C&lt;Getopt::Long&gt; to preserve C&lt;-&gt; as an C&lt;@ARGV&gt; instead of
rejecting it as a broken option.

=cut

# getopt (%OPTION)
# ----------------
# Handle the %OPTION, plus all the common options.
# Work around Getopt bugs wrt `-'.
sub getopt (%)
{
  my (%option) = @_;
  use Getopt::Long;

  # F*k.  Getopt seems bogus and dies when given `-' with `bundling'.
  # If fixed some day, use this: '' =&gt; sub { push @ARGV, "-" }
  my $stdin = grep /^-$/, @ARGV;
  @ARGV = grep !/^-$/, @ARGV;
  %option = ("h|help"     =&gt; sub { print $help; exit 0 },
	     "V|version"  =&gt; sub { print $version; exit 0 },

	     "v|verbose"  =&gt; sub { ++$verbose },
	     "d|debug"    =&gt; sub { ++$debug },
	     'f|force'    =&gt; \$force,

	     # User options last, so that they have precedence.
	     %option);
  Getopt::Long::Configure ("bundling", "pass_through");
  GetOptions (%option)
    or exit 1;

  foreach (grep { /^-./ } @ARGV)
    {
      print STDERR "$0: unrecognized option `$_'\n";
      print STDERR "Try `$0 --help' for more information.\n";
      exit (1);
    }

  push @ARGV, '-'
    if $stdin;

  setup_channel 'note', silent =&gt; !$verbose;
  setup_channel 'verb', silent =&gt; !$verbose;
}


=item C&lt;shell_quote ($file_name)&gt;

Quote C&lt;$file_name&gt; for the shell.

=cut

# $FILE_NAME
# shell_quote ($FILE_NAME)
# ------------------------
# If the string $S is a well-behaved file name, simply return it.
# If it contains white space, quotes, etc., quote it, and return
# the new string.
sub shell_quote($)
{
  my ($s) = @_;
  if ($s =~ m![^\w+/.,-]!)
    {
      # Convert each single quote to '\''
      $s =~ s/\'/\'\\\'\'/g;
      # Then single quote the string.
      $s = "'$s'";
    }
  return $s;
}

=item C&lt;mktmpdir ($signature)&gt;

Create a temporary directory which name is based on C&lt;$signature&gt;.
Store its name in C&lt;$tmp&gt;.  C&lt;END&gt; is in charge of removing it, unless
C&lt;$debug&gt;.

=cut

# mktmpdir ($SIGNATURE)
# ---------------------
sub mktmpdir ($)
{
  my ($signature) = @_;
  my $TMPDIR = $ENV{'TMPDIR'} || '/tmp';
  my $quoted_tmpdir = shell_quote ($TMPDIR);

  # If mktemp supports dirs, use it.
  $tmp = `(umask 077 &amp;&amp;
	   mktemp -d $quoted_tmpdir/"${signature}XXXXXX") 2&gt;/dev/null`;
  chomp $tmp;

  if (!$tmp || ! -d $tmp)
    {
      $tmp = "$TMPDIR/$signature" . int (rand 10000) . ".$$";
      mkdir $tmp, 0700
	or croak "$me: cannot create $tmp: $!\n";
    }

  print STDERR "$me:$$: working in $tmp\n"
    if $debug;
}


=item C&lt;uniq (@list)&gt;

Return C&lt;@list&gt; with no duplicates, keeping only the first
occurrences.

=cut

# @RES
# uniq (@LIST)
# ------------
sub uniq (@)
{
  my @res = ();
  my %seen = ();
  foreach my $item (@_)
    {
      if (! exists $seen{$item})
	{
	  $seen{$item} = 1;
	  push (@res, $item);
	}
    }
  return wantarray ? @res : "@res";
}


=item C&lt;handle_exec_errors ($command)&gt;

Display an error message for C&lt;$command&gt;, based on the content of
C&lt;$?&gt; and C&lt;$!&gt;.

=cut


# handle_exec_errors ($COMMAND)
# -----------------------------
sub handle_exec_errors ($)
{
  my ($command) = @_;

  $command = (split (' ', $command))[0];
  if ($!)
    {
      error "failed to run $command: $!";
    }
  else
    {
      use POSIX qw (WIFEXITED WEXITSTATUS WIFSIGNALED WTERMSIG);

      if (WIFEXITED ($?))
	{
	  my $status = WEXITSTATUS ($?);
	  # WIFEXITED and WEXITSTATUS can alter $!, reset it so that
	  # error() actually propagates the command's exit status, not $!.
	  $! = 0;
	  error "$command failed with exit status: $status";
	}
      elsif (WIFSIGNALED ($?))
	{
	  my $signal = WTERMSIG ($?);
	  # In this case we prefer to exit with status 1.
	  $! = 1;
	  error "$command terminated by signal: $signal";
	}
      else
	{
	  error "$command exited abnormally";
	}
    }
}

=back

=head1 SEE ALSO

L&lt;Autom4te::XFile&gt;

=head1 HISTORY

Written by Alexandre Duret-Lutz E&lt;lt&gt;F&lt;adl@gnu.org&gt;E&lt;gt&gt; and Akim
Demaille E&lt;lt&gt;F&lt;akim@freefriends.org&gt;E&lt;gt&gt;.

=cut



1; # for require

### Setup "GNU" style for perl-mode and cperl-mode.
## Local Variables:
## perl-indent-level: 2
## perl-continued-statement-offset: 2
## perl-continued-brace-offset: 0
## perl-brace-offset: 0
## perl-brace-imaginary-offset: 0
## perl-label-offset: -2
## cperl-indent-level: 2
## cperl-brace-offset: 0
## cperl-continued-brace-offset: 0
## cperl-label-offset: -2
## cperl-extra-newline-before-brace: t
## cperl-merge-trailing-else: nil
## cperl-continued-statement-offset: 2
## End:
</pre></body></html>