#! /usr/bin/perl
# load_txi_modules: Load Texinfo modules for embedding Perl.
#
# Copyright 2010-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 .
#
# Trimmed down texi2any.pl that is used to load the modules when
# Perl code is directly called from C and no Perl script is run.
use 5.006;
use strict;
use warnings;
# Through rules in Makefile.am, directory paths set through configure are
# substituted directly in strings in the code, for example
# $datadir = '/usr/share';
# We always use these strings as byte string, therefore we explicitly
# set no utf8 to be sure that strings in code will never be considered as
# character strings by Perl.
no utf8;
# check that autovivification do not happen incorrectly.
#no autovivification qw(fetch delete exists store strict);
# for file names portability
use File::Spec;
# for dirname and fileparse
use File::Basename;
my ($real_command_name, $command_directory, $command_suffix);
my $datadir;
# This big BEGIN block deals with finding modules and
# some dependencies that we ship
# * in source or
# * installed or
# * installed relative to the script
BEGIN
{
($real_command_name, $command_directory, $command_suffix)
= fileparse($0, '.pl');
my $updir = File::Spec->updir();
# These are substituted by the Makefile to create "load_txi_modules".
my $libdir = '/usr/lib64';
my $converter_libdir;
if ('/usr/share' eq '@' .'datadir@'
or defined($ENV{'TEXINFO_DEV_SOURCE'})
and $ENV{'TEXINFO_DEV_SOURCE'} ne '0')
{
# use installed path for datadir, even if uninstalled. datadir,
# however, is only used for some directories.
if ('/usr/share' eq '@' .'datadir@') {
my $fallback_prefix
= File::Spec->rootdir() . join('/', ('usr', 'local'));
$datadir = "$fallback_prefix/share";
} else {
$datadir = '/usr/share';
}
# Use uninstalled modules
# To find Texinfo::ModulePath
if (defined($ENV{'t2a_builddir'})) {
unshift @INC, join('/', ($ENV{'t2a_builddir'}, 'perl'));
} else {
unshift @INC, $command_directory;
}
require Texinfo::ModulePath;
Texinfo::ModulePath::init(undef, undef, undef, 'updirs' => 1);
} else {
# Look for modules in their installed locations.
$datadir = '/usr/share';
my $converter = 'texi2any';
my $modules_dir = join('/', ($datadir, $converter));
# look for package data in the installed location.
$converter_libdir = join('/', ($libdir, $converter));
# try to make package relocatable, will only work if
# standard relative paths are used
if (! -f join('/', ($modules_dir, 'Texinfo', 'Parser.pm'))
and -f join('/', ($command_directory, $updir, 'share',
$converter, 'Texinfo', 'Parser.pm'))) {
$datadir = join('/', ($command_directory, $updir, 'share'));
$modules_dir = join('/', ($datadir, $converter));
$converter_libdir = join('/', ($command_directory, $updir,
'lib', $converter));
}
unshift @INC, $modules_dir;
require Texinfo::ModulePath;
Texinfo::ModulePath::init($modules_dir, $converter_libdir,
$datadir, 'installed' => 1);
}
} # end BEGIN
BEGIN {
# important to load early to set XS embedded before loading any
# package with XS modules
use Texinfo::XSLoader;
Texinfo::XSLoader::set_XS_embedded();
my $enable_xs = 'no';
if ($enable_xs eq 'no') {
die ("Cannot have XS disabled and embedding Perl\n");
}
}
use Locale::Messages;
use Texinfo::Common;
use Texinfo::Config;
use Texinfo::Report;
# Not a basic module, but contains the initialization of C data
use Texinfo::Document;
# Paths and file names
#my $curdir = File::Spec->curdir();
#my $updir = File::Spec->updir();
my $sysconfdir;
my $converter;
my $fallback_prefix = File::Spec->rootdir() . join('/', ('usr', 'local'));
# The @ delimited strings are substituted by the Makefile to create
# "load_txi_modules".
if ('/etc' ne '@' . 'sysconfdir@') {
$sysconfdir = '/etc';
} else {
$sysconfdir = "$fallback_prefix/etc";
}
if ('texi2any' ne '@' . 'CONVERTER@') {
$converter = 'texi2any';
} else {
$converter = 'texi2any';
}
# initial setup of messages internalisation framework
# work-around in case libintl-perl do not do it itself
# see http://www.gnu.org/software/gettext/manual/html_node/The-LANGUAGE-variable.html#The-LANGUAGE-variable
if ((defined($ENV{"LC_ALL"}) and $ENV{"LC_ALL"} =~ /^(C|POSIX)$/)
or (defined($ENV{"LANG"}) and $ENV{"LANG"} =~ /^(C|POSIX)$/)) {
delete $ENV{"LANGUAGE"} if defined($ENV{"LANGUAGE"});
}
#my $messages_textdomain = 'texinfo';
my $messages_textdomain = 'texinfo';
$messages_textdomain = 'texinfo' if ($messages_textdomain eq '@'.'PACKAGE@');
my $strings_textdomain = 'texinfo' . '_document';
$strings_textdomain = 'texinfo_document'
if ($strings_textdomain eq '@'.'PACKAGE@' . '_document');
# we want a reliable way to switch locale, so we don't use the system
# gettext.
Locale::Messages->select_package('gettext_pp');
# Note: this uses installed or fallback directory messages when
# the program is uninstalled
Locale::Messages::bindtextdomain($messages_textdomain,
join('/', ($datadir, 'locale')));
# Set initial configuration
# We use the configured version for version. If not set we search in
# configure.ac.
# We do not fallback on a Texinfo module version to be able to
# verify that there is no mismatch.
# Version set in configure.ac and substituted in Makefile
my $configured_version = '7.3';
if ($configured_version eq '@' . 'PACKAGE_VERSION@') {
# if not configured/substituted, search for the version in configure.ac
if (open(CONFIGURE,
"< " . join('/', ($Texinfo::ModulePath::t2a_srcdir,
'configure.ac')))) {
while () {
if (/^AC_INIT\(\[[^\]]+\]\s*,\s*\[([^\]]+)\]\s*[,\)]/) {
# add +nc to distinguish from configured and, in general, installed.
# If called from build directory with TEXINFO_DEV_SOURCE=1, however
# there will not be +nc as the $configured_version is set.
$configured_version = "$1+nc";
last;
}
}
close(CONFIGURE);
}
}
if (!defined($configured_version)) {
die "Cannot determine the texi2any version; aborting.\n";
}
# Compare the version of this file with the version of the modules
# it is using. If they are different, don't go any further. This
# can happen if multiple versions are installed under a
# different names, e.g. with the --program-suffix option to 'configure'.
# The version in Common.pm is checked because that file has been present
# since Texinfo 5.0 (the first release with texi2any in Perl).
if ($configured_version ne $Texinfo::Common::VERSION
and $configured_version ne $Texinfo::Common::VERSION."+nc") {
warn "This is load_txi_modules $configured_version but modules ".
"for texi2any $Texinfo::Common::VERSION found!\n";
die "Your installation of Texinfo is broken; aborting.\n";
}
# Compare the version of the code embedding Perl passed on the
# command-line with the version of the modules it is using.
# If the version on the command-line cannot be read or
# the versions are different, don't go any further.
if ($#ARGV != 0 or !defined($ARGV[0]) or $ARGV[0] eq '') {
die "$0: Unexpected command-line argument\n";
}
my $caller_version = $ARGV[0];
if ($caller_version ne $Texinfo::Common::VERSION
and $caller_version ne $Texinfo::Common::VERSION."+nc") {
warn "The caller version is $caller_version but modules ".
"for texi2any $Texinfo::Common::VERSION found!\n";
die "Your installation of Texinfo is broken; aborting.\n";
}
my $configured_package = 'texinfo';
$configured_package = 'texinfo' if ($configured_package eq '@' . 'PACKAGE@');
my $configured_name = 'GNU Texinfo';
$configured_name = 'GNU Texinfo'
if ($configured_name eq '@' .'PACKAGE_NAME@');
my $configured_name_version = "$configured_name $configured_version";
my $configured_url = 'https://www.gnu.org/software/texinfo/';
$configured_url = 'https://www.gnu.org/software/texinfo/'
if ($configured_url eq '@' .'PACKAGE_URL@');
my $configured_information = {
'PACKAGE_VERSION' => $configured_version,
'PACKAGE' => $configured_package,
'PACKAGE_NAME' => $configured_name,
'PACKAGE_AND_VERSION' => $configured_name_version,
'PACKAGE_URL' => $configured_url,
};
# set configure information as constants
foreach my $configured_variable (keys(%$configured_information)) {
Texinfo::Common::set_build_constant($configured_variable,
$configured_information->{$configured_variable});
# set also with _CONFIG prepended, as in C code.
Texinfo::Common::set_build_constant($configured_variable.'_CONFIG',
$configured_information->{$configured_variable});
}
# next three modules are basic and used in call_perl_function.c
use Texinfo::Translations;
use Texinfo::Convert::NodeNameNormalization;
use Texinfo::Indices;
if ($Texinfo::ModulePath::texinfo_uninstalled) {
my $locales_dir
= join('/', ($Texinfo::ModulePath::t2a_builddir, 'LocaleData'));
if (-d $locales_dir) {
Texinfo::Translations::configure($locales_dir, $strings_textdomain);
} else {
warn "Locales dir for document strings not found\n";
}
} else {
my $locales_dir = join('/', ($datadir, 'locale'));
Texinfo::Translations::configure($locales_dir, $strings_textdomain);
}
# useful modules the user can always assume to have.
use Texinfo::ManipulateTree;
use Texinfo::Convert::Texinfo;
use Texinfo::Convert::Utils;
#print STDERR "$0 has run\n";
1;