Example #1
0
/*
<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");
}
Example #2
0
/*
<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");
  }
}
Example #3
0
/*
<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");
}
Example #4
0
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));
            }
        }
    }
}