10
#include "eolian_priv.h"
12
typedef struct _Validate_State
17
Eina_Bool unimplemented_beta;
18
const char *since_ver;
22
_set_stable(Validate_State *vals, Eina_Bool newval)
24
Eina_Bool ret = vals->stable;
25
vals->stable = newval;
30
_reset_stable(Validate_State *vals, Eina_Bool oldval, Eina_Bool ret)
32
vals->stable = oldval;
37
_validate(Eolian_Object *obj)
39
obj->validated = EINA_TRUE;
43
#define _eo_parser_log(_base, ...) \
44
eolian_state_log_obj((_base)->unit->state, (_base), __VA_ARGS__)
47
_validate_docstr(Eina_Stringshare *str, const Eolian_Object *info, Eina_List **rdbg)
49
if (!str || !str[0]) return EINA_TRUE;
51
Eina_Bool ret = EINA_TRUE;
52
Eina_List *pl = eolian_documentation_string_split(str);
54
EINA_LIST_FREE(pl, par)
56
const char *doc = par;
58
eolian_doc_token_init(&tok);
59
while (ret && (doc = eolian_documentation_tokenize(doc, &tok)))
61
if (eolian_doc_token_type_get(&tok) == EOLIAN_DOC_TOKEN_REF)
64
Eolian_Object_Type tp = database_doc_token_ref_resolve(&tok,
65
&info->unit->state->staging.unit,
66
&info->unit->state->main.unit,
68
if (tp == EOLIAN_OBJECT_UNKNOWN)
70
size_t dbgn = (size_t)eina_list_data_get(*rdbg);
71
char *refn = eolian_doc_token_text_get(&tok);
73
memset(&tmp, 0, sizeof(Eolian_Object));
74
tmp.unit = info->unit;
75
tmp.file = info->file;
76
tmp.line = (int)(dbgn & 0xFFFFF);
77
tmp.column = (int)(dbgn >> 20);
78
eolian_state_log_obj(info->unit->state, &tmp,
79
"failed validating reference '%s'", refn);
84
*rdbg = eina_list_next(*rdbg);
94
_validate_doc_since(Validate_State *vals, Eolian_Documentation *doc)
96
if (!doc || !vals->stable)
104
_eo_parser_log(&doc->base, "empty @since tag");
110
const char *snum = doc->since;
111
if (strncmp(snum, "1.", 2))
113
_eo_parser_log(&doc->base, "invalid EFL version in @since");
117
unsigned long min = strtoul(snum, NULL, 10);
120
_eo_parser_log(&doc->base, "stable APIs must be 1.22 or higher");
124
vals->since_ver = doc->since;
126
else if (!vals->since_ver)
128
_eo_parser_log(&doc->base, "missing @since tag");
136
_validate_doc_since_reset(Validate_State *vals, Eolian_Documentation *doc)
138
if (!doc || !doc->since)
141
const char *old_since = vals->since_ver;
142
Eina_Bool ret = _validate_doc_since(vals, doc);
143
vals->since_ver = old_since;
148
_validate_doc(Eolian_Documentation *doc)
153
Eina_List *rdbg = doc->ref_dbg;
155
if (!_validate_docstr(doc->summary, &doc->base, &rdbg))
157
if (!_validate_docstr(doc->description, &doc->base, &rdbg))
160
return _validate(&doc->base);
163
static Eina_Bool _validate_type(Validate_State *vals, Eolian_Type *tp,
164
Eina_Bool by_ref, Eina_Bool is_ret);
165
static Eina_Bool _validate_type_by_ref(Validate_State *vals, Eolian_Type *tp,
166
Eina_Bool by_ref, Eina_Bool move,
168
static Eina_Bool _validate_expr(Eolian_Expression *expr,
169
const Eolian_Type *tp,
170
Eolian_Expression_Mask msk,
172
static Eina_Bool _validate_function(Validate_State *vals,
173
Eolian_Function *func,
176
typedef struct _Cb_Ret
178
Validate_State *vals;
183
_sf_map_cb(const Eina_Hash *hash EINA_UNUSED, const void *key EINA_UNUSED,
184
const Eolian_Struct_Type_Field *sf, Cb_Ret *sc)
186
sc->succ = _validate_type_by_ref(sc->vals, sf->type, sf->by_ref,
187
sf->move, EINA_FALSE);
192
sc->succ = _validate_doc(sf->doc);
193
if (sc->succ) sc->succ = _validate_doc_since_reset(sc->vals, sf->doc);
199
_ef_map_cb(const Eina_Hash *hash EINA_UNUSED, const void *key EINA_UNUSED,
200
const Eolian_Enum_Type_Field *ef, Cb_Ret *sc)
203
sc->succ = _validate_expr(ef->value, NULL, EOLIAN_MASK_INT, EINA_FALSE);
205
sc->succ = EINA_TRUE;
210
sc->succ = _validate_doc(ef->doc);
211
if (sc->succ) sc->succ = _validate_doc_since_reset(sc->vals, ef->doc);
217
_validate_typedecl(Validate_State *vals, Eolian_Typedecl *tp)
219
if (tp->base.validated)
222
const char *old_since = vals->since_ver;
223
vals->since_ver = NULL;
226
Eina_Bool was_stable = _set_stable(vals, !tp->base.is_beta);
228
if (!_validate_doc(tp->doc))
231
if (!_validate_doc_since(vals, tp->doc))
236
case EOLIAN_TYPEDECL_ALIAS:
237
if (!_validate_type(vals, tp->base_type, EINA_FALSE, EINA_FALSE))
238
return _reset_stable(vals, was_stable, EINA_FALSE);
239
if (tp->base_type->ownable)
240
tp->ownable = EINA_TRUE;
241
_reset_stable(vals, was_stable, EINA_TRUE);
242
vals->since_ver = old_since;
243
return _validate(&tp->base);
244
case EOLIAN_TYPEDECL_STRUCT:
246
Cb_Ret rt = { vals, EINA_TRUE };
247
eina_hash_foreach(tp->fields, (Eina_Hash_Foreach)_sf_map_cb, &rt);
249
return _reset_stable(vals, was_stable, EINA_FALSE);
250
_reset_stable(vals, was_stable, EINA_TRUE);
251
vals->since_ver = old_since;
252
return _validate(&tp->base);
254
case EOLIAN_TYPEDECL_STRUCT_OPAQUE:
255
_reset_stable(vals, was_stable, EINA_TRUE);
256
vals->since_ver = old_since;
257
return _validate(&tp->base);
258
case EOLIAN_TYPEDECL_ENUM:
260
if (vals->stable && tp->legacy)
262
_eo_parser_log(&tp->base, "legacy field not allowed in stable enums");
265
Cb_Ret rt = { vals, EINA_TRUE };
266
eina_hash_foreach(tp->fields, (Eina_Hash_Foreach)_ef_map_cb, &rt);
268
return _reset_stable(vals, was_stable, EINA_FALSE);
269
_reset_stable(vals, was_stable, EINA_TRUE);
270
vals->since_ver = old_since;
271
return _validate(&tp->base);
273
case EOLIAN_TYPEDECL_FUNCTION_POINTER:
274
if (!_validate_function(vals, tp->function_pointer, NULL))
275
return _reset_stable(vals, was_stable, EINA_FALSE);
276
_reset_stable(vals, was_stable, EINA_TRUE);
277
vals->since_ver = old_since;
278
return _validate(&tp->base);
280
return _reset_stable(vals, was_stable, EINA_FALSE);
288
_validate_by_ref(Validate_State *vals, Eolian_Type *tp, Eina_Bool by_ref,
291
Eina_Bool maybe_ownable =
292
database_type_is_ownable(tp->base.unit, tp, EINA_FALSE, NULL);
295
if (by_ref && maybe_ownable)
297
_eo_parser_log(&tp->base, "@by_ref is only allowed for value types");
302
if (tp->btype == EOLIAN_TYPE_BUILTIN_FUTURE)
305
if (tp->tdecl && (tp->tdecl->type == EOLIAN_TYPEDECL_STRUCT_OPAQUE))
307
if (vals->stable && !maybe_ownable && !by_ref)
309
_eo_parser_log(&tp->base, "opaque structs must be by reference");
319
if (!maybe_ownable || !tp->ownable)
321
_eo_parser_log(&tp->base, "type '%s' is not ownable", tp->base.name);
329
_validate_type_by_ref(Validate_State *vals, Eolian_Type *tp,
330
Eina_Bool by_ref, Eina_Bool move, Eina_Bool is_ret)
332
if (!_validate_type(vals, tp, by_ref, is_ret))
335
return _validate_by_ref(vals, tp, by_ref, move);
339
_validate_type(Validate_State *vals, Eolian_Type *tp, Eina_Bool by_ref,
342
const Eolian_Unit *src = tp->base.unit;
348
_eo_parser_log(&tp->base, "ptr() used in stable API");
351
tp->is_ptr = EINA_FALSE;
352
Eina_Bool still_ownable = database_type_is_ownable(src, tp, EINA_FALSE, NULL);
353
tp->is_ptr = EINA_TRUE;
356
_eo_parser_log(&tp->base, "cannot take a pointer to pointer type");
361
if (tp->is_const && !tp->is_ptr)
363
if (database_type_is_ownable(src, tp, EINA_FALSE, NULL))
365
int kw = eo_lexer_keyword_str_to_id(tp->base.name);
371
_eo_parser_log(&tp->base, "spurious explicit const on string type");
377
const char *ct = eo_lexer_get_c_type(kw);
378
if (ct && ct[strlen(ct) - 1] != '*')
380
_eo_parser_log(&tp->base, "return const requires a C pointer");
386
else if (!by_ref && is_ret)
388
_eo_parser_log(&tp->base, "value returns cannot be const");
395
case EOLIAN_TYPE_VOID:
396
return _validate(&tp->base);
397
case EOLIAN_TYPE_UNDEFINED:
400
_eo_parser_log(&tp->base,
401
"__undefined_type not allowed in stable context");
404
return _validate(&tp->base);
405
case EOLIAN_TYPE_REGULAR:
409
int kwid = eo_lexer_keyword_str_to_id(tp->base.name);
411
tp->ownable = EINA_TRUE;
412
if ((kwid == KW_hash || kwid == KW_list) && vals->stable)
414
_eo_parser_log(&tp->base, "hashes and lists not allowed in stable context");
417
Eolian_Type *itp = tp->base_type;
421
if (vals->stable && itp->is_ptr)
423
_eo_parser_log(&itp->base,
424
"pointer types not allowed in '%s' in stable context",
428
if (!_validate_type_by_ref(vals, itp, EINA_FALSE, itp->move, EINA_FALSE))
430
itp = itp->next_type;
432
return _validate(&tp->base);
435
int id = eo_lexer_keyword_str_to_id(tp->base.name);
438
if (!eo_lexer_is_type_keyword(id))
445
case KW_any_value_ref:
448
tp->ownable = EINA_TRUE;
453
if (id == KW_void_ptr && vals->stable)
455
_eo_parser_log(&tp->base,
456
"void pointers not allowed in stable context");
459
return _validate(&tp->base);
462
tp->tdecl = database_type_decl_find(src, tp);
465
_eo_parser_log(&tp->base, "undefined type %s", tp->base.name);
468
else if (vals->stable && tp->tdecl->base.is_beta)
471
_eo_parser_log(&tp->base, "beta type declaration '%s' used in stable context",
472
tp->tdecl->base.name);
475
if (!_validate_typedecl(vals, tp->tdecl))
477
if (tp->tdecl->ownable)
478
tp->ownable = EINA_TRUE;
479
tp->base.c_name = eina_stringshare_ref(tp->tdecl->base.c_name);
480
return _validate(&tp->base);
482
case EOLIAN_TYPE_CLASS:
484
tp->klass = (Eolian_Class *)eolian_unit_class_by_name_get(src, tp->base.name);
487
_eo_parser_log(&tp->base, "undefined class %s "
488
"(likely wrong namespacing)", tp->base.name);
491
else if (vals->stable && tp->klass->base.is_beta)
493
_eo_parser_log(&tp->base, "beta class '%s' used in stable context",
494
tp->klass->base.name);
497
tp->ownable = EINA_TRUE;
498
tp->base.c_name = eina_stringshare_ref(tp->klass->base.c_name);
499
return _validate(&tp->base);
501
case EOLIAN_TYPE_ERROR:
503
tp->error = (Eolian_Error *)eolian_unit_error_by_name_get(src, tp->base.name);
506
_eo_parser_log(&tp->base, "undefined error %s "
507
"(likely wrong namespacing)", tp->base.name);
510
else if (vals->stable && tp->error->base.is_beta)
512
_eo_parser_log(&tp->base, "beta error '%s' used in stable context",
513
tp->error->base.name);
516
tp->base.c_name = eina_stringshare_ref(tp->error->base.c_name);
517
if (tp->next_type && !_validate_type(vals, tp->next_type, EINA_FALSE, EINA_FALSE))
519
return _validate(&tp->base);
528
_validate_expr(Eolian_Expression *expr, const Eolian_Type *tp,
529
Eolian_Expression_Mask msk, Eina_Bool by_ref)
533
val = database_expr_eval(expr->base.unit, expr, EOLIAN_MASK_NULL, NULL, NULL);
535
val = database_expr_eval_type(expr->base.unit, expr, tp, NULL, NULL);
537
val = database_expr_eval(expr->base.unit, expr, msk, NULL, NULL);
539
if (val.type == EOLIAN_EXPR_UNKNOWN)
542
return _validate(&expr->base);
546
_validate_param(Validate_State *vals, Eolian_Function_Parameter *param)
548
if (!_validate_type_by_ref(vals, param->type, param->by_ref, param->move, EINA_FALSE))
551
if (param->value && !_validate_expr(param->value, param->type, 0, param->by_ref))
554
if (!_validate_doc(param->doc))
557
return _validate(¶m->base);
561
_validate_function(Validate_State *vals, Eolian_Function *func, Eina_Hash *nhash)
564
Eolian_Function_Parameter *param;
566
const Eolian_Object *oobj = nhash ? eina_hash_find(nhash, &func->base.name) : NULL;
567
if (EINA_UNLIKELY(oobj && (oobj != &func->base)))
569
_eo_parser_log(&func->base,
570
"%sfunction '%s' conflicts with another symbol (at %s:%d:%d)",
571
func->base.is_beta ? "beta " : "", func->base.name, oobj->file,
572
oobj->line, oobj->column);
573
vals->warned = EINA_TRUE;
579
if (func->base.validated)
583
eina_hash_add(nhash, &func->base.name, &func->base);
588
Eina_Bool was_stable = _set_stable(vals, !func->base.is_beta && vals->stable);
590
if (func->get_ret_type && !_validate_type_by_ref(vals, func->get_ret_type,
591
func->get_return_by_ref, func->get_return_move, EINA_TRUE))
592
return _reset_stable(vals, was_stable, EINA_FALSE);
594
if (func->set_ret_type && !_validate_type_by_ref(vals, func->set_ret_type,
595
func->set_return_by_ref, func->set_return_move, EINA_TRUE))
596
return _reset_stable(vals, was_stable, EINA_FALSE);
598
if (func->get_ret_val && !_validate_expr(func->get_ret_val,
599
func->get_ret_type, 0,
600
func->get_return_by_ref))
601
return _reset_stable(vals, was_stable, EINA_FALSE);
603
if (func->set_ret_val && !_validate_expr(func->set_ret_val,
604
func->set_ret_type, 0,
605
func->set_return_by_ref))
606
return _reset_stable(vals, was_stable, EINA_FALSE);
608
#define EOLIAN_PARAMS_VALIDATE(params) \
609
EINA_LIST_FOREACH(params, l, param) \
610
if (!_validate_param(vals, param)) \
611
return _reset_stable(vals, was_stable, EINA_FALSE);
613
EOLIAN_PARAMS_VALIDATE(func->prop_values);
614
EOLIAN_PARAMS_VALIDATE(func->prop_values_get);
615
EOLIAN_PARAMS_VALIDATE(func->prop_values_set);
616
EOLIAN_PARAMS_VALIDATE(func->prop_keys);
617
EOLIAN_PARAMS_VALIDATE(func->prop_keys_get);
618
EOLIAN_PARAMS_VALIDATE(func->prop_keys_set);
620
#undef EOLIAN_PARAMS_VALIDATE
622
if (!_validate_doc(func->get_return_doc))
623
return _reset_stable(vals, was_stable, EINA_FALSE);
624
if (!_validate_doc(func->set_return_doc))
625
return _reset_stable(vals, was_stable, EINA_FALSE);
629
eina_hash_add(nhash, &func->base.name, &func->base);
631
_reset_stable(vals, was_stable, EINA_TRUE);
632
return _validate(&func->base);
636
_validate_part(Validate_State *vals, Eolian_Part *part, Eina_Hash *phash)
638
const Eolian_Object *oobj = eina_hash_find(phash, &part->base.name);
641
_eo_parser_log(&part->base,
642
"part '%s' conflicts with another part (at %s:%d:%d)",
643
part->base.name, oobj->file, oobj->line, oobj->column);
644
vals->warned = EINA_TRUE;
648
if (part->base.validated)
651
eina_hash_add(phash, &part->base.name, &part->base);
655
Eina_Bool was_stable = _set_stable(vals, !part->base.is_beta && vals->stable);
657
if (!_validate_doc(part->doc))
658
return _reset_stable(vals, was_stable, EINA_FALSE);
659
if (!_validate_doc_since_reset(vals, part->doc))
660
return _reset_stable(vals, was_stable, EINA_FALSE);
663
Eolian_Class *pcl = eina_hash_find(part->base.unit->classes, part->klass_name);
666
_eo_parser_log(&part->base, "unknown part class '%s' (incorrect case?)",
668
return _reset_stable(vals, was_stable, EINA_FALSE);
670
else if (vals->stable && pcl->base.is_beta)
672
_eo_parser_log(&part->base, "beta part class '%s' used in stable context",
674
return _reset_stable(vals, was_stable, EINA_FALSE);
676
eina_stringshare_del(part->klass_name);
680
eina_hash_add(phash, &part->base.name, &part->base);
682
_reset_stable(vals, was_stable, EINA_TRUE);
683
return _validate(&part->base);
687
_validate_event(Validate_State *vals, Eolian_Event *event, Eina_Hash *nhash)
689
const Eolian_Object *oobj = NULL;
691
oobj = eina_hash_find(nhash, &event->base.name);
692
if (EINA_UNLIKELY(!!oobj))
694
_eo_parser_log(&event->base,
695
"event '%s' conflicts with another event (at %s:%d:%d)",
696
event->base.name, oobj->file, oobj->line, oobj->column);
697
vals->warned = EINA_TRUE;
700
if (event->base.validated)
702
eina_hash_set(nhash, &event->base.name, &event->base);
706
Eina_Bool was_stable = _set_stable(vals, !event->base.is_beta && vals->stable);
708
if (!_validate_type(vals, event->type, EINA_FALSE, EINA_FALSE))
709
return _reset_stable(vals, was_stable, EINA_FALSE);
714
const Eolian_Type *tp = eolian_type_aliased_base_get(event->type);
719
if (tp->type == EOLIAN_TYPE_REGULAR && vals->stable)
724
_eo_parser_log(&tp->base, "pointers not allowed in events");
725
return _reset_stable(vals, was_stable, EINA_FALSE);
727
int kwid = eo_lexer_keyword_str_to_id(tp->base.name);
733
if (database_type_is_ownable(tp->base.unit, tp, EINA_FALSE, NULL))
743
_eo_parser_log(&tp->base, "event container types must be const");
744
return _reset_stable(vals, was_stable, EINA_FALSE);
748
else if (tp->is_const)
750
_eo_parser_log(&tp->base, "event value types cannot be const");
751
return _reset_stable(vals, was_stable, EINA_FALSE);
754
if (kwid == KW_iterator || kwid == KW_list)
756
_eo_parser_log(&tp->base, "sequence containers not allowed in events");
757
return _reset_stable(vals, was_stable, EINA_FALSE);
760
if (kwid == KW_rw_slice)
762
_eo_parser_log(&tp->base, "mutable slices not allowed in events");
763
return _reset_stable(vals, was_stable, EINA_FALSE);
771
if (kwid >= KW_any_value_ref && kwid != KW_string && kwid != KW_stringshare)
773
_eo_parser_log(&tp->base, "forbidden event type");
774
return _reset_stable(vals, was_stable, EINA_FALSE);
778
if (!_validate_doc(event->doc))
779
return _reset_stable(vals, was_stable, EINA_FALSE);
780
if (!_validate_doc_since_reset(vals, event->doc))
781
return _reset_stable(vals, was_stable, EINA_FALSE);
783
eina_hash_set(nhash, &event->base.name, &event->base);
785
_reset_stable(vals, was_stable, EINA_TRUE);
786
return _validate(&event->base);
790
_get_impl_class(const Eolian_Class *cl, const char *cln)
792
if (!cl || !strcmp(cl->base.name, cln))
795
Eolian_Class *icl = cl->parent;
801
const Eolian_Class *fcl = _get_impl_class(icl, cln);
805
EINA_LIST_FOREACH(cl->requires, l, icl)
807
const Eolian_Class *fcl = _get_impl_class(icl, cln);
811
EINA_LIST_FOREACH(cl->extends, l, icl)
813
const Eolian_Class *fcl = _get_impl_class(icl, cln);
821
_db_fill_implement(Eolian_Class *cl, Eolian_Implement *impl)
823
Eolian_Function_Type ftype = EOLIAN_METHOD;
825
if (impl->is_prop_get && impl->is_prop_set)
826
ftype = EOLIAN_PROPERTY;
827
else if (impl->is_prop_get)
828
ftype = EOLIAN_PROP_GET;
829
else if (impl->is_prop_set)
830
ftype = EOLIAN_PROP_SET;
832
size_t imlen = strlen(impl->base.name);
833
char *clbuf = alloca(imlen + 1);
834
memcpy(clbuf, impl->base.name, imlen + 1);
836
char *ldot = strrchr(clbuf, '.');
841
const char *clname = clbuf;
842
const char *fnname = ldot + 1;
844
const Eolian_Class *tcl = _get_impl_class(cl, clname);
847
_eo_parser_log(&impl->base, "class '%s' not found within the inheritance tree of '%s'",
848
clname, cl->base.name);
853
impl->implklass = cl;
855
const Eolian_Function *fid = eolian_class_function_by_name_get(tcl, fnname, EOLIAN_UNRESOLVED);
858
_eo_parser_log(&impl->base, "function '%s' not known in class '%s'", fnname, clname);
862
Eolian_Function_Type aftype = eolian_function_type_get(fid);
864
Eina_Bool auto_empty = (impl->get_auto || impl->get_empty);
867
if (ftype == EOLIAN_PROPERTY)
870
if (aftype != EOLIAN_PROPERTY)
872
_eo_parser_log(&impl->base, "function '%s' is not a complete property", fnname);
875
auto_empty = auto_empty && (impl->set_auto || impl->set_empty);
877
else if (ftype == EOLIAN_PROP_SET)
880
if ((aftype != EOLIAN_PROP_SET) && (aftype != EOLIAN_PROPERTY))
882
_eo_parser_log(&impl->base, "function '%s' doesn't have a setter", fnname);
885
auto_empty = (impl->set_auto || impl->set_empty);
887
else if (ftype == EOLIAN_PROP_GET)
890
if ((aftype != EOLIAN_PROP_GET) && (aftype != EOLIAN_PROPERTY))
892
_eo_parser_log(&impl->base, "function '%s' doesn't have a getter", fnname);
896
else if (aftype != EOLIAN_METHOD)
898
_eo_parser_log(&impl->base, "function '%s' is not a method", fnname);
902
if ((fid->klass == cl) && !auto_empty)
907
_eo_parser_log(&impl->base, "invalid implement '%s'", impl->base.name);
918
IMPL_STATUS_NONE = 1,
925
_extend_impl(Eina_Hash *fs, Eolian_Implement *impl, Eina_Bool as_iface)
927
const Eolian_Function *fid = impl->foo_id;
928
Impl_Status st = (Impl_Status)eina_hash_find(fs, &fid);
929
if (st == IMPL_STATUS_FULL)
932
eina_hash_set(fs, &fid, (void *)IMPL_STATUS_NONE);
933
if (as_iface || (impl->implklass->type == EOLIAN_CLASS_INTERFACE))
936
if (fid->type == EOLIAN_METHOD ||
937
((st == IMPL_STATUS_GET || fid->type == EOLIAN_PROP_SET) && impl->is_prop_set) ||
938
((st == IMPL_STATUS_SET || fid->type == EOLIAN_PROP_GET) && impl->is_prop_get) ||
939
(impl->is_prop_get && impl->is_prop_set))
942
if (impl->implklass != impl->klass)
944
eina_hash_set(fs, &fid, (void *)IMPL_STATUS_FULL);
945
return (st != IMPL_STATUS_FULL);
948
if (impl->get_pure_virtual && impl->set_pure_virtual)
950
if (impl->get_pure_virtual)
952
if (fid->type == EOLIAN_METHOD || fid->type == EOLIAN_PROP_GET)
954
if (st == IMPL_STATUS_GET)
956
eina_hash_set(fs, &fid, (void *)IMPL_STATUS_FULL);
957
return (st != IMPL_STATUS_FULL);
961
eina_hash_set(fs, &fid, (void *)IMPL_STATUS_SET);
962
return (st <= IMPL_STATUS_NONE);
965
if (impl->set_pure_virtual)
967
if (fid->type == EOLIAN_PROP_SET)
969
if (st == IMPL_STATUS_SET)
971
eina_hash_set(fs, &fid, (void *)IMPL_STATUS_FULL);
972
return (st < IMPL_STATUS_FULL);
976
eina_hash_set(fs, &fid, (void *)IMPL_STATUS_GET);
977
return (st <= IMPL_STATUS_NONE);
980
eina_hash_set(fs, &fid, (void *)IMPL_STATUS_FULL);
981
return (st != IMPL_STATUS_FULL);
983
if (impl->implklass != impl->klass ||
984
(!impl->get_pure_virtual && !impl->set_pure_virtual))
986
if (impl->is_prop_get)
988
eina_hash_set(fs, &fid, (void *)IMPL_STATUS_GET);
989
return (st <= IMPL_STATUS_NONE);
991
else if (impl->is_prop_set)
993
eina_hash_set(fs, &fid, (void *)IMPL_STATUS_SET);
994
return (st <= IMPL_STATUS_NONE);
1005
_db_fill_ihash(Eolian_Class *icl, Eina_Hash *icls)
1008
_db_fill_ihash(icl->parent, icls);
1011
EINA_LIST_FOREACH(icl->extends, l, sicl)
1012
_db_fill_ihash(sicl, icls);
1013
eina_hash_set(icls, &icl, icl);
1017
_db_fill_callables(Eolian_Class *cl, Eolian_Class *icl, Eina_Hash *fs, Eina_Bool parent)
1020
Eolian_Implement *impl;
1021
Eina_Bool allow_impl = parent || (icl->type == EOLIAN_CLASS_MIXIN);
1022
EINA_LIST_FOREACH(icl->callables, l, impl)
1024
Impl_Status ost = (Impl_Status)eina_hash_find(fs, &impl->foo_id);
1032
if (_extend_impl(fs, impl, !allow_impl))
1038
if (ost == IMPL_STATUS_NONE)
1041
Eolian_Implement *old;
1042
EINA_LIST_FOREACH(cl->callables, ll, old)
1044
if (old->foo_id == impl->foo_id)
1045
eina_list_data_set(ll, impl);
1049
cl->callables = eina_list_append(cl->callables, impl);
1055
_db_check_implemented(Validate_State *vals, Eolian_Class *cl, Eina_Hash *fs,
1056
Eina_Hash *cs, Eina_Hash *errh)
1058
if (cl->type != EOLIAN_CLASS_REGULAR)
1061
Eina_Bool succ = EINA_TRUE;
1064
if (!vals->unimplemented_beta && cl->base.is_beta)
1068
Eolian_Implement *impl;
1069
EINA_LIST_FOREACH(cl->callables, l, impl)
1071
const Eolian_Function *fid = impl->foo_id;
1073
if (!vals->unimplemented_beta && fid->base.is_beta)
1076
if (!vals->unimplemented_beta && fid->klass->base.is_beta)
1078
Impl_Status st = (Impl_Status)eina_hash_find(fs, &fid);
1083
if (eina_hash_find(cs, &fid->klass))
1088
if (eina_hash_find(errh, &impl))
1092
case IMPL_STATUS_NONE:
1094
&cl->base, "unimplemented function '%s' (originally defined at %s:%d:%d)",
1095
fid->base.name, fid->base.file, fid->base.line, fid->base.column);
1097
eina_hash_set(errh, &impl, impl);
1099
case IMPL_STATUS_GET:
1100
case IMPL_STATUS_SET:
1102
&cl->base, "partially implemented function '%s' (originally defined at %s:%d:%d)",
1103
fid->base.name, fid->base.file, fid->base.line, fid->base.column);
1105
eina_hash_set(errh, &impl, impl);
1107
case IMPL_STATUS_FULL:
1111
&cl->base, "internal error, unregistered function '%s' (originally defined at %s:%d:%d)",
1112
fid->base.name, fid->base.file, fid->base.line, fid->base.column);
1120
_db_fill_implements(Eolian_Class *cl, Eina_Hash *fs)
1122
Eolian_Implement *impl;
1125
Eina_Bool ret = EINA_TRUE;
1127
Eina_Hash *th = eina_hash_string_small_new(NULL),
1128
*pth = eina_hash_string_small_new(NULL);
1129
EINA_LIST_FOREACH(cl->implements, l, impl)
1131
Eina_Bool prop = (impl->is_prop_get || impl->is_prop_set);
1132
if (eina_hash_find(prop ? pth : th, impl->base.name))
1134
_eo_parser_log(&impl->base, "duplicate implement '%s'", impl->base.name);
1138
if (impl->klass != cl)
1140
if (!_db_fill_implement(cl, impl))
1145
if (eolian_function_is_constructor(impl->foo_id, impl->klass))
1146
database_function_constructor_add((Eolian_Function *)impl->foo_id, cl);
1148
if ((impl->klass != cl) && !_db_fill_implement(cl, impl))
1153
cl->callables = eina_list_append(cl->callables, impl);
1154
eina_hash_add(prop ? pth : th, impl->base.name, impl->base.name);
1155
_extend_impl(fs, impl, cl->type == EOLIAN_CLASS_INTERFACE);
1160
eina_hash_free(pth);
1165
_db_fill_ctors(Eolian_Class *cl)
1167
Eolian_Constructor *ctor;
1170
Eina_Bool ret = EINA_TRUE;
1172
Eina_Hash *th = eina_hash_string_small_new(NULL);
1173
EINA_LIST_FOREACH(cl->constructors, l, ctor)
1175
if (eina_hash_find(th, ctor->base.name))
1177
_eo_parser_log(&ctor->base, "duplicate ctor '%s'", ctor->base.name);
1181
const char *ldot = strrchr(ctor->base.name, '.');
1187
char *cnbuf = alloca(ldot - ctor->base.name + 1);
1188
memcpy(cnbuf, ctor->base.name, ldot - ctor->base.name);
1189
cnbuf[ldot - ctor->base.name] = '\0';
1190
const Eolian_Class *tcl = _get_impl_class(cl, cnbuf);
1193
_eo_parser_log(&ctor->base, "class '%s' not found within the inheritance tree of '%s'",
1194
cnbuf, cl->base.name);
1199
const Eolian_Function *cfunc = eolian_constructor_function_get(ctor);
1202
_eo_parser_log(&ctor->base, "unable to find function '%s'", ctor->base.name);
1206
database_function_constructor_add((Eolian_Function *)cfunc, tcl);
1207
eina_hash_add(th, ctor->base.name, ctor->base.name);
1216
_db_swap_inherit(Eolian_Class *cl, Eina_Bool succ, Eina_Stringshare *in_cl,
1217
Eolian_Class **out_cl, Eina_Bool iface_only)
1221
eina_stringshare_del(in_cl);
1224
Eolian_Class *icl = eina_hash_find(cl->base.unit->classes, in_cl);
1228
_eo_parser_log(&cl->base, "unknown inherit '%s' (incorrect case?)", in_cl);
1230
else if (iface_only && (icl->type != EOLIAN_CLASS_INTERFACE))
1233
_eo_parser_log(&cl->base, "non-interface class '%s' in composite list", icl->base.name);
1237
eina_stringshare_del(in_cl);
1246
_add_composite(Eolian_Class *cl, const Eolian_Class *icl, Eina_Hash *ch)
1248
const Eolian_Class *ccl;
1250
EINA_LIST_FOREACH(icl->composite, l, ccl)
1252
if (eina_hash_find(ch, &ccl))
1254
cl->composite = eina_list_append(cl->composite, ccl);
1255
eina_hash_add(ch, &ccl, ccl);
1260
_add_implicit_composite(Eolian_Class *icl, Eina_Hash *ch, Eina_Bool try_tree)
1262
eina_hash_set(ch, &icl, icl);
1266
EINA_LIST_FOREACH(icl->extends, l, icl)
1267
_add_implicit_composite(icl, ch, try_tree);
1271
_db_fill_inherits(Validate_State *vals, Eolian_Class *cl, Eina_Hash *fhash,
1274
if (eina_hash_find(fhash, &cl->base.name))
1278
if (eina_hash_find(cl->base.unit->state->main.unit.classes, cl->base.name))
1281
Eina_List *il = cl->extends, *rl = cl->requires;
1282
Eina_Stringshare *inn = NULL;
1284
cl->requires = NULL;
1285
Eina_Bool succ = EINA_TRUE;
1287
if (cl->parent_name)
1289
succ = _db_swap_inherit(cl, succ, cl->parent_name, &cl->parent, EINA_FALSE);
1296
succ = _db_fill_inherits(vals, cl->parent, fhash, errh);
1300
EINA_LIST_FREE(il, inn)
1302
Eolian_Class *out_cl = NULL;
1303
succ = _db_swap_inherit(cl, succ, inn, &out_cl, EINA_FALSE);
1306
cl->extends = eina_list_append(cl->extends, out_cl);
1307
succ = _db_fill_inherits(vals, out_cl, fhash, errh);
1310
if (succ && cl->type == EOLIAN_CLASS_MIXIN)
1312
EINA_LIST_FREE(rl, inn)
1314
Eolian_Class *out_cl = NULL;
1315
succ = _db_swap_inherit(cl, succ, inn, &out_cl, EINA_FALSE);
1316
if (succ && !(out_cl->type == EOLIAN_CLASS_REGULAR || out_cl->type == EOLIAN_CLASS_ABSTRACT))
1318
_eo_parser_log(&cl->base, "requires only allows regulars or abstracts");
1323
_db_fill_inherits(vals, out_cl, fhash, errh);
1327
if (!eina_list_data_find(cl->requires, out_cl))
1328
cl->requires = eina_list_append(cl->requires, out_cl);
1333
Eina_Hash *ch = eina_hash_pointer_new(NULL);
1337
cl->composite = NULL;
1339
EINA_LIST_FREE(il, inn)
1341
Eolian_Class *out_cl = NULL;
1342
succ = _db_swap_inherit(cl, succ, inn, &out_cl, EINA_TRUE);
1345
cl->composite = eina_list_append(cl->composite, out_cl);
1346
succ = _db_fill_inherits(vals, out_cl, fhash, errh);
1353
_add_implicit_composite(out_cl, ch, out_cl->type == EOLIAN_CLASS_INTERFACE);
1361
_add_composite(cl, cl->parent, ch);
1365
EINA_LIST_FOREACH(cl->extends, il, icl)
1366
_add_composite(cl, icl, ch);
1377
eina_hash_add(fhash, &cl->base.name, cl);
1383
Eina_Hash *ih = eina_hash_pointer_new(NULL);
1387
_db_fill_ihash(cl->parent, ih);
1389
EINA_LIST_FOREACH(cl->extends, il, icl)
1390
_db_fill_ihash(icl, ih);
1396
EINA_LIST_FOREACH(cl->composite, il, icl)
1402
if (eina_hash_find(ih, &icl))
1404
cl->extends = eina_list_append(cl->extends, icl);
1411
Eina_Hash *fh = eina_hash_pointer_new(NULL);
1414
if (!_db_fill_implements(cl, fh))
1421
if (!_db_fill_ctors(cl))
1433
_db_fill_callables(cl, cl->parent, fh, EINA_TRUE);
1435
EINA_LIST_FOREACH(cl->extends, il, icl)
1436
_db_fill_callables(cl, icl, fh, EINA_FALSE);
1439
if (!_db_check_implemented(vals, cl, fh, ch, errh))
1440
vals->warned = EINA_TRUE;
1449
_validate_implement(Validate_State *vals, Eolian_Implement *impl)
1451
if (impl->base.validated)
1454
if (!_validate_doc(impl->common_doc))
1456
if (!_validate_doc(impl->get_doc))
1458
if (!_validate_doc(impl->set_doc))
1462
const char *old_since = vals->since_ver;
1463
if (impl->common_doc && !_validate_doc_since(vals, impl->common_doc))
1465
if (!_validate_doc_since_reset(vals, impl->get_doc))
1467
if (!_validate_doc_since_reset(vals, impl->set_doc))
1469
vals->since_ver = old_since;
1471
return _validate(&impl->base);
1475
_required_classes(Eolian_Class *mixin)
1477
Eina_List *result = NULL, *n;
1478
Eolian_Class *extension;
1481
result = eina_list_clone(mixin->requires);
1484
result = eina_list_merge(result, _required_classes(mixin->parent));
1486
EINA_LIST_FOREACH(mixin->extends, n, extension)
1487
result = eina_list_merge(result, _required_classes(extension));
1493
_validate_class(Validate_State *vals, Eolian_Class *cl,
1494
Eina_Hash *nhash, Eina_Hash *ehash, Eina_Hash *phash, Eina_Hash *chash)
1497
Eolian_Function *func;
1498
Eolian_Event *event;
1500
Eolian_Implement *impl;
1502
Eina_List *required_classes = NULL;
1508
if (eina_hash_find(chash, &cl))
1511
Eina_Bool valid = cl->base.validated;
1516
if (!valid) switch (cl->type)
1518
case EOLIAN_CLASS_REGULAR:
1519
case EOLIAN_CLASS_ABSTRACT:
1520
if (cl->parent->type != EOLIAN_CLASS_REGULAR && cl->parent->type != EOLIAN_CLASS_ABSTRACT)
1522
_eo_parser_log(&cl->base, "regular classes ('%s') cannot inherit from non-regular classes ('%s')",
1523
cl->base.name, cl->parent->base.name);
1530
if (!cl->base.is_beta && cl->parent->base.is_beta)
1532
_eo_parser_log(&cl->base, "non-beta class cannot have beta parent");
1535
if (!_validate_class(vals, cl->parent, nhash, ehash, phash, chash))
1539
EINA_LIST_FOREACH(cl->extends, l, icl)
1541
if (icl->type == EOLIAN_CLASS_MIXIN)
1543
Eina_List *res = _required_classes(icl);
1544
Eolian_Class *required_class;
1546
EINA_LIST_FOREACH(res, n, required_class)
1548
if (!eina_list_data_find(required_classes, required_class))
1549
required_classes = eina_list_append(required_classes, required_class);
1552
if (!valid) switch (icl->type)
1554
case EOLIAN_CLASS_REGULAR:
1555
case EOLIAN_CLASS_ABSTRACT:
1558
_eo_parser_log(&cl->base, "regular classes ('%s') cannot appear in extensions list of '%s'",
1559
icl->base.name, cl->base.name);
1560
vals->warned = EINA_TRUE;
1567
if (!_validate_class(vals, icl, nhash, ehash, phash, chash))
1570
if (cl->type == EOLIAN_CLASS_ABSTRACT || cl->type == EOLIAN_CLASS_REGULAR)
1576
required_classes = eina_list_remove(required_classes, icl);
1580
if (required_classes)
1582
Eina_Strbuf *classes = eina_strbuf_new();
1583
Eolian_Class *required_class;
1585
EINA_LIST_FOREACH(required_classes, n, required_class)
1587
eina_strbuf_append(classes, required_class->base.name);
1588
eina_strbuf_append_char(classes, ' ');
1590
_eo_parser_log(&cl->base, "required classes %sare not in the inherit chain of %s",
1591
eina_strbuf_string_get(classes), cl->base.name);
1592
eina_strbuf_free(classes);
1597
_set_stable(vals, !cl->base.is_beta);
1598
vals->since_ver = NULL;
1600
if (!_validate_doc_since(vals, cl->doc))
1603
EINA_LIST_FOREACH(cl->properties, l, func)
1604
if (!_validate_function(vals, func, nhash))
1607
EINA_LIST_FOREACH(cl->methods, l, func)
1608
if (!_validate_function(vals, func, nhash))
1611
EINA_LIST_FOREACH(cl->events, l, event)
1612
if (!_validate_event(vals, event, ehash))
1615
EINA_LIST_FOREACH(cl->parts, l, part)
1616
if (!_validate_part(vals, part, phash))
1619
EINA_LIST_FOREACH(cl->implements, l, impl)
1620
if (!_validate_implement(vals, impl))
1627
eina_hash_add(chash, &cl, cl);
1631
if (!_validate_doc(cl->doc))
1635
eina_hash_add(chash, &cl, cl);
1637
return _validate(&cl->base);
1641
_validate_constant(Validate_State *vals, Eolian_Constant *var)
1643
if (var->base.validated)
1646
const char *old_since = vals->since_ver;
1647
vals->since_ver = NULL;
1649
Eina_Bool was_stable = _set_stable(vals, !var->base.is_beta && vals->stable);
1651
if (!_validate_doc_since(vals, var->doc))
1654
if (!_validate_type(vals, var->base_type, EINA_FALSE, EINA_FALSE))
1655
return _reset_stable(vals, was_stable, EINA_FALSE);
1657
if (!_validate_expr(var->value, var->base_type, 0, EINA_FALSE))
1658
return _reset_stable(vals, was_stable, EINA_FALSE);
1660
if (!_validate_doc(var->doc))
1661
return _reset_stable(vals, was_stable, EINA_FALSE);
1663
_reset_stable(vals, was_stable, EINA_TRUE);
1664
vals->since_ver = old_since;
1665
return _validate(&var->base);
1669
_typedecl_map_cb(const Eina_Hash *hash EINA_UNUSED, const void *key EINA_UNUSED,
1670
Eolian_Typedecl *tp, Cb_Ret *sc)
1672
return (sc->succ = _validate_typedecl(sc->vals, tp));
1676
_constant_map_cb(const Eina_Hash *hash EINA_UNUSED, const void *key EINA_UNUSED,
1677
Eolian_Constant *var, Cb_Ret *sc)
1679
return (sc->succ = _validate_constant(sc->vals, var));
1683
database_validate(const Eolian_Unit *src)
1687
Validate_State vals = {
1690
!!getenv("EFL_RUN_IN_TREE"),
1691
!!getenv("EOLIAN_CLASS_UNIMPLEMENTED_BETA_WARN"),
1695
Eina_Iterator *iter = eolian_unit_classes_get(src);
1696
Eina_Hash *fhash = eina_hash_pointer_new(NULL);
1698
Eina_Hash *errh = eina_hash_pointer_new(NULL);
1699
EINA_ITERATOR_FOREACH(iter, cl)
1705
eina_hash_free_buckets(errh);
1706
if (!_db_fill_inherits(&vals, cl, fhash, errh))
1708
eina_hash_free(errh);
1709
eina_hash_free(fhash);
1713
eina_hash_free(errh);
1714
eina_hash_free(fhash);
1715
eina_iterator_free(iter);
1717
iter = eolian_unit_classes_get(src);
1718
Eina_Hash *nhash = eina_hash_pointer_new(NULL);
1719
Eina_Hash *ehash = eina_hash_pointer_new(NULL);
1720
Eina_Hash *phash = eina_hash_pointer_new(NULL);
1721
Eina_Hash *chash = eina_hash_pointer_new(NULL);
1722
EINA_ITERATOR_FOREACH(iter, cl)
1724
eina_hash_free_buckets(nhash);
1725
eina_hash_free_buckets(ehash);
1726
eina_hash_free_buckets(phash);
1727
eina_hash_free_buckets(chash);
1728
if (!_validate_class(&vals, cl, nhash, ehash, phash, chash))
1730
eina_iterator_free(iter);
1731
eina_hash_free(nhash);
1732
eina_hash_free(ehash);
1733
eina_hash_free(phash);
1734
eina_hash_free(chash);
1738
eina_hash_free(chash);
1739
eina_hash_free(phash);
1740
eina_hash_free(ehash);
1741
eina_hash_free(nhash);
1742
eina_iterator_free(iter);
1744
Cb_Ret rt = { &vals, EINA_TRUE };
1746
eina_hash_foreach(src->aliases, (Eina_Hash_Foreach)_typedecl_map_cb, &rt);
1750
eina_hash_foreach(src->structs, (Eina_Hash_Foreach)_typedecl_map_cb, &rt);
1754
eina_hash_foreach(src->enums, (Eina_Hash_Foreach)_typedecl_map_cb, &rt);
1758
eina_hash_foreach(src->constants, (Eina_Hash_Foreach)_constant_map_cb, &rt);