Start supporting function pointer types

This commit is contained in:
Duncan Ogilvie 2023-02-05 23:14:06 +01:00
parent c7ad8a7f7f
commit eaecaf942b
2 changed files with 244 additions and 11 deletions

View File

@ -68,6 +68,7 @@ namespace Types
enum CallingConvention enum CallingConvention
{ {
DefaultDecl,
Cdecl, Cdecl,
Stdcall, Stdcall,
Thiscall, Thiscall,
@ -79,7 +80,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
CallingConvention callconv = Cdecl; //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)
std::vector<Member> args; //Function arguments std::vector<Member> args; //Function arguments
}; };

View File

@ -107,10 +107,22 @@ bool ParseTypes(const std::string& parse, const std::string& owner, std::vector<
} }
break; break;
} }
else if (i + 1 == memToks.size() || memToks[i + 1].Token == Lexer::tok_subopen) //last = name else if (i + 1 == memToks.size() ||
memToks[i + 1].Token == Lexer::tok_subopen ||
memToks[i+1].Token == Lexer::tok_comma)
{ {
m.name = lexer.TokString(memToks[i]); m.name = lexer.TokString(memToks[i]);
} }
else if (t.Token == Lexer::tok_comma) //uint32_t a,b;
{
// Flush the current member, inherit the type and continue
su.members.push_back(m);
auto cm = Member();
cm.type = m.type;
while (!cm.type.empty() && cm.type.back() == '*')
cm.type.pop_back();
m = cm;
}
else if (!t.IsType() && else if (!t.IsType() &&
t.Token != Lexer::tok_op_mul && t.Token != Lexer::tok_op_mul &&
t.Token != Lexer::tok_identifier && t.Token != Lexer::tok_identifier &&
@ -140,10 +152,16 @@ bool ParseTypes(const std::string& parse, const std::string& owner, std::vector<
StructUnion su; StructUnion su;
su.isunion = isToken(Lexer::tok_union); su.isunion = isToken(Lexer::tok_union);
index++; index++;
if (isTokenList({ Lexer::tok_identifier, Lexer::tok_bropen })) if (!isToken(Lexer::tok_identifier))
{ {
errLine(curToken(), "expected identifier after struct");
return false;
}
su.name = lexer.TokString(curToken()); su.name = lexer.TokString(curToken());
index += 2; index++;
if (isToken(Lexer::tok_bropen))
{
index++;
while (!isToken(Lexer::tok_brclose)) while (!isToken(Lexer::tok_brclose))
{ {
if (isToken(Lexer::tok_eof)) if (isToken(Lexer::tok_eof))
@ -170,6 +188,13 @@ bool ParseTypes(const std::string& parse, const std::string& owner, std::vector<
eatSemic(); eatSemic();
return true; return true;
} }
else if (isToken(Lexer::tok_semic))
{
// Forward declaration
model.structUnions.push_back(su);
eatSemic();
return true;
}
else else
{ {
errLine(curToken(), "invalid struct token sequence!"); errLine(curToken(), "invalid struct token sequence!");
@ -188,6 +213,8 @@ bool ParseTypes(const std::string& parse, const std::string& owner, std::vector<
{ {
e.name = lexer.TokString(curToken()); e.name = lexer.TokString(curToken());
index += 2; index += 2;
if (e.name == "BNFunctionGraphType")
__debugbreak();
while (!isToken(Lexer::tok_brclose)) while (!isToken(Lexer::tok_brclose))
{ {
if (isToken(Lexer::tok_eof)) if (isToken(Lexer::tok_eof))
@ -206,6 +233,11 @@ bool ParseTypes(const std::string& parse, const std::string& owner, std::vector<
if (isToken(Lexer::tok_comma)) if (isToken(Lexer::tok_comma))
{ {
index++; index++;
if (isToken(Lexer::tok_brclose))
{
// Support final comma
break;
}
} }
else else
{ {
@ -222,10 +254,34 @@ bool ParseTypes(const std::string& parse, const std::string& owner, std::vector<
EnumValue v; EnumValue v;
v.name = lexer.TokString(curToken()); v.name = lexer.TokString(curToken());
v.value = e.values.empty() ? 0 : e.values.back().value + 1;
e.values.push_back(v);
index++; index++;
if (isToken(Lexer::tok_assign))
{
bool negative = false;
index++;
if (isToken(Lexer::tok_op_min))
{
index++;
negative = true;
}
if (!isToken(Lexer::tok_number))
{
errLine(curToken(), "expected number after = in enum");
return false;
}
v.value = curToken().NumberVal;
if (negative)
{
v.value = -(int64_t)v.value;
}
index++;
}
else
{
v.value = e.values.empty() ? 0 : e.values.back().value + 1;
}
e.values.push_back(v);
} }
index++; //eat tok_brclose index++; //eat tok_brclose
@ -249,18 +305,192 @@ bool ParseTypes(const std::string& parse, const std::string& owner, std::vector<
}; };
auto parseTypedef = [&]() auto parseTypedef = [&]()
{ {
// TODO: support "typedef struct" // TODO: support "typedef struct foo { members... };"
// TODO: support "typedef enum foo { members... };"
if (isToken(Lexer::tok_typedef)) if (isToken(Lexer::tok_typedef))
{ {
index++; index++;
std::vector<Lexer::TokenState> tdefToks;
while (!isToken(Lexer::tok_semic)) std::vector<std::string> tdList;
while (true)
{ {
if (isToken(Lexer::tok_eof)) if (isToken(Lexer::tok_eof))
{ {
errLine(curToken(), "unexpected eof in typedef"); errLine(curToken(), "unexpected eof in typedef");
return false; return false;
} }
if (isToken(Lexer::tok_semic))
{
index++;
__debugbreak();
break;
}
if (isToken(Lexer::tok_struct) || isToken(Lexer::tok_enum))
{
// TODO
__debugbreak();
}
const auto& t = curToken();
if (t.IsType() || t.Token == Lexer::tok_identifier || t.Token == Lexer::tok_void)
{
// Primitive type
index++;
tdList.push_back(lexer.TokString(t));
}
else if (t.Token == Lexer::tok_op_mul)
{
// Pointer to the type on the left
if (tdList.empty())
{
errLine(curToken(), "unexpected * in function typedef");
return false;
}
index++;
tdList.back().push_back('*');
}
else if (t.Token == Lexer::tok_paropen)
{
// Function pointer type
if (tdList.empty())
{
errLine(curToken(), "expected return type before function typedef");
return false;
}
// TODO: calling conventions
index++;
if (!isToken(Lexer::tok_op_mul))
{
errLine(curToken(), "expected * in function typedef");
return false;
}
index++;
if (!isToken(Lexer::tok_identifier))
{
errLine(curToken(), "expected identifier in function typedef");
return false;
}
Function fn;
fn.name = lexer.TokString(curToken());
index++;
if (!isToken(Lexer::tok_parclose))
{
errLine(curToken(), "expected ) after function typedef name");
return false;
}
index++;
if (!isToken(Lexer::tok_paropen))
{
errLine(curToken(), "expected ( for start of parameter list in function typedef");
return false;
}
index++;
for (const auto& type : tdList)
{
if (!fn.rettype.empty())
fn.rettype += ' ';
fn.rettype += type;
}
Member arg;
while (!isToken(Lexer::tok_parclose))
{
if (!fn.args.empty())
{
if (isToken(Lexer::tok_comma))
{
index++;
fn.args.push_back(arg);
}
else
{
errLine(curToken(), "expected comma in function typedef argument list");
return false;
}
}
const auto& t = curToken();
if (t.Token == Lexer::tok_void)
{
// empty argument list
index++;
if (!fn.args.empty())
{
errLine(t, "void only allowed in an empty function typedef argument list");
return false;
}
if (!isToken(Lexer::tok_parclose))
{
errLine(curToken(), "expected ) after void in function typedef argument list");
return false;
}
break;
}
else if (t.IsType() || t.Token == Lexer::tok_identifier)
{
// Primitive type
index++;
if (!arg.type.empty())
{
if (arg.type.back() == '*')
{
errLine(t, "unexpected type after * in function typedef argument list");
return false;
}
arg.type.push_back(' ');
}
arg.type += lexer.TokString(t);
}
else if (t.Token == Lexer::tok_op_mul)
{
// Pointer to the type on the left
if (arg.type.empty())
{
errLine(curToken(), "unexpected * in function typedef argument list");
return false;
}
index++;
fn.args.back().type.push_back('*');
}
else
{
errLine(curToken(), "unsupported token in function typedef argument list");
return false;
}
}
index++;
if (!arg.type.empty())
{
fn.args.push_back(arg);
}
if (!isToken(Lexer::tok_semic))
{
errLine(curToken(), "expected ; after function typedef");
return false;
}
eatSemic();
// TODO: put the fn somewhere
return true;
}
else
{
__debugbreak();
}
}
__debugbreak();
std::vector<Lexer::TokenState> tdefToks;
while (!isToken(Lexer::tok_semic))
{
tdefToks.push_back(curToken()); tdefToks.push_back(curToken());
index++; index++;
} }
@ -276,6 +506,7 @@ bool ParseTypes(const std::string& parse, const std::string& owner, std::vector<
tm.name = lexer.TokString(tdefToks[tdefToks.size() - 1]); tm.name = lexer.TokString(tdefToks[tdefToks.size() - 1]);
tdefToks.pop_back(); tdefToks.pop_back();
for (auto& t : tdefToks) for (auto& t : tdefToks)
{
if (!t.IsType() && if (!t.IsType() &&
t.Token != Lexer::tok_op_mul && t.Token != Lexer::tok_op_mul &&
t.Token != Lexer::tok_identifier && t.Token != Lexer::tok_identifier &&
@ -290,6 +521,7 @@ bool ParseTypes(const std::string& parse, const std::string& owner, std::vector<
tm.type.push_back(' '); tm.type.push_back(' ');
tm.type += lexer.TokString(t); tm.type += lexer.TokString(t);
} }
}
//dprintf("typedef %s:%s\n", tm.type.c_str(), tm.name.c_str()); //dprintf("typedef %s:%s\n", tm.type.c_str(), tm.name.c_str());
model.types.push_back(tm); model.types.push_back(tm);
return true; return true;