efl

Форк
0
/
edje_cc_script.c 
491 строка · 11.7 Кб
1
#ifdef HAVE_CONFIG_H
2
# include "config.h"
3
#endif
4

5
#include "edje_cc.h"
6

7
#define MESSAGE_OVERRIDE
8

9
typedef struct _Code_Symbol
10
{
11
   const char *name;
12
   const char *tag;
13
   Eina_List  *args;
14
   char       *body;
15
   Eina_Bool   is_public : 1;
16
} Code_Symbol;
17

18
typedef enum
19
{
20
   TOKEN_TYPE_INVALID = -1,
21
   TOKEN_TYPE_EOF,
22
   TOKEN_TYPE_COLON = (1 << 0),
23
   TOKEN_TYPE_SEMICOLON = (1 << 1),
24
   TOKEN_TYPE_COMMA = (1 << 2),
25
   TOKEN_TYPE_PARENS = (1 << 3),
26
   TOKEN_TYPE_BRACES = (1 << 4),
27
   TOKEN_TYPE_EQUAL_MARK = (1 << 5),
28
   TOKEN_TYPE_PUBLIC = (1 << 6),
29
   TOKEN_TYPE_IDENTIFIER = (1 << 7)
30
} Token_Type;
31

32
typedef struct _Token
33
{
34
   char      *str;
35
   Token_Type type;
36
} Token;
37

38
static void   code_parse_internal(Code *code);
39
static Token *next_token(char **begin, char *end);
40

41
static void
42
code_parse(Code *code)
43
{
44
   Edje_Part_Collection_Parser *pcp;
45
   Code *base;
46
   Eina_List *l;
47
   int id;
48

49
   if (code->is_lua || code->parsed) return;
50

51
   id = eina_list_data_idx(codes, code);
52
   pcp = eina_list_nth(edje_collections, id);
53

54
   EINA_LIST_FOREACH(pcp->base_codes, l, base)
55
     code_parse(base);
56

57
   if (code->shared)
58
     code_parse_internal(code);
59

60
   code->parsed = EINA_TRUE;
61
}
62

63
static void
64
code_parse_internal(Code *code)
65
{
66
   Code_Symbol *sym = NULL, *func = NULL;
67
   Token *token, *tmp = NULL;
68
   char *begin = code->shared;
69
   char *end = begin + strlen(begin);
70
   char *body;
71
   Eina_Array *name_stack;
72
   Eina_Bool is_args = EINA_FALSE;
73
   Eina_Bool is_public = EINA_FALSE;
74
   int depth = 0;
75

76
   name_stack = eina_array_new(4);
77

78
   while ((token = next_token(&begin, end)))
79
     {
80
        if (token->type == TOKEN_TYPE_EOF)
81
          break;
82

83
        // Variables in script cannot be initialized by assignment.
84
        // Skip until value assignment expression ends.
85
        if (token->type == TOKEN_TYPE_EQUAL_MARK)
86
          {
87
             while ((tmp = next_token(&begin, end)))
88
               {
89
                  if ((tmp->type == TOKEN_TYPE_COMMA) ||
90
                      (tmp->type == TOKEN_TYPE_SEMICOLON))
91
                    {
92
                       if (token->str) free(token->str);
93
                       free(token);
94

95
                       token = tmp;
96
                       tmp = NULL;
97
                       break;
98
                    }
99

100
                  if (tmp->str) free(tmp->str);
101
                  free(tmp);
102
               }
103
          }
104

105
        switch (token->type)
106
          {
107
           case TOKEN_TYPE_COLON:
108
             if (!sym)
109
               sym = mem_alloc(SZ(Code_Symbol));
110
             sym->tag = eina_array_pop(name_stack);
111
             break;
112

113
           case TOKEN_TYPE_SEMICOLON:
114
             if (eina_array_count(name_stack))
115
               {
116
                  if (!sym)
117
                    sym = mem_alloc(SZ(Code_Symbol));
118
                  sym->name = eina_array_pop(name_stack);
119
                  sym->is_public = is_public;
120
                  code->vars = eina_list_append(code->vars, sym);
121
                  sym = NULL;
122
               }
123
             is_public = EINA_FALSE;
124
             break;
125

126
           case TOKEN_TYPE_COMMA:
127
             if (!sym)
128
               sym = mem_alloc(SZ(Code_Symbol));
129
             sym->name = eina_array_pop(name_stack);
130
             if (is_args)
131
               func->args = eina_list_append(func->args, sym);
132
             else
133
               {
134
                  sym->is_public = is_public;
135
                  code->vars = eina_list_append(code->vars, sym);
136
               }
137
             sym = NULL;
138
             break;
139

140
           case TOKEN_TYPE_PARENS:
141
             is_args = !is_args;
142
             if (is_args)
143
               {
144
                  if (!sym)
145
                    func = mem_alloc(SZ(Code_Symbol));
146
                  else
147
                    {
148
                       func = sym;
149
                       sym = NULL;
150
                    }
151
                  func->name = eina_array_pop(name_stack);
152
               }
153
             else
154
               {
155
                  if (eina_array_count(name_stack))
156
                    {
157
                       if (!sym)
158
                         sym = mem_alloc(SZ(Code_Symbol));
159
                       sym->name = eina_array_pop(name_stack);
160
                       func->args = eina_list_append(func->args, sym);
161
                    }
162
                  sym = func;
163
               }
164
             break;
165

166
           case TOKEN_TYPE_BRACES:
167
             depth = 1;
168
             body = begin;
169
             while ((tmp = next_token(&begin, end)))
170
               {
171
                  if (tmp->type == TOKEN_TYPE_BRACES)
172
                    {
173
                       switch (tmp->str[0])
174
                         {
175
                          case '{':
176
                            depth++;
177
                            break;
178

179
                          case '}':
180
                            depth--;
181
                            break;
182
                         }
183
                    }
184
                  if (!depth)
185
                    break;
186

187
                  if (tmp->str) free(tmp->str);
188
                  free(tmp);
189
               }
190
             if (!sym) break;
191
             if ((begin - 1) > body)
192
               {
193
                  sym->body = mem_alloc(sizeof(char) * (begin - body - 1));
194
                  strncpy(sym->body, body, (begin - body - 2));
195
               }
196
             sym->is_public = is_public;
197
             code->func = eina_list_append(code->func, sym);
198
             sym = NULL;
199
             is_public = EINA_FALSE;
200
             break;
201

202
           case TOKEN_TYPE_PUBLIC:
203
             is_public = EINA_TRUE;
204
             break;
205

206
           case TOKEN_TYPE_IDENTIFIER:
207
             eina_array_push(name_stack, token->str);
208
             token->str = NULL;
209
             break;
210

211
           default:
212
             break;
213
          }
214

215
        if (token->str)
216
          free(token->str);
217
        free(token);
218

219
        if (tmp)
220
          {
221
             if (tmp->str) free(tmp->str);
222
             free(tmp);
223
             tmp = NULL;
224
          }
225
     }
226

227
   if (token)
228
     {
229
        if (token->str)
230
          free(token->str);
231
        free(token);
232
     }
233

234
   eina_array_free(name_stack);
235
}
236

237
static Token *
238
next_token(char **begin, char *end)
239
{
240
   char buf[PATH_MAX] = { 0, };
241
   char *src;
242
   int index;
243
   Token *token;
244
   Eina_Bool parsed = EINA_FALSE;
245

246
   if (!begin || (*begin >= end))
247
     return NULL;
248

249
   token = mem_alloc(SZ(Token));
250
   token->type = TOKEN_TYPE_INVALID;
251

252
   src = *begin - 1;
253
   index = 0;
254

255
   while (++src < end)
256
     {
257
        char ch = *src;
258

259
        switch (ch)
260
          {
261
           case ' ':
262
           case '\t':
263
           case '\n':
264
             if (index > 0)
265
               parsed = EINA_TRUE;
266
             break;
267

268
           case ':':
269
           case ';':
270
           case ',':
271
           case '(':
272
           case ')':
273
           case '{':
274
           case '}':
275
           case '=':
276
             if (!index)
277
               {
278
                  buf[index++] = ch;
279
                  src++;
280
               }
281
             goto exit;
282

283
           default:
284
             if (parsed)
285
               goto exit;
286
             buf[index++] = ch;
287
             break;
288
          }
289
     }
290

291
exit:
292
   switch (buf[0])
293
     {
294
      case ':':
295
        token->type = TOKEN_TYPE_COLON;
296
        break;
297

298
      case ';':
299
        token->type = TOKEN_TYPE_SEMICOLON;
300
        break;
301

302
      case ',':
303
        token->type = TOKEN_TYPE_COMMA;
304
        break;
305

306
      case '(':
307
      case ')':
308
        token->type = TOKEN_TYPE_PARENS;
309
        break;
310

311
      case '{':
312
      case '}':
313
        token->type = TOKEN_TYPE_BRACES;
314
        break;
315

316
      case '=':
317
        token->type = TOKEN_TYPE_EQUAL_MARK;
318
        break;
319

320
      case '\0':
321
        token->type = TOKEN_TYPE_EOF;
322
        break;
323
     }
324

325
   if (token->type < 0)
326
     {
327
        if (!strcmp(buf, "public"))
328
          token->type = TOKEN_TYPE_PUBLIC;
329
        else
330
          token->type = TOKEN_TYPE_IDENTIFIER;
331
     }
332

333
   *begin = src;
334
   token->str = strdup(buf);
335
   return token;
336
}
337

