mirror of https://github.com/Icinga/icinga2.git
commit
dc415a620a
|
@ -24,8 +24,8 @@ define objects the `object` keyword is used:
|
|||
|
||||
Each object is uniquely identified by its type (`Host`) and name
|
||||
(`host1.example.org`). Objects can contain a comma-separated list of
|
||||
property declarations. The following data types are available for
|
||||
property values:
|
||||
property declarations. Instead of commas semi-colons may also be used.
|
||||
The following data types are available for property values:
|
||||
|
||||
### Expressions
|
||||
|
||||
|
@ -52,6 +52,9 @@ Example:
|
|||
Supported suffixes include ms (milliseconds), s (seconds), m (minutes),
|
||||
h (hours) and d (days).
|
||||
|
||||
Duration literals are converted to seconds by the config parser and
|
||||
are treated like numeric literals.
|
||||
|
||||
#### <a id="string-literals"></a> String Literals
|
||||
|
||||
A string.
|
||||
|
@ -170,7 +173,7 @@ in | "foo" in [ "foo", "bar" ] (true) | Element contained in
|
|||
!in | "foo" !in [ "bar", "baz" ] (true) | Element not contained in array
|
||||
() | (3 + 3) * 5 | Groups sub-expressions
|
||||
|
||||
Constants may be used in constant expressions:
|
||||
Constants may be used in expressions:
|
||||
|
||||
const MyCheckInterval = 10m
|
||||
|
||||
|
@ -200,6 +203,7 @@ intersection(array, array, ...) | Returns an array containing all unique element
|
|||
string(value) | Converts the value to a string.
|
||||
number(value) | Converts the value to a number.
|
||||
bool(value) | Converts to value to a bool.
|
||||
log(value) | Writes a message to the log. Non-string values are converted to a JSON string.
|
||||
|
||||
### <a id="operators"></a> Dictionary Operators
|
||||
|
||||
|
@ -222,65 +226,67 @@ In this example a has the value 7 after both instructions are executed.
|
|||
|
||||
#### <a id="operator-additive-assignment"></a> Operator +=
|
||||
|
||||
Modifies a dictionary or array by adding new elements to it.
|
||||
|
||||
Example:
|
||||
The += operator is a shortcut. The following expression:
|
||||
|
||||
{
|
||||
a = [ "hello" ],
|
||||
a += [ "world" ]
|
||||
}
|
||||
|
||||
In this example a contains both `"hello"` and `"world"`. This currently
|
||||
only works for dictionaries and arrays.
|
||||
is equivalent to:
|
||||
|
||||
<!--
|
||||
{
|
||||
a = [ "hello" ],
|
||||
a = a + [ "world" ]
|
||||
}
|
||||
|
||||
#### <a id="operator-substractive-assignment"></a> Operator -=
|
||||
|
||||
Removes elements from a dictionary.
|
||||
|
||||
Example:
|
||||
The -= operator is a shortcut. The following expression:
|
||||
|
||||
{
|
||||
a = { "hello", "world" },
|
||||
a -= [ "world" ]
|
||||
a = 10,
|
||||
a -= 5
|
||||
}
|
||||
|
||||
In this example a contains `"hello"`. Trying to remove an item that does
|
||||
not exist is not an error. Not implemented yet.
|
||||
is equivalent to:
|
||||
|
||||
{
|
||||
a = 10,
|
||||
a = a - 5
|
||||
}
|
||||
|
||||
#### <a id="operator-multiply-assignment"></a> Operator \*=
|
||||
|
||||
Multiplies an existing dictionary element with the specified number. If
|
||||
the dictionary element does not already exist 0 is used as its value.
|
||||
|
||||
Example:
|
||||
The *= operator is a shortcut. The following expression:
|
||||
|
||||
{
|
||||
a = 60,
|
||||
a *= 5
|
||||
}
|
||||
|
||||
In this example a is 300. This only works for numbers. Not implemented
|
||||
yet.
|
||||
is equivalent to:
|
||||
|
||||
{
|
||||
a = 60,
|
||||
a = a * 5
|
||||
}
|
||||
|
||||
#### <a id="operator-dividing-assignment"></a> Operator /=
|
||||
|
||||
Divides an existing dictionary element by the specified number. If the
|
||||
dictionary element does not already exist 0 is used as its value.
|
||||
|
||||
Example:
|
||||
The /= operator is a shortcut. The following expression:
|
||||
|
||||
{
|
||||
a = 300,
|
||||
a /= 5
|
||||
}
|
||||
|
||||
In this example a is 60. This only works for numbers. Not implemented
|
||||
yet.
|
||||
is equivalent to:
|
||||
|
||||
-->
|
||||
{
|
||||
a = 300,
|
||||
a = a / 5
|
||||
}
|
||||
|
||||
### <a id="indexer"></a> Indexer
|
||||
|
||||
|
@ -350,13 +356,11 @@ override its value by setting it explicitely to `null`.
|
|||
custom = null
|
||||
}
|
||||
|
||||
|
||||
The same method applies for disabling services defined in the inline `services`
|
||||
dictionary by explicitly overriding their value with `null`.
|
||||
|
||||
services["ping6"] = null
|
||||
|
||||
|
||||
### <a id="constants"></a> Constants
|
||||
|
||||
Global constants can be set using the `const` keyword:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -157,6 +157,14 @@ void Array::Resize(size_t new_size)
|
|||
m_Data.resize(new_size);
|
||||
}
|
||||
|
||||
void Array::Clear(void)
|
||||
{
|
||||
ASSERT(!OwnsLock());
|
||||
ObjectLock olock(this);
|
||||
|
||||
m_Data.clear();
|
||||
}
|
||||
|
||||
void Array::CopyTo(const Array::Ptr& dest) const
|
||||
{
|
||||
ASSERT(!OwnsLock());
|
||||
|
|
|
@ -56,6 +56,7 @@ public:
|
|||
void Remove(Iterator it);
|
||||
|
||||
void Resize(size_t new_size);
|
||||
void Clear(void);
|
||||
|
||||
void CopyTo(const Array::Ptr& dest) const;
|
||||
Array::Ptr ShallowClone(void) const;
|
||||
|
|
|
@ -38,28 +38,31 @@ void __cxa_throw(void *obj, void *pvtinfo, void (*dest)(void *))
|
|||
void *thrown_ptr = obj;
|
||||
const std::type_info *tinfo = static_cast<std::type_info *>(pvtinfo);
|
||||
const std::type_info *boost_exc = &typeid(boost::exception);
|
||||
const std::type_info *user_exc = &typeid(user_error);
|
||||
|
||||
/* Check if the exception is a pointer type. */
|
||||
if (tinfo->__is_pointer_p())
|
||||
thrown_ptr = *(void **)thrown_ptr;
|
||||
|
||||
if (!user_exc->__do_catch(tinfo, &thrown_ptr, 1)) {
|
||||
#endif /* __APPLE__ */
|
||||
StackTrace stack;
|
||||
SetLastExceptionStack(stack);
|
||||
|
||||
StackTrace stack;
|
||||
SetLastExceptionStack(stack);
|
||||
|
||||
ContextTrace context;
|
||||
SetLastExceptionContext(context);
|
||||
ContextTrace context;
|
||||
SetLastExceptionContext(context);
|
||||
|
||||
#ifndef __APPLE__
|
||||
/* Check if thrown_ptr inherits from boost::exception. */
|
||||
if (boost_exc->__do_catch(tinfo, &thrown_ptr, 1)) {
|
||||
boost::exception *ex = (boost::exception *)thrown_ptr;
|
||||
/* Check if thrown_ptr inherits from boost::exception. */
|
||||
if (boost_exc->__do_catch(tinfo, &thrown_ptr, 1)) {
|
||||
boost::exception *ex = (boost::exception *)thrown_ptr;
|
||||
|
||||
if (boost::get_error_info<StackTraceErrorInfo>(*ex) == NULL)
|
||||
*ex << StackTraceErrorInfo(stack);
|
||||
if (boost::get_error_info<StackTraceErrorInfo>(*ex) == NULL)
|
||||
*ex << StackTraceErrorInfo(stack);
|
||||
|
||||
if (boost::get_error_info<ContextTraceErrorInfo>(*ex) == NULL)
|
||||
*ex << ContextTraceErrorInfo(context);
|
||||
if (boost::get_error_info<ContextTraceErrorInfo>(*ex) == NULL)
|
||||
*ex << ContextTraceErrorInfo(context);
|
||||
}
|
||||
}
|
||||
#endif /* __APPLE__ */
|
||||
|
||||
|
|
|
@ -39,6 +39,8 @@
|
|||
namespace icinga
|
||||
{
|
||||
|
||||
class I2_BASE_API user_error : virtual public std::exception, virtual public boost::exception { };
|
||||
|
||||
I2_BASE_API StackTrace *GetLastExceptionStack(void);
|
||||
I2_BASE_API void SetLastExceptionStack(const StackTrace& trace);
|
||||
|
||||
|
@ -55,22 +57,24 @@ String DiagnosticInformation(const T& ex, StackTrace *stack = NULL, ContextTrace
|
|||
|
||||
result << boost::diagnostic_information(ex);
|
||||
|
||||
if (boost::get_error_info<StackTraceErrorInfo>(ex) == NULL) {
|
||||
result << std::endl;
|
||||
if (dynamic_cast<const user_error *>(&ex) == NULL) {
|
||||
if (boost::get_error_info<StackTraceErrorInfo>(ex) == NULL) {
|
||||
result << std::endl;
|
||||
|
||||
if (stack)
|
||||
result << *stack;
|
||||
else
|
||||
result << *GetLastExceptionStack();
|
||||
}
|
||||
if (stack)
|
||||
result << *stack;
|
||||
else
|
||||
result << *GetLastExceptionStack();
|
||||
}
|
||||
|
||||
if (boost::get_error_info<ContextTraceErrorInfo>(ex) == NULL) {
|
||||
result << std::endl;
|
||||
if (boost::get_error_info<ContextTraceErrorInfo>(ex) == NULL) {
|
||||
result << std::endl;
|
||||
|
||||
if (context)
|
||||
result << *context;
|
||||
else
|
||||
result << *GetLastExceptionContext();
|
||||
if (context)
|
||||
result << *context;
|
||||
else
|
||||
result << *GetLastExceptionContext();
|
||||
}
|
||||
}
|
||||
|
||||
return result.str();
|
||||
|
|
|
@ -17,32 +17,37 @@
|
|||
* 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 "base/application.h"
|
||||
#include <boost/regex.hpp>
|
||||
#include <algorithm>
|
||||
#include <set>
|
||||
|
||||
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(len, &ScriptUtils::Len);
|
||||
REGISTER_SCRIPTFUNCTION(union, &ScriptUtils::Union);
|
||||
REGISTER_SCRIPTFUNCTION(intersection, &ScriptUtils::Intersection);
|
||||
REGISTER_SCRIPTFUNCTION(log, &ScriptUtils::Log);
|
||||
REGISTER_SCRIPTFUNCTION(exit, &ScriptUtils::Exit);
|
||||
|
||||
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;
|
||||
|
@ -55,7 +60,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;
|
||||
|
||||
|
@ -75,7 +80,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>();
|
||||
|
@ -98,3 +103,16 @@ Array::Ptr UtilityFuncs::Intersection(const std::vector<Value>& arguments)
|
|||
|
||||
return result;
|
||||
}
|
||||
|
||||
void ScriptUtils::Log(const Value& message)
|
||||
{
|
||||
if (message.IsString())
|
||||
::Log(LogInformation, "config", message);
|
||||
else
|
||||
::Log(LogInformation, "config", JsonSerialize(message));
|
||||
}
|
||||
|
||||
void ScriptUtils::Exit(int code)
|
||||
{
|
||||
exit(code);
|
||||
}
|
|
@ -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,20 +28,22 @@ 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 Value& message);
|
||||
static void Exit(int code);
|
||||
|
||||
private:
|
||||
UtilityFuncs(void);
|
||||
ScriptUtils(void);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* UTILITYFUNCS_H */
|
||||
#endif /* SCRIPTUTILS_H */
|
|
@ -22,7 +22,6 @@
|
|||
#include "base/utility.h"
|
||||
#include "base/convert.h"
|
||||
#include "base/application.h"
|
||||
#include <boost/algorithm/string/trim.hpp>
|
||||
|
||||
#ifdef HAVE_BACKTRACE_SYMBOLS
|
||||
# include <execinfo.h>
|
||||
|
@ -100,43 +99,6 @@ void StackTrace::Initialize(void)
|
|||
#endif /* _WIN32 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks up source file name and line number information for the specified
|
||||
* ELF executable and RVA.
|
||||
*
|
||||
* @param exe The ELF file.
|
||||
* @param rva The RVA.
|
||||
* @returns Source file and line number.
|
||||
*/
|
||||
String StackTrace::Addr2Line(const String& exe, uintptr_t rva)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
std::ostringstream msgbuf;
|
||||
msgbuf << "addr2line -s -e " << Application::GetExePath(exe) << " " << std::hex << rva << " 2>/dev/null";
|
||||
|
||||
String args = msgbuf.str();
|
||||
|
||||
FILE *fp = popen(args.CStr(), "r");
|
||||
|
||||
if (!fp)
|
||||
return "RVA: " + Convert::ToString(rva);
|
||||
|
||||
char buffer[512] = {};
|
||||
fgets(buffer, sizeof(buffer), fp);
|
||||
fclose(fp);
|
||||
|
||||
String line = buffer;
|
||||
boost::algorithm::trim_right(line);
|
||||
|
||||
if (line.GetLength() == 0)
|
||||
return "RVA: " + Convert::ToString(rva);
|
||||
|
||||
return line;
|
||||
#else /* _WIN32 */
|
||||
return String();
|
||||
#endif /* _WIN32 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints a stacktrace to the specified stream.
|
||||
*
|
||||
|
@ -176,15 +138,7 @@ void StackTrace::Print(std::ostream& fp, int ignoreFrames) const
|
|||
path = path.SubStr(slashp + 1);
|
||||
|
||||
message = path + ": " + sym_demangled + " (" + String(sym_end);
|
||||
|
||||
#ifdef HAVE_DLADDR
|
||||
Dl_info dli;
|
||||
|
||||
if (dladdr(m_Frames[i], &dli) > 0) {
|
||||
uintptr_t rva = reinterpret_cast<uintptr_t>(m_Frames[i]) - reinterpret_cast<uintptr_t>(dli.dli_fbase);
|
||||
message += " (" + Addr2Line(dli.dli_fname, rva) + ")";
|
||||
}
|
||||
#endif /* HAVE_DLADDR */
|
||||
message += " (" + Utility::GetSymbolSource(m_Frames[i]) + ")";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -50,7 +50,6 @@ private:
|
|||
static boost::once_flag m_OnceFlag;
|
||||
|
||||
static void Initialize(void);
|
||||
static String Addr2Line(const String& exe, uintptr_t rva);
|
||||
};
|
||||
|
||||
I2_BASE_API std::ostream& operator<<(std::ostream& stream, const StackTrace& trace);
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <boost/foreach.hpp>
|
||||
#include <boost/algorithm/string/split.hpp>
|
||||
#include <boost/algorithm/string/classification.hpp>
|
||||
#include <boost/algorithm/string/trim.hpp>
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
# include <pthread_np.h>
|
||||
|
@ -81,6 +82,69 @@ String Utility::GetTypeName(const std::type_info& ti)
|
|||
return DemangleSymbolName(ti.name());
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks up source file name and line number information for the specified
|
||||
* ELF executable and RVA.
|
||||
*
|
||||
* @param exe The ELF file.
|
||||
* @param rva The RVA.
|
||||
* @returns Source file and line number.
|
||||
*/
|
||||
String Utility::Addr2Line(const String& exe, uintptr_t rva)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
std::ostringstream msgbuf;
|
||||
msgbuf << "addr2line -s -e " << Application::GetExePath(exe) << " " << std::hex << rva << " 2>/dev/null";
|
||||
|
||||
String args = msgbuf.str();
|
||||
|
||||
FILE *fp = popen(args.CStr(), "r");
|
||||
|
||||
if (!fp)
|
||||
return "RVA: " + Convert::ToString(rva);
|
||||
|
||||
char buffer[512] = {};
|
||||
fgets(buffer, sizeof(buffer), fp);
|
||||
fclose(fp);
|
||||
|
||||
String line = buffer;
|
||||
boost::algorithm::trim_right(line);
|
||||
|
||||
if (line.GetLength() == 0)
|
||||
return "RVA: " + Convert::ToString(rva);
|
||||
|
||||
return line;
|
||||
#else /* _WIN32 */
|
||||
return String();
|
||||
#endif /* _WIN32 */
|
||||
}
|
||||
|
||||
String Utility::GetSymbolName(const void *addr)
|
||||
{
|
||||
#ifdef HAVE_DLADDR
|
||||
Dl_info dli;
|
||||
|
||||
if (dladdr(addr, &dli) > 0)
|
||||
return dli.dli_sname;
|
||||
#endif /* HAVE_DLADDR */
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
String Utility::GetSymbolSource(const void *addr)
|
||||
{
|
||||
#ifdef HAVE_DLADDR
|
||||
Dl_info dli;
|
||||
|
||||
if (dladdr(addr, &dli) > 0) {
|
||||
uintptr_t rva = reinterpret_cast<uintptr_t>(addr) - reinterpret_cast<uintptr_t>(dli.dli_fbase);
|
||||
return Addr2Line(dli.dli_fname, rva);
|
||||
}
|
||||
#endif /* HAVE_DLADDR */
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs wildcard pattern matching.
|
||||
*
|
||||
|
|
|
@ -59,6 +59,9 @@ class I2_BASE_API Utility
|
|||
public:
|
||||
static String DemangleSymbolName(const String& sym);
|
||||
static String GetTypeName(const std::type_info& ti);
|
||||
static String Addr2Line(const String& exe, uintptr_t rva);
|
||||
static String GetSymbolName(const void *addr);
|
||||
static String GetSymbolSource(const void *addr);
|
||||
|
||||
static bool Match(const String& pattern, const String& text);
|
||||
|
||||
|
|
|
@ -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() + "'"));
|
||||
|
@ -440,6 +449,8 @@ 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<int>(lhs) < static_cast<int>(rhs);
|
||||
else if (lhs.GetTypeName() != rhs.GetTypeName())
|
||||
return lhs.GetTypeName() < rhs.GetTypeName();
|
||||
else
|
||||
BOOST_THROW_EXCEPTION(std::invalid_argument("Operator < cannot be applied to values of type '" + lhs.GetTypeName() + "' and '" + rhs.GetTypeName() + "'"));
|
||||
}
|
||||
|
@ -470,6 +481,8 @@ 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<int>(lhs) > static_cast<int>(rhs);
|
||||
else if (lhs.GetTypeName() != rhs.GetTypeName())
|
||||
return lhs.GetTypeName() > rhs.GetTypeName();
|
||||
else
|
||||
BOOST_THROW_EXCEPTION(std::invalid_argument("Operator > cannot be applied to values of type '" + lhs.GetTypeName() + "' and '" + rhs.GetTypeName() + "'"));
|
||||
}
|
||||
|
@ -500,6 +513,8 @@ 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<int>(lhs) <= static_cast<int>(rhs);
|
||||
else if (lhs.GetTypeName() != rhs.GetTypeName())
|
||||
return lhs.GetTypeName() <= rhs.GetTypeName();
|
||||
else
|
||||
BOOST_THROW_EXCEPTION(std::invalid_argument("Operator <= cannot be applied to values of type '" + lhs.GetTypeName() + "' and '" + rhs.GetTypeName() + "'"));
|
||||
}
|
||||
|
@ -530,6 +545,8 @@ 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<int>(lhs) >= static_cast<int>(rhs);
|
||||
else if (lhs.GetTypeName() != rhs.GetTypeName())
|
||||
return lhs.GetTypeName() >= rhs.GetTypeName();
|
||||
else
|
||||
BOOST_THROW_EXCEPTION(std::invalid_argument("Operator >= cannot be applied to values of type '" + lhs.GetTypeName() + "' and '" + rhs.GetTypeName() + "'"));
|
||||
}
|
||||
|
|
|
@ -27,10 +27,10 @@ mkembedconfig_target(base-type.conf base-type.cpp)
|
|||
include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
add_library(config SHARED
|
||||
aexpression.cpp applyrule.cpp avalue.cpp base-type.conf base-type.cpp
|
||||
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)
|
||||
|
|
|
@ -18,135 +18,449 @@
|
|||
******************************************************************************/
|
||||
|
||||
#include "config/aexpression.h"
|
||||
#include "config/configerror.h"
|
||||
#include "base/array.h"
|
||||
#include "base/serializer.h"
|
||||
#include "base/context.h"
|
||||
#include "base/scriptfunction.h"
|
||||
#include "base/scriptvariable.h"
|
||||
#include "base/utility.h"
|
||||
#include "base/objectlock.h"
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/exception_ptr.hpp>
|
||||
#include <boost/exception/errinfo_nested_exception.hpp>
|
||||
|
||||
using namespace icinga;
|
||||
|
||||
AExpression::AExpression(AOperator op, const AValue& operand1, const DebugInfo& di)
|
||||
: m_Operator(op), m_Operand1(operand1), m_DebugInfo(di)
|
||||
{
|
||||
ASSERT(op == AEReturn);
|
||||
}
|
||||
AExpression::AExpression(OpCallback op, const Value& operand1, const DebugInfo& di)
|
||||
: m_Operator(op), m_Operand1(operand1), m_Operand2(), m_DebugInfo(di)
|
||||
{ }
|
||||
|
||||
AExpression::AExpression(AOperator op, const AValue& operand1, const AValue& operand2, const DebugInfo& di)
|
||||
AExpression::AExpression(OpCallback op, const Value& operand1, const Value& operand2, const DebugInfo& di)
|
||||
: m_Operator(op), m_Operand1(operand1), m_Operand2(operand2), m_DebugInfo(di)
|
||||
{
|
||||
ASSERT(op == AEAdd || op == AENegate || op == AESubtract || op == AEMultiply || op == AEDivide ||
|
||||
op == AEBinaryAnd || op == AEBinaryOr || op == AEShiftLeft || op == AEShiftRight ||
|
||||
op == AEEqual || op == AENotEqual || op == AEIn || op == AENotIn ||
|
||||
op == AELogicalAnd || op == AELogicalOr || op == AEFunctionCall);
|
||||
}
|
||||
{ }
|
||||
|
||||
Value AExpression::Evaluate(const Dictionary::Ptr& locals) const
|
||||
{
|
||||
Value left, right;
|
||||
Array::Ptr arr, arr2;
|
||||
bool found;
|
||||
String funcName;
|
||||
ScriptFunction::Ptr func;
|
||||
std::vector<Value> arguments;
|
||||
|
||||
left = m_Operand1.Evaluate(locals);
|
||||
right = m_Operand2.Evaluate(locals);
|
||||
|
||||
std::ostringstream msgbuf;
|
||||
msgbuf << "Evaluating AExpression " << m_DebugInfo << "; left=" << JsonSerialize(left) << "; right=" << JsonSerialize(right);
|
||||
CONTEXT(msgbuf.str());
|
||||
|
||||
switch (m_Operator) {
|
||||
case AEReturn:
|
||||
return left;
|
||||
case AENegate:
|
||||
return ~(long)left;
|
||||
case AEAdd:
|
||||
return left + right;
|
||||
case AESubtract:
|
||||
return left - right;
|
||||
case AEMultiply:
|
||||
return left * right;
|
||||
case AEDivide:
|
||||
return left / right;
|
||||
case AEBinaryAnd:
|
||||
return left & right;
|
||||
case AEBinaryOr:
|
||||
return left | right;
|
||||
case AEShiftLeft:
|
||||
return left << right;
|
||||
case AEShiftRight:
|
||||
return left >> right;
|
||||
case AEEqual:
|
||||
return left == right;
|
||||
case AENotEqual:
|
||||
return left != right;
|
||||
case AELessThan:
|
||||
return left < right;
|
||||
case AEGreaterThan:
|
||||
return left > right;
|
||||
case AELessThanOrEqual:
|
||||
return left <= right;
|
||||
case AEGreaterThanOrEqual:
|
||||
return left >= right;
|
||||
case AEIn:
|
||||
if (!right.IsObjectType<Array>())
|
||||
BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid right side argument for 'in' operator: " + JsonSerialize(right)));
|
||||
|
||||
arr = right;
|
||||
found = false;
|
||||
BOOST_FOREACH(const Value& value, arr) {
|
||||
if (value == left) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return found;
|
||||
case AENotIn:
|
||||
if (!right.IsObjectType<Array>())
|
||||
BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid right side argument for 'in' operator: " + JsonSerialize(right)));
|
||||
|
||||
arr = right;
|
||||
found = false;
|
||||
BOOST_FOREACH(const Value& value, arr) {
|
||||
if (value == left) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return !found;
|
||||
case AELogicalAnd:
|
||||
return left.ToBool() && right.ToBool();
|
||||
case AELogicalOr:
|
||||
return left.ToBool() || right.ToBool();
|
||||
case AEFunctionCall:
|
||||
funcName = left;
|
||||
func = ScriptFunctionRegistry::GetInstance()->GetItem(funcName);
|
||||
|
||||
if (!func)
|
||||
BOOST_THROW_EXCEPTION(std::invalid_argument("Function '" + funcName + "' does not exist."));
|
||||
|
||||
arr = right;
|
||||
BOOST_FOREACH(const AExpression::Ptr& aexpr, arr) {
|
||||
arguments.push_back(aexpr->Evaluate(locals));
|
||||
}
|
||||
|
||||
return func->Invoke(arguments);
|
||||
case AEArray:
|
||||
arr = left;
|
||||
arr2 = make_shared<Array>();
|
||||
|
||||
if (arr) {
|
||||
BOOST_FOREACH(const AExpression::Ptr& aexpr, arr) {
|
||||
arr2->Add(aexpr->Evaluate(locals));
|
||||
}
|
||||
}
|
||||
|
||||
return arr2;
|
||||
default:
|
||||
ASSERT(!"Invalid operator.");
|
||||
try {
|
||||
return m_Operator(this, locals);
|
||||
} catch (const std::exception& ex) {
|
||||
if (boost::get_error_info<boost::errinfo_nested_exception>(ex))
|
||||
throw;
|
||||
else
|
||||
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;
|
||||
ObjectLock olock(exprl);
|
||||
BOOST_FOREACH(const AExpression::Ptr& expr, exprl) {
|
||||
expr->ExtractPath(path, result);
|
||||
}
|
||||
} else if ((m_Operator == &AExpression::OpSet || m_Operator == &AExpression::OpSetPlus ||
|
||||
m_Operator == &AExpression::OpSetMinus || m_Operator == &AExpression::OpSetMultiply ||
|
||||
m_Operator == &AExpression::OpSetDivide) && path[0] == m_Operand1) {
|
||||
AExpression::Ptr exprl = m_Operand2;
|
||||
|
||||
if (path.size() == 1) {
|
||||
if (m_Operator == &AExpression::OpSet)
|
||||
result->Clear();
|
||||
|
||||
if (exprl->m_Operator != &AExpression::OpDict)
|
||||
BOOST_THROW_EXCEPTION(ConfigError("The '" + path[0] + "' attribute must be a dictionary.") << errinfo_debuginfo(m_DebugInfo));
|
||||
|
||||
Array::Ptr subexprl = exprl->m_Operand1;
|
||||
ObjectLock olock(subexprl);
|
||||
BOOST_FOREACH(const AExpression::Ptr& expr, subexprl) {
|
||||
result->Add(expr);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<String> sub_path(path.begin() + 1, path.end());
|
||||
exprl->ExtractPath(sub_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;
|
||||
ObjectLock olock(exprl);
|
||||
BOOST_FOREACH(const AExpression::Ptr& expr, exprl) {
|
||||
expr->FindDebugInfoPath(path, result);
|
||||
}
|
||||
} else if ((m_Operator == &AExpression::OpSet || m_Operator == &AExpression::OpSetPlus ||
|
||||
m_Operator == &AExpression::OpSetMinus || m_Operator == &AExpression::OpSetMultiply ||
|
||||
m_Operator == &AExpression::OpSetDivide) && 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AExpression::MakeInline(void)
|
||||
{
|
||||
if (m_Operator == &AExpression::OpDict)
|
||||
m_Operand2 = true;
|
||||
}
|
||||
|
||||
void AExpression::DumpOperand(std::ostream& stream, const Value& operand, int indent) {
|
||||
if (operand.IsObjectType<Array>()) {
|
||||
Array::Ptr arr = operand;
|
||||
stream << String(indent, ' ') << "Array:\n";
|
||||
ObjectLock olock(arr);
|
||||
BOOST_FOREACH(const Value& elem, arr) {
|
||||
DumpOperand(stream, elem, indent + 1);
|
||||
}
|
||||
} else if (operand.IsObjectType<AExpression>()) {
|
||||
AExpression::Ptr left = operand;
|
||||
left->Dump(stream, indent);
|
||||
} else {
|
||||
stream << String(indent, ' ') << JsonSerialize(operand) << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
void AExpression::Dump(std::ostream& stream, int indent) const
|
||||
{
|
||||
String sym = Utility::GetSymbolName(reinterpret_cast<const void *>(m_Operator));
|
||||
stream << String(indent, ' ') << "op: " << Utility::DemangleSymbolName(sym) << "\n";
|
||||
stream << String(indent, ' ') << "left:\n";
|
||||
DumpOperand(stream, m_Operand1, indent + 1);
|
||||
|
||||
stream << String(indent, ' ') << "right:\n";
|
||||
DumpOperand(stream, m_Operand2, indent + 1);
|
||||
}
|
||||
|
||||
void AExpression::Dump(void) const
|
||||
{
|
||||
Dump(std::cerr);
|
||||
}
|
||||
|
||||
Value AExpression::EvaluateOperand1(const Dictionary::Ptr& locals) const
|
||||
{
|
||||
return static_cast<AExpression::Ptr>(m_Operand1)->Evaluate(locals);
|
||||
}
|
||||
|
||||
Value AExpression::EvaluateOperand2(const Dictionary::Ptr& locals) const
|
||||
{
|
||||
return static_cast<AExpression::Ptr>(m_Operand2)->Evaluate(locals);
|
||||
}
|
||||
|
||||
Value AExpression::OpLiteral(const AExpression *expr, const Dictionary::Ptr& locals)
|
||||
{
|
||||
return expr->m_Operand1;
|
||||
}
|
||||
|
||||
Value AExpression::OpVariable(const AExpression *expr, const Dictionary::Ptr& locals)
|
||||
{
|
||||
Dictionary::Ptr scope = locals;
|
||||
|
||||
while (scope) {
|
||||
if (scope->Contains(expr->m_Operand1))
|
||||
return scope->Get(expr->m_Operand1);
|
||||
|
||||
scope = scope->Get("__parent");
|
||||
}
|
||||
|
||||
return ScriptVariable::Get(expr->m_Operand1);
|
||||
}
|
||||
|
||||
Value AExpression::OpNegate(const AExpression *expr, const Dictionary::Ptr& locals)
|
||||
{
|
||||
return ~(long)expr->EvaluateOperand1(locals);
|
||||
}
|
||||
|
||||
Value AExpression::OpAdd(const AExpression *expr, const Dictionary::Ptr& locals)
|
||||
{
|
||||
return expr->EvaluateOperand1(locals) + expr->EvaluateOperand2(locals);
|
||||
}
|
||||
|
||||
Value AExpression::OpSubtract(const AExpression *expr, const Dictionary::Ptr& locals)
|
||||
{
|
||||
return expr->EvaluateOperand1(locals) - expr->EvaluateOperand2(locals);
|
||||
}
|
||||
|
||||
Value AExpression::OpMultiply(const AExpression *expr, const Dictionary::Ptr& locals)
|
||||
{
|
||||
return expr->EvaluateOperand1(locals) * expr->EvaluateOperand2(locals);
|
||||
}
|
||||
|
||||
Value AExpression::OpDivide(const AExpression *expr, const Dictionary::Ptr& locals)
|
||||
{
|
||||
return expr->EvaluateOperand1(locals) / expr->EvaluateOperand2(locals);
|
||||
}
|
||||
|
||||
Value AExpression::OpBinaryAnd(const AExpression *expr, const Dictionary::Ptr& locals)
|
||||
{
|
||||
return expr->EvaluateOperand1(locals) & expr->EvaluateOperand2(locals);
|
||||
}
|
||||
|
||||
Value AExpression::OpBinaryOr(const AExpression *expr, const Dictionary::Ptr& locals)
|
||||
{
|
||||
return expr->EvaluateOperand1(locals) | expr->EvaluateOperand2(locals);
|
||||
}
|
||||
|
||||
Value AExpression::OpShiftLeft(const AExpression *expr, const Dictionary::Ptr& locals)
|
||||
{
|
||||
return expr->EvaluateOperand1(locals) << expr->EvaluateOperand2(locals);
|
||||
}
|
||||
|
||||
Value AExpression::OpShiftRight(const AExpression *expr, const Dictionary::Ptr& locals)
|
||||
{
|
||||
return expr->EvaluateOperand1(locals) >> expr->EvaluateOperand2(locals);
|
||||
}
|
||||
|
||||
Value AExpression::OpEqual(const AExpression *expr, const Dictionary::Ptr& locals)
|
||||
{
|
||||
return expr->EvaluateOperand1(locals) == expr->EvaluateOperand2(locals);
|
||||
}
|
||||
|
||||
Value AExpression::OpNotEqual(const AExpression *expr, const Dictionary::Ptr& locals)
|
||||
{
|
||||
return expr->EvaluateOperand1(locals) != expr->EvaluateOperand2(locals);
|
||||
}
|
||||
|
||||
Value AExpression::OpLessThan(const AExpression *expr, const Dictionary::Ptr& locals)
|
||||
{
|
||||
return expr->EvaluateOperand1(locals) < expr->EvaluateOperand2(locals);
|
||||
}
|
||||
|
||||
Value AExpression::OpGreaterThan(const AExpression *expr, const Dictionary::Ptr& locals)
|
||||
{
|
||||
return expr->EvaluateOperand1(locals) > expr->EvaluateOperand2(locals);
|
||||
}
|
||||
|
||||
Value AExpression::OpLessThanOrEqual(const AExpression *expr, const Dictionary::Ptr& locals)
|
||||
{
|
||||
return expr->EvaluateOperand1(locals) <= expr->EvaluateOperand2(locals);
|
||||
}
|
||||
|
||||
Value AExpression::OpGreaterThanOrEqual(const AExpression *expr, const Dictionary::Ptr& locals)
|
||||
{
|
||||
return expr->EvaluateOperand1(locals) >= expr->EvaluateOperand2(locals);
|
||||
}
|
||||
|
||||
Value AExpression::OpIn(const AExpression *expr, const Dictionary::Ptr& locals)
|
||||
{
|
||||
Value right = expr->EvaluateOperand2(locals);
|
||||
|
||||
if (!right.IsObjectType<Array>())
|
||||
BOOST_THROW_EXCEPTION(ConfigError("Invalid right side argument for 'in' operator: " + JsonSerialize(right)));
|
||||
|
||||
Value left = expr->EvaluateOperand1(locals);
|
||||
|
||||
Array::Ptr arr = right;
|
||||
bool found = false;
|
||||
ObjectLock olock(arr);
|
||||
BOOST_FOREACH(const Value& value, arr) {
|
||||
if (value == left) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
Value AExpression::OpNotIn(const AExpression *expr, const Dictionary::Ptr& locals)
|
||||
{
|
||||
return !OpIn(expr, locals);
|
||||
}
|
||||
|
||||
Value AExpression::OpLogicalAnd(const AExpression *expr, const Dictionary::Ptr& locals)
|
||||
{
|
||||
return expr->EvaluateOperand1(locals).ToBool() && expr->EvaluateOperand2(locals).ToBool();
|
||||
}
|
||||
|
||||
Value AExpression::OpLogicalOr(const AExpression *expr, const Dictionary::Ptr& locals)
|
||||
{
|
||||
return expr->EvaluateOperand1(locals).ToBool() || expr->EvaluateOperand2(locals).ToBool();
|
||||
}
|
||||
|
||||
Value AExpression::OpFunctionCall(const AExpression *expr, const Dictionary::Ptr& locals)
|
||||
{
|
||||
String funcName = expr->m_Operand1;
|
||||
ScriptFunction::Ptr func = ScriptFunctionRegistry::GetInstance()->GetItem(funcName);
|
||||
|
||||
if (!func)
|
||||
BOOST_THROW_EXCEPTION(ConfigError("Function '" + funcName + "' does not exist."));
|
||||
|
||||
Array::Ptr arr = expr->EvaluateOperand2(locals);
|
||||
std::vector<Value> arguments;
|
||||
ObjectLock olock(arr);
|
||||
BOOST_FOREACH(const AExpression::Ptr& aexpr, arr) {
|
||||
arguments.push_back(aexpr->Evaluate(locals));
|
||||
}
|
||||
|
||||
return func->Invoke(arguments);
|
||||
}
|
||||
|
||||
Value AExpression::OpArray(const AExpression *expr, const Dictionary::Ptr& locals)
|
||||
{
|
||||
Array::Ptr arr = expr->m_Operand1;
|
||||
Array::Ptr result = make_shared<Array>();
|
||||
|
||||
if (arr) {
|
||||
ObjectLock olock(arr);
|
||||
BOOST_FOREACH(const AExpression::Ptr& aexpr, arr) {
|
||||
result->Add(aexpr->Evaluate(locals));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Value AExpression::OpDict(const AExpression *expr, const Dictionary::Ptr& locals)
|
||||
{
|
||||
Array::Ptr arr = expr->m_Operand1;
|
||||
bool in_place = expr->m_Operand2;
|
||||
Dictionary::Ptr result = make_shared<Dictionary>();
|
||||
|
||||
result->Set("__parent", locals);
|
||||
|
||||
if (arr) {
|
||||
ObjectLock olock(arr);
|
||||
BOOST_FOREACH(const AExpression::Ptr& aexpr, arr) {
|
||||
aexpr->Evaluate(in_place ? locals : result);
|
||||
}
|
||||
}
|
||||
|
||||
result->Remove("__parent");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Value AExpression::OpSet(const AExpression *expr, const Dictionary::Ptr& locals)
|
||||
{
|
||||
Value right = expr->EvaluateOperand2(locals);
|
||||
locals->Set(expr->m_Operand1, right);
|
||||
return right;
|
||||
}
|
||||
|
||||
Value AExpression::OpSetPlus(const AExpression *expr, const Dictionary::Ptr& locals)
|
||||
{
|
||||
Value left = locals->Get(expr->m_Operand1);
|
||||
AExpression::Ptr exp_right = expr->m_Operand2;
|
||||
Dictionary::Ptr xlocals = locals;
|
||||
|
||||
if (exp_right->m_Operator == &AExpression::OpDict) {
|
||||
xlocals = left;
|
||||
|
||||
if (!xlocals)
|
||||
xlocals = make_shared<Dictionary>();
|
||||
|
||||
xlocals->Set("__parent", locals);
|
||||
}
|
||||
|
||||
Value result = left + expr->EvaluateOperand2(xlocals);
|
||||
|
||||
if (exp_right->m_Operator == &AExpression::OpDict) {
|
||||
Dictionary::Ptr dict = result;
|
||||
dict->Remove("__parent");
|
||||
}
|
||||
|
||||
locals->Set(expr->m_Operand1, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
Value AExpression::OpSetMinus(const AExpression *expr, const Dictionary::Ptr& locals)
|
||||
{
|
||||
Value left = locals->Get(expr->m_Operand1);
|
||||
AExpression::Ptr exp_right = expr->m_Operand2;
|
||||
Dictionary::Ptr xlocals = locals;
|
||||
|
||||
if (exp_right->m_Operator == &AExpression::OpDict) {
|
||||
xlocals = left;
|
||||
|
||||
if (!xlocals)
|
||||
xlocals = make_shared<Dictionary>();
|
||||
|
||||
xlocals->Set("__parent", locals);
|
||||
}
|
||||
|
||||
Value result = left - expr->EvaluateOperand2(xlocals);
|
||||
|
||||
if (exp_right->m_Operator == &AExpression::OpDict) {
|
||||
Dictionary::Ptr dict = result;
|
||||
dict->Remove("__parent");
|
||||
}
|
||||
|
||||
locals->Set(expr->m_Operand1, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
Value AExpression::OpSetMultiply(const AExpression *expr, const Dictionary::Ptr& locals)
|
||||
{
|
||||
Value left = locals->Get(expr->m_Operand1);
|
||||
AExpression::Ptr exp_right = expr->m_Operand2;
|
||||
Dictionary::Ptr xlocals = locals;
|
||||
|
||||
if (exp_right->m_Operator == &AExpression::OpDict) {
|
||||
xlocals = left;
|
||||
|
||||
if (!xlocals)
|
||||
xlocals = make_shared<Dictionary>();
|
||||
|
||||
xlocals->Set("__parent", locals);
|
||||
}
|
||||
|
||||
Value result = left * expr->EvaluateOperand2(xlocals);
|
||||
|
||||
if (exp_right->m_Operator == &AExpression::OpDict) {
|
||||
Dictionary::Ptr dict = result;
|
||||
dict->Remove("__parent");
|
||||
}
|
||||
|
||||
locals->Set(expr->m_Operand1, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
Value AExpression::OpSetDivide(const AExpression *expr, const Dictionary::Ptr& locals)
|
||||
{
|
||||
Value left = locals->Get(expr->m_Operand1);
|
||||
AExpression::Ptr exp_right = expr->m_Operand2;
|
||||
Dictionary::Ptr xlocals = locals;
|
||||
|
||||
if (exp_right->m_Operator == &AExpression::OpDict) {
|
||||
xlocals = left;
|
||||
|
||||
if (!xlocals)
|
||||
xlocals = make_shared<Dictionary>();
|
||||
|
||||
xlocals->Set("__parent", locals);
|
||||
}
|
||||
|
||||
Value result = left / expr->EvaluateOperand2(xlocals);
|
||||
|
||||
if (exp_right->m_Operator == &AExpression::OpDict) {
|
||||
Dictionary::Ptr dict = result;
|
||||
dict->Remove("__parent");
|
||||
}
|
||||
|
||||
locals->Set(expr->m_Operand1, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
Value AExpression::OpIndexer(const AExpression *expr, const Dictionary::Ptr& locals)
|
||||
{
|
||||
Dictionary::Ptr dict = OpVariable(expr, locals);
|
||||
|
||||
if (!dict)
|
||||
BOOST_THROW_EXCEPTION(ConfigError("Script variable '" + expr->m_Operand1 + "' not set in this scope."));
|
||||
|
||||
return dict->Get(expr->m_Operand2);
|
||||
}
|
||||
|
|
|
@ -21,42 +21,13 @@
|
|||
#define AEXPRESSION_H
|
||||
|
||||
#include "config/i2-config.h"
|
||||
#include "config/avalue.h"
|
||||
#include "config/debuginfo.h"
|
||||
#include "base/array.h"
|
||||
#include "base/dictionary.h"
|
||||
|
||||
namespace icinga
|
||||
{
|
||||
|
||||
/**
|
||||
* @ingroup config
|
||||
*/
|
||||
enum AOperator
|
||||
{
|
||||
AEReturn,
|
||||
AENegate,
|
||||
AEAdd,
|
||||
AESubtract,
|
||||
AEMultiply,
|
||||
AEDivide,
|
||||
AEBinaryAnd,
|
||||
AEBinaryOr,
|
||||
AEShiftLeft,
|
||||
AEShiftRight,
|
||||
AEEqual,
|
||||
AENotEqual,
|
||||
AEIn,
|
||||
AENotIn,
|
||||
AELogicalAnd,
|
||||
AELogicalOr,
|
||||
AEFunctionCall,
|
||||
AEArray,
|
||||
AELessThan,
|
||||
AEGreaterThan,
|
||||
AELessThanOrEqual,
|
||||
AEGreaterThanOrEqual
|
||||
};
|
||||
|
||||
/**
|
||||
* @ingroup config
|
||||
*/
|
||||
|
@ -64,17 +35,62 @@ class I2_CONFIG_API AExpression : public Object
|
|||
{
|
||||
public:
|
||||
DECLARE_PTR_TYPEDEFS(AExpression);
|
||||
|
||||
typedef Value (*OpCallback)(const AExpression *, const Dictionary::Ptr&);
|
||||
|
||||
AExpression(AOperator op, const AValue& operand1, const DebugInfo& di);
|
||||
AExpression(AOperator op, const AValue& operand1, const AValue& operand2, const DebugInfo& di);
|
||||
AExpression(OpCallback op, const Value& operand1, const DebugInfo& di);
|
||||
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);
|
||||
|
||||
void Dump(std::ostream& stream, int indent = 0) const;
|
||||
void Dump(void) const;
|
||||
|
||||
static Value OpLiteral(const AExpression *expr, const Dictionary::Ptr& locals);
|
||||
static Value OpVariable(const AExpression *expr, const Dictionary::Ptr& locals);
|
||||
static Value OpNegate(const AExpression *expr, const Dictionary::Ptr& locals);
|
||||
static Value OpAdd(const AExpression *expr, const Dictionary::Ptr& locals);
|
||||
static Value OpSubtract(const AExpression *expr, const Dictionary::Ptr& locals);
|
||||
static Value OpMultiply(const AExpression *expr, const Dictionary::Ptr& locals);
|
||||
static Value OpDivide(const AExpression *expr, const Dictionary::Ptr& locals);
|
||||
static Value OpBinaryAnd(const AExpression *expr, const Dictionary::Ptr& locals);
|
||||
static Value OpBinaryOr(const AExpression *expr, const Dictionary::Ptr& locals);
|
||||
static Value OpShiftLeft(const AExpression *expr, const Dictionary::Ptr& locals);
|
||||
static Value OpShiftRight(const AExpression *expr, const Dictionary::Ptr& locals);
|
||||
static Value OpEqual(const AExpression *expr, const Dictionary::Ptr& locals);
|
||||
static Value OpNotEqual(const AExpression *expr, const Dictionary::Ptr& locals);
|
||||
static Value OpLessThan(const AExpression *expr, const Dictionary::Ptr& locals);
|
||||
static Value OpGreaterThan(const AExpression *expr, const Dictionary::Ptr& locals);
|
||||
static Value OpLessThanOrEqual(const AExpression *expr, const Dictionary::Ptr& locals);
|
||||
static Value OpGreaterThanOrEqual(const AExpression *expr, const Dictionary::Ptr& locals);
|
||||
static Value OpIn(const AExpression *expr, const Dictionary::Ptr& locals);
|
||||
static Value OpNotIn(const AExpression *expr, const Dictionary::Ptr& locals);
|
||||
static Value OpLogicalAnd(const AExpression *expr, const Dictionary::Ptr& locals);
|
||||
static Value OpLogicalOr(const AExpression *expr, const Dictionary::Ptr& locals);
|
||||
static Value OpFunctionCall(const AExpression *expr, const Dictionary::Ptr& locals);
|
||||
static Value OpArray(const AExpression *expr, const Dictionary::Ptr& locals);
|
||||
static Value OpDict(const AExpression *expr, const Dictionary::Ptr& locals);
|
||||
static Value OpSet(const AExpression *expr, const Dictionary::Ptr& locals);
|
||||
static Value OpSetPlus(const AExpression *expr, const Dictionary::Ptr& locals);
|
||||
static Value OpSetMinus(const AExpression *expr, const Dictionary::Ptr& locals);
|
||||
static Value OpSetMultiply(const AExpression *expr, const Dictionary::Ptr& locals);
|
||||
static Value OpSetDivide(const AExpression *expr, const Dictionary::Ptr& locals);
|
||||
static Value OpIndexer(const AExpression *expr, const Dictionary::Ptr& locals);
|
||||
|
||||
private:
|
||||
AOperator m_Operator;
|
||||
AValue m_Operand1;
|
||||
AValue m_Operand2;
|
||||
OpCallback m_Operator;
|
||||
Value m_Operand1;
|
||||
Value m_Operand2;
|
||||
DebugInfo m_DebugInfo;
|
||||
|
||||
Value EvaluateOperand1(const Dictionary::Ptr& locals) const;
|
||||
Value EvaluateOperand2(const Dictionary::Ptr& locals) const;
|
||||
|
||||
static void DumpOperand(std::ostream& stream, const Value& operand, int indent);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -24,8 +24,8 @@ using namespace icinga;
|
|||
ApplyRule::RuleMap ApplyRule::m_Rules;
|
||||
ApplyRule::CallbackMap ApplyRule::m_Callbacks;
|
||||
|
||||
ApplyRule::ApplyRule(const String& tmpl, const AExpression::Ptr& expression, const DebugInfo& di)
|
||||
: m_Template(tmpl), m_Expression(expression), m_DebugInfo(di)
|
||||
ApplyRule::ApplyRule(const String& tmpl, const AExpression::Ptr& expression, const DebugInfo& di, const Dictionary::Ptr& scope)
|
||||
: m_Template(tmpl), m_Expression(expression), m_DebugInfo(di), m_Scope(scope)
|
||||
{ }
|
||||
|
||||
String ApplyRule::GetTemplate(void) const
|
||||
|
@ -43,9 +43,14 @@ DebugInfo ApplyRule::GetDebugInfo(void) const
|
|||
return m_DebugInfo;
|
||||
}
|
||||
|
||||
void ApplyRule::AddRule(const String& sourceType, const String& tmpl, const String& targetType, const AExpression::Ptr& expression, const DebugInfo& di)
|
||||
Dictionary::Ptr ApplyRule::GetScope(void) const
|
||||
{
|
||||
m_Rules[std::make_pair(sourceType, targetType)].push_back(ApplyRule(tmpl, expression, di));
|
||||
return m_Scope;
|
||||
}
|
||||
|
||||
void ApplyRule::AddRule(const String& sourceType, const String& tmpl, const String& targetType, const AExpression::Ptr& expression, const DebugInfo& di, const Dictionary::Ptr& scope)
|
||||
{
|
||||
m_Rules[std::make_pair(sourceType, targetType)].push_back(ApplyRule(tmpl, expression, di, scope));
|
||||
}
|
||||
|
||||
void ApplyRule::EvaluateRules(void)
|
||||
|
|
|
@ -42,8 +42,9 @@ public:
|
|||
String GetTemplate(void) const;
|
||||
AExpression::Ptr GetExpression(void) const;
|
||||
DebugInfo GetDebugInfo(void) const;
|
||||
Dictionary::Ptr GetScope(void) const;
|
||||
|
||||
static void AddRule(const String& sourceType, const String& tmpl, const String& targetType, const AExpression::Ptr& expression, const DebugInfo& di);
|
||||
static void AddRule(const String& sourceType, const String& tmpl, const String& targetType, const AExpression::Ptr& expression, const DebugInfo& di, const Dictionary::Ptr& scope);
|
||||
static void EvaluateRules(void);
|
||||
|
||||
static void RegisterCombination(const String& sourceType, const String& targetType, const ApplyRule::Callback& callback);
|
||||
|
@ -53,11 +54,12 @@ private:
|
|||
String m_Template;
|
||||
AExpression::Ptr m_Expression;
|
||||
DebugInfo m_DebugInfo;
|
||||
Dictionary::Ptr m_Scope;
|
||||
|
||||
static CallbackMap m_Callbacks;
|
||||
static RuleMap m_Rules;
|
||||
|
||||
ApplyRule(const String& tmpl, const AExpression::Ptr& expression, const DebugInfo& di);
|
||||
ApplyRule(const String& tmpl, const AExpression::Ptr& expression, const DebugInfo& di, const Dictionary::Ptr& scope);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -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. *
|
||||
******************************************************************************/
|
||||
|
||||
#include "config/avalue.h"
|
||||
#include "config/aexpression.h"
|
||||
#include "base/scriptvariable.h"
|
||||
|
||||
using namespace icinga;
|
||||
|
||||
AValue::AValue(void)
|
||||
: m_Type(ATSimple)
|
||||
{ }
|
||||
|
||||
AValue::AValue(const AExpression::Ptr& expr)
|
||||
: m_Type(ATExpression), m_Expression(expr)
|
||||
{ }
|
||||
|
||||
AValue::AValue(AValueType type, const Value& value)
|
||||
: m_Type(type), m_Value(value)
|
||||
{ }
|
||||
|
||||
Value AValue::Evaluate(const Dictionary::Ptr& locals) const
|
||||
{
|
||||
switch (m_Type) {
|
||||
case ATSimple:
|
||||
return m_Value;
|
||||
case ATVariable:
|
||||
if (locals && locals->Contains(m_Value))
|
||||
return locals->Get(m_Value);
|
||||
else
|
||||
return ScriptVariable::Get(m_Value);
|
||||
case ATThisRef:
|
||||
VERIFY(!"Not implemented.");
|
||||
case ATExpression:
|
||||
return m_Expression->Evaluate(locals);
|
||||
default:
|
||||
ASSERT(!"Invalid type.");
|
||||
}
|
||||
}
|
|
@ -1,64 +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 AVALUE_H
|
||||
#define AVALUE_H
|
||||
|
||||
#include "config/i2-config.h"
|
||||
#include "base/value.h"
|
||||
#include "base/dictionary.h"
|
||||
|
||||
namespace icinga
|
||||
{
|
||||
|
||||
/**
|
||||
* @ingroup config
|
||||
*/
|
||||
enum AValueType
|
||||
{
|
||||
ATSimple,
|
||||
ATVariable,
|
||||
ATThisRef,
|
||||
ATExpression
|
||||
};
|
||||
|
||||
class AExpression;
|
||||
|
||||
/**
|
||||
* @ingroup config
|
||||
*/
|
||||
class I2_CONFIG_API AValue
|
||||
{
|
||||
public:
|
||||
AValue(void);
|
||||
AValue(const shared_ptr<AExpression>& expr);
|
||||
AValue(AValueType type, const Value& value);
|
||||
|
||||
Value Evaluate(const Dictionary::Ptr& locals) const;
|
||||
|
||||
private:
|
||||
AValueType m_Type;
|
||||
Value m_Value;
|
||||
shared_ptr<AExpression> m_Expression;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* AVALUE_H */
|
||||
|
|
@ -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];
|
||||
|
|
|
@ -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,20 @@ 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> rterm_scope
|
||||
%type <variant> lterm
|
||||
%type <num> variable_decl
|
||||
%left T_LOGICAL_OR
|
||||
%left T_LOGICAL_AND
|
||||
|
@ -179,18 +185,22 @@ 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) {
|
||||
ConfigCompilerContext::GetInstance()->AddMessage(true, ex.what(), ex.GetDebugInfo());
|
||||
const DebugInfo *di = boost::get_error_info<errinfo_debuginfo>(ex);
|
||||
ConfigCompilerContext::GetInstance()->AddMessage(true, ex.what(), di ? *di : DebugInfo());
|
||||
} catch (const std::exception& ex) {
|
||||
ConfigCompilerContext::GetInstance()->AddMessage(true, DiagnosticInformation(ex));
|
||||
}
|
||||
|
@ -206,12 +216,21 @@ statements: /* empty */
|
|||
;
|
||||
|
||||
statement: object | type | include | include_recursive | library | variable | apply
|
||||
{ }
|
||||
| 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
|
||||
{
|
||||
|
@ -220,16 +239,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));
|
||||
}
|
||||
;
|
||||
|
||||
|
@ -240,22 +265,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;
|
||||
}
|
||||
;
|
||||
|
||||
|
@ -285,7 +303,7 @@ type: partial_specifier T_TYPE identifier
|
|||
|
||||
if (!m_Type) {
|
||||
if ($1)
|
||||
BOOST_THROW_EXCEPTION(ConfigError("Partial type definition for unknown type '" + name + "'", DebugInfoRange(@1, @3)));
|
||||
BOOST_THROW_EXCEPTION(ConfigError("Partial type definition for unknown type '" + name + "'") << errinfo_debuginfo(DebugInfoRange(@1, @3)));
|
||||
|
||||
m_Type = make_shared<ConfigType>(name, DebugInfoRange(@1, @3));
|
||||
m_Type->Register();
|
||||
|
@ -393,35 +411,38 @@ object:
|
|||
{
|
||||
m_Abstract = false;
|
||||
}
|
||||
object_declaration identifier T_STRING object_inherits_specifier expressionlist
|
||||
object_declaration identifier rterm object_inherits_specifier rterm_scope
|
||||
{
|
||||
DebugInfo di = DebugInfoRange(@2, @6);
|
||||
ConfigItemBuilder::Ptr item = make_shared<ConfigItemBuilder>(di);
|
||||
|
||||
ConfigItem::Ptr oldItem = ConfigItem::GetObject($3, $4);
|
||||
AExpression::Ptr aexpr = static_cast<AExpression::Ptr>(*$4);
|
||||
delete $4;
|
||||
|
||||
String name = aexpr->Evaluate(m_ModuleScope);
|
||||
|
||||
ConfigItem::Ptr oldItem = ConfigItem::GetObject($3, name);
|
||||
|
||||
if (oldItem) {
|
||||
std::ostringstream msgbuf;
|
||||
msgbuf << "Object '" << $4 << "' of type '" << $3 << "' re-defined: " << di << "; previous definition: " << oldItem->GetDebugInfo();
|
||||
msgbuf << "Object '" << name << "' of type '" << $3 << "' re-defined: " << di << "; previous definition: " << oldItem->GetDebugInfo();
|
||||
free($3);
|
||||
free($4);
|
||||
delete $5;
|
||||
BOOST_THROW_EXCEPTION(ConfigError(msgbuf.str(), di));
|
||||
BOOST_THROW_EXCEPTION(ConfigError(msgbuf.str()) << errinfo_debuginfo(di));
|
||||
}
|
||||
|
||||
item->SetType($3);
|
||||
|
||||
if (strchr($4, '!') != NULL) {
|
||||
if (name.FindFirstOf("!") != String::NPos) {
|
||||
std::ostringstream msgbuf;
|
||||
msgbuf << "Name for object '" << $4 << "' of type '" << $3 << "' is invalid: Object names may not contain '!'";
|
||||
msgbuf << "Name for object '" << name << "' of type '" << $3 << "' is invalid: Object names may not contain '!'";
|
||||
free($3);
|
||||
BOOST_THROW_EXCEPTION(ConfigError(msgbuf.str(), @4));
|
||||
BOOST_THROW_EXCEPTION(ConfigError(msgbuf.str()) << errinfo_debuginfo(@4));
|
||||
}
|
||||
|
||||
free($3);
|
||||
|
||||
item->SetName($4);
|
||||
free($4);
|
||||
item->SetName(name);
|
||||
|
||||
if ($5) {
|
||||
BOOST_FOREACH(const String& parent, *$5) {
|
||||
|
@ -431,13 +452,16 @@ 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);
|
||||
|
||||
item->SetScope(m_ModuleScope);
|
||||
|
||||
item->Compile()->Register();
|
||||
item.reset();
|
||||
}
|
||||
|
@ -481,96 +505,39 @@ object_inherits_specifier:
|
|||
}
|
||||
;
|
||||
|
||||
expressionlist: '{' expressions '}'
|
||||
{
|
||||
if ($2)
|
||||
$$ = $2;
|
||||
else
|
||||
$$ = new ExpressionList();
|
||||
}
|
||||
;
|
||||
|
||||
expressions: expressions_inner
|
||||
{
|
||||
$$ = $1;
|
||||
}
|
||||
| expressions_inner ','
|
||||
{
|
||||
$$ = $1;
|
||||
}
|
||||
|
||||
expressions_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
|
||||
lbinary_op: T_SET
|
||||
| T_SET_PLUS
|
||||
| T_SET_MINUS
|
||||
| T_SET_MULTIPLY
|
||||
| T_SET_DIVIDE
|
||||
{
|
||||
$$ = $1;
|
||||
}
|
||||
;
|
||||
|
||||
array_items: array_items_inner
|
||||
comma_or_semicolon: ',' | ';'
|
||||
;
|
||||
|
||||
lterm_items: lterm_items_inner
|
||||
{
|
||||
$$ = $1;
|
||||
}
|
||||
| array_items_inner ','
|
||||
| lterm_items_inner comma_or_semicolon
|
||||
{
|
||||
$$ = $1;
|
||||
}
|
||||
|
||||
array_items_inner: /* empty */
|
||||
lterm_items_inner: /* empty */
|
||||
{
|
||||
$$ = NULL;
|
||||
$$ = new Array();
|
||||
}
|
||||
| aexpression
|
||||
| lterm
|
||||
{
|
||||
$$ = new Array();
|
||||
$$->Add(*$1);
|
||||
delete $1;
|
||||
}
|
||||
| array_items_inner ',' aexpression
|
||||
| lterm_items_inner comma_or_semicolon lterm
|
||||
{
|
||||
if ($1)
|
||||
$$ = $1;
|
||||
|
@ -582,168 +549,156 @@ array_items_inner: /* empty */
|
|||
}
|
||||
;
|
||||
|
||||
aexpression: T_STRING
|
||||
lterm: identifier lbinary_op rterm
|
||||
{
|
||||
$$ = new Value(make_shared<AExpression>(AEReturn, AValue(ATSimple, $1), @1));
|
||||
AExpression::Ptr aexpr = static_cast<AExpression::Ptr>(*$3);
|
||||
$$ = new Value(make_shared<AExpression>($2, $1, aexpr, DebugInfoRange(@1, @3)));
|
||||
free($1);
|
||||
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);
|
||||
}
|
||||
| T_NUMBER
|
||||
| rterm
|
||||
{
|
||||
$$ = new Value(make_shared<AExpression>(AEReturn, AValue(ATSimple, $1), @1));
|
||||
$$ = $1;
|
||||
}
|
||||
| T_NULL
|
||||
;
|
||||
|
||||
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
|
||||
{
|
||||
$$ = new Value(make_shared<AExpression>(AEReturn, AValue(ATSimple, Empty), @1));
|
||||
$$ = $1;
|
||||
}
|
||||
| T_IDENTIFIER '(' array_items ')'
|
||||
;
|
||||
|
||||
rterm_items: rterm_items_inner
|
||||
{
|
||||
Array::Ptr arguments = Array::Ptr($3);
|
||||
$$ = new Value(make_shared<AExpression>(AEFunctionCall, AValue(ATSimple, $1), AValue(ATSimple, arguments), DebugInfoRange(@1, @4)));
|
||||
free($1);
|
||||
$$ = $1;
|
||||
}
|
||||
| T_IDENTIFIER
|
||||
| rterm_items_inner ','
|
||||
{
|
||||
$$ = new Value(make_shared<AExpression>(AEReturn, AValue(ATVariable, $1), @1));
|
||||
free($1);
|
||||
$$ = $1;
|
||||
}
|
||||
| '!' aexpression
|
||||
;
|
||||
|
||||
rterm_items_inner: /* empty */
|
||||
{
|
||||
$$ = new Value(make_shared<AExpression>(AENegate, static_cast<AExpression::Ptr>(*$2), DebugInfoRange(@1, @2)));
|
||||
delete $2;
|
||||
$$ = new Array();
|
||||
}
|
||||
| '~' aexpression
|
||||
| rterm
|
||||
{
|
||||
$$ = new Value(make_shared<AExpression>(AENegate, static_cast<AExpression::Ptr>(*$2), DebugInfoRange(@1, @2)));
|
||||
delete $2;
|
||||
}
|
||||
| '[' array_items ']'
|
||||
{
|
||||
$$ = new Value(make_shared<AExpression>(AEArray, AValue(ATSimple, Array::Ptr($2)), DebugInfoRange(@1, @3)));
|
||||
}
|
||||
| '(' aexpression ')'
|
||||
{
|
||||
$$ = $2;
|
||||
}
|
||||
| aexpression '+' aexpression
|
||||
{
|
||||
$$ = new Value(make_shared<AExpression>(AEAdd, static_cast<AExpression::Ptr>(*$1), static_cast<AExpression::Ptr>(*$3), DebugInfoRange(@1, @3)));
|
||||
$$ = new Array();
|
||||
$$->Add(*$1);
|
||||
delete $1;
|
||||
delete $3;
|
||||
}
|
||||
| aexpression '-' aexpression
|
||||
| rterm_items_inner ',' rterm
|
||||
{
|
||||
$$ = new Value(make_shared<AExpression>(AESubtract, static_cast<AExpression::Ptr>(*$1), static_cast<AExpression::Ptr>(*$3), DebugInfoRange(@1, @3)));
|
||||
delete $1;
|
||||
delete $3;
|
||||
}
|
||||
| aexpression '*' aexpression
|
||||
{
|
||||
$$ = new Value(make_shared<AExpression>(AEMultiply, static_cast<AExpression::Ptr>(*$1), static_cast<AExpression::Ptr>(*$3), DebugInfoRange(@1, @3)));
|
||||
delete $1;
|
||||
delete $3;
|
||||
}
|
||||
| aexpression '/' aexpression
|
||||
{
|
||||
$$ = new Value(make_shared<AExpression>(AEDivide, static_cast<AExpression::Ptr>(*$1), static_cast<AExpression::Ptr>(*$3), DebugInfoRange(@1, @3)));
|
||||
delete $1;
|
||||
delete $3;
|
||||
}
|
||||
| aexpression '&' aexpression
|
||||
{
|
||||
$$ = new Value(make_shared<AExpression>(AEBinaryAnd, static_cast<AExpression::Ptr>(*$1), static_cast<AExpression::Ptr>(*$3), DebugInfoRange(@1, @3)));
|
||||
delete $1;
|
||||
delete $3;
|
||||
}
|
||||
| aexpression '|' aexpression
|
||||
{
|
||||
$$ = new Value(make_shared<AExpression>(AEBinaryOr, 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>(AEIn, 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>(AENotIn, 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>(AELessThanOrEqual, 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>(AEGreaterThanOrEqual, static_cast<AExpression::Ptr>(*$1), static_cast<AExpression::Ptr>(*$3), DebugInfoRange(@1, @3)));
|
||||
delete $1;
|
||||
delete $3;
|
||||
}
|
||||
| aexpression '<' aexpression
|
||||
{
|
||||
$$ = new Value(make_shared<AExpression>(AELessThan, static_cast<AExpression::Ptr>(*$1), static_cast<AExpression::Ptr>(*$3), DebugInfoRange(@1, @3)));
|
||||
delete $1;
|
||||
delete $3;
|
||||
}
|
||||
| aexpression '>' aexpression
|
||||
{
|
||||
$$ = new Value(make_shared<AExpression>(AEGreaterThan, 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>(AEEqual, 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>(AENotEqual, 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>(AEShiftLeft, 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>(AEShiftRight, 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>(AELogicalAnd, 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>(AELogicalOr, static_cast<AExpression::Ptr>(*$1), static_cast<AExpression::Ptr>(*$3), DebugInfoRange(@1, @3)));
|
||||
delete $1;
|
||||
if ($1)
|
||||
$$ = $1;
|
||||
else
|
||||
$$ = new Array();
|
||||
|
||||
$$->Add(*$3);
|
||||
delete $3;
|
||||
}
|
||||
;
|
||||
|
||||
value: expressionlist
|
||||
rbinary_op: '+'
|
||||
{
|
||||
ExpressionList::Ptr exprl = ExpressionList::Ptr($1);
|
||||
$$ = new Value(exprl);
|
||||
$$ = &AExpression::OpAdd;
|
||||
}
|
||||
| aexpression
|
||||
;
|
||||
|
||||
rterm_scope: '{' lterm_items '}'
|
||||
{
|
||||
AExpression::Ptr aexpr = *$1;
|
||||
$$ = new Value(aexpr->Evaluate(Dictionary::Ptr()));
|
||||
$$ = new Value(make_shared<AExpression>(&AExpression::OpDict, Array::Ptr($2), DebugInfoRange(@1, @3)));
|
||||
}
|
||||
;
|
||||
|
||||
rterm: T_STRING
|
||||
{
|
||||
$$ = new Value(make_shared<AExpression>(&AExpression::OpLiteral, $1, @1));
|
||||
free($1);
|
||||
}
|
||||
| T_NUMBER
|
||||
{
|
||||
$$ = new Value(make_shared<AExpression>(&AExpression::OpLiteral, $1, @1));
|
||||
}
|
||||
| T_NULL
|
||||
{
|
||||
$$ = new Value(make_shared<AExpression>(&AExpression::OpLiteral, Empty, @1));
|
||||
}
|
||||
| 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)));
|
||||
free($1);
|
||||
}
|
||||
| T_IDENTIFIER
|
||||
{
|
||||
$$ = new Value(make_shared<AExpression>(&AExpression::OpVariable, $1, @1));
|
||||
free($1);
|
||||
}
|
||||
| '!' rterm
|
||||
{
|
||||
$$ = new Value(make_shared<AExpression>(&AExpression::OpNegate, static_cast<AExpression::Ptr>(*$2), DebugInfoRange(@1, @2)));
|
||||
delete $2;
|
||||
}
|
||||
| '~' rterm
|
||||
{
|
||||
$$ = new Value(make_shared<AExpression>(&AExpression::OpNegate, static_cast<AExpression::Ptr>(*$2), DebugInfoRange(@1, @2)));
|
||||
delete $2;
|
||||
}
|
||||
| identifier '[' T_STRING ']'
|
||||
{
|
||||
$$ = new Value(make_shared<AExpression>(&AExpression::OpIndexer, $1, $3, DebugInfoRange(@1, @4)));
|
||||
free($1);
|
||||
free($3);
|
||||
}
|
||||
| '[' rterm_items ']'
|
||||
{
|
||||
$$ = new Value(make_shared<AExpression>(&AExpression::OpArray, Array::Ptr($2), DebugInfoRange(@1, @3)));
|
||||
}
|
||||
| rterm_scope
|
||||
{
|
||||
$$ = $1;
|
||||
}
|
||||
| '(' rterm ')'
|
||||
{
|
||||
$$ = $2;
|
||||
}
|
||||
| rterm rbinary_op rterm
|
||||
{
|
||||
$$ = new Value(make_shared<AExpression>($2, static_cast<AExpression::Ptr>(*$1), static_cast<AExpression::Ptr>(*$3), DebugInfoRange(@1, @3)));
|
||||
delete $1;
|
||||
delete $3;
|
||||
}
|
||||
;
|
||||
|
||||
|
@ -751,18 +706,18 @@ 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) + "'.", @1));
|
||||
BOOST_THROW_EXCEPTION(ConfigError("'apply' cannot be used with types '" + String($3) + "' and '" + String($6) + "'.") << errinfo_debuginfo(@1));
|
||||
}
|
||||
|
||||
Array::Ptr arguments = make_shared<Array>();
|
||||
arguments->Add(*$8);
|
||||
delete $8;
|
||||
|
||||
AExpression::Ptr aexpr = make_shared<AExpression>(AEFunctionCall, AValue(ATSimple, "bool"), AValue(ATSimple, arguments), @8);
|
||||
AExpression::Ptr aexpr = make_shared<AExpression>(&AExpression::OpFunctionCall, "bool", make_shared<AExpression>(&AExpression::OpLiteral, arguments, @8), @8);
|
||||
|
||||
ApplyRule::AddRule($3, $4, $6, aexpr, DebugInfoRange(@1, @8));
|
||||
ApplyRule::AddRule($3, $4, $6, aexpr, DebugInfoRange(@1, @8), m_ModuleScope);
|
||||
}
|
||||
%%
|
||||
|
|
|
@ -18,11 +18,12 @@
|
|||
******************************************************************************/
|
||||
|
||||
#include "config/configerror.h"
|
||||
#include <sstream>
|
||||
|
||||
using namespace icinga;
|
||||
|
||||
ConfigError::ConfigError(const String& message, const DebugInfo& di)
|
||||
: m_Message(message), m_DebugInfo(di)
|
||||
ConfigError::ConfigError(const String& message)
|
||||
: m_Message(message)
|
||||
{ }
|
||||
|
||||
ConfigError::~ConfigError(void) throw()
|
||||
|
@ -33,7 +34,10 @@ const char *ConfigError::what(void) const throw()
|
|||
return m_Message.CStr();
|
||||
}
|
||||
|
||||
DebugInfo ConfigError::GetDebugInfo(void) const
|
||||
std::string icinga::to_string(const errinfo_debuginfo& e)
|
||||
{
|
||||
return m_DebugInfo;
|
||||
}
|
||||
std::ostringstream msgbuf;
|
||||
msgbuf << "Config location: " << e.value() << "\n";
|
||||
ShowCodeFragment(msgbuf, e.value());
|
||||
return msgbuf.str();
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
#include "config/i2-config.h"
|
||||
#include "config/debuginfo.h"
|
||||
#include "base/exception.h"
|
||||
|
||||
namespace icinga
|
||||
{
|
||||
|
@ -29,20 +30,23 @@ namespace icinga
|
|||
/*
|
||||
* @ingroup config
|
||||
*/
|
||||
class I2_CONFIG_API ConfigError : public std::exception
|
||||
class I2_CONFIG_API ConfigError : virtual public user_error
|
||||
{
|
||||
public:
|
||||
ConfigError(const String& message, const DebugInfo& di);
|
||||
ConfigError(const String& message);
|
||||
~ConfigError(void) throw();
|
||||
|
||||
const char *what(void) const throw();
|
||||
DebugInfo GetDebugInfo(void) const;
|
||||
|
||||
private:
|
||||
String m_Message;
|
||||
DebugInfo m_DebugInfo;
|
||||
};
|
||||
|
||||
struct errinfo_debuginfo_;
|
||||
typedef boost::error_info<struct errinfo_debuginfo_, DebugInfo> errinfo_debuginfo;
|
||||
|
||||
std::string to_string(const errinfo_debuginfo& e);
|
||||
|
||||
}
|
||||
|
||||
#endif /* CONFIGERROR_H */
|
||||
|
|
|
@ -48,10 +48,12 @@ ConfigItem::ItemMap ConfigItem::m_Items;
|
|||
* @param debuginfo Debug information.
|
||||
*/
|
||||
ConfigItem::ConfigItem(const String& type, const String& name,
|
||||
bool abstract, const ExpressionList::Ptr& exprl,
|
||||
const std::vector<String>& parents, const DebugInfo& debuginfo)
|
||||
bool abstract, const AExpression::Ptr& exprl,
|
||||
const std::vector<String>& parents, const DebugInfo& debuginfo,
|
||||
const Dictionary::Ptr& scope)
|
||||
: m_Type(type), m_Name(name), m_Abstract(abstract), m_Validated(false),
|
||||
m_ExpressionList(exprl), m_ParentNames(parents), m_DebugInfo(debuginfo)
|
||||
m_ExpressionList(exprl), m_ParentNames(parents), m_DebugInfo(debuginfo),
|
||||
m_Scope(scope)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -95,25 +97,30 @@ DebugInfo ConfigItem::GetDebugInfo(void) const
|
|||
return m_DebugInfo;
|
||||
}
|
||||
|
||||
Dictionary::Ptr ConfigItem::GetScope(void) const
|
||||
{
|
||||
return m_Scope;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the expression list for the configuration item.
|
||||
*
|
||||
* @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,19 +130,21 @@ 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;
|
||||
}
|
||||
|
||||
|
@ -143,9 +152,16 @@ Dictionary::Ptr ConfigItem::GetProperties(void)
|
|||
{
|
||||
ASSERT(OwnsLock());
|
||||
|
||||
Dictionary::Ptr properties = make_shared<Dictionary>();
|
||||
GetLinkedExpressionList()->Execute(properties);
|
||||
return properties;
|
||||
if (!m_Properties) {
|
||||
m_Properties = make_shared<Dictionary>();
|
||||
m_Properties->Set("__parent", m_Scope);
|
||||
GetLinkedExpressionList()->Evaluate(m_Properties);
|
||||
m_Properties->Remove("__parent");
|
||||
|
||||
VERIFY(m_Properties->Get("__type") == GetType() && m_Properties->Get("__name") == GetName());
|
||||
}
|
||||
|
||||
return m_Properties;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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,8 +45,8 @@ public:
|
|||
DECLARE_PTR_TYPEDEFS(ConfigItem);
|
||||
|
||||
ConfigItem(const String& type, const String& name, bool abstract,
|
||||
const ExpressionList::Ptr& exprl, const std::vector<String>& parents,
|
||||
const DebugInfo& debuginfo);
|
||||
const AExpression::Ptr& exprl, const std::vector<String>& parents,
|
||||
const DebugInfo& debuginfo, const Dictionary::Ptr& scope);
|
||||
|
||||
String GetType(void) const;
|
||||
String GetName(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);
|
||||
|
@ -62,6 +62,8 @@ public:
|
|||
|
||||
DebugInfo GetDebugInfo(void) const;
|
||||
|
||||
Dictionary::Ptr GetScope(void) const;
|
||||
|
||||
static ConfigItem::Ptr GetObject(const String& type,
|
||||
const String& name);
|
||||
static bool HasObject(const String& type, const String& name);
|
||||
|
@ -72,21 +74,23 @@ 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;
|
||||
Dictionary::Ptr m_Properties;
|
||||
std::vector<String> m_ParentNames; /**< The names of parent configuration
|
||||
items. */
|
||||
DebugInfo m_DebugInfo; /**< Debug information. */
|
||||
Dictionary::Ptr m_Scope; /**< variable scope. */
|
||||
|
||||
ExpressionList::Ptr m_LinkedExpressionList;
|
||||
AExpression::Ptr m_LinkedExpressionList;
|
||||
|
||||
DynamicObject::Ptr m_Object;
|
||||
DynamicObject::Ptr m_Object;
|
||||
|
||||
static boost::mutex m_Mutex;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
@ -55,26 +55,19 @@ void ConfigItemBuilder::SetAbstract(bool abstract)
|
|||
m_Abstract = abstract;
|
||||
}
|
||||
|
||||
void ConfigItemBuilder::SetScope(const Dictionary::Ptr& scope)
|
||||
{
|
||||
m_Scope = scope;
|
||||
}
|
||||
|
||||
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,17 +95,13 @@ 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>();
|
||||
|
||||
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);
|
||||
Array::Ptr exprs = make_shared<Array>();
|
||||
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));
|
||||
exprs->Add(make_shared<AExpression>(&AExpression::OpDict, m_Expressions, true, m_DebugInfo));
|
||||
|
||||
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);
|
||||
m_Parents, m_DebugInfo, m_Scope);
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
@ -46,13 +45,11 @@ public:
|
|||
void SetType(const String& type);
|
||||
void SetName(const String& name);
|
||||
void SetAbstract(bool abstract);
|
||||
void SetScope(const Dictionary::Ptr& scope);
|
||||
|
||||
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,8 +59,9 @@ 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. */
|
||||
Dictionary::Ptr m_Scope; /**< variable scope. */
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -1,238 +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 OperatorNop:
|
||||
/* Nothing to do here. */
|
||||
|
||||
return;
|
||||
|
||||
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::ExtractFiltered(const std::set<String>& keys, const shared_ptr<ExpressionList>& result) const
|
||||
{
|
||||
if (keys.find(m_Key) != keys.end()) {
|
||||
result->AddExpression(*this);
|
||||
} else if (m_Operator == OperatorExecute) {
|
||||
ExpressionList::Ptr exprl = m_Value;
|
||||
exprl->ExtractFiltered(keys, result);
|
||||
}
|
||||
}
|
||||
|
||||
void Expression::ErasePath(const std::vector<String>& path)
|
||||
{
|
||||
ASSERT(!path.empty());
|
||||
|
||||
if (path[0] == m_Key) {
|
||||
if (path.size() == 1) {
|
||||
m_Operator = OperatorNop;
|
||||
} else if (m_Value.IsObjectType<ExpressionList>()) {
|
||||
ExpressionList::Ptr exprl = m_Value;
|
||||
|
||||
std::vector<String> sub_path(path.begin() + 1, path.end());
|
||||
exprl->ErasePath(sub_path);
|
||||
}
|
||||
} else if (m_Operator == OperatorExecute) {
|
||||
ExpressionList::Ptr exprl = m_Value;
|
||||
exprl->ErasePath(path);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
|
@ -1,82 +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
|
||||
{
|
||||
OperatorNop,
|
||||
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 ExtractFiltered(const std::set<String>& keys, const shared_ptr<ExpressionList>& result) const;
|
||||
|
||||
void ErasePath(const std::vector<String>& path);
|
||||
|
||||
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 */
|
|
@ -1,84 +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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of items currently contained in the expression list.
|
||||
*
|
||||
* @returns The length of the list.
|
||||
*/
|
||||
size_t ExpressionList::GetLength(void) const
|
||||
{
|
||||
return m_Expressions.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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::ExtractFiltered(const std::set<String>& keys, const ExpressionList::Ptr& result) const
|
||||
{
|
||||
BOOST_FOREACH(const Expression& expression, m_Expressions) {
|
||||
expression.ExtractFiltered(keys, result);
|
||||
}
|
||||
}
|
||||
|
||||
void ExpressionList::ErasePath(const std::vector<String>& path)
|
||||
{
|
||||
BOOST_FOREACH(Expression& expression, m_Expressions) {
|
||||
expression.ErasePath(path);
|
||||
}
|
||||
}
|
||||
|
||||
void ExpressionList::FindDebugInfoPath(const std::vector<String>& path, DebugInfo& result) const
|
||||
{
|
||||
BOOST_FOREACH(const Expression& expression, m_Expressions) {
|
||||
expression.FindDebugInfoPath(path, result);
|
||||
}
|
||||
}
|
|
@ -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. *
|
||||
******************************************************************************/
|
||||
|
||||
#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;
|
||||
|
||||
size_t GetLength(void) const;
|
||||
|
||||
void ExtractPath(const std::vector<String>& path, const ExpressionList::Ptr& result) const;
|
||||
void ExtractFiltered(const std::set<String>& keys, const ExpressionList::Ptr& result) const;
|
||||
|
||||
void ErasePath(const std::vector<String>& path);
|
||||
|
||||
void FindDebugInfoPath(const std::vector<String>& path, DebugInfo& result) const;
|
||||
|
||||
private:
|
||||
std::vector<Expression> m_Expressions;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* EXPRESSIONLIST_H */
|
|
@ -77,7 +77,8 @@ 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->SetScope(rule.GetScope());
|
||||
builder->AddExpression(make_shared<AExpression>(&AExpression::OpSet, "host", make_shared<AExpression>(&AExpression::OpLiteral, host->GetName(), rule.GetDebugInfo()), rule.GetDebugInfo()));
|
||||
|
||||
builder->AddParent(rule.GetTemplate());
|
||||
|
||||
|
|
|
@ -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,12 @@ 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));
|
||||
|
||||
builder->SetScope(item->GetScope());
|
||||
|
||||
ConfigItem::Ptr serviceItem = builder->Compile();
|
||||
serviceItem->Register();
|
||||
|
|
|
@ -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,12 @@ 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));
|
||||
|
||||
builder->SetScope(item->GetScope());
|
||||
|
||||
ConfigItem::Ptr dependencyItem = builder->Compile();
|
||||
dependencyItem->Register();
|
||||
|
|
|
@ -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,12 @@ 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));
|
||||
|
||||
builder->SetScope(item->GetScope());
|
||||
|
||||
ConfigItem::Ptr scheduledDowntimeItem = builder->Compile();
|
||||
scheduledDowntimeItem->Register();
|
||||
|
|
|
@ -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,12 @@ 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));
|
||||
|
||||
builder->SetScope(item->GetScope());
|
||||
|
||||
ConfigItem::Ptr notificationItem = builder->Compile();
|
||||
notificationItem->Register();
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue