mirror of https://github.com/x64dbg/btparser
				
				
				
			Switch to QualifiedType everywhere
This commit is contained in:
		
							parent
							
								
									659a8e87a6
								
							
						
					
					
						commit
						07a7b308e8
					
				|  | @ -110,7 +110,7 @@ bool DebugParser(const std::string & filename) | ||||||
|     FileHelper::WriteAllText("tests\\" + filename + ".pp.h", ppData); |     FileHelper::WriteAllText("tests\\" + filename + ".pp.h", ppData); | ||||||
| 
 | 
 | ||||||
|     std::vector<std::string> errors; |     std::vector<std::string> errors; | ||||||
|     Types::TypeManager typeManager; |     Types::TypeManager typeManager(sizeof(void*)); | ||||||
|     if (!typeManager.ParseTypes(ppData, filename, errors)) |     if (!typeManager.ParseTypes(ppData, filename, errors)) | ||||||
|     { |     { | ||||||
|         puts("Failed to parse types:"); |         puts("Failed to parse types:"); | ||||||
|  |  | ||||||
|  | @ -9,7 +9,7 @@ using namespace Types; | ||||||
| #define EXCLUSIVE_ACQUIRE(x) | #define EXCLUSIVE_ACQUIRE(x) | ||||||
| #define SHARED_ACQUIRE(x) | #define SHARED_ACQUIRE(x) | ||||||
| 
 | 
 | ||||||
| TypeManager::TypeManager() | TypeManager::TypeManager(size_t pointerSize) | ||||||
| { | { | ||||||
|     auto p = [this](const std::string & n, Primitive p, int size) |     auto p = [this](const std::string & n, Primitive p, int size) | ||||||
|     { |     { | ||||||
|  | @ -21,21 +21,21 @@ TypeManager::TypeManager() | ||||||
|             addType("", p, split); |             addType("", p, split); | ||||||
|         } |         } | ||||||
|     }; |     }; | ||||||
|     p("int8_t,int8,char,byte,bool,signed char", Int8, sizeof(char)); |     p("int8_t,int8,char,byte,bool,signed char", Int8, sizeof(int8_t)); | ||||||
|     p("uint8_t,uint8,uchar,unsigned char,ubyte", Uint8, sizeof(unsigned char)); |     p("uint8_t,uint8,uchar,unsigned char,ubyte", Uint8, sizeof(uint8_t)); | ||||||
|     p("int16_t,int16,wchar_t,char16_t,short", Int16, sizeof(short)); |     p("int16_t,int16,wchar_t,char16_t,short", Int16, sizeof(int16_t)); | ||||||
|     p("uint16_t,uint16,ushort,unsigned short", Int16, sizeof(unsigned short)); |     p("uint16_t,uint16,ushort,unsigned short", Uint16, sizeof(uint16_t)); | ||||||
|     p("int32_t,int32,int,long", Int32, sizeof(int)); |     p("int32_t,int32,int,long", Int32, sizeof(int32_t)); | ||||||
|     p("uint32_t,uint32,unsigned int,unsigned long", Uint32, sizeof(unsigned int)); |     p("uint32_t,uint32,unsigned int,unsigned long", Uint32, sizeof(uint32_t)); | ||||||
|     p("int64_t,int64,long long", Int64, sizeof(long long)); |     p("int64_t,int64,long long", Int64, sizeof(int64_t)); | ||||||
|     p("uint64_t,uint64,unsigned long long", Uint64, sizeof(unsigned long long)); |     p("uint64_t,uint64,unsigned long long", Uint64, sizeof(uint64_t)); | ||||||
|     p("dsint", Dsint, sizeof(void*)); |     p("ssize_t,dsint", Dsint, pointerSize); | ||||||
|     p("size_t,duint", Duint, sizeof(void*)); |     p("size_t,duint", Duint, pointerSize); | ||||||
|     p("float", Float, sizeof(float)); |     p("float", Float, sizeof(float)); | ||||||
|     p("double", Double, sizeof(double)); |     p("double", Double, sizeof(double)); | ||||||
|     p("void*,ptr", Pointer, sizeof(void*)); |     p("void*,ptr", Pointer, pointerSize); | ||||||
|     p("char*,const char*", PtrString, sizeof(char*)); |     p("char*,const char*", PtrString, pointerSize); | ||||||
|     p("wchar_t*,const wchar_t*", PtrWString, sizeof(wchar_t*)); |     p("wchar_t*,const wchar_t*", PtrWString, pointerSize); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| std::string Types::TypeManager::PrimitiveName(Primitive primitive) | std::string Types::TypeManager::PrimitiveName(Primitive primitive) | ||||||
|  | @ -48,7 +48,6 @@ bool TypeManager::AddType(const std::string & owner, const std::string & type, c | ||||||
| { | { | ||||||
|     if(owner.empty()) |     if(owner.empty()) | ||||||
|         return false; |         return false; | ||||||
|     validPtr(type); |  | ||||||
|     auto found = types.find(type); |     auto found = types.find(type); | ||||||
|     if(found == types.end()) |     if(found == types.end()) | ||||||
|         return false; |         return false; | ||||||
|  | @ -60,11 +59,10 @@ bool Types::TypeManager::AddEnum(const std::string& owner, const std::string& na | ||||||
|     Enum e; |     Enum e; | ||||||
|     e.name = name; |     e.name = name; | ||||||
|     e.owner = owner; |     e.owner = owner; | ||||||
|  | 
 | ||||||
|     auto found = types.find(type); |     auto found = types.find(type); | ||||||
|     if (found == types.end()) |     if (found == types.end()) | ||||||
|         return false; |         return false; | ||||||
|     if (!found->second.pointto.empty()) |  | ||||||
|         return false; |  | ||||||
|     switch (found->second.primitive) |     switch (found->second.primitive) | ||||||
|     { |     { | ||||||
|     case Void: |     case Void: | ||||||
|  | @ -98,12 +96,12 @@ bool TypeManager::AddUnion(const std::string & owner, const std::string & name) | ||||||
|     return addStructUnion(u); |     return addStructUnion(u); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool TypeManager::AddMember(const std::string & parent, const std::string & type, const std::string & name, int arrsize, int offset) | bool TypeManager::AddMember(const std::string & parent, const QualifiedType& type, const std::string & name, int arrsize, int offset) | ||||||
| { | { | ||||||
|     if(!isDefined(type) && !validPtr(type)) |     if(!isDefined(type.name)) | ||||||
|         return false; |         return false; | ||||||
|     auto found = structs.find(parent); |     auto found = structs.find(parent); | ||||||
|     if(arrsize < 0 || found == structs.end() || !isDefined(type) || name.empty() || type.empty() || type == parent) |     if(arrsize < 0 || found == structs.end() || name.empty() || type.empty() || type.name == parent) | ||||||
|         return false; |         return false; | ||||||
|     auto & s = found->second; |     auto & s = found->second; | ||||||
| 
 | 
 | ||||||
|  | @ -128,7 +126,7 @@ bool TypeManager::AddMember(const std::string & parent, const std::string & type | ||||||
|         if(offset > s.size) |         if(offset > s.size) | ||||||
|         { |         { | ||||||
|             Member pad; |             Member pad; | ||||||
|             pad.type = "char"; |             pad.type = QualifiedType("char"); | ||||||
|             pad.arrsize = offset - s.size; |             pad.arrsize = offset - s.size; | ||||||
|             char padname[32] = ""; |             char padname[32] = ""; | ||||||
|             sprintf_s(padname, "padding%d", pad.arrsize); |             sprintf_s(padname, "padding%d", pad.arrsize); | ||||||
|  | @ -152,7 +150,7 @@ bool TypeManager::AddMember(const std::string & parent, const std::string & type | ||||||
|     return true; |     return true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool TypeManager::AppendMember(const std::string & type, const std::string & name, int arrsize, int offset) | bool TypeManager::AppendMember(const QualifiedType& type, const std::string & name, int arrsize, int offset) | ||||||
| { | { | ||||||
|     return AddMember(laststruct, type, name, arrsize, offset); |     return AddMember(laststruct, type, name, arrsize, offset); | ||||||
| } | } | ||||||
|  | @ -175,7 +173,7 @@ bool Types::TypeManager::AddEnumerator(const std::string& enumType, const std::s | ||||||
|     return true; |     return true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool TypeManager::AddFunction(const std::string & owner, const std::string & name, const QualifiedType& retqtype, CallingConvention callconv, bool noreturn, bool typeonly) | bool TypeManager::AddFunction(const std::string & owner, const std::string & name, const QualifiedType& rettype, CallingConvention callconv, bool noreturn, bool typeonly) | ||||||
| { | { | ||||||
|     auto found = functions.find(name); |     auto found = functions.find(name); | ||||||
|     if(found != functions.end() || name.empty() || owner.empty()) |     if(found != functions.end() || name.empty() || owner.empty()) | ||||||
|  | @ -184,9 +182,10 @@ bool TypeManager::AddFunction(const std::string & owner, const std::string & nam | ||||||
|     Function f; |     Function f; | ||||||
|     f.owner = owner; |     f.owner = owner; | ||||||
|     f.name = name; |     f.name = name; | ||||||
|     if (retqtype.name != "void" && !isDefined(retqtype.name)) |     auto isVoid = !rettype.isPointer() && rettype.name == "void"; | ||||||
|  |     if (!isVoid && !isDefined(rettype)) | ||||||
|         return false; |         return false; | ||||||
|     f.retqtype = retqtype; |     f.rettype = rettype; | ||||||
|     f.callconv = callconv; |     f.callconv = callconv; | ||||||
|     f.noreturn = noreturn; |     f.noreturn = noreturn; | ||||||
|     f.typeonly = typeonly; |     f.typeonly = typeonly; | ||||||
|  | @ -194,28 +193,27 @@ bool TypeManager::AddFunction(const std::string & owner, const std::string & nam | ||||||
|     return true; |     return true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool TypeManager::AddArg(const std::string & function, const std::string & type, const std::string & name, const QualifiedType& qtype) | bool TypeManager::AddArg(const std::string & function, const QualifiedType& type, const std::string & name) | ||||||
| { | { | ||||||
|     auto found = functions.find(function); |     auto found = functions.find(function); | ||||||
|     if (found == functions.end() || name.empty()) |     if (found == functions.end() || name.empty()) | ||||||
|         return false; |         return false; | ||||||
|     if(type != "..." && !isDefined(type) && !validPtr(type)) |     if(type.name != "..." && !isDefined(type)) | ||||||
|         return false; |         return false; | ||||||
|     lastfunction = function; |     lastfunction = function; | ||||||
|     Member arg; |     Member arg; | ||||||
|     arg.name = name; |     arg.name = name; | ||||||
|     arg.type = type; |     arg.type = type; | ||||||
|     arg.qtype = qtype; |  | ||||||
|     found->second.args.push_back(arg); |     found->second.args.push_back(arg); | ||||||
|     return true; |     return true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool TypeManager::AppendArg(const std::string & type, const std::string & name, const QualifiedType& qtype) | bool TypeManager::AppendArg(const QualifiedType& type, const std::string & name) | ||||||
| { | { | ||||||
|     return AddArg(lastfunction, type, name, qtype); |     return AddArg(lastfunction, type, name); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int TypeManager::Sizeof(const std::string & type) const | int TypeManager::Sizeof(const std::string& type) const | ||||||
| { | { | ||||||
|     auto foundT = types.find(type); |     auto foundT = types.find(type); | ||||||
|     if(foundT != types.end()) |     if(foundT != types.end()) | ||||||
|  | @ -224,21 +222,23 @@ int TypeManager::Sizeof(const std::string & type) const | ||||||
|     if(foundS != structs.end()) |     if(foundS != structs.end()) | ||||||
|         return foundS->second.size; |         return foundS->second.size; | ||||||
|     auto foundF = functions.find(type); |     auto foundF = functions.find(type); | ||||||
|     if(foundF != functions.end()) |     if (foundF != functions.end()) | ||||||
|     { |         return primitivesizes.at(Pointer); | ||||||
|         const auto foundP = primitivesizes.find(Pointer); |  | ||||||
|         if(foundP != primitivesizes.end()) |  | ||||||
|             return foundP->second; |  | ||||||
|         return sizeof(void*); |  | ||||||
|     } |  | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | int TypeManager::Sizeof(const QualifiedType& type) const | ||||||
|  | { | ||||||
|  |     if (type.isPointer()) | ||||||
|  |         return primitivesizes.at(Pointer); | ||||||
|  |     return Sizeof(type.name); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| bool TypeManager::Visit(const std::string & type, const std::string & name, Visitor & visitor) const | bool TypeManager::Visit(const std::string & type, const std::string & name, Visitor & visitor) const | ||||||
| { | { | ||||||
|     Member m; |     Member m; | ||||||
|     m.name = name; |     m.name = name; | ||||||
|     m.type = type; |     m.type = QualifiedType(type); | ||||||
|     return visitMember(m, visitor); |     return visitMember(m, visitor); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -363,30 +363,18 @@ static bool mapContains(const std::unordered_map<K, V> & map, const K & k) | ||||||
|     return map.find(k) != map.end(); |     return map.find(k) != map.end(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | bool Types::TypeManager::isDefined(const QualifiedType& type) const | ||||||
|  | { | ||||||
|  |     if (type.name == "void" && type.isPointer()) | ||||||
|  |         return true; | ||||||
|  |     return isDefined(type.name); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| bool TypeManager::isDefined(const std::string & id) const | bool TypeManager::isDefined(const std::string & id) const | ||||||
| { | { | ||||||
|     return mapContains(types, id) || mapContains(structs, id) || mapContains(enums, id) || mapContains(functions, id); |     return mapContains(types, id) || mapContains(structs, id) || mapContains(enums, id) || mapContains(functions, id); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool TypeManager::validPtr(const std::string & id) |  | ||||||
| { |  | ||||||
|     if(id[id.length() - 1] == '*') |  | ||||||
|     { |  | ||||||
|         auto type = id.substr(0, id.length() - 1); |  | ||||||
|         if(!isDefined(type) && !validPtr(type)) |  | ||||||
|             return false; |  | ||||||
|         std::string owner("ptr"); |  | ||||||
|         auto foundT = types.find(type); |  | ||||||
|         if(foundT != types.end()) |  | ||||||
|             owner = foundT->second.owner; |  | ||||||
|         auto foundS = structs.find(type); |  | ||||||
|         if(foundS != structs.end()) |  | ||||||
|             owner = foundS->second.owner; |  | ||||||
|         return addType(owner, Pointer, id, type); |  | ||||||
|     } |  | ||||||
|     return false; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool TypeManager::addStructUnion(const StructUnion & s) | bool TypeManager::addStructUnion(const StructUnion & s) | ||||||
| { | { | ||||||
|     laststruct = s.name; |     laststruct = s.name; | ||||||
|  | @ -410,7 +398,7 @@ bool TypeManager::addType(const Type & t) | ||||||
|     return types.emplace(t.name, t).second; |     return types.emplace(t.name, t).second; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool TypeManager::addType(const std::string & owner, Primitive primitive, const std::string & name, const std::string & pointto) | bool TypeManager::addType(const std::string & owner, Primitive primitive, const std::string & name) | ||||||
| { | { | ||||||
|     if(name.empty() || isDefined(name)) |     if(name.empty() || isDefined(name)) | ||||||
|         return false; |         return false; | ||||||
|  | @ -419,16 +407,19 @@ bool TypeManager::addType(const std::string & owner, Primitive primitive, const | ||||||
|     t.name = name; |     t.name = name; | ||||||
|     t.primitive = primitive; |     t.primitive = primitive; | ||||||
|     t.size = primitivesizes[primitive]; |     t.size = primitivesizes[primitive]; | ||||||
|     t.pointto = pointto; |  | ||||||
|     return addType(t); |     return addType(t); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool TypeManager::visitMember(const Member & root, Visitor & visitor) const | bool TypeManager::visitMember(const Member & root, Visitor & visitor) const | ||||||
| { | { | ||||||
|     auto foundT = types.find(root.type); |     auto foundT = types.find(root.type.name); | ||||||
|     if(foundT != types.end()) |     if(foundT != types.end()) | ||||||
|     { |     { | ||||||
|         const auto & t = foundT->second; |         const auto & t = foundT->second; | ||||||
|  |         // TODO: add back pointer support
 | ||||||
|  |         if (root.type.isPointer()) | ||||||
|  |             __debugbreak(); | ||||||
|  | #if 0 | ||||||
|         if(!t.pointto.empty()) |         if(!t.pointto.empty()) | ||||||
|         { |         { | ||||||
|             if(!isDefined(t.pointto)) |             if(!isDefined(t.pointto)) | ||||||
|  | @ -441,9 +432,10 @@ bool TypeManager::visitMember(const Member & root, Visitor & visitor) const | ||||||
|             } |             } | ||||||
|             return true; |             return true; | ||||||
|         } |         } | ||||||
|  | #endif | ||||||
|         return visitor.visitType(root, t); |         return visitor.visitType(root, t); | ||||||
|     } |     } | ||||||
|     auto foundS = structs.find(root.type); |     auto foundS = structs.find(root.type.name); | ||||||
|     if(foundS != structs.end()) |     if(foundS != structs.end()) | ||||||
|     { |     { | ||||||
|         const auto & s = foundS->second; |         const auto & s = foundS->second; | ||||||
|  | @ -475,17 +467,17 @@ bool TypeManager::GenerateStubs() const | ||||||
|     std::unordered_set<std::string> declared; |     std::unordered_set<std::string> declared; | ||||||
|     auto formatFunctionPointer = [this](const std::string& name, const Function& fn) |     auto formatFunctionPointer = [this](const std::string& name, const Function& fn) | ||||||
|     { |     { | ||||||
|         std::string r = fn.retqtype.pretty(); |         std::string r = fn.rettype.pretty(); | ||||||
|         r += " (*"; |         r += " (*"; | ||||||
|         r += name; |         r += name; | ||||||
|         r += ")("; |         r += ")("; | ||||||
|         for(size_t i = 0; i < fn.args.size(); i++) |         for(size_t i = 0; i < fn.args.size(); i++) | ||||||
|         { |         { | ||||||
|             const auto& arg = fn.args[i]; |             const auto& arg = fn.args[i]; | ||||||
|             if(functions.count(arg.type) != 0) |             if(functions.count(arg.type.name) != 0) | ||||||
|                 __debugbreak(); |                 __debugbreak(); | ||||||
| 
 | 
 | ||||||
|             r += arg.qtype.pretty(); |             r += arg.type.pretty(); | ||||||
|             if(i + 1 < fn.args.size()) |             if(i + 1 < fn.args.size()) | ||||||
|             { |             { | ||||||
|                 r += ", "; |                 r += ", "; | ||||||
|  | @ -513,7 +505,7 @@ bool TypeManager::GenerateStubs() const | ||||||
|         auto variadic = false; |         auto variadic = false; | ||||||
|         for (const auto &arg: fn.args) |         for (const auto &arg: fn.args) | ||||||
|         { |         { | ||||||
|             if (arg.type == "...") |             if (arg.type.name == "...") | ||||||
|             { |             { | ||||||
|                 variadic = true; |                 variadic = true; | ||||||
|                 break; |                 break; | ||||||
|  | @ -539,25 +531,25 @@ bool TypeManager::GenerateStubs() const | ||||||
|         const auto& fn = functions.at(hook); |         const auto& fn = functions.at(hook); | ||||||
|         puts(""); |         puts(""); | ||||||
|         printf("static "); |         printf("static "); | ||||||
|         printf("%s", fn.retqtype.pretty().c_str()); |         printf("%s", fn.rettype.pretty().c_str()); | ||||||
|         printf(" hook_%s(\n", fn.name.c_str()); |         printf(" hook_%s(\n", fn.name.c_str()); | ||||||
|         std::vector<std::string> argtypes; |         std::vector<std::string> argtypes; | ||||||
|         for(size_t i = 0; i < fn.args.size(); i++) |         for(size_t i = 0; i < fn.args.size(); i++) | ||||||
|         { |         { | ||||||
|             const auto& arg = fn.args[i]; |             const auto& arg = fn.args[i]; | ||||||
|             printf("    "); |             printf("    "); | ||||||
|             auto argPtr = functions.find(arg.type); |             auto argPtr = functions.find(arg.type.name); | ||||||
|             if(argPtr != functions.end()) |             if(argPtr != functions.end()) | ||||||
|             { |             { | ||||||
|                 argtypes.push_back(formatFunctionPointer(arg.name, argPtr->second)); |                 argtypes.push_back(formatFunctionPointer(arg.name, argPtr->second)); | ||||||
|                 printf("%s", argtypes.back().c_str()); |                 printf("%s", argtypes.back().c_str()); | ||||||
|                 if(arg.qtype.isConst) |                 if(arg.type.isConst) | ||||||
|                     __debugbreak(); |                     __debugbreak(); | ||||||
|             } |             } | ||||||
|             else |             else | ||||||
|             { |             { | ||||||
|                 argtypes.push_back(arg.type); |                 argtypes.push_back(arg.type.pretty()); | ||||||
|                 printf("%s", arg.qtype.pretty().c_str()); |                 printf("%s", arg.type.pretty().c_str()); | ||||||
|                 printf(" "); |                 printf(" "); | ||||||
|                 printf("%s", arg.name.c_str()); |                 printf("%s", arg.name.c_str()); | ||||||
|             } |             } | ||||||
|  | @ -574,7 +566,7 @@ bool TypeManager::GenerateStubs() const | ||||||
|         { |         { | ||||||
|             printf("    LOG_ARGUMENT(\"%s\", %s);\n", argtypes[i].c_str(), fn.args[i].name.c_str()); |             printf("    LOG_ARGUMENT(\"%s\", %s);\n", argtypes[i].c_str(), fn.args[i].name.c_str()); | ||||||
|         } |         } | ||||||
|         if(fn.retqtype.name == "void") |         if(fn.rettype.name == "void") | ||||||
|         { |         { | ||||||
|             printf("    orig_%s(", fn.name.c_str()); |             printf("    orig_%s(", fn.name.c_str()); | ||||||
|         } |         } | ||||||
|  | @ -592,7 +584,7 @@ bool TypeManager::GenerateStubs() const | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         puts(");"); |         puts(");"); | ||||||
|         if(fn.retqtype.name == "void") |         if(fn.rettype.name == "void") | ||||||
|         { |         { | ||||||
|             puts("    LOG_RETURN_VOID();"); |             puts("    LOG_RETURN_VOID();"); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  | @ -31,7 +31,6 @@ namespace Types | ||||||
|     { |     { | ||||||
|         std::string owner; //Type owner
 |         std::string owner; //Type owner
 | ||||||
|         std::string name; //Type identifier.
 |         std::string name; //Type identifier.
 | ||||||
|         std::string pointto; //Type identifier of *Type (empty when the type is a primitive type)
 |  | ||||||
|         Primitive primitive = Void; //Primitive type.
 |         Primitive primitive = Void; //Primitive type.
 | ||||||
|         int size = 0; //Size in bytes.
 |         int size = 0; //Size in bytes.
 | ||||||
|     }; |     }; | ||||||
|  | @ -41,6 +40,12 @@ namespace Types | ||||||
|         std::string name; // base name of the type
 |         std::string name; // base name of the type
 | ||||||
|         bool isConst = false; // whether the base type is const
 |         bool isConst = false; // whether the base type is const
 | ||||||
| 
 | 
 | ||||||
|  |         QualifiedType() = default; | ||||||
|  |         explicit QualifiedType(const std::string& name) | ||||||
|  |             : name(name) | ||||||
|  |         { | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         struct Ptr |         struct Ptr | ||||||
|         { |         { | ||||||
|             bool isConst = false; |             bool isConst = false; | ||||||
|  | @ -70,13 +75,22 @@ namespace Types | ||||||
|                 r += '*'; |                 r += '*'; | ||||||
|             return r; |             return r; | ||||||
|         } |         } | ||||||
|  | 
 | ||||||
|  |         bool empty() const | ||||||
|  |         { | ||||||
|  |             return name.empty(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         bool isPointer() const | ||||||
|  |         { | ||||||
|  |             return !pointers.empty(); | ||||||
|  |         } | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     struct Member |     struct Member | ||||||
|     { |     { | ||||||
|         std::string name; //Member identifier
 |         std::string name; //Member identifier
 | ||||||
|         std::string type; //Type.name
 |         QualifiedType type; // Qualified Type
 | ||||||
|         QualifiedType qtype; // Qualified Type
 |  | ||||||
|         int arrsize = 0; //Number of elements if Member is an array (unused for function arguments)
 |         int arrsize = 0; //Number of elements if Member is an array (unused for function arguments)
 | ||||||
|         int offset = -1; //Member offset (only stored for reference)
 |         int offset = -1; //Member offset (only stored for reference)
 | ||||||
|     }; |     }; | ||||||
|  | @ -94,7 +108,7 @@ namespace Types | ||||||
|     { |     { | ||||||
|         std::string owner; //Function owner
 |         std::string owner; //Function owner
 | ||||||
|         std::string name; //Function identifier
 |         std::string name; //Function identifier
 | ||||||
|         QualifiedType retqtype; // Function return type
 |         QualifiedType rettype; // Function return type
 | ||||||
|         CallingConvention callconv = DefaultDecl; //Function calling convention
 |         CallingConvention callconv = DefaultDecl; //Function calling convention
 | ||||||
|         bool noreturn = false; //Function does not return (ExitProcess, _exit)
 |         bool noreturn = false; //Function does not return (ExitProcess, _exit)
 | ||||||
|         bool typeonly = false; //Function is only used as a type (the name is based on where it's used)
 |         bool typeonly = false; //Function is only used as a type (the name is based on where it's used)
 | ||||||
|  | @ -153,19 +167,20 @@ namespace Types | ||||||
|             int size = 0; |             int size = 0; | ||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
|         explicit TypeManager(); |         explicit TypeManager(size_t pointerSize); | ||||||
|         std::string PrimitiveName(Primitive primitive); |         std::string PrimitiveName(Primitive primitive); | ||||||
|         bool AddType(const std::string & owner, const std::string & type, const std::string & name); |         bool AddType(const std::string & owner, const std::string & type, const std::string & name); | ||||||
|         bool AddEnum(const std::string& owner, const std::string& name, const std::string & type); |         bool AddEnum(const std::string& owner, const std::string& name, const std::string & type); | ||||||
|         bool AddStruct(const std::string & owner, const std::string & name); |         bool AddStruct(const std::string & owner, const std::string & name); | ||||||
|         bool AddUnion(const std::string & owner, const std::string & name); |         bool AddUnion(const std::string & owner, const std::string & name); | ||||||
|         bool AddMember(const std::string & parent, const std::string & type, const std::string & name, int arrsize = 0, int offset = -1); |         bool AddMember(const std::string & parent, const QualifiedType & type, const std::string & name, int arrsize = 0, int offset = -1); | ||||||
|         bool AppendMember(const std::string & type, const std::string & name, int arrsize = 0, int offset = -1); |         bool AppendMember(const QualifiedType & type, const std::string & name, int arrsize = 0, int offset = -1); | ||||||
|         bool AddFunction(const std::string & owner, const std::string & name, const QualifiedType& retqtype, CallingConvention callconv = Cdecl, bool noreturn = false, bool typeonly = false); |         bool AddFunction(const std::string & owner, const std::string & name, const QualifiedType& rettype, CallingConvention callconv = Cdecl, bool noreturn = false, bool typeonly = false); | ||||||
|         bool AddEnumerator(const std::string& enumType, const std::string& name, uint64_t value); |         bool AddEnumerator(const std::string& enumType, const std::string& name, uint64_t value); | ||||||
|         bool AddArg(const std::string & function, const std::string & type, const std::string & name, const QualifiedType& qtype); |         bool AddArg(const std::string & function, const QualifiedType & type, const std::string & name); | ||||||
|         bool AppendArg(const std::string & type, const std::string & name, const QualifiedType& qtype); |         bool AppendArg(const QualifiedType& type, const std::string & name); | ||||||
|         int Sizeof(const std::string & type) const; |         int Sizeof(const QualifiedType& type) const; | ||||||
|  |         int Sizeof(const std::string& type) const; | ||||||
|         bool Visit(const std::string & type, const std::string & name, Visitor & visitor) const; |         bool Visit(const std::string & type, const std::string & name, Visitor & visitor) const; | ||||||
|         void Clear(const std::string & owner = ""); |         void Clear(const std::string & owner = ""); | ||||||
|         bool RemoveType(const std::string & type); |         bool RemoveType(const std::string & type); | ||||||
|  | @ -186,11 +201,11 @@ namespace Types | ||||||
|         std::string laststruct; |         std::string laststruct; | ||||||
|         std::string lastfunction; |         std::string lastfunction; | ||||||
| 
 | 
 | ||||||
|  |         bool isDefined(const QualifiedType& type) const; | ||||||
|         bool isDefined(const std::string & id) const; |         bool isDefined(const std::string & id) const; | ||||||
|         bool validPtr(const std::string & id); |  | ||||||
|         bool addStructUnion(const StructUnion & s); |         bool addStructUnion(const StructUnion & s); | ||||||
|         bool addEnum(const Enum& e); |         bool addEnum(const Enum& e); | ||||||
|         bool addType(const std::string & owner, Primitive primitive, const std::string & name, const std::string & pointto = ""); |         bool addType(const std::string & owner, Primitive primitive, const std::string & name); | ||||||
|         bool addType(const Type & t); |         bool addType(const Type & t); | ||||||
|         bool visitMember(const Member & root, Visitor & visitor) const; |         bool visitMember(const Member & root, Visitor & visitor) const; | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|  | @ -78,10 +78,10 @@ struct Parser | ||||||
| 			index++; | 			index++; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	bool parseVariable(const std::vector<Lexer::TokenState>& tlist, QualifiedType& qtype, std::string& name) | 	bool parseVariable(const std::vector<Lexer::TokenState>& tlist, QualifiedType& type, std::string& name) | ||||||
| 	{ | 	{ | ||||||
| 		std::string type; // TODO: get rid of this variable
 | 		std::string stype; // TODO: get rid of this variable
 | ||||||
|         qtype = QualifiedType(); |         type = QualifiedType(); | ||||||
| 		name.clear(); | 		name.clear(); | ||||||
| 
 | 
 | ||||||
| 		bool sawPointer = false; | 		bool sawPointer = false; | ||||||
|  | @ -92,10 +92,10 @@ struct Parser | ||||||
| 			const auto& t = tlist[i]; | 			const auto& t = tlist[i]; | ||||||
| 			if (t.Is(Lexer::tok_const)) | 			if (t.Is(Lexer::tok_const)) | ||||||
| 			{ | 			{ | ||||||
|                 if(i == 0 || qtype.pointers.empty()) |                 if(i == 0 || type.pointers.empty()) | ||||||
|                     qtype.isConst = true; |                     type.isConst = true; | ||||||
|                 else |                 else | ||||||
|                     qtype.pointers.back().isConst = true; |                     type.pointers.back().isConst = true; | ||||||
| 				continue; | 				continue; | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
|  | @ -109,9 +109,9 @@ struct Parser | ||||||
| 			{ | 			{ | ||||||
| 				if (isKeyword) | 				if (isKeyword) | ||||||
| 				{ | 				{ | ||||||
| 					if (!type.empty()) | 					if (!stype.empty()) | ||||||
| 						type += ' '; | 						stype += ' '; | ||||||
| 					type += lexer.TokString(t); | 					stype += lexer.TokString(t); | ||||||
| 				} | 				} | ||||||
| 				else | 				else | ||||||
| 				{ | 				{ | ||||||
|  | @ -121,9 +121,9 @@ struct Parser | ||||||
| 			} | 			} | ||||||
| 			else if (t.Is(Lexer::tok_identifier)) | 			else if (t.Is(Lexer::tok_identifier)) | ||||||
| 			{ | 			{ | ||||||
| 				if (type.empty()) | 				if (stype.empty()) | ||||||
| 				{ | 				{ | ||||||
| 					type = t.IdentifierStr; | 					stype = t.IdentifierStr; | ||||||
| 				} | 				} | ||||||
| 				else if (i + 1 == tlist.size()) | 				else if (i + 1 == tlist.size()) | ||||||
| 				{ | 				{ | ||||||
|  | @ -137,25 +137,25 @@ struct Parser | ||||||
| 			} | 			} | ||||||
| 			else if (t.Is(Lexer::tok_op_mul) || t.Is(Lexer::tok_op_and)) | 			else if (t.Is(Lexer::tok_op_mul) || t.Is(Lexer::tok_op_and)) | ||||||
| 			{ | 			{ | ||||||
| 				if (type.empty()) | 				if (stype.empty()) | ||||||
| 				{ | 				{ | ||||||
| 					errLine(t, "unexpected * in type"); | 					errLine(t, "unexpected * in type"); | ||||||
| 					return false; | 					return false; | ||||||
| 				} | 				} | ||||||
| 
 | 
 | ||||||
| 				if (sawPointer && type.back() != '*') | 				if (sawPointer && stype.back() != '*') | ||||||
| 				{ | 				{ | ||||||
| 					errLine(t, "unexpected * in type"); | 					errLine(t, "unexpected * in type"); | ||||||
| 					return false; | 					return false; | ||||||
| 				} | 				} | ||||||
| 
 | 
 | ||||||
|                 if(!sawPointer) |                 if(!sawPointer) | ||||||
|                     qtype.name = type; |                     type.name = stype; | ||||||
| 
 | 
 | ||||||
|                 qtype.pointers.emplace_back(); |                 type.pointers.emplace_back(); | ||||||
| 
 | 
 | ||||||
| 				// Apply the pointer to the type on the left
 | 				// Apply the pointer to the type on the left
 | ||||||
| 				type += '*'; | 				stype += '*'; | ||||||
| 				sawPointer = true; | 				sawPointer = true; | ||||||
| 			} | 			} | ||||||
| 			else | 			else | ||||||
|  | @ -164,10 +164,10 @@ struct Parser | ||||||
| 				return false; | 				return false; | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		if (type.empty()) | 		if (stype.empty()) | ||||||
| 			__debugbreak(); | 			__debugbreak(); | ||||||
|         if(!sawPointer) |         if(!sawPointer) | ||||||
|             qtype.name = type; |             type.name = stype; | ||||||
| 		return true; | 		return true; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -182,7 +182,7 @@ struct Parser | ||||||
| 		// TODO: calling conventions
 | 		// TODO: calling conventions
 | ||||||
| 
 | 
 | ||||||
| 		std::string retname; | 		std::string retname; | ||||||
| 		if (!parseVariable(rettypes, fn.retqtype, retname)) | 		if (!parseVariable(rettypes, fn.rettype, retname)) | ||||||
| 			return false; | 			return false; | ||||||
| 
 | 
 | ||||||
| 		if (ptr) | 		if (ptr) | ||||||
|  | @ -248,9 +248,8 @@ struct Parser | ||||||
| 		auto finalizeArgument = [&]() | 		auto finalizeArgument = [&]() | ||||||
| 		{ | 		{ | ||||||
| 			Member am; | 			Member am; | ||||||
| 			if (!parseVariable(tlist, am.qtype, am.name)) | 			if (!parseVariable(tlist, am.type, am.name)) | ||||||
| 				return false; | 				return false; | ||||||
| 			am.type = am.qtype.noconst(); // TODO: remove
 |  | ||||||
| 			fn.args.push_back(am); | 			fn.args.push_back(am); | ||||||
| 			tlist.clear(); | 			tlist.clear(); | ||||||
| 			startToken = curToken(); | 			startToken = curToken(); | ||||||
|  | @ -336,7 +335,7 @@ struct Parser | ||||||
| 				} | 				} | ||||||
| 
 | 
 | ||||||
| 				Member am; | 				Member am; | ||||||
| 				am.type = "..."; | 				am.type = QualifiedType("..."); | ||||||
| 				fn.args.push_back(am); | 				fn.args.push_back(am); | ||||||
| 				break; | 				break; | ||||||
| 			} | 			} | ||||||
|  | @ -413,11 +412,10 @@ struct Parser | ||||||
| 				return false; | 				return false; | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			if (!parseVariable(tlist, m.qtype, m.name)) | 			if (!parseVariable(tlist, m.type, m.name)) | ||||||
| 				return false; | 				return false; | ||||||
| 			m.type = m.qtype.noconst(); |  | ||||||
| 
 | 
 | ||||||
| 			if (m.type == "void") | 			if (m.type.name == "void" && !m.type.isPointer()) | ||||||
| 			{ | 			{ | ||||||
| 				errLine(startToken, "void is not a valid member type"); | 				errLine(startToken, "void is not a valid member type"); | ||||||
| 				return false; | 				return false; | ||||||
|  | @ -882,9 +880,8 @@ struct Parser | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			Member tm; | 			Member tm; | ||||||
| 			if (!parseVariable(tlist, tm.qtype, tm.name)) | 			if (!parseVariable(tlist, tm.type, tm.name)) | ||||||
| 				return false; | 				return false; | ||||||
| 			tm.type = tm.qtype.noconst(); |  | ||||||
| 			model.types.push_back(tm); | 			model.types.push_back(tm); | ||||||
| 		} | 		} | ||||||
| 		return true; | 		return true; | ||||||
|  | @ -1033,11 +1030,14 @@ struct Parser | ||||||
| 		//Add simple typedefs
 | 		//Add simple typedefs
 | ||||||
| 		for (auto& type : model.types) | 		for (auto& type : model.types) | ||||||
| 		{ | 		{ | ||||||
| 			auto success = typeManager.AddType(owner, type.type, type.name); | 			// TODO: support pointers
 | ||||||
|  | 			if (type.type.isPointer() || type.type.isConst) | ||||||
|  | 				__debugbreak(); | ||||||
|  | 			auto success = typeManager.AddType(owner, type.type.name, type.name); | ||||||
| 			if (!success) | 			if (!success) | ||||||
| 			{ | 			{ | ||||||
| 				//TODO properly handle errors
 | 				//TODO properly handle errors
 | ||||||
| 				dprintf(QT_TRANSLATE_NOOP("DBG", "Failed to add typedef %s %s;\n"), type.type.c_str(), type.name.c_str()); | 				dprintf(QT_TRANSLATE_NOOP("DBG", "Failed to add typedef %s %s;\n"), type.type.pretty().c_str(), type.name.c_str()); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | @ -1067,11 +1067,11 @@ struct Parser | ||||||
| 		//Add base function types to avoid errors later
 | 		//Add base function types to avoid errors later
 | ||||||
| 		for (auto& function : model.functions) | 		for (auto& function : model.functions) | ||||||
| 		{ | 		{ | ||||||
| 			auto success = typeManager.AddFunction(owner, function.name, function.retqtype, function.callconv, function.noreturn, function.typeonly); | 			auto success = typeManager.AddFunction(owner, function.name, function.rettype, function.callconv, function.noreturn, function.typeonly); | ||||||
| 			if (!success) | 			if (!success) | ||||||
| 			{ | 			{ | ||||||
| 				//TODO properly handle errors
 | 				//TODO properly handle errors
 | ||||||
| 				dprintf(QT_TRANSLATE_NOOP("DBG", "Failed to add function %s %s()\n"), function.retqtype.pretty().c_str(), function.name.c_str()); | 				dprintf(QT_TRANSLATE_NOOP("DBG", "Failed to add function %s %s()\n"), function.rettype.pretty().c_str(), function.name.c_str()); | ||||||
| 				function.name.clear(); //signal error
 | 				function.name.clear(); //signal error
 | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  | @ -1087,7 +1087,7 @@ struct Parser | ||||||
| 				if (!success) | 				if (!success) | ||||||
| 				{ | 				{ | ||||||
| 					//TODO properly handle errors
 | 					//TODO properly handle errors
 | ||||||
| 					dprintf(QT_TRANSLATE_NOOP("DBG", "Failed to add member %s %s.%s;\n"), member.type.c_str(), su.name.c_str(), member.name.c_str()); | 					dprintf(QT_TRANSLATE_NOOP("DBG", "Failed to add member %s %s.%s;\n"), member.type.pretty().c_str(), su.name.c_str(), member.name.c_str()); | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  | @ -1102,11 +1102,11 @@ struct Parser | ||||||
| 				auto& arg = function.args[i]; | 				auto& arg = function.args[i]; | ||||||
| 				if (arg.name.empty()) | 				if (arg.name.empty()) | ||||||
| 					arg.name = "__unnamed_arg_" + std::to_string(i); | 					arg.name = "__unnamed_arg_" + std::to_string(i); | ||||||
| 				auto success = typeManager.AddArg(function.name, arg.type, arg.name, arg.qtype); | 				auto success = typeManager.AddArg(function.name, arg.type, arg.name); | ||||||
| 				if (!success) | 				if (!success) | ||||||
| 				{ | 				{ | ||||||
| 					//TODO properly handle errors
 | 					//TODO properly handle errors
 | ||||||
| 					dprintf(QT_TRANSLATE_NOOP("DBG", "Failed to add argument %s[%zu]: %s %s;\n"), function.name.c_str(), i, arg.type.c_str(), arg.name.c_str()); | 					dprintf(QT_TRANSLATE_NOOP("DBG", "Failed to add argument %s[%zu]: %s %s;\n"), function.name.c_str(), i, arg.type.pretty().c_str(), arg.name.c_str()); | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue