X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FLaTeX.cpp;h=3b06c8e34c0ed936149331ba70ea71999486d777;hb=ab8a290040dc28f39ebb230ab4b8a43467df0906;hp=597efefb7cedecc5aa2d1f2754d76d06a860156f;hpb=f434f947dd82a4093c027408ff9698b27b2a77d3;p=lyx.git diff --git a/src/LaTeX.cpp b/src/LaTeX.cpp index 597efefb7c..3b06c8e34c 100644 --- a/src/LaTeX.cpp +++ b/src/LaTeX.cpp @@ -32,6 +32,7 @@ #include "support/regex.h" #include +#include using namespace std; @@ -64,9 +65,10 @@ docstring runMessage(unsigned int count) */ void TeXErrors::insertError(int line, docstring const & error_desc, - docstring const & error_text) + docstring const & error_text, + string const & child_name) { - Error newerr(line, error_desc, error_text); + Error newerr(line, error_desc, error_text, child_name); errors.push_back(newerr); } @@ -91,8 +93,8 @@ bool operator!=(AuxInfo const & a, AuxInfo const & o) */ LaTeX::LaTeX(string const & latex, OutputParams const & rp, - FileName const & f) - : cmd(latex), file(f), runparams(rp) + FileName const & f, string const & p) + : cmd(latex), file(f), path(p), runparams(rp) { num_errors = 0; if (prefixIs(cmd, "pdf")) { // Do we use pdflatex ? @@ -207,8 +209,7 @@ int LaTeX::run(TeXErrors & terr) LYXERR(Debug::DEPEND, "Dependency file has changed"); } - if (head.extchanged(".bib") || head.extchanged(".bst") - || head.extchanged(".bcf")) + if (head.extchanged(".bib") || head.extchanged(".bst")) run_bibtex = true; } else LYXERR(Debug::DEPEND, @@ -276,9 +277,9 @@ int LaTeX::run(TeXErrors & terr) // 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, above, if it was updated) + // if a bcf file exists (and if it was updated) FileName const bcffile(changeExtension(file.absFileName(), ".bcf")); - bool const biber = bcffile.exists(); + biber |= head.exist(bcffile); // run bibtex // if (scanres & UNDEF_CIT || scanres & RERUN || run_bibtex) @@ -290,7 +291,15 @@ int LaTeX::run(TeXErrors & terr) LYXERR(Debug::LATEX, "Running BibTeX."); message(_("Running BibTeX.")); updateBibtexDependencies(head, bibtex_info); - rerun |= runBibTeX(bibtex_info, runparams, biber); + rerun |= runBibTeX(bibtex_info, runparams); + if (biber) { + // since biber writes no info to the aux file, we have + // to parse the blg file (which only exists after biber + // was first issued) + FileName const blgfile(changeExtension(file.absFileName(), ".blg")); + if (blgfile.exists()) + scanBlgFile(head); + } } 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 @@ -342,7 +351,7 @@ int LaTeX::run(TeXErrors & terr) LYXERR(Debug::LATEX, "Running BibTeX."); message(_("Running BibTeX.")); updateBibtexDependencies(head, bibtex_info); - rerun |= runBibTeX(bibtex_info, runparams, biber); + rerun |= runBibTeX(bibtex_info, runparams); } // 4 @@ -412,7 +421,7 @@ int LaTeX::startscript() + quoteName(onlyFileName(file.toFilesystemEncoding())) + " > " + os::nulldev(); Systemcall one; - return one.startscript(Systemcall::Wait, tmp); + return one.startscript(Systemcall::Wait, tmp, path); } @@ -439,7 +448,7 @@ bool LaTeX::runMakeIndex(string const & f, OutputParams const & runparams, tmp += quoteName(f); tmp += params; Systemcall one; - one.startscript(Systemcall::Wait, tmp); + one.startscript(Systemcall::Wait, tmp, path); return true; } @@ -455,7 +464,7 @@ bool LaTeX::runMakeIndexNomencl(FileName const & file, tmp += " -o " + onlyFileName(changeExtension(file.toFilesystemEncoding(), nls)); Systemcall one; - one.startscript(Systemcall::Wait, tmp); + one.startscript(Systemcall::Wait, tmp, path); return true; } @@ -565,11 +574,17 @@ void LaTeX::updateBibtexDependencies(DepTable & dep, dep.insert(file, true); } } + + // biber writes nothing into the aux file. + // Instead, we have to scan the blg file + if (biber) { + scanBlgFile(dep); + } } bool LaTeX::runBibTeX(vector const & bibtex_info, - OutputParams const & runparams, bool biber) + OutputParams const & runparams) { bool result = false; for (vector::const_iterator it = bibtex_info.begin(); @@ -588,7 +603,7 @@ bool LaTeX::runBibTeX(vector const & bibtex_info, tmp += quoteName(onlyFileName(removeExtension( it->aux_file.absFileName()))); Systemcall one; - one.startscript(Systemcall::Wait, tmp); + one.startscript(Systemcall::Wait, tmp, path); } // Return whether bibtex was run return result; @@ -607,9 +622,13 @@ int LaTeX::scanLogFile(TeXErrors & terr) ifstream ifs(fn.toFilesystemEncoding().c_str()); bool fle_style = false; static regex file_line_error(".+\\.\\D+:[0-9]+: (.+)"); + static regex child_file(".*([0-9]+[A-Za-z]*_.+\\.tex).*"); // Flag for 'File ended while scanning' message. // We need to wait for subsequent processing. string wait_for_error; + string child_name; + int pnest = 0; + stack > child; string token; while (getline(ifs, token)) { @@ -626,6 +645,29 @@ int LaTeX::scanLogFile(TeXErrors & terr) if (token.empty()) continue; + // Track child documents + for (size_t i = 0; i < token.length(); ++i) { + if (token[i] == '(') { + ++pnest; + size_t j = token.find('(', i + 1); + size_t len = j == string::npos + ? token.substr(i + 1).length() + : j - i - 1; + if (regex_match(token.substr(i + 1, len), + sub, child_file)) { + string const name = sub.str(1); + child.push(make_pair(name, pnest)); + i += len; + } + } else if (token[i] == ')') { + if (!child.empty() + && child.top().second == pnest) + child.pop(); + --pnest; + } + } + child_name = child.empty() ? empty_string() : child.top().first; + if (contains(token, "file:line:error style messages enabled")) fle_style = true; @@ -665,6 +707,9 @@ int LaTeX::scanLogFile(TeXErrors & terr) } } else if (contains(token, "run BibTeX")) { retval |= UNDEF_CIT; + } else if (contains(token, "run Biber")) { + retval |= UNDEF_CIT; + biber = true; } else if (contains(token, "Rerun LaTeX") || contains(token, "Please rerun LaTeX") || contains(token, "Rerun to get")) { @@ -702,11 +747,24 @@ int LaTeX::scanLogFile(TeXErrors & terr) if (contains(token, "LaTeX Error:")) retval |= LATEX_ERROR; - // bug 6445. At this point its not clear we finish with error. if (prefixIs(token, "! File ended while scanning")){ - wait_for_error = desc; - continue; + if (prefixIs(token, "! File ended while scanning use of \\Hy@setref@link.")){ + // bug 7344. We must rerun LaTeX if hyperref has been toggled. + retval |= ERROR_RERUN; + LYXERR(Debug::LATEX, "Force rerun."); + } else { + // bug 6445. At this point its not clear we finish with error. + wait_for_error = desc; + continue; + } } + + if (prefixIs(token, "! Paragraph ended before \\Hy@setref@link was complete.")){ + // bug 7344. We must rerun LaTeX if hyperref has been toggled. + retval |= ERROR_RERUN; + LYXERR(Debug::LATEX, "Force rerun."); + } + if (!wait_for_error.empty() && prefixIs(token, "! Emergency stop.")){ retval |= LATEX_ERROR; string errstr; @@ -715,6 +773,7 @@ int LaTeX::scanLogFile(TeXErrors & terr) do { if (!getline(ifs, tmp)) break; + tmp = rtrim(tmp, "\r"); errstr += "\n" + tmp; if (++count > 5) break; @@ -722,7 +781,8 @@ int LaTeX::scanLogFile(TeXErrors & terr) terr.insertError(0, from_local8bit("Emergency stop"), - from_local8bit(errstr)); + from_local8bit(errstr), + child_name); } // get the next line @@ -731,6 +791,7 @@ int LaTeX::scanLogFile(TeXErrors & terr) do { if (!getline(ifs, tmp)) break; + tmp = rtrim(tmp, "\r"); if (++count > 10) break; } while (!prefixIs(tmp, "l.")); @@ -749,6 +810,7 @@ int LaTeX::scanLogFile(TeXErrors & terr) string errstr(tmp, tmp.find(' ')); errstr += '\n'; getline(ifs, tmp); + tmp = rtrim(tmp, "\r"); while (!contains(errstr, "l.") && !tmp.empty() && !prefixIs(tmp, "! ") @@ -756,6 +818,7 @@ int LaTeX::scanLogFile(TeXErrors & terr) errstr += tmp; errstr += "\n"; getline(ifs, tmp); + tmp = rtrim(tmp, "\r"); } LYXERR(Debug::LATEX, "line: " << line << '\n' << "Desc: " << desc << '\n' << "Text: " << errstr); @@ -776,7 +839,8 @@ int LaTeX::scanLogFile(TeXErrors & terr) // assume here it can be wrong. terr.insertError(line, from_local8bit(desc), - from_local8bit(errstr)); + from_local8bit(errstr), + child_name); ++num_errors; } } @@ -802,7 +866,8 @@ int LaTeX::scanLogFile(TeXErrors & terr) retval |= ERRORS; terr.insertError(0, from_local8bit("pdfTeX Error"), - from_local8bit(token)); + from_local8bit(token), + child_name); } } } @@ -983,6 +1048,10 @@ void LaTeX::deplog(DepTable & head) continue; } + // FIXME UNICODE: We assume that the file names in the log + // file are in the file system encoding. + token = to_utf8(from_filesystem8bit(token)); + // Sometimes, filenames are broken across lines. // We care for that and save suspicious lines. // Here we exclude some cases where we are sure @@ -1012,10 +1081,6 @@ void LaTeX::deplog(DepTable & head) smatch sub; - // FIXME UNICODE: We assume that the file names in the log - // file are in the file system encoding. - token = to_utf8(from_filesystem8bit(token)); - // (1) "File: file.ext" if (regex_match(token, sub, reg1)) { // check for dot @@ -1124,4 +1189,30 @@ void LaTeX::deplog(DepTable & head) } +void LaTeX::scanBlgFile(DepTable & dep) +{ + FileName const blg_file(changeExtension(file.absFileName(), "blg")); + LYXERR(Debug::LATEX, "Scanning blg file: " << blg_file); + + ifstream ifs(blg_file.toFilesystemEncoding().c_str()); + string token; + static regex const reg1(".*Found bibtex data file '([^']+).*"); + + while (getline(ifs, token)) { + token = rtrim(token, "\r"); + smatch sub; + // FIXME UNICODE: We assume that citation keys and filenames + // in the aux file are in the file system encoding. + token = to_utf8(from_filesystem8bit(token)); + if (regex_match(token, sub, reg1)) { + string data = sub.str(1); + if (!data.empty()) { + LYXERR(Debug::LATEX, "Found bib file: " << data); + handleFoundFile(data, dep); + } + } + } +} + + } // namespace lyx