338
static void
339
_push_symbol(Eina_List **total, Code_Symbol *sym, Edje_Part_Collection *pc)
340
{
341
   Eina_List *list, *l;
342
   Code_Symbol *sym2;
343

344
   list = *total;
345

346
   EINA_LIST_FOREACH(list, l, sym2)
347
     {
348
        if (!strcmp(sym2->name, sym->name))
349
          {
350
             WRN("Symbols in group \"%s\" have same name \"%s\". Latter defined "
351
                 "will shadow former one.", pc->part, sym->name);
352
             list = eina_list_remove(list, sym2);
353
             break;
354
          }
355
     }
356
   list = eina_list_append(list, sym);
357
   *total = list;
358
}
359

360
void
361
script_rewrite(Code *code)
362
{
363
   Edje_Part_Collection *pc;
364
   Edje_Part_Collection_Parser *pcp;
365
   Code *base;
366
   Eina_List *l, *ll;
367
   int id, count;
368
   Eina_Strbuf *buf;
369
   Eina_List *vars = NULL;
370
   Eina_List *func = NULL;
371
#ifdef MESSAGE_OVERRIDE
372
   Eina_List *message = NULL;
373
#endif
374
   Code_Symbol *sym, *arg;
375

376
   code_parse(code);
377

378
   id = eina_list_data_idx(codes, code);
379
   pc = eina_list_nth(edje_collections, id);
380
   pcp = (Edje_Part_Collection_Parser *)pc;
381

382
   EINA_LIST_FOREACH(pcp->base_codes, l, base)
383
     {
384
        EINA_LIST_FOREACH(base->vars, ll, sym)
385
          _push_symbol(&vars, sym, pc);
386

387
        EINA_LIST_FOREACH(base->func, ll, sym)
388
          {
389
#ifndef MESSAGE_OVERRIDE
390
             _push_symbol(&func, sym, pc);
391
#else
392
             if (strcmp(sym->name, "message"))
393
               _push_symbol(&func, sym, pc);
394
             else
395
               message = eina_list_append(message, sym);
396
#endif
397
          }
398
     }
399

400
   EINA_LIST_FOREACH(code->vars, l, sym)
401
     _push_symbol(&vars, sym, pc);
402
   EINA_LIST_FOREACH(code->func, l, sym)
403
     {
404
#ifndef MESSAGE_OVERRIDE
405
        _push_symbol(&func, sym, pc);
406
#else
407
        if (strcmp(sym->name, "message"))
408
          _push_symbol(&func, sym, pc);
409
        else
410
          message = eina_list_append(message, sym);
411
#endif
412
     }
413

414
   buf = eina_strbuf_new();
415

416
   if (vars)
417
     {
418
        count = 0;
419
        EINA_LIST_FOREACH(vars, l, sym)
420
          {
421
             if (!sym->is_public) continue;
422

423
             if (count++)
424
               eina_strbuf_append(buf, ", ");
425
             else
426
               eina_strbuf_append(buf, "public ");
427

428
             if (sym->tag)
429
               eina_strbuf_append_printf(buf, "%s:", sym->tag);
430
             eina_strbuf_append(buf, sym->name);
431
          }
432
        if (count)
433
          eina_strbuf_append(buf, ";\n");
434
     }
435

436
   if (func)
437
     {
438
        EINA_LIST_FOREACH(func, l, sym)
439
          {
440
             eina_strbuf_append(buf, "\n");
441
             if (sym->is_public)
442
               eina_strbuf_append(buf, "public ");
443

444
             if (sym->tag)
445
               eina_strbuf_append_printf(buf, "%s:", sym->tag);
446
             eina_strbuf_append_printf(buf, "%s(", sym->name);
447

448
             count = 0;
449
             EINA_LIST_FOREACH(sym->args, ll, arg)
450
               {
451
                  if (count++)
452
                    eina_strbuf_append(buf, ", ");
453

454
                  if (arg->tag)
455
                    eina_strbuf_append_printf(buf, "%s:", arg->tag);
456
                  eina_strbuf_append(buf, arg->name);
457
               }
458
             eina_strbuf_append(buf, ") {");
459
             if (sym->body)
460
               {
461
                  eina_strbuf_append(buf, sym->body);
462
                  eina_strbuf_rtrim(buf);
463
               }
464
             eina_strbuf_append(buf, "\n}\n");
465
          }
466
     }
467

468
#ifdef MESSAGE_OVERRIDE
469
   if (message)
470
     {
471
        eina_strbuf_append(buf, "\npublic message(Msg_Type:type, id, ...) {");
472
        EINA_LIST_FOREACH(message, l, sym)
473
          {
474
             eina_strbuf_append(buf, sym->body);
475
             eina_strbuf_rtrim(buf);
476
             eina_strbuf_append(buf, "\n");
477
          }
478
        eina_strbuf_append(buf, "}\n");
479
     }
480
#endif
481

482
   code->shared = eina_strbuf_string_steal(buf);
483
   code->original = strdup(code->shared);
484
   eina_strbuf_free(buf);
485

486
   eina_list_free(code->vars);
487
   eina_list_free(code->func);
488

489
   code->vars = vars;
490
   code->func = func;
491
}
492

493

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.