Exemple #1
0
bool ProgramScriptAction::check(const QString &xmlFile, const TypeRule *rule,
                                SymFactory *factory)
{
    Q_UNUSED(rule);
    Q_UNUSED(factory);

    // Delete old program
    if (_program) {
        delete _program;
        _program = 0;
    }

    QScriptSyntaxCheckResult result =
            QScriptEngine::checkSyntax(_srcCode);
    if (result.state() != QScriptSyntaxCheckResult::Valid) {
        typeRuleError2(xmlFile,
                       srcLine() + result.errorLineNumber() - 1,
                       result.errorColumnNumber(),
                       QString("Syntax error: %1")
                            .arg(result.errorMessage()));
    }
    else {
        // Wrap the code into a function so that the return statement
        // is available to the code
        QString code = QString("function %1() {\n%2\n}")
                .arg(js::inlinefunc).arg(_srcCode);
        _program = new QScriptProgram(code, xmlFile, srcLine() - 1);
    }

    return true;
}
Exemple #2
0
bool FuncCallScriptAction::check(const QString &xmlFile, const TypeRule *rule,
                                 SymFactory *factory)
{
    Q_UNUSED(rule);
    Q_UNUSED(factory);

    // Delete old program
    if (_program) {
        delete _program;
        _program = 0;
    }

    // Read the contents of the script file
    QFile scriptFile(_scriptFile);
    if (!scriptFile.open(QFile::ReadOnly))
        ioError(QString("Error opening file \"%1\" for reading.")
                    .arg(_scriptFile));
    _program = new QScriptProgram(scriptFile.readAll(), _scriptFile);

    // Basic syntax check
    QScriptSyntaxCheckResult result =
            QScriptEngine::checkSyntax(_program->sourceCode());
    if (result.state() != QScriptSyntaxCheckResult::Valid) {
        typeRuleError2(xmlFile, srcLine(), -1,
                       QString("Syntax error in file %1 line %2 column %3: %4")
                               .arg(ShellUtil::shortFileName(_scriptFile))
                               .arg(result.errorLineNumber())
                               .arg(result.errorColumnNumber())
                               .arg(result.errorMessage()));
    }
    // Check if the function exists
    ScriptEngine eng(0);
    ScriptEngine::FuncExistsResult ret =
            eng.functionExists(_function, *_program);
    if (ret == ScriptEngine::feRuntimeError) {
        QString err;
        if (eng.hasUncaughtException()) {
            err = QString("Uncaught exception at line %0: %1")
                    .arg(eng.uncaughtExceptionLineNumber())
                    .arg(eng.lastError());
            QStringList bt = eng.uncaughtExceptionBacktrace();
            for (int i = 0; i < bt.size(); ++i)
                err += "\n    " + bt[i];
        }
        else
            err = eng.lastError();
        typeRuleError2(xmlFile, srcLine(), -1,
                       QString("Runtime error in file %1: %2")
                               .arg(ShellUtil::shortFileName(_scriptFile))
                               .arg(err));
    }
    else if (ret == ScriptEngine::feDoesNotExist) {
        typeRuleError2(xmlFile, srcLine(), -1,
                       QString("Function \"%1\" is not defined in file \"%2\".")
                               .arg(_function)
                               .arg(ShellUtil::shortFileName(_scriptFile)));
    }

    return true;
}
Exemple #3
0
    TEST_FIXTURE(RouterFixture, throws_choose_error_exception_when_unknown_type)
    {
        std::stringstream srcLine("__*fklsajdf");

        this->repeat([&] { return srcLine.get(); }, 2);

        CHECK_THROW(this->router.choose(srcLine.get()),
                    husky::types::TypeChooseError);
    }
Exemple #4
0
    TEST_FIXTURE(RouterFixture, works_with_a_double)
    {
        std::stringstream srcLine(", 123.32 sfds");

        this->repeat([&] { return srcLine.get(); }, 2);

        this->type = this->router.choose(srcLine.get());

        CHECK_EQUAL(husky::types::number::id,
                    this->type->id());
    }
