[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
02: autoconf uses autom4te for expansion
From: |
Akim Demaille |
Subject: |
02: autoconf uses autom4te for expansion |
Date: |
24 Jul 2001 10:46:13 +0200 |
User-agent: |
Gnus/5.0808 (Gnus v5.8.8) XEmacs/21.4 (Academic Rigor) |
Index: ChangeLog
from Akim Demaille <address@hidden>
Let autoconf use autom4te to create configure.
* autoconf.in ($automate): New var.
(task script): Use autom4te.
* autom4te.in (File::Spec): Use it.
(&find_file): New.
(&parse_args): --warning is -W, not -w.
Find the top level files.
(&handle_m4): Pass the warnings flags.
Don't report verbosely m4's failures, unless requested.
(&handle_output): Don't complain for forbidden tokens in comments.
Be sure to report all the forbidden tokens within a single line.
(&trace_format_to_m4): Preserve `$_'.
(&handle_traces): Sort the output macros.
(&up_to_date_p): Find the files before trying to get its time stamp.
Index: Makefile.am
--- Makefile.am Sun, 15 Jul 2001 16:36:26 +0200 akim (ace/45_Makefile.a 1.50
644)
+++ Makefile.am Mon, 23 Jul 2001 20:05:15 +0200 akim (ace/45_Makefile.a 1.50
644)
@@ -124,6 +124,7 @@
-e 's,@prefix\@,$(prefix),g' \
-e 's,@autoconf-name\@,'`echo autoconf | sed '$(transform)'`',g' \
-e 's,@autoheader-name\@,'`echo autoheader | sed '$(transform)'`',g' \
+ -e 's,@autom4te-name\@,'`echo autom4te | sed '$(transform)'`',g' \
-e 's,@M4\@,$(M4),g' \
-e 's,@AWK\@,$(AWK),g' \
-e 's,@VERSION\@,$(VERSION),g' \
Index: autoconf.in
--- autoconf.in Sun, 15 Jul 2001 12:34:11 +0200 akim (ace/17_autoconf.s
1.31.8.46 644)
+++ autoconf.in Mon, 23 Jul 2001 20:05:15 +0200 akim (ace/17_autoconf.s
1.31.8.46 644)
@@ -125,6 +125,16 @@
fi
+# We test "$dir/autom4te" in case we are in the build tree, in which case
+# the names are not transformed yet.
+for autom4te in "$AUTOM4TE" \
+ "$dir/@autom4te-name@" \
+ "$dir/autom4te" \
+ "@bindir@/@autom4te-name@"; do
+ test -f "$autom4te" && break
+done
+
+
# Variables.
: address@hidden@}}
test -z "$AC_ACLOCALDIR" &&
@@ -235,23 +245,6 @@
esac
done
-# The warnings are the concatenation of 1. application's defaults,
-# 2. $WARNINGS, $3 command line options, in that order.
-# Set them in the order expected by the M4 macros: the converse.
-alphabet='abcdefghijklmnopqrstuvwxyz'
-ALPHABET='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
-NUMBERS='0123456789'
-WORDCHAR=_$alphabet$ALPHABET$NUMBERS
-
-m4_warnings=
-for warning in `IFS=,; echo syntax $WARNINGS $warnings |
- tr $ALPHABET $alphabet`
-do
- test -n $warning || continue
- m4_warnings="$warning"`test -n "$m4_warnings" && echo ",$m4_warnings"`
-done
-
-
# Trap on 0 to stop playing with `rm'.
$debug ||
{
@@ -282,6 +275,16 @@
m4f_prefiles="--reload-state=$autoconf_dir/autoconf.m4f $acsite_m4 $aclocal_m4"
run_m4="$M4 $m4_common"
+# Running autom4te.
+run_autom4te="$autom4te "\
+`$verbose "--verbose "`\
+`$debug && echo "--debug "`\
+"--include $autoconf_dir --include $localdir "\
+"--warning syntax,$warnings "\
+"autoconf.m4"`$initialization || echo f`" "\
+"$acsite_m4 "\
+"$aclocal_m4 "
+
# Find the input file.
case $# in
0)
@@ -316,14 +319,6 @@
(exit 1); exit 1
fi
-# Output is produced into FD 4. Prepare it.
-case $outfile in
- -) # Output to stdout
- exec 4>&1 ;;
- * )
- exec 4>$outfile;;
-esac
-
# Initializations are performed. Proceed to the main task.
case $task in
@@ -334,123 +329,14 @@
# M4 expansion.
: >$tmp/forbidden.rx
: >$tmp/allowed.rx
- $verbose "$me: running $run_m4 -Dm4_warnings=$m4_warnings $m4f_prefiles
$infile" >&2
- $run_m4 -Dm4_warnings=$m4_warnings $m4f_prefiles $infile >$tmp/configure ||
+ $verbose "$me: running $run_autom4te $infile --output $outfile" >&2
+ $run_autom4te $infile --output $outfile ||
{ (exit 1); exit 1; }
if test "x$outfile" != x-; then
chmod +x $outfile
fi
- # Put the real line numbers into configure to make config.log more
- # helpful. Because quoting can sometimes get really painful in m4,
- # there are special @tokens@ to substitute.
- sed 's/^ //' >"$tmp/finalize.awk" <<EOF
- # Load the list of tokens which escape the forbidden patterns.
- BEGIN {
- # Be sure the read GAWK documentation to understand the parens
- # around \`tmp "/forbidden.rx"'.
- while ((getline pattern < (tmp "/forbidden.rx")) > 0)
- forbidden = (forbidden ? forbidden "|" : "") pattern
- close (tmp "/forbidden.rx")
- if (verbose)
- errprint("$me: forbidden: " forbidden)
-
- while ((getline pattern < (tmp "/allowed.rx")) > 0)
- allowed = (allowed ? allowed "|" : "") pattern
- if (!allowed)
- allowed = "^$"
- close (tmp "/allowed.rx")
- if (verbose)
- errprint("$me: allowed: " allowed)
- }
-
- function errprint (message)
- {
- # BAD! the pipe to 'cat >&2' doesn't work for DJGPP.
- # print message | "cat >&2"
- # Use normal redirection instead:
- print message > "$tmp/finalize.err"
- }
-
- function undefined (file, line, macro)
- {
- errprint(file ":" line ": error: possibly undefined macro: " macro)
- }
-
- # Body.
- {
- sub (/[ \t]*$/, "")
- if (\$0 == "")
- {
- if (!duplicate)
- {
- oline++
- print
- }
- duplicate = 1
- next
- }
- duplicate = 0
- oline++
- if (\$0 ~ /__oline__/)
- while (sub (/__oline__/, oline))
- continue
- while (sub (/@<:@/, "["))
- continue
- while (sub (/@:>@/, "]"))
- continue
- while (sub (/@S\|@/, "$"))
- continue
- while (sub (/@%:@/, "#"))
- continue
-
- print
-
- # Dubious feature: we tolerate macro names when commented.
- sub (/#.*/, "")
-
- # Get the tokens.
- split (\$0, tokens, /[^$WORDCHAR]*/)
-
- for (token in tokens)
- if (match (tokens[token], forbidden) &&
- !match (tokens[token], allowed))
- {
- macros [tokens [token]] = oline
- some_macros_were_not_expanded = 1
- }
- }
-
- # If there are some macros which are left unexpanded in the output,
- # try to find the input which is responsible. Otherwise, try to help.
- END {
- if (some_macros_were_not_expanded)
- {
- line = 0
- while (getline < "$infile")
- {
- line++
- for (macro in macros)
- if (index (\$0, macro))
- {
- delete macros [macro]
- undefined("$infile", line, macro)
- }
- }
- close ("$infile")
- for (macro in macros)
- undefined("$outfile", macros [macro], macro)
- exit 1
- }
- }
-EOF
- $AWK -v tmp="$tmp" \
- `$verbose "-v verbose=1"` \
- -f "$tmp/finalize.awk" <$tmp/configure >&4 ||
- { test -f "$tmp/finalize.err" && cat "$tmp/finalize.err" >&2
- (exit 1); exit 1; }
- test -f "$tmp/finalize.err" && cat "$tmp/finalize.err" >&2
;; # End of the task script.
@@ -755,6 +641,14 @@
echo "$me: tracing failed" >&2
(exit 1); exit 1
}
+
+ # Output is produced into FD 4. Prepare it.
+ case $outfile in
+ -) # Output to stdout
+ exec 4>&1 ;;
+ * )
+ exec 4>$outfile;;
+ esac
$verbose "$me: running $M4 $tmp/trace.m4" >&2
sed -f $tmp/trace2m4.sed $tmp/traces |
Index: autoconf.m4
--- autoconf.m4 Mon, 04 Jun 2001 18:29:01 +0200 akim (ace/28_autoconf.m 1.20
644)
+++ autoconf.m4 Mon, 23 Jul 2001 20:05:15 +0200 akim (ace/28_autoconf.m 1.20
644)
@@ -1,4 +1,4 @@
-include(m4sh.m4)# -*- Autoconf -*-
+changequote()changequote([, ])include(m4sh.m4)# -*- Autoconf -*-
# This file is part of Autoconf.
# Driver that loads the Autoconf macro files.
# Copyright 1994, 1999, 2000, 2001 Free Software Foundation, Inc.
Index: autom4te.in
--- autom4te.in Sun, 15 Jul 2001 16:36:26 +0200 akim (ace/c/10_autom4te.i 1.2
664)
+++ autom4te.in Mon, 23 Jul 2001 20:11:31 +0200 akim (ace/c/10_autom4te.i 1.2
664)
@@ -47,6 +47,7 @@
use Carp;
use Getopt::Long;
use IO::File;
+use File::Spec;
use strict;
# List of requests
@@ -242,8 +243,12 @@ sub load
my $output = '-';
my @warning;
+# M4 include path.
my @include;
+# 0 for EXIT_SUCCESS.
+my $exit_status = 0;
+
# $M4.
my $m4 = $ENV{"M4"} || '@M4@';
# Some non-GNU m4's don't reject the --help option, so give them /dev/null.
@@ -334,9 +339,38 @@ sub xsystem ($)
(system $command) == 0
or die ("$me: "
. (split (' ', $command))[0]
- . " failed with exit status: $?\n");
+ . " failed with exit status: "
+ . ($? >> 8)
+ . "\n");
}
+
+# $FILENAME
+# find_file ($FILENAME)
+# ---------------------
+# We match exactly the behavior of GNU m4: first look in the current
+# directory (which includes the case of absolute file names), and, if
+# the file is not absolute, just fail. Otherwise, look in the path.
+sub find_file ($)
+{
+ my ($filename) = @_;
+
+ return File::Spec->canonpath ($filename)
+ if -f $filename;
+
+ die "$me: no such for or directory: $filename\n"
+ if File::Spec->file_name_is_absolute ($filename);
+
+ foreach my $path (@include)
+ {
+ return File::Spec->canonpath (File::Spec->catfile ($path, $filename))
+ if -f File::Spec->catfile ($path, $filename)
+ }
+
+ die "$me: programming error";
+}
+
+
# print_usage ()
# --------------
# Display usage (--help).
@@ -416,7 +450,7 @@ sub parse_args ()
"v|verbose" => \$verbose,
"d|debug" => \$debug,
"o|output=s" => \$output,
- "w|warnings=s" => address@hidden,
+ "W|warnings=s" => address@hidden,
# Library directories:
"I|include=s" => address@hidden,
@@ -441,16 +475,24 @@ sub parse_args ()
die "$me: too few arguments
Try `$me --help' for more information.\n"
unless @ARGV;
+
+ # We don't want to depend upon m4's --include to find the top level
+ # files. Try to get a canonical name, as it's a key for caching.
+ for (my $i = 0; $i < $#ARGV; ++$i)
+ {
+ $ARGV[$i] = find_file ($ARGV[$i]);
+ }
}
# handle_m4 ($REQ, @TRACE)
# ------------------------
# Run m4 on the input files, and save the traces on the @TRACE macros.
-sub handle_m4 ($%)
+sub handle_m4 ($@)
{
my ($req, @trace) = @_;
+ # Find the files. We don't want to depend upon m4's --include.
# *.m4f files have to be reloaded.
my $files;
foreach (@ARGV)
@@ -461,19 +503,33 @@ sub handle_m4 ($%)
$files .= "$_";
}
+ # The warnings are the concatenation of 1. application's defaults,
+ # 2. $WARNINGS, $3 command line options, in that order.
+ # Set them in the order expected by the M4 macros: the converse.
+ my $m4_warnings =
+ lc join (',', reverse (split (',', ($ENV{'WARNINGS'} || '')),
+ map { split /,/ } @warning));
+
# GNU m4 appends when using --error-output.
unlink ("$me.cache/" . $req->cache);
# Run m4.
- xsystem ("$m4"
- . " --define m4_tmpdir=$tmp"
- . " --define m4_warnings=" # FIXME: Pass the warnings.
- . ' --debug=aflq'
- . " --error-output=$me.cache/" . $req->cache
- . join (' --trace=', '', @trace)
- . join (' --include=', '', @include)
- . $files
- . " >$tmp/output");
+ my $command = ("$m4"
+ . " --define m4_tmpdir=$tmp"
+ . " --define m4_warnings=$m4_warnings"
+ . ' --debug=aflq'
+ . " --error-output=$me.cache/" . $req->cache
+ . join (' --trace=', '', @trace)
+ . join (' --include=', '', @include)
+ . $files
+ . " >$tmp/output");
+ verbose "running: $command";
+ system $command;
+ if ($?)
+ {
+ verbose "$m4: failed with exit status: " . ($? >> 8) . "\n";
+ exit $? >> 8;
+ }
}
@@ -534,33 +590,48 @@ sub handle_output ($)
print $out "$_\n";
- foreach (split ('\W+'))
+ # Don't complain in comments. Well, until we have something
+ # better, don't consider `#include' etc. are comments.
+ s/\#.*//
+ unless /^\#(if|include|endif|ifdef|ifndef|define)\b/;
+ foreach (split (/\W+/))
{
$prohibited{$_} = $oline
if /$forbidden/ && !/$allowed/;
}
}
- if (%prohibited)
- {
- my $prohibited = '\b(' . join ('|', keys %prohibited) . ')\b';
- my $in = new IO::File ($ARGV[$#ARGV])
- or die "$me: cannot open $ARGV[$#ARGV]: $!\n";
+ # If no forbidden words, we're done.
+ return
+ if ! %prohibited;
+
+ # Locate the forbidden words in the last source file.
+ # This is unsatisfying but...
+ my $prohibited = '\b(' . join ('|', keys %prohibited) . ')\b';
+ my $file = new IO::File ($ARGV[$#ARGV])
+ or die "$me: cannot open $ARGV[$#ARGV]: $!\n";
+ $exit_status = 1;
+
+ while ($_ = $file->getline)
+ {
+ # Don't complain in comments. Well, until we have something
+ # better, don't consider `#include' etc. are comments.
+ s/\#.*//
+ unless /^\#(if|include|endif|ifdef|ifndef|define)\b/;
- while ($_ = $in->getline)
- {
- if (/$prohibited/)
- {
- warn "$ARGV[$#ARGV]: $.: undefined macro: $1\n"
- if exists $prohibited{$1};
- delete $prohibited{$1};
- }
- }
- foreach (keys %prohibited)
+ # Complain once per word, but possibly several times per line.
+ while (/$prohibited/)
{
- warn "$output: $prohibited{$_}: undefined macro: $_\n";
+ warn "$ARGV[$#ARGV]:$.: error: possibly undefined macro: $1\n";
+ delete $prohibited{$1};
+ # If we're done, exit.
+ return
+ if ! %prohibited;
+ $prohibited = '\b(' . join ('|', keys %prohibited) . ')\b';
}
}
+ warn "$output:$prohibited{$_}: error: possibly undefined macro: $_\n"
+ foreach (keys %prohibited);
}
@@ -600,6 +671,7 @@ sub trace_requests
sub trace_format_to_m4 ($)
{
my ($format) = @_;
+ my ($underscore) = $_;
my %escape = (# File name.
'f' => '$1',
# Line number.
@@ -656,6 +728,7 @@ sub trace_format_to_m4 ($)
}
}
+ $_ = $underscore;
return '[[' . $res . ']]';
}
@@ -714,7 +787,7 @@ sub handle_traces ($$%)
}
}
- verbose "formatting traces for `$output': ", join (', ', keys %trace);
+ verbose "formatting traces for `$output': ", join (', ', sort keys %trace);
# Processing the traces.
my $trace_m4 = new IO::File (">$tmp/traces.m4")
@@ -788,7 +861,7 @@ sub handle_traces ($$%)
"## -------------------------------------- ##\n",
"\n";
print $trace_m4 "at_define([AT_$_], [at_dnl])\n"
- foreach (keys %{$req->macro});
+ foreach (sort keys %{$req->macro});
print $trace_m4 "\n";
# Implement traces for current requests (%TRACE).
@@ -797,10 +870,13 @@ sub handle_traces ($$%)
"## Trace processing macros. ##\n",
"## ------------------------- ##\n",
"\n";
- foreach my $key (keys %trace)
+ foreach (sort keys %trace)
{
- print $trace_m4 "at_define([AT_$key],\n";
- print $trace_m4 trace_format_to_m4 ($trace{$key}) . ")\n\n";
+ # Trace request can be embed \n.
+ (my $comment = "Trace $_:$trace{$_}") =~ s/^/\# /;
+ print $trace_m4 "$comment\n";
+ print $trace_m4 "at_define([AT_$_],\n";
+ print $trace_m4 trace_format_to_m4 ($trace{$_}) . ")\n\n";
}
print $trace_m4 "\n";
@@ -828,7 +904,6 @@ sub handle_traces ($$%)
# Single line traces, as the example above.
s{^m4trace:(.+):(\d+): -(\d+)- (.*)$}
{AT_$4([$1], [$2], [$3], [$4]};
-
print $trace_m4 "$_";
}
$trace_m4->close;
@@ -873,18 +948,15 @@ sub up_to_date_p ($$)
# Files may include others. We can use traces since we just checked
# if they are available.
- handle_traces ($req, "$tmp/dependencies", ('include' => '$1'));
+ # If $FILE is younger than one of its dependencies, it is outdated.
+ handle_traces ($req, "$tmp/dependencies",('include' => '$1'));
+ my $mtime = (stat ($file))[9];
my $deps = new IO::File ("$tmp/dependencies");
while ($_ = $deps->getline)
{
chop;
- push @dep, $_;
- }
-
- # If $FILE is younger than one of its dependencies, it is outdated.
- my $mtime = (stat ($file))[9];
- foreach (@dep)
- {
+ $_ = find_file ($_);
+ verbose "$file depends on $_";
if ($mtime < (stat ($_))[9])
{
verbose "$file depends on $_ which is more recent";
@@ -952,4 +1024,4 @@ sub up_to_date_p ($$)
Request->save ("$me.cache/requests");
-exit 0;
+exit $exit_status;
Index: m4sh.m4
--- m4sh.m4 Sat, 23 Jun 2001 23:01:08 +0200 akim (ace/b/41_m4sh.m4 1.28 644)
+++ m4sh.m4 Mon, 23 Jul 2001 20:05:15 +0200 akim (ace/b/41_m4sh.m4 1.28 644)
@@ -1,4 +1,4 @@
-include(m4sugar.m4)# -*- Autoconf -*-
+changequote()changequote([, ])include(m4sugar.m4)# -*- Autoconf -*-
# This file is part of Autoconf.
# M4 sugar for common shell constructs.
# Requires GNU M4 and M4sugar.
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- 02: autoconf uses autom4te for expansion,
Akim Demaille <=