]> granicus.if.org Git - icinga2/commitdiff
Implement support for arbitrarily complex indexers
authorGunnar Beutner <gunnar.beutner@netways.de>
Tue, 4 Nov 2014 14:19:33 +0000 (15:19 +0100)
committerGunnar Beutner <gunnar.beutner@netways.de>
Tue, 4 Nov 2014 14:20:33 +0000 (15:20 +0100)
fixes #7566

lib/base/array.cpp
lib/base/array.hpp
lib/config/config_lexer.ll
lib/config/config_parser.yy
lib/config/configitembuilder.cpp
lib/config/expression.cpp
lib/config/expression.hpp
lib/icinga/dependency-apply.cpp
lib/icinga/notification-apply.cpp
lib/icinga/scheduleddowntime-apply.cpp
lib/icinga/service-apply.cpp

index 3a6f4ccde1c3360f8c3eebad2c561390e85cec56..04760fa6be7e73f92fcfb9b7ed685ec5f7357619 100644 (file)
@@ -200,3 +200,37 @@ Array::Ptr Array::ShallowClone(void) const
        CopyTo(clone);
        return clone;
 }
+
+Array::Ptr icinga::MakeArray(const Value& val1)
+{
+       Array::Ptr result = make_shared<Array>();
+       result->Add(val1);
+       return result;
+}
+
+Array::Ptr icinga::MakeArray(const Value& val1, const Value& val2)
+{
+       Array::Ptr result = make_shared<Array>();
+       result->Add(val1);
+       result->Add(val2);
+       return result;
+}
+
+Array::Ptr icinga::MakeArray(const Value& val1, const Value& val2, const Value& val3)
+{
+       Array::Ptr result = make_shared<Array>();
+       result->Add(val1);
+       result->Add(val2);
+       result->Add(val3);
+       return result;
+}
+
+Array::Ptr icinga::MakeArray(const Value& val1, const Value& val2, const Value& val3, const Value& val4)
+{
+       Array::Ptr result = make_shared<Array>();
+       result->Add(val1);
+       result->Add(val2);
+       result->Add(val3);
+       result->Add(val4);
+       return result;
+}
index 6ac24d1edbeda8dcb72f6668069ea43bd971f328..7459348ab0ac3c3527ba3a79e96ed054e441b7e9 100644 (file)
@@ -79,6 +79,11 @@ inline Array::Iterator range_end(Array::Ptr x)
        return x->End();
 }
 
+I2_BASE_API Array::Ptr MakeArray(const Value& val1);
+I2_BASE_API Array::Ptr MakeArray(const Value& val1, const Value& val2);
+I2_BASE_API Array::Ptr MakeArray(const Value& val1, const Value& val2, const Value& val3);
+I2_BASE_API Array::Ptr MakeArray(const Value& val1, const Value& val2, const Value& val3, const Value& val4);
+
 }
 
 namespace boost
index 42868e71b6a918a4dee67ef4b2d0621e972df0fd..23b46deeb9b6c267982f92c58adb499e470df28c 100644 (file)
@@ -252,11 +252,11 @@ in                                { yylval->op = &Expression::OpIn; return T_IN; }
 -?[0-9]+(\.[0-9]+)?m           { yylval->num = strtod(yytext, NULL) * 60; return T_NUMBER; }
 -?[0-9]+(\.[0-9]+)?s           { yylval->num = strtod(yytext, NULL); return T_NUMBER; }
 -?[0-9]+(\.[0-9]+)?            { yylval->num = strtod(yytext, NULL); return T_NUMBER; }
-=                              { yylval->op = &Expression::OpSet; return T_SET; }
-\+=                            { yylval->op = &Expression::OpSetPlus; return T_SET_PLUS; }
--=                             { yylval->op = &Expression::OpSetMinus; return T_SET_MINUS; }
-\*=                            { yylval->op = &Expression::OpSetMultiply; return T_SET_MULTIPLY; }
-\/=                            { yylval->op = &Expression::OpSetDivide; return T_SET_DIVIDE; }
+=                              { yylval->csop = OpSetLiteral; return T_SET; }
+\+=                            { yylval->csop = OpSetAdd; return T_SET_ADD; }
+-=                             { yylval->csop = OpSetSubtract; return T_SET_SUBTRACT; }
+\*=                            { yylval->csop = OpSetMultiply; return T_SET_MULTIPLY; }
+\/=                            { yylval->csop = OpSetDivide; return T_SET_DIVIDE; }
 \+                             { yylval->op = &Expression::OpAdd; return T_PLUS; }
 \-                             { yylval->op = &Expression::OpSubtract; return T_MINUS; }
 \*                             { yylval->op = &Expression::OpMultiply; return T_MULTIPLY; }
index 5f7bff67a766a8d53712561ae542492e2b130c56..ed4f03315c8b842e46da267d916619da2820e440 100644 (file)
@@ -96,6 +96,7 @@ static void MakeRBinaryOp(Value** result, Expression::OpCallback& op, Value *lef
        double num;
        icinga::Value *variant;
        icinga::Expression::OpCallback op;
+       CombinedSetOp csop;
        icinga::TypeSpecifier type;
        std::vector<String> *slist;
        Array *array;
@@ -108,11 +109,11 @@ static void MakeRBinaryOp(Value** result, Expression::OpCallback& op, Value *lef
 %token T_NULL
 %token <text> T_IDENTIFIER
 
-%token <op> T_SET "= (T_SET)"
-%token <op> T_SET_PLUS "+= (T_SET_PLUS)"
-%token <op> T_SET_MINUS "-= (T_SET_MINUS)"
-%token <op> T_SET_MULTIPLY "*= (T_SET_MULTIPLY)"
-%token <op> T_SET_DIVIDE "/= (T_SET_DIVIDE)"
+%token <csop> T_SET "= (T_SET)"
+%token <csop> T_SET_ADD "+= (T_SET_ADD)"
+%token <csop> T_SET_SUBTRACT "-= (T_SET_SUBTRACT)"
+%token <csop> T_SET_MULTIPLY "*= (T_SET_MULTIPLY)"
+%token <csop> T_SET_DIVIDE "/= (T_SET_DIVIDE)"
 
 %token <op> T_SHIFT_LEFT "<< (T_SHIFT_LEFT)"
 %token <op> T_SHIFT_RIGHT ">> (T_SHIFT_RIGHT)"
@@ -168,10 +169,13 @@ static void MakeRBinaryOp(Value** result, Expression::OpCallback& op, Value *lef
 %type <array> rterm_items_inner
 %type <array> identifier_items
 %type <array> identifier_items_inner
+%type <array> indexer
+%type <array> indexer_items
+%type <variant> indexer_item
 %type <array> lterm_items
 %type <array> lterm_items_inner
 %type <variant> typerulelist
-%type <op> lbinary_op
+%type <csop> combined_set_op
 %type <type> type
 %type <variant> rterm
 %type <variant> rterm_array
@@ -436,8 +440,8 @@ object:
                m_Abstract.push(false);
                m_ObjectAssign.push(true);
                m_SeenAssign.push(false);
-               m_Assign.push(make_shared<Expression>(&Expression::OpLiteral, false, DebugInfo()));
-               m_Ignore.push(make_shared<Expression>(&Expression::OpLiteral, false, DebugInfo()));
+               m_Assign.push(MakeLiteral(false));
+               m_Ignore.push(MakeLiteral(false));
        }
        object_declaration identifier rterm rterm_scope
        {
@@ -516,9 +520,47 @@ identifier_items_inner: /* empty */
        }
        ;
 
-lbinary_op: T_SET
-       | T_SET_PLUS
-       | T_SET_MINUS
+indexer: T_IDENTIFIER
+       {
+               $$ = new Array();
+               $$->Add(MakeLiteral($1));
+               free($1);
+       }
+       | T_IDENTIFIER indexer_items
+       {
+               $$ = $2;
+               $$->Insert(0, MakeLiteral($1));
+       }
+       ;
+
+indexer_items: indexer_item
+       {
+               $$ = new Array();
+               $$->Add(*$1);
+               delete $1;
+       }
+       | indexer_items indexer_item
+       {
+               $$ = $1;
+               $$->Add(*$2);
+               delete $2;
+       }
+       ;
+
+indexer_item: '.' T_IDENTIFIER
+       {
+               $$ = new Value(MakeLiteral($2));
+               free($2);
+       }
+       | '[' rterm ']'
+       {
+               $$ = $2;
+       }
+       ;
+
+combined_set_op: T_SET
+       | T_SET_ADD
+       | T_SET_SUBTRACT
        | T_SET_MULTIPLY
        | T_SET_DIVIDE
        {
@@ -557,44 +599,10 @@ lterm_items_inner: lterm
        }
        ;
 
-lterm: identifier lbinary_op rterm
-       {
-               Expression::Ptr aindex = make_shared<Expression>(&Expression::OpLiteral, $1, @1);
-               free($1);
-
-               $$ = new Value(make_shared<Expression>($2, aindex, *$3, DebugInfoRange(@1, @3)));
-               delete $3;
-       }
-       | identifier '[' rterm ']' lbinary_op rterm
+lterm: indexer combined_set_op rterm
        {
-               Expression::Ptr subexpr = make_shared<Expression>($5, *$3, *$6, DebugInfoRange(@1, @6));
+               $$ = new Value(make_shared<Expression>(&Expression::OpSet, MakeArray(Array::Ptr($1), $2), *$3, DebugInfoRange(@1, @3)));
                delete $3;
-               delete $6;
-
-               Array::Ptr subexprl = make_shared<Array>();
-               subexprl->Add(subexpr);
-               
-               Expression::Ptr aindex = make_shared<Expression>(&Expression::OpLiteral, $1, @1);
-               free($1);
-
-               Expression::Ptr expr = make_shared<Expression>(&Expression::OpDict, subexprl, DebugInfoRange(@1, @6));
-               $$ = new Value(make_shared<Expression>(&Expression::OpSetPlus, aindex, expr, DebugInfoRange(@1, @6)));
-       }
-       | identifier '.' T_IDENTIFIER lbinary_op rterm
-       {
-               Expression::Ptr aindex = make_shared<Expression>(&Expression::OpLiteral, $3, @3);
-               Expression::Ptr subexpr = make_shared<Expression>($4, aindex, *$5, DebugInfoRange(@1, @5));
-               free($3);
-               delete $5;
-
-               Array::Ptr subexprl = make_shared<Array>();
-               subexprl->Add(subexpr);
-
-               Expression::Ptr aindexl = make_shared<Expression>(&Expression::OpLiteral, $1, @1);
-               free($1);
-
-               Expression::Ptr expr = make_shared<Expression>(&Expression::OpDict, subexprl, DebugInfoRange(@1, @5));
-               $$ = new Value(make_shared<Expression>(&Expression::OpSetPlus, aindexl, expr, DebugInfoRange(@1, @5)));
        }
        | T_IMPORT rterm
        {
@@ -612,7 +620,7 @@ lterm: identifier lbinary_op rterm
                m_Assign.top() = make_shared<Expression>(&Expression::OpLogicalOr, m_Assign.top(), *$3, DebugInfoRange(@1, @3));
                delete $3;
 
-               $$ = new Value(make_shared<Expression>(&Expression::OpLiteral, Empty, DebugInfoRange(@1, @3)));
+               $$ = new Value(MakeLiteral());
        }
        | T_IGNORE T_WHERE rterm
        {
@@ -622,12 +630,12 @@ lterm: identifier lbinary_op rterm
                m_Ignore.top() = make_shared<Expression>(&Expression::OpLogicalOr, m_Ignore.top(), *$3, DebugInfoRange(@1, @3));
                delete $3;
 
-               $$ = new Value(make_shared<Expression>(&Expression::OpLiteral, Empty, DebugInfoRange(@1, @3)));
+               $$ = new Value(MakeLiteral());
        }
        | T_RETURN rterm
        {
-               Expression::Ptr aname = make_shared<Expression>(&Expression::OpLiteral, "__result", @1);
-               $$ = new Value(make_shared<Expression>(&Expression::OpSet, aname, *$2, DebugInfoRange(@1, @2)));
+               Expression::Ptr aname = MakeLiteral("__result");
+               $$ = new Value(make_shared<Expression>(&Expression::OpSet, MakeArray(MakeArray(MakeLiteral(aname)), OpSetLiteral), *$2, DebugInfoRange(@1, @2)));
                delete $2;
 
        }
@@ -711,27 +719,26 @@ rterm_scope: '{' newlines lterm_items newlines '}'
 
 rterm: T_STRING
        {
-               $$ = new Value(make_shared<Expression>(&Expression::OpLiteral, $1, @1));
+               $$ = new Value(MakeLiteral($1));
                free($1);
        }
        | T_NUMBER
        {
-               $$ = new Value(make_shared<Expression>(&Expression::OpLiteral, $1, @1));
+               $$ = new Value(MakeLiteral($1));
        }
        | T_NULL
        {
-               $$ = new Value(make_shared<Expression>(&Expression::OpLiteral, Empty, @1));
+               $$ = new Value(MakeLiteral());
        }
        | rterm '.' T_IDENTIFIER
        {
-               $$ = new Value(make_shared<Expression>(&Expression::OpIndexer, *$1, make_shared<Expression>(&Expression::OpLiteral, $3, @3), DebugInfoRange(@1, @3)));
+               $$ = new Value(make_shared<Expression>(&Expression::OpIndexer, *$1, MakeLiteral($3), DebugInfoRange(@1, @3)));
                delete $1;
                free($3);
        }
        | rterm '(' rterm_items ')'
        {
-               Array::Ptr arguments = Array::Ptr($3);
-               $$ = new Value(make_shared<Expression>(&Expression::OpFunctionCall, *$1, make_shared<Expression>(&Expression::OpLiteral, arguments, @3), DebugInfoRange(@1, @4)));
+               $$ = new Value(make_shared<Expression>(&Expression::OpFunctionCall, *$1, MakeLiteral(Array::Ptr($3)), DebugInfoRange(@1, @4)));
                delete $1;
        }
        | T_IDENTIFIER
@@ -792,67 +799,43 @@ rterm: T_STRING
        | rterm T_DIVIDE_OP rterm { MakeRBinaryOp(&$$, $2, $1, $3, @1, @3); }
        | T_FUNCTION identifier '(' identifier_items ')' rterm_scope
        {
-               Array::Ptr arr = make_shared<Array>();
-
-               arr->Add($2);
-               free($2);
-
                Expression::Ptr aexpr = *$6;
                delete $6;
                aexpr->MakeInline();
-               arr->Add(aexpr);
 
-               $$ = new Value(make_shared<Expression>(&Expression::OpFunction, arr, Array::Ptr($4), DebugInfoRange(@1, @6)));
+               $$ = new Value(make_shared<Expression>(&Expression::OpFunction, MakeArray($2, aexpr), Array::Ptr($4), DebugInfoRange(@1, @6)));
+               free($2);
        }
        | T_FUNCTION '(' identifier_items ')' rterm_scope
        {
-               Array::Ptr arr = make_shared<Array>();
-
-               arr->Add(Empty);
-
                Expression::Ptr aexpr = *$5;
                delete $5;
                aexpr->MakeInline();
-               arr->Add(aexpr);
 
-               $$ = new Value(make_shared<Expression>(&Expression::OpFunction, arr, Array::Ptr($3), DebugInfoRange(@1, @5)));
+               $$ = new Value(make_shared<Expression>(&Expression::OpFunction, MakeArray(Empty, aexpr), Array::Ptr($3), DebugInfoRange(@1, @5)));
        }
        | T_FOR '(' identifier T_FOLLOWS identifier T_IN rterm ')' rterm_scope
        {
-               Array::Ptr arr = make_shared<Array>();
-
-               arr->Add($3);
-               free($3);
-
-               arr->Add($5);
-               free($5);
-
                Expression::Ptr aexpr = *$7;
                delete $7;
-               arr->Add(aexpr);
 
                Expression::Ptr ascope = *$9;
                delete $9;
 
-               $$ = new Value(make_shared<Expression>(&Expression::OpFor, arr, ascope, DebugInfoRange(@1, @9)));
+               $$ = new Value(make_shared<Expression>(&Expression::OpFor, MakeArray($3, $5, aexpr), ascope, DebugInfoRange(@1, @9)));
+               free($3);
+               free($5);
        }
        | T_FOR '(' identifier T_IN rterm ')' rterm_scope
        {
-               Array::Ptr arr = make_shared<Array>();
-
-               arr->Add($3);
-               free($3);
-
-               arr->Add(Empty);
-
                Expression::Ptr aexpr = *$5;
                delete $5;
-               arr->Add(aexpr);
 
                Expression::Ptr ascope = *$7;
                delete $7;
 
-               $$ = new Value(make_shared<Expression>(&Expression::OpFor, arr, ascope, DebugInfoRange(@1, @7)));
+               $$ = new Value(make_shared<Expression>(&Expression::OpFor, MakeArray($3, Empty, aexpr), ascope, DebugInfoRange(@1, @7)));
+               free($3);
        }
        ;
 
@@ -892,7 +875,7 @@ apply_for_specifier: /* empty */
 
 optional_rterm: /* empty */
        {
-               $$ = new Value(make_shared<Expression>(&Expression::OpLiteral, Empty, DebugInfo()));
+               $$ = new Value(MakeLiteral(Empty));
        }
        | rterm
        {
@@ -904,8 +887,8 @@ apply:
        {
                m_Apply.push(true);
                m_SeenAssign.push(false);
-               m_Assign.push(make_shared<Expression>(&Expression::OpLiteral, false, DebugInfo()));
-               m_Ignore.push(make_shared<Expression>(&Expression::OpLiteral, false, DebugInfo()));
+               m_Assign.push(MakeLiteral(false));
+               m_Ignore.push(MakeLiteral(false));
                m_FKVar.push("");
                m_FVVar.push("");
                m_FTerm.push(Expression::Ptr());
index 8f14f0c004a080296cda9b75ffb1282f8822a6e6..1334d202e8175415361c6459de38b13206d1d92c 100644 (file)
@@ -93,8 +93,8 @@ ConfigItem::Ptr ConfigItemBuilder::Compile(void)
        Array::Ptr templateArray = make_shared<Array>();
        templateArray->Add(m_Name);
 
-       exprs->Add(make_shared<Expression>(&Expression::OpSetPlus,
-           make_shared<Expression>(&Expression::OpLiteral, "templates", m_DebugInfo),
+       exprs->Add(make_shared<Expression>(&Expression::OpSet,
+           MakeArray(MakeArray(MakeLiteral("templates")), OpSetLiteral),
            make_shared<Expression>(&Expression::OpLiteral, templateArray, m_DebugInfo),
            m_DebugInfo));
 
index 84537777b6d09fac9d023edb40ea19090f961743..01f26bf3595576a5883cff17586e3ee6887f1666 100644 (file)
@@ -312,159 +312,83 @@ Value Expression::OpDict(const Expression *expr, const Dictionary::Ptr& locals,
 
 Value Expression::OpSet(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint)
 {
-       Value index = expr->EvaluateOperand1(locals);
-
-       DebugHint *sdhint = NULL;
-       if (dhint)
-               sdhint = dhint->GetChild(index);
-
-       Value right = expr->EvaluateOperand2(locals, sdhint);
-       locals->Set(index, right);
-
-       if (sdhint)
-               sdhint->AddMessage("=", expr->m_DebugInfo);
-
-       return right;
-}
-
-Value Expression::OpSetPlus(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint)
-{
-       Value index = expr->EvaluateOperand1(locals);
-       Value left = locals->Get(index);
-       Expression::Ptr exp_right = expr->m_Operand2;
-       Dictionary::Ptr xlocals = locals;
-
-       if (exp_right->m_Operator == &Expression::OpDict) {
-               xlocals = left;
-
-               if (!xlocals)
-                       xlocals = make_shared<Dictionary>();
-
-               xlocals->Set("__parent", locals);
-       }
-
-       DebugHint *sdhint = NULL;
-       if (dhint)
-               sdhint = dhint->GetChild(index);
-
-       Value result = left + expr->EvaluateOperand2(xlocals, sdhint);
-
-       if (exp_right->m_Operator == &Expression::OpDict) {
-               Dictionary::Ptr dict = result;
-               dict->Remove("__parent");
-       }
-
-       locals->Set(index, result);
-
-       if (sdhint)
-               sdhint->AddMessage("+=", expr->m_DebugInfo);
-
-       return result;
-}
-
-Value Expression::OpSetMinus(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint)
-{
-       Value index = expr->EvaluateOperand1(locals);
-       Value left = locals->Get(index);
-       Expression::Ptr exp_right = expr->m_Operand2;
-       Dictionary::Ptr xlocals = locals;
-
-       if (exp_right->m_Operator == &Expression::OpDict) {
-               xlocals = left;
-
-               if (!xlocals)
-                       xlocals = make_shared<Dictionary>();
-
-               xlocals->Set("__parent", locals);
-       }
-
-       DebugHint *sdhint = NULL;
-       if (dhint)
-               sdhint = dhint->GetChild(index);
-
-       Value result = left - expr->EvaluateOperand2(xlocals, sdhint);
-
-       if (exp_right->m_Operator == &Expression::OpDict) {
-               Dictionary::Ptr dict = result;
-               dict->Remove("__parent");
-       }
+       Array::Ptr left = expr->m_Operand1;
+       Array::Ptr indexer = left->Get(0);
+       int csop = left->Get(1);
 
-       locals->Set(index, result);
+       DebugHint *sdhint = dhint;
 
-       if (sdhint)
-               sdhint->AddMessage("-=", expr->m_DebugInfo);
+       Value parent, object;
+       String index;
 
-       return result;
-}
+       for (Array::SizeType i = 0; i < indexer->GetLength(); i++) {
+               Expression::Ptr indexExpr = indexer->Get(i);
+               String tempindex = indexExpr->Evaluate(locals, dhint);
 
-Value Expression::OpSetMultiply(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint)
-{
-       Value index = expr->EvaluateOperand1(locals);
-       Value left = locals->Get(index);
-       Expression::Ptr exp_right = expr->m_Operand2;
-       Dictionary::Ptr xlocals = locals;
+               if (i == indexer->GetLength() - 1)
+                       index = tempindex;
 
-       if (exp_right->m_Operator == &Expression::OpDict) {
-               xlocals = left;
+               if (i == 0) {
+                       parent = locals;
+                       object = locals->Get(tempindex);
+               } else {
+                       parent = object;
 
-               if (!xlocals)
-                       xlocals = make_shared<Dictionary>();
+                       Expression::Ptr eparent = make_shared<Expression>(&Expression::OpLiteral, parent, expr->m_DebugInfo);
+                       Expression::Ptr eindex = make_shared<Expression>(&Expression::OpLiteral, tempindex, expr->m_DebugInfo);
 
-               xlocals->Set("__parent", locals);
-       }
+                       Expression::Ptr eip = make_shared<Expression>(&Expression::OpIndexer, eparent, eindex, expr->m_DebugInfo);
+                       object = eip->Evaluate(locals, dhint);
+               }
 
-       DebugHint *sdhint = NULL;
-       if (dhint)
-               sdhint = dhint->GetChild(index);
+               if (sdhint)
+                       sdhint = sdhint->GetChild(index);
 
-       Value result = left * expr->EvaluateOperand2(xlocals, sdhint);
+               if (i != indexer->GetLength() - 1 && object.IsEmpty()) {
+                       object = make_shared<Dictionary>();
 
-       if (exp_right->m_Operator == &Expression::OpDict) {
-               Dictionary::Ptr dict = result;
-               dict->Remove("__parent");
+                       Dictionary::Ptr pdict = parent;
+                       pdict->Set(tempindex, object);
+               }
        }
 
-       locals->Set(index, result);
-
-       if (sdhint)
-               sdhint->AddMessage("*=", expr->m_DebugInfo);
+       Value right = expr->EvaluateOperand2(locals, dhint);
 
-       return result;
-}
+       if (csop != OpSetLiteral) {
+               Expression::OpCallback op;
 
-Value Expression::OpSetDivide(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint)
-{
-       Value index = expr->EvaluateOperand1(locals);
-       Value left = locals->Get(index);
-       Expression::Ptr exp_right = expr->m_Operand2;
-       Dictionary::Ptr xlocals = locals;
-
-       if (exp_right->m_Operator == &Expression::OpDict) {
-               xlocals = left;
-
-               if (!xlocals)
-                       xlocals = make_shared<Dictionary>();
-
-               xlocals->Set("__parent", locals);
-       }
-
-       DebugHint *sdhint = NULL;
-       if (dhint)
-               sdhint = dhint->GetChild(index);
+               switch (csop) {
+                       case OpSetAdd:
+                               op = &Expression::OpAdd;
+                               break;
+                       case OpSetSubtract:
+                               op = &Expression::OpSubtract;
+                               break;
+                       case OpSetMultiply:
+                               op = &Expression::OpMultiply;
+                               break;
+                       case OpSetDivide:
+                               op = &Expression::OpDivide;
+                               break;
+                       default:
+                               VERIFY(!"Invalid opcode.");
+               }
 
-       Value result = left / expr->EvaluateOperand2(xlocals, sdhint);
+               Expression::Ptr ecp = make_shared<Expression>(op,
+                   make_shared<Expression>(&Expression::OpLiteral, object, expr->m_DebugInfo),
+                   make_shared<Expression>(&Expression::OpLiteral, right, expr->m_DebugInfo),
+                   expr->m_DebugInfo);
 
-       if (exp_right->m_Operator == &Expression::OpDict) {
-               Dictionary::Ptr dict = result;
-               dict->Remove("__parent");
+               right = ecp->Evaluate(locals, dhint);
        }
 
-       locals->Set(index, result);
+       Dictionary::Ptr pdict = parent;
+       pdict->Set(index, right);
 
        if (sdhint)
-               sdhint->AddMessage("/=", expr->m_DebugInfo);
+               sdhint->AddMessage("=", expr->m_DebugInfo);
 
-       return result;
+       return right;
 }
 
 Value Expression::OpIndexer(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint)
@@ -692,3 +616,7 @@ Dictionary::Ptr DebugHint::ToDictionary(void) const
        return result;
 }
 
+Expression::Ptr icinga::MakeLiteral(const Value& lit)
+{
+       return make_shared<Expression>(&Expression::OpLiteral, lit, DebugInfo());
+}
index 874f6ff738d5091865e48a9d3bbb49526a5469ab..f4766316265ecb776929ac47886bc7a94dcc3e94 100644 (file)
@@ -46,6 +46,15 @@ struct DebugHint
        Dictionary::Ptr ToDictionary(void) const;
 };
 
+enum CombinedSetOp
+{
+       OpSetLiteral,
+       OpSetAdd,
+       OpSetSubtract,
+       OpSetMultiply,
+       OpSetDivide
+};
+
 /**
  * @ingroup config
  */
@@ -91,10 +100,6 @@ public:
        static Value OpArray(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint);
        static Value OpDict(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint);
        static Value OpSet(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint);
-       static Value OpSetPlus(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint);
-       static Value OpSetMinus(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint);
-       static Value OpSetMultiply(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint);
-       static Value OpSetDivide(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint);
        static Value OpIndexer(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint);
        static Value OpImport(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint);
        static Value OpFunction(const Expression* expr, const Dictionary::Ptr& locals, DebugHint *dhint);
@@ -117,6 +122,8 @@ private:
            const Expression::Ptr& expr, const Dictionary::Ptr& scope);
 };
 
+I2_CONFIG_API Expression::Ptr MakeLiteral(const Value& lit = Value());
+
 }
 
 #endif /* EXPRESSION_H */
index 04460ea29142f7f3feb9d1d2f8a861513e63da54..5a2ef9c1af048866a6507daf6d95e9227c92cb1e 100644 (file)
@@ -59,29 +59,29 @@ void Dependency::EvaluateApplyRuleOneInstance(const Checkable::Ptr& checkable, c
        tie(host, service) = GetHostService(checkable);
 
        builder->AddExpression(make_shared<Expression>(&Expression::OpSet,
-               make_shared<Expression>(&Expression::OpLiteral, "parent_host_name", di),
-               make_shared<Expression>(&Expression::OpLiteral, host->GetName(), di),
-               di));
+           MakeArray(MakeArray(MakeLiteral("parent_host_name")), OpSetLiteral),
+           MakeLiteral(host->GetName()),
+           di));
 
        builder->AddExpression(make_shared<Expression>(&Expression::OpSet,
-               make_shared<Expression>(&Expression::OpLiteral, "child_host_name", di),
-               make_shared<Expression>(&Expression::OpLiteral, host->GetName(), di),
-               di));
+           MakeArray(MakeArray(MakeLiteral("child_host_name")), OpSetLiteral),
+           MakeLiteral(host->GetName()),
+           di));
 
        if (service) {
                builder->AddExpression(make_shared<Expression>(&Expression::OpSet,
-                       make_shared<Expression>(&Expression::OpLiteral, "child_service_name", di),
-                       make_shared<Expression>(&Expression::OpLiteral, service->GetShortName(), di),
-                       di));
+                   MakeArray(MakeArray(MakeLiteral("child_service_name")), OpSetLiteral),
+                   MakeLiteral(service->GetShortName()),
+                   di));
        }
 
        String zone = checkable->GetZone();
 
        if (!zone.IsEmpty()) {
                builder->AddExpression(make_shared<Expression>(&Expression::OpSet,
-                       make_shared<Expression>(&Expression::OpLiteral, "zone", di),
-                       make_shared<Expression>(&Expression::OpLiteral, zone, di),
-                       di));
+                   MakeArray(MakeArray(MakeLiteral("zone")), OpSetLiteral),
+                   MakeLiteral(zone),
+                   di));
        }
 
        builder->AddExpression(rule.GetExpression());
