From: Akim Demaille Date: Tue, 24 Jul 2001 09:05:28 +0000 (+0000) Subject: Let autoconf use autom4te for traces. X-Git-Tag: AUTOCONF-2.52a~21 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=27103b83f0181691e0cf241df6679b3293bafdd4;p=thirdparty%2Fautoconf.git Let autoconf use autom4te for traces. * autoconf.in ($task, task trace): Remove, merely pass --trace to autom4te. * autoheader.in: Don't pass `-' to autoconf, rather, a tmp file. (Because I found no way for autom4te to accept `-'). * autom4te.in (&Request::request): Beware of M4 builtins. (END): Don't try to remove the content of an empty dir. (&parse_args): Default is `$f:$l:$n:$%', not `$f:$l:$n:$*'. (&handle_output): Set a default value to `$forbidden'. * autoupdate.in (&verbose, &xsystem): New, from autom4te.in. ($autoconf): Pass --debug and --verbose. * tests/atspecific.m4 (AT_CHECK_AUTOCONF): Clean up autom4te's cache. --- diff --git a/ChangeLog b/ChangeLog index 9e2e533cf..40d82b68a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +2001-07-24 Akim Demaille + + Let autoconf use autom4te for traces. + + * autoconf.in ($task, task trace): Remove, merely pass --trace to + autom4te. + * autoheader.in: Don't pass `-' to autoconf, rather, a tmp file. + (Because I found no way for autom4te to accept `-'). + * autom4te.in (&Request::request): Beware of M4 builtins. + (END): Don't try to remove the content of an empty dir. + (&parse_args): Default is `$f:$l:$n:$%', not `$f:$l:$n:$*'. + (&handle_output): Set a default value to `$forbidden'. + * autoupdate.in (&verbose, &xsystem): New, from autom4te.in. + ($autoconf): Pass --debug and --verbose. + * tests/atspecific.m4 (AT_CHECK_AUTOCONF): Clean up autom4te's + cache. + 2001-07-24 Akim Demaille Let autoconf use autom4te to create configure. diff --git a/autoconf.in b/autoconf.in index efcbd78a3..394ea9b92 100644 --- a/autoconf.in +++ b/autoconf.in @@ -146,13 +146,6 @@ localdir=. outfile= # Exit status. status=0 -# Tasks: -# - trace -# Trace the first arguments of some macros -# - script -# Produce the configure script (default) -task=script -tmp= verbose=: # Parse command line. @@ -200,14 +193,12 @@ while test $# -gt 0 ; do shift ;; --trace=* | -t?* ) - task=trace - traces="$traces '"`echo "$optarg" | sed "s/'/'\\\\\\\\''/g"`"'" + traces="$traces --trace='"`echo "$optarg" | sed "s/'/'\\\\\\\\''/g"`"'" shift ;; --trace | -t ) test $# = 1 && eval "$exit_missing_arg" - task=trace shift - traces="$traces '"`echo "$1" | sed "s/'/'\\\\\\\\''/g"`"'" + traces="$traces --trace='"`echo "$1" | sed "s/'/'\\\\\\\\''/g"`"'" shift ;; --initialization | -i ) initialization=: @@ -245,36 +236,6 @@ while test $# -gt 0 ; do esac done -# Trap on 0 to stop playing with `rm'. -$debug || -{ - trap 'status=$?; rm -rf $tmp && exit $status' 0 - trap '(exit 1); exit 1' 1 2 13 15 -} - -# Create a (secure) tmp directory for tmp files. -: ${TMPDIR=/tmp} -{ - tmp=`(umask 077 && mktemp -d -q "$TMPDIR/acXXXXXX") 2>/dev/null` && - test -n "$tmp" && test -d "$tmp" -} || -{ - tmp=$TMPDIR/ac$$ - (umask 077 && mkdir $tmp) -} || -{ - echo "$me: cannot create a temporary directory in $TMPDIR" >&2 - (exit 1); exit 1; -} - -# Running m4. -test -f "$autoconf_dir/acsite.m4" && acsite_m4="$autoconf_dir/acsite.m4" -test -f "$localdir/aclocal.m4" && aclocal_m4="$localdir/aclocal.m4" -m4_common="-I $autoconf_dir -I $localdir -Dm4_tmpdir=$tmp" -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 "`\ @@ -282,8 +243,8 @@ run_autom4te="$autom4te "\ "--include $autoconf_dir --include $localdir "\ "--warning syntax,$warnings "\ "autoconf.m4"`$initialization || echo f`" "\ -"$acsite_m4 "\ -"$aclocal_m4 " +`test -f "$autoconf_dir/acsite.m4" && echo "$autoconf_dir/acsite.m4"`" "\ +`test -f "$localdir/aclocal.m4" && echo "$localdir/aclocal.m4"` # Find the input file. case $# in @@ -299,8 +260,9 @@ case $# in echo "$me: no input file" >&2 exit 1;; esac - test $task = script && test -z "$outfile" && outfile=configure;; - 1) infile=$1 ;; + test -z "$traces" && test -z "$outfile" && outfile=configure;; + 1) # autom4te doesn't like `-'. + test "x$1" != "x-" && infile=$1 ;; *) exec >&2 echo "$me: invalid number of arguments." echo "$help" @@ -310,375 +272,15 @@ esac # Unless specified, the output is stdout. test -z "$outfile" && outfile=- -# We need an actual file. -if test z$infile = z-; then - infile=$tmp/stdin - cat >$infile -elif test ! -r "$infile"; then - echo "$me: $infile: No such file or directory" >&2 - (exit 1); exit 1 -fi - -# Initializations are performed. Proceed to the main task. -case $task in - - ## --------------------------------- ## - ## Generate the `configure' script. ## - ## --------------------------------- ## - script) - # M4 expansion. - : >$tmp/forbidden.rx - : >$tmp/allowed.rx - $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 - - ;; # End of the task script. - - - - ## -------------- ## - ## Trace macros. ## - ## -------------- ## - trace) - - # trace.m4 - # -------- - # Routines to process formatted m4 traces. - sed 's/^ //' >$tmp/trace.m4 <<\EOF - divert(-1) - changequote([, ]) - # _at_MODE(SEPARATOR, ELT1, ELT2...) - # ---------------------------------- - # List the elements, separating then with SEPARATOR. - # MODE can be: - # `at' -- the elements are enclosed in brackets. - # `star' -- the elements are listed as are. - # `percent' -- the elements are `flattened': spaces are singled out, - # and no new line remains. - define([_at_at], - [at_ifelse([$#], [1], [], - [$#], [2], [[[$2]]], - [[[$2]][$1]$0([$1], at_shift(at_shift($@)))])]) - define([_at_percent], - [at_ifelse([$#], [1], [], - [$#], [2], [at_flatten([$2])], - [at_flatten([$2])[$1]$0([$1], at_shift(at_shift($@)))])]) - define([_at_star], - [at_ifelse([$#], [1], [], - [$#], [2], [[$2]], - [[$2][$1]$0([$1], at_shift(at_shift($@)))])]) - - # FLATTEN quotes its result. - define([at_flatten], - [at_patsubst(at_patsubst(at_patsubst([[[$1]]], - [\\ - ]), - [[ - ]+], - [ ]), - [^ *\(.*\) *$], [[\1]])]) - - define([at_args], [at_shift(at_shift(at_shift(at_shift(at_shift($@)))))]) - define([at_at], [_$0([$1], at_args($@))]) - define([at_percent], [_$0([$1], at_args($@))]) - define([at_star], [_$0([$1], at_args($@))]) - -EOF - - # If you trace `define', then on `define([m4_exit], defn([m4exit])' you - # will produce - # - # AT_define([m4sugar.m4], [115], [1], [define], [m4_exit], ) - # - # Since `' is not quoted, the outter m4, when processing - # `trace.m4' will exit prematurely. Hence, move all the builtins to - # the `at_' name space. - echo '# Copy the builtins.' >>$tmp/trace.m4 - echo "dumpdef" | - $M4 2>&1 >/dev/null | - sed 's/^\([^:]*\):.*/define([at_\1], defn([\1]))/' >>$tmp/trace.m4 - echo >>$tmp/trace.m4 - - echo '# Disable the builtins.' >>$tmp/trace.m4 - echo "dumpdef" | - $M4 2>&1 >/dev/null | - sed 's/^\([^:]*\):.*/at_undefine([\1])/' >>$tmp/trace.m4 - echo >>$tmp/trace.m4 - - - # trace2m4.sed - # ------------ - # Transform the traces from m4 into an m4 input file. - # Typically, transform: - # - # | m4trace:configure.ac:3: -1- AC_SUBST([exec_prefix], [NONE]) - # - # into - # - # | AT_AC_SUBST([configure.ac], [3], [1], [AC_SUBST], [exec_prefix], [NONE]) - # - # Pay attention that the file name might include colons, if under DOS - # for instance, so we don't use `[^:][^:]*'. - # The first s/// catches multiline traces, the second, traces as above. - preamble='m4trace:\(..*\):\([0-9][0-9]*\): -\([0-9][0-9]*\)-' - cat >$tmp/trace2m4.sed <$tmp/translate.awk <<\EOF - function trans (arg, sep) - { - # File name. - if (arg == "f") - return "$1" - # Line number. - if (arg == "l") - return "$2" - # Depth. - if (arg == "d") - return "$3" - # Name (also available as $0). - if (arg == "n") - return "$4" - # Escaped dollar. - if (arg == "$") - return "$" - - # $@, list of quoted effective arguments. - if (arg == "@") - return "]at_at([" (separator ? separator : ",") "], $@)[" - # $*, list of unquoted effective arguments. - if (arg == "*") - return "]at_star([" (separator ? separator : ",") "], $@)[" - # $%, list of flattened unquoted effective arguments. - if (arg == "%") - return "]at_percent([" (separator ? separator : ":") "], $@)[" - } - - function error (message) - { - print message | "cat >&2" - exit 1 - } - - { - # Accumulate the whole input. - request = request $0 "\n" - } - - END { - # Chomp. - request = substr (request, 1, length (request) - 1) - # The default request is `$f:$l:$n:$*'. - colon = index (request, ":") - macro = colon ? substr (request, 1, colon - 1) : request - request = colon ? substr (request, colon + 1) : "$f:$l:$n:$%" - - res = "" - - for (cp = request; cp; cp = substr (cp, 2)) - { - char = substr (cp, 1, 1) - if (char == "$") - { - if (match (cp, /^\$[0-9]+/)) - { - # $n -> $(n + 4) - res = res "$" (substr (cp, 2, RLENGTH - 1) + 4) - cp = substr (cp, RLENGTH) - } - else if (substr (cp, 2, 1) ~ /[fldn$@%*]/) - { - # $x, no separator given. - res = res trans(substr (cp, 2, 1)) - cp = substr (cp, 2) - } - else if (substr (cp, 2, 1) == "{") - { - # ${sep}x, long separator. - end = index (cp, "}") - if (!end) - error("invalid escape: " cp) - separator = substr (cp, 3, end - 3) - if (substr (cp, end + 1, 1) ~ /[*@%]/) - res = res trans(substr (cp, end + 1, 1), separator) - else - error("invalid escape: " cp) - cp = substr (cp, end + 1) - } - else if (substr (cp, 3, 1) ~ /[*@%]/) - { - # $sx, short separator `s'. - res = res trans(substr (cp, 3, 1), substr (cp, 2, 1)) - cp = substr(cp, 3) - } - else - { - error("invalid escape: " substr (cp, 1, 2)) - } - } - else - res = res char - } - - # Produce the definition of AT_ = the translation of the request. - print "at_define([AT_" macro "]," - print "[[" res "]])" - print "" - close("cat >&2") - } -EOF - - - # Extract both the m4 program and the m4 options from TRACES. - echo "## ------------------------- ##" >>$tmp/trace.m4 - echo "## Trace processing macros. ##" >>$tmp/trace.m4 - echo "## ------------------------- ##" >>$tmp/trace.m4 - echo >>$tmp/trace.m4 - - eval set dummy "$traces" - shift - for trace - do - echo "# $trace" >>$tmp/trace.m4 - - # The request may be several lines long, hence sed has to quit. - macro_name=`echo "$trace" | sed 's/:.*//;q'` - # If for instance TRACE is `define', be sure to have an empty - # TRACE_FORMAT. - case $trace in - $macro_name:* ) - trace_format=`echo "$trace" | sed "1s/^$macro_name:/:/"`;; - * ) - trace_format=;; - esac - - # GNU M4 1.4's tracing of builtins is buggy. When run on this input: - # - # | divert(-1) - # | changequote([, ]) - # | define([m4_eval], defn([eval])) - # | eval(1) - # | m4_eval(2) - # | undefine([eval]) - # | m4_eval(3) - # - # it behaves this way: - # - # | % m4 input.m4 -da -t eval - # | m4trace: -1- eval(1) - # | m4trace: -1- m4_eval(2) - # | m4trace: -1- m4_eval(3) - # | % - # - # Conversely: - # - # | % m4 input.m4 -da -t m4_eval - # | % - # - # So we will merge them, i.e. tracing `BUILTIN' or tracing - # `m4_BUILTIN' will be the same: tracing both, but honoring the - # *last* trace specification. - # FIXME: This is not enough: in the output `$0' will be `BUILTIN' - # sometimes and `m4_BUILTIN' at others. We should render a unique name, - # the one specified by the user. - base_name=`echo "$macro_name" | sed 's/^m4_//'` - if echo "ifdef(\`$base_name', \`', \`m4exit(-1)')" | $M4; then - # BASE_NAME is a builtin. - trace_opt="$trace_opt -t $base_name -t m4_$base_name" - echo "$base_name$trace_format" | - $AWK -f $tmp/translate.awk >>$tmp/trace.m4 || - { (exit 1); exit 1; } - echo "m4_$base_name$trace_format" | - $AWK -f $tmp/translate.awk >>$tmp/trace.m4 || - { (exit 1); exit 1; } - else - # MACRO_NAME is not a builtin. - trace_opt="$trace_opt -t $macro_name" - echo "$trace" | - $AWK -f $tmp/translate.awk >>$tmp/trace.m4 || - { (exit 1); exit 1; } - fi - echo >>$tmp/trace.m4 - done - - echo "## ------------------- ##" >>$tmp/trace.m4 - echo "## Traces to process. ##" >>$tmp/trace.m4 - echo "## ------------------- ##" >>$tmp/trace.m4 - echo >>$tmp/trace.m4 - echo "at_divert(0)at_dnl" >>$tmp/trace.m4 - - # Do we trace the initialization? - # `errprint' must be silent, otherwise there can be warnings mixed - # with traces in m4's stderr. - run_m4_trace="$run_m4 $trace_opt -daflq -Derrprint" - if $initialization; then - trace_prefiles="$m4_prefiles" - else - trace_prefiles="$m4f_prefiles" - fi - - # Run m4 on the input file to get traces. - # - # We used to have a simple pipe, which was very convenient as it - # allows to use traces on never ending expansions (i.e., when - # debugging :) but it is requires to keep error messages *and* - # traces in stderr. This is too fragile, as it results in - # unexpected data in the output. autoheader has been fragile to - # this. - $verbose "$me: running $run_m4_trace $trace_prefiles $infile -o $tmp/traces" >&2 - $run_m4_trace $trace_prefiles $infile -o $tmp/traces >/dev/null || - { - 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 +# Autom4te expansion. +eval set dummy "$traces" +shift +$verbose "$me: running $run_autom4te ""$@"" $infile --output $outfile" >&2 +$run_autom4te "$@" $infile --output $outfile || + { (exit 1); exit 1; } - $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. - if $debug; then - cat >>$tmp/trace.m4 - $M4 $tmp/trace.m4 - else - $M4 $tmp/trace.m4 - - fi | - # It makes no sense to try to transform __oline__. - sed ' - s/@<:@/[/g - s/@:>@/]/g - s/@S|@/$/g - s/@%:@/#/g - ' >&4 || - { - echo "$me: traces formatting failed" >&2 - (exit 1); exit 1 - } - ;; - - - ## ------------ ## - ## Unknown task ## - ## ------------ ## - - *) echo "$me: internal error: unknown task: $task" >&2 - (exit 1); exit 1 -esac +if test -z "$traces" && test "x$outfile" != x-; then + chmod +x $outfile +fi (exit $status); exit $status diff --git a/autoheader.in b/autoheader.in index 0babde46c..492ad0779 100644 --- a/autoheader.in +++ b/autoheader.in @@ -122,7 +122,7 @@ while test $# -gt 0 ; do shift ;; --autoconf-dir=* | -A?* ) - autoconf_dir=$optarg + autoconf_dir=$optarg shift ;; --autoconf-dir | -A ) test $# = 1 && eval "$exit_missing_arg" @@ -238,8 +238,17 @@ case $# in * ) echo "$me: no input file" >&2 (exit 1); exit 1;; - esac;; - 1) infile=$1 ;; + esac + infilename=$infile + ;; + 1) if test "x$1" = "x-"; then + cat >$tmp/stdin + infile=$tmp/stdin + else + infile=$1 + fi + infilename="Standard input" + ;; *) exec >&2 echo "$me: invalid number of arguments." echo "$help" @@ -247,7 +256,9 @@ case $# in esac # Set up autoconf. -autoconf="$autoconf -l $localdir" +autoconf="$autoconf -l $localdir "\ +`$verbose "--verbose "`\ +`$debug && echo "--debug "` export autoconf_dir # ----------------------- # @@ -299,7 +310,7 @@ esac # Don't write "do not edit" -- it will get copied into the # config.h, which it's ok to edit. cat <$tmp/config.hin -/* $config_h_in. Generated automatically from $infile by autoheader. */ +/* $config_h_in. Generated automatically from $infilename by autoheader. */ EOF # Dump the top. diff --git a/autom4te.in b/autom4te.in index d3a91cadf..491e9f69f 100644 --- a/autom4te.in +++ b/autom4te.in @@ -128,7 +128,9 @@ sub request { if (! exists ${$obj->macro}{$_}) { + s/^m4_//; ${$obj->macro}{$_} = 1; + ${$obj->macro}{"m4_$_"} = 1; $obj->valid (0); } } @@ -320,8 +322,11 @@ sub END if (!$debug && defined $tmp && -d $tmp) { - unlink <$tmp/*> - or warn ("$me: cannot empty $tmp: $!\n"), _exit (1); + if (<$tmp/*>) + { + unlink <$tmp/*> + or warn ("$me: cannot empty $tmp: $!\n"), _exit (1); + } rmdir $tmp or warn ("$me: cannot remove $tmp: $!\n"), _exit (1); } @@ -374,7 +379,7 @@ sub find_file ($) if -f File::Spec->catfile ($path, $filename) } - die "$me: programming error"; + die "$me: programming error: $filename"; } @@ -418,7 +423,7 @@ Tracing: Report bugs to . EOF - # Help font-lock: ` + # Help font-lock-mode find an closing back quote: ` exit 0; } @@ -467,22 +472,22 @@ sub parse_args () # instead of mapping `FOO' to undef, Getopt maps it to `1', preventing # us from distinguishing `-t FOO' from `-t FOO=1'. So let's do it # by hand. - "t|trace=s" => \@trace, + "t|trace=s" => \@trace, ) or exit 1; + die "$me: too few arguments +Try `$me --help' for more information.\n" + unless @ARGV; + # Convert @trace to %trace. - # The default format is `$f:$l:$n:$*'. + # The default format is `$f:$l:$n:$%'. foreach (@trace) { - /^([^:]+)(?::(.*))?$/; - $trace{$1} = defined $2 ? $2 : '$f:$l:$n:$*'; + /^([^:]+)(?::(.*))?$/ms; + $trace{$1} = defined $2 ? $2 : '$f:$l:$n:$%'; } - 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) @@ -551,7 +556,7 @@ sub handle_output ($) verbose "creating $output"; # Load the forbidden/allowed patterns. - my $forbidden; + my $forbidden = "^\$"; if (-f "$tmp/forbidden.rx") { my $fh = new IO::File ("$tmp/forbidden.rx"); @@ -980,8 +985,8 @@ sub up_to_date_p ($$) ## Main program. ## ## -------------- ## -parse_args; mktmpdir ('t4'); +parse_args; # We need our cache directory. if (! -d "$me.cache") diff --git a/autoupdate.in b/autoupdate.in index 7cc362a8f..19be24de2 100644 --- a/autoupdate.in +++ b/autoupdate.in @@ -67,6 +67,15 @@ sub mktmpdir () } +# verbose +# ------- +sub verbose (@) +{ + print STDERR "$me: ", @_, "\n" + if $verbose; +} + + # END # --- # Exit nonzero whenever closing STDOUT fails. @@ -97,6 +106,23 @@ sub END } +# xsystem ($COMMAND) +# ------------------ +sub xsystem ($) +{ + my ($command) = @_; + + verbose "running: $command"; + + (system $command) == 0 + or die ("$me: " + . (split (' ', $command))[0] + . " failed with exit status: " + . ($? >> 8) + . "\n"); +} + + # print_usage () # -------------- # Display usage (--help). @@ -105,19 +131,19 @@ sub print_usage () print <<"END"; Usage: $0 [OPTION] ... [TEMPLATE-FILE...] -Update the TEMPLATE-FILE... if given, or \`configure.ac' if present, -or else \`configure.in', to the syntax of the current version of +Update the TEMPLATE-FILE... if given, or \`configure.ac\' if present, +or else \`configure.in\', to the syntax of the current version of Autoconf. The original files are backed up. Operation modes: -h, --help print this help, then exit -V, --version print version number, then exit -v, --verbose verbosely report processing - -d, --debug don't remove temporary files + -d, --debug don\'t remove temporary files Library directories: - -A, --autoconf-dir=ACDIR Autoconf's macro files location (rarely needed) - -l, --localdir=DIR location of \`aclocal.m4' + -A, --autoconf-dir=ACDIR Autoconf\'s macro files location (rarely needed) + -l, --localdir=DIR location of \`aclocal.m4\' Environment variables: M4 GNU M4 1.4 or above @@ -186,8 +212,10 @@ sub parse_args () 'V|version' => \&print_version, 'v|verbose' => \$verbose) or exit 1; + push @ARGV, '-' if $update_stdin; + if (! @ARGV) { my $configure_ac = find_configure_ac; @@ -237,8 +265,9 @@ sub find_slaves () find_slaves; parse_args; mktmpdir; -$autoconf .= " --autoconf-dir $autoconf_dir --localdir $localdir"; - +$autoconf .= " --autoconf-dir $autoconf_dir --localdir $localdir "; +$autoconf .= "--debug " if $debug; +$autoconf .= "--verbose " if $verbose; # @M4_BUILTINS -- M4 builtins and a useful comment. my @m4_builtins = `echo dumpdef | $m4 2>&1 >/dev/null`; @@ -306,7 +335,7 @@ my $au_changequote = 's/\b(' . join ('|', keys %au_macros) . ')\b/_au_changequote([,])$1/g'; # au.m4 -- definitions the AU macros. -system ("$autoconf --trace AU_DEFUN:'_au_defun(\@<:\@\$1\@:>\@, +xsystem ("$autoconf --trace AU_DEFUN:'_au_defun(\@<:\@\$1\@:>\@, \@<:\@\$2\@:>\@)' -i /dev/null " . ">$tmp/au.m4"); diff --git a/bin/autoconf.in b/bin/autoconf.in index efcbd78a3..394ea9b92 100644 --- a/bin/autoconf.in +++ b/bin/autoconf.in @@ -146,13 +146,6 @@ localdir=. outfile= # Exit status. status=0 -# Tasks: -# - trace -# Trace the first arguments of some macros -# - script -# Produce the configure script (default) -task=script -tmp= verbose=: # Parse command line. @@ -200,14 +193,12 @@ while test $# -gt 0 ; do shift ;; --trace=* | -t?* ) - task=trace - traces="$traces '"`echo "$optarg" | sed "s/'/'\\\\\\\\''/g"`"'" + traces="$traces --trace='"`echo "$optarg" | sed "s/'/'\\\\\\\\''/g"`"'" shift ;; --trace | -t ) test $# = 1 && eval "$exit_missing_arg" - task=trace shift - traces="$traces '"`echo "$1" | sed "s/'/'\\\\\\\\''/g"`"'" + traces="$traces --trace='"`echo "$1" | sed "s/'/'\\\\\\\\''/g"`"'" shift ;; --initialization | -i ) initialization=: @@ -245,36 +236,6 @@ while test $# -gt 0 ; do esac done -# Trap on 0 to stop playing with `rm'. -$debug || -{ - trap 'status=$?; rm -rf $tmp && exit $status' 0 - trap '(exit 1); exit 1' 1 2 13 15 -} - -# Create a (secure) tmp directory for tmp files. -: ${TMPDIR=/tmp} -{ - tmp=`(umask 077 && mktemp -d -q "$TMPDIR/acXXXXXX") 2>/dev/null` && - test -n "$tmp" && test -d "$tmp" -} || -{ - tmp=$TMPDIR/ac$$ - (umask 077 && mkdir $tmp) -} || -{ - echo "$me: cannot create a temporary directory in $TMPDIR" >&2 - (exit 1); exit 1; -} - -# Running m4. -test -f "$autoconf_dir/acsite.m4" && acsite_m4="$autoconf_dir/acsite.m4" -test -f "$localdir/aclocal.m4" && aclocal_m4="$localdir/aclocal.m4" -m4_common="-I $autoconf_dir -I $localdir -Dm4_tmpdir=$tmp" -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 "`\ @@ -282,8 +243,8 @@ run_autom4te="$autom4te "\ "--include $autoconf_dir --include $localdir "\ "--warning syntax,$warnings "\ "autoconf.m4"`$initialization || echo f`" "\ -"$acsite_m4 "\ -"$aclocal_m4 " +`test -f "$autoconf_dir/acsite.m4" && echo "$autoconf_dir/acsite.m4"`" "\ +`test -f "$localdir/aclocal.m4" && echo "$localdir/aclocal.m4"` # Find the input file. case $# in @@ -299,8 +260,9 @@ case $# in echo "$me: no input file" >&2 exit 1;; esac - test $task = script && test -z "$outfile" && outfile=configure;; - 1) infile=$1 ;; + test -z "$traces" && test -z "$outfile" && outfile=configure;; + 1) # autom4te doesn't like `-'. + test "x$1" != "x-" && infile=$1 ;; *) exec >&2 echo "$me: invalid number of arguments." echo "$help" @@ -310,375 +272,15 @@ esac # Unless specified, the output is stdout. test -z "$outfile" && outfile=- -# We need an actual file. -if test z$infile = z-; then - infile=$tmp/stdin - cat >$infile -elif test ! -r "$infile"; then - echo "$me: $infile: No such file or directory" >&2 - (exit 1); exit 1 -fi - -# Initializations are performed. Proceed to the main task. -case $task in - - ## --------------------------------- ## - ## Generate the `configure' script. ## - ## --------------------------------- ## - script) - # M4 expansion. - : >$tmp/forbidden.rx - : >$tmp/allowed.rx - $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 - - ;; # End of the task script. - - - - ## -------------- ## - ## Trace macros. ## - ## -------------- ## - trace) - - # trace.m4 - # -------- - # Routines to process formatted m4 traces. - sed 's/^ //' >$tmp/trace.m4 <<\EOF - divert(-1) - changequote([, ]) - # _at_MODE(SEPARATOR, ELT1, ELT2...) - # ---------------------------------- - # List the elements, separating then with SEPARATOR. - # MODE can be: - # `at' -- the elements are enclosed in brackets. - # `star' -- the elements are listed as are. - # `percent' -- the elements are `flattened': spaces are singled out, - # and no new line remains. - define([_at_at], - [at_ifelse([$#], [1], [], - [$#], [2], [[[$2]]], - [[[$2]][$1]$0([$1], at_shift(at_shift($@)))])]) - define([_at_percent], - [at_ifelse([$#], [1], [], - [$#], [2], [at_flatten([$2])], - [at_flatten([$2])[$1]$0([$1], at_shift(at_shift($@)))])]) - define([_at_star], - [at_ifelse([$#], [1], [], - [$#], [2], [[$2]], - [[$2][$1]$0([$1], at_shift(at_shift($@)))])]) - - # FLATTEN quotes its result. - define([at_flatten], - [at_patsubst(at_patsubst(at_patsubst([[[$1]]], - [\\ - ]), - [[ - ]+], - [ ]), - [^ *\(.*\) *$], [[\1]])]) - - define([at_args], [at_shift(at_shift(at_shift(at_shift(at_shift($@)))))]) - define([at_at], [_$0([$1], at_args($@))]) - define([at_percent], [_$0([$1], at_args($@))]) - define([at_star], [_$0([$1], at_args($@))]) - -EOF - - # If you trace `define', then on `define([m4_exit], defn([m4exit])' you - # will produce - # - # AT_define([m4sugar.m4], [115], [1], [define], [m4_exit], ) - # - # Since `' is not quoted, the outter m4, when processing - # `trace.m4' will exit prematurely. Hence, move all the builtins to - # the `at_' name space. - echo '# Copy the builtins.' >>$tmp/trace.m4 - echo "dumpdef" | - $M4 2>&1 >/dev/null | - sed 's/^\([^:]*\):.*/define([at_\1], defn([\1]))/' >>$tmp/trace.m4 - echo >>$tmp/trace.m4 - - echo '# Disable the builtins.' >>$tmp/trace.m4 - echo "dumpdef" | - $M4 2>&1 >/dev/null | - sed 's/^\([^:]*\):.*/at_undefine([\1])/' >>$tmp/trace.m4 - echo >>$tmp/trace.m4 - - - # trace2m4.sed - # ------------ - # Transform the traces from m4 into an m4 input file. - # Typically, transform: - # - # | m4trace:configure.ac:3: -1- AC_SUBST([exec_prefix], [NONE]) - # - # into - # - # | AT_AC_SUBST([configure.ac], [3], [1], [AC_SUBST], [exec_prefix], [NONE]) - # - # Pay attention that the file name might include colons, if under DOS - # for instance, so we don't use `[^:][^:]*'. - # The first s/// catches multiline traces, the second, traces as above. - preamble='m4trace:\(..*\):\([0-9][0-9]*\): -\([0-9][0-9]*\)-' - cat >$tmp/trace2m4.sed <$tmp/translate.awk <<\EOF - function trans (arg, sep) - { - # File name. - if (arg == "f") - return "$1" - # Line number. - if (arg == "l") - return "$2" - # Depth. - if (arg == "d") - return "$3" - # Name (also available as $0). - if (arg == "n") - return "$4" - # Escaped dollar. - if (arg == "$") - return "$" - - # $@, list of quoted effective arguments. - if (arg == "@") - return "]at_at([" (separator ? separator : ",") "], $@)[" - # $*, list of unquoted effective arguments. - if (arg == "*") - return "]at_star([" (separator ? separator : ",") "], $@)[" - # $%, list of flattened unquoted effective arguments. - if (arg == "%") - return "]at_percent([" (separator ? separator : ":") "], $@)[" - } - - function error (message) - { - print message | "cat >&2" - exit 1 - } - - { - # Accumulate the whole input. - request = request $0 "\n" - } - - END { - # Chomp. - request = substr (request, 1, length (request) - 1) - # The default request is `$f:$l:$n:$*'. - colon = index (request, ":") - macro = colon ? substr (request, 1, colon - 1) : request - request = colon ? substr (request, colon + 1) : "$f:$l:$n:$%" - - res = "" - - for (cp = request; cp; cp = substr (cp, 2)) - { - char = substr (cp, 1, 1) - if (char == "$") - { - if (match (cp, /^\$[0-9]+/)) - { - # $n -> $(n + 4) - res = res "$" (substr (cp, 2, RLENGTH - 1) + 4) - cp = substr (cp, RLENGTH) - } - else if (substr (cp, 2, 1) ~ /[fldn$@%*]/) - { - # $x, no separator given. - res = res trans(substr (cp, 2, 1)) - cp = substr (cp, 2) - } - else if (substr (cp, 2, 1) == "{") - { - # ${sep}x, long separator. - end = index (cp, "}") - if (!end) - error("invalid escape: " cp) - separator = substr (cp, 3, end - 3) - if (substr (cp, end + 1, 1) ~ /[*@%]/) - res = res trans(substr (cp, end + 1, 1), separator) - else - error("invalid escape: " cp) - cp = substr (cp, end + 1) - } - else if (substr (cp, 3, 1) ~ /[*@%]/) - { - # $sx, short separator `s'. - res = res trans(substr (cp, 3, 1), substr (cp, 2, 1)) - cp = substr(cp, 3) - } - else - { - error("invalid escape: " substr (cp, 1, 2)) - } - } - else - res = res char - } - - # Produce the definition of AT_ = the translation of the request. - print "at_define([AT_" macro "]," - print "[[" res "]])" - print "" - close("cat >&2") - } -EOF - - - # Extract both the m4 program and the m4 options from TRACES. - echo "## ------------------------- ##" >>$tmp/trace.m4 - echo "## Trace processing macros. ##" >>$tmp/trace.m4 - echo "## ------------------------- ##" >>$tmp/trace.m4 - echo >>$tmp/trace.m4 - - eval set dummy "$traces" - shift - for trace - do - echo "# $trace" >>$tmp/trace.m4 - - # The request may be several lines long, hence sed has to quit. - macro_name=`echo "$trace" | sed 's/:.*//;q'` - # If for instance TRACE is `define', be sure to have an empty - # TRACE_FORMAT. - case $trace in - $macro_name:* ) - trace_format=`echo "$trace" | sed "1s/^$macro_name:/:/"`;; - * ) - trace_format=;; - esac - - # GNU M4 1.4's tracing of builtins is buggy. When run on this input: - # - # | divert(-1) - # | changequote([, ]) - # | define([m4_eval], defn([eval])) - # | eval(1) - # | m4_eval(2) - # | undefine([eval]) - # | m4_eval(3) - # - # it behaves this way: - # - # | % m4 input.m4 -da -t eval - # | m4trace: -1- eval(1) - # | m4trace: -1- m4_eval(2) - # | m4trace: -1- m4_eval(3) - # | % - # - # Conversely: - # - # | % m4 input.m4 -da -t m4_eval - # | % - # - # So we will merge them, i.e. tracing `BUILTIN' or tracing - # `m4_BUILTIN' will be the same: tracing both, but honoring the - # *last* trace specification. - # FIXME: This is not enough: in the output `$0' will be `BUILTIN' - # sometimes and `m4_BUILTIN' at others. We should render a unique name, - # the one specified by the user. - base_name=`echo "$macro_name" | sed 's/^m4_//'` - if echo "ifdef(\`$base_name', \`', \`m4exit(-1)')" | $M4; then - # BASE_NAME is a builtin. - trace_opt="$trace_opt -t $base_name -t m4_$base_name" - echo "$base_name$trace_format" | - $AWK -f $tmp/translate.awk >>$tmp/trace.m4 || - { (exit 1); exit 1; } - echo "m4_$base_name$trace_format" | - $AWK -f $tmp/translate.awk >>$tmp/trace.m4 || - { (exit 1); exit 1; } - else - # MACRO_NAME is not a builtin. - trace_opt="$trace_opt -t $macro_name" - echo "$trace" | - $AWK -f $tmp/translate.awk >>$tmp/trace.m4 || - { (exit 1); exit 1; } - fi - echo >>$tmp/trace.m4 - done - - echo "## ------------------- ##" >>$tmp/trace.m4 - echo "## Traces to process. ##" >>$tmp/trace.m4 - echo "## ------------------- ##" >>$tmp/trace.m4 - echo >>$tmp/trace.m4 - echo "at_divert(0)at_dnl" >>$tmp/trace.m4 - - # Do we trace the initialization? - # `errprint' must be silent, otherwise there can be warnings mixed - # with traces in m4's stderr. - run_m4_trace="$run_m4 $trace_opt -daflq -Derrprint" - if $initialization; then - trace_prefiles="$m4_prefiles" - else - trace_prefiles="$m4f_prefiles" - fi - - # Run m4 on the input file to get traces. - # - # We used to have a simple pipe, which was very convenient as it - # allows to use traces on never ending expansions (i.e., when - # debugging :) but it is requires to keep error messages *and* - # traces in stderr. This is too fragile, as it results in - # unexpected data in the output. autoheader has been fragile to - # this. - $verbose "$me: running $run_m4_trace $trace_prefiles $infile -o $tmp/traces" >&2 - $run_m4_trace $trace_prefiles $infile -o $tmp/traces >/dev/null || - { - 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 +# Autom4te expansion. +eval set dummy "$traces" +shift +$verbose "$me: running $run_autom4te ""$@"" $infile --output $outfile" >&2 +$run_autom4te "$@" $infile --output $outfile || + { (exit 1); exit 1; } - $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. - if $debug; then - cat >>$tmp/trace.m4 - $M4 $tmp/trace.m4 - else - $M4 $tmp/trace.m4 - - fi | - # It makes no sense to try to transform __oline__. - sed ' - s/@<:@/[/g - s/@:>@/]/g - s/@S|@/$/g - s/@%:@/#/g - ' >&4 || - { - echo "$me: traces formatting failed" >&2 - (exit 1); exit 1 - } - ;; - - - ## ------------ ## - ## Unknown task ## - ## ------------ ## - - *) echo "$me: internal error: unknown task: $task" >&2 - (exit 1); exit 1 -esac +if test -z "$traces" && test "x$outfile" != x-; then + chmod +x $outfile +fi (exit $status); exit $status diff --git a/bin/autoheader.in b/bin/autoheader.in index 0babde46c..492ad0779 100644 --- a/bin/autoheader.in +++ b/bin/autoheader.in @@ -122,7 +122,7 @@ while test $# -gt 0 ; do shift ;; --autoconf-dir=* | -A?* ) - autoconf_dir=$optarg + autoconf_dir=$optarg shift ;; --autoconf-dir | -A ) test $# = 1 && eval "$exit_missing_arg" @@ -238,8 +238,17 @@ case $# in * ) echo "$me: no input file" >&2 (exit 1); exit 1;; - esac;; - 1) infile=$1 ;; + esac + infilename=$infile + ;; + 1) if test "x$1" = "x-"; then + cat >$tmp/stdin + infile=$tmp/stdin + else + infile=$1 + fi + infilename="Standard input" + ;; *) exec >&2 echo "$me: invalid number of arguments." echo "$help" @@ -247,7 +256,9 @@ case $# in esac # Set up autoconf. -autoconf="$autoconf -l $localdir" +autoconf="$autoconf -l $localdir "\ +`$verbose "--verbose "`\ +`$debug && echo "--debug "` export autoconf_dir # ----------------------- # @@ -299,7 +310,7 @@ esac # Don't write "do not edit" -- it will get copied into the # config.h, which it's ok to edit. cat <$tmp/config.hin -/* $config_h_in. Generated automatically from $infile by autoheader. */ +/* $config_h_in. Generated automatically from $infilename by autoheader. */ EOF # Dump the top. diff --git a/bin/autom4te.in b/bin/autom4te.in index d3a91cadf..491e9f69f 100644 --- a/bin/autom4te.in +++ b/bin/autom4te.in @@ -128,7 +128,9 @@ sub request { if (! exists ${$obj->macro}{$_}) { + s/^m4_//; ${$obj->macro}{$_} = 1; + ${$obj->macro}{"m4_$_"} = 1; $obj->valid (0); } } @@ -320,8 +322,11 @@ sub END if (!$debug && defined $tmp && -d $tmp) { - unlink <$tmp/*> - or warn ("$me: cannot empty $tmp: $!\n"), _exit (1); + if (<$tmp/*>) + { + unlink <$tmp/*> + or warn ("$me: cannot empty $tmp: $!\n"), _exit (1); + } rmdir $tmp or warn ("$me: cannot remove $tmp: $!\n"), _exit (1); } @@ -374,7 +379,7 @@ sub find_file ($) if -f File::Spec->catfile ($path, $filename) } - die "$me: programming error"; + die "$me: programming error: $filename"; } @@ -418,7 +423,7 @@ Tracing: Report bugs to . EOF - # Help font-lock: ` + # Help font-lock-mode find an closing back quote: ` exit 0; } @@ -467,22 +472,22 @@ sub parse_args () # instead of mapping `FOO' to undef, Getopt maps it to `1', preventing # us from distinguishing `-t FOO' from `-t FOO=1'. So let's do it # by hand. - "t|trace=s" => \@trace, + "t|trace=s" => \@trace, ) or exit 1; + die "$me: too few arguments +Try `$me --help' for more information.\n" + unless @ARGV; + # Convert @trace to %trace. - # The default format is `$f:$l:$n:$*'. + # The default format is `$f:$l:$n:$%'. foreach (@trace) { - /^([^:]+)(?::(.*))?$/; - $trace{$1} = defined $2 ? $2 : '$f:$l:$n:$*'; + /^([^:]+)(?::(.*))?$/ms; + $trace{$1} = defined $2 ? $2 : '$f:$l:$n:$%'; } - 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) @@ -551,7 +556,7 @@ sub handle_output ($) verbose "creating $output"; # Load the forbidden/allowed patterns. - my $forbidden; + my $forbidden = "^\$"; if (-f "$tmp/forbidden.rx") { my $fh = new IO::File ("$tmp/forbidden.rx"); @@ -980,8 +985,8 @@ sub up_to_date_p ($$) ## Main program. ## ## -------------- ## -parse_args; mktmpdir ('t4'); +parse_args; # We need our cache directory. if (! -d "$me.cache") diff --git a/bin/autoupdate.in b/bin/autoupdate.in index 7cc362a8f..19be24de2 100644 --- a/bin/autoupdate.in +++ b/bin/autoupdate.in @@ -67,6 +67,15 @@ sub mktmpdir () } +# verbose +# ------- +sub verbose (@) +{ + print STDERR "$me: ", @_, "\n" + if $verbose; +} + + # END # --- # Exit nonzero whenever closing STDOUT fails. @@ -97,6 +106,23 @@ sub END } +# xsystem ($COMMAND) +# ------------------ +sub xsystem ($) +{ + my ($command) = @_; + + verbose "running: $command"; + + (system $command) == 0 + or die ("$me: " + . (split (' ', $command))[0] + . " failed with exit status: " + . ($? >> 8) + . "\n"); +} + + # print_usage () # -------------- # Display usage (--help). @@ -105,19 +131,19 @@ sub print_usage () print <<"END"; Usage: $0 [OPTION] ... [TEMPLATE-FILE...] -Update the TEMPLATE-FILE... if given, or \`configure.ac' if present, -or else \`configure.in', to the syntax of the current version of +Update the TEMPLATE-FILE... if given, or \`configure.ac\' if present, +or else \`configure.in\', to the syntax of the current version of Autoconf. The original files are backed up. Operation modes: -h, --help print this help, then exit -V, --version print version number, then exit -v, --verbose verbosely report processing - -d, --debug don't remove temporary files + -d, --debug don\'t remove temporary files Library directories: - -A, --autoconf-dir=ACDIR Autoconf's macro files location (rarely needed) - -l, --localdir=DIR location of \`aclocal.m4' + -A, --autoconf-dir=ACDIR Autoconf\'s macro files location (rarely needed) + -l, --localdir=DIR location of \`aclocal.m4\' Environment variables: M4 GNU M4 1.4 or above @@ -186,8 +212,10 @@ sub parse_args () 'V|version' => \&print_version, 'v|verbose' => \$verbose) or exit 1; + push @ARGV, '-' if $update_stdin; + if (! @ARGV) { my $configure_ac = find_configure_ac; @@ -237,8 +265,9 @@ sub find_slaves () find_slaves; parse_args; mktmpdir; -$autoconf .= " --autoconf-dir $autoconf_dir --localdir $localdir"; - +$autoconf .= " --autoconf-dir $autoconf_dir --localdir $localdir "; +$autoconf .= "--debug " if $debug; +$autoconf .= "--verbose " if $verbose; # @M4_BUILTINS -- M4 builtins and a useful comment. my @m4_builtins = `echo dumpdef | $m4 2>&1 >/dev/null`; @@ -306,7 +335,7 @@ my $au_changequote = 's/\b(' . join ('|', keys %au_macros) . ')\b/_au_changequote([,])$1/g'; # au.m4 -- definitions the AU macros. -system ("$autoconf --trace AU_DEFUN:'_au_defun(\@<:\@\$1\@:>\@, +xsystem ("$autoconf --trace AU_DEFUN:'_au_defun(\@<:\@\$1\@:>\@, \@<:\@\$2\@:>\@)' -i /dev/null " . ">$tmp/au.m4"); diff --git a/man/autom4te.1 b/man/autom4te.1 index 39934b059..542a9e9f2 100644 --- a/man/autom4te.1 +++ b/man/autom4te.1 @@ -1,5 +1,5 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.24. -.TH AUTOM4TE "1" "July 2001" "GNU Autoconf 2.50a" FSF +.TH AUTOM4TE "1" "July 2001" "GNU Autoconf 2.52a" FSF .SH NAME autom4te \- Generate files and scripts thanks to M4 .SH SYNOPSIS diff --git a/tests/atspecific.m4 b/tests/atspecific.m4 index 0e822101c..082ecdfd0 100644 --- a/tests/atspecific.m4 +++ b/tests/atspecific.m4 @@ -44,7 +44,7 @@ AC_STATE_SAVE(after) # Also remove `configure.in', just in case one remained from a previous # run. m4_define([AT_CHECK_AUTOCONF], -[AT_CLEANUP_FILES(configure.in configure)dnl +[AT_CLEANUP_FILES(configure.in configure autom4te.cache)dnl AT_CHECK([autoconf --autoconf-dir .. -l $at_srcdir $1], m4_default([$2], [0]), [$3], [$4])]) diff --git a/tests/tools.at b/tests/tools.at index 47bf811fb..133180368 100644 --- a/tests/tools.at +++ b/tests/tools.at @@ -340,7 +340,7 @@ AC_DEFINE(this, "whatever you want.") ]]) AT_CHECK([autoheader --autoconf-dir .. -