Improve pretty printing in NodeVisitor
This commit is contained in:
parent
2e3af1c9c9
commit
d88a62893a
|
@ -631,7 +631,7 @@ bool TypeManager::visitMember(const Member & root, Visitor & visitor, const std:
|
||||||
am.arraySize = -1;
|
am.arraySize = -1;
|
||||||
|
|
||||||
for(auto i = 0; i < child.arraySize; i++)
|
for(auto i = 0; i < child.arraySize; i++)
|
||||||
if(!visitMember(am, visitor, ""))
|
if(!visitMember(am, visitor, am.type))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if(!visitor.visitBack(child))
|
if(!visitor.visitBack(child))
|
||||||
|
@ -735,7 +735,7 @@ TypeBase* LookupTypeById(uint32_t typeId)
|
||||||
return typeManager.LookupTypeById(typeId);
|
return typeManager.LookupTypeById(typeId);
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeBase* LookupTypeByName(const char* name)
|
TypeBase* LookupTypeByName(const std::string & name)
|
||||||
{
|
{
|
||||||
SHARED_ACQUIRE(LockTypeManager);
|
SHARED_ACQUIRE(LockTypeManager);
|
||||||
return typeManager.LookupTypeByName(name);
|
return typeManager.LookupTypeByName(name);
|
||||||
|
|
|
@ -30,14 +30,22 @@ namespace Types
|
||||||
|
|
||||||
struct TypeBase
|
struct TypeBase
|
||||||
{
|
{
|
||||||
|
virtual ~TypeBase() = default;
|
||||||
|
virtual const char* prefix() const = 0;
|
||||||
|
|
||||||
std::string owner; //Type owner (header file name).
|
std::string owner; //Type owner (header file name).
|
||||||
std::string name; //Type identifier.
|
std::string name; //Type identifier.
|
||||||
|
|
||||||
uint32_t typeId = 0; // id from typeIdMap
|
uint32_t typeId = 0; // id from typeIdMap
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Typedef : TypeBase
|
struct Typedef final : TypeBase
|
||||||
{
|
{
|
||||||
|
const char* prefix() const override
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
std::string alias; //Typedef and Pointer primitives have this set to the type they point to
|
std::string alias; //Typedef and Pointer primitives have this set to the type they point to
|
||||||
Primitive primitive; //Primitive type.
|
Primitive primitive; //Primitive type.
|
||||||
int sizeBits = 0; //Size in bits.
|
int sizeBits = 0; //Size in bits.
|
||||||
|
@ -55,8 +63,13 @@ namespace Types
|
||||||
bool isBitfield = false; //Is this a bitfield?
|
bool isBitfield = false; //Is this a bitfield?
|
||||||
};
|
};
|
||||||
|
|
||||||
struct StructUnion : TypeBase
|
struct StructUnion final : TypeBase
|
||||||
{
|
{
|
||||||
|
const char* prefix() const override
|
||||||
|
{
|
||||||
|
return isUnion ? "union" : "struct";
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<Member> members; //StructUnion members
|
std::vector<Member> members; //StructUnion members
|
||||||
bool isUnion = false; //Is this a union?
|
bool isUnion = false; //Is this a union?
|
||||||
int sizeBits = -1; //Structure size in bits
|
int sizeBits = -1; //Structure size in bits
|
||||||
|
@ -70,16 +83,26 @@ namespace Types
|
||||||
Delphi,
|
Delphi,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Function : TypeBase
|
struct Function final : TypeBase
|
||||||
{
|
{
|
||||||
|
const char* prefix() const override
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
std::string returnType; //Function return type
|
std::string returnType; //Function return type
|
||||||
CallingConvention callconv = Cdecl; //Function calling convention
|
CallingConvention callconv = Cdecl; //Function calling convention
|
||||||
bool noreturn = false; //Function does not return (ExitProcess, _exit)
|
bool noreturn = false; //Function does not return (ExitProcess, _exit)
|
||||||
std::vector<Member> args; //Function arguments
|
std::vector<Member> args; //Function arguments
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Enum : TypeBase
|
struct Enum final : TypeBase
|
||||||
{
|
{
|
||||||
|
const char* prefix() const override
|
||||||
|
{
|
||||||
|
return "enum";
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<std::pair<uint64_t, std::string>> members;
|
std::vector<std::pair<uint64_t, std::string>> members;
|
||||||
uint8_t sizeBits; //Enum size in bits
|
uint8_t sizeBits; //Enum size in bits
|
||||||
bool isFlags; //Enum members are bit flags
|
bool isFlags; //Enum members are bit flags
|
||||||
|
@ -198,7 +221,7 @@ bool AddFunction(const std::string & owner, const std::string & name, const std:
|
||||||
bool AddArg(const std::string & function, const std::string & type, const std::string & name);
|
bool AddArg(const std::string & function, const std::string & type, const std::string & name);
|
||||||
bool AppendArg(const std::string & type, const std::string & name);
|
bool AppendArg(const std::string & type, const std::string & name);
|
||||||
Types::TypeBase* LookupTypeById(uint32_t typeId);
|
Types::TypeBase* LookupTypeById(uint32_t typeId);
|
||||||
Types::TypeBase* LookupTypeByName(const char* typeName);
|
Types::TypeBase* LookupTypeByName(const std::string & typeName);
|
||||||
int SizeofType(const std::string & type);
|
int SizeofType(const std::string & type);
|
||||||
bool VisitType(const std::string & type, const std::string & name, Types::TypeManager::Visitor & visitor);
|
bool VisitType(const std::string & type, const std::string & name, Types::TypeManager::Visitor & visitor);
|
||||||
void ClearTypes(const std::string & owner = "");
|
void ClearTypes(const std::string & owner = "");
|
||||||
|
|
|
@ -293,6 +293,17 @@ static bool cbPrintEnum(const TYPEDESCRIPTOR* type, char* dest, size_t* destCoun
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char* LookupTypePrefix(const std::string & typeName)
|
||||||
|
{
|
||||||
|
auto type = LookupTypeByName(typeName);
|
||||||
|
auto td = dynamic_cast<Typedef*>(type);
|
||||||
|
if(td != nullptr && td->primitive == Alias)
|
||||||
|
{
|
||||||
|
return LookupTypePrefix(td->alias);
|
||||||
|
}
|
||||||
|
return type->prefix();
|
||||||
|
}
|
||||||
|
|
||||||
bool NodeVisitor::visitType(const Member & member, const Typedef & type, const std::string & prettyType)
|
bool NodeVisitor::visitType(const Member & member, const Typedef & type, const std::string & prettyType)
|
||||||
{
|
{
|
||||||
if(!mParents.empty() && parent().type == Parent::Union)
|
if(!mParents.empty() && parent().type == Parent::Union)
|
||||||
|
@ -302,31 +313,42 @@ bool NodeVisitor::visitType(const Member & member, const Typedef & type, const s
|
||||||
}
|
}
|
||||||
|
|
||||||
String tname;
|
String tname;
|
||||||
auto ptype = mParents.empty() ? Parent::Struct : parent().type;
|
auto isArrayMember = !mParents.empty() && parent().type == Parent::Type::Array;
|
||||||
if(ptype == Parent::Array)
|
if(isArrayMember)
|
||||||
{
|
{
|
||||||
tname = StringUtils::sprintf("%s[%u]", member.name.c_str(), parent().index++);
|
tname += '[';
|
||||||
|
tname += std::to_string(parent().arrayIndex++);
|
||||||
|
tname += ']';
|
||||||
|
tname += ' ';
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
if(member.isBitfield)
|
|
||||||
tname = StringUtils::sprintf("%s %s : %d", prettyType.c_str(), member.name.c_str(), member.sizeBits);
|
|
||||||
else
|
|
||||||
tname = StringUtils::sprintf("%s %s", prettyType.c_str(), member.name.c_str());
|
|
||||||
|
|
||||||
// Prepend struct/union to pointer types
|
if(type.primitive == Pointer && !type.alias.empty())
|
||||||
if(!type.alias.empty())
|
{
|
||||||
|
auto ptrPrefix = LookupTypePrefix(type.alias);
|
||||||
|
if(*ptrPrefix)
|
||||||
{
|
{
|
||||||
auto ptrname = StructUnionPtrType(type.alias);
|
tname += ptrPrefix;
|
||||||
if(!ptrname.empty())
|
tname += ' ';
|
||||||
tname = ptrname + " " + tname;
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!isArrayMember)
|
||||||
|
{
|
||||||
|
tname += prettyType;
|
||||||
|
tname += ' ';
|
||||||
|
tname += member.name;
|
||||||
|
|
||||||
|
if(member.isBitfield)
|
||||||
|
{
|
||||||
|
tname += " : ";
|
||||||
|
tname += std::to_string(member.sizeBits);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string path;
|
std::string path;
|
||||||
for(size_t i = 0; i < mPath.size(); i++)
|
for(size_t i = 0; i < mPath.size(); i++)
|
||||||
{
|
{
|
||||||
if(ptype == Parent::Array && i + 1 == mPath.size())
|
if(isArrayMember && i + 1 == mPath.size())
|
||||||
break;
|
break;
|
||||||
path.append(mPath[i]);
|
path.append(mPath[i]);
|
||||||
}
|
}
|
||||||
|
@ -335,7 +357,7 @@ bool NodeVisitor::visitType(const Member & member, const Typedef & type, const s
|
||||||
auto ptr = mAddr + mOffset;
|
auto ptr = mAddr + mOffset;
|
||||||
if(mCreateLabels && MemIsValidReadPtr(ptr))
|
if(mCreateLabels && MemIsValidReadPtr(ptr))
|
||||||
{
|
{
|
||||||
if(!LabelGet(ptr, nullptr) && (!mParents.empty() && (parent().index == 1 || ptype != Parent::Array)))
|
if(!LabelGet(ptr, nullptr) && (!mParents.empty() && (parent().arrayIndex == 1 || !isArrayMember)))
|
||||||
LabelSet(ptr, path.c_str(), false, true);
|
LabelSet(ptr, path.c_str(), false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -378,20 +400,29 @@ bool NodeVisitor::visitStructUnion(const Member & member, const StructUnion & ty
|
||||||
mBitOffset = 0;
|
mBitOffset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string targetType;
|
std::string tname;
|
||||||
if(prettyType.find("__anonymous") == 0)
|
auto isArrayMember = !mParents.empty() && parent().type == Parent::Type::Array;
|
||||||
targetType = "";
|
if(isArrayMember)
|
||||||
else
|
{
|
||||||
targetType = prettyType;
|
tname += '[';
|
||||||
|
tname += std::to_string(parent().arrayIndex++);
|
||||||
|
tname += ']';
|
||||||
|
tname += ' ';
|
||||||
|
}
|
||||||
|
|
||||||
std::string targetName;
|
tname += type.isUnion ? "union" : "struct";
|
||||||
if(member.name.find("__anonymous") == 0)
|
|
||||||
targetName = "";
|
|
||||||
else
|
|
||||||
targetName = member.name;
|
|
||||||
|
|
||||||
// TODO: the targetType is empty when displaying array members
|
if(prettyType.find("__anonymous") != 0)
|
||||||
String tname = StringUtils::sprintf("%s %s %s", type.isUnion ? "union" : "struct", targetType.c_str(), targetName.c_str());
|
{
|
||||||
|
tname += ' ';
|
||||||
|
tname += prettyType;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!isArrayMember && member.name.find("__anonymous") != 0)
|
||||||
|
{
|
||||||
|
tname += ' ';
|
||||||
|
tname += member.name;
|
||||||
|
}
|
||||||
|
|
||||||
TYPEDESCRIPTOR td = { };
|
TYPEDESCRIPTOR td = { };
|
||||||
td.expanded = mParents.size() < mMaxExpandDepth;
|
td.expanded = mParents.size() < mMaxExpandDepth;
|
||||||
|
@ -423,7 +454,28 @@ bool NodeVisitor::visitEnum(const Member & member, const Enum & num, const std::
|
||||||
mBitOffset = 0;
|
mBitOffset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
String tname = StringUtils::sprintf("enum %s %s", prettyType.c_str(), member.name.c_str());
|
std::string tname;
|
||||||
|
auto isArrayMember = !mParents.empty() && parent().type == Parent::Type::Array;
|
||||||
|
if(isArrayMember)
|
||||||
|
{
|
||||||
|
tname += '[';
|
||||||
|
tname += std::to_string(parent().arrayIndex++);
|
||||||
|
tname += ']';
|
||||||
|
tname += ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
tname += "enum";
|
||||||
|
if(prettyType.find("__anonymous") != 0)
|
||||||
|
{
|
||||||
|
tname += ' ';
|
||||||
|
tname += prettyType;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!isArrayMember && member.name.find("__anonymous") != 0)
|
||||||
|
{
|
||||||
|
tname += ' ';
|
||||||
|
tname += member.name;
|
||||||
|
}
|
||||||
|
|
||||||
TYPEDESCRIPTOR td = { };
|
TYPEDESCRIPTOR td = { };
|
||||||
td.expanded = mParents.size() < mMaxExpandDepth;
|
td.expanded = mParents.size() < mMaxExpandDepth;
|
||||||
|
@ -446,7 +498,19 @@ bool NodeVisitor::visitEnum(const Member & member, const Enum & num, const std::
|
||||||
|
|
||||||
bool NodeVisitor::visitArray(const Member & member, const std::string & prettyType)
|
bool NodeVisitor::visitArray(const Member & member, const std::string & prettyType)
|
||||||
{
|
{
|
||||||
String tname = StringUtils::sprintf("%s %s[%d]", prettyType.c_str(), member.name.c_str(), member.arraySize);
|
// TODO: support array of arrays?
|
||||||
|
|
||||||
|
std::string tname = LookupTypePrefix(member.type);
|
||||||
|
if(!tname.empty())
|
||||||
|
{
|
||||||
|
tname += ' ';
|
||||||
|
}
|
||||||
|
tname += prettyType;
|
||||||
|
tname += ' ';
|
||||||
|
tname += member.name;
|
||||||
|
tname += '[';
|
||||||
|
tname += std::to_string(member.arraySize);
|
||||||
|
tname += ']';
|
||||||
|
|
||||||
TYPEDESCRIPTOR td = { };
|
TYPEDESCRIPTOR td = { };
|
||||||
auto isPadding = member.name.find("padding") == 0;
|
auto isPadding = member.name.find("padding") == 0;
|
||||||
|
@ -472,6 +536,8 @@ bool NodeVisitor::visitArray(const Member & member, const std::string & prettyTy
|
||||||
|
|
||||||
bool NodeVisitor::visitPtr(const Member & member, const Typedef & type, const std::string & prettyType)
|
bool NodeVisitor::visitPtr(const Member & member, const Typedef & type, const std::string & prettyType)
|
||||||
{
|
{
|
||||||
|
// TODO: support array of pointers?
|
||||||
|
|
||||||
auto offset = mOffset;
|
auto offset = mOffset;
|
||||||
auto res = visitType(member, type, prettyType); //print the pointer value
|
auto res = visitType(member, type, prettyType); //print the pointer value
|
||||||
if(mPtrDepth >= mMaxPtrDepth)
|
if(mPtrDepth >= mMaxPtrDepth)
|
||||||
|
|
|
@ -45,7 +45,7 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
Type type;
|
Type type;
|
||||||
unsigned int index = 0;
|
unsigned int arrayIndex = 0;
|
||||||
duint addr = 0;
|
duint addr = 0;
|
||||||
duint offset = 0;
|
duint offset = 0;
|
||||||
void* node = nullptr;
|
void* node = nullptr;
|
||||||
|
|
|
@ -238,6 +238,10 @@ void TypeWidget::updateValuesSlot()
|
||||||
|
|
||||||
QString TypeWidget::highlightTypeName(QString name) const
|
QString TypeWidget::highlightTypeName(QString name) const
|
||||||
{
|
{
|
||||||
|
// Pass through names that already have HTML tags
|
||||||
|
if(name.contains('<'))
|
||||||
|
return name;
|
||||||
|
|
||||||
// TODO: this can be improved with colors
|
// TODO: this can be improved with colors
|
||||||
static auto re = []
|
static auto re = []
|
||||||
{
|
{
|
||||||
|
@ -295,8 +299,8 @@ QString TypeWidget::highlightTypeName(QString name) const
|
||||||
|
|
||||||
name.replace(re, "<b>\\1</b>");
|
name.replace(re, "<b>\\1</b>");
|
||||||
|
|
||||||
static QRegExp sre("^(struct|union|class|enum) ([a-zA-Z0-9_:$]+)");
|
static QRegExp sre("^(\\[\\d+\\] )?(struct|union|class|enum)( [a-zA-Z0-9_:$]+)?");
|
||||||
name.replace(sre, "<u>\\1</u> <b>\\2</b>");
|
name.replace(sre, "\\1<u>\\2</u><b>\\3</b>");
|
||||||
|
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue