summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Kolesa <d.kolesa@osg.samsung.com>2016-09-23 17:49:44 +0200
committerDaniel Kolesa <d.kolesa@osg.samsung.com>2016-10-07 11:54:23 +0200
commit6c4d705d55947a3ec22cdb8cf6337b7ab2548145 (patch)
treeef9d06a91f8c039f421f4499347b8fa5f40b3acd
parent56cd773836278bbb78708fd526c1f0fda7e801c8 (diff)
eolian gen2: initial partial source generation
-rw-r--r--src/bin/eolian2/headers.c17
-rw-r--r--src/bin/eolian2/main.c41
-rw-r--r--src/bin/eolian2/main.h2
-rw-r--r--src/bin/eolian2/sources.c436
4 files changed, 481 insertions, 15 deletions
diff --git a/src/bin/eolian2/headers.c b/src/bin/eolian2/headers.c
index 0b1247d3fc..fa18a4614d 100644
--- a/src/bin/eolian2/headers.c
+++ b/src/bin/eolian2/headers.c
@@ -199,20 +199,8 @@ eo_gen_header_gen(const Eolian_Class *cl, Eina_Strbuf *buf, Eina_Bool legacy)
199 return; 199 return;
200 200
201 char *cname = NULL, *cnameu = NULL, *cnamel = NULL; 201 char *cname = NULL, *cnameu = NULL, *cnamel = NULL;
202 202 if (!eo_gen_class_names_get(cl, &cname, &cnameu, &cnamel))
203 cname = eo_gen_c_full_name_get(eolian_class_full_name_get(cl)); 203 return;
204 if (!cname)
205 goto end;
206
207 cnameu = strdup(cname);
208 if (!cnameu)
209 goto end;
210 eina_str_toupper(&cnameu);
211
212 cnamel = strdup(cname);
213 if (!cnamel)
214 goto end;
215 eina_str_tolower(&cnamel);
216 204
217 /* class definition */ 205 /* class definition */
218 206
@@ -319,7 +307,6 @@ events:
319 eina_iterator_free(itr); 307 eina_iterator_free(itr);
320 } 308 }
321 309
322end:
323 free(cname); 310 free(cname);
324 free(cnameu); 311 free(cnameu);
325 free(cnamel); 312 free(cnamel);
diff --git a/src/bin/eolian2/main.c b/src/bin/eolian2/main.c
index a2e0e34e1e..18985e8a1f 100644
--- a/src/bin/eolian2/main.c
+++ b/src/bin/eolian2/main.c
@@ -233,6 +233,47 @@ char *eo_gen_c_full_name_get(const char *nm)
233 return buf; 233 return buf;
234} 234}
235 235
236Eina_Bool eo_gen_class_names_get(const Eolian_Class *cl, char **cname,
237 char **cnameu, char **cnamel)
238{
239 char *cn = NULL, *cnu = NULL, *cnl = NULL;
240 cn = eo_gen_c_full_name_get(eolian_class_full_name_get(cl));
241 if (!cn)
242 return EINA_FALSE;
243 if (cname)
244 *cname = cn;
245
246 if (cnameu)
247 {
248 cnu = strdup(cn);
249 if (!cnu)
250 {
251 free(cn);
252 return EINA_FALSE;
253 }
254 eina_str_toupper(&cnu);
255 *cnameu = cnu;
256 }
257
258 if (cnamel)
259 {
260 cnl = strdup(cn);
261 if (!cnl)
262 {
263 free(cn);
264 free(cnu);
265 return EINA_FALSE;
266 }
267 eina_str_tolower(&cnl);
268 *cnamel = cnl;
269 }
270
271 if (!cname)
272 free(cn);
273
274 return EINA_TRUE;
275}
276
236static Eina_Bool 277static Eina_Bool
237_write_header(const char *ofname, const char *ifname, Eina_Bool legacy) 278_write_header(const char *ofname, const char *ifname, Eina_Bool legacy)
238{ 279{
diff --git a/src/bin/eolian2/main.h b/src/bin/eolian2/main.h
index 9ac6312cef..fc12597b4f 100644
--- a/src/bin/eolian2/main.h
+++ b/src/bin/eolian2/main.h
@@ -36,5 +36,7 @@ extern int _eolian_gen_log_dom;
36#define CRIT(...) EINA_LOG_DOM_CRIT(_eolian_gen_log_dom, __VA_ARGS__) 36#define CRIT(...) EINA_LOG_DOM_CRIT(_eolian_gen_log_dom, __VA_ARGS__)
37 37
38char *eo_gen_c_full_name_get(const char *nm); 38char *eo_gen_c_full_name_get(const char *nm);
39Eina_Bool eo_gen_class_names_get(const Eolian_Class *cl, char **cname,
40 char **cnameu, char **cnamel);
39 41
40#endif 42#endif
diff --git a/src/bin/eolian2/sources.c b/src/bin/eolian2/sources.c
index abfd6a5c19..badc3789b3 100644
--- a/src/bin/eolian2/sources.c
+++ b/src/bin/eolian2/sources.c
@@ -1,12 +1,419 @@
1#include "main.h" 1#include "main.h"
2#include "docs.h" 2#include "docs.h"
3 3
4/* Used to store the function names that will have to be appended
5 * with __eolian during C generation. Needed when params have to
6 * be initialized and for future features.
7 */
8static Eina_Hash *_funcs_params_init = NULL;
9
10static const char *
11_get_add_star(Eolian_Function_Type ftype, Eolian_Parameter_Dir pdir)
12{
13 if (ftype == EOLIAN_PROP_GET)
14 return "*";
15 if ((pdir == EOLIAN_OUT_PARAM) || (pdir == EOLIAN_INOUT_PARAM))
16 return "*";
17 return "";
18}
19
20static void
21_gen_func(const Eolian_Class *cl, const Eolian_Function *fid,
22 Eolian_Function_Type ftype, Eina_Strbuf *buf,
23 const Eolian_Implement *impl)
24{
25 Eina_Bool is_empty = eolian_implement_is_empty(impl);
26 Eina_Bool is_auto = eolian_implement_is_auto(impl);
27
28 if ((ftype != EOLIAN_PROP_GET) && (ftype != EOLIAN_PROP_SET))
29 ftype = eolian_function_type_get(fid);
30
31 Eina_Bool is_prop = (ftype == EOLIAN_PROP_GET || ftype == EOLIAN_PROP_SET);
32 Eina_Bool var_as_ret = EINA_FALSE;
33
34 const Eolian_Expression *def_ret = NULL;
35 const Eolian_Type *rtp = eolian_function_return_type_get(fid, ftype);
36 if (rtp)
37 {
38 is_auto = EINA_FALSE; /* can't do auto if func returns */
39 def_ret = eolian_function_return_default_value_get(fid, ftype);
40 }
41
42 const char *func_suffix = "";
43 if (ftype == EOLIAN_PROP_GET)
44 {
45 func_suffix = "_get";
46 if (!rtp)
47 {
48 void *d1, *d2;
49 Eina_Iterator *itr = eolian_property_values_get(fid, ftype);
50 if (eina_iterator_next(itr, &d1) && !eina_iterator_next(itr, &d2))
51 {
52 Eolian_Function_Parameter *pr = d1;
53 rtp = eolian_parameter_type_get(pr);
54 var_as_ret = EINA_TRUE;
55 def_ret = eolian_parameter_default_value_get(pr);
56 }
57 eina_iterator_free(itr);
58 }
59 }
60 else if (ftype == EOLIAN_PROP_SET)
61 func_suffix = "_set";
62
63 Eina_Strbuf *params = eina_strbuf_new(); /* par1, par2, par3, ... */
64 Eina_Strbuf *params_full = eina_strbuf_new(); /* T par1, U par2, ... for decl */
65 Eina_Strbuf *params_full_imp = eina_strbuf_new(); /* as above, for impl */
66 Eina_Strbuf *params_init = eina_strbuf_new(); /* default value inits */
67
68 Eina_Bool has_promise = EINA_FALSE;
69 Eina_Stringshare *promise_param_name = NULL;
70 Eina_Stringshare *promise_param_type = NULL;
71
72 /* property keys */
73 {
74 Eina_Iterator *itr = eolian_property_keys_get(fid, ftype);
75 Eolian_Function_Parameter *pr;
76 EINA_ITERATOR_FOREACH(itr, pr)
77 {
78 const char *prn = eolian_parameter_name_get(pr);
79 const Eolian_Type *pt = eolian_parameter_type_get(pr);
80 Eina_Stringshare *ptn = eolian_type_c_type_get(pt);
81
82 if (eina_strbuf_length_get(params))
83 eina_strbuf_append(params, ", ");
84 eina_strbuf_append(params, prn);
85
86 eina_strbuf_append_printf(params_full, ", %s %s", ptn, prn);
87 eina_strbuf_append_printf(params_full_imp, ", %s %s", ptn, prn);
88 if (is_empty)
89 eina_strbuf_append(params_full_imp, " EINA_UNUSED");
90
91 eina_stringshare_del(ptn);
92 }
93 eina_iterator_free(itr);
94 }
95
96 /* property values or method params if applicable */
97 if (!var_as_ret)
98 {
99 Eina_Iterator *itr;
100 if (is_prop)
101 itr = eolian_property_values_get(fid, ftype);
102 else
103 itr = eolian_function_parameters_get(fid);
104 Eolian_Function_Parameter *pr;
105 EINA_ITERATOR_FOREACH(itr, pr)
106 {
107 Eolian_Parameter_Dir pd = eolian_parameter_direction_get(pr);
108 const Eolian_Expression *dfv = eolian_parameter_default_value_get(pr);
109 const char *prn = eolian_parameter_name_get(pr);
110 const Eolian_Type *pt = eolian_parameter_type_get(pr);
111 Eina_Stringshare *ptn = eolian_type_c_type_get(pt);
112
113 Eina_Bool had_star = !!strchr(ptn, '*');
114 const char *add_star = _get_add_star(ftype, pd);
115
116 if (eina_strbuf_length_get(params))
117 eina_strbuf_append(params, ", ");
118
119 /* XXX: this is really bad */
120 if (!has_promise && !strcmp(ptn, "Eina_Promise *") && !is_prop
121 && (pd == EOLIAN_INOUT_PARAM))
122 {
123 has_promise = EINA_TRUE;
124 promise_param_name = eina_stringshare_add(prn);
125 promise_param_type = eolian_type_c_type_get(eolian_type_base_type_get(pt));
126 eina_strbuf_append(params_full_imp, ", Eina_Promise_Owner *");
127 eina_strbuf_append(params_full_imp, prn);
128 if (is_empty && !dfv)
129 eina_strbuf_append(params_full_imp, " EINA_UNUSED");
130 eina_strbuf_append(params, "__eo_promise");
131 }
132 else
133 {
134 eina_strbuf_append(params_full_imp, ", ");
135 eina_strbuf_append(params_full_imp, ptn);
136 if (!had_star)
137 eina_strbuf_append_char(params_full_imp, ' ');
138 eina_strbuf_append(params_full_imp, add_star);
139 eina_strbuf_append(params_full_imp, prn);
140 if (!dfv && is_empty)
141 eina_strbuf_append(params_full_imp, " EINA_UNUSED");
142 eina_strbuf_append(params, prn);
143 }
144
145 eina_strbuf_append(params_full, ", ");
146 eina_strbuf_append(params_full, ptn);
147 if (!had_star)
148 eina_strbuf_append_char(params_full, ' ');
149 eina_strbuf_append(params_full, add_star);
150 eina_strbuf_append(params_full, prn);
151
152 if (is_auto)
153 {
154 if (ftype == EOLIAN_PROP_SET)
155 eina_strbuf_append_printf(params_init, " %s = pd->%s;\n", prn, prn);
156 else
157 {
158 eina_strbuf_append_printf(params_init, " if (%s) *%s = pd->%s\n",
159 prn, prn, prn);
160 }
161 }
162 else if ((ftype != EOLIAN_PROP_SET) && dfv)
163 {
164 Eolian_Value val = eolian_expression_eval(dfv, EOLIAN_MASK_ALL);
165 if (val.type)
166 {
167 Eina_Stringshare *vals = eolian_expression_value_to_literal(&val);
168 eina_strbuf_append_printf(params_init, " if (%s) *%s = %s;",
169 prn, prn, vals);
170 eina_stringshare_del(vals);
171 if (eolian_expression_type_get(dfv) == EOLIAN_EXPR_NAME)
172 {
173 Eina_Stringshare *vs = eolian_expression_serialize(dfv);
174 eina_strbuf_append_printf(params_init, " /* %s */", vs);
175 eina_stringshare_del(vs);
176 }
177 eina_strbuf_append_char(params_init, '\n');
178 }
179 }
180
181 eina_stringshare_del(ptn);
182 }
183 eina_iterator_free(itr);
184 }
185
186 Eina_Bool impl_same_class = (eolian_implement_class_get(impl) == cl);
187 Eina_Bool impl_need = EINA_TRUE;
188 if (impl_same_class && eolian_function_is_virtual_pure(fid, ftype))
189 impl_need = EINA_FALSE;
190
191 Eina_Stringshare *rtpn = rtp ? eolian_type_c_type_get(rtp)
192 : eina_stringshare_add("void");
193
194 char *cnamel, *ocnamel = NULL;
195 if (!eo_gen_class_names_get(cl, NULL, NULL, &cnamel))
196 goto end;
197 if (!eo_gen_class_names_get(eolian_implement_class_get(impl), NULL, NULL, &ocnamel))
198 goto end;
199
200 if (impl_need)
201 {
202 /* figure out the data type */
203 Eina_Bool is_cf = eolian_function_is_class(fid);
204 const char *dt = eolian_class_data_type_get(cl);
205 char adt[128];
206 if (is_cf || (dt && !strcmp(dt, "null")))
207 snprintf(adt, sizeof(adt), "void");
208 else if (dt)
209 snprintf(adt, sizeof(adt), "%s", dt);
210 else
211 snprintf(adt, sizeof(adt), "%s_Data", eolian_class_full_name_get(cl));
212
213 eina_strbuf_append_char(buf, '\n');
214 /* no need for prototype with empty/auto impl */
215 if (!is_empty && !is_auto)
216 {
217 /* T _class_name[_orig_class]_func_name_suffix */
218 eina_strbuf_append(buf, rtpn);
219 if (!strchr(rtpn, '*'))
220 eina_strbuf_append_char(buf, ' ');
221 eina_strbuf_append_char(buf, '_');
222 eina_strbuf_append(buf, cnamel);
223 if (!impl_same_class)
224 eina_strbuf_append_printf(buf, "_%s", ocnamel);
225 eina_strbuf_append_char(buf, '_');
226 eina_strbuf_append(buf, eolian_function_name_get(fid));
227 eina_strbuf_append(buf, func_suffix);
228 /* ([const ]Eo *obj, Data_Type *pd, impl_full_params); */
229 eina_strbuf_append_char(buf, '(');
230 if (eolian_function_object_is_const(fid))
231 eina_strbuf_append(buf, "const ");
232 eina_strbuf_append(buf, "Eo *obj, ");
233 eina_strbuf_append(buf, adt);
234 eina_strbuf_append(buf, " *pd");
235 eina_strbuf_append(buf, eina_strbuf_string_get(params_full_imp));
236 eina_strbuf_append(buf, ");\n\n");
237 }
238
239 if (is_empty || is_auto || eina_strbuf_length_get(params_init))
240 {
241 /* we need to give the internal function name to Eo,
242 * use this hash table as indication
243 */
244 eina_hash_add(_funcs_params_init,
245 eina_stringshare_add(eolian_function_name_get(fid)), (void *)ftype);
246 /* generation of intermediate __eolian_... */
247 eina_strbuf_append(buf, "static ");
248 eina_strbuf_append(buf, rtpn);
249 if (!strchr(rtpn, '*'))
250 eina_strbuf_append_char(buf, ' ');
251 eina_strbuf_append(buf, "__eolian_");
252 eina_strbuf_append(buf, cnamel);
253 if (!impl_same_class)
254 eina_strbuf_append_printf(buf, "_%s", ocnamel);
255 eina_strbuf_append_char(buf, '_');
256 eina_strbuf_append(buf, eolian_function_name_get(fid));
257 eina_strbuf_append(buf, func_suffix);
258 eina_strbuf_append_char(buf, '(');
259 if (eolian_function_object_is_const(fid))
260 eina_strbuf_append(buf, "const ");
261 eina_strbuf_append(buf, "Eo *obj");
262 if (is_empty || is_auto)
263 eina_strbuf_append(buf, " EINA_UNUSED");
264 eina_strbuf_append(buf, ", ");
265 eina_strbuf_append(buf, adt);
266 eina_strbuf_append(buf, " *pd");
267 eina_strbuf_append(buf, eina_strbuf_string_get(params_full_imp));
268 eina_strbuf_append(buf, ")\n{\n");
269 }
270 if (eina_strbuf_length_get(params_init))
271 eina_strbuf_append(buf, eina_strbuf_string_get(params_init));
272 if (is_empty || is_auto)
273 {
274 if (rtp)
275 {
276 const char *vals = NULL;
277 if (def_ret)
278 {
279 Eolian_Value val = eolian_expression_eval(def_ret, EOLIAN_MASK_ALL);
280 if (val.type)
281 vals = eolian_expression_value_to_literal(&val);
282 }
283 eina_strbuf_append_printf(buf, " return %s;\n", vals ? vals : "0");
284 eina_stringshare_del(vals);
285 }
286 eina_strbuf_append(buf, "}\n\n");
287 }
288 else if (eina_strbuf_length_get(params_init))
289 {
290 eina_strbuf_append(buf, " ");
291 if (rtp)
292 eina_strbuf_append(buf, "return ");
293 eina_strbuf_append_char(buf, '_');
294 eina_strbuf_append(buf, cnamel);
295 if (!impl_same_class)
296 eina_strbuf_append_printf(buf, "_%s", ocnamel);
297 eina_strbuf_append_char(buf, '_');
298 eina_strbuf_append(buf, eolian_function_name_get(fid));
299 eina_strbuf_append(buf, func_suffix);
300 eina_strbuf_append(buf, "(obj, pd, ");
301 eina_strbuf_append(buf, eina_strbuf_string_get(params));
302 eina_strbuf_append(buf, ");\n}\n\n");
303 }
304 }
305
306 if (impl_same_class)
307 {
308 /* XXX: bad */
309 if (has_promise)
310 {
311 eina_strbuf_append_printf(buf,
312 "#undef _EFL_OBJECT_API_BEFORE_HOOK\n#undef _EFL_OBJECT_API_AFTER_HOOK\n#undef _EFL_OBJECT_API_CALL_HOOK\n"
313 "#define _EFL_OBJECT_API_BEFORE_HOOK _EINA_PROMISE_BEFORE_HOOK(%s, %s%s)\n"
314 "#define _EFL_OBJECT_API_AFTER_HOOK _EINA_PROMISE_AFTER_HOOK(%s)\n"
315 "#define _EFL_OBJECT_API_CALL_HOOK(x) _EINA_PROMISE_CALL_HOOK(EFL_FUNC_CALL(%s))\n\n",
316 promise_param_type, rtpn,
317 eina_strbuf_string_get(params_full_imp),
318 promise_param_name,
319 eina_strbuf_string_get(params));
320 }
321
322 void *data;
323 Eina_Iterator *itr = eolian_property_keys_get(fid, ftype);
324 Eina_Bool has_params = eina_iterator_next(itr, &data);
325 eina_iterator_free(itr);
326
327 if (!has_params && !var_as_ret)
328 {
329 if (is_prop)
330 itr = eolian_property_values_get(fid, ftype);
331 else
332 itr = eolian_function_parameters_get(fid);
333 has_params = eina_iterator_next(itr, &data);
334 eina_iterator_free(itr);
335 }
336
337 eina_strbuf_append(buf, "EOAPI EFL_");
338 if (!strcmp(rtpn, "void"))
339 eina_strbuf_append(buf, "VOID_");
340 eina_strbuf_append(buf, "FUNC_BODY");
341 if (has_params)
342 eina_strbuf_append_char(buf, 'V');
343 if ((ftype == EOLIAN_PROP_GET) || eolian_function_object_is_const(fid)
344 || eolian_function_is_class(fid))
345 {
346 eina_strbuf_append(buf, "_CONST");
347 }
348 eina_strbuf_append_char(buf, '(');
349
350 Eina_Stringshare *eofn = eolian_function_full_c_name_get(fid, ftype, EINA_FALSE);
351 eina_strbuf_append(buf, eofn);
352 eina_stringshare_del(eofn);
353
354 if (strcmp(rtpn, "void"))
355 {
356 const char *vals = NULL;
357 if (def_ret)
358 {
359 Eolian_Value val = eolian_expression_eval(def_ret, EOLIAN_MASK_ALL);
360 if (val.type)
361 vals = eolian_expression_value_to_literal(&val);
362 }
363 eina_strbuf_append_printf(buf, ", %s, %s", rtpn, vals ? vals : "0");
364 if (vals && (eolian_expression_type_get(def_ret) == EOLIAN_EXPR_NAME))
365 {
366 Eina_Stringshare *valn = eolian_expression_serialize(def_ret);
367 eina_strbuf_append_printf(buf, " /* %s */", valn);
368 eina_stringshare_del(valn);
369 }
370 eina_stringshare_del(vals);
371 }
372 if (has_params)
373 {
374 eina_strbuf_append(buf, ", EFL_FUNC_CALL(");
375 eina_strbuf_append(buf, eina_strbuf_string_get(params));
376 eina_strbuf_append_char(buf, ')');
377 eina_strbuf_append(buf, eina_strbuf_string_get(params_full));
378 }
379
380 eina_strbuf_append(buf, ");\n");
381
382 if (has_promise)
383 {
384 eina_strbuf_append(buf, "\n#undef _EFL_OBJECT_API_BEFORE_HOOK\n#undef _EFL_OBJECT_API_AFTER_HOOK\n#undef _EFL_OBJECT_API_CALL_HOOK\n"
385 "#define _EFL_OBJECT_API_BEFORE_HOOK\n#define _EFL_OBJECT_API_AFTER_HOOK\n"
386 "#define _EFL_OBJECT_API_CALL_HOOK(x) x\n");
387 }
388 }
389
390end:
391 free(cnamel);
392 free(ocnamel);
393
394 eina_stringshare_del(rtpn);
395
396 eina_stringshare_del(promise_param_name);
397 eina_stringshare_del(promise_param_type);
398
399 eina_strbuf_free(params);
400 eina_strbuf_free(params_full);
401 eina_strbuf_free(params_full_imp);
402 eina_strbuf_free(params_init);
403}
404
4void 405void
5eo_gen_source_gen(const Eolian_Class *cl, Eina_Strbuf *buf) 406eo_gen_source_gen(const Eolian_Class *cl, Eina_Strbuf *buf)
6{ 407{
7 if (!cl) 408 if (!cl)
8 return; 409 return;
9 410
411 char *cname = NULL, *cnameu = NULL, *cnamel = NULL;
412 if (!eo_gen_class_names_get(cl, &cname, &cnameu, &cnamel))
413 return;
414
415 _funcs_params_init = eina_hash_stringshared_new(NULL);
416
10 /* event section, they come first */ 417 /* event section, they come first */
11 { 418 {
12 Eina_Iterator *itr = eolian_class_events_get(cl); 419 Eina_Iterator *itr = eolian_class_events_get(cl);
@@ -26,4 +433,33 @@ eo_gen_source_gen(const Eolian_Class *cl, Eina_Strbuf *buf)
26 } 433 }
27 eina_iterator_free(itr); 434 eina_iterator_free(itr);
28 } 435 }
436
437 /* method section */
438 {
439 Eina_Iterator *itr = eolian_class_implements_get(cl);
440 const Eolian_Implement *imp;
441 EINA_ITERATOR_FOREACH(itr, imp)
442 {
443 if (eolian_implement_class_get(imp) != cl)
444 continue;
445 Eolian_Function_Type ftype = EOLIAN_UNRESOLVED;
446 const Eolian_Function *fid = eolian_implement_function_get(imp, &ftype);
447 switch (ftype)
448 {
449 case EOLIAN_PROP_GET:
450 case EOLIAN_PROP_SET:
451 _gen_func(cl, fid, ftype, buf, imp);
452 break;
453 case EOLIAN_PROPERTY:
454 _gen_func(cl, fid, EOLIAN_PROP_SET, buf, imp);
455 _gen_func(cl, fid, EOLIAN_PROP_GET, buf, imp);
456 break;
457 default:
458 _gen_func(cl, fid, EOLIAN_UNRESOLVED, buf, imp);
459 }
460 }
461 eina_iterator_free(itr);
462 }
463
464 eina_hash_free(_funcs_params_init);
29} 465}