X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FLaTeX.cpp;h=8597e6db6062aa0758ad76cbcee3166a94060be0;hb=28be7d552f62cc02fa86d7f79201d089bfb2d7b5;hp=55e31ec1c1a849e2392db45343bdbf3ebf62f7af;hpb=306b136cc005a1aeb9a6861ee0ac6fe2a2dd53e3;p=lyx.git diff --git a/src/LaTeX.cpp b/src/LaTeX.cpp index 55e31ec1c1..8597e6db60 100644 --- a/src/LaTeX.cpp +++ b/src/LaTeX.cpp @@ -18,6 +18,7 @@ #include "BufferList.h" #include "LaTeX.h" #include "LyXRC.h" +#include "LyX.h" #include "DepTable.h" #include "support/debug.h" @@ -97,7 +98,13 @@ LaTeX::LaTeX(string const & latex, OutputParams const & rp, : cmd(latex), file(f), path(p), lpath(lp), runparams(rp), biber(false) { num_errors = 0; - if (prefixIs(cmd, "pdf")) { // Do we use pdflatex ? + // lualatex can still produce a DVI with --output-format=dvi. However, + // we do not use that internally (we use the "dvilualatex" command) so + // it would only happen from a custom converter. Thus, it is better to + // guess that lualatex produces a PDF than to guess a DVI. + // FIXME we should base the extension on the output format, which we should + // get in a robust way, e.g. from the converter. + if (prefixIs(cmd, "pdf") || prefixIs(cmd, "lualatex") || prefixIs(cmd, "xelatex")) { depfile = FileName(file.absFileName() + ".dep-pdf"); output_file = FileName(changeExtension(file.absFileName(), ".pdf")); @@ -148,6 +155,10 @@ void LaTeX::removeAuxiliaryFiles() const FileName const aux(changeExtension(file.absFileName(), ".aux")); aux.removeFile(); + // Also remove the .out file (e.g. hyperref bookmarks) (#9963) + FileName const out(changeExtension(file.absFileName(), ".out")); + out.removeFile(); + // Remove the output file, which is often generated even if error output_file.removeFile(); } @@ -226,22 +237,23 @@ int LaTeX::run(TeXErrors & terr) /// in which case we will not need to run bibtex again. vector bibtex_info_old; if (!run_bibtex) - bibtex_info_old = scanAuxFiles(aux_file); + bibtex_info_old = scanAuxFiles(aux_file, runparams.only_childbibs); ++count; LYXERR(Debug::LATEX, "Run #" << count); message(runMessage(count)); - int const exit_code = startscript(); + int exit_code = startscript(); scanres = scanLogFile(terr); if (scanres & ERROR_RERUN) { LYXERR(Debug::LATEX, "Rerunning LaTeX"); - startscript(); + terr.clearErrors(); + exit_code = startscript(); scanres = scanLogFile(terr); } - vector const bibtex_info = scanAuxFiles(aux_file); + vector const bibtex_info = scanAuxFiles(aux_file, runparams.only_childbibs); if (!run_bibtex && bibtex_info_old != bibtex_info) run_bibtex = true; @@ -407,8 +419,12 @@ int LaTeX::run(TeXErrors & terr) // Write the dependencies to file. head.write(depfile); - if (exit_code) + if (exit_code) { + // add flag here, just before return, instead of when exit_code + // is defined because scanres is sometimes overwritten above + // (e.g. rerun) scanres |= NONZERO_ERROR; + } LYXERR(Debug::LATEX, "Done."); @@ -475,12 +491,26 @@ bool LaTeX::runMakeIndexNomencl(FileName const & file, vector const -LaTeX::scanAuxFiles(FileName const & file) +LaTeX::scanAuxFiles(FileName const & file, bool const only_childbibs) { vector result; + // With chapterbib, we have to bibtex all children's aux files + // but _not_ the master's! + if (only_childbibs) { + for (string const &s: children) { + FileName fn = + makeAbsPath(s, file.onlyPath().realPath()); + fn.changeExtension("aux"); + if (fn.exists()) + result.push_back(scanAuxFile(fn)); + } + return result; + } + result.push_back(scanAuxFile(file)); + // This is for bibtopic string const basename = removeExtension(file.absFileName()); for (int i = 1; i < 1000; ++i) { FileName const file2(basename @@ -599,11 +629,7 @@ bool LaTeX::runBibTeX(vector const & bibtex_info, continue; result = true; - string tmp = runparams.use_japanese ? - lyxrc.jbibtex_command : lyxrc.bibtex_command; - - if (!runparams.bibtex_command.empty()) - tmp = runparams.bibtex_command; + string tmp = runparams.bibtex_command; tmp += " "; // onlyFileName() is needed for cygwin tmp += quoteName(onlyFileName(removeExtension( @@ -635,6 +661,7 @@ int LaTeX::scanLogFile(TeXErrors & terr) string child_name; int pnest = 0; stack > child; + children.clear(); string token; while (getline(ifs, token)) { @@ -663,6 +690,7 @@ int LaTeX::scanLogFile(TeXErrors & terr) if (regex_match(substr, sub, child_file)) { string const name = sub.str(1); child.push(make_pair(name, pnest)); + children.push_back(name); i += len; } } else if (token[i] == ')') { @@ -757,7 +785,7 @@ int LaTeX::scanLogFile(TeXErrors & terr) if (contains(token, "LaTeX Error:")) retval |= LATEX_ERROR; - if (prefixIs(token, "! File ended while scanning")){ + if (prefixIs(token, "! File ended while scanning")) { 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; @@ -769,6 +797,12 @@ int LaTeX::scanLogFile(TeXErrors & terr) } } + if (prefixIs(token, "! Incomplete \\if")) { + // bug 10666. 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; @@ -780,6 +814,7 @@ int LaTeX::scanLogFile(TeXErrors & terr) string errstr; int count = 0; errstr = wait_for_error; + wait_for_error.clear(); do { if (!getline(ifs, tmp)) break; @@ -869,20 +904,43 @@ int LaTeX::scanLogFile(TeXErrors & terr) } else if (contains(token, "Rerun to get citations")) { // Natbib seems to use this. retval |= UNDEF_CIT; - } else if (contains(token, "No pages of output")) { - // A dvi file was not created + } else if (contains(token, "No pages of output") + || contains(token, "no pages of output")) { + // No output file (e.g. the DVI or PDF) was created retval |= NO_OUTPUT; + } else if (contains(token, "Error 256 (driver return code)")) { + // This is a xdvipdfmx driver error reported by XeTeX. + // We have to check whether an output PDF file was created. + FileName pdffile = file; + pdffile.changeExtension("pdf"); + if (!pdffile.exists()) + // No output PDF file was created (see #10076) + retval |= NO_OUTPUT; } else if (contains(token, "That makes 100 errors")) { - // More than 100 errors were reprted + // More than 100 errors were reported retval |= TOO_MANY_ERRORS; - } else if (prefixIs(token, "!pdfTeX error:")){ + } else if (prefixIs(token, "!pdfTeX error:")) { // otherwise we dont catch e.g.: // !pdfTeX error: pdflatex (file feyn10): Font feyn10 at 600 not found retval |= ERRORS; - terr.insertError(0, - from_local8bit("pdfTeX Error"), - from_local8bit(token), - child_name); + terr.insertError(0, + from_local8bit("pdfTeX Error"), + from_local8bit(token), + child_name); + } else if (!ignore_missing_glyphs + && prefixIs(token, "Missing character: There is no ") + && !contains(token, "nullfont")) { + // Warning about missing glyph in selected font + // may be dataloss (bug 9610) + // but can be ignored for 'nullfont' (bug 10394). + retval |= LATEX_ERROR; + terr.insertError(0, + from_local8bit("Missing glyphs!"), + from_local8bit(token), + child_name); + } else if (!wait_for_error.empty()) { + // We collect information until we know we have an error. + wait_for_error += token + '\n'; } } } @@ -938,8 +996,7 @@ bool handleFoundFile(string const & ff, DepTable & head) return true; // strip off part after last space and try again string tmp = strippedfile; - string const stripoff = - rsplit(tmp, strippedfile, ' '); + rsplit(tmp, strippedfile, ' '); absname.set(strippedfile); if (insertIfExists(absname, head)) return true; @@ -964,8 +1021,7 @@ bool handleFoundFile(string const & ff, DepTable & head) break; // strip off part after last space and try again string strippedfile; - string const stripoff = - rsplit(foundfile, strippedfile, ' '); + rsplit(foundfile, strippedfile, ' '); foundfile = strippedfile; onlyfile = onlyFileName(strippedfile); absname = makeAbsPath(onlyfile);