GNU bug report logs - #67841
[PATCH] Clarify error messages for misuse of m4_warn and --help for -W.

Previous Next

Package: automake-patches;

Reported by: Zack Weinberg <zack <at> owlfolio.org>

Date: Fri, 15 Dec 2023 20:45:02 UTC

Severity: normal

Tags: patch

Done: Karl Berry <karl <at> freefriends.org>

Bug is archived. No further changes may be made.

To add a comment to this bug, you must first unarchive it, by sending
a message to control AT debbugs.gnu.org, with unarchive 67841 in the body.
You can then email your comments to 67841 AT debbugs.gnu.org in the normal way.

Toggle the display of automated, internal messages from the tracker.

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to automake-patches <at> gnu.org:
bug#67841; Package automake-patches. (Fri, 15 Dec 2023 20:45:02 GMT) Full text and rfc822 format available.

Acknowledgement sent to Zack Weinberg <zack <at> owlfolio.org>:
New bug report received and forwarded. Copy sent to automake-patches <at> gnu.org. (Fri, 15 Dec 2023 20:45:02 GMT) Full text and rfc822 format available.

Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Zack Weinberg <zack <at> owlfolio.org>
To: autoconf-patches <at> gnu.org,
	automake-patches <at> gnu.org
Subject: [PATCH] Clarify error messages for misuse of m4_warn and --help for
 -W.
Date: Fri, 15 Dec 2023 15:44:35 -0500
In autoconf 2.69, the manual said that you could use “all” and the
empty string as the first argument to m4_warn.  As far as I can tell
this was never actually true, and the manual was corrected in 2.70,
but we still got a bug report from someone who tried it and got a
confusing internal error from the guts of autom4te.

This patch makes us issue a nice helpful user error, instead of a
confusing internal error, when Autom4te::Channels::msg is called with
a bogus channel argument.  If the bogus channel is “all” or the empty
string, that error is demoted to a -Wobsolete warning.  If it is one
of the other special tokens recognized by -W, we customize the error
message, since someone might’ve thought that “none” being acceptable
to -W meant it was also acceptable to m4_warn.  The --help output for
autoconf, autoheader, autom4te, and autoreconf is also adjusted to
clarify that not all of the tokens recognized by -W count as
warning categories.

(Oddly enough, m4_warn([error], […]) actually issues an error, because
the argument to m4_warn is passed straight through as the channel
argument to Autom4te::Channels::msg.  Since neither m4_errprintn(…)
nor m4_fatal(…)  does quite the same thing as m4_warn([error], […]),
I propose to leave that alone for now and promote it to a proper,
documented feature (probably spelled m4_error(…)) post-2.72.)

Since this touches code shared between Autoconf and Automake, I’m not
checking it in yet and I’m requesting comments from both sides of the
fence.  Also, there’s a perl 2.14ism in one place (s///a) which I need
to figure out how to make 2.6-compatible before it can land.

Addresses <https://savannah.gnu.org/support/?110872>.

 * lib/Autom4te/Channels.pm (msg): If the channel argument is invalid,
   don’t crash; report the mistake and use the ‘syntax’ channel.
   (report_bad_channel): New function for reporting invalid channels.

 * lib/Autom4te/ChannelDefs.pm (usage): Clarify that the list of
   warning categories is exhaustive, and that “all”, “none”,
   “no-CATEGORY”, and “error” are not warning categories.

 * bin/autoconf.in, bin/autoheader.in, bin/autom4te.in,
   bin/autoreconf.in: Tweak --help text.

 * tests/m4sugar.at (m4@&t <at> _warn (bad categories)): New test.
---
 bin/autoconf.in             |  1 +
 bin/autoheader.in           |  1 +
 bin/autom4te.in             |  1 +
 bin/autoreconf.in           | 10 +++---
 lib/Autom4te/ChannelDefs.pm | 10 +++---
 lib/Autom4te/Channels.pm    | 48 +++++++++++++++++++++++++++-
 tests/m4sugar.at            | 63 +++++++++++++++++++++++++++++++++++++
 7 files changed, 123 insertions(+), 11 deletions(-)

diff --git a/bin/autoconf.in b/bin/autoconf.in
index 060a9a04..5f4a2e5c 100644
--- a/bin/autoconf.in
+++ b/bin/autoconf.in
@@ -64,6 +64,7 @@ Operation modes:
   -f, --force               consider all files obsolete
   -o, --output=FILE         save output in FILE (stdout is the default)
   -W, --warnings=CATEGORY   report the warnings falling in CATEGORY
+                            (comma-separated list accepted)
 
 " . Autom4te::ChannelDefs::usage . "
 
diff --git a/bin/autoheader.in b/bin/autoheader.in
index 4afa5f13..f5af0df2 100644
--- a/bin/autoheader.in
+++ b/bin/autoheader.in
@@ -74,6 +74,7 @@ or else 'configure.in'.
   -d, --debug              don\'t remove temporary files
   -f, --force              consider all files obsolete
   -W, --warnings=CATEGORY  report the warnings falling in CATEGORY
+                           (comma-separated list accepted)
 
 " . Autom4te::ChannelDefs::usage . "
 
diff --git a/bin/autom4te.in b/bin/autom4te.in
index 8957a6c9..2e4e7d52 100644
--- a/bin/autom4te.in
+++ b/bin/autom4te.in
@@ -160,6 +160,7 @@ Operation modes:
   -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
+                           (comma-separated list accepted)
   -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
diff --git a/bin/autoreconf.in b/bin/autoreconf.in
index c6077efe..285d0f49 100644
--- a/bin/autoreconf.in
+++ b/bin/autoreconf.in
@@ -84,20 +84,18 @@ Operation modes:
       --no-recursive       don't rebuild sub-packages
   -s, --symlink            with -i, install symbolic links instead of copies
   -m, --make               when applicable, re-run ./configure && make
-  -W, --warnings=CATEGORY  report the warnings falling in CATEGORY [syntax]
+  -W, --warnings=CATEGORY  report the warnings falling in CATEGORY
+                           (comma-separated list accepted)
 
 " . Autom4te::ChannelDefs::usage . "
 
-The environment variable 'WARNINGS' is honored.  Some subtools might
-support other warning types, using 'all' is encouraged.
-
 Library directories:
   -B, --prepend-include=DIR  prepend directory DIR to search path
   -I, --include=DIR          append directory DIR to search path
 
 The environment variables AUTOCONF, ACLOCAL, AUTOHEADER, AUTOM4TE,
-AUTOMAKE, AUTOPOINT, GTKDOCIZE, INTLTOOLIZE, LIBTOOLIZE, M4, and MAKE
-are honored.
+AUTOMAKE, AUTOPOINT, GTKDOCIZE, INTLTOOLIZE, LIBTOOLIZE, M4, MAKE,
+and WARNINGS are honored.
 
 Report bugs to <bug-autoconf\@gnu.org>.
 GNU Autoconf home page: <https://www.gnu.org/software/autoconf/>.
diff --git a/lib/Autom4te/ChannelDefs.pm b/lib/Autom4te/ChannelDefs.pm
index 85ea6f82..9682e8db 100644
--- a/lib/Autom4te/ChannelDefs.pm
+++ b/lib/Autom4te/ChannelDefs.pm
@@ -197,7 +197,7 @@ Return the warning category descriptions.
 
 sub usage ()
 {
-  return "Warning categories include:
+  return "Warning categories are:
   cross                  cross compilation issues
   gnu                    GNU coding standards (default in gnu and gnits modes)
   obsolete               obsolete features or constructions (default)
@@ -207,10 +207,12 @@ sub usage ()
   extra-portability      extra portability issues related to obscure tools
   syntax                 dubious syntactic constructs (default)
   unsupported            unsupported or incomplete features (default)
-  all                    all the warnings
-  no-CATEGORY            turn off warnings in CATEGORY
+
+-W also understands:
+  all                    turn on all the warnings
   none                   turn off all the warnings
-  error                  treat warnings as errors";
+  no-CATEGORY            turn off warnings in CATEGORY
+  error                  treat all enabled warnings as errors";
 }
 
 =item C<prog_error ($MESSAGE, [%OPTIONS])>
diff --git a/lib/Autom4te/Channels.pm b/lib/Autom4te/Channels.pm
index a2ed0a0b..634a61a6 100644
--- a/lib/Autom4te/Channels.pm
+++ b/lib/Autom4te/Channels.pm
@@ -628,7 +628,13 @@ sub msg ($$;$%)
       $location = '';
     }
 
