make split_value_list() sane

don't count parentheses, don't nest quotes, don't create empty elements,
let backslash uniformly escape. in short, behave like a sane parser.

Change-Id: I29252fbe14fd6d28217450ec41cf8acfb2e30681
Reviewed-by: Joerg Bornemann <joerg.bornemann@digia.com>
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@digia.com>
This commit is contained in:
Oswald Buddenhagen 2013-03-07 21:47:42 +01:00 committed by The Qt Project
parent cd94b543cb
commit 6c22b9b3e8

View File

@ -264,48 +264,50 @@ ProStringList QMakeEvaluator::split_value_list(const QString &vals, const ProFil
{
QString build;
ProStringList ret;
QStack<char> quote;
const ushort SPACE = ' ';
const ushort LPAREN = '(';
const ushort RPAREN = ')';
const ushort SINGLEQUOTE = '\'';
const ushort DOUBLEQUOTE = '"';
const ushort BACKSLASH = '\\';
if (!source)
source = currentProFile();
ushort unicode;
const QChar *vals_data = vals.data();
const int vals_len = vals.length();
int parens = 0;
ushort quote = 0;
bool hadWord = false;
for (int x = 0; x < vals_len; x++) {
unicode = vals_data[x].unicode();
if (x != (int)vals_len-1 && unicode == BACKSLASH &&
(vals_data[x+1].unicode() == SINGLEQUOTE || vals_data[x+1].unicode() == DOUBLEQUOTE)) {
build += vals_data[x++]; //get that 'escape'
} else if (!quote.isEmpty() && unicode == quote.top()) {
quote.pop();
} else if (unicode == SINGLEQUOTE || unicode == DOUBLEQUOTE) {
quote.push(unicode);
} else if (unicode == RPAREN) {
--parens;
} else if (unicode == LPAREN) {
++parens;
ushort unicode = vals_data[x].unicode();
if (unicode == quote) {
quote = 0;
continue;
}
if (!parens && quote.isEmpty() && vals_data[x] == SPACE) {
ret << ProString(build).setSource(source);
build.clear();
} else {
build += vals_data[x];
switch (unicode) {
case '"':
case '\'':
quote = unicode;
hadWord = true;
continue;
case ' ':
case '\t':
if (!quote) {
if (hadWord) {
ret << ProString(build).setSource(source);
build.clear();
hadWord = false;
}
continue;
}
build += QChar(unicode);
break;
case '\\':
if (x + 1 != vals_len)
unicode = vals_data[++x].unicode();
// fallthrough
default:
hadWord = true;
build += QChar(unicode);
break;
}
}
if (!build.isEmpty())
if (hadWord)
ret << ProString(build).setSource(source);
if (parens)
deprecationWarning(fL1S("Unmatched parentheses are deprecated."));
return ret;
}