make fetch
[autoconf.git] / lib / Autom4te / Channels.pm
blob42a728af4abfde99d669172d51058cb6af28ff7f
1 # Copyright (C) 2002-2017 Free Software Foundation, Inc.
3 # This program is free software; you can redistribute it and/or modify
4 # it under the terms of the GNU General Public License as published by
5 # the Free Software Foundation; either version 2, or (at your option)
6 # any later version.
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License
14 # along with this program. If not, see <https://www.gnu.org/licenses/>.
16 ###############################################################
17 # The main copy of this file is in Automake's git repository. #
18 # Updates should be sent to automake-patches@gnu.org. #
19 ###############################################################
21 package Autom4te::Channels;
23 =head1 NAME
25 Autom4te::Channels - support functions for error and warning management
27 =head1 SYNOPSIS
29 use Autom4te::Channels;
31 # Register a channel to output warnings about unused variables.
32 register_channel 'unused', type => 'warning';
34 # Register a channel for system errors.
35 register_channel 'system', type => 'error', exit_code => 4;
37 # Output a message on channel 'unused'.
38 msg 'unused', "$file:$line", "unused variable '$var'";
40 # Make the 'unused' channel silent.
41 setup_channel 'unused', silent => 1;
43 # Turn on all channels of type 'warning'.
44 setup_channel_type 'warning', silent => 0;
46 # Redirect all channels to push messages on a Thread::Queue using
47 # the specified serialization key.
48 setup_channel_queue $queue, $key;
50 # Output a message pending in a Thread::Queue.
51 pop_channel_queue $queue;
53 # Treat all warnings as errors.
54 $warnings_are_errors = 1;
56 # Exit with the greatest exit code encountered so far.
57 exit $exit_code;
59 =head1 DESCRIPTION
61 This perl module provides support functions for handling diagnostic
62 channels in programs. Channels can be registered to convey fatal,
63 error, warning, or debug messages. Each channel has various options
64 (e.g. is the channel silent, should duplicate messages be removed,
65 etc.) that can also be overridden on a per-message basis.
67 =cut
69 use 5.006;
70 use strict;
71 use Exporter;
72 use Carp;
73 use File::Basename;
75 use vars qw (@ISA @EXPORT %channels $me);
77 @ISA = qw (Exporter);
78 @EXPORT = qw ($exit_code $warnings_are_errors
79 &reset_local_duplicates &reset_global_duplicates
80 &register_channel &msg &exists_channel &channel_type
81 &setup_channel &setup_channel_type
82 &dup_channel_setup &drop_channel_setup
83 &buffer_messages &flush_messages
84 &setup_channel_queue &pop_channel_queue
85 US_GLOBAL US_LOCAL
86 UP_NONE UP_TEXT UP_LOC_TEXT);
88 $me = basename $0;
90 =head2 Global Variables
92 =over 4
94 =item C<$exit_code>
96 The greatest exit code seen so far. C<$exit_code> is updated from
97 the C<exit_code> options of C<fatal> and C<error> channels.
99 =cut
101 use vars qw ($exit_code);
102 $exit_code = 0;
104 =item C<$warnings_are_errors>
106 Set this variable to 1 if warning messages should be treated as
107 errors (i.e. if they should update C<$exit_code>).
109 =cut
111 use vars qw ($warnings_are_errors);
112 $warnings_are_errors = 0;
114 =back
116 =head2 Constants
118 =over 4
120 =item C<UP_NONE>, C<UP_TEXT>, C<UP_LOC_TEXT>
122 Possible values for the C<uniq_part> options. This selects the part
123 of the message that should be considered when filtering out duplicates.
124 If C<UP_LOC_TEXT> is used, the location and the explanation message
125 are used for filtering. If C<UP_TEXT> is used, only the explanation
126 message is used (so the same message will be filtered out if it appears
127 at different locations). C<UP_NONE> means that duplicate messages
128 should be output.
130 =cut
132 use constant UP_NONE => 0;
133 use constant UP_TEXT => 1;
134 use constant UP_LOC_TEXT => 2;
136 =item C<US_LOCAL>, C<US_GLOBAL>
138 Possible values for the C<uniq_scope> options.
139 Use C<US_GLOBAL> for error messages that should be printed only
140 once during the execution of the program, C<US_LOCAL> for message that
141 should be printed only once per file. (Actually, C<Channels> does not
142 do this now when files are changed, it relies on you calling
143 C<reset_local_duplicates> when this happens.)
145 =cut
147 # possible values for uniq_scope
148 use constant US_LOCAL => 0;
149 use constant US_GLOBAL => 1;
151 =back
153 =head2 Options
155 Channels accept the options described below. These options can be
156 passed as a hash to the C<register_channel>, C<setup_channel>, and C<msg>
157 functions. The possible keys, with their default value are:
159 =over
161 =item C<type =E<gt> 'warning'>
163 The type of the channel. One of C<'debug'>, C<'warning'>, C<'error'>, or
164 C<'fatal'>. Fatal messages abort the program when they are output.
165 Error messages update the exit status. Debug and warning messages are
166 harmless, except that warnings are treated as errors if
167 C<$warnings_are_errors> is set.
169 =item C<exit_code =E<gt> 1>
171 The value to update C<$exit_code> with when a fatal or error message
172 is emitted. C<$exit_code> is also updated for warnings output
173 when C<$warnings_are_errors> is set.
175 =item C<file =E<gt> \*STDERR>
177 The file where the error should be output.
179 =item C<silent =E<gt> 0>
181 Whether the channel should be silent. Use this do disable a
182 category of warning, for instance.
184 =item C<ordered =E<gt> 1>
186 Whether, with multi-threaded execution, the message should be queued
187 for ordered output.
189 =item C<uniq_part =E<gt> UP_LOC_TEXT>
191 The part of the message subject to duplicate filtering. See the
192 documentation for the C<UP_NONE>, C<UP_TEXT>, and C<UP_LOC_TEXT>
193 constants above.
195 C<uniq_part> can also be set to an arbitrary string that will be used
196 instead of the message when considering duplicates.
198 =item C<uniq_scope =E<gt> US_LOCAL>
200 The scope of duplicate filtering. See the documentation for the
201 C<US_LOCAL>, and C<US_GLOBAL> constants above.
203 =item C<header =E<gt> ''>
205 A string to prepend to each message emitted through this channel.
206 With partial messages, only the first part will have C<header>
207 prepended.
209 =item C<footer =E<gt> ''>
211 A string to append to each message emitted through this channel.
212 With partial messages, only the final part will have C<footer>
213 appended.
215 =item C<backtrace =E<gt> 0>
217 Die with a stack backtrace after displaying the message.
219 =item C<partial =E<gt> 0>
221 When set, indicates a partial message that should
222 be output along with the next message with C<partial> unset.
223 Several partial messages can be stacked this way.
225 Duplicate filtering will apply to the I<global> message resulting from
226 all I<partial> messages, using the options from the last (non-partial)
227 message. Linking associated messages is the main reason to use this
228 option.
230 For instance the following messages
232 msg 'channel', 'foo:2', 'redefinition of A ...';
233 msg 'channel', 'foo:1', '... A previously defined here';
234 msg 'channel', 'foo:3', 'redefinition of A ...';
235 msg 'channel', 'foo:1', '... A previously defined here';
237 will result in
239 foo:2: redefinition of A ...
240 foo:1: ... A previously defined here
241 foo:3: redefinition of A ...
243 where the duplicate "I<... A previously defined here>" has been
244 filtered out.
246 Linking these messages using C<partial> as follows will prevent the
247 fourth message to disappear.
249 msg 'channel', 'foo:2', 'redefinition of A ...', partial => 1;
250 msg 'channel', 'foo:1', '... A previously defined here';
251 msg 'channel', 'foo:3', 'redefinition of A ...', partial => 1;
252 msg 'channel', 'foo:1', '... A previously defined here';
254 Note that because the stack of C<partial> messages is printed with the
255 first non-C<partial> message, most options of C<partial> messages will
256 be ignored.
258 =back
260 =cut
262 use vars qw (%_default_options %_global_duplicate_messages
263 %_local_duplicate_messages);
265 # Default options for a channel.
266 %_default_options =
268 type => 'warning',
269 exit_code => 1,
270 file => \*STDERR,
271 silent => 0,
272 ordered => 1,
273 queue => 0,
274 queue_key => undef,
275 uniq_scope => US_LOCAL,
276 uniq_part => UP_LOC_TEXT,
277 header => '',
278 footer => '',
279 backtrace => 0,
280 partial => 0,
283 # Filled with output messages as keys, to detect duplicates.
284 # The value associated with each key is the number of occurrences
285 # filtered out.
286 %_local_duplicate_messages = ();
287 %_global_duplicate_messages = ();
289 sub _reset_duplicates (\%)
291 my ($ref) = @_;
292 my $dup = 0;
293 foreach my $k (keys %$ref)
295 $dup += $ref->{$k};
297 %$ref = ();
298 return $dup;
302 =head2 Functions
304 =over 4
306 =item C<reset_local_duplicates ()>
308 Reset local duplicate messages (see C<US_LOCAL>), and
309 return the number of messages that have been filtered out.
311 =cut
313 sub reset_local_duplicates ()
315 return _reset_duplicates %_local_duplicate_messages;
318 =item C<reset_global_duplicates ()>
320 Reset local duplicate messages (see C<US_GLOBAL>), and
321 return the number of messages that have been filtered out.
323 =cut
325 sub reset_global_duplicates ()
327 return _reset_duplicates %_global_duplicate_messages;
330 sub _merge_options (\%%)
332 my ($hash, %options) = @_;
333 local $_;
335 foreach (keys %options)
337 if (exists $hash->{$_})
339 $hash->{$_} = $options{$_}
341 else
343 confess "unknown option '$_'";
346 if ($hash->{'ordered'})
348 confess "fatal messages cannot be ordered"
349 if $hash->{'type'} eq 'fatal';
350 confess "backtrace cannot be output on ordered messages"
351 if $hash->{'backtrace'};
355 =item C<register_channel ($name, [%options])>
357 Declare channel C<$name>, and override the default options
358 with those listed in C<%options>.
360 =cut
362 sub register_channel ($;%)
364 my ($name, %options) = @_;
365 my %channel_opts = %_default_options;
366 _merge_options %channel_opts, %options;
367 $channels{$name} = \%channel_opts;
370 =item C<exists_channel ($name)>
372 Returns true iff channel C<$name> has been registered.
374 =cut
376 sub exists_channel ($)
378 my ($name) = @_;
379 return exists $channels{$name};
382 =item C<channel_type ($name)>
384 Returns the type of channel C<$name> if it has been registered.
385 Returns the empty string otherwise.
387 =cut
389 sub channel_type ($)
391 my ($name) = @_;
392 return $channels{$name}{'type'} if exists_channel $name;
393 return '';
396 # _format_sub_message ($LEADER, $MESSAGE)
397 # ---------------------------------------
398 # Split $MESSAGE at new lines and add $LEADER to each line.
399 sub _format_sub_message ($$)
401 my ($leader, $message) = @_;
402 return $leader . join ("\n" . $leader, split ("\n", $message)) . "\n";
405 # Store partial messages here. (See the 'partial' option.)
406 use vars qw ($partial);
407 $partial = '';
409 # _format_message ($LOCATION, $MESSAGE, %OPTIONS)
410 # -----------------------------------------------
411 # Format the message. Return a string ready to print.
412 sub _format_message ($$%)
414 my ($location, $message, %opts) = @_;
415 my $msg = ($partial eq '' ? $opts{'header'} : '') . $message
416 . ($opts{'partial'} ? '' : $opts{'footer'});
417 if (ref $location)
419 # If $LOCATION is a reference, assume it's an instance of the
420 # Autom4te::Location class and display contexts.
421 my $loc = $location->get || $me;
422 $msg = _format_sub_message ("$loc: ", $msg);
423 for my $pair ($location->get_contexts)
425 $msg .= _format_sub_message ($pair->[0] . ": ", $pair->[1]);
428 else
430 $location ||= $me;
431 $msg = _format_sub_message ("$location: ", $msg);
433 return $msg;
436 # _enqueue ($QUEUE, $KEY, $UNIQ_SCOPE, $TO_FILTER, $MSG, $FILE)
437 # -------------------------------------------------------------
438 # Push message on a queue, to be processed by another thread.
439 sub _enqueue ($$$$$$)
441 my ($queue, $key, $uniq_scope, $to_filter, $msg, $file) = @_;
442 $queue->enqueue ($key, $msg, $to_filter, $uniq_scope);
443 confess "message queuing works only for STDERR"
444 if $file ne \*STDERR;
447 # _dequeue ($QUEUE)
448 # -----------------
449 # Pop a message from a queue, and print, similarly to how
450 # _print_message would do it. Return 0 if the queue is
451 # empty. Note that the key has already been dequeued.
452 sub _dequeue ($)
454 my ($queue) = @_;
455 my $msg = $queue->dequeue || return 0;
456 my $to_filter = $queue->dequeue;
457 my $uniq_scope = $queue->dequeue;
458 my $file = \*STDERR;
460 if ($to_filter ne '')
462 # Do we want local or global uniqueness?
463 my $dups;
464 if ($uniq_scope == US_LOCAL)
466 $dups = \%_local_duplicate_messages;
468 elsif ($uniq_scope == US_GLOBAL)
470 $dups = \%_global_duplicate_messages;
472 else
474 confess "unknown value for uniq_scope: " . $uniq_scope;
477 # Update the hash of messages.
478 if (exists $dups->{$to_filter})
480 ++$dups->{$to_filter};
481 return 1;
483 else
485 $dups->{$to_filter} = 0;
488 print $file $msg;
489 return 1;
493 # _print_message ($LOCATION, $MESSAGE, %OPTIONS)
494 # ----------------------------------------------
495 # Format the message, check duplicates, and print it.
496 sub _print_message ($$%)
498 my ($location, $message, %opts) = @_;
500 return 0 if ($opts{'silent'});
502 my $msg = _format_message ($location, $message, %opts);
503 if ($opts{'partial'})
505 # Incomplete message. Store, don't print.
506 $partial .= $msg;
507 return;
509 else
511 # Prefix with any partial message send so far.
512 $msg = $partial . $msg;
513 $partial = '';
516 msg ('note', '', 'warnings are treated as errors', uniq_scope => US_GLOBAL)
517 if ($opts{'type'} eq 'warning' && $warnings_are_errors);
519 # Check for duplicate message if requested.
520 my $to_filter;
521 if ($opts{'uniq_part'} ne UP_NONE)
523 # Which part of the error should we match?
524 if ($opts{'uniq_part'} eq UP_TEXT)
526 $to_filter = $message;
528 elsif ($opts{'uniq_part'} eq UP_LOC_TEXT)
530 $to_filter = $msg;
532 else
534 $to_filter = $opts{'uniq_part'};
537 # Do we want local or global uniqueness?
538 my $dups;
539 if ($opts{'uniq_scope'} == US_LOCAL)
541 $dups = \%_local_duplicate_messages;
543 elsif ($opts{'uniq_scope'} == US_GLOBAL)
545 $dups = \%_global_duplicate_messages;
547 else
549 confess "unknown value for uniq_scope: " . $opts{'uniq_scope'};
552 # Update the hash of messages.
553 if (exists $dups->{$to_filter})
555 ++$dups->{$to_filter};
556 return 0;
558 else
560 $dups->{$to_filter} = 0;
563 my $file = $opts{'file'};
564 if ($opts{'ordered'} && $opts{'queue'})
566 _enqueue ($opts{'queue'}, $opts{'queue_key'}, $opts{'uniq_scope'},
567 $to_filter, $msg, $file);
569 else
571 print $file $msg;
573 return 1;
576 =item C<msg ($channel, $location, $message, [%options])>
578 Emit a message on C<$channel>, overriding some options of the channel with
579 those specified in C<%options>. Obviously C<$channel> must have been
580 registered with C<register_channel>.
582 C<$message> is the text of the message, and C<$location> is a location
583 associated to the message.
585 For instance to complain about some unused variable C<mumble>
586 declared at line 10 in F<foo.c>, one could do:
588 msg 'unused', 'foo.c:10', "unused variable 'mumble'";
590 If channel C<unused> is not silent (and if this message is not a duplicate),
591 the following would be output:
593 foo.c:10: unused variable 'mumble'
595 C<$location> can also be an instance of C<Autom4te::Location>. In this
596 case, the stack of contexts will be displayed in addition.
598 If C<$message> contains newline characters, C<$location> is prepended
599 to each line. For instance,
601 msg 'error', 'somewhere', "1st line\n2nd line";
603 becomes
605 somewhere: 1st line
606 somewhere: 2nd line
608 If C<$location> is an empty string, it is replaced by the name of the
609 program. Actually, if you don't use C<%options>, you can even
610 elide the empty C<$location>. Thus
612 msg 'fatal', '', 'fatal error';
613 msg 'fatal', 'fatal error';
615 both print
617 progname: fatal error
619 =cut
622 use vars qw (@backlog %buffering);
624 # See buffer_messages() and flush_messages() below.
625 %buffering = (); # The map of channel types to buffer.
626 @backlog = (); # The buffer of messages.
628 sub msg ($$;$%)
630 my ($channel, $location, $message, %options) = @_;
632 if (! defined $message)
634 $message = $location;
635 $location = '';
638 confess "unknown channel $channel" unless exists $channels{$channel};
640 my %opts = %{$channels{$channel}};
641 _merge_options (%opts, %options);
643 if (exists $buffering{$opts{'type'}})
645 push @backlog, [$channel, $location->clone, $message, %options];
646 return;
649 # Print the message if needed.
650 if (_print_message ($location, $message, %opts))
652 # Adjust exit status.
653 if ($opts{'type'} eq 'error'
654 || $opts{'type'} eq 'fatal'
655 || ($opts{'type'} eq 'warning' && $warnings_are_errors))
657 my $es = $opts{'exit_code'};
658 $exit_code = $es if $es > $exit_code;
661 # Die on fatal messages.
662 confess if $opts{'backtrace'};
663 if ($opts{'type'} eq 'fatal')
665 # flush messages explicitly here, needed in worker threads.
666 STDERR->flush;
667 exit $exit_code;
673 =item C<setup_channel ($channel, %options)>
675 Override the options of C<$channel> with those specified by C<%options>.
677 =cut
679 sub setup_channel ($%)
681 my ($name, %opts) = @_;
682 confess "unknown channel $name" unless exists $channels{$name};
683 _merge_options %{$channels{$name}}, %opts;
686 =item C<setup_channel_type ($type, %options)>
688 Override the options of any channel of type C<$type>
689 with those specified by C<%options>.
691 =cut
693 sub setup_channel_type ($%)
695 my ($type, %opts) = @_;
696 foreach my $channel (keys %channels)
698 setup_channel $channel, %opts
699 if $channels{$channel}{'type'} eq $type;
703 =item C<dup_channel_setup ()>, C<drop_channel_setup ()>
705 Sometimes it is necessary to make temporary modifications to channels.
706 For instance one may want to disable a warning while processing a
707 particular file, and then restore the initial setup. These two
708 functions make it easy: C<dup_channel_setup ()> saves a copy of the
709 current configuration for later restoration by
710 C<drop_channel_setup ()>.
712 You can think of this as a stack of configurations whose first entry
713 is the active one. C<dup_channel_setup ()> duplicates the first
714 entry, while C<drop_channel_setup ()> just deletes it.
716 =cut
718 use vars qw (@_saved_channels @_saved_werrors);
719 @_saved_channels = ();
720 @_saved_werrors = ();
722 sub dup_channel_setup ()
724 my %channels_copy;
725 foreach my $k1 (keys %channels)
727 $channels_copy{$k1} = {%{$channels{$k1}}};
729 push @_saved_channels, \%channels_copy;
730 push @_saved_werrors, $warnings_are_errors;
733 sub drop_channel_setup ()
735 my $saved = pop @_saved_channels;
736 %channels = %$saved;
737 $warnings_are_errors = pop @_saved_werrors;
740 =item C<buffer_messages (@types)>, C<flush_messages ()>
742 By default, when C<msg> is called, messages are processed immediately.
744 Sometimes it is necessary to delay the output of messages.
745 For instance you might want to make diagnostics before
746 channels have been completely configured.
748 After C<buffer_messages(@types)> has been called, messages sent with
749 C<msg> to a channel whose type is listed in C<@types> will be stored in a
750 list for later processing.
752 This backlog of messages is processed when C<flush_messages> is
753 called, with the current channel options (not the options in effect,
754 at the time of C<msg>). So for instance, if some channel was silenced
755 in the meantime, messages to this channel will not be printed.
757 C<flush_messages> cancels the effect of C<buffer_messages>. Following
758 calls to C<msg> are processed immediately as usual.
760 =cut
762 sub buffer_messages (@)
764 foreach my $type (@_)
766 $buffering{$type} = 1;
770 sub flush_messages ()
772 %buffering = ();
773 foreach my $args (@backlog)
775 &msg (@$args);
777 @backlog = ();
780 =item C<setup_channel_queue ($queue, $key)>
782 Set the queue to fill for each channel that is ordered,
783 and the key to use for serialization.
785 =cut
786 sub setup_channel_queue ($$)
788 my ($queue, $key) = @_;
789 foreach my $channel (keys %channels)
791 setup_channel $channel, queue => $queue, queue_key => $key
792 if $channels{$channel}{'ordered'};
796 =item C<pop_channel_queue ($queue)>
798 pop a message off the $queue; the key has already been popped.
800 =cut
801 sub pop_channel_queue ($)
803 my ($queue) = @_;
804 return _dequeue ($queue);
807 =back
809 =head1 SEE ALSO
811 L<Autom4te::Location>
813 =head1 HISTORY
815 Written by Alexandre Duret-Lutz E<lt>F<adl@gnu.org>E<gt>.
817 =cut
821 ### Setup "GNU" style for perl-mode and cperl-mode.
822 ## Local Variables:
823 ## perl-indent-level: 2
824 ## perl-continued-statement-offset: 2
825 ## perl-continued-brace-offset: 0
826 ## perl-brace-offset: 0
827 ## perl-brace-imaginary-offset: 0
828 ## perl-label-offset: -2
829 ## cperl-indent-level: 2
830 ## cperl-brace-offset: 0
831 ## cperl-continued-brace-offset: 0
832 ## cperl-label-offset: -2
833 ## cperl-extra-newline-before-brace: t
834 ## cperl-merge-trailing-else: nil
835 ## cperl-continued-statement-offset: 2
836 ## End: