From 0783eedf8e723d453065acc550d13a39e5c58f95 Mon Sep 17 00:00:00 2001 From: Krisztian Litkey Date: Mon, 3 Sep 2012 09:21:31 +0300 Subject: [PATCH] resolver: script compilation, function lookup and execution, and more. Added basic script compilation, function lookup, and script execution code. Also some of the supporting scripting code (script.c, context.c) has been lifted over to core. The current (dres-like) named variable model with nested scoping probably does not make much sense any more. Needs a bit more thinking and probably a rewrite... --- src/resolver/context.c | 264 -------------------------- src/resolver/context.h | 17 -- src/resolver/murphy-resolver.pc.in | 4 +- src/resolver/parser.y | 2 +- src/resolver/resolver-types.h | 32 ++-- src/resolver/resolver.c | 42 ++-- src/resolver/resolver.h | 121 +----------- src/resolver/script.c | 165 ---------------- src/resolver/script.h | 44 ----- src/resolver/scripting/simple/call.c | 74 ++++++++ src/resolver/scripting/simple/call.h | 4 +- src/resolver/scripting/simple/simple-script.c | 20 +- src/resolver/scripting/simple/simple-script.h | 15 +- src/resolver/target.c | 22 +-- src/resolver/test-input | 8 +- src/resolver/test-input-audio | 8 +- src/resolver/test-input-video | 2 +- src/resolver/tests/parser-test.c | 72 +++++++ 18 files changed, 228 insertions(+), 688 deletions(-) delete mode 100644 src/resolver/context.c delete mode 100644 src/resolver/context.h delete mode 100644 src/resolver/script.c delete mode 100644 src/resolver/script.h diff --git a/src/resolver/context.c b/src/resolver/context.c deleted file mode 100644 index 686604b..0000000 --- a/src/resolver/context.c +++ /dev/null @@ -1,264 +0,0 @@ -#include - -#include -#include -#include -#include -#include - -#include "resolver-types.h" - - -int init_context_table(mrp_resolver_t *r) -{ - context_tbl_t *tbl; - mrp_htbl_config_t hcfg; - - tbl = mrp_allocz(sizeof(*tbl)); - tbl->frame = NULL; - - if (tbl != NULL) { - mrp_clear(&hcfg); - hcfg.comp = mrp_string_comp; - hcfg.hash = mrp_string_hash; - hcfg.free = NULL; - - tbl->names = mrp_htbl_create(&hcfg); - - if (tbl->names != NULL) { - r->ctbl = tbl; - - return 0; - } - - mrp_free(tbl); - } - - return -1; -} - - -void cleanup_context_table(mrp_resolver_t *r) -{ - if (r->ctbl != NULL) { - mrp_htbl_destroy(r->ctbl->names, FALSE); - } -} - - -static context_var_t *lookup_context_var(mrp_resolver_t *r, const char *name) -{ - context_tbl_t *tbl; - int id; - - tbl = r->ctbl; - id = (int)(ptrdiff_t)mrp_htbl_lookup(tbl->names, (void *)name); - - if (0 < id && id <= tbl->nvariable) - return tbl->variables + id - 1; - else - return NULL; -} - - -int declare_context_variable(mrp_resolver_t *r, const char *name, - mrp_script_type_t type) -{ - context_tbl_t *tbl; - context_var_t *var; - - var = lookup_context_var(r, name); - - if (var != NULL) { - if (!var->type) { - var->type = type; - return var->id; - } - - if (!type || var->type == type) - return var->id; - - errno = EEXIST; - return -1; - } - else { - size_t o, n; - - tbl = r->ctbl; - o = sizeof(*tbl->variables) * tbl->nvariable; - n = sizeof(*tbl->variables) * (tbl->nvariable + 1); - - if (!mrp_reallocz(tbl->variables, o, n)) - return -1; - - var = tbl->variables + tbl->nvariable++; - - var->name = mrp_strdup(name); - var->type = type; - var->id = tbl->nvariable; /* this is a 1-based index... */ - - if (var->name != NULL) { - if (mrp_htbl_insert(tbl->names, (void *)var->name, - (void *)(ptrdiff_t)var->id)) - return var->id; - } - - return -1; - } -} - - -int push_context_frame(mrp_resolver_t *r) -{ - context_tbl_t *tbl; - context_frame_t *f; - - tbl = r->ctbl; - f = mrp_allocz(sizeof(*f)); - - if (f != NULL) { - f->values = NULL; - f->prev = tbl->frame; - tbl->frame = f; - - mrp_debug("pushed new context frame..."); - - return 0; - } - else - return -1; -} - - -int pop_context_frame(mrp_resolver_t *r) -{ - context_tbl_t *tbl; - context_frame_t *f; - context_value_t *v, *n; - - tbl = r->ctbl; - f = tbl->frame; - - if (f != NULL) { - for (v = f->values; v != NULL; v = n) { - n = v->next; - - if (v->value.type == MRP_SCRIPT_TYPE_STRING) - mrp_free(v->value.str); - - mrp_debug("popped variable <%d>", v->id); - mrp_free(v); - } - - tbl->frame = f->prev; - mrp_free(f); - - mrp_debug("popped context frame"); - - return 0; - } - else { - errno = ENOENT; - return -1; - } -} - - -int get_context_id(mrp_resolver_t *r, const char *name) -{ - context_tbl_t *tbl; - - tbl = r->ctbl; - - return (int)(ptrdiff_t)mrp_htbl_lookup(tbl->names, (void *)name); -} - - -int get_context_value(mrp_resolver_t *r, int id, mrp_script_value_t *value) -{ - context_tbl_t *tbl; - context_frame_t *f; - context_value_t *v; - - tbl = r->ctbl; - - if (0 < id && id <= tbl->nvariable) { - for (f = tbl->frame; f != NULL; f = f->prev) { - for (v = f->values; v != NULL; v = v->next) { - if (v->id == id) { - *value = v->value; - return 0; - } - } - } - } - - value->type = MRP_SCRIPT_TYPE_INVALID; - errno = ENOENT; - - return -1; -} - - -int set_context_value(mrp_resolver_t *r, int id, mrp_script_value_t *value) -{ - context_tbl_t *tbl; - context_frame_t *f; - context_var_t *var; - context_value_t *val; - char vbuf[64]; - - tbl = r->ctbl; - - if (!(0 < id && id <= tbl->nvariable)) { - errno = ENOENT; - return -1; - } - - var = tbl->variables + id - 1; - if (var->type != MRP_SCRIPT_TYPE_INVALID && var->type != value->type) { - errno = EINVAL; - return -1; - } - - f = tbl->frame; - if (f != NULL) { - val = mrp_allocz(sizeof(*val)); - - if (val != NULL) { - val->id = id; - val->value = *value; - - if (val->value.type != MRP_SCRIPT_TYPE_STRING || - ((val->value.str = mrp_strdup(val->value.str)) != NULL)) { - val->next = f->values; - f->values = val; - - mrp_debug("set &%s=%s", var->name, - mrp_print_value(vbuf, sizeof(vbuf), value)); - - return 0; - } - else - mrp_free(val); - } - } - else - errno = ENOSPC; - - return -1; -} - - -int set_context_values(mrp_resolver_t *r, int *ids, mrp_script_value_t *values, - int nid) -{ - int i; - - for (i = 0; i < nid; i++) { - if (set_context_value(r, ids[i], values + i) < 0) - return -1; - } - - return 0; -} diff --git a/src/resolver/context.h b/src/resolver/context.h deleted file mode 100644 index 6261a0b..0000000 --- a/src/resolver/context.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef __MRP_RESOLVER_CONTEXT_H__ -#define __MRP_RESOLVER_CONTEXT_H__ - -int init_context_table(mrp_resolver_t *r); -void cleanup_context_table(mrp_resolver_t *r); -int declare_context_variable(mrp_resolver_t *r, const char *name, - mrp_script_type_t type); - -int push_context_frame(mrp_resolver_t *r); -int pop_context_frame(mrp_resolver_t *r); -int get_context_id(mrp_resolver_t *r, const char *name); -int get_context_value(mrp_resolver_t *r, int id, mrp_script_value_t *value); -int set_context_values(mrp_resolver_t *r, int *ids, mrp_script_value_t *values, - int nid); -int set_context_value(mrp_resolver_t *r, int id, mrp_script_value_t *value); - -#endif /* __MRP_RESOLVER_CONTEXT_H__ */ diff --git a/src/resolver/murphy-resolver.pc.in b/src/resolver/murphy-resolver.pc.in index dbc83bc..cec8e79 100644 --- a/src/resolver/murphy-resolver.pc.in +++ b/src/resolver/murphy-resolver.pc.in @@ -5,7 +5,7 @@ includedir=@includedir@ Name: murphy-resolver Description: Murphy policy framework, resolver library. -Requires: murphy-common @PACKAGE_VERSION@ +Requires: murphy-core murphy-common @PACKAGE_VERSION@ Version: @PACKAGE_VERSION@ -Libs: -L${libdir} -lmurphy-common +Libs: -L${libdir} -lmurphy-core -lmurphy-common Cflags: -I${includedir} diff --git a/src/resolver/parser.y b/src/resolver/parser.y index 0901312..b3c5dd6 100644 --- a/src/resolver/parser.y +++ b/src/resolver/parser.y @@ -131,7 +131,7 @@ optional_script: $$.source = NULL; } | KEY_UPDATE_SCRIPT script_source KEY_END_SCRIPT { - $$.type = "default"; + $$.type = "simple"; /* "default"; */ $$.source = $2.value; } ; diff --git a/src/resolver/resolver-types.h b/src/resolver/resolver-types.h index d8c1380..a1e90da 100644 --- a/src/resolver/resolver-types.h +++ b/src/resolver/resolver-types.h @@ -4,7 +4,7 @@ #include #include -#include +#include typedef struct target_s target_t; /* opaque type for resolver targets */ typedef struct fact_s fact_t; /* opaque type for tracked facts */ @@ -13,13 +13,13 @@ typedef struct fact_s fact_t; /* opaque type for tracked facts */ * a resolver target */ struct target_s { - char *name; /* target name */ - uint32_t stamp; /* touch-stamp */ - char **depends; /* dependencies stated in the input */ - int ndepend; /* number of dependencies */ - int *update_facts; /* facts to check when updating */ - int *update_targets; /* targets to check when updating */ - mrp_script_t *script; /* update script if any, or NULL */ + char *name; /* target name */ + uint32_t stamp; /* touch-stamp */ + char **depends; /* dependencies stated in the input */ + int ndepend; /* number of dependencies */ + int *update_facts; /* facts to check when updating */ + int *update_targets; /* targets to check when updating */ + mrp_scriptlet_t *script; /* update script if any, or NULL */ }; @@ -59,21 +59,21 @@ struct context_frame_s { }; -typedef struct { +struct mrp_context_tbl_s { context_var_t *variables; /* known/declared context variables */ int nvariable; /* number of variables */ mrp_htbl_t *names; /* variable name to id mapping */ context_frame_t *frame; /* active frame */ -} context_tbl_t; +}; struct mrp_resolver_s { - target_t *targets; /* targets defined in the ruleset */ - int ntarget; /* number of targets */ - fact_t *facts; /* facts tracked as dependencies */ - int nfact; /* number of tracked facts */ - uint32_t stamp; /* update stamp */ - context_tbl_t *ctbl; /* context variable table */ + target_t *targets; /* targets defined in the ruleset */ + int ntarget; /* number of targets */ + fact_t *facts; /* facts tracked as dependencies */ + int nfact; /* number of tracked facts */ + uint32_t stamp; /* update stamp */ + mrp_context_tbl_t *ctbl; /* context variable table */ }; diff --git a/src/resolver/resolver.c b/src/resolver/resolver.c index 1647b10..30d1395 100644 --- a/src/resolver/resolver.c +++ b/src/resolver/resolver.c @@ -10,7 +10,6 @@ #include "target.h" #include "target-sorter.h" #include "fact.h" -#include "context.h" #include "resolver.h" mrp_resolver_t *mrp_resolver_parse(const char *path) @@ -26,7 +25,7 @@ mrp_resolver_t *mrp_resolver_parse(const char *path) if (create_targets(r, &parser) == 0 && sort_targets(r) == 0 && compile_target_scripts(r) == 0 && - init_context_table(r) == 0) { + (r->ctbl = mrp_create_context_table()) != NULL) { parser_cleanup(&parser); return r; } @@ -45,7 +44,7 @@ mrp_resolver_t *mrp_resolver_parse(const char *path) void mrp_resolver_cleanup(mrp_resolver_t *r) { if (r != NULL) { - cleanup_context_table(r); + mrp_destroy_context_table(r->ctbl); destroy_targets(r); destroy_facts(r); @@ -61,10 +60,10 @@ int mrp_resolver_update_targetl(mrp_resolver_t *r, const char *target, ...) va_list ap; int id, status; - if (push_context_frame(r) == 0) { + if (mrp_push_context_frame(r->ctbl) == 0) { va_start(ap, target); while ((name = va_arg(ap, char *)) != NULL) { - id = get_context_id(r, name); + id = mrp_get_context_id(r->ctbl, name); if (id > 0) { value.type = va_arg(ap, int); @@ -94,7 +93,7 @@ int mrp_resolver_update_targetl(mrp_resolver_t *r, const char *target, ...) } #undef HANDLE_TYPE - if (set_context_value(r, id, &value) < 0) { + if (mrp_set_context_value(r->ctbl, id, &value) < 0) { status = -1; goto pop_frame; } @@ -109,7 +108,7 @@ int mrp_resolver_update_targetl(mrp_resolver_t *r, const char *target, ...) status = update_target_by_name(r, target); pop_frame: - pop_context_frame(r); + mrp_pop_context_frame(r->ctbl); va_end(ap); } else @@ -128,14 +127,14 @@ int mrp_resolver_update_targetv(mrp_resolver_t *r, const char *target, mrp_script_value_t *value; int id, i, status; - if (push_context_frame(r) == 0) { + if (mrp_push_context_frame(r->ctbl) == 0) { for (i = 0; i < nvariable; i++) { name = variables[i]; value = values + i; - id = get_context_id(r, name); + id = mrp_get_context_id(r->ctbl, name); if (id > 0) { - if (set_context_value(r, id, value) < 0) { + if (mrp_set_context_value(r->ctbl, id, value) < 0) { status = -1; goto pop_frame; } @@ -150,7 +149,7 @@ int mrp_resolver_update_targetv(mrp_resolver_t *r, const char *target, status = update_target_by_name(r, target); pop_frame: - pop_context_frame(r); + mrp_pop_context_frame(r->ctbl); } else status = -1; @@ -180,42 +179,31 @@ void mrp_resolver_dump_facts(mrp_resolver_t *r, FILE *fp) int mrp_resolver_register_interpreter(mrp_interpreter_t *i) { - return register_interpreter(i); + return mrp_register_interpreter(i); } int mrp_resolver_unregister_interpreter(const char *name) { - mrp_interpreter_t *i; - - i = lookup_interpreter(name); - - if (i != NULL) { - unregister_interpreter(i); - - return TRUE; - } - else - return FALSE; - + return mrp_unregister_interpreter(name); } int mrp_resolver_declare_variable(mrp_resolver_t *r, const char *name, mrp_script_type_t type) { - return declare_context_variable(r, name, type); + return mrp_declare_context_variable(r->ctbl, name, type); } int mrp_resolver_get_value(mrp_resolver_t *r, int id, mrp_script_value_t *v) { - return get_context_value(r, id, v); + return mrp_get_context_value(r->ctbl, id, v); } int mrp_resolver_get_value_by_name(mrp_resolver_t *r, const char *name, mrp_script_value_t *v) { - return get_context_value(r, get_context_id(r, name), v); + return mrp_get_context_value(r->ctbl, mrp_get_context_id(r->ctbl, name), v); } diff --git a/src/resolver/resolver.h b/src/resolver/resolver.h index 0c5c5a4..77a1968 100644 --- a/src/resolver/resolver.h +++ b/src/resolver/resolver.h @@ -5,127 +5,11 @@ #include #include +#include MRP_CDECL_BEGIN -typedef struct mrp_resolver_s mrp_resolver_t; -typedef struct mrp_interpreter_s mrp_interpreter_t; -typedef struct mrp_script_s mrp_script_t; - - -/* - * data types to pass to/from scripts - */ - -#define A(t) MRP_SCRIPT_TYPE_##t -typedef enum { - MRP_SCRIPT_TYPE_UNKNOWN = 0x00, - MRP_SCRIPT_TYPE_INVALID = 0x00, /* defined invalid type */ - MRP_SCRIPT_TYPE_STRING = 0x01, /* string */ - MRP_SCRIPT_TYPE_BOOL = 0x02, /* boolean */ - MRP_SCRIPT_TYPE_UINT8 = 0x03, /* signed 8-bit integer */ - MRP_SCRIPT_TYPE_SINT8 = 0x04, /* unsigned 8-bit integer */ - MRP_SCRIPT_TYPE_INT8 = A(SINT8), /* alias for SINT8 */ - MRP_SCRIPT_TYPE_UINT16 = 0x05, /* unsigned 16-bit integer */ - MRP_SCRIPT_TYPE_SINT16 = 0x06, /* signed 16-bit integer */ - MRP_SCRIPT_TYPE_INT16 = A(SINT16), /* alias for SINT16 */ - MRP_SCRIPT_TYPE_UINT32 = 0x07, /* unsigned 32-bit integer */ - MRP_SCRIPT_TYPE_SINT32 = 0x08, /* signed 32-bit integer */ - MRP_SCRIPT_TYPE_INT32 = A(SINT32), /* alias for SINT32 */ - MRP_SCRIPT_TYPE_UINT64 = 0x09, /* unsigned 64-bit integer */ - MRP_SCRIPT_TYPE_SINT64 = 0x0a, /* signed 64-bit integer */ - MRP_SCRIPT_TYPE_INT64 = A(SINT64), /* alias for SINT64 */ - MRP_SCRIPT_TYPE_DOUBLE = 0x0b, /* double-prec. floating point */ - MRP_SCRIPT_TYPE_ARRAY = 0x80, /* type/marker for arrays */ -} mrp_script_type_t; - -#define MRP_SCRIPT_VALUE_UNION union { \ - char *str; \ - bool bln; \ - uint8_t u8; \ - int8_t s8; \ - uint16_t u16; \ - int16_t s16; \ - uint32_t u32; \ - int32_t s32; \ - uint64_t u64; \ - int64_t s64; \ - double dbl; \ - } - -typedef MRP_SCRIPT_VALUE_UNION mrp_script_value_u; - -typedef struct { - mrp_script_type_t type; - MRP_SCRIPT_VALUE_UNION; -} mrp_script_value_t; - -#define mrp_script_typed_value_t mrp_script_value_t - -#define MRP_SCRIPT_STRING(s) MRP_SCRIPT_TYPE_STRING, s -#define MRP_SCRIPT_BOOL(b) MRP_SCRIPT_TYPE_BOOL , b -#define MRP_SCRIPT_UINT8(u) MRP_SCRIPT_TYPE_UINT8 , u -#define MRP_SCRIPT_SINT8(s) MRP_SCRIPT_TYPE_SINT8 , s -#define MRP_SCRIPT_UINT16(u) MRP_SCRIPT_TYPE_UINT16, u -#define MRP_SCRIPT_SINT16(s) MRP_SCRIPT_TYPE_SINT16, s -#define MRP_SCRIPT_UINT32(u) MRP_SCRIPT_TYPE_UINT32, u -#define MRP_SCRIPT_SINT32(s) MRP_SCRIPT_TYPE_SINT32, s -#define MRP_SCRIPT_UINT64(u) MRP_SCRIPT_TYPE_UINT64, u -#define MRP_SCRIPT_DOUBLE(d) MRP_SCRIPT_TYPE_DOUBLE, d - -/* - * a script interpreter - */ - -struct mrp_interpreter_s { - mrp_list_hook_t hook; /* to list of interpreters */ - const char *name; /* interpreter identifier */ - void *data; /* opaque global interpreter data */ - /* interpreter operations */ - int (*compile)(mrp_script_t *script); - int (*execute)(mrp_script_t *script); - void (*cleanup)(mrp_script_t *script); -#if 0 - void (*print)(char *buf, size_t size, mrp_script_t *script); -#endif -}; - -/** Macro to automatically register an interpreter on startup. */ -#define MRP_REGISTER_INTERPRETER(_type, _compile, _execute, _cleanup) \ - static void auto_register_interpreter(void) \ - __attribute__((constructor)); \ - \ - static void auto_register_interpreter(void) { \ - static mrp_interpreter_t interpreter = { \ - .name = _type, \ - .compile = _compile, \ - .execute = _execute, \ - .cleanup = _cleanup \ - }; \ - \ - mrp_list_init(&interpreter.hook); \ - \ - if (!mrp_resolver_register_interpreter(&interpreter)) \ - mrp_log_error("Failed to register interpreter '%s'.", \ - _type); \ - else \ - mrp_log_info("Registered interpreter '%s'.", _type); \ - } \ - struct mrp_allow_trailing_semicolon - - - -/* - * (execution context for) a script - */ - -struct mrp_script_s { - char *source; /* script in source form */ - mrp_interpreter_t *interpreter; /* interpreter for this */ - void *data; /* interpreter data */ - void *compiled; /* script in compiled form */ -}; - +typedef struct mrp_resolver_s mrp_resolver_t; /** Parse the given resolver input file into a resolver context. */ mrp_resolver_t *mrp_resolver_parse(const char *path); @@ -174,7 +58,6 @@ int mrp_resolver_register_interpreter(mrp_interpreter_t *i); /** Unregister a script interpreter. */ int mrp_resolver_unregister_interpreter(const char *name); - MRP_CDECL_END #endif /* __MURPHY_RESOLVER_H__ */ diff --git a/src/resolver/script.c b/src/resolver/script.c deleted file mode 100644 index dc2be7e..0000000 --- a/src/resolver/script.c +++ /dev/null @@ -1,165 +0,0 @@ -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "resolver.h" - - -/* - * With the low expected number of interpreters it is probably - * much faster to keep interpreters in a linked list than to - * hash them in... - */ -static MRP_LIST_HOOK(interpreters); /* registered interpreters */ -static const char *default_interpreter = "simple"; /* the default interpreter */ - - -void set_default_interpreter(const char *type) -{ - default_interpreter = type; -} - - -int register_interpreter(mrp_interpreter_t *i) -{ - mrp_list_append(&interpreters, &i->hook); - - return TRUE; -} - - -void unregister_interpreter(mrp_interpreter_t *i) -{ - mrp_list_delete(&i->hook); -} - - -mrp_interpreter_t *lookup_interpreter(const char *name) -{ - mrp_list_hook_t *p, *n; - mrp_interpreter_t *i; - - if (!strcmp(name, "default")) - name = default_interpreter; - - mrp_list_foreach(&interpreters, p, n) { - i = mrp_list_entry(p, typeof(*i), hook); - if (!strcmp(i->name, name)) - return i; - } - - return NULL; -} - - -mrp_script_t *create_script(char *type, const char *source) -{ - mrp_interpreter_t *i; - mrp_script_t *s; - - s = NULL; - i = lookup_interpreter(type); - - if (i != NULL) { - s = mrp_allocz(sizeof(*s)); - - if (s != NULL) { - s->interpreter = i; - s->source = mrp_strdup(source); - - if (s->source != NULL) - return s; - else { - mrp_free(s); - s = NULL; - } - } - } - else - errno = ENOENT; - - return NULL; -} - - -void destroy_script(mrp_script_t *script) -{ - if (script != NULL) { - script->interpreter->cleanup(script); - - mrp_free(script->source); - mrp_free(script); - } -} - - -int compile_script(mrp_script_t *s) -{ - if (s != NULL) - return s->interpreter->compile(s); - else - return 0; -} - - -int execute_script(mrp_resolver_t *r, mrp_script_t *s) -{ - MRP_UNUSED(r); - - if (s != NULL) - return s->interpreter->execute(s); - else - return TRUE; -} - - -int eval_script(mrp_resolver_t *r, char *script) -{ - MRP_UNUSED(r); - - if (script == NULL) - return TRUE; - else { - printf("----- running update script -----\n"); - printf("%s", script); - printf("---------------------------------\n"); - - return TRUE; - } -} - - -char *mrp_print_value(char *buf, size_t size, mrp_script_value_t *value) -{ -#define HANDLE_TYPE(type, fmt, val) \ - case MRP_SCRIPT_TYPE_##type: \ - snprintf(buf, size, fmt, val); \ - break - - switch (value->type) { - HANDLE_TYPE(UNKNOWN, "%s" , ""); - HANDLE_TYPE(STRING , "'%s'" , value->str); - HANDLE_TYPE(BOOL , "%s" , value->bln ? "true" : "false"); - HANDLE_TYPE(UINT8 , "%uU8" , value->u8); - HANDLE_TYPE(SINT8 , "%dS8" , value->s8); - HANDLE_TYPE(UINT16 , "%uU16" , value->u16); - HANDLE_TYPE(SINT16 , "%dS16" , value->s16); - HANDLE_TYPE(UINT32 , "%uU32" , value->u32); - HANDLE_TYPE(SINT32 , "%dS32" , value->s32); - HANDLE_TYPE(UINT64 , "%lluU64", (unsigned long long)value->u64); - HANDLE_TYPE(SINT64 , "%lldS64", ( signed long long)value->s64); - HANDLE_TYPE(DOUBLE , "%f" , value->dbl); - default: - snprintf(buf, size, "", value->type); - } - -#undef HANDLE_TYPE - - return buf; -} diff --git a/src/resolver/script.h b/src/resolver/script.h deleted file mode 100644 index 4163357..0000000 --- a/src/resolver/script.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef __MRP_RESOLVER_SCRIPT_H__ -#define __MRP_RESOLVER_SCRIPT_H__ - -#include -#include - -#include -#include - -MRP_CDECL_BEGIN - -#include "resolver.h" - - -/** Set the default interpreter type. */ -void set_default_interpreter(const char *type); - -/** Register the given script interpreter. */ -int register_interpreter(mrp_interpreter_t *i); - -/** Unregister the given interpreter. */ -void unregister_interpreter(mrp_interpreter_t *i); - -/** Lookup an interpreter by name. */ -mrp_interpreter_t *lookup_interpreter(const char *name); - -/** Create (prepare) a script of the given type with the given source. */ -mrp_script_t *create_script(char *type, const char *source); - -/** Destroy the given script freeing all associated resources. */ -void destroy_script(mrp_script_t *script); - -/** Compile the given script, preparing it for execution. */ -int compile_script(mrp_script_t *script); - -/** Execute the given script. */ -int execute_script(mrp_resolver_t *r, mrp_script_t *s); - -/** Dummy routine that just prints the script to be evaluated. */ -int eval_script(mrp_resolver_t *r, char *script); - -MRP_CDECL_END - -#endif /* __MRP_RESOLVER_SCRIPT_H__ */ diff --git a/src/resolver/scripting/simple/call.c b/src/resolver/scripting/simple/call.c index acf759d..b8060ff 100644 --- a/src/resolver/scripting/simple/call.c +++ b/src/resolver/scripting/simple/call.c @@ -1,4 +1,8 @@ +#include + #include +#include /* XXX TODO, needed for method.h */ +#include #include "call.h" @@ -106,6 +110,76 @@ void destroy_arguments(arg_t *args, int narg) } +static int resolve_function(function_call_t *c) +{ + mrp_plugin_t *plugin; + int (*script_ptr)(mrp_plugin_t *plugin, const char *name, + mrp_script_env_t *env); + + if (mrp_import_method(c->name, NULL, NULL, &script_ptr, &plugin) < 0) + return FALSE; + else { + c->script_ptr = script_ptr; + c->plugin = plugin; + + return TRUE; + } +} + +int execute_call(function_call_t *c, mrp_context_tbl_t *tbl) +{ + mrp_script_env_t env; + mrp_script_value_t args[c->narg]; + arg_t *a; + int narg, n, status; + + if (MRP_UNLIKELY(c->script_ptr == NULL)) { + if (!resolve_function(c)) + return -ENOENT; + } + + mrp_push_context_frame(tbl); + + for (n = narg = 0, a = c->args; n < (int)MRP_ARRAY_SIZE(args); n++, a++) { + switch (a->type) { + case ARG_CONST_VALUE: + args[narg++] = a->cst.value; + break; + case ARG_CONTEXT_VAR: + if (a->val.id <= 0) + a->val.id = mrp_get_context_id(tbl, a->val.name); + if (mrp_get_context_value(tbl, a->val.id, args + narg) < 0) { + status = -ENOENT; + goto pop_frame; + } + narg++; + break; + case ARG_CONTEXT_SET: + if (a->set.id <= 0) + a->set.id = mrp_get_context_id(tbl, a->set.name); + if (mrp_set_context_value(tbl, a->set.id, &a->set.value) < 0) { + status = -errno; + goto pop_frame; + } + default: + status = -EINVAL; + goto pop_frame; + } + } + + env.args = args; + env.narg = narg; + env.ctbl = tbl; + + status = c->script_ptr(c->plugin, c->name, &env); + + pop_frame: + mrp_pop_context_frame(tbl); + + return status; +} + + static void dump_arg(FILE *fp, arg_t *arg) { mrp_script_value_t *val; diff --git a/src/resolver/scripting/simple/call.h b/src/resolver/scripting/simple/call.h index e921a60..634dfb5 100644 --- a/src/resolver/scripting/simple/call.h +++ b/src/resolver/scripting/simple/call.h @@ -1,7 +1,7 @@ #ifndef __MURPHY_SIMPLE_SCRIPT_CALL_H__ #define __MURPHY_SIMPLE_SCRIPT_CALL_H__ -#include +#include #include "simple-script.h" @@ -14,6 +14,6 @@ int set_context_value_arg(arg_t *arg, char *name); int set_context_set_arg(arg_t *arg, char *name, mrp_script_value_t *value); void destroy_arguments(arg_t *args, int narg); - +int execute_call(function_call_t *c, mrp_context_tbl_t *tbl); #endif /* __MURPHY_SIMPLE_SCRIPT_CALL_H__ */ diff --git a/src/resolver/scripting/simple/simple-script.c b/src/resolver/scripting/simple/simple-script.c index 3830ea9..0d40d93 100644 --- a/src/resolver/scripting/simple/simple-script.c +++ b/src/resolver/scripting/simple/simple-script.c @@ -23,7 +23,7 @@ static void simple_dump(FILE *fp, simple_script_t *ss) } -static int simple_compile(mrp_script_t *script) +static int simple_compile(mrp_scriptlet_t *script) { yy_smpl_parser_t parser; simple_script_t *ss; @@ -47,21 +47,29 @@ static int simple_compile(mrp_script_t *script) } -static int simple_execute(mrp_script_t *s) +static int simple_execute(mrp_scriptlet_t *s, mrp_context_tbl_t *tbl) { simple_script_t *ss = s->compiled; + mrp_list_hook_t *p, *n; + function_call_t *c; + int status; if (ss != NULL) { - printf("----- should execute simple script -----\n"); - simple_dump(stdout, ss); - printf("----------------------------------------\n"); + mrp_list_foreach(&ss->statements, p, n) { + c = mrp_list_entry(p, typeof(*c), hook); + + status = execute_call(c, tbl); + + if (status <= 0) + return status; + } } return TRUE; } -static void simple_cleanup(mrp_script_t *s) +static void simple_cleanup(mrp_scriptlet_t *s) { MRP_UNUSED(s); diff --git a/src/resolver/scripting/simple/simple-script.h b/src/resolver/scripting/simple/simple-script.h index 1180172..25610aa 100644 --- a/src/resolver/scripting/simple/simple-script.h +++ b/src/resolver/scripting/simple/simple-script.h @@ -1,7 +1,8 @@ #ifndef __MURPHY_SIMPLE_SCRIPT_H__ #define __MURPHY_SIMPLE_SCRIPT_H__ -#include +#include +#include typedef struct { mrp_list_hook_t statements; /* list of (call) statements */ @@ -30,10 +31,10 @@ typedef struct { typedef struct { - arg_type_t type; /* ARG_CONTEXT_SET */ - char *name; /* name of variable */ - int id; /* variable id */ - mrp_script_typed_value_t value; /* value to set to */ + arg_type_t type; /* ARG_CONTEXT_SET */ + char *name; /* name of variable */ + int id; /* variable id */ + mrp_script_value_t value; /* value to set to */ } ctx_set_arg_t; @@ -50,6 +51,10 @@ typedef struct { arg_t *args; /* arguments to pass */ int narg; /* number of arguments */ mrp_list_hook_t hook; /* to list of statements */ + + int (*script_ptr)(mrp_plugin_t *plugin, const char *name, + mrp_script_env_t *env); + mrp_plugin_t *plugin; } function_call_t; diff --git a/src/resolver/target.c b/src/resolver/target.c index aa7f8b8..598305f 100644 --- a/src/resolver/target.c +++ b/src/resolver/target.c @@ -5,12 +5,13 @@ #include #include +#include + #include "resolver-types.h" #include "resolver.h" #include "db.h" #include "fact.h" #include "target.h" -#include "script.h" int create_targets(mrp_resolver_t *r, yy_res_parser_t *parser) @@ -39,12 +40,12 @@ int create_targets(mrp_resolver_t *r, yy_res_parser_t *parser) pt->ndepend = 0; if (pt->script_source != NULL) { - t->script = create_script(pt->script_type, pt->script_source); + t->script = mrp_create_script(pt->script_type, pt->script_source); if (t->script == NULL) { if (errno == ENOENT) mrp_log_error("Unsupported script type '%s' used in " - "target '%s'.", t->name, pt->script_type); + "target '%s'.", pt->script_type, t->name); else mrp_log_error("Failed to set up script for target '%s'.", t->name); @@ -78,7 +79,7 @@ void destroy_targets(mrp_resolver_t *r) mrp_free(t->depends[j]); mrp_free(t->depends); - destroy_script(t->script); + mrp_destroy_script(t->script); } mrp_free(r->targets); @@ -91,12 +92,9 @@ int compile_target_scripts(mrp_resolver_t *r) int i; for (i = 0, t = r->targets; i < r->ntarget; i++, t++) { - if (t->script != NULL) { - if (compile_script(t->script) < 0) { - mrp_log_error("Failed to compile script for target '%s'.", - t->name); - return -1; - } + if (mrp_compile_script(t->script) < 0) { + mrp_log_error("Failed to compile script for target '%s'.", t->name); + return -1; } } @@ -223,7 +221,7 @@ static int update_target(mrp_resolver_t *r, target_t *t) /* hmm... is this really needed? */ if (older_than_facts(r, dep) || older_than_targets(r, dep)) { needs_update = TRUE; - status = execute_script(r, dep->script); + status = mrp_execute_script(dep->script, r->ctbl); if (status <= 0) break; @@ -233,7 +231,7 @@ static int update_target(mrp_resolver_t *r, target_t *t) } if (needs_update && status > 0) { - status = execute_script(r, t->script); + status = mrp_execute_script(t->script, r->ctbl); if (status > 0) t->stamp = r->stamp; diff --git a/src/resolver/test-input b/src/resolver/test-input index 51ec044..302f650 100644 --- a/src/resolver/test-input +++ b/src/resolver/test-input @@ -2,10 +2,12 @@ target all depends on video_route audio_route \ audio_volume audio_cork audio_mute \ $vibra $backlight +# signal_enforcement_points(&target='all', 'audio', 'video', 1, -2, +3) +# foobar(&just='a test', +1, -2, 3.141, -1U8, 0xffffffffffU64) +# hex(-0xf) update script - signal_enforcement_points(&target='all', 'audio', 'video', 1, -2, +3) - foobar(&just='a test', +1, -2, 3.141, -1U8, 0xffffffffffU64) - hex(-0xf) + echo('Running actions for target "all"...') + echo('foo', 'bar', 'foobar...', 1, 2, 3.141, -9.81) end script include "/u/src/work/murphy/src/resolver/test-input-video" diff --git a/src/resolver/test-input-audio b/src/resolver/test-input-audio index 92824d4..56a7d56 100644 --- a/src/resolver/test-input-audio +++ b/src/resolver/test-input-audio @@ -2,23 +2,23 @@ target audio_route depends on $audio_device_selectable $audio_output_configuration \ $resource_owner update script - update_audio_routing() + echo('Running audio_route actions...', 3, 2, 1, 0) end script target audio_volume depends on $resource_owner $resource_set update script - update_audio_volume() + echo('Running actions for target "audio_volume"...') end script target audio_cork depends on $resource_owner update script - cork_audio_stream('telephony') + echo('Running actions for target "audio_cork"...') end script target audio_mute depends on $mute update script - mute_audio_input_devices() + echo('Running actions for target "audio_mute"...') end script diff --git a/src/resolver/test-input-video b/src/resolver/test-input-video index df40fb8..9bc3027 100644 --- a/src/resolver/test-input-video +++ b/src/resolver/test-input-video @@ -1,5 +1,5 @@ target video_route depends on $video_device_selectable $gconf update script - prolog('set_video_routes') + echo('Running actions for target "video_route"...') end script diff --git a/src/resolver/tests/parser-test.c b/src/resolver/tests/parser-test.c index 561d2ae..5171d73 100644 --- a/src/resolver/tests/parser-test.c +++ b/src/resolver/tests/parser-test.c @@ -5,6 +5,8 @@ #include #include +#include /* XXX TODO, needed before method.h */ +#include #include @@ -122,6 +124,47 @@ int parse_cmdline(context_t *ctx, int argc, char **argv) } +static int echo_function(mrp_plugin_t *plugin, const char *name, + mrp_script_env_t *env) +{ + mrp_script_value_t *arg; + int i; + char buf[512], *t; + + MRP_UNUSED(plugin); + MRP_UNUSED(name); + + for (i = 0, arg = env->args, t = ""; i < env->narg; i++, arg++, t=" ") + printf("%s%s", t, mrp_print_value(buf, sizeof(buf), arg)); + + printf("\n"); + + return TRUE; +} + + +void export_test_functions(void) +{ + mrp_method_descr_t methods[] = { + { + .name = "echo", + .signature = NULL , + .native_ptr = NULL , + .script_ptr = echo_function, + .plugin = NULL + }, + { NULL, NULL, NULL, NULL, NULL } + }, *m; + + for (m = methods; m->name != NULL; m++) { + if (mrp_export_method(m) < 0) { + mrp_log_error("Failed to export function '%s'.", m->name); + exit(1); + } + } +} + + int main(int argc, char *argv[]) { context_t c; @@ -142,6 +185,8 @@ int main(int argc, char *argv[]) if (c.r == NULL) mrp_log_error("Failed to parse input file '%s'.", c.file); else { + export_test_functions(); + mrp_log_info("Input file '%s' parsed successfully.", c.file); mrp_resolver_dump_targets(c.r, stdout); mrp_resolver_dump_facts(c.r, stdout); @@ -168,6 +213,33 @@ int main(int argc, char *argv[]) printf("Resolved OK.\n"); else printf("Resolving FAILED.\n"); + +#if 0 + { + int nvariable = 6; + const char *variables[nvariable]; + mrp_script_value_t values[nvariable]; + + variables[0] = "var1"; + values[0] = MRP_SCRIPT_VALUE_STRING("foo"); + variables[1] = "var2"; + values[1] = MRP_SCRIPT_VALUE_STRING("bar"); + variables[2] = "var3"; + values[2] = MRP_SCRIPT_VALUE_BOOL(TRUE); + variables[3] = "var4"; + values[3] = MRP_SCRIPT_VALUE_SINT32(-3); + variables[4] = "var5"; + values[4] = MRP_SCRIPT_VALUE_UINT32(369); + variables[5] = "var6"; + values[5] = MRP_SCRIPT_VALUE_SINT32(-3141); + + if (mrp_resolver_update_targetv(c.r, argv[i], variables, values, + nvariable) > 0) + printf("Resolved OK.\n"); + else + printf("Resolving FAILED.\n"); + } +#endif } } -- 2.7.4