-  confess "unknown channel $channel" unless exists $channels{$channel};
+  if (!exists $channels{$channel})
+    {
+      # This can happen as a result of e.g. m4_warn([nonsense], [message])
+      # so it should not crash.
+      report_bad_channel($channel, $location);
+      $channel = 'syntax';
+    }
 
   my %opts = %{$channels{$channel}};
   _merge_options (%opts, %options);
@@ -662,6 +668,46 @@ sub msg ($$;$%)
     }
 }
 
+sub report_bad_channel ($$)
+{
+  my ($channel, $location) = @_;
+  my $message;
+  my $report_as = 'error';
+
+  # quotemeta is both too aggressive (e.g. it escapes '-') and
+  # too generous (it turns control characters into \ + themselves,
+  # not into symbolic escapes).
+  my $q_channel = $channel;
+  $q_channel =~ s/\\/\\\\/g;
+  $q_channel =~ s/([^\x20-\x7e])/"\\x".sprintf("%02x", ord($1))/aeg;
+  $q_channel =~ s/(?=[\"\$\'\@\`])/\\/g;
+  $q_channel = '"' . $q_channel . '"';
+
+  if ($channel eq '' || $channel eq 'all')
+    {
+      # Prior to version 2.70, the Autoconf manual said it was valid to use
+      # "all" and the empty string as the category argument to m4_warn, so
+      # don't treat those cases as errors.
+      $report_as = 'obsolete';
+      $message = "use of $q_channel as a diagnostic category is obsolete\n";
+      $message .= "(see autom4te --help for a list of valid categories)";
+    }
+  elsif ($channel eq 'none'
+         || ($channel =~ /^no-/ && exists $channels{substr($channel, 3)}))
+    {
+      # Also recognize "none" and "no-[category]", as someone might have
+      # thought anything acceptable to -W is also acceptable to m4_warn.
+      # Note: m4_warn([error], [...]) does actually issue an error.
+      $message = "-W accepts $q_channel, but it is not a diagnostic category";
+    }
+  else
+    {
+      $message = "unknown diagnostic category " . $q_channel;
+    }
+
+  msg $report_as, $location, $message;
+}
+
 
 =item C<setup_channel ($channel, %options)>
 
diff --git a/tests/m4sugar.at b/tests/m4sugar.at
index 2f1dbe37..9a6be0d2 100644
--- a/tests/m4sugar.at
+++ b/tests/m4sugar.at
@@ -244,6 +244,7 @@ AT_CLEANUP
 ## --------- ##
 
 AT_SETUP([m4@&t <at> _warn])
+AT_KEYWORDS([m4@&t <at> _warn])
 
 AT_DATA_M4SUGAR([script.4s],
 [[m4_init
@@ -297,6 +298,68 @@ script.4s:8: the top level
 
 AT_CLEANUP
 
+## ----------------------------------------------- ##
+## Bad m4_warn categories (Autoconf bug #110872).  ##
+## ----------------------------------------------- ##
+
+AT_SETUP([m4@&t <at> _warn (bad categories)])
+AT_KEYWORDS([m4@&t <at> _warn])
+
+AT_DATA_M4SUGAR([script.4s],
+[[m4_init
+m4_warn([],          [empty category])dnl
+m4_warn([bogus],     [invalid category])dnl
+m4_warn([!"%^&*],    [line noise category])dnl " unconfuse editor
+m4_warn([all],       ['all' used as a category])dnl
+m4_warn([none],      ['none' used as a category])dnl
+m4_warn([no-syntax], ['no-syntax' used as a category])dnl
+m4_warn([no-bogus],  ['no-bogus' used as a category])dnl
+m4_warn([error],     [oddly enough, this works])dnl
+]])
+
+AT_CHECK_M4SUGAR([-o- -Wnone], 1, [],
+[script.4s:3: error: unknown diagnostic category "bogus"
+script.4s:4: error: unknown diagnostic category "!\"%^&*"
+script.4s:6: error: -W accepts "none", but it is not a diagnostic category
+script.4s:7: error: -W accepts "no-syntax", but it is not a diagnostic category
+script.4s:8: error: unknown diagnostic category "no-bogus"
+script.4s:9: error: oddly enough, this works
+])
+
+AT_CHECK_M4SUGAR([-o- -Wnone,obsolete], 1, [],
+[script.4s:2: warning: use of "" as a diagnostic category is obsolete
+script.4s:2: (see autom4te --help for a list of valid categories)
+script.4s:3: error: unknown diagnostic category "bogus"
+script.4s:4: error: unknown diagnostic category "!\"%^&*"
+script.4s:5: warning: use of "all" as a diagnostic category is obsolete
+script.4s:5: (see autom4te --help for a list of valid categories)
+script.4s:6: error: -W accepts "none", but it is not a diagnostic category
+script.4s:7: error: -W accepts "no-syntax", but it is not a diagnostic category
+script.4s:8: error: unknown diagnostic category "no-bogus"
+script.4s:9: error: oddly enough, this works
+])
+
+AT_CHECK_M4SUGAR([-o- -Wnone,obsolete,syntax], 1, [],
+[script.4s:2: warning: use of "" as a diagnostic category is obsolete
+script.4s:2: (see autom4te --help for a list of valid categories)
+script.4s:2: warning: empty category
+script.4s:3: error: unknown diagnostic category "bogus"
+script.4s:3: warning: invalid category
+script.4s:4: error: unknown diagnostic category "!\"%^&*"
+script.4s:4: warning: line noise category
+script.4s:5: warning: use of "all" as a diagnostic category is obsolete
+script.4s:5: (see autom4te --help for a list of valid categories)
+script.4s:5: warning: 'all' used as a category
+script.4s:6: error: -W accepts "none", but it is not a diagnostic category
+script.4s:6: warning: 'none' used as a category
+script.4s:7: error: -W accepts "no-syntax", but it is not a diagnostic category
+script.4s:7: warning: 'no-syntax' used as a category
+script.4s:8: error: unknown diagnostic category "no-bogus"
+script.4s:8: warning: 'no-bogus' used as a category
+script.4s:9: error: oddly enough, this works
+])
+
+AT_CLEANUP
 
 ## ----------------- ##
 ## m4_divert_stack.  ##
-- 
2.41.0





Information forwarded to automake-patches <at> gnu.org:
bug#67841; Package automake-patches. (Fri, 15 Dec 2023 23:53:01 GMT) Full text and rfc822 format available.

Message #8 received at 67841 <at> debbugs.gnu.org (full text, mbox):

From: Karl Berry <karl <at> freefriends.org>
To: zack <at> owlfolio.org
Cc: autoconf-patches <at> gnu.org, 67841 <at> debbugs.gnu.org
Subject: Re: [bug#67841] [PATCH] Clarify error messages for misuse of m4_warn
 and --help for -W.
Date: Fri, 15 Dec 2023 16:52:40 -0700
Hi Zack,

    Since this touches code shared between Autoconf and Automake, I'm not
    checking it in yet and I'm requesting comments from both sides of the
    fence.

Well, it seems good to me in principle, FWIW. I don't think this
directly affects automake? I admit I did not try to extract the parts
for automake and run the am tests ... --thanks, karl.





Information forwarded to automake-patches <at> gnu.org:
bug#67841; Package automake-patches. (Sat, 16 Dec 2023 00:09:02 GMT) Full text and rfc822 format available.

Message #11 received at 67841 <at> debbugs.gnu.org (full text, mbox):

From: Jacob Bachmeyer <jcb62281 <at> gmail.com>
To: Zack Weinberg <zack <at> owlfolio.org>
Cc: autoconf-patches <at> gnu.org, 67841 <at> debbugs.gnu.org
Subject: Re: [bug#67841] [PATCH] Clarify error messages for misuse of m4_warn
 and --help for -W.
Date: Fri, 15 Dec 2023 18:08:00 -0600
Zack Weinberg wrote:
> [...]
>
> Since this touches code shared between Autoconf and Automake, I’m not
> checking it in yet and I’m requesting comments from both sides of the
> fence.  Also, there’s a perl 2.14ism in one place (s///a) which I need
> to figure out how to make 2.6-compatible before it can land.
>
> [...]
>  
> +sub report_bad_channel ($$)
> +{
> +  my ($channel, $location) = @_;
> +  my $message;
> +  my $report_as = 'error';
> +
> +  # quotemeta is both too aggressive (e.g. it escapes '-') and
> +  # too generous (it turns control characters into \ + themselves,
> +  # not into symbolic escapes).
> +  my $q_channel = $channel;
> +  $q_channel =~ s/\\/\\\\/g;
> +  $q_channel =~ s/([^\x20-\x7e])/"\\x".sprintf("%02x", ord($1))/aeg;
> +  $q_channel =~ s/(?=[\"\$\'\@\`])/\\/g;
> +  $q_channel = '"' . $q_channel . '"';
>
> [...]
>   

If I am reading perlre correctly, you should be able to simply drop the 
/a modifier because it has no effect on the pattern you have written, 
since you are using an explicit character class and are *not* using the 
/i modifier.  (The documentation says that /a only affects the \d, \s, 
\w Perl character classes and the POSIX character classes.)  Further, 
Perl's sprintf is indeed sprintf, so you should be able to rewrite that 
substitution as:

s/([^\x20-\x7e])/sprintf('\\x%02x', ord $1)/eg


This slightly simplifies the program (eliminating one concatenation), 
which is probably of trivial consequence, since this code is on an error 
path and not an inner loop.  More importantly, including the "\\x" in 
the sprintf format string makes the intended output more clear.  The 
single quotes are both a (very slight) performance optimization and 
serve to document that no direct interpolation is intended because this 
is a format string.  Perl's handling of backslash in single quotes is 
fun:  backslash escapes itself but will also be taken literally if it 
does not form an escape that is allowed in q[].


-- Jacob




Information forwarded to automake-patches <at> gnu.org:
bug#67841; Package automake-patches. (Mon, 18 Dec 2023 18:59:01 GMT) Full text and rfc822 format available.

Message #14 received at 67841 <at> debbugs.gnu.org (full text, mbox):

From: "Zack Weinberg" <zack <at> owlfolio.org>
To: "Jacob Bachmeyer" <jcb62281 <at> gmail.com>
Cc: Autoconf Patches <autoconf-patches <at> gnu.org>, 67841 <at> debbugs.gnu.org
Subject: Re: [bug#67841] [PATCH] Clarify error messages for misuse of m4_warn
 and --help for -W.
Date: Mon, 18 Dec 2023 13:58:27 -0500
On Fri, Dec 15, 2023, at 7:08 PM, Jacob Bachmeyer wrote:
> Zack Weinberg wrote:
>> [...]
>> Also, there’s a perl 2.14ism in one place (s///a) which I need
>> to figure out how to make 2.6-compatible before it can land.
...
>> +  $q_channel =~ s/([^\x20-\x7e])/"\\x".sprintf("%02x", ord($1))/aeg;
...
> If I am reading perlre correctly, you should be able to simply drop the 
> /a modifier because it has no effect on the pattern you have written, 
> since you are using an explicit character class and are *not* using the 
> /i modifier.

Thanks, you've made me realize that /a wasn't even what I wanted in the
first place.  What I thought /a would do is force s/// to act byte by
byte -- or, in the terms of perlunitut, force the target string to be
treated as a binary string.  That might be clearer with a concrete example:

$ perl -e '$_ = "\xE2\x88\x85"; s/([^\x20-\x7e])/sprintf("\\x%02x", ord($1))/eg; print "$_\n";'
\xe2\x88\x85
$ perl -e '$_ = "\N{EMPTY SET}"; s/([^\x20-\x7e])/sprintf("\\x%02x", ord($1))/eg; print "$_\n";'
\x2205

What change do I need to make to the second one-liner to make it also
print \xe2\x88\x85?  How do I express that in a way that is backward
compatible all the way to 5.6.0?  And finally, how do I ensure that
there is absolutely nothing I can put in the initial assignment to
$_ that will cause the rest of the one-liner to crash?  For example
over in the Python universe it's very easy to get Unicode conversion
to crash:

$ python3 -c 'print("\uDC00".encode("utf-8"))'
Traceback (most recent call last):
  File "<string>", line 1, in <module>
UnicodeEncodeError: 'utf-8' codec can't encode character '\udc00' in position 0: surrogates not allowed

Given that having non-ASCII here in the first place is pretty unlikely,
I am going to go ahead and land the patch with your suggested changes,
but I'd still appreciate any further advice you have.

zw




Information forwarded to automake-patches <at> gnu.org:
bug#67841; Package automake-patches. (Mon, 18 Dec 2023 19:03:02 GMT) Full text and rfc822 format available.

Message #17 received at 67841 <at> debbugs.gnu.org (full text, mbox):

From: "Zack Weinberg" <zack <at> owlfolio.org>
To: "Karl Berry" <karl <at> freefriends.org>
Cc: Autoconf Patches <autoconf-patches <at> gnu.org>, 67841 <at> debbugs.gnu.org
Subject: Re: [bug#67841] [PATCH] Clarify error messages for misuse of m4_warn
 and --help for -W.
Date: Mon, 18 Dec 2023 14:02:18 -0500
On Fri, Dec 15, 2023, at 6:52 PM, Karl Berry wrote:
> Hi Zack,
>
>     Since this touches code shared between Autoconf and Automake, I'm not
>     checking it in yet and I'm requesting comments from both sides of the
>     fence.
>
> Well, it seems good to me in principle, FWIW. I don't think this
> directly affects automake?

I doubt it, unless there's something you can put in a Makefile.am that will
cause Automake::Channels::msg to be called with a user-controlled $channel
argument.  (On the autoconf side of the fence, m4_warn([channel], [message])
does exactly that, hence the patch.)

zw




Information forwarded to automake-patches <at> gnu.org:
bug#67841; Package automake-patches. (Mon, 18 Dec 2023 19:28:02 GMT) Full text and rfc822 format available.

Message #20 received at 67841 <at> debbugs.gnu.org (full text, mbox):

From: Zack Weinberg <zack <at> owlfolio.org>
To: autoconf-patches <at> gnu.org,
	67841 <at> debbugs.gnu.org
Subject: [PATCH v2,
 committed] Clarify error messages for misuse of m4_warn and --help
 for -W.
Date: Mon, 18 Dec 2023 14:27:02 -0500
m4_warn([category], [message]) passes its arguments directly to
Autom4te::Channels::msg.  If the category argument is not a recognized
“channel”, that function will crash and emit a *Perl* stack trace,
which makes it look like there’s something wrong with autoconf or
autom4te, rather than something wrong with the script.

Making matters worse, in autoconf 2.69, the manual said you could
use “all” and the empty string as the first argument to m4_warn.
As far as I can tell, neither of those was ever a valid message
channel, and the manual was corrected in 2.70, but we still got
a bug report from someone who tried it.

This patch makes us issue a nice helpful user error, instead of a
confusing internal error, when Autom4te::Channels::msg is called with
a bogus channel argument.  If the bogus channel is “all” or the empty
string, that error is demoted to a -Wobsolete warning.  If it is one
of the other special tokens recognized by -W, we customize the error
message, since someone might’ve thought that “none” being acceptable
to -W meant it was also acceptable to m4_warn.  The --help output for
autoconf, autoheader, autom4te, and autoreconf is also adjusted to
clarify that not all of the tokens recognized by -W count as
warning categories.

(Oddly enough, the lack of filtration at the autom4te level means
m4_warn([error], […]) actually does issue an error.  There’s no other
way to get exactly that effect — m4_errprintn(…)  and m4_fatal(…)
both do something a little different — so I I propose to leave that
alone for now and promote it to a proper, documented feature, probably
spelled m4_error(…), post-2.72.)

Channels.pm and ChannelDefs.pm are shared with Automake.  I believe
there is nothing you can write in a Makefile.am that will cause
Automake::Channels::msg to be called with an arbitrary user-supplied
channel argument, so these changes should have no visible effect on
that side of the fence.

Addresses <https://savannah.gnu.org/support/?110872>.

 * lib/Autom4te/Channels.pm (msg): If the channel argument is invalid,
   don’t crash; report the mistake and use the ‘syntax’ channel.
   (report_bad_channel): New function for reporting invalid channels.

 * lib/Autom4te/ChannelDefs.pm (usage): Clarify that the list of
   warning categories is exhaustive, and that “all”, “none”,
   “no-CATEGORY”, and “error” are not warning categories.

 * bin/autoconf.in, bin/autoheader.in, bin/autom4te.in,
   bin/autoreconf.in: Tweak --help text.

 * tests/m4sugar.at (m4@&t <at> _warn (bad categories)): New test.
---
 bin/autoconf.in             |  1 +
 bin/autoheader.in           |  1 +
 bin/autom4te.in             |  1 +
 bin/autoreconf.in           | 10 +++---
 lib/Autom4te/ChannelDefs.pm | 10 +++---
 lib/Autom4te/Channels.pm    | 47 ++++++++++++++++++++++++++-
 tests/m4sugar.at            | 63 +++++++++++++++++++++++++++++++++++++
 7 files changed, 122 insertions(+), 11 deletions(-)

diff --git a/bin/autoconf.in b/bin/autoconf.in
index 060a9a04..5f4a2e5c 100644
--- a/bin/autoconf.in
+++ b/bin/autoconf.in
@@ -64,6 +64,7 @@ Operation modes:
   -f, --force               consider all files obsolete
   -o, --output=FILE         save output in FILE (stdout is the default)
   -W, --warnings=CATEGORY   report the warnings falling in CATEGORY
+                            (comma-separated list accepted)
 
 " . Autom4te::ChannelDefs::usage . "
 
diff --git a/bin/autoheader.in b/bin/autoheader.in
index 4afa5f13..f5af0df2 100644
--- a/bin/autoheader.in
+++ b/bin/autoheader.in
@@ -74,6 +74,7 @@ or else 'configure.in'.
   -d, --debug              don\'t remove temporary files
   -f, --force              consider all files obsolete
   -W, --warnings=CATEGORY  report the warnings falling in CATEGORY
+                           (comma-separated list accepted)
 
 " . Autom4te::ChannelDefs::usage . "
 
diff --git a/bin/autom4te.in b/bin/autom4te.in
index 8957a6c9..2e4e7d52 100644
--- a/bin/autom4te.in
+++ b/bin/autom4te.in
@@ -160,6 +160,7 @@ Operation modes:
   -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
+                           (comma-separated list accepted)
   -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
diff --git a/bin/autoreconf.in b/bin/autoreconf.in
index c6077efe..285d0f49 100644
--- a/bin/autoreconf.in
+++ b/bin/autoreconf.in
@@ -84,20 +84,18 @@ Operation modes:
       --no-recursive       don't rebuild sub-packages
   -s, --symlink            with -i, install symbolic links instead of copies
   -m, --make               when applicable, re-run ./configure && make
-  -W, --warnings=CATEGORY  report the warnings falling in CATEGORY [syntax]
+  -W, --warnings=CATEGORY  report the warnings falling in CATEGORY
+                           (comma-separated list accepted)
 
 " . Autom4te::ChannelDefs::usage . "
 
-The environment variable 'WARNINGS' is honored.  Some subtools might
-support other warning types, using 'all' is encouraged.
-
 Library directories:
   -B, --prepend-include=DIR  prepend directory DIR to search path
   -I, --include=DIR          append directory DIR to search path
 
 The environment variables AUTOCONF, ACLOCAL, AUTOHEADER, AUTOM4TE,
-AUTOMAKE, AUTOPOINT, GTKDOCIZE, INTLTOOLIZE, LIBTOOLIZE, M4, and MAKE
-are honored.
+AUTOMAKE, AUTOPOINT, GTKDOCIZE, INTLTOOLIZE, LIBTOOLIZE, M4, MAKE,
+and WARNINGS are honored.
 
 Report bugs to <bug-autoconf\@gnu.org>.
 GNU Autoconf home page: <https://www.gnu.org/software/autoconf/>.
diff --git a/lib/Autom4te/ChannelDefs.pm b/lib/Autom4te/ChannelDefs.pm
index 85ea6f82..9682e8db 100644
--- a/lib/Autom4te/ChannelDefs.pm
+++ b/lib/Autom4te/ChannelDefs.pm
@@ -197,7 +197,7 @@ Return the warning category descriptions.
 
 sub usage ()
 {
-  return "Warning categories include:
+  return "Warning categories are:
   cross                  cross compilation issues
   gnu                    GNU coding standards (default in gnu and gnits modes)
   obsolete               obsolete features or constructions (default)
@@ -207,10 +207,12 @@ sub usage ()
   extra-portability      extra portability issues related to obscure tools
   syntax                 dubious syntactic constructs (default)
   unsupported            unsupported or incomplete features (default)
-  all                    all the warnings
-  no-CATEGORY            turn off warnings in CATEGORY
+
+-W also understands:
+  all                    turn on all the warnings
   none                   turn off all the warnings
-  error                  treat warnings as errors";
+  no-CATEGORY            turn off warnings in CATEGORY
+  error                  treat all enabled warnings as errors";
 }
 
 =item C<prog_error ($MESSAGE, [%OPTIONS])>
diff --git a/lib/Autom4te/Channels.pm b/lib/Autom4te/Channels.pm
index a2ed0a0b..cd77be95 100644
--- a/lib/Autom4te/Channels.pm
+++ b/lib/Autom4te/Channels.pm
@@ -628,7 +628,13 @@ sub msg ($$;$%)
       $location = '';
     }
 
-  confess "unknown channel $channel" unless exists $channels{$channel};
+  if (!exists $channels{$channel})
+    {
+      # This can happen as a result of e.g. m4_warn([nonsense], [message])
+      # so it should not crash.
+      report_bad_channel($channel, $location);
+      $channel = 'syntax';
+    }
 
   my %opts = %{$channels{$channel}};
   _merge_options (%opts, %options);
@@ -662,6 +668,45 @@ sub msg ($$;$%)
     }
 }
 
+sub report_bad_channel ($$)
+{
+  my ($channel, $location) = @_;
+  my $message;
+  my $report_as = 'error';
+
+  # quotemeta is both too aggressive (e.g. it escapes '-') and
+  # too generous (it turns control characters into \ + themselves,
+  # not into symbolic escapes).
+  my $q_channel = $channel;
+  $q_channel =~ s/(?=[\"\$\'\@\`\\])/\\/g;
+  $q_channel =~ s/([^\x20-\x7e])/sprintf('\\x%02X', ord $1)/eg;
+  $q_channel = '"' . $q_channel . '"';
+
+  if ($channel eq '' || $channel eq 'all')
+    {
+      # Prior to version 2.70, the Autoconf manual said it was valid to use
+      # "all" and the empty string as the category argument to m4_warn, so
+      # don't treat those cases as errors.
+      $report_as = 'obsolete';
+      $message = "use of $q_channel as a diagnostic category is obsolete\n";
+      $message .= "(see autom4te --help for a list of valid categories)";
+    }
+  elsif ($channel eq 'none'
+         || ($channel =~ /^no-/ && exists $channels{substr($channel, 3)}))
+    {
+      # Also recognize "none" and "no-[category]", as someone might have
+      # thought anything acceptable to -W is also acceptable to m4_warn.
+      # Note: m4_warn([error], [...]) does actually issue an error.
+      $message = "-W accepts $q_channel, but it is not a diagnostic category";
+    }
+  else
+    {
+      $message = "unknown diagnostic category " . $q_channel;
+    }
+
+  msg $report_as, $location, $message;
+}
+
 
 =item C<setup_channel ($channel, %options)>
 
diff --git a/tests/m4sugar.at b/tests/m4sugar.at
index 2f1dbe37..c7e87228 100644
--- a/tests/m4sugar.at
+++ b/tests/m4sugar.at
@@ -244,6 +244,7 @@ AT_CLEANUP
 ## --------- ##
 
 AT_SETUP([m4@&t <at> _warn])
+AT_KEYWORDS([m4@&t <at> _warn])
 
 AT_DATA_M4SUGAR([script.4s],
 [[m4_init
@@ -297,6 +298,68 @@ script.4s:8: the top level
 
 AT_CLEANUP
 
+## ----------------------------------------------- ##
+## Bad m4_warn categories (Autoconf bug #110872).  ##
+## ----------------------------------------------- ##
+
+AT_SETUP([m4@&t <at> _warn (bad categories)])
+AT_KEYWORDS([m4@&t <at> _warn])
+
+AT_DATA_M4SUGAR([script.4s],
+[[m4_init
+m4_warn([],            [empty category])dnl
+m4_warn([bogus],       [invalid category])dnl
+m4_warn([!"\	%^&*], [line noise category])dnl " unconfuse editor
+m4_warn([all],         ['all' used as a category])dnl
+m4_warn([none],        ['none' used as a category])dnl
+m4_warn([no-syntax],   ['no-syntax' used as a category])dnl
+m4_warn([no-bogus],    ['no-bogus' used as a category])dnl
+m4_warn([error],       [oddly enough, this works])dnl
+]])
+
+AT_CHECK_M4SUGAR([-o- -Wnone], 1, [],
+[script.4s:3: error: unknown diagnostic category "bogus"
+script.4s:4: error: unknown diagnostic category "!\"\\\x09%^&*"
+script.4s:6: error: -W accepts "none", but it is not a diagnostic category
+script.4s:7: error: -W accepts "no-syntax", but it is not a diagnostic category
+script.4s:8: error: unknown diagnostic category "no-bogus"
+script.4s:9: error: oddly enough, this works
+])
+
+AT_CHECK_M4SUGAR([-o- -Wnone,obsolete], 1, [],
+[script.4s:2: warning: use of "" as a diagnostic category is obsolete
+script.4s:2: (see autom4te --help for a list of valid categories)
+script.4s:3: error: unknown diagnostic category "bogus"
+script.4s:4: error: unknown diagnostic category "!\"\\\x09%^&*"
+script.4s:5: warning: use of "all" as a diagnostic category is obsolete
+script.4s:5: (see autom4te --help for a list of valid categories)
+script.4s:6: error: -W accepts "none", but it is not a diagnostic category
+script.4s:7: error: -W accepts "no-syntax", but it is not a diagnostic category
+script.4s:8: error: unknown diagnostic category "no-bogus"
+script.4s:9: error: oddly enough, this works
+])
+
+AT_CHECK_M4SUGAR([-o- -Wnone,obsolete,syntax], 1, [],
+[script.4s:2: warning: use of "" as a diagnostic category is obsolete
+script.4s:2: (see autom4te --help for a list of valid categories)
+script.4s:2: warning: empty category
+script.4s:3: error: unknown diagnostic category "bogus"
+script.4s:3: warning: invalid category
+script.4s:4: error: unknown diagnostic category "!\"\\\x09%^&*"
+script.4s:4: warning: line noise category
+script.4s:5: warning: use of "all" as a diagnostic category is obsolete
+script.4s:5: (see autom4te --help for a list of valid categories)
+script.4s:5: warning: 'all' used as a category
+script.4s:6: error: -W accepts "none", but it is not a diagnostic category
+script.4s:6: warning: 'none' used as a category
+script.4s:7: error: -W accepts "no-syntax", but it is not a diagnostic category
+script.4s:7: warning: 'no-syntax' used as a category
+script.4s:8: error: unknown diagnostic category "no-bogus"
+script.4s:8: warning: 'no-bogus' used as a category
+script.4s:9: error: oddly enough, this works
+])
+
+AT_CLEANUP
 
 ## ----------------- ##
 ## m4_divert_stack.  ##
-- 
2.41.0





Information forwarded to automake-patches <at> gnu.org:
bug#67841; Package automake-patches. (Tue, 19 Dec 2023 05:45:02 GMT) Full text and rfc822 format available.

Message #23 received at 67841 <at> debbugs.gnu.org (full text, mbox):

From: Jacob Bachmeyer <jcb62281 <at> gmail.com>
To: Zack Weinberg <zack <at> owlfolio.org>
Cc: Autoconf Patches <autoconf-patches <at> gnu.org>, 67841 <at> debbugs.gnu.org
Subject: Re: [bug#67841] [PATCH] Clarify error messages for misuse of m4_warn
 and --help for -W.
Date: Mon, 18 Dec 2023 23:44:47 -0600
Zack Weinberg wrote:
> On Fri, Dec 15, 2023, at 7:08 PM, Jacob Bachmeyer wrote:
>   
>> Zack Weinberg wrote:
>>     
>>> [...]
>>> Also, there’s a perl 2.14ism in one place (s///a) which I need
>>> to figure out how to make 2.6-compatible before it can land.
>>>       
> ...
>   
>>> +  $q_channel =~ s/([^\x20-\x7e])/"\\x".sprintf("%02x", ord($1))/aeg;
>>>       
> ...
>   
>> If I am reading perlre correctly, you should be able to simply drop the 
>> /a modifier because it has no effect on the pattern you have written, 
>> since you are using an explicit character class and are *not* using the 
>> /i modifier.
>>     
>
> Thanks, you've made me realize that /a wasn't even what I wanted in the
> first place.  What I thought /a would do is force s/// to act byte by
> byte -- or, in the terms of perlunitut, force the target string to be
> treated as a binary string.  That might be clearer with a concrete example:
>
> $ perl -e '$_ = "\xE2\x88\x85"; s/([^\x20-\x7e])/sprintf("\\x%02x", ord($1))/eg; print "$_\n";'
> \xe2\x88\x85
> $ perl -e '$_ = "\N{EMPTY SET}"; s/([^\x20-\x7e])/sprintf("\\x%02x", ord($1))/eg; print "$_\n";'
> \x2205
>
> What change do I need to make to the second one-liner to make it also
> print \xe2\x88\x85?

Add -MEncode to the one-liner and insert "$_ = encode_utf8($_);" before 
the substitution to declare that you want the string as UTF-8 bytes.  
The Encode documentation states:
"All possible characters have a UTF-8 representation so this function 
[encode_utf8] cannot fail."

In the actual patch, try "my $q_channel = encode_utf8($channel);" when 
initially copying the channel name.

>   How do I express that in a way that is backward
> compatible all the way to 5.6.0?

Now the fun part... Perl 5.6 had serious deficiencies in Unicode 
support; Encode was introduced with 5.8.  You will need to make the 
Encode import conditional and generate a stub for encode_utf8 if the 
import fails.  This should not be a problem since non-ASCII here in the 
first place is unlikely, and I think Perl 5.6 would treat non-ASCII as 
exactly the octet string you want anyway.

Something like:  (untested)

BEGIN {
 my $have_Encode = 0;
 eval { require Encode; $have_Encode = 1; };
 if ($have_Encode) {
   Encode->import('encode_utf8');
 } else {
   # for Perl 5.6, which did not really have Unicode support anyway
   eval 'sub encode_utf8 { return pop }';
 }
}

Note that the stub is defined using eval STRING rather than eval BLOCK 
because "sub" has compile-time effects in Perl and we only want it if 
Encode could not be loaded.

>   And finally, how do I ensure that there is absolutely nothing I can put in the initial assignment to $_ that will cause the rest of the one-liner to crash?  For example
> over in the Python universe it's very easy to get Unicode conversion
> to crash:
>
> $ python3 -c 'print("\uDC00".encode("utf-8"))'
> Traceback (most recent call last):
>   File "<string>", line 1, in <module>
> UnicodeEncodeError: 'utf-8' codec can't encode character '\udc00' in position 0: surrogates not allowed
>   

Not a problem in Perl:

$ perl -MEncode -e '$_ = "\x{dc00}"; $_ = encode_utf8($_); 
s/([^\x20-\x7e])/sprintf("\\x%02x", ord($1))/eg; print "$_\n";'
\xed\xb0\x80

:-)

-- Jacob





Information forwarded to automake-patches <at> gnu.org:
bug#67841; Package automake-patches. (Tue, 19 Dec 2023 22:50:02 GMT) Full text and rfc822 format available.

Message #26 received at 67841 <at> debbugs.gnu.org (full text, mbox):

From: Karl Berry <karl <at> freefriends.org>
To: jcb62281 <at> gmail.com
Cc: zack <at> owlfolio.org, 67841 <at> debbugs.gnu.org
Subject: Re: [bug#67841] [PATCH] Clarify error messages for misuse of m4_warn
 and --help for -W.
Date: Tue, 19 Dec 2023 15:49:48 -0700
    "All possible characters have a UTF-8 representation so this function 
    [encode_utf8] cannot fail."

What about non-characters, i.e., byte sequences that are invalid UTF-8?

What I found was that using \N{...} implies a Unicode string. From the
charnames(3) man page (stranged not named "perlcharnames"):

     Otherwise, any string that includes a "\N{charname}" or "\N{U+code
     point}" will automatically have Unicode rules (see "Byte and
     Character Semantics" in perlunicode).

Maybe pack("C") somehow can get to the bytes from a Unicode string?

Sorry I don't have time to experiment more. Must go look at the
first bug reports from the pretest ... --thanks, karl.




Information forwarded to automake-patches <at> gnu.org:
bug#67841; Package automake-patches. (Wed, 20 Dec 2023 03:06:01 GMT) Full text and rfc822 format available.

Message #29 received at 67841 <at> debbugs.gnu.org (full text, mbox):

From: Jacob Bachmeyer <jcb62281 <at> gmail.com>
To: Karl Berry <karl <at> freefriends.org>
Cc: zack <at> owlfolio.org, 67841 <at> debbugs.gnu.org
Subject: Re: [bug#67841] [PATCH] Clarify error messages for misuse of m4_warn
 and --help for -W.
Date: Tue, 19 Dec 2023 21:05:46 -0600
Karl Berry wrote:
>     "All possible characters have a UTF-8 representation so this function 
>     [encode_utf8] cannot fail."
>
> What about non-characters, i.e., byte sequences that are invalid UTF-8?
>   

Each individual byte gets encoded as UTF-8.  0x00..0x7F are an identity 
map, while 0x80..0xFF are translated to 2-octet sequences.  /Decoding/ 
UTF-8 can blow up or produce bogus results (I think Perl might just drop 
in the "substitute" character and emit a warning) but /encoding/ UTF-8 
always works, even on UTF-8.  Remember that Perl could handle arbitrary 
binary data long before it had Unicode support.

> What I found was that using \N{...} implies a Unicode string. From the
> charnames(3) man page (stranged not named "perlcharnames"):
>
>      Otherwise, any string that includes a "\N{charname}" or "\N{U+code
>      point}" will automatically have Unicode rules (see "Byte and
>      Character Semantics" in perlunicode).
>   

That page is named "charnames" because it documents the "charnames" 
pragmatic module.  The man page version was translated from the perldoc 
system when perl was built/installed/packaged.  The "perlunicode" page 
documents general Unicode support in Perl.

> Maybe pack("C") somehow can get to the bytes from a Unicode string?
>   

All strings in Perl are Unicode now, internally stored as UTF-8 or, as 
an optimization if no codepoints exceed 255, raw octets.  (A string of 
raw octets is considered to be a sequence of characters in the range 
[0,255].)  The "utf8 flag" on a string indicates which of those forms is 
in use on any particular string.  Using encode_utf8 simply gives you the 
internal encoding, converting an octet string to UTF-8 if needed, marked 
as an octet string.  If the string is already UTF-8, encode_utf8 simply 
clears the utf8 flag so you get access to the raw bytes.  (Brain twisted 
yet?  Mine was when I first looked at this...)

Perl's Unicode handling is fun because Perl could always handle binary 
data, and Unicode support was more-or-less retrofitted on top of that 
support for binary data.  In other words, if your program does not 
handle Unicode properly (or if you are running on Perl 5.6 and your 
program does not do the Perl 5.6 magic Unicode dances), Perl will treat 
"Unicode" data as its underlying octet sequence; thus my earlier advice 
to conditionally import Encode and shim encode_utf8 with an identity 
function if Encode is not available.


-- Jacob




Information forwarded to automake-patches <at> gnu.org:
bug#67841; Package automake-patches. (Sat, 23 Dec 2023 18:55:01 GMT) Full text and rfc822 format available.

Message #32 received at 67841 <at> debbugs.gnu.org (full text, mbox):

From: Karl Berry <karl <at> freefriends.org>
To: 67841 <at> debbugs.gnu.org
Subject: Re: [PATCH] Clarify error messages for misuse of m4_warn and --help
 for -W.
Date: Sat, 23 Dec 2023 11:54:35 -0700
This was changed in https://debbugs.gnu.org/cgi/bugreport.cgi?bug=67971
and autoconf-2.72 has been released, so closing.

Without Jacob's suggested use of encode(), I see (Jacob, thanks for the
explanations), but Zack, I'm not sure you intended this bug to track
that. Feel free to reopen if so.

Thanks,
Karl




Reply sent to Karl Berry <karl <at> freefriends.org>:
You have taken responsibility. (Sat, 23 Dec 2023 18:55:02 GMT) Full text and rfc822 format available.

Notification sent to Zack Weinberg <zack <at> owlfolio.org>:
bug acknowledged by developer. (Sat, 23 Dec 2023 18:55:02 GMT) Full text and rfc822 format available.

Information forwarded to automake-patches <at> gnu.org:
bug#67841; Package automake-patches. (Sat, 23 Dec 2023 19:26:01 GMT) Full text and rfc822 format available.

Message #40 received at 67841 <at> debbugs.gnu.org (full text, mbox):

From: "Zack Weinberg" <zack <at> owlfolio.org>
To: "Karl Berry" <karl <at> freefriends.org>, 67841 <at> debbugs.gnu.org
Subject: Re: [bug#67841] [PATCH] Clarify error messages for misuse of m4_warn
 and --help for -W.
Date: Sat, 23 Dec 2023 14:25:01 -0500
On Sat, Dec 23, 2023, at 1:54 PM, 
> Without Jacob's suggested use of encode(), I see (Jacob, thanks for the
> explanations), but Zack, I'm not sure you intended this bug to track
> that. Feel free to reopen if so.

I decided I didn't want to write that code and verify it in a hurry. I'll come back to it next year. This bug was just to make sure automake and autoconf were back in sync on all the shared files.




bug archived. Request was from Debbugs Internal Request <help-debbugs <at> gnu.org> to internal_control <at> debbugs.gnu.org. (Sun, 21 Jan 2024 12:24:05 GMT) Full text and rfc822 format available.

This bug report was last modified 1 year and 151 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.