mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-12-22 21:21:32 +00:00
- 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:
parent
360aadd00b
commit
db2a042267
@ -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
|
||||
|
244
src/LaTeX.C
244
src/LaTeX.C
@ -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,55 +140,57 @@ 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
|
||||
}
|
||||
|
||||
}
|
||||
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
|
||||
@ -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);
|
||||
|
41
src/LaTeX.h
41
src/LaTeX.h
@ -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<string> const
|
||||
scanAuxFiles(string const &, DepTable &, bool);
|
||||
///
|
||||
bool scanAuxFile(string const &, DepTable &, bool);
|
||||
std::vector<Aux_Info> const scanAuxFiles(string const &);
|
||||
|
||||
///
|
||||
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;
|
||||
|
Loading…
Reference in New Issue
Block a user