- Fix the bug that bibtex was not always run when needed.

- Fix the babel error (after changing the language of the document) bug.


git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@1444 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
Dekel Tsur 2001-02-03 12:27:21 +00:00
parent 360aadd00b
commit db2a042267
3 changed files with 165 additions and 132 deletions

View File

@ -1,3 +1,9 @@
2001-02-02 Dekel Tsur <dekelts@tau.ac.il>
* LaTeX.C (scanAuxFile): A rewrite of this method. It now returns
all the citation/databases/styles in the auxilary file.
(run): Rerun latex if there was a babel language error.
2001-02-01 Dekel Tsur <dekelts@tau.ac.il> 2001-02-01 Dekel Tsur <dekelts@tau.ac.il>
* text.C (Backspace): Preserve the font when changing newline char * text.C (Backspace): Preserve the font when changing newline char

View File

@ -37,6 +37,7 @@ using std::ifstream;
using std::getline; using std::getline;
using std::endl; using std::endl;
using std::vector; using std::vector;
using std::set;
// TODO: in no particular order // TODO: in no particular order
// - get rid of the extern BufferList and the call to // - get rid of the extern BufferList and the call to
@ -139,55 +140,57 @@ int LaTeX::run(TeXErrors & terr, MiniBuffer * minib)
// run latex once (we need to run latex once anyway) and // run latex once (we need to run latex once anyway) and
// remake the dependency file. // remake the dependency file.
// //
FileInfo fi(depfile); FileInfo fi(depfile);
bool had_depfile = fi.exist();
bool run_bibtex = false; bool run_bibtex = false;
if (fi.exist()) { string aux_file = OnlyFilename(ChangeExtension(file, "aux"));
if (had_depfile) {
lyxerr[Debug::DEPEND] << "Dependency file exists" << endl;
// Read the dep file: // Read the dep file:
head.read(depfile); head.read(depfile);
// Update the checksums // Update the checksums
head.update(); head.update();
if (!head.sumchange()) {
lyxerr[Debug::DEPEND] << "Dependency file exists" << endl;
if (head.sumchange()) {
++count;
lyxerr[Debug::DEPEND]
<< "Dependency file has changed" << endl;
lyxerr[Debug::LATEX]
<< "Run #" << count << endl;
WriteStatus(minib,
string(_("LaTeX run number ")) + tostr(count));
this->operator()();
scanres = scanLogFile(terr);
if (scanres & LaTeX::ERRORS) {
deleteFilesOnError();
return scanres; // return on error
}
run_bibtex = scanAux(head);
if (run_bibtex)
lyxerr[Debug::DEPEND]
<< "Bibtex demands rerun" << endl;
} else {
lyxerr[Debug::DEPEND] << "return no_change" << endl; lyxerr[Debug::DEPEND] << "return no_change" << endl;
return LaTeX::NO_CHANGE; return LaTeX::NO_CHANGE;
} }
} else { lyxerr[Debug::DEPEND]
++count; << "Dependency file has changed" << endl;
if (head.extchanged(".bib") || head.extchanged(".bst"))
run_bibtex = true;
} else
lyxerr[Debug::DEPEND] lyxerr[Debug::DEPEND]
<< "Dependency file does not exist" << endl; << "Dependency file does not exist" << endl;
lyxerr[Debug::LATEX] /// We scan the aux file even when had_depfile = false,
<< "Run #" << count << endl; /// because we can run pdflatex on the file after running latex on it,
head.insert(file, true); /// in which case we will not need to run bibtex again.
WriteStatus(minib, vector<Aux_Info> bibtex_info_old;
string(_("LaTeX run number ")) + tostr(count)); if (!run_bibtex)
bibtex_info_old = scanAuxFiles(aux_file);
++count;
lyxerr[Debug::LATEX] << "Run #" << count << endl;
WriteStatus(minib, string(_("LaTeX run number ")) + tostr(count));
this->operator()(); this->operator()();
scanres = scanLogFile(terr); scanres = scanLogFile(terr);
if (scanres & LaTeX::ERROR_RERUN) {
lyxerr[Debug::LATEX] << "Rerunning LaTeX" << endl;
this->operator()();
scanres = scanLogFile(terr);
}
if (scanres & LaTeX::ERRORS) { if (scanres & LaTeX::ERRORS) {
deleteFilesOnError(); deleteFilesOnError();
return scanres; // return on error return scanres; // return on error
} }
} vector<Aux_Info> const bibtex_info = scanAuxFiles(aux_file);
if (!run_bibtex && bibtex_info_old != bibtex_info)
run_bibtex = true;
// update the dependencies. // update the dependencies.
deplog(head); // reads the latex log deplog(head); // reads the latex log
@ -218,8 +221,13 @@ int LaTeX::run(TeXErrors & terr, MiniBuffer * minib)
// no checks for now // no checks for now
lyxerr[Debug::LATEX] << "Running BibTeX." << endl; lyxerr[Debug::LATEX] << "Running BibTeX." << endl;
WriteStatus(minib, _("Running BibTeX.")); WriteStatus(minib, _("Running BibTeX."));
rerun = runBibTeX(head); updateBibtexDependencies(head, bibtex_info);
} rerun |= runBibTeX(bibtex_info);
} else if (!had_depfile)
/// If we run pdflatex on the file after running latex on it,
/// then we do not need to run bibtex, but we do need to
/// insert the .bib and .bst files into the .dep-pdf file.
updateBibtexDependencies(head, bibtex_info);
// 1 // 1
// 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
@ -337,146 +345,136 @@ bool LaTeX::runMakeIndex(string const & f)
return true; return true;
} }
// scanAux may return a wrong result if there are more than two bibliographies,
// and after LaTeX-ing the file, the user changes the order of the bibliography
// and run LaTeX again. However, in this case, bibtopic prints a warning message which
// is caught by scanLogFile.
bool LaTeX::scanAux(DepTable & dep)
{
// if any of the bib file has changed we don't have to
// check the .aux file.
if (dep.extchanged(".bib")
|| dep.extchanged(".bst")) return true;
string aux = OnlyFilename(ChangeExtension(file, ".aux")); vector<Aux_Info> const
return !scanAuxFiles(aux, dep, false).empty(); LaTeX::scanAuxFiles(string const & file)
}
vector<string> const
LaTeX::scanAuxFiles(string const & file, DepTable & dep, bool insert)
{ {
vector<string> result; vector<Aux_Info> result;
if (scanAuxFile(file, dep, insert)) {
result.push_back(file); result.push_back(scanAuxFile(file));
if (!insert)
return result;
}
for (int i = 1; i < 1000; ++i) { for (int i = 1; i < 1000; ++i) {
string file2 = ChangeExtension(file, "") + "." + tostr(i) string file2 = ChangeExtension(file, "") + "." + tostr(i)
+ ".aux"; + ".aux";
FileInfo fi(file2); FileInfo fi(file2);
if (!fi.exist()) if (!fi.exist())
return result; break;
if (scanAuxFile(file2, dep, insert)) { result.push_back(scanAuxFile(file2));
result.push_back(file2);
if (!insert)
return result;
}
} }
return result; return result;
} }
// If insert = true, then scanAuxFile returns true iff the aux file contains Aux_Info const LaTeX::scanAuxFile(string const & file)
// a bibtex database (i.e. a \bibdata command), or it inputs another auxfile which {
// contains a bibtex database. Aux_Info result;
// Also the dep is updated for all bibtex databases and bibtex styles in the aux result.aux_file = file;
// file. scanAuxFile(file, result);
// Ideally, scanAuxFile should return true iff one of the bibtex database/styles has return result;
// changes from previous run, or a new bibtex database/styles was added to the aux file. }
// However, it is probably not worth the effort.
//
// If insert = false, then scanAuxFile returns true iff the aux file contains a void LaTeX::scanAuxFile(string const & file, Aux_Info & aux_info)
// bibtex database or a bibtex style that do not appear in dep.
//
bool LaTeX::scanAuxFile(string const & file, DepTable & dep, bool insert)
{ {
lyxerr[Debug::LATEX] << "Scanning aux file: " << file << endl; lyxerr[Debug::LATEX] << "Scanning aux file: " << file << endl;
ifstream ifs(file.c_str()); ifstream ifs(file.c_str());
string token; string token;
LRegex reg1("\\\\bibdata\\{([^}]+)\\}"); LRegex reg1("\\\\citation\\{([^}]+)\\}");
LRegex reg2("\\\\bibstyle\\{([^}]+)\\}"); LRegex reg2("\\\\bibdata\\{([^}]+)\\}");
LRegex reg3("\\\\@input\\{([^}]+)\\}"); LRegex reg3("\\\\bibstyle\\{([^}]+)\\}");
bool result = false; LRegex reg4("\\\\@input\\{([^}]+)\\}");
while (getline(ifs, token)) { while (getline(ifs, token)) {
if (reg1.exact_match(token)) { if (reg1.exact_match(token)) {
if (insert)
result = true;
LRegex::SubMatches const & sub = reg1.exec(token); LRegex::SubMatches const & sub = reg1.exec(token);
string data = LSubstring(token, sub[1].first,
sub[1].second);
while (!data.empty()) {
string citation;
data = split(data, citation, ',');
lyxerr[Debug::LATEX] << "Citation: "
<< citation << endl;
aux_info.citations.insert(citation);
}
} else if (reg2.exact_match(token)) {
LRegex::SubMatches const & sub = reg2.exec(token);
string data = LSubstring(token, sub[1].first, string data = LSubstring(token, sub[1].first,
sub[1].second); sub[1].second);
// data is now all the bib files separated by ',' // data is now all the bib files separated by ','
// get them one by one and pass them to the helper // get them one by one and pass them to the helper
while (!data.empty()) { while (!data.empty()) {
string l; string database;
data = split(data, l, ','); data = split(data, database, ',');
string full_l = database = ChangeExtension(database, "bib");
findtexfile(ChangeExtension(l, "bib"),
"bib");
lyxerr[Debug::LATEX] << "Bibtex database: `" lyxerr[Debug::LATEX] << "Bibtex database: `"
<< full_l << "'" << endl; << database << "'" << endl;
if (!full_l.empty()) { aux_info.databases.insert(database);
if (insert)
// add full_l to the dep file.
dep.insert(full_l, true);
else
if (!dep.exist(full_l))
return true;
} }
} } else if (reg3.exact_match(token)) {
} else if (reg2.exact_match(token)) { LRegex::SubMatches const & sub = reg3.exec(token);
LRegex::SubMatches const & sub = reg2.exec(token);
string style = LSubstring(token, sub[1].first, string style = LSubstring(token, sub[1].first,
sub[1].second); sub[1].second);
// token is now the style file // token is now the style file
// pass it to the helper // pass it to the helper
string full_l = style = ChangeExtension(style, "bst");
findtexfile(ChangeExtension(style, "bst"),
"bst");
lyxerr[Debug::LATEX] << "Bibtex style: `" lyxerr[Debug::LATEX] << "Bibtex style: `"
<< full_l << "'" << endl; << style << "'" << endl;
if (!full_l.empty()) { aux_info.styles.insert(style);
if (insert) } else if (reg4.exact_match(token)) {
// add full_l to the dep file. LRegex::SubMatches const & sub = reg4.exec(token);
dep.insert(full_l, true);
else
if (!dep.exist(full_l))
return true;
}
} else if (reg3.exact_match(token)) {
LRegex::SubMatches const & sub = reg3.exec(token);
string file2 = LSubstring(token, sub[1].first, string file2 = LSubstring(token, sub[1].first,
sub[1].second); sub[1].second);
result |= scanAuxFile(file2, dep, insert); scanAuxFile(file2, aux_info);
if (result && !insert)
return true;
} }
} }
return result;
} }
bool LaTeX::runBibTeX(DepTable & dep) void LaTeX::updateBibtexDependencies(DepTable & dep,
vector<Aux_Info> const & bibtex_info)
{ {
// Since a run of Bibtex mandates more latex runs it is ok to // Since a run of Bibtex mandates more latex runs it is ok to
// remove all ".bib" and ".bst" files, it is also required to // remove all ".bib" and ".bst" files.
// discover style and database changes.
dep.remove_files_with_extension(".bib"); dep.remove_files_with_extension(".bib");
dep.remove_files_with_extension(".bst"); dep.remove_files_with_extension(".bst");
string aux = OnlyFilename(ChangeExtension(file, ".aux")); string aux = OnlyFilename(ChangeExtension(file, ".aux"));
vector<string> const aux_files = scanAuxFiles(aux, dep, true);
// Run bibtex on each of the aux files in for (vector<Aux_Info>::const_iterator it = bibtex_info.begin();
for (vector<string>::const_iterator it = aux_files.begin(); it != bibtex_info.end(); ++it) {
it != aux_files.end(); ++it) { for (set<string>::const_iterator it2 = it->databases.begin();
it2 != it->databases.end(); ++it2) {
string file = findtexfile(*it2, "bib");
if (!file.empty())
dep.insert(file, true);
}
for (set<string>::const_iterator it2 = it->styles.begin();
it2 != it->styles.end(); ++it2) {
string file = findtexfile(*it2, "bst");
if (!file.empty())
dep.insert(file, true);
}
}
}
bool LaTeX::runBibTeX(vector<Aux_Info> const & bibtex_info)
{
bool result = false;
for (vector<Aux_Info>::const_iterator it = bibtex_info.begin();
it != bibtex_info.end(); ++it) {
if (it->databases.empty())
continue;
result = true;
string tmp = "bibtex "; string tmp = "bibtex ";
tmp += OnlyFilename(ChangeExtension(*it, string())); tmp += OnlyFilename(ChangeExtension(it->aux_file, string()));
Systemcalls one; Systemcalls one;
one.startscript(Systemcalls::System, tmp); one.startscript(Systemcalls::System, tmp);
} }
// Return whether bibtex was run // Return whether bibtex was run
return !aux_files.empty(); return result;
} }
@ -546,6 +544,8 @@ int LaTeX::scanLogFile(TeXErrors & terr)
if (prefixIs(tmp, "l.")) { if (prefixIs(tmp, "l.")) {
// we have a latex error // we have a latex error
retval |= TEX_ERROR; retval |= TEX_ERROR;
if (contains(desc, "Package babel Error: You haven't defined the language"))
retval |= ERROR_RERUN;
// get the line number: // get the line number:
int line = 0; int line = 0;
sscanf(tmp.c_str(), "l.%d", &line); sscanf(tmp.c_str(), "l.%d", &line);

View File

@ -22,6 +22,7 @@
#include "LString.h" #include "LString.h"
#include "DepTable.h" #include "DepTable.h"
#include <vector> #include <vector>
#include <set>
#include <boost/utility.hpp> #include <boost/utility.hpp>
@ -61,6 +62,26 @@ private:
Errors errors; Errors errors;
}; };
class Aux_Info {
public:
///
Aux_Info() {}
///
string aux_file;
///
std::set<string> citations;
///
std::set<string> databases;
///
std::set<string> styles;
///
operator==(Aux_Info const & o) const {
return aux_file == o.aux_file &&
citations == o.citations &&
databases == o.databases &&
styles == o.styles;
}
};
/// ///
class LaTeX : public noncopyable { class LaTeX : public noncopyable {
@ -100,6 +121,8 @@ public:
/// ///
TOO_MANY_ERRORS = 4096, TOO_MANY_ERRORS = 4096,
/// ///
ERROR_RERUN = 8192,
///
ERRORS = TEX_ERROR + LATEX_ERROR, ERRORS = TEX_ERROR + LATEX_ERROR,
/// ///
WARNINGS = TEX_WARNING + LATEX_WARNING + PACKAGE_WARNING WARNINGS = TEX_WARNING + LATEX_WARNING + PACKAGE_WARNING
@ -138,15 +161,19 @@ protected:
bool runMakeIndex(string const &); bool runMakeIndex(string const &);
/// ///
bool scanAux(DepTable &); std::vector<Aux_Info> const scanAuxFiles(string const &);
///
std::vector<string> const
scanAuxFiles(string const &, DepTable &, bool);
///
bool scanAuxFile(string const &, DepTable &, bool);
/// ///
bool runBibTeX(DepTable &); Aux_Info const scanAuxFile(string const &);
///
void scanAuxFile(string const &, Aux_Info &);
///
void updateBibtexDependencies(DepTable &, vector<Aux_Info> const &);
///
bool runBibTeX(vector<Aux_Info> const &);
/// ///
void deleteFilesOnError() const; void deleteFilesOnError() const;