]> granicus.if.org Git - icinga2/blobdiff - lib/config/expression.cpp
Merge pull request #6999 from Icinga/bugfix/compiler-warnings
[icinga2] / lib / config / expression.cpp
index f355509e5497cd71150ec41df4b561db2c683442..814a153047881c606298f160df2456fa1a89c3bc 100644 (file)
@@ -1,21 +1,4 @@
-/******************************************************************************
- * Icinga 2                                                                   *
- * Copyright (C) 2012-2018 Icinga Development Team (https://www.icinga.com/)  *
- *                                                                            *
- * This program is free software; you can redistribute it and/or              *
- * modify it under the terms of the GNU General Public License                *
- * as published by the Free Software Foundation; either version 2             *
- * of the License, or (at your option) any later version.                     *
- *                                                                            *
- * This program is distributed in the hope that it will be useful,            *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of             *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              *
- * GNU General Public License for more details.                               *
- *                                                                            *
- * You should have received a copy of the GNU General Public License          *
- * along with this program; if not, write to the Free Software Foundation     *
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.             *
- ******************************************************************************/
+/* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */
 
 #include "config/expression.hpp"
 #include "config/configitem.hpp"
@@ -28,6 +11,8 @@
 #include "base/exception.hpp"
 #include "base/scriptglobal.hpp"
 #include "base/loader.hpp"
+#include "base/reference.hpp"
+#include "base/namespace.hpp"
 #include <boost/exception_ptr.hpp>
 #include <boost/exception/errinfo_nested_exception.hpp>
 
@@ -115,6 +100,15 @@ const DebugInfo& DebuggableExpression::GetDebugInfo() const
        return m_DebugInfo;
 }
 
+VariableExpression::VariableExpression(String variable, std::vector<std::shared_ptr<Expression> > imports, const DebugInfo& debugInfo)
+       : DebuggableExpression(debugInfo), m_Variable(std::move(variable)), m_Imports(std::move(imports))
+{
+       m_Imports.push_back(MakeIndexer(ScopeGlobal, "System"));
+       m_Imports.push_back(std::unique_ptr<Expression>(new IndexerExpression(MakeIndexer(ScopeGlobal, "System"), MakeLiteral("Configuration"))));
+       m_Imports.push_back(MakeIndexer(ScopeGlobal, "Types"));
+       m_Imports.push_back(MakeIndexer(ScopeGlobal, "Icinga"));
+}
+
 ExpressionResult VariableExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
 {
        Value value;
@@ -123,7 +117,7 @@ ExpressionResult VariableExpression::DoEvaluate(ScriptFrame& frame, DebugHint *d
                return value;
        else if (frame.Self.IsObject() && frame.Locals != frame.Self.Get<Object::Ptr>() && frame.Self.Get<Object::Ptr>()->GetOwnField(m_Variable, &value))
                return value;
-       else if (VMOps::FindVarImport(frame, m_Variable, &value, m_DebugInfo))
+       else if (VMOps::FindVarImport(frame, m_Imports, m_Variable, &value, m_DebugInfo))
                return value;
        else
                return ScriptGlobal::Get(m_Variable);
@@ -143,7 +137,7 @@ bool VariableExpression::GetReference(ScriptFrame& frame, bool init_dict, Value
 
                if (dhint && *dhint)
                        *dhint = new DebugHint((*dhint)->GetChild(m_Variable));
-       } else if (VMOps::FindVarImportRef(frame, m_Variable, parent, m_DebugInfo)) {
+       } else if (VMOps::FindVarImportRef(frame, m_Imports, m_Variable, parent, m_DebugInfo)) {
                return true;
        } else if (ScriptGlobal::Exists(m_Variable)) {
                *parent = ScriptGlobal::GetGlobals();
@@ -156,6 +150,47 @@ bool VariableExpression::GetReference(ScriptFrame& frame, bool init_dict, Value
        return true;
 }
 
+ExpressionResult RefExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
+{
+       Value parent;
+       String index;
+
+       if (!m_Operand->GetReference(frame, false, &parent, &index, &dhint))
+               BOOST_THROW_EXCEPTION(ScriptError("Cannot obtain reference for expression.", m_DebugInfo));
+
+       if (!parent.IsObject())
+               BOOST_THROW_EXCEPTION(ScriptError("Cannot obtain reference for expression because parent is not an object.", m_DebugInfo));
+
+       return new Reference(parent, index);
+}
+
+ExpressionResult DerefExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
+{
+       ExpressionResult operand = m_Operand->Evaluate(frame);
+       CHECK_RESULT(operand);
+
+       Object::Ptr obj = operand.GetValue();
+       Reference::Ptr ref = dynamic_pointer_cast<Reference>(obj);
+
+       if (!ref)
+               BOOST_THROW_EXCEPTION(ScriptError("Invalid reference specified.", GetDebugInfo()));
+
+       return ref->Get();
+}
+
+bool DerefExpression::GetReference(ScriptFrame& frame, bool init_dict, Value *parent, String *index, DebugHint **dhint) const
+{
+       ExpressionResult operand = m_Operand->Evaluate(frame);
+       if (operand.GetCode() != ResultOK)
+               return false;
+
+       Reference::Ptr ref = operand.GetValue();
+
+       *parent = ref->GetParent();
+       *index = ref->GetIndex();
+       return true;
+}
+
 ExpressionResult NegateExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
 {
        ExpressionResult operand = m_Operand->Evaluate(frame);
@@ -461,17 +496,17 @@ ExpressionResult FunctionCallExpression::DoEvaluate(ScriptFrame& frame, DebugHin
 
 ExpressionResult ArrayExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
 {
-       Array::Ptr result = new Array();
-       result->Reserve(m_Expressions.size());
+       ArrayData result;
+       result.reserve(m_Expressions.size());
 
        for (const auto& aexpr : m_Expressions) {
                ExpressionResult element = aexpr->Evaluate(frame);
                CHECK_RESULT(element);
 
-               result->Add(element.GetValue());
+               result.push_back(element.GetValue());
        }
 
-       return result;
+       return new Array(std::move(result));
 }
 
 ExpressionResult DictExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
@@ -566,7 +601,7 @@ ExpressionResult SetExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint)
                }
        }
 
-       VMOps::SetField(parent, index, operand2.GetValue(), m_DebugInfo);
+       VMOps::SetField(parent, index, operand2.GetValue(), m_OverrideFrozen, m_DebugInfo);
 
        if (psdhint) {
                psdhint->AddMessage("=", m_DebugInfo);
@@ -578,6 +613,33 @@ ExpressionResult SetExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint)
        return Empty;
 }
 
+void SetExpression::SetOverrideFrozen()
+{
+       m_OverrideFrozen = true;
+}
+
+ExpressionResult SetConstExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
+{
+       auto globals = ScriptGlobal::GetGlobals();
+
+       auto attr = globals->GetAttribute(m_Name);
+
+       if (dynamic_pointer_cast<ConstEmbeddedNamespaceValue>(attr)) {
+               std::ostringstream msgbuf;
+               msgbuf << "Value for constant '" << m_Name << "' was modified. This behaviour is deprecated.\n";
+               ShowCodeLocation(msgbuf, GetDebugInfo(), false);
+               Log(LogWarning, msgbuf.str());
+       }
+
+       ExpressionResult operandres = m_Operand->Evaluate(frame);
+       CHECK_RESULT(operandres);
+       Value operand = operandres.GetValue();
+
+       globals->SetAttribute(m_Name, std::make_shared<ConstEmbeddedNamespaceValue>(operand));
+
+       return Empty;
+}
+
 ExpressionResult ConditionalExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
 {
        ExpressionResult condition = m_Condition->Evaluate(frame, dhint);
@@ -654,10 +716,19 @@ bool IndexerExpression::GetReference(ScriptFrame& frame, bool init_dict, Value *
 
        if (m_Operand1->GetReference(frame, init_dict, &vparent, &vindex, &psdhint)) {
                if (init_dict) {
-                       Value old_value =  VMOps::GetField(vparent, vindex, frame.Sandboxed, m_Operand1->GetDebugInfo());
+                       Value old_value;
+                       bool has_field = true;
+
+                       if (vparent.IsObject()) {
+                               Object::Ptr oparent = vparent;
+                               has_field = oparent->HasOwnField(vindex);
+                       }
+
+                       if (has_field)
+                               old_value = VMOps::GetField(vparent, vindex, frame.Sandboxed, m_Operand1->GetDebugInfo());
 
                        if (old_value.IsEmpty() && !old_value.IsString())
-                               VMOps::SetField(vparent, vindex, new Dictionary(), m_Operand1->GetDebugInfo());
+                               VMOps::SetField(vparent, vindex, new Dictionary(), m_OverrideFrozen, m_Operand1->GetDebugInfo());
                }
 
                *parent = VMOps::GetField(vparent, vindex, frame.Sandboxed, m_DebugInfo);
@@ -683,6 +754,11 @@ bool IndexerExpression::GetReference(ScriptFrame& frame, bool init_dict, Value *
        return true;
 }
 
+void IndexerExpression::SetOverrideFrozen()
+{
+       m_OverrideFrozen = true;
+}
+
 void icinga::BindToScope(std::unique_ptr<Expression>& expr, ScopeSpecifier scopeSpec)
 {
        auto *dexpr = dynamic_cast<DictExpression *>(expr.get());
@@ -799,6 +875,17 @@ ExpressionResult ApplyExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhin
                m_Package, m_FKVar, m_FVVar, m_FTerm, m_ClosedVars, m_IgnoreOnError, m_Expression, m_DebugInfo);
 }
 
+ExpressionResult NamespaceExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
+{
+       Namespace::Ptr ns = new Namespace(new ConstNamespaceBehavior());
+
+       ScriptFrame innerFrame(true, ns);
+       ExpressionResult result = m_Expression->Evaluate(innerFrame);
+       CHECK_RESULT(result);
+
+       return ns;
+}
+
 ExpressionResult ObjectExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
 {
        if (frame.Sandboxed)
@@ -922,23 +1009,6 @@ ExpressionResult BreakpointExpression::DoEvaluate(ScriptFrame& frame, DebugHint
        return Empty;
 }
 
-ExpressionResult UsingExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
-{
-       if (frame.Sandboxed)
-               BOOST_THROW_EXCEPTION(ScriptError("Using directives are not allowed in sandbox mode.", m_DebugInfo));
-
-       ExpressionResult importres = m_Name->Evaluate(frame);
-       CHECK_RESULT(importres);
-       Value import = importres.GetValue();
-
-       if (!import.IsObjectType<Dictionary>())
-               BOOST_THROW_EXCEPTION(ScriptError("The parameter must resolve to an object of type 'Dictionary'", m_DebugInfo));
-
-       ScriptFrame::AddImport(import);
-
-       return Empty;
-}
-
 ExpressionResult TryExceptExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
 {
        try {