Exemple #5
0
bool ExpressionAction::checkExprComplexity(const QString& xmlFile,
                                           const QString &what,
                                           const QString &expr) const
{
    static const QString illegal("{};\"?");
    QRegExp rx("[" + QRegExp::escape(illegal) + "]") ;
    if (expr.contains(rx))
        typeRuleError2(xmlFile, srcLine(), -1,
                       QString("The %1 contains one of the following "
                               "unsupported characters: %2")
                            .arg(what)
                            .arg(illegal));
    return true;
}
Exemple #6
0
bool ExpressionAction::check(const QString &xmlFile, const TypeRule *rule,
                             SymFactory *factory)
{
    for (int i = 0; i < _exprList.size(); ++i)
        delete _exprList[i];
    _exprList.clear();
    _srcType = 0;
    _targetType = 0;
    _expr = 0;

    checkExprComplexity(xmlFile, _srcTypeStr, "source type");
    checkExprComplexity(xmlFile, _targetTypeStr, "target type");
    checkExprComplexity(xmlFile, _exprStr, "expression");

    QString srcId;

    // Check target type
    bool targetUsesId = false;
    _targetType = parseTypeStr(xmlFile, 0, factory, "target type",
                               _targetTypeStr, srcId, &targetUsesId);

    if (_targetType)
        _targetType = _targetType->dereferencedBaseType(BaseType::trLexical);

    // Check source type
    bool srcUsesId = false;
    _srcType = parseTypeStr(xmlFile, rule, factory, "source type",
                            _srcTypeStr, srcId, &srcUsesId);

    // Is the srcId valid?
    if (srcId.isEmpty())
        typeRuleError2(xmlFile, srcLine(), -1,
                       QString("The source type does not specify an identifier:"
                               " %1")
                            .arg(_srcTypeStr));

    // Make sure the expression contains the srcId
    if (!_exprStr.contains(QRegExp("\\b" + srcId + "\\b")))
        typeRuleError2(xmlFile, srcLine(), -1,
                       QString("The expression does not use identifier \"%1\" "
                               "which was defined in the source type.")
                            .arg(srcId));

    // Check complete expression
    AbstractSyntaxTree ast;
    ASTBuilder builder(&ast, factory);
    QString codeStr;
    // If the type was specified via ID, we have to use the pseudo typedef here
    if (srcUsesId)
        codeStr = QString("__0x%0__ %1;").arg((uint)_srcType->id(), 0, 16).arg(srcId);
    else
        codeStr = _srcTypeStr + ";";
    codeStr += " int __dest__ = " + _exprStr + ";";
    if (builder.buildFrom(codeStr.toAscii()) != 0)
        typeRuleError2(xmlFile, srcLine(), -1,
                       QString("Syntax error in expression: %1")
                            .arg(codeStr));

    // We should finde exatcely one initializer
    QList<const ASTNode*> init_nodes =
            ASTNodeFinder::find(nt_initializer, &ast);
    if (init_nodes.isEmpty())
        typeRuleError2(xmlFile, srcLine(), -1,
                       QString("Error parsing expression: %1")
                            .arg(codeStr));

    // Try to evaluate expression
    ASTTypeEvaluator t_eval(&ast, factory->memSpecs().sizeofLong,
                            factory->memSpecs().sizeofPointer, factory);
    ASTExpressionEvaluator e_eval(&t_eval, factory);
    ASTNodeNodeHash ptsTo;
    _expr = e_eval.exprOfNode(init_nodes.first(), ptsTo);
    if (_expr)
        // Expression belongs to the evaluator, we need to clone it
        _expr = _expr->copy(_exprList);
    else
        typeRuleError2(xmlFile, srcLine(), -1,
                       QString("Error evaluating expression: %1")
                            .arg(QString(_exprStr)));

    _altRefType.setId(_targetType->id());
    _altRefType.setExpr(_expr);

    return true;
}
Exemple #7
0
const BaseType* ExpressionAction::parseTypeStr(
        const QString &xmlFile, const TypeRule *rule, SymFactory *factory,
        const QString& what, const QString& typeStr, QString& id,
        bool *usesTypeId) const
{
    // Did we get a type name or a type ID?
    if (typeStr.startsWith("0x")) {
        if (usesTypeId)
            *usesTypeId = true;
        QStringList typeStrParts = typeStr.split(QRegExp("\\s+"));
        if (typeStrParts.isEmpty() || typeStrParts.size() > 2)
            typeRuleError2(xmlFile, srcLine(), -1,
                           QString("The specified %0 '%1' is invalid (expected "
                                   "a type ID and an identifier, e.g. '0x89ab "
                                   "src').")
                                .arg(what)
                                .arg(typeStr));

        QString typeIdStr = typeStrParts.first();
        bool ok = false;
        int typeId = typeIdStr.right(typeIdStr.size() - 2).toUInt(&ok, 16);
        if (!ok)
            typeRuleError2(xmlFile, srcLine(), -1,
                           QString("The type ID '%0' for the %1 is invalid.")
                                .arg(typeIdStr)
                                .arg(what));

        const BaseType* ret = factory->findBaseTypeById(typeId);
        if (!ret)
            typeRuleError2(xmlFile, srcLine(), -1,
                           QString("The type ID '%0' for the %1 does not exist.")
                                .arg(typeIdStr)
                                .arg(what));
        if (typeStrParts.size() > 1)
            id = typeStrParts.last();
        return ret;
    }
    else if (usesTypeId)
        *usesTypeId = false;

    // We got a type name expression, so parse it with the C parser
    AbstractSyntaxTree ast;
    ASTBuilder builder(&ast, factory);

    // Parse the code
    QByteArray code = QString("void %1(%2);").arg("__FUNCTION__").arg(typeStr).toAscii();
    if (builder.buildFrom(code) != 0)
        typeRuleError3(xmlFile, srcLine(), -1, TypeRuleException::ecSyntaxError,
                       QString("Syntax error in %0: %1")
                            .arg(what)
                            .arg(typeStr));

    QList<const ASTNode*> paramNodes =
            ASTNodeFinder::find(nt_parameter_declaration, &ast);
    // We might have more than one parameter for function pointer types, but the
    // first one is the one in __FUNCTION__()
    assert(paramNodes.size() > 0);
    const ASTNode* paramNode = paramNodes.first();

    // Do we have a declarator with or without an identifier?
    id.clear();
    const ASTNode* d_ad = paramNode->u.parameter_declaration.declarator_list ?
                paramNode->u.parameter_declaration.declarator_list->item : 0;
    if (d_ad && d_ad->type == nt_declarator)  {
        // Find the direct declaratior with identifier
        const ASTNode* dd = d_ad->u.declarator.direct_declarator;
        while (dd && !dd->u.direct_declarator.identifier) {
            dd = dd->u.direct_declarator.declarator
                   ->u.declarator.direct_declarator;
        }
        assert(dd != 0);
        assert(dd->u.direct_declarator.identifier);
        id = ast.antlrTokenToStr(dd->u.direct_declarator.identifier);
    }

    KernelSourceTypeEvaluator t_eval(&ast, factory);

    // Evaluate type of parameter_declaration
    ASTType* astType = t_eval.typeofNode(paramNode);
    if (!astType)
        typeRuleError2(xmlFile, srcLine(), -1,
                       QString("Error parsing expression: %1").arg(QString(code)));

    // Search correspondig BaseType
    FoundBaseTypes found =
            factory->findBaseTypesForAstType(astType, &t_eval, false);
    if (found.types.isEmpty())
        typeRuleError2(xmlFile, srcLine(), -1,
                       QString("Cannot find %1: %2").arg(what).arg(QString(code)));
    else if (found.types.size() > 1) {
        static const int type_ambiguous = -1;
        static const int no_type_found = -2;
        int match_idx = type_ambiguous;

        if (rule) {
            match_idx = no_type_found;
            // Find a unique type that matches the filter
            for (int i = 0; i < found.types.size(); ++i) {
                if (rule->match(found.types.at(i)) ||
                    rule->match(found.typesNonPtr.at(i)))
                {
                    if (match_idx < 0)
                        match_idx = i;
                    else {
                        const BaseType* t1 =
                                found.typesNonPtr.at(match_idx)->dereferencedBaseType(BaseType::trLexical);
                        const BaseType* t2 =
                                found.typesNonPtr.at(i)->dereferencedBaseType(BaseType::trLexical);
                        // Compare the hashes of the non-lexical types, only if
                        // they are different the type is ambiguous.
                        if (t1->hash() != t2->hash()) {
                            match_idx = type_ambiguous;
                            break;
                        }
                        else {
                            // Prefer the type that exactly corresponds to the
                            // ASTType
                            if (found.typesNonPtr.at(i)->type() == found.astTypeNonPtr->type())
                                match_idx = i;
                        }
                    }
                }
            }
        }

        if (match_idx >= 0)
            return found.types.at(match_idx);
        else if (match_idx == type_ambiguous)
            typeRuleError3(xmlFile, srcLine(), -1, TypeRuleException::ecTypeAmbiguous,
                           QString("The %1 is ambiguous, %2 types found for: %3")
                           .arg(what)
                           .arg(found.types.size())
                           .arg(typeStr));
        else
            typeRuleError3(xmlFile, srcLine(), -1, TypeRuleException::ecNotCompatible,
                           QString("Cannot find any compatible type for the %1: %2")
                           .arg(what).arg(typeStr));
    }
    else
        return found.types.first();

    return 0;
}