diff options
author | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
commit | e0c6872cf40896c7be36b11dcc744620f10adf1d (patch) | |
tree | 60335e10d2f4354b0674ec22d7b53f0f8abee672 /macros/latex/contrib/glossaries/makeglossaries |
Initial commit
Diffstat (limited to 'macros/latex/contrib/glossaries/makeglossaries')
-rwxr-xr-x | macros/latex/contrib/glossaries/makeglossaries | 1676 |
1 files changed, 1676 insertions, 0 deletions
diff --git a/macros/latex/contrib/glossaries/makeglossaries b/macros/latex/contrib/glossaries/makeglossaries new file mode 100755 index 0000000000..643e36b3c1 --- /dev/null +++ b/macros/latex/contrib/glossaries/makeglossaries @@ -0,0 +1,1676 @@ +#!/usr/bin/env perl + +# File : makeglossaries +# Author : Nicola Talbot +# Version : 4.41 +# Description: simple Perl script that calls makeindex or xindy. +# Intended for use with "glossaries.sty" (saves having to remember +# all the various switches) + +# This file is distributed as part of the glossaries LaTeX package. +# Copyright 2007 Nicola L.C. Talbot +# This work may be distributed and/or modified under the +# conditions of the LaTeX Project Public License, either version 1.3 +# of this license or any later version. +# The latest version of this license is in +# http://www.latex-project.org/lppl.txt +# and version 1.3 or later is part of all distributions of LaTeX +# version 2005/12/01 or later. +# +# This work has the LPPL maintenance status `maintained'. +# +# The Current Maintainer of this work is Nicola Talbot. + +# This work consists of the files glossaries.dtx and glossaries.ins +# and the derived files glossaries.sty, glossaries-prefix.sty, +# glossary-hypernav.sty, glossary-inline.sty, glossary-list.sty, +# glossary-long.sty, glossary-longbooktabs.sty, glossary-longragged.sty, +# glossary-mcols.sty, glossary-super.sty, glossary-superragged.sty, +# glossary-tree.sty, glossaries-compatible-207.sty, +# glossaries-compatible-307.sty, glossaries-accsupp.sty, +# glossaries-babel.sty, glossaries-polyglossia.sty, glossaries.perl. +# Also makeglossaries and makeglossaries-lite.lua. + +my $version="4.41 (2018-07-23)"; + +# History: +# v4.41: +# * No change. +# v4.40: +# * No change. +# v4.39: +# * No change. +# v4.38: +# * No change. +# v4.37: +# * No change. +# v4.36: +# * No change. +# v4.35: +# * No change. +# v4.34: +# * Added check for \glsxtr@resource +# v4.33: +# * Version number synchronized with glossaries.sty +# v2.21: +# * Fixed spelling of \GlsAddXdyLocation +# * Adjusted range encap clash +# v2.20 (2016/12/16) +# * Added check for \glsxtr@makeglossaries +# v2.19 (2016/05/27) +# * Improved check in &parse_for_xindy_nosort +# v2.18 (2016/01/24) +# * Added &parse_for_xindy_nosort to help diagnose xindy's empty +# index key warning/error. +# * Added check for makeindex's multiple encap warning. +# v2.17 (2015/11/30) +# * Escaped { in regular expressions. +# http://www.dickimaw-books.com/cgi-bin/bugtracker.cgi?action=view&key=101 +# v2.16 (2015/06/28) +# * Added check for "german" and codepage that doesn't contain +# "din5007", "duden" or "braille". If missing, "din5007-" is +# prefixed to the codepage. +# v2.15 (2014/07/30) +# * Removed hard-coded three character extension assumption +# www.dickimaw-books.com/cgi-bin/bugtracker.cgi?action=view&key=55 +# * Added message to indicate the number of ignored glossaries +# when the extension is specified. +# v2.14 (2014/03/06) +# * Added -Q and -k options +# v2.13 (2014/01/21) +# * Added check for leading and trailing quotes in filename +# v2.12 (2014/01/20) +# * Added check for '*' in istfilename +# * Fixed bug report +# http://www.dickimaw-books.com/cgi-bin/bugtracker.cgi?action=view&key=33 +# * Added error text hashes +# v2.11 (2014/01/17): +# * Added check for backslashes in -x, -m and -d paths +# * Added double-quotes around $appname in &run_app +# v2.10 (2013/12/01): +# * initialise $language to suppress warnings +# v2.09 (2013-11-12): +# * added check for -q switch when issuing warnings. +# v2.08 (2013-10-14): +# * added -x and -m options +# v2.07 (2013-06-17): +# * added check for success on chdir if -d used +# * added dialect map +# v2.06 (2013-04-21): +# * added "din5007" as default if language is set to "german" +# v2.05 (2012-11-12): +# * added -d option +# v2.04 (2012-04-19): +# * fixed bug in &scan_aux +# v2.03 (2011-04-12): +# * added warning about possibly needing 'nomain' package option +# v2.02 (2011-04-2): +# * Prints version number at start of run unless -q +# * Added more diagnostics. +# v2.01 (2010-09-29): +# * Added 'use warnings' +# v2.0 (2010-06-30) : +# * Made file handle local in &scan_aux +# v1.9 (2010-06-14) : +# * Check for \@input +# v1.8 (2009-11-03) : +# * Create an empty output file if the input file is empty +# without calling xindy/makeindex +# v1.7 (2009-09-23) : +# * Issue warning rather than error when empty/non existant file +# checks fail +# v1.6 (2009-05-24) : +# * main glossary no longer automatically added +# (only added if information in aux file) +# * if file extension is specified, check added to ensure it +# corresponds to a known glossary extension. +# * added file existance test and file empty test +# v1.5 (2008-12-26) : +# * added support for xindy +# * picks up ordering information from aux file +# v1.4 (2008-05-10) : +# * added support for filenames with spaces. +# v1.3 (2008-03-08) : +# * changed first line from /usr/bin/perl -w to /usr/bin/env perl +# (Thanks to Karl Berry for suggesting this.) +# v1.2 (2008-03-02) : +# * added support for --help and --version +# * improved error handling +# v1.1 (2008-02-13) : +# * added -w and strict +# * added check to ensure .tex file not passed to makeglossaries +# +# v1.0 (2007-05-10) : Initial release. + +use Getopt::Std; +use strict; +# v2.01 added the following line +use warnings; +# v2.05 added $opt_d +# v2.08 added $opt_x and $opt_m +use vars qw($opt_q $opt_t $opt_o $opt_s $opt_p $opt_g $opt_c $opt_r + $opt_l $opt_i $opt_L $opt_n $opt_C $opt_d $opt_x $opt_m $opt_Q + $opt_k); + + +$Getopt::Std::STANDARD_HELP_VERSION = 1; + +# v1.5 added -L <lang> for xindy (but language can be specified in +# .tex file) +# v1.5 added -n (print the command that would be issued but +# don't actually run the command) +getopts('s:o:t:p:L:C:ilqQkrcgnd:x:m:'); + +unless ($#ARGV == 0) +{ + die "makeglossaries: Need exactly one file argument.\n", + "Use `makeglossaries --help' for help.\n"; +} + +# v2.02: added: +print "makeglossaries version $version\n" unless ($opt_q); + +# v2.07: added babel dialect -> xindy language map: +my %languagemap = +( + 'american' => 'english', + 'austrian' => 'german', + 'british' => 'english', + 'francais' => 'french', + 'frenchb' => 'french', + 'germanb' => 'german', + 'lsorbian' => 'lower-sorbian', + 'magyar' => 'hungarian', + 'naustrian' => 'german', + 'ngermanb' => 'german', + 'ngerman' => 'german', # v2.16 + 'norsk' => 'norwegian', + 'portuges' => 'portuguese', + 'russianb' => 'russian', + 'slovene' => 'slovenian', + 'UKenglish' => 'english', + 'USenglish' => 'english', + 'ukraineb' => 'ukrainian', + 'usorbian' => 'upper-sorbian' +); + +# v2.07 added check for success and for -q +# v2.05 added: + +if ($opt_d) +{ + # v2.11 check for backslash character if on Windows + $opt_d=~s/\\/\//g if $^O=~/Win/; + + if (chdir $opt_d) + { + print "Changed to '$opt_d'\n" unless ($opt_q); + } + else + { + die "Unable to chdir to '$opt_d' $!\n"; + } +} + +# v2.02: added: +# v2.19: changed value +my $xdynotist = 2; +# v2.13: removed +#my $needcompatibilitymode=2; + +# v2.13: added $istnotfound +my $istnotfound = 3; + +# v2.13: added error text: +my %makeindex_error_text = + ( + $xdynotist => "Style name indicates makeindex, but may be in xindy format.\n" + . "Remember to use \\setStyleFile to specify the name\n" + . "of the style file rather than redefining \\istfilename\n" + . "explicitly.", + $istnotfound => "Style file not found. (Have you used \\noist by mistake?)" + ); + +my %xindy_error_text = + ( + 'nosort' => "Sort key required for entries only containing command names.", + 'istnotxdy' => + "Style name has xdy extension, but may be in makeindex format.\n" + . "Remember to use \\setStyleFile to specify the name\n" + . "of the style file rather than redefining \\istfilename\n" + . "explicitly.", + 'missingendquote' => + "You may have missed a \" character in a command such as \\GlsAddXdyLocation.", + 'nolanguage' => + "No language detected.\nHave you remembered to use \\printglossary\n". + "or \\printglossaries in your document?", + 'nomain' => + "\nRemember to use package option 'nomain' if you don't\n". + "want to use the main glossary.", +#v2.21: fixed spelling of \GlsAddXdyLocation + 'badlocation' => + "You may have forgotten to add a location \n" + . "class with \\GlsAddXdyLocation or you may have \n" + . "the format incorrect.\n", + 'comp207' => "You may need to add 'compatible-2.07' package option.", + 'noxdyfile' => "Style file not found. (Have you used \\noist by mistake?)" + ); + +# define known extensions + +# v1.6: removed adding main glossary here as there's no guarantee +# that it's been used. If it has been used, the information will +# be picked up later in the aux file +my %exttype = ( +# main => {in=>'glo', out=>'gls', 'log'=>'glg'}, + ); + +# v1.5 define require languages for xindy + +my %language = (); +my %codepage = (); + +my $ext = ''; +my $name = $ARGV[0]; + +# v2.13 added: +#$name=~s/^"(.*)"$/$1/; +# v2.15: fix provided by Herb Schulz to allow for extensions that +# aren't exactly three characters: +# (HS) changes fix for 3 character extension limit +my ($basename,$extension) = ($name =~ m/^(.*?)(?:\.([^\.]*))?$/); +# (HS) end of changes fix for 3 character extension limit + +# make sure $extension is defined. (If there was no match in the +# above, it cause an uninitialised error later.) +$extension = '' unless ($extension); + +# Make sure users don't try passing the tex file: + +#if (length($ARGV[0]) > 3 and substr($ARGV[0],-4,1) eq ".") +#{ +# $name = substr($ARGV[0],0,length($ARGV[0])-4); +# +# $ext = substr($ARGV[0],-3,3); +# +# if (lc($ext) eq 'tex') +# (HS) changes fix for 3 character extension limit +#if (length($ARGV[0]) > 3 and substr($ARGV[0],-4,1) eq ".") +#{ +# $name = substr($ARGV[0],0,length($ARGV[0])-4); +# +# $ext = substr($ARGV[0],-3,3); +# +# if (lc($ext) eq 'tex') + if (lc($extension) eq 'tex') + { + die("Don't pass the tex file to makeglossaries:\n" + ."either omit the extension to make all the glossaries, " + ."or specify one of the glossary files, e.g. $name.glo, to " + ."make just that glossary.\n") + } +#} +# (HS) end of fix for 3 character extension limit + +# (HS) changes fix for 3 character extension limit +$ext = $extension; +$name = $basename; +# (HS) end of changes fix for 3 character extension limit + +# v2.01 add check to see if aux file exists + +unless (-e "$name.aux") +{ + die "Auxiliary file '$name.aux' doesn't exist. Have you run LaTeX?\n"; +} + +my $istfile = ""; + +my $glslist = ""; + +# should letter ordering be used? (v1.5 added) + +my $letterordering = defined($opt_l); + +# v2.19 added: +my $extramkidxopts = ''; + +# v4.34 added: +my $foundbib2glsresource = ''; + +# Check aux file for other glossary types, +# style file name and various other bits of information. + +&scan_aux($name); + +# has the style file been specified? +unless ($istfile) +{ + if ($foundbib2glsresource) + { + die "Found \\glsxtr\@resource in '$name.aux',\n", + "but not found \\\@istfilename.\n", + "You need to run bib2gls not makeglossaries.\n"; + } + else + { + die "No \\\@istfilename found in '$name.aux'.\n", + "Did your LaTeX run fail?\n", + "Did your LaTeX run produce any output?\n", + "Did you remember to use \\makeglossaries?\n"; + } +} + +# v2.08 added $xindyapp and $makeindexapp +# By default assume they are on the operating system's path +my $xindyapp = ($opt_x ? $opt_x :'xindy'); +my $makeindexapp = ($opt_m ? $opt_m :'makeindex'); + +# v2.11 check for backslash character if on Windows +if ($^O=~/Win/) +{ + $xindyapp=~s/\\/\//g; + $makeindexapp=~s/\\/\//g; +} + +# v1.5 save the general xindy switches + +my $xdyopts = ''; + +# v2.01 replaced 'unless ($opt_L eq "")' with 'if ($opt_L)' +if ($opt_L) +{ + $xdyopts .= " -L $opt_L"; +} + +# save all the general makeindex switches + +my $mkidxopts = ''; + +if ($opt_i) +{ + $mkidxopts .= " -i"; +} + +if ($letterordering) +{ + $mkidxopts .= " -l"; + $xdyopts .= " -M ord/letorder"; +} + +if ($opt_q) +{ +# v2.01 removed following lines. (This script now deals with +# printing messages to STDOUT.) + #$mkidxopts .= " -q"; + #$xdyopts .= " -q"; +} + +if ($opt_r) +{ + $mkidxopts .= " -r"; +} + +if ($opt_c) +{ + $mkidxopts .= " -c"; +} + +if ($opt_g) +{ + $mkidxopts .= " -g"; +} + +# v2.01 replaced 'unless ($opt_p eq "")' with 'if ($opt_p)' +if ($opt_p) +{ + $mkidxopts .= " -p $opt_p"; +} + +if ($extramkidxopts) +{ + $mkidxopts .= " $extramkidxopts"; +} + +# v2.01 replaced 'unless ($opt_s eq "")' with 'if ($opt_s)' +if ($opt_s) +{ + # v2.01 check if user has specified -s <file>.ist but aux file + # indicates .xdy ought to be used and vice-versa. Also check if + # requested style file exists + + unless (-e $opt_s) + { + die "\n", + "Requested style file '$opt_s' doesn't exist.\n\n"; + } + + if ($istfile=~/\.xdy$/ and $opt_s!~/\.xdy$/) + { + die "\n", + "The auxiliary file indicates that you should be using xindy,\n", + "but you have specified makeindex style file '$opt_s'\n", + "Make sure you don't specify 'xindy' as a package option if\n", + "you want to use makeindex.\n\n", + "\\usepackage[makeindex]{glossaries}\n\n"; + } + elsif ($istfile!~/\.xdy$/ and $opt_s=~/\.xdy$/) + { + die "\n", + "The auxiliary file indicates that you should be using\n", + "makeindex, but you have specified xindy style file '$opt_s'.\n", + "Make sure you specify 'xindy' as a package option if you\n", + "want to use xindy.\n\n", + "\\usepackage[xindy]{glossaries}\n\n"; + } + + $istfile = $opt_s; +} + +# Use xindy if style file ends with .xdy otherwise use makeindex + +my $usexindy = ($istfile=~m/\.xdy\Z/); + +if ($ext) +{ + # an extension has been specified, so only process + # the specified file + + # v1.6 %thistype is no longer given a default value + my %thistype; + + my $thislang = ""; + my $thiscodepage = ""; + + my @types = ($glslist ? split /,/, $glslist : keys %exttype); + + foreach my $type (@types) + { + if ($exttype{$type}{'in'} eq $ext) + { + %thistype = %{$exttype{$type}}; + + $thislang = $language{$type}; + + $thiscodepage = $codepage{$type}; + + last; + } + } + + # v1.6 If %thistype hasn't been defined, then the given + # extension doesn't correspond to any known glossary type + + # v2.01 replaced deprecated 'defined(%thistype)' with %thistype + unless (%thistype) + { + die "The file extension '$ext' doesn't correspond to any\n", + "known glossary extension. Try running makeglossaries\n", + "without an extension, e.g. makeglossaries \"$name\".\n"; + } + + my $outfile; + +# v2.01 replaced 'if ($opt_o eq "")' with 'unless ($opt_o)' + unless ($opt_o) + { + $outfile = "$name.$thistype{out}"; + } + else + { + $outfile = $opt_o; + } + + my $transcript; + +# v2.01 replaced 'if ($opt_t eq "")' with 'unless ($opt_t)' + unless ($opt_t) + { + $transcript = "$name.$thistype{'log'}"; + } + else + { + $transcript = $opt_t; + } + +# v2.01 remove old transcript file + + unless ($opt_n) + { + unlink($transcript); + } + + if ($usexindy) + { + &xindy("$name.$ext", $outfile, $transcript,$istfile, + $thislang, $thiscodepage, $xdyopts, $opt_q, $opt_n, $xindyapp); + } + else + { + &makeindex("$name.$ext",$outfile,$transcript,$istfile, + $mkidxopts,$opt_q, $opt_n, $makeindexapp, 1); + } + + + # v2.15 added: + + my $num_omitted = $#types; + + if ($num_omitted == 1) + { + print "1 glossary ignored.\n" unless $opt_q; + } + elsif ($num_omitted > 1) + { + print "$num_omitted glossaries ignored.\n" unless $opt_q; + } +} +else +{ + # no file extension specified so process all glossary types + + my @types = ($glslist ? split /,/, $glslist : keys %exttype); + + foreach my $type (@types) + { + my %thistype = %{$exttype{$type}}; + + my $inputfile = "$name.$thistype{in}"; + + my $outfile; + +# v2.01 changed 'if ($opt_o eq "")' with 'unless ($opt_o)' + unless ($opt_o) + { + $outfile = "$name.$thistype{out}"; + } + else + { + $outfile = $opt_o; + } + + # v1.7 print warnings to STDOUT instead of STDERR + + # v1.6 added file existence test + unless (-e $inputfile) + { + # v2.09 suppress warning if -q switch in use + print "Warning: File '$inputfile' doesn't exist.\n", + "*** Skipping glossary '$type'. ***\n" unless ($opt_q); + next; + } + + unless (-r $inputfile) + { + print "Warning: No read access for '$inputfile' $!\n", + "*** Skipping glossary '$type'. ***\n" unless ($opt_q); + next; + } + + my $transcript; + +# v2.01 changed 'if ($opt_t eq "")' with 'unless ($opt)' + unless ($opt_t) + { + $transcript = "$name.$thistype{'log'}"; + } + else + { + $transcript = $opt_t; + } + + # v1.6 added file empty test + if (-z $inputfile) + { + my $message = + "Warning: File '$inputfile' is empty.\n". + "Have you used any entries defined in glossary '$type'?\n"; + + if ($type eq 'main') + { + $message .= + "Remember to use package option 'nomain' if you\n". + "don't want to use the main glossary.\n"; + } + + # v2.09 suppress warning if -q switch in use + warn $message unless $opt_q; + + # Write warning to transcript file. + + if (open TRANSFD, ">$transcript") + { + print TRANSFD $message; + close TRANSFD; + } + + # create an empty output file and move on to the next glossary + + if (open OFD, ">$outfile") + { + print OFD "\\null\n"; + close OFD; + } + else + { + warn "Unable to create '$outfile' $!\n"; + } + + next; + } + +# v2.01 remove old transcript file + + unless ($opt_n) + { + unlink($transcript); + } + + if ($usexindy) + { + &xindy($inputfile,$outfile,$transcript,$istfile, + $language{$type},$codepage{$type}, + $xdyopts,$opt_q,$opt_n, $xindyapp); + } + else + { + &makeindex($inputfile,$outfile,$transcript, + $istfile,$mkidxopts,$opt_q,$opt_n, $makeindexapp, 1); + } + } +} + +sub scan_aux{ + my $name = shift; + + # v2.0 added + local(*AUXFILE); + + if (open AUXFILE, "$name.aux") + { + while (<AUXFILE>) + { + #v2.14 added + if (m/\\\@gls\@reference/ and not $glslist) + { + die "Your document has used \\makenoidxglossaries\n", + "You don't need makeindex or xindy.\n"; + } + + if (m/\\glsxtr\@makeglossaries\{(.*)\}/) + { + #v2.20 added + + $glslist = $1; + + unless ($opt_q) + { + print "only processing subset '$glslist'\n"; + } + } + elsif (m/\\\@input\{(.+)\.aux\}/) + { + # v1.9 added + # v2.17 escaped { in regex + &scan_aux($1); + + # v2.04 added + # (Fix provided by Daniel Grund) + next; + } + elsif (m/\\\@newglossary\s*\{(.*)\}\{(.*)\}\{(.*)\}\{(.*)\}/) + { + # v2.17 escaped { in regex + + $exttype{$1}{'log'} = $2; + $exttype{$1}{'out'} = $3; + $exttype{$1}{'in'} = $4; + + unless ($opt_q) + { + print "added glossary type '$1' ($2,$3,$4)\n"; + } + } + elsif (m/\\\@istfilename\s*\{([^}]*)\}/) + { + # v2.17 escaped { in regex + + $istfile = $1; + + # check if double quotes were added to \jobname + # v2.12 added check for xdy (bug ID 33) + $istfile=~s/^"(.*)"\.(ist|xdy)$/$1.$2/; + + # v2.12 if on Windows, substitute any '*' with ' ' + # to compensate for MiKTeX bug + # http://sourceforge.net/p/miktex/bugs/2301/ + + if ($^O=~/Win/) + { + $istfile=~tr/\*/ /; + } + } + elsif (m/\\\@xdylanguage\s*\{([^}]+)\}\{([^}]*)\}/) + { + # v1.5 added + # v2.17 escaped { in regex + + $language{$1} = $2; + } + elsif (m/\\\@gls\@codepage\s*\{([^}]+)\}\{([^}]*)\}/) + { + # v1.5 added + # v2.17 escaped { in regex + + $codepage{$1} = $2; + } + elsif (m/\\\@gls\@extramakeindexopts\{(.*)\}/) + { + # v2.19 added + + $extramkidxopts .= $1; + } + elsif (m/\\glsxtr\@resource/) + { + # v4.34 added + + # No error at this point as a hybrid method is allowed. + # Error only occurs if no \@istfilename found. + + $foundbib2glsresource = 1; + } + + # v1.5 added + # Allow -l switch to override specification in aux file + unless (defined($opt_l)) + { + # v2.17 escaped { in regex + if (m/\\\@glsorder\s*\{([^}]+)\}/) + { + my $ordering = $1; + + if ($ordering eq "word") + { + $letterordering = 0; + } + elsif ($ordering eq "letter") + { + $letterordering = 1; + } + else + { + warn + "Unknown ordering '$ordering'\n", + "Assuming word ordering\n" unless ($opt_q); + $letterordering = 0; + } + } + } + } + + close AUXFILE; + } + else + { + warn "Unable to open $name.aux: $!\n"; + } +} + +# v2.01 new subroutine run_app added +sub run_app{ + my($appname, $appargs, $trans, $quiet, $dontexec) = @_; + + local(*STATUS); + + my $status = ''; + my $warnings = ''; + my $errno = 0; + my $log = ''; + + print "$appname $appargs\n" if ($dontexec or not $quiet); + + return if ($dontexec); + + # v2.11 added double-quotes around $appname + # v2.14 added -k switch + if (not $opt_k and open (STATUS, "\"$appname\" $appargs 2>&1 |")) + { + while (<STATUS>) + { + print unless ($quiet); + + $warnings .= $_ if (/WARNING:/); + + $status .= $_ unless (/^[\w]+ing/ or /^Finished/ or /^Usage:/); + + $log .= $_; + } + + close STATUS; + } + else + { + unless ($opt_k) + { + $warnings = "Unable to fork \"$appname\" with redirection $!\n"; + + # v2.14 added check for quiet switches + warn $warnings, + "Retrying without redirection.\n" unless ($quiet or $opt_Q); + } + + $status = `\"$appname\" $appargs`; + + $log = $status; + + print $status unless ($quiet); + } + + if ($?) + { + # v2.14 Fixed error number assignment + $errno = ($? >> 8); + + # v2.14 Added check for existence of transcript + unless (-e $trans) + { + $log .= "\n$appname didn't create a transcript.\n"; + + if (not $appname=~/\//) + { + # No path specified + $log .= "Check that $appname has been installed and\nis on your system's PATH.\n"; + + if (defined $ENV{PATH}) + { + $log .= "Your PATH environment variable is set to: \n" + . $ENV{PATH} . "\n"; + } + else + { + $log .= "I'm sorry, I can't detect your PATH environment variable\n"; + } + + $log .= "Try manually running:\n\"$appname\" $appargs\n"; + } + elsif (not -e $appname) + { + if ($^O=~/Win/) + { + if (-e "$appname.exe" or -e "$appname.bat") + { + $log .= "Try manually running:\n\"$appname\" $appargs\n"; + } + else + { + $log .= "File '$appname' doesn't exist.\n"; + } + } + else + { + $log .= "File '$appname' doesn't exist.\n"; + } + } + else + { + $log .= "Try manually running:\n\"$appname\" $appargs\n"; + } + } + + if (open LOGFILE, ">>$trans") + { + print LOGFILE "\n\n*** Unable to execute: '\"$appname\" $appargs' ***\n\n"; + print LOGFILE "Failed with error code $errno.\n\n"; + + if ($log) + { + print LOGFILE "Status report:\n\n"; + print LOGFILE "$log", "\n"; + } + + print LOGFILE "Warnings:\n\n",$warnings, "\n" if $warnings; + close LOGFILE; + } + else + { + warn "Unable to open '$trans' $!\n"; + } + } + + if ($log=~/\(0 entries accepted,/ + or ( ($log=~/(\d+) warnings?/ and $1 gt 0)) + or $log=~/not found/) + { + # Attempt to diagnose what's gone wrong + + if (open TRANS, $trans) + { + while (<TRANS>) + { + if (/Index style file .* not found/) + { + $errno = $istnotfound; + last; + } + elsif (/Unknown specifier ;/) + { + $errno = $xdynotist; + last; + } + elsif (/## Warning \(.*\):\s*$/) + { + $warnings .= $_ . <TRANS>; + } + } + + close TRANS; + } + + } + + return ($status, $warnings, $errno); +} + +# v2.08 added $app parameter +sub makeindex{ + my($in,$out,$trans,$ist,$rest,$quiet,$dontexec,$app,$repairencaps) = @_; + + my $args = "$rest -s \"$ist\" -t \"$trans\" -o \"$out\" \"$in\""; + +# v2.01 replaced code with call to &run_app + + my ($status, $warnings, $errno) + = &run_app($app, $args, $trans, $quiet, $dontexec); + + return if ($dontexec); + + if ($errno) + { + my $diagnostic = ''; + + if ($makeindex_error_text{$errno}) + { + $diagnostic = $makeindex_error_text{$errno}; + } + else + { + $diagnostic = "Can't find diagnostic message for error code $errno"; + } + + if (open LOGFILE, ">>$trans") + { + print LOGFILE "\nmakeglossaries diagnostic messages:\n$diagnostic\n"; + close LOGFILE; + } + + die "\n***Call to makeindex failed***\n", + ($diagnostic ? + "\nPossible cause of problem:\n\n". $diagnostic . "\n\n": + "\n" + ), + "Check '$trans' for details\n"; + } + + # 2.18: added check and repair for multiple encaps + if ($warnings) + { + warn $warnings unless $quiet; + + if ($repairencaps and $warnings=~/multiple encaps/) + { + unless ($quiet) + { + print "Multiple encaps detected. Attempting to remedy.\n"; + print "Reading $in...\n"; + } + + # if $in can't be opened at this point something wrong + # has occurred (otherwise how did makeindex manage to open + # it?) + + open INFD, $in or die "Can't open '$in' $!\n"; + + my @entries = (); + + while (<INFD>) + { + if (/\\glossaryentry\{(.*)\|([^\|]*)\}\{(.*?)\}/) + { + my %entry = + ( + 'entry' => $1, + 'encap' => $2, + 'location' => $3 + ); + + my $add = 1; + + for (my $idx = 0; $idx <= $#entries; $idx++) + { + my $existing = $entries[$idx]; + + if ($entry{'entry'} eq $existing->{'entry'} + and $entry{'location'} eq $existing->{'location'} + and $entry{'encap'} ne $existing->{'encap'}) + { + $add = 0 if ($add == 1); + + # Range encaps should take precedence. + + if ($entry{'encap'}=~/^[\(\)]/) + { + $add = 2; + + if ($existing->{'encap'}=~/^[\(\)]/) + { + # too complicated, keep both + + last; + } + else + { + # remove existing + + splice @entries, $idx, 1; + + $idx--; + } + } + elsif ($existing->{'encap'}=~/^[\(\)]/) + { + if ($entry{'encap'}=~/^[\(\)]/) + { + # too complicated, keep both + + $add = 1; + last; + } + # (otherwise drop new entry) + } + elsif (&encap_overrides($entry{'encap'}, + $existing->{'encap'})) + { + $entries[$idx] = \%entry; + } + } + } + + push @entries, \%entry if $add > 0; + } + else + { + warn "Abandoning attempt. Can't parse: $_" unless $quiet; + + close INFD; + return; + } + } + + close INFD; + + if (open OUTFD, ">$in") + { + print "Writing $in...\n" unless $quiet; + + foreach my $entry (@entries) + { + print OUTFD '\\glossaryentry{', + $entry->{'entry'}, '|', + $entry->{'encap'}, '}{', + $entry->{'location'}, '}', "\n"; + } + + close OUTFD; + + print "Retrying\n" unless $quiet; + + &makeindex($in,$out,$trans,$ist,$rest,$quiet,$dontexec,$app,0); + } + else + { + warn "Can't open '$in' $!\n" unless $quiet; + } + } + } +} + +# 2.18 new +# This is a subroutine in case of possible extension. +# For example, what happens in the event of 'textbf' and 'emph'? +# Should one override the other or be combined? Combining is harder +# as it would need a corresponding LaTeX command. +# 2.21 check for range encap moved earlier + +sub encap_overrides{ + my ($newencap, $existing) = @_; + + ($existing=~/\\glsnumberformat\s*$/ or $newencap!~/\\glsnumberformat\s*$/ ) +} + +# v2.08 added $app parameter +sub xindy{ + my($in,$out,$trans,$ist,$language,$codepage,$rest,$quiet, + $dontexec, $app) = @_; + my($args, $langparam, $main, $retry); + my($module); + + $module = $ist; + $module=~s/\.xdy\Z//; + + if ($language) + { + # map babel names to xindy names + + $language = $languagemap{$language} if ($languagemap{$language}); + + $langparam = "-L $language"; + } + else + { + $langparam = ""; + # v2.10 initialise $language to suppress warnings + $language = ""; + } + + # most languages work with xindy's default codepage, but + # some don't, so if the codepage isn't specific, check + # the known cases that will generate an error + # and supply a default. (For all other cases, it's up to the + # user to supply a codepage.) + +# v2.01 changed 'if ($codepage eq "")' to 'unless ($codepage)' + unless ($codepage) + { + if ($language eq 'dutch') + { + $codepage = "ij-as-ij"; + } + elsif ($language eq 'german') + { + $codepage = "din5007"; + } + elsif ($language eq 'gypsy') + { + $codepage = "northrussian"; + } + elsif ($language eq 'hausa') + { + $codepage = "utf"; + } + elsif ($language eq 'klingon') + { + $codepage = "utf"; + } + elsif ($language eq 'latin') + { + $codepage = "utf"; + } + elsif ($language eq 'mongolian') + { + $codepage = "cyrillic"; + } + elsif ($language eq 'slovak') + { + $codepage = "small"; + } + elsif ($language eq 'spanish') + { + $codepage = "modern"; + } + elsif ($language eq 'vietnamese') + { + $codepage = "utf"; + } + } + elsif ($language eq 'german' and $codepage!~/(din5007|duden|braille)/) + { +#v2.16 added check for german din/duden + + $codepage = "din5007-$codepage"; + } + + + my $codepageparam = ""; + + if ($codepage) + { + $codepageparam = "-C $codepage"; + } + + $main = join(' ', + "-I xindy", + "-M \"$module\"", + "-t \"$trans\"", + "-o \"$out\"", + "\"$in\""); + + $args = join(' ', $rest, $langparam, $codepageparam, $main); + +# v2.01 replaced code with call to &run_app + + my ($status, $warnings, $errno) + = &run_app($app, $args, $trans, $quiet, $dontexec); + + return if ($dontexec); + + if ($status=~/Cannot locate xindy module for language ([^\s]+) in codepage ([^\s]+)/) + { + $args = join(' ', $rest, $langparam, $main); + + unless ($quiet) + { + my $message = "$&\nRetrying using default codepage.\n"; + + warn $message; + + $retry .= $message; + } + + ($status, $warnings, $errno) + = &run_app('xindy', $args, $trans, $quiet, $dontexec); + + } + + if ($status=~/Cannot locate xindy module for language ([^\s]+)/ + and $1 ne 'general') + { + $args = join(' ', $rest, "-L general", $main); + + unless ($quiet) + { + my $message = "$&\nRetrying with -L general\n"; + + warn $message; + $retry .= $message; + } + + ($status, $warnings, $errno) + = &run_app('xindy', $args, $trans, $quiet, $dontexec); + + } + + if ($errno) + { + # attempt further diagnostic + + my $diagnostic = ''; + + if ($status=~/index 0 should be less than the length of the string/m) + { + $diagnostic = $xindy_error_text{nosort}; + + $diagnostic .= &parse_for_xindy_nosort($in); + } + elsif ($status=~/variable .+ has no value/m) + { + # v2.19 fixed misspelt key + $diagnostic = $xindy_error_text{istnotxdy}; + } + elsif ($status=~/Could not find file /m) + { + # v2.19 added + $diagnostic = $xindy_error_text{noxdyfile}; + } + elsif ($status=~/Possible read-error due to ill-formed string " :sep/m) + { + $diagnostic = $xindy_error_text{missingendquote}; + } + elsif (not $language) + { + # If the language hasn't been set, then it may be + # because the document doesn't contain + # \printglossaries/\printglossary or it may be + # because the user has a customized style file that + # contains the language settings. + + $diagnostic = $xindy_error_text{nolanguage}; + + if ($in eq 'glo') + { + # or it may be that the user doesn't want to use the main + # glossary and has forgotten to suppress it with the + # "nomain" package option + + $diagnostic .= $xindy_error_text{nomain}; + } + } + + # v2.19 added: + if ($diagnostic and open LOGFILE, ">>$trans") + { + print LOGFILE "\nmakeglossaries diagnostic messages:\n\n$diagnostic\n"; + close LOGFILE; + } + + die "\n***Call to xindy failed***\n", + ($diagnostic ? + "\nPossible cause of problem:\n\n". $diagnostic . "\n\n": + "\n"), + "Check '$trans' for details\n"; + } + + # Check xindy warnings + + if ($status=~/^WARNING:/m) + { + my $diagwarn = ''; + + if ($status=~/did not match any location-class/m) + { + $diagwarn = $xindy_error_text{badlocation}; + } + + if ($status=~/unknown attribute `pageglsnumberformat'/m) + { + $diagwarn .= $xindy_error_text{comp207}; + } + + if ($status=~/Would replace complete index key by empty string, ignoring/m) + { + $diagwarn .= $xindy_error_text{nosort}; + $diagwarn .= &parse_for_xindy_nosort($in); + } + + if ($diagwarn) + { + warn "\n**Warning:**\n\n", $diagwarn, "\n"; + + $warnings .= "\nmakeglossaries diagnostic messages:\n\n" + . $diagwarn; + } + } + + if ($retry or $warnings) + { + if (open LOGFILE, ">>$trans") + { + print LOGFILE "\n$warnings"; + + if ($retry) + { + print LOGFILE "\nmakeglossaries messages:\n\n", $retry; + } + + close LOGFILE; + } + else + { + warn "Unable to open '$trans' $!\n"; + } + } +} + +# v2.18 added: +sub parse_for_xindy_nosort{ + my ($in) = @_; + + my $msg = join("\n", "", + "Attempting to determine which entries have problem sort keys.", + "Parsing '$in'"); + + my %entries = (); + + if (open FD, $in) + { + while (<FD>) + { +# v2.19 extra conditions added + if (/:tkey \(\("((?:\\\\[a-zA-Z@]+ *)+)" "\\\\glossentry\{(.*)\}"\) \)/) + { + my $label = $2; + + unless ($entries{$label}) + { + $entries{$label}->{sort} = $label; + $entries{$label}->{suggestion} = $label; + $entries{$label}->{suggestion}=~s/([\\\s]+)//g; + + } + } + elsif (/:tkey \(\("(\\\\[a-zA-Z@]+ *{(?:\\\\[a-zA-Z@]+ *)+})+" "\\\\glossentry\{(.*)\}"\) \)/) + { +# name in the form \cs{\cs} + my $label = $2; + + unless ($entries{$label}) + { + $entries{$label}->{sort} = $1; + $entries{$label}->{suggestion} = $label; + $entries{$label}->{suggestion}=~s/^[a-zA-Z]+[:\-\.]//; + $entries{$label}->{suggestion}=~s/([^\w]+)//g; + } + } + elsif (/:tkey \(\("(\$\s*(?:\{?\\\\[a-zA-Z@]+ *\}?)+\$)" "\\\\glossentry\{(.*)\}"\) \)/) + { +# name in the form $\cs$ + my $label = $2; + + unless ($entries{$label}) + { + $entries{$label}->{sort} = $1; + $entries{$label}->{suggestion} = $label; + $entries{$label}->{suggestion}=~s/^[a-zA-Z]+[:\-\.]//; + $entries{$label}->{suggestion}=~s/([^\w]+)//g; + } + } + } + + close FD; + + my @labels = keys %entries; + + my $n = $#labels+1; + + if ($n == 0) + { + $msg .= "\nCouldn't find anything! Sorry, I'm stumped."; + } + else + { + $msg .= ($n == 1 ? "\n1 problematic entry found:\n" + : "\n$n problematic entries found:\n"); + + foreach my $label (@labels) + { + my $thisentry = $entries{$label}; + + $msg .= "\nLabel: '$label'. Sort value : '$thisentry->{sort}'"; + $msg .= "\n(Try adding sort={$thisentry->{suggestion}} to the definition.)"; + } + } + } + else + { + $msg .= "\nFailed to open '$in' $!\n"; + } + + $msg; +} + +sub HELP_MESSAGE{ + print "\nSyntax : makeglossaries [options] <filename>\n\n"; + print "For use with the glossaries package to pass relevant\n"; + print "files to makeindex or xindy.\n\n"; + print "<filename>\tBase name of glossary file(s). This should\n"; + print "\t\tbe the name of your main LaTeX document without any\n"; + print "\t\textension.\n"; + print "\nGeneral Options:\n\n"; + print "-o <gls>\tUse <gls> as the output file.\n"; + print "\t\t(Don't use -o if you have more than one glossary.)\n"; + print "-q\t\tQuiet mode.\n"; + print "-Q\t\tSilence unable to fork warning.\n"; + print "-k\t\tDon't try to use piped redirection.\n"; + print "-l\t\tLetter ordering.\n"; + print "-s <sty>\tEmploy <sty> as the style file.\n"; + print "-t <log>\tEmploy <log> as the transcript file.\n"; + print "\t\t(Don't use -t if you have more than one glossary\n"; + print "\t\tor the transcripts will be overwritten.)\n"; + print "-d <directory>\tDirectory in which the .aux, .glo etc files are located.\n", + "\t\t(Default is the directory in which <filename> resides.)\n"; + print "-n\t\tPrint the command that would normally be executed,\n", + "\t\tbut don't execute it.\n"; + + print "\nXindy Options:\n\n"; + print "-L <language>\tUse <language>.\n"; + print "-x <file>\tFull path to xindy executable.\n", + "\t\t(Default assumes xindy is on the operating system's path.)\n"; + + print "\nMakeindex Options:\n"; + print "(See makeindex documentation for further details on these "; + print "options.)\n\n"; + print "-c\t\tCompress intermediate blanks.\n"; + print "-g\t\tEmploy German word ordering.\n"; + print "-p <num>\tSet the starting page number to be <num>.\n"; + print "-r\t\tDisable implicit page range formation.\n"; + print "-m <file>\tFull path to makeindex executable.\n", + "\t\t(Default assumes makeindex is on the operating system's path.)\n"; +} + +sub VERSION_MESSAGE{ + + my $verYear = ''; + + if ($version=~/(\d{4})-\d{2}-\d{2}/) + { + $verYear = "-$1"; + } + + print "Makeglossaries Version $version\n"; + print "Copyright (C) 2007$verYear Nicola L C Talbot\n"; + print "This material is subject to the LaTeX Project Public License.\n"; +} + +1; + +=head1 NAME + +makeglossaries - Calls makeindex/xindy for LaTeX documents using glossaries package + +=head1 SYNOPSIS + +B<makeglossaries> [B<-o> I<file>] [B<-q>] [B<-Q>] [B<-k>] [B<-n>] +[B<-s> I<file>] [B<-t> I<file>] [B<-L> I<language>] [B<-c>] [B<-g>] [B<-l>] +[B<-p> I<num>] [B<-r>] [B<-d> I<aux dir>] [B<-m> I<file>] [B<-x> I<file>] +[B<--version>] [B<--help>] I<basename> + +=head1 DESCRIPTION + +B<makeglossaries> is designed for use with LaTeX documents that +use the glossaries package. The mandatory argument I<basename> should +be the name of the LaTeX document without the .tex extension. +B<makeglossaries> will read the auxiliary file to determine whether +B<makeindex> or B<xindy> should be called. All the information +required to be passed to the relevant indexing application should +also be contained in the auxiliary file, but may be overridden by +the option arguments to B<makeglossaries>. + +=head1 OPTIONS + +=over 4 + +=item B<-q> + +Quiet mode. Reduces chatter to standard output. + +=item B<-Q> + +Silences warning about being unable to fork. + +=item B<-k> + +Don't try forking with piped redirection. (Lessens the +effect of -q) + +=item B<-n> + +Print the commands that would normally be executed but don't run them. + +=item B<-o> I<file> + +Use I<file> as the output file. (Only suitable for documents +containing a single glossary, otherwise each glossary will be +overridden.) + +=item B<-s> I<file> + +Use I<file> as the style file. Note that if you use this option, +you need to know whether B<makeindex> or B<xindy> will be called, as +they have different style files. + +=item B<-t> I<file> + +Use I<file> as the transcript file. + +=item B<-l> + +Letter ordering. + +=item B<-L> I<language> + +This option only has an effect if B<xindy> is called. Sets the +language. See B<xindy> documentation for further details. + +=item B<-c> + +Compress intermediate blanks (B<makeindex> only). + +=item B<-g> + +Employ German word ordering (B<makeindex> only). + +=item B<-p> I<num> + +Sets the starting page number to be I<num> (B<makeindex> only). + +=item B<-r> + +Disable implicit page range formation (B<makeindex> only). + +=item B<-d> I<aux dir> + +Specify the directory the .aux, .glo etc files are located. +Defaults to the parent directory of the base file I<filename>. + +=item B<-m> I<file> + +Specify the full path name for B<makeindex> to I<file> in the +event that B<makeindex> isn't on the operating system's path. + +=item B<-x> I<file> + +Specify the full path name for B<xindy> to I<file> in the +event that B<xindy> isn't on the operating system's path. + +=item B<--version> + +Prints version number and exits. + +=item B<--help> + +Prints help message and exits. + +=back + +=head1 REQUIRES + +Perl, Getopt::Std, and makeindex or xindy (depending on glossaries +package options). + +=head1 LICENSE + +This is free software distributed under the LaTeX Project Public +License. There is NO WARRANTY. +See L<http://www.latex-project.org/lppl.txt> for details. + +=head1 AUTHOR + +Nicola L. C. Talbot, +L<http://www.dickimaw-books.com/> + +=head1 RECOMMENDED READING + +The glossaries manual: + + texdoc glossaries + +=cut |