diff --git a/src/libslic3r/Config.hpp b/src/libslic3r/Config.hpp
index e6953739a..64fc69dd5 100644
--- a/src/libslic3r/Config.hpp
+++ b/src/libslic3r/Config.hpp
@@ -378,7 +378,7 @@ public:
     static double 			nil_value() { return std::numeric_limits<double>::quiet_NaN(); }
     // A scalar is nil, or all values of a vector are nil.
     bool 					is_nil() const override { for (auto v : this->values) if (! std::isnan(v)) return false; return true; }
-    bool 					is_nil(size_t idx) const override { return std::isnan(v->values[idx]); }
+    bool 					is_nil(size_t idx) const override { return std::isnan(this->values[idx]); }
 
     std::string serialize() const override
     {
@@ -524,7 +524,7 @@ public:
     static int	 			nil_value() { return std::numeric_limits<int>::max(); }
     // A scalar is nil, or all values of a vector are nil.
     bool 					is_nil() const override { for (auto v : this->values) if (v != nil_value()) return false; return true; }
-    bool 					is_nil(size_t idx) const override { return v->values[idx] == nil_value(); }
+    bool 					is_nil(size_t idx) const override { return this->values[idx] == nil_value(); }
 
     std::string serialize() const override
     {
@@ -633,6 +633,7 @@ public:
     ConfigOption*           clone() const override { return new ConfigOptionStrings(*this); }
     ConfigOptionStrings&    operator=(const ConfigOption *opt) { this->set(opt); return *this; }
     bool                    operator==(const ConfigOptionStrings &rhs) const { return this->values == rhs.values; }
+	bool					is_nil(size_t idx) const override { return false; }
 
     std::string serialize() const override
     {
@@ -847,6 +848,7 @@ public:
     ConfigOption*           clone() const override { return new ConfigOptionPoints(*this); }
     ConfigOptionPoints&     operator=(const ConfigOption *opt) { this->set(opt); return *this; }
     bool                    operator==(const ConfigOptionPoints &rhs) const { return this->values == rhs.values; }
+	bool					is_nil(size_t idx) const override { return false; }
 
     std::string serialize() const override
     {
@@ -994,7 +996,7 @@ public:
     static unsigned char	nil_value() { return std::numeric_limits<unsigned char>::max(); }
     // A scalar is nil, or all values of a vector are nil.
     bool 					is_nil() const override { for (auto v : this->values) if (v != nil_value()) return false; return true; }
-    bool 					is_nil(size_t idx) const override { return v->values[idx] == nil_value(); }
+    bool 					is_nil(size_t idx) const override { return this->values[idx] == nil_value(); }
 
     bool& get_at(size_t i) {
         assert(! this->values.empty());
diff --git a/src/libslic3r/PlaceholderParser.cpp b/src/libslic3r/PlaceholderParser.cpp
index 2bfe9b745..604afad20 100644
--- a/src/libslic3r/PlaceholderParser.cpp
+++ b/src/libslic3r/PlaceholderParser.cpp
@@ -62,7 +62,7 @@
 
 namespace Slic3r {
 
-PlaceholderParser::PlaceholderParser()
+PlaceholderParser::PlaceholderParser(const DynamicConfig *external_config) : m_external_config(external_config)
 {
     this->set("version", std::string(SLIC3R_VERSION));
     this->apply_env_variables();
@@ -608,6 +608,7 @@ namespace client
     }
 
     struct MyContext {
+    	const DynamicConfig     *external_config        = nullptr;
         const DynamicConfig     *config                 = nullptr;
         const DynamicConfig     *config_override        = nullptr;
         size_t                   current_extruder_id    = 0;
@@ -628,6 +629,8 @@ namespace client
                 opt = config_override->option(opt_key);
             if (opt == nullptr)
                 opt = config->option(opt_key);
+            if (opt == nullptr && external_config != nullptr)
+                opt = external_config->option(opt_key);
             return opt;
         }
 
@@ -1255,6 +1258,7 @@ static std::string process_macro(const std::string &templ, client::MyContext &co
 std::string PlaceholderParser::process(const std::string &templ, unsigned int current_extruder_id, const DynamicConfig *config_override) const
 {
     client::MyContext context;
+    context.external_config 	= this->external_config();
     context.config              = &this->config();
     context.config_override     = config_override;
     context.current_extruder_id = current_extruder_id;
@@ -1266,8 +1270,8 @@ std::string PlaceholderParser::process(const std::string &templ, unsigned int cu
 bool PlaceholderParser::evaluate_boolean_expression(const std::string &templ, const DynamicConfig &config, const DynamicConfig *config_override)
 {
     client::MyContext context;
-    context.config                  = &config;
-    context.config_override         = config_override;
+    context.config              = &config;
+    context.config_override     = config_override;
     // Let the macro processor parse just a boolean expression, not the full macro language.
     context.just_boolean_expression = true;
     return process_macro(templ, context) == "true";
diff --git a/src/libslic3r/PlaceholderParser.hpp b/src/libslic3r/PlaceholderParser.hpp
index 22c790e6b..f682c3252 100644
--- a/src/libslic3r/PlaceholderParser.hpp
+++ b/src/libslic3r/PlaceholderParser.hpp
@@ -12,7 +12,7 @@ namespace Slic3r {
 class PlaceholderParser
 {
 public:    
-    PlaceholderParser();
+    PlaceholderParser(const DynamicConfig *external_config = nullptr);
     
     // Return a list of keys, which should be changed in m_config from rhs.
     // This contains keys, which are found in rhs, but not in m_config.
@@ -35,6 +35,8 @@ public:
 	DynamicConfig&			config_writable()					{ return m_config; }
 	const DynamicConfig&    config() const                      { return m_config; }
     const ConfigOption*     option(const std::string &key) const { return m_config.option(key); }
+    // External config is not owned by PlaceholderParser. It has a lowest priority when looking up an option.
+	const DynamicConfig*	external_config() const  			{ return m_external_config; }
 
     // Fill in the template using a macro processing language.
     // Throws std::runtime_error on syntax or runtime error.
@@ -50,7 +52,9 @@ public:
     void update_timestamp() { update_timestamp(m_config); }
 
 private:
-    DynamicConfig m_config;
+	// config has a higher priority than external_config when looking up a symbol.
+    DynamicConfig 			 m_config;
+    const DynamicConfig 	*m_external_config;
 };
 
 }
diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp
index af2479e5a..ac2e4f151 100644
--- a/src/libslic3r/Print.cpp
+++ b/src/libslic3r/Print.cpp
@@ -545,9 +545,8 @@ Print::ApplyStatus Print::apply(const Model &model, const DynamicPrintConfig &co
             m_ranges.reserve(in.size());
             // Input ranges are sorted lexicographically. First range trims the other ranges.
             coordf_t last_z = 0;
-            for (const std::pair<const t_layer_height_range, DynamicPrintConfig> &range : in) {
-//            for (auto &range : in) {
-			if (range.first.second > last_z) {
+            for (const std::pair<const t_layer_height_range, DynamicPrintConfig> &range : in)
+				if (range.first.second > last_z) {
                     coordf_t min_z = std::max(range.first.first, 0.);
                     if (min_z > last_z + EPSILON) {
                         m_ranges.emplace_back(t_layer_height_range(last_z, min_z), nullptr);
@@ -559,7 +558,6 @@ Print::ApplyStatus Print::apply(const Model &model, const DynamicPrintConfig &co
                         last_z = range.first.second;
                     }
                 }
-            }
             if (m_ranges.empty())
                 m_ranges.emplace_back(t_layer_height_range(0, DBL_MAX), nullptr);
             else if (m_ranges.back().second == nullptr)