111 lines
3.1 KiB
C++
111 lines
3.1 KiB
C++
#include "FunctionInfo.hpp"
|
|
#include <algorithm>
|
|
#include <format>
|
|
#include <regex>
|
|
|
|
std::smatch match;
|
|
|
|
const std::regex usg_vld_rgx(R"(Usage: .+?\((.*?)\))");
|
|
|
|
void FunctionInfo::chk_vld()
|
|
{ // run all checks, so we have the full picture
|
|
bool vld = true;
|
|
if (prs_msg.size() > 0) vld = false; // parsing messages up until this point are hard errors
|
|
if (in_cnt > -1)
|
|
{ // in varmap is not dynamic
|
|
if (!usg.empty())
|
|
{ // check against usage string
|
|
if (std::regex_search(usg, match, usg_vld_rgx))
|
|
{
|
|
std::string usg_params = match[1];
|
|
int comma_cnt = 0;
|
|
for (char c : usg_params) comma_cnt += c == ',';
|
|
if (in_cnt == 0 && !usg_params.empty() || in_cnt != comma_cnt + 1)
|
|
{
|
|
prs_msg.push_back(std::format("in param count ({}) does not match usage string ({})", in_cnt, !usg_params.empty() * (comma_cnt + 1)));
|
|
vld = false;
|
|
}
|
|
}
|
|
else prs_msg.push_back("usage string is malformed"); // do not consider this for validity
|
|
}
|
|
for (int i = 1; i <= in_cnt; i++)
|
|
{ // lua indexes start with 1
|
|
if (!in.contains(i))
|
|
{
|
|
prs_msg.push_back("in param index not in order");
|
|
vld = false;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (out_cnt != -1 && out_cnt != out.size())
|
|
{
|
|
prs_msg.push_back(std::format("out param count ({}) does not match return value ({})", out.size(), out_cnt));
|
|
vld = false;
|
|
}
|
|
prs_vld = vld;
|
|
}
|
|
|
|
bool FunctionInfo::nil_in_varmap(bool proc_in) const
|
|
{
|
|
const varmap& params = proc_in ? in : out;
|
|
for (auto& [key, value] : params)
|
|
if (std::find(value.begin(), value.end(), "nil") != value.end())
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
void FunctionInfo::cln_varmap(bool proc_in)
|
|
{
|
|
varmap& params = proc_in ? in : out;
|
|
int cnt = proc_in ? in_cnt : out_cnt;
|
|
if (cnt == -1)
|
|
{
|
|
params.clear(); // dynamic varmap does not need entries
|
|
return;
|
|
}
|
|
for (auto& [lua_index, lua_types] : params)
|
|
{
|
|
std::sort(lua_types.begin(), lua_types.end());
|
|
lua_types.erase(std::unique(lua_types.begin(), lua_types.end()), lua_types.end());
|
|
}
|
|
if (proc_in) in_cnt = in.size(); // input count can only be inferred by in varmap size
|
|
}
|
|
|
|
std::string FunctionInfo::str() const
|
|
{
|
|
std::string str = std::format("{:X} {}{}\n", addr, nm, prs_vld ? "" : " (invalid)");
|
|
if (!usg.empty()) str += " " + usg + "\n";
|
|
str += " in: " + str_varmap(true) + "\n";
|
|
str += " out: " + str_varmap(false);
|
|
for (const std::string& err : prs_msg) str += "\n " + err;
|
|
return str;
|
|
}
|
|
|
|
std::string FunctionInfo::str_varmap(bool proc_in) const
|
|
{
|
|
int cnt = proc_in ? in_cnt : out_cnt;
|
|
switch (cnt)
|
|
{
|
|
case -1:
|
|
return "dynamic";
|
|
case 0:
|
|
return "0 ()";
|
|
}
|
|
const varmap& params = proc_in ? in : out;
|
|
if (params.size() > 0)
|
|
{ // cnt and params.size() might differ - lua_push* calls can be undetected
|
|
std::string str = std::to_string(cnt) + " (";
|
|
for (const auto& [lua_index, lua_types] : params)
|
|
{
|
|
for (const auto& lua_type : lua_types) str += lua_type + "/";
|
|
str.pop_back(); // remove last slash
|
|
str += ", ";
|
|
}
|
|
str[str.length() - 2] = ')'; // replace last comma with closing bracket
|
|
str.pop_back(); // remove space after last comma
|
|
return str;
|
|
}
|
|
return std::to_string(cnt) + " ()";
|
|
}
|