blob: 4ebebf49ac6db8fb5406dde0043a63592adf6a23 [file]
#!/usr/bin/env perl
# Copyright 2012-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/>.
#
# Original author: Karl Berry.
#
# Kludge of a script to check customization variables in refman vs. texi2any
# for consistency.
use strict;
my $srcdir = $ENV{'srcdir'};
$srcdir = '.' if (!defined($srcdir));
exit (&main ());
sub main {
my $no_common = $ARGV[0] eq "--no-common";
my ($man_customization_vars, $man_cmds_customization_vars)
= &read_refman ("$srcdir/texinfo.texi");
my @man_vars = @$man_customization_vars;
my @man_cmds_vars = @$man_cmds_customization_vars;
my @t2a_vars = &read_vars ("$srcdir/../util/txicustomvars");
my @t2a_cmds_vars = &read_vars ("$srcdir/../util/txicustomvars --commands");
my (%man_vars, %t2a_vars, %man_cmds_vars, %t2a_cmds_vars); # list to hash
@man_vars{@man_vars} = ();
@t2a_vars{@t2a_vars} = ();
@man_cmds_vars{@man_cmds_vars} = ();
@t2a_cmds_vars{@t2a_cmds_vars} = ();
my @found_vars = ();
for my $name (@t2a_vars) {
if (exists $man_vars{$name}) {
push (@found_vars, $name);
delete $man_vars{$name};
delete $t2a_vars{$name};
}
}
printf ("common %3s: @{[sort @found_vars]}\n", scalar(@found_vars))
unless $no_common;
# we can't reasonably reduce the list of variable names only in the
# manual to null, since the manual necessarily includes many non-variables.
#
my @man_vars_only = sort(keys(%man_vars));
printf "man only %3s: @man_vars_only\n", scalar(@man_vars_only);
my @t2a_vars_only = sort(keys(%t2a_vars));
printf "texi2any only %3s: @t2a_vars_only\n", scalar(@t2a_vars_only);
my @found_cmds_vars = ();
for my $name (@t2a_cmds_vars) {
if (exists $man_cmds_vars{$name}) {
push (@found_cmds_vars, $name);
delete $man_cmds_vars{$name};
delete $t2a_cmds_vars{$name};
}
}
print "\n";
printf ("common cmds %3s: @{[sort @found_cmds_vars]}\n", scalar(@found_cmds_vars))
unless $no_common;
my @man_cmds_vars_only = sort(keys(%man_cmds_vars));
printf "man only cmds %3s: @man_cmds_vars_only\n", scalar(@man_cmds_vars_only);
my @t2a_cmds_vars_only = sort(keys(%t2a_cmds_vars));
printf "texi2any only cmds %3s: @t2a_cmds_vars_only\n",
scalar(@t2a_cmds_vars_only);
return scalar(@t2a_vars_only) + scalar(@t2a_cmds_vars_only);
}
# Return customization variable names from the relevant sections in
# the reference manual. We assume their names are all uppercase, to
# avoid returning numerous non-variables.
#
sub read_refman {
my ($fname) = @_;
my @commands_customization_variables = ();
my @other_customization_variables = ();
local *FILE;
my $FILE = $fname;
open (FILE, $FILE) || die "open($FILE) failed: $!";
# since we have to look at generic commands like @item, ignore until
# the first relevant section to reduce chance of false matches.
while (<FILE>) {
last if /^\@section Invoking \@command{texi2any} from a Shell$/;
}
while (<FILE>) {
if (/^\@node Customization Variables for \@\@/) {
# in this node we have a list of @-commands which have cust.vars.
while (<FILE>) {
last if /^\@example/;
}
my $atcmds = "";
while (<FILE>) {
last if /^\@end example/;
s/\@\@//g; # the variable names don't start with @
$atcmds .= $_;
}
# done with special node.
my @atcmds = split (" ", $atcmds);
push (@commands_customization_variables, @atcmds);
next;
}
# end of section with command-line customization variables
if (/^\@section Environment Variables Recognized by \@command{texi2any}/) {
# Skip to next relevant node
while (<FILE>) {
last if /^\@section Customization Variables$/;
}
}
# end of main section on customization variables
if (/^\@node Internationalization of Document Strings/) {
# Skip to next relevant node
while (<FILE>) {
last if /^\@section HTML Output Customization/;
}
}
# Stop looking for cust.var names after those nodes are done.
last if /^\@node Command Syntax/;
# Otherwise, we're looking at a line in one of the cust.var
# documentation nodes.
next unless s/^\@(itemx?|vindex) *//; # look for item[x]s and vindex
next unless /^[A-Z0-9_]+$/; # uppercase only
chomp;
push (@other_customization_variables, $_);
}
close (FILE) || warn "close($FILE) failed: $!";
return \@other_customization_variables, \@commands_customization_variables;
}
# Return customization variable names implemented in the general parser.
# The argument is the command to run which returns the list.
#
sub read_vars {
my ($prog) = @_;
my @ret = ();
local *FILE;
my $FILE = "$prog |";
open (FILE, $FILE) || die "open($FILE) failed: $!";
while (<FILE>) {
chomp;
my $var = $_;
# not for users
next if ($var =~ /^XS_/
# internal customization variables
or $var =~ /^_/
# not interesting to document/classify
or $var eq "SILENT");
push (@ret, $var);
}
close (FILE) || warn "close($FILE) failed: $!";
return @ret;
}