schema CHANGE integrate statement parser with the compilation process
Does not cover all the statements - focused mainly for yang-data
extension, so it handles schema nodes processing.
diff --git a/src/schema_compile.c b/src/schema_compile.c
index 07133d7..51ea049 100644
--- a/src/schema_compile.c
+++ b/src/schema_compile.c
@@ -619,125 +619,149 @@
}
LY_ERR
-lys_compile_extension_instance(struct lysc_ctx *ctx, const struct lysp_ext_instance *ext, struct lysc_ext_substmt *substmts)
+lys_compile_extension_instance(struct lysc_ctx *ctx, const struct lysp_ext_instance *ext_p, struct lysc_ext_instance *ext)
{
LY_ERR ret = LY_EVALID, r;
LY_ARRAY_COUNT_TYPE u;
struct lysp_stmt *stmt;
- struct lysp_qname *iffeatures, *iffeat;
void *parsed = NULL, **compiled = NULL;
- ly_bool enabled;
/* check for invalid substatements */
- for (stmt = ext->child; stmt; stmt = stmt->next) {
+ for (stmt = ext_p->child; stmt; stmt = stmt->next) {
if (stmt->flags & (LYS_YIN_ATTR | LYS_YIN_ARGUMENT)) {
continue;
}
- LY_ARRAY_FOR(substmts, u) {
- if (substmts[u].stmt == stmt->kw) {
+ LY_ARRAY_FOR(ext->substmts, u) {
+ if (ext->substmts[u].stmt == stmt->kw) {
break;
}
}
- if (u == LY_ARRAY_COUNT(substmts)) {
+ if (u == LY_ARRAY_COUNT(ext->substmts)) {
LOGVAL(ctx->ctx, LYVE_SYNTAX_YANG, "Invalid keyword \"%s\" as a child of \"%s%s%s\" extension instance.",
- stmt->stmt, ext->name, ext->argument ? " " : "", ext->argument ? ext->argument : "");
+ stmt->stmt, ext_p->name, ext_p->argument ? " " : "", ext_p->argument ? ext_p->argument : "");
goto cleanup;
}
}
/* TODO store inherited data, e.g. status first, but mark them somehow to allow to overwrite them and not detect duplicity */
+ /* note into the compile context that we are processing extension now */
+ ctx->ext = ext;
+
/* keep order of the processing the same as the order in the defined substmts,
* the order is important for some of the statements depending on others (e.g. type needs status and units) */
- LY_ARRAY_FOR(substmts, u) {
- ly_bool stmt_present = 0;
- for (stmt = ext->child; stmt; stmt = stmt->next) {
- if (substmts[u].stmt != stmt->kw) {
+ LY_ARRAY_FOR(ext->substmts, u) {
+ uint64_t stmt_counter = 0;
+
+ for (stmt = ext_p->child; stmt; stmt = stmt->next) {
+ if (ext->substmts[u].stmt != stmt->kw) {
continue;
}
- stmt_present = 1;
- if (substmts[u].storage) {
+ parsed = NULL;
+ stmt_counter++;
+ if (ext->substmts[u].storage) {
switch (stmt->kw) {
- case LY_STMT_STATUS:
- assert(substmts[u].cardinality < LY_STMT_CARD_SOME);
- LY_CHECK_ERR_GOTO(r = lysp_stmt_parse(ctx, stmt, &substmts[u].storage, /* TODO */ NULL), ret = r, cleanup);
+ case LY_STMT_ACTION:
+ case LY_STMT_ANYDATA:
+ case LY_STMT_ANYXML:
+ case LY_STMT_CONTAINER:
+ case LY_STMT_CHOICE:
+ case LY_STMT_LEAF:
+ case LY_STMT_LEAF_LIST:
+ case LY_STMT_LIST:
+ case LY_STMT_NOTIFICATION:
+ case LY_STMT_RPC:
+ case LY_STMT_USES:
+ r = lysp_stmt_parse(ctx, stmt, &parsed, NULL);
+ LY_CHECK_ERR_GOTO(r, ret = r, cleanup);
+
+ /* set storage as an alternative document root in the compile context */
+ r = lys_compile_node(ctx, parsed, NULL, 0, NULL);
+ lysp_node_free(ctx->ctx, parsed);
+ LY_CHECK_ERR_GOTO(r, ret = r, cleanup);
break;
case LY_STMT_DESCRIPTION:
case LY_STMT_REFERENCE:
case LY_STMT_UNITS: {
- const char **units;
+ const char **str_p;
- if (substmts[u].cardinality < LY_STMT_CARD_SOME) {
+ if (ext->substmts[u].cardinality < LY_STMT_CARD_SOME) {
/* single item */
- if (*((const char **)substmts[u].storage)) {
+ if (*((const char **)ext->substmts[u].storage)) {
LOGVAL(ctx->ctx, LY_VCODE_DUPSTMT, stmt->stmt);
goto cleanup;
}
- units = (const char **)substmts[u].storage;
+ str_p = (const char **)ext->substmts[u].storage;
} else {
/* sized array */
- const char ***units_array = (const char ***)substmts[u].storage;
- LY_ARRAY_NEW_GOTO(ctx->ctx, *units_array, units, ret, cleanup);
+ const char ***strings_array = (const char ***)ext->substmts[u].storage;
+ LY_ARRAY_NEW_GOTO(ctx->ctx, *strings_array, str_p, ret, cleanup);
}
- r = lydict_insert(ctx->ctx, stmt->arg, 0, units);
+ r = lydict_insert(ctx->ctx, stmt->arg, 0, str_p);
LY_CHECK_ERR_GOTO(r, ret = r, cleanup);
break;
}
- case LY_STMT_TYPE: {
- uint16_t *flags = lys_compile_extension_instance_storage(LY_STMT_STATUS, substmts);
- const char **units = lys_compile_extension_instance_storage(LY_STMT_UNITS, substmts);
-
- if (substmts[u].cardinality < LY_STMT_CARD_SOME) {
- /* single item */
- if (*(struct lysc_type **)substmts[u].storage) {
- LOGVAL(ctx->ctx, LY_VCODE_DUPSTMT, stmt->stmt);
- goto cleanup;
- }
- compiled = substmts[u].storage;
- } else {
- /* sized array */
- struct lysc_type ***types = (struct lysc_type ***)substmts[u].storage, **type = NULL;
- LY_ARRAY_NEW_GOTO(ctx->ctx, *types, type, ret, cleanup);
- compiled = (void *)type;
- }
+ case LY_STMT_IF_FEATURE: {
+ ly_bool enabled;
r = lysp_stmt_parse(ctx, stmt, &parsed, NULL);
LY_CHECK_ERR_GOTO(r, ret = r, cleanup);
- r = lys_compile_type(ctx, NULL, flags ? *flags : 0, ext->name, parsed, (struct lysc_type **)compiled,
- units && !*units ? units : NULL, NULL);
- lysp_type_free(ctx->ctx, parsed);
- free(parsed);
- LY_CHECK_ERR_GOTO(r, ret = r, cleanup);
- break;
- }
- case LY_STMT_IF_FEATURE:
- iffeatures = NULL;
- LY_ARRAY_NEW_GOTO(ctx->ctx, iffeatures, iffeat, ret, cleanup);
- iffeat->str = stmt->arg;
- iffeat->mod = ctx->pmod;
- r = lys_eval_iffeatures(ctx->ctx, iffeatures, &enabled);
- LY_ARRAY_FREE(iffeatures);
+
+ r = lys_eval_iffeatures(ctx->ctx, parsed, &enabled);
+ FREE_ARRAY(ctx->ctx, (struct lysp_qname *)parsed, lysp_qname_free);
LY_CHECK_ERR_GOTO(r, ret = r, cleanup);
if (!enabled) {
/* it is disabled, remove the whole extension instance */
return LY_ENOT;
}
break;
+ }
+ case LY_STMT_STATUS:
+ assert(ext->substmts[u].cardinality < LY_STMT_CARD_SOME);
+ LY_CHECK_ERR_GOTO(r = lysp_stmt_parse(ctx, stmt, &ext->substmts[u].storage, /* TODO */ NULL), ret = r, cleanup);
+ break;
+ case LY_STMT_TYPE: {
+ uint16_t *flags = lys_compile_extension_instance_storage(LY_STMT_STATUS, ext->substmts);
+ const char **units = lys_compile_extension_instance_storage(LY_STMT_UNITS, ext->substmts);
+
+ if (ext->substmts[u].cardinality < LY_STMT_CARD_SOME) {
+ /* single item */
+ if (*(struct lysc_type **)ext->substmts[u].storage) {
+ LOGVAL(ctx->ctx, LY_VCODE_DUPSTMT, stmt->stmt);
+ goto cleanup;
+ }
+ compiled = ext->substmts[u].storage;
+ } else {
+ /* sized array */
+ struct lysc_type ***types = (struct lysc_type ***)ext->substmts[u].storage, **type = NULL;
+ LY_ARRAY_NEW_GOTO(ctx->ctx, *types, type, ret, cleanup);
+ compiled = (void *)type;
+ }
+
+ r = lysp_stmt_parse(ctx, stmt, &parsed, NULL);
+ LY_CHECK_ERR_GOTO(r, ret = r, cleanup);
+ r = lys_compile_type(ctx, NULL, flags ? *flags : 0, ext_p->name, parsed, (struct lysc_type **)compiled,
+ units && !*units ? units : NULL, NULL);
+ lysp_type_free(ctx->ctx, parsed);
+ free(parsed);
+ LY_CHECK_ERR_GOTO(r, ret = r, cleanup);
+ break;
+ }
/* TODO support other substatements (parse stmt to lysp and then compile lysp to lysc),
* also note that in many statements their extensions are not taken into account */
default:
LOGVAL(ctx->ctx, LYVE_SYNTAX_YANG, "Statement \"%s\" is not supported as an extension (found in \"%s%s%s\") substatement.",
- stmt->stmt, ext->name, ext->argument ? " " : "", ext->argument ? ext->argument : "");
+ stmt->stmt, ext_p->name, ext_p->argument ? " " : "", ext_p->argument ? ext_p->argument : "");
goto cleanup;
}
}
}
- if (((substmts[u].cardinality == LY_STMT_CARD_MAND) || (substmts[u].cardinality == LY_STMT_CARD_SOME)) && !stmt_present) {
+ if (((ext->substmts[u].cardinality == LY_STMT_CARD_MAND) || (ext->substmts[u].cardinality == LY_STMT_CARD_SOME)) && !stmt_counter) {
LOGVAL(ctx->ctx, LYVE_SYNTAX_YANG, "Missing mandatory keyword \"%s\" as a child of \"%s%s%s\".",
- ly_stmt2str(substmts[u].stmt), ext->name, ext->argument ? " " : "", ext->argument ? ext->argument : "");
+ ly_stmt2str(ext->substmts[u].stmt), ext_p->name, ext_p->argument ? " " : "", ext_p->argument ? ext_p->argument : "");
goto cleanup;
}
}
@@ -745,6 +769,7 @@
ret = LY_SUCCESS;
cleanup:
+ ctx->ext = NULL;
return ret;
}