don't pre-split RHS of variable assignments

creating tons of items is a tad allocation-intensive and thus slow.

this is probably slower for often-included files, as now the splitting
is done in every evaluation pass.
This commit is contained in:
Oswald Buddenhagen
2010-01-14 12:34:46 +01:00
parent 61772da250
commit 9c7d803aec
5 changed files with 158 additions and 267 deletions

View File

@@ -44,13 +44,10 @@ struct AbstractProItemVisitor
virtual ProItem::ProItemReturn visitProLoopIteration() = 0; virtual ProItem::ProItemReturn visitProLoopIteration() = 0;
virtual void visitProLoopCleanup() = 0; virtual void visitProLoopCleanup() = 0;
virtual void visitBeginProVariable(ProVariable *variable) = 0;
virtual void visitEndProVariable(ProVariable *variable) = 0;
virtual ProItem::ProItemReturn visitBeginProFile(ProFile *value) = 0; virtual ProItem::ProItemReturn visitBeginProFile(ProFile *value) = 0;
virtual ProItem::ProItemReturn visitEndProFile(ProFile *value) = 0; virtual ProItem::ProItemReturn visitEndProFile(ProFile *value) = 0;
virtual void visitProValue(ProValue *value) = 0; virtual void visitProVariable(ProVariable *variable) = 0;
virtual ProItem::ProItemReturn visitProFunction(ProFunction *function) = 0; virtual ProItem::ProItemReturn visitProFunction(ProFunction *function) = 0;
virtual void visitProOperator(ProOperator *function) = 0; virtual void visitProOperator(ProOperator *function) = 0;
virtual void visitProCondition(ProCondition *function) = 0; virtual void visitProCondition(ProCondition *function) = 0;

View File

