From: Gunnar Beutner Date: Sat, 10 May 2014 09:26:56 +0000 (+0200) Subject: Implement for loops. X-Git-Tag: v0.0.11~49 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=0e34968e8f497bdcf409a9aae1e24547ad196528;p=icinga2 Implement for loops. Fixes #6183 --- diff --git a/lib/base/scriptutils.cpp b/lib/base/scriptutils.cpp index 6cefd1d5c..b14a313b8 100644 --- a/lib/base/scriptutils.cpp +++ b/lib/base/scriptutils.cpp @@ -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& arguments) ::Log(severity, facility, JsonSerialize(message)); } +Array::Ptr ScriptUtils::Range(const std::vector& 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(); + + 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); diff --git a/lib/base/scriptutils.h b/lib/base/scriptutils.h index 2e753560a..e4c190383 100644 --- a/lib/base/scriptutils.h +++ b/lib/base/scriptutils.h @@ -38,6 +38,7 @@ public: static Array::Ptr Union(const std::vector& arguments); static Array::Ptr Intersection(const std::vector& arguments); static void Log(const std::vector& arguments); + static Array::Ptr Range(const std::vector& arguments); static void Exit(int code); private: diff --git a/lib/config/aexpression.cpp b/lib/config/aexpression.cpp index bd4f0ef2f..6295aab2a 100644 --- a/lib/config/aexpression.cpp +++ b/lib/config/aexpression.cpp @@ -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; +} diff --git a/lib/config/aexpression.h b/lib/config/aexpression.h index d9b6b4ac9..5ab2da859 100644 --- a/lib/config/aexpression.h +++ b/lib/config/aexpression.h @@ -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; diff --git a/lib/config/config_lexer.ll b/lib/config/config_lexer.ll index 829cd9c2e..8970edd24 100644 --- a/lib/config/config_lexer.ll +++ b/lib/config/config_lexer.ll @@ -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; } diff --git a/lib/config/config_parser.yy b/lib/config/config_parser.yy index d7e439988..0425a47c9 100644 --- a/lib/config/config_parser.yy +++ b/lib/config/config_parser.yy @@ -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 identifier %type rterm_items @@ -877,6 +878,22 @@ rterm: T_STRING $$ = new Value(make_shared(&AExpression::OpFunction, arr, Array::Ptr($2), DebugInfoRange(@1, @4))); } + | T_FOR '(' identifier T_IN rterm ')' rterm_scope + { + Array::Ptr arr = make_shared(); + + 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::OpFor, arr, ascope, DebugInfoRange(@1, @7))); + } ; target_type_specifier: /* empty */ diff --git a/lib/icinga/apievents.cpp b/lib/icinga/apievents.cpp index 835aa06cd..562546890 100644 --- a/lib/icinga/apievents.cpp +++ b/lib/icinga/apievents.cpp @@ -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) {