6b85ebf663c057bf896a66f243a183ebee28beb7
[profile/ivi/murphy.git] / src / core / scripting.h
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 #ifndef __MURPHY_CORE_SCRIPTING_H__
31 #define __MURPHY_CORE_SCRIPTING_H__
32
33 #include <stdio.h>
34 #include <stdbool.h>
35
36 #include <murphy/common/macros.h>
37 #include <murphy/common/list.h>
38 #include <murphy/common/log.h>
39
40
41 MRP_CDECL_BEGIN
42
43 typedef struct mrp_interpreter_s  mrp_interpreter_t;
44 typedef struct mrp_scriptlet_s    mrp_scriptlet_t;
45 typedef struct mrp_context_tbl_s  mrp_context_tbl_t;
46 typedef struct mrp_script_value_s mrp_script_value_t;
47
48
49 /*
50  * call/execution context passed to exported boilerplate methods
51  *
52  * This context is used to pass positional and keyword arguments
53  * when calling exported scripting boilerplate methods. For instance
54  * the primitive resolver scriptlet interpreter uses this to execute
55  * function calls.
56  */
57
58 typedef struct {
59     mrp_script_value_t *args;            /* positional arguments */
60     int                 narg;            /* number of arguments */
61     mrp_context_tbl_t  *ctbl;            /* named arguments */
62 } mrp_script_env_t;
63
64
65 /*
66  * supported data types to pass to/from scripts (XXX TODO: arrays...)
67  */
68
69 #define A(t) MRP_SCRIPT_TYPE_##t
70 typedef enum {
71     MRP_SCRIPT_TYPE_UNKNOWN = 0x00,
72     MRP_SCRIPT_TYPE_INVALID = 0x00,      /* defined invalid type */
73     MRP_SCRIPT_TYPE_STRING  = 0x01,      /* string */
74     MRP_SCRIPT_TYPE_BOOL    = 0x02,      /* boolean */
75     MRP_SCRIPT_TYPE_UINT8   = 0x03,      /* signed 8-bit integer */
76     MRP_SCRIPT_TYPE_SINT8   = 0x04,      /* unsigned 8-bit integer */
77     MRP_SCRIPT_TYPE_INT8    = A(SINT8),  /* alias for SINT8 */
78     MRP_SCRIPT_TYPE_UINT16  = 0x05,      /* unsigned 16-bit integer */
79     MRP_SCRIPT_TYPE_SINT16  = 0x06,      /* signed 16-bit integer */
80     MRP_SCRIPT_TYPE_INT16   = A(SINT16), /* alias for SINT16 */
81     MRP_SCRIPT_TYPE_UINT32  = 0x07,      /* unsigned 32-bit integer */
82     MRP_SCRIPT_TYPE_SINT32  = 0x08,      /* signed 32-bit integer */
83     MRP_SCRIPT_TYPE_INT32   = A(SINT32), /* alias for SINT32 */
84     MRP_SCRIPT_TYPE_UINT64  = 0x09,      /* unsigned 64-bit integer */
85     MRP_SCRIPT_TYPE_SINT64  = 0x0a,      /* signed 64-bit integer */
86     MRP_SCRIPT_TYPE_INT64   = A(SINT64), /* alias for SINT64 */
87     MRP_SCRIPT_TYPE_DOUBLE  = 0x0b,      /* double-prec. floating point */
88     MRP_SCRIPT_TYPE_ARRAY   = 0x80,      /* type/marker for arrays */
89 } mrp_script_type_t;
90 #undef A
91
92 #define MRP_SCRIPT_VALUE_UNION union {          \
93         char      *str;                         \
94         bool       bln;                         \
95         uint8_t    u8;                          \
96         int8_t     s8;                          \
97         uint16_t   u16;                         \
98         int16_t    s16;                         \
99         uint32_t   u32;                         \
100         int32_t    s32;                         \
101         uint64_t   u64;                         \
102         int64_t    s64;                         \
103         double     dbl;                         \
104     }
105
106 typedef MRP_SCRIPT_VALUE_UNION mrp_script_value_u;
107
108 struct mrp_script_value_s {
109     mrp_script_type_t type;
110     MRP_SCRIPT_VALUE_UNION;
111 };
112
113 /** Helper macros for passing values to variadic arglist functions. */
114 #define MRP_SCRIPT_STRING(s) MRP_SCRIPT_TYPE_STRING, s
115 #define MRP_SCRIPT_BOOL(b)   MRP_SCRIPT_TYPE_BOOL  , b
116 #define MRP_SCRIPT_UINT8(u)  MRP_SCRIPT_TYPE_UINT8 , u
117 #define MRP_SCRIPT_SINT8(s)  MRP_SCRIPT_TYPE_SINT8 , s
118 #define MRP_SCRIPT_UINT16(u) MRP_SCRIPT_TYPE_UINT16, u
119 #define MRP_SCRIPT_SINT16(s) MRP_SCRIPT_TYPE_SINT16, s
120 #define MRP_SCRIPT_UINT32(u) MRP_SCRIPT_TYPE_UINT32, u
121 #define MRP_SCRIPT_SINT32(s) MRP_SCRIPT_TYPE_SINT32, s
122 #define MRP_SCRIPT_UINT64(u) MRP_SCRIPT_TYPE_UINT64, u
123 #define MRP_SCRIPT_DOUBLE(d) MRP_SCRIPT_TYPE_DOUBLE, d
124
125 /** Helper macro for initializing/assigning to value arrays. */
126 #define __MRP_SCRIPT_VALUE(_t, _m, _v) \
127     (mrp_script_value_t){ .type = MRP_SCRIPT_TYPE_##_t, ._m = _v }
128
129 #define MRP_SCRIPT_VALUE_STRING(v) __MRP_SCRIPT_VALUE(STRING, str, v)
130 #define MRP_SCRIPT_VALUE_BOOL(v)   __MRP_SCRIPT_VALUE(BOOL  , bln, v)
131 #define MRP_SCRIPT_VALUE_UINT8(v)  __MRP_SCRIPT_VALUE(UINT8 , u8 , v)
132 #define MRP_SCRIPT_VALUE_SINT8(v)  __MRP_SCRIPT_VALUE(SINT8 , s8 , v)
133 #define MRP_SCRIPT_VALUE_UINT16(v) __MRP_SCRIPT_VALUE(UINT16, u16, v)
134 #define MRP_SCRIPT_VALUE_SINT16(v) __MRP_SCRIPT_VALUE(SINT16, s16, v)
135 #define MRP_SCRIPT_VALUE_UINT32(v) __MRP_SCRIPT_VALUE(UINT32, u32, v)
136 #define MRP_SCRIPT_VALUE_SINT32(v) __MRP_SCRIPT_VALUE(SINT32, s32, v)
137 #define MRP_SCRIPT_VALUE_UINT64(v) __MRP_SCRIPT_VALUE(UINT64, u64, v)
138 #define MRP_SCRIPT_VALUE_SINT64(v) __MRP_SCRIPT_VALUE(SINT64, s64, v)
139 #define MRP_SCRIPT_VALUE_DOUBLE(v) __MRP_SCRIPT_VALUE(DOUBLE, dbl, v)
140
141 /** Print the given value to the given buffer. */
142 char *mrp_print_value(char *buf, size_t size, mrp_script_value_t *value);
143
144
145 /*
146  * a script interpreter as exposed to the resolver
147  */
148
149 struct mrp_interpreter_s {
150     mrp_list_hook_t    hook;             /* to list of interpreters */
151     const char        *name;             /* interpreter identifier */
152     void              *data;             /* opaque global interpreter data */
153     /*                                      interpreter operations */
154     int  (*compile)(mrp_scriptlet_t *script);
155     int  (*prepare)(mrp_scriptlet_t *script);
156     int  (*execute)(mrp_scriptlet_t *script, mrp_context_tbl_t *ctbl);
157     void (*cleanup)(mrp_scriptlet_t *script);
158 };
159
160 /** Macro to automatically register an interpreter on startup. */
161 #define MRP_REGISTER_INTERPRETER(_type, _compile, _prepare, _execute,   \
162                                  _cleanup)                              \
163     static void auto_register_interpreter(void)                         \
164          __attribute__((constructor));                                  \
165                                                                         \
166     static void auto_register_interpreter(void) {                       \
167         static mrp_interpreter_t interpreter = {                        \
168             .name    = _type,                                           \
169             .compile = _compile,                                        \
170             .prepare = _prepare,                                        \
171             .execute = _execute,                                        \
172             .cleanup = _cleanup                                         \
173         };                                                              \
174                                                                         \
175         if (!mrp_register_interpreter(&interpreter))                    \
176             mrp_log_error("Failed to register interpreter '%s'.",       \
177                           _type);                                       \
178         else                                                            \
179             mrp_log_info("Registered interpreter '%s'.", _type);        \
180     }                                                                   \
181     struct mrp_allow_trailing_semicolon
182
183
184 /** Register a new scriptlet interpreter. */
185 int mrp_register_interpreter(mrp_interpreter_t *i);
186
187 /** Unregister a scriptlet interpreter. */
188 int mrp_unregister_interpreter(const char *type);
189
190 /** Find a scriptlet interpreter by type. */
191 mrp_interpreter_t *mrp_lookup_interpreter(const char *type);
192
193
194 /*
195  * a resolver target update script
196  */
197
198 struct mrp_scriptlet_s {
199     char              *source;           /* scriptlet code */
200     mrp_interpreter_t *interpreter;      /* interpreter handling this */
201     void              *data;             /* opaque interpreter data */
202     void              *compiled;         /* compiled scriptlet */
203 };
204
205 /** Create a scriptlet of the given type and source. */
206 mrp_scriptlet_t *mrp_create_script(const char *type, const char *source);
207
208 /** Destroy the given scriptlet, freeing all of its resources. */
209 void mrp_destroy_script(mrp_scriptlet_t *script);
210
211 /** Compile the given scriptlet. */
212 int mrp_compile_script(mrp_scriptlet_t *s);
213
214 /** Prepare the given scriptlet for execution. */
215 int mrp_prepare_script(mrp_scriptlet_t *s);
216
217 /** Execute the given scriptlet with the given context variables. */
218 int mrp_execute_script(mrp_scriptlet_t *s, mrp_context_tbl_t *ctbl);
219
220
221
222 /*
223  * Context variable (keyword argument) handling.
224  * XXX TODO: Uhmm... this needs to be rethought/redone. :-(
225  */
226
227 mrp_context_tbl_t *mrp_create_context_table(void);
228 void mrp_destroy_context_table(mrp_context_tbl_t *tbl);
229 int mrp_declare_context_variable(mrp_context_tbl_t *tbl, const char *name,
230                                  mrp_script_type_t type);
231 int mrp_push_context_frame(mrp_context_tbl_t *tbl);
232 int mrp_pop_context_frame(mrp_context_tbl_t *tbl);
233 int mrp_get_context_id(mrp_context_tbl_t *tbl, const char *name);
234 int mrp_get_context_value(mrp_context_tbl_t *tbl, int id,
235                           mrp_script_value_t *value);
236 int mrp_set_context_value(mrp_context_tbl_t *tbl, int id,
237                           mrp_script_value_t *value);
238 int mrp_get_context_value_by_name(mrp_context_tbl_t *tbl, const char *name,
239                           mrp_script_value_t *value);
240 int mrp_set_context_value_by_name(mrp_context_tbl_t *tbl, const char *name,
241                                   mrp_script_value_t *value);
242
243
244
245
246 MRP_CDECL_END
247
248
249
250
251 #endif /* __MURPHY_CORE_SCRIPTING_H__ */