package upload
[framework/uifw/elementary.git] / src / bin / elementary_codegen.c
1 #include <Elementary.h>
2
3 #ifdef HAVE_CONFIG_H
4 # include "elementary_config.h"
5 #endif
6
7 #include <Ecore.h>
8 #include <Ecore_Evas.h>
9 #include <Ecore_Getopt.h>
10 #include <Edje.h>
11 #define EDJE_EDIT_IS_UNSTABLE_AND_I_KNOW_ABOUT_IT 1
12 #include <Edje_Edit.h>
13 #include <Eina.h>
14
15 #include <ctype.h>
16 #include <fcntl.h>
17 #include <locale.h>
18 #include <stdio.h>
19 #include <unistd.h>
20
21 #ifndef ENABLE_NLS
22 # ifndef libintl_setlocale
23 #  define libintl_setlocale(c, l)
24 # endif
25 #endif
26
27 static int _log_dom;
28 #define DBG(...)  EINA_LOG_DOM_DBG(_log_dom, __VA_ARGS__)
29 #define ERR(...)  EINA_LOG_DOM_ERR(_log_dom, __VA_ARGS__)
30 #define WRN(...)  EINA_LOG_DOM_WARN(_log_dom, __VA_ARGS__)
31
32 static Ecore_Evas *ee = NULL;
33 static char *file = NULL;
34 static char *group = NULL;
35 static char *prefix = NULL;
36 static FILE *source_fd = NULL;
37 static FILE *header_fd = NULL;
38
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
262 const Ecore_Getopt optdesc = {
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 *
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
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
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
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, 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
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
375 _theme_set_write(void)
376 {
377    Eina_Bool ret = EINA_FALSE;
378    char *str[3];  /* *klas, *style, *group */
379    char *aux, *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    token = strtok(_group, "/");
389    for (i = 0, aux = NULL; i < 3; i++, aux = NULL)
390      {
391         token = strtok(aux, "/");
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
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
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 *
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 *
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
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
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
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 *
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
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         edje_edit_string_free(sig);
705         edje_edit_string_free(source);
706         free(apiname);
707      }
708
709    edje_edit_string_list_free(programs);
710    if (!ret)
711      {
712         edje_edit_string_free(description);
713         edje_edit_string_free(sig);
714         edje_edit_string_free(source);
715         free(apiname);
716      }
717
718    return ret;
719 }
720
721 static Eina_Bool
722 _parse(void)
723 {
724    Evas_Object *ed;
725    Eina_Bool ret;
726
727    ed = edje_edit_object_add(ecore_evas_get(ee));
728    if (!edje_object_file_set(ed, file, group))
729      {
730         Edje_Load_Error err = edje_object_load_error_get(ed);
731         const char *errmsg = edje_load_error_str(err);
732         ERR("could not load group '%s' from file '%s': %s",
733             group, file, errmsg);
734         evas_object_del(ed);
735         return EINA_FALSE;
736      }
737
738    ret = _parts_parse(ed) && _programs_parse(ed);
739
740    evas_object_del(ed);
741    return ret;
742 }
743
744 int
745 main(int argc, char *argv[])
746 {
747    Eina_Bool quit_option = EINA_FALSE;
748    char *source = NULL, *header = NULL;
749    int arg_index, ret = 0;
750    Ecore_Getopt_Value values[] = {
751      ECORE_GETOPT_VALUE_STR(prefix),
752      ECORE_GETOPT_VALUE_BOOL(quit_option),
753      ECORE_GETOPT_VALUE_BOOL(quit_option),
754      ECORE_GETOPT_VALUE_BOOL(quit_option),
755      ECORE_GETOPT_VALUE_BOOL(quit_option),
756      ECORE_GETOPT_VALUE_NONE
757    };
758
759    setlocale(LC_NUMERIC, "C");
760
761    eina_init();
762    ecore_init();
763    ecore_evas_init();
764    edje_init();
765
766    if (argc < 2)
767      {
768         fprintf(stderr, "Missing action. See '--help or -h'.\n");
769         ret = 1;
770         goto error_log;
771      }
772
773    _log_dom = eina_log_domain_register("elementary_codegen", EINA_COLOR_YELLOW);
774    if (_log_dom < 0)
775      {
776         EINA_LOG_CRIT("could not register log domain 'elementary_codegen'");
777         ret = 1;
778         goto error_log;
779      }
780
781    arg_index = ecore_getopt_parse(&optdesc, values, argc, argv);
782    if (arg_index < 0)
783      {
784         ERR("could not parse arguments.");
785         ret = 1;
786         goto error_getopt;
787      }
788    else if (quit_option) goto error_getopt;
789    else if (arg_index != argc - 4)
790      {
791         fprintf(stderr, "Incorrect number of parameters. Requires "     \
792                 "fours arguments, an edje, the group, "                 \
793                 "the source output (foo.c) and the header(foo.h).\n"    \
794                 "See %s --help\n", argv[0]);
795         ret = 1;
796         goto error_getopt;
797      }
798
799    file = argv[arg_index++];
800
801    // check if the file is accessible
802    if (access(file, R_OK) == -1)
803      {
804         ERR("File '%s' not accessible, error %d (%s).\n",
805             file, errno, strerror(errno));
806         ret = 1;
807         goto error_getopt;
808      }
809
810    group = argv[arg_index++];
811    source = argv[arg_index++];
812    header = argv[arg_index++];
813
814    if (!edje_file_group_exists(file, group))
815      {
816         ERR("The group %s not exists", group);
817         ret = 2;
818         goto error_getopt;
819      }
820
821    ee = ecore_evas_buffer_new(1, 1);
822    if (!ee)
823      {
824         ERR("could not create ecore_evas_buffer");
825         ret = 3;
826         goto error_getopt;
827      }
828
829    if (!_file_descriptors_open(source, header))
830      {
831         ERR("Could not create the source files, error %d (%s)",
832             errno, strerror(errno));
833         ret = 4;
834         goto error_getopt;
835      }
836
837    if (!_headers_write(header))
838      {
839         ERR("Could not write the header, error %d (%s)",
840             errno, strerror(errno));
841         ret = 5;
842         goto error_getopt;
843      }
844
845    if (!_theme_set_write())
846      WRN("Theme set getter/setter not created. Group name: %s invalid.", group);
847
848    if (!_parse())
849      {
850         ERR("Could not parsing the EDJE");
851         ret = 6;
852         goto error_getopt;
853      }
854
855    if (!_footer_write(header))
856      {
857         ERR("Could not write the footer, error %d (%s)",
858             errno, strerror(errno));
859         ret = 7;
860         goto error_getopt;
861      }
862
863    if (!_file_descriptors_close())
864      {
865         ERR("Could not close the source files, error %d (%s)",
866             errno, strerror(errno));
867         ret = 8;
868      }
869
870  error_getopt:
871    if (ee)
872      ecore_evas_free(ee);
873
874  error_log:
875    edje_shutdown();
876    ecore_evas_shutdown();
877    ecore_shutdown();
878    eina_log_domain_unregister(_log_dom);
879    eina_shutdown();
880
881    if (ret > 4)
882      {
883         unlink(header);
884         unlink(source);
885      }
886
887    return ret;
888 }