From: Gunnar Beutner Date: Sat, 3 May 2014 18:01:23 +0000 (+0200) Subject: Implement support for the "package" keyword. X-Git-Tag: v0.0.11~78 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b1dab6c07461ad59c659340211cd6f5cf9e45900;p=icinga2 Implement support for the "package" keyword. Refs #6107 --- diff --git a/lib/base/dynamicobject.ti b/lib/base/dynamicobject.ti index 04ac40d26..6adbcc5ef 100644 --- a/lib/base/dynamicobject.ti +++ b/lib/base/dynamicobject.ti @@ -20,6 +20,7 @@ abstract class DynamicObject }}} }; [config, get_protected] String type (TypeName); + [config] String package; [config, get_protected] Array::Ptr templates; [config] Dictionary::Ptr methods; [config] Dictionary::Ptr vars (VarsRaw); diff --git a/lib/config/aexpression.cpp b/lib/config/aexpression.cpp index 81ba0290f..8d152188f 100644 --- a/lib/config/aexpression.cpp +++ b/lib/config/aexpression.cpp @@ -523,6 +523,7 @@ Value AExpression::OpObject(const AExpression* expr, const Dictionary::Ptr& loca String type = left->Get(1); AExpression::Ptr aname = left->Get(2); AExpression::Ptr filter = left->Get(3); + String package = left->Get(4); String name = aname->Evaluate(locals); @@ -560,6 +561,7 @@ Value AExpression::OpObject(const AExpression* expr, const Dictionary::Ptr& loca item->AddExpression(exprl); item->SetAbstract(abstract); item->SetScope(locals); + item->SetPackage(package); item->Compile()->Register(); ObjectRule::AddRule(type, name, exprl, filter, expr->m_DebugInfo, locals); diff --git a/lib/config/base-type.conf b/lib/config/base-type.conf index 75c3a6d5f..46ee8b606 100644 --- a/lib/config/base-type.conf +++ b/lib/config/base-type.conf @@ -24,6 +24,8 @@ %require "type", %attribute %string "type", + %attribute %string "package", + %attribute %array "templates" { %attribute %string "*" }, diff --git a/lib/config/config_lexer.ll b/lib/config/config_lexer.ll index 017affc0a..c7564e46a 100644 --- a/lib/config/config_lexer.ll +++ b/lib/config/config_lexer.ll @@ -231,6 +231,7 @@ ignore return T_IGNORE; function return T_FUNCTION; lambda return T_LAMBDA; return return T_RETURN; +package return T_PACKAGE; \<\< { 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 841105eb7..4dd436dbb 100644 --- a/lib/config/config_parser.yy +++ b/lib/config/config_parser.yy @@ -160,6 +160,7 @@ static void MakeRBinaryOp(Value** result, AExpression::OpCallback& op, Value *le %token T_FUNCTION "function (T_FUNCTION)" %token T_LAMBDA "lambda (T_LAMBDA)" %token T_RETURN "return (T_RETURN)" +%token T_PACKAGE "package (T_PACKAGE)" %type identifier %type rterm_items @@ -213,6 +214,8 @@ static std::stack m_RuleLists; static ConfigType::Ptr m_Type; static Dictionary::Ptr m_ModuleScope; +static String m_Package; +static int m_StatementNum; static bool m_Apply; static bool m_ObjectAssign; @@ -223,6 +226,10 @@ static AExpression::Ptr m_Ignore; void ConfigCompiler::Compile(void) { m_ModuleScope = make_shared(); + + String parentPackage = m_Package; + int parentStatementNum = m_StatementNum; + m_StatementNum = 0; try { yyparse(this); @@ -232,6 +239,9 @@ void ConfigCompiler::Compile(void) } catch (const std::exception& ex) { ConfigCompilerContext::GetInstance()->AddMessage(true, DiagnosticInformation(ex)); } + + m_Package = parentPackage; + m_StatementNum = parentStatementNum; } #define scanner (context->GetScanner()) @@ -243,13 +253,54 @@ statements: /* empty */ | statements statement ; -statement: type | include | include_recursive | library | constant | newlines +statement: type | package | include | include_recursive | library | constant + { + m_StatementNum++; + } + | newlines { } | lterm { AExpression::Ptr aexpr = *$1; aexpr->Evaluate(m_ModuleScope); delete $1; + + m_StatementNum++; + } + ; + +package: T_PACKAGE rterm sep + { + AExpression::Ptr aexpr = *$2; + delete $2; + + if (!m_Package.IsEmpty()) + BOOST_THROW_EXCEPTION(std::invalid_argument("Package name cannot be changed once it's been set.")); + + if (m_StatementNum != 0) + BOOST_THROW_EXCEPTION(std::invalid_argument("'package' directive must be the first statement in a file.")); + + m_Package = aexpr->Evaluate(m_ModuleScope); + } + | T_PACKAGE rterm rterm_scope sep + { + AExpression::Ptr aexpr = *$2; + delete $2; + + AExpression::Ptr ascope = *$3; + delete $3; + + if (!m_Package.IsEmpty()) + BOOST_THROW_EXCEPTION(std::invalid_argument("Package name cannot be changed once it's been set.")); + + m_Package = aexpr->Evaluate(m_ModuleScope); + + try { + ascope->Evaluate(m_ModuleScope); + m_Package = String(); + } catch (...) { + m_Package = String(); + } } ; @@ -433,7 +484,7 @@ object: m_Assign = make_shared(&AExpression::OpLiteral, false, DebugInfo()); m_Ignore = make_shared(&AExpression::OpLiteral, false, DebugInfo()); } - object_declaration identifier rterm rterm_scope sep + object_declaration identifier rterm rterm_scope { m_ObjectAssign = false; @@ -460,6 +511,8 @@ object: args->Add(filter); + args->Add(m_Package); + $$ = new Value(make_shared(&AExpression::OpObject, args, exprl, DebugInfoRange(@2, @5))); m_Assign.reset(); diff --git a/lib/config/configitem.cpp b/lib/config/configitem.cpp index 194fa9c27..e405d8dff 100644 --- a/lib/config/configitem.cpp +++ b/lib/config/configitem.cpp @@ -49,10 +49,11 @@ ConfigItem::ItemMap ConfigItem::m_Items; */ ConfigItem::ConfigItem(const String& type, const String& name, bool abstract, const AExpression::Ptr& exprl, - const DebugInfo& debuginfo, const Dictionary::Ptr& scope) + const DebugInfo& debuginfo, const Dictionary::Ptr& scope, + const String& package) : m_Type(type), m_Name(name), m_Abstract(abstract), m_Validated(false), m_ExpressionList(exprl), m_DebugInfo(debuginfo), - m_Scope(scope) + m_Scope(scope), m_Package(package) { } diff --git a/lib/config/configitem.h b/lib/config/configitem.h index 370195ec8..743d111c2 100644 --- a/lib/config/configitem.h +++ b/lib/config/configitem.h @@ -39,7 +39,7 @@ public: ConfigItem(const String& type, const String& name, bool abstract, const AExpression::Ptr& exprl, const DebugInfo& debuginfo, - const Dictionary::Ptr& scope); + const Dictionary::Ptr& scope, const String& package); String GetType(void) const; String GetName(void) const; @@ -57,6 +57,8 @@ public: Dictionary::Ptr GetScope(void) const; + String GetPackage(void) const; + static ConfigItem::Ptr GetObject(const String& type, const String& name); static bool HasObject(const String& type, const String& name); @@ -79,6 +81,7 @@ private: items. */ DebugInfo m_DebugInfo; /**< Debug information. */ Dictionary::Ptr m_Scope; /**< variable scope. */ + String m_Package; /**< The package. */ DynamicObject::Ptr m_Object; diff --git a/lib/config/configitembuilder.cpp b/lib/config/configitembuilder.cpp index 4a6a8d6dd..3d2901654 100644 --- a/lib/config/configitembuilder.cpp +++ b/lib/config/configitembuilder.cpp @@ -60,6 +60,11 @@ void ConfigItemBuilder::SetScope(const Dictionary::Ptr& scope) m_Scope = scope; } +void ConfigItemBuilder::SetPackage(const String& package) +{ + m_Package = package; +} + void ConfigItemBuilder::AddExpression(const AExpression::Ptr& expr) { m_Expressions->Add(expr); @@ -99,5 +104,5 @@ ConfigItem::Ptr ConfigItemBuilder::Compile(void) AExpression::Ptr exprl = make_shared(&AExpression::OpDict, exprs, true, m_DebugInfo); return make_shared(m_Type, m_Name, m_Abstract, exprl, - m_DebugInfo, m_Scope); + m_DebugInfo, m_Scope, m_Package); } diff --git a/lib/config/configitembuilder.h b/lib/config/configitembuilder.h index 14537f1d8..c9609a9cd 100644 --- a/lib/config/configitembuilder.h +++ b/lib/config/configitembuilder.h @@ -46,6 +46,7 @@ public: void SetName(const String& name); void SetAbstract(bool abstract); void SetScope(const Dictionary::Ptr& scope); + void SetPackage(const String& name); void AddExpression(const AExpression::Ptr& expr); @@ -58,6 +59,7 @@ private: Array::Ptr m_Expressions; /**< Expressions for this item. */ DebugInfo m_DebugInfo; /**< Debug information. */ Dictionary::Ptr m_Scope; /**< variable scope. */ + String m_Package; /**< The package. */ }; }