]> git.lyx.org Git - lyx.git/blobdiff - src/LaTeX.C
Fix bug 2474; partial fix for 1777. Added last_reference_ member to QRef class and...
[lyx.git] / src / LaTeX.C
index 4585b1a7188887ae65ff2e311a97927a2b7840ed..29a7d6b2dbe42f9a84a9a41b117bb89f52524367 100644 (file)
@@ -30,6 +30,7 @@
 #include "support/os.h"
 
 #include <boost/filesystem/operations.hpp>
+#include <boost/filesystem/path.hpp>
 #include <boost/regex.hpp>
 
 #include <fstream>
@@ -167,6 +168,10 @@ void LaTeX::deleteFilesOnError() const
        FileName const nls(changeExtension(file.absFilename(), ".nls"));
        unlink(nls);
 
+       // nomencl file (old version of the package)
+       FileName const gls(changeExtension(file.absFilename(), ".gls"));
+       unlink(gls);
+
        // Also remove the aux file
        FileName const aux(changeExtension(file.absFilename(), ".aux"));
        unlink(aux);
@@ -214,7 +219,7 @@ int LaTeX::run(TeXErrors & terr)
        FileName const aux_file(changeExtension(file.absFilename(), "aux"));
 
        if (had_depfile) {
-               lyxerr[Debug::DEPEND] << "Dependency file exists" << endl;
+               LYXERR(Debug::DEPEND) << "Dependency file exists" << endl;
                // Read the dep file:
                had_depfile = head.read(depfile);
        }
@@ -227,21 +232,21 @@ int LaTeX::run(TeXErrors & terr)
                // to re-run latex and collect the error messages 
                // (even if they are the same).
                if (!fs::exists(output_file.toFilesystemEncoding())) {
-                       lyxerr[Debug::DEPEND]
+                       LYXERR(Debug::DEPEND)
                                << "re-running LaTeX because output file doesn't exist."
                                << endl;
                } else if (!head.sumchange()) {
-                       lyxerr[Debug::DEPEND] << "return no_change" << endl;
+                       LYXERR(Debug::DEPEND) << "return no_change" << endl;
                        return NO_CHANGE;
                } else {
-                       lyxerr[Debug::DEPEND]
+                       LYXERR(Debug::DEPEND)
                                << "Dependency file has changed" << endl;
                }
 
                if (head.extchanged(".bib") || head.extchanged(".bst"))
                        run_bibtex = true;
        } else
-               lyxerr[Debug::DEPEND]
+               LYXERR(Debug::DEPEND)
                        << "Dependency file does not exist, or has wrong format"
                        << endl;
 
@@ -253,13 +258,13 @@ int LaTeX::run(TeXErrors & terr)
                bibtex_info_old = scanAuxFiles(aux_file);
 
        ++count;
-       lyxerr[Debug::LATEX] << "Run #" << count << endl;
+       LYXERR(Debug::LATEX) << "Run #" << count << endl;
        message(runMessage(count));
 
        startscript();
        scanres = scanLogFile(terr);
        if (scanres & ERROR_RERUN) {
-               lyxerr[Debug::LATEX] << "Rerunning LaTeX" << endl;
+               LYXERR(Debug::LATEX) << "Rerunning LaTeX" << endl;
                startscript();
                scanres = scanLogFile(terr);
        }
@@ -293,26 +298,18 @@ int LaTeX::run(TeXErrors & terr)
        // run makeindex
        if (head.haschanged(idxfile)) {
                // no checks for now
-               lyxerr[Debug::LATEX] << "Running MakeIndex." << endl;
+               LYXERR(Debug::LATEX) << "Running MakeIndex." << endl;
                message(_("Running MakeIndex."));
                // onlyFilename() is needed for cygwin
                rerun |= runMakeIndex(onlyFilename(idxfile.absFilename()),
                                runparams);
        }
-       if (head.haschanged(FileName(changeExtension(file.absFilename(), ".nlo")))) {
-               lyxerr[Debug::LATEX] 
-                       << "Running MakeIndex for nomencl."
-                       << endl;
-               message(_("Running MakeIndex for nomencl."));
-               // onlyFilename() is needed for cygwin
-               string const nomenclstr = " -s nomencl.ist -o " 
-                       + onlyFilename(changeExtension(
-                               file.toFilesystemEncoding(), ".nls"));
-               rerun |= runMakeIndex(onlyFilename(changeExtension(
-                               file.absFilename(), ".nlo")),
-                               runparams,
-                               nomenclstr);
-       }
+       FileName const nlofile(changeExtension(file.absFilename(), ".nlo"));
+       if (head.haschanged(nlofile))
+               rerun |= runMakeIndexNomencl(file, runparams, ".nlo", ".nls");
+       FileName const glofile(changeExtension(file.absFilename(), ".glo"));
+       if (head.haschanged(glofile))
+               rerun |= runMakeIndexNomencl(file, runparams, ".glo", ".gls");
 
        // run bibtex
        // if (scanres & UNDEF_CIT || scanres & RERUN || run_bibtex)
