keywords.push_back("globals");
keywords.push_back("locals");
keywords.push_back("use");
+ keywords.push_back("__using");
keywords.push_back("ignore_on_error");
keywords.push_back("current_filename");
keywords.push_back("current_line");
Callback m_Callback;
};
-#define REGISTER_SCRIPTFUNCTION(name, callback) \
- namespace { namespace UNIQUE_NAME(sf) { namespace sf ## name { \
+#define REGISTER_SCRIPTFUNCTION_NS(ns, name, callback) \
+ namespace { namespace UNIQUE_NAME(sf) { namespace sf ## ns ## name { \
void RegisterFunction(void) { \
- Function::Ptr sf = new icinga::Function(#name, WrapFunction(callback)); \
- ScriptGlobal::Set(#name, sf); \
+ Function::Ptr sf = new icinga::Function(#ns "#" #name, WrapFunction(callback), false); \
+ ScriptGlobal::Set(#ns "." #name, sf); \
} \
INITIALIZE_ONCE_WITH_PRIORITY(RegisterFunction, 10); \
} } }
-#define REGISTER_SCRIPTFUNCTION_NS(ns, name, callback) \
+#define REGISTER_SCRIPTFUNCTION_NS_PREFIX(ns, name, callback) \
namespace { namespace UNIQUE_NAME(sf) { namespace sf ## ns ## name { \
void RegisterFunction(void) { \
Function::Ptr sf = new icinga::Function(#ns "#" #name, WrapFunction(callback), false); \
ScriptGlobal::Set(#ns "." #name, sf); \
Function::Ptr dsf = new icinga::Function("__" #name " (deprecated)", WrapFunction(callback), false, true); \
- ScriptGlobal::Set("__" #name, dsf); \
+ ScriptGlobal::Set("System.__" #name, dsf); \
} \
INITIALIZE_ONCE_WITH_PRIORITY(RegisterFunction, 10); \
} } }
INITIALIZE_ONCE_WITH_PRIORITY(RegisterFunction, 10); \
} } }
-#define REGISTER_SAFE_SCRIPTFUNCTION(name, callback) \
- namespace { namespace UNIQUE_NAME(sf) { namespace sf ## name { \
+#define REGISTER_SAFE_SCRIPTFUNCTION_NS(ns, name, callback) \
+ namespace { namespace UNIQUE_NAME(sf) { namespace sf ## ns ## name { \
void RegisterFunction(void) { \
- Function::Ptr sf = new icinga::Function(#name, WrapFunction(callback), true); \
- ScriptGlobal::Set(#name, sf); \
+ Function::Ptr sf = new icinga::Function(#ns "#" #name, WrapFunction(callback), true); \
+ ScriptGlobal::Set(#ns "." #name, sf); \
} \
INITIALIZE_ONCE_WITH_PRIORITY(RegisterFunction, 10); \
} } }
-#define REGISTER_SAFE_SCRIPTFUNCTION_NS(ns, name, callback) \
+#define REGISTER_SAFE_SCRIPTFUNCTION_NS_PREFIX(ns, name, callback) \
namespace { namespace UNIQUE_NAME(sf) { namespace sf ## ns ## name { \
void RegisterFunction(void) { \
Function::Ptr sf = new icinga::Function(#ns "#" #name, WrapFunction(callback), true); \
ScriptGlobal::Set(#ns "." #name, sf); \
Function::Ptr dsf = new icinga::Function("__" #name " (deprecated)", WrapFunction(callback), true, true); \
- ScriptGlobal::Set("__" #name, dsf); \
+ ScriptGlobal::Set("System.__" #name, dsf); \
} \
INITIALIZE_ONCE_WITH_PRIORITY(RegisterFunction, 10); \
} } }
{
std::stack<ScriptFrame *> *frames = m_ScriptFrames.get();
- if (frames && !frames->empty())
- Sandboxed = frames->top()->Sandboxed;
+ if (frames && !frames->empty()) {
+ ScriptFrame *frame = frames->top();
+
+ Sandboxed = frame->Sandboxed;
+ Imports = frame->Imports;
+ } else {
+ Imports = new Array();
+ Imports->Add(ScriptGlobal::Get("System"));
+ }
PushFrame(this);
}
#include "config/i2-config.hpp"
#include "base/dictionary.hpp"
+#include "base/array.hpp"
#include <boost/thread/tss.hpp>
#include <stack>
struct I2_BASE_API ScriptFrame
{
Dictionary::Ptr Locals;
+ Array::Ptr Imports;
Value Self;
bool Sandboxed;
int Depth;
using namespace icinga;
-REGISTER_SAFE_SCRIPTFUNCTION(regex, &ScriptUtils::Regex);
-REGISTER_SAFE_SCRIPTFUNCTION(match, &Utility::Match);
-REGISTER_SAFE_SCRIPTFUNCTION(cidr_match, &Utility::CidrMatch);
-REGISTER_SAFE_SCRIPTFUNCTION(len, &ScriptUtils::Len);
-REGISTER_SAFE_SCRIPTFUNCTION(union, &ScriptUtils::Union);
-REGISTER_SAFE_SCRIPTFUNCTION(intersection, &ScriptUtils::Intersection);
-REGISTER_SCRIPTFUNCTION(log, &ScriptUtils::Log);
-REGISTER_SCRIPTFUNCTION(range, &ScriptUtils::Range);
-REGISTER_SCRIPTFUNCTION(exit, &Application::Exit);
-REGISTER_SAFE_SCRIPTFUNCTION(typeof, &ScriptUtils::TypeOf);
-REGISTER_SAFE_SCRIPTFUNCTION(keys, &ScriptUtils::Keys);
-REGISTER_SAFE_SCRIPTFUNCTION(random, &Utility::Random);
-REGISTER_SAFE_SCRIPTFUNCTION(get_object, &ScriptUtils::GetObject);
-REGISTER_SAFE_SCRIPTFUNCTION(get_objects, &ScriptUtils::GetObjects);
-REGISTER_SCRIPTFUNCTION(assert, &ScriptUtils::Assert);
-REGISTER_SAFE_SCRIPTFUNCTION(string, &ScriptUtils::CastString);
-REGISTER_SAFE_SCRIPTFUNCTION(number, &ScriptUtils::CastNumber);
-REGISTER_SAFE_SCRIPTFUNCTION(bool, &ScriptUtils::CastBool);
-REGISTER_SAFE_SCRIPTFUNCTION(get_time, &Utility::GetTime);
-REGISTER_SAFE_SCRIPTFUNCTION(basename, &Utility::BaseName);
-REGISTER_SAFE_SCRIPTFUNCTION(dirname, &Utility::DirName);
-REGISTER_SAFE_SCRIPTFUNCTION(msi_get_component_path, &ScriptUtils::MsiGetComponentPathShim);
-REGISTER_SAFE_SCRIPTFUNCTION(track_parents, &ScriptUtils::TrackParents);
-REGISTER_SAFE_SCRIPTFUNCTION(escape_shell_cmd, &Utility::EscapeShellCmd);
-REGISTER_SAFE_SCRIPTFUNCTION(escape_shell_arg, &Utility::EscapeShellArg);
+REGISTER_SAFE_SCRIPTFUNCTION_NS(System, regex, &ScriptUtils::Regex);
+REGISTER_SAFE_SCRIPTFUNCTION_NS(System, match, &Utility::Match);
+REGISTER_SAFE_SCRIPTFUNCTION_NS(System, cidr_match, &Utility::CidrMatch);
+REGISTER_SAFE_SCRIPTFUNCTION_NS(System, len, &ScriptUtils::Len);
+REGISTER_SAFE_SCRIPTFUNCTION_NS(System, union, &ScriptUtils::Union);
+REGISTER_SAFE_SCRIPTFUNCTION_NS(System, intersection, &ScriptUtils::Intersection);
+REGISTER_SCRIPTFUNCTION_NS(System, log, &ScriptUtils::Log);
+REGISTER_SCRIPTFUNCTION_NS(System, range, &ScriptUtils::Range);
+REGISTER_SCRIPTFUNCTION_NS(System, exit, &Application::Exit);
+REGISTER_SAFE_SCRIPTFUNCTION_NS(System, typeof, &ScriptUtils::TypeOf);
+REGISTER_SAFE_SCRIPTFUNCTION_NS(System, keys, &ScriptUtils::Keys);
+REGISTER_SAFE_SCRIPTFUNCTION_NS(System, random, &Utility::Random);
+REGISTER_SAFE_SCRIPTFUNCTION_NS(System, get_object, &ScriptUtils::GetObject);
+REGISTER_SAFE_SCRIPTFUNCTION_NS(System, get_objects, &ScriptUtils::GetObjects);
+REGISTER_SCRIPTFUNCTION_NS(System, assert, &ScriptUtils::Assert);
+REGISTER_SAFE_SCRIPTFUNCTION_NS(System, string, &ScriptUtils::CastString);
+REGISTER_SAFE_SCRIPTFUNCTION_NS(System, number, &ScriptUtils::CastNumber);
+REGISTER_SAFE_SCRIPTFUNCTION_NS(System, bool, &ScriptUtils::CastBool);
+REGISTER_SAFE_SCRIPTFUNCTION_NS(System, get_time, &Utility::GetTime);
+REGISTER_SAFE_SCRIPTFUNCTION_NS(System, basename, &Utility::BaseName);
+REGISTER_SAFE_SCRIPTFUNCTION_NS(System, dirname, &Utility::DirName);
+REGISTER_SAFE_SCRIPTFUNCTION_NS(System, msi_get_component_path, &ScriptUtils::MsiGetComponentPathShim);
+REGISTER_SAFE_SCRIPTFUNCTION_NS(System, track_parents, &ScriptUtils::TrackParents);
+REGISTER_SAFE_SCRIPTFUNCTION_NS(System, escape_shell_cmd, &Utility::EscapeShellCmd);
+REGISTER_SAFE_SCRIPTFUNCTION_NS(System, escape_shell_arg, &Utility::EscapeShellArg);
#ifdef _WIN32
-REGISTER_SAFE_SCRIPTFUNCTION(escape_create_process_arg, &Utility::EscapeCreateProcessArg);
+REGISTER_SAFE_SCRIPTFUNCTION_NS(System, escape_create_process_arg, &Utility::EscapeCreateProcessArg);
#endif /* _WIN32 */
-REGISTER_SCRIPTFUNCTION(ptr, &ScriptUtils::Ptr);
+REGISTER_SCRIPTFUNCTION_NS(System, ptr, &ScriptUtils::Ptr);
String ScriptUtils::CastString(const Value& value)
{
globals return T_GLOBALS;
locals return T_LOCALS;
use return T_USE;
+__using return T_USING;
apply return T_APPLY;
to return T_TO;
where return T_WHERE;
%token T_CURRENT_LINE "current_line (T_CURRENT_LINE)"
%token T_DEBUGGER "debugger (T_DEBUGGER)"
%token T_USE "use (T_USE)"
+%token T_USING "__using (T_USING)"
%token T_OBJECT "object (T_OBJECT)"
%token T_TEMPLATE "template (T_TEMPLATE)"
%token T_INCLUDE "include (T_INCLUDE)"
{
$$ = new BreakpointExpression(@$);
}
+ | T_USING rterm
+ {
+ $$ = new UsingExpression($2, @$);
+ }
| apply
| object
| T_FOR '(' identifier T_FOLLOWS identifier T_IN rterm ')'
#include "config/configcompiler.hpp"
#include "base/initialize.hpp"
#include "base/debug.hpp"
+#include "base/exception.hpp"
+#include "base/application.hpp"
#define REGISTER_CONFIG_FRAGMENT(id, name, fragment) \
namespace { \
{ \
icinga::Expression *expression = icinga::ConfigCompiler::CompileText(name, fragment); \
VERIFY(expression); \
- icinga::ScriptFrame frame; \
- expression->Evaluate(frame); \
+ try { \
+ icinga::ScriptFrame frame; \
+ expression->Evaluate(frame); \
+ } catch (const std::exception& ex) { \
+ std::cerr << icinga::DiagnosticInformation(ex) << std::endl; \
+ icinga::Application::Exit(1); \
+ } \
delete expression; \
} \
\
ConfigItem::ItemList ConfigItem::m_UnnamedItems;
ConfigItem::IgnoredItemList ConfigItem::m_IgnoredItems;
-REGISTER_SCRIPTFUNCTION_NS(Internal, run_with_activation_context, &ConfigItem::RunWithActivationContext);
+REGISTER_SCRIPTFUNCTION_NS_PREFIX(Internal, run_with_activation_context, &ConfigItem::RunWithActivationContext);
/**
* Constructor for the ConfigItem class.
return value;
else if (frame.Self.IsObject() && frame.Locals != static_cast<Object::Ptr>(frame.Self) && static_cast<Object::Ptr>(frame.Self)->HasOwnField(m_Variable))
return VMOps::GetField(frame.Self, m_Variable, frame.Sandboxed, m_DebugInfo);
+ else if (VMOps::FindVarImport(frame, m_Variable, &value, m_DebugInfo))
+ return value;
else
return ScriptGlobal::Get(m_Variable);
}
if (dhint && *dhint)
*dhint = new DebugHint((*dhint)->GetChild(m_Variable));
+ } else if (VMOps::FindVarImportRef(frame, m_Variable, parent, m_DebugInfo)) {
+ return true;
} else if (ScriptGlobal::Exists(m_Variable)) {
*parent = ScriptGlobal::GetGlobals();
return Empty;
}
+ExpressionResult UsingExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
+{
+ if (frame.Sandboxed)
+ BOOST_THROW_EXCEPTION(ScriptError("Using directives are not allowed in sandbox mode.", m_DebugInfo));
+
+ ExpressionResult importres = m_Name->Evaluate(frame);
+ CHECK_RESULT(importres);
+ Value import = importres.GetValue();
+
+ if (!import.IsObject())
+ BOOST_THROW_EXCEPTION(ScriptError("The parameter does not resolve to an object", m_DebugInfo));
+
+ if (!frame.Imports)
+ frame.Imports = new Array();
+ else
+ frame.Imports = static_pointer_cast<Array>(frame.Imports->Clone());
+
+ frame.Imports->Add(import);
+
+ return Empty;
+}
+
virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const override;
};
+class I2_CONFIG_API UsingExpression : public DebuggableExpression
+{
+public:
+ UsingExpression(Expression *name, const DebugInfo& debugInfo = DebugInfo())
+ : DebuggableExpression(debugInfo), m_Name(name)
+ { }
+
+ ~UsingExpression(void)
+ {
+ delete m_Name;
+ }
+
+protected:
+ virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const override;
+
+private:
+ Expression *m_Name;
+};
+
}
#endif /* EXPRESSION_H */
class VMOps
{
public:
- static inline Value Variable(ScriptFrame& frame, const String& name, const DebugInfo& debugInfo = DebugInfo())
+ static inline bool FindVarImportRef(ScriptFrame& frame, const String& name, Value *result, const DebugInfo& debugInfo = DebugInfo())
{
- Value value;
- if (frame.Locals && frame.Locals->Get(name, &value))
- return value;
- else if (frame.Self.IsObject() && frame.Locals != static_cast<Object::Ptr>(frame.Self) && static_cast<Object::Ptr>(frame.Self)->HasOwnField(name))
- return GetField(frame.Self, name, frame.Sandboxed, debugInfo);
- else
- return ScriptGlobal::Get(name);
+ if (!frame.Imports)
+ return false;
+
+ ObjectLock olock(frame.Imports);
+ BOOST_FOREACH(const Value& import, frame.Imports) {
+ Object::Ptr obj = import;
+ if (obj->HasOwnField(name)) {
+ *result = import;
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ static inline bool FindVarImport(ScriptFrame& frame, const String& name, Value *result, const DebugInfo& debugInfo = DebugInfo())
+ {
+ Value parent;
+
+ if (FindVarImportRef(frame, name, &parent, debugInfo)) {
+ *result = GetField(parent, name, frame.Sandboxed, debugInfo);
+ return true;
+ }
+
+ return false;
}
static inline Value ConstructorCall(const Type::Ptr& type, const std::vector<Value>& args, const DebugInfo& debugInfo = DebugInfo())
using namespace icinga;
-REGISTER_SCRIPTFUNCTION(get_host, &Host::GetByName);
-REGISTER_SCRIPTFUNCTION(get_service, &ObjectUtils::GetService);
-REGISTER_SCRIPTFUNCTION(get_user, &User::GetByName);
-REGISTER_SCRIPTFUNCTION(get_check_command, &CheckCommand::GetByName);
-REGISTER_SCRIPTFUNCTION(get_event_command, &EventCommand::GetByName);
-REGISTER_SCRIPTFUNCTION(get_notification_command, &NotificationCommand::GetByName);
-REGISTER_SCRIPTFUNCTION(get_host_group, &HostGroup::GetByName);
-REGISTER_SCRIPTFUNCTION(get_service_group, &ServiceGroup::GetByName);
-REGISTER_SCRIPTFUNCTION(get_user_group, &UserGroup::GetByName);
-REGISTER_SCRIPTFUNCTION(get_time_period, &TimePeriod::GetByName);
+REGISTER_SCRIPTFUNCTION_NS(System, get_host, &Host::GetByName);
+REGISTER_SCRIPTFUNCTION_NS(System, get_service, &ObjectUtils::GetService);
+REGISTER_SCRIPTFUNCTION_NS(System, get_user, &User::GetByName);
+REGISTER_SCRIPTFUNCTION_NS(System, get_check_command, &CheckCommand::GetByName);
+REGISTER_SCRIPTFUNCTION_NS(System, get_event_command, &EventCommand::GetByName);
+REGISTER_SCRIPTFUNCTION_NS(System, get_notification_command, &NotificationCommand::GetByName);
+REGISTER_SCRIPTFUNCTION_NS(System, get_host_group, &HostGroup::GetByName);
+REGISTER_SCRIPTFUNCTION_NS(System, get_service_group, &ServiceGroup::GetByName);
+REGISTER_SCRIPTFUNCTION_NS(System, get_user_group, &UserGroup::GetByName);
+REGISTER_SCRIPTFUNCTION_NS(System, get_time_period, &TimePeriod::GetByName);
Service::Ptr ObjectUtils::GetService(const String& host, const String& name)
{
using namespace icinga;
REGISTER_TYPE(PerfdataValue);
-REGISTER_SCRIPTFUNCTION(parse_performance_data, PerfdataValue::Parse);
+REGISTER_SCRIPTFUNCTION_NS(System, parse_performance_data, PerfdataValue::Parse);
PerfdataValue::PerfdataValue(void)
{ }
matches.push_back(suggestion);
}
+static void AddSuggestions(std::vector<String>& matches, const String& word, const String& pword, const Value& value)
+{
+ String prefix;
+
+ if (!pword.IsEmpty())
+ prefix = pword + ".";
+
+ if (value.IsObjectType<Dictionary>()) {
+ Dictionary::Ptr dict = value;
+
+ ObjectLock olock(dict);
+ BOOST_FOREACH(const Dictionary::Pair& kv, dict) {
+ AddSuggestion(matches, word, prefix + kv.first);
+ }
+ }
+
+ Type::Ptr type = value.GetReflectionType();
+
+ for (int i = 0; i < type->GetFieldCount(); i++) {
+ Field field = type->GetFieldInfo(i);
+
+ AddSuggestion(matches, word, prefix + field.Name);
+ }
+
+ while (type) {
+ Object::Ptr prototype = type->GetPrototype();
+ Dictionary::Ptr dict = dynamic_pointer_cast<Dictionary>(prototype);
+
+ if (dict) {
+ ObjectLock olock(dict);
+ BOOST_FOREACH(const Dictionary::Pair& kv, dict) {
+ AddSuggestion(matches, word, prefix + kv.first);
+ }
+ }
+
+ type = type->GetBaseType();
+ }
+}
+
std::vector<String> ConsoleHandler::GetAutocompletionSuggestions(const String& word, ScriptFrame& frame)
{
std::vector<String> matches;
}
}
+ if (frame.Imports) {
+ ObjectLock olock(frame.Imports);
+ BOOST_FOREACH(const Value& import, frame.Imports) {
+ AddSuggestions(matches, word, "", import);
+ }
+ }
+
String::SizeType cperiod = word.RFind(".");
if (cperiod != String::NPos) {
if (expr)
value = expr->Evaluate(frame);
- if (value.IsObjectType<Dictionary>()) {
- Dictionary::Ptr dict = value;
-
- ObjectLock olock(dict);
- BOOST_FOREACH(const Dictionary::Pair& kv, dict) {
- AddSuggestion(matches, word, pword + "." + kv.first);
- }
- }
+ AddSuggestions(matches, word, pword, value);
- Type::Ptr type = value.GetReflectionType();
-
- for (int i = 0; i < type->GetFieldCount(); i++) {
- Field field = type->GetFieldInfo(i);
-
- AddSuggestion(matches, word, pword + "." + field.Name);
- }
-
- while (type) {
- Object::Ptr prototype = type->GetPrototype();
- Dictionary::Ptr dict = dynamic_pointer_cast<Dictionary>(prototype);
-
- if (dict) {
- ObjectLock olock(dict);
- BOOST_FOREACH(const Dictionary::Pair& kv, dict) {
- AddSuggestion(matches, word, pword + "." + kv.first);
- }
- }
-
- type = type->GetBaseType();
- }
} catch (...) { /* Ignore the exception */ }
}