/* <unscoped_template_name> ::= <unscoped_name> ::= <substitution> */ static int parseUnscopedTemplateName(LargeStaticString &src, LargeStaticString &dest, demangle_t &data) { START("UnscopedTemplateName"); LargeStaticString origsrc = src; LargeStaticString origdest = dest; // Try substitution first. if (parseSubstitution(src, dest, data) == SUCCESS) END_SUCCESS("UnscopedTemplateName"); src = origsrc; dest = origdest; if (parseUnqualifiedName(src, dest, data) == SUCCESS) END_SUCCESS("UnscopedTemplateName"); else END_FAIL("UnscopedTemplateName"); }
/* <type> ::= <CV-qualifiers> <type> ::= P <type> ::= R <type> ::= <builtin-type> ::= <function-type> ::= <name> # class-enum-type ::= <array-type> ::= <pointer-to-member-type> ::= <template-param> ::= <template-template-param> <template-args> ::= <substitution> */ static int parseType(LargeStaticString &src, LargeStaticString &dest, demangle_t &data) { START("Type"); // CV-qualifiers? if (src[0] == 'r' || src[0] == 'V' || src[0] == 'K') { LargeStaticString tmp; if (parseCvQualifiers(src, tmp, data) == FAIL) END_FAIL("Type"); if (parseType(src, tmp, data) == FAIL) END_FAIL("Type"); dest += tmp; addSubstitution(tmp, data); END_SUCCESS("Type"); } // Pointer? else if (src[0] == 'P') { src.stripFirst(1); LargeStaticString tmp; if (parseType(src, tmp, data) == FAIL) END_FAIL("Type"); dest += tmp; tmp += "*"; dest += "*"; addSubstitution(tmp, data); END_SUCCESS("Type"); } // Reference? else if (src[0] == 'R') { src.stripFirst(1); LargeStaticString tmp; if (parseType(src, tmp, data) == FAIL) END_FAIL("Type"); dest += tmp; tmp += "&"; dest += "&"; addSubstitution(tmp, data); END_SUCCESS("Type"); } // Function-type? else if (src[0] == 'F') { if (parseFunctionType(src, dest, data) == FAIL) END_FAIL("Type"); END_SUCCESS("Type"); } // Array type? else if (src[0] == 'A') { if (parseArrayType(src, dest, data) == FAIL) END_FAIL("Type"); END_SUCCESS("Type"); } // Pointer-to-member type? else if (src[0] == 'M') { if (parsePointerToMemberType(src, dest, data) == FAIL) END_FAIL("Type"); END_SUCCESS("Type"); } // Template parameter type? else if (src[0] == 'T') { // Try the template-template-type first, if it fails fall back. LargeStaticString origsrc = src; LargeStaticString origdest = dest; if (parseTemplateTemplateParam(src, dest, data) == SUCCESS && parseTemplateArgs(src, dest, data) == SUCCESS) END_SUCCESS("Type"); src = origsrc; dest = origdest; if (parseTemplateParam(src, dest, data) == FAIL) END_FAIL("Type"); END_SUCCESS("Type"); } else { // OK then, try a builtin-type. LargeStaticString origsrc = src; LargeStaticString origdest = dest; if (parseBuiltinType(src, dest, data) == SUCCESS) END_SUCCESS("Type"); src = origsrc; dest = origdest; LargeStaticString tmp; if (parseName(src, tmp, data) == SUCCESS) { dest += tmp; addSubstitution(tmp, data); END_SUCCESS("Type"); } if (src[0] == 'S') { src = origsrc; dest = origdest; if (parseSubstitution(src, dest, data) == FAIL) END_FAIL("Type"); END_SUCCESS("Type"); } END_FAIL("Type"); } }
/* <prefix> ::= <prefix> <unqualified_name> ::= <template_prefix> <template_args> ::= <template_param> ::= # empty ::= <substitution> =============== CHANGED TO <prefix> ::= <unqualified_name> <prefix> ::= <unqualified_name> <template_args> <prefix> ::= <template_param> ::= # empty ::= <substitution> */ static int parsePrefix(LargeStaticString &src, LargeStaticString &dest, demangle_t &data, LargeStaticString &thisPrefix) { START("Prefix"); LargeStaticString origsrc = src; LargeStaticString origdest = dest; // Check for a template_param. // if (parseTemplateParam(src, dest, data) == SUCCESS) // END_SUCCESS("Prefix"); src = origsrc; dest = origdest; // Check for a substitution. if (parseSubstitution(src, dest, data) == SUCCESS) END_SUCCESS("Prefix"); src = origsrc; dest = origdest; // Check for an unqualified name LargeStaticString unqualName; if (parseUnqualifiedName(src, unqualName, data) == SUCCESS) { dest += "::"; dest += unqualName; origsrc = src; origdest = dest; // Checkpoint! thisPrefix += "::"; thisPrefix += unqualName; addSubstitution(thisPrefix, data); // Do we have a template_args? unqualName = ""; if (parseTemplateArgs(src, unqualName, data) == FAIL) { src = origsrc; dest = origdest; } else { dest += unqualName; thisPrefix += unqualName; addSubstitution(thisPrefix, data); } // Recurse. if (parsePrefix(src, dest, data, thisPrefix) == SUCCESS) END_SUCCESS("Prefix"); else END_FAIL("Prefix"); } src = origsrc; dest = origdest; // Empty rule. END_SUCCESS("Prefix"); }
void Rules::load(const QString &filename) { qDebug() << "Loading rules from" << filename; // initialize the regexps we will use QRegExp repoLine("create repository\\s+(\\S+)", Qt::CaseInsensitive); QString varRegex("[A-Za-z0-9_]+"); QRegExp matchLine("match\\s+(.*)", Qt::CaseInsensitive); QRegExp matchActionLine("action\\s+(\\w+)", Qt::CaseInsensitive); QRegExp matchRepoLine("repository\\s+(\\S+)", Qt::CaseInsensitive); QRegExp matchDescLine("description\\s+(.+)$", Qt::CaseInsensitive); QRegExp matchRepoSubstLine("substitute repository\\s+(.+)$", Qt::CaseInsensitive); QRegExp matchBranchLine("branch\\s+(\\S+)", Qt::CaseInsensitive); QRegExp matchBranchSubstLine("substitute branch\\s+(.+)$", Qt::CaseInsensitive); QRegExp matchRevLine("(min|max) revision (\\d+)", Qt::CaseInsensitive); QRegExp matchAnnotateLine("annotated\\s+(\\S+)", Qt::CaseInsensitive); QRegExp matchPrefixLine("prefix\\s+(.*)$", Qt::CaseInsensitive); QRegExp declareLine("declare\\s+("+varRegex+")\\s*=\\s*(\\S+)", Qt::CaseInsensitive); QRegExp variableLine("\\$\\{("+varRegex+")(\\|[^}$]*)?\\}", Qt::CaseInsensitive); QRegExp includeLine("include\\s+(.*)", Qt::CaseInsensitive); enum { ReadingNone, ReadingRepository, ReadingMatch } state = ReadingNone; Repository repo; Match match; int lineNumber = 0; QFile file(filename); if (!file.open(QIODevice::ReadOnly)) qFatal("Could not read the rules file: %s", qPrintable(filename)); QTextStream s(&file); QStringList lines = s.readAll().split('\n', QString::KeepEmptyParts); QStringList::iterator it; for(it = lines.begin(); it != lines.end(); ++it) { ++lineNumber; QString origLine = *it; QString line = origLine; int hash = line.indexOf('#'); if (hash != -1) line.truncate(hash); line = line.trimmed(); if (line.isEmpty()) continue; bool isIncludeRule = includeLine.exactMatch(line); if (isIncludeRule) { int index = filename.lastIndexOf("/"); QString includeFile = filename.left( index + 1) + includeLine.cap(1); load(includeFile); } else { while( variableLine.indexIn(line) != -1 ) { QString replacement; if (m_variables.contains(variableLine.cap(1))) { replacement = m_variables[variableLine.cap(1)]; } else { if (variableLine.cap(2).startsWith('|')) { replacement = variableLine.cap(2).mid(1); } else { qFatal("Undeclared variable: %s", qPrintable(variableLine.cap(1))); } } line = line.replace(variableLine.cap(0), replacement); } if (state == ReadingRepository) { if (matchBranchLine.exactMatch(line)) { Repository::Branch branch; branch.name = matchBranchLine.cap(1); repo.branches += branch; continue; } else if (matchDescLine.exactMatch(line)) { repo.description = matchDescLine.cap(1); continue; } else if (matchRepoLine.exactMatch(line)) { repo.forwardTo = matchRepoLine.cap(1); continue; } else if (matchPrefixLine.exactMatch(line)) { repo.prefix = matchPrefixLine.cap(1); continue; } else if (line == "end repository") { if (!repo.forwardTo.isEmpty() && !repo.description.isEmpty()) { qFatal("Specifing repository and description on repository is invalid on line %d", lineNumber); } if (!repo.forwardTo.isEmpty() && !repo.branches.isEmpty()) { qFatal("Specifing repository and branches on repository is invalid on line %d", lineNumber); } m_repositories += repo; { // clear out 'repo' Repository temp; std::swap(repo, temp); } state = ReadingNone; continue; } } else if (state == ReadingMatch) { if (matchRepoLine.exactMatch(line)) { match.repository = matchRepoLine.cap(1); continue; } else if (matchBranchLine.exactMatch(line)) { match.branch = matchBranchLine.cap(1); continue; } else if (matchRepoSubstLine.exactMatch(line)) { Match::Substitution subst = parseSubstitution(matchRepoSubstLine.cap(1)); if (!subst.isValid()) { qFatal("Malformed substitution in rules file: line %d: %s", lineNumber, qPrintable(origLine)); } match.repo_substs += subst; continue; } else if (matchBranchSubstLine.exactMatch(line)) { Match::Substitution subst = parseSubstitution(matchBranchSubstLine.cap(1)); if (!subst.isValid()) { qFatal("Malformed substitution in rules file: line %d: %s", lineNumber, qPrintable(origLine)); } match.branch_substs += subst; continue; } else if (matchRevLine.exactMatch(line)) { if (matchRevLine.cap(1) == "min") match.minRevision = matchRevLine.cap(2).toInt(); else // must be max match.maxRevision = matchRevLine.cap(2).toInt(); continue; } else if (matchPrefixLine.exactMatch(line)) { match.prefix = matchPrefixLine.cap(1); if( match.prefix.startsWith('/')) match.prefix = match.prefix.mid(1); continue; } else if (matchActionLine.exactMatch(line)) { QString action = matchActionLine.cap(1); if (action == "export") match.action = Match::Export; else if (action == "ignore") match.action = Match::Ignore; else if (action == "recurse") match.action = Match::Recurse; else qFatal("Invalid action \"%s\" on line %d", qPrintable(action), lineNumber); continue; } else if (matchAnnotateLine.exactMatch(line)) { match.annotate = matchAnnotateLine.cap(1) == "true"; continue; } else if (line == "end match") { if (!match.repository.isEmpty()) match.action = Match::Export; m_matchRules += match; Stats::instance()->addRule(match); state = ReadingNone; continue; } } bool isRepositoryRule = repoLine.exactMatch(line); bool isMatchRule = matchLine.exactMatch(line); bool isVariableRule = declareLine.exactMatch(line); if (isRepositoryRule) { // repository rule state = ReadingRepository; repo = Repository(); // clear repo.name = repoLine.cap(1); repo.lineNumber = lineNumber; repo.filename = filename; } else if (isMatchRule) { // match rule state = ReadingMatch; match = Match(); match.rx = QRegExp(matchLine.cap(1), Qt::CaseSensitive, QRegExp::RegExp2); if( !match.rx.isValid() ) qFatal("Malformed regular expression '%s' in file:'%s':%d, Error: %s", qPrintable(matchLine.cap(1)), qPrintable(filename), lineNumber, qPrintable(match.rx.errorString())); match.lineNumber = lineNumber; match.filename = filename; } else if (isVariableRule) { QString variable = declareLine.cap(1); QString value = declareLine.cap(2); m_variables.insert(variable, value); } else { qFatal("Malformed line in rules file: line %d: %s", lineNumber, qPrintable(origLine)); } } } }