# Report.pm: prepare error messages.
#
# Copyright 2010-2024 Free Software Foundation, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License,
# or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
#
# Original author: Patrice Dumas
package Texinfo::Report;
use 5.00405;
use strict;
# To check if there is no erroneous autovivification
#no autovivification qw(fetch delete exists store strict);
use Carp qw(cluck);
# for fileparse
use File::Basename;
use Locale::Messages;
my $messages_textdomain = 'texinfo';
# this module does not use Texinfo::Common, therefore does not
# obtain those functions, they are defined here
sub __($) {
my $msgid = shift;
return Locale::Messages::dgettext($messages_textdomain, $msgid);
}
sub __p($$) {
my $context = shift;
my $msgid = shift;
return Locale::Messages::dpgettext($messages_textdomain, $context, $msgid);
}
sub new()
{
my $self = {'errors_warnings' => [],
'error_nrs' => 0,};
bless $self;
return $self;
}
# return the errors and warnings
sub errors($)
{
my $self = shift;
return ($self->{'errors_warnings'}, $self->{'error_nrs'});
}
sub clear($)
{
my $self = shift;
$self->{'errors_warnings'} = [];
$self->{'error_nrs'} = 0;
}
# add an already formatted/setup message
sub add_formatted_message($$)
{
my $self = shift;
my $message = shift;
$self->{'error_nrs'}++ if ($message->{'type'} eq 'error'
and !$message->{'continuation'});
push @{$self->{'errors_warnings'}}, $message;
}
# TODO document? Or consider that this method is internal?
sub format_line_message($$$$;$)
{
my $type = shift;
my $text = shift;
my $error_location_info = shift;
my $continuation = shift;
my $warn = shift;
if (!defined($error_location_info)) {
cluck("BUG: format_line_message: error_location_info undef");
return;
}
my $message_line;
if (defined($error_location_info->{'macro'})) {
if ($type eq 'warning') {
$message_line = sprintf(__p("Texinfo source file warning in macro",
"warning: %s (possibly involving \@%s)")."\n",
$text, $error_location_info->{'macro'});
} else {
$message_line = sprintf(__p("Texinfo source file error in macro",
"%s (possibly involving \@%s)")."\n",
$text, $error_location_info->{'macro'});
}
} else {
if ($type eq 'warning') {
$message_line = sprintf(__p("Texinfo source file warning",
"warning: %s")."\n",
$text);
} else {
$message_line = $text."\n";
}
}
warn $message_line if ($warn);
my %location_info = %{$error_location_info};
delete $location_info{'file_name'} if (exists ($location_info{'file_name'})
and not defined($location_info{'file_name'}));
my $result
= { 'type' => $type, 'text' => $text, 'error_line' => $message_line,
%location_info };
$result->{'continuation'} = $continuation if ($continuation);
return $result;
}
# format a line warning
sub line_warn($$$;$$$)
{
my $self = shift;
my $text = shift;
my $error_location_info = shift;
my $continuation = shift;
my $debug = shift;
my $silent = shift;
if (!defined($error_location_info)) {
cluck("BUG: line_warn: error_location_info undef");
return;
}
my $warn = ($debug and not $silent);
my $warning = format_line_message('warning', $text, $error_location_info,
$continuation, $warn);
$self->add_formatted_message($warning);
}
sub line_error($$$;$$$)
{
my $self = shift;
my $text = shift;
my $error_location_info = shift;
my $continuation = shift;
my $debug = shift;
my $silent = shift;
if (!defined($error_location_info)) {
cluck("BUG: line_error: error_location_info undef");
return;
}
my $warn = ($debug and not $silent);
my $error = format_line_message('error', $text, $error_location_info,
$continuation, $warn);
$self->add_formatted_message($error);
}
sub format_document_message($$;$$)
{
my $type = shift;
my $text = shift;
my $program_name = shift;
my $continuation = shift;
my $message_line;
if (defined($program_name)) {
if ($type eq 'warning') {
$message_line = sprintf(__p("whole document warning", "%s: warning: %s")."\n",
$program_name, $text);
} else {
$message_line = sprintf("%s: %s\n",
$program_name, $text);
}
} else {
if ($type eq 'warning') {
$message_line = sprintf(__p("whole document warning", "warning: %s")."\n",
$text);
} else {
$message_line = "$text\n";
}
}
my $result = { 'type' => $type, 'text' => $text, 'error_line' => $message_line };
$result->{'continuation'} = $continuation if ($continuation);
return $result;
}
sub document_warn($$$;$)
{
my $self = shift;
my $text = shift;
my $program_name = shift;
my $continuation = shift;
my $warning = format_document_message('warning', $text, $program_name,
$continuation);
$self->add_formatted_message($warning);
}
sub document_error($$$;$)
{
my $self = shift;
my $text = shift;
my $program_name = shift;
my $continuation = shift;
my $error = format_document_message('error', $text, $program_name,
$continuation);
$self->add_formatted_message($error);
}
1;
__END__
=head1 NAME
Texinfo::Report - Error storing for Texinfo modules
=head1 SYNOPSIS
use Texinfo::Report;
my $registrar = Texinfo::Report::new();
if ($warning_happened) {
$registrar->line_warn($converter, sprintf(__("\@%s is wrongly used"),
$current->{'cmdname'}), $current->{'source_info'});
}
my ($errors, $errors_count) = $registrar->errors();
foreach my $error_message (@$errors) {
warn $error_message->{'error_line'};
}
$registrar->clear();
=head1 NOTES
The Texinfo Perl module main purpose is to be used in C to convert
Texinfo to other formats. There is no promise of API stability.
=head1 DESCRIPTION
The C module helps with error handling. Errors
and warnings can be setup, stored and retrieved later on.
This module is used by the Texinfo modules L and
L.
=head1 METHODS
No method is exported in the default case.
The C method initializes a C object.
The errors collected are available through the C method, the other
methods allow registering errors and warnings.
=over
=item my $registrar = Texinfo::Report::new()
X>
Return an initialized C object.
=item ($error_warnings_list, $error_count) = errors($registrar)
X>
This function returns as I<$error_count> the count of errors since
calling C. The I<$error_warnings_list> is an array of hash references
one for each error, warning or error line continuation. Each of these has
the following keys:
=over
=item continuation
If set, the line is a continuation line of a message.
=item error_line
The text of the error formatted with the macro name, as needed.
=item file_name
The file name where the error or warning occurs.
=item line_nr
The line number of the error or warning.
=item macro
The user macro name that is expanded at the location of
the error or warning.
=item text
The text of the error.
=item type
May be C, or C.
=back
=item $registrar->clear ()
X>
Clear the previously registered messages.
=item $registrar->add_formatted_message ($msg)
X>
Register the I<$msg> hash reference corresponding to an error, warning or error line
continuation. The I<$msg> hash reference should correspond to the structure returned
by C.
=item $registrar->line_warn($text, $error_location_info, $continuation, $debug, $silent)
=item $registrar->line_error($text, $error_location_info, $continuation, $debug, $silent)
X>
X>
Register a warning or an error. The I<$text> is the text of the
error or warning. The mandatory I<$error_location_info> holds the information
on the error or warning location. The I<$error_location_info> reference on
hash may be obtained from Texinfo elements I keys. It may also
be setup to point to a file name, using the C key and to a line
number, using the C key. The C key value should be a
binary string.
The I<$continuation> optional arguments, if true, conveys that
the line is a continuation line of a message.
The I<$debug> optional integer arguments sets the debug level.
The I<$silent> optional arguments, if true, suppresses the output of
a message that is output immediatly if debugging is set.
The I key of Texinfo tree elements is described
in more details in L.
=item $registrar->document_warn($text, $program_name, $continuation)
=item $registrar->document_error($text, $program_name, $continuation)
X>
X>
Register a document-wide error or warning. I<$text> is the error or
warning message. The I<$program_name> is prepended to the
message, if defined. The I<$continuation> optional arguments, if true, conveys
that the line is a continuation line of a message.
=back
=head1 AUTHOR
Patrice Dumas, Epertusus@free.frE
=head1 COPYRIGHT AND LICENSE
Copyright 2010- Free Software Foundation, Inc. See the source file for
all copyright years.
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or (at
your option) any later version.
=cut