forked from qt-creator/qt-creator
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:
@@ -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 "
|
||||||
|
@@ -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();
|
||||||
|
@@ -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
|
||||||
|
@@ -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(); }
|
||||||
|
@@ -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")));
|
||||||
}
|
}
|
||||||
|
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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
|
||||||
|
@@ -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);
|
||||||
|
@@ -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;
|
||||||
}
|
}
|
||||||
|
@@ -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;
|
||||||
|
@@ -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
|
||||||
|
@@ -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;
|
||||||
}
|
}
|
||||||
|
@@ -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
Reference in New Issue
Block a user