From: Akim Demaille Date: Thu, 16 Nov 2000 08:33:46 +0000 (+0000) Subject: Provide a means for escaping the forbidden patterns test. X-Git-Tag: autoconf-2.50~418 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e62a041a2f5bd5da177598d69418746d32a52194;p=thirdparty%2Fautoconf.git 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. --- diff --git a/ChangeLog b/ChangeLog index 5e243196b..9db3e81cc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2000-11-16 Akim Demaille + + 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 * acspecific.m4 (AC_SYS_LARGEFILE): Don't worry about diff --git a/autoconf.in b/autoconf.in index 24221af96..b6836b590 100644 --- a/autoconf.in +++ b/autoconf.in @@ -260,7 +260,8 @@ $debug || # 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" @@ -314,11 +315,40 @@ case $task in # helpful. Because quoting can sometimes get really painful in m4, # there are special @tokens@ to substitute. cat >$tmp/finalize.awk < 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 == "") @@ -351,21 +381,9 @@ case $task in # 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 } @@ -379,11 +397,11 @@ case $task in { 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) @@ -392,7 +410,10 @@ case $task in } } 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. @@ -711,7 +732,7 @@ EOF ## Unknown task ## ## ------------ ## - *)echo "$me: internal error: unknown task: $task" >&2 + *) echo "$me: internal error: unknown task: $task" >&2 (exit 1); exit esac diff --git a/autoconf.sh b/autoconf.sh index 24221af96..b6836b590 100644 --- a/autoconf.sh +++ b/autoconf.sh @@ -260,7 +260,8 @@ $debug || # 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" @@ -314,11 +315,40 @@ case $task in # helpful. Because quoting can sometimes get really painful in m4, # there are special @tokens@ to substitute. cat >$tmp/finalize.awk < 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 == "") @@ -351,21 +381,9 @@ case $task in # 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 } @@ -379,11 +397,11 @@ case $task in { 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) @@ -392,7 +410,10 @@ case $task in } } 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. @@ -711,7 +732,7 @@ EOF ## Unknown task ## ## ------------ ## - *)echo "$me: internal error: unknown task: $task" >&2 + *) echo "$me: internal error: unknown task: $task" >&2 (exit 1); exit esac diff --git a/bin/autoconf.in b/bin/autoconf.in index 24221af96..b6836b590 100644 --- a/bin/autoconf.in +++ b/bin/autoconf.in @@ -260,7 +260,8 @@ $debug || # 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" @@ -314,11 +315,40 @@ case $task in # helpful. Because quoting can sometimes get really painful in m4, # there are special @tokens@ to substitute. cat >$tmp/finalize.awk < 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 == "") @@ -351,21 +381,9 @@ case $task in # 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 } @@ -379,11 +397,11 @@ case $task in { 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) @@ -392,7 +410,10 @@ case $task in } } 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. @@ -711,7 +732,7 @@ EOF ## Unknown task ## ## ------------ ## - *)echo "$me: internal error: unknown task: $task" >&2 + *) echo "$me: internal error: unknown task: $task" >&2 (exit 1); exit esac diff --git a/lib/m4sugar/m4sugar.m4 b/lib/m4sugar/m4sugar.m4 index 7b8f560c0..dadb4f277 100644 --- a/lib/m4sugar/m4sugar.m4 +++ b/lib/m4sugar/m4sugar.m4 @@ -667,6 +667,7 @@ m4_divert_pop()dnl ]) + ## -------------------------------------------- ## ## 8. Defining macros with bells and whistles. ## ## -------------------------------------------- ## @@ -1085,6 +1086,14 @@ m4_define([$1], [_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. ## ## ----------------------------- ## @@ -1485,3 +1494,22 @@ m4_define([m4_version_unletter], 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])]) diff --git a/m4sugar.m4 b/m4sugar.m4 index 7b8f560c0..dadb4f277 100644 --- a/m4sugar.m4 +++ b/m4sugar.m4 @@ -667,6 +667,7 @@ m4_divert_pop()dnl ]) + ## -------------------------------------------- ## ## 8. Defining macros with bells and whistles. ## ## -------------------------------------------- ## @@ -1085,6 +1086,14 @@ m4_define([$1], [_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. ## ## ----------------------------- ## @@ -1485,3 +1494,22 @@ m4_define([m4_version_unletter], 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])]) diff --git a/tests/tools.at b/tests/tools.at index 50dd7ba20..d4bdc3c11 100644 --- a/tests/tools.at +++ b/tests/tools.at @@ -334,11 +334,11 @@ AT_CLEANUP -## ----------------------------------------------- ## -## 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 @@ -349,12 +349,19 @@ and_AZ_that_too 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 ]])