summaryrefslogtreecommitdiff
path: root/src/bin/eldbus/parser.c
diff options
context:
space:
mode:
authorLucas De Marchi <lucas.demarchi@profusion.mobi>2013-04-23 11:40:05 -0300
committerLucas De Marchi <lucas.demarchi@profusion.mobi>2013-04-23 12:36:29 -0300
commit4e3804041f8e865e007b2a6a0d45a05f39500c3b (patch)
treea493b9c8f8a610d2667651f3ba81819ed16fbe8c /src/bin/eldbus/parser.c
parent4cf68bf728b5a858ce1c0efac25ded1a49ba8d9d (diff)
Rename edbus->eldbus
git grep -l edbus2 | while read f; do sed -i 's/edbus2/eldbus/g' "$f"; done find . -name '*edbus2*' -exec rename edbus2 eldbus {} \; git grep -l "EDBUS" | while read f; do sed -i 's/EDBUS/ELDBUS/g' "$f"; done git grep -l "EDBus" | while read f; do sed -i 's/EDBus/Eldbus/g' "$f"; done git grep -l "edbus (v2)" | while read f; do sed -i 's/edbus (v2)/eldbus/g' "$f"; done git grep -l "Edbus" | while read f; do sed -i 's/Edbus/Eldbus/g' "$f"; done git grep -l "edbus" | while read f; do sed -i 's/edbus/eldbus/g' "$f"; done find . -name '*edbus*' -exec rename edbus eldbus {} \; find . -name '*EDBus*' -exec rename EDBus Eldbus {} \;
Diffstat (limited to 'src/bin/eldbus/parser.c')
-rw-r--r--src/bin/eldbus/parser.c491
1 files changed, 491 insertions, 0 deletions
diff --git a/src/bin/eldbus/parser.c b/src/bin/eldbus/parser.c
new file mode 100644
index 0000000000..96a8f9e354
--- /dev/null
+++ b/src/bin/eldbus/parser.c
@@ -0,0 +1,491 @@
1#include "codegen.h"
2
3#define OBJECT_TAG "node"
4#define OBJECT_TAG_LENGHT strlen(OBJECT_TAG)
5#define INTERFACE_TAG "interface"
6#define INTERFACE_TAG_LENGHT strlen(INTERFACE_TAG)
7#define SIGNAL_TAG "signal"
8#define SIGNAL_TAG_LENGHT strlen(SIGNAL_TAG)
9#define METHOD_TAG "method"
10#define METHOD_TAG_LENGHT strlen(METHOD_TAG)
11#define PROPERTY_TAG "property"
12#define PROPERTY_TAG_LENGHT strlen(PROPERTY_TAG)
13#define ARG_TAG "arg"
14#define ARG_TAG_LENGHT strlen(ARG_TAG)
15#define ANNOTATION_TAG "annotation"
16#define ANNOTATION_TAG_LENGHT strlen(ANNOTATION_TAG)
17
18//attributes
19#define NAME_ATTR "name"
20#define TYPE_ATTR "type"
21#define DIRECTION_ATTR "direction"
22#define ACCESS_ATTR "access"
23#define VALUE_ATTR "value"
24
25#define ACCESS_ATTR_VALUE_WRITE "write"
26#define ACCESS_ATTR_VALUE_READ "read"
27
28#define DBUS_INTERFACE "org.freedesktop.DBus."
29
30static DBus_Interface *iface;
31static DBus_Signal *d_signal;
32static DBus_Method *method;
33static DBus_Property *property;
34
35static Eina_Bool attributes_parse(const char *content, unsigned length, Eina_Simple_XML_Attribute_Cb func, const void *data);
36
37static Eina_Bool
38obj_attributes_parser(void *data, const char *key, const char *value)
39{
40 DBus_Object *obj = data;
41
42 if (!strcmp(key, NAME_ATTR))
43 obj->name = strdup(value);
44
45 return EINA_TRUE;
46}
47
48static Eina_Bool
49iface_attributes_parser(void *data EINA_UNUSED, const char *key, const char *value)
50{
51 if (!strcmp(key, NAME_ATTR))
52 iface->name = strdup(value);
53
54 return EINA_TRUE;
55}
56
57static Eina_Bool
58signal_attributes_parser(void *data EINA_UNUSED, const char *key, const char *value)
59{
60 if (!strcmp(key, NAME_ATTR))
61 d_signal->name = strdup(value);
62
63 return EINA_TRUE;
64}
65
66static Eina_Bool
67arg_attributes_parser(void *data EINA_UNUSED, const char *key, const char *value)
68{
69 DBus_Arg *arg = data;
70 if (!strcmp(key, NAME_ATTR))
71 arg->name = strdup(value);
72 else if (!strcmp(key, TYPE_ATTR))
73 arg->type = strdup(value);
74 else if (!strcmp(key, DIRECTION_ATTR))
75 arg->direction = value[0];
76
77 return EINA_TRUE;
78}
79
80static Eina_Bool
81method_attributes_parser(void *data EINA_UNUSED, const char *key, const char *value)
82{
83 if (!strcmp(key, NAME_ATTR))
84 method->name = strdup(value);
85
86 return EINA_TRUE;
87}
88
89static Eina_Bool
90property_attributes_parser(void *data EINA_UNUSED, const char *key, const char *value)
91{
92 if (!strcmp(key, NAME_ATTR))
93 property->name = strdup(value);
94 else if (!strcmp(key, TYPE_ATTR))
95 {
96 property->type = strdup(value);
97 if (value[1] || value[0] == 'v')
98 property->complex = EINA_TRUE;
99 }
100 else if (!strcmp(key, ACCESS_ATTR))
101 {
102 if (!strcmp(value, ACCESS_ATTR_VALUE_READ))
103 property->access = ACCESS_READ;
104 else if (!strcmp(value, ACCESS_ATTR_VALUE_WRITE))
105 property->access = ACCESS_WRITE;
106 else
107 property->access = (ACCESS_WRITE | ACCESS_READ);
108 }
109
110 return EINA_TRUE;
111}
112
113static Eina_Bool
114open_object(const char *content, unsigned length, Eina_Bool is_open_empty, DBus_Object **ptr_obj)
115{
116 Eina_Bool r;
117 DBus_Object *obj = *ptr_obj;
118
119 if (is_open_empty) return EINA_TRUE;
120
121 if (obj)
122 {
123 printf("Only one object is supported per file.");
124 return EINA_FALSE;
125 }
126 obj = calloc(1, sizeof(DBus_Object));
127 EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE);
128
129 r = attributes_parse(content, length, obj_attributes_parser, obj);
130 if (!obj->name) obj->name = strdup("/");
131
132 obj->c_name = dbus_name_to_c(obj->name);
133
134 *ptr_obj = obj;
135 return r;
136}
137
138static void
139interface_close(void)
140{
141 //its not necessary generate code to FreeDesktop interfaces
142 if (!strncmp(iface->name, DBUS_INTERFACE, strlen(DBUS_INTERFACE)))
143 interface_free(iface);
144 iface = NULL;
145}
146
147static Eina_Bool
148open_interface(const char *content, unsigned length, Eina_Bool is_open_empty, DBus_Object *obj)
149{
150 Eina_Bool r;
151 char *tmp_name;
152
153 iface = interface_new(obj);
154 EINA_SAFETY_ON_NULL_RETURN_VAL(iface, EINA_FALSE);
155
156 r = attributes_parse(content, length, iface_attributes_parser, NULL);
157 if (!iface->name)
158 {
159 interface_free(iface);
160 printf("Error interface without name.\n");
161 return EINA_FALSE;
162 }
163
164 tmp_name = get_pieces(iface->name, '.', 2);
165 iface->c_name = dbus_name_to_c(tmp_name);
166 free(tmp_name);
167
168 if (is_open_empty)
169 interface_close();
170
171 return r;
172}
173
174static void
175signal_close(void)
176{
177 DBus_Arg *arg;
178 EINA_INLIST_FOREACH(d_signal->args, arg)
179 {
180 if ((arg->type[1]) || (arg->type[0] == 'v'))
181 {
182 d_signal->complex = EINA_TRUE;
183 break;
184 }
185 }
186 d_signal = NULL;
187}
188
189static Eina_Bool
190open_signal(const char *content, unsigned length, Eina_Bool is_open_empty)
191{
192 Eina_Bool r;
193 char *tmp;
194 int i;
195 Eina_Strbuf *buf = eina_strbuf_new();
196
197 d_signal = signal_new(iface);
198 EINA_SAFETY_ON_NULL_RETURN_VAL(d_signal, EINA_FALSE);
199
200 r = attributes_parse(content, length, signal_attributes_parser, NULL);
201 if (!d_signal->name)
202 {
203 signal_free(d_signal);
204 d_signal = NULL;
205 printf("Error signal without name.\n");
206 return EINA_FALSE;
207 }
208
209 tmp = dbus_name_to_c(d_signal->name);
210 d_signal->c_name = string_build("%s_%s", iface->c_name, tmp);
211 free(tmp);
212 d_signal->cb_name = string_build("on_%s", d_signal->c_name);
213 d_signal->free_function = string_build("%s_data_free", d_signal->c_name);
214 d_signal->struct_name = string_build("%s_%s_Data", iface->c_name, d_signal->name);
215 d_signal->struct_name[0] = toupper(d_signal->struct_name[0]);
216 for (i = 0; d_signal->struct_name[i]; i++)
217 {
218 if (d_signal->struct_name[i] == '_' && d_signal->struct_name[i+1])
219 d_signal->struct_name[i+1] = toupper(d_signal->struct_name[i+1]);
220 }
221 for (i = 0; iface->c_name[i]; i++)
222 eina_strbuf_append_char(buf, toupper(iface->c_name[i]));
223 eina_strbuf_append_char(buf, '_');
224 for (i = 0; d_signal->name[i]; i++)
225 {
226 if (i && isupper(d_signal->name[i]) && !isupper(d_signal->name[i-1]))
227 eina_strbuf_append_char(buf, '_');
228 eina_strbuf_append_char(buf, toupper(d_signal->name[i]));
229 }
230 eina_strbuf_append(buf, "_EVENT");
231 d_signal->signal_event = eina_strbuf_string_steal(buf);
232 eina_strbuf_free(buf);
233
234 if (is_open_empty)
235 signal_close();
236
237 return r;
238}
239
240#define ANNOTATION_NO_REPLY "org.freedesktop.DBus.Method.NoReply"
241
242static Eina_Bool
243annotation_attributes_parser(void *data, const char *key, const char *value)
244{
245 DBus_Annotation *annotation = data;
246 if (!strcmp(key, NAME_ATTR))
247 {
248 if (!strcmp(value, ANNOTATION_NO_REPLY))
249 annotation->type = NO_REPLY;
250 }
251 else if (!strcmp(key, VALUE_ATTR))
252 {
253 unsigned i;
254 annotation->value = strdup(value);
255 for (i = 0; annotation->value[i]; i++)
256 annotation->value[i] = tolower(annotation->value[i]);
257 }
258
259 return EINA_TRUE;
260}
261
262static Eina_Bool
263open_annotation(const char *content, unsigned length)
264{
265 DBus_Annotation annotation;
266 Eina_Bool r;
267
268 annotation.type = INVALID;
269 r = attributes_parse(content, length, annotation_attributes_parser, &annotation);
270
271 if (annotation.type == NO_REPLY)
272 {
273 Eina_Bool value = EINA_FALSE;
274 if (!strcmp(annotation.value, "true"))
275 value = EINA_TRUE;
276 free(annotation.value);
277
278 if (method)
279 method->no_reply = value;
280 }
281
282 return r;
283}
284
285static Eina_Bool
286open_arg(const char *content, unsigned length)
287{
288 Eina_Bool r;
289 unsigned int *without_name;
290 DBus_Arg *arg = calloc(1, sizeof(DBus_Arg));
291 EINA_SAFETY_ON_NULL_RETURN_VAL(arg, EINA_FALSE);
292
293 r = attributes_parse(content, length, arg_attributes_parser, arg);
294 if (d_signal)
295 {
296 d_signal->args = eina_inlist_append(d_signal->args, EINA_INLIST_GET(arg));
297 without_name = &d_signal->arg_without_name;
298 }
299 else if (method)
300 {
301 method->args = eina_inlist_append(method->args, EINA_INLIST_GET(arg));
302 without_name = &method->arg_without_name;
303 }
304 else
305 {
306 printf("Error find an argument without any valid parent.\n");
307 return EINA_FALSE;
308 }
309
310 if (!arg->name)
311 {
312 arg->c_name = string_build("arg%d", *without_name);
313 (*without_name)++;
314 }
315 else
316 arg->c_name = dbus_name_to_c(arg->name);
317
318 return r;
319}
320
321static void
322method_close(void)
323{
324 DBus_Arg *arg;
325 EINA_INLIST_FOREACH(method->args, arg)
326 {
327 if ((arg->type[1]) || (arg->type[0] == 'v'))
328 {
329 if (arg->direction == 'o')
330 method->out_complex = EINA_TRUE;
331 else
332 method->in_complex = EINA_TRUE;
333 }
334 }
335 if (method->no_reply)
336 {
337 free(method->cb_name);
338 method->cb_name = strdup("NULL");
339 }
340 method = NULL;
341}
342
343static Eina_Bool
344open_method(const char *content, unsigned lenght, Eina_Bool is_open_empty)
345{
346 Eina_Bool r;
347 char *tmp;
348 int i;
349
350 method = method_new(iface);
351 EINA_SAFETY_ON_NULL_RETURN_VAL(method, EINA_FALSE);
352
353 r = attributes_parse(content, lenght, method_attributes_parser, NULL);
354 if (!method->name)
355 {
356 method_free(method);
357 method = NULL;
358 printf("Error method without name.\n");
359 return EINA_FALSE;
360 }
361
362 tmp = dbus_name_to_c(method->name);
363 method->c_name = string_build("%s_%s", iface->c_name, tmp);
364 free(tmp);
365 method->cb_name = string_build("cb_%s", method->c_name);
366 method->function_cb = string_build("%s_Cb", method->c_name);
367 method->function_cb[0] = toupper(method->function_cb[0]);
368 for (i = 0; method->function_cb[i]; i++)
369 {
370 if (method->function_cb[i] == '_' && method->function_cb[i+1])
371 method->function_cb[i+1] = toupper(method->function_cb[i+1]);
372 }
373
374 if (is_open_empty)
375 method_close();
376
377 return r;
378}
379
380static Eina_Bool
381open_property(const char *content, unsigned length)
382{
383 Eina_Bool r;
384 char *tmp;
385
386 property = property_new(iface);
387 EINA_SAFETY_ON_NULL_RETURN_VAL(property, EINA_FALSE);
388
389 r = attributes_parse(content, length, property_attributes_parser, NULL);
390 if (!property->name)
391 {
392 property_free(property);
393 property = NULL;
394 printf("Error property without name.\n");
395 return EINA_FALSE;
396 }
397
398 tmp = dbus_name_to_c(property->name);
399 property->c_name = string_build("%s_%s", iface->c_name, tmp);
400 free(tmp);
401 property->cb_name = string_build("cb_%s", property->c_name);
402
403 return r;
404}
405
406static Eina_Bool
407open_tag(const char *content, unsigned length, Eina_Bool is_open_empty, DBus_Object **obj)
408{
409 unsigned int i;
410 if (!strncmp(content, OBJECT_TAG, OBJECT_TAG_LENGHT))
411 return open_object(content, length, is_open_empty, obj);
412 else if (!strncmp(content, INTERFACE_TAG, INTERFACE_TAG_LENGHT) && *obj)
413 return open_interface(content, length, is_open_empty, *obj);
414 else if (!strncmp(content, SIGNAL_TAG, SIGNAL_TAG_LENGHT) && iface)
415 return open_signal(content, length, is_open_empty);
416 else if (!strncmp(content, ARG_TAG, ARG_TAG_LENGHT) && iface)
417 return open_arg(content, length);
418 else if (!strncmp(content, ANNOTATION_TAG, ANNOTATION_TAG_LENGHT) && iface)
419 return open_annotation(content, length);
420 else if (!strncmp(content, METHOD_TAG, METHOD_TAG_LENGHT) && iface)
421 return open_method(content, length, is_open_empty);
422 else if (!strncmp(content, PROPERTY_TAG, PROPERTY_TAG_LENGHT) && iface)
423 return open_property(content, length);
424 else if (!strncmp(content, ANNOTATION_TAG, ANNOTATION_TAG_LENGHT) && iface)
425 return EINA_TRUE;
426
427 printf("Warning: Tag not handled:\n");
428 for (i = 0; i < length; i++)
429 printf("%c", content[i]);
430 printf("\n\n");
431
432 return EINA_TRUE;
433}
434
435static Eina_Bool
436close_tag(const char *content)
437{
438 if (!strncmp(content, INTERFACE_TAG, INTERFACE_TAG_LENGHT))
439 interface_close();
440 if (!strncmp(content, SIGNAL_TAG, SIGNAL_TAG_LENGHT))
441 signal_close();
442 else if (!strncmp(content, METHOD_TAG, METHOD_TAG_LENGHT))
443 method_close();
444 else if (!strncmp(content, PROPERTY_TAG, PROPERTY_TAG_LENGHT))
445 property = NULL;
446
447 return EINA_TRUE;
448}
449
450Eina_Bool
451parser(void *data, Eina_Simple_XML_Type type, const char *content, unsigned offset EINA_UNUSED, unsigned length)
452{
453 Eina_Bool r = EINA_TRUE;
454 DBus_Object **obj = data;
455
456 switch (type)
457 {
458 case EINA_SIMPLE_XML_OPEN:
459 case EINA_SIMPLE_XML_OPEN_EMPTY:
460 {
461 r = open_tag(content, length, type == EINA_SIMPLE_XML_OPEN_EMPTY,
462 obj);
463 break;
464 }
465 case EINA_SIMPLE_XML_CLOSE:
466 {
467 r = close_tag(content);
468 break;
469 }
470 default:
471 break;
472 }
473 return r;
474}
475
476static Eina_Bool
477attributes_parse(const char *content, unsigned length, Eina_Simple_XML_Attribute_Cb func, const void *data)
478{
479 const char *attrs = eina_simple_xml_tag_attributes_find(content, length);
480 unsigned attrslen = 0;
481 if (attrs)
482 {
483 attrslen = length - (attrs - content);
484 if (!eina_simple_xml_attributes_parse(attrs, attrslen, func, data))
485 {
486 printf("Parser error - attrs=%s | content=%s\n", attrs, content);
487 return EINA_FALSE;
488 }
489 }
490 return EINA_TRUE;
491}