blob: e5a50b914ac2a04b5021ebcdce671b446abca384 [file]
# Copyright 2023-2026 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 <https://www.gnu.org/licenses/>.
# This package provides a view of a parsed Texinfo document.
#
# ALTIMP perl/XSTexinfo/parser_document/DocumentXS.xs
# ALTIMP C/main/document.c
package Texinfo::Document;
use strict;
use warnings;
# To check if there is no erroneous autovivification
#no autovivification qw(fetch delete exists store strict);
use Carp qw(cluck confess);
use Texinfo::Indices;
sub set_document_global_info($$$) {
my ($document, $key, $value) = @_;
$document->{'global_info'}->{$key} = $value;
}
# $HANDLER_ONLY is only relevant in XS.
sub tree($;$) {
my ($self, $handler_only) = @_;
return $self->{'tree'};
}
# return indices information
sub indices_information($) {
my $self = shift;
return $self->{'indices'};
}
sub floats_information($) {
my $self = shift;
return $self->{'listoffloats_list'};
}
sub internal_references_information($) {
my $self = shift;
return $self->{'internal_references'};
}
sub global_commands_information($) {
my $self = shift;
return $self->{'commands_info'};
}
sub global_information($) {
my $self = shift;
return $self->{'global_info'};
}
sub labels_information($) {
my $self = shift;
return $self->{'identifiers_target'};
}
sub labels_list($) {
my $self = shift;
return $self->{'labels_list'};
}
sub nodes_list($) {
my $self = shift;
return $self->{'nodes_list'};
}
sub sections_list($) {
my $self = shift;
return $self->{'sections_list'};
}
sub sectioning_root($) {
my $self = shift;
return $self->{'sectioning_root'};
}
sub headings_list($) {
my $self = shift;
return $self->{'headings_list'};
}
# Useful for options used in structuring/tree transformations.
sub register_document_options($$) {
my ($self, $options) = @_;
$self->{'options'} = $options;
}
sub get_conf($$) {
my ($self, $var) = @_;
if (exists($self->{'options'})) {
return $self->{'options'}->{$var};
}
# This may happen if a tree/document is manipulated without having
# any configuration set. This is or was the case for pod2texi.
# This is allowed.
return undef;
}
sub destroy_document($;$) {
my ($document, $remove_references) = @_;
remove_document_references($document, $remove_references);
}
# this method does nothing, but the XS override rebuilds the Perl
# tree based on XS data.
sub build_tree($;$) {
my ($tree, $no_store) = @_;
return $tree;
}
# Errors and warnings handling
sub parser_errors($) {
my $document = shift;
my $errors_output = [@{$document->{'parser_error_messages'}}];
$document->{'parser_error_messages'} = [];
return $errors_output;
}
# The XS override pass C error messages to the document
# error_messages and remove error messages in C.
sub errors($) {
my $document = shift;
my $errors_output = [splice(@{$document->{'error_messages'}})];
return $errors_output;
}
# Indices
# calls Texinfo::Indices::setup_index_entries_sort_strings and caches the
# result.
# In general, it is not needed to call that function directly,
# as it is called by Texinfo::Indices::sort_indices_by_*. It could
# be called in advance if errors need to be collected early.
# This function does not return anything, therefore the XS override
# does not build the data to Perl.
sub setup_indices_sort_strings($$) {
my ($document, $converter) = @_;
if (!exists($document->{'index_entries_sort_strings'})) {
my $indices_sort_strings
= Texinfo::Indices::setup_index_entries_sort_strings($document,
$converter, $document->merged_indices(),
$document->indices_information(), 0);
$document->{'index_entries_sort_strings'} = $indices_sort_strings;
}
}
# index_entries_sort_strings accessor. A different function from
# setup_indices_sort_strings such that there is no necessity to build C data
# to Perl when only setup_indices_sort_strings is called. It is thus possible
# to call setup_indices_sort_strings but delay building Perl data until
# the indices_sort_strings function is called.
sub document_indices_sort_strings($) {
my $document = shift;
setup_indices_sort_strings($document, undef);
return $document->{'index_entries_sort_strings'};
}
# wrapper on print_indices_information that can be used for XS overriding.
# Used in tests only.
sub print_document_indices_information($) {
my $document = shift;
my $indices_info_text;
if (defined($document)) {
my $indices_information = $document->indices_information();
if (defined($indices_information)) {
$indices_info_text
= Texinfo::Indices::print_indices_information($indices_information);
}
}
return $indices_info_text;
}
# for tests, to be used for overriding
sub print_document_indices_sort_strings($;$) {
my ($document, $converter) = @_;
# read from C data if needed
$document->indices_information();
my $merged_index_entries = $document->merged_indices();
# use merged indices here as there are only indices with
# entries in that data
return undef unless (defined($merged_index_entries));
my $use_unicode_collation
= $document->get_conf('USE_UNICODE_COLLATION');
my $lang_sorting_locale;
if (!(defined($use_unicode_collation) and !$use_unicode_collation)) {
my $lang_sorting_locale = $document->get_conf('COLLATION_LANGUAGE');
}
my $indices_sort_strings = document_indices_sort_strings($document);
my $index_entries_sort_strings
= Texinfo::Indices::format_index_entries_sort_strings(
$indices_sort_strings);
my $sorted_index_entries
= sorted_indices_by_index($document,
$use_unicode_collation, $lang_sorting_locale);
my $idx_sort_strings_str = '';
foreach my $index_name (sort(keys(%$sorted_index_entries))) {
# index entries sort strings sorted in the order of the index entries
my $index_entries = $sorted_index_entries->{$index_name};
if (scalar(@{$index_entries})) {
$idx_sort_strings_str .= "${index_name}:\n";
foreach my $index_entry (@{$index_entries}) {
my $sort_string = $index_entries_sort_strings->{$index_entry};
$idx_sort_strings_str .= " ${sort_string}\n";
}
}
}
return $idx_sort_strings_str;
}
1;