yin parser CHANGE parse known extension subelements correctly finished
diff --git a/src/parser_yin.c b/src/parser_yin.c
index 3576471..914f6f9 100644
--- a/src/parser_yin.c
+++ b/src/parser_yin.c
@@ -3210,20 +3210,28 @@
return LY_SUCCESS;
}
-LY_ERR
-yin_parse_arg_inext_known(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, enum ly_stmt elem_type,
- enum ly_stmt parent, struct lysp_stmt **args)
+/**
+ * @brief Parse argument of extension subelement that is classic yang keyword and not another instance of extension.
+ *
+ * @param[in,out] ctx Yin parser context for logging and to store current state.
+ * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of extension instance.
+ * @param[in,out] data Data to read from, always moved to currently handled character.
+ * @param[in] elem_type Type of element that is currently being parsed.
+ * @param[out] arg Value to write to.
+ *
+ * @return LY_ERR values.
+ */
+static LY_ERR
+yin_parse_arg_inext_known(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, enum ly_stmt elem_type,
+ const char **arg)
{
LY_ERR ret = LY_SUCCESS;
- struct lysp_stmt *arg;
char *out = NULL;
const char *name, *prefix;
size_t out_len, name_len, prefix_len;
int dynamic;
enum ly_stmt child;
- LY_LIST_NEW_RET(ctx->xml_ctx.ctx, args, arg, next);
-
switch (elem_type) {
case LY_STMT_ACTION:
case LY_STMT_ANYDATA:
@@ -3251,12 +3259,12 @@
case LY_STMT_TYPEDEF:
case LY_STMT_UNITS:
case LY_STMT_USES:
- LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &arg->arg, Y_MAYBE_STR_ARG, elem_type));
+ LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, arg, Y_MAYBE_STR_ARG, elem_type));
break;
case LY_STMT_AUGMENT:
case LY_STMT_DEVIATION:
case LY_STMT_REFINE:
- LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_TARGET_NODE, &arg->arg, Y_MAYBE_STR_ARG, elem_type));
+ LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_TARGET_NODE, arg, Y_MAYBE_STR_ARG, elem_type));
break;
case LY_STMT_CONFIG:
case LY_STMT_DEFAULT:
@@ -3281,30 +3289,30 @@
case LY_STMT_VALUE:
case LY_STMT_YANG_VERSION:
case LY_STMT_YIN_ELEMENT:
- LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &arg->arg, Y_MAYBE_STR_ARG, elem_type));
+ LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, arg, Y_MAYBE_STR_ARG, elem_type));
break;
case LY_STMT_IMPORT:
case LY_STMT_INCLUDE:
case LY_STMT_BELONGS_TO:
- LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_MODULE, &arg->arg, Y_MAYBE_STR_ARG, elem_type));
+ LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_MODULE, arg, Y_MAYBE_STR_ARG, elem_type));
break;
case LY_STMT_INPUT:
case LY_STMT_OUTPUT:
- LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NONE, &arg->arg, Y_MAYBE_STR_ARG, elem_type));
+ LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NONE, arg, Y_MAYBE_STR_ARG, elem_type));
break;
case LY_STMT_MUST:
case LY_STMT_WHEN:
- LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_CONDITION, &arg->arg, Y_MAYBE_STR_ARG, elem_type));
+ LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_CONDITION, arg, Y_MAYBE_STR_ARG, elem_type));
break;
case LY_STMT_NAMESPACE:
- LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_URI, &arg->arg, Y_MAYBE_STR_ARG, elem_type));
+ LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_URI, arg, Y_MAYBE_STR_ARG, elem_type));
break;
case LY_STMT_REVISION:
case LY_STMT_REVISION_DATE:
- LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_DATE, &arg->arg, Y_MAYBE_STR_ARG, elem_type));
+ LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_DATE, arg, Y_MAYBE_STR_ARG, elem_type));
break;
case LY_STMT_UNIQUE:
- LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_TAG, &arg->arg, Y_MAYBE_STR_ARG, elem_type));
+ LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_TAG, arg, Y_MAYBE_STR_ARG, elem_type));
break;
/* argument is mapped to yin element */
case LY_STMT_CONTACT:
@@ -3312,22 +3320,29 @@
case LY_STMT_ORGANIZATION:
case LY_STMT_REFERENCE:
case LY_STMT_ERROR_MESSAGE:
- /* there should be no attribute, argument is supposed to be first subelement */
- LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NONE, &arg->arg, Y_MAYBE_STR_ARG, elem_type));
+ /* there shouldn't be any attribute, argument is supposed to be first subelement */
+ LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NONE, arg, Y_MAYBE_STR_ARG, elem_type));
ret = lyxml_get_string(&ctx->xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
- /* TODO fix message */
- LY_CHECK_ERR_RET(ret != LY_EINVAL, LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_FIRT_SUBELEM, ly_stmt2str(elem_type), parent), LY_EVALID);
+ LY_CHECK_ERR_RET(ret != LY_EINVAL, LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_FIRT_SUBELEM,
+ elem_type == LY_STMT_ERROR_MESSAGE ? "value" : "text", ly_stmt2str(elem_type)),
+ LY_EVALID);
LY_CHECK_RET(lyxml_get_element(&ctx->xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
child = yin_match_keyword(ctx, name, name_len, prefix, prefix_len, elem_type);
- if ((elem_type == LY_STMT_ERROR_MESSAGE && child != LY_STMT_ARG_VALUE) || child != LY_STMT_ARG_TEXT) {
- LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_SUBELEM, name_len, name, elem_type);
+ if ((elem_type == LY_STMT_ERROR_MESSAGE && child == LY_STMT_ARG_VALUE) ||
+ (elem_type != LY_STMT_ERROR_MESSAGE && child == LY_STMT_ARG_TEXT)) {
+ LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_SUBELEM, name_len, name, ly_stmt2str(elem_type));
return LY_EVALID;
}
/* load and save content */
LY_CHECK_RET(lyxml_get_string(&ctx->xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic));
- INSERT_STRING(ctx->xml_ctx.ctx, arg->arg, dynamic, out, out_len);
- /* load closing tag */
+ INSERT_STRING(ctx->xml_ctx.ctx, *arg, dynamic, out, out_len);
+ LY_CHECK_RET(!*arg, LY_EMEM);
+ /* load closing tag of subelement */
LY_CHECK_RET(lyxml_get_element(&ctx->xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
+ /* if only subelement was parsed as argument, load also closing tag */
+ if (ctx->xml_ctx.status == LYXML_ELEMENT) {
+ LY_CHECK_RET(lyxml_get_element(&ctx->xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
+ }
break;
default:
LOGINT(ctx->xml_ctx.ctx);
@@ -3338,7 +3353,7 @@
}
LY_ERR
-yin_parse_element_generic(struct yin_parser_ctx *ctx, const char *name, size_t name_len, const char *prefix, size_t prefix_len, enum ly_stmt parent,
+yin_parse_element_generic(struct yin_parser_ctx *ctx, const char *name, size_t name_len, const char *prefix, size_t prefix_len, enum ly_stmt parent,
const char **data, struct lysp_stmt **element)
{
LY_ERR ret = LY_SUCCESS;
@@ -3359,23 +3374,23 @@
ret = yin_load_attributes(ctx, data, &attrs);
LY_CHECK_GOTO(ret, cleanup);
- (*element)->kw = yin_match_keyword(ctx, name, name_len, prefix, prefix_len, LY_STMT_EXTENSION_INSTANCE);
+ (*element)->kw = yin_match_keyword(ctx, name, name_len, prefix, prefix_len, parent);
last = (*element)->child;
if ((*element)->kw == LY_STMT_NONE) {
/* unrecognized element */
- /* TODO set parrent correctly */
- LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_SUBELEM, name_len, name, ly_stmt2str(LY_STMT_EXTENSION_INSTANCE));
- return LY_EVALID;
+ LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_SUBELEM, name_len, name, ly_stmt2str(parent));
+ ret = LY_EVALID;
+ goto cleanup;
} else if ((*element)->kw != LY_STMT_EXTENSION_INSTANCE) {
/* element is known yang keyword, which means argument can be parsed correctly. */
- LY_CHECK_RET(yin_parse_arg_inext_known(ctx, attrs, data, (*element)->kw, parent, &(*element)->child));
+ ret = yin_parse_arg_inext_known(ctx, attrs, data, (*element)->kw, &(*element)->arg);
+ LY_CHECK_GOTO(ret, cleanup);
} else {
- /* load attributes in generic way
- /* save all attributes in linked list */
+ /* load attributes in generic way, save all attributes in linked list */
LY_ARRAY_FOR(attrs, struct yin_arg_record, iter) {
new = calloc(1, sizeof(*last));
- LY_CHECK_ERR_RET(!new, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
+ LY_CHECK_ERR_GOTO(!new, LOGMEM(ctx->xml_ctx.ctx); ret = LY_EMEM, cleanup);
if (!(*element)->child) {
/* save first */
(*element)->child = new;
@@ -3390,7 +3405,7 @@
/* attributes with prefix are ignored */
if (!iter->prefix) {
INSERT_STRING(ctx->xml_ctx.ctx, last->arg, iter->dynamic_content, iter->content, iter->content_len);
- LY_CHECK_RET(!last->arg, LY_EMEM);
+ LY_CHECK_ERR_GOTO(!last->arg, ret = LY_EMEM, cleanup);
/* string is no longer supposed to be freed when the array is freed */
iter->dynamic_content = 0;
}
@@ -3403,12 +3418,14 @@
if (ret == LY_EINVAL) {
while (ctx->xml_ctx.status == LYXML_ELEMENT) {
/* parse subelements */
- LY_CHECK_RET(lyxml_get_element(&ctx->xml_ctx, data, &temp_prefix, &temp_prefix_len, &temp_name, &temp_name_len));
+ ret = lyxml_get_element(&ctx->xml_ctx, data, &temp_prefix, &temp_prefix_len, &temp_name, &temp_name_len);
+ LY_CHECK_GOTO(ret , cleanup);
if (!temp_name) {
/* end of element reached */
break;
}
- LY_CHECK_RET(yin_parse_element_generic(ctx, temp_name, temp_name_len, temp_prefix, temp_prefix_len, (*element)->kw, data, &new));
+ ret = yin_parse_element_generic(ctx, temp_name, temp_name_len, temp_prefix, temp_prefix_len, (*element)->kw, data, &new);
+ LY_CHECK_GOTO(ret, cleanup);
if (!(*element)->child) {
/* save first */
(*element)->child = new;
@@ -3419,15 +3436,16 @@
}
ret = LY_SUCCESS;
} else {
- LY_CHECK_RET(ret);
+ LY_CHECK_GOTO(ret, cleanup);
/* save element content */
if (out_len != 0) {
INSERT_STRING(ctx->xml_ctx.ctx, (*element)->arg, dynamic, out, out_len);
- LY_CHECK_RET(!(*element)->arg, LY_EMEM);
+ LY_CHECK_ERR_GOTO(!(*element)->arg, ret = LY_EMEM, cleanup);
}
/* read closing tag */
- LY_CHECK_RET(lyxml_get_element(&ctx->xml_ctx, data, &temp_prefix, &temp_prefix_len, &temp_name, &temp_name_len));
+ ret = lyxml_get_element(&ctx->xml_ctx, data, &temp_prefix, &temp_prefix_len, &temp_name, &temp_name_len);
+ LY_CHECK_GOTO(ret, cleanup);
}
}