mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-12-24 13:48:59 +00:00
Improve the command-line parser meant to be used for QProcess.
Now, both single- and double-quotes posix-like quoting styles are implemented, such that a command-line meant for the shell can also be used for QProcess. However, only redirecting the output to a file is supported. Supporting piping would require a (major?) rewrite of the Systemcall class. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@32590 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
parent
45b0c6be47
commit
04580d2122
@ -75,22 +75,83 @@ int Systemcall::startscript(Starttype how, string const & what,
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
string const parsecmd(string const & cmd, string & outfile)
|
/*
|
||||||
|
* This is a parser that (mostly) mimics the behavior of a posix shell but
|
||||||
|
* its output is tailored for being processed by QProcess.
|
||||||
|
*
|
||||||
|
* The escape character is the backslash.
|
||||||
|
* A backslash that is not quoted preserves the literal value of the following
|
||||||
|
* character, with the exception of a double-quote '"'. If a double-quote
|
||||||
|
* follows a backslash, it will be replaced by three consecutive double-quotes
|
||||||
|
* (this is how the QProcess parser recognizes a '"' as a simple character
|
||||||
|
* instead of a quoting character). Thus, for example:
|
||||||
|
* \\ -> \
|
||||||
|
* \a -> a
|
||||||
|
* \" -> """
|
||||||
|
*
|
||||||
|
* Single-quotes.
|
||||||
|
* Characters enclosed in single-quotes ('') have their literal value preserved.
|
||||||
|
* A single-quote cannot occur within single-quotes. Indeed, a backslash cannot
|
||||||
|
* be used to escape a single-quote in a single-quoted string. In other words,
|
||||||
|
* anything enclosed in single-quotes is passed as is, but the single-quotes
|
||||||
|
* themselves are eliminated. Thus, for example:
|
||||||
|
* '\' -> \
|
||||||
|
* '\\' -> \\
|
||||||
|
* '\a' -> \a
|
||||||
|
* 'a\"b' -> a\"b
|
||||||
|
*
|
||||||
|
* Double-quotes.
|
||||||
|
* Characters enclosed in double-quotes ("") have their literal value preserved,
|
||||||
|
* with the exception of the backslash. The backslash retains its special
|
||||||
|
* meaning as an escape character only when followed by a double-quote.
|
||||||
|
* Contrarily to the behavior of a posix shell, the double-quotes themselves
|
||||||
|
* are *not* eliminated. Thus, for example:
|
||||||
|
* "\\" -> "\\"
|
||||||
|
* "\a" -> "\a"
|
||||||
|
* "a\"b" -> "a"""b"
|
||||||
|
*/
|
||||||
|
string const parsecmd(string const & inputcmd, string & outfile)
|
||||||
{
|
{
|
||||||
bool inquote = false;
|
bool in_single_quote = false;
|
||||||
|
bool in_double_quote = false;
|
||||||
bool escaped = false;
|
bool escaped = false;
|
||||||
|
string cmd;
|
||||||
|
|
||||||
for (size_t i = 0; i < cmd.length(); ++i) {
|
for (size_t i = 0; i < inputcmd.length(); ++i) {
|
||||||
char c = cmd[i];
|
char c = inputcmd[i];
|
||||||
if (c == '"' && !escaped)
|
if (c == '\'') {
|
||||||
inquote = !inquote;
|
if (in_double_quote || escaped) {
|
||||||
else if (c == '\\' && !escaped)
|
if (in_double_quote && escaped)
|
||||||
escaped = !escaped;
|
cmd += '\\';
|
||||||
else if (c == '>' && !(inquote || escaped)) {
|
cmd += c;
|
||||||
outfile = trim(cmd.substr(i + 1), " \"");
|
} else
|
||||||
return trim(cmd.substr(0, i));
|
in_single_quote = !in_single_quote;
|
||||||
} else
|
|
||||||
escaped = false;
|
escaped = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (in_single_quote) {
|
||||||
|
cmd += c;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (c == '"') {
|
||||||
|
if (escaped) {
|
||||||
|
cmd += "\"\"\"";
|
||||||
|
escaped = false;
|
||||||
|
} else {
|
||||||
|
cmd += c;
|
||||||
|
in_double_quote = !in_double_quote;
|
||||||
|
}
|
||||||
|
} else if (c == '\\' && !escaped) {
|
||||||
|
escaped = !escaped;
|
||||||
|
} else if (c == '>' && !(in_double_quote || escaped)) {
|
||||||
|
outfile = trim(inputcmd.substr(i + 1), " \"");
|
||||||
|
return trim(cmd);
|
||||||
|
} else {
|
||||||
|
if (escaped && in_double_quote)
|
||||||
|
cmd += '\\';
|
||||||
|
cmd += c;
|
||||||
|
escaped = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
outfile.erase();
|
outfile.erase();
|
||||||
return cmd;
|
return cmd;
|
||||||
|
@ -144,7 +144,9 @@ string const quoteName(string const & name, quote_style style)
|
|||||||
#else
|
#else
|
||||||
// According to the QProcess parser, a single double
|
// According to the QProcess parser, a single double
|
||||||
// quote is represented by three consecutive ones.
|
// quote is represented by three consecutive ones.
|
||||||
return '"' + subst(name, "\"", "\"\"\"") + '"';
|
// Here we simply escape the double quote and let our
|
||||||
|
// simple parser in Systemcall.cpp do the substitution.
|
||||||
|
return '"' + subst(name, "\"", "\\\"") + '"';
|
||||||
#endif
|
#endif
|
||||||
case quote_python:
|
case quote_python:
|
||||||
return "\"" + subst(subst(name, "\\", "\\\\"), "\"", "\\\"")
|
return "\"" + subst(subst(name, "\\", "\\\\"), "\"", "\\\"")
|
||||||
|
Loading…
Reference in New Issue
Block a user