Refactor the config parser's AST.

Refs #5846
This commit is contained in:
Gunnar Beutner 2014-03-23 11:27:40 +01:00
parent 67d8bc219e
commit aacc699dd4
23 changed files with 411 additions and 762 deletions

View File

@ -30,7 +30,7 @@ add_library(base SHARED
netstring.cpp networkstream.cpp object.cpp objectlock.cpp process.cpp
process-unix.cpp process-windows.cpp qstring.cpp ringbuffer.cpp script.cpp
script.th scriptfunction.cpp scriptfunctionwrapper.cpp scriptinterpreter.cpp
scriptlanguage.cpp scriptvariable.cpp serializer.cpp socket.cpp stacktrace.cpp
scriptlanguage.cpp scriptutils.cpp scriptvariable.cpp serializer.cpp socket.cpp stacktrace.cpp
statsfunction.cpp stdiostream.cpp stream_bio.cpp stream.cpp streamlogger.cpp streamlogger.th
sysloglogger.cpp sysloglogger.th tcpsocket.cpp threadpool.cpp timer.cpp
tlsstream.cpp tlsutility.cpp type.cpp unixsocket.cpp utility.cpp value.cpp

View File

@ -17,12 +17,13 @@
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
******************************************************************************/
#include "methods/utilityfuncs.h"
#include "base/scriptutils.h"
#include "base/scriptfunction.h"
#include "base/utility.h"
#include "base/convert.h"
#include "base/array.h"
#include "base/dictionary.h"
#include "base/serializer.h"
#include "base/logger_fwd.h"
#include <boost/regex.hpp>
#include <algorithm>
@ -30,21 +31,21 @@
using namespace icinga;
REGISTER_SCRIPTFUNCTION(regex, &UtilityFuncs::Regex);
REGISTER_SCRIPTFUNCTION(regex, &ScriptUtils::Regex);
REGISTER_SCRIPTFUNCTION(match, &Utility::Match);
REGISTER_SCRIPTFUNCTION(len, &UtilityFuncs::Len);
REGISTER_SCRIPTFUNCTION(union, &UtilityFuncs::Union);
REGISTER_SCRIPTFUNCTION(intersection, &UtilityFuncs::Intersection);
REGISTER_SCRIPTFUNCTION(log, &UtilityFuncs::Log);
REGISTER_SCRIPTFUNCTION(len, &ScriptUtils::Len);
REGISTER_SCRIPTFUNCTION(union, &ScriptUtils::Union);
REGISTER_SCRIPTFUNCTION(intersection, &ScriptUtils::Intersection);
REGISTER_SCRIPTFUNCTION(log, &ScriptUtils::Log);
bool UtilityFuncs::Regex(const String& pattern, const String& text)
bool ScriptUtils::Regex(const String& pattern, const String& text)
{
boost::regex expr(pattern.GetData());
boost::smatch what;
return boost::regex_search(text.GetData(), what, expr);
}
int UtilityFuncs::Len(const Value& value)
int ScriptUtils::Len(const Value& value)
{
if (value.IsObjectType<Dictionary>()) {
Dictionary::Ptr dict = value;
@ -57,7 +58,7 @@ int UtilityFuncs::Len(const Value& value)
}
}
Array::Ptr UtilityFuncs::Union(const std::vector<Value>& arguments)
Array::Ptr ScriptUtils::Union(const std::vector<Value>& arguments)
{
std::set<Value> values;
@ -77,7 +78,7 @@ Array::Ptr UtilityFuncs::Union(const std::vector<Value>& arguments)
return result;
}
Array::Ptr UtilityFuncs::Intersection(const std::vector<Value>& arguments)
Array::Ptr ScriptUtils::Intersection(const std::vector<Value>& arguments)
{
if (arguments.size() == 0)
return make_shared<Array>();
@ -101,7 +102,10 @@ Array::Ptr UtilityFuncs::Intersection(const std::vector<Value>& arguments)
return result;
}
void UtilityFuncs::Log(const String& message)
void ScriptUtils::Log(const Value& message)
{
::Log(LogInformation, "config", message);
if (message.IsString())
::Log(LogInformation, "config", message);
else
::Log(LogInformation, "config", JsonSerialize(message));
}

View File

@ -17,10 +17,10 @@
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
******************************************************************************/
#ifndef UTILITYFUNCS_H
#define UTILITYFUNCS_H
#ifndef SCRIPTUTILS_H
#define SCRIPTUTILS_H
#include "methods/i2-methods.h"
#include "base/i2-base.h"
#include "base/qstring.h"
#include "base/array.h"
@ -28,21 +28,21 @@ namespace icinga
{
/**
* @ingroup methods
* @ingroup base
*/
class I2_METHODS_API UtilityFuncs
class I2_BASE_API ScriptUtils
{
public:
static bool Regex(const String& pattern, const String& text);
static int Len(const Value& value);
static Array::Ptr Union(const std::vector<Value>& arguments);
static Array::Ptr Intersection(const std::vector<Value>& arguments);
static void Log(const String& message);
static void Log(const Value& message);
private:
UtilityFuncs(void);
ScriptUtils(void);
};
}
#endif /* UTILITYFUNCS_H */
#endif /* SCRIPTUTILS_H */

View File

@ -201,10 +201,19 @@ Value icinga::operator+(const Value& lhs, const Value& rhs)
return static_cast<String>(lhs) + static_cast<String>(rhs);
else if ((lhs.IsNumber() || lhs.IsEmpty()) && (rhs.IsNumber() || rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty()))
return static_cast<double>(lhs) + static_cast<double>(rhs);
else if (lhs.IsObjectType<Array>() && rhs.IsObjectType<Array>()) {
else if ((lhs.IsObjectType<Array>() || lhs.IsEmpty()) && (rhs.IsObjectType<Array>() || rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty())) {
Array::Ptr result = make_shared<Array>();
static_cast<Array::Ptr>(lhs)->CopyTo(result);
static_cast<Array::Ptr>(rhs)->CopyTo(result);
if (!lhs.IsEmpty())
static_cast<Array::Ptr>(lhs)->CopyTo(result);
if (!rhs.IsEmpty())
static_cast<Array::Ptr>(rhs)->CopyTo(result);
return result;
} else if ((lhs.IsObjectType<Dictionary>() || lhs.IsEmpty()) && (rhs.IsObjectType<Dictionary>() || rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty())) {
Dictionary::Ptr result = make_shared<Dictionary>();
if (!lhs.IsEmpty())
static_cast<Dictionary::Ptr>(lhs)->CopyTo(result);
if (!rhs.IsEmpty())
static_cast<Dictionary::Ptr>(rhs)->CopyTo(result);
return result;
} else {
BOOST_THROW_EXCEPTION(std::invalid_argument("Operator + cannot be applied to values of type '" + lhs.GetTypeName() + "' and '" + rhs.GetTypeName() + "'"));

View File

@ -30,7 +30,7 @@ add_library(config SHARED
aexpression.cpp applyrule.cpp base-type.conf base-type.cpp
configcompilercontext.cpp configcompiler.cpp configerror.cpp configitembuilder.cpp
configitem.cpp ${FLEX_config_lexer_OUTPUTS} ${BISON_config_parser_OUTPUTS}
configtype.cpp debuginfo.cpp expression.cpp expressionlist.cpp typerule.cpp typerulelist.cpp
configtype.cpp debuginfo.cpp typerule.cpp typerulelist.cpp
)
target_link_libraries(config ${Boost_LIBRARIES} base)

View File

@ -31,7 +31,7 @@
using namespace icinga;
AExpression::AExpression(OpCallback op, const Value& operand1, const DebugInfo& di)
: m_Operator(op), m_Operand1(operand1), m_DebugInfo(di)
: m_Operator(op), m_Operand1(operand1), m_Operand2(), m_DebugInfo(di)
{ }
AExpression::AExpression(OpCallback op, const Value& operand1, const Value& operand2, const DebugInfo& di)
@ -46,10 +46,66 @@ Value AExpression::Evaluate(const Dictionary::Ptr& locals) const
if (boost::get_error_info<boost::errinfo_nested_exception>(ex))
throw;
else
BOOST_THROW_EXCEPTION(ConfigError("Error while evaluating expression.") << boost::errinfo_nested_exception(boost::current_exception()) << errinfo_debuginfo(m_DebugInfo));
BOOST_THROW_EXCEPTION(ConfigError("Error while evaluating expression: " + String(ex.what())) << boost::errinfo_nested_exception(boost::current_exception()) << errinfo_debuginfo(m_DebugInfo));
}
}
void AExpression::ExtractPath(const std::vector<String>& path, const Array::Ptr& result) const
{
ASSERT(!path.empty());
if (m_Operator == &AExpression::OpDict) {
Array::Ptr exprl = m_Operand1;
BOOST_FOREACH(const AExpression::Ptr& expr, exprl) {
expr->ExtractPath(path, result);
}
} else if (m_Operator == &AExpression::OpSet && path[0] == m_Operand1) {
AExpression::Ptr exprl = m_Operand2;
if (path.size() == 1) {
result->Add(m_Operand1);
return;
}
std::vector<String> sub_path(path.begin() + 1, path.end());
exprl->ExtractPath(sub_path, result);
} else if (m_Operator == &AExpression::OpDict && static_cast<bool>(m_Operand2)) {
AExpression::Ptr exprl = m_Operand1;
exprl->ExtractPath(path, result);
}
}
void AExpression::FindDebugInfoPath(const std::vector<String>& path, DebugInfo& result) const
{
ASSERT(!path.empty());
if (m_Operator == &AExpression::OpDict) {
Array::Ptr exprl = m_Operand1;
BOOST_FOREACH(const AExpression::Ptr& expr, exprl) {
expr->FindDebugInfoPath(path, result);
}
} else if (m_Operator == &AExpression::OpSet && path[0] == m_Operand1) {
AExpression::Ptr exprl = m_Operand2;
if (path.size() == 1) {
result = m_DebugInfo;
} else {
std::vector<String> sub_path(path.begin() + 1, path.end());
exprl->FindDebugInfoPath(sub_path, result);
}
} else if (m_Operator == &AExpression::OpDict && static_cast<bool>(m_Operand2)) {
AExpression::Ptr exprl = m_Operand1;
exprl->FindDebugInfoPath(path, result);
}
}
void AExpression::MakeInline(void)
{
ASSERT(m_Operator == &AExpression::OpDict);
m_Operand2 = true;
}
Value AExpression::EvaluateOperand1(const Dictionary::Ptr& locals) const
{
return static_cast<AExpression::Ptr>(m_Operand1)->Evaluate(locals);
@ -150,12 +206,12 @@ Value AExpression::OpGreaterThanOrEqual(const Dictionary::Ptr& locals) const
Value AExpression::OpIn(const Dictionary::Ptr& locals) const
{
Value right = EvaluateOperand1(locals);
Value right = EvaluateOperand2(locals);
if (!right.IsObjectType<Array>())
BOOST_THROW_EXCEPTION(ConfigError("Invalid right side argument for 'in' operator: " + JsonSerialize(right)));
Value left = EvaluateOperand2(locals);
Value left = EvaluateOperand1(locals);
Array::Ptr arr = right;
bool found = false;
@ -214,3 +270,53 @@ Value AExpression::OpArray(const Dictionary::Ptr& locals) const
return result;
}
Value AExpression::OpDict(const Dictionary::Ptr& locals) const
{
Array::Ptr arr = m_Operand1;
bool in_place = m_Operand2;
Dictionary::Ptr result = make_shared<Dictionary>();
if (arr) {
BOOST_FOREACH(const AExpression::Ptr& aexpr, arr) {
aexpr->Evaluate(in_place ? locals : result);
}
}
return result;
}
Value AExpression::OpSet(const Dictionary::Ptr& locals) const
{
Value right = EvaluateOperand2(locals);
locals->Set(m_Operand1, right);
return right;
}
Value AExpression::OpSetPlus(const Dictionary::Ptr& locals) const
{
Value result = locals->Get(m_Operand1) + EvaluateOperand2(locals);
locals->Set(m_Operand1, result);
return result;
}
Value AExpression::OpSetMinus(const Dictionary::Ptr& locals) const
{
Value result = locals->Get(m_Operand1) - EvaluateOperand2(locals);
locals->Set(m_Operand1, result);
return result;
}
Value AExpression::OpSetMultiply(const Dictionary::Ptr& locals) const
{
Value result = locals->Get(m_Operand1) * EvaluateOperand2(locals);
locals->Set(m_Operand1, result);
return result;
}
Value AExpression::OpSetDivide(const Dictionary::Ptr& locals) const
{
Value result = locals->Get(m_Operand1) / EvaluateOperand2(locals);
locals->Set(m_Operand1, result);
return result;
}

View File

@ -22,6 +22,7 @@
#include "config/i2-config.h"
#include "config/debuginfo.h"
#include "base/array.h"
#include "base/dictionary.h"
namespace icinga
@ -41,6 +42,10 @@ public:
AExpression(OpCallback op, const Value& operand1, const Value& operand2, const DebugInfo& di);
Value Evaluate(const Dictionary::Ptr& locals) const;
void ExtractPath(const std::vector<String>& path, const Array::Ptr& result) const;
void FindDebugInfoPath(const std::vector<String>& path, DebugInfo& result) const;
void MakeInline(void);
Value OpLiteral(const Dictionary::Ptr& locals) const;
Value OpVariable(const Dictionary::Ptr& locals) const;
@ -65,6 +70,12 @@ public:
Value OpLogicalOr(const Dictionary::Ptr& locals) const;
Value OpFunctionCall(const Dictionary::Ptr& locals) const;
Value OpArray(const Dictionary::Ptr& locals) const;
Value OpDict(const Dictionary::Ptr& locals) const;
Value OpSet(const Dictionary::Ptr& locals) const;
Value OpSetPlus(const Dictionary::Ptr& locals) const;
Value OpSetMinus(const Dictionary::Ptr& locals) const;
Value OpSetMultiply(const Dictionary::Ptr& locals) const;
Value OpSetDivide(const Dictionary::Ptr& locals) const;
private:
OpCallback m_Operator;

View File

@ -19,7 +19,6 @@
******************************************************************************/
#include "config/configcompiler.h"
#include "config/expression.h"
#include "config/typerule.h"
#include "config/configcompilercontext.h"
@ -225,16 +224,16 @@ const return T_CONST;
apply return T_APPLY;
to return T_TO;
where return T_WHERE;
\<\< return T_SHIFT_LEFT;
\>\> return T_SHIFT_RIGHT;
\<= return T_LESS_THAN_OR_EQUAL;
\>= return T_GREATER_THAN_OR_EQUAL;
== return T_EQUAL;
!= return T_NOT_EQUAL;
!in return T_NOT_IN;
in return T_IN;
&& return T_LOGICAL_AND;
\|\| return T_LOGICAL_OR;
\<\< { 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; }
\>= { yylval->op = &AExpression::OpGreaterThanOrEqual; return T_GREATER_THAN_OR_EQUAL; }
== { yylval->op = &AExpression::OpEqual; return T_EQUAL; }
!= { yylval->op = &AExpression::OpNotEqual; return T_NOT_EQUAL; }
!in { yylval->op = &AExpression::OpNotIn; return T_NOT_IN; }
in { yylval->op = &AExpression::OpIn; return T_IN; }
&& { yylval->op = &AExpression::OpLogicalAnd; return T_LOGICAL_AND; }
\|\| { yylval->op = &AExpression::OpLogicalOr; return T_LOGICAL_OR; }
[a-zA-Z_][:a-zA-Z0-9\-_]* { yylval->text = strdup(yytext); return T_IDENTIFIER; }
\<[^\>]*\> { yytext[yyleng-1] = '\0'; yylval->text = strdup(yytext + 1); return T_STRING_ANGLE; }
-?[0-9]+(\.[0-9]+)?ms { yylval->num = strtod(yytext, NULL) / 1000; return T_NUMBER; }
@ -243,11 +242,19 @@ in 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 = OperatorSet; return T_SET; }
\+= { yylval->op = OperatorPlus; return T_PLUS_EQUAL; }
-= { yylval->op = OperatorMinus; return T_MINUS_EQUAL; }
\*= { yylval->op = OperatorMultiply; return T_MULTIPLY_EQUAL; }
\/= { yylval->op = OperatorDivide; return T_DIVIDE_EQUAL; }
= { yylval->op = &AExpression::OpSet; return T_SET; }
\+= { yylval->op = &AExpression::OpSetPlus; return T_SET_PLUS; }
-= { yylval->op = &AExpression::OpSetMinus; return T_SET_MINUS; }
\*= { yylval->op = &AExpression::OpSetMultiply; return T_SET_MULTIPLY; }
\/= { yylval->op = &AExpression::OpSetDivide; return T_SET_DIVIDE; }
\+ { yylval->op = &AExpression::OpAdd; return T_PLUS; }
\- { yylval->op = &AExpression::OpSubtract; return T_MINUS; }
\* { yylval->op = &AExpression::OpMultiply; return T_MULTIPLY; }
\/ { yylval->op = &AExpression::OpMultiply; return T_DIVIDE; }
\& { yylval->op = &AExpression::OpBinaryAnd; return T_BINARY_AND; }
\| { yylval->op = &AExpression::OpBinaryOr; return T_BINARY_OR; }
\< { yylval->op = &AExpression::OpLessThan; return T_LESS_THAN; }
\> { yylval->op = &AExpression::OpLessThan; return T_GREATER_THAN; }
}
. return yytext[0];

