add $$system_quote() & $$shell_quote() functions

follow suit with qmake ...

Change-Id: I3db37ba73cb709d8baf200600ae29241bc26bee5
Reviewed-by: Daniel Teske <daniel.teske@nokia.com>
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@nokia.com>
This commit is contained in:
Oswald Buddenhagen
2012-07-25 20:02:23 +02:00
parent 3522a3e050
commit 3d629b1a2b
3 changed files with 62 additions and 33 deletions

View File

@@ -91,11 +91,40 @@ QString IoUtils::resolvePath(const QString &baseDir, const QString &fileName)
return QDir::cleanPath(baseDir + QLatin1Char('/') + fileName); return QDir::cleanPath(baseDir + QLatin1Char('/') + fileName);
} }
#ifdef QT_BOOTSTRAPPED inline static
inline static bool isSpecialChar(ushort c) bool hasSpecialChars(const QString &arg, const uchar (&iqm)[16])
{
for (int x = arg.length() - 1; x >= 0; --x) {
ushort c = arg.unicode()[x].unicode();
if ((c < sizeof(iqm) * 8) && (iqm[c / 8] & (1 << (c & 7))))
return true;
}
return false;
}
QString IoUtils::shellQuoteUnix(const QString &arg)
{
// Chars that should be quoted (TM). This includes:
static const uchar iqm[] = {
0xff, 0xff, 0xff, 0xff, 0xdf, 0x07, 0x00, 0xd8,
0x00, 0x00, 0x00, 0x38, 0x01, 0x00, 0x00, 0x78
}; // 0-32 \'"$`<>|;&(){}*?#!~[]
if (!arg.length())
return QString::fromLatin1("\"\"");
QString ret(arg);
if (hasSpecialChars(ret, iqm)) {
ret.replace(QLatin1Char('\''), QLatin1String("'\\''"));
ret.prepend(QLatin1Char('\''));
ret.append(QLatin1Char('\''));
}
return ret;
}
QString IoUtils::shellQuoteWin(const QString &arg)
{ {
// Chars that should be quoted (TM). This includes: // Chars that should be quoted (TM). This includes:
#ifdef Q_OS_WIN
// - control chars & space // - control chars & space
// - the shell meta chars "&()<>^| // - the shell meta chars "&()<>^|
// - the potential separators ,;= // - the potential separators ,;=
@@ -103,32 +132,12 @@ inline static bool isSpecialChar(ushort c)
0xff, 0xff, 0xff, 0xff, 0x45, 0x13, 0x00, 0x78, 0xff, 0xff, 0xff, 0xff, 0x45, 0x13, 0x00, 0x78,
0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10
}; };
#else
static const uchar iqm[] = {
0xff, 0xff, 0xff, 0xff, 0xdf, 0x07, 0x00, 0xd8,
0x00, 0x00, 0x00, 0x38, 0x01, 0x00, 0x00, 0x78
}; // 0-32 \'"$`<>|;&(){}*?#!~[]
#endif
return (c < sizeof(iqm) * 8) && (iqm[c / 8] & (1 << (c & 7)));
}
inline static bool hasSpecialChars(const QString &arg)
{
for (int x = arg.length() - 1; x >= 0; --x)
if (isSpecialChar(arg.unicode()[x].unicode()))
return true;
return false;
}
QString IoUtils::shellQuote(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 (hasSpecialChars(ret, iqm)) {
#ifdef Q_OS_WIN
// 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".
@@ -141,14 +150,8 @@ QString IoUtils::shellQuote(const QString &arg)
--i; --i;
ret.insert(i, QLatin1Char('"')); ret.insert(i, QLatin1Char('"'));
ret.prepend(QLatin1Char('"')); ret.prepend(QLatin1Char('"'));
#else // Q_OS_WIN
ret.replace(QLatin1Char('\''), QLatin1String("'\\''"));
ret.prepend(QLatin1Char('\''));
ret.append(QLatin1Char('\''));
#endif // Q_OS_WIN
} }
return ret; return ret;
} }
#endif
QT_END_NAMESPACE QT_END_NAMESPACE

View File

@@ -55,8 +55,13 @@ public:
static bool isAbsolutePath(const QString &fileName) { return !isRelativePath(fileName); } static bool isAbsolutePath(const QString &fileName) { return !isRelativePath(fileName); }
static QStringRef fileName(const QString &fileName); // Requires normalized path static QStringRef fileName(const QString &fileName); // Requires normalized path
static QString resolvePath(const QString &baseDir, const QString &fileName); static QString resolvePath(const QString &baseDir, const QString &fileName);
#ifdef QT_BOOTSTRAPPED static QString shellQuoteUnix(const QString &arg);
static QString shellQuote(const QString &arg); static QString shellQuoteWin(const QString &arg);
static QString shellQuote(const QString &arg)
#ifdef Q_OS_UNIX
{ return shellQuoteUnix(arg); }
#else
{ return shellQuoteWin(arg); }
#endif #endif
}; };

View File

@@ -78,7 +78,7 @@ enum ExpandFunc {
E_UPPER, E_LOWER, E_FILES, E_PROMPT, E_RE_ESCAPE, E_VAL_ESCAPE, E_UPPER, E_LOWER, E_FILES, E_PROMPT, E_RE_ESCAPE, E_VAL_ESCAPE,
E_REPLACE, E_SORT_DEPENDS, E_RESOLVE_DEPENDS, E_ENUMERATE_VARS, E_REPLACE, E_SORT_DEPENDS, E_RESOLVE_DEPENDS, E_ENUMERATE_VARS,
E_SHADOWED, E_ABSOLUTE_PATH, E_RELATIVE_PATH, E_CLEAN_PATH, E_SHADOWED, E_ABSOLUTE_PATH, E_RELATIVE_PATH, E_CLEAN_PATH,
E_SYSTEM_PATH, E_SHELL_PATH E_SYSTEM_PATH, E_SHELL_PATH, E_SYSTEM_QUOTE, E_SHELL_QUOTE
}; };
enum TestFunc { enum TestFunc {
@@ -131,6 +131,8 @@ void QMakeEvaluator::initFunctionStatics()
{ "clean_path", E_CLEAN_PATH }, { "clean_path", E_CLEAN_PATH },
{ "system_path", E_SYSTEM_PATH }, { "system_path", E_SYSTEM_PATH },
{ "shell_path", E_SHELL_PATH }, { "shell_path", E_SHELL_PATH },
{ "system_quote", E_SYSTEM_QUOTE },
{ "shell_quote", E_SHELL_QUOTE },
}; };
for (unsigned i = 0; i < sizeof(expandInits)/sizeof(expandInits[0]); ++i) for (unsigned i = 0; i < sizeof(expandInits)/sizeof(expandInits[0]); ++i)
statics.expands.insert(ProString(expandInits[i].name), expandInits[i].func); statics.expands.insert(ProString(expandInits[i].name), expandInits[i].func);
@@ -890,6 +892,25 @@ ProStringList QMakeEvaluator::evaluateExpandFunction(
ret << ProString(rstr, NoHash).setSource(args.at(0)); ret << ProString(rstr, NoHash).setSource(args.at(0));
} }
break; break;
case E_SYSTEM_QUOTE:
if (args.count() != 1)
evalError(fL1S("system_quote(arg) requires one argument."));
else
ret << ProString(IoUtils::shellQuote(args.at(0).toQString(m_tmp1)),
NoHash).setSource(args.at(0));
break;
case E_SHELL_QUOTE:
if (args.count() != 1) {
evalError(fL1S("shell_quote(arg) requires one argument."));
} else {
QString rstr = args.at(0).toQString(m_tmp1);
if (m_option->dir_sep.at(0) != QLatin1Char('/'))
rstr = IoUtils::shellQuoteWin(rstr);
else
rstr = IoUtils::shellQuoteUnix(rstr);
ret << ProString(rstr, NoHash).setSource(args.at(0));
}
break;
case E_INVALID: case E_INVALID:
evalError(fL1S("'%1' is not a recognized replace function.") evalError(fL1S("'%1' is not a recognized replace function.")
.arg(func.toQString(m_tmp1))); .arg(func.toQString(m_tmp1)));