1 #include "main.h"
2 #include "docs.h"
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 */
8 static Eina_Hash *_funcs_params_init_get = NULL;
9 static Eina_Hash *_funcs_params_init_set = NULL;
10
11 static const char *
_get_add_star(Eolian_Function_Type ftype,Eolian_Parameter_Direction pdir)12 _get_add_star(Eolian_Function_Type ftype, Eolian_Parameter_Direction pdir)
13 {
14 if (ftype == EOLIAN_PROP_GET)
15 return "*";
16 if ((pdir == EOLIAN_PARAMETER_OUT) || (pdir == EOLIAN_PARAMETER_INOUT))
17 return "*";
18 return "";
19 }
20
21 static Eina_Bool
_function_exists(const char * fname,Eina_Strbuf * buf)22 _function_exists(const char *fname, Eina_Strbuf *buf)
23 {
24 const char *ptr = eina_strbuf_string_get(buf);
25 size_t flen = strlen(fname);
26 while ((ptr = strstr(ptr, fname)) != NULL)
27 {
28 switch (*(ptr - 1))
29 {
30 case '\n':
31 case ' ':
32 switch (*(ptr + flen))
33 {
34 case ' ':
35 case '(':
36 return EINA_TRUE;
37 }
38 }
39 ++ptr;
40 }
41 return EINA_FALSE;
42 }
43
44 /* Check if the type is used in the file, not if it is a typedef... */
45 static Eina_Bool
_type_exists(const char * tname,Eina_Strbuf * buf)46 _type_exists(const char *tname, Eina_Strbuf *buf)
47 {
48 const char *ptr = eina_strbuf_string_get(buf);
49 size_t tlen = strlen(tname);
50 while ((ptr = strstr(ptr, tname)) != NULL)
51 {
52 switch (*(ptr - 1))
53 {
54 case '\n':
55 case ' ':
56 case ',':
57 switch (*(ptr + tlen))
58 {
59 case '\n':
60 case ' ':
61 case ',':
62 case ';':
63 return EINA_TRUE;
64 }
65 }
66 ++ptr;
67 }
68 return EINA_FALSE;
69 }
70
71 static void
_gen_func_pointer_param(const char * name,Eina_Stringshare * c_type,const Eolian_Typedecl * typedecl EINA_UNUSED,Eina_Strbuf * params,Eina_Strbuf * params_full,Eina_Strbuf * params_full_imp,Eina_Bool is_empty EINA_UNUSED)72 _gen_func_pointer_param(const char *name, Eina_Stringshare *c_type,
73 const Eolian_Typedecl *typedecl EINA_UNUSED,
74 Eina_Strbuf *params, Eina_Strbuf *params_full,
75 Eina_Strbuf *params_full_imp,
76 Eina_Bool is_empty EINA_UNUSED)
77 {
78 Eina_Strbuf *dataname = eina_strbuf_new();
79 Eina_Strbuf *freename = eina_strbuf_new();
80
81 eina_strbuf_append_printf(dataname, "%s_data", name);
82 eina_strbuf_append_printf(freename, "%s_free_cb", name);
83
84 if (eina_strbuf_length_get(params))
85 eina_strbuf_append(params, ", ");
86
87 eina_strbuf_append_printf(params, "%s, %s, %s",
88 eina_strbuf_string_get(dataname),
89 name,
90 eina_strbuf_string_get(freename));
91
92 eina_strbuf_append_printf(params_full_imp, ", void *%s, %s %s, Eina_Free_Cb %s",
93 eina_strbuf_string_get(dataname),
94 c_type, name,
95 eina_strbuf_string_get(freename));
96 eina_strbuf_append_printf(params_full, ", void *%s, %s %s, Eina_Free_Cb %s",
97 eina_strbuf_string_get(dataname),
98 c_type, name,
99 eina_strbuf_string_get(freename));
100
101 eina_strbuf_free(dataname);
102 eina_strbuf_free(freename);
103 }
104
105 static void
_append_defval(Eina_Strbuf * buf,const Eolian_Expression * exp,const Eolian_Type * tp,const char * ctp)106 _append_defval(Eina_Strbuf *buf, const Eolian_Expression *exp, const Eolian_Type *tp, const char *ctp)
107 {
108 if (exp)
109 {
110 Eolian_Value val = eolian_expression_eval(exp, EOLIAN_MASK_ALL);
111 Eina_Stringshare *lit = eolian_expression_value_to_literal(&val);
112 if (lit)
113 {
114 eina_strbuf_append(buf, lit);
115 Eina_Stringshare *exps = eolian_expression_serialize(exp);
116 if (exps && strcmp(lit, exps))
117 eina_strbuf_append_printf(buf, " /* %s */", exps);
118 eina_stringshare_del(exps);
119 eina_stringshare_del(lit);
120 return;
121 }
122 else WRN("evaluation of default value failed");
123 }
124 /* default value or fallback */
125 const Eolian_Type *btp = eolian_type_aliased_base_get(tp);
126 if (eolian_type_is_ptr(btp) || strchr(ctp, '*'))
127 {
128 eina_strbuf_append(buf, "NULL");
129 return;
130 }
131 const Eolian_Typedecl *tdcl = eolian_type_typedecl_get(btp);
132 if (tdcl && (eolian_typedecl_type_get(tdcl) == EOLIAN_TYPEDECL_STRUCT))
133 {
134 char *sn = eo_gen_c_full_name_get(eolian_typedecl_name_get(tdcl));
135 if (eina_streq(sn, "Eina_Rect"))
136 eina_strbuf_append(buf, "(EINA_RECT_EMPTY())");
137 else
138 eina_strbuf_append_printf(buf, "((%s){0})", sn);
139 free(sn);
140 return;
141 }
142 /* slices are value types that don't boil down to pointers */
143 switch (eolian_type_builtin_type_get(btp))
144 {
145 case EOLIAN_TYPE_BUILTIN_SLICE:
146 case EOLIAN_TYPE_BUILTIN_RW_SLICE:
147 eina_strbuf_append_printf(buf, "((%s){0})", eolian_type_c_name_get(btp));
148 return;
149 default:
150 break;
151 }
152 /* enums and remaining regulars... 0 should do */
153 eina_strbuf_append(buf, "0");
154 }
155
156 static const char *
_free_func_get(const Eolian_Type * type)157 _free_func_get(const Eolian_Type *type)
158 {
159 const Eolian_Type *ab = eolian_type_aliased_base_get(type);
160 switch (eolian_type_builtin_type_get(ab))
161 {
162 /* simple types */
163 case EOLIAN_TYPE_BUILTIN_MSTRING:
164 return "free";
165 case EOLIAN_TYPE_BUILTIN_STRINGSHARE:
166 return "eina_stringshare_del";
167 case EOLIAN_TYPE_BUILTIN_ANY_VALUE:
168 return "eina_value_flush";
169 case EOLIAN_TYPE_BUILTIN_ANY_VALUE_REF:
170 return "eina_value_free";
171 case EOLIAN_TYPE_BUILTIN_STRBUF:
172 return "eina_strbuf_free";
173 case EOLIAN_TYPE_BUILTIN_BINBUF:
174 return "eina_binbuf_free";
175 /* complex types */
176 case EOLIAN_TYPE_BUILTIN_ACCESSOR:
177 return "eina_accessor_free";
178 case EOLIAN_TYPE_BUILTIN_ARRAY:
179 return "eina_array_free";
180 case EOLIAN_TYPE_BUILTIN_FUTURE:
181 return "(void)";
182 case EOLIAN_TYPE_BUILTIN_ITERATOR:
183 return "eina_iterator_free";
184 case EOLIAN_TYPE_BUILTIN_HASH:
185 return "eina_hash_free";
186 case EOLIAN_TYPE_BUILTIN_LIST:
187 return "eina_list_free";
188 /* class and user types */
189 case EOLIAN_TYPE_BUILTIN_INVALID:
190 if (eolian_type_type_get(ab) == EOLIAN_TYPE_CLASS)
191 return "efl_del";
192 else
193 return eolian_typedecl_free_func_get(eolian_type_typedecl_get(ab));
194 /* no free func */
195 default:
196 return NULL;
197 }
198 }
199
200 static void
_generate_normal_free(Eina_Strbuf ** buf,const Eolian_Type * type,const Eina_Strbuf * parameter,const char * additional_intention)201 _generate_normal_free(Eina_Strbuf **buf, const Eolian_Type *type, const Eina_Strbuf *parameter, const char *additional_intention)
202 {
203 const char *free_func = _free_func_get(type);
204 if (!free_func)
205 {
206 printf("No free type %s\n", eolian_type_short_name_get(type));
207 return;
208 }
209
210 if (eolian_type_builtin_type_get(type) == EOLIAN_TYPE_BUILTIN_HASH)
211 {
212 eina_strbuf_append_printf(*buf," eina_hash_free_cb_set(");
213 eina_strbuf_append_buffer(*buf, parameter);
214 eina_strbuf_append(*buf, ",NULL);\n");
215 }
216
217 eina_strbuf_append_printf(*buf," %s%s(", additional_intention, free_func);
218 eina_strbuf_append_buffer(*buf, parameter);
219 eina_strbuf_append(*buf, ");\n");
220 }
221
222 static void
_generate_loop_content(Eina_Strbuf ** buf,const Eolian_Type * inner_type,const Eina_Strbuf * iter_param)223 _generate_loop_content(Eina_Strbuf **buf, const Eolian_Type *inner_type, const Eina_Strbuf *iter_param)
224 {
225 eina_strbuf_append(*buf, " {\n");
226 _generate_normal_free(buf, inner_type, iter_param, " ");
227 eina_strbuf_append(*buf, " }\n");
228 }
229
230 static void
_generate_iterative_free(Eina_Strbuf ** buf,const Eolian_Type * type,const Eolian_Type * inner_type,Eolian_Function_Parameter * parameter,Eina_Strbuf * param)231 _generate_iterative_free(Eina_Strbuf **buf, const Eolian_Type *type, const Eolian_Type *inner_type, Eolian_Function_Parameter *parameter, Eina_Strbuf *param)
232 {
233 Eina_Strbuf *iterator_header, *iter_param;
234
235 iterator_header = eina_strbuf_new();
236 iter_param = eina_strbuf_new();
237
238 Eolian_Type_Builtin_Type t = eolian_type_builtin_type_get(type);
239
240 eina_strbuf_append_printf(iter_param, "%s_iter", eolian_parameter_name_get(parameter));
241
242 //generate the field definition
243 eina_strbuf_append_printf(*buf, " %s", eolian_type_c_type_get(inner_type));
244 eina_strbuf_append_buffer(*buf, iter_param);
245 eina_strbuf_append(*buf, ";\n");
246
247
248 if (t == EOLIAN_TYPE_BUILTIN_LIST)
249 {
250 eina_strbuf_append_printf(*buf, " EINA_LIST_FREE(");
251 eina_strbuf_append_buffer(*buf, param);
252 eina_strbuf_append_char(*buf, ',');
253 eina_strbuf_append_buffer(*buf, iter_param);
254 eina_strbuf_append(*buf, ")\n");
255 _generate_loop_content(buf, inner_type, iter_param);
256 }
257 else if (t == EOLIAN_TYPE_BUILTIN_ITERATOR)
258 {
259 eina_strbuf_append_printf(*buf, " EINA_ITERATOR_FOREACH(");
260 eina_strbuf_append_buffer(*buf, param);
261 eina_strbuf_append_char(*buf, ',');
262 eina_strbuf_append_buffer(*buf, iter_param);
263 eina_strbuf_append(*buf, ")\n");
264 _generate_loop_content(buf, inner_type, iter_param);
265 }
266 else if (t == EOLIAN_TYPE_BUILTIN_ACCESSOR)
267 {
268 eina_strbuf_append_printf(*buf, " unsigned int %s_i = 0;\n", eolian_parameter_name_get(parameter));
269 eina_strbuf_append_printf(*buf, " EINA_ACCESSOR_FOREACH(");
270 eina_strbuf_append_buffer(*buf, param);
271 eina_strbuf_append_printf(*buf, ",%s_i,", eolian_parameter_name_get(parameter));
272 eina_strbuf_append_buffer(*buf, iter_param);
273 eina_strbuf_append(*buf, ")\n");
274 _generate_loop_content(buf, inner_type, iter_param);
275 }
276 else if (t == EOLIAN_TYPE_BUILTIN_HASH)
277 {
278 eina_strbuf_append_printf(*buf," eina_hash_free_cb_set(");
279 eina_strbuf_append_buffer(*buf, param);
280 eina_strbuf_append_printf(*buf, ",%s);\n",_free_func_get(inner_type));
281 eina_strbuf_append_printf(*buf," eina_hash_free(");
282 eina_strbuf_append_buffer(*buf, param);
283 eina_strbuf_append(*buf, ");\n");
284 }
285 else if (t == EOLIAN_TYPE_BUILTIN_ARRAY)
286 {
287 eina_strbuf_append_printf(*buf, " while((");
288 eina_strbuf_append_buffer(*buf, iter_param);
289 eina_strbuf_append_printf(*buf, " = eina_array_pop(");
290 eina_strbuf_append_buffer(*buf, param);
291 eina_strbuf_append_printf(*buf, ")))\n");
292 _generate_loop_content(buf, inner_type, iter_param);
293 eina_strbuf_append_printf(*buf, " eina_array_free(");
294 eina_strbuf_append_buffer(*buf, param);
295 eina_strbuf_append_printf(*buf, ");\n");
296 }
297 else
298 {
299 printf("Error, container unknown?! %d\n", (int)t);
300 }
301
302 eina_strbuf_free(iterator_header);
303 eina_strbuf_free(iter_param);
304 }
305
306 static int
_gen_function_param_fallback(Eina_Iterator * itr,Eina_Strbuf * fallback_free_ownership,Eina_Strbuf * param_call)307 _gen_function_param_fallback(Eina_Iterator *itr, Eina_Strbuf *fallback_free_ownership, Eina_Strbuf *param_call)
308 {
309 Eolian_Function_Parameter *pr;
310 int owners = 0;
311
312 EINA_ITERATOR_FOREACH(itr, pr)
313 {
314 const Eolian_Type *type, *inner_type;
315
316 type = eolian_parameter_type_get(pr);
317 inner_type = eolian_type_base_type_get(type);
318
319 //check if they should be freed or just ignored
320 if (!eolian_parameter_is_move(pr) || eolian_parameter_direction_get(pr) == EOLIAN_PARAMETER_OUT)
321 {
322 eina_strbuf_append_printf(fallback_free_ownership, " (void)%s;\n", eolian_parameter_name_get(pr));
323 /* FIXME: quick hack to avoid warnings, but should be rewritten properly */
324 if (eolian_type_typedecl_get(type) &&
325 eolian_typedecl_type_get(eolian_type_typedecl_get(type)) == EOLIAN_TYPEDECL_FUNCTION_POINTER)
326 {
327 eina_strbuf_append_printf(fallback_free_ownership, " (void)%s_data;\n", eolian_parameter_name_get(pr));
328 eina_strbuf_append_printf(fallback_free_ownership, " (void)%s_free_cb;\n", eolian_parameter_name_get(pr));
329 }
330 continue;
331 }
332
333 owners ++;
334
335 eina_strbuf_reset(param_call);
336
337 if (eolian_parameter_direction_get(pr) == EOLIAN_PARAMETER_INOUT)
338 eina_strbuf_append_char(param_call, '*');
339 eina_strbuf_append(param_call, eolian_parameter_name_get(pr));
340
341 //check if we might want to free or handle the children
342 if (!inner_type || !eolian_type_is_move(inner_type))
343 {
344 _generate_normal_free(&fallback_free_ownership, type, param_call, "");
345 }
346 else if (inner_type && eolian_type_is_move(inner_type))
347 {
348 _generate_iterative_free(&fallback_free_ownership, type, inner_type, pr, param_call);
349 }
350 }
351 eina_iterator_free(itr);
352
353 return owners;
354 }
355
356 static const char *
_get_reflect_initf(const Eolian_Type * abtp)357 _get_reflect_initf(const Eolian_Type *abtp)
358 {
359 Eolian_Type_Builtin_Type btp = eolian_type_builtin_type_get(abtp);
360 const char *initf = NULL;
361 switch (btp)
362 {
363 case EOLIAN_TYPE_BUILTIN_BYTE:
364 case EOLIAN_TYPE_BUILTIN_CHAR:
365 initf = "char"; break;
366 case EOLIAN_TYPE_BUILTIN_UBYTE:
367 initf = "uchar"; break;
368 case EOLIAN_TYPE_BUILTIN_SHORT:
369 case EOLIAN_TYPE_BUILTIN_USHORT:
370 case EOLIAN_TYPE_BUILTIN_INT:
371 case EOLIAN_TYPE_BUILTIN_UINT:
372 case EOLIAN_TYPE_BUILTIN_LONG:
373 case EOLIAN_TYPE_BUILTIN_ULONG:
374 case EOLIAN_TYPE_BUILTIN_INT64:
375 case EOLIAN_TYPE_BUILTIN_UINT64:
376 case EOLIAN_TYPE_BUILTIN_TIME:
377 case EOLIAN_TYPE_BUILTIN_FLOAT:
378 case EOLIAN_TYPE_BUILTIN_DOUBLE:
379 case EOLIAN_TYPE_BUILTIN_BOOL:
380 case EOLIAN_TYPE_BUILTIN_STRING:
381 case EOLIAN_TYPE_BUILTIN_STRINGSHARE:
382 initf = eolian_type_name_get(abtp); break;
383 default:
384 break;
385 }
386 return initf;
387 }
388
389 static void
_gen_reflect_get(Eina_Strbuf * buf,const char * cnamel,const Eolian_Function_Parameter * pr,const Eolian_Function * fid,Eina_Hash * refh)390 _gen_reflect_get(Eina_Strbuf *buf, const char *cnamel,
391 const Eolian_Function_Parameter *pr,
392 const Eolian_Function *fid, Eina_Hash *refh)
393 {
394 const Eolian_Type *valt = eolian_parameter_type_get(pr);
395 if (eolian_type_is_ptr(valt))
396 return;
397
398 const Eolian_Type *abtp = eolian_type_aliased_base_get(valt);
399 const char *initf = _get_reflect_initf(abtp);
400 if (!initf)
401 return;
402
403 Eolian_Function_Type et = (Eolian_Function_Type)eina_hash_find(refh, &fid);
404 if (et == EOLIAN_PROP_SET)
405 eina_hash_set(refh, &fid, (void *)EOLIAN_PROPERTY);
406 else
407 eina_hash_set(refh, &fid, (void *)EOLIAN_PROP_GET);
408
409 eina_strbuf_append(buf, "\nstatic Eina_Value\n");
410 eina_strbuf_append_printf(buf, "__eolian_%s_%s_get_reflect(const Eo *obj)\n",
411 cnamel, eolian_function_name_get(fid));
412 eina_strbuf_append(buf, "{\n");
413
414 Eina_Stringshare *ct = eolian_parameter_c_type_get(pr, EINA_TRUE);
415 const char *starsp = (ct[strlen(ct) - 1] != '*') ? " " : "";
416
417 Eina_Stringshare *fcn = eolian_function_full_c_name_get(fid, EOLIAN_PROP_GET);
418 eina_strbuf_append_printf(buf, " %s%sval = %s(obj);\n", ct, starsp, fcn);
419 eina_stringshare_del(fcn);
420 eina_stringshare_del(ct);
421
422 eina_strbuf_append_printf(buf, " return eina_value_%s_init(val);\n", initf);
423 eina_strbuf_append(buf, "}\n\n");
424 }
425
426 static void
_gen_reflect_set(Eina_Strbuf * buf,const char * cnamel,const Eolian_Function_Parameter * pr,const Eolian_Function * fid,Eina_Hash * refh)427 _gen_reflect_set(Eina_Strbuf *buf, const char *cnamel,
428 const Eolian_Function_Parameter *pr,
429 const Eolian_Function *fid, Eina_Hash *refh)
430 {
431 const Eolian_Type *valt = eolian_parameter_type_get(pr);
432 if (eolian_type_is_ptr(valt))
433 return;
434
435 const Eolian_Type *abtp = eolian_type_aliased_base_get(valt);
436 const char *initf = _get_reflect_initf(abtp);
437 if (!initf)
438 return;
439
440 Eolian_Function_Type et = (Eolian_Function_Type)eina_hash_find(refh, &fid);
441 if (et == EOLIAN_PROP_GET)
442 eina_hash_set(refh, &fid, (void *)EOLIAN_PROPERTY);
443 else
444 eina_hash_set(refh, &fid, (void *)EOLIAN_PROP_SET);
445
446 eina_strbuf_append(buf, "\nstatic Eina_Error\n");
447 eina_strbuf_append_printf(buf, "__eolian_%s_%s_set_reflect(Eo *obj, Eina_Value val)\n",
448 cnamel, eolian_function_name_get(fid));
449 eina_strbuf_append(buf, "{\n");
450 eina_strbuf_append(buf, " Eina_Error r = 0;");
451
452 Eina_Stringshare *ct = eolian_parameter_c_type_get(pr, EINA_FALSE);
453 const char *starsp = (ct[strlen(ct) - 1] != '*') ? " " : "";
454 eina_strbuf_append_printf(buf, " %s%scval;\n", ct, starsp);
455 eina_stringshare_del(ct);
456
457 eina_strbuf_append_printf(buf, " if (!eina_value_%s_convert(&val, &cval))\n", initf);
458 eina_strbuf_append(buf, " {\n");
459 eina_strbuf_append(buf, " r = EINA_ERROR_VALUE_FAILED;\n");
460 eina_strbuf_append(buf, " goto end;\n");
461 eina_strbuf_append(buf, " }\n");
462
463 Eina_Stringshare *fcn = eolian_function_full_c_name_get(fid, EOLIAN_PROP_SET);
464 eina_strbuf_append_printf(buf, " %s(obj, cval);\n", fcn);
465 eina_stringshare_del(fcn);
466
467 eina_strbuf_append(buf, " end:\n");
468 eina_strbuf_append(buf, " eina_value_flush(&val);\n");
469 eina_strbuf_append(buf, " return r;\n");
470
471 eina_strbuf_append(buf, "}\n\n");
472 }
473
474 static void
_emit_class_function(Eina_Strbuf * buf,const Eolian_Function * fid,const Eolian_Function_Type ftype,const Eolian_Type * rtp,const char * rtpn,Eina_Strbuf * params_full,const char * ocnamel,const char * func_suffix,Eina_Strbuf * params,const char * function_name)475 _emit_class_function(Eina_Strbuf *buf, const Eolian_Function *fid, const Eolian_Function_Type ftype, const Eolian_Type *rtp, const char *rtpn, Eina_Strbuf *params_full,
476 const char *ocnamel, const char *func_suffix, Eina_Strbuf *params, const char *function_name)
477 {
478 eina_strbuf_append(buf, "EOAPI ");
479 eina_strbuf_append(buf, rtpn);
480 eina_strbuf_append(buf, " ");
481 eina_strbuf_append(buf, function_name);
482 eina_strbuf_append(buf, "(");
483 if (eina_strbuf_length_get(params_full) == 0)
484 eina_strbuf_append(buf, "void");
485 else
486 eina_strbuf_append_buffer(buf, params_full);
487 eina_strbuf_append(buf, ")\n");
488 eina_strbuf_append(buf, "{\n");
489 eina_strbuf_append_printf(buf, " const Efl_Class *klass = %s();\n", eolian_class_c_get_function_name_get(eolian_function_class_get(fid)));
490 if (!!strcmp(rtpn, "void") && rtp)
491 {
492 const Eolian_Expression *default_value_expression = eolian_function_return_default_value_get(fid, ftype);
493
494 eina_strbuf_append_printf(buf, " EINA_SAFETY_ON_NULL_RETURN_VAL(klass,");
495 _append_defval(buf, default_value_expression, rtp, rtpn);
496 eina_strbuf_append_printf(buf, ");\n");
497
498 eina_strbuf_append(buf, " return ");
499 }
500 else
501 {
502 eina_strbuf_append(buf, " EINA_SAFETY_ON_NULL_RETURN(klass);\n");
503 eina_strbuf_append(buf, " ");
504 }
505 eina_strbuf_append_printf(buf, "_%s", ocnamel);
506 eina_strbuf_append_char(buf, '_');
507 eina_strbuf_append(buf, eolian_function_name_get(fid));
508 eina_strbuf_append(buf, func_suffix);
509 eina_strbuf_append(buf, "(");
510 eina_strbuf_append_buffer(buf, params);
511 eina_strbuf_append(buf, ");\n");
512 eina_strbuf_append(buf, "}\n");
513 }
514
515 static void
_gen_func(const Eolian_Class * cl,const Eolian_Function * fid,Eolian_Function_Type ftype,Eina_Strbuf * buf,const Eolian_Implement * impl,Eina_Hash * refh)516 _gen_func(const Eolian_Class *cl, const Eolian_Function *fid,
517 Eolian_Function_Type ftype, Eina_Strbuf *buf,
518 const Eolian_Implement *impl, Eina_Hash *refh)
519 {
520 Eina_Bool is_empty = eolian_implement_is_empty(impl, ftype);
521 Eina_Bool is_auto = eolian_implement_is_auto(impl, ftype);
522
523 if ((ftype != EOLIAN_PROP_GET) && (ftype != EOLIAN_PROP_SET))
524 ftype = eolian_function_type_get(fid);
525
526 Eina_Bool is_prop = (ftype == EOLIAN_PROP_GET || ftype == EOLIAN_PROP_SET);
527 Eina_Bool var_as_ret = EINA_FALSE;
528 /* assume we're not generating reflection api by default */
529 const Eolian_Function_Parameter *reflect_param = NULL;
530
531 const Eolian_Expression *def_ret = NULL;
532 const Eolian_Type *rtp = eolian_function_return_type_get(fid, ftype);
533 Eina_Stringshare *rtpn = NULL;
534 if (rtp)
535 {
536 is_auto = EINA_FALSE; /* can't do auto if func returns */
537 def_ret = eolian_function_return_default_value_get(fid, ftype);
538 rtpn = eolian_function_return_c_type_get(fid, ftype);
539 }
540
541 const char *func_suffix = "";
542 if (ftype == EOLIAN_PROP_GET)
543 {
544 func_suffix = "_get";
545 if (!rtp)
546 {
547 void *d1, *d2;
548 Eina_Iterator *itr = eolian_property_values_get(fid, ftype);
549 if (eina_iterator_next(itr, &d1) && !eina_iterator_next(itr, &d2))
550 {
551 Eolian_Function_Parameter *pr = d1;
552 rtp = eolian_parameter_type_get(pr);
553 /* reflect only when returning 1 val */
554 if (!eolian_parameter_is_by_ref(pr))
555 reflect_param = pr;
556 var_as_ret = EINA_TRUE;
557 def_ret = eolian_parameter_default_value_get(pr);
558 rtpn = eolian_parameter_c_type_get(pr, EINA_TRUE);
559 }
560 eina_iterator_free(itr);
561 }
562 }
563 else if (ftype == EOLIAN_PROP_SET)
564 {
565 func_suffix = "_set";
566 Eina_Iterator *itr = eolian_property_values_get(fid, ftype);
567 void *d1, *d2;
568 /* reflect with 1 value */
569 if (eina_iterator_next(itr, &d1) && !eina_iterator_next(itr, &d2))
570 {
571 Eolian_Function_Parameter *pr = d1;
572 if (!eolian_parameter_is_by_ref(pr))
573 reflect_param = pr;
574 }
575 eina_iterator_free(itr);
576 }
577
578 Eina_Strbuf *params = eina_strbuf_new(); /* par1, par2, par3, ... */
579 Eina_Strbuf *params_full = eina_strbuf_new(); /* T par1, U par2, ... for decl */
580 Eina_Strbuf *params_full_imp = eina_strbuf_new(); /* as above, for impl */
581 Eina_Strbuf *params_init = eina_strbuf_new(); /* default value inits */
582 Eina_Strbuf *fallback_free_ownership = eina_strbuf_new(); /* list of function calls that are freeing the owned parameters, or doing nothing on the normal parameters, NULL if there is nothing owned*/
583
584 /* property keys */
585 {
586 Eina_Iterator *itr = eolian_property_keys_get(fid, ftype);
587 if (itr) /* has keys: no reflection */
588 reflect_param = NULL;
589 Eolian_Function_Parameter *pr;
590 EINA_ITERATOR_FOREACH(itr, pr)
591 {
592 const char *prn = eolian_parameter_name_get(pr);
593 Eina_Stringshare *ptn = eolian_parameter_c_type_get(pr, EINA_FALSE);
594
595 if (eina_strbuf_length_get(params))
596 eina_strbuf_append(params, ", ");
597 eina_strbuf_append(params, prn);
598
599 if (eina_strbuf_length_get(params_full) || !eolian_function_is_static(fid))
600 {
601 eina_strbuf_append(params_full, ", ");
602 eina_strbuf_append(params_full_imp, ", ");
603 }
604 eina_strbuf_append_printf(params_full, "%s", ptn);
605 eina_strbuf_append_printf(params_full_imp, "%s", ptn);
606
607 if (ptn[strlen(ptn) - 1] != '*')
608 {
609 eina_strbuf_append_char(params_full, ' ');
610 eina_strbuf_append_char(params_full_imp, ' ');
611 }
612 eina_strbuf_append(params_full, prn);
613 eina_strbuf_append(params_full_imp, prn);
614 if (is_empty || is_auto)
615 eina_strbuf_append(params_full_imp, " EINA_UNUSED");
616
617 eina_stringshare_del(ptn);
618 }
619 eina_iterator_free(itr);
620 }
621
622 /* check if we have owning data that we would have to free in a error case */
623 if (ftype == EOLIAN_PROP_GET)
624 {
625 eina_strbuf_free(fallback_free_ownership);
626 fallback_free_ownership = NULL;
627 }
628 else
629 {
630 Eina_Iterator *itr;
631 int owners = 0;
632 Eina_Strbuf *param_call;
633
634 param_call = eina_strbuf_new();
635
636 if (is_prop)
637 {
638 itr = eolian_property_values_get(fid, ftype);
639 owners += _gen_function_param_fallback(itr, fallback_free_ownership, param_call);
640 itr = eolian_property_keys_get(fid, ftype);
641 owners += _gen_function_param_fallback(itr, fallback_free_ownership, param_call);
642 }
643 else
644 {
645 itr = eolian_function_parameters_get(fid);
646 owners += _gen_function_param_fallback(itr, fallback_free_ownership, param_call);
647 }
648
649 if (owners == 0)
650 {
651 eina_strbuf_free(fallback_free_ownership);
652 fallback_free_ownership = NULL;
653 }
654
655 eina_strbuf_free(param_call);
656 }
657
658 /* property values or method params if applicable */
659 if (!var_as_ret)
660 {
661 Eina_Iterator *itr;
662 if (is_prop)
663 itr = eolian_property_values_get(fid, ftype);
664 else
665 itr = eolian_function_parameters_get(fid);
666 Eolian_Function_Parameter *pr;
667 EINA_ITERATOR_FOREACH(itr, pr)
668 {
669 Eolian_Parameter_Direction pd = eolian_parameter_direction_get(pr);
670 const Eolian_Expression *dfv = eolian_parameter_default_value_get(pr);
671 const char *prn = eolian_parameter_name_get(pr);
672 const Eolian_Type *pt = eolian_parameter_type_get(pr);
673 Eina_Stringshare *ptn = eolian_parameter_c_type_get(pr, EINA_FALSE);
674 const Eolian_Typedecl *ptd = eolian_type_typedecl_get(pt);
675
676 Eina_Bool had_star = ptn[strlen(ptn) - 1] == '*';
677 const char *add_star = _get_add_star(ftype, pd);
678
679 if (ptd && eolian_typedecl_type_get(ptd) == EOLIAN_TYPEDECL_FUNCTION_POINTER)
680 {
681 _gen_func_pointer_param(prn, ptn, ptd, params, params_full, params_full_imp, is_empty);
682 eina_stringshare_del(ptn);
683 continue;
684 }
685
686 if (eina_strbuf_length_get(params))
687 eina_strbuf_append(params, ", ");
688
689 if (eina_strbuf_length_get(params_full_imp) || !eolian_function_is_static(fid))
690 eina_strbuf_append(params_full_imp, ", ");
691 eina_strbuf_append(params_full_imp, ptn);
692 if (!had_star)
693 eina_strbuf_append_char(params_full_imp, ' ');
694 eina_strbuf_append(params_full_imp, add_star);
695 eina_strbuf_append(params_full_imp, prn);
696 if ((!dfv || ftype == EOLIAN_PROP_SET) && is_empty)
697 eina_strbuf_append(params_full_imp, " EINA_UNUSED");
698 eina_strbuf_append(params, prn);
699
700 if (eina_strbuf_length_get(params_full) || !eolian_function_is_static(fid))
701 eina_strbuf_append(params_full, ", ");
702 eina_strbuf_append(params_full, ptn);
703 if (!had_star)
704 eina_strbuf_append_char(params_full, ' ');
705 eina_strbuf_append(params_full, add_star);
706 eina_strbuf_append(params_full, prn);
707
708 if (is_auto)
709 {
710 if (ftype == EOLIAN_PROP_SET)
711 eina_strbuf_append_printf(params_init, " pd->%s = %s;\n", prn, prn);
712 else
713 {
714 eina_strbuf_append_printf(params_init, " if (%s) *%s = pd->%s;\n",
715 prn, prn, prn);
716 }
717 }
718 else if ((ftype != EOLIAN_PROP_SET) && dfv)
719 {
720 Eolian_Value val = eolian_expression_eval(dfv, EOLIAN_MASK_ALL);
721 if (val.type)
722 {
723 Eina_Stringshare *vals = eolian_expression_value_to_literal(&val);
724 eina_strbuf_append_printf(params_init, " if (%s) *%s = %s;",
725 prn, prn, vals);
726 eina_stringshare_del(vals);
727 if (eolian_expression_type_get(dfv) == EOLIAN_EXPR_NAME)
728 {
729 Eina_Stringshare *vs = eolian_expression_serialize(dfv);
730 eina_strbuf_append_printf(params_init, " /* %s */", vs);
731 eina_stringshare_del(vs);
732 }
733 eina_strbuf_append_char(params_init, '\n');
734 }
735 }
736
737 eina_stringshare_del(ptn);
738 }
739 eina_iterator_free(itr);
740 }
741
742 Eina_Bool impl_same_class = (eolian_implement_class_get(impl) == cl);
743 Eina_Bool impl_need = EINA_TRUE;
744 if (impl_same_class && eolian_implement_is_pure_virtual(impl, ftype))
745 impl_need = EINA_FALSE;
746
747 if (!rtpn)
748 rtpn = eina_stringshare_add("void");
749
750 char *cname = NULL, *cnamel = NULL, *ocnamel = NULL;
751 eo_gen_class_names_get(cl, &cname, NULL, &cnamel);
752 eo_gen_class_names_get(eolian_implement_class_get(impl), NULL, NULL, &ocnamel);
753
754 if (impl_need)
755 {
756 /* figure out the data type */
757 Eina_Stringshare *dt = NULL;
758 if (eolian_function_is_static(fid))
759 dt = eina_stringshare_add("void");
760 else
761 dt = eolian_class_c_data_type_get(cl);
762
763 eina_strbuf_append_char(buf, '\n');
764 /* no need for prototype with empty/auto impl */
765 if (!is_empty && !is_auto)
766 {
767 /* T _class_name[_orig_class]_func_name_suffix */
768 eina_strbuf_append(buf, rtpn);
769 if (rtpn[strlen(rtpn) - 1] != '*')
770 eina_strbuf_append_char(buf, ' ');
771 eina_strbuf_append_char(buf, '_');
772 eina_strbuf_append(buf, cnamel);
773 if (!impl_same_class)
774 eina_strbuf_append_printf(buf, "_%s", ocnamel);
775 eina_strbuf_append_char(buf, '_');
776 eina_strbuf_append(buf, eolian_function_name_get(fid));
777 eina_strbuf_append(buf, func_suffix);
778 /* ([const ]Eo *obj, Data_Type *pd, impl_full_params); */
779 eina_strbuf_append_char(buf, '(');
780 if (!eolian_function_is_static(fid))
781 {
782 if ((ftype == EOLIAN_PROP_GET) || eolian_function_object_is_const(fid))
783 eina_strbuf_append(buf, "const ");
784 eina_strbuf_append(buf, "Eo *obj, ");
785 eina_strbuf_append(buf, dt);
786 eina_strbuf_append(buf, " *pd");
787 }
788 eina_strbuf_append(buf, eina_strbuf_string_get(params_full_imp));
789 if (eina_strbuf_length_get(params_full_imp) == 0 && eolian_function_is_static(fid))
790 eina_strbuf_append(buf, "void");
791 eina_strbuf_append(buf, ");\n\n");
792 }
793
794 if (is_empty || is_auto || eina_strbuf_length_get(params_init))
795 {
796 /* we need to give the internal function name to Eo,
797 * use this hash table as indication
798 */
799 if (ftype == EOLIAN_PROP_SET)
800 eina_hash_add(_funcs_params_init_set, &impl, impl);
801 else
802 eina_hash_add(_funcs_params_init_get, &impl, impl);
803 /* generation of intermediate __eolian_... */
804 eina_strbuf_append(buf, "static ");
805 eina_strbuf_append(buf, rtpn);
806 if (rtpn[strlen(rtpn) - 1] != '*')
807 eina_strbuf_append_char(buf, ' ');
808 eina_strbuf_append(buf, "__eolian_");
809 eina_strbuf_append(buf, cnamel);
810 if (!impl_same_class)
811 eina_strbuf_append_printf(buf, "_%s", ocnamel);
812 eina_strbuf_append_char(buf, '_');
813 eina_strbuf_append(buf, eolian_function_name_get(fid));
814 eina_strbuf_append(buf, func_suffix);
815 eina_strbuf_append_char(buf, '(');
816 if ((ftype == EOLIAN_PROP_GET) || eolian_function_object_is_const(fid))
817 eina_strbuf_append(buf, "const ");
818 eina_strbuf_append(buf, "Eo *obj");
819 if (is_empty || is_auto)
820 eina_strbuf_append(buf, " EINA_UNUSED");
821 eina_strbuf_append(buf, ", ");
822 eina_strbuf_append(buf, dt);
823 eina_strbuf_append(buf, " *pd");
824 if (is_empty || (is_auto && !eina_strbuf_length_get(params_init)))
825 eina_strbuf_append(buf, " EINA_UNUSED");
826 eina_strbuf_append(buf, eina_strbuf_string_get(params_full_imp));
827 eina_strbuf_append(buf, ")\n{\n");
828 }
829 if (eina_strbuf_length_get(params_init))
830 eina_strbuf_append(buf, eina_strbuf_string_get(params_init));
831 if (is_empty || is_auto)
832 {
833 if (rtp)
834 {
835 eina_strbuf_append(buf, " return ");
836 _append_defval(buf, def_ret, rtp, rtpn);
837 eina_strbuf_append(buf, ";\n");
838 }
839 eina_strbuf_append(buf, "}\n\n");
840 }
841 else if (eina_strbuf_length_get(params_init))
842 {
843 eina_strbuf_append(buf, " ");
844 if (rtp)
845 eina_strbuf_append(buf, "return ");
846 eina_strbuf_append_char(buf, '_');
847 eina_strbuf_append(buf, cnamel);
848 if (!impl_same_class)
849 eina_strbuf_append_printf(buf, "_%s", ocnamel);
850 eina_strbuf_append_char(buf, '_');
851 eina_strbuf_append(buf, eolian_function_name_get(fid));
852 eina_strbuf_append(buf, func_suffix);
853 eina_strbuf_append(buf, "(obj, pd, ");
854 eina_strbuf_append(buf, eina_strbuf_string_get(params));
855 eina_strbuf_append(buf, ");\n}\n\n");
856 }
857
858 eina_stringshare_del(dt);
859 }
860
861 if (impl_same_class && !eolian_function_is_static(fid))
862 {
863 /* generate reflection implementation */
864 if (reflect_param)
865 {
866 if (ftype == EOLIAN_PROP_GET)
867 _gen_reflect_get(buf, cnamel, reflect_param, fid, refh);
868 else
869 _gen_reflect_set(buf, cnamel, reflect_param, fid, refh);
870 }
871
872 void *data;
873 Eina_Iterator *itr = eolian_property_keys_get(fid, ftype);
874 Eina_Bool has_params = eina_iterator_next(itr, &data);
875 eina_iterator_free(itr);
876
877 if (!has_params && !var_as_ret)
878 {
879 if (is_prop)
880 itr = eolian_property_values_get(fid, ftype);
881 else
882 itr = eolian_function_parameters_get(fid);
883 has_params = eina_iterator_next(itr, &data);
884 eina_iterator_free(itr);
885 }
886
887 if (fallback_free_ownership)
888 {
889 //we have owned parameters we need to take care of
890 eina_strbuf_append_printf(buf, "static void\n");
891 eina_strbuf_append_printf(buf, "_%s_ownership_fallback(%s)\n{\n", eolian_function_full_c_name_get(fid, ftype), eina_strbuf_string_get(params_full) + 2);
892
893 eina_strbuf_append_buffer(buf, fallback_free_ownership);
894 eina_strbuf_append_printf(buf, "}\n\n");
895 }
896
897 eina_strbuf_append(buf, "EOAPI EFL_");
898 if (!strcmp(rtpn, "void"))
899 eina_strbuf_append(buf, "VOID_");
900 eina_strbuf_append(buf, "FUNC_BODY");
901 if (has_params)
902 eina_strbuf_append_char(buf, 'V');
903 if ((ftype == EOLIAN_PROP_GET) || eolian_function_object_is_const(fid)
904 || eolian_function_is_static(fid))
905 {
906 eina_strbuf_append(buf, "_CONST");
907 }
908
909 if (fallback_free_ownership)
910 eina_strbuf_append(buf, "_FALLBACK");
911
912 eina_strbuf_append_char(buf, '(');
913
914 Eina_Stringshare *eofn = eolian_function_full_c_name_get(fid, ftype);
915 eina_strbuf_append(buf, eofn);
916
917 if (strcmp(rtpn, "void"))
918 {
919 eina_strbuf_append_printf(buf, ", %s, ", rtpn);
920 _append_defval(buf, def_ret, rtp, rtpn);
921 }
922
923 if (fallback_free_ownership)
924 eina_strbuf_append_printf(buf, ", _%s_ownership_fallback(%s);", eolian_function_full_c_name_get(fid, ftype), eina_strbuf_string_get(params));
925
926 if (has_params)
927 {
928 eina_strbuf_append(buf, ", EFL_FUNC_CALL(");
929 eina_strbuf_append(buf, eina_strbuf_string_get(params));
930 eina_strbuf_append_char(buf, ')');
931 eina_strbuf_append(buf, eina_strbuf_string_get(params_full));
932 }
933
934 eina_strbuf_append(buf, ");\n");
935
936 eina_stringshare_del(eofn);
937 }
938 if (impl_same_class && eolian_function_is_static(fid))
939 _emit_class_function(buf, fid, ftype, rtp, rtpn, params_full, ocnamel, func_suffix, params, eolian_function_full_c_name_get(fid, ftype));
940
941 free(cname);
942 free(cnamel);
943 free(ocnamel);
944
945 eina_stringshare_del(rtpn);
946
947 eina_strbuf_free(params);
948 eina_strbuf_free(params_full);
949 eina_strbuf_free(params_full_imp);
950 eina_strbuf_free(params_init);
951 if (fallback_free_ownership)
952 eina_strbuf_free(fallback_free_ownership);
953 }
954
955 static void
_gen_opfunc(const Eolian_Function * fid,Eolian_Function_Type ftype,Eina_Strbuf * buf,const Eolian_Implement * impl,Eina_Bool pinit,const char * cnamel,const char * ocnamel)956 _gen_opfunc(const Eolian_Function *fid, Eolian_Function_Type ftype,
957 Eina_Strbuf *buf, const Eolian_Implement *impl, Eina_Bool pinit,
958 const char *cnamel, const char *ocnamel)
959 {
960 Eina_Stringshare *fnm = eolian_function_full_c_name_get(fid, ftype);
961 eina_strbuf_append(buf, " EFL_OBJECT_OP_FUNC(");
962 eina_strbuf_append(buf, fnm);
963 eina_strbuf_append(buf, ", ");
964 if (!ocnamel && eolian_implement_is_pure_virtual(impl, ftype))
965 eina_strbuf_append(buf, "NULL),\n");
966 else
967 {
968 if (pinit)
969 eina_strbuf_append(buf, "__eolian");
970 eina_strbuf_append_printf(buf, "_%s_", cnamel);
971 if (ocnamel)
972 eina_strbuf_append_printf(buf, "%s_", ocnamel);
973 eina_strbuf_append(buf, eolian_function_name_get(fid));
974 if (ftype == EOLIAN_PROP_GET)
975 eina_strbuf_append(buf, "_get");
976 else if (ftype == EOLIAN_PROP_SET)
977 eina_strbuf_append(buf, "_set");
978 eina_strbuf_append(buf, "),\n");
979 }
980 }
981
982 static void
_gen_reflop(const Eolian_Function * fid,Eina_Strbuf * buf,const char * cnamel,Eina_Hash * refh)983 _gen_reflop(const Eolian_Function *fid, Eina_Strbuf *buf, const char *cnamel, Eina_Hash *refh)
984 {
985 Eolian_Function_Type aftype = (Eolian_Function_Type)eina_hash_find(refh, &fid);
986 if (aftype == EOLIAN_UNRESOLVED)
987 return;
988
989 eina_strbuf_append_printf(buf, " {\"%s\", ", eolian_function_name_get(fid));
990
991 if (aftype == EOLIAN_PROP_SET || aftype == EOLIAN_PROPERTY)
992 {
993 eina_strbuf_append_printf(buf, "__eolian_%s_%s_set_reflect, ",
994 cnamel, eolian_function_name_get(fid));
995 }
996 else
997 eina_strbuf_append(buf, "NULL, ");
998
999 if (aftype == EOLIAN_PROP_GET || aftype == EOLIAN_PROPERTY)
1000 {
1001 eina_strbuf_append_printf(buf, "__eolian_%s_%s_get_reflect},\n",
1002 cnamel, eolian_function_name_get(fid));
1003 }
1004 else
1005 eina_strbuf_append(buf, "NULL},\n");
1006 }
1007
1008 static void
_gen_initializer(const Eolian_Class * cl,Eina_Strbuf * buf,Eina_Hash * refh)1009 _gen_initializer(const Eolian_Class *cl, Eina_Strbuf *buf, Eina_Hash *refh)
1010 {
1011 char *cnamel = NULL, *cnameu = NULL;
1012 eo_gen_class_names_get(cl, NULL, &cnameu, &cnamel);
1013
1014 eina_strbuf_append(buf, "\nstatic Eina_Bool\n_");
1015 eina_strbuf_append(buf, cnamel);
1016 eina_strbuf_append(buf, "_class_initializer(Efl_Class *klass)\n{\n");
1017 eina_strbuf_append(buf, " const Efl_Object_Ops *opsp = NULL;\n\n");
1018 eina_strbuf_append(buf, " const Efl_Object_Property_Reflection_Ops *ropsp = NULL;\n\n");
1019
1020 Eina_Strbuf *ops = eina_strbuf_new();
1021 Eina_Strbuf *refls = eina_strbuf_new();
1022
1023 /* start over with clean itearator */
1024 const Eolian_Implement *imp;
1025 Eina_Iterator *itr = eolian_class_implements_get(cl);
1026 EINA_ITERATOR_FOREACH(itr, imp)
1027 {
1028 const Eolian_Class *icl = eolian_implement_class_get(imp);
1029 Eolian_Function_Type ftype;
1030 const Eolian_Function *fid = eolian_implement_function_get(imp, &ftype);
1031
1032 if (eolian_function_is_static(fid)) continue;
1033
1034 if (!eina_strbuf_length_get(ops))
1035 eina_strbuf_append_printf(ops, " EFL_OPS_DEFINE(ops,\n");
1036
1037 Eina_Bool found_get = !!eina_hash_find(_funcs_params_init_get, &imp);
1038 Eina_Bool found_set = !!eina_hash_find(_funcs_params_init_set, &imp);
1039 char *ocnamel = NULL;
1040 if (cl != icl)
1041 eo_gen_class_names_get(icl, NULL, NULL, &ocnamel);
1042
1043 switch (ftype)
1044 {
1045 case EOLIAN_PROP_GET:
1046 _gen_opfunc(fid, EOLIAN_PROP_GET, ops, imp, found_get, cnamel, ocnamel);
1047 _gen_reflop(fid, refls, cnamel, refh);
1048 break;
1049 case EOLIAN_PROP_SET:
1050 _gen_opfunc(fid, EOLIAN_PROP_SET, ops, imp, found_set, cnamel, ocnamel);
1051 _gen_reflop(fid, refls, cnamel, refh);
1052 break;
1053 case EOLIAN_PROPERTY:
1054 _gen_opfunc(fid, EOLIAN_PROP_SET, ops, imp, found_set, cnamel, ocnamel);
1055 _gen_opfunc(fid, EOLIAN_PROP_GET, ops, imp, found_get, cnamel, ocnamel);
1056 _gen_reflop(fid, refls, cnamel, refh);
1057 break;
1058 default:
1059 _gen_opfunc(fid, EOLIAN_METHOD, ops, imp, found_get, cnamel, ocnamel);
1060 break;
1061 }
1062
1063 free(ocnamel);
1064 }
1065 eina_iterator_free(itr);
1066
1067 if (eina_strbuf_length_get(ops))
1068 {
1069 /* make sure the extras are defined */
1070 eina_strbuf_append_printf(buf, "#ifndef %s_EXTRA_OPS\n", cnameu);
1071 eina_strbuf_append_printf(buf, "#define %s_EXTRA_OPS\n", cnameu);
1072 eina_strbuf_append(buf, "#endif\n\n");
1073
1074 eina_strbuf_append_printf(ops, " %s_EXTRA_OPS\n );\n", cnameu);
1075 eina_strbuf_append(buf, eina_strbuf_string_get(ops));
1076 eina_strbuf_append(buf, " opsp = &ops;\n\n");
1077 }
1078 else
1079 {
1080 /* no predefined, but if custom ones are required define it anyway */
1081 eina_strbuf_append_printf(buf, "#ifdef %s_EXTRA_OPS\n", cnameu);
1082 eina_strbuf_append_printf(buf, " EFL_OPS_DEFINE(ops, %s_EXTRA_OPS);\n", cnameu);
1083 eina_strbuf_append(buf, " opsp = &ops;\n");
1084 eina_strbuf_append(buf, "#endif\n\n");
1085 }
1086
1087 if (eina_strbuf_length_get(refls))
1088 {
1089 eina_strbuf_append(buf, " static const Efl_Object_Property_Reflection refl_table[] = {\n");
1090 eina_strbuf_append_buffer(buf, refls);
1091 eina_strbuf_append(buf, " };\n");
1092 eina_strbuf_append(buf, " static const Efl_Object_Property_Reflection_Ops rops = {\n");
1093 eina_strbuf_append(buf, " refl_table, EINA_C_ARRAY_LENGTH(refl_table)\n");
1094 eina_strbuf_append(buf, " };\n");
1095 eina_strbuf_append(buf, " ropsp = &rops;\n\n");
1096 }
1097
1098 eina_strbuf_append(buf, " return efl_class_functions_set(klass, opsp, ropsp);\n");
1099
1100 eina_strbuf_free(ops);
1101 eina_strbuf_free(refls);
1102
1103 eina_strbuf_append(buf, "}\n\n");
1104
1105 free(cnameu);
1106 free(cnamel);
1107 }
1108
1109 void
eo_gen_source_gen(const Eolian_Class * cl,Eina_Strbuf * buf)1110 eo_gen_source_gen(const Eolian_Class *cl, Eina_Strbuf *buf)
1111 {
1112 if (!cl)
1113 return;
1114
1115 _funcs_params_init_get = eina_hash_pointer_new(NULL);
1116 _funcs_params_init_set = eina_hash_pointer_new(NULL);
1117
1118 char *cnamel = NULL;
1119 eo_gen_class_names_get(cl, NULL, NULL, &cnamel);
1120
1121 /* event section, they come first */
1122 {
1123 Eina_Iterator *itr = eolian_class_events_get(cl);
1124 Eolian_Event *ev;
1125 EINA_ITERATOR_FOREACH(itr, ev)
1126 {
1127 Eina_Stringshare *evn = eolian_event_c_macro_get(ev);
1128 eina_strbuf_append(buf, "EWAPI const Efl_Event_Description _");
1129 eina_strbuf_append(buf, evn);
1130 eina_strbuf_append(buf, " =\n EFL_EVENT_DESCRIPTION");
1131 if (eolian_event_is_hot(ev))
1132 eina_strbuf_append(buf, "_HOT");
1133 if (eolian_event_is_restart(ev))
1134 eina_strbuf_append(buf, "_RESTART");
1135 eina_strbuf_append_printf(buf, "(\"%s\");\n", eolian_event_name_get(ev));
1136 eina_stringshare_del(evn);
1137 }
1138 eina_iterator_free(itr);
1139 }
1140
1141 /* Eolian_Function -> Eolian_Function_Type
1142 * maps which parts of which functions are qualified for reflection
1143 */
1144 Eina_Hash *refh = eina_hash_pointer_new(NULL);
1145
1146 /* method section */
1147 {
1148 Eina_Iterator *itr = eolian_class_implements_get(cl);
1149 const Eolian_Implement *imp;
1150 EINA_ITERATOR_FOREACH(itr, imp)
1151 {
1152 Eolian_Function_Type ftype = EOLIAN_UNRESOLVED;
1153 const Eolian_Function *fid = eolian_implement_function_get(imp, &ftype);
1154 switch (ftype)
1155 {
1156 case EOLIAN_PROP_GET:
1157 case EOLIAN_PROP_SET:
1158 _gen_func(cl, fid, ftype, buf, imp, refh);
1159 break;
1160 case EOLIAN_PROPERTY:
1161 _gen_func(cl, fid, EOLIAN_PROP_SET, buf, imp, refh);
1162 _gen_func(cl, fid, EOLIAN_PROP_GET, buf, imp, refh);
1163 break;
1164 default:
1165 _gen_func(cl, fid, EOLIAN_METHOD, buf, imp, refh);
1166 }
1167 }
1168 eina_iterator_free(itr);
1169 }
1170
1171 /* class initializer - contains method defs */
1172 _gen_initializer(cl, buf, refh);
1173 eina_hash_free(refh);
1174
1175 /* class description */
1176 eina_strbuf_append(buf, "static const Efl_Class_Description _");
1177 eina_strbuf_append(buf, cnamel);
1178 eina_strbuf_append(buf, "_class_desc = {\n"
1179 " EO_VERSION,\n");
1180 eina_strbuf_append_printf(buf, " \"%s\",\n", eolian_class_name_get(cl));
1181
1182 switch (eolian_class_type_get(cl))
1183 {
1184 case EOLIAN_CLASS_ABSTRACT:
1185 eina_strbuf_append(buf, " EFL_CLASS_TYPE_REGULAR_NO_INSTANT,\n");
1186 break;
1187 case EOLIAN_CLASS_MIXIN:
1188 eina_strbuf_append(buf, " EFL_CLASS_TYPE_MIXIN,\n");
1189 break;
1190 case EOLIAN_CLASS_INTERFACE:
1191 eina_strbuf_append(buf, " EFL_CLASS_TYPE_INTERFACE,\n");
1192 break;
1193 default:
1194 eina_strbuf_append(buf, " EFL_CLASS_TYPE_REGULAR,\n");
1195 break;
1196 }
1197
1198 Eina_Stringshare *dt = eolian_class_c_data_type_get(cl);
1199 if (!strcmp(dt, "void"))
1200 eina_strbuf_append(buf, " 0,\n");
1201 else
1202 eina_strbuf_append_printf(buf, " sizeof(%s),\n", dt);
1203 eina_stringshare_del(dt);
1204
1205 eina_strbuf_append_printf(buf, " _%s_class_initializer,\n", cnamel);
1206
1207 if (eolian_class_ctor_enable_get(cl))
1208 eina_strbuf_append_printf(buf, " _%s_class_constructor,\n", cnamel);
1209 else
1210 eina_strbuf_append(buf, " NULL,\n");
1211
1212 if (eolian_class_dtor_enable_get(cl))
1213 eina_strbuf_append_printf(buf, " _%s_class_destructor\n", cnamel);
1214 else
1215 eina_strbuf_append(buf, " NULL\n");
1216
1217 eina_strbuf_append(buf, "};\n\n");
1218
1219 /* class def */
1220 eina_strbuf_append(buf, "EFL_DEFINE_CLASS(");
1221
1222 Eina_Stringshare *cgfunc = eolian_class_c_get_function_name_get(cl);
1223 eina_strbuf_append(buf, cgfunc);
1224 eina_stringshare_del(cgfunc);
1225
1226 eina_strbuf_append_printf(buf, ", &_%s_class_desc", cnamel);
1227
1228 /* inherits in EFL_DEFINE_CLASS */
1229 {
1230 const Eolian_Class *icl = eolian_class_parent_get(cl);
1231 /* no inherits, NULL parent */
1232 if (!icl)
1233 eina_strbuf_append(buf, ", NULL");
1234 else
1235 {
1236 Eina_Stringshare *mname = eolian_class_c_macro_get(icl);
1237 eina_strbuf_append_printf(buf, ", %s", mname);
1238 eina_stringshare_del(mname);
1239 }
1240 Eina_Iterator *itr = eolian_class_extensions_get(cl);
1241 EINA_ITERATOR_FOREACH(itr, icl)
1242 {
1243 Eina_Stringshare *mname = eolian_class_c_macro_get(icl);
1244 eina_strbuf_append_printf(buf, ", %s", mname);
1245 eina_stringshare_del(mname);
1246 }
1247 eina_iterator_free(itr);
1248 }
1249
1250 /* terminate inherits */
1251 eina_strbuf_append(buf, ", NULL);\n");
1252
1253 /* and we're done */
1254 free(cnamel);
1255 eina_hash_free(_funcs_params_init_get);
1256 eina_hash_free(_funcs_params_init_set);
1257 }
1258
1259 static void
_gen_params(const Eolian_Function * fid,Eolian_Function_Type ftype,Eina_Bool var_as_ret,Eina_Strbuf * params,Eina_Strbuf * params_full)1260 _gen_params(const Eolian_Function *fid, Eolian_Function_Type ftype,
1261 Eina_Bool var_as_ret, Eina_Strbuf *params, Eina_Strbuf *params_full)
1262 {
1263 Eina_Bool is_prop = (ftype == EOLIAN_PROP_GET || ftype == EOLIAN_PROP_SET);
1264
1265 /* property keys */
1266 {
1267 Eina_Iterator *itr = eolian_property_keys_get(fid, ftype);
1268 Eolian_Function_Parameter *pr;
1269 EINA_ITERATOR_FOREACH(itr, pr)
1270 {
1271 const char *prn = eolian_parameter_name_get(pr);
1272 Eina_Stringshare *ptn = eolian_parameter_c_type_get(pr, EINA_FALSE);
1273
1274 eina_strbuf_append(params, ", ");
1275 eina_strbuf_append(params, prn);
1276
1277 eina_strbuf_append_printf(params_full, ", %s", ptn);
1278 if (ptn[strlen(ptn) - 1] != '*')
1279 eina_strbuf_append_char(params_full, ' ');
1280 eina_strbuf_append(params_full, prn);
1281
1282 eina_stringshare_del(ptn);
1283 }
1284 eina_iterator_free(itr);
1285 }
1286
1287 /* property values or method params if applicable */
1288 if (!var_as_ret)
1289 {
1290 Eina_Iterator *itr;
1291 if (is_prop)
1292 itr = eolian_property_values_get(fid, ftype);
1293 else
1294 itr = eolian_function_parameters_get(fid);
1295 Eolian_Function_Parameter *pr;
1296 EINA_ITERATOR_FOREACH(itr, pr)
1297 {
1298 Eolian_Parameter_Direction pd = eolian_parameter_direction_get(pr);
1299 const char *prn = eolian_parameter_name_get(pr);
1300 const Eolian_Type *pt = eolian_parameter_type_get(pr);
1301 const Eolian_Typedecl *ptd = eolian_type_typedecl_get(pt);
1302 Eina_Stringshare *ptn = eolian_parameter_c_type_get(pr, EINA_FALSE);
1303
1304 if (ptd && eolian_typedecl_type_get(ptd) == EOLIAN_TYPEDECL_FUNCTION_POINTER)
1305 {
1306 eina_strbuf_append_printf(params, ", %s_data, %s, %s_free_cb", prn, prn, prn);
1307 eina_strbuf_append_printf(params_full, ", void *%s_data, %s %s, Eina_Free_Cb %s_free_cb", prn, ptn, prn, prn);
1308
1309 eina_stringshare_del(ptn);
1310 continue;
1311 }
1312
1313 Eina_Bool had_star = ptn[strlen(ptn) - 1] == '*';
1314 const char *add_star = _get_add_star(ftype, pd);
1315
1316 eina_strbuf_append(params, ", ");
1317 eina_strbuf_append(params, prn);
1318
1319 eina_strbuf_append(params_full, ", ");
1320 eina_strbuf_append(params_full, ptn);
1321 if (!had_star)
1322 eina_strbuf_append_char(params_full, ' ');
1323 eina_strbuf_append(params_full, add_star);
1324 eina_strbuf_append(params_full, prn);
1325
1326 eina_stringshare_del(ptn);
1327 }
1328 eina_iterator_free(itr);
1329 }
1330 }
1331
1332 static void
_gen_proto(const Eolian_Class * cl,const Eolian_Function * fid,Eolian_Function_Type ftype,Eina_Strbuf * buf,const Eolian_Implement * impl,const char * dtype,const char * cnamel)1333 _gen_proto(const Eolian_Class *cl, const Eolian_Function *fid,
1334 Eolian_Function_Type ftype, Eina_Strbuf *buf,
1335 const Eolian_Implement *impl, const char *dtype, const char *cnamel)
1336 {
1337 Eina_Bool impl_same_class = (eolian_implement_class_get(impl) == cl);
1338 if (impl_same_class && eolian_implement_is_pure_virtual(impl, ftype))
1339 return;
1340
1341 char *ocnamel = NULL;
1342 if (!impl_same_class)
1343 eo_gen_class_names_get(eolian_implement_class_get(impl), NULL, NULL, &ocnamel);
1344
1345 char fname[256 + 128], iname[256];
1346 if (!impl_same_class)
1347 snprintf(iname, sizeof(iname), "%s_%s", cnamel, ocnamel);
1348 else
1349 snprintf(iname, sizeof(iname), "%s", cnamel);
1350
1351 snprintf(fname, sizeof(fname), "_%s_%s%s", iname, eolian_function_name_get(fid),
1352 (ftype == EOLIAN_PROP_GET)
1353 ? "_get" : ((ftype == EOLIAN_PROP_SET) ? "_set" : ""));
1354
1355 if (_function_exists(fname, buf))
1356 {
1357 free(ocnamel);
1358 return;
1359 }
1360
1361 printf("generating function %s...\n", fname);
1362
1363 Eina_Bool var_as_ret = EINA_FALSE;
1364 const Eolian_Type *rtp = eolian_function_return_type_get(fid, ftype);
1365 Eina_Stringshare *rtpn = NULL;
1366 if ((ftype == EOLIAN_PROP_GET) && !rtp)
1367 {
1368 void *d1, *d2;
1369 Eina_Iterator *itr = eolian_property_values_get(fid, ftype);
1370 if (eina_iterator_next(itr, &d1) && !eina_iterator_next(itr, &d2))
1371 {
1372 Eolian_Function_Parameter *pr = d1;
1373 rtp = eolian_parameter_type_get(pr);
1374 rtpn = eolian_parameter_c_type_get(pr, EINA_FALSE);
1375 var_as_ret = EINA_TRUE;
1376 }
1377 eina_iterator_free(itr);
1378 }
1379
1380 eina_strbuf_append(buf, "EOLIAN static ");
1381 if (rtp)
1382 {
1383 if (!rtpn)
1384 rtpn = eolian_function_return_c_type_get(fid, ftype);
1385 eina_strbuf_append(buf, rtpn);
1386 eina_stringshare_del(rtpn);
1387 }
1388 else
1389 eina_strbuf_append(buf, "void");
1390
1391 eina_strbuf_append_printf(buf, "\n%s(", fname);
1392
1393 if ((ftype == EOLIAN_PROP_GET) || eolian_function_object_is_const(fid))
1394 eina_strbuf_append(buf, "const ");
1395
1396 eina_strbuf_append(buf, "Eo *obj, ");
1397 if (strcmp(dtype, "void"))
1398 eina_strbuf_append_printf(buf, "%s *pd", dtype);
1399 else
1400 eina_strbuf_append(buf, "void *pd EINA_UNUSED");
1401
1402 /* gen params here */
1403 Eina_Strbuf *params = eina_strbuf_new();
1404 Eina_Strbuf *params_full = eina_strbuf_new();
1405 _gen_params(fid, ftype, var_as_ret, params, params_full);
1406
1407 if (eina_strbuf_length_get(params_full))
1408 eina_strbuf_append(buf, eina_strbuf_string_get(params_full));
1409
1410 eina_strbuf_append(buf, ")\n{\n");
1411
1412 const char *efname = eolian_function_name_get(fid);
1413 if (strlen(efname) >= (sizeof("destructor") - 1) && !impl_same_class)
1414 if (!strcmp(efname + strlen(efname) - sizeof("destructor") + 1, "destructor"))
1415 {
1416 Eina_Stringshare *fcn = eolian_function_full_c_name_get(fid, ftype);
1417 Eina_Stringshare *mname = eolian_class_c_macro_get(cl);
1418 eina_strbuf_append(buf, " ");
1419 eina_strbuf_append(buf, fcn);
1420 eina_stringshare_del(fcn);
1421 eina_strbuf_append_printf(buf, "(efl_super(obj, %s)", mname);
1422 eina_stringshare_del(mname);
1423 if (eina_strbuf_length_get(params))
1424 eina_strbuf_append(buf, eina_strbuf_string_get(params));
1425 eina_strbuf_append(buf, ");\n");
1426 }
1427 eina_strbuf_append(buf, "\n}\n\n");
1428
1429 eina_strbuf_free(params_full);
1430 eina_strbuf_free(params);
1431 free(ocnamel);
1432 }
1433
1434 void
eo_gen_impl_gen(const Eolian_Class * cl,Eina_Strbuf * buf)1435 eo_gen_impl_gen(const Eolian_Class *cl, Eina_Strbuf *buf)
1436 {
1437 if (!cl)
1438 return;
1439
1440 char *cname = NULL, *cnamel = NULL;
1441 eo_gen_class_names_get(cl, &cname, NULL, &cnamel);
1442
1443 Eina_Strbuf *beg = eina_strbuf_new();
1444
1445 if (!_type_exists("EFL_BETA_API_SUPPORT", buf))
1446 {
1447 printf("generating EFL_BETA_API_SUPPORT...\n");
1448 eina_strbuf_append(beg, "#define EFL_BETA_API_SUPPORT\n");
1449 }
1450
1451 if (!_type_exists("<Eo.h>", buf))
1452 {
1453 printf("generating includes for <Eo.h> and \"%s.eo.h\"...\n", cnamel);
1454 eina_strbuf_append(beg, "#include <Eo.h>\n");
1455 eina_strbuf_append_printf(beg, "#include \"%s.eo.h\"\n\n", cnamel);
1456 }
1457
1458 /* determine data type name */
1459 Eina_Stringshare *dt = eolian_class_c_data_type_get(cl);
1460
1461 /* generate data type struct */
1462 if (strcmp(dt, "void") && !_type_exists(dt, buf))
1463 {
1464 printf("generating data type structure %s...\n", dt);
1465 eina_strbuf_append_printf(beg, "typedef struct\n{\n\n} %s;\n\n", dt);
1466 }
1467
1468 if (eina_strbuf_length_get(beg))
1469 eina_strbuf_prepend(buf, eina_strbuf_string_get(beg));
1470
1471 eina_strbuf_free(beg);
1472
1473 /* method section */
1474 {
1475 Eina_Iterator *itr = eolian_class_implements_get(cl);
1476 const Eolian_Implement *imp;
1477 EINA_ITERATOR_FOREACH(itr, imp)
1478 {
1479 Eolian_Function_Type ftype = EOLIAN_UNRESOLVED;
1480 const Eolian_Function *fid = eolian_implement_function_get(imp, &ftype);
1481 switch (ftype)
1482 {
1483 case EOLIAN_PROP_GET:
1484 case EOLIAN_PROP_SET:
1485 _gen_proto(cl, fid, ftype, buf, imp, dt, cnamel);
1486 break;
1487 case EOLIAN_PROPERTY:
1488 _gen_proto(cl, fid, EOLIAN_PROP_SET, buf, imp, dt, cnamel);
1489 _gen_proto(cl, fid, EOLIAN_PROP_GET, buf, imp, dt, cnamel);
1490 break;
1491 default:
1492 _gen_proto(cl, fid, EOLIAN_METHOD, buf, imp, dt, cnamel);
1493 }
1494 }
1495 eina_iterator_free(itr);
1496 }
1497
1498 /* free the data type */
1499 eina_stringshare_del(dt);
1500
1501 if (eolian_class_ctor_enable_get(cl))
1502 {
1503 char fname[128];
1504 snprintf(fname, sizeof(fname), "_%s_class_constructor", cnamel);
1505 if (!_function_exists(fname, buf))
1506 {
1507 printf("generating function %s...\n", fname);
1508 eina_strbuf_append_printf(buf,
1509 "EOLIAN static void\n"
1510 "_%s_class_constructor(Efl_Class *klass)\n"
1511 "{\n\n"
1512 "}\n\n", cnamel);
1513 }
1514 }
1515
1516 if (eolian_class_dtor_enable_get(cl))
1517 {
1518 char fname[128];
1519 snprintf(fname, sizeof(fname), "_%s_class_destructor", cnamel);
1520 if (!_function_exists(fname, buf))
1521 {
1522 printf("generating function %s...\n", fname);
1523 eina_strbuf_append_printf(buf,
1524 "EOLIAN static void\n"
1525 "_%s_class_destructor(Efl_Class *klass)\n"
1526 "{\n\n"
1527 "}\n\n", cnamel);
1528 }
1529 }
1530
1531 printf("removing includes for \"%s.eo.c\"\n", cnamel);
1532 char ibuf[512];
1533 snprintf(ibuf, sizeof(ibuf), "\n#include \"%s.eo.c\"\n", cnamel);
1534 eina_strbuf_replace_all(buf, ibuf, "\n");
1535
1536 printf("generating include for \"%s.eo.c\"\n", cnamel);
1537 eina_strbuf_append_printf(buf, "#include \"%s.eo.c\"\n", cnamel);
1538
1539 free(cname);
1540 free(cnamel);
1541 }
1542