QtcProcess: Introduce a QtcProcess::Arguments class

This is used to get a platform-agnostic handle on "command line
arguments". It essentially wraps a single QString on Windows,
and a QStringList everywhere else.

As a consequence, several occurrences of #ifdef Q_OS_*
can be removed from the codebase.

Change-Id: Ic93118c1bd0bce0ebb58f416d395dbaebb861772
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@digia.com>
This commit is contained in:
hjk
2014-02-05 10:43:21 +01:00
committed by Eike Ziller
parent a0d29eeb03
commit c68ebeed2e
14 changed files with 1257 additions and 1196 deletions

View File

@@ -75,7 +75,8 @@ bool ConsoleProcess::start(const QString &program, const QString &args)
return false; return false;
QtcProcess::SplitError perr; QtcProcess::SplitError perr;
QStringList pargs = QtcProcess::prepareArgs(args, &perr, &d->m_environment, &d->m_workingDir); QtcProcess::Arguments pargs = QtcProcess::prepareArgs(args, &perr, HostOsInfo::hostOs(),
&d->m_environment, &d->m_workingDir);
QString pcmd; QString pcmd;
if (perr == QtcProcess::SplitOk) { if (perr == QtcProcess::SplitOk) {
pcmd = program; pcmd = program;
@@ -91,11 +92,14 @@ bool ConsoleProcess::start(const QString &program, const QString &args)
return false; return false;
} }
pcmd = QLatin1String("/bin/sh"); pcmd = QLatin1String("/bin/sh");
pargs << QLatin1String("-c") << (QtcProcess::quoteArg(program) + QLatin1Char(' ') + args); pargs = QtcProcess::Arguments::createUnixArgs(QStringList()
<< QLatin1String("-c")
<< (QtcProcess::quoteArg(program) + QLatin1Char(' ') + args));
} }
QtcProcess::SplitError qerr; QtcProcess::SplitError qerr;
QStringList xtermArgs = QtcProcess::prepareArgs(terminalEmulator(d->m_settings), &qerr, QtcProcess::Arguments xtermArgs = QtcProcess::prepareArgs(terminalEmulator(d->m_settings), &qerr,
HostOsInfo::hostOs(),
&d->m_environment, &d->m_workingDir); &d->m_environment, &d->m_workingDir);
if (qerr != QtcProcess::SplitOk) { if (qerr != QtcProcess::SplitOk) {
emit processError(qerr == QtcProcess::BadQuoting emit processError(qerr == QtcProcess::BadQuoting
@@ -134,23 +138,23 @@ bool ConsoleProcess::start(const QString &program, const QString &args)
} }
} }
if (Utils::HostOsInfo::isMacHost()) { QString stubPath = QCoreApplication::applicationDirPath();
xtermArgs << (QCoreApplication::applicationDirPath() if (Utils::HostOsInfo::isMacHost())
+ QLatin1String("/../Resources/qtcreator_process_stub")); stubPath.append(QLatin1String("/../Resources/qtcreator_process_stub"));
} else { else
xtermArgs << (QCoreApplication::applicationDirPath() stubPath.append(QLatin1String("/qtcreator_process_stub"));
+ QLatin1String("/qtcreator_process_stub"));
} QStringList allArgs = xtermArgs.toUnixArgs();
xtermArgs allArgs << stubPath
<< modeOption(d->m_mode) << modeOption(d->m_mode)
<< d->m_stubServer.fullServerName() << d->m_stubServer.fullServerName()
<< msgPromptToClose() << msgPromptToClose()
<< workingDirectory() << workingDirectory()
<< (d->m_tempFile ? d->m_tempFile->fileName() : QString()) << (d->m_tempFile ? d->m_tempFile->fileName() : QString())
<< pcmd << pargs; << pcmd << pargs.toUnixArgs();
QString xterm = xtermArgs.takeFirst(); QString xterm = allArgs.takeFirst();
d->m_process.start(xterm, xtermArgs); d->m_process.start(xterm, allArgs);
if (!d->m_process.waitForStarted()) { if (!d->m_process.waitForStarted()) {
stubServerShutdown(); stubServerShutdown();
emit processError(tr("Cannot start the terminal emulator '%1', change the setting in the " emit processError(tr("Cannot start the terminal emulator '%1', change the setting in the "

View File

@@ -75,7 +75,10 @@ bool ConsoleProcess::start(const QString &program, const QString &args)
pcmd = program; pcmd = program;
pargs = args; pargs = args;
} else { } else {
QtcProcess::prepareCommand(program, args, &pcmd, &pargs, &d->m_environment, &d->m_workingDir); QtcProcess::Arguments outArgs;
QtcProcess::prepareCommand(program, args, &pcmd, &outArgs, OsTypeWindows,
&d->m_environment, &d->m_workingDir);
pargs = outArgs.toWindowsArgs();
} }
const QString err = stubServerListen(); const QString err = stubServerListen();

View File

@@ -31,16 +31,43 @@
#include "stringutils.h" #include "stringutils.h"
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <utils/hostosinfo.h>
#include <QDir> #include <QDir>
#include <QDebug> #include <QDebug>
#include <QCoreApplication> #include <QCoreApplication>
#include <QStack>
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
#include <qt_windows.h> #include <qt_windows.h>
#endif #endif
using namespace Utils;
// The main state of the Unix shell parser
enum MxQuoting { MxBasic, MxSingleQuote, MxDoubleQuote, MxParen, MxSubst, MxGroup, MxMath };
struct MxState
{
MxQuoting current;
// Bizarrely enough, double quoting has an impact on the behavior of some
// complex expressions within the quoted string.
bool dquote;
};
QT_BEGIN_NAMESPACE
Q_DECLARE_TYPEINFO(MxState, Q_PRIMITIVE_TYPE);
QT_END_NAMESPACE
// Pushed state for the case where a $(()) expansion turns out bogus
struct MxSave
{
QString str;
int pos, varPos;
};
QT_BEGIN_NAMESPACE
Q_DECLARE_TYPEINFO(MxSave, Q_MOVABLE_TYPE);
QT_END_NAMESPACE
namespace Utils {
/*! /*!
\class Utils::QtcProcess \class Utils::QtcProcess
@@ -49,9 +76,7 @@ using namespace Utils;
shell-quoted process arguments. shell-quoted process arguments.
*/ */
#ifdef Q_OS_WIN inline static bool isMetaCharWin(ushort c)
inline static bool isMetaChar(ushort c)
{ {
static const uchar iqm[] = { static const uchar iqm[] = {
0x00, 0x00, 0x00, 0x00, 0x40, 0x03, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x03, 0x00, 0x50,
@@ -61,7 +86,7 @@ inline static bool isMetaChar(ushort c)
return (c < sizeof(iqm) * 8) && (iqm[c / 8] & (1 << (c & 7))); return (c < sizeof(iqm) * 8) && (iqm[c / 8] & (1 << (c & 7)));
} }
static void envExpand(QString &args, const Environment *env, const QString *pwd) static void envExpandWin(QString &args, const Environment *env, const QString *pwd)
{ {
static const QString cdName = QLatin1String("CD"); static const QString cdName = QLatin1String("CD");
int off = 0; int off = 0;
@@ -82,18 +107,18 @@ static void envExpand(QString &args, const Environment *env, const QString *pwd)
} }
} }
QString QtcProcess::prepareArgs(const QString &_args, SplitError *err, static QtcProcess::Arguments prepareArgsWin(const QString &_args, QtcProcess::SplitError *err,
const Environment *env, const QString *pwd) const Environment *env, const QString *pwd)
{ {
QString args(_args); QString args(_args);
if (env) { if (env) {
envExpand(args, env, pwd); envExpandWin(args, env, pwd);
} else { } else {
if (args.indexOf(QLatin1Char('%')) >= 0) { if (args.indexOf(QLatin1Char('%')) >= 0) {
if (err) if (err)
*err = FoundMeta; *err = QtcProcess::FoundMeta;
return QString(); return QtcProcess::Arguments::createWindowsArgs(QString());
} }
} }
@@ -109,24 +134,24 @@ QString QtcProcess::prepareArgs(const QString &_args, SplitError *err,
if (++p == args.length()) if (++p == args.length())
break; // For cmd, this is no error. break; // For cmd, this is no error.
} while (args.unicode()[p].unicode() != '"'); } while (args.unicode()[p].unicode() != '"');
} else if (isMetaChar(c)) { } else if (isMetaCharWin(c)) {
if (err) if (err)
*err = FoundMeta; *err = QtcProcess::FoundMeta;
return QString(); return QtcProcess::Arguments::createWindowsArgs(QString());
} }
} }
if (err) if (err)
*err = SplitOk; *err = QtcProcess::SplitOk;
return args; return QtcProcess::Arguments::createWindowsArgs(args);
} }
inline static bool isWhiteSpace(ushort c) inline static bool isWhiteSpaceWin(ushort c)
{ {
return c == ' ' || c == '\t'; return c == ' ' || c == '\t';
} }
static QStringList doSplitArgs(const QString &args, QtcProcess::SplitError *err) static QStringList doSplitArgsWin(const QString &args, QtcProcess::SplitError *err)
{ {
QStringList ret; QStringList ret;
@@ -139,7 +164,7 @@ static QStringList doSplitArgs(const QString &args, QtcProcess::SplitError *err)
forever { forever {
if (p == length) if (p == length)
return ret; return ret;
if (!isWhiteSpace(args.unicode()[p].unicode())) if (!isWhiteSpaceWin(args.unicode()[p].unicode()))
break; break;
++p; ++p;
} }
@@ -181,7 +206,7 @@ static QStringList doSplitArgs(const QString &args, QtcProcess::SplitError *err)
while (--bslashes >= 0) while (--bslashes >= 0)
arg.append(QLatin1Char('\\')); arg.append(QLatin1Char('\\'));
if (p == length || (!inquote && isWhiteSpace(args.unicode()[p].unicode()))) { if (p == length || (!inquote && isWhiteSpaceWin(args.unicode()[p].unicode()))) {
ret.append(arg); ret.append(arg);
if (inquote) { if (inquote) {
if (err) if (err)
@@ -258,28 +283,29 @@ static QStringList doSplitArgs(const QString &args, QtcProcess::SplitError *err)
\c{foo " bar}. \c{foo " bar}.
*/ */
QStringList QtcProcess::splitArgs(const QString &_args, bool abortOnMeta, SplitError *err,
static QStringList splitArgsWin(const QString &_args, bool abortOnMeta,
QtcProcess::SplitError *err,
const Environment *env, const QString *pwd) const Environment *env, const QString *pwd)
{ {
if (abortOnMeta) { if (abortOnMeta) {
SplitError perr; QtcProcess::SplitError perr;
if (!err) if (!err)
err = &perr; err = &perr;
QString args = prepareArgs(_args, &perr, env, pwd); QString args = prepareArgsWin(_args, &perr, env, pwd).toWindowsArgs();
if (*err != SplitOk) if (*err != QtcProcess::SplitOk)
return QStringList(); return QStringList();
return doSplitArgs(args, err); return doSplitArgsWin(args, err);
} else { } else {
QString args = _args; QString args = _args;
if (env) if (env)
envExpand(args, env, pwd); envExpandWin(args, env, pwd);
return doSplitArgs(args, err); return doSplitArgsWin(args, err);
} }
} }
#else // Q_OS_WIN
inline static bool isMeta(QChar cUnicode) static bool isMetaUnix(QChar cUnicode)
{ {
static const uchar iqm[] = { static const uchar iqm[] = {
0x00, 0x00, 0x00, 0x00, 0xdc, 0x07, 0x00, 0xd8, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x07, 0x00, 0xd8,
@@ -291,7 +317,8 @@ inline static bool isMeta(QChar cUnicode)
return (c < sizeof(iqm) * 8) && (iqm[c / 8] & (1 << (c & 7))); return (c < sizeof(iqm) * 8) && (iqm[c / 8] & (1 << (c & 7)));
} }
QStringList QtcProcess::splitArgs(const QString &args, bool abortOnMeta, SplitError *err, static QStringList splitArgsUnix(const QString &args, bool abortOnMeta,
QtcProcess::SplitError *err,
const Environment *env, const QString *pwd) const Environment *env, const QString *pwd)
{ {
static const QString pwdName = QLatin1String("PWD"); static const QString pwdName = QLatin1String("PWD");
@@ -448,7 +475,7 @@ QStringList QtcProcess::splitArgs(const QString &args, bool abortOnMeta, SplitEr
if (pos >= args.length()) if (pos >= args.length())
goto quoteerr; goto quoteerr;
c = args.unicode()[pos++]; c = args.unicode()[pos++];
} else if (abortOnMeta && isMeta(c)) { } else if (abortOnMeta && isMetaUnix(c)) {
goto metaerr; goto metaerr;
} }
cret += c; cret += c;
@@ -466,22 +493,20 @@ QStringList QtcProcess::splitArgs(const QString &args, bool abortOnMeta, SplitEr
okret: okret:
if (err) if (err)
*err = SplitOk; *err = QtcProcess::SplitOk;
return ret; return ret;
quoteerr: quoteerr:
if (err) if (err)
*err = BadQuoting; *err = QtcProcess::BadQuoting;
return QStringList(); return QStringList();
metaerr: metaerr:
if (err) if (err)
*err = FoundMeta; *err = QtcProcess::FoundMeta;
return QStringList(); return QStringList();
} }
#endif // Q_OS_WIN
inline static bool isSpecialCharUnix(ushort c) inline static bool isSpecialCharUnix(ushort c)
{ {
// Chars that should be quoted (TM). This includes: // Chars that should be quoted (TM). This includes:
@@ -501,6 +526,16 @@ inline static bool hasSpecialCharsUnix(const QString &arg)
return false; return false;
} }
QStringList QtcProcess::splitArgs(const QString &args, OsType osType,
bool abortOnMeta, QtcProcess::SplitError *err,
const Environment *env, const QString *pwd)
{
if (osType == OsTypeWindows)
return splitArgsWin(args, abortOnMeta, err, env, pwd);
else
return splitArgsUnix(args, abortOnMeta, err, env, pwd);
}
QString QtcProcess::quoteArgUnix(const QString &arg) QString QtcProcess::quoteArgUnix(const QString &arg)
{ {
if (!arg.length()) if (!arg.length())
@@ -515,23 +550,7 @@ QString QtcProcess::quoteArgUnix(const QString &arg)
return ret; return ret;
} }
void QtcProcess::addArgUnix(QString *args, const QString &arg) static bool isSpecialCharWin(ushort c)
{
if (!args->isEmpty())
*args += QLatin1Char(' ');
*args += quoteArgUnix(arg);
}
QString QtcProcess::joinArgsUnix(const QStringList &args)
{
QString ret;
foreach (const QString &arg, args)
addArgUnix(&ret, arg);
return ret;
}
#ifdef Q_OS_WIN
inline static bool isSpecialChar(ushort c)
{ {
// Chars that should be quoted (TM). This includes: // Chars that should be quoted (TM). This includes:
// - control chars & space // - control chars & space
@@ -545,21 +564,21 @@ inline static bool isSpecialChar(ushort c)
return (c < sizeof(iqm) * 8) && (iqm[c / 8] & (1 << (c & 7))); return (c < sizeof(iqm) * 8) && (iqm[c / 8] & (1 << (c & 7)));
} }
inline static bool hasSpecialChars(const QString &arg) static bool hasSpecialCharsWin(const QString &arg)
{ {
for (int x = arg.length() - 1; x >= 0; --x) for (int x = arg.length() - 1; x >= 0; --x)
if (isSpecialChar(arg.unicode()[x].unicode())) if (isSpecialCharWin(arg.unicode()[x].unicode()))
return true; return true;
return false; return false;
} }
QString QtcProcess::quoteArg(const QString &arg) static QString quoteArgWin(const QString &arg)
{ {
if (!arg.length()) if (!arg.length())
return QString::fromLatin1("\"\""); return QString::fromLatin1("\"\"");
QString ret(arg); QString ret(arg);
if (hasSpecialChars(ret)) { if (hasSpecialCharsWin(ret)) {
// Quotes are escaped and their preceding backslashes are doubled. // Quotes are escaped and their preceding backslashes are doubled.
// It's impossible to escape anything inside a quoted string on cmd // It's impossible to escape anything inside a quoted string on cmd
// level, so the outer quoting must be "suspended". // level, so the outer quoting must be "suspended".
@@ -578,21 +597,38 @@ QString QtcProcess::quoteArg(const QString &arg)
return ret; return ret;
} }
void QtcProcess::addArg(QString *args, const QString &arg) QtcProcess::Arguments QtcProcess::prepareArgs(const QString &cmd, SplitError *err, OsType osType,
const Environment *env, const QString *pwd)
{
if (osType == OsTypeWindows)
return prepareArgsWin(cmd, err, env, pwd);
else
return Arguments::createUnixArgs(splitArgs(cmd, osType, true, err, env, pwd));
}
QString QtcProcess::quoteArg(const QString &arg, OsType osType)
{
if (osType == OsTypeWindows)
return quoteArgWin(arg);
else
return quoteArgUnix(arg);
}
void QtcProcess::addArg(QString *args, const QString &arg, OsType osType)
{ {
if (!args->isEmpty()) if (!args->isEmpty())
*args += QLatin1Char(' '); *args += QLatin1Char(' ');
*args += quoteArg(arg); *args += quoteArg(arg, osType);
} }
QString QtcProcess::joinArgs(const QStringList &args) QString QtcProcess::joinArgs(const QStringList &args, OsType osType)
{ {
QString ret; QString ret;
foreach (const QString &arg, args) foreach (const QString &arg, args)
addArg(&ret, arg); addArg(&ret, arg, osType);
return ret; return ret;
} }
#endif
void QtcProcess::addArgs(QString *args, const QString &inArgs) void QtcProcess::addArgs(QString *args, const QString &inArgs)
{ {
@@ -609,44 +645,36 @@ void QtcProcess::addArgs(QString *args, const QStringList &inArgs)
addArg(args, arg); addArg(args, arg);
} }
#ifdef Q_OS_WIN bool QtcProcess::prepareCommand(const QString &command, const QString &arguments,
void QtcProcess::prepareCommand(const QString &command, const QString &arguments, QString *outCmd, Arguments *outArgs, OsType osType,
QString *outCmd, QString *outArgs,
const Environment *env, const QString *pwd) const Environment *env, const QString *pwd)
{ {
QtcProcess::SplitError err; QtcProcess::SplitError err;
*outArgs = QtcProcess::prepareArgs(arguments, &err, env, pwd); *outArgs = QtcProcess::prepareArgs(arguments, &err, osType, env, pwd);
if (err == QtcProcess::SplitOk) { if (err == QtcProcess::SplitOk) {
*outCmd = command; *outCmd = command;
} else { } else {
if (osType == OsTypeWindows) {
*outCmd = QString::fromLatin1(qgetenv("COMSPEC")); *outCmd = QString::fromLatin1(qgetenv("COMSPEC"));
*outArgs = QLatin1String("/v:off /s /c \"") *outArgs = Arguments::createWindowsArgs(QLatin1String("/v:off /s /c \"")
+ quoteArg(QDir::toNativeSeparators(command)) + QLatin1Char(' ') + arguments + quoteArg(QDir::toNativeSeparators(command)) + QLatin1Char(' ') + arguments
+ QLatin1Char('"'); + QLatin1Char('"'));
}
}
#else
bool QtcProcess::prepareCommand(const QString &command, const QString &arguments,
QString *outCmd, QStringList *outArgs,
const Environment *env, const QString *pwd)
{
QtcProcess::SplitError err;
*outArgs = QtcProcess::prepareArgs(arguments, &err, env, pwd);
if (err == QtcProcess::SplitOk) {
*outCmd = command;
} else { } else {
if (err != QtcProcess::FoundMeta) if (err != QtcProcess::FoundMeta)
return false; return false;
*outCmd = QLatin1String("/bin/sh"); *outCmd = QLatin1String("/bin/sh");
*outArgs << QLatin1String("-c") << (quoteArg(command) + QLatin1Char(' ') + arguments); *outArgs = Arguments::createUnixArgs(QStringList()
<< QLatin1String("-c")
<< (quoteArg(command) + QLatin1Char(' ') + arguments));
}
} }
return true; return true;
} }
#endif
void QtcProcess::start() void QtcProcess::start()
{ {
Environment env; Environment env;
const OsType osType = HostOsInfo::hostOs();
if (m_haveEnv) { if (m_haveEnv) {
if (m_environment.size() == 0) if (m_environment.size() == 0)
qWarning("QtcProcess::start: Empty environment set when running '%s'.", qPrintable(m_command)); qWarning("QtcProcess::start: Empty environment set when running '%s'.", qPrintable(m_command));
@@ -655,16 +683,12 @@ void QtcProcess::start()
// If the process environemnt has no libraryPath, // If the process environemnt has no libraryPath,
// Qt will copy creator's libraryPath into the process environment. // Qt will copy creator's libraryPath into the process environment.
// That's brain dead, and we work around it // That's brain dead, and we work around it
#if defined(Q_OS_UNIX) if (osType != OsTypeWindows) { // a.k.a "Unixoid"
# if defined(Q_OS_MAC) const QString libraryPath =
static const char libraryPathC[] = "DYLD_LIBRARY_PATH"; QLatin1String(osType == OsTypeMac ? "DYLD_LIBRARY_PATH" : "LD_LIBRARY_PATH");
# else
static const char libraryPathC[] = "LD_LIBRARY_PATH";
# endif
const QString libraryPath = QLatin1String(libraryPathC);
if (env.constFind(libraryPath) == env.constEnd()) if (env.constFind(libraryPath) == env.constEnd())
env.set(libraryPath, QString()); env.set(libraryPath, QString());
#endif }
QProcess::setEnvironment(env.toStringList()); QProcess::setEnvironment(env.toStringList());
} else { } else {
env = Environment::systemEnvironment(); env = Environment::systemEnvironment();
@@ -672,27 +696,28 @@ void QtcProcess::start()
const QString &workDir = workingDirectory(); const QString &workDir = workingDirectory();
QString command; QString command;
QtcProcess::Arguments arguments;
bool success = prepareCommand(m_command, m_arguments, &command, &arguments, osType, &env, &workDir);
if (osType == OsTypeWindows) {
QString args = arguments.toWindowsArgs();
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
QString arguments; setNativeArguments(args);
QStringList argList; #endif
prepareCommand(m_command, m_arguments, &command, &arguments, &env, &workDir);
setNativeArguments(arguments);
if (m_useCtrlCStub) { if (m_useCtrlCStub) {
argList << QDir::toNativeSeparators(command); args = QDir::toNativeSeparators(command);
command = QCoreApplication::applicationDirPath() + QLatin1String("/qtcreator_ctrlc_stub.exe"); command = QCoreApplication::applicationDirPath() + QLatin1String("/qtcreator_ctrlc_stub.exe");
} }
QProcess::start(command, argList); QProcess::start(command, QStringList(args));
#else } else {
QStringList arguments; if (!success) {
if (!prepareCommand(m_command, m_arguments, &command, &arguments, &env, &workDir)) {
setErrorString(tr("Error in command line.")); setErrorString(tr("Error in command line."));
// Should be FailedToStart, but we cannot set the process error from the outside, // Should be FailedToStart, but we cannot set the process error from the outside,
// so it would be inconsistent. // so it would be inconsistent.
emit error(QProcess::UnknownError); emit error(QProcess::UnknownError);
return; return;
} }
QProcess::start(command, arguments); QProcess::start(command, arguments.toUnixArgs());
#endif }
} }
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
@@ -738,10 +763,9 @@ void QtcProcess::interrupt()
#endif #endif
} }
#ifdef Q_OS_WIN
// This function assumes that the resulting string will be quoted. // This function assumes that the resulting string will be quoted.
// That's irrelevant if it does not contain quotes itself. // That's irrelevant if it does not contain quotes itself.
static int quoteArgInternal(QString &ret, int bslashes) static int quoteArgInternalWin(QString &ret, int bslashes)
{ {
// Quotes are escaped and their preceding backslashes are doubled. // Quotes are escaped and their preceding backslashes are doubled.
// It's impossible to escape anything inside a quoted string on cmd // It's impossible to escape anything inside a quoted string on cmd
@@ -765,32 +789,6 @@ static int quoteArgInternal(QString &ret, int bslashes)
return bslashes; return bslashes;
} }
#else
// The main state of the Unix shell parser
enum MxQuoting { MxBasic, MxSingleQuote, MxDoubleQuote, MxParen, MxSubst, MxGroup, MxMath };
typedef struct {
MxQuoting current;
// Bizarrely enough, double quoting has an impact on the behavior of some
// complex expressions within the quoted string.
bool dquote;
} MxState;
QT_BEGIN_NAMESPACE
Q_DECLARE_TYPEINFO(MxState, Q_PRIMITIVE_TYPE);
QT_END_NAMESPACE
// Pushed state for the case where a $(()) expansion turns out bogus
typedef struct {
QString str;
int pos, varPos;
} MxSave;
QT_BEGIN_NAMESPACE
Q_DECLARE_TYPEINFO(MxSave, Q_MOVABLE_TYPE);
QT_END_NAMESPACE
#include <QStack>
#endif
// TODO: This documentation is relevant for end-users. Where to put it? // TODO: This documentation is relevant for end-users. Where to put it?
/** /**
@@ -864,7 +862,7 @@ QT_END_NAMESPACE
* \return false if the string could not be parsed and therefore no safe * \return false if the string could not be parsed and therefore no safe
* substitution was possible * substitution was possible
*/ */
bool QtcProcess::expandMacros(QString *cmd, AbstractMacroExpander *mx) bool QtcProcess::expandMacros(QString *cmd, AbstractMacroExpander *mx, OsType osType)
{ {
QString str = *cmd; QString str = *cmd;
if (str.isEmpty()) if (str.isEmpty())
@@ -878,7 +876,7 @@ bool QtcProcess::expandMacros(QString *cmd, AbstractMacroExpander *mx)
int pos = 0; int pos = 0;
#ifdef Q_OS_WIN if (osType == OsTypeWindows) {
enum { // cmd.exe parsing state enum { // cmd.exe parsing state
ShellBasic, // initial state ShellBasic, // initial state
ShellQuoted, // double-quoted state => *no* other meta chars are interpreted ShellQuoted, // double-quoted state => *no* other meta chars are interpreted
@@ -913,12 +911,12 @@ bool QtcProcess::expandMacros(QString *cmd, AbstractMacroExpander *mx)
crtState = CrtNeedWord; crtState = CrtNeedWord;
} }
} else { } else {
if (hasSpecialChars(rsts)) { if (hasSpecialCharsWin(rsts)) {
if (crtState == CrtClosed) { if (crtState == CrtClosed) {
// Quoted expando right after closing quote. Can't do that. // Quoted expando right after closing quote. Can't do that.
return false; return false;
} }
int tbslashes = quoteArgInternal(rsts, 0); int tbslashes = quoteArgInternalWin(rsts, 0);
rsts.prepend(QLatin1Char('"')); rsts.prepend(QLatin1Char('"'));
if (rbslashes) if (rbslashes)
rsts.prepend(QString(rbslashes, QLatin1Char('\\'))); rsts.prepend(QString(rbslashes, QLatin1Char('\\')));
@@ -928,11 +926,11 @@ bool QtcProcess::expandMacros(QString *cmd, AbstractMacroExpander *mx)
crtState = CrtInWord; // We know that this string contains no spaces. crtState = CrtInWord; // We know that this string contains no spaces.
// We know that this string contains no quotes, // We know that this string contains no quotes,
// so the function won't make a mess. // so the function won't make a mess.
rbslashes = quoteArgInternal(rsts, rbslashes); rbslashes = quoteArgInternalWin(rsts, rbslashes);
} }
} }
} else { } else {
rbslashes = quoteArgInternal(rsts, rbslashes); rbslashes = quoteArgInternalWin(rsts, rbslashes);
} }
str.replace(pos, varLen, rsts); str.replace(pos, varLen, rsts);
pos += rsts.length(); pos += rsts.length();
@@ -1026,7 +1024,8 @@ bool QtcProcess::expandMacros(QString *cmd, AbstractMacroExpander *mx)
} }
pos++; pos++;
} }
#else } else {
// !Windows
MxState state = { MxBasic, false }; MxState state = { MxBasic, false };
QStack<MxState> sstack; QStack<MxState> sstack;
QStack<MxSave> ostack; QStack<MxSave> ostack;
@@ -1181,16 +1180,16 @@ bool QtcProcess::expandMacros(QString *cmd, AbstractMacroExpander *mx)
pos++; pos++;
} }
// FIXME? May complain if (!sstack.empty()), but we don't really care anyway. // FIXME? May complain if (!sstack.empty()), but we don't really care anyway.
#endif }
*cmd = str; *cmd = str;
return true; return true;
} }
QString QtcProcess::expandMacros(const QString &str, AbstractMacroExpander *mx) QString QtcProcess::expandMacros(const QString &str, AbstractMacroExpander *mx, OsType osType)
{ {
QString ret = str; QString ret = str;
expandMacros(&ret, mx); expandMacros(&ret, mx, osType);
return ret; return ret;
} }
@@ -1203,7 +1202,7 @@ bool QtcProcess::ArgIterator::next()
m_simple = true; m_simple = true;
m_value.clear(); m_value.clear();
#ifdef Q_OS_WIN if (m_osType == OsTypeWindows) {
enum { // cmd.exe parsing state enum { // cmd.exe parsing state
ShellBasic, // initial state ShellBasic, // initial state
ShellQuoted, // double-quoted state => *no* other meta chars are interpreted ShellQuoted, // double-quoted state => *no* other meta chars are interpreted
@@ -1223,7 +1222,7 @@ bool QtcProcess::ArgIterator::next()
if (shellState == ShellBasic && cc == '^') { if (shellState == ShellBasic && cc == '^') {
varState = NoVar; varState = NoVar;
shellState = ShellEscaped; shellState = ShellEscaped;
} else if ((shellState == ShellBasic && isMetaChar(cc)) || !cc) { // A "bit" simplistic ... } else if ((shellState == ShellBasic && isMetaCharWin(cc)) || !cc) { // A "bit" simplistic ...
// We ignore crtQuote state here. Whatever ... // We ignore crtQuote state here. Whatever ...
doReturn: doReturn:
if (m_simple) if (m_simple)
@@ -1302,7 +1301,7 @@ bool QtcProcess::ArgIterator::next()
shellState = ShellBasic; shellState = ShellBasic;
} }
} }
#else } else {
MxState state = { MxBasic, false }; MxState state = { MxBasic, false };
QStack<MxState> sstack; QStack<MxState> sstack;
QStack<int> ostack; QStack<int> ostack;
@@ -1448,7 +1447,7 @@ bool QtcProcess::ArgIterator::next()
return true; return true;
} }
return false; return false;
#endif }
} }
void QtcProcess::ArgIterator::deleteArg() void QtcProcess::ArgIterator::deleteArg()
@@ -1470,8 +1469,6 @@ void QtcProcess::ArgIterator::appendArg(const QString &str)
m_pos += qstr.length() + 1; m_pos += qstr.length() + 1;
} }
namespace Utils {
QTCREATOR_UTILS_EXPORT unsigned long qPidToPid(const Q_PID qpid) QTCREATOR_UTILS_EXPORT unsigned long qPidToPid(const Q_PID qpid)
{ {
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
@@ -1482,4 +1479,40 @@ QTCREATOR_UTILS_EXPORT unsigned long qPidToPid(const Q_PID qpid)
#endif #endif
} }
QtcProcess::Arguments QtcProcess::Arguments::createWindowsArgs(const QString &args)
{
Arguments result;
result.m_windowsArgs = args;
result.m_isWindows = true;
return result;
}
QtcProcess::Arguments QtcProcess::Arguments::createUnixArgs(const QStringList &args)
{
Arguments result;
result.m_unixArgs = args;
result.m_isWindows = false;
return result;
}
QString QtcProcess::Arguments::toWindowsArgs() const
{
QTC_CHECK(m_isWindows);
return m_windowsArgs;
}
QStringList QtcProcess::Arguments::toUnixArgs() const
{
QTC_CHECK(!m_isWindows);
return m_unixArgs;
}
QString QtcProcess::Arguments::toString() const
{
if (m_isWindows)
return m_windowsArgs;
else
return QtcProcess::joinArgs(m_unixArgs, OsTypeLinux);
}
} // namespace Utils } // namespace Utils

View File

@@ -56,6 +56,22 @@ public:
void terminate(); void terminate();
void interrupt(); void interrupt();
class QTCREATOR_UTILS_EXPORT Arguments
{
public:
static Arguments createWindowsArgs(const QString &args);
static Arguments createUnixArgs(const QStringList &args);
QString toWindowsArgs() const;
QStringList toUnixArgs() const;
QString toString() const;
private:
QString m_windowsArgs;
QStringList m_unixArgs;
bool m_isWindows;
};
enum SplitError { enum SplitError {
SplitOk = 0, //! All went just fine SplitOk = 0, //! All went just fine
BadQuoting, //! Command contains quoting errors BadQuoting, //! Command contains quoting errors
@@ -64,45 +80,33 @@ public:
//! Quote a single argument for usage in a unix shell command //! Quote a single argument for usage in a unix shell command
static QString quoteArgUnix(const QString &arg); static QString quoteArgUnix(const QString &arg);
//! Quote a single argument and append it to a unix shell command
static void addArgUnix(QString *args, const QString &arg);
//! Join an argument list into a unix shell command
static QString joinArgsUnix(const QStringList &args);
#ifdef Q_OS_WIN
//! Quote a single argument for usage in a shell command //! Quote a single argument for usage in a shell command
static QString quoteArg(const QString &arg); static QString quoteArg(const QString &arg, OsType osType = HostOsInfo::hostOs());
//! Quote a single argument and append it to a shell command //! Quote a single argument and append it to a shell command
static void addArg(QString *args, const QString &arg); static void addArg(QString *args, const QString &arg, OsType osType = HostOsInfo::hostOs());
//! Join an argument list into a shell command //! Join an argument list into a shell command
static QString joinArgs(const QStringList &args); static QString joinArgs(const QStringList &args, OsType osType = HostOsInfo::hostOs());
//! Prepare argument of a shell command for feeding into QProcess //! Prepare argument of a shell command for feeding into QProcess
static QString prepareArgs(const QString &cmd, SplitError *err, static Arguments prepareArgs(const QString &cmd, SplitError *err,
OsType osType = HostOsInfo::hostOs(),
const Environment *env = 0, const QString *pwd = 0); const Environment *env = 0, const QString *pwd = 0);
//! Prepare a shell command for feeding into QProcess //! Prepare a shell command for feeding into QProcess
static void prepareCommand(const QString &command, const QString &arguments,
QString *outCmd, QString *outArgs,
const Environment *env = 0, const QString *pwd = 0);
#else
static QString quoteArg(const QString &arg) { return quoteArgUnix(arg); }
static void addArg(QString *args, const QString &arg) { addArgUnix(args, arg); }
static QString joinArgs(const QStringList &args) { return joinArgsUnix(args); }
static QStringList prepareArgs(const QString &cmd, SplitError *err,
const Environment *env = 0, const QString *pwd = 0)
{ return splitArgs(cmd, true, err, env, pwd); }
static bool prepareCommand(const QString &command, const QString &arguments, static bool prepareCommand(const QString &command, const QString &arguments,
QString *outCmd, QStringList *outArgs, QString *outCmd, Arguments *outArgs, OsType osType = HostOsInfo::hostOs(),
const Environment *env = 0, const QString *pwd = 0); const Environment *env = 0, const QString *pwd = 0);
#endif
//! Quote and append each argument to a shell command //! Quote and append each argument to a shell command
static void addArgs(QString *args, const QStringList &inArgs); static void addArgs(QString *args, const QStringList &inArgs);
//! Append already quoted arguments to a shell command //! Append already quoted arguments to a shell command
static void addArgs(QString *args, const QString &inArgs); static void addArgs(QString *args, const QString &inArgs);
//! Split a shell command into separate arguments. ArgIterator is usually a better choice. //! Split a shell command into separate arguments. ArgIterator is usually a better choice.
static QStringList splitArgs(const QString &cmd, bool abortOnMeta = false, SplitError *err = 0, static QStringList splitArgs(const QString &cmd, OsType osType = HostOsInfo::hostOs(),
bool abortOnMeta = false, SplitError *err = 0,
const Environment *env = 0, const QString *pwd = 0); const Environment *env = 0, const QString *pwd = 0);
//! Safely replace the expandos in a shell command //! Safely replace the expandos in a shell command
static bool expandMacros(QString *cmd, AbstractMacroExpander *mx); static bool expandMacros(QString *cmd, AbstractMacroExpander *mx,
static QString expandMacros(const QString &str, AbstractMacroExpander *mx); OsType osType = HostOsInfo::hostOs());
static QString expandMacros(const QString &str, AbstractMacroExpander *mx,
OsType osType = HostOsInfo::hostOs());
/*! Iterate over arguments from a command line. /*! Iterate over arguments from a command line.
* Assumes that the name of the actual command is *not* part of the line. * Assumes that the name of the actual command is *not* part of the line.
@@ -110,7 +114,9 @@ public:
*/ */
class QTCREATOR_UTILS_EXPORT ArgIterator { class QTCREATOR_UTILS_EXPORT ArgIterator {
public: public:
ArgIterator(QString *str) : m_str(str), m_pos(0), m_prev(-1) {} ArgIterator(QString *str, OsType osType = HostOsInfo::hostOs())
: m_str(str), m_pos(0), m_prev(-1), m_osType(osType)
{}
//! Get the next argument. Returns false on encountering end of first command. //! Get the next argument. Returns false on encountering end of first command.
bool next(); bool next();
//! True iff the argument is a plain string, possibly after unquoting. //! True iff the argument is a plain string, possibly after unquoting.
@@ -126,11 +132,14 @@ public:
QString *m_str, m_value; QString *m_str, m_value;
int m_pos, m_prev; int m_pos, m_prev;
bool m_simple; bool m_simple;
OsType m_osType;
}; };
class QTCREATOR_UTILS_EXPORT ConstArgIterator { class QTCREATOR_UTILS_EXPORT ConstArgIterator {
public: public:
ConstArgIterator(const QString &str) : m_str(str), m_ait(&m_str) {} ConstArgIterator(const QString &str, OsType osType = HostOsInfo::hostOs())
: m_str(str), m_ait(&m_str, osType)
{}
bool next() { return m_ait.next(); } bool next() { return m_ait.next(); }
bool isSimple() const { return m_ait.isSimple(); } bool isSimple() const { return m_ait.isSimple(); }
QString value() const { return m_ait.value(); } QString value() const { return m_ait.value(); }

View File

@@ -121,13 +121,14 @@ void FileUtils::openTerminal(const QString &path)
// Get terminal application // Get terminal application
QString terminalEmulator; QString terminalEmulator;
QStringList args; QStringList args;
if (HostOsInfo::isWindowsHost()) { const OsType hostOs = HostOsInfo::hostOs();
if (hostOs == OsTypeWindows) {
terminalEmulator = ConsoleProcess::defaultTerminalEmulator(); terminalEmulator = ConsoleProcess::defaultTerminalEmulator();
} else if (HostOsInfo::isMacHost()) { } else if (hostOs == OsTypeMac) {
terminalEmulator = ICore::resourcePath() terminalEmulator = ICore::resourcePath()
+ QLatin1String("/scripts/openTerminal.command"); + QLatin1String("/scripts/openTerminal.command");
} else { } else {
args = QtcProcess::splitArgs(ConsoleProcess::terminalEmulator(ICore::settings())); args = QtcProcess::splitArgs(ConsoleProcess::terminalEmulator(ICore::settings()), hostOs);
terminalEmulator = args.takeFirst(); terminalEmulator = args.takeFirst();
args.append(QString::fromLocal8Bit(qgetenv("SHELL"))); args.append(QString::fromLocal8Bit(qgetenv("SHELL")));
} }

View File

@@ -4771,11 +4771,12 @@ void GdbEngine::write(const QByteArray &data)
bool GdbEngine::prepareCommand() bool GdbEngine::prepareCommand()
{ {
#ifdef Q_OS_WIN if (HostOsInfo::isWindowsHost()) {
Utils::QtcProcess::SplitError perr; DebuggerStartParameters &sp = startParameters();
startParameters().processArgs = Utils::QtcProcess::prepareArgs( QtcProcess::SplitError perr;
startParameters().processArgs, &perr, sp.processArgs = QtcProcess::prepareArgs(sp.processArgs, &perr,
&startParameters().environment, &startParameters().workingDirectory); Utils::HostOsInfo::hostOs(),
&sp.environment, &sp.workingDirectory).toWindowsArgs();
if (perr != Utils::QtcProcess::SplitOk) { if (perr != Utils::QtcProcess::SplitOk) {
// perr == BadQuoting is never returned on Windows // perr == BadQuoting is never returned on Windows
// FIXME? QTCREATORBUG-2809 // FIXME? QTCREATORBUG-2809
@@ -4783,7 +4784,7 @@ bool GdbEngine::prepareCommand()
"Debugging complex command lines is currently not supported on Windows."), Core::Id()); "Debugging complex command lines is currently not supported on Windows."), Core::Id());
return false; return false;
} }
#endif }
return true; return true;
} }

View File

@@ -201,11 +201,7 @@ void LldbEngine::setupInferior()
const DebuggerStartParameters &sp = startParameters(); const DebuggerStartParameters &sp = startParameters();
QString executable; QString executable;
#ifdef Q_OS_WIN Utils::QtcProcess::Arguments args;
QString args;
#else
QStringList args;
#endif
Utils::QtcProcess::prepareCommand(QFileInfo(sp.executable).absoluteFilePath(), Utils::QtcProcess::prepareCommand(QFileInfo(sp.executable).absoluteFilePath(),
sp.processArgs, &executable, &args); sp.processArgs, &executable, &args);
@@ -213,12 +209,8 @@ void LldbEngine::setupInferior()
cmd.arg("executable", executable); cmd.arg("executable", executable);
cmd.arg("startMode", sp.startMode); // directly relying on this is brittle wrt. insertions, so check it here cmd.arg("startMode", sp.startMode); // directly relying on this is brittle wrt. insertions, so check it here
cmd.beginList("processArgs"); cmd.beginList("processArgs");
#ifdef Q_OS_WIN foreach (const QString &arg, args.toUnixArgs())
// fixme?
#else
foreach (const QString &arg, args)
cmd.arg(arg.toUtf8().toHex()); cmd.arg(arg.toUtf8().toHex());
#endif
cmd.endList(); cmd.endList();
// it is better not to check the start mode on the python sid (as we would have to duplicate the // it is better not to check the start mode on the python sid (as we would have to duplicate the

View File

@@ -2990,7 +2990,7 @@ bool GitClient::tryLauchingGitK(const QProcessEnvironment &env,
VcsBase::VcsBaseOutputWindow *outwin = VcsBase::VcsBaseOutputWindow::instance(); VcsBase::VcsBaseOutputWindow *outwin = VcsBase::VcsBaseOutputWindow::instance();
const QString gitkOpts = settings()->stringValue(GitSettings::gitkOptionsKey); const QString gitkOpts = settings()->stringValue(GitSettings::gitkOptionsKey);
if (!gitkOpts.isEmpty()) if (!gitkOpts.isEmpty())
arguments.append(Utils::QtcProcess::splitArgs(gitkOpts)); arguments.append(Utils::QtcProcess::splitArgs(gitkOpts, Utils::HostOsInfo::hostOs()));
if (!fileName.isEmpty()) if (!fileName.isEmpty())
arguments << QLatin1String("--") << fileName; arguments << QLatin1String("--") << fileName;
outwin->appendCommand(workingDirectory, binary, arguments); outwin->appendCommand(workingDirectory, binary, arguments);

View File

@@ -51,6 +51,7 @@
using namespace ProjectExplorer; using namespace ProjectExplorer;
using namespace QmakeProjectManager; using namespace QmakeProjectManager;
using namespace Utils;
namespace Ios { namespace Ios {
namespace Internal { namespace Internal {
@@ -341,27 +342,27 @@ QString IosRunConfigurationWidget::argListToString(const QStringList &args) cons
QStringList IosRunConfigurationWidget::stringToArgList(const QString &args) const QStringList IosRunConfigurationWidget::stringToArgList(const QString &args) const
{ {
Utils::QtcProcess::SplitError err; QtcProcess::SplitError err;
QStringList res = Utils::QtcProcess::splitArgs(args, false, &err); QStringList res = QtcProcess::splitArgs(args, OsTypeMac, false, &err);
switch (err) { switch (err) {
case Utils::QtcProcess::SplitOk: case QtcProcess::SplitOk:
break; break;
case Utils::QtcProcess::BadQuoting: case QtcProcess::BadQuoting:
if (args.at(args.size()-1) == QLatin1Char('\\')) { if (args.at(args.size()-1) == QLatin1Char('\\')) {
res = Utils::QtcProcess::splitArgs(args + QLatin1Char('\\'), false, &err); res = QtcProcess::splitArgs(args + QLatin1Char('\\'), OsTypeMac, false, &err);
if (err != Utils::QtcProcess::SplitOk) if (err != QtcProcess::SplitOk)
res = Utils::QtcProcess::splitArgs(args + QLatin1Char('\\') + QLatin1Char('\''), res = QtcProcess::splitArgs(args + QLatin1Char('\\') + QLatin1Char('\''),
false, &err); OsTypeMac, false, &err);
if (err != Utils::QtcProcess::SplitOk) if (err != QtcProcess::SplitOk)
res = Utils::QtcProcess::splitArgs(args + QLatin1Char('\\') + QLatin1Char('\"'), res = QtcProcess::splitArgs(args + QLatin1Char('\\') + QLatin1Char('\"'),
false, &err); OsTypeMac, false, &err);
} }
if (err != Utils::QtcProcess::SplitOk) if (err != QtcProcess::SplitOk)
res = Utils::QtcProcess::splitArgs(args + QLatin1Char('\''), false, &err); res = QtcProcess::splitArgs(args + QLatin1Char('\''), OsTypeMac, false, &err);
if (err != Utils::QtcProcess::SplitOk) if (err != QtcProcess::SplitOk)
res = Utils::QtcProcess::splitArgs(args + QLatin1Char('\"'), false, &err); res = QtcProcess::splitArgs(args + QLatin1Char('\"'), OsTypeMac, false, &err);
break; break;
case Utils::QtcProcess::FoundMeta: case QtcProcess::FoundMeta:
qDebug() << "IosRunConfigurationWidget FoundMeta (should not happen)"; qDebug() << "IosRunConfigurationWidget FoundMeta (should not happen)";
break; break;
} }

View File

@@ -928,13 +928,14 @@ void GccToolChainConfigWidget::makeReadOnlyImpl()
QStringList GccToolChainConfigWidget::splitString(const QString &s) QStringList GccToolChainConfigWidget::splitString(const QString &s)
{ {
QtcProcess::SplitError splitError; QtcProcess::SplitError splitError;
QStringList res = QtcProcess::splitArgs(s, false, &splitError); const OsType osType = HostOsInfo::hostOs();
QStringList res = QtcProcess::splitArgs(s, osType, false, &splitError);
if (splitError != QtcProcess::SplitOk){ if (splitError != QtcProcess::SplitOk){
res = QtcProcess::splitArgs(s + QLatin1Char('\\'), false, &splitError); res = QtcProcess::splitArgs(s + QLatin1Char('\\'), osType, false, &splitError);
if (splitError != QtcProcess::SplitOk){ if (splitError != QtcProcess::SplitOk){
res = QtcProcess::splitArgs(s + QLatin1Char('"'), false, &splitError); res = QtcProcess::splitArgs(s + QLatin1Char('"'), osType, false, &splitError);
if (splitError != QtcProcess::SplitOk) if (splitError != QtcProcess::SplitOk)
res = QtcProcess::splitArgs(s + QLatin1Char('\''), false, &splitError); res = QtcProcess::splitArgs(s + QLatin1Char('\''), osType, false, &splitError);
} }
} }
return res; return res;

View File

@@ -169,20 +169,12 @@ QString ProcessParameters::prettyArguments() const
{ {
QString margs = effectiveArguments(); QString margs = effectiveArguments();
QString workDir = effectiveWorkingDirectory(); QString workDir = effectiveWorkingDirectory();
#ifdef Q_OS_WIN
QString args;
#else
QStringList args;
#endif
Utils::QtcProcess::SplitError err; Utils::QtcProcess::SplitError err;
args = Utils::QtcProcess::prepareArgs(margs, &err, &m_environment, &workDir); Utils::QtcProcess::Arguments args =
Utils::QtcProcess::prepareArgs(margs, &err, Utils::HostOsInfo::hostOs(), &m_environment, &workDir);
if (err != Utils::QtcProcess::SplitOk) if (err != Utils::QtcProcess::SplitOk)
return margs; // Sorry, too complex - just fall back. return margs; // Sorry, too complex - just fall back.
#ifdef Q_OS_WIN return args.toString();
return args;
#else
return Utils::QtcProcess::joinArgs(args);
#endif
} }
QString ProcessParameters::summary(const QString &displayName) const QString ProcessParameters::summary(const QString &displayName) const

View File

@@ -69,7 +69,7 @@ QString LinuxDeviceProcess::fullCommandLine() const
fullCommandLine.append(quote(executable())); fullCommandLine.append(quote(executable()));
if (!arguments().isEmpty()) { if (!arguments().isEmpty()) {
fullCommandLine.append(QLatin1Char(' ')); fullCommandLine.append(QLatin1Char(' '));
fullCommandLine.append(Utils::QtcProcess::joinArgsUnix(arguments())); fullCommandLine.append(Utils::QtcProcess::joinArgs(arguments(), Utils::OsTypeLinux));
} }
return fullCommandLine; return fullCommandLine;
} }

View File

@@ -207,7 +207,7 @@ QString RemoteLinuxRunConfiguration::remoteExecutableFilePath() const
void RemoteLinuxRunConfiguration::setArguments(const QString &args) void RemoteLinuxRunConfiguration::setArguments(const QString &args)
{ {
d->arguments = QtcProcess::splitArgs(args); // TODO: Widget should be list-based. d->arguments = QtcProcess::splitArgs(args, OsTypeLinux); // TODO: Widget should be list-based.
} }
QString RemoteLinuxRunConfiguration::workingDirectory() const QString RemoteLinuxRunConfiguration::workingDirectory() const

File diff suppressed because it is too large Load Diff