📄 autom4te.in
字号:
#! @PERL@ -w# -*- perl -*-# @configure_input@eval 'case $# in 0) exec @PERL@ -S "$0";; *) exec @PERL@ -S "$0" "$@";; esac' if 0;# autom4te - Wrapper around M4 libraries.# Copyright (C) 2001, 2002, 2003, 2005, 2006 Free Software Foundation, Inc.# This program is free software; you can redistribute it and/or modify# it under the terms of the GNU General Public License as published by# the Free Software Foundation; either version 2, or (at your option)# any later version.# This program is distributed in the hope that it will be useful,# but WITHOUT ANY WARRANTY; without even the implied warranty of# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the# GNU General Public License for more details.# You should have received a copy of the GNU General Public License# along with this program; if not, write to the Free Software# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA# 02110-1301, USA.BEGIN{ my $datadir = $ENV{'autom4te_perllibdir'} || '@datadir@'; unshift @INC, $datadir; # Override SHELL. On DJGPP SHELL may not be set to a shell # that can handle redirection and quote arguments correctly, # e.g.: COMMAND.COM. For DJGPP always use the shell that configure # has detected. $ENV{'SHELL'} = '@SHELL@' if ($^O eq 'dos');}use Autom4te::C4che;use Autom4te::ChannelDefs;use Autom4te::Channels;use Autom4te::FileUtils;use Autom4te::General;use Autom4te::XFile;use File::Basename;use strict;# Data directory.my $datadir = $ENV{'AC_MACRODIR'} || '@datadir@';# $LANGUAGE{LANGUAGE} -- Automatic options for LANGUAGE.my %language;my $output = '-';# Mode of the output file except for traces.my $mode = "0666";# If melt, don't use frozen files.my $melt = 0;# Names of the cache directory, cache directory index, trace cache# prefix, and output cache prefix. And the IO objet for the index.my $cache;my $icache;my $tcache;my $ocache;my $icache_file;# The macros to trace mapped to their format, as specified by the# user.my %trace;# The macros the user will want to trace in the future.# We need `include' to get the included file, `m4_pattern_forbid' and# `m4_pattern_allow' to check the output.## FIXME: What about `sinclude'?my @preselect = ('include', 'm4_pattern_allow', 'm4_pattern_forbid', '_m4_warn');# M4 include path.my @include;# Do we freeze?my $freeze = 0;# $M4.my $m4 = $ENV{"M4"} || '@M4@';# Some non-GNU m4's don't reject the --help option, so give them /dev/null.fatal "need GNU m4 1.4 or later: $m4" if system "$m4 --help </dev/null 2>&1 | grep reload-state >/dev/null";# Set some high recursion limit as the default limit, 250, has already# been hit with AC_OUTPUT. Don't override the user's choice.$m4 .= ' --nesting-limit=1024' if " $m4 " !~ / (--nesting-limit(=[0-9]+)?|-L[0-9]*) /;# @M4_BUILTIN -- M4 builtins and a useful comment.my @m4_builtin = `echo dumpdef | $m4 2>&1 >/dev/null`;map { s/:.*//;s/\W// } @m4_builtin;# %M4_BUILTIN_ALTERNATE_NAME# --------------------------# The builtins are renamed, e.g., `define' is renamed `m4_define'.# So map `define' to `m4_define' and conversely.# Some macros don't follow this scheme: be sure to properly map to their# alternate name too.## This is because 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 return a unique name,# the one specified by the user.## FIXME: To be absolutely rigorous, I would say that given that we# _redefine_ divert (instead of _copying_ it), divert and the like# should not be part of this list.my %m4_builtin_alternate_name;@m4_builtin_alternate_name{"$_", "m4_$_"} = ("m4_$_", "$_") foreach (grep { !/m4wrap|m4exit|dnl|ifelse|__.*__/ } @m4_builtin);@m4_builtin_alternate_name{"ifelse", "m4_if"} = ("m4_if", "ifelse");@m4_builtin_alternate_name{"m4exit", "m4_exit"} = ("m4_exit", "m4exit");@m4_builtin_alternate_name{"m4wrap", "m4_wrap"} = ("m4_wrap", "m4wrap");# $HELP# -----$help = "Usage: $0 [OPTION] ... [FILES]Run GNU M4 on the FILES, avoiding useless runs. Output the traces if tracing,the frozen file if freezing, otherwise the expansion of the FILES.If some of the FILES are named \`FILE.m4f\' they are considered to be M4frozen files of all the previous files (which are therefore not loaded).If \`FILE.m4f\' is not found, then \`FILE.m4\' will be used, together withall the previous files.Some files may be optional, i.e., will only be processed if found in theinclude path, but then must end in \`.m4?\'; the question mark is not part ofthe actual file name.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 -o, --output=FILE save output in FILE (defaults to \`-\', stdout) -f, --force don\'t rely on cached values -W, --warnings=CATEGORY report the warnings falling in CATEGORY -l, --language=LANG specify the set of M4 macros to use -C, --cache=DIRECTORY preserve results for future runs in DIRECTORY --no-cache disable the cache -m, --mode=OCTAL change the non trace output file mode (0666) -M, --melt don\'t use M4 frozen filesLanguages include: \`Autoconf\' create Autoconf configure scripts \`Autotest\' create Autotest test suites \`M4sh\' create M4sh shell scripts \`M4sugar\' create M4sugar output" . Autom4te::ChannelDefs::usage . "The environment variables \`M4\' and \`WARNINGS\' are honored.Library directories: -B, --prepend-include=DIR prepend directory DIR to search path -I, --include=DIR append directory DIR to search pathTracing: -t, --trace=MACRO report the MACRO invocations -p, --preselect=MACRO prepare to trace MACRO in a future runFreezing: -F, --freeze produce an M4 frozen state file for FILESReport bugs to <bug-autoconf\@gnu.org>.";# $VERSION# --------$version = <<"EOF";autom4te (@PACKAGE_NAME@) @VERSION@Written by Akim Demaille.Copyright (C) 2006 Free Software Foundation, Inc.This is free software; see the source for copying conditions. There is NOwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.EOF## ---------- #### Routines. #### ---------- ### $OPTION# files_to_options (@FILE)# ------------------------# Transform Autom4te conventions (e.g., using foo.m4f to designate a frozen# file) into a suitable command line for M4 (e.g., using --reload-state).sub files_to_options (@){ my (@file) = @_; my @res; foreach my $file (@file) { if ($file =~ /\.m4f$/) { push @res, "--reload-state=$file"; } else { push @res, $file; } } return join ' ', @res;}# load_configuration ($FILE)# --------------------------# Load the configuration $FILE.sub load_configuration ($){ my ($file) = @_; use Text::ParseWords; my $cfg = new Autom4te::XFile ($file); my $lang; while ($_ = $cfg->getline) { chomp; # Comments. next if /^\s*(\#.*)?$/; my @words = shellwords ($_); my $type = shift @words; if ($type eq 'begin-language:') { fatal "$file:$.: end-language missing for: $lang" if defined $lang; $lang = lc $words[0]; } elsif ($type eq 'end-language:') { error "$file:$.: end-language mismatch: $lang" if $lang ne lc $words[0]; $lang = undef; } elsif ($type eq 'args:') { fatal "$file:$.: no current language" unless defined $lang; push @{$language{$lang}}, @words; } else { error "$file:$.: unknown directive: $type"; } }}# parse_args ()# -------------# Process any command line arguments.sub parse_args (){ # We want to look for the early options, which should not be found # in the configuration file. Prepend to the user arguments. # Perform this repeatedly so that we can use --language in language # definitions. Beware that there can be several --language # invocations. my @language; do { @language = (); use Getopt::Long; Getopt::Long::Configure ("pass_through", "permute"); GetOptions ("l|language=s" => \@language); foreach (@language) { error "unknown language: $_" unless exists $language{lc $_}; unshift @ARGV, @{$language{lc $_}}; } } while @language; # --debug is useless: it is parsed below. if (exists $ENV{'AUTOM4TE_DEBUG'}) { print STDERR "$me: concrete arguments:\n"; foreach my $arg (@ARGV) { print STDERR "| $arg\n"; } } # Process the arguments for real this time. my @trace; my @prepend_include; parse_WARNINGS; getopt ( # Operation modes: "o|output=s" => \$output, "W|warnings=s" => \&parse_warnings, "m|mode=s" => \$mode, "M|melt" => \$melt, # Library directories: "B|prepend-include=s" => \@prepend_include, "I|include=s" => \@include, # Tracing: # Using a hash for traces is seducing. Unfortunately, upon `-t FOO', # 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, "p|preselect=s" => \@preselect, # Freezing. "F|freeze" => \$freeze, # Caching. "C|cache=s" => \$cache, "no-cache" => sub { $cache = undef; }, ); fatal "too few argumentsTry `$me --help' for more information." unless @ARGV; # Freezing: # We cannot trace at the same time (well, we can, but it sounds insane). # And it implies melting: there is risk not to update properly using # old frozen files, and worse yet: we could load a frozen file and # refreeze it! A sort of caching :) fatal "cannot freeze and trace" if $freeze && @trace; $melt = 1 if $freeze; # Names of the cache directory, cache directory index, trace cache # prefix, and output cache prefix. If the cache is not to be # preserved, default to a temporary directory (automatically removed # on exit). $cache = $tmp unless $cache; $icache = "$cache/requests"; $tcache = "$cache/traces."; $ocache = "$cache/output."; # Normalize the includes: the first occurrence is enough, several is # a pain since it introduces a useless difference in the path which # invalidates the cache. And strip `.' which is implicit and always # first. @include = grep { !/^\.$/ } uniq (reverse(@prepend_include), @include); # Convert @trace to %trace, and work around the M4 builtins tracing # problem. # The default format is `$f:$l:$n:$%'. foreach (@trace) { /^([^:]+)(?::(.*))?$/ms; $trace{$1} = defined $2 ? $2 : '$f:$l:$n:$%'; $trace{$m4_builtin_alternate_name{$1}} = $trace{$1} if exists $m4_builtin_alternate_name{$1}; } # Work around the M4 builtins tracing problem for @PRESELECT. push (@preselect, map { $m4_builtin_alternate_name{$_} } grep { exists $m4_builtin_alternate_name{$_} } @preselect); # If we find frozen files, then all the files before it are # discarded: the frozen file is supposed to include them all. # # We don't want to depend upon m4's --include to find the top level # files, so we use `find_file' here. Try to get a canonical name, # as it's part of the key for caching. And some files are optional # (also handled by `find_file'). my @argv; foreach (@ARGV) { if (/\.m4f$/) { # Frozen files are optional => pass a `?' to `find_file'. my $file = find_file ("$_?", @include); if (!$melt && $file) { @argv = ($file); } else { s/\.m4f$/.m4/; push @argv, find_file ($_, @include); } } else { my $file = find_file ($_, @include); push @argv, $file if $file; } } @ARGV = @argv;}# handle_m4 ($REQ, @MACRO)# ------------------------# Run m4 on the input files, and save the traces on the @MACRO.sub handle_m4 ($@){ my ($req, @macro) = @_; # GNU m4 appends when using --error-output. unlink ($tcache . $req->id . "t"); # Run m4. # # Neutralize its stdin, so that GNU M4 1.5 doesn't neutralize SIGINT. # # We don't output directly to the cache files, to avoid problems # when we are interrupted (that leaves corrupted files). xsystem ("$m4" . join (' --include=', '', @include) . ' --debug=aflq' . (!exists $ENV{'AUTOM4TE_NO_FATAL'} ? ' --fatal-warning' : '') . " --error-output=$tcache" . $req->id . "t" . join (' --trace=', '', sort @macro) . " " . files_to_options (@ARGV) . ' </dev/null' . " >$ocache" . $req->id . "t"); # Everything went ok: preserve the outputs. foreach my $file (map { $_ . $req->id } ($tcache, $ocache)) { use File::Copy; move ("${file}t", "$file") or fatal "cannot rename ${file}t as $file: $!"; }}# warn_forbidden ($WHERE, $WORD, %FORBIDDEN)# ------------------------------------------# $WORD is forbidden. Warn with a dedicated error message if in# %FORBIDDEN, otherwise, a simple `error: possibly undefined macro'# will do.my $first_warn_forbidden = 1;sub warn_forbidden ($$%){ my ($where, $word, %forbidden) = @_; my $message; for my $re (sort keys %forbidden) { if ($word =~ $re) { $message = $forbidden{$re}; last; } } $message ||= "possibly undefined macro: $word"; warn "$where: error: $message\n"; if ($first_warn_forbidden) { warn <<EOF; If this token and others are legitimate, please use m4_pattern_allow. See the Autoconf documentation.EOF $first_warn_forbidden = 0; }}# handle_output ($REQ, $OUTPUT)# -----------------------------# Run m4 on the input files, perform quadrigraphs substitution, check for# forbidden tokens, and save into $OUTPUT.sub handle_output ($$){ my ($req, $output) = @_; verb "creating $output"; # Load the forbidden/allowed patterns. handle_traces ($req, "$tmp/patterns", ('m4_pattern_forbid' => 'forbid:$1:$2', 'm4_pattern_allow' => 'allow:$1')); my @patterns = new Autom4te::XFile ("$tmp/patterns")->getlines; chomp @patterns; my %forbidden =
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -