#!/usr/bin/perl -w $VERSION = 0.9; =pod =head1 NAME reflabel.pl -- check latex references and labels =head1 SYNOPSIS This program prints all latex labels that are multiply defined, as well as all latex labels that are not defined but referenced. Both are of course errors. The program outputs these errors in a format that allow the emacs next-error function to work. It also can check for labels that are defined and never referenced. =head1 USAGE reflabel.pl [-v[0|1]] texfiles*.tex -v0 or -v also print labels that are never referenced -v1 or -vv print a description for each label and each reference. -v2 like -v1, but splits lines. =head1 BUGS Probably many. =head1 BACKGROUND INFORMATION =head2 AUTHOR ivo welch =head2 DATE June 26, 2002 =head2 LICENSE (C) Ivo Welch, 2002. GNU copyleft usage permitted by the author. =head2 THANKS Thanks to all the chaps on comp.text.tex who constantly help me out with necessary latex macros---especially Don Arseneau. This perl code may help give back a little to the community. =head2 LATEST VERSION I will try to keep the latest version at http://welch.econ.brown.edu/ . Please check there first. The site also contains another useful perl program for latex, called B. It cross-references information about labels and references, again in an output format that is useful for emacs use. For now, the perl code is at B =head2 SUPPORT None. Don't even think about it. Expect absolutely no support from the author. Make changes yourself. =cut ################################################################ use strict; #### admittedly ugly argument processing my $VERBOSE = ($ARGV[0] =~ /^\-v[2]$/) ? 3 : ($ARGV[0] =~ /^\-v[1|v]$/) ? 2 : (($ARGV[0] =~ /^\-v$/)||($ARGV[0] =~ /^\-v0$/)) ? 1 : 0; if ($VERBOSE) { shift(@ARGV); print STDERR "$0: Operations Verbose Level $VERBOSE\n"; } #### initialization my $linenum=0; my (%labels,%refs); my $multiply=0; my $multiplelabelwarnings=""; print STDERR "Processing Files "; foreach my $filename (@ARGV) { print STDERR "[$filename]"; open(FIN, "$filename") or die "File $filename cannot be opened: $!\n"; $linenum=0; while (my $file=) { ++$linenum; # extract, process, and store all labels; while ($file =~ /(\\label\{[^\}]*\})/g) { my $label= $1; $label=~ s/\\label\{([^\}]*)\}/$1/g; if (defined($labels{$label})) { $multiplelabelwarnings.= "$labels{$label}: Label '$label' multiply defined. First definition is here.\n". "$filename:$linenum: Label '$label' multiply defined. Second definition is here.\n"; ++$multiply; } $labels{$1} = $filename . ":" . $linenum . ($labels{$1} or ""); } # extract, process, and store all references; while ($file =~ /(\\ref\{[^\}]*\})/g) { my $ref= $1; $ref =~ s/ref\{([^\}]*)\}/$1/g; # ok, assume that this is reasonable $refs{$1} = $filename . ":" . $linenum . ($refs{$1} ? ":&$refs{$1}" : ""); } while ($file =~ /(\\pageref\{[^\}]*\})/g) { my $ref= $1; $ref =~ s/pageref\{([^\}]*)\}/$1/g; # ok, assume that this is reasonable $refs{$1} = $filename . ":" . $linenum . ($refs{$1} ? ":&$refs{$1}" : ""); } } close(FIN); } print STDERR "\n\n"; ################################################################ errors print "\nChecking whether labels were multiply defined.\n"; if ($multiply>0) { print "\t$multiply multiple labels were found:\n"; print $multiplelabelwarnings; } else { print "\tNo multiple labels were found.\n"; } ################################################################ print "\nChecking That All Labels Exist:\n"; { my $neverdefined=0; my @keys = sort (keys %refs); foreach my $key (@keys) { if (!defined($labels{$key})) { print "$refs{$key}: label '$key', referenced here, never defined!\n"; ++$neverdefined; } else { if ($VERBOSE>=3) { # we could also split this by '&' to show all references print "$refs{$key}: The reference '$key' is referencing here...\n"; print "$labels{$key}: ...and the label that the reference '$refs{$key}' refers to.\n"; } elsif ($VERBOSE>=2) { print "$refs{$key}: $key -> ($labels{$key})\n"; } } } print(($neverdefined) ? "\t$neverdefined labels were never defined.\n" : "\tNo undefined labels.\n"); } ################################################################ warnings if ($VERBOSE) { my $neverused=0; print "\nChecking That All Labels Are Used:\n"; my @keys = sort (keys %labels); foreach my $key (@keys) { print ""; if (!defined($refs{$key})) { print "$labels{$key}: label '$key' never used.\n"; ++$neverused; } else { if ($VERBOSE>=2) { print "$labels{$key}: $key <- $refs{$key}\n"; } } } print(($neverused) ? "\t$neverused labels were never used.\n" : "\tNo unreferenced labels.\n"); }