]> granicus.if.org Git - icinga2/commitdiff
Implement for loops.
authorGunnar Beutner <gunnar@beutner.name>
Sat, 10 May 2014 09:26:56 +0000 (11:26 +0200)
committerGunnar Beutner <gunnar@beutner.name>
Sat, 10 May 2014 09:26:56 +0000 (11:26 +0200)
Fixes #6183

lib/base/scriptutils.cpp
lib/base/scriptutils.h
lib/config/aexpression.cpp
lib/config/aexpression.h
lib/config/config_lexer.ll
lib/config/config_parser.yy
lib/icinga/apievents.cpp

index 6cefd1d5cbdd75886557fd6eb8cc02dbe3ebea51..b14a313b8e9a2cd5e1caffacb09ff4c87f377497 100644 (file)
@@ -38,6 +38,7 @@ REGISTER_SCRIPTFUNCTION(len, &ScriptUtils::Len);
 REGISTER_SCRIPTFUNCTION(union, &ScriptUtils::Union);
 REGISTER_SCRIPTFUNCTION(intersection, &ScriptUtils::Intersection);
 REGISTER_SCRIPTFUNCTION(log, &ScriptUtils::Log);
+REGISTER_SCRIPTFUNCTION(range, &ScriptUtils::Range);
 REGISTER_SCRIPTFUNCTION(exit, &ScriptUtils::Exit);
 
 bool ScriptUtils::Regex(const String& pattern, const String& text)
@@ -130,6 +131,41 @@ void ScriptUtils::Log(const std::vector<Value>& arguments)
                ::Log(severity, facility, JsonSerialize(message));
 }
 
+Array::Ptr ScriptUtils::Range(const std::vector<Value>& arguments)
+{
+       int start, end, increment;
+
+       switch (arguments.size()) {
+               case 1:
+                       start = 0;
+                       end = arguments[0];
+                       increment = 1;
+                       break;
+               case 2:
+                       start = arguments[0];
+                       end = arguments[1];
+                       increment = 1;
+                       break;
+               case 3:
+                       start = arguments[0];
+                       end = arguments[1];
+                       increment = arguments[2];
+                       break;
+       }
+
+       Array::Ptr result = make_shared<Array>();
+
+       if ((start < end && increment <= 0) ||
+           (start > end && increment >= 0))
+               return result;
+
+       for (int i = start; i < end; i += increment) {
+               result->Add(i);
+       }
+
+       return result;
+}
+
 void ScriptUtils::Exit(int code)
 {
        exit(code);
index 2e753560ada8e092e3562b5720cadedf8d76e407..e4c1903830dceaf56227f3d0d6d18b2fdb639a68 100644 (file)
@@ -38,6 +38,7 @@ public:
        static Array::Ptr Union(const std::vector<Value>& arguments);
        static Array::Ptr Intersection(const std::vector<Value>& arguments);
        static void Log(const std::vector<Value>& arguments);
+       static Array::Ptr Range(const std::vector<Value>& arguments);
        static void Exit(int code);
 
 private:
index bd4f0ef2f190497329af0744a75515e68e460760..6295aab2ab15603914d36d39516b04e67bdf590b 100644 (file)
@@ -574,3 +574,23 @@ Value AExpression::OpObject(const AExpression* expr, const Dictionary::Ptr& loca
 
        return Empty;
 }
+
+Value AExpression::OpFor(const AExpression* expr, const Dictionary::Ptr& locals)
+{
+       Array::Ptr left = expr->m_Operand1;
+       String varname = left->Get(0);
+       AExpression::Ptr aexpr = left->Get(1);
+       AExpression::Ptr ascope = expr->m_Operand2;
+
+       Array::Ptr arr = aexpr->Evaluate(locals);
+
+       ObjectLock olock(arr);
+       BOOST_FOREACH(const Value& value, arr) {
+               locals->Set(varname, value);
+               ascope->Evaluate(locals);
+       }
+
+       locals->Remove(varname);
+
+       return Empty;
+}
index d9b6b4ac9647c1a411c4002f512e4ff6f9ddbf7d..5ab2da8599eb7eecbfc234004997b45771c15c82 100644 (file)
@@ -82,6 +82,7 @@ public:
        static Value OpFunction(const AExpression* expr, const Dictionary::Ptr& locals);
        static Value OpApply(const AExpression* expr, const Dictionary::Ptr& locals);
        static Value OpObject(const AExpression* expr, const Dictionary::Ptr& locals);
+       static Value OpFor(const AExpression* expr, const Dictionary::Ptr& locals);
 
 private:
        OpCallback m_Operator;
index 829cd9c2ee3814ab610fffd3cb30f16e7ae547c4..8970edd24540f3bd0811bbe0571601fd9851c53e 100644 (file)
@@ -232,6 +232,7 @@ function                    return T_FUNCTION;
 lambda                         return T_LAMBDA;
 return                         return T_RETURN;
 zone                           return T_ZONE;
+for                            return T_FOR;
 \<\<                           { yylval->op = &AExpression::OpShiftLeft; return T_SHIFT_LEFT; }
 \>\>                           { yylval->op = &AExpression::OpShiftRight; return T_SHIFT_RIGHT; }
 \<=                            { yylval->op = &AExpression::OpLessThanOrEqual; return T_LESS_THAN_OR_EQUAL; }
index d7e4399889b5701eb2fb12b2a1d1c7224fbced6f..0425a47c910ebae29597065b2883a0de1558864b 100644 (file)
@@ -161,6 +161,7 @@ static void MakeRBinaryOp(Value** result, AExpression::OpCallback& op, Value *le
 %token T_LAMBDA "lambda (T_LAMBDA)"
 %token T_RETURN "return (T_RETURN)"
 %token T_ZONE "zone (T_ZONE)"
+%token T_FOR "for (T_FOR)"
 
 %type <text> identifier
 %type <array> rterm_items
@@ -877,6 +878,22 @@ rterm: T_STRING
 
                $$ = new Value(make_shared<AExpression>(&AExpression::OpFunction, arr, Array::Ptr($2), DebugInfoRange(@1, @4)));
        }
+       | T_FOR '(' identifier T_IN rterm ')' rterm_scope
+       {
+               Array::Ptr arr = make_shared<Array>();
+
+               arr->Add($3);
+               free($3);
+
+               AExpression::Ptr aexpr = *$5;
+               delete $5;
+               arr->Add(aexpr);
+
+               AExpression::Ptr ascope = *$7;
+               delete $7;
+
+               $$ = new Value(make_shared<AExpression>(&AExpression::OpFor, arr, ascope, DebugInfoRange(@1, @7)));
+       }
        ;
 
 target_type_specifier: /* empty */
index 835aa06cd932fdb23087ddfb551476bf40a69032..562546890f5e970c0d107db9dd038b35a2fc5cf1 100644 (file)
@@ -937,7 +937,7 @@ Value ApiEvents::UpdateRepositoryAPIHandler(const MessageOrigin& origin, const D
        fp.close();
 
 #ifdef _WIN32
-       _unlink(inventoryFile.CStr());
+       _unlink(repositoryFile.CStr());
 #endif /* _WIN32 */
 
        if (rename(repositoryTempFile.CStr(), repositoryFile.CStr()) < 0) {