@@ -196,7 +196,8 @@ public:
ProBlock *currentBlock(); ProBlock *currentBlock();
void updateItem(ushort *ptr); void updateItem(ushort *ptr);
void updateItem2(); void updateItem2();
bool insertVariable(ushort *ptr, bool *doSplit, bool *doSemicolon); ProVariable *startVariable(ushort *ptr);
void finalizeVariable(ProVariable *var);
void insertOperator(const char op); void insertOperator(const char op);
void enterScope(bool multiLine); void enterScope(bool multiLine);
void leaveScope(); void leaveScope();
@@ -214,11 +215,9 @@ public:
void visitEndProBlock(ProBlock *block); void visitEndProBlock(ProBlock *block);
ProItem::ProItemReturn visitProLoopIteration(); ProItem::ProItemReturn visitProLoopIteration();
void visitProLoopCleanup(); void visitProLoopCleanup();
void visitBeginProVariable(ProVariable *variable);
void visitEndProVariable(ProVariable *variable);
ProItem::ProItemReturn visitBeginProFile(ProFile *value); ProItem::ProItemReturn visitBeginProFile(ProFile *value);
ProItem::ProItemReturn visitEndProFile(ProFile *value); ProItem::ProItemReturn visitEndProFile(ProFile *value);
void visitProValue(ProValue *value); void visitProVariable(ProVariable *variable);
ProItem::ProItemReturn visitProFunction(ProFunction *function); ProItem::ProItemReturn visitProFunction(ProFunction *function);
void visitProOperator(ProOperator *oper); void visitProOperator(ProOperator *oper);
void visitProCondition(ProCondition *condition); void visitProCondition(ProCondition *condition);
@@ -230,8 +229,8 @@ public:
const ProFile *pro) const; const ProFile *pro) const;
QString propertyValue(const QString &val, bool complain = true) const; QString propertyValue(const QString &val, bool complain = true) const;
QStringList split_value_list(const QString &vals, bool do_semicolon = false); static QStringList split_value_list(const QString &vals, bool do_semicolon = false);
QStringList split_arg_list(const QString &params); static QStringList split_arg_list(const QString &params);
bool isActiveConfig(const QString &config, bool regex = false); bool isActiveConfig(const QString &config, bool regex = false);
QStringList expandVariableReferences(const QString &value); QStringList expandVariableReferences(const QString &value);
void doVariableReplace(QString *str); void doVariableReplace(QString *str);
@@ -266,7 +265,6 @@ public:
struct State { struct State {
bool condition; bool condition;
bool prevCondition; bool prevCondition;
QStringList varVal;
} m_sts; } m_sts;
bool m_invertNext; // Short-lived, so not in State bool m_invertNext; // Short-lived, so not in State
bool m_hadCondition; // Nested calls set it on return, so no need for it to be in State bool m_hadCondition; // Nested calls set it on return, so no need for it to be in State
@@ -358,11 +356,9 @@ bool ProFileEvaluator::Private::read(ProBlock *pro, QTextStream *ts)
m_blockstack.push(pro); m_blockstack.push(pro);
freshLine: freshLine:
ProVariable *currAssignment = 0;
int parens = 0; int parens = 0;
bool inError = false; bool inError = false;
bool inAssignment = false;
bool doSplit = false;
bool doSemicolon = false;
bool putSpace = false; bool putSpace = false;
ushort quote = 0; ushort quote = 0;
while (!ts->atEnd()) { while (!ts->atEnd()) {
@@ -374,7 +370,12 @@ bool ProFileEvaluator::Private::read(ProBlock *pro, QTextStream *ts)
// First, skip leading whitespace // First, skip leading whitespace
forever { forever {
if (cur == end) { // Entirely empty line (sans whitespace) if (cur == end) { // Entirely empty line (sans whitespace)
updateItem2(); if (currAssignment) {
finalizeVariable(currAssignment);
currAssignment = 0;
} else {
updateItem2();
}
finalizeBlock(); finalizeBlock();
++m_lineNo; ++m_lineNo;
goto freshLine; goto freshLine;
@@ -419,7 +420,7 @@ bool ProFileEvaluator::Private::read(ProBlock *pro, QTextStream *ts)
m_proitem.reserve(m_proitem.length() + (end - cur)); m_proitem.reserve(m_proitem.length() + (end - cur));
// Finally, do the tokenization // Finally, do the tokenization
if (!inAssignment) { if (!currAssignment) {
newItem: newItem:
ptr = (ushort *)m_proitem.unicode() + m_proitem.length(); ptr = (ushort *)m_proitem.unicode() + m_proitem.length();
do { do {
@@ -454,8 +455,7 @@ bool ProFileEvaluator::Private::read(ProBlock *pro, QTextStream *ts)
goto nextItem; goto nextItem;
} }
if (c == '=') { if (c == '=') {
if (insertVariable(ptr, &doSplit, &doSemicolon)) { if ((currAssignment = startVariable(ptr))) {
inAssignment = true;
putSpace = false; putSpace = false;
break; break;
} }
@@ -485,97 +485,41 @@ bool ProFileEvaluator::Private::read(ProBlock *pro, QTextStream *ts)
putSpace = true; putSpace = true;
} }
} }
} // !inAssignment } // !currAssignment
nextVal:
ptr = (ushort *)m_proitem.unicode() + m_proitem.length(); ptr = (ushort *)m_proitem.unicode() + m_proitem.length();
do { do {
if (cur == end) if (cur == end)
goto lineEnd; goto lineEnd;
c = *cur++; c = *cur++;
} while (c == ' ' || c == '\t'); } while (c == ' ' || c == '\t');
if (doSplit) { forever {
// Qmake's parser supports truly bizarre quote nesting here, but later if (putSpace) {
// stages (in qmake) don't grok it anyway. So make it simple instead. putSpace = false;
forever { *ptr++ = ' ';
if (c == '\\') {
ushort ec;
if (cur != end && ((ec = *cur) == '"' || ec == '\'')) {
++cur;
if (putSpace) {
putSpace = false;
*ptr++ = ' ';
}
*ptr++ = '\\';
*ptr++ = ec;
goto getNext;
}
} else {
if (quote) {
if (c == quote) {
quote = 0;
} else if (c == ' ' || c == '\t') {
putSpace = true;
goto getNext;
}
} else {
if (c == '"' || c == '\'') {
quote = c;
} else if (c == ')') {
--parens;
} else if (c == '(') {
++parens;
} else if (c == ' ' || c == '\t') {
if (parens) {
putSpace = true;
goto getNext;
}
updateItem(ptr);
// assert(!putSpace);
goto nextVal;
}
}
}
if (putSpace) {
putSpace = false;
*ptr++ = ' ';
}
*ptr++ = c;
getNext:
if (cur == end) {
if (!quote && !parens)
goto flushItem;
break;
}
c = *cur++;
} }
} else { // doSplit *ptr++ = c;
forever {
if (putSpace) {
putSpace = false;
*ptr++ = ' ';
}
*ptr++ = c;
forever { forever {
if (cur == end) if (cur == end)
goto lineEnd; goto lineEnd;
c = *cur++; c = *cur++;
if (c != ' ' && c != '\t') if (c != ' ' && c != '\t')
break; break;
putSpace = true; putSpace = true;
}
} }
} }
lineEnd: lineEnd:
m_proitem.resize(ptr - (ushort *)m_proitem.unicode());
if (lineCont) { if (lineCont) {
m_proitem.resize(ptr - (ushort *)m_proitem.unicode());
putSpace = !m_proitem.isEmpty(); putSpace = !m_proitem.isEmpty();
} else { } else {
flushItem: if (currAssignment) {
updateItem(ptr); finalizeVariable(currAssignment);
currAssignment = 0;
} else {
updateItem2();
}
putSpace = false; putSpace = false;
} }
} // !inError } // !inError
@@ -599,13 +543,13 @@ void ProFileEvaluator::Private::finalizeBlock()
m_block = 0; m_block = 0;
} }
bool ProFileEvaluator::Private::insertVariable(ushort *ptr, bool *doSplit, bool *doSemicolon) ProVariable *ProFileEvaluator::Private::startVariable(ushort *ptr)
{ {
ProVariable::VariableOperator opkind; ProVariable::VariableOperator opkind;
ushort *uc = (ushort *)m_proitem.unicode(); ushort *uc = (ushort *)m_proitem.unicode();
if (ptr == uc) // Line starting with '=', like a conflict marker if (ptr == uc) // Line starting with '=', like a conflict marker
return false; return 0;
switch (*(ptr - 1)) { switch (*(ptr - 1)) {
case '+': case '+':
@@ -630,7 +574,7 @@ bool ProFileEvaluator::Private::insertVariable(ushort *ptr, bool *doSplit, bool
} }
if (ptr == uc) // Line starting with manipulation operator if (ptr == uc) // Line starting with manipulation operator
return false; return 0;
if (*(ptr - 1) == ' ') if (*(ptr - 1) == ' ')
--ptr; --ptr;
@@ -638,20 +582,23 @@ bool ProFileEvaluator::Private::insertVariable(ushort *ptr, bool *doSplit, bool
m_proitem.resize(ptr - uc); m_proitem.resize(ptr - uc);
QString proVar = m_proitem; QString proVar = m_proitem;
proVar.detach(); proVar.detach();
ProBlock *block = m_blockstack.top();
ProVariable *variable = new ProVariable(proVar, block);
variable->setLineNumber(m_lineNo);
variable->setVariableOperator(opkind);
block->appendItem(variable);
m_block = variable;
m_proitem.resize(0); m_proitem.resize(0);
*doSplit = (opkind != ProVariable::ReplaceOperator); ProVariable *variable = new ProVariable(proVar);
*doSemicolon = (proVar == QLatin1String("DEPENDPATH") variable->setLineNumber(m_lineNo);
|| proVar == QLatin1String("INCLUDEPATH")); variable->setVariableOperator(opkind);
return true; return variable;
}
void ProFileEvaluator::Private::finalizeVariable(ProVariable *variable)
{
QString proItem = m_proitem;
proItem.detach();
m_proitem.resize(0);
variable->setValue(proItem);
ProBlock *block = m_blockstack.top();
block->appendItem(variable);
} }
void ProFileEvaluator::Private::insertOperator(const char op) void ProFileEvaluator::Private::insertOperator(const char op)
@@ -730,9 +677,7 @@ void ProFileEvaluator::Private::updateItem2()
ProBlock *block = currentBlock(); ProBlock *block = currentBlock();
ProItem *item; ProItem *item;
if (block->blockKind() & ProBlock::VariableKind) { if (proItem.endsWith(QLatin1Char(')'))) {
item = new ProValue(proItem, static_cast<ProVariable*>(block));
} else if (proItem.endsWith(QLatin1Char(')'))) {
item = new ProFunction(proItem); item = new ProFunction(proItem);
} else { } else {
item = new ProCondition(proItem); item = new ProCondition(proItem);
@@ -1001,89 +946,91 @@ void ProFileEvaluator::Private::visitProLoopCleanup()
m_loopStack.pop_back(); m_loopStack.pop_back();
} }
void ProFileEvaluator::Private::visitBeginProVariable(ProVariable *) void ProFileEvaluator::Private::visitProVariable(ProVariable *var)
{ {
m_sts.varVal.clear(); m_lineNo = var->lineNumber();
} const QString &varName = var->variable();
void ProFileEvaluator::Private::visitEndProVariable(ProVariable *variable) if (var->variableOperator() == ProVariable::ReplaceOperator) { // ~=
{ // DEFINES ~= s/a/b/?[gqi]
QString varName = variable->variable();
switch (variable->variableOperator()) { QString val = var->value();
doVariableReplace(&val);
if (val.length() < 4 || val.at(0) != QLatin1Char('s')) {
logMessage(format("the ~= operator can handle only the s/// function."));
return;
}
QChar sep = val.at(1);
QStringList func = val.split(sep);
if (func.count() < 3 || func.count() > 4) {
logMessage(format("the s/// function expects 3 or 4 arguments."));
return;
}
bool global = false, quote = false, case_sense = false;
if (func.count() == 4) {
global = func[3].indexOf(QLatin1Char('g')) != -1;
case_sense = func[3].indexOf(QLatin1Char('i')) == -1;
quote = func[3].indexOf(QLatin1Char('q')) != -1;
}
QString pattern = func[1];
QString replace = func[2];
if (quote)
pattern = QRegExp::escape(pattern);
QRegExp regexp(pattern, case_sense ? Qt::CaseSensitive : Qt::CaseInsensitive);
if (!m_skipLevel || m_cumulative) {
// We could make a union of modified and unmodified values,
// but this will break just as much as it fixes, so leave it as is.
replaceInList(&m_valuemap[varName], regexp, replace, global);
replaceInList(&m_filevaluemap[currentProFile()][varName], regexp, replace, global);
}
} else {
static const QString deppath(QLatin1String("DEPENDPATH"));
static const QString incpath(QLatin1String("INCLUDEPATH"));
bool doSemicolon = (varName == deppath || varName == incpath);
QStringList varVal;
foreach (const QString &arg, split_value_list(var->value(), doSemicolon))
varVal += expandVariableReferences(arg);
switch (var->variableOperator()) {
default: // ReplaceOperator - cannot happen
case ProVariable::SetOperator: // = case ProVariable::SetOperator: // =
if (!m_cumulative) { if (!m_cumulative) {
if (!m_skipLevel) { if (!m_skipLevel) {
m_valuemap[varName] = m_sts.varVal; m_valuemap[varName] = varVal;
m_filevaluemap[currentProFile()][varName] = m_sts.varVal; m_filevaluemap[currentProFile()][varName] = varVal;
} }
} else { } else {
// We are greedy for values. // We are greedy for values.
m_valuemap[varName] += m_sts.varVal; m_valuemap[varName] += varVal;
m_filevaluemap[currentProFile()][varName] += m_sts.varVal; m_filevaluemap[currentProFile()][varName] += varVal;
} }
break; break;
case ProVariable::UniqueAddOperator: // *= case ProVariable::UniqueAddOperator: // *=
if (!m_skipLevel || m_cumulative) { if (!m_skipLevel || m_cumulative) {
insertUnique(&m_valuemap, varName, m_sts.varVal); insertUnique(&m_valuemap, varName, varVal);
insertUnique(&m_filevaluemap[currentProFile()], varName, m_sts.varVal); insertUnique(&m_filevaluemap[currentProFile()], varName, varVal);
} }
break; break;
case ProVariable::AddOperator: // += case ProVariable::AddOperator: // +=
if (!m_skipLevel || m_cumulative) { if (!m_skipLevel || m_cumulative) {
m_valuemap[varName] += m_sts.varVal; m_valuemap[varName] += varVal;
m_filevaluemap[currentProFile()][varName] += m_sts.varVal; m_filevaluemap[currentProFile()][varName] += varVal;
} }
break; break;
case ProVariable::RemoveOperator: // -= case ProVariable::RemoveOperator: // -=
if (!m_cumulative) { if (!m_cumulative) {
if (!m_skipLevel) { if (!m_skipLevel) {
removeEach(&m_valuemap, varName, m_sts.varVal); removeEach(&m_valuemap, varName, varVal);
removeEach(&m_filevaluemap[currentProFile()], varName, m_sts.varVal); removeEach(&m_filevaluemap[currentProFile()], varName, varVal);
} }
} else { } else {
// We are stingy with our values, too. // We are stingy with our values, too.
} }
break; break;
case ProVariable::ReplaceOperator: // ~= }
{
// DEFINES ~= s/a/b/?[gqi]
QString val = m_sts.varVal.first();
doVariableReplace(&val);
if (val.length() < 4 || val.at(0) != QLatin1Char('s')) {
logMessage(format("the ~= operator can handle only the s/// function."));
break;
}
QChar sep = val.at(1);
QStringList func = val.split(sep);
if (func.count() < 3 || func.count() > 4) {
logMessage(format("the s/// function expects 3 or 4 arguments."));
break;
}
bool global = false, quote = false, case_sense = false;
if (func.count() == 4) {
global = func[3].indexOf(QLatin1Char('g')) != -1;
case_sense = func[3].indexOf(QLatin1Char('i')) == -1;
quote = func[3].indexOf(QLatin1Char('q')) != -1;
}
QString pattern = func[1];
QString replace = func[2];
if (quote)
pattern = QRegExp::escape(pattern);
QRegExp regexp(pattern, case_sense ? Qt::CaseSensitive : Qt::CaseInsensitive);
if (!m_skipLevel || m_cumulative) {
// We could make a union of modified and unmodified values,
// but this will break just as much as it fixes, so leave it as is.
replaceInList(&m_valuemap[varName], regexp, replace, global);
replaceInList(&m_filevaluemap[currentProFile()][varName], regexp, replace, global);
}
}
break;
} }
} }
@@ -1266,12 +1213,6 @@ ProItem::ProItemReturn ProFileEvaluator::Private::visitEndProFile(ProFile * pro)
return returnBool(QDir::setCurrent(m_oldPathStack.pop())); return returnBool(QDir::setCurrent(m_oldPathStack.pop()));
} }
void ProFileEvaluator::Private::visitProValue(ProValue *value)
{
m_lineNo = value->lineNumber();
m_sts.varVal += expandVariableReferences(value->value());
}
ProItem::ProItemReturn ProFileEvaluator::Private::visitProFunction(ProFunction *func) ProItem::ProItemReturn ProFileEvaluator::Private::visitProFunction(ProFunction *func)
{ {
// Make sure that called subblocks don't inherit & destroy the state // Make sure that called subblocks don't inherit & destroy the state

View File

@@ -126,10 +126,8 @@ ProItem::ProItemReturn ProBlock::Accept(AbstractProItemVisitor *visitor)
} }
// --------------- ProVariable ---------------- // --------------- ProVariable ----------------
ProVariable::ProVariable(const QString &name, ProBlock *parent) ProVariable::ProVariable(const QString &name)
: ProBlock(parent)
{ {
setBlockKind(ProBlock::VariableKind);
m_variable = name; m_variable = name;
m_variableKind = SetOperator; m_variableKind = SetOperator;
} }
@@ -154,50 +152,24 @@ QString ProVariable::variable() const
return m_variable; return m_variable;
} }
ProItem::ProItemReturn ProVariable::Accept(AbstractProItemVisitor *visitor) void ProVariable::setValue(const QString &val)
{ {
visitor->visitBeginProVariable(this); m_value = val;
foreach (ProItem *item, m_proitems)
item->Accept(visitor); // cannot fail
visitor->visitEndProVariable(this);
return ReturnTrue;
} }
// --------------- ProValue ---------------- QString ProVariable::value() const
ProValue::ProValue(const QString &value, ProVariable *variable)
{
m_variable = variable;
m_value = value;
}
void ProValue::setValue(const QString &value)
{
m_value = value;
}
QString ProValue::value() const
{ {
return m_value; return m_value;
} }
void ProValue::setVariable(ProVariable *variable) ProItem::ProItemKind ProVariable::kind() const
{ {
m_variable = variable; return ProItem::VariableKind;
} }
ProVariable *ProValue::variable() const ProItem::ProItemReturn ProVariable::Accept(AbstractProItemVisitor *visitor)
{ {
return m_variable; visitor->visitProVariable(this);
}
ProItem::ProItemKind ProValue::kind() const
{
return ProItem::ValueKind;
}
ProItem::ProItemReturn ProValue::Accept(AbstractProItemVisitor *visitor)
{
visitor->visitProValue(this);
return ReturnTrue; return ReturnTrue;
} }

