From 0c9bc4b2d47ff44891b6d9142a1fe57eec3c6eda Mon Sep 17 00:00:00 2001 From: Celtic Minstrel Date: Sat, 10 Feb 2018 20:08:01 -0500 Subject: [PATCH] Implement crude dynamic linking of the formula evaluation function --- src/formula/formula.cpp | 29 +++++++++++++++++++++++++++++ src/formula/string_utils.cpp | 25 ++++++++++--------------- src/formula/string_utils.hpp | 4 ++++ 3 files changed, 43 insertions(+), 15 deletions(-) diff --git a/src/formula/formula.cpp b/src/formula/formula.cpp index 8a14acd6519c8..a278ebcddd9aa 100644 --- a/src/formula/formula.cpp +++ b/src/formula/formula.cpp @@ -16,13 +16,42 @@ #include "formula/callable.hpp" #include "formula/function.hpp" +#include "formula/string_utils.hpp" #include "random.hpp" #include "serialization/string_utils.hpp" +#include "log.hpp" #include #include #include +// This is here only for the below initialization code. +// If other logging is required in this file, it should use a different logdomain +// (probably "scripting/wfl" or something) +static lg::log_domain log_engine("engine"); +#define ERR_NG LOG_STREAM(err, log_engine) + +namespace utils { + namespace detail { + std::string evaluate_formula_impl(const std::string& formula) { + try { + const wfl::formula form(formula); + return form.evaluate().string_cast(); + } catch(wfl::formula_error& e) { + ERR_NG << "Formula in WML string cannot be evaluated due to " + << e.type << "\n\t--> \""; + return ""; + } + } + + struct formula_initer { + formula_initer() { + evaluate_formula = &evaluate_formula_impl; + } + } init; + } +} + namespace wfl { using expr_table = std::map; diff --git a/src/formula/string_utils.cpp b/src/formula/string_utils.cpp index 26573eea77f3f..51e458f685f00 100644 --- a/src/formula/string_utils.cpp +++ b/src/formula/string_utils.cpp @@ -19,7 +19,6 @@ #include "config.hpp" #include "log.hpp" -//#include "formula/formula.hpp" #include "gettext.hpp" static lg::log_domain log_engine("engine"); @@ -30,6 +29,10 @@ static bool two_dots(char a, char b) { return a == '.' && b == '.'; } namespace utils { + namespace detail { + std::string(* evaluate_formula)(const std::string& formula) = nullptr; + } + template class string_map_variable_set : public variable_set { @@ -110,7 +113,11 @@ static std::string do_interpolation(const std::string &str, const variable_set& // TODO: support escape sequences when/if they are allowed in FormulaAI strings } } while(++var_end != res.end() && paren_nesting_level > 0); -#ifdef WESNOTH_GAME + if(utils::detail::evaluate_formula == nullptr) { + WRN_NG << "Formula substitution ignored (and removed) because WFL engine is not present in the server.\n"; + res.replace(var_begin, var_end, ""); + continue; + } if(paren_nesting_level > 0) { ERR_NG << "Formula in WML string cannot be evaluated due to " << "a missing closing parenthesis:\n\t--> \"" @@ -118,19 +125,7 @@ static std::string do_interpolation(const std::string &str, const variable_set& res.replace(var_begin, var_end, ""); continue; } - try { - const wfl::formula form(std::string(var_begin+2, var_end-1)); - res.replace(var_begin, var_end, form.evaluate().string_cast()); - } catch(wfl::formula_error& e) { - ERR_NG << "Formula in WML string cannot be evaluated due to " - << e.type << "\n\t--> \"" - << e.formula << "\"\n"; - res.replace(var_begin, var_end, ""); - } -#else - WRN_NG << "Formula substitution ignored (and removed) because WFL engine is not present in the server.\n"; - res.replace(var_begin, var_end, ""); -#endif + res.replace(var_begin, var_end, utils::detail::evaluate_formula(std::string(var_begin+2, var_end-1))); continue; } diff --git a/src/formula/string_utils.hpp b/src/formula/string_utils.hpp index 2224acc6336bb..d920de4f878bb 100644 --- a/src/formula/string_utils.hpp +++ b/src/formula/string_utils.hpp @@ -21,6 +21,10 @@ class variable_set; namespace utils { + namespace detail { + extern std::string(* evaluate_formula)(const std::string& formula); + } + /** * Determines if a string might contain variables to interpolate. * This can allow one to skip future interpolations (plural -- if there is only