8 # define alloca __builtin_alloca
10 # define alloca __alloca
11 #elif defined _MSC_VER
13 # define alloca _alloca
19 void *alloca (size_t);
26 #include <sys/types.h>
34 #include <Ecore_File.h>
37 # define EPP_EXT ".exe"
42 static void new_object(void);
43 static void new_statement(void);
44 static char *perform_math (char *input);
45 static int isdelim(char c);
46 static char *next_token(char *p, char *end, char **new_p, int *delim);
47 static char *stack_id(void);
48 static void stack_chop_top(void);
49 static void parse(char *data, off_t size);
51 /* simple expression parsing protos */
52 static int my_atoi(const char * s);
53 static char * _alphai(char *s, int * val);
54 static char * _betai(char *s, int * val);
55 static char * _gammai(char *s, int * val);
56 static char * _deltai(char *s, int * val);
57 static char * _get_numi(char *s, int * val);
58 static int _is_numi(char c);
59 static int _is_op1i(char c);
60 static int _is_op2i(char c);
61 static int _calci(char op, int a, int b);
63 static double my_atof(const char * s);
64 static char * _alphaf(char *s, double * val);
65 static char * _betaf(char *s, double * val);
66 static char * _gammaf(char *s, double * val);
67 static char * _deltaf(char *s, double * val);
68 static char * _get_numf(char *s, double * val);
69 static int _is_numf(char c);
70 static int _is_op1f(char c);
71 static int _is_op2f(char c);
72 static double _calcf(char op, double a, double b);
73 static int strstrip(const char *in, char *out, size_t size);
77 Eina_List *stack = NULL;
78 Eina_List *params = NULL;
80 static char file_buf[4096];
81 static int verbatim = 0;
82 static int verbatim_line1 = 0;
83 static int verbatim_line2 = 0;
84 static char *verbatim_str = NULL;
94 ERR("PARSE STACK:\n%s", s);
98 ERR("NO PARSE STACK");
102 err_show_params(void)
108 EINA_LIST_FOREACH(params, l, p)
121 static Eina_Hash *_new_object_hash = NULL;
122 static Eina_Hash *_new_statement_hash = NULL;
124 fill_object_statement_hashes(void)
128 if (_new_object_hash) return;
130 _new_object_hash = eina_hash_string_superfast_new(NULL);
131 _new_statement_hash = eina_hash_string_superfast_new(NULL);
133 n = object_handler_num();
134 for (i = 0; i < n; i++)
136 eina_hash_add(_new_object_hash, object_handlers[i].type,
137 &(object_handlers[i]));
139 n = statement_handler_num();
140 for (i = 0; i < n; i++)
142 eina_hash_add(_new_statement_hash, statement_handlers[i].type,
143 &(statement_handlers[i]));
151 New_Object_Handler *oh;
152 New_Statement_Handler *sh;
154 fill_object_statement_hashes();
156 oh = eina_hash_find(_new_object_hash, id);
159 if (oh->func) oh->func();
163 sh = eina_hash_find(_new_statement_hash, id);
166 ERR("%s:%i unhandled keyword %s",
168 (char *)eina_list_data_get(eina_list_last(stack)));
180 New_Statement_Handler *sh;
182 fill_object_statement_hashes();
184 sh = eina_hash_find(_new_statement_hash, id);
187 if (sh->func) sh->func();
191 ERR("%s:%i unhandled keyword %s",
193 (char *)eina_list_data_get(eina_list_last(stack)));
201 perform_math (char *input)
207 * Always apply floating-point arithmetic.
208 * Does this cause problems for integer parameters? (yes it will)
210 * What we should do is, loop over the string and figure out whether
211 * there are floating point operands, too and then switch to
212 * floating point math.
214 res = my_atof(input);
215 snprintf(buf, sizeof (buf), "%lf", res);
222 const char *delims = "{},;:";
228 if (c == *d) return 1;
235 next_token(char *p, char *end, char **new_p, int *delim)
237 char *tok_start = NULL, *tok_end = NULL, *tok = NULL, *sa_start = NULL;
241 int in_comment_ss = 0;
242 int in_comment_cpp = 0;
243 int in_comment_sa = 0;
248 if (p >= end) return NULL;
257 if ((!in_comment_ss) && (!in_comment_sa))
259 if ((!in_quote) && (*p == '/') && (p < (end - 1)) && (*(p + 1) == '/'))
261 if ((!in_quote) && (*p == '#'))
263 if ((!in_quote) && (*p == '/') && (p < (end - 1)) && (*(p + 1) == '*'))
269 if ((in_comment_cpp) && (*p == '#'))
275 /* handle cpp comments */
276 /* their line format is
277 * #line <line no. of next line> <filename from next line on> [??]
281 while ((pp < end) && (*pp != '\n'))
286 tmpstr = alloca(l + 1);
289 ERR("%s:%i malloc %i bytes failed",
290 file_in, line - 1, l + 1);
293 strncpy(tmpstr, p, l);
295 l = sscanf(tmpstr, "%*s %i \"%[^\"]\"", &nm, fl);
298 strcpy(file_buf, fl);
303 else if ((!in_comment_ss) && (!in_comment_sa) && (!in_comment_cpp))
321 if (isdelim(*p)) *delim = 1;
330 is_escaped = !is_escaped;
331 else if (((*p) == '"') && (!is_escaped))
341 if (((*p) == ')') && (!is_escaped))
354 /* check for end-of-token */
357 ((*delim) && (!isdelim(*p))) ||
360 {/*the line below this is never used because it skips to
361 * the 'done' label which is after the return call for
362 * in_tok being 0. is this intentional?
367 if (*p == '\n') line--;
375 if ((*p == '/') && (*(p - 1) == '*') && ((p - sa_start) > 2))
380 if (!in_tok) return NULL;
386 tok = mem_alloc(tok_end - tok_start + 2);
387 strncpy(tok, tok_start, tok_end - tok_start + 1);
388 tok[tok_end - tok_start + 1] = 0;
397 if ((*p == '\"') && (!is_escaped))
399 memmove(p, p + 1, strlen(p));
401 else if ((*p == '\\') && (*(p + 1) == 'n'))
403 memmove(p, p + 1, strlen(p));
406 else if ((*p == '\\') && (*(p + 1) == 't'))
408 memmove(p, p + 1, strlen(p));
413 memmove(p, p + 1, strlen(p));
419 if (is_escaped) is_escaped = 0;
424 else if ((tok) && (*tok == '('))
428 tok = perform_math(tok);
444 EINA_LIST_FOREACH(stack, l, data)
445 len += strlen(data) + 1;
448 EINA_LIST_FOREACH(stack, l, data)
451 if (eina_list_next(l)) strcat(id, ".");
461 /* remove top from stack */
462 top = eina_list_data_get(eina_list_last(stack));
466 stack = eina_list_remove(stack, top);
470 ERR("parse error %s:%i. } marker without matching { marker",
478 parse(char *data, off_t size)
480 char *p, *end, *token;
484 DBG("Parsing input file");
489 while ((token = next_token(p, end, &p, &delim)))
491 /* if we are in param mode, the only delimiter
492 * we'll accept is the semicolon
494 if (do_params && delim && *token != ';')
496 ERR("parse error %s:%i. %c marker before ; marker",
497 file_in, line - 1, *token);
503 if (*token == ',' || *token == ':') do_params = 1;
504 else if (*token == '}')
508 ERR("Parse error %s:%i. } marker before ; marker",
516 else if (*token == ';')
522 /* clear out params */
525 free(eina_list_data_get(params));
526 params = eina_list_remove(params, eina_list_data_get(params));
528 /* remove top from stack */
532 else if (*token == '{')
536 ERR("parse error %s:%i. { marker before ; marker",
547 params = eina_list_append(params, token);
550 stack = eina_list_append(stack, token);
552 if ((verbatim == 1) && (p < (end - 2)))
563 while ((p[0] != '{') && (p < end))
565 if (*p == '\n') line++;
573 if (*p == '\n') line++;
574 if (escaped) escaped = 0;
577 if (p[0] == '\\') escaped = 1;
578 else if (p[0] == '\"')
582 if (inquotes) inquotes = 0;
586 else if (p[0] == '\'')
590 if (insquotes) insquotes = 0;
594 else if ((!inquotes) && (!insquotes))
596 if (p[0] == '{') squigglie++;
597 else if (p[0] == '}') squigglie--;
607 if (verbatim_2 > verbatim_1)
612 l = verbatim_2 - verbatim_1 + 1;
614 strncpy(v, verbatim_1, l);
616 set_verbatim(v, l1, l2);
620 ERR("Parse error %s:%i. { marker does not have matching } marker",
635 static char *clean_file = NULL;
639 if (clean_file) unlink(clean_file);
649 track_verbatim(int on)
655 set_verbatim(char *s, int l1, int l2)
669 get_verbatim_line1(void)
671 return verbatim_line1;
675 get_verbatim_line2(void)
677 return verbatim_line2;
683 char buf[4096], buf2[4096];
685 static char tmpn[4096];
694 tmp_dir = (char *)evil_tmpdir_get();
699 strncpy(inc, file_in, 4000);
701 p = strrchr(inc, '/');
702 if (!p) strcpy(inc, "./");
704 snprintf(tmpn, PATH_MAX, "%s/edje_cc.edc-tmp-XXXXXX", tmp_dir);
713 atexit(clean_tmp_file);
715 def = mem_strdup("");
722 EINA_LIST_FOREACH(defines, l, define)
723 len += strlen(define) + 1;
724 def = mem_alloc(len + 1);
726 EINA_LIST_FOREACH(defines, l, define)
734 * Run the input through the C pre-processor.
737 snprintf(buf2, sizeof(buf2), "%s/edje/utils/epp" EPP_EXT,
738 eina_prefix_lib_get(pfx));
739 if (ecore_file_exists(buf2))
741 snprintf(buf, sizeof(buf), "%s -a %s %s -I%s %s -o %s",
742 buf2, watchfile ? watchfile : "/dev/null", file_in, inc, def, tmpn);
747 ERR("Cannot run epp: %s", buf2);
750 if (ret == EXIT_SUCCESS)
754 ERR("Exit code of epp not clean: %i", ret);
759 fd = open(file_in, O_RDONLY | O_BINARY, S_IRUSR | S_IWUSR);
762 ERR("Cannot open file \"%s\" for input. %s",
763 file_in, strerror(errno));
766 DBG("Opening \"%s\" for input", file_in);
768 size = lseek(fd, 0, SEEK_END);
769 lseek(fd, 0, SEEK_SET);
771 if (data && (read(fd, data, size) == size))
775 ERR("Cannot read file \"%s\". %s", file_in, strerror(errno));
781 EINA_LIST_FOREACH(edje_file->styles, l, stl)
785 ERR("style must have a name.");
796 str = eina_list_nth(params, n);
808 str = eina_list_nth(params, n);
811 ERR("%s:%i no parameter supplied as argument %i",
812 file_in, line - 1, n + 1);
816 if (str[0] == 0) return 0;
818 ret = strtol(str, &end, 0);
819 if ((ret == LONG_MIN) || (ret == LONG_MAX))
821 n = 0; // do nothing. shut gcc warnings up
823 if ((end != str) && (end[0] == 0)) return 1;
833 str = eina_list_nth(params, n);
836 ERR("%s:%i no parameter supplied as argument %i",
837 file_in, line - 1, n + 1);
846 _parse_enum(char *str, va_list va)
849 va_copy(va2, va); /* iterator for the error message */
856 s = va_arg(va, char *);
858 /* End of the list, nothing matched. */
861 ERR("%s:%i token %s not one of:", file_in, line - 1, str);
862 s = va_arg(va2, char *);
866 fprintf(stderr, " %s", s);
867 s = va_arg(va2, char *);
870 fprintf(stderr, "\n");
891 parse_enum(int n, ...)
897 str = eina_list_nth(params, n);
900 ERR("%s:%i no parameter supplied as argument %i",
901 file_in, line - 1, n + 1);
907 result = _parse_enum(str, va);
914 parse_flags(int n, ...)
922 EINA_LIST_FOREACH(eina_list_nth_list(params, n), lst, data)
923 result |= _parse_enum(data, va);
935 str = eina_list_nth(params, n);
938 ERR("%s:%i no parameter supplied as argument %i",
939 file_in, line - 1, n + 1);
948 parse_int_range(int n, int f, int t)
953 str = eina_list_nth(params, n);
956 ERR("%s:%i no parameter supplied as argument %i",
957 file_in, line - 1, n + 1);
962 if ((i < f) || (i > t))
964 ERR("%s:%i integer %i out of range of %i to %i inclusive",
965 file_in, line - 1, i, f, t);
975 char *str, buf[4096];
978 str = eina_list_nth(params, n);
981 ERR("%s:%i no parameter supplied as argument %i",
982 file_in, line - 1, n + 1);
987 if (!strstrip(str, buf, sizeof (buf)))
989 ERR("%s:%i expression is too long",
994 if (!strcasecmp(buf, "false") || !strcasecmp(buf, "off"))
996 if (!strcasecmp(buf, "true") || !strcasecmp(buf, "on"))
1000 if ((i < 0) || (i > 1))
1002 ERR("%s:%i integer %i out of range of 0 to 1 inclusive",
1003 file_in, line - 1, i);
1016 str = eina_list_nth(params, n);
1019 ERR("%s:%i no parameter supplied as argument %i",
1020 file_in, line - 1, n + 1);
1029 parse_float_range(int n, double f, double t)
1034 str = eina_list_nth(params, n);
1037 ERR("%s:%i no parameter supplied as argument %i",
1038 file_in, line - 1, n + 1);
1043 if ((i < f) || (i > t))
1045 ERR("%s:%i float %3.3f out of range of %3.3f to %3.3f inclusive",
1046 file_in, line - 1, i, f, t);
1056 return eina_list_count (params);
1060 check_arg_count(int required_args)
1062 int num_args = eina_list_count (params);
1064 if (num_args != required_args)
1066 ERR("%s:%i got %i arguments, but expected %i",
1067 file_in, line - 1, num_args, required_args);
1074 check_min_arg_count(int min_required_args)
1076 int num_args = eina_list_count (params);
1078 if (num_args < min_required_args)
1080 ERR("%s:%i got %i arguments, but expected at least %i",
1081 file_in, line - 1, num_args, min_required_args);
1087 /* simple expression parsing stuff */
1090 * alpha ::= beta + beta || beta
1091 * beta ::= gamma + gamma || gamma
1092 * gamma ::= num || delta
1093 * delta ::= '(' alpha ')'
1097 /* int set of function */
1100 my_atoi(const char *s)
1106 if (!strstrip(s, buf, sizeof(buf)))
1108 ERR("%s:%i expression is too long",
1117 _deltai(char *s, int *val)
1119 if (!val) return NULL;
1122 ERR("%s:%i unexpected character at %s",
1123 file_in, line - 1, s);
1129 s = _alphai(s, val);
1137 _funci(char *s, int *val)
1139 if (!strncmp(s, "floor(", 6))
1142 s = _deltai(s, val);
1145 else if (!strncmp(s, "ceil(", 5))
1148 s = _deltai(s, val);
1153 ERR("%s:%i unexpected character at %s",
1154 file_in, line - 1, s);
1160 _gammai(char *s, int *val)
1162 if (!val) return NULL;
1165 s = _get_numi(s, val);
1168 else if ('(' == s[0])
1170 s = _deltai(s, val);
1176 // ERR("%s:%i unexpected character at %s",
1177 // progname, file_in, line - 1, s);
1183 _betai(char *s, int *val)
1188 if (!val) return NULL;
1189 s = _gammai(s, &a1);
1190 while (_is_op1i(s[0]))
1194 s = _gammai(s, &a2);
1195 a1 = _calci(op, a1, a2);
1202 _alphai(char *s, int *val)
1207 if (!val) return NULL;
1209 while (_is_op2i(s[0]))
1214 a1 = _calci(op, a1, a2);
1221 _get_numi(char *s, int *val)
1227 while ((('0' <= s[pos]) && ('9' >= s[pos])) ||
1228 ((0 == pos) && ('-' == s[pos])))
1241 if (((c >= '0') && (c <= '9')) || ('-' == c) || ('+' == c))
1273 _calci(char op, int a, int b)
1286 ERR("%s:%i divide by zero", file_in, line - 1);
1292 if (0 != b) a = a % b;
1294 ERR("%s:%i modula by zero", file_in, line - 1);
1297 ERR("%s:%i unexpected character '%c'", file_in, line - 1, op);
1302 /* float set of functoins */
1305 my_atof(const char *s)
1312 if (!strstrip(s, buf, sizeof (buf)))
1314 ERR("%s:%i expression is too long", file_in, line - 1);
1322 _deltaf(char *s, double *val)
1324 if (!val) return NULL;
1327 ERR("%s:%i unexpected character at %s", file_in, line - 1, s);
1333 s = _alphaf(s, val);
1340 _funcf(char *s, double *val)
1342 if (!strncmp(s, "floor(", 6))
1345 s = _deltaf(s, val);
1348 else if (!strncmp(s, "ceil(", 5))
1351 s = _deltaf(s, val);
1356 ERR("%s:%i unexpected character at %s", file_in, line - 1, s);
1362 _gammaf(char *s, double *val)
1364 if (!val) return NULL;
1368 s = _get_numf(s, val);
1371 else if ('(' == s[0])
1373 s = _deltaf(s, val);
1379 // ERR("%s:%i unexpected character at %s",
1380 // progname, file_in, line - 1, s);
1386 _betaf(char *s, double *val)
1391 if (!val) return NULL;
1392 s = _gammaf(s, &a1);
1393 while (_is_op1f(s[0]))
1397 s = _gammaf(s, &a2);
1398 a1 = _calcf(op, a1, a2);
1405 _alphaf(char *s, double *val)
1410 if (!val) return NULL;
1412 while (_is_op2f(s[0]))
1417 a1 = _calcf(op, a1, a2);
1424 _get_numf(char *s, double *val)
1431 while ((('0' <= s[pos]) && ('9' >= s[pos])) ||
1433 ((0 == pos) && ('-' == s[pos])))
1446 if (((c >= '0') && (c <= '9'))
1480 _calcf(char op, double a, double b)
1493 ERR("%s:%i divide by zero", file_in, line - 1);
1499 if (0 != b) a = (double)((int)a % (int)b);
1501 ERR("%s:%i modula by zero", file_in, line - 1);
1504 ERR("%s:%i unexpected character '%c'", file_in, line - 1, op);
1510 strstrip(const char *in, char *out, size_t size)
1512 if ((size -1 ) < strlen(in))
1514 ERR("%s:%i expression is too long", file_in, line - 1);
1517 /* remove spaces and tabs */
1520 if ((0x20 != *in) && (0x09 != *in))