mirror of https://github.com/x64dbg/btparser
Add qualified types and improve parsing support
This commit is contained in:
parent
a87d84cc5b
commit
6d3f1f75c4
|
@ -7,3 +7,6 @@ My Amplifier XE Results */
|
||||||
actual.out
|
actual.out
|
||||||
expected.out
|
expected.out
|
||||||
.vs/
|
.vs/
|
||||||
|
cmake-build*/
|
||||||
|
build*/
|
||||||
|
.idea/
|
||||||
|
|
|
@ -287,23 +287,23 @@ std::string preprocess(const std::string& input, std::string& error, const std::
|
||||||
t.skip_spaces();
|
t.skip_spaces();
|
||||||
|
|
||||||
auto directive = t.identifier();
|
auto directive = t.identifier();
|
||||||
line.print();
|
//line.print();
|
||||||
|
|
||||||
if (directive == "ifndef")
|
if (directive == "ifndef")
|
||||||
{
|
{
|
||||||
t.skip_spaces(true);
|
t.skip_spaces(true);
|
||||||
auto identifier = t.identifier();
|
auto identifier = t.identifier();
|
||||||
printf("#ifndef(%s)\n", identifier.c_str());
|
//printf("#ifndef(%s)\n", identifier.c_str());
|
||||||
stack.push_back({ i, "!defined(" + identifier + ")", state.count(identifier) == 0 });
|
stack.push_back({ i, "!defined(" + identifier + ")", state.count(identifier) == 0 });
|
||||||
printf("emitting: %d\n", emitting());
|
//printf("emitting: %d\n", emitting());
|
||||||
}
|
}
|
||||||
else if (directive == "ifdef")
|
else if (directive == "ifdef")
|
||||||
{
|
{
|
||||||
t.skip_spaces(true);
|
t.skip_spaces(true);
|
||||||
auto identifier = t.identifier();
|
auto identifier = t.identifier();
|
||||||
printf("#ifdef(%s)\n", identifier.c_str());
|
//printf("#ifdef(%s)\n", identifier.c_str());
|
||||||
stack.push_back({ i, identifier, state.count(identifier) != 0 });
|
stack.push_back({ i, identifier, state.count(identifier) != 0 });
|
||||||
printf("emitting: %d\n", emitting());
|
//printf("emitting: %d\n", emitting());
|
||||||
}
|
}
|
||||||
else if (directive == "else")
|
else if (directive == "else")
|
||||||
{
|
{
|
||||||
|
@ -313,16 +313,16 @@ std::string preprocess(const std::string& input, std::string& error, const std::
|
||||||
{
|
{
|
||||||
stack.back().value = true;
|
stack.back().value = true;
|
||||||
}
|
}
|
||||||
printf("#else (%s)\n", stack.back().condition.c_str());
|
//printf("#else (%s)\n", stack.back().condition.c_str());
|
||||||
printf("emitting: %d\n", emitting());
|
//printf("emitting: %d\n", emitting());
|
||||||
}
|
}
|
||||||
else if (directive == "endif")
|
else if (directive == "endif")
|
||||||
{
|
{
|
||||||
if (stack.empty())
|
if (stack.empty())
|
||||||
throw std::runtime_error("no matching #if for #endif");
|
throw std::runtime_error("no matching #if for #endif");
|
||||||
printf("#endif (%s)\n", stack.back().condition.c_str());
|
//("#endif (%s)\n", stack.back().condition.c_str());
|
||||||
stack.pop_back();
|
stack.pop_back();
|
||||||
printf("emitting: %d\n", emitting());
|
//printf("emitting: %d\n", emitting());
|
||||||
}
|
}
|
||||||
else if (directive == "define")
|
else if (directive == "define")
|
||||||
{
|
{
|
||||||
|
@ -367,7 +367,7 @@ std::string preprocess(const std::string& input, std::string& error, const std::
|
||||||
pretty += parameters[i];
|
pretty += parameters[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("#define %s('%s' = '%s')\n", identifier.c_str(), pretty.c_str(), token.c_str());
|
//printf("#define %s('%s' = '%s')\n", identifier.c_str(), pretty.c_str(), token.c_str());
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -376,11 +376,11 @@ std::string preprocess(const std::string& input, std::string& error, const std::
|
||||||
auto token = t.remainder();
|
auto token = t.remainder();
|
||||||
if (token.empty())
|
if (token.empty())
|
||||||
{
|
{
|
||||||
printf("#define(%s)\n", identifier.c_str());
|
//printf("#define(%s)\n", identifier.c_str());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
printf("#define('%s' = '%s')\n", identifier.c_str(), token.c_str());
|
//printf("#define('%s' = '%s')\n", identifier.c_str(), token.c_str());
|
||||||
}
|
}
|
||||||
if (emitting())
|
if (emitting())
|
||||||
{
|
{
|
||||||
|
@ -396,13 +396,13 @@ std::string preprocess(const std::string& input, std::string& error, const std::
|
||||||
{
|
{
|
||||||
t.consume();
|
t.consume();
|
||||||
auto file = t.until('\"');
|
auto file = t.until('\"');
|
||||||
printf("#include \"%s\"\n", file.c_str());
|
//printf("#include \"%s\"\n", file.c_str());
|
||||||
}
|
}
|
||||||
else if (type == '<')
|
else if (type == '<')
|
||||||
{
|
{
|
||||||
t.consume();
|
t.consume();
|
||||||
auto file = t.until('>');
|
auto file = t.until('>');
|
||||||
printf("#include <%s>\n", file.c_str());
|
//printf("#include <%s>\n", file.c_str());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -411,7 +411,7 @@ std::string preprocess(const std::string& input, std::string& error, const std::
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
printf("directive: '%s'\n", directive.c_str());
|
//printf("directive: '%s'\n", directive.c_str());
|
||||||
throw std::runtime_error("unknown directive '" + directive + "'");
|
throw std::runtime_error("unknown directive '" + directive + "'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <unordered_set>
|
||||||
|
#include <ctime>
|
||||||
|
|
||||||
using namespace Types;
|
using namespace Types;
|
||||||
|
|
||||||
|
@ -175,7 +177,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 std::string & rettype, CallingConvention callconv, bool noreturn, bool typeonly)
|
bool TypeManager::AddFunction(const std::string & owner, const std::string & name, const std::string & rettype, CallingConvention callconv, bool noreturn, bool typeonly, const QualifiedType& retqtype)
|
||||||
{
|
{
|
||||||
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())
|
||||||
|
@ -189,11 +191,13 @@ bool TypeManager::AddFunction(const std::string & owner, const std::string & nam
|
||||||
f.rettype = rettype;
|
f.rettype = rettype;
|
||||||
f.callconv = callconv;
|
f.callconv = callconv;
|
||||||
f.noreturn = noreturn;
|
f.noreturn = noreturn;
|
||||||
|
f.typeonly = typeonly;
|
||||||
|
f.retqtype = retqtype;
|
||||||
functions.emplace(f.name, f);
|
functions.emplace(f.name, f);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TypeManager::AddArg(const std::string & function, const std::string & type, const std::string & name)
|
bool TypeManager::AddArg(const std::string & function, const std::string & type, const std::string & name, const QualifiedType& qtype)
|
||||||
{
|
{
|
||||||
auto found = functions.find(function);
|
auto found = functions.find(function);
|
||||||
if (found == functions.end() || name.empty())
|
if (found == functions.end() || name.empty())
|
||||||
|
@ -204,13 +208,14 @@ bool TypeManager::AddArg(const std::string & function, const std::string & type,
|
||||||
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)
|
bool TypeManager::AppendArg(const std::string & type, const std::string & name, const QualifiedType& qtype)
|
||||||
{
|
{
|
||||||
return AddArg(lastfunction, type, name);
|
return AddArg(lastfunction, type, name, qtype);
|
||||||
}
|
}
|
||||||
|
|
||||||
int TypeManager::Sizeof(const std::string & type) const
|
int TypeManager::Sizeof(const std::string & type) const
|
||||||
|
@ -467,6 +472,153 @@ bool TypeManager::visitMember(const Member & root, Visitor & visitor) const
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool TypeManager::GenerateStubs() const
|
||||||
|
{
|
||||||
|
std::unordered_map<std::string, const Function*> fnptrs;
|
||||||
|
std::unordered_set<std::string> declared;
|
||||||
|
auto formatFunctionPointer = [this](const std::string& name, const Function& fn)
|
||||||
|
{
|
||||||
|
std::string r = fn.retqtype.pretty();
|
||||||
|
r += " (*";
|
||||||
|
r += name;
|
||||||
|
r += ")(";
|
||||||
|
for(size_t i = 0; i < fn.args.size(); i++)
|
||||||
|
{
|
||||||
|
const auto& arg = fn.args[i];
|
||||||
|
if(functions.count(arg.type) != 0)
|
||||||
|
__debugbreak();
|
||||||
|
|
||||||
|
r += arg.qtype.pretty();
|
||||||
|
if(i + 1 < fn.args.size())
|
||||||
|
{
|
||||||
|
r += ", ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
r += ")";
|
||||||
|
return r;
|
||||||
|
};
|
||||||
|
|
||||||
|
printf("// THIS WAS AUTOGENERATED YOU MORONS %ju\n", time(nullptr));
|
||||||
|
puts("#include \"hooks.h\"");
|
||||||
|
puts("");
|
||||||
|
|
||||||
|
std::vector<std::string> hooks;
|
||||||
|
for(const auto& itr : functions)
|
||||||
|
{
|
||||||
|
const auto &fn = itr.second;
|
||||||
|
// Skip non-declarations
|
||||||
|
if (fn.typeonly)
|
||||||
|
{
|
||||||
|
fnptrs.emplace(fn.name, &fn);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto variadic = false;
|
||||||
|
for (const auto &arg: fn.args)
|
||||||
|
{
|
||||||
|
if (arg.type == "...")
|
||||||
|
{
|
||||||
|
variadic = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (variadic)
|
||||||
|
{
|
||||||
|
printf("// Skipping variadic function %s\n", fn.name.c_str());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
hooks.push_back(fn.name);
|
||||||
|
}
|
||||||
|
puts("");
|
||||||
|
|
||||||
|
for(const auto& hook : hooks)
|
||||||
|
{
|
||||||
|
printf("static decltype(&%s) orig_%s;\n", hook.c_str(), hook.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
for(const auto& hook : hooks)
|
||||||
|
{
|
||||||
|
const auto& fn = functions.at(hook);
|
||||||
|
puts("");
|
||||||
|
printf("static ");
|
||||||
|
printf("%s", fn.retqtype.pretty().c_str());
|
||||||
|
printf(" hook_%s(\n", fn.name.c_str());
|
||||||
|
std::vector<std::string> argtypes;
|
||||||
|
for(size_t i = 0; i < fn.args.size(); i++)
|
||||||
|
{
|
||||||
|
const auto& arg = fn.args[i];
|
||||||
|
printf(" ");
|
||||||
|
auto argPtr = functions.find(arg.type);
|
||||||
|
if(argPtr != functions.end())
|
||||||
|
{
|
||||||
|
argtypes.push_back(formatFunctionPointer(arg.name, argPtr->second));
|
||||||
|
printf("%s", argtypes.back().c_str());
|
||||||
|
if(arg.qtype.isConst)
|
||||||
|
__debugbreak();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
argtypes.push_back(arg.type);
|
||||||
|
printf("%s", arg.qtype.pretty().c_str());
|
||||||
|
printf(" ");
|
||||||
|
printf("%s", arg.name.c_str());
|
||||||
|
}
|
||||||
|
if(i + 1 < fn.args.size())
|
||||||
|
{
|
||||||
|
printf(",");
|
||||||
|
}
|
||||||
|
puts("");
|
||||||
|
}
|
||||||
|
puts(")");
|
||||||
|
puts("{");
|
||||||
|
printf(" LOG_CALL(\"%s\");\n", fn.name.c_str());
|
||||||
|
for(size_t i = 0; i < fn.args.size(); i++)
|
||||||
|
{
|
||||||
|
printf(" LOG_ARGUMENT(\"%s\", %s);\n", argtypes[i].c_str(), fn.args[i].name.c_str());
|
||||||
|
}
|
||||||
|
if(fn.rettype == "void")
|
||||||
|
{
|
||||||
|
printf(" orig_%s(", fn.name.c_str());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf(" auto _hook_result = orig_%s(", fn.name.c_str());
|
||||||
|
}
|
||||||
|
for(size_t i = 0; i < fn.args.size(); i++)
|
||||||
|
{
|
||||||
|
const auto& arg = fn.args[i];
|
||||||
|
printf("%s", arg.name.c_str());
|
||||||
|
if(i + 1 < fn.args.size())
|
||||||
|
{
|
||||||
|
printf(", ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
puts(");");
|
||||||
|
if(fn.rettype == "void")
|
||||||
|
{
|
||||||
|
puts(" LOG_RETURN_VOID();");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
puts(" LOG_RETURN(_hook_result);");
|
||||||
|
puts(" return _hook_result;");
|
||||||
|
}
|
||||||
|
puts("}");
|
||||||
|
}
|
||||||
|
|
||||||
|
puts("");
|
||||||
|
puts("void InstallHooks()");
|
||||||
|
puts("{");
|
||||||
|
for(const auto& hook : hooks)
|
||||||
|
{
|
||||||
|
printf(" HOOK(%s);\n", hook.c_str(), hook.c_str());
|
||||||
|
}
|
||||||
|
puts("}");
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
EXCLUSIVE_ACQUIRE(LockTypeManager);
|
EXCLUSIVE_ACQUIRE(LockTypeManager);
|
||||||
|
@ -503,16 +655,16 @@ bool AddFunction(const std::string & owner, const std::string & name, const std:
|
||||||
return typeManager.AddFunction(owner, name, rettype, callconv, noreturn);
|
return typeManager.AddFunction(owner, name, rettype, callconv, noreturn);
|
||||||
}
|
}
|
||||||
|
|
||||||
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, const QualifiedType& qtype)
|
||||||
{
|
{
|
||||||
EXCLUSIVE_ACQUIRE(LockTypeManager);
|
EXCLUSIVE_ACQUIRE(LockTypeManager);
|
||||||
return typeManager.AddArg(function, type, name);
|
return typeManager.AddArg(function, type, name, qtype);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AppendArg(const std::string & type, const std::string & name)
|
bool AppendArg(const std::string & type, const std::string & name, const QualifiedType& qtype)
|
||||||
{
|
{
|
||||||
EXCLUSIVE_ACQUIRE(LockTypeManager);
|
EXCLUSIVE_ACQUIRE(LockTypeManager);
|
||||||
return typeManager.AppendArg(type, name);
|
return typeManager.AppendArg(type, name, qtype);
|
||||||
}
|
}
|
||||||
|
|
||||||
int SizeofType(const std::string & type)
|
int SizeofType(const std::string & type)
|
||||||
|
@ -709,7 +861,7 @@ void LoadModel(const std::string & owner, Model & model)
|
||||||
//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.rettype, function.callconv, function.noreturn, function.typeonly);
|
auto success = typeManager.AddFunction(owner, function.name, function.rettype, function.callconv, function.noreturn, function.typeonly, function.retqtype);
|
||||||
if(!success)
|
if(!success)
|
||||||
{
|
{
|
||||||
//TODO properly handle errors
|
//TODO properly handle errors
|
||||||
|
@ -743,8 +895,8 @@ void LoadModel(const std::string & owner, Model & model)
|
||||||
{
|
{
|
||||||
auto& arg = function.args[i];
|
auto& arg = function.args[i];
|
||||||
if (arg.name.empty())
|
if (arg.name.empty())
|
||||||
arg.name = "__unnamed" + std::to_string(i);
|
arg.name = "__unnamed_arg_" + std::to_string(i);
|
||||||
auto success = typeManager.AddArg(function.name, arg.type, arg.name);
|
auto success = typeManager.AddArg(function.name, arg.type, arg.name, arg.qtype);
|
||||||
if(!success)
|
if(!success)
|
||||||
{
|
{
|
||||||
//TODO properly handle errors
|
//TODO properly handle errors
|
||||||
|
@ -794,3 +946,8 @@ std::string StructUnionPtrType(const std::string & pointto)
|
||||||
{
|
{
|
||||||
return typeManager.StructUnionPtrType(pointto);
|
return typeManager.StructUnionPtrType(pointto);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GenerateStubs()
|
||||||
|
{
|
||||||
|
return typeManager.GenerateStubs();
|
||||||
|
}
|
||||||
|
|
|
@ -36,12 +36,48 @@ namespace Types
|
||||||
int size = 0; //Size in bytes.
|
int size = 0; //Size in bytes.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct QualifiedType
|
||||||
|
{
|
||||||
|
std::string name; // base name of the type
|
||||||
|
bool isConst = false; // whether the base type is const
|
||||||
|
|
||||||
|
struct Ptr
|
||||||
|
{
|
||||||
|
bool isConst = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<Ptr> pointers; // arbitrary amount of pointers
|
||||||
|
|
||||||
|
std::string pretty() const
|
||||||
|
{
|
||||||
|
std::string r;
|
||||||
|
if(isConst)
|
||||||
|
r += "const ";
|
||||||
|
r += name;
|
||||||
|
for(const auto& ptr : pointers)
|
||||||
|
{
|
||||||
|
r += '*';
|
||||||
|
if(ptr.isConst)
|
||||||
|
r += " const";
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string noconst() const
|
||||||
|
{
|
||||||
|
auto r = name;
|
||||||
|
for(const auto& ptr : pointers)
|
||||||
|
r += '*';
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct Member
|
struct Member
|
||||||
{
|
{
|
||||||
std::string name; //Member identifier
|
std::string name; //Member identifier
|
||||||
std::string type; //Type.name
|
std::string type; //Type.name
|
||||||
bool isConst = false; //Whether the member is marked as const
|
QualifiedType qtype; // Qualified Type
|
||||||
int arrsize = 0; //Number of elements if Member is an array
|
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)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -82,6 +118,7 @@ namespace Types
|
||||||
std::string owner; //Function owner
|
std::string owner; //Function owner
|
||||||
std::string name; //Function identifier
|
std::string name; //Function identifier
|
||||||
std::string rettype; //Function return type
|
std::string rettype; //Function return type
|
||||||
|
QualifiedType retqtype; // Function return qualified 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)
|
||||||
|
@ -116,16 +153,17 @@ namespace Types
|
||||||
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 std::string & 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 std::string & type, const std::string & name, int arrsize = 0, int offset = -1);
|
||||||
bool AddFunction(const std::string & owner, const std::string & name, const std::string & rettype, CallingConvention callconv = Cdecl, bool noreturn = false, bool typeonly = false);
|
bool AddFunction(const std::string & owner, const std::string & name, const std::string & rettype, CallingConvention callconv = Cdecl, bool noreturn = false, bool typeonly = false, const QualifiedType& retqtype = {});
|
||||||
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);
|
bool AddArg(const std::string & function, const std::string & type, const std::string & name, const QualifiedType& qtype);
|
||||||
bool AppendArg(const std::string & type, const std::string & name);
|
bool AppendArg(const std::string & type, const std::string & name, const QualifiedType& qtype);
|
||||||
int Sizeof(const std::string & 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);
|
||||||
void Enumerate(std::vector<Summary> & typeList) const;
|
void Enumerate(std::vector<Summary> & typeList) const;
|
||||||
std::string StructUnionPtrType(const std::string & pointto) const;
|
std::string StructUnionPtrType(const std::string & pointto) const;
|
||||||
|
bool GenerateStubs() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unordered_map<Primitive, int> primitivesizes;
|
std::unordered_map<Primitive, int> primitivesizes;
|
||||||
|
@ -162,8 +200,8 @@ 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 std::string & 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 std::string & type, const std::string & name, int arrsize = 0, int offset = -1);
|
||||||
bool AddFunction(const std::string & owner, const std::string & name, const std::string & rettype, Types::CallingConvention callconv = Types::Cdecl, bool noreturn = false);
|
bool AddFunction(const std::string & owner, const std::string & name, const std::string & rettype, Types::CallingConvention callconv = Types::Cdecl, bool noreturn = false);
|
||||||
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, const Types::QualifiedType& qtype);
|
||||||
bool AppendArg(const std::string & type, const std::string & name);
|
bool AppendArg(const std::string & type, const std::string & name, const Types::QualifiedType& qtype);
|
||||||
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 = "");
|
||||||
|
@ -172,4 +210,5 @@ void EnumTypes(std::vector<Types::TypeManager::Summary> & typeList);
|
||||||
bool LoadTypesJson(const std::string & json, const std::string & owner);
|
bool LoadTypesJson(const std::string & json, const std::string & owner);
|
||||||
bool LoadTypesFile(const std::string & path, const std::string & owner);
|
bool LoadTypesFile(const std::string & path, const std::string & owner);
|
||||||
bool ParseTypes(const std::string & code, const std::string & owner, std::vector<std::string> & errors);
|
bool ParseTypes(const std::string & code, const std::string & owner, std::vector<std::string> & errors);
|
||||||
std::string StructUnionPtrType(const std::string & pointto);
|
std::string StructUnionPtrType(const std::string & pointto);
|
||||||
|
bool GenerateStubs();
|
|
@ -62,10 +62,10 @@ struct Parser
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool parseVariable(const std::vector<Lexer::TokenState>& tlist, std::string& type, bool& isConst, std::string& name)
|
bool parseVariable(const std::vector<Lexer::TokenState>& tlist, std::string& type, QualifiedType& qtype, std::string& name)
|
||||||
{
|
{
|
||||||
type.clear();
|
type.clear();
|
||||||
isConst = false;
|
qtype = QualifiedType();
|
||||||
name.clear();
|
name.clear();
|
||||||
|
|
||||||
bool sawPointer = false;
|
bool sawPointer = false;
|
||||||
|
@ -76,7 +76,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))
|
||||||
{
|
{
|
||||||
isConst = true;
|
if(i == 0 || qtype.pointers.empty())
|
||||||
|
qtype.isConst = true;
|
||||||
|
else
|
||||||
|
qtype.pointers.back().isConst = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,6 +133,11 @@ struct Parser
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!sawPointer)
|
||||||
|
qtype.name = type;
|
||||||
|
|
||||||
|
qtype.pointers.emplace_back();
|
||||||
|
|
||||||
// Apply the pointer to the type on the left
|
// Apply the pointer to the type on the left
|
||||||
type += '*';
|
type += '*';
|
||||||
sawPointer = true;
|
sawPointer = true;
|
||||||
|
@ -142,6 +150,8 @@ struct Parser
|
||||||
}
|
}
|
||||||
if (type.empty())
|
if (type.empty())
|
||||||
__debugbreak();
|
__debugbreak();
|
||||||
|
if(!sawPointer)
|
||||||
|
qtype.name = type;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,8 +166,7 @@ struct Parser
|
||||||
// TODO: calling conventions
|
// TODO: calling conventions
|
||||||
|
|
||||||
std::string retname;
|
std::string retname;
|
||||||
bool retconst = false;
|
if (!parseVariable(rettypes, fn.rettype, fn.retqtype, retname))
|
||||||
if (!parseVariable(rettypes, fn.rettype, retconst, retname))
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (ptr)
|
if (ptr)
|
||||||
|
@ -212,7 +221,7 @@ struct Parser
|
||||||
auto finalizeArgument = [&]()
|
auto finalizeArgument = [&]()
|
||||||
{
|
{
|
||||||
Member am;
|
Member am;
|
||||||
if (!parseVariable(tlist, am.type, am.isConst, am.name))
|
if (!parseVariable(tlist, am.type, am.qtype, am.name))
|
||||||
return false;
|
return false;
|
||||||
fn.args.push_back(am);
|
fn.args.push_back(am);
|
||||||
tlist.clear();
|
tlist.clear();
|
||||||
|
@ -305,9 +314,6 @@ struct Parser
|
||||||
auto typeToken = tlist.back();
|
auto typeToken = tlist.back();
|
||||||
typeToken.Token = Lexer::tok_identifier;
|
typeToken.Token = Lexer::tok_identifier;
|
||||||
typeToken.IdentifierStr = fn.name + "_" + subfn.name + "_fnptr";
|
typeToken.IdentifierStr = fn.name + "_" + subfn.name + "_fnptr";
|
||||||
|
|
||||||
subfn.name = typeToken.IdentifierStr;
|
|
||||||
model.functions.push_back(subfn);
|
|
||||||
|
|
||||||
auto nameToken = startToken;
|
auto nameToken = startToken;
|
||||||
nameToken.Token = Lexer::tok_identifier;
|
nameToken.Token = Lexer::tok_identifier;
|
||||||
|
@ -317,6 +323,10 @@ struct Parser
|
||||||
tlist.clear();
|
tlist.clear();
|
||||||
tlist.push_back(typeToken);
|
tlist.push_back(typeToken);
|
||||||
tlist.push_back(nameToken);
|
tlist.push_back(nameToken);
|
||||||
|
|
||||||
|
// Add the function to the model
|
||||||
|
subfn.name = typeToken.IdentifierStr;
|
||||||
|
model.functions.push_back(subfn);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -362,7 +372,7 @@ struct Parser
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!parseVariable(tlist, m.type, m.isConst, m.name))
|
if (!parseVariable(tlist, m.type, m.qtype, m.name))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (m.type == "void")
|
if (m.type == "void")
|
||||||
|
@ -472,9 +482,6 @@ struct Parser
|
||||||
typeToken.Token = Lexer::tok_identifier;
|
typeToken.Token = Lexer::tok_identifier;
|
||||||
typeToken.IdentifierStr = su.name + "_" + subfn.name + "_fnptr";
|
typeToken.IdentifierStr = su.name + "_" + subfn.name + "_fnptr";
|
||||||
|
|
||||||
subfn.name = typeToken.IdentifierStr;
|
|
||||||
model.functions.push_back(subfn);
|
|
||||||
|
|
||||||
auto nameToken = startToken;
|
auto nameToken = startToken;
|
||||||
nameToken.Token = Lexer::tok_identifier;
|
nameToken.Token = Lexer::tok_identifier;
|
||||||
nameToken.IdentifierStr = subfn.name;
|
nameToken.IdentifierStr = subfn.name;
|
||||||
|
@ -484,6 +491,10 @@ struct Parser
|
||||||
tlist.push_back(typeToken);
|
tlist.push_back(typeToken);
|
||||||
tlist.push_back(nameToken);
|
tlist.push_back(nameToken);
|
||||||
|
|
||||||
|
// Add the function to the model
|
||||||
|
subfn.name = typeToken.IdentifierStr;
|
||||||
|
model.functions.push_back(subfn);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (t.Is(Lexer::tok_comma))
|
else if (t.Is(Lexer::tok_comma))
|
||||||
|
@ -814,7 +825,7 @@ struct Parser
|
||||||
}
|
}
|
||||||
|
|
||||||
Member tm;
|
Member tm;
|
||||||
if (!parseVariable(tlist, tm.type, tm.isConst, tm.name))
|
if (!parseVariable(tlist, tm.type, tm.qtype, tm.name))
|
||||||
return false;
|
return false;
|
||||||
model.types.push_back(tm);
|
model.types.push_back(tm);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue