Manage the setting of the latex environment for Systemcall and ForkedCall

in a central place. This is a backport of r39754 and r39758-r39762.
No status line needed.


git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/branches/BRANCH_2_0_X@39770 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
Enrico Forestieri 2011-09-26 17:14:24 +00:00
parent d69a5c79b9
commit 9c5a8a5baa
6 changed files with 71 additions and 79 deletions

View File

@ -15,7 +15,6 @@
#include "support/ForkedCalls.h"
#include "support/debug.h"
#include "support/environment.h"
#include "support/filetools.h"
#include "support/lstrings.h"
#include "support/lyxlib.h"
@ -24,8 +23,6 @@
#include "support/bind.h"
#include "LyXRC.h"
#include <cerrno>
#include <queue>
#include <sstream>
@ -274,23 +271,8 @@ int ForkedProcess::waitForChild()
/////////////////////////////////////////////////////////////////////
ForkedCall::ForkedCall(string const & path)
: cmd_prefix_(empty_string())
{
if (path.empty() || lyxrc.texinputs_prefix.empty())
return;
string const texinputs = os::latex_path_list(
replaceCurdirPath(path, lyxrc.texinputs_prefix));
string const sep = string(1, os::path_separator(os::TEXENGINE));
string const env = getEnv("TEXINPUTS");
if (os::shell() == os::UNIX)
cmd_prefix_ = "env 'TEXINPUTS=." + sep + texinputs
+ sep + env + "' ";
else
cmd_prefix_ = "cmd /d /c set TEXINPUTS=." + sep + texinputs
+ sep + env + " & ";
}
: cmd_prefix_(to_filesystem8bit(from_utf8(latexEnvCmdPrefix(path))))
{}
int ForkedCall::startScript(Starttype wait, string const & what)
@ -300,7 +282,7 @@ int ForkedCall::startScript(Starttype wait, string const & what)
return retval_;
}
command_ = what;
command_ = trim(what);
signal_.reset();
return run(Wait);
}
@ -308,7 +290,7 @@ int ForkedCall::startScript(Starttype wait, string const & what)
int ForkedCall::startScript(string const & what, SignalTypePtr signal)
{
command_ = what;
command_ = trim(what);
signal_ = signal;
return run(DontWait);
@ -318,10 +300,11 @@ int ForkedCall::startScript(string const & what, SignalTypePtr signal)
// generate child in background
int ForkedCall::generateChild()
{
string const line = trim(cmd_prefix_ + command_);
if (line.empty())
if (command_.empty())
return 1;
string const line = cmd_prefix_ + command_;
#if !defined (_WIN32)
// POSIX
@ -341,25 +324,44 @@ int ForkedCall::generateChild()
// 2. If we are inside quotes, then don't replace the white space
// but do remove the quotes themselves. We do this naively by
// replacing the quote with '\0' which is fine if quotes
// delimit the entire word.
// delimit the entire word. However, if quotes do not delimit the
// entire word (i.e., open quote is inside word), simply discard
// them such as not to break the current word.
char inside_quote = 0;
char c_before_open_quote = ' ';
vector<char>::iterator it = vec.begin();
vector<char>::iterator itc = vec.begin();
vector<char>::iterator const end = vec.end();
for (; it != end; ++it) {
for (; it != end; ++it, ++itc) {
char const c = *it;
if (!inside_quote) {
if (c == ' ')
*it = '\0';
else if (c == '\'' || c == '"') {
*it = '\0';
if (c == '\'' || c == '"') {
if (c_before_open_quote == ' ')
*itc = '\0';
else
--itc;
inside_quote = c;
} else {
if (c == ' ')
*itc = '\0';
else
*itc = c;
c_before_open_quote = c;
}
} else if (c == inside_quote) {
*it = '\0';
if (c_before_open_quote == ' ')
*itc = '\0';
else
--itc;
inside_quote = 0;
}
} else
*itc = c;
}
// Clear what remains.
for (; itc != end; ++itc)
*itc = '\0';
// Build an array of pointers to each word.
it = vec.begin();
vector<char *> argv;

View File

@ -14,7 +14,6 @@
#include <config.h>
#include "support/debug.h"
#include "support/environment.h"
#include "support/filetools.h"
#include "support/lstrings.h"
#include "support/qstring_helpers.h"
@ -101,24 +100,8 @@ ProgressInterface* ProgressInterface::instance()
int Systemcall::startscript(Starttype how, string const & what,
std::string const & path, bool /*process_events*/)
{
string command;
string const texinputs = os::latex_path_list(
replaceCurdirPath(path, lyxrc.texinputs_prefix));
string const sep = string(1, os::path_separator(os::TEXENGINE));
string const env = getEnv("TEXINPUTS");
switch (os::shell()) {
case os::UNIX:
command = path.empty() || lyxrc.texinputs_prefix.empty() ? what
: "env TEXINPUTS='." + sep + texinputs
+ sep + env + "' " + what;
break;
case os::CMD_EXE:
command = path.empty() || lyxrc.texinputs_prefix.empty() ? what
: "set TEXINPUTS=." + sep + texinputs
+ sep + env + " & " + what;
break;
}
string command =
to_filesystem8bit(from_utf8(latexEnvCmdPrefix(path))) + what;
if (how == DontWait) {
switch (os::shell()) {
@ -129,7 +112,8 @@ int Systemcall::startscript(Starttype how, string const & what,
command = "start /min " + command;
break;
}
}
} else if (os::shell() == os::CMD_EXE)
command = subst(command, "cmd /d /c ", "");
return ::system(command.c_str());
}
@ -228,7 +212,7 @@ int Systemcall::startscript(Starttype how, string const & what,
string const & path, bool process_events)
{
string outfile;
QString cmd = toqstr(parsecmd(what, outfile));
QString cmd = QString::fromLocal8Bit(parsecmd(what, outfile).c_str());
SystemcallPrivate d(outfile);
@ -268,13 +252,12 @@ SystemcallPrivate::SystemcallPrivate(const std::string& of) :
out_index_(0),
err_index_(0),
out_file_(of),
texinputs_(getEnv("TEXINPUTS")),
process_events_(false)
{
if (!out_file_.empty()) {
// Check whether we have to simply throw away the output.
if (out_file_ != os::nulldev())
process_->setStandardOutputFile(toqstr(out_file_));
process_->setStandardOutputFile(QString::fromLocal8Bit(out_file_.c_str()));
}
connect(process_, SIGNAL(readyReadStandardOutput()), SLOT(stdOut()));
@ -285,27 +268,12 @@ SystemcallPrivate::SystemcallPrivate(const std::string& of) :
}
void SystemcallPrivate::startProcess(QString const & cmd, string const & path)
{
cmd_ = cmd;
if (process_) {
if (!path.empty() && !lyxrc.texinputs_prefix.empty()) {
string const texinputs = os::latex_path_list(
replaceCurdirPath(path, lyxrc.texinputs_prefix));
string const sep = string(1,
os::path_separator(os::TEXENGINE));
string const prefix = "." + sep + texinputs + sep;
if (prefixIs(texinputs_, prefix))
texinputs_.clear();
else
setEnv("TEXINPUTS", prefix + texinputs_);
}
state = SystemcallPrivate::Starting;
if (os::shell() == os::CMD_EXE)
process_->start(QLatin1String("cmd /d /c ") + cmd_);
else
process_->start(cmd_);
process_->start(toqstr(latexEnvCmdPrefix(path)) + cmd_);
}
}
@ -362,9 +330,6 @@ bool SystemcallPrivate::waitWhile(State waitwhile, bool process_events, int time
SystemcallPrivate::~SystemcallPrivate()
{
if (!texinputs_.empty())
setEnv("TEXINPUTS", texinputs_);
if (out_index_) {
out_data_[out_index_] = '\0';
out_index_ = 0;

View File

@ -40,9 +40,10 @@ public:
/** Start child process.
* The string "what" contains a commandline with arguments separated
* by spaces. The string "path" contains the path to be prepended to
* the TEXINPUTS environment variable. Unset "process_events" in
* case UI should be blocked while processing the external command.
* by spaces and encoded in the filesystem encoding. The string "path"
* contains the path to be prepended to the TEXINPUTS environment
* variable and encoded in utf-8. Unset "process_events" in case
* UI should be blocked while processing the external command.
*/
int startscript(Starttype how, std::string const & what,
std::string const & path = empty_string(),

View File

@ -74,8 +74,6 @@ private:
size_t err_index_;
///
std::string out_file_;
///
std::string texinputs_;
/// Size of buffers.
static size_t const buffer_size_ = 200;

View File

@ -578,6 +578,26 @@ string const replaceEnvironmentPath(string const & path)
}
// Return a command prefix for setting the environment of the TeX engine.
string latexEnvCmdPrefix(string const & path)
{
if (path.empty() || lyxrc.texinputs_prefix.empty())
return string();
string const texinputs_prefix = os::latex_path_list(
replaceCurdirPath(path, lyxrc.texinputs_prefix));
string const sep = string(1, os::path_separator(os::TEXENGINE));
string const texinputs = getEnv("TEXINPUTS");
if (os::shell() == os::UNIX)
return "env TEXINPUTS=\"." + sep + texinputs_prefix
+ sep + texinputs + "\" ";
else
return "cmd /d /c set TEXINPUTS=." + sep + texinputs_prefix
+ sep + texinputs + " & ";
}
// Replace current directory in all elements of a path list with a given path.
string const replaceCurdirPath(string const & path, string const & pathlist)
{

View File

@ -247,6 +247,12 @@ std::string const onlyFileName(std::string const & fname);
*/
std::string const replaceEnvironmentPath(std::string const & path);
/**
Return a string to be used as a prefix to a command for setting the
environment of the TeX engine with respect to the path \p path.
*/
std::string latexEnvCmdPrefix(std::string const & path);
/** Replace all references to a current directory (a lonely '.' or
the prefix "./") in \c pathlist with \c path. Also prefixes
all non-absolute paths with \c path.