Skip to content

Commit

Permalink
Update gsc-tool + add gsc error lines
Browse files Browse the repository at this point in the history
  • Loading branch information
alicealys committed Jan 17, 2024
1 parent dbe9954 commit d8cf3f5
Show file tree
Hide file tree
Showing 6 changed files with 127 additions and 24 deletions.
2 changes: 1 addition & 1 deletion deps/gsc-tool
Submodule gsc-tool updated 212 files
11 changes: 8 additions & 3 deletions src/client/component/gsc/script_error.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ namespace gsc
{
const auto& pos = function.value();
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
Expand Down Expand Up @@ -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)
{
const auto first_function = file.second.begin();
for (auto i = file.second.begin(); i != file.second.end() && std::next(i) != file.second.end(); ++i)
{
const auto next = std::next(i);
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};
}
}
}
Expand Down
9 changes: 8 additions & 1 deletion src/client/component/gsc/script_error.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,12 @@ namespace gsc
{
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);
}
33 changes: 28 additions & 5 deletions src/client/component/gsc/script_extension.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,16 +130,39 @@ namespace gsc
{
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 function = find_function(frame->fs.pos);
const auto pos = frame == game::scr_VmPub->function_frame ? game::scr_function_stack->pos - 1 : 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
{
console::warn("\tat function \"%s\" in file \"%s.gsc\"\n", function.data(), file.data());
}
}
else
{
console::warn("\tat unknown location %p\n", pos);
console::warn("\tat function \"%s\" in file \"%s.gsc\"\n", function.data(), file.data());
}
}
}
Expand Down
88 changes: 74 additions & 14 deletions src/client/component/gsc/script_loading.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,13 @@ namespace gsc
std::unordered_map<std::string, unsigned int> main_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;

struct
Expand Down Expand Up @@ -97,11 +103,44 @@ namespace gsc
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)
{
if (const auto itr = loaded_scripts.find(file_name); itr != loaded_scripts.end())
{
return itr->second;
return itr->second.ptr;
}

try
Expand All @@ -119,26 +158,29 @@ namespace gsc
data.assign(source_buffer.begin(), source_buffer.end());

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)));
script_file_ptr->name = file_name;

script_file_ptr->len = static_cast<int>(output_script.second.size);
script_file_ptr->bytecodeLen = static_cast<int>(output_script.first.size);
script_file_ptr->len = static_cast<int>(stack.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 byte_code_size = static_cast<std::uint32_t>(output_script.first.size + 1);
const auto stack_size = static_cast<std::uint32_t>(stack.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));
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);
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;

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;
}
Expand All @@ -153,7 +195,7 @@ namespace gsc

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;
}
Expand All @@ -163,10 +205,17 @@ namespace gsc

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)
{
return name;
return script_name;
}

return std::to_string(id);
Expand Down Expand Up @@ -319,7 +368,7 @@ namespace gsc
? xsk::gsc::build::dev
: 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>>
{
const auto real_name = get_raw_script_file_name(include_name);
Expand Down Expand Up @@ -388,6 +437,17 @@ namespace gsc
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
{
public:
Expand Down
8 changes: 8 additions & 0 deletions src/client/component/gsc/script_loading.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,16 @@

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 game::dvar_t* developer_script;

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);
}

0 comments on commit d8cf3f5

Please sign in to comment.