index c5b48987ba488135f0c4e966f21178c39e45f68a..3cabfde8986f04abb2519968d90bc95349bcf504 100644 (file)
@@ -59,24 +59,24 @@ void Notification::EvaluateApplyRuleOneInstance(const Checkable::Ptr& checkable,
        tie(host, service) = GetHostService(checkable);
 
        builder->AddExpression(make_shared<Expression>(&Expression::OpSet,
-               make_shared<Expression>(&Expression::OpLiteral, "host_name", di),
-               make_shared<Expression>(&Expression::OpLiteral, host->GetName(), di),
-               di));
+           MakeArray(MakeArray(MakeLiteral("host_name")), OpSetLiteral),
+           MakeLiteral(host->GetName()),
+           di));
 
        if (service) {
                builder->AddExpression(make_shared<Expression>(&Expression::OpSet,
-                       make_shared<Expression>(&Expression::OpLiteral, "service_name", di),
-                       make_shared<Expression>(&Expression::OpLiteral, service->GetShortName(), di),
-                       di));
+                   MakeArray(MakeArray(MakeLiteral("service_name")), OpSetLiteral),
+                   MakeLiteral(service->GetShortName()),
+                   di));
        }
 
        String zone = checkable->GetZone();
 
        if (!zone.IsEmpty()) {
                builder->AddExpression(make_shared<Expression>(&Expression::OpSet,
-                       make_shared<Expression>(&Expression::OpLiteral, "zone", di),
-                       make_shared<Expression>(&Expression::OpLiteral, zone, di),
-                       di));
+                   MakeArray(MakeArray(MakeLiteral("zone")), OpSetLiteral),
+                   MakeLiteral(zone),
+                   di));
        }
 
        builder->AddExpression(rule.GetExpression());
