* tests/tools.at (Forbidden tokens): Test m4_token_allow.
* m4sugar.m4 (m4_file_append, m4_token_allow): New macros.
* autoconf.sh (task script): Pass `tmp' and `verbose' to
finalize.awk.
(finalize.awk::check_patterns): Eve out from the body.
(finalize.awk): Read `$tmp/tokens_allowed', and don't complain for
these exceptions.
+2000-11-16 Akim Demaille <akim@epita.fr>
+
+ Provide a means for escaping the forbidden patterns test.
+
+ * tests/tools.at (Forbidden tokens): Test m4_token_allow.
+ * m4sugar.m4 (m4_file_append, m4_token_allow): New macros.
+ * autoconf.sh (task script): Pass `tmp' and `verbose' to
+ finalize.awk.
+ (finalize.awk::check_patterns): Eve out from the body.
+ (finalize.awk): Read `$tmp/tokens_allowed', and don't complain for
+ these exceptions.
+
2000-11-14 Paul Eggert <eggert@twinsun.com>
* acspecific.m4 (AC_SYS_LARGEFILE): Don't worry about
# 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="$acsite_m4 $aclocal_m4 -I $autoconf_dir -I $localdir"
+m4_common="$acsite_m4 $aclocal_m4 -I $autoconf_dir -I $localdir \
+ -Dm4_tmpdir=\"$tmp\""
run_m4="$M4 $autoconf_dir/autoconf.m4 $m4_common"
run_m4f="$M4 --reload $autoconf_dir/autoconf.m4f $m4_common"
# helpful. Because quoting can sometimes get really painful in m4,
# there are special @tokens@ to substitute.
cat >$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 "/tokens_allowed"'.
+ while ((getline token < (tmp "/tokens_allowed")) > 0)
+ {
+ if (verbose)
+ print "$0: token \`" token "' is allowed" | "cat >&2"
+ tokens_allowed[token] = 1
+ }
+ close (tmp "/tokens_allowed")
+ }
+
function undefined (file, line, macro)
{
print file ":" line ": error: undefined macro: " macro | "cat >&2"
}
+ # If the token in CODE_PART from BEGIN to END is forbidden,
+ # register it for further complains.
+ function check_pattern (pattern, offset)
+ {
+ if (match (code_part, pattern))
+ {
+ token = substr (code_part, RSTART + offset, RLENGTH - offset)
+ if (! tokens_allowed[token])
+ {
+ macros [token] = oline
+ some_macros_were_not_expanded = 1
+ }
+ }
+ }
+
+ # Body.
{
sub(/[ ]*$/, "")
if (\$0 == "")
# We don't \`if ... else if ...' because a single line may contain
# several unexpanded names. That's also why the last two \`match'
# are not grouped together.
- if (match (code_part, /[^$WORDCHAR](A[$ALPHABET]|m4)_[$WORDCHAR]*/))
- {
- macros [substr (code_part, RSTART + 1, RLENGTH - 1)] = oline
- some_macros_were_not_expanded = 1
- }
- if (match (code_part, /^(A[$ALPHABET]|m4)_[$WORDCHAR]*/))
- {
- macros [substr (code_part, RSTART, RLENGTH)] = oline
- some_macros_were_not_expanded = 1
- }
- if (match (code_part, /[$WORDCHAR]*_A[$ALPHABET]_[$WORDCHAR]*/))
- {
- macros [substr (code_part, RSTART, RLENGTH)] = oline
- some_macros_were_not_expanded = 1
- }
+ check_pattern("[^$WORDCHAR](A[$ALPHABET]|m4)_[$WORDCHAR]*", 1)
+ check_pattern("^(A[$ALPHABET]|m4)_[$WORDCHAR]*", 0)
+ check_pattern("[$WORDCHAR]*_A[$ALPHABET]_[$WORDCHAR]*", 0)
print
}
{
line++
for (macro in macros)
- if (index (\$0, macro))
- {
- delete macros [macro]
- undefined("$infile", line, macro)
- }
+ if (index (\$0, macro))
+ {
+ delete macros [macro]
+ undefined("$infile", line, macro)
+ }
}
close ("$infile")
for (macro in macros)
}
}
EOF
- $AWK -f $tmp/finalize.awk <$tmp/configure >&4 || { (exit 1); exit; }
+ $AWK -v tmp="$tmp" \
+ `$verbose "-v verbose=1"` \
+ -f $tmp/finalize.awk <$tmp/configure >&4 ||
+ { (exit 1); exit; }
;; # End of the task script.
## Unknown task ##
## ------------ ##
- *)echo "$me: internal error: unknown task: $task" >&2
+ *) echo "$me: internal error: unknown task: $task" >&2
(exit 1); exit
esac
# 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="$acsite_m4 $aclocal_m4 -I $autoconf_dir -I $localdir"
+m4_common="$acsite_m4 $aclocal_m4 -I $autoconf_dir -I $localdir \
+ -Dm4_tmpdir=\"$tmp\""
run_m4="$M4 $autoconf_dir/autoconf.m4 $m4_common"
run_m4f="$M4 --reload $autoconf_dir/autoconf.m4f $m4_common"
# helpful. Because quoting can sometimes get really painful in m4,
# there are special @tokens@ to substitute.
cat >$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 "/tokens_allowed"'.
+ while ((getline token < (tmp "/tokens_allowed")) > 0)
+ {
+ if (verbose)
+ print "$0: token \`" token "' is allowed" | "cat >&2"
+ tokens_allowed[token] = 1
+ }
+ close (tmp "/tokens_allowed")
+ }
+
function undefined (file, line, macro)
{
print file ":" line ": error: undefined macro: " macro | "cat >&2"
}
+ # If the token in CODE_PART from BEGIN to END is forbidden,
+ # register it for further complains.
+ function check_pattern (pattern, offset)
+ {
+ if (match (code_part, pattern))
+ {
+ token = substr (code_part, RSTART + offset, RLENGTH - offset)
+ if (! tokens_allowed[token])
+ {
+ macros [token] = oline
+ some_macros_were_not_expanded = 1
+ }
+ }
+ }
+
+ # Body.
{
sub(/[ ]*$/, "")
if (\$0 == "")
# We don't \`if ... else if ...' because a single line may contain
# several unexpanded names. That's also why the last two \`match'
# are not grouped together.
- if (match (code_part, /[^$WORDCHAR](A[$ALPHABET]|m4)_[$WORDCHAR]*/))
- {
- macros [substr (code_part, RSTART + 1, RLENGTH - 1)] = oline
- some_macros_were_not_expanded = 1
- }
- if (match (code_part, /^(A[$ALPHABET]|m4)_[$WORDCHAR]*/))
- {
- macros [substr (code_part, RSTART, RLENGTH)] = oline
- some_macros_were_not_expanded = 1
- }
- if (match (code_part, /[$WORDCHAR]*_A[$ALPHABET]_[$WORDCHAR]*/))
- {
- macros [substr (code_part, RSTART, RLENGTH)] = oline
- some_macros_were_not_expanded = 1
- }
+ check_pattern("[^$WORDCHAR](A[$ALPHABET]|m4)_[$WORDCHAR]*", 1)
+ check_pattern("^(A[$ALPHABET]|m4)_[$WORDCHAR]*", 0)
+ check_pattern("[$WORDCHAR]*_A[$ALPHABET]_[$WORDCHAR]*", 0)
print
}
{
line++
for (macro in macros)
- if (index (\$0, macro))
- {
- delete macros [macro]
- undefined("$infile", line, macro)
- }
+ if (index (\$0, macro))
+ {
+ delete macros [macro]
+ undefined("$infile", line, macro)
+ }
}
close ("$infile")
for (macro in macros)
}
}
EOF
- $AWK -f $tmp/finalize.awk <$tmp/configure >&4 || { (exit 1); exit; }
+ $AWK -v tmp="$tmp" \
+ `$verbose "-v verbose=1"` \
+ -f $tmp/finalize.awk <$tmp/configure >&4 ||
+ { (exit 1); exit; }
;; # End of the task script.
## Unknown task ##
## ------------ ##
- *)echo "$me: internal error: unknown task: $task" >&2
+ *) echo "$me: internal error: unknown task: $task" >&2
(exit 1); exit
esac
# 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="$acsite_m4 $aclocal_m4 -I $autoconf_dir -I $localdir"
+m4_common="$acsite_m4 $aclocal_m4 -I $autoconf_dir -I $localdir \
+ -Dm4_tmpdir=\"$tmp\""
run_m4="$M4 $autoconf_dir/autoconf.m4 $m4_common"
run_m4f="$M4 --reload $autoconf_dir/autoconf.m4f $m4_common"
# helpful. Because quoting can sometimes get really painful in m4,
# there are special @tokens@ to substitute.
cat >$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 "/tokens_allowed"'.
+ while ((getline token < (tmp "/tokens_allowed")) > 0)
+ {
+ if (verbose)
+ print "$0: token \`" token "' is allowed" | "cat >&2"
+ tokens_allowed[token] = 1
+ }
+ close (tmp "/tokens_allowed")
+ }
+
function undefined (file, line, macro)
{
print file ":" line ": error: undefined macro: " macro | "cat >&2"
}
+ # If the token in CODE_PART from BEGIN to END is forbidden,
+ # register it for further complains.
+ function check_pattern (pattern, offset)
+ {
+ if (match (code_part, pattern))
+ {
+ token = substr (code_part, RSTART + offset, RLENGTH - offset)
+ if (! tokens_allowed[token])
+ {
+ macros [token] = oline
+ some_macros_were_not_expanded = 1
+ }
+ }
+ }
+
+ # Body.
{
sub(/[ ]*$/, "")
if (\$0 == "")
# We don't \`if ... else if ...' because a single line may contain
# several unexpanded names. That's also why the last two \`match'
# are not grouped together.
- if (match (code_part, /[^$WORDCHAR](A[$ALPHABET]|m4)_[$WORDCHAR]*/))
- {
- macros [substr (code_part, RSTART + 1, RLENGTH - 1)] = oline
- some_macros_were_not_expanded = 1
- }
- if (match (code_part, /^(A[$ALPHABET]|m4)_[$WORDCHAR]*/))
- {
- macros [substr (code_part, RSTART, RLENGTH)] = oline
- some_macros_were_not_expanded = 1
- }
- if (match (code_part, /[$WORDCHAR]*_A[$ALPHABET]_[$WORDCHAR]*/))
- {
- macros [substr (code_part, RSTART, RLENGTH)] = oline
- some_macros_were_not_expanded = 1
- }
+ check_pattern("[^$WORDCHAR](A[$ALPHABET]|m4)_[$WORDCHAR]*", 1)
+ check_pattern("^(A[$ALPHABET]|m4)_[$WORDCHAR]*", 0)
+ check_pattern("[$WORDCHAR]*_A[$ALPHABET]_[$WORDCHAR]*", 0)
print
}
{
line++
for (macro in macros)
- if (index (\$0, macro))
- {
- delete macros [macro]
- undefined("$infile", line, macro)
- }
+ if (index (\$0, macro))
+ {
+ delete macros [macro]
+ undefined("$infile", line, macro)
+ }
}
close ("$infile")
for (macro in macros)
}
}
EOF
- $AWK -f $tmp/finalize.awk <$tmp/configure >&4 || { (exit 1); exit; }
+ $AWK -v tmp="$tmp" \
+ `$verbose "-v verbose=1"` \
+ -f $tmp/finalize.awk <$tmp/configure >&4 ||
+ { (exit 1); exit; }
;; # End of the task script.
## Unknown task ##
## ------------ ##
- *)echo "$me: internal error: unknown task: $task" >&2
+ *) echo "$me: internal error: unknown task: $task" >&2
(exit 1); exit
esac
])
+
## -------------------------------------------- ##
## 8. Defining macros with bells and whistles. ##
## -------------------------------------------- ##
[_m4_defun_pro([$1])$2[]_m4_defun_epi([$1])])])])
+# m4_token_allow(TOKEN)
+# ---------------------
+# Declare TOKEN is allowed in the output, even if it matches the forbidden
+# patterns such as `m4_*'.
+m4_define([m4_token_allow],
+[m4_file_append(m4_defn([m4_tmpdir])/tokens_allowed, [$1])])
+
+
## ----------------------------- ##
## Dependencies between macros. ##
## ----------------------------- ##
m4_define([m4_version_compare],
[m4_list_cmp((m4_split(m4_version_unletter([$1]), [\.])),
(m4_split(m4_version_unletter([$2]), [\.])))])
+
+
+
+## ------------------- ##
+## 12. File handling. ##
+## ------------------- ##
+
+
+# It is a real pity that M4 comes with no macros to bind a diversion
+# to a file. So we have to deal without, which makes us a lot more
+# fragile that we should.
+
+
+# m4_file_append(FILE-NAME, CONTENT)
+# ----------------------------------
+m4_define([m4_file_append],
+[m4_syscmd([cat >>$1 <<_m4eof
+$2
+_m4eof])])
])
+
## -------------------------------------------- ##
## 8. Defining macros with bells and whistles. ##
## -------------------------------------------- ##
[_m4_defun_pro([$1])$2[]_m4_defun_epi([$1])])])])
+# m4_token_allow(TOKEN)
+# ---------------------
+# Declare TOKEN is allowed in the output, even if it matches the forbidden
+# patterns such as `m4_*'.
+m4_define([m4_token_allow],
+[m4_file_append(m4_defn([m4_tmpdir])/tokens_allowed, [$1])])
+
+
## ----------------------------- ##
## Dependencies between macros. ##
## ----------------------------- ##
m4_define([m4_version_compare],
[m4_list_cmp((m4_split(m4_version_unletter([$1]), [\.])),
(m4_split(m4_version_unletter([$2]), [\.])))])
+
+
+
+## ------------------- ##
+## 12. File handling. ##
+## ------------------- ##
+
+
+# It is a real pity that M4 comes with no macros to bind a diversion
+# to a file. So we have to deal without, which makes us a lot more
+# fragile that we should.
+
+
+# m4_file_append(FILE-NAME, CONTENT)
+# ----------------------------------
+m4_define([m4_file_append],
+[m4_syscmd([cat >>$1 <<_m4eof
+$2
+_m4eof])])
-## ----------------------------------------------- ##
-## autoconf's ability to catch unexpanded macros. ##
-## ----------------------------------------------- ##
+## ------------------ ##
+## Forbidden tokens. ##
+## ------------------ ##
-AT_SETUP([unexpanded macros])
+AT_SETUP([Forbidden tokens])
AT_DATA([configure.in],
[[AC_PLAIN_SCRIPT()dnl
BAC_DEFINE
# AC_THIS_IS_A_COMMENT so just shut up.
It would be very bad if Autoconf forgot to expand [AC_]OUTPUT!
+
+# This is allowed in spite of the name.
+m4_token_allow([AC_UNDEFINED])
+AC_UNDEFINED
+# But it does not allow this,
+MY_AC_UNDEFINED
]])
AT_CHECK([autoconf --autoconf-dir .. -l $at_srcdir], 1, [],
[[configure.in:2: error: undefined macro: AB_THIS_IS_PROBABLY_NOT_DEFINED
configure.in:3: error: undefined macro: AND_AZ_THAT_EITHER
configure.in:4: error: undefined macro: and_AZ_that_too
+configure.in:14: error: undefined macro: MY_AC_UNDEFINED
configure:7: error: undefined macro: AC_OUTPUT
]])