- 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>
* text.C (Backspace): Preserve the font when changing newline char

View File

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

View File

@ -22,6 +22,7 @@
#include "LString.h"
#include "DepTable.h"
#include <vector>
#include <set>
#include <boost/utility.hpp>
@ -61,6 +62,26 @@ private:
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 {
@ -100,6 +121,8 @@ public:
///
TOO_MANY_ERRORS = 4096,
///
ERROR_RERUN = 8192,
///
ERRORS = TEX_ERROR + LATEX_ERROR,
///
WARNINGS = TEX_WARNING + LATEX_WARNING + PACKAGE_WARNING
@ -138,15 +161,19 @@ protected:
bool runMakeIndex(string const &);
///
bool scanAux(DepTable &);
std::vector<Aux_Info> const scanAuxFiles(string const &);
///
std::vector<string> const
scanAuxFiles(string const &, DepTable &, bool);
Aux_Info const scanAuxFile(string const &);
///
bool scanAuxFile(string const &, DepTable &, bool);
void scanAuxFile(string const &, Aux_Info &);
///
bool runBibTeX(DepTable &);
void updateBibtexDependencies(DepTable &, vector<Aux_Info> const &);
///
bool runBibTeX(vector<Aux_Info> const &);
///
void deleteFilesOnError() const;