#include "LyXRC.h"
#include "LyX.h"
#include "DepTable.h"
+#include "Encoding.h"
#include "support/debug.h"
#include "support/convert.h"
}
+void TeXErrors::insertRef(int line, docstring const & error_desc,
+ docstring const & error_text,
+ string const & child_name)
+{
+ Error newerr(line, error_desc, error_text, child_name);
+ undef_ref.push_back(newerr);
+}
+
+
bool operator==(AuxInfo const & a, AuxInfo const & o)
{
return a.aux_file == o.aux_file
FileName const & f, string const & p, string const & lp,
bool allow_cancellation, bool const clean_start)
: cmd(latex), file(f), path(p), lpath(lp), runparams(rp), biber(false),
- allow_cancel(allow_cancellation)
+ allow_cancel(allow_cancellation)
{
num_errors = 0;
// lualatex can still produce a DVI with --output-format=dvi. However,
FileName const gls(changeExtension(file.absFileName(), ".gls"));
gls.removeFile();
+ // endnotes file
+ FileName const ent(changeExtension(file.absFileName(), ".ent"));
+ ent.removeFile();
+
// Also remove the aux file
FileName const aux(changeExtension(file.absFileName(), ".aux"));
aux.removeFile();
{
int scanres = NO_ERRORS;
int bscanres = NO_ERRORS;
+ int iscanres = NO_ERRORS;
unsigned int count = 0; // number of times run
num_errors = 0; // just to make sure.
unsigned int const MAX_RUN = 6;
runMakeIndex(onlyFileName(idxfile.absFileName()), runparams);
if (ret == Systemcall::KILLED)
return Systemcall::KILLED;
+ FileName const ilgfile(changeExtension(file.absFileName(), ".ilg"));
+ if (ilgfile.exists())
+ iscanres = scanIlgFile(terr);
rerun = true;
}
file.absFileName(), ".idx")), runparams);
if (ret == Systemcall::KILLED)
return Systemcall::KILLED;
- rerun = true;
+ FileName const ilgfile(changeExtension(file.absFileName(), ".ilg"));
+ if (ilgfile.exists())
+ iscanres = scanIlgFile(terr);
+ rerun = true;
}
// MSVC complains that bool |= int is unsafe. Not sure why.
if (bscanres & ERRORS)
return bscanres; // return on error
+ if (iscanres & ERRORS)
+ return iscanres; // return on error
+
return scanres;
}
if (!rp.index_command.empty())
tmp = rp.index_command;
+
+ if (contains(tmp, "$$x")) {
+ // This adds appropriate [te]xindy options
+ // such as language and codepage (for the
+ // main document language/encoding) as well
+ // as input markup (latex or xelatex)
+ string xdyopts = rp.xindy_language;
+ if (!xdyopts.empty())
+ xdyopts = "-L " + xdyopts;
+ if (rp.isFullUnicode() && rp.encoding->package() == Encoding::none) {
+ if (!xdyopts.empty())
+ xdyopts += " ";
+ // xelatex includes lualatex
+ xdyopts += "-I xelatex";
+ }
+ else if (rp.encoding->iconvName() == "UTF-8") {
+ if (!xdyopts.empty())
+ xdyopts += " ";
+ // -I not really needed for texindy, but for xindy
+ xdyopts += "-C utf8 -I latex";
+ }
+ else {
+ if (!xdyopts.empty())
+ xdyopts += " ";
+ // not really needed for texindy, but for xindy
+ xdyopts += "-I latex";
+ }
+ tmp = subst(tmp, "$$x", xdyopts);
+ }
+
+ if (contains(tmp, "$$b")) {
+ // advise xindy to write a log file
+ tmp = subst(tmp, "$$b", removeExtension(f));
+ }
LYXERR(Debug::LATEX,
"idx file has been made, running index processor ("
}
+//helper func for scanLogFile; gets line number X from strings "... on input line X ..."
+//returns 0 if none is found
+int getLineNumber(const string &token){
+ string l = support::token(token, ' ', tokenPos(token,' ',"line") + 1);
+ return l.empty() ? 0 : convert<int>(l);
+}
+
+
int LaTeX::scanLogFile(TeXErrors & terr)
{
int last_line = -1;
stack <pair<string, int> > child;
children.clear();
+ terr.clearRefs();
+
string token;
while (getline(ifs, token)) {
// MikTeX sometimes inserts \0 in the log file. They can't be
if (contains(token, "file:line:error style messages enabled"))
fle_style = true;
+ //Handles both "LaTeX Warning:" & "Package natbib Warning:"
+ //Various handlers for missing citations below won't catch the problem if citation
+ //key is long (>~25chars), because pdflatex splits output at line length 80.
+ //TODO: TL 2020 engines will contain new commandline switch --cnf-line which we
+ //can use to set max_print_line variable for appropriate length and detect all
+ //errors correctly.
+ if (contains(token, "There were undefined citations.") ||
+ prefixIs(token, "Package biblatex Warning: The following entry could not be found"))
+ retval |= UNDEF_CIT;
+
if (prefixIs(token, "LaTeX Warning:") ||
prefixIs(token, "! pdfTeX warning")) {
// Here shall we handle different
} else if (contains(token, "Etaremune labels have changed")) {
retval |= ERROR_RERUN;
LYXERR(Debug::LATEX, "Force rerun.");
+ // package enotez
+ } else if (contains(token, "Endnotes may have changed. Rerun")) {
+ retval |= RERUN;
+ LYXERR(Debug::LATEX, "We should rerun.");
+ //"Citation `cit' on page X undefined on input line X."
} else if (contains(token, "Citation")
- && contains(token, "on page")
+ //&& contains(token, "on input line") //often split to newline
&& contains(token, "undefined")) {
retval |= UNDEF_CIT;
- } else if (contains(token, "Citation")
- && contains(token, "on input line")
+ terr.insertRef(getLineNumber(token), from_ascii("Citation undefined"),
+ from_utf8(token), child_name);
+ //"Reference `X' on page Y undefined on input line Z."
+ } else if (contains(token, "Reference")
+ //&& contains(token, "on input line")) //often split to new line
&& contains(token, "undefined")) {
- retval |= UNDEF_CIT;
+ retval |= UNDEF_REF;
+ terr.insertRef(getLineNumber(token), from_ascii("Reference undefined"),
+ from_utf8(token), child_name);
+
+ //If label is too long pdlaftex log line splitting will make the above fail
+ //so we catch at least this generic statement occuring for both CIT & REF.
+ } else if (contains(token, "There were undefined references.")) {
+ if (!(retval & UNDEF_CIT)) //if not handled already
+ retval |= UNDEF_REF;
}
+
} else if (prefixIs(token, "Package")) {
// Package warnings
retval |= PACKAGE_WARNING;
&& contains(token, "on page")
&& contains(token, "undefined")) {
retval |= UNDEF_CIT;
+ //Unf only keys up to ~6 chars will make it due to line splits
+ terr.insertRef(getLineNumber(token), from_ascii("Citation undefined"),
+ from_utf8(token), child_name);
}
} else if (contains(token, "run BibTeX")) {
retval |= UNDEF_CIT;
static regex const reg1("File: (.+).*");
static regex const reg2("No file (.+)(.).*");
- static regex const reg3("\\\\openout[0-9]+.*=.*`(.+)(..).*");
+ static regex const reg3a("\\\\openout[0-9]+.*=.*`(.+)(..).*");
+ // LuaTeX has a slightly different output
+ static regex const reg3b("\\\\openout[0-9]+.*=\\s*(.+)");
// If an index should be created, MikTex does not write a line like
// \openout# = 'sample.idx'.
// but instead only a line like this into the log:
// Writing index file sample.idx
static regex const reg4("Writing index file (.+).*");
static regex const regoldnomencl("Writing glossary file (.+).*");
- static regex const regnomencl("Writing nomenclature file (.+).*");
+ static regex const regnomencl(".*Writing nomenclature file (.+).*");
// If a toc should be created, MikTex does not write a line like
// \openout# = `sample.toc'.
// but only a line like this into the log:
else
// we suspect a line break
fragment = true;
- // (3) "\openout<nr> = `file.ext'."
- } else if (regex_match(token, sub, reg3)) {
+ // (3)(a) "\openout<nr> = `file.ext'."
+ } else if (regex_match(token, sub, reg3a)) {
// search for closing '. at the end of the line
if (sub.str(2) == "\'.")
fragment = !handleFoundFile(sub.str(1), head);
else
// potential fragment
fragment = true;
+ // (3)(b) "\openout<nr> = file.ext" (LuaTeX)
+ } else if (regex_match(token, sub, reg3b)) {
+ // file names must contains a dot
+ if (contains(sub.str(1), '.'))
+ fragment = !handleFoundFile(sub.str(1), head);
+ else
+ // potential fragment
+ fragment = true;
// (4) "Writing index file file.ext"
} else if (regex_match(token, sub, reg4))
// fragmential file name?
}
+int LaTeX::scanIlgFile(TeXErrors & terr)
+{
+ FileName const ilg_file(changeExtension(file.absFileName(), "ilg"));
+ LYXERR(Debug::LATEX, "Scanning ilg file: " << ilg_file);
+
+ ifstream ifs(ilg_file.toFilesystemEncoding().c_str());
+ string token;
+ int retval = NO_ERRORS;
+
+ string prevtoken;
+ while (getline(ifs, token)) {
+ token = rtrim(token, "\r");
+ smatch sub;
+ if (prefixIs(token, "!! "))
+ prevtoken = token;
+ else if (!prevtoken.empty()) {
+ retval |= INDEX_ERROR;
+ string errstr = N_("Makeindex error: ") + prevtoken;
+ string msg = prevtoken + '\n';
+ msg += token;
+ terr.insertError(0,
+ from_local8bit(errstr),
+ from_local8bit(msg));
+ prevtoken.clear();
+ } else if (prefixIs(token, "ERROR: ")) {
+ retval |= BIBTEX_ERROR;
+ string errstr = N_("Xindy error: ") + token.substr(6);
+ string msg = token;
+ terr.insertError(0,
+ from_local8bit(errstr),
+ from_local8bit(msg));
+ }
+ }
+ return retval;
+}
+
+
+
} // namespace lyx