From: Jürgen Spitzmüller Date: Sun, 18 Feb 2007 16:06:12 +0000 (+0000) Subject: Fix dependency checking, This fixes bug 1027 and probably others. X-Git-Tag: 1.6.10~10773 X-Git-Url: https://git.lyx.org/gitweb/?a=commitdiff_plain;h=bfee5a107c4047cc85ce56b4a5c424282dc3d56e;p=lyx.git 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 --- diff --git a/src/LaTeX.C b/src/LaTeX.C index 5a8b81f761..3606071dc3 100644 --- a/src/LaTeX.C +++ b/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 = `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) "" + 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" (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); }