diff options
Diffstat (limited to 'servers/rendering/shader_preprocessor.cpp')
-rw-r--r-- | servers/rendering/shader_preprocessor.cpp | 65 |
1 files changed, 55 insertions, 10 deletions
diff --git a/servers/rendering/shader_preprocessor.cpp b/servers/rendering/shader_preprocessor.cpp index 7af326f779..8d6ddf9121 100644 --- a/servers/rendering/shader_preprocessor.cpp +++ b/servers/rendering/shader_preprocessor.cpp @@ -420,11 +420,11 @@ void ShaderPreprocessor::process_define(Tokenizer *p_tokenizer) { return; } + Vector<String> args; if (p_tokenizer->peek() == '(') { // Macro has arguments. p_tokenizer->get_token(); - Vector<String> args; while (true) { String name = p_tokenizer->get_identifier(); if (name.is_empty()) { @@ -442,17 +442,24 @@ void ShaderPreprocessor::process_define(Tokenizer *p_tokenizer) { return; } } + } - Define *define = memnew(Define); + String body = tokens_to_string(p_tokenizer->advance('\n')).strip_edges(); + if (body.begins_with("##")) { + set_error(RTR("'##' must not appear at beginning of macro expansion."), line); + return; + } + if (body.ends_with("##")) { + set_error(RTR("'##' must not appear at end of macro expansion."), line); + return; + } + + Define *define = memnew(Define); + if (!args.is_empty()) { define->arguments = args; - define->body = tokens_to_string(p_tokenizer->advance('\n')).strip_edges(); - state->defines[label] = define; - } else { - // Simple substitution macro. - Define *define = memnew(Define); - define->body = tokens_to_string(p_tokenizer->advance('\n')).strip_edges(); - state->defines[label] = define; } + define->body = body; + state->defines[label] = define; } void ShaderPreprocessor::process_elif(Tokenizer *p_tokenizer) { @@ -1074,9 +1081,13 @@ bool ShaderPreprocessor::expand_macros_once(const String &p_line, int p_line_num } } + concatenate_macro_body(body); + result = result.substr(0, index) + " " + body + " " + result.substr(args_end + 1, result.length()); } else { - result = result.substr(0, index) + body + result.substr(index + key.length(), result.length() - (index + key.length())); + concatenate_macro_body(body); + + result = result.substr(0, index) + " " + body + " " + result.substr(index + key.length(), result.length() - (index + key.length())); } r_expanded = result; @@ -1115,6 +1126,40 @@ bool ShaderPreprocessor::find_match(const String &p_string, const String &p_valu return false; } +void ShaderPreprocessor::concatenate_macro_body(String &r_body) { + int index_start = r_body.find("##"); + while (index_start > -1) { + int index_end = index_start + 2; // First character after ##. + // The macro was checked during creation so this should never happen. + ERR_FAIL_INDEX(index_end, r_body.size()); + + // If there more than two # in a row, then it's not a concatenation. + bool is_concat = true; + while (index_end <= r_body.length() && r_body[index_end] == '#') { + index_end++; + is_concat = false; + } + if (!is_concat) { + index_start = r_body.find("##", index_end); + continue; + } + + // Skip whitespace after ##. + while (index_end < r_body.length() && is_char_space(r_body[index_end])) { + index_end++; + } + + // Skip whitespace before ##. + while (index_start >= 1 && is_char_space(r_body[index_start - 1])) { + index_start--; + } + + r_body = r_body.substr(0, index_start) + r_body.substr(index_end, r_body.length() - index_end); + + index_start = r_body.find("##", index_start); + } +} + String ShaderPreprocessor::next_directive(Tokenizer *p_tokenizer, const Vector<String> &p_directives) { const int line = p_tokenizer->get_line(); int nesting = 0; |