forked from qt-creator/qt-creator
make QMakeParser take a QStringRef as input
the only place where this actually saves a deep copy is the evaluation of if(), but as a side effect the parser is now able to deal with not null-terminated strings, which is kinda nice as well. Change-Id: Ib6d08617aa79d2f9eaecd4906d4d548f34bf377d Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io> Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@theqtcompany.com> (cherry picked from qtbase/ad17a35853fe21a93fc34f7b2d9262c5ac992b29) Reviewed-by: Jake Petroules <jake.petroules@qt.io>
This commit is contained in:
@@ -1229,7 +1229,7 @@ QPair<ProFile *, QStringList> QmakePriFileNode::readProFile(const QString &file)
|
||||
QMakeVfs vfs;
|
||||
QtSupport::ProMessageHandler handler;
|
||||
QMakeParser parser(0, &vfs, &handler);
|
||||
includeFile = parser.parsedProBlock(contents, file, 1);
|
||||
includeFile = parser.parsedProBlock(QStringRef(&contents), file, 1);
|
||||
}
|
||||
return qMakePair(includeFile, lines);
|
||||
}
|
||||
@@ -1264,7 +1264,8 @@ bool QmakePriFileNode::renameFile(const QString &oldName,
|
||||
|
||||
// We need to re-parse here: The file has changed.
|
||||
QMakeParser parser(0, 0, 0);
|
||||
includeFile = parser.parsedProBlock(lines.join(QLatin1Char('\n')),
|
||||
QString contents = lines.join(QLatin1Char('\n'));
|
||||
includeFile = parser.parsedProBlock(QStringRef(&contents),
|
||||
m_projectFilePath.toString(), 1, QMakeParser::FullGrammar);
|
||||
QTC_ASSERT(includeFile, return false); // The file should still be valid after what we did.
|
||||
|
||||
|
@@ -175,7 +175,7 @@ QString ProWriter::compileScope(const QString &scope)
|
||||
if (scope.isEmpty())
|
||||
return QString();
|
||||
QMakeParser parser(0, 0, 0);
|
||||
ProFile *includeFile = parser.parsedProBlock(scope, QLatin1String("no-file"), 1);
|
||||
ProFile *includeFile = parser.parsedProBlock(QStringRef(&scope), QLatin1String("no-file"), 1);
|
||||
if (!includeFile)
|
||||
return QString();
|
||||
QString result = includeFile->items();
|
||||
|
@@ -1221,7 +1221,8 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
|
||||
return ReturnFalse; // Another qmake breakage
|
||||
case T_EVAL: {
|
||||
VisitReturn ret = ReturnFalse;
|
||||
ProFile *pro = m_parser->parsedProBlock(args.join(statics.field_sep),
|
||||
QString contents = args.join(statics.field_sep);
|
||||
ProFile *pro = m_parser->parsedProBlock(QStringRef(&contents),
|
||||
m_current.pro->fileName(), m_current.line);
|
||||
if (m_cumulative || pro->isOk()) {
|
||||
m_locationStack.push(m_current);
|
||||
@@ -1237,7 +1238,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
|
||||
evalError(fL1S("if(condition) requires one argument."));
|
||||
return ReturnFalse;
|
||||
}
|
||||
return evaluateConditional(args.at(0).toQString(),
|
||||
return evaluateConditional(args.at(0).toQStringRef(),
|
||||
m_current.pro->fileName(), m_current.line);
|
||||
}
|
||||
case T_CONFIG: {
|
||||
|
@@ -1288,7 +1288,7 @@ void QMakeEvaluator::setupProject()
|
||||
void QMakeEvaluator::evaluateCommand(const QString &cmds, const QString &where)
|
||||
{
|
||||
if (!cmds.isEmpty()) {
|
||||
ProFile *pro = m_parser->parsedProBlock(cmds, where, -1);
|
||||
ProFile *pro = m_parser->parsedProBlock(QStringRef(&cmds), where, -1);
|
||||
if (pro->isOk()) {
|
||||
m_locationStack.push(m_current);
|
||||
visitProBlock(pro, pro->tokPtr());
|
||||
@@ -1780,7 +1780,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateExpandFunction(
|
||||
}
|
||||
|
||||
QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateConditional(
|
||||
const QString &cond, const QString &where, int line)
|
||||
const QStringRef &cond, const QString &where, int line)
|
||||
{
|
||||
VisitReturn ret = ReturnFalse;
|
||||
ProFile *pro = m_parser->parsedProBlock(cond, where, line, QMakeParser::TestGrammar);
|
||||
@@ -1798,7 +1798,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::checkRequirements(const ProStringLis
|
||||
{
|
||||
ProStringList &failed = valuesRef(ProKey("QMAKE_FAILED_REQUIREMENTS"));
|
||||
for (const ProString &dep : deps) {
|
||||
VisitReturn vr = evaluateConditional(dep.toQString(), m_current.pro->fileName(), m_current.line);
|
||||
VisitReturn vr = evaluateConditional(dep.toQStringRef(), m_current.pro->fileName(), m_current.line);
|
||||
if (vr == ReturnError)
|
||||
return ReturnError;
|
||||
if (vr != ReturnTrue)
|
||||
|
@@ -211,7 +211,7 @@ public:
|
||||
ProStringList evaluateBuiltinExpand(int func_t, const ProKey &function, const ProStringList &args);
|
||||
VisitReturn evaluateBuiltinConditional(int func_t, const ProKey &function, const ProStringList &args);
|
||||
|
||||
VisitReturn evaluateConditional(const QString &cond, const QString &where, int line = -1);
|
||||
VisitReturn evaluateConditional(const QStringRef &cond, const QString &where, int line = -1);
|
||||
#ifdef PROEVALUATOR_FULL
|
||||
VisitReturn checkRequirements(const ProStringList &deps);
|
||||
#endif
|
||||
|
@@ -221,7 +221,7 @@ ProFile *QMakeParser::parsedProFile(const QString &fileName, ParseFlags flags)
|
||||
}
|
||||
|
||||
ProFile *QMakeParser::parsedProBlock(
|
||||
const QString &contents, const QString &name, int line, SubGrammar grammar)
|
||||
const QStringRef &contents, const QString &name, int line, SubGrammar grammar)
|
||||
{
|
||||
ProFile *pro = new ProFile(name);
|
||||
read(pro, contents, line, grammar);
|
||||
@@ -244,7 +244,7 @@ bool QMakeParser::read(ProFile *pro, ParseFlags flags)
|
||||
fL1S("Cannot read %1: %2").arg(pro->fileName(), errStr));
|
||||
return false;
|
||||
}
|
||||
read(pro, content, 1, FullGrammar);
|
||||
read(pro, QStringRef(&content), 1, FullGrammar);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -286,7 +286,7 @@ void QMakeParser::finalizeHashStr(ushort *buf, uint len)
|
||||
buf[-2] = (ushort)(hash >> 16);
|
||||
}
|
||||
|
||||
void QMakeParser::read(ProFile *pro, const QString &in, int line, SubGrammar grammar)
|
||||
void QMakeParser::read(ProFile *pro, const QStringRef &in, int line, SubGrammar grammar)
|
||||
{
|
||||
m_proFile = pro;
|
||||
m_lineNo = line;
|
||||
@@ -334,8 +334,8 @@ void QMakeParser::read(ProFile *pro, const QString &in, int line, SubGrammar gra
|
||||
QStack<ParseCtx> xprStack;
|
||||
xprStack.reserve(10);
|
||||
|
||||
// We rely on QStrings being null-terminated, so don't maintain a global end pointer.
|
||||
const ushort *cur = (const ushort *)in.unicode();
|
||||
const ushort *inend = cur + in.length();
|
||||
m_canElse = false;
|
||||
freshLine:
|
||||
m_state = StNew;
|
||||
@@ -418,7 +418,7 @@ void QMakeParser::read(ProFile *pro, const QString &in, int line, SubGrammar gra
|
||||
int indent;
|
||||
|
||||
if (context == CtxPureValue) {
|
||||
end = (const ushort *)in.unicode() + in.length();
|
||||
end = inend;
|
||||
cptr = 0;
|
||||
lineCont = false;
|
||||
indent = 0; // just gcc being stupid
|
||||
@@ -430,24 +430,30 @@ void QMakeParser::read(ProFile *pro, const QString &in, int line, SubGrammar gra
|
||||
|
||||
// First, skip leading whitespace
|
||||
for (indent = 0; ; ++cur, ++indent) {
|
||||
if (cur == inend) {
|
||||
cur = 0;
|
||||
goto flushLine;
|
||||
}
|
||||
c = *cur;
|
||||
if (c == '\n') {
|
||||
++cur;
|
||||
goto flushLine;
|
||||
} else if (!c) {
|
||||
cur = 0;
|
||||
goto flushLine;
|
||||
} else if (c != ' ' && c != '\t' && c != '\r') {
|
||||
break;
|
||||
}
|
||||
if (c != ' ' && c != '\t' && c != '\r')
|
||||
break;
|
||||
}
|
||||
|
||||
// Then strip comments. Yep - no escaping is possible.
|
||||
for (cptr = cur;; ++cptr) {
|
||||
if (cptr == inend) {
|
||||
end = cptr;
|
||||
break;
|
||||
}
|
||||
c = *cptr;
|
||||
if (c == '#') {
|
||||
for (end = cptr; (c = *++cptr);) {
|
||||
if (c == '\n') {
|
||||
end = cptr;
|
||||
while (++cptr < inend) {
|
||||
if (*cptr == '\n') {
|
||||
++cptr;
|
||||
break;
|
||||
}
|
||||
@@ -460,10 +466,6 @@ void QMakeParser::read(ProFile *pro, const QString &in, int line, SubGrammar gra
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!c) {
|
||||
end = cptr;
|
||||
break;
|
||||
}
|
||||
if (c == '\n') {
|
||||
end = cptr++;
|
||||
break;
|
||||
@@ -1215,7 +1217,7 @@ void QMakeParser::finalizeCall(ushort *&tokPtr, ushort *uc, ushort *ptr, int arg
|
||||
bool QMakeParser::resolveVariable(ushort *xprPtr, int tlen, int needSep, ushort **ptr,
|
||||
ushort **buf, QString *xprBuff,
|
||||
ushort **tokPtr, QString *tokBuff,
|
||||
const ushort *cur, const QString &in)
|
||||
const ushort *cur, const QStringRef &in)
|
||||
{
|
||||
QString out;
|
||||
m_tmp.setRawData((const QChar *)xprPtr, tlen);
|
||||
|
@@ -83,7 +83,7 @@ public:
|
||||
enum SubGrammar { FullGrammar, TestGrammar, ValueGrammar };
|
||||
// fileName is expected to be absolute and cleanPath()ed.
|
||||
ProFile *parsedProFile(const QString &fileName, ParseFlags flags = ParseDefault);
|
||||
ProFile *parsedProBlock(const QString &contents, const QString &name, int line = 0,
|
||||
ProFile *parsedProBlock(const QStringRef &contents, const QString &name, int line = 0,
|
||||
SubGrammar grammar = FullGrammar);
|
||||
|
||||
void discardFileFromCache(const QString &fileName);
|
||||
@@ -126,7 +126,7 @@ private:
|
||||
};
|
||||
|
||||
bool read(ProFile *pro, ParseFlags flags);
|
||||
void read(ProFile *pro, const QString &content, int line, SubGrammar grammar);
|
||||
void read(ProFile *pro, const QStringRef &content, int line, SubGrammar grammar);
|
||||
|
||||
ALWAYS_INLINE void putTok(ushort *&tokPtr, ushort tok);
|
||||
ALWAYS_INLINE void putBlockLen(ushort *&tokPtr, uint len);
|
||||
@@ -137,7 +137,7 @@ private:
|
||||
ALWAYS_INLINE bool resolveVariable(ushort *xprPtr, int tlen, int needSep, ushort **ptr,
|
||||
ushort **buf, QString *xprBuff,
|
||||
ushort **tokPtr, QString *tokBuff,
|
||||
const ushort *cur, const QString &in);
|
||||
const ushort *cur, const QStringRef &in);
|
||||
void finalizeCond(ushort *&tokPtr, ushort *uc, ushort *ptr, int wordCount);
|
||||
void finalizeCall(ushort *&tokPtr, ushort *uc, ushort *ptr, int argc);
|
||||
void warnOperator(const char *msg);
|
||||
|
Reference in New Issue
Block a user