Fix run of index processor in the export chain (#2696)

It does not make sense to issue the index processor before the
pagination is fixed. Particularly, if (classic) BibTeX is run,
we need one or more extra LaTeX runs after that before issuing
the index processor, since the citation labels and references are
only expanded then, which might change pagination. As a consequence,
we ended up in wrong index references.

This fixes a 16 year old bug report.
This commit is contained in:
Juergen Spitzmueller 2022-02-16 12:03:38 +01:00
parent 9729b22d9e
commit 8cb7fb26d7

View File

@ -306,63 +306,14 @@ int LaTeX::run(TeXErrors & terr)
head.update();
// 1
// At this point we must run external programs if needed.
// makeindex will be run if a .idx file changed or was generated.
// And if there were undefined citations or changes in references
// the .aux file is checked for signs of bibtex. Bibtex is then run
// if needed.
// memoir (at least) writes an empty *idx file in the first place.
// A second latex run is needed.
FileName const idxfile(changeExtension(file.absFileName(), ".idx"));
rerun = idxfile.exists() && idxfile.isFileEmpty();
// run makeindex
if (head.haschanged(idxfile)) {
// no checks for now
LYXERR(Debug::LATEX, "Running MakeIndex.");
message(_("Running Index Processor."));
// onlyFileName() is needed for cygwin
int const ret =
runMakeIndex(onlyFileName(idxfile.absFileName()), runparams);
if (ret == Systemcall::KILLED || ret == Systemcall::TIMEOUT)
return ret;
FileName const ilgfile(changeExtension(file.absFileName(), ".ilg"));
if (ilgfile.exists())
iscanres = scanIlgFile(terr);
rerun = true;
}
FileName const nlofile(changeExtension(file.absFileName(), ".nlo"));
// If all nomencl entries are removed, nomencl writes an empty nlo file.
// DepTable::hasChanged() returns false in this case, since it does not
// distinguish empty files from non-existing files. This is why we need
// the extra checks here (to trigger a rerun). Cf. discussions in #8905.
// FIXME: Sort out the real problem in DepTable.
if (head.haschanged(nlofile) || (nlofile.exists() && nlofile.isFileEmpty())) {
int const ret = runMakeIndexNomencl(file, ".nlo", ".nls");
if (ret == Systemcall::KILLED || ret == Systemcall::TIMEOUT)
return ret;
rerun = true;
}
FileName const glofile(changeExtension(file.absFileName(), ".glo"));
if (head.haschanged(glofile)) {
int const ret = runMakeIndexNomencl(file, ".glo", ".gls");
if (ret)
return ret;
rerun = true;
}
// check if we're using biber instead of bibtex
// At this point we must run the bibliography processor if needed.
// First, check if we're using biber instead of bibtex --
// biber writes no info to the aux file, so we just check
// if a bcf file exists (and if it was updated)
// if a bcf file exists (and if it was updated).
FileName const bcffile(changeExtension(file.absFileName(), ".bcf"));
biber |= head.exist(bcffile);
// run bibtex
// if (scanres & UNDEF_CIT || scanres & RERUN || run_bibtex)
// If (scanres & UNDEF_CIT || scanres & RERUN || run_bibtex)
// We do not run bibtex/biber on an "includeall" call (whose purpose is
// to set up/maintain counters and references for includeonly) since
// (1) bibliographic references will be updated on the subsequent includeonly run
@ -373,8 +324,8 @@ int LaTeX::run(TeXErrors & terr)
// "\bibdata" and/or "\bibstyle". If one of those
// tags is found -> run bibtex and set rerun = true;
// no checks for now
LYXERR(Debug::LATEX, "Running BibTeX.");
message(_("Running BibTeX."));
LYXERR(Debug::LATEX, "Running Bibliography Processor.");
message(_("Running Bibliography Processor."));
updateBibtexDependencies(head, bibtex_info);
int exit_code;
rerun |= runBibTeX(bibtex_info, runparams, exit_code);
@ -391,7 +342,7 @@ int LaTeX::run(TeXErrors & terr)
}
// 2
// we know on this point that latex has been run once (or we just
// We know on this point that latex has been run once (or we just
// returned) and the question now is to decide if we need to run
// it any more. This is done by asking if any of the files in the
// dependency file has changed. (remember that the checksum for
@ -421,7 +372,7 @@ int LaTeX::run(TeXErrors & terr)
}
// 3
// rerun bibtex?
// Rerun bibliography processor?
// Complex bibliography packages such as Biblatex require
// an additional bibtex cycle sometimes.
// We do not run bibtex/biber on an "includeall" call (whose purpose is
@ -434,8 +385,8 @@ int LaTeX::run(TeXErrors & terr)
// "\bibdata" and/or "\bibstyle". If one of those
// tags is found -> run bibtex and set rerun = true;
// no checks for now
LYXERR(Debug::LATEX, "Running BibTeX.");
message(_("Running BibTeX."));
LYXERR(Debug::LATEX, "Re-Running Bibliography Processor.");
message(_("Re-Running Bibliography Processor."));
updateBibtexDependencies(head, bibtex_info);
int exit_code;
rerun |= runBibTeX(bibtex_info, runparams, exit_code);
@ -447,21 +398,38 @@ int LaTeX::run(TeXErrors & terr)
}
// 4
// The inclusion of files generated by external programs such as
// makeindex or bibtex might have done changes to pagenumbering,
// etc. And because of this we must run the external programs
// again to make sure everything is redone correctly.
// Also there should be no need to run the external programs any
// more after this.
// After the bibliography was processed, we need more passes of LaTeX
// in order to resolve the citations. We need to do this before the index
// is being generated (since we need the correct pagination, see #2696).
// Also, memoir (at least) writes an empty *idx file in the first place.
// A further latex run is needed in that case as well.
FileName const idxfile(changeExtension(file.absFileName(), ".idx"));
if (run_bibtex || (idxfile.exists() && idxfile.isFileEmpty())) {
while ((head.sumchange() || rerun || (scanres & RERUN))
&& count < MAX_RUN) {
// Yes rerun until message goes away, or until
// MAX_RUNS are reached.
rerun = false;
++count;
LYXERR(Debug::LATEX, "Run #" << count);
message(runMessage(count));
startscript();
scanres = scanLogFile(terr);
// keep this updated
head.update();
}
}
// run makeindex if the <file>.idx has changed or was generated.
if (head.haschanged(idxfile)) {
// 5
// Now that we have final pagination, run the index and nomencl processors
if (idxfile.exists()) {
// no checks for now
LYXERR(Debug::LATEX, "Running MakeIndex.");
LYXERR(Debug::LATEX, "Running Index Processor.");
message(_("Running Index Processor."));
// onlyFileName() is needed for cygwin
int const ret = runMakeIndex(onlyFileName(changeExtension(
file.absFileName(), ".idx")), runparams);
int const ret =
runMakeIndex(onlyFileName(idxfile.absFileName()), runparams);
if (ret == Systemcall::KILLED || ret == Systemcall::TIMEOUT)
return ret;
FileName const ilgfile(changeExtension(file.absFileName(), ".ilg"));
@ -469,15 +437,28 @@ int LaTeX::run(TeXErrors & terr)
iscanres = scanIlgFile(terr);
rerun = true;
}
FileName const nlofile(changeExtension(file.absFileName(), ".nlo"));
// If all nomencl entries are removed, nomencl writes an empty nlo file.
// DepTable::hasChanged() returns false in this case, since it does not
// distinguish empty files from non-existing files. This is why we need
// the extra checks here (to trigger a rerun). Cf. discussions in #8905.
// FIXME: Sort out the real problem in DepTable.
if (head.haschanged(nlofile) || (nlofile.exists() && nlofile.isFileEmpty())) {
int const ret = runMakeIndexNomencl(file, ".nlo", ".nls");
if (ret == Systemcall::KILLED || ret == Systemcall::TIMEOUT)
return ret;
rerun = true;
}
FileName const glofile(changeExtension(file.absFileName(), ".glo"));
if (head.haschanged(glofile)) {
int const ret = runMakeIndexNomencl(file, ".glo", ".gls");
if (ret)
return ret;
rerun = true;
}
// MSVC complains that bool |= int is unsafe. Not sure why.
if (head.haschanged(nlofile))
rerun |= (runMakeIndexNomencl(file, ".nlo", ".nls") != 0);
if (head.haschanged(glofile))
rerun |= (runMakeIndexNomencl(file, ".glo", ".gls") != 0);
// 5
// we will only run latex more if the log file asks for it.
// 6
// We will re-run latex if the log file asks for it,
// or if the sumchange() is true.
// -> rerun asked for:
// run latex and