resource: add resource.method.recalc(zone_name) function
[profile/ivi/murphy.git] / src / resource / config-lua.c
1 /*
2  * Copyright (c) 2012, Intel Corporation
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  *   * Redistributions of source code must retain the above copyright notice,
9  *     this list of conditions and the following disclaimer.
10  *   * Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution.
13  *   * Neither the name of Intel Corporation nor the names of its contributors
14  *     may be used to endorse or promote products derived from this software
15  *     without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <errno.h>
34
35 #include <lualib.h>
36 #include <lauxlib.h>
37
38 #include <murphy/common.h>
39 #include <murphy/common/debug.h>
40 #include <murphy/core/lua-bindings/murphy.h>
41 #include <murphy/core/lua-utils/object.h>
42
43 #include "config-lua.h"
44 #include "resource-lua.h"
45 #include "config-api.h"
46 #include "client-api.h"
47 #include "manager-api.h"
48 #include "zone.h"
49 #include "application-class.h"
50 #include "resource.h"
51 #include "resource-set.h"
52 #include "resource-owner.h"
53 #include "attribute.h"
54
55 #define ZONE_CLASS             MRP_LUA_CLASS_SIMPLE(zone)
56 #define APPCLASS_CLASS         MRP_LUA_CLASS_SIMPLE(application_class)
57 #define ZONE_ATTR_CLASS        MRP_LUA_CLASS(zone, attributes)
58 #define RESCLASS_CLASS         MRP_LUA_CLASS(resource, class)
59 #define RESMETHOD_CLASS        MRP_LUA_CLASS_SIMPLE(resource)
60
61 #define ATTRIBUTE_CLASSID      MRP_LUA_CLASSID_ROOT "attribute"
62 #define RESOURCE_CLASSID       MRP_LUA_CLASSID_ROOT "resource.instance"
63
64 typedef enum   field_e         field_t;
65 typedef enum   attr_owner_e    attr_owner_t;
66 typedef struct appclass_s      appclass_t;
67 typedef struct zone_s          zone_t;
68 typedef struct resclass_s      resclass_t;
69 typedef struct resource_s      resource_t;
70 typedef struct attr_def_s      attr_def_t;
71 typedef struct attr_s          attr_t;
72
73 typedef bool (*attribute_access_t)(attr_t *, int, mrp_attr_t *);
74
75 enum field_e {
76     ATTRIBUTES = 1,
77     CLASS,
78     NAME,
79     PRIORITY,
80     SHAREABLE,
81     MANDATORY,
82     MODAL,
83     SHARE,
84     GRANT,
85     ORDER,
86     SHARED,
87     METHOD,
88     OWNERS,
89     RECALC,
90     VETO,
91     ID
92 };
93
94 enum attr_owner_e {
95     ZONE = 1,
96     RESOURCE
97 };
98
99 struct appclass_s {
100     const char *name;
101 };
102
103 struct zone_s {
104     uint32_t  id;
105     const char *name;
106     int attr_tbl;
107 };
108
109 struct resclass_s {
110     uint32_t id;
111     const char *name;
112     mrp_attr_def_t *attrs;
113 };
114
115 struct resource_s {
116     uint32_t rsetid;
117     uint32_t resid;
118     const char *name;
119     int attr_tbl;
120 };
121
122 struct attr_def_s {
123     int nattr;
124     mrp_attr_def_t *attrs;
125 };
126
127 struct attr_s {
128     struct {
129         attr_owner_t type;
130         void *data;
131     } owner;
132     attr_def_t *def;
133     attribute_access_t fetch;
134     attribute_access_t update;
135 };
136
137
138 static void attributes_class_create(lua_State *);
139 static void appclass_class_create(lua_State *);
140 static void zone_class_create(lua_State *);
141 static void resclass_class_create(lua_State *);
142 static void resource_class_create(lua_State *);
143 static void resource_methods_create(lua_State *);
144
145
146 static int  attributes_create(lua_State *, attr_owner_t, void *,
147                               attr_def_t *, attribute_access_t,
148                               attribute_access_t);
149 static int  attributes_getvalue(lua_State *);
150 static int  attributes_setvalue(lua_State *);
151 static int  attributes_getlength(lua_State *);
152 static attr_t *check_attributes(lua_State *, int);
153 static int  push_attributes(lua_State *, int);
154
155 static int  appclass_create(lua_State *);
156 static int  appclass_getfield(lua_State *);
157 static int  appclass_setfield(lua_State *);
158 static void appclass_destroy(void *);
159 /* static appclass_t *check_appclass(lua_State *, int); */
160 static appclass_t *to_appclass(lua_State *, int);
161
162 static int  zone_create(lua_State *);
163 static int  zone_getfield(lua_State *);
164 static int  zone_setfield(lua_State *);
165 static void zone_destroy(void *);
166 /* static zone_t *check_zone(lua_State *, int); */
167 static zone_t *to_zone(lua_State *, int);
168
169 static int  zone_attr_create(lua_State *);
170 static int  zone_attr_getfield(lua_State *);
171 static int  zone_attr_setfield(lua_State *);
172 static void zone_attr_destroy(void *);
173 /* static attr_def_t *check_zone_attr(lua_State *, int); */
174 /* static attr_def_t *to_zone_attr(lua_State *, int); */
175 static bool fetch_zone_attribute(attr_t *, int, mrp_attr_t *);
176 static bool update_zone_attribute(attr_t *, int, mrp_attr_t *);
177
178 static int  resclass_create_from_lua(lua_State *);
179 static int  resclass_getfield(lua_State *);
180 static int  resclass_setfield(lua_State *);
181 static void resclass_destroy(void *);
182 /* static resclass_t *check_resclass(lua_State *, int); */
183 static resclass_t *to_resclass(lua_State *, int);
184
185 static int  resource_getfield(lua_State *);
186 static int  resource_setfield(lua_State *);
187 static resource_t *check_resource(lua_State *, int);
188 static bool fetch_resource_attribute(attr_t *, int, mrp_attr_t *);
189 static bool update_resource_attribute(attr_t *, int, mrp_attr_t *);
190
191 static mrp_lua_resmethod_t *resmethod_create_from_c(lua_State *);
192 static int  resmethod_create_from_lua(lua_State *);
193 static int  resmethod_getfield(lua_State *);
194 static int  resmethod_setfield(lua_State *);
195 static void resmethod_destroy(void *);
196 static mrp_lua_resmethod_t *to_resmethod(lua_State *, int);
197
198 static mrp_attr_def_t *check_attrdefs(lua_State *, int, int *);
199 static void free_attrdefs(mrp_attr_def_t *);
200 static mrp_attr_t *check_attrs(lua_State *, int, attr_def_t *);
201 static void free_attrs(mrp_attr_t *);
202 static int check_attrindex(lua_State *, int, attr_def_t *);
203 static int check_boolean(lua_State *, int);
204 static mrp_resource_order_t check_order(lua_State *, int);
205 static int push_order(lua_State *, mrp_resource_order_t);
206 static field_t field_check(lua_State *, int, const char **);
207 static field_t field_name_to_type(const char *, size_t);
208
209 static int method_recalc(lua_State *);
210
211
212 MRP_LUA_METHOD_LIST_TABLE (
213     zone_attr_methods,       /* methodlist name */
214     MRP_LUA_METHOD_CONSTRUCTOR  (zone_attr_create)
215 );
216
217 MRP_LUA_METHOD_LIST_TABLE (
218     resclass_methods,         /* methodlist name */
219     MRP_LUA_METHOD_CONSTRUCTOR  (resclass_create_from_lua)
220 );
221
222
223 MRP_LUA_METHOD_LIST_TABLE (
224     attributes_overrides,    /* methodlist name */
225     MRP_LUA_OVERRIDE_GETFIELD   (attributes_getvalue)
226     MRP_LUA_OVERRIDE_SETFIELD   (attributes_setvalue)
227     MRP_LUA_OVERRIDE_GETLENGTH  (attributes_getlength)
228 );
229
230 MRP_LUA_METHOD_LIST_TABLE (
231     zone_attr_overrides,     /* methodlist name */
232     MRP_LUA_OVERRIDE_CALL       (zone_attr_create)
233     MRP_LUA_OVERRIDE_GETFIELD   (zone_attr_getfield)
234     MRP_LUA_OVERRIDE_SETFIELD   (zone_attr_setfield)
235 );
236
237 MRP_LUA_METHOD_LIST_TABLE (
238     resclass_overrides,       /* methodlist name */
239     MRP_LUA_OVERRIDE_CALL       (resclass_create_from_lua)
240     MRP_LUA_OVERRIDE_GETFIELD   (resclass_getfield)
241     MRP_LUA_OVERRIDE_SETFIELD   (resclass_setfield)
242 );
243
244 MRP_LUA_METHOD_LIST_TABLE (
245     resource_overrides,       /* methodlist name */
246     MRP_LUA_OVERRIDE_GETFIELD   (resource_getfield)
247     MRP_LUA_OVERRIDE_SETFIELD   (resource_setfield)
248 );
249
250 MRP_LUA_CLASS_DEF_SIMPLE (
251     application_class,          /* main class & constructor name */
252     appclass_t,                 /* userdata type */
253     appclass_destroy,           /* userdata destructor */
254     MRP_LUA_METHOD_LIST (       /* main class methods */
255         MRP_LUA_METHOD_CONSTRUCTOR  (appclass_create)
256     ),
257     MRP_LUA_METHOD_LIST (       /* main class overrides */
258         MRP_LUA_OVERRIDE_CALL       (appclass_create)
259         MRP_LUA_OVERRIDE_GETFIELD   (appclass_getfield)
260         MRP_LUA_OVERRIDE_SETFIELD   (appclass_setfield)
261     )
262 );
263
264 MRP_LUA_CLASS_DEF_SIMPLE (
265     zone,                       /* main class & constructor name */
266     zone_t,                     /* userdata type */
267     zone_destroy,               /* userdata destructor */
268     MRP_LUA_METHOD_LIST (       /* main class methods */
269         MRP_LUA_METHOD_CONSTRUCTOR  (zone_create)
270     ),
271     MRP_LUA_METHOD_LIST (       /* main class overrides */
272         MRP_LUA_OVERRIDE_CALL       (zone_create)
273         MRP_LUA_OVERRIDE_GETFIELD   (zone_getfield)
274         MRP_LUA_OVERRIDE_SETFIELD   (zone_setfield)
275     )
276 );
277
278 MRP_LUA_CLASS_DEF (
279     zone,                       /* main class name */
280     attributes,                 /* constructor name */
281     attr_def_t,                 /* userdata type */
282     zone_attr_destroy,          /* userdata destructor */
283     zone_attr_methods,          /* class methods */
284     zone_attr_overrides         /* class overrides */
285 );
286
287 MRP_LUA_CLASS_DEF (
288     resource,                   /* main class name */
289     class,                      /* constructor name */
290     resclass_t,                 /* userdata type */
291     resclass_destroy,           /* userdata destructor */
292     resclass_methods,           /* class methods */
293     resclass_overrides          /* class overrides */
294 );
295
296
297 MRP_LUA_CLASS_DEF_SIMPLE (
298     resource,                   /* main class name */
299     mrp_lua_resmethod_t,        /* userdata type */
300     resmethod_destroy,          /* userdata destructor */
301     MRP_LUA_METHOD_LIST (
302         MRP_LUA_METHOD_CONSTRUCTOR  (resmethod_create_from_lua)
303     ),
304     MRP_LUA_METHOD_LIST (
305         MRP_LUA_OVERRIDE_CALL       (resmethod_create_from_lua)
306         MRP_LUA_OVERRIDE_GETFIELD   (resmethod_getfield)
307         MRP_LUA_OVERRIDE_SETFIELD   (resmethod_setfield)
308     )
309 );
310
311 attr_def_t           *zone_attr_defs;
312 attr_def_t           *resource_attr_defs[MRP_RESOURCE_MAX];
313 mrp_lua_resmethod_t  *resource_methods;
314
315
316 void mrp_resource_configuration_init(void)
317 {
318     static bool initialised = false;
319
320     lua_State *L;
321
322     if (!initialised && (L =  mrp_lua_get_lua_state())) {
323
324         appclass_class_create(L);
325         zone_class_create(L);
326         resclass_class_create(L);
327         resource_class_create(L);
328
329         mrp_resource_lua_init(L);
330
331         resource_methods_create(L);
332
333         mrp_debug("lua classes are ready for resource "
334                   "configuration and management");
335
336         initialised = true;
337     }
338 }
339
340
341 mrp_lua_resmethod_t *mrp_lua_get_resource_methods(void)
342 {
343     return resource_methods;
344 }
345
346 uint32_t mrp_lua_to_resource_id(lua_State *L, int t)
347 {
348     resclass_t *rc = to_resclass(L, t);
349
350     return rc ? rc->id : MRP_RESOURCE_ID_INVALID;
351 }
352
353 void mrp_lua_resclass_create_from_c(uint32_t id)
354 {
355     lua_State *L;
356     mrp_resource_def_t *rdef;
357     resclass_t *resclass;
358     attr_def_t *adef;
359     mrp_attr_def_t *attrs;
360     int nattr;
361
362     if ((L = mrp_lua_get_lua_state())) {
363
364         if (!(rdef = mrp_resource_definition_find_by_id(id)))
365             luaL_error(L, "invalid resource definition ID %d", id);
366
367         resclass = (resclass_t *)mrp_lua_create_object(L, RESCLASS_CLASS,
368                                                        rdef->name,0);
369         adef = mrp_allocz(sizeof(attr_def_t));
370         nattr = rdef->nattr;
371         attrs = mrp_allocz(sizeof(mrp_attr_def_t) * (nattr + 1));
372
373         if (!nattr)
374             mrp_attribute_copy_definitions(rdef->attrdefs, attrs);
375
376         if (!resclass)
377             luaL_error(L, "invalid or duplicate name '%s'", rdef->name);
378         if (!adef)
379             luaL_error(L,"can't to allocate memory for attribute definitions");
380
381         resclass->id = id;
382         resclass->name = mrp_strdup(rdef->name);
383         resclass->attrs = attrs;
384
385         adef->nattr = nattr;
386         adef->attrs = attrs;
387
388         resource_attr_defs[id] = adef;
389
390         lua_pop(L, 1);
391
392         mrp_log_info("resource class '%s' created", rdef->name);
393     }
394 }
395
396 int mrp_lua_resource_create(lua_State *L, mrp_resource_t *res)
397 {
398     mrp_resource_def_t *rdef;
399     attr_def_t *adef;
400     resource_t *r;
401
402     MRP_LUA_ENTER;
403
404     MRP_ASSERT(res, "invalid argument");
405
406     if (!(rdef = res->def))
407         lua_pushnil(L);
408     else {
409         adef = resource_attr_defs[rdef->id];
410
411         MRP_ASSERT(resource_attr_defs[rdef->id], "can't find attribute defs");
412
413         r = lua_newuserdata(L, sizeof(resource_t));
414
415         r->rsetid = res->rsetid;
416         r->resid = rdef->id;
417         r->name = rdef->name;
418         r->attr_tbl = attributes_create(L, RESOURCE,r, adef,
419                                         fetch_resource_attribute,
420                                         update_resource_attribute);
421
422         luaL_getmetatable(L, RESOURCE_CLASSID);
423         lua_setmetatable(L, -2);
424     }
425
426     MRP_LUA_LEAVE(1);
427 }
428
429
430 static void attributes_class_create(lua_State *L)
431 {
432     /* create a metatable for attributes */
433     luaL_newmetatable(L, ATTRIBUTE_CLASSID);
434     lua_pushliteral(L, "__index");
435     lua_pushvalue(L, -2);
436     lua_settable(L, -3);        /* metatable.__index = metatable */
437     luaL_openlib(L, NULL, attributes_overrides, 0);
438 }
439
440 static void appclass_class_create(lua_State *L)
441 {
442     mrp_lua_create_object_class(L, APPCLASS_CLASS);
443 }
444
445 static void zone_class_create(lua_State *L)
446 {
447     mrp_lua_create_object_class(L, ZONE_CLASS);
448     mrp_lua_create_object_class(L, ZONE_ATTR_CLASS);
449
450     attributes_class_create(L);
451
452     zone_attr_defs = mrp_lua_create_object(L, ZONE_ATTR_CLASS, NULL,0);
453     mrp_lua_set_object_name(L, ZONE_ATTR_CLASS, "attributes");
454     lua_pop(L, 1);
455 }
456
457 static void resclass_class_create(lua_State *L)
458 {
459     mrp_lua_create_object_class(L, RESCLASS_CLASS);
460 }
461
462 static void resource_class_create(lua_State *L)
463 {
464     /* create a metatable for resource instances */
465     luaL_newmetatable(L, RESOURCE_CLASSID);
466     lua_pushliteral(L, "__index");
467     lua_pushvalue(L, -2);
468     lua_settable(L, -3);        /* metatable.__index = metatable */
469     luaL_openlib(L, NULL, resource_overrides, 0);
470 }
471
472 static void resource_methods_create(lua_State *L)
473 {
474     typedef struct {
475         const char *name;
476         lua_CFunction func;
477     } method_def_t;
478
479     static method_def_t method_defs[] = {
480         { "recalc",  method_recalc },
481         {   NULL  ,      NULL      }
482     };
483
484     method_def_t *md;
485
486     mrp_lua_create_object_class(L, RESMETHOD_CLASS);
487     resource_methods = resmethod_create_from_c(L);
488
489     for (md = method_defs;  md->name;   md++) {
490         lua_pushstring(L, md->name);
491         lua_pushcfunction(L, md->func);
492         lua_rawset(L, -3);
493     }
494 }
495
496
497 static int attributes_create(lua_State *L,
498                              attr_owner_t type, void *data,
499                              attr_def_t *def,
500                              attribute_access_t fetch,
501                              attribute_access_t update)
502 {
503     attr_t *attr;
504     int tblref;
505
506     MRP_LUA_ENTER;
507
508     attr = lua_newuserdata(L, sizeof(attr_t));
509
510     attr->owner.type = type;
511     attr->owner.data = data;
512     attr->def = def;
513     attr->fetch = fetch;
514     attr->update = update;
515
516     luaL_getmetatable(L, ATTRIBUTE_CLASSID);
517     lua_setmetatable(L, -2);
518
519     tblref = luaL_ref(L, LUA_REGISTRYINDEX);
520
521     MRP_LUA_LEAVE(tblref);
522 }
523
524 static int attributes_getvalue(lua_State *L)
525 {
526     attr_t *attr = check_attributes(L, 1);
527     int idx = check_attrindex(L, 2, attr->def);
528     mrp_attr_def_t *def = attr->def->attrs + idx;
529     mrp_attr_t av;
530
531     MRP_LUA_ENTER;
532
533     if (idx < 0) {
534         lua_pushnil(L);
535         return 1;
536     }
537
538     if (!(def->access & MRP_RESOURCE_READ)) {
539         luaL_error(L, "attempt to read a non-readable attribute %s",
540                    def->name);
541         MRP_LUA_LEAVE(0);
542     }
543
544     if (!attr->fetch(attr, idx, &av)) {
545         lua_pushnil(L);
546         MRP_LUA_LEAVE(1);
547     }
548
549     switch (def->type) {
550     case mqi_string:
551         if (av.value.string)
552             lua_pushstring(L, av.value.string);
553         else
554             lua_pushnil(L);
555         break;
556     case mqi_integer:
557     case mqi_unsignd:
558         lua_pushinteger(L, av.value.integer);
559         break;
560     case mqi_floating:
561         lua_pushnumber(L, av.value.floating);
562         break;
563     default:
564         lua_pushnil(L);
565         break;
566     }
567
568     MRP_LUA_LEAVE(1);
569 }
570
571 static int attributes_setvalue(lua_State *L)
572 {
573     attr_t *attr = check_attributes(L, 1);
574     int idx = check_attrindex(L, 2, attr->def);
575     mrp_attr_def_t *def = attr->def->attrs + idx;
576     mrp_attr_t av;
577
578     MRP_LUA_ENTER;
579
580     if (idx < 0)
581         luaL_error(L, "attribute %s dows not exist", def->name);
582
583     if (!(def->access & MRP_RESOURCE_WRITE))
584         luaL_error(L, "attempt to read a readonly attribute %s", def->name);
585
586     switch (def->type) {
587     case mqi_string:
588         av.value.string = luaL_checkstring(L, 3);
589         break;
590     case mqi_integer:
591         av.value.integer =  luaL_checkinteger(L, 3);
592         break;
593     case mqi_unsignd:
594         if ((av.value.integer = luaL_checkinteger(L, 3)) < 0) {
595             luaL_error(L, "attempt to update an unsigned attribute "
596                        "with negative value");
597         }
598         break;
599     case mqi_floating:
600         av.value.floating = luaL_checknumber(L, 3);
601         break;
602     default:
603         luaL_error(L, "internal error: invalid attribute type");
604         break;
605     }
606
607     if (!attr->update(attr, idx, &av))
608         luaL_error(L, "attribute update failed");
609
610     MRP_LUA_LEAVE(0);
611 }
612
613 static int attributes_getlength(lua_State *L)
614 {
615     attr_t *attr = check_attributes(L, 1);
616     attr_def_t *def = attr->def;
617
618     MRP_LUA_ENTER;
619
620     lua_pushinteger(L, def ? def->nattr : 0);
621
622     MRP_LUA_LEAVE(1);
623 }
624
625 static attr_t *check_attributes(lua_State *L, int idx)
626 {
627     return (attr_t *)luaL_checkudata(L, idx, ATTRIBUTE_CLASSID);
628 }
629
630 static int push_attributes(lua_State *L, int attr_tbl)
631 {
632     lua_rawgeti(L, LUA_REGISTRYINDEX, attr_tbl);
633     return 1;
634 }
635
636
637 static int appclass_create(lua_State *L)
638 {
639     appclass_t *appclass;
640     size_t fldnamlen;
641     const char *fldnam;
642     int priority = 0;
643     int modal = -1;
644     int share = -1;
645     mrp_resource_order_t order = 0;
646     const char *name = NULL;
647
648     MRP_LUA_ENTER;
649
650     MRP_LUA_FOREACH_FIELD(L, 2, fldnam, fldnamlen) {
651
652         switch (field_name_to_type(fldnam, fldnamlen)) {
653
654         case NAME:
655             name = mrp_strdup(luaL_checkstring(L, -1));
656             break;
657
658         case PRIORITY:
659             priority = luaL_checkint(L, -1);
660             break;
661
662         case MODAL:
663             modal = check_boolean(L, -1);
664             break;
665
666         case SHARE:
667             share = check_boolean(L, -1);
668             break;
669
670         case ORDER:
671             order = check_order(L, -1);
672             break;
673
674         default:
675             luaL_error(L, "unexpected field '%s'", fldnam);
676             break;
677         }
678     }
679
680     if (!name)
681         luaL_error(L, "missing or wrong name field");
682     if (modal < 0)
683         luaL_error(L, "missing or wrong modal field");
684     if (modal && share)
685         luaL_error(L, "modal class can't share");
686     if (share < 0)
687         luaL_error(L, "missing or wrong share field");
688     if (!order)
689         luaL_error(L, "missing or wrong order field");
690     if (priority < 0)
691         luaL_error(L, "negative priority");
692     if (!mrp_application_class_create(name, priority, modal, share, order))
693         luaL_error(L, "failed to create application class '%s'", name);
694
695     appclass = (appclass_t *)mrp_lua_create_object(L, APPCLASS_CLASS, name,0);
696
697     if (!appclass)
698         luaL_error(L, "invalid or duplicate name '%s'", name);
699     else {
700         appclass->name = name;
701         mrp_log_info("application class '%s' created", name);
702     }
703     MRP_LUA_LEAVE(1);
704 }
705
706 static int appclass_getfield(lua_State *L)
707 {
708     appclass_t *appclass = to_appclass(L, 1);
709     field_t fld = field_check(L, 2, NULL);
710     mrp_application_class_t *ac;
711
712     MRP_LUA_ENTER;
713
714     lua_pop(L, 1);
715
716     if (!appclass || !(ac = mrp_application_class_find(appclass->name)))
717         lua_pushnil(L);
718     else {
719         switch (fld) {
720         case NAME:       lua_pushstring(L, ac->name);         break;
721         case PRIORITY:   lua_pushinteger(L, ac->priority);    break;
722         case MODAL:      lua_pushboolean(L, ac->modal);       break;
723         case SHARE:      lua_pushboolean(L, ac->share);       break;
724         case ORDER:      push_order(L, ac->order);            break;
725         default:         lua_pushnil(L);                      break;
726         }
727     }
728
729     MRP_LUA_LEAVE(1);
730 }
731
732 static int appclass_setfield(lua_State *L)
733 {
734     MRP_LUA_ENTER;
735
736     luaL_error(L, "can't modify application classes after definition");
737
738     MRP_LUA_LEAVE(0);
739 }
740
741 static void appclass_destroy(void *data)
742 {
743     appclass_t *appclass = (appclass_t *)data;
744
745     MRP_LUA_ENTER;
746
747     mrp_free((void *)appclass->name);
748
749     MRP_LUA_LEAVE_NOARG;
750 }
751
752 #if 0
753 static appclass_t *check_appclass(lua_State *L, int idx)
754 {
755     return (appclass_t *)mrp_lua_check_object(L, APPCLASS_CLASS, idx);
756 }
757 #endif
758
759 static appclass_t *to_appclass(lua_State *L, int idx)
760 {
761     return (appclass_t *)mrp_lua_to_object(L, APPCLASS_CLASS, idx);
762 }
763
764
765 static int zone_create(lua_State *L)
766 {
767     zone_t *zone;
768     size_t fldnamlen;
769     const char *fldnam;
770     uint32_t id;
771     const char *name = NULL;
772     mrp_attr_t *attrs = NULL;
773
774     MRP_LUA_ENTER;
775
776     MRP_ASSERT(zone_attr_defs, "invocation prior to initialization");
777
778     if (!zone_attr_defs->attrs)
779         luaL_error(L, "attempt to create zone before defining attributes");
780
781     MRP_LUA_FOREACH_FIELD(L, 2, fldnam, fldnamlen) {
782
783         switch (field_name_to_type(fldnam, fldnamlen)) {
784
785         case NAME:
786             name = mrp_strdup(luaL_checkstring(L, -1));
787             break;
788
789         case ATTRIBUTES:
790             attrs = check_attrs(L, -1, zone_attr_defs);
791             break;
792
793         default:
794             luaL_error(L, "unexpected field '%s'", fldnam);
795             break;
796         }
797     }
798
799     if (!name)
800         luaL_error(L, "missing or wrong name field");
801     if ((id = mrp_zone_create(name,attrs)) == MRP_ZONE_ID_INVALID)
802         luaL_error(L, "failed to create zone");
803
804     free_attrs(attrs);
805
806     zone = (zone_t *)mrp_lua_create_object(L, ZONE_CLASS, name,0);
807
808     if (!zone)
809         luaL_error(L, "invalid or duplicate name '%s'", name);
810     else {
811         zone->id = id;
812         zone->name = name;
813         zone->attr_tbl = attributes_create(L, ZONE,zone, zone_attr_defs,
814                                            fetch_zone_attribute,
815                                            update_zone_attribute);
816
817         mrp_log_info("zone '%s' created", name);
818     }
819
820     MRP_LUA_LEAVE(1);
821 }
822
823 static int zone_getfield(lua_State *L)
824 {
825     zone_t  *zone = to_zone(L, 1);
826     field_t  fld  = field_check(L, 2, NULL);
827
828     MRP_LUA_ENTER;
829
830     lua_pop(L, 1);
831
832     if (!zone) {
833         /* attempt to access a zone definition field */
834         switch (fld) {
835         case ATTRIBUTES:    mrp_lua_push_object(L, zone_attr_defs);     break;
836         default:            lua_pushnil(L);                             break;
837         }
838     }
839     else {
840         /* attempt to access a zone instance field */
841         switch (fld) {
842         case ATTRIBUTES:     push_attributes(L, zone->attr_tbl);        break;
843         case ID:             lua_pushinteger(L, zone->id + 1);          break;
844         case NAME:           lua_pushstring(L, zone->name);             break;
845         default:             lua_pushnil(L);                            break;
846         }
847     }
848
849     MRP_LUA_LEAVE(1);
850 }
851
852 static int zone_setfield(lua_State *L)
853 {
854     zone_t *zone = to_zone(L, 1);
855     field_t fld  = field_check(L, 2, NULL);
856
857     MRP_LUA_ENTER;
858
859     if (zone || fld != ATTRIBUTES)
860         luaL_error(L, "zones can't be exetended after definition");
861
862     MRP_LUA_LEAVE(0);
863 }
864
865 static void zone_destroy(void *data)
866 {
867     /* zone_t *zone = (zone_t *)data; */
868
869     MRP_UNUSED(data);
870
871     MRP_LUA_ENTER;
872
873     MRP_LUA_LEAVE_NOARG;
874 }
875
876 #if 0
877 static zone_t *check_zone(lua_State *L, int idx)
878 {
879     return (zone_t *)mrp_lua_check_object(L, ZONE_CLASS, idx);
880 }
881 #endif
882
883 static zone_t *to_zone(lua_State *L, int idx)
884 {
885     return (zone_t *)mrp_lua_to_object(L, ZONE_CLASS, idx);
886 }
887
888 static int zone_attr_create(lua_State *L)
889 {
890     mrp_attr_def_t *attrs;
891     int nattr;
892
893     MRP_LUA_ENTER;
894
895     MRP_ASSERT(zone_attr_defs, "invocation prior to initialization");
896
897     if (zone_attr_defs->attrs)
898         luaL_error(L, "zone attributes already defined");
899     else {
900         attrs = check_attrdefs(L, 2, &nattr);
901
902         mrp_zone_definition_create(attrs);
903
904         zone_attr_defs->nattr = nattr;
905         zone_attr_defs->attrs = attrs;
906     }
907
908     mrp_lua_push_object(L, zone_attr_defs);
909
910     mrp_log_info("zone attributes defined");
911
912     MRP_LUA_LEAVE(1);
913 }
914
915 static int  zone_attr_getfield(lua_State *L)
916 {
917     zone_t *zone;
918     int idx;
919
920     MRP_LUA_ENTER;
921
922     MRP_ASSERT(zone_attr_defs, "invocation prior to initialization");
923
924     if (!(zone = to_zone(L, 1))) {
925         mrp_debug("zone attribute definition => attribute index");
926         if ((idx = check_attrindex(L, 2, zone_attr_defs)) < 0)
927             lua_pushnil(L);
928         else
929             lua_pushinteger(L, idx);
930     }
931     else {
932         mrp_debug("zone attribute => nil");
933         lua_pushnil(L);
934     }
935
936     MRP_LUA_LEAVE(1);
937 }
938
939 static int  zone_attr_setfield(lua_State *L)
940 {
941     MRP_UNUSED(L);
942
943     MRP_LUA_ENTER;
944
945     MRP_LUA_LEAVE(0);
946 }
947
948
949 static void zone_attr_destroy(void *data)
950 {
951     /* attr_def_t *attr = (attr_def_t *)data; */
952
953     MRP_UNUSED(data);
954
955     MRP_LUA_ENTER;
956
957     MRP_LUA_LEAVE_NOARG;
958 }
959
960 #if 0
961 static attr_def_t *check_zone_attr(lua_State *L, int idx)
962 {
963     return (attr_def_t *)mrp_lua_check_object(L, ZONE_ATTR_CLASS, idx);
964 }
965 #endif
966
967 #if 0
968 static attr_def_t *to_zone_attr(lua_State *L, int idx)
969 {
970     return (attr_def_t *)mrp_lua_to_object(L, ZONE_ATTR_CLASS, idx);
971 }
972 #endif
973
974 static bool fetch_zone_attribute(attr_t *attr, int idx, mrp_attr_t *retval)
975 {
976     mrp_zone_t *z;
977     zone_t *zone;
978
979     if (attr->owner.type == ZONE && (zone = (zone_t *)attr->owner.data)) {
980         if ((z = mrp_zone_find_by_id(zone->id))) {
981             if (mrp_zone_read_attribute(z, idx, retval))
982                 return true;
983         }
984     }
985
986     return false;
987 }
988
989 static bool update_zone_attribute(attr_t *attr, int idx, mrp_attr_t *value)
990 {
991     mrp_zone_t *z;
992     zone_t *zone;
993
994     MRP_UNUSED(idx);
995     MRP_UNUSED(value);
996
997     if (attr->owner.type == ZONE && (zone = (zone_t *)attr->owner.data)) {
998         if ((z = mrp_zone_find_by_id(zone->id))) {
999 #if 0
1000             if (mrp_zone_write_attribute(z, idx, value))
1001                 return true;
1002 #endif
1003         }
1004     }
1005
1006     return false;
1007 }
1008
1009 static int resclass_create_from_lua(lua_State *L)
1010 {
1011     resclass_t *resclass;
1012     size_t fldnamlen;
1013     const char *fldnam;
1014     int nattr = 0;
1015     uint32_t id;
1016     const char *name = NULL;
1017     mrp_attr_def_t *attrs = NULL;
1018     bool shareable = false;
1019     mrp_resource_mgr_ftbl_t *ftbl = NULL;
1020     void *mgrdata = NULL;
1021     attr_def_t *adef;
1022
1023     MRP_LUA_ENTER;
1024
1025     MRP_LUA_FOREACH_FIELD(L, 2, fldnam, fldnamlen) {
1026
1027         switch (field_name_to_type(fldnam, fldnamlen)) {
1028
1029         case NAME:
1030             name = mrp_strdup(luaL_checkstring(L, -1));
1031             break;
1032
1033         case SHAREABLE:
1034             luaL_argcheck(L, lua_isboolean(L,-1), 2, "attempt to assign "
1035                           "non-boolean value to 'shareable' field");
1036             shareable = lua_toboolean(L, -1);
1037             break;
1038
1039         case ATTRIBUTES:
1040             attrs = check_attrdefs(L, -1, &nattr);
1041             break;
1042
1043         default:
1044             luaL_error(L, "unexpected field '%s'", fldnam);
1045             break;
1046         }
1047     }
1048
1049     if (!name)
1050         luaL_error(L, "missing or wrong name field");
1051
1052     id = mrp_resource_definition_create(name, shareable, attrs,ftbl,mgrdata);
1053
1054     MRP_ASSERT(id < MRP_RESOURCE_MAX, "resource id is out of range");
1055
1056     if (id == MRP_RESOURCE_ID_INVALID)
1057         luaL_error(L, "failed to register resource class '%s'", name);
1058
1059     resclass = (resclass_t *)mrp_lua_create_object(L, RESCLASS_CLASS, name,0);
1060     adef = mrp_allocz(sizeof(attr_def_t));
1061
1062     if (!resclass)
1063         luaL_error(L, "invalid or duplicate name '%s'", name);
1064     if (!adef)
1065         luaL_error(L, "failed to allocate memory for attribute definitions");
1066
1067     resclass->id = id;
1068     resclass->name = name;
1069     resclass->attrs = attrs;
1070
1071     adef->nattr = nattr;
1072     adef->attrs = attrs;
1073
1074     resource_attr_defs[id] = adef;
1075
1076     mrp_log_info("resource class '%s' created", name);
1077
1078     MRP_LUA_LEAVE(1);
1079 }
1080
1081 static int resclass_getfield(lua_State *L)
1082 {
1083     resclass_t *rc = to_resclass(L, 1);
1084     field_t fld = field_check(L, 2, NULL);
1085     mrp_resource_def_t *rd;
1086
1087     MRP_LUA_ENTER;
1088
1089     lua_pop(L, 1);
1090
1091     if (!rc || !(rd = mrp_resource_definition_find_by_name(rc->name)))
1092         lua_pushnil(L);
1093     else {
1094         switch (fld) {
1095         case NAME:       lua_pushstring(L, rd->name);         break;
1096         case ID:         lua_pushinteger(L, rd->id + 1);      break;
1097         case SHAREABLE:  lua_pushboolean(L, rd->shareable);   break;
1098         default:         lua_pushnil(L);                      break;
1099         }
1100     }
1101
1102     MRP_LUA_LEAVE(1);
1103 }
1104
1105 static int resclass_setfield(lua_State *L)
1106 {
1107     MRP_LUA_ENTER;
1108
1109     luaL_error(L, "can't modify resource classes after definition");
1110
1111     MRP_LUA_LEAVE(1);
1112 }
1113
1114 static void resclass_destroy(void *data)
1115 {
1116     resclass_t *rc = (resclass_t *)data;
1117
1118     MRP_LUA_ENTER;
1119
1120     mrp_free((void *)rc->name);
1121     free_attrdefs(rc->attrs);
1122
1123     MRP_LUA_LEAVE_NOARG;
1124 }
1125
1126 #if 0
1127 static resclass_t *check_resclass(lua_State *L, int idx)
1128 {
1129     return (resclass_t *)mrp_lua_check_object(L, RESCLASS_CLASS, idx);
1130 }
1131 #endif
1132
1133 static resclass_t *to_resclass(lua_State *L, int idx)
1134 {
1135     return (resclass_t *)mrp_lua_to_object(L, RESCLASS_CLASS, idx);
1136 }
1137
1138 static int resource_getfield(lua_State *L)
1139 {
1140     const char *name;
1141     resource_t *res = check_resource(L, 1);
1142     field_t fld = field_check(L, 2, &name);
1143     mrp_resource_set_t *s;
1144     mrp_resource_t *r;
1145     mrp_resource_mask_t m;
1146
1147     MRP_LUA_ENTER;
1148
1149     switch (fld) {
1150
1151     case ATTRIBUTES:
1152         push_attributes(L, res->attr_tbl);
1153         break;
1154
1155     case SHARED:
1156     case SHARE:
1157         if (!(r = mrp_resource_set_find_resource(res->rsetid, res->name)))
1158             lua_pushnil(L);
1159         else
1160             lua_pushboolean(L, r->shared);
1161         break;
1162
1163     default:
1164         if (!(s = mrp_resource_set_find_by_id(res->rsetid)))
1165             m = 0;
1166         else
1167             m = ((mrp_resource_mask_t)1) << res->resid;
1168
1169         switch (fld) {
1170         case MANDATORY:
1171             lua_pushboolean(L, s->resource.mask.mandatory & m ? true : false);
1172             break;
1173         case GRANT:
1174             lua_pushboolean(L, s->resource.mask.grant & m ? true : false);
1175             break;
1176         default:
1177             lua_pushnil(L);
1178             break;
1179         }
1180
1181         break;
1182     }
1183
1184     MRP_LUA_LEAVE(1);
1185 }
1186
1187 static int resource_setfield(lua_State *L)
1188 {
1189     MRP_UNUSED(L);
1190
1191     MRP_LUA_ENTER;
1192
1193     MRP_LUA_LEAVE(0);
1194 }
1195
1196 static resource_t *check_resource(lua_State *L, int idx)
1197 {
1198     return (resource_t *)luaL_checkudata(L, idx, RESOURCE_CLASSID);
1199 }
1200
1201 static bool fetch_resource_attribute(attr_t *attr, int idx, mrp_attr_t *retval)
1202 {
1203     mrp_resource_set_t *rset;
1204     resource_t *resource;
1205     mrp_attr_t *a;
1206
1207     if (attr->owner.type == RESOURCE) {
1208         if ((resource = (resource_t *)attr->owner.data)) {
1209             if ((rset = mrp_resource_set_find_by_id(resource->rsetid))) {
1210                 a = mrp_resource_set_read_attribute(rset, resource->name,
1211                                                     idx, retval);
1212                 return a ? true : false;
1213             }
1214         }
1215     }
1216
1217     return false;
1218 }
1219
1220
1221 static bool update_resource_attribute(attr_t *attr, int idx, mrp_attr_t *value)
1222 {
1223     mrp_resource_set_t *rset;
1224     resource_t *resource;
1225     mrp_attr_t values[2];
1226     int sts;
1227
1228     MRP_UNUSED(idx);
1229
1230     if (attr->owner.type == RESOURCE) {
1231         if ((resource = (resource_t *)attr->owner.data)) {
1232             if ((rset = mrp_resource_set_find_by_id(resource->rsetid))) {
1233                 memcpy(values + 0, value, sizeof(mrp_attr_t));
1234                 memset(values + 1, 0,     sizeof(mrp_attr_t));
1235
1236                 sts = mrp_resource_set_write_attributes(rset, resource->name,
1237                                                         values);
1238                 return (sts < 0) ? false : true;
1239             }
1240         }
1241     }
1242
1243     return false;
1244 }
1245
1246 static mrp_lua_resmethod_t *resmethod_create_from_c(lua_State *L)
1247 {
1248     mrp_lua_resmethod_t *method = mrp_lua_create_object(L, RESMETHOD_CLASS,
1249                                                         "method",0);
1250
1251     if (!method)
1252         luaL_error(L, "invalid or duplicate name 'method'");
1253
1254     return method;
1255 }
1256
1257 static int resmethod_create_from_lua(lua_State *L)
1258 {
1259     MRP_LUA_ENTER;
1260
1261     luaL_error(L, "singleton object has already been created");
1262
1263     lua_pushnil(L);
1264
1265     MRP_LUA_LEAVE(1);
1266 }
1267
1268 static int resmethod_getfield(lua_State *L)
1269 {
1270     const char *name;
1271     mrp_lua_resmethod_t *method = to_resmethod(L, 1);
1272     field_t fld = field_check(L, 2, &name);
1273
1274     MRP_LUA_ENTER;
1275
1276     lua_pop(L, 1);
1277
1278     if (!method) {
1279         /* attempt to access a resclass or owners */
1280         switch (fld) {
1281         case METHOD:   mrp_lua_push_object(L, resource_methods);  break;
1282         case OWNERS:   lua_pushstring(L,name); lua_rawget(L,1);   break;
1283         default:       lua_pushnil(L);                            break;
1284         }
1285     }
1286     else {
1287         /* attempt to access a method member */
1288         if (!resource_methods)
1289             lua_pushnil(L);
1290         else {
1291             switch (fld) {
1292             case VETO:
1293             case RECALC:
1294                 lua_pushstring(L, name);
1295                 lua_rawget(L, 1);
1296                 break;
1297             default:
1298                 lua_pushnil(L);
1299                 break;
1300             }
1301         }
1302     }
1303
1304     MRP_LUA_LEAVE(1);
1305 }
1306
1307 static int resmethod_setfield(lua_State *L)
1308 {
1309     const char *name;
1310     mrp_lua_resmethod_t *method = to_resmethod(L, 1);
1311     field_t fld = field_check(L, 2, &name);
1312
1313     MRP_LUA_ENTER;
1314
1315     if (method) {
1316         switch (fld) {
1317         case VETO:
1318             lua_pushstring(L, name);
1319             lua_pushvalue(L, 3);
1320             method->veto = mrp_funcarray_check(L, -1);
1321             lua_rawset(L, 1);
1322             break;
1323         default:
1324             luaL_error(L, "invalid method '%s'", name);
1325             break;
1326         }
1327     }
1328
1329     MRP_LUA_LEAVE(0);
1330 }
1331
1332 static void resmethod_destroy(void *data)
1333 {
1334     mrp_lua_resmethod_t *method = (mrp_lua_resmethod_t *)data;
1335
1336     MRP_LUA_ENTER;
1337
1338     method->veto = NULL;
1339
1340     MRP_LUA_LEAVE_NOARG;
1341 }
1342
1343 static mrp_lua_resmethod_t *to_resmethod(lua_State *L, int idx)
1344 {
1345     return (mrp_lua_resmethod_t *)mrp_lua_to_object(L, RESMETHOD_CLASS, idx);
1346 }
1347
1348
1349 static mrp_attr_def_t *check_attrdefs(lua_State *L, int t, int *ret_len)
1350 {
1351     mrp_attr_def_t attrdefs[128];
1352     mrp_attr_def_t *ad, *end, *dup;
1353     size_t i;
1354     const char *name;
1355     const char *string;
1356     const char *access;
1357     bool value_set;
1358     int len;
1359     size_t size;
1360     size_t namlen;
1361
1362     t = (t < 0) ? lua_gettop(L) + t + 1 : t;
1363
1364     luaL_checktype(L, t, LUA_TTABLE);
1365
1366     end = (ad = attrdefs) + (MRP_ARRAY_SIZE(attrdefs) - 1);
1367
1368     MRP_LUA_FOREACH_FIELD(L, t, name, namlen) {
1369         if (!name[0])
1370             luaL_error(L, "invalid attribute definition");
1371         if (ad >= end)
1372             luaL_error(L, "too many attributes");
1373
1374         ad->name = mrp_strdup(name);
1375         ad->type = mqi_error;
1376         ad->access = MRP_RESOURCE_READ;
1377
1378         value_set = false;
1379
1380         luaL_checktype(L, -1, LUA_TTABLE);
1381
1382
1383         for (lua_pushnil(L);  lua_next(L, -2);  lua_pop(L, 1)) {
1384             if (lua_type(L, -2) != LUA_TNUMBER)
1385                 goto error;
1386
1387             i = lua_tointeger(L, -2);
1388
1389             switch (i) {
1390             case 1:
1391                 ad->type = lua_tointeger(L, -1);
1392                 break;
1393             case 2:
1394                 switch (ad->type) {
1395                 case mqi_string:
1396                     if ((string = lua_tostring(L, -1))) {
1397                         ad->value.string = mrp_strdup(string);
1398                         value_set = true;
1399                     }
1400                     break;
1401                 case mqi_integer:
1402                     ad->value.integer = lua_tointeger(L, -1);
1403                     value_set = true;
1404                     break;
1405                 case mqi_unsignd:
1406                     ad->value.integer = lua_tointeger(L, -1);
1407                     value_set = true;
1408                     break;
1409                 case mqi_floating:
1410                     ad->value.floating = lua_tonumber(L, -1);
1411                     value_set = true;
1412                     break;
1413                 default:
1414                     break;
1415                 }
1416                 break;
1417             case 3:
1418                 if (!(access = lua_tostring(L, -1)))
1419                     ad->type = mqi_error;
1420                 else {
1421                     if (!strcasecmp(access, "read"))
1422                         ad->access = MRP_RESOURCE_READ;
1423                     else if (!strcasecmp(access, "write"))
1424                         ad->access = MRP_RESOURCE_WRITE;
1425                     else if (!strcasecmp(access, "rw"))
1426                         ad->access = MRP_RESOURCE_RW;
1427                     else
1428                         ad->type = mqi_error;
1429                 }
1430                 break;
1431             default:
1432                 ad->type = mqi_error;
1433                 break;
1434             }
1435         } /* for */
1436
1437         if (!value_set ||
1438             (ad->type != mqi_string  &&
1439              ad->type != mqi_integer &&
1440              ad->type != mqi_unsignd &&
1441              ad->type != mqi_floating ))
1442             goto error;
1443
1444         ad++;
1445     } /* foreach */
1446
1447     memset(ad, 0, sizeof(mrp_attr_def_t));
1448
1449     len  = ad - attrdefs;
1450     size = sizeof(mrp_attr_def_t) * (len+1);
1451     dup  = mrp_alloc(size);
1452
1453     if (!dup)
1454         luaL_error(L, "failed to allocate %u byte memory", size);
1455
1456     memcpy(dup, attrdefs, size);
1457
1458     if (ret_len)
1459         *ret_len = len;
1460
1461     return dup;
1462
1463  error:
1464     luaL_argerror(L, t, "malformed attribute definition");
1465     return NULL;
1466 }
1467
1468
1469 static void free_attrdefs(mrp_attr_def_t *attrdefs)
1470 {
1471     mrp_attr_def_t *ad;
1472
1473     if (attrdefs) {
1474         for (ad = attrdefs;  ad->name;  ad++) {
1475             mrp_free((void *)ad->name);
1476             if (ad->type == mqi_string)
1477                 mrp_free((void *)ad->value.string);
1478         }
1479         mrp_free(attrdefs);
1480     }
1481 }
1482
1483 static int attr_name_to_index(const char *name, attr_def_t *def)
1484 {
1485     mrp_attr_def_t *attrs = def->attrs;
1486     int idx;
1487
1488     for (idx = 0;  idx < def->nattr;  idx++) {
1489         if (!strcmp(name, attrs[idx].name))
1490             return idx;
1491     }
1492
1493     return -1;
1494 }
1495
1496 static mrp_attr_t *check_attrs(lua_State *L, int t, attr_def_t *defs)
1497 {
1498     mrp_attr_t attr[128];
1499     mrp_attr_t *at, *end, *dup;
1500     const char *name;
1501     size_t namlen;
1502     size_t len;
1503     size_t size;
1504     int i;
1505
1506     t = (t < 0) ? lua_gettop(L) + t + 1 : t;
1507
1508     luaL_checktype(L, t, LUA_TTABLE);
1509
1510     end = (at = attr) + (MRP_ARRAY_SIZE(attr) - 1);
1511
1512     MRP_LUA_FOREACH_FIELD(L, t, name, namlen) {
1513         if (!name[0])
1514             luaL_error(L, "invalid attribute definition");
1515         if (at >= end)
1516             luaL_error(L, "too many attributes");
1517         if ((i = attr_name_to_index(name, defs)) < 0)
1518             luaL_error(L, "attribute %s do not exist", name);
1519
1520         at->name = mrp_strdup(name);
1521
1522         switch ((at->type = defs->attrs[i].type)) {
1523         case mqi_string:
1524             at->value.string = mrp_strdup(luaL_checkstring(L,-1));
1525             break;
1526         case mqi_integer:
1527             at->value.integer = luaL_checkinteger(L,-1);
1528             break;
1529         case mqi_unsignd:
1530             if ((at->value.integer = luaL_checkinteger(L,-1)) < 0)
1531                 luaL_error(L, "attempt to give negative value to an "
1532                            "unsigned integer");
1533             break;
1534         default:
1535             luaL_error(L, "Internal error: invalid type for attribute");
1536             break;
1537         }
1538
1539         at++;
1540     }
1541
1542     memset(at, 0, sizeof(mrp_attr_t));
1543
1544     len  = at - attr;
1545     size = sizeof(mrp_attr_t) * (len + 1);
1546
1547     dup = mrp_alloc(size);
1548     memcpy(dup, attr, size);
1549
1550     return dup;
1551 }
1552
1553
1554 static void free_attrs(mrp_attr_t *attrs)
1555 {
1556     mrp_attr_t *at;
1557
1558     if (attrs) {
1559         for (at = attrs;  at->name;  at++) {
1560             mrp_free((void *)at->name);
1561             if (at->type == mqi_string)
1562                 mrp_free((void *)at->value.string);
1563         }
1564         mrp_free(attrs);
1565     }
1566 }
1567
1568
1569 static int check_attrindex(lua_State *L, int arg, attr_def_t *def)
1570 {
1571     const char *name;
1572     int idx;
1573
1574     if (!def || !def->attrs)
1575         return -1;
1576
1577     switch (lua_type(L, arg)) {
1578     case LUA_TNUMBER:
1579         idx = lua_tointeger(L, arg);
1580         return (idx >= 0 && idx < def->nattr) ? idx : -1;
1581     case LUA_TSTRING:
1582         name = lua_tostring(L, arg);
1583         return attr_name_to_index(name, def);
1584     default:
1585         return -1;
1586     }
1587 }
1588
1589
1590 static int check_boolean(lua_State *L, int idx)
1591 {
1592     if (!lua_isboolean(L, idx))
1593         luaL_argerror(L, idx, "expected boolean");
1594     return lua_toboolean(L, idx) ? 1 : 0;
1595 }
1596
1597 static mrp_resource_order_t check_order(lua_State *L, int idx)
1598 {
1599     const char *str = luaL_checkstring(L, idx);
1600
1601     if (!strcasecmp(str, "fifo"))
1602         return MRP_RESOURCE_ORDER_FIFO;
1603
1604     if (!strcasecmp(str, "lifo"))
1605         return MRP_RESOURCE_ORDER_LIFO;
1606
1607     luaL_error(L, "invalid value for order ('fifo' or 'lifo' accepted only)");
1608
1609     return MRP_RESOURCE_ORDER_UNKNOWN;
1610 }
1611
1612 static int push_order(lua_State *L, mrp_resource_order_t order)
1613 {
1614     const char *str;
1615
1616     switch (order) {
1617     case MRP_RESOURCE_ORDER_FIFO:   str = "fifo";        break;
1618     case MRP_RESOURCE_ORDER_LIFO:   str = "lifo";        break;
1619     default:                        str = "<unknown>";   break;
1620     }
1621
1622     lua_pushstring(L, str);
1623
1624     return 1;
1625 }
1626
1627
1628 static field_t field_check(lua_State *L, int idx, const char **ret_fldnam)
1629 {
1630     const char *fldnam;
1631     size_t fldnamlen;
1632     field_t fldtyp;
1633
1634     if (!(fldnam = lua_tolstring(L, idx, &fldnamlen)))
1635         fldtyp = 0;
1636     else
1637         fldtyp = field_name_to_type(fldnam, fldnamlen);
1638
1639     if (ret_fldnam)
1640         *ret_fldnam = fldnam;
1641
1642     return fldtyp;
1643 }
1644
1645
1646 static field_t field_name_to_type(const char *name, size_t len)
1647 {
1648     switch (len) {
1649
1650     case 2:
1651         if (!strcmp(name, "id"))
1652             return ID;
1653         break;
1654
1655     case 4:
1656         if (!strcmp(name, "name"))
1657             return NAME;
1658         if (!strcmp(name, "veto"))
1659             return VETO;
1660         break;
1661
1662     case 5:
1663         if (!strcmp(name, "class"))
1664             return CLASS;
1665         if (!strcmp(name, "modal"))
1666             return MODAL;
1667         if (!strcmp(name, "share"))
1668             return SHARE;
1669         if (!strcmp(name, "grant"))
1670             return GRANT;
1671         if (!strcmp(name, "order"))
1672             return ORDER;
1673         break;
1674
1675     case 6:
1676         if (!strcmp(name, "method"))
1677             return METHOD;
1678         if (!strcmp(name, "owners"))
1679             return OWNERS;
1680         if (!strcmp(name, "shared"))
1681             return SHARED;
1682         if (!strcmp(name, "recalc"))
1683             return RECALC;
1684         break;
1685
1686     case 8:
1687         if (!strcmp(name, "priority"))
1688             return PRIORITY;
1689         break;
1690
1691     case 9:
1692         if (!strcmp(name, "mandatory"))
1693             return MANDATORY;
1694         if (!strcmp(name, "shareable"))
1695             return SHAREABLE;
1696         break;
1697
1698     case 10:
1699         if (!strcmp(name, "attributes"))
1700             return ATTRIBUTES;
1701         break;
1702
1703     default:
1704         break;
1705     }
1706
1707     return 0;
1708 }
1709
1710 static int method_recalc(lua_State *L)
1711 {
1712     const char *zone_name;
1713     mrp_zone_t *zone;
1714
1715     if (lua_type(L, 1) == LUA_TSTRING && (zone_name = lua_tostring(L, 1))) {
1716
1717         if (!(zone = mrp_zone_find_by_name(zone_name))) {
1718             luaL_error(L, "can't recalculate resources in zone '%s': "
1719                        "no such zone", zone_name);
1720         }
1721
1722         mrp_resource_owner_update_zone(zone->id, NULL, 0);
1723     }
1724
1725     return 0;
1726 }
1727
1728 /*
1729  * Local Variables:
1730  * c-basic-offset: 4
1731  * indent-tabs-mode: nil
1732  * End:
1733  *
1734  */