@@ -321,7 +318,7 @@ int LaTeX::run(TeXErrors & terr)
                // "\bibdata" and/or "\bibstyle". If one of those
                // tags is found -> run bibtex and set rerun = true;
                // no checks for now
-               lyxerr[Debug::LATEX] << "Running BibTeX." << endl;
+               LYXERR(Debug::LATEX) << "Running BibTeX." << endl;
                message(_("Running BibTeX."));
                updateBibtexDependencies(head, bibtex_info);
                rerun |= runBibTeX(bibtex_info);
@@ -347,10 +344,10 @@ int LaTeX::run(TeXErrors & terr)
        if (rerun || head.sumchange()) {
                rerun = false;
                ++count;
-               lyxerr[Debug::DEPEND]
+               LYXERR(Debug::DEPEND)
                        << "Dep. file has changed or rerun requested"
                        << endl;
-               lyxerr[Debug::LATEX]
+               LYXERR(Debug::LATEX)
                        << "Run #" << count << endl;
                message(runMessage(count));
                startscript();
@@ -364,7 +361,7 @@ int LaTeX::run(TeXErrors & terr)
                deplog(head); // reads the latex log
                head.update();
        } else {
-               lyxerr[Debug::DEPEND]
+               LYXERR(Debug::DEPEND)
                        << "Dep. file has NOT changed"
                        << endl;
        }
@@ -378,9 +375,9 @@ int LaTeX::run(TeXErrors & terr)
        // more after this.
 
        // run makeindex if the <file>.idx has changed or was generated.
