aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/edje/src/bin/edje_cc_out.c
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/edje/src/bin/edje_cc_out.c')
-rw-r--r--libraries/edje/src/bin/edje_cc_out.c1995
1 files changed, 1995 insertions, 0 deletions
diff --git a/libraries/edje/src/bin/edje_cc_out.c b/libraries/edje/src/bin/edje_cc_out.c
new file mode 100644
index 0000000..443a702
--- /dev/null
+++ b/libraries/edje/src/bin/edje_cc_out.c
@@ -0,0 +1,1995 @@
1#ifdef HAVE_CONFIG_H
2# include "config.h"
3#endif
4
5#ifdef HAVE_ALLOCA_H
6# include <alloca.h>
7#elif defined __GNUC__
8# define alloca __builtin_alloca
9#elif defined _AIX
10# define alloca __alloca
11#elif defined _MSC_VER
12# include <malloc.h>
13# define alloca _alloca
14#else
15# include <stddef.h>
16# ifdef __cplusplus
17extern "C"
18# endif
19void *alloca (size_t);
20#endif
21
22#include <string.h>
23#include <limits.h>
24#include <unistd.h>
25#include <sys/stat.h>
26
27#include <Ecore_Evas.h>
28
29#include "edje_cc.h"
30#include "edje_convert.h"
31#include "edje_multisense_convert.h"
32
33#include <lua.h>
34#include <lauxlib.h>
35
36typedef struct _External_Lookup External_Lookup;
37typedef struct _Part_Lookup Part_Lookup;
38typedef struct _Program_Lookup Program_Lookup;
39typedef struct _Group_Lookup Group_Lookup;
40typedef struct _Image_Lookup Image_Lookup;
41typedef struct _Slave_Lookup Slave_Lookup;
42typedef struct _Code_Lookup Code_Lookup;
43
44
45struct _External_Lookup
46{
47 char *name;
48};
49
50struct _Part_Lookup
51{
52 Edje_Part_Collection *pc;
53 char *name;
54 int *dest;
55};
56
57struct _Program_Lookup
58{
59 Edje_Part_Collection *pc;
60
61 union
62 {
63 char *name;
64 Edje_Program *ep;
65 } u;
66
67 int *dest;
68
69 Eina_Bool anonymous : 1;
70};
71
72struct _Group_Lookup
73{
74 char *name;
75};
76
77struct _String_Lookup
78{
79 char *name;
80 int *dest;
81};
82
83struct _Image_Lookup
84{
85 char *name;
86 int *dest;
87 Eina_Bool *set;
88};
89
90struct _Slave_Lookup
91{
92 int *master;
93 int *slave;
94};
95
96struct _Code_Lookup
97{
98 char *ptr;
99 int len;
100 int val;
101 Eina_Bool set;
102};
103
104static void data_process_string(Edje_Part_Collection *pc, const char *prefix, char *s, void (*func)(Edje_Part_Collection *pc, char *name, char *ptr, int len));
105
106Edje_File *edje_file = NULL;
107Eina_List *edje_collections = NULL;
108Eina_List *externals = NULL;
109Eina_List *fonts = NULL;
110Eina_List *codes = NULL;
111Eina_List *code_lookups = NULL;
112Eina_List *aliases = NULL;
113
114static Eet_Data_Descriptor *edd_edje_file = NULL;
115static Eet_Data_Descriptor *edd_edje_part_collection = NULL;
116
117static Eina_List *part_lookups = NULL;
118static Eina_List *program_lookups = NULL;
119static Eina_List *group_lookups = NULL;
120static Eina_List *image_lookups = NULL;
121static Eina_List *part_slave_lookups = NULL;
122static Eina_List *image_slave_lookups= NULL;
123
124#define ABORT_WRITE(eet_file, file) \
125 eet_close(eet_file); \
126 unlink(file); \
127 exit(-1);
128
129void
130error_and_abort(Eet_File *ef, const char *fmt, ...)
131{
132 va_list ap;
133
134 fprintf(stderr, "%s: Error. ", progname);
135
136 va_start(ap, fmt);
137 vfprintf(stderr, fmt, ap);
138 va_end(ap);
139 ABORT_WRITE(ef, file_out);
140}
141
142void
143data_setup(void)
144{
145 edd_edje_file = _edje_edd_edje_file;
146 edd_edje_part_collection = _edje_edd_edje_part_collection;
147}
148
149static void
150check_image_part_desc (Edje_Part_Collection *pc, Edje_Part *ep,
151 Edje_Part_Description_Image *epd, Eet_File *ef)
152{
153 unsigned int i;
154
155#if 0 /* FIXME: This check sounds like not a useful one */
156 if (epd->image.id == -1)
157 ERR(ef, "Collection %s(%i): image attributes missing for "
158 "part \"%s\", description \"%s\" %f\n",
159 pc->part, pc->id, ep->name, epd->common.state.name, epd->common.state.value);
160#endif
161
162 for (i = 0; i < epd->image.tweens_count; ++i)
163 {
164 if (epd->image.tweens[i]->id == -1)
165 error_and_abort(ef, "Collection %i: tween image id missing for "
166 "part \"%s\", description \"%s\" %f\n",
167 pc->id, ep->name, epd->common.state.name, epd->common.state.value);
168 }
169}
170
171static void
172check_packed_items(Edje_Part_Collection *pc, Edje_Part *ep, Eet_File *ef)
173{
174 unsigned int i;
175
176 for (i = 0; i < ep->items_count; ++i)
177 {
178 if (ep->items[i]->type == EDJE_PART_TYPE_GROUP && !ep->items[i]->source)
179 error_and_abort(ef, "Collection %i: missing source on packed item "
180 "of type GROUP in part \"%s\"\n",
181 pc->id, ep->name);
182 if (ep->type == EDJE_PART_TYPE_TABLE && (ep->items[i]->col < 0 || ep->items[i]->row < 0))
183 error_and_abort(ef, "Collection %i: missing col/row on packed item "
184 "for part \"%s\" of type TABLE\n",
185 pc->id, ep->name);
186 }
187}
188
189static void
190check_nameless_state(Edje_Part_Collection *pc, Edje_Part *ep, Edje_Part_Description_Common *ed, Eet_File *ef)
191{
192 if (!ed->state.name)
193 error_and_abort(ef, "Collection %i: description with state missing on part \"%s\"\n",
194 pc->id, ep->name);
195}
196
197static void
198check_part (Edje_Part_Collection *pc, Edje_Part *ep, Eet_File *ef)
199{
200 unsigned int i;
201 /* FIXME: check image set and sort them. */
202 if (!ep->default_desc)
203 error_and_abort(ef, "Collection %i: default description missing "
204 "for part \"%s\"\n", pc->id, ep->name);
205
206 for (i = 0; i < ep->other.desc_count; ++i)
207 check_nameless_state(pc, ep, ep->other.desc[i], ef);
208
209 if (ep->type == EDJE_PART_TYPE_IMAGE)
210 {
211 check_image_part_desc(pc, ep, (Edje_Part_Description_Image*) ep->default_desc, ef);
212
213 for (i = 0; i < ep->other.desc_count; ++i)
214 check_image_part_desc (pc, ep, (Edje_Part_Description_Image*) ep->other.desc[i], ef);
215 }
216 else if ((ep->type == EDJE_PART_TYPE_BOX) ||
217 (ep->type == EDJE_PART_TYPE_TABLE))
218 check_packed_items(pc, ep, ef);
219}
220
221static void
222check_program (Edje_Part_Collection *pc, Edje_Program *ep, Eet_File *ef)
223{
224 switch (ep->action)
225 {
226 case EDJE_ACTION_TYPE_STATE_SET:
227 case EDJE_ACTION_TYPE_ACTION_STOP:
228 case EDJE_ACTION_TYPE_DRAG_VAL_SET:
229 case EDJE_ACTION_TYPE_DRAG_VAL_STEP:
230 case EDJE_ACTION_TYPE_DRAG_VAL_PAGE:
231 if (!ep->targets)
232 error_and_abort(ef, "Collection %i: target missing in program "
233 "\"%s\"\n", pc->id, ep->name);
234 break;
235 default:
236 break;
237 }
238}
239
240static int
241data_write_header(Eet_File *ef)
242{
243 int bytes = 0;
244
245 if (edje_file)
246 {
247 if (edje_file->collection)
248 {
249 Edje_Part_Collection_Directory_Entry *ce;
250
251 /* copy aliases into collection directory */
252 EINA_LIST_FREE(aliases, ce)
253 {
254 Edje_Part_Collection_Directory_Entry *sce;
255 Eina_Iterator *it;
256
257 if (!ce->entry)
258 error_and_abort(ef, "Collection %i: name missing.\n", ce->id);
259
260 it = eina_hash_iterator_data_new(edje_file->collection);
261
262 EINA_ITERATOR_FOREACH(it, sce)
263 if (ce->id == sce->id)
264 {
265 memcpy(&ce->count, &sce->count, sizeof (ce->count));
266 break;
267 }
268
269 if (!sce)
270 error_and_abort(ef, "Collection %s (%i) can't find an correct alias.\n", ce->entry, ce->id);
271
272 eina_iterator_free(it);
273
274 eina_hash_direct_add(edje_file->collection, ce->entry, ce);
275 }
276 }
277 bytes = eet_data_write(ef, edd_edje_file, "edje/file", edje_file, 1);
278 if (bytes <= 0)
279 error_and_abort(ef, "Unable to write \"edje_file\" entry to \"%s\" \n",
280 file_out);
281 }
282
283 if (verbose)
284 {
285 printf("%s: Wrote %9i bytes (%4iKb) for \"edje_file\" header\n",
286 progname, bytes, (bytes + 512) / 1024);
287 }
288
289 return bytes;
290}
291
292static int
293data_write_fonts(Eet_File *ef, int *font_num, int *input_bytes, int *input_raw_bytes)
294{
295 Eina_Iterator *it;
296 int bytes = 0;
297 int total_bytes = 0;
298 Font *fn;
299
300 if (!edje_file->fonts)
301 return 0;
302
303 it = eina_hash_iterator_data_new(edje_file->fonts);
304 EINA_ITERATOR_FOREACH(it, fn)
305 {
306 void *fdata = NULL;
307 int fsize = 0;
308 Eina_List *ll;
309 FILE *f;
310
311 f = fopen(fn->file, "rb");
312 if (f)
313 {
314 long pos;
315
316 fseek(f, 0, SEEK_END);
317 pos = ftell(f);
318 rewind(f);
319 fdata = malloc(pos);
320 if (fdata)
321 {
322 if (fread(fdata, pos, 1, f) != 1)
323 error_and_abort(ef, "Unable to read all of font "
324 "file \"%s\"\n", fn->file);
325 fsize = pos;
326 }
327 fclose(f);
328 }
329 else
330 {
331 char *data;
332
333 EINA_LIST_FOREACH(fnt_dirs, ll, data)
334 {
335 char buf[4096];
336
337 snprintf(buf, sizeof(buf), "%s/%s", data, fn->file);
338 f = fopen(buf, "rb");
339 if (f)
340 {
341 long pos;
342
343 fseek(f, 0, SEEK_END);
344 pos = ftell(f);
345 rewind(f);
346 fdata = malloc(pos);
347 if (fdata)
348 {
349 if (fread(fdata, pos, 1, f) != 1)
350 error_and_abort(ef, "Unable to read all of font "
351 "file \"%s\"\n", buf);
352 fsize = pos;
353 }
354 fclose(f);
355 if (fdata) break;
356 }
357 }
358 }
359 if (!fdata)
360 {
361 error_and_abort(ef, "Unable to load font part \"%s\" entry "
362 "to %s \n", fn->file, file_out);
363 }
364 else
365 {
366 char buf[4096];
367
368 snprintf(buf, sizeof(buf), "edje/fonts/%s", fn->name);
369 bytes = eet_write(ef, buf, fdata, fsize, 1);
370 if (bytes <= 0)
371 error_and_abort(ef, "Unable to write font part \"%s\" as \"%s\" "
372 "part entry to %s \n", fn->file, buf, file_out);
373
374 *font_num += 1;
375 total_bytes += bytes;
376 *input_bytes += fsize;
377 *input_raw_bytes += fsize;
378
379 if (verbose)
380 {
381 printf("%s: Wrote %9i bytes (%4iKb) for \"%s\" font entry \"%s\" compress: [real: %2.1f%%]\n",
382 progname, bytes, (bytes + 512) / 1024, buf, fn->file,
383 100 - (100 * (double)bytes) / ((double)(fsize))
384 );
385 }
386 free(fdata);
387 }
388 }
389 eina_iterator_free(it);
390
391 return total_bytes;
392}
393
394static void
395error_and_abort_image_load_error(Eet_File *ef, const char *file, int error)
396{
397 const char *errmsg = evas_load_error_str(error);
398 char hint[1024] = "";
399
400 if (error == EVAS_LOAD_ERROR_DOES_NOT_EXIST)
401 {
402 snprintf
403 (hint, sizeof(hint),
404 " Check if path to file \"%s\" is correct "
405 "(both directory and file name).",
406 file);
407 }
408 else if (error == EVAS_LOAD_ERROR_CORRUPT_FILE)
409 {
410 snprintf
411 (hint, sizeof(hint),
412 " Check if file \"%s\" is consistent.",
413 file);
414 }
415 else if (error == EVAS_LOAD_ERROR_UNKNOWN_FORMAT)
416 {
417 const char *ext = strrchr(file, '.');
418 const char **itr, *known_loaders[] = {
419 /* list from evas_image_load.c */
420 "png",
421 "jpg",
422 "jpeg",
423 "jfif",
424 "eet",
425 "edj",
426 "eap",
427 "edb",
428 "xpm",
429 "tiff",
430 "tif",
431 "svg",
432 "svgz",
433 "gif",
434 "pbm",
435 "pgm",
436 "ppm",
437 "pnm",
438 NULL
439 };
440
441 if (!ext)
442 {
443 snprintf
444 (hint, sizeof(hint),
445 " File \"%s\" does not have an extension, "
446 "maybe it should?",
447 file);
448 goto show_err;
449 }
450
451 ext++;
452 for (itr = known_loaders; *itr; itr++)
453 {
454 if (strcasecmp(ext, *itr) == 0)
455 {
456 snprintf
457 (hint, sizeof(hint),
458 " Check if Evas was compiled with %s module enabled and "
459 "all required dependencies exist.",
460 ext);
461 goto show_err;
462 }
463 }
464
465 snprintf(hint, sizeof(hint),
466 " Check if Evas supports loading files of type \"%s\" (%s) "
467 "and this module was compiled and all its dependencies exist.",
468 ext, file);
469 }
470 show_err:
471 error_and_abort
472 (ef, "Unable to load image \"%s\" used by file \"%s\": %s.%s\n",
473 file, file_out, errmsg, hint);
474}
475
476static int
477data_write_images(Eet_File *ef, int *image_num, int *input_bytes, int *input_raw_bytes)
478{
479 unsigned int i;
480 int bytes = 0;
481 int total_bytes = 0;
482
483 if ((edje_file) && (edje_file->image_dir))
484 {
485 Ecore_Evas *ee;
486 Evas *evas;
487 Edje_Image_Directory_Entry *img;
488
489 ecore_init();
490 ecore_evas_init();
491
492 ee = ecore_evas_buffer_new(1, 1);
493 if (!ee)
494 error_and_abort(ef, "Cannot create buffer engine canvas for image "
495 "load.\n");
496
497 evas = ecore_evas_get(ee);
498 for (i = 0; i < edje_file->image_dir->entries_count; i++)
499 {
500 img = &edje_file->image_dir->entries[i];
501
502 if (img->source_type == EDJE_IMAGE_SOURCE_TYPE_EXTERNAL)
503 {
504 }
505 else
506 {
507 Evas_Object *im;
508 Eina_List *ll;
509 char *data;
510 int load_err = EVAS_LOAD_ERROR_NONE;
511
512 im = NULL;
513 EINA_LIST_FOREACH(img_dirs, ll, data)
514 {
515 char buf[4096];
516
517 snprintf(buf, sizeof(buf), "%s/%s",
518 data, img->entry);
519 im = evas_object_image_add(evas);
520 if (im)
521 {
522 evas_object_image_file_set(im, buf, NULL);
523 load_err = evas_object_image_load_error_get(im);
524 if (load_err == EVAS_LOAD_ERROR_NONE)
525 break;
526 evas_object_del(im);
527 im = NULL;
528 if (load_err != EVAS_LOAD_ERROR_DOES_NOT_EXIST)
529 break;
530 }
531 }
532 if ((!im) && (load_err == EVAS_LOAD_ERROR_DOES_NOT_EXIST))
533 {
534 im = evas_object_image_add(evas);
535 if (im)
536 {
537 evas_object_image_file_set(im, img->entry, NULL);
538 load_err = evas_object_image_load_error_get(im);
539 if (load_err != EVAS_LOAD_ERROR_NONE)
540 {
541 evas_object_del(im);
542 im = NULL;
543 }
544 }
545 }
546 if (im)
547 {
548 void *im_data;
549 int im_w, im_h;
550 int im_alpha;
551 char buf[256];
552
553 evas_object_image_size_get(im, &im_w, &im_h);
554 im_alpha = evas_object_image_alpha_get(im);
555 im_data = evas_object_image_data_get(im, 0);
556 if ((im_data) && (im_w > 0) && (im_h > 0))
557 {
558 int mode, qual;
559
560 snprintf(buf, sizeof(buf), "edje/images/%i", img->id);
561 qual = 80;
562 if ((img->source_type == EDJE_IMAGE_SOURCE_TYPE_INLINE_PERFECT) &&
563 (img->source_param == 0))
564 mode = 0; /* RAW */
565 else if ((img->source_type == EDJE_IMAGE_SOURCE_TYPE_INLINE_PERFECT) &&
566 (img->source_param == 1))
567 mode = 1; /* COMPRESS */
568 else
569 mode = 2; /* LOSSY */
570 if ((mode == 0) && (no_raw))
571 {
572 mode = 1; /* promote compression */
573 img->source_param = 95;
574 }
575 if ((mode == 2) && (no_lossy)) mode = 1; /* demote compression */
576 if ((mode == 1) && (no_comp))
577 {
578 if (no_lossy) mode = 0; /* demote compression */
579 else if (no_raw)
580 {
581 img->source_param = 90;
582 mode = 2; /* no choice. lossy */
583 }
584 }
585 if (mode == 2)
586 {
587 qual = img->source_param;
588 if (qual < min_quality) qual = min_quality;
589 if (qual > max_quality) qual = max_quality;
590 }
591 if (mode == 0)
592 bytes = eet_data_image_write(ef, buf,
593 im_data, im_w, im_h,
594 im_alpha,
595 0, 0, 0);
596 else if (mode == 1)
597 bytes = eet_data_image_write(ef, buf,
598 im_data, im_w, im_h,
599 im_alpha,
600 1, 0, 0);
601 else if (mode == 2)
602 bytes = eet_data_image_write(ef, buf,
603 im_data, im_w, im_h,
604 im_alpha,
605 0, qual, 1);
606 if (bytes <= 0)
607 error_and_abort(ef, "Unable to write image part "
608 "\"%s\" as \"%s\" part entry to "
609 "%s\n", img->entry, buf,
610 file_out);
611
612 *image_num += 1;
613 total_bytes += bytes;
614 }
615 else
616 {
617 error_and_abort_image_load_error
618 (ef, img->entry, load_err);
619 }
620
621 if (verbose)
622 {
623 struct stat st;
624 const char *file = NULL;
625
626 evas_object_image_file_get(im, &file, NULL);
627 if (!file || (stat(file, &st) != 0))
628 st.st_size = 0;
629 *input_bytes += st.st_size;
630 *input_raw_bytes += im_w * im_h * 4;
631 printf("%s: Wrote %9i bytes (%4iKb) for \"%s\" image entry \"%s\" compress: [raw: %2.1f%%] [real: %2.1f%%]\n",
632 progname, bytes, (bytes + 512) / 1024, buf, img->entry,
633 100 - (100 * (double)bytes) / ((double)(im_w * im_h * 4)),
634 100 - (100 * (double)bytes) / ((double)(st.st_size))
635 );
636 }
637 evas_object_del(im);
638 }
639 else
640 {
641 error_and_abort_image_load_error
642 (ef, img->entry, load_err);
643 }
644 }
645 }
646 ecore_evas_free(ee);
647 ecore_evas_shutdown();
648 ecore_shutdown();
649 }
650
651 return total_bytes;
652}
653
654static int
655data_write_sounds(Eet_File * ef, int *sound_num, int *input_bytes, int *input_raw_bytes)
656{
657 int bytes = 0;
658 int total_bytes = 0;
659
660 if ((edje_file) && (edje_file->sound_dir))
661 {
662 Eina_List *ll;
663 Edje_Sound_Sample *sample;
664#ifdef HAVE_LIBSNDFILE
665 Edje_Sound_Encode *enc_info;
666#endif
667 char *dir_path = NULL;
668 char snd_path[PATH_MAX];
669 char sndid_str[15];
670 void *fdata;
671 FILE *fp = NULL;
672 struct stat st;
673 int size = 0;
674 int i;
675
676 for (i = 0; i < (int)edje_file->sound_dir->samples_count; i++)
677 {
678 sample = &edje_file->sound_dir->samples[i];
679 memset(&st, 0, sizeof(struct stat));
680
681 // Search the Sound file in all the -sd ( sound directory )
682 EINA_LIST_FOREACH(snd_dirs, ll, dir_path)
683 {
684 snprintf((char *)snd_path, sizeof(snd_path), "%s/%s", dir_path,
685 sample->snd_src);
686 stat(snd_path, &st);
687 if (st.st_size) break;
688 }
689 if (!st.st_size)
690 {
691 snprintf((char *)snd_path, sizeof(snd_path), "%s",
692 sample->snd_src);
693 stat(snd_path, &st);
694 }
695 size = st.st_size;
696 if (!size)
697 {
698 ERR("%s: Error. Unable to load sound source file : %s",
699 progname, sample->snd_src);
700 exit(-1);
701 }
702#ifdef HAVE_LIBSNDFILE
703 enc_info = _edje_multisense_encode(snd_path, sample, sample->quality);
704
705 stat(enc_info->file, &st);
706 size = st.st_size;
707 fp = fopen(enc_info->file, "rb");
708#else
709 fp = fopen(snd_path, "rb");
710#endif
711 if (!fp)
712 {
713 ERR("%s: Error: Unable to load sound data of: %s",
714 progname, sample->name);
715 exit(-1);
716 }
717
718 snprintf(sndid_str, sizeof(sndid_str), "edje/sounds/%i", sample->id);
719 fdata = malloc(size);
720 if (!fdata)
721 {
722 ERR("%s: Error. %s:%i while allocating memory to load file \"%s\"",
723 progname, file_in, line, snd_path);
724 exit(-1);
725 }
726 if (fread(fdata, size, 1, fp))
727 bytes = eet_write(ef, sndid_str, fdata, size, EINA_FALSE);
728 free(fdata);
729 fclose(fp);
730
731#ifdef HAVE_LIBSNDFILE
732 //If encoded temporary file, delete it.
733 if (enc_info->encoded) unlink(enc_info->file);
734#endif
735 *sound_num += 1;
736 total_bytes += bytes;
737 *input_bytes += size;
738 *input_raw_bytes += size;
739
740 if (verbose)
741 {
742#ifdef HAVE_LIBSNDFILE
743 printf ("%s: Wrote %9i bytes (%4iKb) for \"%s\" %s sound entry"
744 "\"%s\" \n", progname, bytes, (bytes + 512) / 1024,
745 sndid_str, enc_info->comp_type, sample->name);
746#else
747 printf ("%s: Wrote %9i bytes (%4iKb) for \"%s\" %s sound entry"
748 "\"%s\" \n", progname, bytes, (bytes + 512) / 1024,
749 sndid_str, "RAW PCM", sample->name);
750#endif
751 }
752#ifdef HAVE_LIBSNDFILE
753 if ((enc_info->file) && (!enc_info->encoded)) eina_stringshare_del(enc_info->file);
754 if (enc_info) free(enc_info);
755 enc_info = NULL;
756#endif
757 }
758 }
759 return total_bytes;
760}
761
762static void
763check_groups(Eet_File *ef)
764{
765 Edje_Part_Collection *pc;
766 Eina_List *l;
767
768 /* sanity checks for parts and programs */
769 EINA_LIST_FOREACH(edje_collections, l, pc)
770 {
771 unsigned int i;
772
773 for (i = 0; i < pc->parts_count; ++i)
774 check_part(pc, pc->parts[i], ef);
775
776#define CHECK_PROGRAM(Type, Pc, It) \
777 for (It = 0; It < Pc->programs.Type ## _count; ++It) \
778 check_program(Pc, Pc->programs.Type[i], ef); \
779
780 CHECK_PROGRAM(fnmatch, pc, i);
781 CHECK_PROGRAM(strcmp, pc, i);
782 CHECK_PROGRAM(strncmp, pc, i);
783 CHECK_PROGRAM(strrncmp, pc, i);
784 CHECK_PROGRAM(nocmp, pc, i);
785 }
786}
787
788static int
789data_write_groups(Eet_File *ef, int *collection_num)
790{
791 Eina_List *l;
792 Edje_Part_Collection *pc;
793 int bytes = 0;
794 int total_bytes = 0;
795
796 EINA_LIST_FOREACH(edje_collections, l, pc)
797 {
798 char buf[4096];
799
800 snprintf(buf, sizeof(buf), "edje/collections/%i", pc->id);
801 bytes = eet_data_write(ef, edd_edje_part_collection, buf, pc, 1);
802 if (bytes <= 0)
803 error_and_abort(ef, "Error. Unable to write \"%s\" part entry "
804 "to %s\n", buf, file_out);
805
806 *collection_num += 1;
807 total_bytes += bytes;
808
809 if (verbose)
810 {
811 printf("%s: Wrote %9i bytes (%4iKb) for \"%s\" collection entry\n",
812 progname, bytes, (bytes + 512) / 1024, buf);
813 }
814 }
815
816 return total_bytes;
817}
818
819static void
820create_script_file(Eet_File *ef, const char *filename, const Code *cd, int fd)
821{
822 FILE *f = fdopen(fd, "wb");
823 if (!f)
824 error_and_abort(ef, "Unable to open temp file \"%s\" for script "
825 "compilation.\n", filename);
826
827 Eina_List *ll;
828 Code_Program *cp;
829
830 fprintf(f, "#include <edje>\n");
831 int ln = 2;
832
833 if (cd->shared)
834 {
835 while (ln < (cd->l1 - 1))
836 {
837 fprintf(f, " \n");
838 ln++;
839 }
840 {
841 char *sp;
842 int hash = 0;
843 int newlined = 0;
844
845 for (sp = cd->shared; *sp; sp++)
846 {
847 if ((sp[0] == '#') && (newlined))
848 {
849 hash = 1;
850 }
851 newlined = 0;
852 if (sp[0] == '\n') newlined = 1;
853 if (!hash) fputc(sp[0], f);
854 else if (sp[0] == '\n') hash = 0;
855 }
856 fputc('\n', f);
857 }
858 ln += cd->l2 - cd->l1 + 1;
859 }
860 EINA_LIST_FOREACH(cd->programs, ll, cp)
861 {
862 if (cp->script)
863 {
864 while (ln < (cp->l1 - 1))
865 {
866 fprintf(f, " \n");
867 ln++;
868 }
869 /* FIXME: this prototype needs to be */
870 /* formalised and set in stone */
871 fprintf(f, "public _p%i(sig[], src[]) {", cp->id);
872 {
873 char *sp;
874 int hash = 0;
875 int newlined = 0;
876
877 for (sp = cp->script; *sp; sp++)
878 {
879 if ((sp[0] == '#') && (newlined))
880 {
881 hash = 1;
882 }
883 newlined = 0;
884 if (sp[0] == '\n') newlined = 1;
885 if (!hash) fputc(sp[0], f);
886 else if (sp[0] == '\n') hash = 0;
887 }
888 }
889 fprintf(f, "}\n");
890 ln += cp->l2 - cp->l1 + 1;
891 }
892 }
893
894 fclose(f);
895}
896
897static void
898compile_script_file(Eet_File *ef, const char *source, const char *output,
899 int script_num, int fd)
900{
901 FILE *f;
902 char buf[4096];
903 int ret;
904
905 snprintf(buf, sizeof(buf),
906 "embryo_cc -i %s/include -o %s %s",
907 eina_prefix_data_get(pfx), output, source);
908 ret = system(buf);
909
910 /* accept warnings in the embryo code */
911 if (ret < 0 || ret > 1)
912 error_and_abort(ef, "Compiling script code not clean.\n");
913
914 f = fdopen(fd, "rb");
915 if (!f)
916 error_and_abort(ef, "Unable to open script object \"%s\" for reading.\n",
917 output);
918
919 fseek(f, 0, SEEK_END);
920 int size = ftell(f);
921 rewind(f);
922
923 if (size > 0)
924 {
925 void *data = malloc(size);
926
927 if (data)
928 {
929 if (fread(data, size, 1, f) != 1)
930 error_and_abort(ef, "Unable to read all of script object "
931 "\"%s\"\n", output);
932
933 snprintf(buf, sizeof(buf), "edje/scripts/embryo/compiled/%i", script_num);
934 eet_write(ef, buf, data, size, 1);
935 free(data);
936 }
937 }
938
939 fclose(f);
940}
941
942static void
943data_write_scripts(Eet_File *ef)
944{
945 Eina_List *l;
946 int i;
947
948 if (!tmp_dir)
949#ifdef HAVE_EVIL
950 tmp_dir = (char *)evil_tmpdir_get();
951#else
952 tmp_dir = "/tmp";
953#endif
954
955 for (i = 0, l = codes; l; l = eina_list_next(l), i++)
956 {
957 char tmpn[PATH_MAX];
958 char tmpo[PATH_MAX];
959 int fd;
960 Code *cd = eina_list_data_get(l);
961
962 if (cd->is_lua)
963 continue;
964 if ((!cd->shared) && (!cd->programs))
965 continue;
966
967 snprintf(tmpn, PATH_MAX, "%s/edje_cc.sma-tmp-XXXXXX", tmp_dir);
968 fd = mkstemp(tmpn);
969 if (fd < 0)
970 error_and_abort(ef, "Unable to open temp file \"%s\" for script "
971 "compilation.\n", tmpn);
972
973 create_script_file(ef, tmpn, cd, fd);
974
975 snprintf(tmpo, PATH_MAX, "%s/edje_cc.amx-tmp-XXXXXX", tmp_dir);
976 fd = mkstemp(tmpo);
977 if (fd < 0)
978 {
979 unlink(tmpn);
980 error_and_abort(ef, "Unable to open temp file \"%s\" for script "
981 "compilation.\n", tmpn);
982 }
983 compile_script_file(ef, tmpn, tmpo, i, fd);
984
985 unlink(tmpn);
986 unlink(tmpo);
987
988 if (!no_save)
989 {
990 char buf[PATH_MAX];
991 Eina_List *ll;
992 Code_Program *cp;
993
994 if (cd->original)
995 {
996 snprintf(buf, PATH_MAX, "edje/scripts/embryo/source/%i", i);
997 eet_write(ef, buf, cd->original, strlen(cd->original) + 1, 1);
998 }
999 EINA_LIST_FOREACH(cd->programs, ll, cp)
1000 {
1001 if (!cp->original)
1002 continue;
1003 snprintf(buf, PATH_MAX, "edje/scripts/embryo/source/%i/%i", i,
1004 cp->id);
1005 eet_write(ef, buf, cp->original, strlen(cp->original) + 1, 1);
1006 }
1007 }
1008 }
1009}
1010
1011typedef struct _Edje_Lua_Script_Writer_Struct Edje_Lua_Script_Writer_Struct;
1012
1013struct _Edje_Lua_Script_Writer_Struct
1014{
1015 char *buf;
1016 int size;
1017};
1018
1019#ifdef LUA_BINARY
1020static int
1021_edje_lua_script_writer(lua_State *L __UNUSED__, const void *chunk_buf, size_t chunk_size, void *_data)
1022{
1023 Edje_Lua_Script_Writer_Struct *data;
1024 void *old;
1025
1026 data = (Edje_Lua_Script_Writer_Struct *)_data;
1027 old = data->buf;
1028 data->buf = malloc (data->size + chunk_size);
1029 memcpy (data->buf, old, data->size);
1030 memcpy (&((data->buf)[data->size]), chunk_buf, chunk_size);
1031 if (old)
1032 free (old);
1033 data->size += chunk_size;
1034
1035 return 0;
1036}
1037#endif
1038
1039void
1040_edje_lua_error_and_abort(lua_State * L, int err_code, Eet_File *ef)
1041{
1042 char *err_type;
1043
1044 switch (err_code)
1045 {
1046 case LUA_ERRRUN:
1047 err_type = "runtime";
1048 break;
1049 case LUA_ERRSYNTAX:
1050 err_type = "syntax";
1051 break;
1052 case LUA_ERRMEM:
1053 err_type = "memory allocation";
1054 break;
1055 case LUA_ERRERR:
1056 err_type = "error handler";
1057 break;
1058 default:
1059 err_type = "unknown";
1060 break;
1061 }
1062 error_and_abort(ef, "Lua %s error: %s\n", err_type, lua_tostring(L, -1));
1063}
1064
1065
1066static void
1067data_write_lua_scripts(Eet_File *ef)
1068{
1069 Eina_List *l;
1070 Eina_List *ll;
1071 Code_Program *cp;
1072 int i;
1073
1074 for (i = 0, l = codes; l; l = eina_list_next(l), i++)
1075 {
1076 char buf[4096];
1077 Code *cd;
1078 lua_State *L;
1079 int ln = 1;
1080 luaL_Buffer b;
1081 Edje_Lua_Script_Writer_Struct data;
1082#ifdef LUA_BINARY
1083 int err_code;
1084#endif
1085
1086 cd = (Code *)eina_list_data_get(l);
1087 if (!cd->is_lua)
1088 continue;
1089 if ((!cd->shared) && (!cd->programs))
1090 continue;
1091
1092 L = luaL_newstate();
1093 if (!L)
1094 error_and_abort(ef, "Lua error: Lua state could not be initialized\n");
1095
1096 luaL_buffinit(L, &b);
1097
1098 data.buf = NULL;
1099 data.size = 0;
1100 if (cd->shared)
1101 {
1102 while (ln < (cd->l1 - 1))
1103 {
1104 luaL_addchar(&b, '\n');
1105 ln++;
1106 }
1107 luaL_addstring(&b, cd->shared);
1108 ln += cd->l2 - cd->l1;
1109 }
1110
1111 EINA_LIST_FOREACH(cd->programs, ll, cp)
1112 {
1113 if (cp->script)
1114 {
1115 while (ln < (cp->l1 - 1))
1116 {
1117 luaL_addchar(&b, '\n');
1118 ln++;
1119 }
1120 luaL_addstring(&b, "_G[");
1121 lua_pushnumber(L, cp->id);
1122 luaL_addvalue(&b);
1123 luaL_addstring(&b, "] = function (ed, signal, source)");
1124 luaL_addstring(&b, cp->script);
1125 luaL_addstring(&b, "end\n");
1126 ln += cp->l2 - cp->l1 + 1;
1127 }
1128 }
1129 luaL_pushresult(&b);
1130#ifdef LUA_BINARY
1131 if (err_code = luaL_loadstring(L, lua_tostring (L, -1)))
1132 _edje_lua_error_and_abort(L, err_code, ef);
1133 lua_dump(L, _edje_lua_script_writer, &data);
1134#else // LUA_PLAIN_TEXT
1135 data.buf = (char *)lua_tostring(L, -1);
1136 data.size = strlen(data.buf);
1137#endif
1138 //printf("lua chunk size: %d\n", data.size);
1139
1140 /*
1141 * TODO load and test Lua chunk
1142 */
1143
1144 /*
1145 if (luaL_loadbuffer(L, globbuf, globbufsize, "edje_lua_script"))
1146 printf("lua load error: %s\n", lua_tostring (L, -1));
1147 if (lua_pcall(L, 0, 0, 0))
1148 printf("lua call error: %s\n", lua_tostring (L, -1));
1149 */
1150
1151 snprintf(buf, sizeof(buf), "edje/scripts/lua/%i", i);
1152 eet_write(ef, buf, data.buf, data.size, 1);
1153#ifdef LUA_BINARY
1154 free(data.buf);
1155#endif
1156 lua_close(L);
1157 }
1158}
1159
1160void
1161data_write(void)
1162{
1163 Eet_File *ef;
1164 int input_bytes = 0;
1165 int total_bytes = 0;
1166 int src_bytes = 0;
1167 int fmap_bytes = 0;
1168 int input_raw_bytes = 0;
1169 int image_num = 0;
1170 int sound_num = 0;
1171 int font_num = 0;
1172 int collection_num = 0;
1173
1174 if (!edje_file)
1175 {
1176 ERR("%s: Error. No data to put in \"%s\"",
1177 progname, file_out);
1178 exit(-1);
1179 }
1180
1181 ef = eet_open(file_out, EET_FILE_MODE_WRITE);
1182 if (!ef)
1183 {
1184 ERR("%s: Error. Unable to open \"%s\" for writing output",
1185 progname, file_out);
1186 exit(-1);
1187 }
1188
1189 check_groups(ef);
1190
1191 total_bytes += data_write_header(ef);
1192 total_bytes += data_write_fonts(ef, &font_num, &input_bytes,
1193 &input_raw_bytes);
1194 total_bytes += data_write_images(ef, &image_num, &input_bytes,
1195 &input_raw_bytes);
1196 total_bytes += data_write_sounds(ef, &sound_num, &input_bytes,
1197 &input_raw_bytes);
1198
1199 total_bytes += data_write_groups(ef, &collection_num);
1200 data_write_scripts(ef);
1201 data_write_lua_scripts(ef);
1202
1203 src_bytes = source_append(ef);
1204 total_bytes += src_bytes;
1205 fmap_bytes = source_fontmap_save(ef, fonts);
1206 total_bytes += fmap_bytes;
1207
1208 eet_close(ef);
1209
1210 if (verbose)
1211 {
1212 struct stat st;
1213
1214 if (stat(file_in, &st) != 0)
1215 st.st_size = 0;
1216 input_bytes += st.st_size;
1217 input_raw_bytes += st.st_size;
1218 printf("Summary:\n"
1219 " Wrote %i collections\n"
1220 " Wrote %i images\n"
1221 " Wrote %i sounds\n"
1222 " Wrote %i fonts\n"
1223 " Wrote %i bytes (%iKb) of original source data\n"
1224 " Wrote %i bytes (%iKb) of original source font map\n"
1225 "Conservative compression summary:\n"
1226 " Wrote total %i bytes (%iKb) from %i (%iKb) input data\n"
1227 " Output file is %3.1f%% the size of the input data\n"
1228 " Saved %i bytes (%iKb)\n"
1229 "Raw compression summary:\n"
1230 " Wrote total %i bytes (%iKb) from %i (%iKb) raw input data\n"
1231 " Output file is %3.1f%% the size of the raw input data\n"
1232 " Saved %i bytes (%iKb)\n"
1233 ,
1234 collection_num,
1235 image_num,
1236 sound_num,
1237 font_num,
1238 src_bytes, (src_bytes + 512) / 1024,
1239 fmap_bytes, (fmap_bytes + 512) / 1024,
1240 total_bytes, (total_bytes + 512) / 1024,
1241 input_bytes, (input_bytes + 512) / 1024,
1242 (100.0 * (double)total_bytes) / (double)input_bytes,
1243 input_bytes - total_bytes,
1244 (input_bytes - total_bytes + 512) / 1024,
1245 total_bytes, (total_bytes + 512) / 1024,
1246 input_raw_bytes, (input_raw_bytes + 512) / 1024,
1247 (100.0 * (double)total_bytes) / (double)input_raw_bytes,
1248 input_raw_bytes - total_bytes,
1249 (input_raw_bytes - total_bytes + 512) / 1024);
1250 }
1251}
1252
1253void
1254reorder_parts(void)
1255{
1256 Edje_Part_Collection *pc;
1257 Edje_Part **parts;
1258 Edje_Part_Parser *ep, *ep2;
1259 Eina_List *l;
1260
1261 /* sanity checks for parts and programs */
1262 EINA_LIST_FOREACH(edje_collections, l, pc)
1263 {
1264 unsigned int i, j, k;
1265 Eina_Bool found = EINA_FALSE;
1266
1267 for (i = 0; i < pc->parts_count; i++)
1268 {
1269 ep = (Edje_Part_Parser *)pc->parts[i];
1270 if (ep->reorder.insert_before && ep->reorder.insert_after)
1271 ERR("%s: Error. Unable to use together insert_before and insert_after in part \"%s\".", progname, pc->parts[i]->name);
1272
1273 if (ep->reorder.done)
1274 {
1275 continue;
1276 }
1277 if (ep->reorder.insert_before || ep->reorder.insert_after)
1278 {
1279 found = EINA_FALSE;
1280 for (j = 0; j < pc->parts_count; j++)
1281 {
1282 if (ep->reorder.insert_before &&
1283 !strcmp(ep->reorder.insert_before, pc->parts[j]->name))
1284 {
1285 ep2 = (Edje_Part_Parser *)pc->parts[j];
1286 if (ep2->reorder.after)
1287 ERR("%s: Error. The part \"%s\" is ambiguous ordered part.", progname, pc->parts[i]->name);
1288 if (ep2->reorder.linked_prev)
1289 ERR("%s: Error. Unable to insert two or more parts in same part \"%s\".", progname, pc->parts[j]->name);
1290 k = j - 1;
1291 found = EINA_TRUE;
1292 ep2->reorder.linked_prev += ep->reorder.linked_prev + 1;
1293 ep->reorder.before = (Edje_Part_Parser *)pc->parts[j];
1294 while (ep2->reorder.before)
1295 {
1296 ep2->reorder.before->reorder.linked_prev = ep2->reorder.linked_prev + 1;
1297 ep2 = ep2->reorder.before;
1298 }
1299 break;
1300 }
1301 else if (ep->reorder.insert_after &&
1302 !strcmp(ep->reorder.insert_after, pc->parts[j]->name))
1303 {
1304 ep2 = (Edje_Part_Parser *)pc->parts[j];
1305 if (ep2->reorder.before)
1306 ERR("%s: Error. The part \"%s\" is ambiguous ordered part.", progname, pc->parts[i]->name);
1307 if (ep2->reorder.linked_next)
1308 ERR("%s: Error. Unable to insert two or more parts in same part \"%s\".", progname, pc->parts[j]->name);
1309 k = j;
1310 found = EINA_TRUE;
1311 ep2->reorder.linked_next += ep->reorder.linked_next + 1;
1312 ep->reorder.after = (Edje_Part_Parser *)pc->parts[j];
1313 while (ep2->reorder.after)
1314 {
1315 ep2->reorder.after->reorder.linked_next = ep2->reorder.linked_next + 1;
1316 ep2 = ep2->reorder.after;
1317 }
1318 break;
1319 }
1320 }
1321 if (found)
1322 {
1323 unsigned int amount, linked;
1324
1325 if (((i > k) && ((i - ep->reorder.linked_prev) <= k))
1326 || ((i < k) && ((i + ep->reorder.linked_next) >= k)))
1327 ERR("%s: Error. The part order is wrong. It has circular dependency.",
1328 progname);
1329
1330 amount = ep->reorder.linked_prev + ep->reorder.linked_next + 1;
1331 linked = i - ep->reorder.linked_prev;
1332 parts = malloc(amount * sizeof(Edje_Part));
1333 for (j = 0 ; j < amount ; j++)
1334 {
1335 parts[j] = pc->parts[linked];
1336 linked++;
1337 }
1338 if (i > k)
1339 {
1340 for (j = i - ep->reorder.linked_prev - 1 ; j >= k ; j--)
1341 {
1342 pc->parts[j + amount] = pc->parts[j];
1343 pc->parts[j + amount]->id = j + amount;
1344 }
1345 for (j = 0 ; j < amount ; j++)
1346 {
1347 pc->parts[j + k] = parts[j];
1348 pc->parts[j + k]->id = j + k;
1349 }
1350 }
1351 else if (i < k)
1352 {
1353 for (j = i + ep->reorder.linked_next + 1 ; j <= k ; j++)
1354 {
1355 pc->parts[j - amount] = pc->parts[j];
1356 pc->parts[j - amount]->id = j - amount;
1357 }
1358 for (j = 0 ; j < amount ; j++)
1359 {
1360 pc->parts[j + k - amount + 1] = parts[j];
1361 pc->parts[j + k - amount + 1]->id = j + k - amount + 1;
1362 }
1363 i -= amount;
1364 }
1365 ep->reorder.done = EINA_TRUE;
1366 free(parts);
1367 }
1368 }
1369 }
1370 }
1371}
1372
1373void
1374data_queue_group_lookup(char *name)
1375{
1376 Group_Lookup *gl;
1377
1378 gl = mem_alloc(SZ(Group_Lookup));
1379 group_lookups = eina_list_append(group_lookups, gl);
1380 gl->name = mem_strdup(name);
1381}
1382
1383void
1384data_queue_part_lookup(Edje_Part_Collection *pc, const char *name, int *dest)
1385{
1386 Eina_List *l;
1387 Part_Lookup *pl;
1388
1389 EINA_LIST_FOREACH(part_lookups, l, pl)
1390 {
1391 if ((pl->pc == pc) && (pl->dest == dest))
1392 {
1393 free(pl->name);
1394 if (name[0])
1395 pl->name = mem_strdup(name);
1396 else
1397 {
1398 part_lookups = eina_list_remove(part_lookups, pl);
1399 free(pl);
1400 }
1401 return;
1402 }
1403 }
1404 if (!name[0]) return;
1405
1406 pl = mem_alloc(SZ(Part_Lookup));
1407 part_lookups = eina_list_append(part_lookups, pl);
1408 pl->pc = pc;
1409 pl->name = mem_strdup(name);
1410 pl->dest = dest;
1411}
1412
1413void
1414data_queue_copied_part_lookup(Edje_Part_Collection *pc, int *src, int *dest)
1415{
1416 Eina_List *l;
1417 Part_Lookup *pl;
1418
1419 EINA_LIST_FOREACH(part_lookups, l, pl)
1420 {
1421 if (pl->dest == src)
1422 data_queue_part_lookup(pc, pl->name, dest);
1423 }
1424}
1425
1426void
1427data_queue_anonymous_lookup(Edje_Part_Collection *pc, Edje_Program *ep, int *dest)
1428{
1429 Eina_List *l, *l2;
1430 Program_Lookup *pl;
1431
1432 if (!ep) return ; /* FIXME: should we stop compiling ? */
1433
1434 EINA_LIST_FOREACH(program_lookups, l, pl)
1435 {
1436 if (pl->u.ep == ep)
1437 {
1438 Code *cd;
1439 Code_Program *cp;
1440
1441 cd = eina_list_data_get(eina_list_last(codes));
1442
1443 EINA_LIST_FOREACH(cd->programs, l2, cp)
1444 {
1445 if (&(cp->id) == pl->dest)
1446 {
1447 cd->programs = eina_list_remove(cd->programs, cp);
1448 free(cp);
1449 cp = NULL;
1450 }
1451 }
1452 program_lookups = eina_list_remove(program_lookups, pl);
1453 free(pl);
1454 }
1455 }
1456
1457 if (dest)
1458 {
1459 pl = mem_alloc(SZ(Program_Lookup));
1460 program_lookups = eina_list_append(program_lookups, pl);
1461 pl->pc = pc;
1462 pl->u.ep = ep;
1463 pl->dest = dest;
1464 pl->anonymous = EINA_TRUE;
1465 }
1466}
1467
1468void
1469data_queue_copied_anonymous_lookup(Edje_Part_Collection *pc, int *src, int *dest)
1470{
1471 Eina_List *l;
1472 Program_Lookup *pl;
1473 unsigned int i;
1474
1475 EINA_LIST_FOREACH(program_lookups, l, pl)
1476 {
1477 if (pl->dest == src)
1478 {
1479 for (i = 0 ; i < pc->programs.fnmatch_count ; i++)
1480 {
1481 if (!strcmp(pl->u.ep->name, pc->programs.fnmatch[i]->name))
1482 data_queue_anonymous_lookup(pc, pc->programs.fnmatch[i], dest);
1483 }
1484 for (i = 0 ; i < pc->programs.strcmp_count ; i++)
1485 {
1486 if (!strcmp(pl->u.ep->name, pc->programs.strcmp[i]->name))
1487 data_queue_anonymous_lookup(pc, pc->programs.strcmp[i], dest);
1488 }
1489 for (i = 0 ; i < pc->programs.strncmp_count ; i++)
1490 {
1491 if (!strcmp(pl->u.ep->name, pc->programs.strncmp[i]->name))
1492 data_queue_anonymous_lookup(pc, pc->programs.strncmp[i], dest);
1493 }
1494 for (i = 0 ; i < pc->programs.strrncmp_count ; i++)
1495 {
1496 if (!strcmp(pl->u.ep->name, pc->programs.strrncmp[i]->name))
1497 data_queue_anonymous_lookup(pc, pc->programs.strrncmp[i], dest);
1498 }
1499 for (i = 0 ; i < pc->programs.nocmp_count ; i++)
1500 {
1501 if (!strcmp(pl->u.ep->name, pc->programs.nocmp[i]->name))
1502 data_queue_anonymous_lookup(pc, pc->programs.nocmp[i], dest);
1503 }
1504 }
1505 }
1506}
1507
1508void
1509data_queue_program_lookup(Edje_Part_Collection *pc, const char *name, int *dest)
1510{
1511 Program_Lookup *pl;
1512
1513 if (!name) return ; /* FIXME: should we stop compiling ? */
1514
1515 pl = mem_alloc(SZ(Program_Lookup));
1516 program_lookups = eina_list_append(program_lookups, pl);
1517 pl->pc = pc;
1518 pl->u.name = mem_strdup(name);
1519 pl->dest = dest;
1520 pl->anonymous = EINA_FALSE;
1521}
1522
1523void
1524data_queue_copied_program_lookup(Edje_Part_Collection *pc, int *src, int *dest)
1525{
1526 Eina_List *l;
1527 Program_Lookup *pl;
1528
1529 EINA_LIST_FOREACH(program_lookups, l, pl)
1530 {
1531 if (pl->dest == src)
1532 data_queue_program_lookup(pc, pl->u.name, dest);
1533 }
1534}
1535
1536void
1537data_queue_image_lookup(char *name, int *dest, Eina_Bool *set)
1538{
1539 Image_Lookup *il;
1540
1541 il = mem_alloc(SZ(Image_Lookup));
1542 image_lookups = eina_list_append(image_lookups, il);
1543 il->name = mem_strdup(name);
1544 il->dest = dest;
1545 il->set = set;
1546}
1547
1548void
1549data_queue_copied_image_lookup(int *src, int *dest, Eina_Bool *set)
1550{
1551 Eina_List *l;
1552 Image_Lookup *il;
1553
1554 EINA_LIST_FOREACH(image_lookups, l, il)
1555 {
1556 if (il->dest == src)
1557 data_queue_image_lookup(il->name, dest, set);
1558 }
1559}
1560void
1561data_queue_part_slave_lookup(int *master, int *slave)
1562{
1563 Slave_Lookup *sl;
1564
1565 sl = mem_alloc(SZ(Slave_Lookup));
1566 part_slave_lookups = eina_list_append(part_slave_lookups, sl);
1567 sl->master = master;
1568 sl->slave = slave;
1569}
1570
1571void
1572data_queue_image_slave_lookup(int *master, int *slave)
1573{
1574 Slave_Lookup *sl;
1575
1576 sl = mem_alloc(SZ(Slave_Lookup));
1577 image_slave_lookups = eina_list_append(image_slave_lookups, sl);
1578 sl->master = master;
1579 sl->slave = slave;
1580}
1581
1582void
1583handle_slave_lookup(Eina_List *list, int *master, int value)
1584{
1585 Eina_List *l;
1586 Slave_Lookup *sl;
1587
1588 EINA_LIST_FOREACH(list, l, sl)
1589 if (sl->master == master)
1590 *sl->slave = value;
1591}
1592
1593void
1594data_process_lookups(void)
1595{
1596 Edje_Part_Collection *pc;
1597 Part_Lookup *part;
1598 Program_Lookup *program;
1599 Group_Lookup *group;
1600 Image_Lookup *image;
1601 Eina_List *l;
1602 void *data;
1603
1604 EINA_LIST_FOREACH(edje_collections, l, pc)
1605 {
1606 unsigned int count = 0;
1607 unsigned int i;
1608
1609#define PROGRAM_ID_SET(Type, Pc, It, Count) \
1610 for (It = 0; It < Pc->programs.Type ## _count; ++It) \
1611 { \
1612 Pc->programs.Type[It]->id = Count++; \
1613 }
1614
1615 PROGRAM_ID_SET(fnmatch, pc, i, count);
1616 PROGRAM_ID_SET(strcmp, pc, i, count);
1617 PROGRAM_ID_SET(strncmp, pc, i, count);
1618 PROGRAM_ID_SET(strrncmp, pc, i, count);
1619 PROGRAM_ID_SET(nocmp, pc, i, count);
1620
1621#undef PROGRAM_ID_SET
1622 }
1623
1624 EINA_LIST_FREE(part_lookups, part)
1625 {
1626 Edje_Part *ep;
1627 unsigned int i;
1628
1629 for (i = 0; i < part->pc->parts_count; ++i)
1630 {
1631 ep = part->pc->parts[i];
1632
1633 if ((ep->name) && (!strcmp(ep->name, part->name)))
1634 {
1635 handle_slave_lookup(part_slave_lookups, part->dest, ep->id);
1636 *(part->dest) = ep->id;
1637 break;
1638 }
1639 }
1640
1641 if (i == part->pc->parts_count)
1642 {
1643 ERR("%s: Error. Unable to find part name \"%s\".",
1644 progname, part->name);
1645 exit(-1);
1646 }
1647
1648 free(part->name);
1649 free(part);
1650 }
1651
1652 EINA_LIST_FREE(program_lookups, program)
1653 {
1654 unsigned int i;
1655 Eina_Bool find = EINA_FALSE;
1656
1657#define PROGRAM_MATCH(Type, Pl, It) \
1658 for (It = 0; It < Pl->pc->programs.Type ## _count; ++It) \
1659 { \
1660 Edje_Program *ep; \
1661 \
1662 ep = Pl->pc->programs.Type[It]; \
1663 \
1664 if ((Pl->anonymous && ep == Pl->u.ep) || \
1665 ((!Pl->anonymous) && (ep->name) && (!strcmp(ep->name, Pl->u.name)))) \
1666 { \
1667 *(Pl->dest) = ep->id; \
1668 find = EINA_TRUE; \
1669 break; \
1670 } \
1671 }
1672
1673 PROGRAM_MATCH(fnmatch, program, i);
1674 PROGRAM_MATCH(strcmp, program, i);
1675 PROGRAM_MATCH(strncmp, program, i);
1676 PROGRAM_MATCH(strrncmp, program, i);
1677 PROGRAM_MATCH(nocmp, program, i);
1678
1679#undef PROGRAM_MATCH
1680
1681 if (!find)
1682 {
1683 if (!program->anonymous)
1684 ERR("%s: Error. Unable to find program name \"%s\".",
1685 progname, program->u.name);
1686 else
1687 ERR("%s: Error. Unable to find anonymous program.",
1688 progname);
1689 exit(-1);
1690 }
1691
1692 if (!program->anonymous)
1693 free(program->u.name);
1694 free(program);
1695 }
1696
1697 EINA_LIST_FREE(group_lookups, group)
1698 {
1699 Edje_Part_Collection_Directory_Entry *de;
1700
1701 de = eina_hash_find(edje_file->collection, group->name);
1702
1703 if (!de)
1704 {
1705 ERR("%s: Error. Unable to find group name \"%s\".",
1706 progname, group->name);
1707 exit(-1);
1708 }
1709
1710 free(group->name);
1711 free(group);
1712 }
1713
1714 EINA_LIST_FREE(image_lookups, image)
1715 {
1716 Edje_Image_Directory_Entry *de;
1717 Eina_Bool find = EINA_FALSE;
1718
1719 if (edje_file->image_dir)
1720 {
1721 unsigned int i;
1722
1723 for (i = 0; i < edje_file->image_dir->entries_count; ++i)
1724 {
1725 de = edje_file->image_dir->entries + i;
1726
1727 if ((de->entry) && (!strcmp(de->entry, image->name)))
1728 {
1729 handle_slave_lookup(image_slave_lookups, image->dest, de->id);
1730 if (de->source_type == EDJE_IMAGE_SOURCE_TYPE_EXTERNAL)
1731 *(image->dest) = -de->id - 1;
1732 else
1733 *(image->dest) = de->id;
1734 *(image->set) = EINA_FALSE;
1735 find = EINA_TRUE;
1736 break;
1737 }
1738 }
1739
1740 if (!find)
1741 {
1742 Edje_Image_Directory_Set *set;
1743
1744 for (i = 0; i < edje_file->image_dir->sets_count; ++i)
1745 {
1746 set = edje_file->image_dir->sets + i;
1747
1748 if ((set->name) && (!strcmp(set->name, image->name)))
1749 {
1750 handle_slave_lookup(image_slave_lookups, image->dest, set->id);
1751 *(image->dest) = set->id;
1752 *(image->set) = EINA_TRUE;
1753 find = EINA_TRUE;
1754 break;
1755 }
1756 }
1757 }
1758 }
1759
1760 if (!find)
1761 {
1762 ERR("%s: Error. Unable to find image name \"%s\".",
1763 progname, image->name);
1764 exit(-1);
1765 }
1766
1767 free(image->name);
1768 free(image);
1769 }
1770
1771 EINA_LIST_FREE(part_slave_lookups, data)
1772 free(data);
1773
1774 EINA_LIST_FREE(image_slave_lookups, data)
1775 free(data);
1776}
1777
1778static void
1779data_process_string(Edje_Part_Collection *pc, const char *prefix, char *s, void (*func)(Edje_Part_Collection *pc, char *name, char* ptr, int len))
1780{
1781 char *p;
1782 char *key;
1783 int keyl;
1784 int quote, escape;
1785
1786 key = alloca(strlen(prefix) + 2 + 1);
1787 if (!key) return;
1788 strcpy(key, prefix);
1789 strcat(key, ":\"");
1790 keyl = strlen(key);
1791 quote = 0;
1792 escape = 0;
1793 for (p = s; (p) && (*p); p++)
1794 {
1795 if (!quote)
1796 {
1797 if (*p == '\"')
1798 {
1799 quote = 1;
1800 p++;
1801 }
1802 }
1803 if (!quote)
1804 {
1805 if (!strncmp(p, key, keyl))
1806 {
1807 char *ptr;
1808 int len;
1809 int inesc = 0;
1810 char *name;
1811
1812 ptr = p;
1813 p += keyl;
1814 while ((*p))
1815 {
1816 if (!inesc)
1817 {
1818 if (*p == '\\') inesc = 1;
1819 else if (*p == '\"')
1820 {
1821 /* string concatenation, see below */
1822 if (*(p + 1) != '\"')
1823 break;
1824 else
1825 p++;
1826 }
1827 }
1828 else
1829 inesc = 0;
1830 p++;
1831 }
1832 len = p - ptr + 1;
1833 name = alloca(len);
1834 if (name)
1835 {
1836 char *pp;
1837 int i;
1838
1839 name[0] = 0;
1840 pp = ptr + keyl;
1841 inesc = 0;
1842 i = 0;
1843 while (*pp)
1844 {
1845 if (!inesc)
1846 {
1847 if (*pp == '\\') inesc = 1;
1848 else if (*pp == '\"')
1849 {
1850 /* concat strings like "foo""bar" to "foobar" */
1851 if (*(pp + 1) == '\"')
1852 pp++;
1853 else
1854 {
1855 name[i] = 0;
1856 break;
1857 }
1858 }
1859 else
1860 {
1861 name[i] = *pp;
1862 name[i + 1] = 0;
1863 i++;
1864 }
1865 }
1866 else
1867 inesc = 0;
1868 pp++;
1869 }
1870 func(pc, name, ptr, len);
1871 }
1872 }
1873 }
1874 else
1875 {
1876 if (!escape)
1877 {
1878 if (*p == '\"') quote = 0;
1879 else if (*p == '\\') escape = 1;
1880 }
1881 else if (escape)
1882 {
1883 escape = 0;
1884 }
1885 }
1886 }
1887}
1888
1889static void
1890_data_queue_part_lookup(Edje_Part_Collection *pc, char *name, char *ptr, int len)
1891{
1892 Code_Lookup *cl;
1893 cl = mem_alloc(SZ(Code_Lookup));
1894 cl->ptr = ptr;
1895 cl->len = len;
1896
1897 data_queue_part_lookup(pc, name, &(cl->val));
1898
1899 code_lookups = eina_list_append(code_lookups, cl);
1900}
1901static void
1902_data_queue_program_lookup(Edje_Part_Collection *pc, char *name, char *ptr, int len)
1903{
1904 Code_Lookup *cl;
1905
1906 cl = mem_alloc(SZ(Code_Lookup));
1907 cl->ptr = ptr;
1908 cl->len = len;
1909
1910 data_queue_program_lookup(pc, name, &(cl->val));
1911
1912 code_lookups = eina_list_append(code_lookups, cl);
1913}
1914static void
1915_data_queue_group_lookup(Edje_Part_Collection *pc __UNUSED__, char *name, char *ptr __UNUSED__, int len __UNUSED__)
1916{
1917 data_queue_group_lookup(name);
1918}
1919static void
1920_data_queue_image_pc_lookup(Edje_Part_Collection *pc __UNUSED__, char *name, char *ptr, int len)
1921{
1922 Code_Lookup *cl;
1923
1924 cl = mem_alloc(SZ(Code_Lookup));
1925 cl->ptr = ptr;
1926 cl->len = len;
1927
1928 data_queue_image_lookup(name, &(cl->val), &(cl->set));
1929
1930 code_lookups = eina_list_append(code_lookups, cl);
1931}
1932
1933void
1934data_process_scripts(void)
1935{
1936 Eina_List *l, *l2;
1937
1938 for (l = codes, l2 = edje_collections; (l) && (l2); l = eina_list_next(l), l2 = eina_list_next(l2))
1939 {
1940 Edje_Part_Collection *pc;
1941 Code *cd;
1942
1943 cd = eina_list_data_get(l);
1944 pc = eina_list_data_get(l2);
1945
1946 if ((cd->shared) && (!cd->is_lua))
1947 {
1948 data_process_string(pc, "PART", cd->shared, _data_queue_part_lookup);
1949 data_process_string(pc, "PROGRAM", cd->shared, _data_queue_program_lookup);
1950 data_process_string(pc, "IMAGE", cd->shared, _data_queue_image_pc_lookup);
1951 data_process_string(pc, "GROUP", cd->shared, _data_queue_group_lookup);
1952 }
1953
1954 if (cd->programs)
1955 {
1956 Code_Program *cp;
1957 Eina_List *ll;
1958
1959 EINA_LIST_FOREACH(cd->programs, ll, cp)
1960 {
1961 if (cp->script)
1962 {
1963 data_process_string(pc, "PART", cp->script, _data_queue_part_lookup);
1964 data_process_string(pc, "PROGRAM", cp->script, _data_queue_program_lookup);
1965 data_process_string(pc, "IMAGE", cp->script, _data_queue_image_pc_lookup);
1966 data_process_string(pc, "GROUP", cp->script, _data_queue_group_lookup);
1967 }
1968 }
1969 }
1970 }
1971}
1972
1973void
1974data_process_script_lookups(void)
1975{
1976 Eina_List *l;
1977 Code_Lookup *cl;
1978
1979 EINA_LIST_FOREACH(code_lookups, l, cl)
1980 {
1981 char buf[12];
1982 int n;
1983
1984 /* FIXME !! Handle set in program */
1985 n = eina_convert_itoa(cl->val, buf);
1986 if (n > cl->len)
1987 {
1988 ERR("%s: Error. The unexpected happened. A numeric replacement string was larger than the original!",
1989 progname);
1990 exit(-1);
1991 }
1992 memset(cl->ptr, ' ', cl->len);
1993 strncpy(cl->ptr, buf, n);
1994 }
1995}