View File

@ -21,8 +21,6 @@
******************************************************************************/
#include "i2-config.h"
#include "config/expression.h"
#include "config/expressionlist.h"
#include "config/configitembuilder.h"
#include "config/configcompiler.h"
#include "config/configcompilercontext.h"
@ -86,13 +84,10 @@ using namespace icinga;
char *text;
double num;
icinga::Value *variant;
icinga::ExpressionOperator op;
icinga::AExpression::OpCallback op;
icinga::TypeSpecifier type;
std::vector<String> *slist;
Expression *expr;
ExpressionList *exprl;
Array *array;
Value *aexpr;
}
%token <text> T_STRING
@ -100,23 +95,34 @@ using namespace icinga;
%token <num> T_NUMBER
%token T_NULL
%token <text> T_IDENTIFIER
%token <op> T_SET "= (T_SET)"
%token <op> T_PLUS_EQUAL "+= (T_PLUS_EQUAL)"
%token <op> T_MINUS_EQUAL "-= (T_MINUS_EQUAL)"
%token <op> T_MULTIPLY_EQUAL "*= (T_MULTIPLY_EQUAL)"
%token <op> T_DIVIDE_EQUAL "/= (T_DIVIDE_EQUAL)"
%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 <op> T_SHIFT_LEFT "<< (T_SHIFT_LEFT)"
%token <op> T_SHIFT_RIGHT ">> (T_SHIFT_RIGHT)"
%token <op> T_EQUAL "== (T_EQUAL)"
%token <op> T_NOT_EQUAL "!= (T_NOT_EQUAL)"
%token <op> T_IN "in (T_IN)"
%token <op> T_NOT_IN "!in (T_NOT_IN)"
%token <op> T_LOGICAL_AND "&& (T_LOGICAL_AND)"
%token <op> T_LOGICAL_OR "|| (T_LOGICAL_OR)"
%token <op> T_LESS_THAN_OR_EQUAL "<= (T_LESS_THAN_OR_EQUAL)"
%token <op> T_GREATER_THAN_OR_EQUAL ">= (T_GREATER_THAN_OR_EQUAL)"
%token <op> T_PLUS "+ (T_PLUS)"
%token <op> T_MINUS "- (T_MINUS)"
%token <op> T_MULTIPLY "* (T_MULTIPLY)"
%token <op> T_DIVIDE "/ (T_DIVIDE)"
%token <op> T_BINARY_AND "& (T_BINARY_AND)"
%token <op> T_BINARY_OR "| (T_BINARY_OR)"
%token <op> T_LESS_THAN "< (T_LESS_THAN)"
%token <op> T_GREATER_THAN "> (T_GREATER_THAN)"
%token T_VAR "var (T_VAR)"
%token T_CONST "const (T_CONST)"
%token T_SHIFT_LEFT "<< (T_SHIFT_LEFT)"
%token T_SHIFT_RIGHT ">> (T_SHIFT_RIGHT)"
%token T_EQUAL "== (T_EQUAL)"
%token T_NOT_EQUAL "!= (T_NOT_EQUAL)"
%token T_IN "in (T_IN)"
%token T_NOT_IN "!in (T_NOT_IN)"
%token T_LOGICAL_AND "&& (T_LOGICAL_AND)"
%token T_LOGICAL_OR "|| (T_LOGICAL_OR)"
%token T_LESS_THAN_OR_EQUAL "<= (T_LESS_THAN_OR_EQUAL)"
%token T_GREATER_THAN_OR_EQUAL ">= (T_GREATER_THAN_OR_EQUAL)"
%token <type> T_TYPE_DICTIONARY "dictionary (T_TYPE_DICTIONARY)"
%token <type> T_TYPE_ARRAY "array (T_TYPE_ARRAY)"
%token <type> T_TYPE_NUMBER "number (T_TYPE_NUMBER)"
@ -139,20 +145,19 @@ using namespace icinga;
%token T_TO "to (T_TO)"
%token T_WHERE "where (T_WHERE)"
%type <text> identifier
%type <array> array_items
%type <array> array_items_inner
%type <variant> value
%type <expr> expression
%type <exprl> expressions
%type <exprl> expressions_inner
%type <exprl> expressionlist
%type <array> rterm_items
%type <array> rterm_items_inner
%type <array> lterm_items
%type <array> lterm_items_inner
%type <variant> typerulelist
%type <op> operator
%type <op> lbinary_op
%type <op> rbinary_op
%type <type> type
%type <num> partial_specifier
%type <slist> object_inherits_list
%type <slist> object_inherits_specifier
%type <aexpr> aexpression
%type <variant> rterm
%type <variant> lterm
%type <num> variable_decl
%left T_LOGICAL_OR
%left T_LOGICAL_AND
@ -179,14 +184,17 @@ void yyerror(YYLTYPE *locp, ConfigCompiler *, const char *err)
int yyparse(ConfigCompiler *context);
static std::stack<Array::Ptr> m_Arrays;
static bool m_Abstract;
static std::stack<TypeRuleList::Ptr> m_RuleLists;
static ConfigType::Ptr m_Type;
static Dictionary::Ptr m_ModuleScope;
void ConfigCompiler::Compile(void)
{
m_ModuleScope = make_shared<Dictionary>();
try {
yyparse(this);
} catch (const ConfigError& ex) {
@ -208,16 +216,20 @@ statements: /* empty */
statement: object | type | include | include_recursive | library | variable | apply
{ }
| value
| lterm
{
AExpression::Ptr aexpr = *$1;
aexpr->Evaluate(m_ModuleScope);
delete $1;
}
;
include: T_INCLUDE value
include: T_INCLUDE rterm
{
context->HandleInclude(*$2, false, DebugInfoRange(@1, @2));
AExpression::Ptr aexpr = static_cast<AExpression::Ptr>(*$2);
delete $2;
context->HandleInclude(aexpr->Evaluate(m_ModuleScope), false, DebugInfoRange(@1, @2));
}
| T_INCLUDE T_STRING_ANGLE
{
@ -226,16 +238,22 @@ include: T_INCLUDE value
}
;
include_recursive: T_INCLUDE_RECURSIVE value
include_recursive: T_INCLUDE_RECURSIVE rterm
{
context->HandleIncludeRecursive(*$2, "*.conf", DebugInfoRange(@1, @2));
AExpression::Ptr aexpr = static_cast<AExpression::Ptr>(*$2);
delete $2;
context->HandleIncludeRecursive(aexpr->Evaluate(m_ModuleScope), "*.conf", DebugInfoRange(@1, @2));
}
| T_INCLUDE_RECURSIVE value value
| T_INCLUDE_RECURSIVE rterm rterm
{
context->HandleIncludeRecursive(*$2, *$3, DebugInfoRange(@1, @3));
AExpression::Ptr aexpr1 = static_cast<AExpression::Ptr>(*$2);
delete $2;
AExpression::Ptr aexpr2 = static_cast<AExpression::Ptr>(*$3);
delete $3;
context->HandleIncludeRecursive(aexpr1->Evaluate(m_ModuleScope), aexpr2->Evaluate(m_ModuleScope), DebugInfoRange(@1, @3));
}
;
@ -246,22 +264,15 @@ library: T_LIBRARY T_STRING
}
;
variable: variable_decl identifier T_SET value
variable: variable_decl identifier T_SET rterm
{
Value *value = $4;
if (value->IsObjectType<ExpressionList>()) {
Dictionary::Ptr dict = make_shared<Dictionary>();
ExpressionList::Ptr exprl = *value;
exprl->Execute(dict);
delete value;
value = new Value(dict);
}
AExpression::Ptr aexpr = static_cast<AExpression::Ptr>(*$4);
delete $4;
ScriptVariable::Ptr sv = ScriptVariable::Set($2, *value);
ScriptVariable::Ptr sv = ScriptVariable::Set($2, aexpr->Evaluate(m_ModuleScope));
sv->SetConstant(true);
free($2);
delete value;
}
;
@ -399,7 +410,7 @@ object:
{
m_Abstract = false;
}
object_declaration identifier T_STRING object_inherits_specifier expressionlist
object_declaration identifier T_STRING object_inherits_specifier rterm
{
DebugInfo di = DebugInfoRange(@2, @6);
ConfigItemBuilder::Ptr item = make_shared<ConfigItemBuilder>(di);
@ -437,10 +448,11 @@ object:
delete $5;
}
if ($6) {
ExpressionList::Ptr exprl = ExpressionList::Ptr($6);
item->AddExpressionList(exprl);
}
AExpression::Ptr exprl = static_cast<AExpression::Ptr>(*$6);
delete $6;
exprl->MakeInline();
item->AddExpression(exprl);
item->SetAbstract(m_Abstract);
@ -487,96 +499,36 @@ object_inherits_specifier:
}
;
expressionlist: '{' expressions '}'
lbinary_op: T_SET
| T_SET_PLUS
| T_SET_MINUS
| T_SET_MULTIPLY
| T_SET_DIVIDE
{
if ($2)
$$ = $2;
else
$$ = new ExpressionList();
$$ = $1;
}
;
expressions: expressions_inner
lterm_items: lterm_items_inner
{
$$ = $1;
}
| expressions_inner ','
| lterm_items_inner ','
{
$$ = $1;
}
expressions_inner: /* empty */
lterm_items_inner: /* empty */
{
$$ = NULL;
}
| expression
{
$$ = new ExpressionList();
$$->AddExpression(*$1);
delete $1;
}
| expressions_inner ',' expression
{
if ($1)
$$ = $1;
else
$$ = new ExpressionList();
$$->AddExpression(*$3);
delete $3;
}
;
expression: identifier operator value
{
$$ = new Expression($1, $2, *$3, DebugInfoRange(@1, @3));
free($1);
delete $3;
}
| identifier '[' T_STRING ']' operator value
{
Expression subexpr($3, $5, *$6, DebugInfoRange(@1, @6));
free($3);
delete $6;
ExpressionList::Ptr subexprl = make_shared<ExpressionList>();
subexprl->AddExpression(subexpr);
$$ = new Expression($1, OperatorPlus, subexprl, DebugInfoRange(@1, @6));
free($1);
}
;
operator: T_SET
| T_PLUS_EQUAL
| T_MINUS_EQUAL
| T_MULTIPLY_EQUAL
| T_DIVIDE_EQUAL
{
$$ = $1;
}
;
array_items: array_items_inner
{
$$ = $1;
}
| array_items_inner ','
{
$$ = $1;
}
array_items_inner: /* empty */
{
$$ = NULL;
}
| aexpression
| lterm
{
$$ = new Array();
$$->Add(*$1);
delete $1;
}
| array_items_inner ',' aexpression
| lterm_items_inner ',' lterm
{
if ($1)
$$ = $1;
@ -588,7 +540,93 @@ array_items_inner: /* empty */
}
;
aexpression: T_STRING
lterm: T_IDENTIFIER lbinary_op rterm
{
$$ = new Value(make_shared<AExpression>($2, $1, static_cast<AExpression::Ptr>(*$3), DebugInfoRange(@1, @3)));
delete $3;
}
| identifier '[' T_STRING ']' lbinary_op rterm
{
AExpression::Ptr subexpr = make_shared<AExpression>($5, $3, static_cast<AExpression::Ptr>(*$6), DebugInfoRange(@1, @6));
free($3);
delete $6;
Array::Ptr subexprl = make_shared<Array>();
subexprl->Add(subexpr);
AExpression::Ptr expr = make_shared<AExpression>(&AExpression::OpDict, subexprl, DebugInfoRange(@1, @6));
$$ = new Value(make_shared<AExpression>(&AExpression::OpSetPlus, $1, expr, DebugInfoRange(@1, @6)));
free($1);
}
| rterm
{
$$ = $1;
}
;
rbinary_op: T_PLUS
| T_MINUS
| T_MULTIPLY
| T_DIVIDE
| T_BINARY_AND
| T_BINARY_OR
| T_LESS_THAN
| T_GREATER_THAN
| T_LESS_THAN_OR_EQUAL
| T_GREATER_THAN_OR_EQUAL
| T_EQUAL
| T_NOT_EQUAL
| T_IN
| T_NOT_IN
| T_LOGICAL_AND
| T_LOGICAL_OR
| T_SHIFT_LEFT
| T_SHIFT_RIGHT
{
$$ = $1;
}
;
rterm_items: rterm_items_inner
{
$$ = $1;
}
| rterm_items_inner ','
{
$$ = $1;
}
;
rterm_items_inner: /* empty */
{
$$ = NULL;
}
| rterm
{
$$ = new Array();
$$->Add(*$1);
delete $1;
}
| rterm_items_inner ',' rterm
{
if ($1)
$$ = $1;
else
$$ = new Array();
$$->Add(*$3);
delete $3;
}
;
rbinary_op: '+'
{
$$ = &AExpression::OpAdd;
}
;
rterm: T_STRING
{
$$ = new Value(make_shared<AExpression>(&AExpression::OpLiteral, $1, @1));
free($1);
@ -601,7 +639,7 @@ aexpression: T_STRING
{
$$ = new Value(make_shared<AExpression>(&AExpression::OpLiteral, Empty, @1));
}
| T_IDENTIFIER '(' array_items ')'
| T_IDENTIFIER '(' rterm_items ')'
{
Array::Ptr arguments = Array::Ptr($3);
$$ = new Value(make_shared<AExpression>(&AExpression::OpFunctionCall, $1, make_shared<AExpression>(&AExpression::OpLiteral, arguments, @3), DebugInfoRange(@1, @4)));
@ -612,152 +650,41 @@ aexpression: T_STRING
$$ = new Value(make_shared<AExpression>(&AExpression::OpVariable, $1, @1));
free($1);
}
| '!' aexpression
| '!' rterm
{
$$ = new Value(make_shared<AExpression>(&AExpression::OpNegate, static_cast<AExpression::Ptr>(*$2), DebugInfoRange(@1, @2)));
delete $2;
}
| '~' aexpression
| '~' rterm
{
$$ = new Value(make_shared<AExpression>(&AExpression::OpNegate, static_cast<AExpression::Ptr>(*$2), DebugInfoRange(@1, @2)));
delete $2;
}
| '[' array_items ']'
| '[' rterm_items ']'
{
$$ = new Value(make_shared<AExpression>(&AExpression::OpArray, Array::Ptr($2), DebugInfoRange(@1, @3)));
}
| '(' aexpression ')'
| '{' lterm_items '}'
{
$$ = new Value(make_shared<AExpression>(&AExpression::OpDict, Array::Ptr($2), DebugInfoRange(@1, @3)));
}
| '(' rterm ')'
{
$$ = $2;
}
| aexpression '+' aexpression
| rterm rbinary_op rterm
{
$$ = new Value(make_shared<AExpression>(&AExpression::OpAdd, static_cast<AExpression::Ptr>(*$1), static_cast<AExpression::Ptr>(*$3), DebugInfoRange(@1, @3)));
$$ = new Value(make_shared<AExpression>($2, static_cast<AExpression::Ptr>(*$1), static_cast<AExpression::Ptr>(*$3), DebugInfoRange(@1, @3)));
delete $1;
delete $3;
}
| aexpression '-' aexpression
{
$$ = new Value(make_shared<AExpression>(&AExpression::OpSubtract, static_cast<AExpression::Ptr>(*$1), static_cast<AExpression::Ptr>(*$3), DebugInfoRange(@1, @3)));
delete $1;
delete $3;
}
| aexpression '*' aexpression
{
$$ = new Value(make_shared<AExpression>(&AExpression::OpMultiply, static_cast<AExpression::Ptr>(*$1), static_cast<AExpression::Ptr>(*$3), DebugInfoRange(@1, @3)));
delete $1;
delete $3;
}
| aexpression '/' aexpression
{
$$ = new Value(make_shared<AExpression>(&AExpression::OpDivide, static_cast<AExpression::Ptr>(*$1), static_cast<AExpression::Ptr>(*$3), DebugInfoRange(@1, @3)));
delete $1;
delete $3;
}
| aexpression '&' aexpression
{
$$ = new Value(make_shared<AExpression>(&AExpression::OpBinaryAnd, static_cast<AExpression::Ptr>(*$1), static_cast<AExpression::Ptr>(*$3), DebugInfoRange(@1, @3)));
delete $1;
delete $3;
}
| aexpression '|' aexpression
{
$$ = new Value(make_shared<AExpression>(&AExpression::OpBinaryOr, static_cast<AExpression::Ptr>(*$1), static_cast<AExpression::Ptr>(*$3), DebugInfoRange(@1, @2)));
delete $1;
delete $3;
}
| aexpression T_IN aexpression
{
$$ = new Value(make_shared<AExpression>(&AExpression::OpIn, static_cast<AExpression::Ptr>(*$1), static_cast<AExpression::Ptr>(*$3), DebugInfoRange(@1, @3)));
delete $1;
delete $3;
}
| aexpression T_NOT_IN aexpression
{
$$ = new Value(make_shared<AExpression>(&AExpression::OpNotIn, static_cast<AExpression::Ptr>(*$1), static_cast<AExpression::Ptr>(*$3), DebugInfoRange(@1, @3)));
delete $1;
delete $3;
}
| aexpression T_LESS_THAN_OR_EQUAL aexpression
{
$$ = new Value(make_shared<AExpression>(&AExpression::OpLessThanOrEqual, static_cast<AExpression::Ptr>(*$1), static_cast<AExpression::Ptr>(*$3), DebugInfoRange(@1, @3)));
delete $1;
delete $3;
}
| aexpression T_GREATER_THAN_OR_EQUAL aexpression
{
$$ = new Value(make_shared<AExpression>(&AExpression::OpGreaterThanOrEqual, static_cast<AExpression::Ptr>(*$1), static_cast<AExpression::Ptr>(*$3), DebugInfoRange(@1, @3)));
delete $1;
delete $3;
}
| aexpression '<' aexpression
{
$$ = new Value(make_shared<AExpression>(&AExpression::OpLessThan, static_cast<AExpression::Ptr>(*$1), static_cast<AExpression::Ptr>(*$3), DebugInfoRange(@1, @3)));
delete $1;
delete $3;
}
| aexpression '>' aexpression
{
$$ = new Value(make_shared<AExpression>(&AExpression::OpGreaterThan, static_cast<AExpression::Ptr>(*$1), static_cast<AExpression::Ptr>(*$3), DebugInfoRange(@1, @3)));
delete $1;
delete $3;
}
| aexpression T_EQUAL aexpression
{
$$ = new Value(make_shared<AExpression>(&AExpression::OpEqual, static_cast<AExpression::Ptr>(*$1), static_cast<AExpression::Ptr>(*$3), DebugInfoRange(@1, @3)));
delete $1;
delete $3;
}
| aexpression T_NOT_EQUAL aexpression
{
$$ = new Value(make_shared<AExpression>(&AExpression::OpNotEqual, static_cast<AExpression::Ptr>(*$1), static_cast<AExpression::Ptr>(*$3), DebugInfoRange(@1, @3)));
delete $1;
delete $3;
}
| aexpression T_SHIFT_LEFT aexpression
{
$$ = new Value(make_shared<AExpression>(&AExpression::OpShiftLeft, static_cast<AExpression::Ptr>(*$1), static_cast<AExpression::Ptr>(*$3), DebugInfoRange(@1, @3)));
delete $1;
delete $3;
}
| aexpression T_SHIFT_RIGHT aexpression
{
$$ = new Value(make_shared<AExpression>(&AExpression::OpShiftRight, static_cast<AExpression::Ptr>(*$1), static_cast<AExpression::Ptr>(*$3), DebugInfoRange(@1, @3)));
delete $1;
delete $3;
}
| aexpression T_LOGICAL_AND aexpression
{
$$ = new Value(make_shared<AExpression>(&AExpression::OpLogicalAnd, static_cast<AExpression::Ptr>(*$1), static_cast<AExpression::Ptr>(*$3), DebugInfoRange(@1, @3)));
delete $1;
delete $3;
}
| aexpression T_LOGICAL_OR aexpression
{
$$ = new Value(make_shared<AExpression>(&AExpression::OpLogicalOr, static_cast<AExpression::Ptr>(*$1), static_cast<AExpression::Ptr>(*$3), DebugInfoRange(@1, @3)));
delete $1;
delete $3;
}
;
value: expressionlist
{
ExpressionList::Ptr exprl = ExpressionList::Ptr($1);
$$ = new Value(exprl);
}
| aexpression
{
AExpression::Ptr aexpr = *$1;
$$ = new Value(aexpr->Evaluate(Dictionary::Ptr()));
delete $1;
}
;
optional_template: /* empty */
| T_TEMPLATE
;
apply: T_APPLY optional_template identifier identifier T_TO identifier T_WHERE aexpression
apply: T_APPLY optional_template identifier identifier T_TO identifier T_WHERE rterm
{
if (!ApplyRule::IsValidCombination($3, $6)) {
BOOST_THROW_EXCEPTION(ConfigError("'apply' cannot be used with types '" + String($3) + "' and '" + String($6) + "'.") << errinfo_debuginfo(@1));

View File

@ -48,7 +48,7 @@ ConfigItem::ItemMap ConfigItem::m_Items;
* @param debuginfo Debug information.
*/
ConfigItem::ConfigItem(const String& type, const String& name,
bool abstract, const ExpressionList::Ptr& exprl,
bool abstract, const AExpression::Ptr& exprl,
const std::vector<String>& parents, const DebugInfo& debuginfo)
: m_Type(type), m_Name(name), m_Abstract(abstract), m_Validated(false),
m_ExpressionList(exprl), m_ParentNames(parents), m_DebugInfo(debuginfo)
@ -100,19 +100,19 @@ DebugInfo ConfigItem::GetDebugInfo(void) const
*
* @returns The expression list.
*/
ExpressionList::Ptr ConfigItem::GetExpressionList(void) const
AExpression::Ptr ConfigItem::GetExpressionList(void) const
{
return m_ExpressionList;
}
ExpressionList::Ptr ConfigItem::GetLinkedExpressionList(void)
AExpression::Ptr ConfigItem::GetLinkedExpressionList(void)
{
ASSERT(OwnsLock());
if (m_LinkedExpressionList)
return m_LinkedExpressionList;
m_LinkedExpressionList = make_shared<ExpressionList>();
Array::Ptr subexprs = make_shared<Array>();
BOOST_FOREACH(const String& name, m_ParentNames) {
ConfigItem::Ptr parent = ConfigItem::GetObject(m_Type, name);
@ -123,18 +123,20 @@ ExpressionList::Ptr ConfigItem::GetLinkedExpressionList(void)
" exist (" << m_DebugInfo << ")";
ConfigCompilerContext::GetInstance()->AddMessage(true, message.str(), m_DebugInfo);
} else {
ExpressionList::Ptr pexprl;
AExpression::Ptr pexprl;
{
ObjectLock olock(parent);
pexprl = parent->GetLinkedExpressionList();
}
m_LinkedExpressionList->AddExpression(Expression("", OperatorExecute, pexprl, m_DebugInfo));
subexprs->Add(pexprl);
}
}
m_LinkedExpressionList->AddExpression(Expression("", OperatorExecute, m_ExpressionList, m_DebugInfo));
subexprs->Add(m_ExpressionList);
m_LinkedExpressionList = make_shared<AExpression>(&AExpression::OpDict, subexprs, true, m_DebugInfo);
return m_LinkedExpressionList;
}
@ -144,7 +146,7 @@ Dictionary::Ptr ConfigItem::GetProperties(void)
ASSERT(OwnsLock());
Dictionary::Ptr properties = make_shared<Dictionary>();
GetLinkedExpressionList()->Execute(properties);
GetLinkedExpressionList()->Evaluate(properties);
return properties;
}

View File

@ -21,7 +21,7 @@
#define CONFIGITEM_H
#include "config/i2-config.h"
#include "config/expressionlist.h"
#include "config/aexpression.h"
#include "base/dynamicobject.h"
namespace icinga
@ -45,7 +45,7 @@ public:
DECLARE_PTR_TYPEDEFS(ConfigItem);
ConfigItem(const String& type, const String& name, bool abstract,
const ExpressionList::Ptr& exprl, const std::vector<String>& parents,
const AExpression::Ptr& exprl, const std::vector<String>& parents,
const DebugInfo& debuginfo);
String GetType(void) const;
@ -54,7 +54,7 @@ public:
std::vector<ConfigItem::Ptr> GetParents(void) const;
ExpressionList::Ptr GetLinkedExpressionList(void);
AExpression::Ptr GetLinkedExpressionList(void);
Dictionary::Ptr GetProperties(void);
DynamicObject::Ptr Commit(void);
@ -72,21 +72,21 @@ public:
static void DiscardItems(void);
private:
ExpressionList::Ptr GetExpressionList(void) const;
AExpression::Ptr GetExpressionList(void) const;
String m_Type; /**< The object type. */
String m_Name; /**< The name. */
bool m_Abstract; /**< Whether this is a template. */
bool m_Validated; /** Whether this object has been validated. */
ExpressionList::Ptr m_ExpressionList;
AExpression::Ptr m_ExpressionList;
std::vector<String> m_ParentNames; /**< The names of parent configuration
items. */
DebugInfo m_DebugInfo; /**< Debug information. */
ExpressionList::Ptr m_LinkedExpressionList;
AExpression::Ptr m_LinkedExpressionList;
DynamicObject::Ptr m_Object;
DynamicObject::Ptr m_Object;
static boost::mutex m_Mutex;

View File

@ -26,7 +26,7 @@
using namespace icinga;
ConfigItemBuilder::ConfigItemBuilder(void)
: m_Abstract(false), m_ExpressionList(make_shared<ExpressionList>())
: m_Abstract(false), m_Expressions(make_shared<Array>())
{
m_DebugInfo.FirstLine = 0;
m_DebugInfo.FirstColumn = 0;
@ -35,7 +35,7 @@ ConfigItemBuilder::ConfigItemBuilder(void)
}
ConfigItemBuilder::ConfigItemBuilder(const DebugInfo& debugInfo)
: m_Abstract(false), m_ExpressionList(make_shared<ExpressionList>())
: m_Abstract(false), m_Expressions(make_shared<Array>())
{
m_DebugInfo = debugInfo;
}
@ -60,21 +60,9 @@ void ConfigItemBuilder::AddParent(const String& parent)
m_Parents.push_back(parent);
}
void ConfigItemBuilder::AddExpression(const Expression& expr)
void ConfigItemBuilder::AddExpression(const AExpression::Ptr& expr)
{
m_ExpressionList->AddExpression(expr);
}
void ConfigItemBuilder::AddExpression(const String& key, ExpressionOperator op,
const Value& value)
{
Expression expr(key, op, value, m_DebugInfo);
AddExpression(expr);
}
void ConfigItemBuilder::AddExpressionList(const ExpressionList::Ptr& exprl)
{
AddExpression("", OperatorExecute, exprl);
m_Expressions->Add(expr);
}
ConfigItem::Ptr ConfigItemBuilder::Compile(void)
@ -102,16 +90,12 @@ ConfigItem::Ptr ConfigItemBuilder::Compile(void)
BOOST_THROW_EXCEPTION(std::invalid_argument("Configuration item '" + m_Name + "' of type '" + m_Type + "' must not inherit from itself."));
}
ExpressionList::Ptr exprl = make_shared<ExpressionList>();
Array::Ptr exprs = make_shared<Array>();
exprs->Add(make_shared<AExpression>(&AExpression::OpDict, m_Expressions, true, m_DebugInfo));
exprs->Add(make_shared<AExpression>(&AExpression::OpSet, "__type", make_shared<AExpression>(&AExpression::OpLiteral, m_Type, m_DebugInfo), m_DebugInfo));
exprs->Add(make_shared<AExpression>(&AExpression::OpSet, "__name", make_shared<AExpression>(&AExpression::OpLiteral, m_Name, m_DebugInfo), m_DebugInfo));
Expression execExpr("", OperatorExecute, m_ExpressionList, m_DebugInfo);
exprl->AddExpression(execExpr);
Expression typeExpr("__type", OperatorSet, m_Type, m_DebugInfo);
exprl->AddExpression(typeExpr);
Expression nameExpr("__name", OperatorSet, m_Name, m_DebugInfo);
exprl->AddExpression(nameExpr);
AExpression::Ptr exprl = make_shared<AExpression>(&AExpression::OpDict, exprs, true, m_DebugInfo);
return make_shared<ConfigItem>(m_Type, m_Name, m_Abstract, exprl,
m_Parents, m_DebugInfo);

