diff options
Diffstat (limited to '')
-rw-r--r-- | libraries/edje/src/bin/edje_cc_parse.c | 1552 |
1 files changed, 1552 insertions, 0 deletions
diff --git a/libraries/edje/src/bin/edje_cc_parse.c b/libraries/edje/src/bin/edje_cc_parse.c new file mode 100644 index 0000000..ae68e00 --- /dev/null +++ b/libraries/edje/src/bin/edje_cc_parse.c | |||
@@ -0,0 +1,1552 @@ | |||
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 | ||
17 | extern "C" | ||
18 | # endif | ||
19 | void *alloca (size_t); | ||
20 | #endif | ||
21 | |||
22 | #include <string.h> | ||
23 | #include <ctype.h> | ||
24 | #include <limits.h> | ||
25 | #include <errno.h> | ||
26 | #include <sys/types.h> | ||
27 | #include <sys/stat.h> | ||
28 | #include <unistd.h> | ||
29 | #include <fcntl.h> | ||
30 | #include <math.h> | ||
31 | |||
32 | #include "edje_cc.h" | ||
33 | #include <Ecore.h> | ||
34 | #include <Ecore_File.h> | ||
35 | |||
36 | #ifdef _WIN32 | ||
37 | # define EPP_EXT ".exe" | ||
38 | #else | ||
39 | # define EPP_EXT | ||
40 | #endif | ||
41 | |||
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); | ||
50 | |||
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); | ||
62 | |||
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); | ||
74 | |||
75 | |||
76 | int line = 0; | ||
77 | Eina_List *stack = NULL; | ||
78 | Eina_List *params = NULL; | ||
79 | |||
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; | ||
85 | |||
86 | static void | ||
87 | err_show_stack(void) | ||
88 | { | ||
89 | char *s; | ||
90 | |||
91 | s = stack_id(); | ||
92 | if (s) | ||
93 | { | ||
94 | printf("PARSE STACK:\n%s\n", s); | ||
95 | free(s); | ||
96 | } | ||
97 | else | ||
98 | printf("NO PARSE STACK\n"); | ||
99 | } | ||
100 | |||
101 | static void | ||
102 | err_show_params(void) | ||
103 | { | ||
104 | Eina_List *l; | ||
105 | char *p; | ||
106 | |||
107 | printf("PARAMS:"); | ||
108 | EINA_LIST_FOREACH(params, l, p) | ||
109 | { | ||
110 | printf(" %s", p); | ||
111 | } | ||
112 | printf("\n"); | ||
113 | } | ||
114 | |||
115 | static void | ||
116 | err_show(void) | ||
117 | { | ||
118 | err_show_stack(); | ||
119 | err_show_params(); | ||
120 | } | ||
121 | |||
122 | static void | ||
123 | new_object(void) | ||
124 | { | ||
125 | char *id; | ||
126 | int i; | ||
127 | int handled = 0; | ||
128 | |||
129 | id = stack_id(); | ||
130 | for (i = 0; i < object_handler_num(); i++) | ||
131 | { | ||
132 | if (!strcmp(object_handlers[i].type, id)) | ||
133 | { | ||
134 | handled = 1; | ||
135 | if (object_handlers[i].func) | ||
136 | { | ||
137 | object_handlers[i].func(); | ||
138 | } | ||
139 | break; | ||
140 | } | ||
141 | } | ||
142 | if (!handled) | ||
143 | { | ||
144 | for (i = 0; i < statement_handler_num(); i++) | ||
145 | { | ||
146 | if (!strcmp(statement_handlers[i].type, id)) | ||
147 | { | ||
148 | free(id); | ||
149 | return; | ||
150 | } | ||
151 | } | ||
152 | } | ||
153 | if (!handled) | ||
154 | { | ||
155 | ERR("%s: Error. %s:%i unhandled keyword %s", | ||
156 | progname, file_in, line - 1, | ||
157 | (char *)eina_list_data_get(eina_list_last(stack))); | ||
158 | err_show(); | ||
159 | exit(-1); | ||
160 | } | ||
161 | free(id); | ||
162 | } | ||
163 | |||
164 | static void | ||
165 | new_statement(void) | ||
166 | { | ||
167 | char *id; | ||
168 | int i; | ||
169 | int handled = 0; | ||
170 | |||
171 | id = stack_id(); | ||
172 | for (i = 0; i < statement_handler_num(); i++) | ||
173 | { | ||
174 | if (!strcmp(statement_handlers[i].type, id)) | ||
175 | { | ||
176 | handled = 1; | ||
177 | if (statement_handlers[i].func) | ||
178 | { | ||
179 | statement_handlers[i].func(); | ||
180 | } | ||
181 | break; | ||
182 | } | ||
183 | } | ||
184 | if (!handled) | ||
185 | { | ||
186 | ERR("%s: Error. %s:%i unhandled keyword %s", | ||
187 | progname, file_in, line - 1, | ||
188 | (char *)eina_list_data_get(eina_list_last(stack))); | ||
189 | err_show(); | ||
190 | exit(-1); | ||
191 | } | ||
192 | free(id); | ||
193 | } | ||
194 | |||
195 | static char * | ||
196 | perform_math (char *input) | ||
197 | { | ||
198 | char buf[256]; | ||
199 | double res; | ||
200 | |||
201 | /* FIXME | ||
202 | * Always apply floating-point arithmetic. | ||
203 | * Does this cause problems for integer parameters? (yes it will) | ||
204 | * | ||
205 | * What we should do is, loop over the string and figure out whether | ||
206 | * there are floating point operands, too and then switch to | ||
207 | * floating point math. | ||
208 | */ | ||
209 | res = my_atof(input); | ||
210 | snprintf(buf, sizeof (buf), "%lf", res); | ||
211 | return strdup(buf); | ||
212 | } | ||
213 | |||
214 | static int | ||
215 | isdelim(char c) | ||
216 | { | ||
217 | const char *delims = "{},;:"; | ||
218 | char *d; | ||
219 | |||
220 | d = (char *)delims; | ||
221 | while (*d) | ||
222 | { | ||
223 | if (c == *d) return 1; | ||
224 | d++; | ||
225 | } | ||
226 | return 0; | ||
227 | } | ||
228 | |||
229 | static char * | ||
230 | next_token(char *p, char *end, char **new_p, int *delim) | ||
231 | { | ||
232 | char *tok_start = NULL, *tok_end = NULL, *tok = NULL, *sa_start = NULL; | ||
233 | int in_tok = 0; | ||
234 | int in_quote = 0; | ||
235 | int in_parens = 0; | ||
236 | int in_comment_ss = 0; | ||
237 | int in_comment_cpp = 0; | ||
238 | int in_comment_sa = 0; | ||
239 | int had_quote = 0; | ||
240 | int is_escaped = 0; | ||
241 | char *cpp_token_line = NULL; | ||
242 | char *cpp_token_file = NULL; | ||
243 | |||
244 | *delim = 0; | ||
245 | if (p >= end) return NULL; | ||
246 | while (p < end) | ||
247 | { | ||
248 | if (*p == '\n') | ||
249 | { | ||
250 | in_comment_ss = 0; | ||
251 | in_comment_cpp = 0; | ||
252 | cpp_token_line = NULL; | ||
253 | cpp_token_file = NULL; | ||
254 | line++; | ||
255 | } | ||
256 | if ((!in_comment_ss) && (!in_comment_sa)) | ||
257 | { | ||
258 | if ((!in_quote) && (*p == '/') && (p < (end - 1)) && (*(p + 1) == '/')) | ||
259 | in_comment_ss = 1; | ||
260 | if ((!in_quote) && (*p == '#')) | ||
261 | in_comment_cpp = 1; | ||
262 | if ((!in_quote) && (*p == '/') && (p < (end - 1)) && (*(p + 1) == '*')) | ||
263 | { | ||
264 | in_comment_sa = 1; | ||
265 | sa_start = p; | ||
266 | } | ||
267 | } | ||
268 | if ((in_comment_cpp) && (*p == '#')) | ||
269 | { | ||
270 | char *pp, fl[4096]; | ||
271 | char *tmpstr = NULL; | ||
272 | int l, nm; | ||
273 | |||
274 | /* handle cpp comments */ | ||
275 | /* their line format is | ||
276 | * #line <line no. of next line> <filename from next line on> [??] | ||
277 | */ | ||
278 | cpp_token_line = NULL; | ||
279 | cpp_token_file = NULL; | ||
280 | |||
281 | pp = p; | ||
282 | while ((pp < end) && (*pp != '\n')) | ||
283 | { | ||
284 | pp++; | ||
285 | } | ||
286 | l = pp - p; | ||
287 | tmpstr = alloca(l + 1); | ||
288 | if (!tmpstr) | ||
289 | { | ||
290 | ERR("%s: Error. %s:%i malloc %i bytes failed", | ||
291 | progname, file_in, line - 1, l + 1); | ||
292 | exit(-1); | ||
293 | } | ||
294 | strncpy(tmpstr, p, l); | ||
295 | tmpstr[l] = 0; | ||
296 | l = sscanf(tmpstr, "%*s %i \"%[^\"]\"", &nm, fl); | ||
297 | if (l == 2) | ||
298 | { | ||
299 | strcpy(file_buf, fl); | ||
300 | line = nm; | ||
301 | file_in = file_buf; | ||
302 | } | ||
303 | } | ||
304 | else if ((!in_comment_ss) && (!in_comment_sa) && (!in_comment_cpp)) | ||
305 | { | ||
306 | if (!in_tok) | ||
307 | { | ||
308 | if (!in_quote) | ||
309 | { | ||
310 | if (!isspace(*p)) | ||
311 | { | ||
312 | if (*p == '"') | ||
313 | { | ||
314 | in_quote = 1; | ||
315 | had_quote = 1; | ||
316 | } | ||
317 | else if (*p == '(') | ||
318 | in_parens++; | ||
319 | |||
320 | in_tok = 1; | ||
321 | tok_start = p; | ||
322 | if (isdelim(*p)) *delim = 1; | ||
323 | } | ||
324 | } | ||
325 | } | ||
326 | else | ||
327 | { | ||
328 | if (in_quote) | ||
329 | { | ||
330 | if ((*p) == '\\') | ||
331 | is_escaped = !is_escaped; | ||
332 | else if (((*p) == '"') && (!is_escaped)) | ||
333 | { | ||
334 | in_quote = 0; | ||
335 | had_quote = 1; | ||
336 | } | ||
337 | else if (is_escaped) | ||
338 | is_escaped = 0; | ||
339 | } | ||
340 | else if (in_parens) | ||
341 | { | ||
342 | if (((*p) == ')') && (!is_escaped)) | ||
343 | in_parens--; | ||
344 | } | ||
345 | else | ||
346 | { | ||
347 | if (*p == '"') | ||
348 | { | ||
349 | in_quote = 1; | ||
350 | had_quote = 1; | ||
351 | } | ||
352 | else if (*p == '(') | ||
353 | in_parens++; | ||
354 | |||
355 | /* check for end-of-token */ | ||
356 | if ( | ||
357 | (isspace(*p)) || | ||
358 | ((*delim) && (!isdelim(*p))) || | ||
359 | (isdelim(*p)) | ||
360 | ) | ||
361 | {/*the line below this is never used because it skips to | ||
362 | * the 'done' label which is after the return call for | ||
363 | * in_tok being 0. is this intentional? | ||
364 | */ | ||
365 | in_tok = 0; | ||
366 | |||
367 | tok_end = p - 1; | ||
368 | if (*p == '\n') line--; | ||
369 | goto done; | ||
370 | } | ||
371 | } | ||
372 | } | ||
373 | } | ||
374 | if (in_comment_sa) | ||
375 | { | ||
376 | if ((*p == '/') && (*(p - 1) == '*') && ((p - sa_start) > 2)) | ||
377 | in_comment_sa = 0; | ||
378 | } | ||
379 | p++; | ||
380 | } | ||
381 | if (!in_tok) return NULL; | ||
382 | tok_end = p - 1; | ||
383 | |||
384 | done: | ||
385 | *new_p = p; | ||
386 | |||
387 | tok = mem_alloc(tok_end - tok_start + 2); | ||
388 | strncpy(tok, tok_start, tok_end - tok_start + 1); | ||
389 | tok[tok_end - tok_start + 1] = 0; | ||
390 | |||
391 | if (had_quote) | ||
392 | { | ||
393 | is_escaped = 0; | ||
394 | p = tok; | ||
395 | |||
396 | while (*p) | ||
397 | { | ||
398 | if ((*p == '\"') && (!is_escaped)) | ||
399 | { | ||
400 | memmove(p, p + 1, strlen(p)); | ||
401 | } | ||
402 | else if ((*p == '\\') && (*(p + 1) == 'n')) | ||
403 | { | ||
404 | memmove(p, p + 1, strlen(p)); | ||
405 | *p = '\n'; | ||
406 | } | ||
407 | else if ((*p == '\\') && (*(p + 1) == 't')) | ||
408 | { | ||
409 | memmove(p, p + 1, strlen(p)); | ||
410 | *p = '\t'; | ||
411 | } | ||
412 | else if (*p == '\\') | ||
413 | { | ||
414 | memmove(p, p + 1, strlen(p)); | ||
415 | if (*p == '\\') p++; | ||
416 | else is_escaped = 1; | ||
417 | } | ||
418 | else | ||
419 | { | ||
420 | if (is_escaped) is_escaped = 0; | ||
421 | p++; | ||
422 | } | ||
423 | } | ||
424 | } | ||
425 | else if ((tok) && (*tok == '(')) | ||
426 | { | ||
427 | char *tmp; | ||
428 | tmp = tok; | ||
429 | tok = perform_math(tok); | ||
430 | free(tmp); | ||
431 | } | ||
432 | |||
433 | return tok; | ||
434 | } | ||
435 | |||
436 | static char * | ||
437 | stack_id(void) | ||
438 | { | ||
439 | char *id; | ||
440 | int len; | ||
441 | Eina_List *l; | ||
442 | char *data; | ||
443 | |||
444 | len = 0; | ||
445 | EINA_LIST_FOREACH(stack, l, data) | ||
446 | len += strlen(data) + 1; | ||
447 | id = mem_alloc(len); | ||
448 | id[0] = 0; | ||
449 | EINA_LIST_FOREACH(stack, l, data) | ||
450 | { | ||
451 | strcat(id, data); | ||
452 | if (eina_list_next(l)) strcat(id, "."); | ||
453 | } | ||
454 | return id; | ||
455 | } | ||
456 | |||
457 | static void | ||
458 | stack_chop_top(void) | ||
459 | { | ||
460 | char *top; | ||
461 | |||
462 | /* remove top from stack */ | ||
463 | top = eina_list_data_get(eina_list_last(stack)); | ||
464 | if (top) | ||
465 | { | ||
466 | free(top); | ||
467 | stack = eina_list_remove(stack, top); | ||
468 | } | ||
469 | else | ||
470 | { | ||
471 | ERR("%s: Error. parse error %s:%i. } marker without matching { marker", | ||
472 | progname, file_in, line - 1); | ||
473 | err_show(); | ||
474 | exit(-1); | ||
475 | } | ||
476 | } | ||
477 | |||
478 | static void | ||
479 | parse(char *data, off_t size) | ||
480 | { | ||
481 | char *p, *end, *token; | ||
482 | int delim = 0; | ||
483 | int do_params = 0; | ||
484 | |||
485 | if (verbose) | ||
486 | { | ||
487 | INF("%s: Parsing input file", | ||
488 | progname); | ||
489 | } | ||
490 | p = data; | ||
491 | end = data + size; | ||
492 | line = 1; | ||
493 | while ((token = next_token(p, end, &p, &delim))) | ||
494 | { | ||
495 | /* if we are in param mode, the only delimiter | ||
496 | * we'll accept is the semicolon | ||
497 | */ | ||
498 | if (do_params && delim && *token != ';') | ||
499 | { | ||
500 | ERR("%s: Error. parse error %s:%i. %c marker before ; marker", | ||
501 | progname, file_in, line - 1, *token); | ||
502 | err_show(); | ||
503 | exit(-1); | ||
504 | } | ||
505 | else if (delim) | ||
506 | { | ||
507 | if (*token == ',' || *token == ':') do_params = 1; | ||
508 | else if (*token == '}') | ||
509 | { | ||
510 | if (do_params) | ||
511 | { | ||
512 | ERR("%s: Error. parse error %s:%i. } marker before ; marker", | ||
513 | progname, file_in, line - 1); | ||
514 | err_show(); | ||
515 | exit(-1); | ||
516 | } | ||
517 | else | ||
518 | stack_chop_top(); | ||
519 | } | ||
520 | else if (*token == ';') | ||
521 | { | ||
522 | if (do_params) | ||
523 | { | ||
524 | do_params = 0; | ||
525 | new_statement(); | ||
526 | /* clear out params */ | ||
527 | while (params) | ||
528 | { | ||
529 | free(eina_list_data_get(params)); | ||
530 | params = eina_list_remove(params, eina_list_data_get(params)); | ||
531 | } | ||
532 | /* remove top from stack */ | ||
533 | stack_chop_top(); | ||
534 | } | ||
535 | } | ||
536 | else if (*token == '{') | ||
537 | { | ||
538 | if (do_params) | ||
539 | { | ||
540 | ERR("%s: Error. parse error %s:%i. { marker before ; marker", | ||
541 | progname, file_in, line - 1); | ||
542 | err_show(); | ||
543 | exit(-1); | ||
544 | } | ||
545 | } | ||
546 | free(token); | ||
547 | } | ||
548 | else | ||
549 | { | ||
550 | if (do_params) | ||
551 | params = eina_list_append(params, token); | ||
552 | else | ||
553 | { | ||
554 | stack = eina_list_append(stack, token); | ||
555 | new_object(); | ||
556 | if ((verbatim == 1) && (p < (end - 2))) | ||
557 | { | ||
558 | int escaped = 0; | ||
559 | int inquotes = 0; | ||
560 | int insquotes = 0; | ||
561 | int squigglie = 1; | ||
562 | int l1 = 0, l2 = 0; | ||
563 | char *verbatim_1; | ||
564 | char *verbatim_2; | ||
565 | |||
566 | l1 = line; | ||
567 | while ((p[0] != '{') && (p < end)) | ||
568 | { | ||
569 | if (*p == '\n') line++; | ||
570 | p++; | ||
571 | } | ||
572 | p++; | ||
573 | verbatim_1 = p; | ||
574 | verbatim_2 = NULL; | ||
575 | for (; p < end; p++) | ||
576 | { | ||
577 | if (*p == '\n') line++; | ||
578 | if (escaped) escaped = 0; | ||
579 | if (!escaped) | ||
580 | { | ||
581 | if (p[0] == '\\') escaped = 1; | ||
582 | else if (p[0] == '\"') | ||
583 | { | ||
584 | if (!insquotes) | ||
585 | { | ||
586 | if (inquotes) inquotes = 0; | ||
587 | else inquotes = 1; | ||
588 | } | ||
589 | } | ||
590 | else if (p[0] == '\'') | ||
591 | { | ||
592 | if (!inquotes) | ||
593 | { | ||
594 | if (insquotes) insquotes = 0; | ||
595 | else insquotes = 1; | ||
596 | } | ||
597 | } | ||
598 | else if ((!inquotes) && (!insquotes)) | ||
599 | { | ||
600 | if (p[0] == '{') squigglie++; | ||
601 | else if (p[0] == '}') squigglie--; | ||
602 | if (squigglie == 0) | ||
603 | { | ||
604 | verbatim_2 = p - 1; | ||
605 | l2 = line; | ||
606 | break; | ||
607 | } | ||
608 | } | ||
609 | } | ||
610 | } | ||
611 | if (verbatim_2 > verbatim_1) | ||
612 | { | ||
613 | int l; | ||
614 | char *v; | ||
615 | |||
616 | l = verbatim_2 - verbatim_1 + 1; | ||
617 | v = malloc(l + 1); | ||
618 | strncpy(v, verbatim_1, l); | ||
619 | v[l] = 0; | ||
620 | set_verbatim(v, l1, l2); | ||
621 | } | ||
622 | else | ||
623 | { | ||
624 | ERR("%s: Error. parse error %s:%i. { marker does not have matching } marker", | ||
625 | progname, file_in, line - 1); | ||
626 | err_show(); | ||
627 | exit(-1); | ||
628 | } | ||
629 | new_object(); | ||
630 | verbatim = 0; | ||
631 | } | ||
632 | } | ||
633 | } | ||
634 | } | ||
635 | if (verbose) | ||
636 | { | ||
637 | INF("%s: Parsing done", | ||
638 | progname); | ||
639 | } | ||
640 | } | ||
641 | |||
642 | static char *clean_file = NULL; | ||
643 | static void | ||
644 | clean_tmp_file(void) | ||
645 | { | ||
646 | if (clean_file) unlink(clean_file); | ||
647 | } | ||
648 | |||
649 | int | ||
650 | is_verbatim(void) | ||
651 | { | ||
652 | return verbatim; | ||
653 | } | ||
654 | |||
655 | void | ||
656 | track_verbatim(int on) | ||
657 | { | ||
658 | verbatim = on; | ||
659 | } | ||
660 | |||
661 | void | ||
662 | set_verbatim(char *s, int l1, int l2) | ||
663 | { | ||
664 | verbatim_line1 = l1; | ||
665 | verbatim_line2 = l2; | ||
666 | verbatim_str = s; | ||
667 | } | ||
668 | |||
669 | char * | ||
670 | get_verbatim(void) | ||
671 | { | ||
672 | return verbatim_str; | ||
673 | } | ||
674 | |||
675 | int | ||
676 | get_verbatim_line1(void) | ||
677 | { | ||
678 | return verbatim_line1; | ||
679 | } | ||
680 | |||
681 | int | ||
682 | get_verbatim_line2(void) | ||
683 | { | ||
684 | return verbatim_line2; | ||
685 | } | ||
686 | |||
687 | void | ||
688 | compile(void) | ||
689 | { | ||
690 | char buf[4096], buf2[4096]; | ||
691 | char inc[4096]; | ||
692 | static char tmpn[4096]; | ||
693 | int fd; | ||
694 | off_t size; | ||
695 | char *data, *p; | ||
696 | Eina_List *l; | ||
697 | Edje_Style *stl; | ||
698 | |||
699 | if (!tmp_dir) | ||
700 | #ifdef HAVE_EVIL | ||
701 | tmp_dir = (char *)evil_tmpdir_get(); | ||
702 | #else | ||
703 | tmp_dir = "/tmp"; | ||
704 | #endif | ||
705 | |||
706 | strncpy(inc, file_in, 4000); | ||
707 | inc[4001] = 0; | ||
708 | p = strrchr(inc, '/'); | ||
709 | if (!p) strcpy(inc, "./"); | ||
710 | else *p = 0; | ||
711 | snprintf(tmpn, PATH_MAX, "%s/edje_cc.edc-tmp-XXXXXX", tmp_dir); | ||
712 | fd = mkstemp(tmpn); | ||
713 | if (fd >= 0) | ||
714 | { | ||
715 | int ret; | ||
716 | char *def; | ||
717 | |||
718 | clean_file = tmpn; | ||
719 | close(fd); | ||
720 | atexit(clean_tmp_file); | ||
721 | if (!defines) | ||
722 | def = mem_strdup(""); | ||
723 | else | ||
724 | { | ||
725 | int len; | ||
726 | char *define; | ||
727 | |||
728 | len = 0; | ||
729 | EINA_LIST_FOREACH(defines, l, define) | ||
730 | len += strlen(define) + 1; | ||
731 | def = mem_alloc(len + 1); | ||
732 | def[0] = 0; | ||
733 | EINA_LIST_FOREACH(defines, l, define) | ||
734 | { | ||
735 | strcat(def, define); | ||
736 | strcat(def, " "); | ||
737 | } | ||
738 | } | ||
739 | |||
740 | /* | ||
741 | * Run the input through the C pre-processor. | ||
742 | */ | ||
743 | ret = -1; | ||
744 | snprintf(buf2, sizeof(buf2), "%s/edje/utils/epp" EPP_EXT, | ||
745 | eina_prefix_lib_get(pfx)); | ||
746 | if (ecore_file_exists(buf2)) | ||
747 | { | ||
748 | snprintf(buf, sizeof(buf), "%s %s -I%s %s -o %s", | ||
749 | buf2, file_in, inc, def, tmpn); | ||
750 | ret = system(buf); | ||
751 | } | ||
752 | else | ||
753 | { | ||
754 | ERR("Error. Cannot run epp: %s", buf2); | ||
755 | exit(-1); | ||
756 | } | ||
757 | if (ret == EXIT_SUCCESS) | ||
758 | file_in = tmpn; | ||
759 | else | ||
760 | { | ||
761 | ERR("Error. Exit code of epp not clean: %i", ret); | ||
762 | exit(-1); | ||
763 | } | ||
764 | free(def); | ||
765 | } | ||
766 | fd = open(file_in, O_RDONLY | O_BINARY, S_IRUSR | S_IWUSR); | ||
767 | if (fd < 0) | ||
768 | { | ||
769 | ERR("%s: Error. cannot open file \"%s\" for input. %s", | ||
770 | progname, file_in, strerror(errno)); | ||
771 | exit(-1); | ||
772 | } | ||
773 | if (verbose) | ||
774 | { | ||
775 | INF("%s: Opening \"%s\" for input", progname, file_in); | ||
776 | } | ||
777 | |||
778 | size = lseek(fd, 0, SEEK_END); | ||
779 | lseek(fd, 0, SEEK_SET); | ||
780 | data = malloc(size); | ||
781 | if (data && (read(fd, data, size) == size)) | ||
782 | parse(data, size); | ||
783 | else | ||
784 | { | ||
785 | ERR("%s: Error. cannot read file \"%s\". %s", | ||
786 | progname, file_in, strerror(errno)); | ||
787 | exit(-1); | ||
788 | } | ||
789 | free(data); | ||
790 | close(fd); | ||
791 | |||
792 | EINA_LIST_FOREACH(edje_file->styles, l, stl) | ||
793 | { | ||
794 | if (!stl->name) | ||
795 | { | ||
796 | ERR("%s: Error. style must have a name.", progname); | ||
797 | exit(-1); | ||
798 | } | ||
799 | } | ||
800 | } | ||
801 | |||
802 | int | ||
803 | is_param(int n) | ||
804 | { | ||
805 | char *str; | ||
806 | |||
807 | str = eina_list_nth(params, n); | ||
808 | if (str) return 1; | ||
809 | return 0; | ||
810 | } | ||
811 | |||
812 | int | ||
813 | is_num(int n) | ||
814 | { | ||
815 | char *str; | ||
816 | char *end; | ||
817 | long int ret; | ||
818 | |||
819 | str = eina_list_nth(params, n); | ||
820 | if (!str) | ||
821 | { | ||
822 | ERR("%s: Error. %s:%i no parameter supplied as argument %i", | ||
823 | progname, file_in, line - 1, n + 1); | ||
824 | err_show(); | ||
825 | exit(-1); | ||
826 | } | ||
827 | if (str[0] == 0) return 0; | ||
828 | end = str; | ||
829 | ret = strtol(str, &end, 0); | ||
830 | if ((ret == LONG_MIN) || (ret == LONG_MAX)) | ||
831 | { | ||
832 | n = 0; // do nothing. shut gcc warnings up | ||
833 | } | ||
834 | if ((end != str) && (end[0] == 0)) return 1; | ||
835 | return 0; | ||
836 | } | ||
837 | |||
838 | char * | ||
839 | parse_str(int n) | ||
840 | { | ||
841 | char *str; | ||
842 | char *s; | ||
843 | |||
844 | str = eina_list_nth(params, n); | ||
845 | if (!str) | ||
846 | { | ||
847 | ERR("%s: Error. %s:%i no parameter supplied as argument %i", | ||
848 | progname, file_in, line - 1, n + 1); | ||
849 | err_show(); | ||
850 | exit(-1); | ||
851 | } | ||
852 | s = mem_strdup(str); | ||
853 | return s; | ||
854 | } | ||
855 | |||
856 | static int | ||
857 | _parse_enum(char *str, va_list va) | ||
858 | { | ||
859 | va_list va2; | ||
860 | va_copy(va2, va); /* iterator for the error message */ | ||
861 | |||
862 | for (;;) | ||
863 | { | ||
864 | char *s; | ||
865 | int v; | ||
866 | |||
867 | s = va_arg(va, char *); | ||
868 | |||
869 | /* End of the list, nothing matched. */ | ||
870 | if (!s) | ||
871 | { | ||
872 | fprintf(stderr, "%s: Error. %s:%i token %s not one of:", | ||
873 | progname, file_in, line - 1, str); | ||
874 | s = va_arg(va2, char *); | ||
875 | while (s) | ||
876 | { | ||
877 | va_arg(va2, int); | ||
878 | fprintf(stderr, " %s", s); | ||
879 | s = va_arg(va2, char *); | ||
880 | if (!s) break; | ||
881 | } | ||
882 | fprintf(stderr, "\n"); | ||
883 | va_end(va2); | ||
884 | va_end(va); | ||
885 | err_show(); | ||
886 | exit(-1); | ||
887 | } | ||
888 | |||
889 | v = va_arg(va, int); | ||
890 | if (!strcmp(s, str)) | ||
891 | { | ||
892 | va_end(va2); | ||
893 | va_end(va); | ||
894 | return v; | ||
895 | } | ||
896 | } | ||
897 | va_end(va2); | ||
898 | va_end(va); | ||
899 | return 0; | ||
900 | } | ||
901 | |||
902 | int | ||
903 | parse_enum(int n, ...) | ||
904 | { | ||
905 | char *str; | ||
906 | int result; | ||
907 | va_list va; | ||
908 | |||
909 | str = eina_list_nth(params, n); | ||
910 | if (!str) | ||
911 | { | ||
912 | ERR("%s: Error. %s:%i no parameter supplied as argument %i", | ||
913 | progname, file_in, line - 1, n + 1); | ||
914 | err_show(); | ||
915 | exit(-1); | ||
916 | } | ||
917 | |||
918 | va_start(va, n); | ||
919 | result = _parse_enum(str, va); | ||
920 | va_end(va); | ||
921 | |||
922 | return result; | ||
923 | } | ||
924 | |||
925 | int | ||
926 | parse_flags(int n, ...) | ||
927 | { | ||
928 | Eina_List *lst; | ||
929 | int result = 0; | ||
930 | va_list va; | ||
931 | char *data; | ||
932 | |||
933 | va_start(va, n); | ||
934 | EINA_LIST_FOREACH(eina_list_nth_list(params, n), lst, data) | ||
935 | result |= _parse_enum(data, va); | ||
936 | va_end(va); | ||
937 | |||
938 | return result; | ||
939 | } | ||
940 | |||
941 | int | ||
942 | parse_int(int n) | ||
943 | { | ||
944 | char *str; | ||
945 | int i; | ||
946 | |||
947 | str = eina_list_nth(params, n); | ||
948 | if (!str) | ||
949 | { | ||
950 | ERR("%s: Error. %s:%i no parameter supplied as argument %i", | ||
951 | progname, file_in, line - 1, n + 1); | ||
952 | err_show(); | ||
953 | exit(-1); | ||
954 | } | ||
955 | i = my_atoi(str); | ||
956 | return i; | ||
957 | } | ||
958 | |||
959 | int | ||
960 | parse_int_range(int n, int f, int t) | ||
961 | { | ||
962 | char *str; | ||
963 | int i; | ||
964 | |||
965 | str = eina_list_nth(params, n); | ||
966 | if (!str) | ||
967 | { | ||
968 | ERR("%s: Error. %s:%i no parameter supplied as argument %i", | ||
969 | progname, file_in, line - 1, n + 1); | ||
970 | err_show(); | ||
971 | exit(-1); | ||
972 | } | ||
973 | i = my_atoi(str); | ||
974 | if ((i < f) || (i > t)) | ||
975 | { | ||
976 | ERR("%s: Error. %s:%i integer %i out of range of %i to %i inclusive", | ||
977 | progname, file_in, line - 1, i, f, t); | ||
978 | err_show(); | ||
979 | exit(-1); | ||
980 | } | ||
981 | return i; | ||
982 | } | ||
983 | |||
984 | int | ||
985 | parse_bool(int n) | ||
986 | { | ||
987 | char *str, buf[4096]; | ||
988 | int i; | ||
989 | |||
990 | str = eina_list_nth(params, n); | ||
991 | if (!str) | ||
992 | { | ||
993 | ERR("%s: Error. %s:%i no parameter supplied as argument %i", | ||
994 | progname, file_in, line - 1, n + 1); | ||
995 | err_show(); | ||
996 | exit(-1); | ||
997 | } | ||
998 | |||
999 | if (!strstrip(str, buf, sizeof (buf))) | ||
1000 | { | ||
1001 | ERR("%s: Error. %s:%i expression is too long", | ||
1002 | progname, file_in, line - 1); | ||
1003 | return 0; | ||
1004 | } | ||
1005 | |||
1006 | if (!strcasecmp(buf, "false") || !strcasecmp(buf, "off")) | ||
1007 | return 0; | ||
1008 | if (!strcasecmp(buf, "true") || !strcasecmp(buf, "on")) | ||
1009 | return 1; | ||
1010 | |||
1011 | i = my_atoi(str); | ||
1012 | if ((i < 0) || (i > 1)) | ||
1013 | { | ||
1014 | ERR("%s: Error. %s:%i integer %i out of range of 0 to 1 inclusive", | ||
1015 | progname, file_in, line - 1, i); | ||
1016 | err_show(); | ||
1017 | exit(-1); | ||
1018 | } | ||
1019 | return i; | ||
1020 | } | ||
1021 | |||
1022 | double | ||
1023 | parse_float(int n) | ||
1024 | { | ||
1025 | char *str; | ||
1026 | double i; | ||
1027 | |||
1028 | str = eina_list_nth(params, n); | ||
1029 | if (!str) | ||
1030 | { | ||
1031 | ERR("%s: Error. %s:%i no parameter supplied as argument %i", | ||
1032 | progname, file_in, line - 1, n + 1); | ||
1033 | err_show(); | ||
1034 | exit(-1); | ||
1035 | } | ||
1036 | i = my_atof(str); | ||
1037 | return i; | ||
1038 | } | ||
1039 | |||
1040 | double | ||
1041 | parse_float_range(int n, double f, double t) | ||
1042 | { | ||
1043 | char *str; | ||
1044 | double i; | ||
1045 | |||
1046 | str = eina_list_nth(params, n); | ||
1047 | if (!str) | ||
1048 | { | ||
1049 | ERR("%s: Error. %s:%i no parameter supplied as argument %i", | ||
1050 | progname, file_in, line - 1, n + 1); | ||
1051 | err_show(); | ||
1052 | exit(-1); | ||
1053 | } | ||
1054 | i = my_atof(str); | ||
1055 | if ((i < f) || (i > t)) | ||
1056 | { | ||
1057 | ERR("%s: Error. %s:%i float %3.3f out of range of %3.3f to %3.3f inclusive", | ||
1058 | progname, file_in, line - 1, i, f, t); | ||
1059 | err_show(); | ||
1060 | exit(-1); | ||
1061 | } | ||
1062 | return i; | ||
1063 | } | ||
1064 | |||
1065 | int | ||
1066 | get_arg_count(void) | ||
1067 | { | ||
1068 | return eina_list_count (params); | ||
1069 | } | ||
1070 | |||
1071 | void | ||
1072 | check_arg_count(int required_args) | ||
1073 | { | ||
1074 | int num_args = eina_list_count (params); | ||
1075 | |||
1076 | if (num_args != required_args) | ||
1077 | { | ||
1078 | ERR("%s: Error. %s:%i got %i arguments, but expected %i", | ||
1079 | progname, file_in, line - 1, num_args, required_args); | ||
1080 | err_show(); | ||
1081 | exit(-1); | ||
1082 | } | ||
1083 | } | ||
1084 | |||
1085 | void | ||
1086 | check_min_arg_count(int min_required_args) | ||
1087 | { | ||
1088 | int num_args = eina_list_count (params); | ||
1089 | |||
1090 | if (num_args < min_required_args) | ||
1091 | { | ||
1092 | ERR("%s: Error. %s:%i got %i arguments, " | ||
1093 | "but expected at least %i", | ||
1094 | progname, file_in, line - 1, num_args, min_required_args); | ||
1095 | err_show(); | ||
1096 | exit(-1); | ||
1097 | } | ||
1098 | } | ||
1099 | |||
1100 | /* simple expression parsing stuff */ | ||
1101 | |||
1102 | /* | ||
1103 | * alpha ::= beta + beta || beta | ||
1104 | * beta ::= gamma + gamma || gamma | ||
1105 | * gamma ::= num || delta | ||
1106 | * delta ::= '(' alpha ')' | ||
1107 | * | ||
1108 | */ | ||
1109 | |||
1110 | /* int set of function */ | ||
1111 | |||
1112 | static int | ||
1113 | my_atoi(const char *s) | ||
1114 | { | ||
1115 | int res = 0; | ||
1116 | char buf[4096]; | ||
1117 | |||
1118 | if (!s) return 0; | ||
1119 | if (!strstrip(s, buf, sizeof(buf))) | ||
1120 | { | ||
1121 | ERR("%s: Error. %s:%i expression is too long\n", | ||
1122 | progname, file_in, line - 1); | ||
1123 | return 0; | ||
1124 | } | ||
1125 | _alphai(buf, &res); | ||
1126 | return res; | ||
1127 | } | ||
1128 | |||
1129 | static char * | ||
1130 | _deltai(char *s, int *val) | ||
1131 | { | ||
1132 | if (!val) return NULL; | ||
1133 | if ('(' != s[0]) | ||
1134 | { | ||
1135 | ERR("%s: Error. %s:%i unexpected character at %s\n", | ||
1136 | progname, file_in, line - 1, s); | ||
1137 | return s; | ||
1138 | } | ||
1139 | else | ||
1140 | { | ||
1141 | s++; | ||
1142 | s = _alphai(s, val); | ||
1143 | s++; | ||
1144 | return s; | ||
1145 | } | ||
1146 | return s; | ||
1147 | } | ||
1148 | |||
1149 | static char * | ||
1150 | _funci(char *s, int *val) | ||
1151 | { | ||
1152 | if (!strncmp(s, "floor(", 6)) | ||
1153 | { | ||
1154 | s += 5; | ||
1155 | s = _deltai(s, val); | ||
1156 | *val = *val; | ||
1157 | } | ||
1158 | else if (!strncmp(s, "ceil(", 5)) | ||
1159 | { | ||
1160 | s += 4; | ||
1161 | s = _deltai(s, val); | ||
1162 | *val = *val; | ||
1163 | } | ||
1164 | else | ||
1165 | { | ||
1166 | ERR("%s: Error. %s:%i unexpected character at %s\n", | ||
1167 | progname, file_in, line - 1, s); | ||
1168 | } | ||
1169 | return s; | ||
1170 | } | ||
1171 | |||
1172 | static char * | ||
1173 | _gammai(char *s, int *val) | ||
1174 | { | ||
1175 | if (!val) return NULL; | ||
1176 | if (_is_numi(s[0])) | ||
1177 | { | ||
1178 | s = _get_numi(s, val); | ||
1179 | return s; | ||
1180 | } | ||
1181 | else if ('(' == s[0]) | ||
1182 | { | ||
1183 | s = _deltai(s, val); | ||
1184 | return s; | ||
1185 | } | ||
1186 | else | ||
1187 | { | ||
1188 | s = _funci(s, val); | ||
1189 | // ERR("%s: Error. %s:%i unexpected character at %s\n", | ||
1190 | // progname, file_in, line - 1, s); | ||
1191 | } | ||
1192 | return s; | ||
1193 | } | ||
1194 | |||
1195 | static char * | ||
1196 | _betai(char *s, int *val) | ||
1197 | { | ||
1198 | int a1, a2; | ||
1199 | char op; | ||
1200 | |||
1201 | if (!val) return NULL; | ||
1202 | s = _gammai(s, &a1); | ||
1203 | while (_is_op1i(s[0])) | ||
1204 | { | ||
1205 | op = s[0]; | ||
1206 | s++; | ||
1207 | s = _gammai(s, &a2); | ||
1208 | a1 = _calci(op, a1, a2); | ||
1209 | } | ||
1210 | (*val) = a1; | ||
1211 | return s; | ||
1212 | } | ||
1213 | |||
1214 | static char * | ||
1215 | _alphai(char *s, int *val) | ||
1216 | { | ||
1217 | int a1, a2; | ||
1218 | char op; | ||
1219 | |||
1220 | if (!val) return NULL; | ||
1221 | s = _betai(s, &a1); | ||
1222 | while (_is_op2i(s[0])) | ||
1223 | { | ||
1224 | op = s[0]; | ||
1225 | s++; | ||
1226 | s = _betai(s, &a2); | ||
1227 | a1 = _calci(op, a1, a2); | ||
1228 | } | ||
1229 | (*val) = a1; | ||
1230 | return s; | ||
1231 | } | ||
1232 | |||
1233 | char * | ||
1234 | _get_numi(char *s, int *val) | ||
1235 | { | ||
1236 | char buf[4096]; | ||
1237 | int pos = 0; | ||
1238 | |||
1239 | if (!val) return s; | ||
1240 | while ((('0' <= s[pos]) && ('9' >= s[pos])) || | ||
1241 | ((0 == pos) && ('-' == s[pos]))) | ||
1242 | { | ||
1243 | buf[pos] = s[pos]; | ||
1244 | pos++; | ||
1245 | } | ||
1246 | buf[pos] = '\0'; | ||
1247 | (*val) = atoi(buf); | ||
1248 | return (s + pos); | ||
1249 | } | ||
1250 | |||
1251 | int | ||
1252 | _is_numi(char c) | ||
1253 | { | ||
1254 | if (((c >= '0') && (c <= '9')) || ('-' == c) || ('+' == c)) | ||
1255 | return 1; | ||
1256 | else | ||
1257 | return 0; | ||
1258 | } | ||
1259 | |||
1260 | int | ||
1261 | _is_op1i(char c) | ||
1262 | { | ||
1263 | switch (c) | ||
1264 | { | ||
1265 | case '*':; | ||
1266 | case '%':; | ||
1267 | case '/': return 1; | ||
1268 | default: break; | ||
1269 | } | ||
1270 | return 0; | ||
1271 | } | ||
1272 | |||
1273 | int | ||
1274 | _is_op2i(char c) | ||
1275 | { | ||
1276 | switch (c) | ||
1277 | { | ||
1278 | case '+':; | ||
1279 | case '-': return 1; | ||
1280 | default: break; | ||
1281 | } | ||
1282 | return 0; | ||
1283 | } | ||
1284 | |||
1285 | int | ||
1286 | _calci(char op, int a, int b) | ||
1287 | { | ||
1288 | switch(op) | ||
1289 | { | ||
1290 | case '+': | ||
1291 | a += b; | ||
1292 | return a; | ||
1293 | case '-': | ||
1294 | a -= b; | ||
1295 | return a; | ||
1296 | case '/': | ||
1297 | if (0 != b) a /= b; | ||
1298 | else | ||
1299 | ERR("%s: Error. %s:%i divide by zero\n", | ||
1300 | progname, file_in, line - 1); | ||
1301 | return a; | ||
1302 | case '*': | ||
1303 | a *= b; | ||
1304 | return a; | ||
1305 | case '%': | ||
1306 | if (0 != b) a = a % b; | ||
1307 | else | ||
1308 | ERR("%s: Error. %s:%i modula by zero\n", | ||
1309 | progname, file_in, line - 1); | ||
1310 | return a; | ||
1311 | default: | ||
1312 | ERR("%s: Error. %s:%i unexpected character '%c'\n", | ||
1313 | progname, file_in, line - 1, op); | ||
1314 | } | ||
1315 | return a; | ||
1316 | } | ||
1317 | |||
1318 | /* float set of functoins */ | ||
1319 | |||
1320 | double | ||
1321 | my_atof(const char *s) | ||
1322 | { | ||
1323 | double res = 0; | ||
1324 | char buf[4096]; | ||
1325 | |||
1326 | if (!s) return 0; | ||
1327 | |||
1328 | if (!strstrip(s, buf, sizeof (buf))) | ||
1329 | { | ||
1330 | ERR("%s: Error. %s:%i expression is too long", | ||
1331 | progname, file_in, line - 1); | ||
1332 | return 0; | ||
1333 | } | ||
1334 | _alphaf(buf, &res); | ||
1335 | return res; | ||
1336 | } | ||
1337 | |||
1338 | static char * | ||
1339 | _deltaf(char *s, double *val) | ||
1340 | { | ||
1341 | if (!val) return NULL; | ||
1342 | if ('(' != s[0]) | ||
1343 | { | ||
1344 | ERR("%s: Error. %s:%i unexpected character at %s", | ||
1345 | progname, file_in, line - 1, s); | ||
1346 | return s; | ||
1347 | } | ||
1348 | else | ||
1349 | { | ||
1350 | s++; | ||
1351 | s = _alphaf(s, val); | ||
1352 | s++; | ||
1353 | } | ||
1354 | return s; | ||
1355 | } | ||
1356 | |||
1357 | static char * | ||
1358 | _funcf(char *s, double *val) | ||
1359 | { | ||
1360 | if (!strncmp(s, "floor(", 6)) | ||
1361 | { | ||
1362 | s += 5; | ||
1363 | s = _deltaf(s, val); | ||
1364 | *val = floor(*val); | ||
1365 | } | ||
1366 | else if (!strncmp(s, "ceil(", 5)) | ||
1367 | { | ||
1368 | s += 4; | ||
1369 | s = _deltaf(s, val); | ||
1370 | *val = ceil(*val); | ||
1371 | } | ||
1372 | else | ||
1373 | { | ||
1374 | ERR("%s: Error. %s:%i unexpected character at %s\n", | ||
1375 | progname, file_in, line - 1, s); | ||
1376 | } | ||
1377 | return s; | ||
1378 | } | ||
1379 | |||
1380 | static char * | ||
1381 | _gammaf(char *s, double *val) | ||
1382 | { | ||
1383 | if (!val) return NULL; | ||
1384 | |||
1385 | if (_is_numf(s[0])) | ||
1386 | { | ||
1387 | s = _get_numf(s, val); | ||
1388 | return s; | ||
1389 | } | ||
1390 | else if ('(' == s[0]) | ||
1391 | { | ||
1392 | s = _deltaf(s, val); | ||
1393 | return s; | ||
1394 | } | ||
1395 | else | ||
1396 | { | ||
1397 | s = _funcf(s, val); | ||
1398 | // ERR("%s: Error. %s:%i unexpected character at %s\n", | ||
1399 | // progname, file_in, line - 1, s); | ||
1400 | } | ||
1401 | return s; | ||
1402 | } | ||
1403 | |||
1404 | static char * | ||
1405 | _betaf(char *s, double *val) | ||
1406 | { | ||
1407 | double a1=0, a2=0; | ||
1408 | char op; | ||
1409 | |||
1410 | if (!val) return NULL; | ||
1411 | s = _gammaf(s, &a1); | ||
1412 | while (_is_op1f(s[0])) | ||
1413 | { | ||
1414 | op = s[0]; | ||
1415 | s++; | ||
1416 | s = _gammaf(s, &a2); | ||
1417 | a1 = _calcf(op, a1, a2); | ||
1418 | } | ||
1419 | (*val) = a1; | ||
1420 | return s; | ||
1421 | } | ||
1422 | |||
1423 | static char * | ||
1424 | _alphaf(char *s, double *val) | ||
1425 | { | ||
1426 | double a1=0, a2=0; | ||
1427 | char op; | ||
1428 | |||
1429 | if (!val) return NULL; | ||
1430 | s = _betaf(s, &a1); | ||
1431 | while (_is_op2f(s[0])) | ||
1432 | { | ||
1433 | op = s[0]; | ||
1434 | s++; | ||
1435 | s = _betaf(s, &a2); | ||
1436 | a1 = _calcf(op, a1, a2); | ||
1437 | } | ||
1438 | (*val) = a1; | ||
1439 | return s; | ||
1440 | } | ||
1441 | |||
1442 | static char * | ||
1443 | _get_numf(char *s, double *val) | ||
1444 | { | ||
1445 | char buf[4096]; | ||
1446 | int pos = 0; | ||
1447 | |||
1448 | if (!val) return s; | ||
1449 | |||
1450 | while ((('0' <= s[pos]) && ('9' >= s[pos])) || | ||
1451 | ('.' == s[pos]) || | ||
1452 | ((0 == pos) && ('-' == s[pos]))) | ||
1453 | { | ||
1454 | buf[pos] = s[pos]; | ||
1455 | pos++; | ||
1456 | } | ||
1457 | buf[pos] = '\0'; | ||
1458 | (*val) = atof(buf); | ||
1459 | return (s+pos); | ||
1460 | } | ||
1461 | |||
1462 | static int | ||
1463 | _is_numf(char c) | ||
1464 | { | ||
1465 | if (((c >= '0') && (c <= '9')) | ||
1466 | || ('-' == c) | ||
1467 | || ('.' == c) | ||
1468 | || ('+' == c)) | ||
1469 | return 1; | ||
1470 | return 0; | ||
1471 | } | ||
1472 | |||
1473 | static int | ||
1474 | _is_op1f(char c) | ||
1475 | { | ||
1476 | switch(c) | ||
1477 | { | ||
1478 | case '*':; | ||
1479 | case '%':; | ||
1480 | case '/': return 1; | ||
1481 | default: break; | ||
1482 | } | ||
1483 | return 0; | ||
1484 | } | ||
1485 | |||
1486 | static int | ||
1487 | _is_op2f(char c) | ||
1488 | { | ||
1489 | switch(c) | ||
1490 | { | ||
1491 | case '+':; | ||
1492 | case '-': return 1; | ||
1493 | default: break; | ||
1494 | } | ||
1495 | return 0; | ||
1496 | } | ||
1497 | |||
1498 | static double | ||
1499 | _calcf(char op, double a, double b) | ||
1500 | { | ||
1501 | switch(op) | ||
1502 | { | ||
1503 | case '+': | ||
1504 | a += b; | ||
1505 | return a; | ||
1506 | case '-': | ||
1507 | a -= b; | ||
1508 | return a; | ||
1509 | case '/': | ||
1510 | if (b != 0) a /= b; | ||
1511 | else | ||
1512 | ERR("%s: Error. %s:%i divide by zero\n", | ||
1513 | progname, file_in, line - 1); | ||
1514 | return a; | ||
1515 | case '*': | ||
1516 | a *= b; | ||
1517 | return a; | ||
1518 | case '%': | ||
1519 | if (0 != b) a = (double)((int)a % (int)b); | ||
1520 | else | ||
1521 | ERR("%s: Error. %s:%i modula by zero\n", | ||
1522 | progname, file_in, line - 1); | ||
1523 | return a; | ||
1524 | default: | ||
1525 | ERR("%s: Error. %s:%i unexpected character '%c'\n", | ||
1526 | progname, file_in, line - 1, op); | ||
1527 | } | ||
1528 | return a; | ||
1529 | } | ||
1530 | |||
1531 | static int | ||
1532 | strstrip(const char *in, char *out, size_t size) | ||
1533 | { | ||
1534 | if ((size -1 ) < strlen(in)) | ||
1535 | { | ||
1536 | ERR("%s: Error. %s:%i expression is too long", | ||
1537 | progname, file_in, line - 1); | ||
1538 | return 0; | ||
1539 | } | ||
1540 | /* remove spaces and tabs */ | ||
1541 | while (*in) | ||
1542 | { | ||
1543 | if ((0x20 != *in) && (0x09 != *in)) | ||
1544 | { | ||
1545 | *out = *in; | ||
1546 | out++; | ||
1547 | } | ||
1548 | in++; | ||
1549 | } | ||
1550 | *out = '\0'; | ||
1551 | return 1; | ||
1552 | } | ||