# # The perl script requires bindings for the following # variables to be prepended: # DEFAULT_TMPDIR # CONTEXTDIFF # $Pgm = $0; $Pgm =~ s/.*\/([^\/]+)$/\1/; # # set up signal handler sub quit_upon_signal { &rm_temp_files_and_exit(); } $SIG{'INT'} = 'quit_upon_signal'; $SIG{'QUIT'} = 'quit_upon_signal'; # $Verbose = 0; if ($ARGV[0] eq '-v') { $Verbose = 1; shift(@ARGV); } # die "$Pgm: must have exactly one argument\n" if $#ARGV != 0; # figure out input file and its filename root if (-f $ARGV[0]) { $TeX_input = $ARGV[0]; if ($TeX_input =~ /(.+)\.[^\.\/\n]+$/) { $TeX_root = $1; } else { $TeX_root = $TeX_input; } } elsif (-f $ARGV[0].'.tex') { $TeX_input = $ARGV[0].'.tex'; $TeX_root = $ARGV[0]; } else { die "$Pgm: input file $ARGV[0] doesn't exist\n"; } if ( $ENV{'TMPDIR'} ) { # where to make tmp file names $Tmp_prefix = $ENV{'TMPDIR'} ; } else { $Tmp_prefix ="$DEFAULT_TMPDIR"; $ENV{'TMPDIR'} = "$DEFAULT_TMPDIR"; # set the env var as well } sub rm_temp_files { system("rm -f $Tmp_prefix/ltx-*.$$"); } sub rm_temp_files_and_exit { system("rm -f $Tmp_prefix/ltx-*.$$"); exit(1); } $SIG{'INT'} = 'rm_temp_files_and_exit'; $SIG{'QUIT'} = 'rm_temp_files_and_exit'; sub die_gracefully { local($msg) = @_; print STDERR $msg; &rm_temp_files_and_exit(); } # must read through root file to see if a \bibliography # is there... $Bibliography_requested = 0; open(TEXIF, "<$TeX_input") || &die_gracefully("$Pgm: Can't read $TeX_input\n"); while () { $Bibliography_requested = 1 if /^\\bibliography/; } close(TEXIF); &die_gracefully("$Pgm: reading $TeX_input had errors\n") if $? >> 8; # run latex first time (?) &run_latex(); # sets $Says_labels_changed $Times_run = 1; while (&something_more_needed()) { print STDERR "labels_changed=$Says_label_changed;bibtex_needed=$BibTeX_run_needed;makeindex_needed=$MakeIndex_run_needed\n" if $Verbose; if ($BibTeX_run_needed) { &run_bibtex(); } if ($MakeIndex_run_needed) { unlink "$TeX_root.ind"; (system("makeindex $TeX_root.idx") >> 8) && &die_gracefully("$Pgm: makeindex $TeX_root.idx had errors\n"); } # save (copy) .aux file as .aux-prev file for future ref # ditto for .idx file unlink "$TeX_root.aux-prev"; (system("cp $TeX_root.aux $TeX_root.aux-prev") >> 8) && &die_gracefully("$Pgm: cp $TeX_root.aux $TeX_root.aux-prev failed\n"); if (-f "$TeX_root.idx") { unlink "$TeX_root.idx-prev"; (system("cp $TeX_root.idx $TeX_root.idx-prev") >> 8) && &die_gracefully("$Pgm: cp $TeX_root.idx $TeX_root.idx-prev failed\n"); } # run latex again &run_latex(); # sets $Says_labels_changed $Times_run++; if ($Times_run >= 4) { print STDERR "*** I don't run LaTeX more than four times;\n"; print STDERR "*** Something is probably wrong...\n"; &rm_temp_files_and_exit(); } } &rm_temp_files(); exit(0); sub run_latex { $Says_labels_changed = 0; $Multiply_defined_labels = 0; select(STDERR); $| = 1; select(STDOUT); # no buffering on STDERR print STDERR "$Pgm: *** running LaTeX...\n" if $Verbose; unlink "$TeX_root.dvi"; open(LTXPIPE, "latex $TeX_input 2>&1 |") || &die_gracefully("$Pgm: Can't run latex pipe\n"); while () { $Multiply_defined_labels = 1 if /^LaTeX Warning: Label .* multiply defined/; $Says_labels_changed = 1 if /^LaTeX Warning: Label\(s\) may have changed/ && ! $Multiply_defined_labels; print STDERR $_; } close(LTXPIPE); &die_gracefully("$Pgm: LaTeX run had errors\n") if $? >> 8; # sort .idx file, because this helps makeindex # (can you say `bug'?) if (-f "$TeX_root.idx") { print STDERR "$Pgm: *** sorting $TeX_root.idx...\n" if $Verbose; (system("sort $TeX_root.idx -o $TeX_root.idx") >> 8) && &die_gracefully("$Pgm: sorting $TeX_root.idx failed\n"); } } sub run_bibtex { # ugly because bibtex doesn't return a correct error status local($bibtex_had_errors) = 0; print STDERR "$Pgm: *** running BibTeX...\n" if $Verbose; unlink "$TeX_root.bbl"; $| = 1; # no buffering open(BIBTXPIPE, "bibtex $TeX_root 2>&1 |") || &die_gracefully("$Pgm: Can't run bibtex pipe\n"); while () { $bibtex_had_errors = 1 if /^\(There.*error message(s)?\)$/; print STDERR $_; } close(BIBTXPIPE); &die_gracefully("$Pgm: BibTeX run had errors\n") if $? >> 8 || $bibtex_had_errors; } sub something_more_needed { # returns 1 or 0 if we need to run LaTeX # possibly preceded by bibtex and/or makeindex run # $Says_labels_changed was set by previous &run_latex... $BibTeX_run_needed = 0; $MakeIndex_run_needed = 0; if ( ! -f ($TeX_root . '.aux-prev')) { # this was the first run print STDERR "$Pgm: *** 'twas first run of LaTeX on $TeX_input\n" if $Verbose; # we need makeindex to run if a non-zero-sized .idx file exists # $MakeIndex_run_needed = 1 if -f "$TeX_root.idx" && -s "$TeX_root.idx"; # we need bibtex to run if there are \citations in the .aux file # &slurp_aux_file('aux'); $BibTeX_run_needed = 1 if $Bibliography_requested && -f "$Tmp_prefix/ltx-aux-cite.$$" && -s "$Tmp_prefix/ltx-aux-cite.$$"; } else { # ltx had been run before (.aux-prev/.idx-prev files exist) # slurp both .aux and .aux-prev files &slurp_aux_file('aux'); &slurp_aux_file('aux-prev'); local($tmp_pre) = "$Tmp_prefix/ltx"; if ((-s "$tmp_pre-.aux-cite.$$") # there are still \cite's in there && (system("cmp -s $tmp_pre-.aux-cite.$$ $tmp_pre-.aux-prev-cite.$$") >> 8)) { $BibTeX_run_needed = 1 if $Bibliography_requested; if ($Verbose) { system("$CONTEXT_DIFF $tmp_pre-.aux-prev-cite.$$ $tmp_pre-.aux-cite.$$"); } } if (-f "$TeX_root.idx") { $MakeIndex_run_needed = (system("cmp -s $TeX_root.idx $TeX_root.idx-prev") >> 8) ? 1 : 0; if ($MakeIndex_run_needed && $Verbose) { system("$CONTEXT_DIFF $TeX_root.idx-prev $TeX_root.idx"); } } } $Says_labels_changed || $BibTeX_run_needed || $MakeIndex_run_needed; } sub slurp_aux_file { local($ext) = @_; # copy all citations from slurpfile into $Tmp_prefix/ltx-$ext-cite.$$ open(SLURPF,"< $TeX_root.$ext") || &die_gracefully("$Pgm: Can't open $TeX_root.$ext for reading\n"); open(CITEF,"> $Tmp_prefix/ltx-$ext-cite.$$") || &die_gracefully("$Pgm: Can't open $Tmp_prefix/ltx-$ext-cite.$$ for writing\n"); while () { print CITEF $_ if /\\citation/; } close(CITEF); close(SLURPF); }