]> git.ipfire.org Git - thirdparty/autoconf.git/commitdiff
Let autoconf use autom4te to create configure.
authorAkim Demaille <akim@epita.fr>
Tue, 24 Jul 2001 08:57:55 +0000 (08:57 +0000)
committerAkim Demaille <akim@epita.fr>
Tue, 24 Jul 2001 08:57:55 +0000 (08:57 +0000)
* 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.

12 files changed:
BUGS
ChangeLog
Makefile.am
Makefile.in
autoconf.in
autoconf.m4
autom4te.in
bin/autoconf.in
bin/autom4te.in
lib/autoconf/autoconf.m4
lib/m4sugar/m4sh.m4
m4sh.m4

diff --git a/BUGS b/BUGS
index 9f531d92af9ba0abec839306360dbacce7d7795b..2178637f1a66397bb67a8f84cf81ac1307efab71 100644 (file)
--- a/BUGS
+++ b/BUGS
@@ -15,6 +15,13 @@ address them.
 
 * Status
 
-       /*--------------------------.
-       | Good for production use.  |
-       `--------------------------*/
+       /*----------------------------------.
+       | Don't use it for production use.  |
+       `----------------------------------*/
+
+* Serious bugs
+
+** `make check' requires `make install'
+Currently autoconf requires autom4te to be installed.  This is very
+bad, but will be fixed.  In order to use this version of Autoconf, you
+will first have to `make install'.
index 22487609ef3eeb069971a39207eee87d5d704b58..9e2e533cfbd37fc9a652906c00cc12e0c3dc6a94 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
+2001-07-24  Akim Demaille  <akim@epita.fr>
+
+       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.
+
 2001-07-24  Akim Demaille  <akim@epita.fr>
 
        * Makefile.am: Ship, build and install Autom4te.
index 582050d5320cb4255ccabc943f2f6305449859fa..b3bb3352f8614eae9ece047416f1ae1bb99e933d 100644 (file)
@@ -122,6 +122,7 @@ edit = sed \
        -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 b5fb1de5db7b2dc261daa56dac9af3f970b2a49d..680ea4bb0f95957b62cacd629d704f3b2473096a 100644 (file)
@@ -107,7 +107,7 @@ MAKEINFO = @MAKEINFO@ --no-headers --no-validate --no-split
 
 MAINTAINERCLEANFILES = acversion.m4 INSTALL.txt
 
-edit = sed     -e 's,@SHELL\@,$(SHELL),g'      -e 's,@PERL\@,$(PERL),g'        -e 's,@bindir\@,$(bindir),g'    -e 's,@datadir\@,$(pkgdatadir),g'       -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,@M4\@,$(M4),g'    -e 's,@AWK\@,$(AWK),g'  -e 's,@VERSION\@,$(VERSION),g'  -e 's,@PACKAGE_NAME\@,$(PACKAGE_NAME),g'
+edit = sed     -e 's,@SHELL\@,$(SHELL),g'      -e 's,@PERL\@,$(PERL),g'        -e 's,@bindir\@,$(bindir),g'    -e 's,@datadir\@,$(pkgdatadir),g'       -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'  -e 's,@PACKAGE_NAME\@,$(PACKAGE_NAME),g'
 
 
 prev_version_file = $(srcdir)/config/prev-version.txt
index 75d94c9e1733f3332e6209b6c24384ff066d37b2..efcbd78a34a8b29e715e25a399a58adc4cc8b68d 100644 (file)
@@ -125,6 +125,16 @@ if echo xfoo | $AWK '/foo|^bar$/ { print }' | grep xfoo >/dev/null; then :; else
 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.
 : ${autoconf_dir=${AC_MACRODIR=@datadir@}}
 test -z "$AC_ACLOCALDIR" &&
@@ -235,23 +245,6 @@ while test $# -gt 0 ; do
   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 @@ m4_prefiles="                $autoconf_dir/autoconf.m4  $acsite_m4 $aclocal_m4"
 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 @@ elif test ! -r "$infile"; then
   (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 @@ case $task in
   # 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.
 
 
@@ -756,6 +642,14 @@ EOF
       (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 |
     # Now we are ready to run m4 to process the trace file.
index 0ea9c435060fcb45d700ae6cd9cc2b71e537ec6d..425516a36ab73cbacefc19edc146b9da60f4800d 100644 (file)
@@ -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 08cd024f269f314121a4b61e643ee4181e085522..d3a91cadf0ce53ede71a8ebb13ed2a2f4c904498 100644 (file)
@@ -47,6 +47,7 @@ use Autoconf::Struct;
 use Carp;
 use Getopt::Long;
 use IO::File;
+use File::Spec;
 use strict;
 
 # List of requests.
@@ -249,8 +250,12 @@ my $debug = 0;
 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.
@@ -341,9 +346,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).
@@ -423,7 +457,7 @@ sub parse_args ()
      "v|verbose"    => \$verbose,
      "d|debug"      => \$debug,
      "o|output=s"   => \$output,
-     "w|warnings=s" => \@warning,
+     "W|warnings=s" => \@warning,
 
      # Library directories:
      "I|include=s" => \@include,
@@ -448,16 +482,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)
@@ -468,19 +510,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;
+    }
 }
 
 
@@ -541,33 +597,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)
+  # 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)
     {
-      my $prohibited = '\b(' . join ('|', keys %prohibited) . ')\b';
-      my $in = new IO::File ($ARGV[$#ARGV])
-        or die "$me: cannot open $ARGV[$#ARGV]: $!\n";
+      # 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);
 }
 
 
@@ -607,6 +678,7 @@ sub trace_requests
 sub trace_format_to_m4 ($)
 {
   my ($format) = @_;
+  my ($underscore) = $_;
   my %escape = (# File name.
                'f' => '$1',
                # Line number.
@@ -663,6 +735,7 @@ sub trace_format_to_m4 ($)
         }
     }
 
+  $_ = $underscore;
   return '[[' . $res . ']]';
 }
 
@@ -721,7 +794,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")
@@ -795,7 +868,7 @@ EOF
    "## -------------------------------------- ##\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).
@@ -804,10 +877,13 @@ EOF
     "## 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";
 
@@ -835,7 +911,6 @@ EOF
       # Single line traces, as the example above.
       s{^m4trace:(.+):(\d+): -(\d+)- (.*)$}
        {AT_$4([$1], [$2], [$3], [$4]};
-
       print $trace_m4 "$_";
     }
   $trace_m4->close;
@@ -880,18 +955,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";
@@ -965,4 +1037,4 @@ $req->valid (1);
 
 Request->save ("$me.cache/requests");
 
-exit 0;
+exit $exit_status;
index 75d94c9e1733f3332e6209b6c24384ff066d37b2..efcbd78a34a8b29e715e25a399a58adc4cc8b68d 100644 (file)
@@ -125,6 +125,16 @@ if echo xfoo | $AWK '/foo|^bar$/ { print }' | grep xfoo >/dev/null; then :; else
 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.
 : ${autoconf_dir=${AC_MACRODIR=@datadir@}}
 test -z "$AC_ACLOCALDIR" &&
@@ -235,23 +245,6 @@ while test $# -gt 0 ; do
   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 @@ m4_prefiles="                $autoconf_dir/autoconf.m4  $acsite_m4 $aclocal_m4"
 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 @@ elif test ! -r "$infile"; then
   (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 @@ case $task in
   # 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.
 
 
@@ -756,6 +642,14 @@ EOF
       (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 |
     # Now we are ready to run m4 to process the trace file.
index 08cd024f269f314121a4b61e643ee4181e085522..d3a91cadf0ce53ede71a8ebb13ed2a2f4c904498 100644 (file)
@@ -47,6 +47,7 @@ use Autoconf::Struct;
 use Carp;
 use Getopt::Long;
 use IO::File;
+use File::Spec;
 use strict;
 
 # List of requests.
@@ -249,8 +250,12 @@ my $debug = 0;
 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.
@@ -341,9 +346,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).
@@ -423,7 +457,7 @@ sub parse_args ()
      "v|verbose"    => \$verbose,
      "d|debug"      => \$debug,
      "o|output=s"   => \$output,
-     "w|warnings=s" => \@warning,
+     "W|warnings=s" => \@warning,
 
      # Library directories:
      "I|include=s" => \@include,
@@ -448,16 +482,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)
@@ -468,19 +510,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;
+    }
 }
 
 
@@ -541,33 +597,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)
+  # 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)
     {
-      my $prohibited = '\b(' . join ('|', keys %prohibited) . ')\b';
-      my $in = new IO::File ($ARGV[$#ARGV])
-        or die "$me: cannot open $ARGV[$#ARGV]: $!\n";
+      # 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);
 }
 
 
@@ -607,6 +678,7 @@ sub trace_requests
 sub trace_format_to_m4 ($)
 {
   my ($format) = @_;
+  my ($underscore) = $_;
   my %escape = (# File name.
                'f' => '$1',
                # Line number.
@@ -663,6 +735,7 @@ sub trace_format_to_m4 ($)
         }
     }
 
+  $_ = $underscore;
   return '[[' . $res . ']]';
 }
 
@@ -721,7 +794,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")
@@ -795,7 +868,7 @@ EOF
    "## -------------------------------------- ##\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).
@@ -804,10 +877,13 @@ EOF
     "## 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";
 
@@ -835,7 +911,6 @@ EOF
       # Single line traces, as the example above.
       s{^m4trace:(.+):(\d+): -(\d+)- (.*)$}
        {AT_$4([$1], [$2], [$3], [$4]};
-
       print $trace_m4 "$_";
     }
   $trace_m4->close;
@@ -880,18 +955,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";
@@ -965,4 +1037,4 @@ $req->valid (1);
 
 Request->save ("$me.cache/requests");
 
-exit 0;
+exit $exit_status;
index 0ea9c435060fcb45d700ae6cd9cc2b71e537ec6d..425516a36ab73cbacefc19edc146b9da60f4800d 100644 (file)
@@ -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 a0036e17dc2b87d2f9afd1048fa429deef3f5ea8..feefb15eb0374f3327bf8e68b72db7c3f1868224 100644 (file)
@@ -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.
diff --git a/m4sh.m4 b/m4sh.m4
index a0036e17dc2b87d2f9afd1048fa429deef3f5ea8..feefb15eb0374f3327bf8e68b72db7c3f1868224 100644 (file)
--- a/m4sh.m4
+++ b/m4sh.m4
@@ -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.