1# autoconf -- create `configure' using m4 macros 2# Copyright (C) 2001, 2002, 2003, 2004, 2006 Free Software Foundation, Inc. 3 4# This program is free software; you can redistribute it and/or modify 5# it under the terms of the GNU General Public License as published by 6# the Free Software Foundation; either version 2, or (at your option) 7# any later version. 8 9# This program is distributed in the hope that it will be useful, 10# but WITHOUT ANY WARRANTY; without even the implied warranty of 11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12# GNU General Public License for more details. 13 14# You should have received a copy of the GNU General Public License 15# along with this program; if not, write to the Free Software 16# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 17# 02110-1301, USA. 18 19package Autom4te::General; 20 21=head1 NAME 22 23Autom4te::General - general support functions for Autoconf and Automake 24 25=head1 SYNOPSIS 26 27 use Autom4te::General 28 29=head1 DESCRIPTION 30 31This perl module provides various general purpose support functions 32used in several executables of the Autoconf and Automake packages. 33 34=cut 35 36use 5.005_03; 37use Exporter; 38use Autom4te::ChannelDefs; 39use Autom4te::Channels; 40use File::Basename; 41use File::Path (); 42use File::stat; 43use IO::File; 44use Carp; 45use strict; 46 47use vars qw (@ISA @EXPORT); 48 49@ISA = qw (Exporter); 50 51# Variables we define and export. 52my @export_vars = 53 qw ($debug $force $help $me $tmp $verbose $version); 54 55# Functions we define and export. 56my @export_subs = 57 qw (&debug 58 &getopt &mktmpdir 59 &uniq); 60 61# Functions we forward (coming from modules we use). 62my @export_forward_subs = 63 qw (&basename &dirname &fileparse); 64 65@EXPORT = (@export_vars, @export_subs, @export_forward_subs); 66 67 68# Variable we share with the main package. Be sure to have a single 69# copy of them: using `my' together with multiple inclusion of this 70# package would introduce several copies. 71 72=head2 Global Variables 73 74=over 4 75 76=item C<$debug> 77 78Set this variable to 1 if debug messages should be enabled. Debug 79messages are meant for developpers only, or when tracking down an 80incorrect execution. 81 82=cut 83 84use vars qw ($debug); 85$debug = 0; 86 87=item C<$force> 88 89Set this variable to 1 to recreate all the files, or to consider all 90the output files are obsolete. 91 92=cut 93 94use vars qw ($force); 95$force = undef; 96 97=item C<$help> 98 99Set to the help message associated to the option C<--help>. 100 101=cut 102 103use vars qw ($help); 104$help = undef; 105 106=item C<$me> 107 108The name of this application, as should be used in diagostic messages. 109 110=cut 111 112use vars qw ($me); 113$me = basename ($0); 114 115=item C<$tmp> 116 117The name of the temporary directory created by C<mktmpdir>. Left 118C<undef> otherwise. 119 120=cut 121 122# Our tmp dir. 123use vars qw ($tmp); 124$tmp = undef; 125 126=item C<$verbose> 127 128Enable verbosity messages. These messages are meant for ordinary 129users, and typically make explicit the steps being performed. 130 131=cut 132 133use vars qw ($verbose); 134$verbose = 0; 135 136=item C<$version> 137 138Set to the version message associated to the option C<--version>. 139 140=cut 141 142use vars qw ($version); 143$version = undef; 144 145=back 146 147=cut 148 149 150 151## ----- ## 152## END. ## 153## ----- ## 154 155=head2 Functions 156 157=over 4 158 159=item C<END> 160 161Filter Perl's exit codes, delete any temporary directory (unless 162C<$debug>), and exit nonzero whenever closing C<STDOUT> fails. 163 164=cut 165 166# END 167# --- 168sub END 169{ 170 # $? contains the exit status we will return. 171 # It was set using one of the following ways: 172 # 173 # 1) normal termination 174 # this sets $? = 0 175 # 2) calling `exit (n)' 176 # this sets $? = n 177 # 3) calling die or friends (croak, confess...): 178 # a) when $! is non-0 179 # this set $? = $! 180 # b) when $! is 0 but $? is not 181 # this sets $? = ($? >> 8) (i.e., the exit code of the 182 # last program executed) 183 # c) when both $! and $? are 0 184 # this sets $? = 255 185 # 186 # Cases 1), 2), and 3b) are fine, but we prefer $? = 1 for 3a) and 3c). 187 my $status = $?; 188 $status = 1 if ($! && $! == $?) || $? == 255; 189 # (Note that we cannot safely distinguish calls to `exit (n)' 190 # from calls to die when `$! = n'. It's not big deal because 191 # we only call `exit (0)' or `exit (1)'.) 192 193 if (!$debug && defined $tmp && -d $tmp) 194 { 195 local $SIG{__WARN__} = sub { $status = 1; warn $_[0] }; 196 File::Path::rmtree $tmp; 197 } 198 199 # This is required if the code might send any output to stdout 200 # E.g., even --version or --help. So it's best to do it unconditionally. 201 if (! close STDOUT) 202 { 203 print STDERR "$me: closing standard output: $!\n"; 204 $? = 1; 205 return; 206 } 207 208 $? = $status; 209} 210 211 212## ----------- ## 213## Functions. ## 214## ----------- ## 215 216 217=item C<debug (@message)> 218 219If the debug mode is enabled (C<$debug> and C<$verbose>), report the 220C<@message> on C<STDERR>, signed with the name of the program. 221 222=cut 223 224# &debug(@MESSAGE) 225# ---------------- 226# Messages displayed only if $DEBUG and $VERBOSE. 227sub debug (@) 228{ 229 print STDERR "$me: ", @_, "\n" 230 if $verbose && $debug; 231} 232 233 234=item C<getopt (%option)> 235 236Wrapper around C<Getopt::Long>. In addition to the user C<option>s, 237support C<-h>/C<--help>, C<-V>/C<--version>, C<-v>/C<--verbose>, 238C<-d>/C<--debug>, C<-f>/C<--force>. Conform to the GNU Coding 239Standards for error messages. Try to work around a weird behavior 240from C<Getopt::Long> to preserve C<-> as an C<@ARGV> instead of 241rejecting it as a broken option. 242 243=cut 244 245# getopt (%OPTION) 246# ---------------- 247# Handle the %OPTION, plus all the common options. 248# Work around Getopt bugs wrt `-'. 249sub getopt (%) 250{ 251 my (%option) = @_; 252 use Getopt::Long; 253 254 # F*k. Getopt seems bogus and dies when given `-' with `bundling'. 255 # If fixed some day, use this: '' => sub { push @ARGV, "-" } 256 my $stdin = grep /^-$/, @ARGV; 257 @ARGV = grep !/^-$/, @ARGV; 258 %option = ("h|help" => sub { print $help; exit 0 }, 259 "V|version" => sub { print $version; exit 0 }, 260 261 "v|verbose" => sub { ++$verbose }, 262 "d|debug" => sub { ++$debug }, 263 'f|force' => \$force, 264 265 # User options last, so that they have precedence. 266 %option); 267 Getopt::Long::Configure ("bundling", "pass_through"); 268 GetOptions (%option) 269 or exit 1; 270 271 foreach (grep { /^-./ } @ARGV) 272 { 273 print STDERR "$0: unrecognized option `$_'\n"; 274 print STDERR "Try `$0 --help' for more information.\n"; 275 exit (1); 276 } 277 278 push @ARGV, '-' 279 if $stdin; 280 281 setup_channel 'note', silent => !$verbose; 282 setup_channel 'verb', silent => !$verbose; 283} 284 285 286=item C<mktmpdir ($signature)> 287 288Create a temporary directory which name is based on C<$signature>. 289Store its name in C<$tmp>. C<END> is in charge of removing it, unless 290C<$debug>. 291 292=cut 293 294# mktmpdir ($SIGNATURE) 295# --------------------- 296sub mktmpdir ($) 297{ 298 my ($signature) = @_; 299 my $TMPDIR = $ENV{'TMPDIR'} || '/tmp'; 300 301 # If mktemp supports dirs, use it. 302 $tmp = `(umask 077 && 303 mktemp -d "$TMPDIR/${signature}XXXXXX") 2>/dev/null`; 304 chomp $tmp; 305 306 if (!$tmp || ! -d $tmp) 307 { 308 $tmp = "$TMPDIR/$signature" . int (rand 10000) . ".$$"; 309 mkdir $tmp, 0700 310 or croak "$me: cannot create $tmp: $!\n"; 311 } 312 313 print STDERR "$me:$$: working in $tmp\n" 314 if $debug; 315} 316 317 318=item C<uniq (@list)> 319 320Return C<@list> with no duplicates, keeping only the first 321occurrences. 322 323=cut 324 325# @RES 326# uniq (@LIST) 327# ------------ 328sub uniq (@) 329{ 330 my @res = (); 331 my %seen = (); 332 foreach my $item (@_) 333 { 334 if (! exists $seen{$item}) 335 { 336 $seen{$item} = 1; 337 push (@res, $item); 338 } 339 } 340 return wantarray ? @res : "@res"; 341} 342 343 344=item C<handle_exec_errors ($command)> 345 346Display an error message for C<$command>, based on the content of 347C<$?> and C<$!>. 348 349=cut 350 351 352# handle_exec_errors ($COMMAND) 353# ----------------------------- 354sub handle_exec_errors ($) 355{ 356 my ($command) = @_; 357 358 $command = (split (' ', $command))[0]; 359 if ($!) 360 { 361 error "failed to run $command: $!"; 362 } 363 else 364 { 365 use POSIX qw (WIFEXITED WEXITSTATUS WIFSIGNALED WTERMSIG); 366 367 if (WIFEXITED ($?)) 368 { 369 my $status = WEXITSTATUS ($?); 370 # WIFEXITED and WEXITSTATUS can alter $!, reset it so that 371 # error() actually propagates the command's exit status, not $!. 372 $! = 0; 373 error "$command failed with exit status: $status"; 374 } 375 elsif (WIFSIGNALED ($?)) 376 { 377 my $signal = WTERMSIG ($?); 378 # In this case we prefer to exit with status 1. 379 $! = 1; 380 error "$command terminated by signal: $signal"; 381 } 382 else 383 { 384 error "$command exited abnormally"; 385 } 386 } 387} 388 389=back 390 391=head1 SEE ALSO 392 393L<Autom4te::XFile> 394 395=head1 HISTORY 396 397Written by Alexandre Duret-Lutz E<lt>F<adl@gnu.org>E<gt> and Akim 398Demaille E<lt>F<akim@freefriends.org>E<gt>. 399 400=cut 401 402 403 4041; # for require 405 406### Setup "GNU" style for perl-mode and cperl-mode. 407## Local Variables: 408## perl-indent-level: 2 409## perl-continued-statement-offset: 2 410## perl-continued-brace-offset: 0 411## perl-brace-offset: 0 412## perl-brace-imaginary-offset: 0 413## perl-label-offset: -2 414## cperl-indent-level: 2 415## cperl-brace-offset: 0 416## cperl-continued-brace-offset: 0 417## cperl-label-offset: -2 418## cperl-extra-newline-before-brace: t 419## cperl-merge-trailing-else: nil 420## cperl-continued-statement-offset: 2 421## End: 422