diff --git a/src/ChangeLog b/src/ChangeLog index 90ebe67e58..78a177a155 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,9 @@ +2001-02-02 Dekel Tsur + + * 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 * text.C (Backspace): Preserve the font when changing newline char diff --git a/src/LaTeX.C b/src/LaTeX.C index 86015ec716..2a70e096df 100644 --- a/src/LaTeX.C +++ b/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,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 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 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 const -LaTeX::scanAuxFiles(string const & file, DepTable & dep, bool insert) +vector const +LaTeX::scanAuxFiles(string const & file) { - vector result; - if (scanAuxFile(file, dep, insert)) { - result.push_back(file); - if (!insert) - return result; - } + vector 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 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 const aux_files = scanAuxFiles(aux, dep, true); - // Run bibtex on each of the aux files in - for (vector::const_iterator it = aux_files.begin(); - it != aux_files.end(); ++it) { + + for (vector::const_iterator it = bibtex_info.begin(); + it != bibtex_info.end(); ++it) { + for (set::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::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 const & bibtex_info) +{ + bool result = false; + for (vector::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); diff --git a/src/LaTeX.h b/src/LaTeX.h index 652369cae5..74e1317074 100644 --- a/src/LaTeX.h +++ b/src/LaTeX.h @@ -22,6 +22,7 @@ #include "LString.h" #include "DepTable.h" #include +#include #include @@ -61,6 +62,26 @@ private: Errors errors; }; +class Aux_Info { +public: + /// + Aux_Info() {} + /// + string aux_file; + /// + std::set citations; + /// + std::set databases; + /// + std::set 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 const scanAuxFiles(string const &); + /// - std::vector 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 const &); + + /// + bool runBibTeX(vector const &); /// void deleteFilesOnError() const;