]> granicus.if.org Git - icinga2/commitdiff
Fix incorrect variable scoping
authorGunnar Beutner <gunnar.beutner@netways.de>
Mon, 15 Dec 2014 11:57:40 +0000 (12:57 +0100)
committerGunnar Beutner <gunnar.beutner@netways.de>
Mon, 15 Dec 2014 11:58:55 +0000 (12:58 +0100)
refs #8074

lib/base/scriptglobal.cpp
lib/base/scriptglobal.hpp
lib/config/config_parser.yy
lib/config/expression.cpp
lib/config/expression.hpp
lib/config/vmops.hpp

index 9ffa689cdab05819726aba7fbaa2bd1a9418dd31..cf2b26914f0e5d41718302b172944282c115c265 100644 (file)
@@ -50,6 +50,11 @@ void ScriptGlobal::Set(const String& name, const Value& value)
        m_Globals->Set(name, value);
 }
 
+bool ScriptGlobal::Exists(const String& name)
+{
+       return m_Globals->Contains(name);
+}
+
 Dictionary::Ptr ScriptGlobal::GetGlobals(void)
 {
        return m_Globals;
index 2c2af1bfb23b17fd5a64b05560b3ca958edd8a89..abccf02da137518c66f6b7a47e15df75269a7ea4 100644 (file)
@@ -36,6 +36,7 @@ class I2_BASE_API ScriptGlobal
 public:
        static Value Get(const String& name, const Value *defaultValue = NULL);
        static void Set(const String& name, const Value& value);
+       static bool Exists(const String& name);
 
        static void WriteToFile(const String& filename);
 
index 2522bca5ef0bb201cec67ba7c480d3761c7bd63e..0c0534da47a72909bbdccc00e77fad9071682f86 100644 (file)
@@ -559,7 +559,6 @@ lterm: type
        | rterm combined_set_op rterm
        {
                Expression *expr = $1;
-               BindToScope(expr, ScopeCurrent);
                $$ = new SetExpression(expr, $2, $3, DebugInfoRange(@1, @3));
        }
        | T_INCLUDE T_STRING
@@ -787,7 +786,9 @@ rterm: T_STRING
        }
        | rterm_scope
        {
-               $$ = $1;
+               Expression *expr = $1;
+               BindToScope(expr, ScopeCurrent);
+               $$ = expr;
        }
        | '('
        {
index 2040641448c163e51a52620d66d152918855b35e..a2cc2b09f5e6cac5bc594646da4beadb8ec3bb86 100644 (file)
@@ -94,12 +94,37 @@ const DebugInfo& DebuggableExpression::GetDebugInfo(void) const
 
 Value VariableExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
 {
-       return VMOps::Variable(frame, m_Variable, m_DebugInfo);
+       if (frame.Locals && frame.Locals->Contains(m_Variable))
+               return frame.Locals->Get(m_Variable);
+       else if (frame.Self.IsObject() && frame.Locals != static_cast<Object::Ptr>(frame.Self) && VMOps::HasField(frame.Self, m_Variable))
+               return VMOps::GetField(frame.Self, m_Variable, m_DebugInfo);
+       else
+               return ScriptGlobal::Get(m_Variable);
 }
 
 bool VariableExpression::GetReference(ScriptFrame& frame, bool init_dict, Value *parent, String *index, DebugHint **dhint) const
 {
-       return false;
+       *index = m_Variable;
+
+       if (frame.Locals && frame.Locals->Contains(m_Variable)) {
+               *parent = frame.Locals;
+
+               if (dhint)
+                       *dhint = NULL;
+       } else if (frame.Self.IsObject() && frame.Locals != static_cast<Object::Ptr>(frame.Self) && VMOps::HasField(frame.Self, m_Variable)) {
+               *parent = frame.Self;
+
+               if (dhint && *dhint)
+                       *dhint = new DebugHint((*dhint)->GetChild(m_Variable));
+       } else if (ScriptGlobal::Exists(m_Variable)) {
+               *parent = ScriptGlobal::GetGlobals();
+
+               if (dhint)
+                       *dhint = NULL;
+       } else
+               *parent = frame.Locals;
+
+       return true;
 }
 
 Value NegateExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
@@ -410,6 +435,23 @@ bool IndexerExpression::GetReference(ScriptFrame& frame, bool init_dict, Value *
 
 void icinga::BindToScope(Expression *& expr, ScopeSpecifier scopeSpec)
 {
+       DictExpression *dexpr = dynamic_cast<DictExpression *>(expr);
+
+       if (dexpr) {
+               BOOST_FOREACH(Expression *& expr, dexpr->m_Expressions)
+                       BindToScope(expr, scopeSpec);
+
+               return;
+       }
+
+       SetExpression *aexpr = dynamic_cast<SetExpression *>(expr);
+
+       if (aexpr) {
+               BindToScope(aexpr->m_Operand1, scopeSpec);
+
+               return;
+       }
+
        IndexerExpression *iexpr = dynamic_cast<IndexerExpression *>(expr);
 
        if (iexpr) {
index a450829cc340bb3ea5778c5dc5d9a38f9fe51fa3..7165658b14bac30f3b53d7c231ed9f26358bb449 100644 (file)
@@ -280,7 +280,7 @@ protected:
 private:
        String m_Variable;
 
-       friend void BindToScope(Expression *& expr, ScopeSpecifier scopeSpec);
+       friend I2_CONFIG_API void BindToScope(Expression *& expr, ScopeSpecifier scopeSpec);
 };
        
 class I2_CONFIG_API NegateExpression : public UnaryExpression
@@ -589,6 +589,8 @@ protected:
 private:
        std::vector<Expression *> m_Expressions;
        bool m_Inline;
+
+       friend I2_CONFIG_API void BindToScope(Expression *& expr, ScopeSpecifier scopeSpec);
 };
        
 class I2_CONFIG_API SetExpression : public BinaryExpression
@@ -603,6 +605,8 @@ protected:
 
 private:
        CombinedSetOp m_Op;
+
+       friend I2_CONFIG_API void BindToScope(Expression *& expr, ScopeSpecifier scopeSpec);
 };
 
 class I2_CONFIG_API ConditionalExpression : public DebuggableExpression
@@ -664,7 +668,7 @@ protected:
        virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
        virtual bool GetReference(ScriptFrame& frame, bool init_dict, Value *parent, String *index, DebugHint **dhint) const;
 
-       friend void BindToScope(Expression *& expr, ScopeSpecifier scopeSpec);
+       friend I2_CONFIG_API void BindToScope(Expression *& expr, ScopeSpecifier scopeSpec);
 };
 
 I2_CONFIG_API void BindToScope(Expression *& expr, ScopeSpecifier scopeSpec);
index 3ad9ece008195a5502333dd06e5424c7752fa583..be035d6491f5b288586d28ee3e513aa008dbbeb4 100644 (file)
@@ -46,9 +46,6 @@ class VMOps
 public:
        static inline Value Variable(ScriptFrame& frame, const String& name, const DebugInfo& debugInfo = DebugInfo())
        {
-               if (name == "this")
-                       return frame.Self;
-
                if (frame.Locals && frame.Locals->Contains(name))
                        return frame.Locals->Get(name);
                else if (frame.Self.IsObject() && frame.Locals != static_cast<Object::Ptr>(frame.Self) && HasField(frame.Self, name))