sync variable expansion and list splitting with qmake

This commit is contained in:
Oswald Buddenhagen
2009-03-11 17:47:43 +01:00
parent 5bc97eb1a0
commit 027b52a25d
2 changed files with 151 additions and 156 deletions

View File

@@ -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(&current);
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(&current);
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(&current);
if (!replaced)
ret = QStringList(str);
else if (!current.isEmpty())
ret.append(current);
} else if (!current.isEmpty()) {
unquote(&current);
ret.append(current);
}
return ret;
}