Beispiel #1
0
PyType PyType::target() const
{
    const std::string &typeName = name();
    if (isPointerType(typeName) || isArrayType(typeName))
        return lookupType(targetName(), m_module);
    return PyType();
}
Beispiel #2
0
PyType PyType::lookupType(const std::string &typeNameIn, ULONG64 module)
{
    if (debuggingTypeEnabled())
        DebugPrint() << "lookup type '" << typeNameIn << "'";
    std::string typeName = typeNameIn;
    trimBack(typeName);
    trimFront(typeName);

    if (isPointerType(typeName) || isArrayType(typeName))
        return PyType(0, 0, typeName);

    if (typeName.find("enum ") == 0)
        typeName.erase(0, 5);
    if (endsWith(typeName, " const"))
        typeName.erase(typeName.length() - 6);
    if (typeName == "__int64" || typeName == "unsigned __int64")
        typeName.erase(typeName.find("__"), 2);

    const static std::regex typeNameRE("^[a-zA-Z_][a-zA-Z0-9_]*!?[a-zA-Z0-9_<>:, \\*\\&\\[\\]]*$");
    if (!std::regex_match(typeName, typeNameRE))
        return PyType();

    CIDebugSymbols *symbols = ExtensionCommandContext::instance()->symbols();
    ULONG typeId;
    HRESULT result = S_FALSE;
    if (module != 0 && !isIntegralType(typeName) && !isFloatType(typeName))
        result = symbols->GetTypeId(module, typeName.c_str(), &typeId);
    if (FAILED(result) || result == S_FALSE)
        result = symbols->GetSymbolTypeId(typeName.c_str(), &typeId, &module);
    if (FAILED(result))
        return createUnresolvedType(typeName);
    return PyType(module, typeId, typeName);

}
// Create a new storage instance.
Chimera::Storage::Storage(const Chimera *ct)
    : _parsed_type(ct), _ptr_storage(0), _tmp_state(0), _valid(true)
{
    if (!isPointerType())
    {
        // Create a default fundamental or value type.
        _value_storage = QVariant(_parsed_type->metatype(), (const void *)0);
    }
}
Beispiel #4
0
QByteArray gdbQuoteTypes(const QByteArray &type)
{
    // gdb does not understand sizeof(Core::IDocument*).
    // "sizeof('Core::IDocument*')" is also not acceptable,
    // it needs to be "sizeof('Core::IDocument'*)"
    //
    // We never will have a perfect solution here (even if we had a full blown
    // C++ parser as we do not have information on what is a type and what is
    // a variable name. So "a<b>::c" could either be two comparisons of values
    // 'a', 'b' and '::c', or a nested type 'c' in a template 'a<b>'. We
    // assume here it is the latter.
    //return type;

    // (*('myns::QPointer<myns::QObject>*'*)0x684060)" is not acceptable
    // (*('myns::QPointer<myns::QObject>'**)0x684060)" is acceptable
    if (isPointerType(type))
        return gdbQuoteTypes(stripPointerType(type)) + '*';

    QByteArray accu;
    QByteArray result;
    int templateLevel = 0;

    const char colon = ':';
    const char singleQuote = '\'';
    const char lessThan = '<';
    const char greaterThan = '>';
    for (int i = 0; i != type.size(); ++i) {
        const char c = type.at(i);
        if (isLetterOrNumber(c) || c == '_' || c == colon || c == ' ') {
            accu += c;
        } else if (c == lessThan) {
            ++templateLevel;
            accu += c;
        } else if (c == greaterThan) {
            --templateLevel;
            accu += c;
        } else if (templateLevel > 0) {
            accu += c;
        } else {
            if (accu.contains(colon) || accu.contains(lessThan))
                result += singleQuote + accu + singleQuote;
            else
                result += accu;
            accu.clear();
            result += c;
        }
    }
    if (accu.contains(colon) || accu.contains(lessThan))
        result += singleQuote + accu + singleQuote;
    else
        result += accu;
    //qDebug() << "GDB_QUOTING" << type << " TO " << result;

    return result;
}
Beispiel #5
0
static GuessChildrenResult guessChildren(const QByteArray &type)
{
    if (isIntOrFloatType(type))
        return HasNoChildren;
    if (isCharPointerType(type))
        return HasNoChildren;
    if (isPointerType(type))
        return HasChildren;
    if (type.endsWith("QString"))
        return HasNoChildren;
    return HasPossiblyChildren;
}
Beispiel #6
0
TCResult ast::SliceOp::typecheck(sst::TypecheckState* fs, fir::Type* inferred)
{
	fs->pushLoc(this);
	defer(fs->popLoc());

	fs->pushAnonymousTree();
	defer(fs->popTree());

	auto array = this->expr->typecheck(fs).expr();
	auto ty = array->type;

	fs->enterSubscript(array);
	defer(fs->leaveSubscript());

	fir::Type* elm = 0;
	if(ty->isDynamicArrayType() || ty->isArraySliceType() || ty->isArrayType())
		elm = ty->getArrayElementType();

	else if(ty->isStringType())
		elm = fir::Type::getInt8();

	else if(ty->isPointerType())
		elm = ty->getPointerElementType();

	else
		error(array, "invalid type '%s' for slice operation", ty);

	auto begin = this->start ? this->start->typecheck(fs, fir::Type::getInt64()).expr() : 0;
	auto end = this->end ? this->end->typecheck(fs, fir::Type::getInt64()).expr() : 0;

	if(begin && !begin->type->isIntegerType())
		error(begin, "expected integer type for start index of slice; found '%s'", begin->type);

	if(end && !end->type->isIntegerType())
		error(end, "expected integer type for end index of slice; found '%s'", end->type);

	//* how it goes:
	// 1. strings and dynamic arrays are always sliced mutably.
	// 2. slices of slices naturally inherit their mutability.
	// 3. arrays are sliced immutably.
	// 4. pointers inherit their mutability as well.

	bool ismut = sst::getMutabilityOfSliceOfType(ty);

	auto ret = util::pool<sst::SliceOp>(this->loc, fir::ArraySliceType::get(elm, ismut));
	ret->expr = array;
	ret->begin = begin;
	ret->end = end;

	return TCResult(ret);
}
// Return the address of the storage.
void *Chimera::Storage::address()
{
    if (isPointerType())
    {
        if (_parsed_type->name().endsWith('*'))
            return &_ptr_storage;

        return _ptr_storage;
    }

    if (_parsed_type->typeDef() == sipType_QVariant)
        return &_value_storage;

    return _value_storage.data();
}
Beispiel #8
0
std::string PyType::targetName() const
{
    const std::string &typeName = name();
    if (isPointerType(typeName))
        return stripPointerType(typeName);
    if (isArrayType(typeName)) {
        const auto openArrayPos = typeName.find_first_of('[');
        if (openArrayPos == std::string::npos)
            return typeName;
        const auto closeArrayPos = typeName.find_first_of(']', openArrayPos);
        if (closeArrayPos == std::string::npos)
            return typeName;
        return typeName.substr(0, openArrayPos) + typeName.substr(closeArrayPos + 1);
    }
    return typeName;
}
Beispiel #9
0
int PyType::code() const
{
    if (!m_resolved)
        return TypeCodeUnresolvable;

    if (m_tag < 0) {
        // try to parse typeName
        const std::string &typeName = name();
        if (typeName.empty())
            return TypeCodeUnresolvable;
        if (isPointerType(typeName))
            return TypeCodePointer;
        if (isArrayType(typeName))
            return TypeCodeArray;
        if (typeName.find("<function>") == 0)
            return TypeCodeFunction;
        if (isIntegralType(typeName))
            return TypeCodeIntegral;
        if (isFloatType(typeName))
            return TypeCodeFloat;

        IDebugSymbolGroup2 *sg = 0;
        if (FAILED(ExtensionCommandContext::instance()->symbols()->CreateSymbolGroup2(&sg)))
            return TypeCodeStruct;

        if (knownType(name(), 0) != KT_Unknown)
            return TypeCodeStruct;

        const std::string helperValueName = SymbolGroupValue::pointedToSymbolName(0, name(true));
        ULONG index = DEBUG_ANY_ID;
        if (SUCCEEDED(sg->AddSymbol(helperValueName.c_str(), &index)))
            m_tag = PyValue(index, sg).tag();
        sg->Release();
    }
    switch (m_tag) {
    case SymTagUDT: return TypeCodeStruct;
    case SymTagEnum: return TypeCodeEnum;
    case SymTagTypedef: return TypeCodeTypedef;
    case SymTagFunctionType: return TypeCodeFunction;
    case SymTagPointerType: return TypeCodePointer;
    case SymTagArrayType: return TypeCodeArray;
    case SymTagBaseType: return isIntegralType(name()) ? TypeCodeIntegral : TypeCodeFloat;
    default: break;
    }

    return TypeCodeStruct;
}
Beispiel #10
0
PyFields PyType::fields() const
{
    CIDebugSymbols *symbols = ExtensionCommandContext::instance()->symbols();
    PyFields fields;
    if (isArrayType(name()) || isPointerType(name()))
        return fields;
    for (ULONG fieldIndex = 0;; ++fieldIndex) {
        ULONG size = 0;
        symbols->GetFieldName(m_module, m_typeId, fieldIndex, NULL, 0, &size);
        if (size == 0)
            break;
        std::string name(size - 1, '\0');
        if (FAILED(symbols->GetFieldName(m_module, m_typeId, fieldIndex, &name[0], size, NULL)))
            break;

        fields.push_back(PyField(name, *this));
    }
    return fields;
}
// Convert the stored value to a Python object.
PyObject *Chimera::Storage::toPyObject() const
{
    // Pointer-class and mapped types are not stored in the QVariant.
    if (isPointerType())
    {
        if (!_ptr_storage)
        {
            Py_INCREF(Py_None);
            return Py_None;
        }

        return sipConvertFromType(_ptr_storage, _parsed_type->typeDef(), 0);
    }

    if (_parsed_type->typeDef() == sipType_QVariant)
            return Chimera::toAnyPyObject(_value_storage);

    return _parsed_type->toPyObject(_value_storage);
}
// Create a new storage instance containing a converted Python object.
Chimera::Storage::Storage(const Chimera *ct, PyObject *py)
    : _parsed_type(ct), _ptr_storage(0), _tmp_state(0)
{
    // We convert to a QVariant even for pointer types because this has the
    // side-effect of ensuring the object doesn't get garbage collected.
    _valid = _parsed_type->fromPyObject(py, &_value_storage);

    if (isPointerType())
    {
        int is_err = 0;

        _ptr_storage = sipForceConvertToType(py, _parsed_type->typeDef(), 0, 0,
                &_tmp_state, &is_err);

        if (is_err)
        {
            _value_storage = QVariant();
            _valid = false;
        }
    }
}
Beispiel #13
0
void WatchData::setValue(const QString &value0)
{
    value = value0;
    if (value == "{...}") {
        value.clear();
        hasChildren = true; // at least one...
    }
    // strip off quoted characters for chars.
    if (value.endsWith(QLatin1Char('\'')) && type.endsWith("char")) {
        const int blankPos = value.indexOf(QLatin1Char(' '));
        if (blankPos != -1)
            value.truncate(blankPos);
    }

    // avoid duplicated information
    if (value.startsWith(QLatin1Char('(')) && value.contains(") 0x"))
        value = value.mid(value.lastIndexOf(") 0x") + 2);

    // doubles are sometimes displayed as "@0x6141378: 1.2".
    // I don't want that.
    if (/*isIntOrFloatType(type) && */ value.startsWith("@0x")
         && value.contains(':')) {
        value = value.mid(value.indexOf(':') + 2);
        setHasChildren(false);
    }

    // "numchild" is sometimes lying
    //MODEL_DEBUG("\n\n\nPOINTER: " << type << value);
    if (isPointerType(type))
        setHasChildren(value != "0x0" && value != "<null>"
            && !isCharPointerType(type));

    // pointer type information is available in the 'type'
    // column. No need to duplicate it here.
    if (value.startsWith(QLatin1Char('(') + type + ") 0x"))
        value = value.section(QLatin1Char(' '), -1, -1);

    setValueUnneeded();
}