index 575ad603ef3655cebcaf74760e6f772b780d73c2..a31710ce9976715e685e26dd09adae1ffd098a76 100644 (file)
@@ -58,24 +58,24 @@ void ScheduledDowntime::EvaluateApplyRuleOneInstance(const Checkable::Ptr& check
        tie(host, service) = GetHostService(checkable);
 
        builder->AddExpression(make_shared<Expression>(&Expression::OpSet,
-               make_shared<Expression>(&Expression::OpLiteral, "host_name", di),
-               make_shared<Expression>(&Expression::OpLiteral, host->GetName(), di),
-               di));
+           MakeArray(MakeArray(MakeLiteral("host_name")), OpSetLiteral),
+           MakeLiteral(host->GetName()),
+           di));
 
        if (service) {
                builder->AddExpression(make_shared<Expression>(&Expression::OpSet,
-                       make_shared<Expression>(&Expression::OpLiteral, "service_name", di),
-                       make_shared<Expression>(&Expression::OpLiteral, service->GetShortName(), di),
-                       di));
+                   MakeArray(MakeArray(MakeLiteral("service_name")), OpSetLiteral),
+                   MakeLiteral(service->GetShortName()),
+                   di));
        }
 
        String zone = checkable->GetZone();
 
        if (!zone.IsEmpty()) {
                builder->AddExpression(make_shared<Expression>(&Expression::OpSet,
-                       make_shared<Expression>(&Expression::OpLiteral, "zone", di),
-                       make_shared<Expression>(&Expression::OpLiteral, zone, di),
-                       di));
+                   MakeArray(MakeArray(MakeLiteral("zone")), OpSetLiteral),
+                   MakeLiteral(zone),
+                   di));
        }
 
        builder->AddExpression(rule.GetExpression());
