From 33aba14197045b7a0bea31ab09c1625e2f32fce4 Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Sat, 2 Feb 2013 14:28:11 +0100 Subject: [PATCH] Implement type keyword in the config compiler Fixes #3616 --- icinga-app/icinga.cpp | 33 +- itl/Makefile.am | 9 +- itl/{itl-host.conf => host.conf} | 0 itl/itl.conf | 8 +- ...ervice-common.conf => service-common.conf} | 0 itl/{itl-service.conf => service.conf} | 0 itl/{itl-standalone.conf => standalone.conf} | 0 itl/types.conf | 108 +++++ lib/base/dynamicobject.cpp | 5 + lib/base/dynamicobject.h | 2 + lib/config/Makefile.am | 8 +- lib/config/config.vcxproj | 8 +- lib/config/config_lexer.cc | 347 ++++++++------ lib/config/config_lexer.ll | 9 +- lib/config/config_parser.cc | 452 ++++++++++++------ lib/config/config_parser.h | 41 +- lib/config/config_parser.yy | 112 ++++- lib/config/configcompiler.cpp | 94 ++-- lib/config/configcompiler.h | 29 +- lib/config/configtype.cpp | 119 +++++ lib/config/configtype.h | 70 +++ lib/config/i2-config.h | 3 + lib/config/typerule.cpp | 63 +++ lib/config/typerule.h | 64 +++ lib/config/typerulelist.cpp | 73 +++ lib/config/typerulelist.h | 52 ++ 26 files changed, 1351 insertions(+), 358 deletions(-) rename itl/{itl-host.conf => host.conf} (100%) rename itl/{itl-service-common.conf => service-common.conf} (100%) rename itl/{itl-service.conf => service.conf} (100%) rename itl/{itl-standalone.conf => standalone.conf} (100%) create mode 100644 itl/types.conf create mode 100644 lib/config/configtype.cpp create mode 100644 lib/config/configtype.h create mode 100644 lib/config/typerule.cpp create mode 100644 lib/config/typerule.h create mode 100644 lib/config/typerulelist.cpp create mode 100644 lib/config/typerulelist.h diff --git a/icinga-app/icinga.cpp b/icinga-app/icinga.cpp index 7ed039f42..b117fb53b 100644 --- a/icinga-app/icinga.cpp +++ b/icinga-app/icinga.cpp @@ -93,14 +93,41 @@ int main(int argc, char **argv) /* load config file */ String configFile = argv[2]; - vector configItems = ConfigCompiler::CompileFile(configFile); - + vector items; + vector types; + + ConfigCompiler::CompileFile(configFile, &items, &types); + + Logger::Write(LogInformation, "icinga-app", "Registering config types..."); + + BOOST_FOREACH(const ConfigType::Ptr& type, types) { + type->Commit(); + } + Logger::Write(LogInformation, "icinga-app", "Executing config items..."); - BOOST_FOREACH(const ConfigItem::Ptr& item, configItems) { + BOOST_FOREACH(const ConfigItem::Ptr& item, items) { item->Commit(); } + Logger::Write(LogInformation, "icinga-app", "Validating config items..."); + + DynamicType::Ptr type; + BOOST_FOREACH(tie(tuples::ignore, type), DynamicType::GetTypes()) { + ConfigType::Ptr ctype = ConfigType::GetByName(type->GetName()); + + if (!ctype) { + Logger::Write(LogWarning, "icinga-app", "No config type found for type '" + type->GetName() + "'"); + + continue; + } + + DynamicObject::Ptr object; + BOOST_FOREACH(tie(tuples::ignore, object), type->GetObjects()) { + ctype->ValidateObject(object); + } + } + DynamicObject::FinishTx(); } catch (const exception& ex) { Logger::Write(LogCritical, "icinga-app", "Configuration error: " + String(ex.what())); diff --git a/itl/Makefile.am b/itl/Makefile.am index 568a34f17..1f0215aca 100644 --- a/itl/Makefile.am +++ b/itl/Makefile.am @@ -1,7 +1,8 @@ icinga2itldir = ${pkgdatadir}/itl icinga2itl_DATA = \ itl.conf \ - itl-host.conf \ - itl-service.conf \ - itl-service-common.conf \ - itl-standalone.conf + host.conf \ + service.conf \ + service-common.conf \ + standalone.conf \ + types.conf diff --git a/itl/itl-host.conf b/itl/host.conf similarity index 100% rename from itl/itl-host.conf rename to itl/host.conf diff --git a/itl/itl.conf b/itl/itl.conf index 34d507915..271a286fb 100644 --- a/itl/itl.conf +++ b/itl/itl.conf @@ -22,6 +22,8 @@ * configuration templates. */ -#include "itl-host.conf" -#include "itl-service.conf" -#include "itl-service-common.conf" +#include "types.conf" + +#include "host.conf" +#include "service.conf" +#include "service-common.conf" diff --git a/itl/itl-service-common.conf b/itl/service-common.conf similarity index 100% rename from itl/itl-service-common.conf rename to itl/service-common.conf diff --git a/itl/itl-service.conf b/itl/service.conf similarity index 100% rename from itl/itl-service.conf rename to itl/service.conf diff --git a/itl/itl-standalone.conf b/itl/standalone.conf similarity index 100% rename from itl/itl-standalone.conf rename to itl/standalone.conf diff --git a/itl/types.conf b/itl/types.conf new file mode 100644 index 000000000..d1fbb7ea9 --- /dev/null +++ b/itl/types.conf @@ -0,0 +1,108 @@ +/****************************************************************************** + * Icinga 2 * + * Copyright (C) 2012 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. * + ******************************************************************************/ + +type DynamicObject { + number __abstract, + number __local, + number __name, + number __type, + + dictionary methods { + string *, + }, + + any custom::* +} + +type Component { +} + +type Logger { + string type, + string path, + string severity +} + +type Host { + string alias, + dictionary hostgroups { + string * + }, + dictionary dependencies { + string * + }, + dictionary hostchecks { + string * + }, + dictionary macros { + string * + }, + dictionary services { + any * /* TODO: more specific validation rules */ + } +} + +type HostGroup { + string alias, + string notes_url, + string action_url +} + +type IcingaApplication { + string cert_path, + string ca_path, + string node, + string service, + string pid_path, + string state_path, + string macros +} + +type Service { + string alias, + string host_name, + dictionary macros { + string * + }, + string check_command, + number max_check_attempts, + number check_interval, + number retry_interval, + dictionary dependencies { + string * + }, + dictionary servicegroups { + string * + }, + dictionary checkers { + string * + } +} + +type ServiceGroup { + string alias, + string notes_url, + string action_url +} + +type Endpoint { + string node, + string service, + number local +} diff --git a/lib/base/dynamicobject.cpp b/lib/base/dynamicobject.cpp index 6e706d868..d850b1013 100644 --- a/lib/base/dynamicobject.cpp +++ b/lib/base/dynamicobject.cpp @@ -481,3 +481,8 @@ DynamicObject::Ptr DynamicObject::GetObject(const String& type, const String& na DynamicType::Ptr dtype = DynamicType::GetByName(type); return dtype->GetObject(name); } + +const DynamicObject::AttributeMap& DynamicObject::GetAttributes(void) const +{ + return m_Attributes; +} \ No newline at end of file diff --git a/lib/base/dynamicobject.h b/lib/base/dynamicobject.h index 88973cf3c..e99841fd6 100644 --- a/lib/base/dynamicobject.h +++ b/lib/base/dynamicobject.h @@ -131,6 +131,8 @@ public: virtual void Start(void); + const AttributeMap& GetAttributes(void) const; + static DynamicObject::Ptr GetObject(const String& type, const String& name); static void DumpObjects(const String& filename); diff --git a/lib/config/Makefile.am b/lib/config/Makefile.am index 606208b26..5a1ce8cd6 100644 --- a/lib/config/Makefile.am +++ b/lib/config/Makefile.am @@ -18,11 +18,17 @@ libconfig_la_SOURCES = \ configitem.h \ configitembuilder.cpp \ configitembuilder.h \ + configtype.cpp \ + configtype.h \ debuginfo.h \ expression.cpp \ expression.h \ expressionlist.cpp \ - expressionlist.h + expressionlist.h \ + typerule.cpp \ + typerule.h \ + typerulelist.cpp \ + typerulelist.h libconfig_la_CPPFLAGS = \ -DI2_CONFIG_BUILD \ diff --git a/lib/config/config.vcxproj b/lib/config/config.vcxproj index 0986ab37a..ded9a97b5 100644 --- a/lib/config/config.vcxproj +++ b/lib/config/config.vcxproj @@ -22,16 +22,20 @@ + + + + NotUsing NotUsing @@ -52,6 +56,8 @@ Create Create + + @@ -220,4 +226,4 @@ - \ No newline at end of file + diff --git a/lib/config/config_lexer.cc b/lib/config/config_lexer.cc index 471c7b6af..463ba091b 100644 --- a/lib/config/config_lexer.cc +++ b/lib/config/config_lexer.cc @@ -370,8 +370,8 @@ static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner ); *yy_cp = '\0'; \ yyg->yy_c_buf_p = yy_cp; -#define YY_NUM_RULES 29 -#define YY_END_OF_BUFFER 30 +#define YY_NUM_RULES 36 +#define YY_END_OF_BUFFER 37 /* This struct is not used in this scanner, but its presence is necessary. */ struct yy_trans_info @@ -379,19 +379,23 @@ struct yy_trans_info flex_int32_t yy_verify; flex_int32_t yy_nxt; }; -static yyconst flex_int16_t yy_accept[97] = +static yyconst flex_int16_t yy_accept[134] = { 0, - 0, 0, 0, 0, 30, 28, 27, 27, 28, 28, - 28, 28, 28, 28, 16, 28, 17, 10, 10, 10, - 10, 10, 10, 10, 10, 24, 25, 27, 0, 11, - 0, 0, 20, 18, 16, 19, 22, 0, 21, 0, - 13, 14, 15, 0, 12, 10, 10, 10, 10, 10, - 10, 10, 10, 24, 23, 0, 0, 26, 16, 10, - 10, 10, 10, 10, 10, 10, 0, 0, 10, 10, - 10, 10, 7, 10, 8, 0, 0, 10, 9, 10, - 2, 10, 0, 0, 10, 10, 3, 0, 0, 10, - 10, 4, 5, 1, 6, 0 - + 0, 0, 0, 0, 37, 35, 34, 34, 35, 35, + 17, 35, 35, 35, 23, 35, 24, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 31, 32, + 34, 0, 18, 0, 0, 17, 27, 25, 23, 26, + 29, 0, 28, 0, 20, 21, 22, 0, 19, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 31, 30, 0, 0, 33, 23, 17, 6, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 0, 0, 17, 17, 17, 17, 17, 13, + 17, 17, 17, 17, 17, 15, 1, 0, 0, 17, + + 17, 16, 17, 8, 17, 17, 17, 17, 17, 0, + 0, 17, 17, 17, 3, 9, 17, 5, 4, 0, + 0, 17, 17, 17, 14, 10, 11, 7, 17, 12, + 17, 2, 0 } ; static yyconst flex_int32_t yy_ec[256] = @@ -401,15 +405,15 @@ static yyconst flex_int32_t yy_ec[256] = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 4, 5, 1, 1, 1, 1, 1, 1, 6, 7, 1, 8, 9, 10, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 1, 1, 12, - 13, 14, 1, 1, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 1, 1, 1, 1, 15, 1, 16, 17, 18, 19, - - 20, 21, 15, 22, 23, 24, 15, 25, 26, 27, - 28, 15, 15, 29, 30, 31, 32, 15, 15, 15, - 33, 15, 1, 1, 1, 1, 1, 1, 1, 1, + 11, 11, 11, 11, 11, 11, 11, 12, 1, 13, + 14, 15, 1, 1, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 1, 1, 1, 1, 16, 1, 17, 18, 19, 20, + + 21, 22, 23, 24, 25, 26, 16, 27, 28, 29, + 30, 31, 16, 32, 33, 34, 35, 16, 16, 16, + 36, 16, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -426,95 +430,127 @@ static yyconst flex_int32_t yy_ec[256] = 1, 1, 1, 1, 1 } ; -static yyconst flex_int32_t yy_meta[34] = +static yyconst flex_int32_t yy_meta[37] = { 0, 1, 1, 2, 1, 1, 3, 1, 4, 1, 1, - 4, 1, 1, 1, 4, 4, 4, 4, 4, 4, + 4, 4, 1, 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4 + 4, 4, 4, 4, 4, 4 } ; -static yyconst flex_int16_t yy_base[103] = +static yyconst flex_int16_t yy_base[140] = { 0, - 0, 0, 124, 123, 128, 131, 32, 34, 123, 15, - 113, 112, 28, 36, 41, 110, 131, 0, 106, 106, - 94, 92, 87, 101, 88, 0, 106, 41, 111, 131, - 87, 90, 131, 131, 0, 131, 131, 0, 131, 101, - 131, 131, 131, 97, 131, 0, 80, 84, 86, 89, - 81, 81, 72, 0, 131, 85, 85, 0, 34, 70, - 70, 79, 82, 72, 76, 75, 69, 64, 63, 69, - 57, 45, 0, 51, 0, 36, 50, 49, 0, 39, - 0, 30, 40, 29, 39, 24, 0, 34, 20, 20, - 18, 131, 131, 0, 0, 131, 71, 75, 79, 43, - - 83, 87 + 0, 0, 246, 245, 250, 253, 35, 37, 245, 16, + 234, 233, 31, 38, 38, 231, 253, 231, 32, 39, + 37, 41, 42, 43, 45, 51, 55, 44, 0, 234, + 79, 239, 253, 213, 216, 226, 253, 253, 64, 253, + 253, 0, 253, 228, 253, 253, 253, 223, 253, 46, + 63, 71, 69, 70, 72, 73, 79, 81, 89, 84, + 88, 90, 0, 253, 218, 218, 0, 96, 94, 221, + 96, 98, 97, 100, 95, 101, 111, 112, 113, 119, + 120, 121, 207, 199, 122, 123, 124, 125, 129, 214, + 137, 133, 135, 136, 141, 196, 195, 173, 190, 145, + + 147, 192, 149, 191, 150, 151, 152, 154, 153, 184, + 171, 159, 158, 157, 187, 184, 161, 183, 182, 174, + 158, 165, 166, 167, 179, 253, 253, 178, 170, 176, + 175, 53, 253, 211, 215, 217, 221, 225, 229 } ; -static yyconst flex_int16_t yy_def[103] = +static yyconst flex_int16_t yy_def[140] = { 0, - 96, 1, 97, 97, 96, 96, 96, 96, 98, 96, - 96, 96, 96, 96, 96, 99, 96, 100, 100, 100, - 100, 100, 100, 100, 100, 101, 96, 96, 98, 96, - 96, 96, 96, 96, 15, 96, 96, 102, 96, 96, - 96, 96, 96, 99, 96, 100, 100, 100, 100, 100, - 100, 100, 100, 101, 96, 96, 96, 102, 96, 100, - 100, 100, 100, 100, 100, 100, 96, 96, 100, 100, - 100, 100, 100, 100, 100, 96, 96, 100, 100, 100, - 100, 100, 96, 96, 100, 100, 100, 96, 96, 100, - 100, 96, 96, 100, 100, 0, 96, 96, 96, 96, - - 96, 96 + 133, 1, 134, 134, 133, 133, 133, 133, 135, 133, + 136, 133, 133, 133, 133, 137, 133, 136, 136, 136, + 136, 136, 136, 136, 136, 136, 136, 136, 138, 133, + 133, 135, 133, 133, 133, 136, 133, 133, 133, 133, + 133, 139, 133, 133, 133, 133, 133, 137, 133, 136, + 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, + 136, 136, 138, 133, 133, 133, 139, 133, 136, 136, + 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, + 136, 136, 133, 133, 136, 136, 136, 136, 136, 136, + 136, 136, 136, 136, 136, 136, 136, 133, 133, 136, + + 136, 136, 136, 136, 136, 136, 136, 136, 136, 133, + 133, 136, 136, 136, 136, 136, 136, 136, 136, 133, + 133, 136, 136, 136, 136, 133, 133, 136, 136, 136, + 136, 136, 0, 133, 133, 133, 133, 133, 133 } ; -static yyconst flex_int16_t yy_nxt[165] = +static yyconst flex_int16_t yy_nxt[290] = { 0, 6, 7, 8, 9, 10, 11, 12, 13, 6, 14, - 15, 16, 17, 6, 18, 19, 18, 18, 18, 18, - 20, 18, 21, 18, 22, 18, 23, 24, 18, 18, - 25, 18, 18, 28, 28, 28, 28, 31, 35, 32, - 36, 37, 28, 28, 59, 38, 46, 95, 39, 40, - 94, 35, 93, 92, 91, 41, 90, 89, 88, 42, - 87, 86, 41, 43, 85, 84, 42, 83, 82, 81, - 43, 26, 26, 26, 26, 29, 29, 29, 29, 44, - 44, 44, 44, 54, 54, 80, 54, 58, 79, 58, - 58, 78, 77, 76, 75, 74, 73, 72, 71, 70, - - 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, - 45, 59, 57, 56, 30, 55, 53, 52, 51, 50, - 49, 48, 47, 45, 34, 33, 30, 96, 27, 27, - 5, 96, 96, 96, 96, 96, 96, 96, 96, 96, - 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, - 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, - 96, 96, 96, 96 + 15, 6, 16, 17, 6, 18, 19, 18, 18, 20, + 18, 21, 18, 18, 22, 18, 23, 18, 24, 25, + 26, 18, 27, 28, 18, 18, 31, 31, 31, 31, + 34, 39, 35, 41, 40, 133, 44, 42, 39, 50, + 133, 43, 133, 53, 133, 133, 133, 133, 133, 133, + 51, 45, 57, 52, 133, 46, 133, 58, 133, 54, + 47, 55, 44, 59, 39, 61, 133, 56, 69, 62, + 31, 31, 133, 133, 133, 133, 133, 45, 60, 71, + 74, 46, 133, 73, 133, 72, 47, 133, 70, 75, + + 76, 133, 133, 133, 77, 79, 68, 133, 133, 133, + 133, 133, 78, 133, 133, 80, 89, 88, 91, 45, + 82, 90, 81, 46, 133, 133, 133, 85, 47, 86, + 87, 92, 133, 133, 133, 133, 133, 133, 133, 94, + 96, 97, 133, 95, 102, 93, 133, 101, 133, 133, + 133, 106, 108, 100, 133, 104, 103, 105, 133, 107, + 133, 112, 133, 133, 133, 133, 133, 133, 117, 109, + 133, 133, 133, 114, 133, 119, 113, 122, 133, 133, + 133, 115, 129, 133, 116, 118, 123, 125, 133, 133, + 124, 133, 133, 127, 126, 133, 133, 133, 128, 130, + + 133, 131, 121, 120, 133, 133, 111, 110, 133, 133, + 132, 29, 29, 29, 29, 32, 32, 32, 32, 36, + 36, 48, 48, 48, 48, 63, 63, 133, 63, 67, + 99, 67, 67, 98, 133, 84, 83, 49, 68, 133, + 66, 65, 33, 64, 133, 49, 38, 37, 33, 133, + 30, 30, 5, 133, 133, 133, 133, 133, 133, 133, + 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, + 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, + 133, 133, 133, 133, 133, 133, 133, 133, 133 } ; -static yyconst flex_int16_t yy_chk[165] = +static yyconst flex_int16_t yy_chk[290] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 7, 7, 8, 8, 10, 13, 10, - 13, 14, 28, 28, 59, 14, 100, 91, 14, 15, - 90, 15, 89, 88, 86, 59, 85, 84, 83, 59, - 82, 80, 15, 59, 78, 77, 15, 76, 74, 72, - 15, 97, 97, 97, 97, 98, 98, 98, 98, 99, - 99, 99, 99, 101, 101, 71, 101, 102, 70, 102, - 102, 69, 68, 67, 66, 65, 64, 63, 62, 61, - - 60, 57, 56, 53, 52, 51, 50, 49, 48, 47, - 44, 40, 32, 31, 29, 27, 25, 24, 23, 22, - 21, 20, 19, 16, 12, 11, 9, 5, 4, 3, - 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, - 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, - 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, - 96, 96, 96, 96 + 1, 1, 1, 1, 1, 1, 7, 7, 8, 8, + 10, 13, 10, 14, 13, 19, 15, 14, 15, 19, + 21, 14, 20, 21, 22, 23, 24, 28, 25, 50, + 19, 15, 25, 20, 26, 15, 132, 26, 27, 22, + 15, 23, 39, 27, 39, 28, 51, 24, 50, 28, + 31, 31, 53, 54, 52, 55, 56, 39, 27, 52, + 55, 39, 57, 54, 58, 53, 39, 60, 51, 56, + + 56, 61, 59, 62, 57, 59, 68, 69, 75, 71, + 73, 72, 58, 74, 76, 60, 74, 73, 76, 68, + 62, 75, 61, 68, 77, 78, 79, 69, 68, 71, + 72, 77, 80, 81, 82, 85, 86, 87, 88, 79, + 81, 82, 89, 80, 87, 78, 92, 86, 93, 94, + 91, 92, 94, 85, 95, 89, 88, 91, 100, 93, + 101, 100, 103, 105, 106, 107, 109, 108, 107, 95, + 114, 113, 112, 103, 117, 109, 101, 112, 122, 123, + 124, 105, 123, 129, 106, 108, 113, 117, 131, 130, + 114, 128, 125, 121, 120, 119, 118, 116, 122, 124, + + 115, 129, 111, 110, 104, 102, 99, 98, 97, 96, + 131, 134, 134, 134, 134, 135, 135, 135, 135, 136, + 136, 137, 137, 137, 137, 138, 138, 90, 138, 139, + 84, 139, 139, 83, 70, 66, 65, 48, 44, 36, + 35, 34, 32, 30, 18, 16, 12, 11, 9, 5, + 4, 3, 133, 133, 133, 133, 133, 133, 133, 133, + 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, + 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, + 133, 133, 133, 133, 133, 133, 133, 133, 133 } ; /* Table of booleans, true if rule could match eol. */ -static yyconst flex_int32_t yy_rule_can_match_eol[30] = +static yyconst flex_int32_t yy_rule_can_match_eol[37] = { 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, }; +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, }; /* The intent behind this definition is that it'll catch * any uses of REJECT which flex missed. @@ -566,7 +602,7 @@ do { \ } while (0) #define YY_NO_UNISTD_H 1 -#line 570 "config_lexer.cc" +#line 606 "config_lexer.cc" #define INITIAL 0 #define IN_C_COMMENT 1 @@ -815,7 +851,7 @@ YY_DECL #line 49 "config_lexer.ll" -#line 819 "config_lexer.cc" +#line 855 "config_lexer.cc" yylval = yylval_param; @@ -872,13 +908,13 @@ yy_match: while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 97 ) + if ( yy_current_state >= 134 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; ++yy_cp; } - while ( yy_current_state != 96 ); + while ( yy_current_state != 133 ); yy_cp = yyg->yy_last_accepting_cpos; yy_current_state = yyg->yy_last_accepting_state; @@ -913,157 +949,192 @@ do_action: /* This label is used only to access EOF actions. */ case 1: YY_RULE_SETUP #line 50 "config_lexer.ll" -return T_ABSTRACT; +return T_TYPE; YY_BREAK case 2: YY_RULE_SETUP #line 51 "config_lexer.ll" -return T_LOCAL; +{ yylval->type = TypeDictionary; return T_TYPE_DICTIONARY; } YY_BREAK case 3: YY_RULE_SETUP #line 52 "config_lexer.ll" -return T_OBJECT; +{ yylval->type = TypeNumber; return T_TYPE_NUMBER; } YY_BREAK case 4: YY_RULE_SETUP #line 53 "config_lexer.ll" -return T_INCLUDE; +{ yylval->type = TypeString; return T_TYPE_STRING; } YY_BREAK case 5: YY_RULE_SETUP #line 54 "config_lexer.ll" -return T_LIBRARY; +{ yylval->type = TypeScalar; return T_TYPE_SCALAR; } YY_BREAK case 6: YY_RULE_SETUP #line 55 "config_lexer.ll" -return T_INHERITS; +{ yylval->type = TypeAny; return T_TYPE_ANY; } YY_BREAK case 7: YY_RULE_SETUP #line 56 "config_lexer.ll" -return T_NULL; +return T_ABSTRACT; YY_BREAK case 8: YY_RULE_SETUP #line 57 "config_lexer.ll" -{ yylval->num = 1; return T_NUMBER; } +return T_LOCAL; YY_BREAK case 9: YY_RULE_SETUP #line 58 "config_lexer.ll" -{ yylval->num = 0; return T_NUMBER; } +return T_OBJECT; YY_BREAK case 10: YY_RULE_SETUP #line 59 "config_lexer.ll" -{ yylval->text = strdup(yytext); return T_IDENTIFIER; } +return T_INCLUDE; YY_BREAK case 11: -/* rule 11 can match eol */ YY_RULE_SETUP #line 60 "config_lexer.ll" -{ yytext[yyleng-1] = '\0'; yylval->text = strdup(yytext + 1); return T_STRING; } +return T_LIBRARY; YY_BREAK case 12: -/* rule 12 can match eol */ YY_RULE_SETUP #line 61 "config_lexer.ll" -{ yytext[yyleng-1] = '\0'; yylval->text = strdup(yytext + 1); return T_STRING_ANGLE; } +return T_INHERITS; YY_BREAK case 13: YY_RULE_SETUP #line 62 "config_lexer.ll" -{ yylval->num = strtod(yytext, NULL) * 60 * 60; return T_NUMBER; } +return T_NULL; YY_BREAK case 14: YY_RULE_SETUP #line 63 "config_lexer.ll" -{ yylval->num = strtod(yytext, NULL) * 60; return T_NUMBER; } +return T_PARTIAL; YY_BREAK case 15: YY_RULE_SETUP #line 64 "config_lexer.ll" -{ yylval->num = strtod(yytext, NULL); return T_NUMBER; } +{ yylval->num = 1; return T_NUMBER; } YY_BREAK case 16: YY_RULE_SETUP #line 65 "config_lexer.ll" -{ yylval->num = strtod(yytext, NULL); return T_NUMBER; } +{ yylval->num = 0; return T_NUMBER; } YY_BREAK case 17: YY_RULE_SETUP #line 66 "config_lexer.ll" -{ yylval->op = OperatorSet; return T_EQUAL; } +{ yylval->text = strdup(yytext); return T_IDENTIFIER; } YY_BREAK case 18: +/* rule 18 can match eol */ YY_RULE_SETUP #line 67 "config_lexer.ll" -{ yylval->op = OperatorPlus; return T_PLUS_EQUAL; } +{ yytext[yyleng-1] = '\0'; yylval->text = strdup(yytext + 1); return T_STRING; } YY_BREAK case 19: +/* rule 19 can match eol */ YY_RULE_SETUP #line 68 "config_lexer.ll" -{ yylval->op = OperatorMinus; return T_MINUS_EQUAL; } +{ yytext[yyleng-1] = '\0'; yylval->text = strdup(yytext + 1); return T_STRING_ANGLE; } YY_BREAK case 20: YY_RULE_SETUP #line 69 "config_lexer.ll" -{ yylval->op = OperatorMultiply; return T_MULTIPLY_EQUAL; } +{ yylval->num = strtod(yytext, NULL) * 60 * 60; return T_NUMBER; } YY_BREAK case 21: YY_RULE_SETUP #line 70 "config_lexer.ll" -{ yylval->op = OperatorDivide; return T_DIVIDE_EQUAL; } +{ yylval->num = strtod(yytext, NULL) * 60; return T_NUMBER; } YY_BREAK - case 22: YY_RULE_SETUP +#line 71 "config_lexer.ll" +{ yylval->num = strtod(yytext, NULL); return T_NUMBER; } + YY_BREAK +case 23: +YY_RULE_SETUP +#line 72 "config_lexer.ll" +{ yylval->num = strtod(yytext, NULL); return T_NUMBER; } + YY_BREAK +case 24: +YY_RULE_SETUP #line 73 "config_lexer.ll" +{ yylval->op = OperatorSet; return T_EQUAL; } + YY_BREAK +case 25: +YY_RULE_SETUP +#line 74 "config_lexer.ll" +{ yylval->op = OperatorPlus; return T_PLUS_EQUAL; } + YY_BREAK +case 26: +YY_RULE_SETUP +#line 75 "config_lexer.ll" +{ yylval->op = OperatorMinus; return T_MINUS_EQUAL; } + YY_BREAK +case 27: +YY_RULE_SETUP +#line 76 "config_lexer.ll" +{ yylval->op = OperatorMultiply; return T_MULTIPLY_EQUAL; } + YY_BREAK +case 28: +YY_RULE_SETUP +#line 77 "config_lexer.ll" +{ yylval->op = OperatorDivide; return T_DIVIDE_EQUAL; } + YY_BREAK + +case 29: +YY_RULE_SETUP +#line 80 "config_lexer.ll" BEGIN(IN_C_COMMENT); YY_BREAK -case 23: +case 30: YY_RULE_SETUP -#line 77 "config_lexer.ll" +#line 84 "config_lexer.ll" BEGIN(INITIAL); YY_BREAK -case 24: -/* rule 24 can match eol */ +case 31: +/* rule 31 can match eol */ YY_RULE_SETUP -#line 78 "config_lexer.ll" +#line 85 "config_lexer.ll" /* ignore comment */ YY_BREAK -case 25: +case 32: YY_RULE_SETUP -#line 79 "config_lexer.ll" +#line 86 "config_lexer.ll" /* ignore star */ YY_BREAK -case 26: +case 33: YY_RULE_SETUP -#line 82 "config_lexer.ll" +#line 89 "config_lexer.ll" /* ignore C++-style comments */ YY_BREAK -case 27: -/* rule 27 can match eol */ +case 34: +/* rule 34 can match eol */ YY_RULE_SETUP -#line 83 "config_lexer.ll" +#line 90 "config_lexer.ll" /* ignore whitespace */ YY_BREAK -case 28: +case 35: YY_RULE_SETUP -#line 85 "config_lexer.ll" +#line 92 "config_lexer.ll" return yytext[0]; YY_BREAK -case 29: +case 36: YY_RULE_SETUP -#line 86 "config_lexer.ll" +#line 93 "config_lexer.ll" ECHO; YY_BREAK -#line 1067 "config_lexer.cc" +#line 1138 "config_lexer.cc" case YY_STATE_EOF(INITIAL): case YY_STATE_EOF(IN_C_COMMENT): yyterminate(); @@ -1359,7 +1430,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner) while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 97 ) + if ( yy_current_state >= 134 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; @@ -1388,11 +1459,11 @@ static int yy_get_next_buffer (yyscan_t yyscanner) while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 97 ) + if ( yy_current_state >= 134 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; - yy_is_jam = (yy_current_state == 96); + yy_is_jam = (yy_current_state == 133); return yy_is_jam ? 0 : yy_current_state; } @@ -2251,7 +2322,7 @@ void yyfree (void * ptr , yyscan_t yyscanner) #define YYTABLES_NAME "yytables" -#line 86 "config_lexer.ll" +#line 93 "config_lexer.ll" diff --git a/lib/config/config_lexer.ll b/lib/config/config_lexer.ll index 9d8dc2bc0..a94bd280e 100644 --- a/lib/config/config_lexer.ll +++ b/lib/config/config_lexer.ll @@ -47,6 +47,12 @@ do { \ %x IN_C_COMMENT %% +type return T_TYPE; +dictionary { yylval->type = TypeDictionary; return T_TYPE_DICTIONARY; } +number { yylval->type = TypeNumber; return T_TYPE_NUMBER; } +string { yylval->type = TypeString; return T_TYPE_STRING; } +scalar { yylval->type = TypeScalar; return T_TYPE_SCALAR; } +any { yylval->type = TypeAny; return T_TYPE_ANY; } abstract return T_ABSTRACT; local return T_LOCAL; object return T_OBJECT; @@ -54,9 +60,10 @@ object return T_OBJECT; #library return T_LIBRARY; inherits return T_INHERITS; null return T_NULL; +partial return T_PARTIAL; true { yylval->num = 1; return T_NUMBER; } false { yylval->num = 0; return T_NUMBER; } -[a-zA-Z_][a-zA-Z0-9\-_]* { yylval->text = strdup(yytext); return T_IDENTIFIER; } +[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; } \<[^\>]*\> { yytext[yyleng-1] = '\0'; yylval->text = strdup(yytext + 1); return T_STRING_ANGLE; } -?[0-9]+(\.[0-9]+)?h { yylval->num = strtod(yytext, NULL) * 60 * 60; return T_NUMBER; } diff --git a/lib/config/config_parser.cc b/lib/config/config_parser.cc index 43981b6e7..a06c8c942 100644 --- a/lib/config/config_parser.cc +++ b/lib/config/config_parser.cc @@ -139,12 +139,19 @@ using namespace icinga; T_MINUS_EQUAL = 265, T_MULTIPLY_EQUAL = 266, T_DIVIDE_EQUAL = 267, - T_ABSTRACT = 268, - T_LOCAL = 269, - T_OBJECT = 270, - T_INCLUDE = 271, - T_LIBRARY = 272, - T_INHERITS = 273 + T_TYPE_DICTIONARY = 268, + T_TYPE_NUMBER = 269, + T_TYPE_STRING = 270, + T_TYPE_SCALAR = 271, + T_TYPE_ANY = 272, + T_TYPE = 273, + T_ABSTRACT = 274, + T_LOCAL = 275, + T_OBJECT = 276, + T_INCLUDE = 277, + T_LIBRARY = 278, + T_INHERITS = 279, + T_PARTIAL = 280 }; #endif /* Tokens. */ @@ -158,12 +165,19 @@ using namespace icinga; #define T_MINUS_EQUAL 265 #define T_MULTIPLY_EQUAL 266 #define T_DIVIDE_EQUAL 267 -#define T_ABSTRACT 268 -#define T_LOCAL 269 -#define T_OBJECT 270 -#define T_INCLUDE 271 -#define T_LIBRARY 272 -#define T_INHERITS 273 +#define T_TYPE_DICTIONARY 268 +#define T_TYPE_NUMBER 269 +#define T_TYPE_STRING 270 +#define T_TYPE_SCALAR 271 +#define T_TYPE_ANY 272 +#define T_TYPE 273 +#define T_ABSTRACT 274 +#define T_LOCAL 275 +#define T_OBJECT 276 +#define T_INCLUDE 277 +#define T_LIBRARY 278 +#define T_INHERITS 279 +#define T_PARTIAL 280 @@ -179,11 +193,12 @@ typedef union YYSTYPE double num; icinga::Value *variant; icinga::ExpressionOperator op; + icinga::TypeSpecifier type; /* Line 293 of yacc.c */ -#line 187 "config_parser.cc" +#line 202 "config_parser.cc" } YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 # define yystype YYSTYPE /* obsolescent; will be withdrawn */ @@ -207,7 +222,7 @@ typedef struct YYLTYPE /* Copy the second part of user declarations. */ /* Line 343 of yacc.c */ -#line 68 "config_parser.yy" +#line 79 "config_parser.yy" int yylex(YYSTYPE *lvalp, YYLTYPE *llocp, void *scanner); @@ -225,7 +240,9 @@ static stack m_ExpressionLists; static ConfigItemBuilder::Ptr m_Item; static bool m_Abstract; static bool m_Local; -static Dictionary::Ptr m_Array; + +static stack m_RuleLists; +static ConfigType::Ptr m_Type; void ConfigCompiler::Compile(void) { @@ -237,7 +254,7 @@ void ConfigCompiler::Compile(void) /* Line 343 of yacc.c */ -#line 241 "config_parser.cc" +#line 258 "config_parser.cc" #ifdef short # undef short @@ -458,20 +475,20 @@ union yyalloc /* YYFINAL -- State number of the termination state. */ #define YYFINAL 2 /* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 44 +#define YYLAST 80 /* YYNTOKENS -- Number of terminals. */ -#define YYNTOKENS 28 +#define YYNTOKENS 35 /* YYNNTS -- Number of nonterminals. */ -#define YYNNTS 22 +#define YYNNTS 31 /* YYNRULES -- Number of rules. */ -#define YYNRULES 43 +#define YYNRULES 64 /* YYNRULES -- Number of states. */ -#define YYNSTATES 58 +#define YYNSTATES 84 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ #define YYUNDEFTOK 2 -#define YYMAXUTOK 273 +#define YYMAXUTOK 280 #define YYTRANSLATE(YYX) \ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) @@ -483,15 +500,15 @@ static const yytype_uint8 yytranslate[] = 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 21, 19, 23, 20, 2, 22, 2, 2, + 2, 2, 28, 26, 32, 27, 2, 29, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 26, 2, 27, 2, 2, 2, 2, 2, 2, + 2, 33, 2, 34, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 24, 2, 25, 2, 2, 2, 2, + 2, 2, 2, 30, 2, 31, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, @@ -506,7 +523,8 @@ static const yytype_uint8 yytranslate[] = 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18 + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25 }; #if YYDEBUG @@ -514,37 +532,46 @@ static const yytype_uint8 yytranslate[] = YYRHS. */ static const yytype_uint8 yyprhs[] = { - 0, 0, 3, 4, 7, 9, 11, 13, 16, 19, - 22, 24, 26, 27, 28, 37, 38, 41, 43, 45, - 47, 51, 53, 54, 57, 58, 63, 65, 68, 69, - 71, 75, 79, 86, 88, 90, 92, 94, 96, 98, - 100, 102, 104, 106 + 0, 0, 3, 4, 7, 9, 11, 13, 15, 18, + 21, 24, 26, 28, 29, 36, 37, 39, 40, 45, + 47, 50, 51, 53, 57, 60, 64, 65, 68, 70, + 72, 74, 76, 78, 79, 80, 89, 90, 93, 95, + 97, 99, 103, 105, 106, 109, 110, 115, 117, 120, + 121, 123, 127, 131, 138, 140, 142, 144, 146, 148, + 150, 152, 154, 156, 158 }; /* YYRHS -- A `-1'-separated list of the rules' RHS. */ static const yytype_int8 yyrhs[] = { - 29, 0, -1, -1, 29, 30, -1, 34, -1, 31, - -1, 32, -1, 16, 3, -1, 16, 4, -1, 17, - 3, -1, 7, -1, 3, -1, -1, -1, 35, 37, - 15, 33, 3, 36, 41, 42, -1, -1, 37, 38, - -1, 13, -1, 14, -1, 40, -1, 39, 23, 40, - -1, 3, -1, -1, 18, 39, -1, -1, 24, 43, - 44, 25, -1, 45, -1, 45, 23, -1, -1, 46, - -1, 45, 23, 46, -1, 33, 47, 49, -1, 33, - 26, 3, 27, 47, 49, -1, 3, -1, 8, -1, - 9, -1, 10, -1, 11, -1, 12, -1, 3, -1, - 5, -1, 6, -1, 48, -1, 42, -1 + 36, 0, -1, -1, 36, 37, -1, 50, -1, 41, + -1, 38, -1, 39, -1, 22, 3, -1, 22, 4, + -1, 23, 3, -1, 7, -1, 3, -1, -1, 43, + 18, 40, 42, 49, 44, -1, -1, 25, -1, -1, + 30, 45, 46, 31, -1, 47, -1, 47, 32, -1, + -1, 48, -1, 47, 32, 48, -1, 41, 40, -1, + 41, 40, 44, -1, -1, 24, 3, -1, 13, -1, + 14, -1, 15, -1, 16, -1, 17, -1, -1, -1, + 51, 53, 21, 40, 3, 52, 57, 58, -1, -1, + 53, 54, -1, 19, -1, 20, -1, 56, -1, 55, + 32, 56, -1, 3, -1, -1, 24, 55, -1, -1, + 30, 59, 60, 31, -1, 61, -1, 61, 32, -1, + -1, 62, -1, 61, 32, 62, -1, 40, 63, 65, + -1, 40, 33, 3, 34, 63, 65, -1, 3, -1, + 8, -1, 9, -1, 10, -1, 11, -1, 12, -1, + 3, -1, 5, -1, 6, -1, 64, -1, 58, -1 }; /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ static const yytype_uint16 yyrline[] = { - 0, 97, 97, 98, 101, 101, 101, 104, 108, 113, - 118, 119, 126, 131, 126, 150, 151, 154, 158, 164, - 165, 168, 175, 176, 180, 179, 191, 192, 194, 195, - 196, 199, 207, 221, 230, 231, 232, 233, 234, 240, - 245, 249, 255, 256 + 0, 110, 110, 111, 114, 114, 114, 114, 117, 121, + 126, 131, 132, 139, 138, 162, 165, 172, 171, 183, + 184, 186, 187, 188, 191, 196, 204, 205, 211, 212, + 213, 214, 215, 222, 227, 222, 246, 247, 250, 254, + 260, 261, 264, 271, 272, 276, 275, 287, 288, 290, + 291, 292, 295, 303, 317, 326, 327, 328, 329, 330, + 336, 341, 345, 351, 352 }; #endif @@ -555,12 +582,16 @@ static const char *const yytname[] = { "$end", "error", "$undefined", "T_STRING", "T_STRING_ANGLE", "T_NUMBER", "T_NULL", "T_IDENTIFIER", "T_EQUAL", "T_PLUS_EQUAL", "T_MINUS_EQUAL", - "T_MULTIPLY_EQUAL", "T_DIVIDE_EQUAL", "T_ABSTRACT", "T_LOCAL", - "T_OBJECT", "T_INCLUDE", "T_LIBRARY", "T_INHERITS", "'+'", "'-'", "'*'", - "'/'", "','", "'{'", "'}'", "'['", "']'", "$accept", "statements", - "statement", "include", "library", "identifier", "object", "$@1", "$@2", - "attributes", "attribute", "inherits_list", "inherits_item", - "inherits_specifier", "expressionlist", "$@3", "expressions", + "T_MULTIPLY_EQUAL", "T_DIVIDE_EQUAL", "T_TYPE_DICTIONARY", + "T_TYPE_NUMBER", "T_TYPE_STRING", "T_TYPE_SCALAR", "T_TYPE_ANY", + "T_TYPE", "T_ABSTRACT", "T_LOCAL", "T_OBJECT", "T_INCLUDE", "T_LIBRARY", + "T_INHERITS", "T_PARTIAL", "'+'", "'-'", "'*'", "'/'", "'{'", "'}'", + "','", "'['", "']'", "$accept", "statements", "statement", "include", + "library", "identifier", "type", "$@1", "partial_specifier", + "typerulelist", "$@2", "typerules", "typerules_inner", "typerule", + "type_inherits_specifier", "object", "$@3", "$@4", "attributes", + "attribute", "object_inherits_list", "object_inherits_item", + "object_inherits_specifier", "expressionlist", "$@5", "expressions", "expressions_inner", "expression", "operator", "simplevalue", "value", 0 }; #endif @@ -571,29 +602,34 @@ static const char *const yytname[] = static const yytype_uint16 yytoknum[] = { 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, - 265, 266, 267, 268, 269, 270, 271, 272, 273, 43, - 45, 42, 47, 44, 123, 125, 91, 93 + 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, + 275, 276, 277, 278, 279, 280, 43, 45, 42, 47, + 123, 125, 44, 91, 93 }; # endif /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ static const yytype_uint8 yyr1[] = { - 0, 28, 29, 29, 30, 30, 30, 31, 31, 32, - 33, 33, 35, 36, 34, 37, 37, 38, 38, 39, - 39, 40, 41, 41, 43, 42, 44, 44, 45, 45, - 45, 46, 46, 46, 47, 47, 47, 47, 47, 48, - 48, 48, 49, 49 + 0, 35, 36, 36, 37, 37, 37, 37, 38, 38, + 39, 40, 40, 42, 41, 43, 43, 45, 44, 46, + 46, 47, 47, 47, 48, 48, 49, 49, 41, 41, + 41, 41, 41, 51, 52, 50, 53, 53, 54, 54, + 55, 55, 56, 57, 57, 59, 58, 60, 60, 61, + 61, 61, 62, 62, 62, 63, 63, 63, 63, 63, + 64, 64, 64, 65, 65 }; /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ static const yytype_uint8 yyr2[] = { - 0, 2, 0, 2, 1, 1, 1, 2, 2, 2, - 1, 1, 0, 0, 8, 0, 2, 1, 1, 1, - 3, 1, 0, 2, 0, 4, 1, 2, 0, 1, - 3, 3, 6, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1 + 0, 2, 0, 2, 1, 1, 1, 1, 2, 2, + 2, 1, 1, 0, 6, 0, 1, 0, 4, 1, + 2, 0, 1, 3, 2, 3, 0, 2, 1, 1, + 1, 1, 1, 0, 0, 8, 0, 2, 1, 1, + 1, 3, 1, 0, 2, 0, 4, 1, 2, 0, + 1, 3, 3, 6, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 }; /* YYDEFACT[STATE-NAME] -- Default reduction number in state STATE-NUM. @@ -601,81 +637,100 @@ static const yytype_uint8 yyr2[] = means the default is an error. */ static const yytype_uint8 yydefact[] = { - 2, 12, 1, 0, 0, 3, 5, 6, 4, 15, - 7, 8, 9, 0, 17, 18, 0, 16, 11, 10, - 0, 13, 22, 0, 0, 21, 23, 19, 24, 14, - 0, 28, 20, 11, 0, 0, 26, 29, 34, 35, - 36, 37, 38, 0, 0, 25, 27, 0, 39, 40, - 41, 43, 42, 31, 30, 0, 0, 32 + 2, 33, 1, 28, 29, 30, 31, 32, 0, 0, + 16, 3, 6, 7, 5, 0, 4, 36, 8, 9, + 10, 0, 0, 12, 11, 13, 38, 39, 0, 37, + 26, 0, 0, 0, 34, 27, 17, 14, 43, 21, + 0, 0, 0, 0, 19, 22, 42, 44, 40, 45, + 35, 24, 18, 15, 0, 49, 25, 23, 41, 12, + 0, 0, 47, 50, 55, 56, 57, 58, 59, 0, + 0, 46, 48, 0, 60, 61, 62, 64, 63, 52, + 51, 0, 0, 53 }; /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int8 yydefgoto[] = { - -1, 1, 5, 6, 7, 34, 8, 9, 22, 13, - 17, 26, 27, 24, 51, 31, 35, 36, 37, 44, - 52, 53 + -1, 1, 11, 12, 13, 60, 42, 30, 15, 37, + 39, 43, 44, 45, 33, 16, 17, 38, 22, 29, + 47, 48, 41, 77, 55, 61, 62, 63, 70, 78, + 79 }; /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ -#define YYPACT_NINF -15 +#define YYPACT_NINF -12 static const yytype_int8 yypact[] = { - -15, 1, -15, 26, 6, -15, -15, -15, -15, -15, - -15, -15, -15, 10, -15, -15, 12, -15, -15, -15, - 24, -15, 14, 28, 9, -15, 11, -15, -15, -15, - 28, 13, -15, 3, -4, 15, 16, -15, -15, -15, - -15, -15, -15, 32, -3, -15, 13, 17, -15, -15, - -15, -15, -15, -15, -15, 2, -3, -15 + -12, 1, -12, -12, -12, -12, -12, -12, 45, 9, + -12, -12, -12, -12, -12, 4, -12, -12, -12, -12, + -12, 18, -10, -12, -12, -12, -12, -12, 18, -12, + 26, 30, 43, 21, -12, -12, -12, -12, 35, 27, + 57, 31, 18, 32, 33, -12, -12, 34, -12, -12, + -12, 21, -12, 22, 57, 25, -12, -12, -12, -1, + -4, 36, 37, -12, -12, -12, -12, -12, -12, 59, + -3, -12, 25, 38, -12, -12, -12, -12, -12, -12, + -12, 46, -3, -12 }; /* YYPGOTO[NTERM-NUM]. */ static const yytype_int8 yypgoto[] = { - -15, -15, -15, -15, -15, 20, -15, -15, -15, -15, - -15, -15, 7, -15, 18, -15, -15, -15, -8, -14, - -15, -13 + -12, -12, -12, -12, -12, -8, 63, -12, -12, 17, + -12, -12, -12, 20, -12, -12, -12, -12, -12, -12, + -12, 16, -12, 39, -12, -12, -12, 2, -6, -12, + -11 }; /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If positive, shift that token. If negative, reduce the rule which number is the opposite. If YYTABLE_NINF, syntax error. */ -#define YYTABLE_NINF -34 +#define YYTABLE_NINF -55 static const yytype_int8 yytable[] = { - 48, 2, 49, 50, 38, 39, 40, 41, 42, 12, - 38, 39, 40, 41, 42, 18, 33, 3, 4, 19, - 19, 28, 43, 14, 15, 16, -33, 21, -33, 10, - 11, 25, 23, 28, 30, 47, 20, 32, 54, 46, - 45, 56, 29, 57, 55 + 74, 2, 75, 76, 64, 65, 66, 67, 68, 26, + 27, 28, 20, 25, 3, 4, 5, 6, 7, -15, + 31, 23, 21, 8, 9, 24, 10, 49, 59, 69, + -54, -54, 24, 34, 51, 3, 4, 5, 6, 7, + 3, 4, 5, 6, 7, -15, 35, 10, 18, 19, + 32, 36, 10, -20, 64, 65, 66, 67, 68, 40, + 46, 49, 73, 52, 14, 53, 54, 71, 56, 72, + 58, 83, 81, 57, 80, 82, 0, 0, 0, 0, + 50 }; #define yypact_value_is_default(yystate) \ - ((yystate) == (-15)) + ((yystate) == (-12)) #define yytable_value_is_error(yytable_value) \ YYID (0) -static const yytype_uint8 yycheck[] = +static const yytype_int8 yycheck[] = { - 3, 0, 5, 6, 8, 9, 10, 11, 12, 3, - 8, 9, 10, 11, 12, 3, 3, 16, 17, 7, - 7, 24, 26, 13, 14, 15, 23, 3, 25, 3, - 4, 3, 18, 24, 23, 3, 16, 30, 46, 23, - 25, 55, 24, 56, 27 + 3, 0, 5, 6, 8, 9, 10, 11, 12, 19, + 20, 21, 3, 21, 13, 14, 15, 16, 17, 18, + 28, 3, 18, 22, 23, 7, 25, 30, 3, 33, + 31, 32, 7, 3, 42, 13, 14, 15, 16, 17, + 13, 14, 15, 16, 17, 18, 3, 25, 3, 4, + 24, 30, 25, 31, 8, 9, 10, 11, 12, 24, + 3, 30, 3, 31, 1, 32, 32, 31, 51, 32, + 54, 82, 34, 53, 72, 81, -1, -1, -1, -1, + 41 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing symbol of state STATE-NUM. */ static const yytype_uint8 yystos[] = { - 0, 29, 0, 16, 17, 30, 31, 32, 34, 35, - 3, 4, 3, 37, 13, 14, 15, 38, 3, 7, - 33, 3, 36, 18, 41, 3, 39, 40, 24, 42, - 23, 43, 40, 3, 33, 44, 45, 46, 8, 9, - 10, 11, 12, 26, 47, 25, 23, 3, 3, 5, - 6, 42, 48, 49, 46, 27, 47, 49 + 0, 36, 0, 13, 14, 15, 16, 17, 22, 23, + 25, 37, 38, 39, 41, 43, 50, 51, 3, 4, + 3, 18, 53, 3, 7, 40, 19, 20, 21, 54, + 42, 40, 24, 49, 3, 3, 30, 44, 52, 45, + 24, 57, 41, 46, 47, 48, 3, 55, 56, 30, + 58, 40, 31, 32, 32, 59, 44, 48, 56, 3, + 40, 60, 61, 62, 8, 9, 10, 11, 12, 33, + 63, 31, 32, 3, 3, 5, 6, 58, 64, 65, + 62, 34, 63, 65 }; #define yyerrok (yyerrstatus = 0) @@ -1558,56 +1613,163 @@ yyreduce: YY_REDUCE_PRINT (yyn); switch (yyn) { - case 7: + case 8: /* Line 1806 of yacc.c */ -#line 105 "config_parser.yy" +#line 118 "config_parser.yy" { context->HandleInclude((yyvsp[(2) - (2)].text), false); } break; - case 8: + case 9: /* Line 1806 of yacc.c */ -#line 109 "config_parser.yy" +#line 122 "config_parser.yy" { context->HandleInclude((yyvsp[(2) - (2)].text), true); } break; - case 9: + case 10: /* Line 1806 of yacc.c */ -#line 114 "config_parser.yy" +#line 127 "config_parser.yy" { context->HandleLibrary((yyvsp[(2) - (2)].text)); } break; - case 11: + case 12: /* Line 1806 of yacc.c */ -#line 120 "config_parser.yy" +#line 133 "config_parser.yy" { (yyval.text) = (yyvsp[(1) - (1)].text); } break; - case 12: + case 13: /* Line 1806 of yacc.c */ -#line 126 "config_parser.yy" +#line 139 "config_parser.yy" + { + String name = String((yyvsp[(3) - (3)].text)); + m_Type = context->GetTypeByName(name); + + if (!m_Type) { + if ((yyvsp[(1) - (3)].num)) + throw_exception(invalid_argument("partial type definition for unknown type '" + name + "'")); + + m_Type = boost::make_shared(name, yylloc); + context->AddType(m_Type); + } + } + break; + + case 14: + +/* Line 1806 of yacc.c */ +#line 152 "config_parser.yy" + { + TypeRuleList::Ptr ruleList = *(yyvsp[(6) - (6)].variant); + m_Type->GetRuleList()->AddRules(ruleList); + delete (yyvsp[(6) - (6)].variant); + + std::cout << "Created ConfigType: " << m_Type->GetName() << " with " << m_Type->GetRuleList()->GetLength() << " top-level rules." << std::endl; + } + break; + + case 15: + +/* Line 1806 of yacc.c */ +#line 162 "config_parser.yy" + { + (yyval.num) = 0; + } + break; + + case 16: + +/* Line 1806 of yacc.c */ +#line 166 "config_parser.yy" + { + (yyval.num) = 1; + } + break; + + case 17: + +/* Line 1806 of yacc.c */ +#line 172 "config_parser.yy" + { + m_RuleLists.push(boost::make_shared()); + } + break; + + case 18: + +/* Line 1806 of yacc.c */ +#line 177 "config_parser.yy" + { + (yyval.variant) = new Value(m_RuleLists.top()); + m_RuleLists.pop(); + } + break; + + case 24: + +/* Line 1806 of yacc.c */ +#line 192 "config_parser.yy" + { + TypeRule rule((yyvsp[(1) - (2)].type), (yyvsp[(2) - (2)].text), TypeRuleList::Ptr(), yylloc); + m_RuleLists.top()->AddRule(rule); + } + break; + + case 25: + +/* Line 1806 of yacc.c */ +#line 197 "config_parser.yy" + { + TypeRule rule((yyvsp[(1) - (3)].type), (yyvsp[(2) - (3)].text), *(yyvsp[(3) - (3)].variant), yylloc); + delete (yyvsp[(3) - (3)].variant); + m_RuleLists.top()->AddRule(rule); + } + break; + + case 27: + +/* Line 1806 of yacc.c */ +#line 206 "config_parser.yy" + { + m_Type->SetParent((yyvsp[(2) - (2)].text)); + } + break; + + case 32: + +/* Line 1806 of yacc.c */ +#line 216 "config_parser.yy" + { + (yyval.type) = (yyvsp[(1) - (1)].type); + } + break; + + case 33: + +/* Line 1806 of yacc.c */ +#line 222 "config_parser.yy" { m_Abstract = false; m_Local = false; } break; - case 13: + case 34: /* Line 1806 of yacc.c */ -#line 131 "config_parser.yy" +#line 227 "config_parser.yy" { m_Item = boost::make_shared(yylloc); m_Item->SetType((yyvsp[(4) - (5)].text)); @@ -1615,10 +1777,10 @@ yyreduce: } break; - case 14: + case 35: /* Line 1806 of yacc.c */ -#line 137 "config_parser.yy" +#line 233 "config_parser.yy" { ExpressionList::Ptr exprl = *(yyvsp[(8) - (8)].variant); delete (yyvsp[(8) - (8)].variant); @@ -1632,57 +1794,57 @@ yyreduce: } break; - case 17: + case 38: /* Line 1806 of yacc.c */ -#line 155 "config_parser.yy" +#line 251 "config_parser.yy" { m_Abstract = true; } break; - case 18: + case 39: /* Line 1806 of yacc.c */ -#line 159 "config_parser.yy" +#line 255 "config_parser.yy" { m_Local = true; } break; - case 21: + case 42: /* Line 1806 of yacc.c */ -#line 169 "config_parser.yy" +#line 265 "config_parser.yy" { m_Item->AddParent((yyvsp[(1) - (1)].text)); free((yyvsp[(1) - (1)].text)); } break; - case 24: + case 45: /* Line 1806 of yacc.c */ -#line 180 "config_parser.yy" +#line 276 "config_parser.yy" { m_ExpressionLists.push(boost::make_shared()); } break; - case 25: + case 46: /* Line 1806 of yacc.c */ -#line 185 "config_parser.yy" +#line 281 "config_parser.yy" { (yyval.variant) = new Value(m_ExpressionLists.top()); m_ExpressionLists.pop(); } break; - case 31: + case 52: /* Line 1806 of yacc.c */ -#line 200 "config_parser.yy" +#line 296 "config_parser.yy" { Expression expr((yyvsp[(1) - (3)].text), (yyvsp[(2) - (3)].op), *(yyvsp[(3) - (3)].variant), yylloc); free((yyvsp[(1) - (3)].text)); @@ -1692,10 +1854,10 @@ yyreduce: } break; - case 32: + case 53: /* Line 1806 of yacc.c */ -#line 208 "config_parser.yy" +#line 304 "config_parser.yy" { Expression subexpr((yyvsp[(3) - (6)].text), (yyvsp[(5) - (6)].op), *(yyvsp[(6) - (6)].variant), yylloc); free((yyvsp[(3) - (6)].text)); @@ -1711,10 +1873,10 @@ yyreduce: } break; - case 33: + case 54: /* Line 1806 of yacc.c */ -#line 222 "config_parser.yy" +#line 318 "config_parser.yy" { Expression expr((yyvsp[(1) - (1)].text), OperatorSet, (yyvsp[(1) - (1)].text), yylloc); free((yyvsp[(1) - (1)].text)); @@ -1723,47 +1885,47 @@ yyreduce: } break; - case 38: + case 59: /* Line 1806 of yacc.c */ -#line 235 "config_parser.yy" +#line 331 "config_parser.yy" { (yyval.op) = (yyvsp[(1) - (1)].op); } break; - case 39: + case 60: /* Line 1806 of yacc.c */ -#line 241 "config_parser.yy" +#line 337 "config_parser.yy" { (yyval.variant) = new Value((yyvsp[(1) - (1)].text)); free((yyvsp[(1) - (1)].text)); } break; - case 40: + case 61: /* Line 1806 of yacc.c */ -#line 246 "config_parser.yy" +#line 342 "config_parser.yy" { (yyval.variant) = new Value((yyvsp[(1) - (1)].num)); } break; - case 41: + case 62: /* Line 1806 of yacc.c */ -#line 250 "config_parser.yy" +#line 346 "config_parser.yy" { (yyval.variant) = new Value(); } break; - case 43: + case 64: /* Line 1806 of yacc.c */ -#line 257 "config_parser.yy" +#line 353 "config_parser.yy" { (yyval.variant) = (yyvsp[(1) - (1)].variant); } @@ -1772,7 +1934,7 @@ yyreduce: /* Line 1806 of yacc.c */ -#line 1776 "config_parser.cc" +#line 1938 "config_parser.cc" default: break; } /* User semantic actions sometimes alter yychar, and that requires @@ -2010,6 +2172,6 @@ yyreturn: /* Line 2067 of yacc.c */ -#line 261 "config_parser.yy" +#line 357 "config_parser.yy" diff --git a/lib/config/config_parser.h b/lib/config/config_parser.h index f82f5fb1e..63c7dabbe 100644 --- a/lib/config/config_parser.h +++ b/lib/config/config_parser.h @@ -82,12 +82,19 @@ using namespace icinga; T_MINUS_EQUAL = 265, T_MULTIPLY_EQUAL = 266, T_DIVIDE_EQUAL = 267, - T_ABSTRACT = 268, - T_LOCAL = 269, - T_OBJECT = 270, - T_INCLUDE = 271, - T_LIBRARY = 272, - T_INHERITS = 273 + T_TYPE_DICTIONARY = 268, + T_TYPE_NUMBER = 269, + T_TYPE_STRING = 270, + T_TYPE_SCALAR = 271, + T_TYPE_ANY = 272, + T_TYPE = 273, + T_ABSTRACT = 274, + T_LOCAL = 275, + T_OBJECT = 276, + T_INCLUDE = 277, + T_LIBRARY = 278, + T_INHERITS = 279, + T_PARTIAL = 280 }; #endif /* Tokens. */ @@ -101,12 +108,19 @@ using namespace icinga; #define T_MINUS_EQUAL 265 #define T_MULTIPLY_EQUAL 266 #define T_DIVIDE_EQUAL 267 -#define T_ABSTRACT 268 -#define T_LOCAL 269 -#define T_OBJECT 270 -#define T_INCLUDE 271 -#define T_LIBRARY 272 -#define T_INHERITS 273 +#define T_TYPE_DICTIONARY 268 +#define T_TYPE_NUMBER 269 +#define T_TYPE_STRING 270 +#define T_TYPE_SCALAR 271 +#define T_TYPE_ANY 272 +#define T_TYPE 273 +#define T_ABSTRACT 274 +#define T_LOCAL 275 +#define T_OBJECT 276 +#define T_INCLUDE 277 +#define T_LIBRARY 278 +#define T_INHERITS 279 +#define T_PARTIAL 280 @@ -122,11 +136,12 @@ typedef union YYSTYPE double num; icinga::Value *variant; icinga::ExpressionOperator op; + icinga::TypeSpecifier type; /* Line 2068 of yacc.c */ -#line 130 "config_parser.h" +#line 145 "config_parser.h" } YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 # define yystype YYSTYPE /* obsolescent; will be withdrawn */ diff --git a/lib/config/config_parser.yy b/lib/config/config_parser.yy index 2ec519035..53566f6bd 100644 --- a/lib/config/config_parser.yy +++ b/lib/config/config_parser.yy @@ -40,6 +40,7 @@ using namespace icinga; double num; icinga::Value *variant; icinga::ExpressionOperator op; + icinga::TypeSpecifier type; } %token T_STRING @@ -52,17 +53,27 @@ using namespace icinga; %token T_MINUS_EQUAL %token T_MULTIPLY_EQUAL %token T_DIVIDE_EQUAL +%token T_TYPE_DICTIONARY +%token T_TYPE_NUMBER +%token T_TYPE_STRING +%token T_TYPE_SCALAR +%token T_TYPE_ANY +%token T_TYPE %token T_ABSTRACT %token T_LOCAL %token T_OBJECT %token T_INCLUDE %token T_LIBRARY %token T_INHERITS +%token T_PARTIAL %type identifier %type simplevalue %type value %type expressionlist +%type typerulelist %type operator +%type type +%type partial_specifier %left '+' '-' %left '*' '/' %{ @@ -82,7 +93,9 @@ static stack m_ExpressionLists; static ConfigItemBuilder::Ptr m_Item; static bool m_Abstract; static bool m_Local; -static Dictionary::Ptr m_Array; + +static stack m_RuleLists; +static ConfigType::Ptr m_Type; void ConfigCompiler::Compile(void) { @@ -98,7 +111,7 @@ statements: /* empty */ | statements statement ; -statement: object | include | library +statement: object | type | include | library ; include: T_INCLUDE T_STRING @@ -122,6 +135,89 @@ identifier: T_IDENTIFIER } ; +type: partial_specifier T_TYPE identifier + { + String name = String($3); + m_Type = context->GetTypeByName(name); + + if (!m_Type) { + if ($1) + throw_exception(invalid_argument("partial type definition for unknown type '" + name + "'")); + + m_Type = boost::make_shared(name, yylloc); + context->AddType(m_Type); + } + } + type_inherits_specifier typerulelist + { + TypeRuleList::Ptr ruleList = *$6; + m_Type->GetRuleList()->AddRules(ruleList); + delete $6; + + std::cout << "Created ConfigType: " << m_Type->GetName() << " with " << m_Type->GetRuleList()->GetLength() << " top-level rules." << std::endl; + } + ; + +partial_specifier: /* Empty */ + { + $$ = 0; + } + | T_PARTIAL + { + $$ = 1; + } + ; + +typerulelist: '{' + { + m_RuleLists.push(boost::make_shared()); + } + typerules + '}' + { + $$ = new Value(m_RuleLists.top()); + m_RuleLists.pop(); + } + ; + +typerules: typerules_inner + | typerules_inner ',' + +typerules_inner: /* empty */ + | typerule + | typerules_inner ',' typerule + ; + +typerule: type identifier + { + TypeRule rule($1, $2, TypeRuleList::Ptr(), yylloc); + m_RuleLists.top()->AddRule(rule); + } + | type identifier typerulelist + { + TypeRule rule($1, $2, *$3, yylloc); + delete $3; + m_RuleLists.top()->AddRule(rule); + } + ; + +type_inherits_specifier: /* empty */ + | T_INHERITS T_STRING + { + m_Type->SetParent($2); + } + ; + +type: T_TYPE_DICTIONARY + | T_TYPE_NUMBER + | T_TYPE_STRING + | T_TYPE_SCALAR + | T_TYPE_ANY + { + $$ = $1; + } + ; + object: { m_Abstract = false; @@ -133,7 +229,7 @@ attributes T_OBJECT identifier T_STRING m_Item->SetType($4); m_Item->SetName($5); } -inherits_specifier expressionlist +object_inherits_specifier expressionlist { ExpressionList::Ptr exprl = *$8; delete $8; @@ -161,19 +257,19 @@ attribute: T_ABSTRACT } ; -inherits_list: inherits_item - | inherits_list ',' inherits_item +object_inherits_list: object_inherits_item + | object_inherits_list ',' object_inherits_item ; -inherits_item: T_STRING +object_inherits_item: T_STRING { m_Item->AddParent($1); free($1); } ; -inherits_specifier: /* empty */ - | T_INHERITS inherits_list +object_inherits_specifier: /* empty */ + | T_INHERITS object_inherits_list ; expressionlist: '{' diff --git a/lib/config/configcompiler.cpp b/lib/config/configcompiler.cpp index fa0427726..a9b1a25ac 100644 --- a/lib/config/configcompiler.cpp +++ b/lib/config/configcompiler.cpp @@ -76,9 +76,26 @@ void *ConfigCompiler::GetScanner(void) const * * @returns A list of configuration items. */ -vector ConfigCompiler::GetResult(void) const +vector ConfigCompiler::GetResultObjects(void) const { - return m_Result; + return m_ResultObjects; +} + +/** + * Retrieves the resulting type objects from the compiler. + * + * @returns A list of type objects. + */ +vector ConfigCompiler::GetResultTypes(void) const +{ + vector types; + + ConfigType::Ptr type; + BOOST_FOREACH(tie(tuples::ignore, type), m_ResultTypes) { + types.push_back(type); + } + + return types; } /** @@ -101,8 +118,13 @@ String ConfigCompiler::GetPath(void) const void ConfigCompiler::HandleInclude(const String& include, bool search) { String path = Utility::DirName(GetPath()) + "/" + include; - vector items = m_HandleInclude(path, search); - std::copy(items.begin(), items.end(), back_inserter(m_Result)); + + vector types; + m_HandleInclude(path, search, &m_ResultObjects, &types); + + BOOST_FOREACH(const ConfigType::Ptr& type, types) { + AddType(type); + } } /** @@ -122,14 +144,23 @@ void ConfigCompiler::HandleLibrary(const String& library) * @param stream The input stream. * @returns Configuration items. */ -vector ConfigCompiler::CompileStream(const String& path, - istream *stream) +void ConfigCompiler::CompileStream(const String& path, + istream *stream, vector *resultItems, vector *resultTypes) { stream->exceptions(istream::badbit); ConfigCompiler ctx(path, stream); ctx.Compile(); - return ctx.GetResult(); + + if (resultItems) { + vector items = ctx.GetResultObjects(); + std::copy(items.begin(), items.end(), std::back_inserter(*resultItems)); + } + + if (resultTypes) { + vector types = ctx.GetResultTypes(); + std::copy(types.begin(), types.end(), std::back_inserter(*resultTypes)); + } } /** @@ -138,7 +169,8 @@ vector ConfigCompiler::CompileStream(const String& path, * @param path The path. * @returns Configuration items. */ -vector ConfigCompiler::CompileFile(const String& path) +void ConfigCompiler::CompileFile(const String& path, + vector *resultItems, vector *resultTypes) { ifstream stream; stream.open(path.CStr(), ifstream::in); @@ -148,7 +180,7 @@ vector ConfigCompiler::CompileFile(const String& path) Logger::Write(LogInformation, "config", "Compiling config file: " + path); - return CompileStream(path, &stream); + return CompileStream(path, &stream, resultItems, resultTypes); } /** @@ -158,23 +190,11 @@ vector ConfigCompiler::CompileFile(const String& path) * @param text The text. * @returns Configuration items. */ -vector ConfigCompiler::CompileText(const String& path, - const String& text) +void ConfigCompiler::CompileText(const String& path, const String& text, + vector *resultItems, vector *resultTypes) { stringstream stream(text); - return CompileStream(path, &stream); -} - -/** - * Compiles the specified file and returns the resulting config items in the passed vector. - * - * @param path The file that should be compiled. - * @param resultItems The vector that should be used to store the config items. - */ -void ConfigCompiler::CompileFileIncludeHelper(const String& path, vector& resultItems) -{ - vector items = CompileFile(path); - std::copy(items.begin(), items.end(), std::back_inserter(resultItems)); + return CompileStream(path, &stream, resultItems, resultTypes); } /** @@ -182,9 +202,9 @@ void ConfigCompiler::CompileFileIncludeHelper(const String& path, vector ConfigCompiler::HandleFileInclude(const String& include, bool search) +void ConfigCompiler::HandleFileInclude(const String& include, bool search, + vector *resultItems, vector *resultTypes) { String includePath = include; @@ -209,10 +229,8 @@ vector ConfigCompiler::HandleFileInclude(const String& include, vector items; - if (!Utility::Glob(includePath, boost::bind(&ConfigCompiler::CompileFileIncludeHelper, _1, boost::ref(items)))) + if (!Utility::Glob(includePath, boost::bind(&ConfigCompiler::CompileFile, _1, resultItems, resultTypes))) throw_exception(invalid_argument("Include file '" + include + "' does not exist (or no files found for pattern).")); - - return items; } /** @@ -222,7 +240,7 @@ vector ConfigCompiler::HandleFileInclude(const String& include, */ void ConfigCompiler::AddObject(const ConfigItem::Ptr& object) { - m_Result.push_back(object); + m_ResultObjects.push_back(object); } /** @@ -235,3 +253,19 @@ void ConfigCompiler::AddIncludeSearchDir(const String& dir) m_IncludeSearchDirs.push_back(dir); } +void ConfigCompiler::AddType(const ConfigType::Ptr& type) +{ + m_ResultTypes[type->GetName()] = type; +} + +ConfigType::Ptr ConfigCompiler::GetTypeByName(const String& name) const +{ + map::const_iterator it; + + it = m_ResultTypes.find(name); + + if (it == m_ResultTypes.end()) + return ConfigType::Ptr(); + + return it->second; +} diff --git a/lib/config/configcompiler.h b/lib/config/configcompiler.h index 95e66de93..c697162c6 100644 --- a/lib/config/configcompiler.h +++ b/lib/config/configcompiler.h @@ -32,7 +32,7 @@ namespace icinga class I2_CONFIG_API ConfigCompiler { public: - typedef function (const String&, bool)> HandleIncludeFunc; + typedef function *, vector *)> HandleIncludeFunc; ConfigCompiler(const String& path, istream *input = &cin, HandleIncludeFunc includeHandler = &ConfigCompiler::HandleFileInclude); @@ -40,23 +40,31 @@ public: void Compile(void); - static vector CompileStream(const String& path, - istream *stream); - static vector CompileFile(const String& path); - static vector CompileText(const String& path, - const String& text); + static void CompileStream(const String& path, + istream *stream, vector *resultItems, vector *resultTypes); + static void CompileFile(const String& path, vector *resultItems, vector *resultTypes); + static void CompileText(const String& path, + const String& text, vector *resultItems, vector *resultTypes); - static vector HandleFileInclude(const String& include, bool search); static void AddIncludeSearchDir(const String& dir); - vector GetResult(void) const; + vector GetResultObjects(void) const; + vector GetResultTypes(void) const; String GetPath(void) const; + static void HandleFileInclude(const String& include, bool search, + vector *resultItems, vector *resultTypes); + /* internally used methods */ void HandleInclude(const String& include, bool search); void HandleLibrary(const String& library); + void AddObject(const ConfigItem::Ptr& object); + void AddType(const ConfigType::Ptr& type); + + ConfigType::Ptr GetTypeByName(const String& name) const; + size_t ReadInput(char *buffer, size_t max_bytes); void *GetScanner(void) const; @@ -67,14 +75,13 @@ private: HandleIncludeFunc m_HandleInclude; void *m_Scanner; - vector m_Result; + vector m_ResultObjects; + map m_ResultTypes; static vector m_IncludeSearchDirs; void InitializeScanner(void); void DestroyScanner(void); - - static void CompileFileIncludeHelper(const String& path, vector& resultItems); }; } diff --git a/lib/config/configtype.cpp b/lib/config/configtype.cpp new file mode 100644 index 000000000..c57533736 --- /dev/null +++ b/lib/config/configtype.cpp @@ -0,0 +1,119 @@ +/****************************************************************************** + * Icinga 2 * + * Copyright (C) 2012 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 "i2-config.h" + +using namespace icinga; + +ConfigType::TypeMap ConfigType::m_Types; + +ConfigType::ConfigType(const String& name, const DebugInfo& debuginfo) + : m_Name(name), m_RuleList(boost::make_shared()), m_DebugInfo(debuginfo) +{ } + +String ConfigType::GetName(void) const +{ + return m_Name; +} + +String ConfigType::GetParent(void) const +{ + return m_Parent; +} + +void ConfigType::SetParent(const String& parent) +{ + m_Parent = parent; +} + +TypeRuleList::Ptr ConfigType::GetRuleList(void) const +{ + return m_RuleList; +} + +DebugInfo ConfigType::GetDebugInfo(void) const +{ + return m_DebugInfo; +} + +void ConfigType::ValidateObject(const DynamicObject::Ptr& object) const +{ + DynamicObject::AttributeConstIterator it; + const DynamicObject::AttributeMap& attributes = object->GetAttributes(); + + for (it = attributes.begin(); it != attributes.end(); it++) { + if ((it->second.Type & Attribute_Config) == 0) + continue; + + if (!ValidateAttribute(it->first, it->second.Data)) + Logger::Write(LogWarning, "base", "Configuration attribute '" + it->first + + "' on object '" + object->GetName() + "' of type '" + object->GetType()->GetName() + "' is unknown."); + } +} + +void ConfigType::ValidateDictionary(const Dictionary::Ptr& dictionary, const TypeRuleList::Ptr& ruleList) +{ + String key; + Value value; + BOOST_FOREACH(tie(key, value), dictionary) { + + } +} + +bool ConfigType::ValidateAttribute(const String& name, const Value& value) const +{ + ConfigType::Ptr parent; + + if (m_Parent.IsEmpty()) { + if (GetName() != "DynamicObject") + parent = ConfigType::GetByName("DynamicObject"); + } else { + parent = ConfigType::GetByName(m_Parent); + } + + if (parent && parent->ValidateAttribute(name, value)) + return true; + + TypeRuleList::Ptr subRules; + + if (!m_RuleList->FindMatch(name, value, &subRules)) + return false; + + if (subRules && value.IsObjectType()) + ValidateDictionary(value, subRules); + + return true; +} + +void ConfigType::Commit(void) +{ + m_Types[GetName()] = GetSelf(); +} + +ConfigType::Ptr ConfigType::GetByName(const String& name) +{ + ConfigType::TypeMap::iterator it; + + it = m_Types.find(name); + + if (it == m_Types.end()) + return ConfigType::Ptr(); + + return it->second; +} diff --git a/lib/config/configtype.h b/lib/config/configtype.h new file mode 100644 index 000000000..08d2d9347 --- /dev/null +++ b/lib/config/configtype.h @@ -0,0 +1,70 @@ +/****************************************************************************** + * Icinga 2 * + * Copyright (C) 2012 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 CONFIGTYPE_H +#define CONFIGTYPE_H + +namespace icinga +{ + +/** + * A configuration type. Used to validate config objects. + * + * @ingroup config + */ +class I2_CONFIG_API ConfigType : public Object { +public: + typedef shared_ptr Ptr; + typedef weak_ptr WeakPtr; + + ConfigType(const String& name, const DebugInfo& debuginfo); + + String GetName(void) const; + + String GetParent(void) const; + void SetParent(const String& parent); + + void Commit(void); + + TypeRuleList::Ptr GetRuleList(void) const; + + DebugInfo GetDebugInfo(void) const; + + void ValidateObject(const DynamicObject::Ptr& object) const; + + static ConfigType::Ptr GetByName(const String& name); + +private: + String m_Name; /**< The type name. */ + String m_Parent; /**< The parent type. */ + + TypeRuleList::Ptr m_RuleList; + DebugInfo m_DebugInfo; /**< Debug information. */ + + typedef map TypeMap; + static TypeMap m_Types; /**< All registered configuration types. */ + + bool ValidateAttribute(const String& name, const Value& value) const; + static void ValidateDictionary(const Dictionary::Ptr& dictionary, const TypeRuleList::Ptr& ruleList); + +}; + +} + +#endif /* CONFIGTYPE_H */ diff --git a/lib/config/i2-config.h b/lib/config/i2-config.h index c378e182d..468f1a92e 100644 --- a/lib/config/i2-config.h +++ b/lib/config/i2-config.h @@ -46,6 +46,9 @@ using std::endl; #endif /* I2_CONFIG_BUILD */ #include "debuginfo.h" +#include "typerulelist.h" +#include "typerule.h" +#include "configtype.h" #include "expression.h" #include "expressionlist.h" #include "configitem.h" diff --git a/lib/config/typerule.cpp b/lib/config/typerule.cpp new file mode 100644 index 000000000..d7293535e --- /dev/null +++ b/lib/config/typerule.cpp @@ -0,0 +1,63 @@ +/****************************************************************************** + * Icinga 2 * + * Copyright (C) 2012 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 "i2-config.h" + +using namespace icinga; + +TypeRule::TypeRule(TypeSpecifier type, const String& namePattern, + const TypeRuleList::Ptr& subRules, const DebugInfo& debuginfo) + : m_Type(type), m_NamePattern(namePattern), m_SubRules(subRules), m_DebugInfo(debuginfo) +{ } + +TypeRuleList::Ptr TypeRule::GetSubRules(void) const +{ + return m_SubRules; +} + +bool TypeRule::Matches(const String& name, const Value& value) const +{ + if (!Utility::Match(m_NamePattern, name)) + return false; + + switch (m_Type) { + case TypeAny: + return true; + + case TypeString: + /* fall through; any scalar can be converted to a string */ + case TypeScalar: + return value.IsScalar(); + + case TypeNumber: + try { + Convert::ToDouble(value); + } catch (...) { + return false; + } + + return true; + + case TypeDictionary: + return value.IsObjectType(); + + default: + assert(!"Type rule has invalid type specifier."); + } +} diff --git a/lib/config/typerule.h b/lib/config/typerule.h new file mode 100644 index 000000000..e95974f49 --- /dev/null +++ b/lib/config/typerule.h @@ -0,0 +1,64 @@ +/****************************************************************************** + * Icinga 2 * + * Copyright (C) 2012 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 TYPERULE_H +#define TYPERULE_H + +namespace icinga +{ + +/** + * The allowed type for a type rule. + * + * @ingroup config + */ +enum TypeSpecifier +{ + TypeAny, + TypeScalar, + TypeNumber, + TypeString, + TypeDictionary +}; + +/** + * A configuration type rule. + * + * @ingroup config + */ +struct I2_CONFIG_API TypeRule +{ +public: + TypeRule(TypeSpecifier type, const String& namePattern, + const TypeRuleList::Ptr& subRules, const DebugInfo& debuginfo); + + TypeRuleList::Ptr GetSubRules(void) const; + + bool Matches(const String& name, const Value& value) const; + +private: + TypeSpecifier m_Type; + String m_NamePattern; + TypeRuleList::Ptr m_SubRules; + DebugInfo m_DebugInfo; +}; + +} + +#endif /* TYPERULE_H */ diff --git a/lib/config/typerulelist.cpp b/lib/config/typerulelist.cpp new file mode 100644 index 000000000..d9d156dbd --- /dev/null +++ b/lib/config/typerulelist.cpp @@ -0,0 +1,73 @@ +/****************************************************************************** + * Icinga 2 * + * Copyright (C) 2012 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 "i2-config.h" + +using namespace icinga; + +/** + * Adds a rule to a rule list. + * + * @param rule The rule that should be added. + */ +void TypeRuleList::AddRule(const TypeRule& rule) +{ + m_Rules.push_back(rule); +} + +/** + * Adds all rules from the specified rule list. + * + * @param ruleList The rule list to copy rules from. + */ +void TypeRuleList::AddRules(const TypeRuleList::Ptr& ruleList) +{ + BOOST_FOREACH(const TypeRule& rule, ruleList->m_Rules) { + AddRule(rule); + } +} + +/** + * Returns the number of rules currently contained in the list. + * + * @returns The length of the list. + */ +size_t TypeRuleList::GetLength(void) const +{ + return m_Rules.size(); +} + +/** + * Finds a matching rule. + * + * @param name The name of the attribute. + * @param value The value of the attribute. + * *@param[out] subRules The list of sub-rules for the matching rule. + */ +bool TypeRuleList::FindMatch(const String& name, const Value& value, TypeRuleList::Ptr *subRules) +{ + BOOST_FOREACH(const TypeRule& rule, m_Rules) { + if (rule.Matches(name, value)) { + *subRules = rule.GetSubRules(); + return true; + } + } + + return false; +} diff --git a/lib/config/typerulelist.h b/lib/config/typerulelist.h new file mode 100644 index 000000000..4ec128ed6 --- /dev/null +++ b/lib/config/typerulelist.h @@ -0,0 +1,52 @@ +/****************************************************************************** + * Icinga 2 * + * Copyright (C) 2012 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 TYPERULELIST_H +#define TYPERULELIST_H + +namespace icinga +{ + +struct TypeRule; + +/** + * A list of configuration type rules. + * + * @ingroup config + */ +class I2_CONFIG_API TypeRuleList : public Object +{ +public: + typedef shared_ptr Ptr; + typedef weak_ptr WeakPtr; + + void AddRule(const TypeRule& rule); + void AddRules(const TypeRuleList::Ptr& ruleList); + + bool FindMatch(const String& name, const Value& value, TypeRuleList::Ptr *subRules); + + size_t GetLength(void) const; + +private: + vector m_Rules; +}; + +} + +#endif /* TYPERULELIST_H */ -- 2.50.0