dep/reshadefx: Add manual include callbacks
This commit is contained in:
parent
273979405d
commit
1a79a2f196
|
@ -29,15 +29,26 @@ namespace reshadefx
|
||||||
bool is_function_like = false;
|
bool is_function_like = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Callbacks for manual file reading.
|
||||||
|
using include_file_exists_callback = bool(*)(const std::string &path);
|
||||||
|
using include_read_file_callback = bool(*)(const std::string &path, std::string &data);
|
||||||
|
static bool stdfs_read_file_callback(const std::string &path, std::string& data);
|
||||||
|
static bool stdfs_file_exists_callback(const std::string &path);
|
||||||
|
|
||||||
// Define constructor explicitly because lexer class is not included here
|
// Define constructor explicitly because lexer class is not included here
|
||||||
preprocessor();
|
preprocessor();
|
||||||
~preprocessor();
|
~preprocessor();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets callbacks to use for reading files. If this is not called, std::filesystem will be used.
|
||||||
|
/// </summary>
|
||||||
|
void set_include_callbacks(include_file_exists_callback file_exists, include_read_file_callback read_file);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds an include directory to the list of search paths used when resolving #include directives.
|
/// Adds an include directory to the list of search paths used when resolving #include directives.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="path">Path to the directory to add.</param>
|
/// <param name="path">Path to the directory to add.</param>
|
||||||
void add_include_path(const std::filesystem::path &path);
|
void add_include_path(const std::string &path);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds a new macro definition. This is equal to appending '#define name macro' to this preprocessor instance.
|
/// Adds a new macro definition. This is equal to appending '#define name macro' to this preprocessor instance.
|
||||||
|
@ -62,14 +73,14 @@ namespace reshadefx
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="path">Path to the file to parse.</param>
|
/// <param name="path">Path to the file to parse.</param>
|
||||||
/// <returns><see langword="true"/> if parsing was successful, <see langword="false"/> otherwise.</returns>
|
/// <returns><see langword="true"/> if parsing was successful, <see langword="false"/> otherwise.</returns>
|
||||||
bool append_file(const std::filesystem::path &path);
|
bool append_file(const std::string &path);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Parses the specified string and appends it to the output.
|
/// Parses the specified string and appends it to the output.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="source_code">String to parse.</param>
|
/// <param name="source_code">String to parse.</param>
|
||||||
/// <param name="path">Optional file path to identify this string with.</param>
|
/// <param name="path">Optional file path to identify this string with.</param>
|
||||||
/// <returns><see langword="true"/> if parsing was successful, <see langword="false"/> otherwise.</returns>
|
/// <returns><see langword="true"/> if parsing was successful, <see langword="false"/> otherwise.</returns>
|
||||||
bool append_string(std::string source_code, const std::filesystem::path &path = std::filesystem::path());
|
bool append_string(std::string source_code, const std::string &path = std::string());
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the list of error messages.
|
/// Gets the list of error messages.
|
||||||
|
@ -144,6 +155,8 @@ namespace reshadefx
|
||||||
void create_macro_replacement_list(macro ¯o);
|
void create_macro_replacement_list(macro ¯o);
|
||||||
|
|
||||||
bool _success = true;
|
bool _success = true;
|
||||||
|
include_file_exists_callback _file_exists_cb;
|
||||||
|
include_read_file_callback _read_file_cb;
|
||||||
std::string _output, _errors;
|
std::string _output, _errors;
|
||||||
|
|
||||||
std::string _current_token_raw_data;
|
std::string _current_token_raw_data;
|
||||||
|
|
|
@ -61,27 +61,14 @@ static const int precedence_lookup[] = {
|
||||||
11, 11, 11, 11 // unary operators
|
11, 11, 11, 11 // unary operators
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool read_file(const std::filesystem::path &path, std::string &data)
|
static bool read_file(const std::string &path, std::string &data, reshadefx::preprocessor::include_read_file_callback &cb)
|
||||||
{
|
{
|
||||||
std::ifstream file(path, std::ios::binary);
|
std::string file_data;
|
||||||
if (!file)
|
if (!cb(path, file_data))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Read file contents into memory
|
|
||||||
std::error_code ec;
|
|
||||||
const uintmax_t file_size = std::filesystem::file_size(path, ec);
|
|
||||||
if (ec)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
std::string file_data(static_cast<size_t>(file_size + 1), '\0');
|
|
||||||
if (!file.read(file_data.data(), file_size))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// No longer need to have a handle open to the file, since all data was read, so can safely close it
|
|
||||||
file.close();
|
|
||||||
|
|
||||||
// Append a new line feed to the end of the input string to avoid issues with parsing
|
// Append a new line feed to the end of the input string to avoid issues with parsing
|
||||||
file_data.back() = '\n';
|
file_data.push_back('\n');
|
||||||
|
|
||||||
// Remove BOM (0xefbbbf means 0xfeff)
|
// Remove BOM (0xefbbbf means 0xfeff)
|
||||||
if (file_data.size() >= 3 &&
|
if (file_data.size() >= 3 &&
|
||||||
|
@ -94,6 +81,33 @@ static bool read_file(const std::filesystem::path &path, std::string &data)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool reshadefx::preprocessor::stdfs_read_file_callback(const std::string &path, std::string &data)
|
||||||
|
{
|
||||||
|
std::ifstream file(std::filesystem::path(path), std::ios::binary);
|
||||||
|
if (!file)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Read file contents into memory
|
||||||
|
std::error_code ec;
|
||||||
|
const uintmax_t file_size = std::filesystem::file_size(path, ec);
|
||||||
|
if (ec)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
data.reserve(file_size + 1);
|
||||||
|
data.resize(static_cast<size_t>(file_size), '\0');
|
||||||
|
if (!file.read(data.data(), file_size))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// No longer need to have a handle open to the file, since all data was read, so can safely close it
|
||||||
|
file.close();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool reshadefx::preprocessor::stdfs_file_exists_callback(const std::string &path)
|
||||||
|
{
|
||||||
|
return std::filesystem::exists(std::filesystem::path(path));
|
||||||
|
}
|
||||||
|
|
||||||
template <char ESCAPE_CHAR = '\\'>
|
template <char ESCAPE_CHAR = '\\'>
|
||||||
static std::string escape_string(std::string s)
|
static std::string escape_string(std::string s)
|
||||||
{
|
{
|
||||||
|
@ -103,16 +117,25 @@ static std::string escape_string(std::string s)
|
||||||
}
|
}
|
||||||
|
|
||||||
reshadefx::preprocessor::preprocessor()
|
reshadefx::preprocessor::preprocessor()
|
||||||
|
: _file_exists_cb(stdfs_file_exists_callback)
|
||||||
|
, _read_file_cb(stdfs_read_file_callback)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
reshadefx::preprocessor::~preprocessor()
|
reshadefx::preprocessor::~preprocessor()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void reshadefx::preprocessor::add_include_path(const std::filesystem::path &path)
|
void reshadefx::preprocessor::set_include_callbacks(include_file_exists_callback file_exists,
|
||||||
|
include_read_file_callback read_file)
|
||||||
|
{
|
||||||
|
_file_exists_cb = file_exists;
|
||||||
|
_read_file_cb = read_file;
|
||||||
|
}
|
||||||
|
|
||||||
|
void reshadefx::preprocessor::add_include_path(const std::string &path)
|
||||||
{
|
{
|
||||||
assert(!path.empty());
|
assert(!path.empty());
|
||||||
_include_paths.push_back(path);
|
_include_paths.push_back(std::filesystem::path(path));
|
||||||
}
|
}
|
||||||
bool reshadefx::preprocessor::add_macro_definition(const std::string &name, const macro ¯o)
|
bool reshadefx::preprocessor::add_macro_definition(const std::string &name, const macro ¯o)
|
||||||
{
|
{
|
||||||
|
@ -120,15 +143,15 @@ bool reshadefx::preprocessor::add_macro_definition(const std::string &name, cons
|
||||||
return _macros.emplace(name, macro).second;
|
return _macros.emplace(name, macro).second;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool reshadefx::preprocessor::append_file(const std::filesystem::path &path)
|
bool reshadefx::preprocessor::append_file(const std::string &path)
|
||||||
{
|
{
|
||||||
std::string source_code;
|
std::string source_code;
|
||||||
if (!read_file(path, source_code))
|
if (!read_file(path, source_code, _read_file_cb))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return append_string(std::move(source_code), path);
|
return append_string(std::move(source_code), path);
|
||||||
}
|
}
|
||||||
bool reshadefx::preprocessor::append_string(std::string source_code, const std::filesystem::path &path)
|
bool reshadefx::preprocessor::append_string(std::string source_code, const std::string &path /* = std::string() */)
|
||||||
{
|
{
|
||||||
// Enforce all input strings to end with a line feed
|
// Enforce all input strings to end with a line feed
|
||||||
assert(!source_code.empty() && source_code.back() == '\n');
|
assert(!source_code.empty() && source_code.back() == '\n');
|
||||||
|
@ -138,7 +161,7 @@ bool reshadefx::preprocessor::append_string(std::string source_code, const std::
|
||||||
// Give this push a name, so that lexer location starts at a new line
|
// Give this push a name, so that lexer location starts at a new line
|
||||||
// This is necessary in case this string starts with a preprocessor directive, since the lexer only reports those as such if they appear at the beginning of a new line
|
// This is necessary in case this string starts with a preprocessor directive, since the lexer only reports those as such if they appear at the beginning of a new line
|
||||||
// But without a name, the lexer location is set to the last token location, which most likely will not be at the start of the line
|
// But without a name, the lexer location is set to the last token location, which most likely will not be at the start of the line
|
||||||
push(std::move(source_code), path.empty() ? "unknown" : path.u8string());
|
push(std::move(source_code), path.empty() ? "unknown" : path);
|
||||||
parse();
|
parse();
|
||||||
|
|
||||||
return _success;
|
return _success;
|
||||||
|
@ -667,10 +690,9 @@ void reshadefx::preprocessor::parse_include()
|
||||||
std::filesystem::path file_path = std::filesystem::u8path(_output_location.source);
|
std::filesystem::path file_path = std::filesystem::u8path(_output_location.source);
|
||||||
file_path.replace_filename(file_name);
|
file_path.replace_filename(file_name);
|
||||||
|
|
||||||
std::error_code ec;
|
if (!_file_exists_cb(file_path.u8string()))
|
||||||
if (!std::filesystem::exists(file_path, ec))
|
|
||||||
for (const std::filesystem::path &include_path : _include_paths)
|
for (const std::filesystem::path &include_path : _include_paths)
|
||||||
if (std::filesystem::exists(file_path = include_path / file_name, ec))
|
if (_file_exists_cb((file_path = include_path / file_name).u8string()))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
const std::string file_path_string = file_path.u8string();
|
const std::string file_path_string = file_path.u8string();
|
||||||
|
@ -687,7 +709,7 @@ void reshadefx::preprocessor::parse_include()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!read_file(file_path, input))
|
if (!read_file(file_path_string, input, _read_file_cb))
|
||||||
return error(keyword_location, "could not open included file '" + file_name.u8string() + '\'');
|
return error(keyword_location, "could not open included file '" + file_name.u8string() + '\'');
|
||||||
|
|
||||||
_file_cache.emplace(file_path_string, input);
|
_file_cache.emplace(file_path_string, input);
|
||||||
|
@ -863,13 +885,12 @@ bool reshadefx::preprocessor::evaluate_expression()
|
||||||
if (has_parentheses && !expect(tokenid::parenthesis_close))
|
if (has_parentheses && !expect(tokenid::parenthesis_close))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
std::error_code ec;
|
if (!_file_exists_cb(file_path.u8string()))
|
||||||
if (!std::filesystem::exists(file_path, ec))
|
|
||||||
for (const std::filesystem::path &include_path : _include_paths)
|
for (const std::filesystem::path &include_path : _include_paths)
|
||||||
if (std::filesystem::exists(file_path = include_path / file_name, ec))
|
if (_file_exists_cb((file_path = include_path / file_name).u8string()))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
rpn[rpn_index++] = { std::filesystem::exists(file_path, ec) ? 1 : 0, false };
|
rpn[rpn_index++] = { _file_exists_cb(file_path.u8string()) ? 1 : 0, false };
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (_token.literal_as_string == "defined")
|
if (_token.literal_as_string == "defined")
|
||||||
|
|
|
@ -321,8 +321,8 @@ bool PostProcessing::ReShadeFXShader::CreateModule(s32 buffer_width, s32 buffer_
|
||||||
Error* error)
|
Error* error)
|
||||||
{
|
{
|
||||||
reshadefx::preprocessor pp;
|
reshadefx::preprocessor pp;
|
||||||
pp.add_include_path(std::filesystem::path(Path::GetDirectory(m_filename)));
|
pp.add_include_path(std::string(Path::GetDirectory(m_filename)));
|
||||||
pp.add_include_path(std::filesystem::path(Path::Combine(
|
pp.add_include_path(std::string(Path::Combine(
|
||||||
EmuFolders::Resources, "shaders" FS_OSPATH_SEPARATOR_STR "reshade" FS_OSPATH_SEPARATOR_STR "Shaders")));
|
EmuFolders::Resources, "shaders" FS_OSPATH_SEPARATOR_STR "reshade" FS_OSPATH_SEPARATOR_STR "Shaders")));
|
||||||
pp.add_macro_definition("__RESHADE__", "50901");
|
pp.add_macro_definition("__RESHADE__", "50901");
|
||||||
pp.add_macro_definition("BUFFER_WIDTH", std::to_string(buffer_width)); // TODO: can we make these uniforms?
|
pp.add_macro_definition("BUFFER_WIDTH", std::to_string(buffer_width)); // TODO: can we make these uniforms?
|
||||||
|
@ -350,7 +350,7 @@ bool PostProcessing::ReShadeFXShader::CreateModule(s32 buffer_width, s32 buffer_
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pp.append_file(std::filesystem::path(m_filename)))
|
if (!pp.append_file(m_filename))
|
||||||
{
|
{
|
||||||
Error::SetString(error, fmt::format("Failed to preprocess:\n{}", pp.errors()));
|
Error::SetString(error, fmt::format("Failed to preprocess:\n{}", pp.errors()));
|
||||||
return false;
|
return false;
|
||||||
|
|
Loading…
Reference in New Issue