#! /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 <https://www.gnu.org/licenses/>.
#
# 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/lib';
  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 (<CONFIGURE>) {
      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;
