mirror of https://github.com/Icinga/icinga2.git
parent
3c067e9547
commit
2a6a75d52e
|
@ -18,11 +18,14 @@
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
#include "config/aexpression.h"
|
#include "config/aexpression.h"
|
||||||
|
#include "config/configerror.h"
|
||||||
#include "base/array.h"
|
#include "base/array.h"
|
||||||
#include "base/serializer.h"
|
#include "base/serializer.h"
|
||||||
#include "base/context.h"
|
#include "base/context.h"
|
||||||
#include "base/scriptfunction.h"
|
#include "base/scriptfunction.h"
|
||||||
#include <boost/foreach.hpp>
|
#include <boost/foreach.hpp>
|
||||||
|
#include <boost/exception_ptr.hpp>
|
||||||
|
#include <boost/exception/errinfo_nested_exception.hpp>
|
||||||
|
|
||||||
using namespace icinga;
|
using namespace icinga;
|
||||||
|
|
||||||
|
@ -57,96 +60,103 @@ Value AExpression::Evaluate(const Dictionary::Ptr& locals) const
|
||||||
msgbuf << "Evaluating AExpression " << m_DebugInfo << "; left=" << JsonSerialize(left) << "; right=" << JsonSerialize(right);
|
msgbuf << "Evaluating AExpression " << m_DebugInfo << "; left=" << JsonSerialize(left) << "; right=" << JsonSerialize(right);
|
||||||
CONTEXT(msgbuf.str());
|
CONTEXT(msgbuf.str());
|
||||||
|
|
||||||
switch (m_Operator) {
|
try {
|
||||||
case AEReturn:
|
switch (m_Operator) {
|
||||||
return left;
|
case AEReturn:
|
||||||
case AENegate:
|
return left;
|
||||||
return ~(long)left;
|
case AENegate:
|
||||||
case AEAdd:
|
return ~(long)left;
|
||||||
return left + right;
|
case AEAdd:
|
||||||
case AESubtract:
|
return left + right;
|
||||||
return left - right;
|
case AESubtract:
|
||||||
case AEMultiply:
|
return left - right;
|
||||||
return left * right;
|
case AEMultiply:
|
||||||
case AEDivide:
|
return left * right;
|
||||||
return left / right;
|
case AEDivide:
|
||||||
case AEBinaryAnd:
|
return left / right;
|
||||||
return left & right;
|
case AEBinaryAnd:
|
||||||
case AEBinaryOr:
|
return left & right;
|
||||||
return left | right;
|
case AEBinaryOr:
|
||||||
case AEShiftLeft:
|
return left | right;
|
||||||
return left << right;
|
case AEShiftLeft:
|
||||||
case AEShiftRight:
|
return left << right;
|
||||||
return left >> right;
|
case AEShiftRight:
|
||||||
case AEEqual:
|
return left >> right;
|
||||||
return left == right;
|
case AEEqual:
|
||||||
case AENotEqual:
|
return left == right;
|
||||||
return left != right;
|
case AENotEqual:
|
||||||
case AELessThan:
|
return left != right;
|
||||||
return left < right;
|
case AELessThan:
|
||||||
case AEGreaterThan:
|
return left < right;
|
||||||
return left > right;
|
case AEGreaterThan:
|
||||||
case AELessThanOrEqual:
|
return left > right;
|
||||||
return left <= right;
|
case AELessThanOrEqual:
|
||||||
case AEGreaterThanOrEqual:
|
return left <= right;
|
||||||
return left >= right;
|
case AEGreaterThanOrEqual:
|
||||||
case AEIn:
|
return left >= right;
|
||||||
if (!right.IsObjectType<Array>())
|
case AEIn:
|
||||||
BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid right side argument for 'in' operator: " + JsonSerialize(right)));
|
if (!right.IsObjectType<Array>())
|
||||||
|
BOOST_THROW_EXCEPTION(ConfigError("Invalid right side argument for 'in' operator: " + JsonSerialize(right)));
|
||||||
|
|
||||||
arr = right;
|
arr = right;
|
||||||
found = false;
|
found = false;
|
||||||
BOOST_FOREACH(const Value& value, arr) {
|
BOOST_FOREACH(const Value& value, arr) {
|
||||||
if (value == left) {
|
if (value == left) {
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return found;
|
return found;
|
||||||
case AENotIn:
|
case AENotIn:
|
||||||
if (!right.IsObjectType<Array>())
|
if (!right.IsObjectType<Array>())
|
||||||
BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid right side argument for 'in' operator: " + JsonSerialize(right)));
|
BOOST_THROW_EXCEPTION(ConfigError("Invalid right side argument for 'in' operator: " + JsonSerialize(right)));
|
||||||
|
|
||||||
arr = right;
|
arr = right;
|
||||||
found = false;
|
found = false;
|
||||||
BOOST_FOREACH(const Value& value, arr) {
|
BOOST_FOREACH(const Value& value, arr) {
|
||||||
if (value == left) {
|
if (value == left) {
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return !found;
|
return !found;
|
||||||
case AELogicalAnd:
|
case AELogicalAnd:
|
||||||
return left.ToBool() && right.ToBool();
|
return left.ToBool() && right.ToBool();
|
||||||
case AELogicalOr:
|
case AELogicalOr:
|
||||||
return left.ToBool() || right.ToBool();
|
return left.ToBool() || right.ToBool();
|
||||||
case AEFunctionCall:
|
case AEFunctionCall:
|
||||||
funcName = left;
|
funcName = left;
|
||||||
func = ScriptFunctionRegistry::GetInstance()->GetItem(funcName);
|
func = ScriptFunctionRegistry::GetInstance()->GetItem(funcName);
|
||||||
|
|
||||||
if (!func)
|
if (!func)
|
||||||
BOOST_THROW_EXCEPTION(std::invalid_argument("Function '" + funcName + "' does not exist."));
|
BOOST_THROW_EXCEPTION(ConfigError("Function '" + funcName + "' does not exist."));
|
||||||
|
|
||||||
arr = right;
|
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) {
|
BOOST_FOREACH(const AExpression::Ptr& aexpr, arr) {
|
||||||
arr2->Add(aexpr->Evaluate(locals));
|
arguments.push_back(aexpr->Evaluate(locals));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return arr2;
|
return func->Invoke(arguments);
|
||||||
default:
|
case AEArray:
|
||||||
ASSERT(!"Invalid operator.");
|
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.");
|
||||||
|
}
|
||||||
|
} 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.") << boost::errinfo_nested_exception(boost::current_exception()) << errinfo_debuginfo(m_DebugInfo));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -190,7 +190,8 @@ void ConfigCompiler::Compile(void)
|
||||||
try {
|
try {
|
||||||
yyparse(this);
|
yyparse(this);
|
||||||
} catch (const ConfigError& ex) {
|
} 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) {
|
} catch (const std::exception& ex) {
|
||||||
ConfigCompilerContext::GetInstance()->AddMessage(true, DiagnosticInformation(ex));
|
ConfigCompilerContext::GetInstance()->AddMessage(true, DiagnosticInformation(ex));
|
||||||
}
|
}
|
||||||
|
@ -285,7 +286,7 @@ type: partial_specifier T_TYPE identifier
|
||||||
|
|
||||||
if (!m_Type) {
|
if (!m_Type) {
|
||||||
if ($1)
|
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 = make_shared<ConfigType>(name, DebugInfoRange(@1, @3));
|
||||||
m_Type->Register();
|
m_Type->Register();
|
||||||
|
@ -406,7 +407,7 @@ object:
|
||||||
free($3);
|
free($3);
|
||||||
free($4);
|
free($4);
|
||||||
delete $5;
|
delete $5;
|
||||||
BOOST_THROW_EXCEPTION(ConfigError(msgbuf.str(), di));
|
BOOST_THROW_EXCEPTION(ConfigError(msgbuf.str()) << errinfo_debuginfo(di));
|
||||||
}
|
}
|
||||||
|
|
||||||
item->SetType($3);
|
item->SetType($3);
|
||||||
|
@ -415,7 +416,7 @@ object:
|
||||||
std::ostringstream msgbuf;
|
std::ostringstream msgbuf;
|
||||||
msgbuf << "Name for object '" << $4 << "' of type '" << $3 << "' is invalid: Object names may not contain '!'";
|
msgbuf << "Name for object '" << $4 << "' of type '" << $3 << "' is invalid: Object names may not contain '!'";
|
||||||
free($3);
|
free($3);
|
||||||
BOOST_THROW_EXCEPTION(ConfigError(msgbuf.str(), @4));
|
BOOST_THROW_EXCEPTION(ConfigError(msgbuf.str()) << errinfo_debuginfo(@4));
|
||||||
}
|
}
|
||||||
|
|
||||||
free($3);
|
free($3);
|
||||||
|
@ -754,7 +755,7 @@ optional_template: /* empty */
|
||||||
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 aexpression
|
||||||
{
|
{
|
||||||
if (!ApplyRule::IsValidCombination($3, $6)) {
|
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>();
|
Array::Ptr arguments = make_shared<Array>();
|
||||||
|
|
|
@ -18,11 +18,12 @@
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
#include "config/configerror.h"
|
#include "config/configerror.h"
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
using namespace icinga;
|
using namespace icinga;
|
||||||
|
|
||||||
ConfigError::ConfigError(const String& message, const DebugInfo& di)
|
ConfigError::ConfigError(const String& message)
|
||||||
: m_Message(message), m_DebugInfo(di)
|
: m_Message(message)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
ConfigError::~ConfigError(void) throw()
|
ConfigError::~ConfigError(void) throw()
|
||||||
|
@ -33,7 +34,10 @@ const char *ConfigError::what(void) const throw()
|
||||||
return m_Message.CStr();
|
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/i2-config.h"
|
||||||
#include "config/debuginfo.h"
|
#include "config/debuginfo.h"
|
||||||
|
#include "base/exception.h"
|
||||||
|
|
||||||
namespace icinga
|
namespace icinga
|
||||||
{
|
{
|
||||||
|
@ -29,20 +30,23 @@ namespace icinga
|
||||||
/*
|
/*
|
||||||
* @ingroup config
|
* @ingroup config
|
||||||
*/
|
*/
|
||||||
class I2_CONFIG_API ConfigError : public std::exception
|
class I2_CONFIG_API ConfigError : virtual public user_error
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ConfigError(const String& message, const DebugInfo& di);
|
ConfigError(const String& message);
|
||||||
~ConfigError(void) throw();
|
~ConfigError(void) throw();
|
||||||
|
|
||||||
const char *what(void) const throw();
|
const char *what(void) const throw();
|
||||||
DebugInfo GetDebugInfo(void) const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
String m_Message;
|
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 */
|
#endif /* CONFIGERROR_H */
|
||||||
|
|
Loading…
Reference in New Issue