1 #ifdef HAVE_CONFIG_H
2 # include "elementary_config.h"
3 #endif
4 
5 #include <Ecore.h>
6 #include <Ecore_File.h>
7 #include <Ecore_Evas.h>
8 #include <Ecore_Getopt.h>
9 #include <Edje.h>
10 #define EDJE_EDIT_IS_UNSTABLE_AND_I_KNOW_ABOUT_IT 1
11 #include <Edje_Edit.h>
12 #include <Eina.h>
13 
14 #include <Elementary.h>
15 
16 #include <ctype.h>
17 #include <fcntl.h>
18 #include <locale.h>
19 #include <stdio.h>
20 #include <unistd.h>
21 
22 #ifndef ENABLE_NLS
23 # ifndef libintl_setlocale
24 #  define libintl_setlocale(c, l)
25 # endif
26 #endif
27 
28 static int _log_dom;
29 #define DBG(...)  EINA_LOG_DOM_DBG(_log_dom, __VA_ARGS__)
30 #define ERR(...)  EINA_LOG_DOM_ERR(_log_dom, __VA_ARGS__)
31 #define WRN(...)  EINA_LOG_DOM_WARN(_log_dom, __VA_ARGS__)
32 
33 static Ecore_Evas *ee = NULL;
34 static char *file = NULL;
35 static char *group = NULL;
36 static char *prefix = NULL;
37 static FILE *source_fd = NULL;
38 static FILE *header_fd = NULL;
39 
40 #define H_HEADER                       \
41   "#ifndef _%s\n"                      \
42   "#define _%s\n\n"                    \
43   "#include <Edje.h>\n"                \
44   "#include <Elementary.h>\n"          \
45   "#include <Evas.h>\n\n"              \
46   "#include <stdlib.h>\n\n"
47 
48 #define H_FOOTER                       \
49   "\n#endif /* _%s */\n"
50 
51 #define C_HEADER                       \
52   "#include \"%s\"\n\n"
53 
54 #define H_CODEGEN_LAYOUT_ADD                                                \
55   "/**\n * @brief Creates the layout object and set the theme\n"            \
56   " * @param o The parent\n"                                                \
57   " * @param th The theme to add to, or if NULL, the default theme\n"       \
58   " * @param edje_file The path to edj, if NULL it's used the path given\n" \
59   " *                  to elementary_codegen\n */\n"                        \
60   "Evas_Object *%s_layout_add(Evas_Object *o, Elm_Theme *th, "              \
61   "const char *edje_file);\n"
62 
63 #define C_CODEGEN_LAYOUT_ADD                                               \
64   "Evas_Object *\n"                                                        \
65   "%s_layout_add(Evas_Object *o, Elm_Theme *th, const char *edje_file)\n"  \
66   "{\n"                                                                    \
67   "   Evas_Object *l;\n\n"                                                 \
68   "   if (edje_file)\n"                                                    \
69   "     elm_theme_extension_add(th, edje_file);\n"                         \
70   "   else\n"                                                              \
71   "     elm_theme_extension_add(th, \"./%s\");\n\n"                        \
72   "   l = elm_layout_add(o);\n"                                            \
73   "   if (!l) return NULL;\n\n"                                            \
74   "   if (!elm_layout_theme_set(l, \"%s\", \"%s\", \"%s\"))\n"             \
75   "     {\n"                                                               \
76   "        evas_object_del(l);\n"                                          \
77   "        return NULL;\n"                                                 \
78   "     }\n\n"                                                             \
79   "   return l;\n"                                                         \
80   "}\n\n"
81 
82 #define C_CODEGEN_PART_CONTENT_SET                             \
83   "void\n"                                                     \
84   "%s_%s_set(Evas_Object *o, Evas_Object *value)\n"            \
85   "{\n"                                                        \
86   "   elm_layout_content_set(o, \"%s\", value);\n"             \
87   "}\n\n"
88 
89 #define C_CODEGEN_PART_TEXT_SET                                \
90   "void\n"                                                     \
91   "%s_%s_set(Evas_Object *o, const char *value)\n"             \
92   "{\n"                                                        \
93   "   elm_layout_text_set(o, \"%s\", value);\n"                \
94   "}\n\n"
95 
96 #define C_CODEGEN_PART_CONTENT_UNSET                          \
97   "Evas_Object *\n"                                           \
98   "%s_%s_unset(Evas_Object *o)\n"                             \
99   "{\n"                                                       \
100   "   return elm_layout_content_unset(o, \"%s\");\n"          \
101   "}\n\n"
102 
103 #define H_CODEGEN_PART_CONTENT_SET                            \
104   "void %s_%s_set(Evas_Object *o, Evas_Object *value);\n"
105 
106 #define H_CODEGEN_PART_TEXT_SET                               \
107   "void %s_%s_set(Evas_Object *o, const char *value);\n"
108 
109 #define H_CODEGEN_PART_CONTENT_UNSET                    \
110   "Evas_Object *%s_%s_unset(Evas_Object *o);\n"
111 
112 #define C_CODEGEN_PART_CONTENT_GET                      \
113   "Evas_Object *\n"                                     \
114   "%s_%s_get(const Evas_Object *o)\n"                   \
115   "{\n"                                                 \
116   "   return elm_layout_content_get(o, \"%s\");\n"      \
117   "}\n\n"
118 
119 #define H_CODEGEN_PART_CONTENT_GET                      \
120   "Evas_Object *%s_%s_get(const Evas_Object *o);\n"
121 
122 #define C_CODEGEN_PART_TEXT_GET                        \
123   "const char *\n"                                     \
124   "%s_%s_get(const Evas_Object *o)\n"                  \
125   "{\n"                                                \
126   "   return elm_layout_text_get(o, \"%s\");\n"        \
127   "}\n\n"
128 
129 #define H_CODEGEN_PART_TEXT_GET                        \
130   "const char *%s_%s_get(const Evas_Object *o);\n"
131 
132 #define C_CODEGEN_PART_BOX_APPEND                                \
133   "Eina_Bool\n"                                                  \
134   "%s_%s_append(Evas_Object *o, Evas_Object *child)\n"           \
135   "{\n"                                                          \
136   "   return elm_layout_box_append(o, \"%s\", child);\n"         \
137   "}\n\n"
138 
139 #define H_CODEGEN_PART_BOX_APPEND                                  \
140   "Eina_Bool %s_%s_append(Evas_Object *o, Evas_Object *child);\n"
141 
142 #define C_CODEGEN_PART_BOX_PREPEND                                \
143   "Eina_Bool\n"                                                   \
144   "%s_%s_prepend(Evas_Object *o, Evas_Object *child)\n"           \
145   "{\n"                                                           \
146   "   return elm_layout_box_prepend(o, \"%s\", child);\n"         \
147   "}\n\n"
148 
149 #define H_CODEGEN_PART_BOX_PREPEND                                 \
150   "Eina_Bool %s_%s_prepend(Evas_Object *o, Evas_Object *child);\n"
151 
152 #define C_CODEGEN_PART_BOX_INSERT_BEFORE                          \
153   "Eina_Bool\n"                                                   \
154   "%s_%s_insert_before(Evas_Object *o, Evas_Object *child, "      \
155   "const Evas_Object *reference)\n"                               \
156   "{\n"                                                           \
157   "   return elm_layout_box_insert_before(o, \"%s\", "            \
158   "child, reference);\n"                                          \
159   "}\n\n"
160 
161 #define H_CODEGEN_PART_BOX_INSERT_BEFORE                                \
162   "Eina_Bool %s_%s_insert_before(Evas_Object *o, Evas_Object *child, "  \
163   "const Evas_Object *reference);\n"
164 
165 #define C_CODEGEN_PART_BOX_INSERT_AT                                        \
166   "Eina_Bool\n"                                                             \
167   "%s_%s_insert_at(Evas_Object *o, Evas_Object *child, unsigned int pos)\n" \
168   "{\n"                                                                     \
169   "   return elm_layout_box_insert_at(o, \"%s\", child, pos);\n"            \
170   "}\n\n"
171 
172 #define H_CODEGEN_PART_BOX_INSERT_AT                                     \
173   "Eina_Bool %s_%s_insert_at(Evas_Object *o, Evas_Object *child, "       \
174   "unsigned int pos);\n"
175 
176 #define C_CODEGEN_PART_BOX_REMOVE                             \
177   "Evas_Object *\n"                                           \
178   "%s_%s_remove(Evas_Object *o, Evas_Object *child)\n"        \
179   "{\n"                                                       \
180   "   return elm_layout_box_remove(o, \"%s\", child);\n"      \
181   "}\n\n"
182 
183 #define H_CODEGEN_PART_BOX_REMOVE                                    \
184   "Evas_Object *%s_%s_remove(Evas_Object *o, Evas_Object *child);\n"
185 
186 #define C_CODEGEN_PART_BOX_REMOVE_ALL                           \
187   "Eina_Bool\n"                                                 \
188   "%s_%s_remove_all(Evas_Object *o, Eina_Bool clear)\n"         \
189   "{\n"                                                         \
190   "   return elm_layout_box_remove_all(o, \"%s\", clear);\n"    \
191   "}\n\n"
192 
193 #define H_CODEGEN_PART_BOX_REMOVE_ALL                               \
194   "Eina_Bool %s_%s_remove_all(Evas_Object *o, Eina_Bool clear);\n"
195 
196 #define C_CODEGEN_PART_TABLE_PACK                                         \
197   "Eina_Bool\n"                                                           \
198   "%s_%s_pack(Evas_Object *o, Evas_Object *child, unsigned short col, "   \
199   "unsigned short row, unsigned short colspan, unsigned short rowspan)\n" \
200   "{\n"                                                                   \
201   "   return elm_layout_table_pack(o, \"%s\", child, col, row, "          \
202   "colspan, rowspan);\n"                                                  \
203   "}\n\n"
204 
205 #define H_CODEGEN_PART_TABLE_PACK                                \
206   "Eina_Bool %s_%s_pack(Evas_Object *o, Evas_Object *child, "    \
207   "unsigned short col, unsigned short row, unsigned short "      \
208   "colspan, unsigned short rowspan);\n"
209 
210 #define C_CODEGEN_PART_TABLE_UNPACK                                  \
211   "Evas_Object *\n"                                                  \
212   "%s_%s_unpack(Evas_Object *o, Evas_Object *child)\n"               \
213   "{\n"                                                              \
214   "   return elm_layout_table_unpack(o, \"%s\", child);\n"           \
215   "}\n\n"
216 
217 #define H_CODEGEN_PART_TABLE_UNPACK                                  \
218   "Evas_Object *%s_%s_unpack(Evas_Object *o, Evas_Object *child);\n"
219 
220 #define C_CODEGEN_PART_TABLE_CLEAR                               \
221   "Eina_Bool\n"                                                  \
222   "%s_%s_clear(Evas_Object *o, Eina_Bool clear)\n"               \
223   "{\n"                                                          \
224   "   return elm_layout_table_clear(o, \"%s\", clear);\n"        \
225   "}\n\n"
226 
227 #define H_CODEGEN_PART_TABLE_CLEAR                                   \
228   "Eina_Bool %s_%s_clear(Evas_Object *o, Eina_Bool clear);\n"
229 
230 #define C_CODEGEN_PROGRAM_EMIT                          \
231   "void\n"                                              \
232   "%s_%s_emit(Evas_Object *o)\n"                        \
233   "{\n"                                                 \
234   "   elm_layout_signal_emit(o, \"%s\", \"%s\");\n"     \
235   "}\n\n"
236 
237 #define H_CODEGEN_PROGRAM_EMIT                          \
238   "void %s_%s_emit(Evas_Object *o);\n"
239 
240 #define C_CODEGEN_PROGRAM_CALLBACK_ADD                                      \
241   "void\n"                                                                  \
242   "%s_%s_callback_add(Evas_Object *o, Edje_Signal_Cb func, void *data)\n"   \
243   "{\n"                                                                     \
244   "   elm_layout_signal_callback_add(o, \"%s\", \"%s\", func, data);\n"     \
245   "}\n\n"
246 
247 #define H_CODEGEN_PROGRAM_CALLBACK_ADD                                  \
248   "void %s_%s_callback_add(Evas_Object *o, Edje_Signal_Cb func, "       \
249   "void *data);\n"
250 
251 #define C_CODEGEN_PROGRAM_CALLBACK_DEL                              \
252   "void\n"                                                          \
253   "%s_%s_callback_del(Evas_Object *o, Edje_Signal_Cb func)\n"       \
254   "{\n"                                                             \
255   "   elm_layout_signal_callback_del(o, \"%s\", \"%s\", func);\n"   \
256   "}\n\n"
257 
258 #define H_CODEGEN_PROGRAM_CALLBACK_DEL                              \
259   "void %s_%s_callback_del(Evas_Object *o, Edje_Signal_Cb func);\n"
260 
261 const Ecore_Getopt optdesc =
262 {
263    "elm_codegen",
264    "%prog [options] <file.edj> <group> <source_file_name> <header_file_name>",
265    PACKAGE_VERSION,
266    "(C) 2012 - The Enlightenment Project",
267    "BSD",
268    "elm_codegen generates the boilerplate code to get and set the "
269       "parts of a group from a compiled (binary) edje "
270       "file avoiding common errors with typos.\n",
271    0,
272    {
273       ECORE_GETOPT_STORE_STR('p', "prefix", "The prefix for the " \
274                              "generataed code."),
275       ECORE_GETOPT_LICENSE('L', "license"),
276       ECORE_GETOPT_COPYRIGHT('C', "copyright"),
277       ECORE_GETOPT_VERSION('V', "version"),
278       ECORE_GETOPT_HELP('h', "help"),
279       ECORE_GETOPT_SENTINEL
280    }
281 };
282 
283 static char *
_header_standardize(const char * filename)284 _header_standardize(const char *filename)
285 {
286    char *str, *itr, *aux;
287 
288    aux = strrchr(filename, '/');
289    str = itr = strdup(aux ? aux + 1 : filename);
290 
291    for (; *itr; itr++)
292      if (*itr == '.')
293        *itr = '_';
294      else
295        *itr = toupper(*itr);
296 
297    return str;
298 }
299 
300 static Eina_Bool
_file_descriptors_open(const char * source,const char * header)301 _file_descriptors_open(const char *source, const char *header)
302 {
303    header_fd = fopen(header, "w");
304    if (!header_fd)
305      return EINA_FALSE;
306 
307    source_fd = fopen(source, "w");
308    if (!source_fd)
309      goto err;
310 
311    return EINA_TRUE;
312 
313  err:
314    fclose(header_fd);
315    return EINA_FALSE;
316 }
317 
318 static Eina_Bool
_file_descriptors_close(void)319 _file_descriptors_close(void)
320 {
321    Eina_Bool ret = EINA_FALSE;
322 
323    if (!fclose(header_fd))
324      ret = EINA_TRUE;
325 
326    if (!fclose(source_fd))
327      ret &= EINA_TRUE;
328 
329    return ret;
330 }
331 
332 static Eina_Bool
_headers_write(const char * filename)333 _headers_write(const char *filename)
334 {
335    char buf[512];
336    char *str;
337 
338    str = _header_standardize(filename);
339    snprintf(buf, sizeof(buf), H_HEADER, str, str);
340    if (fwrite(buf, strlen(buf), 1, header_fd) != 1)
341      {
342         free(str);
343         return EINA_FALSE;
344      }
345 
346    free(str);
347 
348    snprintf(buf, sizeof(buf), C_HEADER, ecore_file_file_get(filename));
349    if (fwrite(buf, strlen(buf), 1, source_fd) != 1)
350      return EINA_FALSE;
351 
352    return EINA_TRUE;
353 }
354 
355 static Eina_Bool
_footer_write(const char * filename)356 _footer_write(const char *filename)
357 {
358    char buf[512];
359    char *str;
360 
361    str = _header_standardize(filename);
362    snprintf(buf, sizeof(buf), H_FOOTER, str);
363    if (fwrite(buf, strlen(buf), 1, header_fd) != 1)
364      {
365         free(str);
366         return EINA_FALSE;
367      }
368 
369    free(str);
370 
371    return EINA_TRUE;
372 }
373 
374 static Eina_Bool
_theme_set_write(void)375 _theme_set_write(void)
376 {
377    Eina_Bool ret = EINA_FALSE;
378    char *str[3];  /* *klas, *style, *group */
379    char *token, *_group, buf[512];
380    int i;
381 
382    str[0] = str[1] = str[2] = NULL;
383    if (strncmp(group, "elm/", 4)) return EINA_FALSE;
384 
385    _group = strdup(group);
386    if (!_group) return EINA_FALSE;
387 
388    strtok(_group, "/");
389    for (i = 0; i < 3; i++)
390      {
391         token = strtok(NULL, "/");
392         if (!token) break;
393 
394         str[i] = token;
395      }
396 
397    if (!str[0] || !str[1] || !str[2])
398      goto end;
399 
400    snprintf(buf, sizeof(buf), C_CODEGEN_LAYOUT_ADD, prefix, file, str[0],
401             str[1], str[2]);
402    if (fwrite(buf, strlen(buf), 1, source_fd) != 1)
403      goto end;
404 
405    snprintf(buf, sizeof(buf), H_CODEGEN_LAYOUT_ADD, prefix);
406    if (fwrite(buf, strlen(buf), 1, header_fd) != 1)
407      goto end;
408 
409    ret = EINA_TRUE;
410 
411 end:
412    free(_group);
413    return ret;
414 }
415 
416 static Eina_Bool
_part_write(const char * apiname,const char * partname,const char * description,Edje_Part_Type type)417 _part_write(const char *apiname, const char *partname, const char *description,
418             Edje_Part_Type type)
419 {
420    char buf[1024];
421 
422 #define TEMPLATE_NAME(sufix)                                      \
423    do {                                                           \
424      snprintf(buf, sizeof(buf), C_CODEGEN_PART_##sufix, prefix,   \
425               apiname, partname);                                 \
426      if (fwrite(buf, strlen(buf), 1, source_fd) != 1)             \
427        goto err;                                                  \
428      snprintf(buf, sizeof(buf), H_CODEGEN_PART_##sufix, prefix,   \
429               apiname);                                           \
430      if (fwrite(buf, strlen(buf), 1, header_fd) != 1)             \
431        goto err;                                                  \
432    } while(0)
433 
434    if (description)
435      {
436         snprintf(buf, sizeof(buf), "\n/**\n * @brief %s\n */\n", description);
437         if (fwrite(buf, strlen(buf), 1, header_fd) != 1)
438           goto err;
439      }
440 
441    switch (type)
442      {
443       case EDJE_PART_TYPE_BOX:
444          TEMPLATE_NAME(BOX_APPEND);
445          TEMPLATE_NAME(BOX_PREPEND);
446          TEMPLATE_NAME(BOX_INSERT_BEFORE);
447          TEMPLATE_NAME(BOX_INSERT_AT);
448          TEMPLATE_NAME(BOX_REMOVE);
449          TEMPLATE_NAME(BOX_REMOVE_ALL);
450          break;
451 
452       case EDJE_PART_TYPE_TABLE:
453          TEMPLATE_NAME(TABLE_PACK);
454          TEMPLATE_NAME(TABLE_UNPACK);
455          TEMPLATE_NAME(TABLE_CLEAR);
456          break;
457 
458       case EDJE_PART_TYPE_TEXT:
459          TEMPLATE_NAME(TEXT_SET);
460          TEMPLATE_NAME(TEXT_GET);
461          break;
462 
463       default:
464          TEMPLATE_NAME(CONTENT_SET);
465          TEMPLATE_NAME(CONTENT_UNSET);
466          TEMPLATE_NAME(CONTENT_GET);
467          break;
468      }
469 
470 #undef TEMPLATE_NAME
471 
472    return EINA_TRUE;
473 
474  err:
475    ERR("Could not write the part: %s", partname);
476    return EINA_FALSE;
477 }
478 
479 static inline Eina_Bool
_c_id_allowed(char c)480 _c_id_allowed(char c)
481 {
482    if ((c >= '0') && (c <= '9')) return EINA_TRUE;
483    if ((c >= 'a') && (c <= 'z')) return EINA_TRUE;
484    if ((c >= 'A') && (c <= 'Z')) return EINA_TRUE;
485 
486    return EINA_FALSE;
487 }
488 
489 static char *
_api_name_fix(const char * orig)490 _api_name_fix(const char *orig)
491 {
492    char *d, *d_end, buf[256];
493    const char *s;
494 
495    if (!orig) return NULL;
496 
497    s = orig;
498    d = buf;
499    d_end = d + sizeof(buf) - 1;
500 
501    for (; (*s != '\0') && (d < d_end); s++, d++)
502      if (_c_id_allowed(*s)) *d = *s;
503      else *d = '_';
504    *d = '\0';
505 
506    return strdup(buf);
507 }
508 
509 static char *
_part_api_name_get(Evas_Object * ed,const char * program)510 _part_api_name_get(Evas_Object *ed, const char *program)
511 {
512    const char *orig;
513    char *fix;
514 
515    orig = edje_edit_part_api_name_get(ed, program);
516    fix = _api_name_fix(orig);
517    edje_edit_string_free(orig);
518 
519    return fix;
520 }
521 
522 static Eina_Bool
_parts_parse(Evas_Object * ed)523 _parts_parse(Evas_Object *ed)
524 {
525    Eina_List *parts, *l;
526    const char *name, *description;
527    char *apiname;
528    Edje_Part_Type type;
529    Eina_Bool ret = EINA_TRUE;
530 
531    parts = edje_edit_parts_list_get(ed);
532    EINA_LIST_FOREACH(parts, l, name)
533      {
534         if (!(apiname = _part_api_name_get(ed, name)))
535           {
536              DBG("filter out part '%s': not API.", name);
537              continue;
538           }
539 
540         type = edje_edit_part_type_get(ed, name);
541         if ((type != EDJE_PART_TYPE_SWALLOW) &&
542             (type != EDJE_PART_TYPE_TEXT)    &&
543             (type != EDJE_PART_TYPE_BOX)     &&
544             (type != EDJE_PART_TYPE_TABLE))
545           {
546              free(apiname);
547              continue;
548           }
549 
550         description = edje_edit_part_api_description_get(ed, name);
551         if (!_part_write(apiname, name, description, type))
552           {
553              ret = EINA_FALSE;
554              edje_edit_string_free(description);
555              free(apiname);
556              break;
557           }
558 
559         edje_edit_string_free(description);
560         free(apiname);
561      }
562 
563    edje_edit_string_list_free(parts);
564    return ret;
565 }
566 
567 static Eina_Bool
_program_emit_write(const char * apiname,const char * source,const char * sig,const char * description)568 _program_emit_write(const char *apiname, const char *source, const char *sig,
569                     const char *description)
570 {
571    char buf[512];
572 
573    snprintf(buf, sizeof(buf), C_CODEGEN_PROGRAM_EMIT, prefix,
574             apiname, sig, source);
575    if (fwrite(buf, strlen(buf), 1, source_fd) != 1)
576      goto err;
577 
578    if (description)
579      {
580         snprintf(buf, sizeof(buf), "\n/**\n * @brief %s\n */\n", description);
581         if (fwrite(buf, strlen(buf), 1, header_fd) != 1)
582           goto err;
583      }
584 
585    snprintf(buf, sizeof(buf), H_CODEGEN_PROGRAM_EMIT, prefix,
586             apiname);
587    if (fwrite(buf, strlen(buf), 1, header_fd) != 1)
588      goto err;
589 
590    return EINA_TRUE;
591 
592  err:
593    ERR("Could not write the program: %s", apiname);
594    return EINA_FALSE;
595 }
596 
597 static Eina_Bool
_program_add_write(const char * apiname,const char * source,const char * sig,const char * description)598 _program_add_write(const char *apiname, const char *source, const char *sig,
599                    const char *description)
600 {
601    char buf[512];
602 
603    snprintf(buf, sizeof(buf), C_CODEGEN_PROGRAM_CALLBACK_ADD, prefix,
604             apiname, sig, source);
605    if (fwrite(buf, strlen(buf), 1, source_fd) != 1)
606      goto err;
607 
608    snprintf(buf, sizeof(buf), C_CODEGEN_PROGRAM_CALLBACK_DEL, prefix,
609             apiname, sig, source);
610    if (fwrite(buf, strlen(buf), 1, source_fd) != 1)
611      goto err;
612 
613    if (description)
614      {
615         snprintf(buf, sizeof(buf), "\n/**\n * @brief %s\n */\n", description);
616         if (fwrite(buf, strlen(buf), 1, header_fd) != 1)
617           goto err;
618      }
619 
620    snprintf(buf, sizeof(buf), H_CODEGEN_PROGRAM_CALLBACK_ADD, prefix,
621             apiname);
622    if (fwrite(buf, strlen(buf), 1, header_fd) != 1)
623      goto err;
624 
625    snprintf(buf, sizeof(buf), H_CODEGEN_PROGRAM_CALLBACK_DEL, prefix,
626             apiname);
627    if (fwrite(buf, strlen(buf), 1, header_fd) != 1)
628      goto err;
629 
630    return EINA_TRUE;
631 
632  err:
633    ERR("Could not write the program [action]: %s", apiname);
634    return EINA_FALSE;
635 }
636 
637 static char *
_program_api_name_get(Evas_Object * ed,const char * program)638 _program_api_name_get(Evas_Object *ed, const char *program)
639 {
640    const char *orig;
641    char *fix;
642 
643    orig = edje_edit_program_api_name_get(ed, program);
644    fix = _api_name_fix(orig);
645    edje_edit_string_free(orig);
646 
647    return fix;
648 }
649 
650 static Eina_Bool
_programs_parse(Evas_Object * ed)651 _programs_parse(Evas_Object *ed)
652 {
653    Eina_Bool ret = EINA_TRUE;
654    Eina_List *programs, *l;
655    const char *name, *source = NULL, *sig = NULL, *description;
656    char *apiname;
657    Edje_Action_Type type;
658 
659    programs = edje_edit_programs_list_get(ed);
660    EINA_LIST_FOREACH(programs, l, name)
661      {
662         if (!(apiname = _program_api_name_get(ed, name)))
663           {
664              DBG("filter out program '%s': not API.", name);
665              continue;
666           }
667 
668         description = edje_edit_program_api_description_get(ed, name);
669         type = edje_edit_program_action_get(ed, name);
670         if (type == EDJE_ACTION_TYPE_SIGNAL_EMIT)
671           {
672              const char *str, *str2;
673              str = edje_edit_program_state_get(ed, name);
674              str2 = edje_edit_program_state2_get(ed, name);
675 
676              if (!_program_add_write(apiname, str2, str, description))
677                {
678                   ret = EINA_FALSE;
679                   edje_edit_string_free(str);
680                   edje_edit_string_free(str2);
681                   break;
682                }
683 
684              edje_edit_string_free(str);
685              edje_edit_string_free(str2);
686           }
687 
688         sig = edje_edit_program_signal_get(ed, name);
689         if (!sig) sig = eina_stringshare_add("");
690 
691         source = edje_edit_program_source_get(ed, name);
692         if (!source) source = eina_stringshare_add("");
693 
694         if (strlen (sig))
695           {
696              if (!_program_emit_write(apiname, source, sig, description))
697                {
698                   ret = EINA_FALSE;
699                   break;
700                }
701           }
702 
703         edje_edit_string_free(description);
704         description = NULL;
705         edje_edit_string_free(sig);
706         sig = NULL;
707         edje_edit_string_free(source);
708         source = NULL;
709         free(apiname);
710         apiname = NULL;
711      }
712 
713    edje_edit_string_list_free(programs);
714    if (!ret)
715      {
716         edje_edit_string_free(description);
717         edje_edit_string_free(sig);
718         edje_edit_string_free(source);
719         free(apiname);
720      }
721 
722    return ret;
723 }
724 
725 static Eina_Bool
_parse(void)726 _parse(void)
727 {
728    Evas_Object *ed;
729    Eina_Bool ret;
730 
731    ed = edje_edit_object_add(ecore_evas_get(ee));
732    if (!edje_object_file_set(ed, file, group))
733      {
734         Edje_Load_Error err = edje_object_load_error_get(ed);
735         const char *errmsg = edje_load_error_str(err);
736         ERR("could not load group '%s' from file '%s': %s",
737             group, file, errmsg);
738         evas_object_del(ed);
739         return EINA_FALSE;
740      }
741 
742    ret = _parts_parse(ed) && _programs_parse(ed);
743 
744    evas_object_del(ed);
745    return ret;
746 }
747 
748 int
main(int argc,char * argv[])749 main(int argc, char *argv[])
750 {
751    Eina_Bool quit_option = EINA_FALSE;
752    char *source = NULL, *header = NULL;
753    int arg_index, ret = 0;
754    Ecore_Getopt_Value values[] = {
755      ECORE_GETOPT_VALUE_STR(prefix),
756      ECORE_GETOPT_VALUE_BOOL(quit_option),
757      ECORE_GETOPT_VALUE_BOOL(quit_option),
758      ECORE_GETOPT_VALUE_BOOL(quit_option),
759      ECORE_GETOPT_VALUE_BOOL(quit_option),
760      ECORE_GETOPT_VALUE_NONE
761    };
762 
763    setlocale(LC_NUMERIC, "C");
764 
765    eina_init();
766    ecore_init();
767    ecore_evas_init();
768    edje_init();
769 
770    if (argc < 2)
771      {
772         fprintf(stderr, "Missing action. See '--help or -h'.\n");
773         ret = 1;
774         goto error_log;
775      }
776 
777    _log_dom = eina_log_domain_register("elementary_codegen", EINA_COLOR_YELLOW);
778    if (_log_dom < 0)
779      {
780         EINA_LOG_CRIT("could not register log domain 'elementary_codegen'");
781         ret = 1;
782         goto error_log;
783      }
784 
785    arg_index = ecore_getopt_parse(&optdesc, values, argc, argv);
786    if (arg_index < 0)
787      {
788         ERR("could not parse arguments.");
789         ret = 1;
790         goto error_getopt;
791      }
792    else if (quit_option) goto error_getopt;
793    else if (arg_index != argc - 4)
794      {
795         fprintf(stderr, "Incorrect number of parameters. Requires "  \
796                 "fours arguments, an edje, the group, "              \
797                 "the source output (foo.c) and the header(foo.h).\n" \
798                 "See %s --help\n", argv[0]);
799         ret = 1;
800         goto error_getopt;
801      }
802 
803    file = argv[arg_index++];
804 
805    // check if the file is accessible
806    if (access(file, R_OK) == -1)
807      {
808         ERR("File '%s' not accessible, error %d (%s).\n",
809             file, errno, strerror(errno));
810         ret = 1;
811         goto error_getopt;
812      }
813 
814    group = argv[arg_index++];
815    source = argv[arg_index++];
816    header = argv[arg_index++];
817 
818    if (!edje_file_group_exists(file, group))
819      {
820         ERR("The group %s not exists", group);
821         ret = 2;
822         goto error_getopt;
823      }
824 
825    ee = ecore_evas_buffer_new(1, 1);
826    if (!ee)
827      {
828         ERR("could not create ecore_evas_buffer");
829         ret = 3;
830         goto error_getopt;
831      }
832 
833    if (!_file_descriptors_open(source, header))
834      {
835         ERR("Could not create the source files, error %d (%s)",
836             errno, strerror(errno));
837         ret = 4;
838         goto error_getopt;
839      }
840 
841    if (!_headers_write(header))
842      {
843         ERR("Could not write the header, error %d (%s)",
844             errno, strerror(errno));
845         ret = 5;
846         goto error_getopt;
847      }
848 
849    if (!_theme_set_write())
850      WRN("Theme set getter/setter not created. Group name: %s invalid.", group);
851 
852    if (!_parse())
853      {
854         ERR("Could not parsing the EDJE");
855         ret = 6;
856         goto error_getopt;
857      }
858 
859    if (!_footer_write(header))
860      {
861         ERR("Could not write the footer, error %d (%s)",
862             errno, strerror(errno));
863         ret = 7;
864         goto error_getopt;
865      }
866 
867    if (!_file_descriptors_close())
868      {
869         ERR("Could not close the source files, error %d (%s)",
870             errno, strerror(errno));
871         ret = 8;
872      }
873 
874 error_getopt:
875    if (ee)
876      ecore_evas_free(ee);
877 
878 error_log:
879    edje_shutdown();
880    ecore_evas_shutdown();
881    ecore_shutdown();
882    eina_log_domain_unregister(_log_dom);
883    eina_shutdown();
884 
885    if (ret > 4)
886      {
887         unlink(header);
888         unlink(source);
889      }
890 
891    return ret;
892 }
893