Update gsc-tool + add gsc error lines
This commit is contained in:
parent
dbe995452c
commit
d8cf3f53ab
2
deps/gsc-tool
vendored
2
deps/gsc-tool
vendored
@ -1 +1 @@
|
|||||||
Subproject commit 4806a285b6e6719f5ea968a4199a34ee86eb7cfb
|
Subproject commit 2dbff1a408096e418c5b3eda01bc9a91eee6587b
|
@ -76,7 +76,7 @@ namespace gsc
|
|||||||
{
|
{
|
||||||
const auto& pos = function.value();
|
const auto& pos = function.value();
|
||||||
unknown_function_error = std::format(
|
unknown_function_error = std::format(
|
||||||
"while processing function '{}' in script '{}':\nunknown script '{}'", pos.first, pos.second, scripting::current_file
|
"while processing function '{}' in script '{}':\nunknown script '{}'", pos.function, pos.file, scripting::current_file
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -293,16 +293,21 @@ namespace gsc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<std::pair<std::string, std::string>> find_function(const char* pos)
|
std::optional<script_info_t> find_function(const char* pos)
|
||||||
{
|
{
|
||||||
for (const auto& file : scripting::script_function_table_sort)
|
for (const auto& file : scripting::script_function_table_sort)
|
||||||
{
|
{
|
||||||
|
const auto first_function = file.second.begin();
|
||||||
for (auto i = file.second.begin(); i != file.second.end() && std::next(i) != file.second.end(); ++i)
|
for (auto i = file.second.begin(); i != file.second.end() && std::next(i) != file.second.end(); ++i)
|
||||||
{
|
{
|
||||||
const auto next = std::next(i);
|
const auto next = std::next(i);
|
||||||
if (pos >= i->second && pos < next->second)
|
if (pos >= i->second && pos < next->second)
|
||||||
{
|
{
|
||||||
return {std::make_pair(i->first, file.first)};
|
script_info_t info{};
|
||||||
|
info.function = i->first;
|
||||||
|
info.file = file.first;
|
||||||
|
info.script_start = first_function->second;
|
||||||
|
return {info};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,5 +4,12 @@ namespace gsc
|
|||||||
{
|
{
|
||||||
extern std::array<const char*, 27> var_typename;
|
extern std::array<const char*, 27> var_typename;
|
||||||
|
|
||||||
std::optional<std::pair<std::string, std::string>> find_function(const char* pos);
|
struct script_info_t
|
||||||
|
{
|
||||||
|
const char* script_start;
|
||||||
|
std::string file;
|
||||||
|
std::string function;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::optional<script_info_t> find_function(const char* pos);
|
||||||
}
|
}
|
||||||
|
@ -130,16 +130,39 @@ namespace gsc
|
|||||||
{
|
{
|
||||||
for (auto frame = game::scr_VmPub->function_frame; frame != game::scr_VmPub->function_frame_start; --frame)
|
for (auto frame = game::scr_VmPub->function_frame; frame != game::scr_VmPub->function_frame_start; --frame)
|
||||||
{
|
{
|
||||||
const auto pos = frame == game::scr_VmPub->function_frame ? game::scr_function_stack->pos : frame->fs.pos;
|
const auto pos = frame == game::scr_VmPub->function_frame ? game::scr_function_stack->pos - 1 : frame->fs.pos;
|
||||||
const auto function = find_function(frame->fs.pos);
|
const auto info = find_function(pos);
|
||||||
|
|
||||||
if (function.has_value())
|
if (!info.has_value())
|
||||||
{
|
{
|
||||||
console::warn("\tat function \"%s\" in file \"%s.gsc\"\n", function.value().first.data(), function.value().second.data());
|
console::warn("\tat unknown location %p\n", pos);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& function = info->function;
|
||||||
|
const auto& file = info->file;
|
||||||
|
const auto devmap_opt = get_script_devmap(file);
|
||||||
|
|
||||||
|
if (devmap_opt.has_value())
|
||||||
|
{
|
||||||
|
const auto& devmap = devmap_opt.value();
|
||||||
|
const auto rel_pos = static_cast<std::uint32_t>(pos - info->script_start);
|
||||||
|
const auto& iter = devmap->find(rel_pos);
|
||||||
|
|
||||||
|
if (iter != devmap->end())
|
||||||
|
{
|
||||||
|
console::warn("\tat function \"%s\" in file \"%s.gsc\" (line %d, column %d)\n",
|
||||||
|
function.data(), file.data(),
|
||||||
|
iter->second.line, iter->second.column);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
console::warn("\tat unknown location %p\n", pos);
|
console::warn("\tat function \"%s\" in file \"%s.gsc\"\n", function.data(), file.data());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
console::warn("\tat function \"%s\" in file \"%s.gsc\"\n", function.data(), file.data());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,13 @@ namespace gsc
|
|||||||
std::unordered_map<std::string, unsigned int> main_handles;
|
std::unordered_map<std::string, unsigned int> main_handles;
|
||||||
std::unordered_map<std::string, unsigned int> init_handles;
|
std::unordered_map<std::string, unsigned int> init_handles;
|
||||||
|
|
||||||
std::unordered_map<std::string, game::ScriptFile*> loaded_scripts;
|
struct loaded_script_t
|
||||||
|
{
|
||||||
|
game::ScriptFile* ptr;
|
||||||
|
std::map<std::uint32_t, col_line_t> devmap;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::unordered_map<std::string, loaded_script_t> loaded_scripts;
|
||||||
utils::memory::allocator script_allocator;
|
utils::memory::allocator script_allocator;
|
||||||
|
|
||||||
struct
|
struct
|
||||||
@ -97,11 +103,44 @@ namespace gsc
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::map<std::uint32_t, col_line_t> parse_devmap(const xsk::gsc::buffer& devmap)
|
||||||
|
{
|
||||||
|
auto devmap_ptr = devmap.data;
|
||||||
|
|
||||||
|
const auto read_32 = [&]()
|
||||||
|
{
|
||||||
|
const auto val = *reinterpret_cast<const std::uint32_t*>(devmap_ptr);
|
||||||
|
devmap_ptr += sizeof(std::uint32_t);
|
||||||
|
return val;
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto read_16 = [&]()
|
||||||
|
{
|
||||||
|
const auto val = *reinterpret_cast<const std::uint16_t*>(devmap_ptr);
|
||||||
|
devmap_ptr += sizeof(std::uint16_t);
|
||||||
|
return val;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::map<std::uint32_t, col_line_t> pos_map;
|
||||||
|
|
||||||
|
const auto devmap_count = read_32();
|
||||||
|
for (auto i = 0u; i < devmap_count; i++)
|
||||||
|
{
|
||||||
|
const auto script_pos = read_32() - 1;
|
||||||
|
const auto line = read_16();
|
||||||
|
const auto col = read_16();
|
||||||
|
|
||||||
|
pos_map[script_pos] = {line, col};
|
||||||
|
}
|
||||||
|
|
||||||
|
return pos_map;
|
||||||
|
}
|
||||||
|
|
||||||
game::ScriptFile* load_custom_script(const char* file_name, const std::string& real_name)
|
game::ScriptFile* load_custom_script(const char* file_name, const std::string& real_name)
|
||||||
{
|
{
|
||||||
if (const auto itr = loaded_scripts.find(file_name); itr != loaded_scripts.end())
|
if (const auto itr = loaded_scripts.find(file_name); itr != loaded_scripts.end())
|
||||||
{
|
{
|
||||||
return itr->second;
|
return itr->second.ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
@ -119,26 +158,29 @@ namespace gsc
|
|||||||
data.assign(source_buffer.begin(), source_buffer.end());
|
data.assign(source_buffer.begin(), source_buffer.end());
|
||||||
|
|
||||||
const auto assembly_ptr = compiler.compile(real_name, data);
|
const auto assembly_ptr = compiler.compile(real_name, data);
|
||||||
const auto output_script = assembler.assemble(*assembly_ptr);
|
[[maybe_unused]] const auto& [script, stack, devmap] = assembler.assemble(*assembly_ptr);
|
||||||
|
|
||||||
const auto script_file_ptr = static_cast<game::ScriptFile*>(script_allocator.allocate(sizeof(game::ScriptFile)));
|
const auto script_file_ptr = static_cast<game::ScriptFile*>(script_allocator.allocate(sizeof(game::ScriptFile)));
|
||||||
script_file_ptr->name = file_name;
|
script_file_ptr->name = file_name;
|
||||||
|
|
||||||
script_file_ptr->len = static_cast<int>(output_script.second.size);
|
script_file_ptr->len = static_cast<int>(stack.size);
|
||||||
script_file_ptr->bytecodeLen = static_cast<int>(output_script.first.size);
|
script_file_ptr->bytecodeLen = static_cast<int>(script.size);
|
||||||
|
|
||||||
const auto stack_size = static_cast<std::uint32_t>(output_script.second.size + 1);
|
const auto stack_size = static_cast<std::uint32_t>(stack.size + 1);
|
||||||
const auto byte_code_size = static_cast<std::uint32_t>(output_script.first.size + 1);
|
const auto byte_code_size = static_cast<std::uint32_t>(script.size + 1);
|
||||||
|
|
||||||
script_file_ptr->buffer = static_cast<char*>(script_allocator.allocate(stack_size));
|
script_file_ptr->buffer = static_cast<char*>(script_allocator.allocate(stack_size));
|
||||||
std::memcpy(const_cast<char*>(script_file_ptr->buffer), output_script.second.data, output_script.second.size);
|
std::memcpy(const_cast<char*>(script_file_ptr->buffer), stack.data, stack.size);
|
||||||
|
|
||||||
script_file_ptr->bytecode = allocate_buffer(byte_code_size);
|
script_file_ptr->bytecode = allocate_buffer(byte_code_size);
|
||||||
std::memcpy(script_file_ptr->bytecode, output_script.first.data, output_script.first.size);
|
std::memcpy(script_file_ptr->bytecode, script.data, script.size);
|
||||||
|
|
||||||
script_file_ptr->compressedLen = 0;
|
script_file_ptr->compressedLen = 0;
|
||||||
|
|
||||||
loaded_scripts[file_name] = script_file_ptr;
|
loaded_script_t loaded_script{};
|
||||||
|
loaded_script.ptr = script_file_ptr;
|
||||||
|
loaded_script.devmap = parse_devmap(devmap);
|
||||||
|
loaded_scripts.insert(std::make_pair(file_name, loaded_script));
|
||||||
|
|
||||||
return script_file_ptr;
|
return script_file_ptr;
|
||||||
}
|
}
|
||||||
@ -153,7 +195,7 @@ namespace gsc
|
|||||||
|
|
||||||
std::string get_raw_script_file_name(const std::string& name)
|
std::string get_raw_script_file_name(const std::string& name)
|
||||||
{
|
{
|
||||||
if (name.ends_with(".gsh"))
|
if (name.ends_with(".gsh") || name.ends_with(".gsc"))
|
||||||
{
|
{
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
@ -163,10 +205,17 @@ namespace gsc
|
|||||||
|
|
||||||
std::string get_script_file_name(const std::string& name)
|
std::string get_script_file_name(const std::string& name)
|
||||||
{
|
{
|
||||||
const auto id = gsc_ctx->token_id(name);
|
std::string script_name = name;
|
||||||
|
if (script_name.ends_with(".gsc"))
|
||||||
|
{
|
||||||
|
const auto dot_idx = script_name.find_last_of('.');
|
||||||
|
script_name = script_name.substr(0, dot_idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto id = gsc_ctx->token_id(script_name);
|
||||||
if (!id)
|
if (!id)
|
||||||
{
|
{
|
||||||
return name;
|
return script_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::to_string(id);
|
return std::to_string(id);
|
||||||
@ -319,7 +368,7 @@ namespace gsc
|
|||||||
? xsk::gsc::build::dev
|
? xsk::gsc::build::dev
|
||||||
: xsk::gsc::build::prod;
|
: xsk::gsc::build::prod;
|
||||||
|
|
||||||
gsc_ctx->init(comp_mode, [](const std::string& include_name)
|
gsc_ctx->init(comp_mode, [](const xsk::gsc::context* context, const std::string& include_name)
|
||||||
-> std::pair<xsk::gsc::buffer, std::vector<std::uint8_t>>
|
-> std::pair<xsk::gsc::buffer, std::vector<std::uint8_t>>
|
||||||
{
|
{
|
||||||
const auto real_name = get_raw_script_file_name(include_name);
|
const auto real_name = get_raw_script_file_name(include_name);
|
||||||
@ -388,6 +437,17 @@ namespace gsc
|
|||||||
return game::DB_FindXAssetHeader(type, name, allow_create_default).scriptfile;
|
return game::DB_FindXAssetHeader(type, name, allow_create_default).scriptfile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<std::map<std::uint32_t, col_line_t>*> get_script_devmap(const std::string& name)
|
||||||
|
{
|
||||||
|
const auto iter = loaded_scripts.find(name);
|
||||||
|
if (iter == loaded_scripts.end())
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {&iter->second.devmap};
|
||||||
|
}
|
||||||
|
|
||||||
class loading final : public component_interface
|
class loading final : public component_interface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -5,8 +5,16 @@
|
|||||||
|
|
||||||
namespace gsc
|
namespace gsc
|
||||||
{
|
{
|
||||||
|
struct col_line_t
|
||||||
|
{
|
||||||
|
std::uint16_t line;
|
||||||
|
std::uint16_t column;
|
||||||
|
};
|
||||||
|
|
||||||
extern std::unique_ptr<xsk::gsc::h2::context> gsc_ctx;
|
extern std::unique_ptr<xsk::gsc::h2::context> gsc_ctx;
|
||||||
extern game::dvar_t* developer_script;
|
extern game::dvar_t* developer_script;
|
||||||
|
|
||||||
game::ScriptFile* find_script(game::XAssetType type, const char* name, int allow_create_default);
|
game::ScriptFile* find_script(game::XAssetType type, const char* name, int allow_create_default);
|
||||||
|
|
||||||
|
std::optional<std::map<std::uint32_t, col_line_t>*> get_script_devmap(const std::string& name);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user