summaryrefslogtreecommitdiff
path: root/src/resource/config-lua.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/resource/config-lua.c')
-rw-r--r--src/resource/config-lua.c1751
1 files changed, 1751 insertions, 0 deletions
diff --git a/src/resource/config-lua.c b/src/resource/config-lua.c
new file mode 100644
index 0000000..5a0a5d7
--- /dev/null
+++ b/src/resource/config-lua.c
@@ -0,0 +1,1751 @@
+/*
+ * Copyright (c) 2012, Intel Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include <lualib.h>
+#include <lauxlib.h>
+
+#include <murphy/common.h>
+#include <murphy/common/debug.h>
+#include <murphy/core/lua-bindings/murphy.h>
+#include <murphy/core/lua-utils/object.h>
+
+#include "config-lua.h"
+#include "resource-lua.h"
+#include "config-api.h"
+#include "client-api.h"
+#include "manager-api.h"
+#include "zone.h"
+#include "application-class.h"
+#include "resource.h"
+#include "resource-set.h"
+#include "resource-owner.h"
+#include "attribute.h"
+
+#define ZONE_CLASS MRP_LUA_CLASS_SIMPLE(zone)
+#define APPCLASS_CLASS MRP_LUA_CLASS_SIMPLE(application_class)
+#define ZONE_ATTR_CLASS MRP_LUA_CLASS(zone, attributes)
+#define RESCLASS_CLASS MRP_LUA_CLASS(resource, class)
+#define RESMETHOD_CLASS MRP_LUA_CLASS_SIMPLE(resource)
+
+#define ATTRIBUTE_CLASSID MRP_LUA_CLASSID_ROOT "attribute"
+#define RESOURCE_CLASSID MRP_LUA_CLASSID_ROOT "resource.instance"
+
+typedef enum field_e field_t;
+typedef enum attr_owner_e attr_owner_t;
+typedef struct appclass_s appclass_t;
+typedef struct zone_s zone_t;
+typedef struct resclass_s resclass_t;
+typedef struct resource_s resource_t;
+typedef struct attr_def_s attr_def_t;
+typedef struct attr_s attr_t;
+
+typedef bool (*attribute_access_t)(attr_t *, int, mrp_attr_t *);
+
+enum field_e {
+ ATTRIBUTES = 1,
+ CLASS,
+ NAME,
+ PRIORITY,
+ SHAREABLE,
+ MANDATORY,
+ MODAL,
+ SHARE,
+ GRANT,
+ ORDER,
+ SHARED,
+ METHOD,
+ OWNERS,
+ RECALC,
+ VETO,
+ ID
+};
+
+enum attr_owner_e {
+ ZONE = 1,
+ RESOURCE
+};
+
+struct appclass_s {
+ const char *name;
+};
+
+struct zone_s {
+ uint32_t id;
+ const char *name;
+ int attr_tbl;
+};
+
+struct resclass_s {
+ uint32_t id;
+ const char *name;
+ mrp_attr_def_t *attrs;
+};
+
+struct resource_s {
+ uint32_t rsetid;
+ uint32_t resid;
+ const char *name;
+ int attr_tbl;
+};
+
+struct attr_def_s {
+ int nattr;
+ mrp_attr_def_t *attrs;
+};
+
+struct attr_s {
+ struct {
+ attr_owner_t type;
+ void *data;
+ } owner;
+ attr_def_t *def;
+ attribute_access_t fetch;
+ attribute_access_t update;
+};
+
+
+static void attributes_class_create(lua_State *);
+static void appclass_class_create(lua_State *);
+static void zone_class_create(lua_State *);
+static void resclass_class_create(lua_State *);
+static void resource_class_create(lua_State *);
+static void resource_methods_create(lua_State *);
+
+
+static int attributes_create(lua_State *, attr_owner_t, void *,
+ attr_def_t *, attribute_access_t,
+ attribute_access_t);
+static int attributes_getvalue(lua_State *);
+static int attributes_setvalue(lua_State *);
+static int attributes_getlength(lua_State *);
+static attr_t *check_attributes(lua_State *, int);
+static int push_attributes(lua_State *, int);
+
+static int appclass_create(lua_State *);
+static int appclass_getfield(lua_State *);
+static int appclass_setfield(lua_State *);
+static void appclass_destroy(void *);
+/* static appclass_t *check_appclass(lua_State *, int); */
+static appclass_t *to_appclass(lua_State *, int);
+
+static int zone_create(lua_State *);
+static int zone_getfield(lua_State *);
+static int zone_setfield(lua_State *);
+static void zone_destroy(void *);
+/* static zone_t *check_zone(lua_State *, int); */
+static zone_t *to_zone(lua_State *, int);
+
+static int zone_attr_create(lua_State *);
+static int zone_attr_getfield(lua_State *);
+static int zone_attr_setfield(lua_State *);
+static void zone_attr_destroy(void *);
+/* static attr_def_t *check_zone_attr(lua_State *, int); */
+/* static attr_def_t *to_zone_attr(lua_State *, int); */
+static bool fetch_zone_attribute(attr_t *, int, mrp_attr_t *);
+static bool update_zone_attribute(attr_t *, int, mrp_attr_t *);
+
+static int resclass_create_from_lua(lua_State *);
+static int resclass_getfield(lua_State *);
+static int resclass_setfield(lua_State *);
+static void resclass_destroy(void *);
+/* static resclass_t *check_resclass(lua_State *, int); */
+static resclass_t *to_resclass(lua_State *, int);
+
+static int resource_getfield(lua_State *);
+static int resource_setfield(lua_State *);
+static resource_t *check_resource(lua_State *, int);
+static bool fetch_resource_attribute(attr_t *, int, mrp_attr_t *);
+static bool update_resource_attribute(attr_t *, int, mrp_attr_t *);
+
+static mrp_lua_resmethod_t *resmethod_create_from_c(lua_State *);
+static int resmethod_create_from_lua(lua_State *);
+static int resmethod_getfield(lua_State *);
+static int resmethod_setfield(lua_State *);
+static void resmethod_destroy(void *);
+static mrp_lua_resmethod_t *to_resmethod(lua_State *, int);
+
+static mrp_attr_def_t *check_attrdefs(lua_State *, int, int *);
+static void free_attrdefs(mrp_attr_def_t *);
+static mrp_attr_t *check_attrs(lua_State *, int, attr_def_t *);
+static void free_attrs(mrp_attr_t *);
+static int check_attrindex(lua_State *, int, attr_def_t *);
+static int check_boolean(lua_State *, int);
+static mrp_resource_order_t check_order(lua_State *, int);
+static int push_order(lua_State *, mrp_resource_order_t);
+static field_t field_check(lua_State *, int, const char **);
+static field_t field_name_to_type(const char *, size_t);
+
+static int method_recalc(lua_State *);
+
+
+MRP_LUA_METHOD_LIST_TABLE (
+ zone_attr_methods, /* methodlist name */
+ MRP_LUA_METHOD_CONSTRUCTOR (zone_attr_create)
+);
+
+MRP_LUA_METHOD_LIST_TABLE (
+ resclass_methods, /* methodlist name */
+ MRP_LUA_METHOD_CONSTRUCTOR (resclass_create_from_lua)
+);
+
+
+MRP_LUA_METHOD_LIST_TABLE (
+ attributes_overrides, /* methodlist name */
+ MRP_LUA_OVERRIDE_GETFIELD (attributes_getvalue)
+ MRP_LUA_OVERRIDE_SETFIELD (attributes_setvalue)
+ MRP_LUA_OVERRIDE_GETLENGTH (attributes_getlength)
+);
+
+MRP_LUA_METHOD_LIST_TABLE (
+ zone_attr_overrides, /* methodlist name */
+ MRP_LUA_OVERRIDE_CALL (zone_attr_create)
+ MRP_LUA_OVERRIDE_GETFIELD (zone_attr_getfield)
+ MRP_LUA_OVERRIDE_SETFIELD (zone_attr_setfield)
+);
+
+MRP_LUA_METHOD_LIST_TABLE (
+ resclass_overrides, /* methodlist name */
+ MRP_LUA_OVERRIDE_CALL (resclass_create_from_lua)
+ MRP_LUA_OVERRIDE_GETFIELD (resclass_getfield)
+ MRP_LUA_OVERRIDE_SETFIELD (resclass_setfield)
+);
+
+MRP_LUA_METHOD_LIST_TABLE (
+ resource_overrides, /* methodlist name */
+ MRP_LUA_OVERRIDE_GETFIELD (resource_getfield)
+ MRP_LUA_OVERRIDE_SETFIELD (resource_setfield)
+);
+
+MRP_LUA_CLASS_DEF_SIMPLE (
+ application_class, /* main class & constructor name */
+ appclass_t, /* userdata type */
+ appclass_destroy, /* userdata destructor */
+ MRP_LUA_METHOD_LIST ( /* main class methods */
+ MRP_LUA_METHOD_CONSTRUCTOR (appclass_create)
+ ),
+ MRP_LUA_METHOD_LIST ( /* main class overrides */
+ MRP_LUA_OVERRIDE_CALL (appclass_create)
+ MRP_LUA_OVERRIDE_GETFIELD (appclass_getfield)
+ MRP_LUA_OVERRIDE_SETFIELD (appclass_setfield)
+ )
+);
+
+MRP_LUA_CLASS_DEF_SIMPLE (
+ zone, /* main class & constructor name */
+ zone_t, /* userdata type */
+ zone_destroy, /* userdata destructor */
+ MRP_LUA_METHOD_LIST ( /* main class methods */
+ MRP_LUA_METHOD_CONSTRUCTOR (zone_create)
+ ),
+ MRP_LUA_METHOD_LIST ( /* main class overrides */
+ MRP_LUA_OVERRIDE_CALL (zone_create)
+ MRP_LUA_OVERRIDE_GETFIELD (zone_getfield)
+ MRP_LUA_OVERRIDE_SETFIELD (zone_setfield)
+ )
+);
+
+MRP_LUA_CLASS_DEF (
+ zone, /* main class name */
+ attributes, /* constructor name */
+ attr_def_t, /* userdata type */
+ zone_attr_destroy, /* userdata destructor */
+ zone_attr_methods, /* class methods */
+ zone_attr_overrides /* class overrides */
+);
+
+MRP_LUA_CLASS_DEF (
+ resource, /* main class name */
+ class, /* constructor name */
+ resclass_t, /* userdata type */
+ resclass_destroy, /* userdata destructor */
+ resclass_methods, /* class methods */
+ resclass_overrides /* class overrides */
+);
+
+
+MRP_LUA_CLASS_DEF_SIMPLE (
+ resource, /* main class name */
+ mrp_lua_resmethod_t, /* userdata type */
+ resmethod_destroy, /* userdata destructor */
+ MRP_LUA_METHOD_LIST (
+ MRP_LUA_METHOD_CONSTRUCTOR (resmethod_create_from_lua)
+ ),
+ MRP_LUA_METHOD_LIST (
+ MRP_LUA_OVERRIDE_CALL (resmethod_create_from_lua)
+ MRP_LUA_OVERRIDE_GETFIELD (resmethod_getfield)
+ MRP_LUA_OVERRIDE_SETFIELD (resmethod_setfield)
+ )
+);
+
+attr_def_t *zone_attr_defs;
+attr_def_t *resource_attr_defs[MRP_RESOURCE_MAX];
+mrp_lua_resmethod_t *resource_methods;
+
+
+void mrp_resource_configuration_init(void)
+{
+ static bool initialised = false;
+
+ lua_State *L;
+
+ if (!initialised && (L = mrp_lua_get_lua_state())) {
+
+ appclass_class_create(L);
+ zone_class_create(L);
+ resclass_class_create(L);
+ resource_class_create(L);
+
+ mrp_resource_lua_init(L);
+
+ resource_methods_create(L);
+
+ mrp_debug("lua classes are ready for resource "
+ "configuration and management");
+
+ initialised = true;
+ }
+}
+
+
+mrp_lua_resmethod_t *mrp_lua_get_resource_methods(void)
+{
+ return resource_methods;
+}
+
+uint32_t mrp_lua_to_resource_id(lua_State *L, int t)
+{
+ resclass_t *rc = to_resclass(L, t);
+
+ return rc ? rc->id : MRP_RESOURCE_ID_INVALID;
+}
+
+void mrp_lua_resclass_create_from_c(uint32_t id)
+{
+ lua_State *L;
+ mrp_resource_def_t *rdef;
+ resclass_t *resclass;
+ attr_def_t *adef;
+ mrp_attr_def_t *attrs;
+ int nattr;
+
+ if ((L = mrp_lua_get_lua_state())) {
+
+ if (!(rdef = mrp_resource_definition_find_by_id(id)))
+ luaL_error(L, "invalid resource definition ID %d", id);
+
+ resclass = (resclass_t *)mrp_lua_create_object(L, RESCLASS_CLASS,
+ rdef->name,0);
+ adef = mrp_allocz(sizeof(attr_def_t));
+ nattr = rdef->nattr;
+ attrs = mrp_allocz(sizeof(mrp_attr_def_t) * (nattr + 1));
+
+ if (!nattr)
+ mrp_attribute_copy_definitions(rdef->attrdefs, attrs);
+
+ if (!resclass)
+ luaL_error(L, "invalid or duplicate name '%s'", rdef->name);
+ if (!adef)
+ luaL_error(L,"can't to allocate memory for attribute definitions");
+
+ resclass->id = id;
+ resclass->name = mrp_strdup(rdef->name);
+ resclass->attrs = attrs;
+
+ adef->nattr = nattr;
+ adef->attrs = attrs;
+
+ resource_attr_defs[id] = adef;
+
+ lua_pop(L, 1);
+
+ mrp_log_info("resource class '%s' created", rdef->name);
+ }
+}
+
+int mrp_lua_resource_create(lua_State *L, mrp_resource_t *res)
+{
+ mrp_resource_def_t *rdef;
+ attr_def_t *adef;
+ resource_t *r;
+
+ MRP_LUA_ENTER;
+
+ MRP_ASSERT(res, "invalid argument");
+
+ if (!(rdef = res->def))
+ lua_pushnil(L);
+ else {
+ adef = resource_attr_defs[rdef->id];
+
+ MRP_ASSERT(resource_attr_defs[rdef->id], "can't find attribute defs");
+
+ r = lua_newuserdata(L, sizeof(resource_t));
+
+ r->rsetid = res->rsetid;
+ r->resid = rdef->id;
+ r->name = rdef->name;
+ r->attr_tbl = attributes_create(L, RESOURCE,r, adef,
+ fetch_resource_attribute,
+ update_resource_attribute);
+
+ luaL_getmetatable(L, RESOURCE_CLASSID);
+ lua_setmetatable(L, -2);
+ }
+
+ MRP_LUA_LEAVE(1);
+}
+
+
+static void attributes_class_create(lua_State *L)
+{
+ /* create a metatable for attributes */
+ luaL_newmetatable(L, ATTRIBUTE_CLASSID);
+ lua_pushliteral(L, "__index");
+ lua_pushvalue(L, -2);
+ lua_settable(L, -3); /* metatable.__index = metatable */
+ luaL_openlib(L, NULL, attributes_overrides, 0);
+}
+
+static void appclass_class_create(lua_State *L)
+{
+ mrp_lua_create_object_class(L, APPCLASS_CLASS);
+}
+
+static void zone_class_create(lua_State *L)
+{
+ mrp_lua_create_object_class(L, ZONE_CLASS);
+ mrp_lua_create_object_class(L, ZONE_ATTR_CLASS);
+
+ attributes_class_create(L);
+
+ zone_attr_defs = mrp_lua_create_object(L, ZONE_ATTR_CLASS, NULL,0);
+ mrp_lua_set_object_name(L, ZONE_ATTR_CLASS, "attributes");
+ lua_pop(L, 1);
+}
+
+static void resclass_class_create(lua_State *L)
+{
+ mrp_lua_create_object_class(L, RESCLASS_CLASS);
+}
+
+static int resource_destructor(lua_State *L)
+{
+ resource_t *r;
+
+ if ((r = lua_touserdata(L, -1)) != NULL) {
+ mrp_debug("destroying Lua resource %p", r);
+ luaL_unref(L, LUA_REGISTRYINDEX, r->attr_tbl);
+ r->attr_tbl = LUA_NOREF;
+ }
+
+ return 0;
+}
+
+static void resource_class_create(lua_State *L)
+{
+ /* create a metatable for resource instances */
+ luaL_newmetatable(L, RESOURCE_CLASSID);
+ lua_pushcfunction(L, resource_destructor);
+ lua_setfield(L, -2, "__gc");
+ lua_pushliteral(L, "__index");
+ lua_pushvalue(L, -2);
+ lua_settable(L, -3); /* metatable.__index = metatable */
+ luaL_openlib(L, NULL, resource_overrides, 0);
+}
+
+static void resource_methods_create(lua_State *L)
+{
+ typedef struct {
+ const char *name;
+ lua_CFunction func;
+ } method_def_t;
+
+ static method_def_t method_defs[] = {
+ { "recalc", method_recalc },
+ { NULL , NULL }
+ };
+
+ method_def_t *md;
+
+ mrp_lua_create_object_class(L, RESMETHOD_CLASS);
+ resource_methods = resmethod_create_from_c(L);
+
+ for (md = method_defs; md->name; md++) {
+ lua_pushstring(L, md->name);
+ lua_pushcfunction(L, md->func);
+ lua_rawset(L, -3);
+ }
+}
+
+
+static int attributes_create(lua_State *L,
+ attr_owner_t type, void *data,
+ attr_def_t *def,
+ attribute_access_t fetch,
+ attribute_access_t update)
+{
+ attr_t *attr;
+ int tblref;
+
+ MRP_LUA_ENTER;
+
+ attr = lua_newuserdata(L, sizeof(attr_t));
+
+ attr->owner.type = type;
+ attr->owner.data = data;
+ attr->def = def;
+ attr->fetch = fetch;
+ attr->update = update;
+
+ luaL_getmetatable(L, ATTRIBUTE_CLASSID);
+ lua_setmetatable(L, -2);
+
+ tblref = luaL_ref(L, LUA_REGISTRYINDEX);
+
+ MRP_LUA_LEAVE(tblref);
+}
+
+static int attributes_getvalue(lua_State *L)
+{
+ attr_t *attr = check_attributes(L, 1);
+ int idx = check_attrindex(L, 2, attr->def);
+ mrp_attr_def_t *def = attr->def->attrs + idx;
+ mrp_attr_t av;
+
+ MRP_LUA_ENTER;
+
+ if (idx < 0) {
+ lua_pushnil(L);
+ return 1;
+ }
+
+ if (!(def->access & MRP_RESOURCE_READ)) {
+ luaL_error(L, "attempt to read a non-readable attribute %s",
+ def->name);
+ MRP_LUA_LEAVE(0);
+ }
+
+ if (!attr->fetch(attr, idx, &av)) {
+ lua_pushnil(L);
+ MRP_LUA_LEAVE(1);
+ }
+
+ switch (def->type) {
+ case mqi_string:
+ if (av.value.string)
+ lua_pushstring(L, av.value.string);
+ else
+ lua_pushnil(L);
+ break;
+ case mqi_integer:
+ case mqi_unsignd:
+ lua_pushinteger(L, av.value.integer);
+ break;
+ case mqi_floating:
+ lua_pushnumber(L, av.value.floating);
+ break;
+ default:
+ lua_pushnil(L);
+ break;
+ }
+
+ MRP_LUA_LEAVE(1);
+}
+
+static int attributes_setvalue(lua_State *L)
+{
+ attr_t *attr = check_attributes(L, 1);
+ int idx = check_attrindex(L, 2, attr->def);
+ mrp_attr_def_t *def = attr->def->attrs + idx;
+ mrp_attr_t av;
+
+ MRP_LUA_ENTER;
+
+ if (idx < 0)
+ luaL_error(L, "attribute %s dows not exist", def->name);
+
+ if (!(def->access & MRP_RESOURCE_WRITE))
+ luaL_error(L, "attempt to read a readonly attribute %s", def->name);
+
+ switch (def->type) {
+ case mqi_string:
+ av.value.string = luaL_checkstring(L, 3);
+ break;
+ case mqi_integer:
+ av.value.integer = luaL_checkinteger(L, 3);
+ break;
+ case mqi_unsignd:
+ if ((av.value.integer = luaL_checkinteger(L, 3)) < 0) {
+ luaL_error(L, "attempt to update an unsigned attribute "
+ "with negative value");
+ }
+ break;
+ case mqi_floating:
+ av.value.floating = luaL_checknumber(L, 3);
+ break;
+ default:
+ luaL_error(L, "internal error: invalid attribute type");
+ break;
+ }
+
+ if (!attr->update(attr, idx, &av))
+ luaL_error(L, "attribute update failed");
+
+ MRP_LUA_LEAVE(0);
+}
+
+static int attributes_getlength(lua_State *L)
+{
+ attr_t *attr = check_attributes(L, 1);
+ attr_def_t *def = attr->def;
+
+ MRP_LUA_ENTER;
+
+ lua_pushinteger(L, def ? def->nattr : 0);
+
+ MRP_LUA_LEAVE(1);
+}
+
+static attr_t *check_attributes(lua_State *L, int idx)
+{
+ return (attr_t *)luaL_checkudata(L, idx, ATTRIBUTE_CLASSID);
+}
+
+static int push_attributes(lua_State *L, int attr_tbl)
+{
+ lua_rawgeti(L, LUA_REGISTRYINDEX, attr_tbl);
+ return 1;
+}
+
+
+static int appclass_create(lua_State *L)
+{
+ appclass_t *appclass;
+ size_t fldnamlen;
+ const char *fldnam;
+ int priority = 0;
+ int modal = -1;
+ int share = -1;
+ mrp_resource_order_t order = 0;
+ const char *name = NULL;
+
+ MRP_LUA_ENTER;
+
+ MRP_LUA_FOREACH_FIELD(L, 2, fldnam, fldnamlen) {
+
+ switch (field_name_to_type(fldnam, fldnamlen)) {
+
+ case NAME:
+ name = mrp_strdup(luaL_checkstring(L, -1));
+ break;
+
+ case PRIORITY:
+ priority = luaL_checkint(L, -1);
+ break;
+
+ case MODAL:
+ modal = check_boolean(L, -1);
+ break;
+
+ case SHARE:
+ share = check_boolean(L, -1);
+ break;
+
+ case ORDER:
+ order = check_order(L, -1);
+ break;
+
+ default:
+ luaL_error(L, "unexpected field '%s'", fldnam);
+ break;
+ }
+ }
+
+ if (!name)
+ luaL_error(L, "missing or wrong name field");
+ if (modal < 0)
+ luaL_error(L, "missing or wrong modal field");
+ if (modal && share)
+ luaL_error(L, "modal class can't share");
+ if (share < 0)
+ luaL_error(L, "missing or wrong share field");
+ if (!order)
+ luaL_error(L, "missing or wrong order field");
+ if (priority < 0)
+ luaL_error(L, "negative priority");
+ if (!mrp_application_class_create(name, priority, modal, share, order))
+ luaL_error(L, "failed to create application class '%s'", name);
+
+ appclass = (appclass_t *)mrp_lua_create_object(L, APPCLASS_CLASS, name,0);
+
+ if (!appclass)
+ luaL_error(L, "invalid or duplicate name '%s'", name);
+ else {
+ appclass->name = name;
+ mrp_log_info("application class '%s' created", name);
+ }
+ MRP_LUA_LEAVE(1);
+}
+
+static int appclass_getfield(lua_State *L)
+{
+ appclass_t *appclass = to_appclass(L, 1);
+ field_t fld = field_check(L, 2, NULL);
+ mrp_application_class_t *ac;
+
+ MRP_LUA_ENTER;
+
+ lua_pop(L, 1);
+
+ if (!appclass || !(ac = mrp_application_class_find(appclass->name)))
+ lua_pushnil(L);
+ else {
+ switch (fld) {
+ case NAME: lua_pushstring(L, ac->name); break;
+ case PRIORITY: lua_pushinteger(L, ac->priority); break;
+ case MODAL: lua_pushboolean(L, ac->modal); break;
+ case SHARE: lua_pushboolean(L, ac->share); break;
+ case ORDER: push_order(L, ac->order); break;
+ default: lua_pushnil(L); break;
+ }
+ }
+
+ MRP_LUA_LEAVE(1);
+}
+
+static int appclass_setfield(lua_State *L)
+{
+ MRP_LUA_ENTER;
+
+ luaL_error(L, "can't modify application classes after definition");
+
+ MRP_LUA_LEAVE(0);
+}
+
+static void appclass_destroy(void *data)
+{
+ appclass_t *appclass = (appclass_t *)data;
+
+ MRP_LUA_ENTER;
+
+ mrp_free((void *)appclass->name);
+
+ MRP_LUA_LEAVE_NOARG;
+}
+
+#if 0
+static appclass_t *check_appclass(lua_State *L, int idx)
+{
+ return (appclass_t *)mrp_lua_check_object(L, APPCLASS_CLASS, idx);
+}
+#endif
+
+static appclass_t *to_appclass(lua_State *L, int idx)
+{
+ return (appclass_t *)mrp_lua_to_object(L, APPCLASS_CLASS, idx);
+}
+
+
+static int zone_create(lua_State *L)
+{
+ zone_t *zone;
+ size_t fldnamlen;
+ const char *fldnam;
+ uint32_t id;
+ const char *name = NULL;
+ mrp_attr_t *attrs = NULL;
+
+ MRP_LUA_ENTER;
+
+ MRP_ASSERT(zone_attr_defs, "invocation prior to initialization");
+
+ if (!zone_attr_defs->attrs)
+ luaL_error(L, "attempt to create zone before defining attributes");
+
+ MRP_LUA_FOREACH_FIELD(L, 2, fldnam, fldnamlen) {
+
+ switch (field_name_to_type(fldnam, fldnamlen)) {
+
+ case NAME:
+ name = mrp_strdup(luaL_checkstring(L, -1));
+ break;
+
+ case ATTRIBUTES:
+ attrs = check_attrs(L, -1, zone_attr_defs);
+ break;
+
+ default:
+ luaL_error(L, "unexpected field '%s'", fldnam);
+ break;
+ }
+ }
+
+ if (!name)
+ luaL_error(L, "missing or wrong name field");
+ if ((id = mrp_zone_create(name,attrs)) == MRP_ZONE_ID_INVALID)
+ luaL_error(L, "failed to create zone");
+
+ free_attrs(attrs);
+
+ zone = (zone_t *)mrp_lua_create_object(L, ZONE_CLASS, name,0);
+
+ if (!zone)
+ luaL_error(L, "invalid or duplicate name '%s'", name);
+ else {
+ zone->id = id;
+ zone->name = name;
+ zone->attr_tbl = attributes_create(L, ZONE,zone, zone_attr_defs,
+ fetch_zone_attribute,
+ update_zone_attribute);
+
+ mrp_log_info("zone '%s' created", name);
+ }
+
+ MRP_LUA_LEAVE(1);
+}
+
+static int zone_getfield(lua_State *L)
+{
+ zone_t *zone = to_zone(L, 1);
+ field_t fld = field_check(L, 2, NULL);
+
+ MRP_LUA_ENTER;
+
+ lua_pop(L, 1);
+
+ if (!zone) {
+ /* attempt to access a zone definition field */
+ switch (fld) {
+ case ATTRIBUTES: mrp_lua_push_object(L, zone_attr_defs); break;
+ default: lua_pushnil(L); break;
+ }
+ }
+ else {
+ /* attempt to access a zone instance field */
+ switch (fld) {
+ case ATTRIBUTES: push_attributes(L, zone->attr_tbl); break;
+ case ID: lua_pushinteger(L, zone->id + 1); break;
+ case NAME: lua_pushstring(L, zone->name); break;
+ default: lua_pushnil(L); break;
+ }
+ }
+
+ MRP_LUA_LEAVE(1);
+}
+
+static int zone_setfield(lua_State *L)
+{
+ zone_t *zone = to_zone(L, 1);
+ field_t fld = field_check(L, 2, NULL);
+
+ MRP_LUA_ENTER;
+
+ if (zone || fld != ATTRIBUTES)
+ luaL_error(L, "zones can't be exetended after definition");
+
+ MRP_LUA_LEAVE(0);
+}
+
+static void zone_destroy(void *data)
+{
+ /* zone_t *zone = (zone_t *)data; */
+
+ MRP_UNUSED(data);
+
+ MRP_LUA_ENTER;
+
+ MRP_LUA_LEAVE_NOARG;
+}
+
+#if 0
+static zone_t *check_zone(lua_State *L, int idx)
+{
+ return (zone_t *)mrp_lua_check_object(L, ZONE_CLASS, idx);
+}
+#endif
+
+static zone_t *to_zone(lua_State *L, int idx)
+{
+ return (zone_t *)mrp_lua_to_object(L, ZONE_CLASS, idx);
+}
+
+static int zone_attr_create(lua_State *L)
+{
+ mrp_attr_def_t *attrs;
+ int nattr;
+
+ MRP_LUA_ENTER;
+
+ MRP_ASSERT(zone_attr_defs, "invocation prior to initialization");
+
+ if (zone_attr_defs->attrs)
+ luaL_error(L, "zone attributes already defined");
+ else {
+ attrs = check_attrdefs(L, 2, &nattr);
+
+ mrp_zone_definition_create(attrs);
+
+ zone_attr_defs->nattr = nattr;
+ zone_attr_defs->attrs = attrs;
+ }
+
+ mrp_lua_push_object(L, zone_attr_defs);
+
+ mrp_log_info("zone attributes defined");
+
+ MRP_LUA_LEAVE(1);
+}
+
+static int zone_attr_getfield(lua_State *L)
+{
+ zone_t *zone;
+ int idx;
+
+ MRP_LUA_ENTER;
+
+ MRP_ASSERT(zone_attr_defs, "invocation prior to initialization");
+
+ if (!(zone = to_zone(L, 1))) {
+ mrp_debug("zone attribute definition => attribute index");
+ if ((idx = check_attrindex(L, 2, zone_attr_defs)) < 0)
+ lua_pushnil(L);
+ else
+ lua_pushinteger(L, idx);
+ }
+ else {
+ mrp_debug("zone attribute => nil");
+ lua_pushnil(L);
+ }
+
+ MRP_LUA_LEAVE(1);
+}
+
+static int zone_attr_setfield(lua_State *L)
+{
+ MRP_UNUSED(L);
+
+ MRP_LUA_ENTER;
+
+ MRP_LUA_LEAVE(0);
+}
+
+
+static void zone_attr_destroy(void *data)
+{
+ /* attr_def_t *attr = (attr_def_t *)data; */
+
+ MRP_UNUSED(data);
+
+ MRP_LUA_ENTER;
+
+ MRP_LUA_LEAVE_NOARG;
+}
+
+#if 0
+static attr_def_t *check_zone_attr(lua_State *L, int idx)
+{
+ return (attr_def_t *)mrp_lua_check_object(L, ZONE_ATTR_CLASS, idx);
+}
+#endif
+
+#if 0
+static attr_def_t *to_zone_attr(lua_State *L, int idx)
+{
+ return (attr_def_t *)mrp_lua_to_object(L, ZONE_ATTR_CLASS, idx);
+}
+#endif
+
+static bool fetch_zone_attribute(attr_t *attr, int idx, mrp_attr_t *retval)
+{
+ mrp_zone_t *z;
+ zone_t *zone;
+
+ if (attr->owner.type == ZONE && (zone = (zone_t *)attr->owner.data)) {
+ if ((z = mrp_zone_find_by_id(zone->id))) {
+ if (mrp_zone_read_attribute(z, idx, retval))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static bool update_zone_attribute(attr_t *attr, int idx, mrp_attr_t *value)
+{
+ mrp_zone_t *z;
+ zone_t *zone;
+
+ MRP_UNUSED(idx);
+ MRP_UNUSED(value);
+
+ if (attr->owner.type == ZONE && (zone = (zone_t *)attr->owner.data)) {
+ if ((z = mrp_zone_find_by_id(zone->id))) {
+#if 0
+ if (mrp_zone_write_attribute(z, idx, value))
+ return true;
+#endif
+ }
+ }
+
+ return false;
+}
+
+static int resclass_create_from_lua(lua_State *L)
+{
+ resclass_t *resclass;
+ size_t fldnamlen;
+ const char *fldnam;
+ int nattr = 0;
+ uint32_t id;
+ const char *name = NULL;
+ mrp_attr_def_t *attrs = NULL;
+ bool shareable = false;
+ mrp_resource_mgr_ftbl_t *ftbl = NULL;
+ void *mgrdata = NULL;
+ attr_def_t *adef;
+
+ MRP_LUA_ENTER;
+
+ MRP_LUA_FOREACH_FIELD(L, 2, fldnam, fldnamlen) {
+
+ switch (field_name_to_type(fldnam, fldnamlen)) {
+
+ case NAME:
+ name = mrp_strdup(luaL_checkstring(L, -1));
+ break;
+
+ case SHAREABLE:
+ luaL_argcheck(L, lua_isboolean(L,-1), 2, "attempt to assign "
+ "non-boolean value to 'shareable' field");
+ shareable = lua_toboolean(L, -1);
+ break;
+
+ case ATTRIBUTES:
+ attrs = check_attrdefs(L, -1, &nattr);
+ break;
+
+ default:
+ luaL_error(L, "unexpected field '%s'", fldnam);
+ break;
+ }
+ }
+
+ if (!name)
+ luaL_error(L, "missing or wrong name field");
+
+ id = mrp_resource_definition_create(name, shareable, attrs,ftbl,mgrdata);
+
+ MRP_ASSERT(id < MRP_RESOURCE_MAX, "resource id is out of range");
+
+ if (id == MRP_RESOURCE_ID_INVALID)
+ luaL_error(L, "failed to register resource class '%s'", name);
+
+ resclass = (resclass_t *)mrp_lua_create_object(L, RESCLASS_CLASS, name,0);
+ adef = mrp_allocz(sizeof(attr_def_t));
+
+ if (!resclass)
+ luaL_error(L, "invalid or duplicate name '%s'", name);
+ if (!adef)
+ luaL_error(L, "failed to allocate memory for attribute definitions");
+
+ resclass->id = id;
+ resclass->name = name;
+ resclass->attrs = attrs;
+
+ adef->nattr = nattr;
+ adef->attrs = attrs;
+
+ resource_attr_defs[id] = adef;
+
+ mrp_log_info("resource class '%s' created", name);
+
+ MRP_LUA_LEAVE(1);
+}
+
+static int resclass_getfield(lua_State *L)
+{
+ resclass_t *rc = to_resclass(L, 1);
+ field_t fld = field_check(L, 2, NULL);
+ mrp_resource_def_t *rd;
+
+ MRP_LUA_ENTER;
+
+ lua_pop(L, 1);
+
+ if (!rc || !(rd = mrp_resource_definition_find_by_name(rc->name)))
+ lua_pushnil(L);
+ else {
+ switch (fld) {
+ case NAME: lua_pushstring(L, rd->name); break;
+ case ID: lua_pushinteger(L, rd->id + 1); break;
+ case SHAREABLE: lua_pushboolean(L, rd->shareable); break;
+ default: lua_pushnil(L); break;
+ }
+ }
+
+ MRP_LUA_LEAVE(1);
+}
+
+static int resclass_setfield(lua_State *L)
+{
+ MRP_LUA_ENTER;
+
+ luaL_error(L, "can't modify resource classes after definition");
+
+ MRP_LUA_LEAVE(1);
+}
+
+static void resclass_destroy(void *data)
+{
+ resclass_t *rc = (resclass_t *)data;
+
+ MRP_LUA_ENTER;
+
+ mrp_free((void *)rc->name);
+ free_attrdefs(rc->attrs);
+
+ MRP_LUA_LEAVE_NOARG;
+}
+
+#if 0
+static resclass_t *check_resclass(lua_State *L, int idx)
+{
+ return (resclass_t *)mrp_lua_check_object(L, RESCLASS_CLASS, idx);
+}
+#endif
+
+static resclass_t *to_resclass(lua_State *L, int idx)
+{
+ return (resclass_t *)mrp_lua_to_object(L, RESCLASS_CLASS, idx);
+}
+
+static int resource_getfield(lua_State *L)
+{
+ const char *name;
+ resource_t *res = check_resource(L, 1);
+ field_t fld = field_check(L, 2, &name);
+ mrp_resource_set_t *s;
+ mrp_resource_t *r;
+ mrp_resource_mask_t m;
+
+ MRP_LUA_ENTER;
+
+ switch (fld) {
+
+ case ATTRIBUTES:
+ push_attributes(L, res->attr_tbl);
+ break;
+
+ case SHARED:
+ case SHARE:
+ if (!(r = mrp_resource_set_find_resource(res->rsetid, res->name)))
+ lua_pushnil(L);
+ else
+ lua_pushboolean(L, r->shared);
+ break;
+
+ default:
+ if (!(s = mrp_resource_set_find_by_id(res->rsetid))) {
+ lua_pushnil(L);
+ break;
+ } else {
+ m = ((mrp_resource_mask_t)1) << res->resid;
+ }
+
+ switch (fld) {
+ case MANDATORY:
+ lua_pushboolean(L, s->resource.mask.mandatory & m ? true : false);
+ break;
+ case GRANT:
+ lua_pushboolean(L, s->resource.mask.grant & m ? true : false);
+ break;
+ default:
+ lua_pushnil(L);
+ break;
+ }
+
+ break;
+ }
+
+ MRP_LUA_LEAVE(1);
+}
+
+static int resource_setfield(lua_State *L)
+{
+ MRP_UNUSED(L);
+
+ MRP_LUA_ENTER;
+
+ MRP_LUA_LEAVE(0);
+}
+
+static resource_t *check_resource(lua_State *L, int idx)
+{
+ return (resource_t *)luaL_checkudata(L, idx, RESOURCE_CLASSID);
+}
+
+static bool fetch_resource_attribute(attr_t *attr, int idx, mrp_attr_t *retval)
+{
+ mrp_resource_set_t *rset;
+ resource_t *resource;
+ mrp_attr_t *a;
+
+ if (attr->owner.type == RESOURCE) {
+ if ((resource = (resource_t *)attr->owner.data)) {
+ if ((rset = mrp_resource_set_find_by_id(resource->rsetid))) {
+ a = mrp_resource_set_read_attribute(rset, resource->name,
+ idx, retval);
+ return a ? true : false;
+ }
+ }
+ }
+
+ return false;
+}
+
+
+static bool update_resource_attribute(attr_t *attr, int idx, mrp_attr_t *value)
+{
+ mrp_resource_set_t *rset;
+ resource_t *resource;
+ mrp_attr_t values[2];
+ int sts;
+
+ MRP_UNUSED(idx);
+
+ if (attr->owner.type == RESOURCE) {
+ if ((resource = (resource_t *)attr->owner.data)) {
+ if ((rset = mrp_resource_set_find_by_id(resource->rsetid))) {
+ memcpy(values + 0, value, sizeof(mrp_attr_t));
+ memset(values + 1, 0, sizeof(mrp_attr_t));
+
+ sts = mrp_resource_set_write_attributes(rset, resource->name,
+ values);
+ return (sts < 0) ? false : true;
+ }
+ }
+ }
+
+ return false;
+}
+
+static mrp_lua_resmethod_t *resmethod_create_from_c(lua_State *L)
+{
+ mrp_lua_resmethod_t *method = mrp_lua_create_object(L, RESMETHOD_CLASS,
+ "method",0);
+
+ if (!method)
+ luaL_error(L, "invalid or duplicate name 'method'");
+
+ return method;
+}
+
+static int resmethod_create_from_lua(lua_State *L)
+{
+ MRP_LUA_ENTER;
+
+ luaL_error(L, "singleton object has already been created");
+
+ lua_pushnil(L);
+
+ MRP_LUA_LEAVE(1);
+}
+
+static int resmethod_getfield(lua_State *L)
+{
+ const char *name;
+ mrp_lua_resmethod_t *method = to_resmethod(L, 1);
+ field_t fld = field_check(L, 2, &name);
+
+ MRP_LUA_ENTER;
+
+ lua_pop(L, 1);
+
+ if (!method) {
+ /* attempt to access a resclass or owners */
+ switch (fld) {
+ case METHOD: mrp_lua_push_object(L, resource_methods); break;
+ case OWNERS: lua_pushstring(L,name); lua_rawget(L,1); break;
+ default: lua_pushnil(L); break;
+ }
+ }
+ else {
+ /* attempt to access a method member */
+ if (!resource_methods)
+ lua_pushnil(L);
+ else {
+ switch (fld) {
+ case VETO:
+ case RECALC:
+ lua_pushstring(L, name);
+ lua_rawget(L, 1);
+ break;
+ default:
+ lua_pushnil(L);
+ break;
+ }
+ }
+ }
+
+ MRP_LUA_LEAVE(1);
+}
+
+static int resmethod_setfield(lua_State *L)
+{
+ const char *name;
+ mrp_lua_resmethod_t *method = to_resmethod(L, 1);
+ field_t fld = field_check(L, 2, &name);
+
+ MRP_LUA_ENTER;
+
+ if (method) {
+ switch (fld) {
+ case VETO:
+ lua_pushstring(L, name);
+ lua_pushvalue(L, 3);
+ method->veto = mrp_funcarray_check(L, -1);
+ lua_rawset(L, 1);
+ break;
+ default:
+ luaL_error(L, "invalid method '%s'", name);
+ break;
+ }
+ }
+
+ MRP_LUA_LEAVE(0);
+}
+
+static void resmethod_destroy(void *data)
+{
+ mrp_lua_resmethod_t *method = (mrp_lua_resmethod_t *)data;
+
+ MRP_LUA_ENTER;
+
+ method->veto = NULL;
+
+ MRP_LUA_LEAVE_NOARG;
+}
+
+static mrp_lua_resmethod_t *to_resmethod(lua_State *L, int idx)
+{
+ return (mrp_lua_resmethod_t *)mrp_lua_to_object(L, RESMETHOD_CLASS, idx);
+}
+
+
+static mrp_attr_def_t *check_attrdefs(lua_State *L, int t, int *ret_len)
+{
+ mrp_attr_def_t attrdefs[128];
+ mrp_attr_def_t *ad, *end, *dup;
+ size_t i;
+ const char *name;
+ const char *string;
+ const char *access;
+ bool value_set;
+ int len;
+ size_t size;
+ size_t namlen;
+
+ t = (t < 0) ? lua_gettop(L) + t + 1 : t;
+
+ luaL_checktype(L, t, LUA_TTABLE);
+
+ end = (ad = attrdefs) + (MRP_ARRAY_SIZE(attrdefs) - 1);
+
+ MRP_LUA_FOREACH_FIELD(L, t, name, namlen) {
+ if (!name[0])
+ luaL_error(L, "invalid attribute definition");
+ if (ad >= end)
+ luaL_error(L, "too many attributes");
+
+ ad->name = mrp_strdup(name);
+ ad->type = mqi_error;
+ ad->access = MRP_RESOURCE_READ;
+
+ value_set = false;
+
+ luaL_checktype(L, -1, LUA_TTABLE);
+
+
+ for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
+ if (lua_type(L, -2) != LUA_TNUMBER)
+ goto error;
+
+ i = lua_tointeger(L, -2);
+
+ switch (i) {
+ case 1:
+ ad->type = lua_tointeger(L, -1);
+ break;
+ case 2:
+ switch (ad->type) {
+ case mqi_string:
+ if ((string = lua_tostring(L, -1))) {
+ ad->value.string = mrp_strdup(string);
+ value_set = true;
+ }
+ break;
+ case mqi_integer:
+ ad->value.integer = lua_tointeger(L, -1);
+ value_set = true;
+ break;
+ case mqi_unsignd:
+ ad->value.integer = lua_tointeger(L, -1);
+ value_set = true;
+ break;
+ case mqi_floating:
+ ad->value.floating = lua_tonumber(L, -1);
+ value_set = true;
+ break;
+ default:
+ break;
+ }
+ break;
+ case 3:
+ if (!(access = lua_tostring(L, -1)))
+ ad->type = mqi_error;
+ else {
+ if (!strcasecmp(access, "read"))
+ ad->access = MRP_RESOURCE_READ;
+ else if (!strcasecmp(access, "write"))
+ ad->access = MRP_RESOURCE_WRITE;
+ else if (!strcasecmp(access, "rw"))
+ ad->access = MRP_RESOURCE_RW;
+ else
+ ad->type = mqi_error;
+ }
+ break;
+ default:
+ ad->type = mqi_error;
+ break;
+ }
+ } /* for */
+
+ if (!value_set ||
+ (ad->type != mqi_string &&
+ ad->type != mqi_integer &&
+ ad->type != mqi_unsignd &&
+ ad->type != mqi_floating ))
+ goto error;
+
+ ad++;
+ } /* foreach */
+
+ memset(ad, 0, sizeof(mrp_attr_def_t));
+
+ len = ad - attrdefs;
+ size = sizeof(mrp_attr_def_t) * (len+1);
+ dup = mrp_alloc(size);
+
+ if (!dup)
+ luaL_error(L, "failed to allocate %u byte memory", size);
+
+ memcpy(dup, attrdefs, size);
+
+ if (ret_len)
+ *ret_len = len;
+
+ return dup;
+
+ error:
+ luaL_argerror(L, t, "malformed attribute definition");
+ return NULL;
+}
+
+
+static void free_attrdefs(mrp_attr_def_t *attrdefs)
+{
+ mrp_attr_def_t *ad;
+
+ if (attrdefs) {
+ for (ad = attrdefs; ad->name; ad++) {
+ mrp_free((void *)ad->name);
+ if (ad->type == mqi_string)
+ mrp_free((void *)ad->value.string);
+ }
+ mrp_free(attrdefs);
+ }
+}
+
+static int attr_name_to_index(const char *name, attr_def_t *def)
+{
+ mrp_attr_def_t *attrs = def->attrs;
+ int idx;
+
+ for (idx = 0; idx < def->nattr; idx++) {
+ if (!strcmp(name, attrs[idx].name))
+ return idx;
+ }
+
+ return -1;
+}
+
+static mrp_attr_t *check_attrs(lua_State *L, int t, attr_def_t *defs)
+{
+ mrp_attr_t attr[128];
+ mrp_attr_t *at, *end, *dup;
+ const char *name;
+ size_t namlen;
+ size_t len;
+ size_t size;
+ int i;
+
+ t = (t < 0) ? lua_gettop(L) + t + 1 : t;
+
+ luaL_checktype(L, t, LUA_TTABLE);
+
+ end = (at = attr) + (MRP_ARRAY_SIZE(attr) - 1);
+
+ MRP_LUA_FOREACH_FIELD(L, t, name, namlen) {
+ if (!name[0])
+ luaL_error(L, "invalid attribute definition");
+ if (at >= end)
+ luaL_error(L, "too many attributes");
+ if ((i = attr_name_to_index(name, defs)) < 0)
+ luaL_error(L, "attribute %s do not exist", name);
+
+ at->name = mrp_strdup(name);
+
+ switch ((at->type = defs->attrs[i].type)) {
+ case mqi_string:
+ at->value.string = mrp_strdup(luaL_checkstring(L,-1));
+ break;
+ case mqi_integer:
+ at->value.integer = luaL_checkinteger(L,-1);
+ break;
+ case mqi_unsignd:
+ if ((at->value.integer = luaL_checkinteger(L,-1)) < 0)
+ luaL_error(L, "attempt to give negative value to an "
+ "unsigned integer");
+ break;
+ default:
+ luaL_error(L, "Internal error: invalid type for attribute");
+ break;
+ }
+
+ at++;
+ }
+
+ memset(at, 0, sizeof(mrp_attr_t));
+
+ len = at - attr;
+ size = sizeof(mrp_attr_t) * (len + 1);
+
+ dup = mrp_alloc(size);
+ memcpy(dup, attr, size);
+
+ return dup;
+}
+
+
+static void free_attrs(mrp_attr_t *attrs)
+{
+ mrp_attr_t *at;
+
+ if (attrs) {
+ for (at = attrs; at->name; at++) {
+ mrp_free((void *)at->name);
+ if (at->type == mqi_string)
+ mrp_free((void *)at->value.string);
+ }
+ mrp_free(attrs);
+ }
+}
+
+
+static int check_attrindex(lua_State *L, int arg, attr_def_t *def)
+{
+ const char *name;
+ int idx;
+
+ if (!def || !def->attrs)
+ return -1;
+
+ switch (lua_type(L, arg)) {
+ case LUA_TNUMBER:
+ idx = lua_tointeger(L, arg);
+ return (idx >= 0 && idx < def->nattr) ? idx : -1;
+ case LUA_TSTRING:
+ name = lua_tostring(L, arg);
+ return attr_name_to_index(name, def);
+ default:
+ return -1;
+ }
+}
+
+
+static int check_boolean(lua_State *L, int idx)
+{
+ if (!lua_isboolean(L, idx))
+ luaL_argerror(L, idx, "expected boolean");
+ return lua_toboolean(L, idx) ? 1 : 0;
+}
+
+static mrp_resource_order_t check_order(lua_State *L, int idx)
+{
+ const char *str = luaL_checkstring(L, idx);
+
+ if (!strcasecmp(str, "fifo"))
+ return MRP_RESOURCE_ORDER_FIFO;
+
+ if (!strcasecmp(str, "lifo"))
+ return MRP_RESOURCE_ORDER_LIFO;
+
+ luaL_error(L, "invalid value for order ('fifo' or 'lifo' accepted only)");
+
+ return MRP_RESOURCE_ORDER_UNKNOWN;
+}
+
+static int push_order(lua_State *L, mrp_resource_order_t order)
+{
+ const char *str;
+
+ switch (order) {
+ case MRP_RESOURCE_ORDER_FIFO: str = "fifo"; break;
+ case MRP_RESOURCE_ORDER_LIFO: str = "lifo"; break;
+ default: str = "<unknown>"; break;
+ }
+
+ lua_pushstring(L, str);
+
+ return 1;
+}
+
+
+static field_t field_check(lua_State *L, int idx, const char **ret_fldnam)
+{
+ const char *fldnam;
+ size_t fldnamlen;
+ field_t fldtyp;
+
+ if (!(fldnam = lua_tolstring(L, idx, &fldnamlen)))
+ fldtyp = 0;
+ else
+ fldtyp = field_name_to_type(fldnam, fldnamlen);
+
+ if (ret_fldnam)
+ *ret_fldnam = fldnam;
+
+ return fldtyp;
+}
+
+
+static field_t field_name_to_type(const char *name, size_t len)
+{
+ switch (len) {
+
+ case 2:
+ if (!strcmp(name, "id"))
+ return ID;
+ break;
+
+ case 4:
+ if (!strcmp(name, "name"))
+ return NAME;
+ if (!strcmp(name, "veto"))
+ return VETO;
+ break;
+
+ case 5:
+ if (!strcmp(name, "class"))
+ return CLASS;
+ if (!strcmp(name, "modal"))
+ return MODAL;
+ if (!strcmp(name, "share"))
+ return SHARE;
+ if (!strcmp(name, "grant"))
+ return GRANT;
+ if (!strcmp(name, "order"))
+ return ORDER;
+ break;
+
+ case 6:
+ if (!strcmp(name, "method"))
+ return METHOD;
+ if (!strcmp(name, "owners"))
+ return OWNERS;
+ if (!strcmp(name, "shared"))
+ return SHARED;
+ if (!strcmp(name, "recalc"))
+ return RECALC;
+ break;
+
+ case 8:
+ if (!strcmp(name, "priority"))
+ return PRIORITY;
+ break;
+
+ case 9:
+ if (!strcmp(name, "mandatory"))
+ return MANDATORY;
+ if (!strcmp(name, "shareable"))
+ return SHAREABLE;
+ break;
+
+ case 10:
+ if (!strcmp(name, "attributes"))
+ return ATTRIBUTES;
+ break;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int method_recalc(lua_State *L)
+{
+ const char *zone_name;
+ mrp_zone_t *zone;
+
+ if (lua_type(L, 1) == LUA_TSTRING && (zone_name = lua_tostring(L, 1))) {
+
+ if (!(zone = mrp_zone_find_by_name(zone_name))) {
+ luaL_error(L, "can't recalculate resources in zone '%s': "
+ "no such zone", zone_name);
+ }
+
+ mrp_resource_owner_recalc(zone->id);
+ }
+
+ return 0;
+}
+
+/*
+ * Local Variables:
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ *
+ */