fix execution location tracking

function calls need to change _FILE_ - but none of the other
context-indicating variables.
This commit is contained in:
Oswald Buddenhagen
2010-06-23 13:58:44 +02:00
parent fa79b97511
commit 01c0b84508
2 changed files with 63 additions and 36 deletions

View File

@@ -126,7 +126,6 @@ public:
~Private(); ~Private();
ProFileEvaluator *q; ProFileEvaluator *q;
int m_lineNo; // Error reporting
enum VisitReturn { enum VisitReturn {
ReturnFalse, ReturnFalse,
@@ -145,6 +144,7 @@ public:
void skipExpression(const ushort *&tokPtr); void skipExpression(const ushort *&tokPtr);
VisitReturn visitProFile(ProFile *pro, ProFileEvaluatorHandler::EvalFileType type); VisitReturn visitProFile(ProFile *pro, ProFileEvaluatorHandler::EvalFileType type);
VisitReturn visitProBlock(ProFile *pro, const ushort *tokPtr);
VisitReturn visitProBlock(const ushort *tokPtr); VisitReturn visitProBlock(const ushort *tokPtr);
VisitReturn visitProLoop(const ProString &variable, const ushort *exprPtr, VisitReturn visitProLoop(const ProString &variable, const ushort *exprPtr,
const ushort *tokPtr); const ushort *tokPtr);
@@ -200,8 +200,17 @@ public:
int m_skipLevel; int m_skipLevel;
int m_loopLevel; // To report unexpected break() and next()s int m_loopLevel; // To report unexpected break() and next()s
bool m_cumulative; bool m_cumulative;
QStack<ProFile*> m_profileStack; // To handle 'include(a.pri), so we can track back to 'a.pro' when finished with 'a.pri'
QStack<QString> m_stringStack; // To handle token string refcounting struct Location {
Location() : pro(0), line(0) {}
Location(ProFile *_pro, int _line) : pro(_pro), line(_line) {}
ProFile *pro;
int line;
};
Location m_current; // Currently evaluated location
QStack<Location> m_locationStack; // All execution location changes
QStack<ProFile *> m_profileStack; // Includes only
QString m_outputDir; QString m_outputDir;
@@ -448,7 +457,7 @@ uint ProFileEvaluator::Private::getBlockLen(const ushort *&tokPtr)
ProString ProFileEvaluator::Private::getStr(const ushort *&tokPtr) ProString ProFileEvaluator::Private::getStr(const ushort *&tokPtr)
{ {
const QString &str(m_stringStack.top()); const QString &str(m_current.pro->items());
uint len = *tokPtr++; uint len = *tokPtr++;
ProString ret(str, tokPtr - (const ushort *)str.constData(), len, NoHash); ProString ret(str, tokPtr - (const ushort *)str.constData(), len, NoHash);
tokPtr += len; tokPtr += len;
@@ -459,7 +468,7 @@ ProString ProFileEvaluator::Private::getHashStr(const ushort *&tokPtr)
{ {
uint hash = getBlockLen(tokPtr); uint hash = getBlockLen(tokPtr);
uint len = *tokPtr++; uint len = *tokPtr++;
const QString &str(m_stringStack.top()); const QString &str(m_current.pro->items());
ProString ret(str, tokPtr - (const ushort *)str.constData(), len, hash); ProString ret(str, tokPtr - (const ushort *)str.constData(), len, hash);
tokPtr += len; tokPtr += len;
return ret; return ret;
@@ -670,7 +679,7 @@ void ProFileEvaluator::Private::evaluateExpression(
ushort maskedTok = tok & TokMask; ushort maskedTok = tok & TokMask;
switch (maskedTok) { switch (maskedTok) {
case TokLine: case TokLine:
m_lineNo = *tokPtr++; m_current.line = *tokPtr++;
break; break;
case TokLiteral: case TokLiteral:
addStr(getStr(tokPtr), ret, pending, joined); addStr(getStr(tokPtr), ret, pending, joined);
@@ -707,7 +716,7 @@ void ProFileEvaluator::Private::skipExpression(const ushort *&pTokPtr)
ushort tok = *tokPtr++; ushort tok = *tokPtr++;
switch (tok) { switch (tok) {
case TokLine: case TokLine:
m_lineNo = *tokPtr++; m_current.line = *tokPtr++;
break; break;
case TokValueTerminator: case TokValueTerminator:
case TokFuncTerminator: case TokFuncTerminator:
@@ -740,6 +749,14 @@ void ProFileEvaluator::Private::skipExpression(const ushort *&pTokPtr)
} }
} }
ProFileEvaluator::Private::VisitReturn ProFileEvaluator::Private::visitProBlock(
ProFile *pro, const ushort *tokPtr)
{
m_current.pro = pro;
m_current.line = 0;
return visitProBlock(tokPtr);
}
ProFileEvaluator::Private::VisitReturn ProFileEvaluator::Private::visitProBlock( ProFileEvaluator::Private::VisitReturn ProFileEvaluator::Private::visitProBlock(
const ushort *tokPtr) const ushort *tokPtr)
{ {
@@ -750,7 +767,7 @@ ProFileEvaluator::Private::VisitReturn ProFileEvaluator::Private::visitProBlock(
while (ushort tok = *tokPtr++) { while (ushort tok = *tokPtr++) {
switch (tok) { switch (tok) {
case TokLine: case TokLine:
m_lineNo = *tokPtr++; m_current.line = *tokPtr++;
continue; continue;
case TokAssign: case TokAssign:
case TokAppend: case TokAppend:
@@ -897,10 +914,8 @@ void ProFileEvaluator::Private::visitProFunctionDef(
(tok == TokTestDef (tok == TokTestDef
? &m_functionDefs.testFunctions ? &m_functionDefs.testFunctions
: &m_functionDefs.replaceFunctions); : &m_functionDefs.replaceFunctions);
FunctionDef def; hash->insert(name, FunctionDef(m_current.pro,
def.string = m_stringStack.top(); tokPtr - (const ushort *)m_current.pro->items().constData()));
def.offset = tokPtr - (const ushort *)def.string.constData();
hash->insert(name, def);
} }
ProFileEvaluator::Private::VisitReturn ProFileEvaluator::Private::visitProLoop( ProFileEvaluator::Private::VisitReturn ProFileEvaluator::Private::visitProLoop(
@@ -1104,7 +1119,6 @@ ProFileEvaluator::Private::VisitReturn ProFileEvaluator::Private::visitProFile(
ProFile *pro, ProFileEvaluatorHandler::EvalFileType type) ProFile *pro, ProFileEvaluatorHandler::EvalFileType type)
{ {
m_handler->aboutToEval(currentProFile(), pro, type); m_handler->aboutToEval(currentProFile(), pro, type);
m_lineNo = 0;
m_profileStack.push(pro); m_profileStack.push(pro);
if (m_profileStack.count() == 1) { if (m_profileStack.count() == 1) {
// Do this only for the initial profile we visit, since // Do this only for the initial profile we visit, since
@@ -1269,9 +1283,7 @@ ProFileEvaluator::Private::VisitReturn ProFileEvaluator::Private::visitProFile(
} }
} }
m_stringStack.push(pro->items()); visitProBlock(pro, (const ushort *)pro->items().constData());
visitProBlock((const ushort *)pro->items().constData());
m_stringStack.pop();
if (m_profileStack.count() == 1) { if (m_profileStack.count() == 1) {
if (m_parsePreAndPostFiles) { if (m_parsePreAndPostFiles) {
@@ -1825,13 +1837,12 @@ ProStringList ProFileEvaluator::Private::evaluateFunction(
bool oki; bool oki;
ProStringList ret; ProStringList ret;
const ushort *tokPtr = (const ushort *)func.string.constData() + func.offset;
if (m_valuemapStack.count() >= 100) { if (m_valuemapStack.count() >= 100) {
evalError(fL1S("ran into infinite recursion (depth > 100).")); evalError(fL1S("ran into infinite recursion (depth > 100)."));
oki = false; oki = false;
} else { } else {
m_valuemapStack.push(QHash<ProString, ProStringList>()); m_valuemapStack.push(QHash<ProString, ProStringList>());
m_stringStack.push(func.string); m_locationStack.push(m_current);
int loopLevel = m_loopLevel; int loopLevel = m_loopLevel;
m_loopLevel = 0; m_loopLevel = 0;
@@ -1841,12 +1852,12 @@ ProStringList ProFileEvaluator::Private::evaluateFunction(
m_valuemapStack.top()[ProString(QString::number(i+1))] = argumentsList[i]; m_valuemapStack.top()[ProString(QString::number(i+1))] = argumentsList[i];
} }
m_valuemapStack.top()[statics.strARGS] = args; m_valuemapStack.top()[statics.strARGS] = args;
oki = (visitProBlock(tokPtr) != ReturnFalse); // True || Return oki = (visitProBlock(func.pro(), func.tokPtr()) != ReturnFalse); // True || Return
ret = m_returnValue; ret = m_returnValue;
m_returnValue.clear(); m_returnValue.clear();
m_loopLevel = loopLevel; m_loopLevel = loopLevel;
m_stringStack.pop(); m_current = m_locationStack.pop();
m_valuemapStack.pop(); m_valuemapStack.pop();
} }
if (ok) if (ok)
@@ -2408,9 +2419,9 @@ ProFileEvaluator::Private::VisitReturn ProFileEvaluator::Private::evaluateCondit
args.join(statics.field_sep)); args.join(statics.field_sep));
if (!pro) if (!pro)
return ReturnFalse; return ReturnFalse;
m_stringStack.push(pro->items()); m_locationStack.push(m_current);
VisitReturn ret = visitProBlock((const ushort *)pro->items().constData()); VisitReturn ret = visitProBlock(pro, (const ushort *)pro->items().constData());
m_stringStack.pop(); m_current = m_locationStack.pop();
pro->deref(); pro->deref();
return ret; return ret;
} }
@@ -2832,10 +2843,10 @@ ProStringList ProFileEvaluator::Private::values(const ProString &variableName) c
case V_LITERAL_WHITESPACE: ret = QLatin1String("\t"); break; case V_LITERAL_WHITESPACE: ret = QLatin1String("\t"); break;
case V_LITERAL_DOLLAR: ret = QLatin1String("$"); break; case V_LITERAL_DOLLAR: ret = QLatin1String("$"); break;
case V_LITERAL_HASH: ret = QLatin1String("#"); break; case V_LITERAL_HASH: ret = QLatin1String("#"); break;
case V_OUT_PWD: //the outgoing dir case V_OUT_PWD: // the outgoing dir (shadow of _PRO_FILE_PWD_)
ret = m_outputDir; ret = m_outputDir;
break; break;
case V_PWD: //current working dir (of _FILE_) case V_PWD: // containing directory of most nested project/include file
case V_IN_PWD: case V_IN_PWD:
ret = currentDirectory(); ret = currentDirectory();
break; break;
@@ -2845,11 +2856,11 @@ ProStringList ProFileEvaluator::Private::values(const ProString &variableName) c
case V_DIRLIST_SEPARATOR: case V_DIRLIST_SEPARATOR:
ret = m_option->dirlist_sep; ret = m_option->dirlist_sep;
break; break;
case V__LINE_: //parser line number case V__LINE_: // currently executed line number
ret = QString::number(m_lineNo); ret = QString::number(m_current.line);
break; break;
case V__FILE_: //parser file case V__FILE_: // currently executed file
ret = currentFileName(); ret = m_current.pro->fileName();
break; break;
case V__DATE_: //current date/time case V__DATE_: //current date/time
ret = QDateTime::currentDateTime().toString(); ret = QDateTime::currentDateTime().toString();
@@ -2950,14 +2961,13 @@ ProStringList ProFileEvaluator::Private::values(const ProString &variableName) c
bool ProFileEvaluator::Private::evaluateFileDirect( bool ProFileEvaluator::Private::evaluateFileDirect(
const QString &fileName, ProFileEvaluatorHandler::EvalFileType type) const QString &fileName, ProFileEvaluatorHandler::EvalFileType type)
{ {
int lineNo = m_lineNo;
if (ProFile *pro = m_parser->parsedProFile(fileName, true)) { if (ProFile *pro = m_parser->parsedProFile(fileName, true)) {
m_locationStack.push(m_current);
bool ok = (visitProFile(pro, type) == ReturnTrue); bool ok = (visitProFile(pro, type) == ReturnTrue);
m_current = m_locationStack.pop();
pro->deref(); pro->deref();
m_lineNo = lineNo;
return ok; return ok;
} else { } else {
m_lineNo = lineNo;
return false; return false;
} }
} }
@@ -3046,7 +3056,7 @@ bool ProFileEvaluator::Private::evaluateFileInto(
void ProFileEvaluator::Private::evalError(const QString &message) const void ProFileEvaluator::Private::evalError(const QString &message) const
{ {
if (!m_skipLevel) if (!m_skipLevel)
m_handler->evalError(currentFileName(), m_lineNo, message); m_handler->evalError(m_current.pro->fileName(), m_current.line, message);
} }

View File

@@ -65,9 +65,26 @@ class ProFileEvaluator
class Private; class Private;
public: public:
struct FunctionDef { class FunctionDef {
QString string; public:
int offset; FunctionDef(ProFile *pro, int offset) : m_pro(pro), m_offset(offset) { m_pro->ref(); }
FunctionDef(const FunctionDef &o) : m_pro(o.m_pro), m_offset(o.m_offset) { m_pro->ref(); }
~FunctionDef() { m_pro->deref(); }
FunctionDef &operator=(const FunctionDef &o)
{
if (this != &o) {
m_pro->deref();
m_pro = o.m_pro;
m_pro->ref();
m_offset = o.m_offset;
}
return *this;
}
ProFile *pro() const { return m_pro; }
const ushort *tokPtr() const { return (const ushort *)m_pro->items().constData() + m_offset; }
private:
ProFile *m_pro;
int m_offset;
}; };
struct FunctionDefs { struct FunctionDefs {