View File

@ -21,8 +21,7 @@
#define CONFIGITEMBUILDER_H
#include "config/debuginfo.h"
#include "config/expression.h"
#include "config/expressionlist.h"
#include "config/aexpression.h"
#include "config/configitem.h"
#include "base/object.h"
@ -49,10 +48,7 @@ public:
void AddParent(const String& parent);
void AddExpression(const Expression& expr);
void AddExpression(const String& key, ExpressionOperator op,
const Value& value);
void AddExpressionList(const ExpressionList::Ptr& exprl);
void AddExpression(const AExpression::Ptr& expr);
ConfigItem::Ptr Compile(void);
@ -62,7 +58,7 @@ private:
bool m_Abstract; /**< Whether the item is abstract. */
std::vector<String> m_Parents; /**< The names of parent configuration
items. */
ExpressionList::Ptr m_ExpressionList; /**< Expressions for this item. */
Array::Ptr m_Expressions; /**< Expressions for this item. */
DebugInfo m_DebugInfo; /**< Debug information. */
};

View File

@ -1,204 +0,0 @@
/******************************************************************************
* Icinga 2 *
* Copyright (C) 2012-2014 Icinga Development Team (http://www.icinga.org) *
* *
* 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. *
******************************************************************************/
#include "config/expression.h"
#include "config/expressionlist.h"
#include "base/objectlock.h"
#include "base/debug.h"
#include "base/array.h"
#include <sstream>
#include <boost/foreach.hpp>
using namespace icinga;
Expression::Expression(const String& key, ExpressionOperator op,
const Value& value, const DebugInfo& debuginfo)
: m_Key(key), m_Operator(op), m_Value(value), m_DebugInfo(debuginfo)
{
ASSERT(op != OperatorExecute || value.IsObjectType<ExpressionList>());
}
Value Expression::DeepClone(const Value& value)
{
if (value.IsObjectType<Array>()) {
Array::Ptr array = value;
Array::Ptr result = make_shared<Array>();
ObjectLock olock(array);
BOOST_FOREACH(const Value& item, array) {
result->Add(DeepClone(item));
}
return result;
} else if (value.IsObjectType<Dictionary>()) {
Dictionary::Ptr dict = value;
Dictionary::Ptr result = make_shared<Dictionary>();
ObjectLock olock(dict);
BOOST_FOREACH(const Dictionary::Pair& kv, dict) {
result->Set(kv.first, DeepClone(kv.second));
}
return result;
}
return value;
}
void Expression::Execute(const Dictionary::Ptr& dictionary) const
{
Value oldValue, newValue;
ExpressionList::Ptr valueExprl;
Dictionary::Ptr valueDict;
Array::Ptr valueArray;
if (m_Value.IsObjectType<ExpressionList>())
valueExprl = m_Value;
if (m_Value.IsObjectType<Dictionary>())
valueDict = m_Value;
if (m_Value.IsObjectType<Array>())
valueArray = m_Value;
newValue = m_Value;
Dictionary::Ptr dict;
Array::Ptr array;
switch (m_Operator) {
case OperatorExecute:
if (!valueExprl)
BOOST_THROW_EXCEPTION(std::invalid_argument("Operand for OperatorExecute must be an ExpressionList."));
valueExprl->Execute(dictionary);
return;
case OperatorSet:
if (valueExprl) {
dict = make_shared<Dictionary>();
valueExprl->Execute(dict);
newValue = dict;
} else {
newValue = DeepClone(newValue);
}
break;
case OperatorPlus:
oldValue = dictionary->Get(m_Key);
if (oldValue.IsObjectType<Dictionary>())
dict = oldValue;
if (oldValue.IsObjectType<Array>())
array = oldValue;
if (valueExprl) {
if (!dict)
dict = make_shared<Dictionary>();
valueExprl->Execute(dict);
newValue = dict;
} else if (valueDict) {
if (!dict)
dict = make_shared<Dictionary>();
ObjectLock olock(valueDict);
String key;
Value value;
BOOST_FOREACH(const Dictionary::Pair& kv, valueDict) {
dict->Set(kv.first, DeepClone(kv.second));
}
newValue = dict;
} else if (valueArray) {
if (!array)
array = make_shared<Array>();
ObjectLock olock(valueArray);
BOOST_FOREACH(const Value& value, valueArray) {
array->Add(DeepClone(value));
}
newValue = array;
} else {
std::ostringstream message;
message << "+= only works for dictionaries and arrays ("
<< m_DebugInfo << ")";
BOOST_THROW_EXCEPTION(std::invalid_argument(message.str()));
}
break;
default:
BOOST_THROW_EXCEPTION(std::runtime_error("Not yet implemented."));
}
dictionary->Set(m_Key, newValue);
}
void Expression::ExtractPath(const std::vector<String>& path, const ExpressionList::Ptr& result) const
{
ASSERT(!path.empty());
if (path[0] == m_Key) {
if (!m_Value.IsObjectType<ExpressionList>())
BOOST_THROW_EXCEPTION(std::invalid_argument("Specified path does not exist."));
ExpressionList::Ptr exprl = m_Value;
if (path.size() == 1) {
result->AddExpression(Expression("", OperatorExecute, exprl, m_DebugInfo));
return;
}
std::vector<String> sub_path(path.begin() + 1, path.end());
exprl->ExtractPath(sub_path, result);
} else if (m_Operator == OperatorExecute) {
ExpressionList::Ptr exprl = m_Value;
exprl->ExtractPath(path, result);
}
}
void Expression::FindDebugInfoPath(const std::vector<String>& path, DebugInfo& result) const
{
ASSERT(!path.empty());
if (path[0] == m_Key) {
if (path.size() == 1) {
result = m_DebugInfo;
} else if (m_Value.IsObjectType<ExpressionList>()) {
ExpressionList::Ptr exprl = m_Value;
std::vector<String> sub_path(path.begin() + 1, path.end());
exprl->FindDebugInfoPath(sub_path, result);
}
} else if (m_Operator == OperatorExecute) {
ExpressionList::Ptr exprl = m_Value;
exprl->FindDebugInfoPath(path, result);
}
}

View File

@ -1,78 +0,0 @@
/******************************************************************************
* Icinga 2 *
* Copyright (C) 2012-2014 Icinga Development Team (http://www.icinga.org) *
* *
* 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. *
******************************************************************************/
#ifndef EXPRESSION_H
#define EXPRESSION_H
#include "config/i2-config.h"
#include "config/debuginfo.h"
#include "base/dictionary.h"
#include <iostream>
#include <vector>
#include <set>
namespace icinga
{
/**
* The operator in a configuration expression.
*
* @ingroup config
*/
enum ExpressionOperator
{
OperatorExecute,
OperatorSet,
OperatorPlus,
OperatorMinus,
OperatorMultiply,
OperatorDivide
};
class ExpressionList;
/**
* A configuration expression.
*
* @ingroup config
*/
struct I2_CONFIG_API Expression
{
public:
Expression(const String& key, ExpressionOperator op, const Value& value,
const DebugInfo& debuginfo);
void Execute(const Dictionary::Ptr& dictionary) const;
void ExtractPath(const std::vector<String>& path, const shared_ptr<ExpressionList>& result) const;
void FindDebugInfoPath(const std::vector<String>& path, DebugInfo& result) const;
private:
String m_Key;
ExpressionOperator m_Operator;
Value m_Value;
DebugInfo m_DebugInfo;
static Value DeepClone(const Value& value);
};
}
#endif /* EXPRESSION_H */

View File

@ -1,60 +0,0 @@
/******************************************************************************
* Icinga 2 *
* Copyright (C) 2012-2014 Icinga Development Team (http://www.icinga.org) *
* *
* 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. *
******************************************************************************/
#include "config/expressionlist.h"
#include <boost/foreach.hpp>
using namespace icinga;
/**
* Adds an expression to an expression list.
*
* @param expression The expression that should be added.
*/
void ExpressionList::AddExpression(const Expression& expression)
{
m_Expressions.push_back(expression);
}
/**
* Executes the expression list.
*
* @param dictionary The dictionary that should be manipulated by the
* expressions.
*/
void ExpressionList::Execute(const Dictionary::Ptr& dictionary) const
{
BOOST_FOREACH(const Expression& expression, m_Expressions) {
expression.Execute(dictionary);
}
}
void ExpressionList::ExtractPath(const std::vector<String>& path, const ExpressionList::Ptr& result) const
{
BOOST_FOREACH(const Expression& expression, m_Expressions) {
expression.ExtractPath(path, result);
}
}
void ExpressionList::FindDebugInfoPath(const std::vector<String>& path, DebugInfo& result) const
{
BOOST_FOREACH(const Expression& expression, m_Expressions) {
expression.FindDebugInfoPath(path, result);
}
}

View File

@ -1,55 +0,0 @@
/******************************************************************************
* Icinga 2 *
* Copyright (C) 2012-2014 Icinga Development Team (http://www.icinga.org) *
* *
* 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. *
******************************************************************************/
#ifndef EXPRESSIONLIST_H
#define EXPRESSIONLIST_H
#include "config/i2-config.h"
#include "config/expression.h"
#include "base/dictionary.h"
#include <vector>
namespace icinga
{
/**
* A list of configuration expressions.
*
* @ingroup config
*/
class I2_CONFIG_API ExpressionList : public Object
{
public:
DECLARE_PTR_TYPEDEFS(ExpressionList);
void AddExpression(const Expression& expression);
void Execute(const Dictionary::Ptr& dictionary) const;
void ExtractPath(const std::vector<String>& path, const ExpressionList::Ptr& result) const;
void FindDebugInfoPath(const std::vector<String>& path, DebugInfo& result) const;
private:
std::vector<Expression> m_Expressions;
};
}
#endif /* EXPRESSIONLIST_H */

View File

@ -77,7 +77,7 @@ void Host::EvaluateApplyRules(const std::vector<ApplyRule>& rules)
ConfigItemBuilder::Ptr builder = make_shared<ConfigItemBuilder>(rule.GetDebugInfo());
builder->SetType("Service");
builder->SetName(name);
builder->AddExpression("host", OperatorSet, host->GetName());
builder->AddExpression(make_shared<AExpression>(&AExpression::OpSet, "host", make_shared<AExpression>(&AExpression::OpLiteral, host->GetName(), rule.GetDebugInfo()), rule.GetDebugInfo()));
builder->AddParent(rule.GetTemplate());

View File

@ -113,7 +113,7 @@ void Host::UpdateSlaveServices(void)
path.push_back("services");
path.push_back(kv.first);
ExpressionList::Ptr exprl;
AExpression::Ptr exprl;
{
ObjectLock ilock(item);
@ -130,9 +130,9 @@ void Host::UpdateSlaveServices(void)
ConfigItemBuilder::Ptr builder = make_shared<ConfigItemBuilder>(di);
builder->SetType("Service");
builder->SetName(name);
builder->AddExpression("host", OperatorSet, GetName());
builder->AddExpression("display_name", OperatorSet, kv.first);
builder->AddExpression("short_name", OperatorSet, kv.first);
builder->AddExpression(make_shared<AExpression>(&AExpression::OpSet, "host", make_shared<AExpression>(&AExpression::OpLiteral, GetName(), di), di));
builder->AddExpression(make_shared<AExpression>(&AExpression::OpSet, "display_name", make_shared<AExpression>(&AExpression::OpLiteral, kv.first, di), di));
builder->AddExpression(make_shared<AExpression>(&AExpression::OpSet, "short_name", make_shared<AExpression>(&AExpression::OpLiteral, kv.first, di), di));
if (!kv.second.IsObjectType<Dictionary>())
BOOST_THROW_EXCEPTION(std::invalid_argument("Service description must be either a string or a dictionary."));
@ -150,10 +150,10 @@ void Host::UpdateSlaveServices(void)
}
/* Clone attributes from the service expression list. */
ExpressionList::Ptr svc_exprl = make_shared<ExpressionList>();
Array::Ptr svc_exprl = make_shared<Array>();
exprl->ExtractPath(path, svc_exprl);
builder->AddExpressionList(svc_exprl);
builder->AddExpression(make_shared<AExpression>(&AExpression::OpDict, svc_exprl, true, di));
ConfigItem::Ptr serviceItem = builder->Compile();
serviceItem->Register();

View File

@ -193,7 +193,7 @@ void Service::UpdateSlaveDependencies(void)
path.push_back("dependencies");
path.push_back(kv.first);
ExpressionList::Ptr exprl;
AExpression::Ptr exprl;
{
ObjectLock ilock(item);
@ -210,8 +210,8 @@ void Service::UpdateSlaveDependencies(void)
ConfigItemBuilder::Ptr builder = make_shared<ConfigItemBuilder>(di);
builder->SetType("Dependency");
builder->SetName(name);
builder->AddExpression("child_host", OperatorSet, GetHost()->GetName());
builder->AddExpression("child_service", OperatorSet, GetShortName());
builder->AddExpression(make_shared<AExpression>(&AExpression::OpSet, "child_host", make_shared<AExpression>(&AExpression::OpLiteral, GetHost()->GetName(), di), di));
builder->AddExpression(make_shared<AExpression>(&AExpression::OpSet, "child_service", make_shared<AExpression>(&AExpression::OpLiteral, GetShortName(), di), di));
Dictionary::Ptr dependency = kv.second;
@ -226,10 +226,10 @@ void Service::UpdateSlaveDependencies(void)
}
/* Clone attributes from the scheduled downtime expression list. */
ExpressionList::Ptr sd_exprl = make_shared<ExpressionList>();
Array::Ptr sd_exprl = make_shared<Array>();
exprl->ExtractPath(path, sd_exprl);
builder->AddExpressionList(sd_exprl);
builder->AddExpression(make_shared<AExpression>(&AExpression::OpDict, sd_exprl, true, di));
ConfigItem::Ptr dependencyItem = builder->Compile();
dependencyItem->Register();

View File

@ -342,7 +342,7 @@ void Service::UpdateSlaveScheduledDowntimes(void)
path.push_back("scheduled_downtimes");
path.push_back(kv.first);
ExpressionList::Ptr exprl;
AExpression::Ptr exprl;
{
ObjectLock ilock(item);
@ -359,8 +359,8 @@ void Service::UpdateSlaveScheduledDowntimes(void)
ConfigItemBuilder::Ptr builder = make_shared<ConfigItemBuilder>(di);
builder->SetType("ScheduledDowntime");
builder->SetName(name);
builder->AddExpression("host", OperatorSet, GetHost()->GetName());
builder->AddExpression("service", OperatorSet, GetShortName());
builder->AddExpression(make_shared<AExpression>(&AExpression::OpSet, "host", make_shared<AExpression>(&AExpression::OpLiteral, GetHost()->GetName(), di), di));
builder->AddExpression(make_shared<AExpression>(&AExpression::OpSet, "service", make_shared<AExpression>(&AExpression::OpLiteral, GetShortName(), di), di));
Dictionary::Ptr scheduledDowntime = kv.second;
@ -375,10 +375,10 @@ void Service::UpdateSlaveScheduledDowntimes(void)
}
/* Clone attributes from the scheduled downtime expression list. */
ExpressionList::Ptr sd_exprl = make_shared<ExpressionList>();
Array::Ptr sd_exprl = make_shared<Array>();
exprl->ExtractPath(path, sd_exprl);
builder->AddExpressionList(sd_exprl);
builder->AddExpression(make_shared<AExpression>(&AExpression::OpDict, sd_exprl, true, di));
ConfigItem::Ptr scheduledDowntimeItem = builder->Compile();
scheduledDowntimeItem->Register();

View File

@ -121,7 +121,7 @@ void Service::UpdateSlaveNotifications(void)
path.push_back("notifications");
path.push_back(kv.first);
ExpressionList::Ptr exprl;
AExpression::Ptr exprl;
{
ObjectLock ilock(item);
@ -138,8 +138,8 @@ void Service::UpdateSlaveNotifications(void)
ConfigItemBuilder::Ptr builder = make_shared<ConfigItemBuilder>(di);
builder->SetType("Notification");
builder->SetName(name);
builder->AddExpression("host", OperatorSet, GetHost()->GetName());
builder->AddExpression("service", OperatorSet, GetShortName());
builder->AddExpression(make_shared<AExpression>(&AExpression::OpSet, "host", make_shared<AExpression>(&AExpression::OpLiteral, GetHost()->GetName(), di), di));
builder->AddExpression(make_shared<AExpression>(&AExpression::OpSet, "service", make_shared<AExpression>(&AExpression::OpLiteral, GetShortName(), di), di));
Dictionary::Ptr notification = kv.second;
@ -154,10 +154,10 @@ void Service::UpdateSlaveNotifications(void)
}
/* Clone attributes from the notification expression list. */
ExpressionList::Ptr nfc_exprl = make_shared<ExpressionList>();
Array::Ptr nfc_exprl = make_shared<Array>();
exprl->ExtractPath(path, nfc_exprl);
builder->AddExpressionList(nfc_exprl);
builder->AddExpression(make_shared<AExpression>(&AExpression::OpDict, nfc_exprl, true, di));
ConfigItem::Ptr notificationItem = builder->Compile();
notificationItem->Register();

View File

@ -18,7 +18,7 @@
add_library(methods SHARED
castfuncs.cpp icingachecktask.cpp nullchecktask.cpp nulleventtask.cpp
pluginchecktask.cpp plugineventtask.cpp pluginnotificationtask.cpp
randomchecktask.cpp timeperiodtask.cpp utilityfuncs.cpp
randomchecktask.cpp timeperiodtask.cpp
)
target_link_libraries(methods ${Boost_LIBRARIES} base config icinga)