View File

@@ -45,6 +45,7 @@ public:
FunctionKind, FunctionKind,
ConditionKind, ConditionKind,
OperatorKind, OperatorKind,
VariableKind,
BlockKind BlockKind
}; };
@@ -78,7 +79,6 @@ public:
NormalKind = 0x00, NormalKind = 0x00,
ScopeKind = 0x01, ScopeKind = 0x01,
ScopeContentsKind = 0x02, ScopeContentsKind = 0x02,
VariableKind = 0x04,
ProFileKind = 0x08, ProFileKind = 0x08,
FunctionBodyKind = 0x10, FunctionBodyKind = 0x10,
SingleLine = 0x80 SingleLine = 0x80
@@ -111,7 +111,7 @@ private:
int m_refCount; int m_refCount;
}; };
class ProVariable : public ProBlock class ProVariable : public ProItem
{ {
public: public:
enum VariableOperator { enum VariableOperator {
@@ -122,7 +122,7 @@ public:
UniqueAddOperator = 4 UniqueAddOperator = 4
}; };
ProVariable(const QString &name, ProBlock *parent); ProVariable(const QString &name);
void setVariableOperator(VariableOperator variableKind); void setVariableOperator(VariableOperator variableKind);
VariableOperator variableOperator() const; VariableOperator variableOperator() const;
@@ -130,29 +130,16 @@ public:
void setVariable(const QString &name); void setVariable(const QString &name);
QString variable() const; QString variable() const;
virtual ProItemReturn Accept(AbstractProItemVisitor *visitor);
private:
VariableOperator m_variableKind;
QString m_variable;
};
class ProValue : public ProItem
{
public:
ProValue(const QString &value, ProVariable *variable);
void setValue(const QString &value); void setValue(const QString &value);
QString value() const; QString value() const;
void setVariable(ProVariable *variable);
ProVariable *variable() const;
ProItem::ProItemKind kind() const; ProItem::ProItemKind kind() const;
virtual ProItemReturn Accept(AbstractProItemVisitor *visitor); virtual ProItemReturn Accept(AbstractProItemVisitor *visitor);
private: private:
VariableOperator m_variableKind;
QString m_variable;
QString m_value; QString m_value;
ProVariable *m_variable;
}; };
class ProFunction : public ProItem class ProFunction : public ProItem

View File

@@ -41,41 +41,38 @@ void ProWriter::addFiles(ProFile *profile, QStringList *lines,
{ {
// Check if variable item exists as child of root item // Check if variable item exists as child of root item
foreach (ProItem *item, profile->items()) { foreach (ProItem *item, profile->items()) {
if (item->kind() == ProItem::BlockKind) { if (item->kind() == ProItem::VariableKind) {
ProBlock *block = static_cast<ProBlock *>(item); ProVariable *proVar = static_cast<ProVariable*>(item);
if (block->blockKind() == ProBlock::VariableKind) { if (vars.contains(proVar->variable())
ProVariable *proVar = static_cast<ProVariable*>(block); && proVar->variableOperator() != ProVariable::RemoveOperator
if (vars.contains(proVar->variable()) && proVar->variableOperator() != ProVariable::ReplaceOperator) {
&& proVar->variableOperator() != ProVariable::RemoveOperator
&& proVar->variableOperator() != ProVariable::ReplaceOperator) {
int lineNo = proVar->lineNumber() - 1; int lineNo = proVar->lineNumber() - 1;
for (; lineNo < lines->count(); lineNo++) { for (; lineNo < lines->count(); lineNo++) {
QString line = lines->at(lineNo); QString line = lines->at(lineNo);
int idx = line.indexOf(QLatin1Char('#')); int idx = line.indexOf(QLatin1Char('#'));
if (idx >= 0)
line.truncate(idx);
while (line.endsWith(QLatin1Char(' ')) || line.endsWith(QLatin1Char('\t')))
line.chop(1);
if (line.isEmpty()) {
if (idx >= 0) if (idx >= 0)
line.truncate(idx); continue;
while (line.endsWith(QLatin1Char(' ')) || line.endsWith(QLatin1Char('\t'))) break;
line.chop(1); }
if (line.isEmpty()) { if (!line.endsWith(QLatin1Char('\\'))) {
if (idx >= 0) (*lines)[lineNo].insert(line.length(), QLatin1String(" \\"));
continue; lineNo++;
break; break;
}
if (!line.endsWith(QLatin1Char('\\'))) {
(*lines)[lineNo].insert(line.length(), QLatin1String(" \\"));
lineNo++;
break;
}
} }
QString added;
foreach (const QString &filePath, filePaths)
added += QLatin1String(" ") + proFileDir.relativeFilePath(filePath)
+ QLatin1String(" \\\n");
added.chop(3);
lines->insert(lineNo, added);
return;
} }
QString added;
foreach (const QString &filePath, filePaths)
added += QLatin1String(" ") + proFileDir.relativeFilePath(filePath)
+ QLatin1String(" \\\n");
added.chop(3);
lines->insert(lineNo, added);
return;
} }
} }
} }
@@ -92,14 +89,11 @@ static void findProVariables(ProBlock *block, const QStringList &vars,
{ {
foreach (ProItem *item, block->items()) { foreach (ProItem *item, block->items()) {
if (item->kind() == ProItem::BlockKind) { if (item->kind() == ProItem::BlockKind) {
ProBlock *subBlock = static_cast<ProBlock *>(item); findProVariables(static_cast<ProBlock*>(item), vars, proVars);
if (subBlock->blockKind() == ProBlock::VariableKind) { } else if (item->kind() == ProItem::VariableKind) {
ProVariable *proVar = static_cast<ProVariable*>(subBlock); ProVariable *proVar = static_cast<ProVariable*>(item);
if (vars.contains(proVar->variable())) if (vars.contains(proVar->variable()))
*proVars << proVar; *proVars << proVar;
} else {
findProVariables(subBlock, vars, proVars);
}
} }
} }
} }