summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--crawl-ref/source/externs.h2
-rw-r--r--crawl-ref/source/initfile.cc64
2 files changed, 63 insertions, 3 deletions
diff --git a/crawl-ref/source/externs.h b/crawl-ref/source/externs.h
index 3277e74189..102e7f7fc3 100644
--- a/crawl-ref/source/externs.h
+++ b/crawl-ref/source/externs.h
@@ -1890,6 +1890,7 @@ public:
private:
typedef std::map<std::string, std::string> string_map;
string_map aliases;
+ string_map variables;
std::set<std::string> included; // Files we've included already.
public:
@@ -1905,6 +1906,7 @@ public:
private:
std::string unalias(const std::string &key) const;
+ std::string expand_vars(const std::string &field) const;
void add_alias(const std::string &alias, const std::string &name);
void clear_feature_overrides();
diff --git a/crawl-ref/source/initfile.cc b/crawl-ref/source/initfile.cc
index 5b414e5158..45c0c45df3 100644
--- a/crawl-ref/source/initfile.cc
+++ b/crawl-ref/source/initfile.cc
@@ -1523,15 +1523,72 @@ int game_options::read_explore_stop_conditions(const std::string &field) const
void game_options::add_alias(const std::string &key, const std::string &val)
{
- aliases[key] = val;
+ if (key[0] == '$')
+ variables[key.substr(1)] = val;
+ else
+ aliases[key] = val;
}
std::string game_options::unalias(const std::string &key) const
{
- std::map<std::string, std::string>::const_iterator i = aliases.find(key);
+ string_map::const_iterator i = aliases.find(key);
return (i == aliases.end()? key : i->second);
}
+#define IS_VAR_CHAR(c) (isalpha(c) || c == '_')
+
+std::string game_options::expand_vars(const std::string &field) const
+{
+ std::string field_out = field;
+
+ std::string::size_type curr_pos = 0;
+
+ // Only try 100 times, so as to not get stuck in infinite recursion.
+ for (int i = 0; i < 100; i++)
+ {
+ std::string::size_type dollar_pos = field_out.find("$", curr_pos);
+
+ if (dollar_pos == std::string::npos
+ || field_out.size() == (dollar_pos + 1))
+ {
+ break;
+ }
+
+ std::string::size_type start_pos = dollar_pos + 1;
+
+ if (!IS_VAR_CHAR(field_out[start_pos]))
+ continue;
+
+ std::string::size_type end_pos;
+ for (end_pos = start_pos; end_pos < field_out.size(); end_pos++)
+ {
+ if (!IS_VAR_CHAR(field_out[end_pos + 1]))
+ break;
+ }
+
+ std::string var_name = field_out.substr(start_pos,
+ end_pos - start_pos + 1);
+
+ string_map::const_iterator x = variables.find(var_name);
+
+ if (x == aliases.end())
+ {
+ curr_pos = end_pos + 1;
+ continue;
+ }
+
+ std::string dollar_plus_name = "$";
+ dollar_plus_name += var_name;
+
+ field_out = replace_all(field_out, dollar_plus_name, x->second);
+
+ // Start over at begining
+ curr_pos = 0;
+ }
+
+ return field_out;
+}
+
void game_options::add_message_colour_mappings(const std::string &field)
{
std::vector<std::string> fragments = split_string(",", field);
@@ -1688,7 +1745,8 @@ void game_options::read_option_line(const std::string &str, bool runscript)
if (first_equals < 0)
return;
- field = str.substr( first_equals + 1 );
+ field = str.substr( first_equals + 1 );
+ field = expand_vars(field);
std::string prequal = trimmed_string( str.substr(0, first_equals) );