mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-11-09 18:31:04 +00:00
Fix dependency checking, This fixes bug 1027 and probably others.
* src/LaTeX.C: - (deplog): fix and refine parsing of file names. - (handleFoundFile): handle files with spaces in their name/path correctly - (checkLinebreak): new helper function for deplog. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@17240 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
parent
fff190773f
commit
bfee5a107c
221
src/LaTeX.C
221
src/LaTeX.C
@ -49,6 +49,7 @@ using support::prefixIs;
|
||||
using support::quoteName;
|
||||
using support::removeExtension;
|
||||
using support::rtrim;
|
||||
using support::rsplit;
|
||||
using support::split;
|
||||
using support::subst;
|
||||
using support::suffixIs;
|
||||
@ -722,10 +723,10 @@ int LaTeX::scanLogFile(TeXErrors & terr)
|
||||
|
||||
namespace {
|
||||
|
||||
void handleFoundFile(string const & ff, DepTable & head)
|
||||
bool handleFoundFile(string const & ff, DepTable & head)
|
||||
{
|
||||
// convert from native os path to unix path
|
||||
string const foundfile = os::internal_path(trim(ff));
|
||||
string foundfile = os::internal_path(trim(ff));
|
||||
|
||||
lyxerr[Debug::DEPEND] << "Found file: " << foundfile << endl;
|
||||
|
||||
@ -744,16 +745,46 @@ void handleFoundFile(string const & ff, DepTable & head)
|
||||
// On initial insert we want to do the update at once
|
||||
// since this file cannot be a file generated by
|
||||
// the latex run.
|
||||
FileName const absname(foundfile);
|
||||
FileName absname(foundfile);
|
||||
if (fs::exists(absname.toFilesystemEncoding()) &&
|
||||
!fs::is_directory(absname.toFilesystemEncoding()))
|
||||
head.insert(absname, true);
|
||||
|
||||
return;
|
||||
!fs::is_directory(absname.toFilesystemEncoding())) {
|
||||
head.insert(absname, true);
|
||||
return true;
|
||||
} else {
|
||||
// check for spaces
|
||||
string strippedfile = foundfile;
|
||||
while (contains(strippedfile, " ")) {
|
||||
// strip off part after last space and try again
|
||||
string tmp = strippedfile;
|
||||
string const stripoff =
|
||||
rsplit(tmp, strippedfile, ' ');
|
||||
absname.set(strippedfile);
|
||||
if (fs::exists(absname.toFilesystemEncoding()) &&
|
||||
!fs::is_directory(absname.toFilesystemEncoding())) {
|
||||
head.insert(absname, true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string const onlyfile = onlyFilename(foundfile);
|
||||
FileName const absname(makeAbsPath(onlyfile));
|
||||
string onlyfile = onlyFilename(foundfile);
|
||||
FileName absname(makeAbsPath(onlyfile));
|
||||
|
||||
// check for spaces
|
||||
while (contains(foundfile, " ")) {
|
||||
if (fs::exists(absname.toFilesystemEncoding()))
|
||||
// everything o.k.
|
||||
break;
|
||||
else {
|
||||
// strip off part after last space and try again
|
||||
string strippedfile;
|
||||
string const stripoff = rsplit(foundfile, strippedfile, ' ');
|
||||
foundfile = strippedfile;
|
||||
onlyfile = onlyFilename(strippedfile);
|
||||
absname = makeAbsPath(onlyfile);
|
||||
}
|
||||
}
|
||||
|
||||
// (2) foundfile is in the tmpdir
|
||||
// insert it into head
|
||||
@ -781,10 +812,24 @@ void handleFoundFile(string const & ff, DepTable & head)
|
||||
<< endl;
|
||||
head.insert(absname);
|
||||
}
|
||||
} else
|
||||
return true;
|
||||
} else {
|
||||
lyxerr[Debug::DEPEND]
|
||||
<< "Not a file or we are unable to find it."
|
||||
<< endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool checkLineBreak(string const & ff, DepTable & head)
|
||||
{
|
||||
if (contains(ff, '.'))
|
||||
// if we have a dot, we let handleFoundFile decide
|
||||
return handleFoundFile(ff, head);
|
||||
else
|
||||
// else, we suspect a line break
|
||||
return false;
|
||||
}
|
||||
|
||||
} // anon namespace
|
||||
@ -798,16 +843,17 @@ void LaTeX::deplog(DepTable & head)
|
||||
|
||||
string const logfile = onlyFilename(changeExtension(file.absFilename(), ".log"));
|
||||
|
||||
static regex reg1(".*\\([^)]+.*");
|
||||
static regex reg2("File: ([^ ]+).*");
|
||||
static regex reg3("No file ([^ ]+)\\..*");
|
||||
static regex reg4("\\\\openout[0-9]+.*=.*`([^ ]+)'\\..*");
|
||||
static regex reg1("File: (.+).*");
|
||||
static regex reg2("No file (.+)(.).*");
|
||||
static regex reg3("\\\\openout[0-9]+.*=.*`(.+)(..).*");
|
||||
// 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 reg5("Writing index file ([^ ]+).*");
|
||||
static regex regnomencl("Writing nomenclature file ([^ ]+).*");
|
||||
static regex reg4("Writing index file (.+).*");
|
||||
// files also can be enclosed in <...>
|
||||
static regex reg5("<([^>]+)(.).*");
|
||||
static regex 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:
|
||||
@ -815,19 +861,18 @@ void LaTeX::deplog(DepTable & head)
|
||||
// This line is also written by tetex.
|
||||
// This line is not present if no toc should be created.
|
||||
static regex miktexTocReg("\\\\tf@toc=\\\\write.*");
|
||||
static regex reg6(".*\\([^)]+.*");
|
||||
|
||||
FileName const fn(makeAbsPath(logfile));
|
||||
ifstream ifs(fn.toFilesystemEncoding().c_str());
|
||||
string lastline;
|
||||
while (ifs) {
|
||||
// Ok, the scanning of files here is not sufficient.
|
||||
// Sometimes files are named by "File: xxx" only
|
||||
// So I think we should use some regexps to find files instead.
|
||||
// "\(([^ ()]+\.+[^ ()]+)" should match the "(file.ext " variant,
|
||||
// note that we can have several of these on one line.
|
||||
// "File: ([^\.]+\.+[^ ]+).*" should match the "File: file.ext " variant.
|
||||
// FIXME: sometimes, LaTeX inserts linebreaks while outputting
|
||||
// file names. This case is not handled correctly (bug 1027).
|
||||
// Note: all file names and paths might contains spaces.
|
||||
|
||||
bool found_file = false;
|
||||
string token;
|
||||
getline(ifs, token);
|
||||
// MikTeX sometimes inserts \0 in the log file. They can't be
|
||||
@ -836,8 +881,26 @@ void LaTeX::deplog(DepTable & head)
|
||||
// \r's afterwards, since we need to remove them anyway.
|
||||
token = subst(token, '\0', '\r');
|
||||
token = subst(token, "\r", "");
|
||||
if (token.empty())
|
||||
if (token.empty() || token == ")") {
|
||||
lastline = string();
|
||||
continue;
|
||||
}
|
||||
|
||||
// Sometimes, filenames are broken across lines.
|
||||
// We care for that and save suspicious lines.
|
||||
// Here we exclude some cases where we are sure
|
||||
// that there is no continued filename
|
||||
if (prefixIs(token, "File:") || prefixIs(token, "(Font)")
|
||||
|| prefixIs(token, "Package:")
|
||||
|| prefixIs(token, "Language:")
|
||||
|| prefixIs(token, "LaTeX Font Info:")
|
||||
|| prefixIs(token, "\\openout[")
|
||||
|| prefixIs(token, "))"))
|
||||
lastline = string();
|
||||
|
||||
if (!lastline.empty())
|
||||
// probably a continued filename from last line
|
||||
token = lastline + token;
|
||||
|
||||
smatch sub;
|
||||
|
||||
@ -845,33 +908,109 @@ void LaTeX::deplog(DepTable & head)
|
||||
// file are in the file system encoding.
|
||||
token = to_utf8(from_filesystem8bit(token));
|
||||
|
||||
// (1) "File: file.ext"
|
||||
if (regex_match(token, sub, reg1)) {
|
||||
// search for strings in (...) that must not contain
|
||||
// a blank, but must contain a dot
|
||||
static regex reg1_1("\\(([^()]+\\.+[^ ()]+)");
|
||||
// check for dot
|
||||
found_file = checkLineBreak(sub.str(1), head);
|
||||
// However, ...
|
||||
if (suffixIs(token, ")"))
|
||||
// no line break for sure
|
||||
// pretend we've been succesfully searching
|
||||
found_file = true;
|
||||
// (2) "No file file.ext"
|
||||
} else if (regex_match(token, sub, reg2)) {
|
||||
// file names must contains a dot, line ends with dot
|
||||
if (contains(sub.str(1), '.') && sub.str(2) == ".")
|
||||
found_file = handleFoundFile(sub.str(1), head);
|
||||
else
|
||||
// we suspect a line break
|
||||
found_file = false;
|
||||
// (3) "\openout<nr> = `file.ext'."
|
||||
} else if (regex_match(token, sub, reg3)) {
|
||||
// search for closing '. at the end of the line
|
||||
if (sub.str(2) == "\'.")
|
||||
found_file = handleFoundFile(sub.str(1), head);
|
||||
else
|
||||
// probable line break
|
||||
found_file = false;
|
||||
// (4) "Writing index file file.ext"
|
||||
} else if (regex_match(token, sub, reg4))
|
||||
// check for dot
|
||||
found_file = checkLineBreak(sub.str(1), head);
|
||||
// (5) "<file.ext>"
|
||||
else if (regex_match(token, sub, reg5)) {
|
||||
// search for closing '>' and dot ('*.*>') at the eol
|
||||
if (contains(sub.str(1), '.') && sub.str(2) == ">")
|
||||
found_file = handleFoundFile(sub.str(1), head);
|
||||
else
|
||||
// probable line break
|
||||
found_file = false;
|
||||
// (6) "Writing nomenclature file file.ext"
|
||||
} else if (regex_match(token, sub, regnomencl))
|
||||
// check for dot
|
||||
found_file = checkLineBreak(sub.str(1), head);
|
||||
// (7) "\tf@toc=\write<nr>" (for MikTeX)
|
||||
else if (regex_match(token, sub, miktexTocReg))
|
||||
found_file = handleFoundFile(onlyFilename(changeExtension(
|
||||
file.absFilename(), ".toc")), head);
|
||||
else
|
||||
// not found, but we won't check further
|
||||
// pretend we've been succesfully searching
|
||||
found_file = true;
|
||||
|
||||
// (8) "(file.ext"
|
||||
// note that we can have several of these on one line
|
||||
// this must be queried separated, because of
|
||||
// cases such as "File: file.ext (type eps)"
|
||||
// where "File: file.ext" would be skipped
|
||||
if (regex_match(token, sub, reg6)) {
|
||||
// search for strings in (...)
|
||||
static regex reg6_1("\\(([^()]+)(.).*");
|
||||
smatch what;
|
||||
string::const_iterator first = token.begin();
|
||||
string::const_iterator end = token.end();
|
||||
|
||||
while (regex_search(first, end, what, reg1_1)) {
|
||||
first = what[0].second;
|
||||
handleFoundFile(what.str(1), head);
|
||||
while (regex_search(first, end, what, reg6_1)) {
|
||||
// if we have a dot, try to handle as file
|
||||
if (contains(what.str(1), '.')) {
|
||||
first = what[0].second;
|
||||
if (what.str(2) == ")") {
|
||||
handleFoundFile(what.str(1), head);
|
||||
// since we had a closing bracket,
|
||||
// do not investigate further
|
||||
found_file = true;
|
||||
} else
|
||||
// if we have no closing bracket,
|
||||
// try to handle as file nevertheless
|
||||
found_file = handleFoundFile(
|
||||
what.str(1) + what.str(2), head);
|
||||
}
|
||||
// if we do not have a dot, check if the line has
|
||||
// a closing bracket (else, we suspect a line break)
|
||||
else if (what.str(2) != ")") {
|
||||
first = what[0].second;
|
||||
found_file = false;
|
||||
} else {
|
||||
// we have a closing bracket, so the content
|
||||
// is not a file name.
|
||||
// no need to investigate further
|
||||
// pretend we've been succesfully searching
|
||||
first = what[0].second;
|
||||
found_file = true;
|
||||
}
|
||||
}
|
||||
} else if (regex_match(token, sub, reg2))
|
||||
handleFoundFile(sub.str(1), head);
|
||||
else if (regex_match(token, sub, reg3))
|
||||
handleFoundFile(sub.str(1), head);
|
||||
else if (regex_match(token, sub, reg4))
|
||||
handleFoundFile(sub.str(1), head);
|
||||
else if (regex_match(token, sub, reg5))
|
||||
handleFoundFile(sub.str(1), head);
|
||||
else if (regex_match(token, sub, regnomencl))
|
||||
handleFoundFile(sub.str(1), head);
|
||||
else if (regex_match(token, sub, miktexTocReg))
|
||||
handleFoundFile(onlyFilename(changeExtension(file.absFilename(), ".toc")), head);
|
||||
}
|
||||
|
||||
if (!found_file)
|
||||
// probable linebreak:
|
||||
// save this line
|
||||
lastline = token;
|
||||
else
|
||||
// no linebreak: reset
|
||||
lastline = string();
|
||||
}
|
||||
|
||||
// Make sure that the main .tex file is in the dependancy file.
|
||||
// Make sure that the main .tex file is in the dependency file.
|
||||
head.insert(file, true);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user