schema BUGFIX reflect the way YIN parser stores extension's arguments
YIN parser is not able to detect what is the argument in extension
without the definition of the extension which is known as late as during the
compilation process. Therefore if the data come from YIN source, it is
necessary to get the extension's argument before compiling the extension
instance.
diff --git a/src/printer_yang.c b/src/printer_yang.c
index 629c35b..e9957c5 100755
--- a/src/printer_yang.c
+++ b/src/printer_yang.c
@@ -59,7 +59,7 @@
*
* @param[in] out Output specification.
* @param[in] text String to be printed.
- * @param[in] len Length of the string from @p text to be printed. In case of 0,
+ * @param[in] len Length of the string from @p text to be printed. In case of -1,
* the @p text is printed completely as a NULL-terminated string.
*/
static void
@@ -221,6 +221,8 @@
{
unsigned int u;
struct lysp_stmt *stmt;
+ int child_presence;
+ const char *argument;
if (!count && ext) {
count = LY_ARRAY_SIZE(ext);
@@ -229,26 +231,51 @@
if (!count) {
break;
}
- if (ext->yin) {
- ly_print(ctx->out, "%*s%s Model comes from different input format, extensions must be resolved first.", INDENT, ext[u].name);
- } else if (ext->insubstmt == substmt && ext->insubstmt_index == substmt_index) {
- ypr_open(ctx->out, flag);
- if (ext[u].argument) {
- ly_print(ctx->out, "%*s%s %s%s", INDENT, ext[u].name, ext[u].argument, ext[u].child ? " {\n" : ";\n");
- } else {
- ly_print(ctx->out, "%*s%s%s", INDENT, ext[u].name, ext[u].child ? " {\n" : ";\n");
- }
- if (ext[u].child) {
- LEVEL++;
- LY_LIST_FOR(ext[u].child, stmt) {
- yprp_stmt(ctx, stmt);
- }
- LEVEL--;
- ly_print(ctx->out, "%*s}\n", INDENT);
- }
- }
count--;
+ if (ext->insubstmt != substmt || ext->insubstmt_index != substmt_index) {
+ continue;
+ }
+
+ if (!ext->compiled && ext->yin) {
+ ly_print(ctx->out, "%*s%s; // Model comes from different input format, extensions must be resolved first.\n", INDENT, ext[u].name);
+ continue;
+ }
+
+
+ ypr_open(ctx->out, flag);
+ argument = NULL;
+ if (ext[u].compiled) {
+ argument = ext[u].compiled->argument;
+ } else {
+ argument = ext[u].argument;
+ }
+ if (argument) {
+ ly_print(ctx->out, "%*s%s \"", INDENT, ext[u].name);
+ ypr_encode(ctx->out, argument, -1);
+ ly_print(ctx->out, "\"");
+ } else {
+ ly_print(ctx->out, "%*s%s", INDENT, ext[u].name);
+ }
+
+ child_presence = 0;
+ LEVEL++;
+ LY_LIST_FOR(ext[u].child, stmt) {
+ if (stmt->flags & (LYS_YIN_ATTR | LYS_YIN_ARGUMENT)) {
+ continue;
+ }
+ if (!child_presence) {
+ ly_print(ctx->out, " {\n");
+ child_presence = 1;
+ }
+ yprp_stmt(ctx, stmt);
+ }
+ LEVEL--;
+ if (child_presence) {
+ ly_print(ctx->out, "%*s}\n", INDENT);
+ } else {
+ ly_print(ctx->out, ";\n");
+ }
}
}
diff --git a/src/tree_schema.h b/src/tree_schema.h
index fe84d17..9f7e470 100644
--- a/src/tree_schema.h
+++ b/src/tree_schema.h
@@ -370,7 +370,7 @@
const char *dsc; /**< description statement */
const char *ref; /**< reference statement */
struct lysp_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
- uint16_t flags; /**< LYS_STATUS_* and LYS_YINELEM values (@ref snodeflags) */
+ uint16_t flags; /**< LYS_STATUS_* and LYS_YINELEM_* values (@ref snodeflags) */
};
/**
@@ -396,6 +396,8 @@
void *parent; /**< pointer to the parent element holding the extension instance(s), use
::lysp_ext_instance#parent_type to access the schema element */
struct lysp_stmt *child; /**< list of the extension's substatements (linked list) */
+ struct lysc_ext_instance *compiled; /**< pointer to the compiled data if any - in case the source format is YIN,
+ some of the information (argument) are available only after compilation */
LYEXT_SUBSTMT insubstmt; /**< value identifying placement of the extension instance */
uint32_t insubstmt_index; /**< in case the instance is in a substatement, this identifies
the index of that substatement */
@@ -683,6 +685,8 @@
* LYS_USED_GRP | | | | | | | | | | | | | | | |x| | | | | | | |
* LYS_YIN_ATTR | | | | | | | | | | | | | | | | | | | | | | |x|
* ---------------------+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * 12 LYS_YIN_ARGUMENT | | | | | | | | | | | | | | | | | | | | | | |x|
+ * ---------------------+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
*/
@@ -792,10 +796,11 @@
#define LYS_SET_UNITS 0x0400 /**< flag to know if the leaf's/leaflist's units are their own (flag set) or it is taken from the type. */
#define LYS_SET_CONFIG 0x0800 /**< flag to know if the config property was set explicitly (flag set) or it is inherited. */
-#define LYS_SINGLEQUOTED 0x100 /**< flag for single-quoted argument of an extension instance's substatement */
-#define LYS_DOUBLEQUOTED 0x200 /**< flag for double-quoted argument of an extension instance's substatement */
+#define LYS_SINGLEQUOTED 0x100 /**< flag for single-quoted argument of an extension instance's substatement, only when the source is YANG */
+#define LYS_DOUBLEQUOTED 0x200 /**< flag for double-quoted argument of an extension instance's substatement, only when the source is YANG */
-#define LYS_YIN_ATTR 0x400 /**< flag to identify YIN attribute */
+#define LYS_YIN_ATTR 0x400 /**< flag to identify YIN attribute parsed as extension's substatement, only when the source is YIN */
+#define LYS_YIN_ARGUMENT 0x800 /**< flag to identify statement representing extension's argument, only when the source is YIN */
#define LYS_ISENUM 0x200 /**< flag to simply distinguish type in struct lysc_type_bitenum_item */
diff --git a/src/tree_schema_compile.c b/src/tree_schema_compile.c
index 6155ee4..3c6f8c2 100644
--- a/src/tree_schema_compile.c
+++ b/src/tree_schema_compile.c
@@ -439,6 +439,9 @@
ext->parent = parent;
ext->parent_type = parent_type;
+ lysc_update_path(ctx, ext->parent_type == LYEXT_PAR_NODE ? (struct lysc_node*)ext->parent : NULL, "{extension}");
+ lysc_update_path(ctx, NULL, ext_p->name );
+
/* get module where the extension definition should be placed */
for (u = 0; ext_p->name[u] != ':'; ++u);
mod = lys_module_find_prefix(ctx->mod_def, ext_p->name, u);
@@ -469,19 +472,56 @@
"Extension definition of extension instance \"%s\" not found.", ext_p->name),
LY_EVALID);
+ /* unify the parsed extension from YIN and YANG sources. Without extension definition, it is not possible
+ * to get extension's argument from YIN source, so it is stored as one of the substatements. Here we have
+ * to find it, mark it with LYS_YIN_ARGUMENT and store it in the compiled structure. */
+ if (ext_p->yin && ext->def->argument) {
+ /* Schema was parsed from YIN and an argument is expected, ... */
+ struct lysp_stmt *stmt = NULL;
+
+ if (ext->def->flags & LYS_YINELEM_TRUE) {
+ /* ... argument was the first XML child element */
+ if (ext_p->child && !(ext_p->child->flags & LYS_YIN_ATTR)) {
+ /* TODO check namespace of the statement */
+ if (!strcmp(ext_p->child->stmt, ext->def->argument)) {
+ stmt = ext_p->child;
+ }
+ }
+ } else {
+ /* ... argument was one of the XML attributes which are represented as child stmt
+ * with LYS_YIN_ATTR flag */
+ for (stmt = ext_p->child; stmt && (stmt->flags & LYS_YIN_ATTR); stmt = stmt->next) {
+ if (!strcmp(stmt->stmt, ext->def->argument)) {
+ /* this is the extension's argument */
+ ext->argument = lydict_insert(ctx->ctx, stmt->arg, 0);
+ break;
+ }
+ }
+ }
+ if (!stmt) {
+ /* missing extension's argument */
+ LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
+ "Extension instance \"%s\" misses argument \"%s\".", ext_p->name, ext->def->argument);
+ return LY_EVALID;
+
+ }
+ ext->argument = lydict_insert(ctx->ctx, stmt->arg, 0);
+ stmt->flags |= LYS_YIN_ARGUMENT;
+ }
+
if (ext->def->plugin && ext->def->plugin->compile) {
- lysc_update_path(ctx, ext->parent_type == LYEXT_PAR_NODE ? (struct lysc_node*)ext->parent : NULL, "{extension}");
- lysc_update_path(ctx, NULL, ext_p->name );
if (ext->argument) {
lysc_update_path(ctx, (struct lysc_node*)ext, ext->argument);
}
- LY_CHECK_RET(ext->def->plugin->compile(ctx, ext_p, ext),LY_EVALID);
+ LY_CHECK_RET(ext->def->plugin->compile(ctx, ext_p, ext), LY_EVALID);
if (ext->argument) {
lysc_update_path(ctx, NULL, NULL);
}
- lysc_update_path(ctx, NULL, NULL);
- lysc_update_path(ctx, NULL, NULL);
}
+ ext_p->compiled = ext;
+
+ lysc_update_path(ctx, NULL, NULL);
+ lysc_update_path(ctx, NULL, NULL);
return LY_SUCCESS;
}
@@ -6669,6 +6709,9 @@
/* check for invalid substatements */
for (stmt = ext->child; stmt; stmt = stmt->next) {
+ if (stmt->flags & (LYS_YIN_ATTR | LYS_YIN_ARGUMENT)) {
+ continue;
+ }
for (u = 0; substmts[u].stmt; ++u) {
if (substmts[u].stmt == stmt->kw) {
break;