index a2facbff814b4d6e6395ffd7650dfb6ce2888747..a4125e75c3e35ed8859ee0abf36162e3dd66449a 100644 (file)
@@ -53,21 +53,21 @@ void Service::EvaluateApplyRuleOneInstance(const Host::Ptr& host, const String&
        builder->SetScope(locals);
 
        builder->AddExpression(make_shared<Expression>(&Expression::OpSet,
-           make_shared<Expression>(&Expression::OpLiteral, "host_name", di),
-           make_shared<Expression>(&Expression::OpLiteral, host->GetName(), di),
+           MakeArray(MakeArray(MakeLiteral("host_name")), OpSetLiteral),
+           MakeLiteral(host->GetName()),
            di));
 
        builder->AddExpression(make_shared<Expression>(&Expression::OpSet,
-           make_shared<Expression>(&Expression::OpLiteral, "name", di),
-           make_shared<Expression>(&Expression::OpLiteral, name, di),
+           MakeArray(MakeArray(MakeLiteral("service_name")), OpSetLiteral),
+           MakeLiteral(name),
            di));
 
        String zone = host->GetZone();
 
        if (!zone.IsEmpty()) {
                builder->AddExpression(make_shared<Expression>(&Expression::OpSet,
-                   make_shared<Expression>(&Expression::OpLiteral, "zone", di),
-                   make_shared<Expression>(&Expression::OpLiteral, zone, di),
+                   MakeArray(MakeArray(MakeLiteral("zone")), OpSetLiteral),
+                   MakeLiteral(zone),
                    di));
        }