-       if (head.haschanged(FileName(changeExtension(file.absFilename(), ".idx")))) {
+       if (head.haschanged(idxfile)) {
                // no checks for now
-               lyxerr[Debug::LATEX] << "Running MakeIndex." << endl;
+               LYXERR(Debug::LATEX) << "Running MakeIndex." << endl;
                message(_("Running MakeIndex."));
                // onlyFilename() is needed for cygwin
                rerun = runMakeIndex(onlyFilename(changeExtension(
@@ -388,20 +385,10 @@ int LaTeX::run(TeXErrors & terr)
        }
 
        // I am not pretty sure if need this twice.
-       if (head.haschanged(FileName(changeExtension(file.absFilename(), ".nlo")))) {
-               lyxerr[Debug::LATEX] 
-                       << "Running MakeIndex for nomencl."
-                       << endl;
-               message(_("Running MakeIndex for nomencl."));
-               // onlyFilename() is needed for cygwin
-               string nomenclstr = " -s nomencl.ist -o " 
-                       + onlyFilename(changeExtension(
-                               file.toFilesystemEncoding(), ".nls"));
-               rerun |= runMakeIndex(onlyFilename(changeExtension(
-                               file.absFilename(), ".nlo")),
-                               runparams,
-                               nomenclstr);
-       }
+       if (head.haschanged(nlofile))
+               rerun |= runMakeIndexNomencl(file, runparams, ".nlo", ".nls");
+       if (head.haschanged(glofile))
+               rerun |= runMakeIndexNomencl(file, runparams, ".glo", ".gls");
 
        // 2
        // we will only run latex more if the log file asks for it.
@@ -419,7 +406,7 @@ int LaTeX::run(TeXErrors & terr)
                // MAX_RUNS are reached.
                rerun = false;
                ++count;
-               lyxerr[Debug::LATEX] << "Run #" << count << endl;
+               LYXERR(Debug::LATEX) << "Run #" << count << endl;
                message(runMessage(count));
                startscript();
                scanres = scanLogFile(terr);
@@ -434,7 +421,7 @@ int LaTeX::run(TeXErrors & terr)
 
        // Write the dependencies to file.
        head.write(depfile);
-       lyxerr[Debug::LATEX] << "Done." << endl;
+       LYXERR(Debug::LATEX) << "Done." << endl;
        return scanres;
 }
 
@@ -453,7 +440,7 @@ int LaTeX::startscript()
 bool LaTeX::runMakeIndex(string const & f, OutputParams const & runparams,
                          string const & params)
 {
-       lyxerr[Debug::LATEX]
+       LYXERR(Debug::LATEX)
                << "idx file has been made, running makeindex on file "
                << f << endl;
        string tmp = lyxrc.index_command + ' ';
@@ -467,6 +454,21 @@ bool LaTeX::runMakeIndex(string const & f, OutputParams const & runparams,
 }
 
 
+bool LaTeX::runMakeIndexNomencl(FileName const & file,
+               OutputParams const & runparams,
+               string const & nlo, string const & nls)
+{
+       LYXERR(Debug::LATEX) << "Running MakeIndex for nomencl." << endl;
+       message(_("Running MakeIndex for nomencl."));
+       // onlyFilename() is needed for cygwin
+       string const nomenclstr = " -s nomencl.ist -o "
+               + onlyFilename(changeExtension(file.toFilesystemEncoding(), nls));
+       return runMakeIndex(
+                       onlyFilename(changeExtension(file.absFilename(), nlo)),
+                       runparams, nomenclstr);
+}
+
+
 vector<Aux_Info> const
 LaTeX::scanAuxFiles(FileName const & file)
 {
@@ -498,7 +500,7 @@ Aux_Info const LaTeX::scanAuxFile(FileName const & file)
 
 void LaTeX::scanAuxFile(FileName const & file, Aux_Info & aux_info)
 {
-       lyxerr[Debug::LATEX] << "Scanning aux file: " << file << endl;
+       LYXERR(Debug::LATEX) << "Scanning aux file: " << file << endl;
 
        ifstream ifs(file.toFilesystemEncoding().c_str());
        string token;
@@ -518,7 +520,7 @@ void LaTeX::scanAuxFile(FileName const & file, Aux_Info & aux_info)
                        while (!data.empty()) {
                                string citation;
                                data = split(data, citation, ',');
-                               lyxerr[Debug::LATEX] << "Citation: "
+                               LYXERR(Debug::LATEX) << "Citation: "
                                                     << citation << endl;
                                aux_info.citations.insert(citation);
                        }
@@ -530,7 +532,7 @@ void LaTeX::scanAuxFile(FileName const & file, Aux_Info & aux_info)
                                string database;
                                data = split(data, database, ',');
                                database = changeExtension(database, "bib");
-                               lyxerr[Debug::LATEX] << "BibTeX database: `"
+                               LYXERR(Debug::LATEX) << "BibTeX database: `"
                                                     << database << '\'' << endl;
                                aux_info.databases.insert(database);
                        }
@@ -539,7 +541,7 @@ void LaTeX::scanAuxFile(FileName const & file, Aux_Info & aux_info)
                        // token is now the style file
                        // pass it to the helper
                        style = changeExtension(style, "bst");
-                       lyxerr[Debug::LATEX] << "BibTeX style: `"
+                       LYXERR(Debug::LATEX) << "BibTeX style: `"
                                             << style << '\'' << endl;
                        aux_info.styles.insert(style);
                } else if (regex_match(token, sub, reg4)) {
@@ -606,7 +608,7 @@ int LaTeX::scanLogFile(TeXErrors & terr)
        int retval = NO_ERRORS;
        string tmp =
                onlyFilename(changeExtension(file.absFilename(), ".log"));
-       lyxerr[Debug::LATEX] << "Log file: " << tmp << endl;
+       LYXERR(Debug::LATEX) << "Log file: " << tmp << endl;
        FileName const fn = FileName(makeAbsPath(tmp));
        ifstream ifs(fn.toFilesystemEncoding().c_str());
 
@@ -619,7 +621,7 @@ int LaTeX::scanLogFile(TeXErrors & terr)
                token = subst(token, '\0', '\r');
                token = subst(token, "\r", "");
 
-               lyxerr[Debug::LATEX] << "Log line: " << token << endl;
+               LYXERR(Debug::LATEX) << "Log line: " << token << endl;
 
                if (token.empty())
                        continue;
@@ -629,10 +631,10 @@ int LaTeX::scanLogFile(TeXErrors & terr)
                        // Here shall we handle different
                        // types of warnings
                        retval |= LATEX_WARNING;
-                       lyxerr[Debug::LATEX] << "LaTeX Warning." << endl;
+                       LYXERR(Debug::LATEX) << "LaTeX Warning." << endl;
                        if (contains(token, "Rerun to get cross-references")) {
                                retval |= RERUN;
-                               lyxerr[Debug::LATEX]
+                               LYXERR(Debug::LATEX)
                                        << "We should rerun." << endl;
                        } else if (contains(token, "Citation")
                                   && contains(token, "on page")
@@ -655,7 +657,7 @@ int LaTeX::scanLogFile(TeXErrors & terr)
                                   contains(token, "Rerun to get")) {
                                // at least longtable.sty and bibtopic.sty
                                // might use this.
-                               lyxerr[Debug::LATEX]
+                               LYXERR(Debug::LATEX)
                                        << "We should rerun." << endl;
                                retval |= RERUN;
                        }
@@ -663,7 +665,7 @@ int LaTeX::scanLogFile(TeXErrors & terr)
                        if (contains(token, "Rerun LaTeX") ||
                            contains(token, "Rerun to get")) {
                                // Used by natbib
-                               lyxerr[Debug::LATEX]
+                               LYXERR(Debug::LATEX)
                                        << "We should rerun." << endl;
                                retval |= RERUN;
                        }
@@ -705,7 +707,7 @@ int LaTeX::scanLogFile(TeXErrors & terr)
                                        errstr += "\n";
                                        getline(ifs, tmp);
                                }
-                               lyxerr[Debug::LATEX]
+                               LYXERR(Debug::LATEX)
                                        << "line: " << line << '\n'
                                        << "Desc: " << desc << '\n'
                                        << "Text: " << errstr << endl;
@@ -749,25 +751,40 @@ int LaTeX::scanLogFile(TeXErrors & terr)
                        }
                }
        }
-       lyxerr[Debug::LATEX] << "Log line: " << token << endl;
+       LYXERR(Debug::LATEX) << "Log line: " << token << endl;
        return retval;
 }
 
 
 namespace {
 
-bool insertIfExists(FileName const & absname, DepTable & head)
-{
-       // fs::path may throw an exception if absname is too strange
-       if (!fs::native(absname.toFilesystemEncoding())) {
-               lyxerr[Debug::DEPEND] << '`' << absname.absFilename()
-                       << "' is no valid file name." << endl;
+/**
+ * Wrapper around fs::exists that can handle invalid file names.
+ * In theory we could test with fs::native whether a filename is valid
+ * before calling fs::exists, but in practice it is unusable: On windows it
+ * does not allow spaces, and on unix it does not allow absolute file names.
+ * This function has the disadvantage that it catches also other errors than
+ * invalid names, but for dependency checking we can live with that.
+ */
+bool exists(FileName const & possible_name) {
+       try {
+               return fs::exists(possible_name.toFilesystemEncoding());
+       }
+       catch (fs::filesystem_error const & fe) {
+               LYXERR(Debug::DEPEND) << "Got error `" << fe.what()
+                       << "' while checking whether file `" << possible_name
+                       << "' exists." << endl;
                return false;
        }
-       fs::path const path(absname.toFilesystemEncoding());
-       if (fs::exists(path) && !fs::is_directory(path)) {
-                       head.insert(absname, true);
-                       return true;
+}
+
+
+bool insertIfExists(FileName const & absname, DepTable & head)
+{
+       if (exists(absname) &&
+           !fs::is_directory(absname.toFilesystemEncoding())) {
+               head.insert(absname, true);
+               return true;
        }
        return false;
 }
@@ -778,7 +795,7 @@ bool handleFoundFile(string const & ff, DepTable & head)
        // convert from native os path to unix path
        string foundfile = os::internal_path(trim(ff));
 
-       lyxerr[Debug::DEPEND] << "Found file: " << foundfile << endl;
+       LYXERR(Debug::DEPEND) << "Found file: " << foundfile << endl;
 
        // Ok now we found a file.
        // Now we should make sure that this is a file that we can
@@ -790,7 +807,7 @@ bool handleFoundFile(string const & ff, DepTable & head)
        //     absolute path and should
        //     be inserted.
        if (absolutePath(foundfile)) {
-               lyxerr[Debug::DEPEND] << "AbsolutePath file: "
+               LYXERR(Debug::DEPEND) << "AbsolutePath file: "
                                      << foundfile << endl;
                // On initial insert we want to do the update at once
                // since this file cannot be a file generated by
@@ -802,7 +819,7 @@ bool handleFoundFile(string const & ff, DepTable & head)
                        while (contains(strippedfile, " ")) {
                                // files with spaces are often enclosed in quotation
                                // marks; those have to be removed
-                               string unquoted = subst(strippedfile, '"', char());
+                               string unquoted = subst(strippedfile, "\"", "");
                                absname.set(unquoted);
                                if (insertIfExists(absname, head))
                                        return true;
@@ -822,23 +839,15 @@ bool handleFoundFile(string const & ff, DepTable & head)
 
        // check for spaces
        while (contains(foundfile, ' ')) {
-               // fs::path may throw an exception if absname is too strange
-               bool exists = fs::native(absname.toFilesystemEncoding());
-               if (exists)
-                       exists = fs::exists(absname.toFilesystemEncoding());
-               else {
-                       lyxerr[Debug::DEPEND] << '`' << absname.absFilename()
-                               << "' is no valid file name." << endl;
-               }
-               if (exists)
+               if (exists(absname))
                        // everything o.k.
                        break;
                else {
                        // files with spaces are often enclosed in quotation
                        // marks; those have to be removed
-                       string unquoted = subst(foundfile, '"', char());
+                       string unquoted = subst(foundfile, "\"", "");
                        absname = makeAbsPath(unquoted);
-                       if (fs::exists(absname.toFilesystemEncoding()))
+                       if (exists(absname))
                                break;
                        // strip off part after last space and try again
                        string strippedfile;
@@ -852,19 +861,13 @@ bool handleFoundFile(string const & ff, DepTable & head)
 
        // (2) foundfile is in the tmpdir
        //     insert it into head
-       // fs::path may throw an exception if absname is too strange
-       bool exists = fs::native(absname.toFilesystemEncoding());
-       if (exists) {
-               fs::path const path = absname.toFilesystemEncoding();
-               exists = fs::exists(path) && !fs::is_directory(path);
-       } else {
-               lyxerr[Debug::DEPEND] << '`' << absname.absFilename()
-                       << "' is no valid file name." << endl;
-       }
-       if (exists) {
-               static regex unwanted("^.*\\.(aux|log|dvi|bbl|ind|glo)$");
+       if (exists(absname) &&
+           !fs::is_directory(absname.toFilesystemEncoding())) {
+               // FIXME: This regex contained glo, but glo is used by the old
+               // version of nomencl.sty. Do we need to put it back?
+               static regex unwanted("^.*\\.(aux|log|dvi|bbl|ind)$");
                if (regex_match(onlyfile, unwanted)) {
-                       lyxerr[Debug::DEPEND]
+                       LYXERR(Debug::DEPEND)
                                << "We don't want "
                                << onlyfile
                                << " in the dep file"
@@ -873,13 +876,13 @@ bool handleFoundFile(string const & ff, DepTable & head)
                        // This is a tex file generated by LyX
                        // and latex is not likely to change this
                        // during its runs.
-                       lyxerr[Debug::DEPEND]
+                       LYXERR(Debug::DEPEND)
                                << "Tmpdir TeX file: "
                                << onlyfile
                                << endl;
                        head.insert(absname, true);
                } else {
-                       lyxerr[Debug::DEPEND]
+                       LYXERR(Debug::DEPEND)
                                << "In tmpdir file:"
                                << onlyfile
                                << endl;
@@ -887,7 +890,7 @@ bool handleFoundFile(string const & ff, DepTable & head)
                }
                return true;
        } else {
-               lyxerr[Debug::DEPEND]
+               LYXERR(Debug::DEPEND)
                        << "Not a file or we are unable to find it."
                        << endl;
                return false;
@@ -927,6 +930,7 @@ void LaTeX::deplog(DepTable & head)
        static regex reg4("Writing index file (.+).*");
        // files also can be enclosed in <...>
        static regex reg5("<([^>]+)(.).*");
+       static regex regoldnomencl("Writing glossary file (.+).*");
        static regex regnomencl("Writing nomenclature file (.+).*");
        // If a toc should be created, MikTex does not write a line like
        //    \openout# = `sample.toc'.
@@ -983,9 +987,7 @@ void LaTeX::deplog(DepTable & head)
                        token = lastline + token;
                if (token.length() > 255) {
                        // string too long. Cut off.
-                       int r = token.length() - 250;
-                       string ntoken = token.substr(r, token.length());
-                       token = ntoken;
+                       token.erase(0, token.length() - 251);
                }
 
                smatch sub;
@@ -1032,7 +1034,8 @@ void LaTeX::deplog(DepTable & head)
                                // probable line break
                                found_file = false;
                // (6) "Writing nomenclature file file.ext"
-               } else if (regex_match(token, sub, regnomencl))
+               } else if (regex_match(token, sub, regnomencl) ||
+                          regex_match(token, sub, regoldnomencl))
                        // check for dot
                        found_file = checkLineBreak(sub.str(1), head);
                // (7) "\tf@toc=\write<nr>" (for MikTeX)