X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FLaTeX.cpp;h=04a86f795a95cd6de5b36fc98e4e3cd03a22662d;hb=c48091f33a773732fa6c789927e5833e44108d9d;hp=47c2201a51bea2d172a5cabfb1911cb20d358d7c;hpb=c5200a848e9c6ea2507fe78b07413557eaffc3bb;p=lyx.git diff --git a/src/LaTeX.cpp b/src/LaTeX.cpp index 47c2201a51..04a86f795a 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 ? @@ -122,6 +124,10 @@ void LaTeX::deleteFilesOnError() const FileName const bbl(changeExtension(file.absFileName(), ".bbl")); bbl.removeFile(); + // biber file + FileName const bcf(changeExtension(file.absFileName(), ".bcf")); + bcf.removeFile(); + // makeindex file FileName const ind(changeExtension(file.absFileName(), ".ind")); ind.removeFile(); @@ -269,6 +275,12 @@ int LaTeX::run(TeXErrors & terr) if (head.haschanged(glofile)) rerun |= runMakeIndexNomencl(file, ".glo", ".gls"); + // 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 if it was updated) + FileName const bcffile(changeExtension(file.absFileName(), ".bcf")); + bool const biber = head.exist(bcffile); + // run bibtex // if (scanres & UNDEF_CIT || scanres & RERUN || run_bibtex) if (scanres & UNDEF_CIT || run_bibtex) { @@ -278,13 +290,21 @@ int LaTeX::run(TeXErrors & terr) // no checks for now LYXERR(Debug::LATEX, "Running BibTeX."); message(_("Running BibTeX.")); - updateBibtexDependencies(head, bibtex_info); - rerun |= runBibTeX(bibtex_info, runparams); + updateBibtexDependencies(head, bibtex_info, biber); + rerun |= runBibTeX(bibtex_info, runparams, biber); + 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 /// insert the .bib and .bst files into the .dep-pdf file. - updateBibtexDependencies(head, bibtex_info); + updateBibtexDependencies(head, bibtex_info, biber); } // 2 @@ -330,8 +350,8 @@ int LaTeX::run(TeXErrors & terr) // no checks for now LYXERR(Debug::LATEX, "Running BibTeX."); message(_("Running BibTeX.")); - updateBibtexDependencies(head, bibtex_info); - rerun |= runBibTeX(bibtex_info, runparams); + updateBibtexDependencies(head, bibtex_info, biber); + rerun |= runBibTeX(bibtex_info, runparams, biber); } // 4 @@ -401,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); } @@ -428,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; } @@ -444,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; } @@ -530,7 +550,8 @@ void LaTeX::scanAuxFile(FileName const & file, AuxInfo & aux_info) void LaTeX::updateBibtexDependencies(DepTable & dep, - vector const & bibtex_info) + vector const & bibtex_info, + bool biber) { // Since a run of Bibtex mandates more latex runs it is ok to // remove all ".bib" and ".bst" files. @@ -554,16 +575,22 @@ 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) + OutputParams const & runparams, bool biber) { bool result = false; for (vector::const_iterator it = bibtex_info.begin(); it != bibtex_info.end(); ++it) { - if (it->databases.empty()) + if (!biber && it->databases.empty()) continue; result = true; @@ -577,7 +604,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; @@ -596,9 +623,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)) { @@ -615,6 +646,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; @@ -633,6 +687,10 @@ int LaTeX::scanLogFile(TeXErrors & terr) && contains(token, "undefined")) { retval |= ERROR_RERUN; LYXERR(Debug::LATEX, "Force rerun."); + // package etaremune + } else if (contains(token, "Etaremune labels have changed")) { + retval |= ERROR_RERUN; + LYXERR(Debug::LATEX, "Force rerun."); } else if (contains(token, "Citation") && contains(token, "on page") && contains(token, "undefined")) { @@ -687,11 +745,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; @@ -700,6 +771,7 @@ int LaTeX::scanLogFile(TeXErrors & terr) do { if (!getline(ifs, tmp)) break; + tmp = rtrim(tmp, "\r"); errstr += "\n" + tmp; if (++count > 5) break; @@ -707,7 +779,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 @@ -716,6 +789,7 @@ int LaTeX::scanLogFile(TeXErrors & terr) do { if (!getline(ifs, tmp)) break; + tmp = rtrim(tmp, "\r"); if (++count > 10) break; } while (!prefixIs(tmp, "l.")); @@ -734,6 +808,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, "! ") @@ -741,6 +816,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); @@ -761,7 +837,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; } } @@ -787,7 +864,8 @@ int LaTeX::scanLogFile(TeXErrors & terr) retval |= ERRORS; terr.insertError(0, from_local8bit("pdfTeX Error"), - from_local8bit(token)); + from_local8bit(token), + child_name); } } } @@ -968,6 +1046,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 @@ -997,10 +1079,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 @@ -1008,7 +1086,7 @@ void LaTeX::deplog(DepTable & head) // However, ... if (suffixIs(token, ")")) // no line break for sure - // pretend we've been succesfully searching + // pretend we've been successfully searching found_file = true; // (2) "No file file.ext" } else if (regex_match(token, sub, reg2)) { @@ -1049,7 +1127,7 @@ void LaTeX::deplog(DepTable & head) file.absFileName(), ".toc")), head); else // not found, but we won't check further - // pretend we've been succesfully searching + // pretend we've been successfully searching found_file = true; // (8) "(file.ext" @@ -1088,7 +1166,7 @@ void LaTeX::deplog(DepTable & head) // we have a closing bracket, so the content // is not a file name. // no need to investigate further - // pretend we've been succesfully searching + // pretend we've been successfully searching first = what[0].second; found_file = true; } @@ -1109,4 +1187,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