forked from qt-creator/qt-creator
sync variable expansion and list splitting with qmake
This commit is contained in:
@@ -978,11 +978,9 @@ QString ProFileEvaluator::Private::currentDirectory() const
|
||||
|
||||
QStringList ProFileEvaluator::Private::expandVariableReferences(const QString &str)
|
||||
{
|
||||
bool fOK;
|
||||
bool *ok = &fOK;
|
||||
QStringList ret;
|
||||
if (ok)
|
||||
*ok = true;
|
||||
// if (ok)
|
||||
// *ok = true;
|
||||
if (str.isEmpty())
|
||||
return ret;
|
||||
|
||||
@@ -998,7 +996,10 @@ QStringList ProFileEvaluator::Private::expandVariableReferences(const QString &s
|
||||
const ushort DOT = '.';
|
||||
const ushort SPACE = ' ';
|
||||
const ushort TAB = '\t';
|
||||
const ushort SINGLEQUOTE = '\'';
|
||||
const ushort DOUBLEQUOTE = '"';
|
||||
|
||||
ushort unicode, quote = 0;
|
||||
const QChar *str_data = str.data();
|
||||
const int str_len = str.length();
|
||||
|
||||
@@ -1008,13 +1009,120 @@ QStringList ProFileEvaluator::Private::expandVariableReferences(const QString &s
|
||||
int replaced = 0;
|
||||
QString current;
|
||||
for (int i = 0; i < str_len; ++i) {
|
||||
ushort c = str_data[i].unicode();
|
||||
unicode = str_data[i].unicode();
|
||||
const int start_var = i;
|
||||
if (c == BACKSLASH) {
|
||||
if (unicode == DOLLAR && str_len > i+2) {
|
||||
unicode = str_data[++i].unicode();
|
||||
if (unicode == DOLLAR) {
|
||||
term = 0;
|
||||
var.clear();
|
||||
args.clear();
|
||||
enum { VAR, ENVIRON, FUNCTION, PROPERTY } var_type = VAR;
|
||||
unicode = str_data[++i].unicode();
|
||||
if (unicode == LSQUARE) {
|
||||
unicode = str_data[++i].unicode();
|
||||
term = RSQUARE;
|
||||
var_type = PROPERTY;
|
||||
} else if (unicode == LCURLY) {
|
||||
unicode = str_data[++i].unicode();
|
||||
var_type = VAR;
|
||||
term = RCURLY;
|
||||
} else if (unicode == LPAREN) {
|
||||
unicode = str_data[++i].unicode();
|
||||
var_type = ENVIRON;
|
||||
term = RPAREN;
|
||||
}
|
||||
forever {
|
||||
if (!(unicode & (0xFF<<8)) &&
|
||||
unicode != DOT && unicode != UNDERSCORE &&
|
||||
//unicode != SINGLEQUOTE && unicode != DOUBLEQUOTE &&
|
||||
(unicode < 'a' || unicode > 'z') && (unicode < 'A' || unicode > 'Z') &&
|
||||
(unicode < '0' || unicode > '9'))
|
||||
break;
|
||||
var.append(QChar(unicode));
|
||||
if (++i == str_len)
|
||||
break;
|
||||
unicode = str_data[i].unicode();
|
||||
// at this point, i points to either the 'term' or 'next' character (which is in unicode)
|
||||
}
|
||||
if (var_type == VAR && unicode == LPAREN) {
|
||||
var_type = FUNCTION;
|
||||
int depth = 0;
|
||||
forever {
|
||||
if (++i == str_len)
|
||||
break;
|
||||
unicode = str_data[i].unicode();
|
||||
if (unicode == LPAREN) {
|
||||
depth++;
|
||||
} else if (unicode == RPAREN) {
|
||||
if (!depth)
|
||||
break;
|
||||
--depth;
|
||||
}
|
||||
args.append(QChar(unicode));
|
||||
}
|
||||
if (++i < str_len)
|
||||
unicode = str_data[i].unicode();
|
||||
else
|
||||
unicode = 0;
|
||||
// at this point i is pointing to the 'next' character (which is in unicode)
|
||||
// this might actually be a term character since you can do $${func()}
|
||||
}
|
||||
if (term) {
|
||||
if (unicode != term) {
|
||||
q->logMessage(format("Missing %1 terminator [found %2]")
|
||||
.arg(QChar(term))
|
||||
.arg(unicode ? QString(unicode) : QString::fromLatin1(("end-of-line"))));
|
||||
// if (ok)
|
||||
// *ok = false;
|
||||
return QStringList();
|
||||
}
|
||||
} else {
|
||||
// move the 'cursor' back to the last char of the thing we were looking at
|
||||
--i;
|
||||
}
|
||||
// since i never points to the 'next' character, there is no reason for this to be set
|
||||
unicode = 0;
|
||||
|
||||
QStringList replacement;
|
||||
if (var_type == ENVIRON) {
|
||||
replacement = split_value_list(QString::fromLocal8Bit(qgetenv(var.toLatin1().constData())));
|
||||
} else if (var_type == PROPERTY) {
|
||||
replacement << propertyValue(var);
|
||||
} else if (var_type == FUNCTION) {
|
||||
replacement << evaluateExpandFunction(var, args);
|
||||
} else if (var_type == VAR) {
|
||||
replacement = values(var);
|
||||
}
|
||||
if (!(replaced++) && start_var)
|
||||
current = str.left(start_var);
|
||||
if (!replacement.isEmpty()) {
|
||||
if (quote) {
|
||||
current += replacement.join(QString(Option::field_sep));
|
||||
} else {
|
||||
current += replacement.takeFirst();
|
||||
if (!replacement.isEmpty()) {
|
||||
if (!current.isEmpty())
|
||||
ret.append(current);
|
||||
current = replacement.takeLast();
|
||||
if (!replacement.isEmpty())
|
||||
ret += replacement;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (replaced)
|
||||
current.append(QLatin1Char('$'));
|
||||
}
|
||||
}
|
||||
if (quote && unicode == quote) {
|
||||
unicode = 0;
|
||||
quote = 0;
|
||||
} else if (unicode == BACKSLASH) {
|
||||
bool escape = false;
|
||||
const char *symbols = "[]{}()$\\";
|
||||
const char *symbols = "[]{}()$\\'\"";
|
||||
for (const char *s = symbols; *s; ++s) {
|
||||
if (str_data[i+1] == (ushort)*s) {
|
||||
if (str_data[i+1].unicode() == (ushort)*s) {
|
||||
i++;
|
||||
escape = true;
|
||||
if (!(replaced++))
|
||||
@@ -1023,129 +1131,27 @@ QStringList ProFileEvaluator::Private::expandVariableReferences(const QString &s
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!escape && replaced)
|
||||
current.append(QChar(c));
|
||||
continue;
|
||||
}
|
||||
if (c == SPACE || c == TAB) {
|
||||
c = 0;
|
||||
if (escape || !replaced)
|
||||
unicode =0;
|
||||
} else if (!quote && (unicode == SINGLEQUOTE || unicode == DOUBLEQUOTE)) {
|
||||
quote = unicode;
|
||||
unicode = 0;
|
||||
if (!(replaced++) && i)
|
||||
current = str.left(i);
|
||||
} else if (!quote && (unicode == SPACE || unicode == TAB)) {
|
||||
unicode = 0;
|
||||
if (!current.isEmpty()) {
|
||||
unquote(¤t);
|
||||
ret.append(current);
|
||||
current.clear();
|
||||
}
|
||||
} else if (c == DOLLAR && str_len > i+2) {
|
||||
c = str_data[++i].unicode();
|
||||
if (c == DOLLAR) {
|
||||
term = 0;
|
||||
var.clear();
|
||||
args.clear();
|
||||
enum { VAR, ENVIRON, FUNCTION, PROPERTY } var_type = VAR;
|
||||
c = str_data[++i].unicode();
|
||||
if (c == LSQUARE) {
|
||||
c = str_data[++i].unicode();
|
||||
term = RSQUARE;
|
||||
var_type = PROPERTY;
|
||||
} else if (c == LCURLY) {
|
||||
c = str_data[++i].unicode();
|
||||
var_type = VAR;
|
||||
term = RCURLY;
|
||||
} else if (c == LPAREN) {
|
||||
c = str_data[++i].unicode();
|
||||
var_type = ENVIRON;
|
||||
term = RPAREN;
|
||||
}
|
||||
while (1) {
|
||||
if (!(c & (0xFF<<8)) &&
|
||||
c != DOT && c != UNDERSCORE &&
|
||||
(c < 'a' || c > 'z') && (c < 'A' || c > 'Z') && (c < '0' || c > '9'))
|
||||
break;
|
||||
var.append(QChar(c));
|
||||
if (++i == str_len)
|
||||
break;
|
||||
c = str_data[i].unicode();
|
||||
}
|
||||
if (var_type == VAR && c == LPAREN) {
|
||||
var_type = FUNCTION;
|
||||
int depth = 0;
|
||||
while (1) {
|
||||
if (++i == str_len)
|
||||
break;
|
||||
c = str_data[i].unicode();
|
||||
if (c == LPAREN) {
|
||||
depth++;
|
||||
} else if (c == RPAREN) {
|
||||
if (!depth)
|
||||
break;
|
||||
--depth;
|
||||
}
|
||||
args.append(QChar(c));
|
||||
}
|
||||
if (i < str_len-1)
|
||||
c = str_data[++i].unicode();
|
||||
else
|
||||
c = 0;
|
||||
}
|
||||
if (term) {
|
||||
if (c != term) {
|
||||
q->logMessage(format("Missing %1 terminator [found %2]")
|
||||
.arg(QChar(term)).arg(QChar(c)));
|
||||
if (ok)
|
||||
*ok = false;
|
||||
return QStringList();
|
||||
}
|
||||
c = 0;
|
||||
} else if (i > str_len-1) {
|
||||
c = 0;
|
||||
}
|
||||
|
||||
QStringList replacement;
|
||||
if (var_type == ENVIRON) {
|
||||
replacement << QString::fromLocal8Bit(qgetenv(var.toLocal8Bit().constData()));
|
||||
} else if (var_type == PROPERTY) {
|
||||
replacement << propertyValue(var);
|
||||
//if (prop)
|
||||
// replacement = QStringList(prop->value(var));
|
||||
} else if (var_type == FUNCTION) {
|
||||
replacement << evaluateExpandFunction(var, args);
|
||||
} else if (var_type == VAR) {
|
||||
replacement += values(var);
|
||||
}
|
||||
if (!(replaced++) && start_var)
|
||||
current = str.left(start_var);
|
||||
if (!replacement.isEmpty()) {
|
||||
/* If a list is beteen two strings make sure it expands in such a way
|
||||
* that the string to the left is prepended to the first string and
|
||||
* the string to the right is appended to the last string, example:
|
||||
* LIST = a b c
|
||||
* V3 = x/$$LIST/f.cpp
|
||||
* message($$member(V3,0)) # Outputs "x/a"
|
||||
* message($$member(V3,1)) # Outputs "b"
|
||||
* message($$member(V3,2)) # Outputs "c/f.cpp"
|
||||
*/
|
||||
current.append(replacement.at(0));
|
||||
for (int i = 1; i < replacement.count(); ++i) {
|
||||
unquote(¤t);
|
||||
ret.append(current);
|
||||
current = replacement.at(i);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (replaced)
|
||||
current.append(QLatin1Char('$'));
|
||||
}
|
||||
}
|
||||
if (replaced && c != 0)
|
||||
current.append(QChar(c));
|
||||
if (replaced && unicode)
|
||||
current.append(QChar(unicode));
|
||||
}
|
||||
if (!replaced) {
|
||||
current = str;
|
||||
unquote(¤t);
|
||||
if (!replaced)
|
||||
ret = QStringList(str);
|
||||
else if (!current.isEmpty())
|
||||
ret.append(current);
|
||||
} else if (!current.isEmpty()) {
|
||||
unquote(¤t);
|
||||
ret.append(current);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user