Merge branch 'master' into devel
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c3693af..ea1758d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -62,12 +62,12 @@
# set version of the project
set(LIBYANG_MAJOR_VERSION 2)
set(LIBYANG_MINOR_VERSION 0)
-set(LIBYANG_MICRO_VERSION 88)
+set(LIBYANG_MICRO_VERSION 92)
set(LIBYANG_VERSION ${LIBYANG_MAJOR_VERSION}.${LIBYANG_MINOR_VERSION}.${LIBYANG_MICRO_VERSION})
# set version of the library
set(LIBYANG_MAJOR_SOVERSION 2)
set(LIBYANG_MINOR_SOVERSION 8)
-set(LIBYANG_MICRO_SOVERSION 18)
+set(LIBYANG_MICRO_SOVERSION 21)
set(LIBYANG_SOVERSION_FULL ${LIBYANG_MAJOR_SOVERSION}.${LIBYANG_MINOR_SOVERSION}.${LIBYANG_MICRO_SOVERSION})
set(LIBYANG_SOVERSION ${LIBYANG_MAJOR_SOVERSION})
diff --git a/src/lyb.h b/src/lyb.h
index 687e760..165dfe5 100644
--- a/src/lyb.h
+++ b/src/lyb.h
@@ -23,6 +23,48 @@
struct ly_ctx;
struct lysc_node;
+/*
+ * LYB format
+ *
+ * Unlike XML or JSON, it is binary format so most data are represented in similar way but in binary.
+ * Some notable differences:
+ *
+ * - schema nodes are identified based on their hash instead of their string name. In case of collisions
+ * an array of hashes is created with each next hash one bit shorter until a unique sequence of all these
+ * hashes is found and then all of them are stored.
+ *
+ * - tree structure is represented as individual strictly bounded "siblings". Each "siblings" begins
+ * with its metadata, which consist of 1) the whole "sibling" length in bytes and 2) number
+ * of included metadata chunks of nested "siblings".
+ *
+ * - since length of a "sibling" is not known before it is printed, holes are first written and
+ * after the "sibling" is printed, they are filled with actual valid metadata. As a consequence,
+ * LYB data cannot be directly printed into streams!
+ *
+ * - data are preceded with information about all the used modules. It is needed because of
+ * possible augments and deviations which must be known beforehand, otherwise schema hashes
+ * could be matched to the wrong nodes.
+ *
+ * This is a short summary of the format:
+ * @verbatim
+
+ sb = siblings_start
+ se = siblings_end
+ siblings = zero-LYB_SIZE_BYTES | (sb instance+ se)
+ instance = model hash node
+ model = 16bit_zero | (model_name_length model_name revision)
+ node = opaq | leaflist | list | any | inner | leaf
+ opaq = opaq_data siblings
+ leaflist = sb leaf+ se
+ list = sb (node_header siblings)+ se
+ any = node_header anydata_data
+ inner = node_header siblings
+ leaf = node_header term_value
+ node_header = metadata node_flags
+
+ @endverbatim
+ */
+
/**
* @brief LYB format parser context
*/
@@ -52,29 +94,6 @@
*/
void lyd_lyb_ctx_free(struct lyd_ctx *lydctx);
-/**
- * LYB format
- *
- * Unlike XML or JSON, it is binary format so most data are represented in similar way but in binary.
- * Some notable differences:
- *
- * - schema nodes are identified based on their hash instead of their string name. In case of collisions
- * an array of hashes is created with each next hash one bit shorter until a unique sequence of all these
- * hashes is found and then all of them are stored.
- *
- * - tree structure is represented as individual strictly bounded "siblings". Each "siblings" begins
- * with its metadata, which consist of 1) the whole "sibling" length in bytes and 2) number
- * of included metadata chunks of nested "siblings".
- *
- * - since length of a "sibling" is not known before it is printed, holes are first written and
- * after the "sibling" is printed, they are filled with actual valid metadata. As a consequence,
- * LYB data cannot be directly printed into streams!
- *
- * - data are preceded with information about all the used modules. It is needed because of
- * possible augments and deviations which must be known beforehand, otherwise schema hashes
- * could be matched to the wrong nodes.
- */
-
/* just a shortcut */
#define LYB_LAST_SIBLING(lybctx) lybctx->siblings[LY_ARRAY_COUNT(lybctx->siblings) - 1]
@@ -82,7 +101,7 @@
#define LYB_SIBLING_STEP 4
/* current LYB format version */
-#define LYB_VERSION_NUM 0x02
+#define LYB_VERSION_NUM 0x03
/* LYB format version mask of the header byte */
#define LYB_VERSION_MASK 0x0F
diff --git a/src/parser_lyb.c b/src/parser_lyb.c
index 5e84cc1..202319b 100644
--- a/src/parser_lyb.c
+++ b/src/parser_lyb.c
@@ -195,54 +195,47 @@
* @brief Read a string.
*
* @param[in] str Destination buffer, is allocated.
- * @param[in] with_length Whether the string is preceded with its length or it ends at the end of this "sibling".
+ * @param[in] len_size Number of bytes on which the length of the string is written.
* @param[in] lybctx LYB context.
* @return LY_ERR value.
*/
static LY_ERR
-lyb_read_string(char **str, ly_bool with_length, struct lylyb_ctx *lybctx)
+lyb_read_string(char **str, uint8_t len_size, struct lylyb_ctx *lybctx)
{
- ly_bool next_chunk = 0;
- size_t len = 0, cur_len;
+ uint64_t len = 0;
+
+ assert((len_size == 1) || (len_size == 2) || (len_size == 4) || (len_size == 8));
*str = NULL;
- if (with_length) {
- lyb_read_number(&len, sizeof len, 2, lybctx);
- } else {
- /* read until the end of this "sibling" */
- len = LYB_LAST_SIBLING(lybctx).written;
- if (LYB_LAST_SIBLING(lybctx).position) {
- next_chunk = 1;
- }
- }
+ lyb_read_number(&len, sizeof len, len_size, lybctx);
*str = malloc((len + 1) * sizeof **str);
LY_CHECK_ERR_RET(!*str, LOGMEM(lybctx->ctx), LY_EMEM);
lyb_read((uint8_t *)*str, len, lybctx);
- while (next_chunk) {
- cur_len = LYB_LAST_SIBLING(lybctx).written;
- if (LYB_LAST_SIBLING(lybctx).position) {
- next_chunk = 1;
- } else {
- next_chunk = 0;
- }
-
- *str = ly_realloc(*str, (len + cur_len + 1) * sizeof **str);
- LY_CHECK_ERR_RET(!*str, LOGMEM(lybctx->ctx), LY_EMEM);
-
- lyb_read(((uint8_t *)*str) + len, cur_len, lybctx);
-
- len += cur_len;
- }
-
(*str)[len] = '\0';
return LY_SUCCESS;
}
/**
+ * @brief Skip string.
+ *
+ * @param[in] len_size Number of bytes on which the length of the string is written.
+ * @param[in] lybctx LYB context.
+ */
+static void
+lyb_skip_string(uint8_t len_size, struct lylyb_ctx *lybctx)
+{
+ size_t len = 0;
+
+ lyb_read_number(&len, sizeof len, len_size, lybctx);
+
+ lyb_read(NULL, len, lybctx);
+}
+
+/**
* @brief Read value of term node.
*
* @param[in] term Compiled term node.
@@ -254,7 +247,7 @@
* @return LY_ERR value.
*/
static LY_ERR
-lyb_read_term_value(const struct lysc_node_leaf *term, uint8_t **term_value, uint32_t *term_value_len,
+lyb_read_term_value(const struct lysc_node_leaf *term, uint8_t **term_value, uint64_t *term_value_len,
struct lylyb_ctx *lybctx)
{
uint32_t allocated_size;
@@ -438,27 +431,25 @@
/* read attributes */
for (i = 0; i < count; ++i) {
- ret = lyb_read_start_siblings(lybctx->lybctx);
- LY_CHECK_GOTO(ret, cleanup);
-
/* find model */
ret = lyb_parse_model(lybctx->lybctx, lybctx->parse_opts, &mod);
LY_CHECK_GOTO(ret, cleanup);
if (!mod) {
- /* skip it */
- do {
- lyb_read(NULL, LYB_LAST_SIBLING(lybctx->lybctx).written, lybctx->lybctx);
- } while (LYB_LAST_SIBLING(lybctx->lybctx).written);
- goto stop_sibling;
+ /* skip meta name */
+ lyb_skip_string(sizeof(uint16_t), lybctx->lybctx);
+
+ /* skip meta value */
+ lyb_skip_string(sizeof(uint16_t), lybctx->lybctx);
+ continue;
}
/* meta name */
- ret = lyb_read_string(&meta_name, 1, lybctx->lybctx);
+ ret = lyb_read_string(&meta_name, sizeof(uint16_t), lybctx->lybctx);
LY_CHECK_GOTO(ret, cleanup);
/* meta value */
- ret = lyb_read_string(&meta_value, 0, lybctx->lybctx);
+ ret = lyb_read_string(&meta_value, sizeof(uint64_t), lybctx->lybctx);
LY_CHECK_GOTO(ret, cleanup);
dynamic = 1;
@@ -475,10 +466,6 @@
}
LY_CHECK_GOTO(ret, cleanup);
-
-stop_sibling:
- ret = lyb_read_stop_siblings(lybctx->lybctx);
- LY_CHECK_GOTO(ret, cleanup);
}
cleanup:
@@ -521,10 +508,10 @@
ns = calloc(1, sizeof *ns);
/* prefix */
- LY_CHECK_GOTO(ret = lyb_read_string(&ns->prefix, 1, lybctx), cleanup);
+ LY_CHECK_GOTO(ret = lyb_read_string(&ns->prefix, sizeof(uint16_t), lybctx), cleanup);
/* namespace */
- LY_CHECK_GOTO(ret = lyb_read_string(&ns->uri, 1, lybctx), cleanup);
+ LY_CHECK_GOTO(ret = lyb_read_string(&ns->uri, sizeof(uint16_t), lybctx), cleanup);
LY_CHECK_GOTO(ret = ly_set_add(set, ns, 1, NULL), cleanup);
ns = NULL;
@@ -577,11 +564,8 @@
/* read attributes */
for (i = 0; i < count; ++i) {
- ret = lyb_read_start_siblings(lybctx);
- LY_CHECK_GOTO(ret, cleanup);
-
/* prefix, may be empty */
- ret = lyb_read_string(&prefix, 1, lybctx);
+ ret = lyb_read_string(&prefix, sizeof(uint16_t), lybctx);
LY_CHECK_GOTO(ret, cleanup);
if (!prefix[0]) {
free(prefix);
@@ -589,7 +573,7 @@
}
/* namespace, may be empty */
- ret = lyb_read_string(&module_name, 1, lybctx);
+ ret = lyb_read_string(&module_name, sizeof(uint16_t), lybctx);
LY_CHECK_GOTO(ret, cleanup);
if (!module_name[0]) {
free(module_name);
@@ -597,7 +581,7 @@
}
/* name */
- ret = lyb_read_string(&name, 1, lybctx);
+ ret = lyb_read_string(&name, sizeof(uint16_t), lybctx);
LY_CHECK_GOTO(ret, cleanup);
/* format */
@@ -608,7 +592,7 @@
LY_CHECK_GOTO(ret, cleanup);
/* value */
- ret = lyb_read_string(&value, 0, lybctx);
+ ret = lyb_read_string(&value, sizeof(uint64_t), lybctx);
LY_CHECK_ERR_GOTO(ret, ly_free_prefix_data(format, val_prefix_data), cleanup);
dynamic = 1;
@@ -630,7 +614,6 @@
*attr = attr2;
}
- ret = lyb_read_stop_siblings(lybctx);
LY_CHECK_GOTO(ret, cleanup);
}
@@ -977,7 +960,7 @@
LY_ERR ret;
ly_bool dynamic;
uint8_t *term_value;
- uint32_t term_value_len;
+ uint64_t term_value_len;
ret = lyb_read_term_value((struct lysc_node_leaf *)snode, &term_value, &term_value_len, lybctx->lybctx);
LY_CHECK_RET(ret);
@@ -1059,19 +1042,19 @@
lyb_read_number(&flags, sizeof flags, sizeof flags, lybctx->lybctx);
/* parse prefix */
- ret = lyb_read_string(&prefix, 1, lybctx->lybctx);
+ ret = lyb_read_string(&prefix, sizeof(uint16_t), lybctx->lybctx);
LY_CHECK_GOTO(ret, cleanup);
/* parse module key */
- ret = lyb_read_string(&module_key, 1, lybctx->lybctx);
+ ret = lyb_read_string(&module_key, sizeof(uint16_t), lybctx->lybctx);
LY_CHECK_GOTO(ret, cleanup);
/* parse name */
- ret = lyb_read_string(&name, 1, lybctx->lybctx);
+ ret = lyb_read_string(&name, sizeof(uint16_t), lybctx->lybctx);
LY_CHECK_GOTO(ret, cleanup);
/* parse value */
- ret = lyb_read_string(&value, 1, lybctx->lybctx);
+ ret = lyb_read_string(&value, sizeof(uint64_t), lybctx->lybctx);
LY_CHECK_ERR_GOTO(ret, ly_free_prefix_data(format, val_prefix_data), cleanup);
dynamic = 1;
@@ -1161,7 +1144,7 @@
}
/* read anydata content */
- ret = lyb_read_string(&value, 1, lybctx->lybctx);
+ ret = lyb_read_string(&value, sizeof(uint64_t), lybctx->lybctx);
LY_CHECK_GOTO(ret, error);
if (value_type == LYD_ANYDATA_LYB) {
diff --git a/src/plugins_types/integer.c b/src/plugins_types/integer.c
index cca3a23..5a50306 100644
--- a/src/plugins_types/integer.c
+++ b/src/plugins_types/integer.c
@@ -98,19 +98,23 @@
LY_CHECK_GOTO(ret, cleanup);
}
- /* set the value, matters for big-endian */
+ /* set the value (matters for big-endian) and get the correct int64 number */
switch (type->basetype) {
case LY_TYPE_INT8:
storage->int8 = num;
+ num = storage->int8;
break;
case LY_TYPE_INT16:
storage->int16 = num;
+ num = storage->int16;
break;
case LY_TYPE_INT32:
storage->int32 = num;
+ num = storage->int32;
break;
case LY_TYPE_INT64:
storage->int64 = num;
+ num = storage->int64;
break;
default:
break;
diff --git a/src/printer_lyb.c b/src/printer_lyb.c
index 26f33d2..846c5e2 100644
--- a/src/printer_lyb.c
+++ b/src/printer_lyb.c
@@ -239,9 +239,9 @@
uint64_t num = 0;
/* write the meta chunk information */
- num = htole64(sib->written & LYB_SIZE_MAX);
+ num = htole64((uint64_t)sib->written & LYB_SIZE_MAX);
memcpy(meta_buf, &num, LYB_SIZE_BYTES);
- num = htole64(sib->inner_chunks & LYB_INCHUNK_MAX);
+ num = htole64((uint64_t)sib->inner_chunks & LYB_INCHUNK_MAX);
memcpy(meta_buf + LYB_SIZE_BYTES, &num, LYB_INCHUNK_BYTES);
LY_CHECK_RET(ly_write_skipped(out, sib->position, (char *)&meta_buf, LYB_META_BYTES));
@@ -397,30 +397,47 @@
*
* @param[in] str String to write.
* @param[in] str_len Length of @p str.
- * @param[in] with_length Whether to precede the string with its length.
+ * @param[in] len_size Size of @ str_len in bytes.
* @param[in] out Out structure.
* @param[in] lybctx LYB context.
* @return LY_ERR value.
*/
static LY_ERR
-lyb_write_string(const char *str, size_t str_len, ly_bool with_length, struct ly_out *out, struct lylyb_ctx *lybctx)
+lyb_write_string(const char *str, size_t str_len, uint8_t len_size, struct ly_out *out, struct lylyb_ctx *lybctx)
{
+ ly_bool error;
+
if (!str) {
str = "";
LY_CHECK_ERR_RET(str_len, LOGINT(lybctx->ctx), LY_EINT);
}
+
if (!str_len) {
str_len = strlen(str);
}
- if (with_length) {
- /* print length on 2 bytes */
- if (str_len > UINT16_MAX) {
- LOGINT(lybctx->ctx);
- return LY_EINT;
- }
- LY_CHECK_RET(lyb_write_number(str_len, 2, out, lybctx));
+ switch (len_size) {
+ case sizeof(uint8_t):
+ error = str_len > UINT8_MAX;
+ break;
+ case sizeof(uint16_t):
+ error = str_len > UINT16_MAX;
+ break;
+ case sizeof(uint32_t):
+ error = str_len > UINT32_MAX;
+ break;
+ case sizeof(uint64_t):
+ error = str_len > UINT64_MAX;
+ break;
+ default:
+ error = 1;
}
+ if (error) {
+ LOGINT(lybctx->ctx);
+ return LY_EINT;
+ }
+
+ LY_CHECK_RET(lyb_write_number(str_len, len_size, out, lybctx));
LY_CHECK_RET(lyb_write(out, (const uint8_t *)str, str_len, lybctx));
@@ -442,7 +459,7 @@
/* model name length and model name */
if (mod) {
- LY_CHECK_RET(lyb_write_string(mod->name, 0, 1, out, lybctx));
+ LY_CHECK_RET(lyb_write_string(mod->name, 0, sizeof(uint16_t), out, lybctx));
} else {
lyb_write_number(0, 2, out, lybctx);
return LY_SUCCESS;
@@ -610,10 +627,10 @@
ns = set->objs[i];
/* prefix */
- LY_CHECK_RET(lyb_write_string(ns->prefix, 0, 1, out, lybctx));
+ LY_CHECK_RET(lyb_write_string(ns->prefix, 0, sizeof(uint16_t), out, lybctx));
/* namespace */
- LY_CHECK_RET(lyb_write_string(ns->uri, 0, 1, out, lybctx));
+ LY_CHECK_RET(lyb_write_string(ns->uri, 0, sizeof(uint16_t), out, lybctx));
}
break;
case LY_VALUE_JSON:
@@ -668,8 +685,8 @@
goto cleanup;
}
- /* Print the length of the data as 32-bit unsigned integer. */
- ret = lyb_write_number(value_len, sizeof(uint32_t), out, lybctx);
+ /* Print the length of the data as 64-bit unsigned integer. */
+ ret = lyb_write_number(value_len, sizeof(uint64_t), out, lybctx);
LY_CHECK_GOTO(ret, cleanup);
} else {
/* Fixed-length data. */
@@ -739,29 +756,21 @@
if (wd_mod) {
/* write the "default" metadata */
- LY_CHECK_RET(lyb_write_start_siblings(out, lybctx->lybctx));
LY_CHECK_RET(lyb_print_model(out, wd_mod, lybctx->lybctx));
- LY_CHECK_RET(lyb_write_string("default", 0, 1, out, lybctx->lybctx));
- LY_CHECK_RET(lyb_write_string("true", 0, 0, out, lybctx->lybctx));
- LY_CHECK_RET(lyb_write_stop_siblings(out, lybctx->lybctx));
+ LY_CHECK_RET(lyb_write_string("default", 0, sizeof(uint16_t), out, lybctx->lybctx));
+ LY_CHECK_RET(lyb_write_string("true", 0, sizeof(uint16_t), out, lybctx->lybctx));
}
/* write all the node metadata */
LY_LIST_FOR(node->meta, iter) {
- /* each metadata is a sibling */
- LY_CHECK_RET(lyb_write_start_siblings(out, lybctx->lybctx));
-
/* model */
LY_CHECK_RET(lyb_print_model(out, iter->annotation->module, lybctx->lybctx));
/* annotation name with length */
- LY_CHECK_RET(lyb_write_string(iter->name, 0, 1, out, lybctx->lybctx));
+ LY_CHECK_RET(lyb_write_string(iter->name, 0, sizeof(uint16_t), out, lybctx->lybctx));
/* metadata value */
- LY_CHECK_RET(lyb_write_string(lyd_get_meta_value(iter), 0, 0, out, lybctx->lybctx));
-
- /* finish metadata sibling */
- LY_CHECK_RET(lyb_write_stop_siblings(out, lybctx->lybctx));
+ LY_CHECK_RET(lyb_write_string(lyd_get_meta_value(iter), 0, sizeof(uint64_t), out, lybctx->lybctx));
}
return LY_SUCCESS;
@@ -794,17 +803,14 @@
/* write all the attributes */
LY_LIST_FOR(node->attr, iter) {
- /* each attribute is a sibling */
- LY_CHECK_RET(lyb_write_start_siblings(out, lybctx));
-
/* prefix */
- LY_CHECK_RET(lyb_write_string(iter->name.prefix, 0, 1, out, lybctx));
+ LY_CHECK_RET(lyb_write_string(iter->name.prefix, 0, sizeof(uint16_t), out, lybctx));
/* namespace */
- LY_CHECK_RET(lyb_write_string(iter->name.module_name, 0, 1, out, lybctx));
+ LY_CHECK_RET(lyb_write_string(iter->name.module_name, 0, sizeof(uint16_t), out, lybctx));
/* name */
- LY_CHECK_RET(lyb_write_string(iter->name.name, 0, 1, out, lybctx));
+ LY_CHECK_RET(lyb_write_string(iter->name.name, 0, sizeof(uint16_t), out, lybctx));
/* format */
LY_CHECK_RET(lyb_write_number(iter->format, 1, out, lybctx));
@@ -813,10 +819,7 @@
LY_CHECK_RET(lyb_print_prefix_data(out, iter->format, iter->val_prefix_data, lybctx));
/* value */
- LY_CHECK_RET(lyb_write_string(iter->value, 0, 0, out, lybctx));
-
- /* finish attribute sibling */
- LY_CHECK_RET(lyb_write_stop_siblings(out, lybctx));
+ LY_CHECK_RET(lyb_write_string(iter->value, 0, sizeof(uint64_t), out, lybctx));
}
return LY_SUCCESS;
@@ -959,16 +962,16 @@
LY_CHECK_RET(lyb_write_number(opaq->flags, sizeof opaq->flags, out, lybctx));
/* prefix */
- LY_CHECK_RET(lyb_write_string(opaq->name.prefix, 0, 1, out, lybctx));
+ LY_CHECK_RET(lyb_write_string(opaq->name.prefix, 0, sizeof(uint16_t), out, lybctx));
/* module reference */
- LY_CHECK_RET(lyb_write_string(opaq->name.module_name, 0, 1, out, lybctx));
+ LY_CHECK_RET(lyb_write_string(opaq->name.module_name, 0, sizeof(uint16_t), out, lybctx));
/* name */
- LY_CHECK_RET(lyb_write_string(opaq->name.name, 0, 1, out, lybctx));
+ LY_CHECK_RET(lyb_write_string(opaq->name.name, 0, sizeof(uint16_t), out, lybctx));
/* value */
- LY_CHECK_RET(lyb_write_string(opaq->value, 0, 1, out, lybctx));
+ LY_CHECK_RET(lyb_write_string(opaq->value, 0, sizeof(uint64_t), out, lybctx));
/* format */
LY_CHECK_RET(lyb_write_number(opaq->format, 1, out, lybctx));
@@ -1032,7 +1035,7 @@
}
/* followed by the content */
- LY_CHECK_GOTO(ret = lyb_write_string(str, (size_t)len, 1, out, lybctx), cleanup);
+ LY_CHECK_GOTO(ret = lyb_write_string(str, (size_t)len, sizeof(uint64_t), out, lybctx), cleanup);
cleanup:
ly_out_free(out2, NULL, 1);
@@ -1185,24 +1188,6 @@
/**
* @brief Print siblings.
*
- * @verbatim
-
- sb = siblings_start
- se = siblings_end
- siblings = zero-LYB_SIZE_BYTES | (sb instance+ se)
- instance = model hash node
- model = 16bit_zero | (model_name_length model_name revision)
- node = opaq | leaflist | list | any | inner | leaf
- opaq = opaq_data siblings
- leaflist = sb leaf+ se
- list = sb (node_header siblings)+ se
- any = node_header anydata_data
- inner = node_header siblings
- leaf = node_header term_value
- node_header = metadata node_flags
-
- @endverbatim
- *
* @param[in] out Out structure.
* @param[in] node Current data node to print.
* @param[in] lybctx LYB context.
diff --git a/src/xpath.c b/src/xpath.c
index 9f4d173..9491ddb 100644
--- a/src/xpath.c
+++ b/src/xpath.c
@@ -1211,9 +1211,8 @@
set->val.nodes[idx].pos = pos;
++set->used;
- if (set->val.nodes[idx].type == LYXP_NODE_ELEM) {
- set_insert_node_hash(set, (struct lyd_node *)node, node_type);
- }
+ /* add into hash table */
+ set_insert_node_hash(set, (struct lyd_node *)node, node_type);
}
LY_ERR
diff --git a/tools/lint/main_ni.c b/tools/lint/main_ni.c
index 2900a3f..f63e97a 100644
--- a/tools/lint/main_ni.c
+++ b/tools/lint/main_ni.c
@@ -63,6 +63,7 @@
/* specification of printing schema node subtree, option --schema-node */
const char *schema_node_path;
const struct lysc_node *schema_node;
+ const char *submodule;
/* value of --format in case of schema format */
LYS_OUTFORMAT schema_out_format;
@@ -133,22 +134,16 @@
" -v, --version Show version number and exit.\n"
" -V, --verbose Show verbose messages, can be used multiple times to\n"
" increase verbosity.\n");
-#ifndef NDEBUG
- printf(" -G GROUPS, --debug=GROUPS\n"
- " Enable printing of specific debugging message group\n"
- " (nothing will be printed unless verbosity is set to debug):\n"
- " <group>[,<group>]* (dict, xpath)\n\n");
-#endif
- printf(" -d MODE, --default=MODE\n"
- " Print data with default values, according to the MODE\n"
- " (to print attributes, ietf-netconf-with-defaults model\n"
- " must be loaded):\n"
- " all - Add missing default nodes.\n"
- " all-tagged - Add missing default nodes and mark all the default\n"
- " nodes with the attribute.\n"
- " trim - Remove all nodes with a default value.\n"
- " implicit-tagged - Add missing nodes and mark them with the attribute.\n\n");
+ printf(" -f FORMAT, --format=FORMAT\n"
+ " Convert input into FORMAT. Supported formats: \n"
+ " yang, yin, tree and info for schemas,\n"
+ " xml, json for data.\n\n");
+
+ printf(" -p PATH, --path=PATH\n"
+ " Search path for schema (YANG/YIN) modules. The option can be\n"
+ " used multiple times. The current working directory and the\n"
+ " path of the module being added is used implicitly.\n\n");
printf(" -D, --disable-searchdir\n"
" Do not implicitly search in current working directory for\n"
@@ -156,11 +151,6 @@
" search in the module directory (all modules must be \n"
" explicitly specified).\n\n");
- printf(" -p PATH, --path=PATH\n"
- " Search path for schema (YANG/YIN) modules. The option can be\n"
- " used multiple times. The current working directory and the\n"
- " path of the module being added is used implicitly.\n\n");
-
printf(" -F FEATURES, --features=FEATURES\n"
" Features to support, default all.\n"
" <modname>:[<feature>,]*\n\n");
@@ -170,23 +160,6 @@
" module also implemented. If specified a second time, all the\n"
" modules are set implemented.\n\n");
- printf(" -l, --list Print info about the loaded schemas.\n"
- " (i - imported module, I - implemented module)\n"
- " In case the -f option with data encoding is specified,\n"
- " the list is printed as ietf-yang-library data.\n\n");
-
- printf(" -L LINE_LENGTH, --tree-line-length=LINE_LENGTH\n"
- " The limit of the maximum line length on which the 'tree'\n"
- " format will try to be printed.\n\n");
-
- printf(" -o OUTFILE, --output=OUTFILE\n"
- " Write the output to OUTFILE instead of stdout.\n\n");
-
- printf(" -f FORMAT, --format=FORMAT\n"
- " Convert input into FORMAT. Supported formats: \n"
- " yang, yin, tree and info for schemas,\n"
- " xml, json for data.\n\n");
-
printf(" -P PATH, --schema-node=PATH\n"
" Print only the specified subtree of the schema.\n"
" The PATH is the XPath subset mentioned in documentation as\n"
@@ -196,6 +169,9 @@
" Supplement to the --schema-node option to print information\n"
" only about a single node specified as PATH argument.\n\n");
+ printf(" -s SUBMODULE, --submodule=SUBMODULE\n"
+ " Print the specific submodule instead of the main module.\n\n");
+
printf(" -n, --not-strict\n"
" Do not require strict data parsing (silently skip unknown data),\n"
" has no effect for schemas.\n\n");
@@ -220,7 +196,29 @@
" RPC/Action. This is necessary to identify appropriate\n"
" data definitions in the schema module.\n"
" notif - Notification instance (content of the <notification>\n"
- " element without <eventTime>).\n");
+ " element without <eventTime>).\n\n");
+
+ printf(" -d MODE, --default=MODE\n"
+ " Print data with default values, according to the MODE\n"
+ " (to print attributes, ietf-netconf-with-defaults model\n"
+ " must be loaded):\n"
+ " all - Add missing default nodes.\n"
+ " all-tagged - Add missing default nodes and mark all the default\n"
+ " nodes with the attribute.\n"
+ " trim - Remove all nodes with a default value.\n"
+ " implicit-tagged - Add missing nodes and mark them with the attribute.\n\n");
+
+ printf(" -l, --list Print info about the loaded schemas.\n"
+ " (i - imported module, I - implemented module)\n"
+ " In case the -f option with data encoding is specified,\n"
+ " the list is printed as ietf-yang-library data.\n\n");
+
+ printf(" -L LINE_LENGTH, --tree-line-length=LINE_LENGTH\n"
+ " The limit of the maximum line length on which the 'tree'\n"
+ " format will try to be printed.\n\n");
+
+ printf(" -o OUTFILE, --output=OUTFILE\n"
+ " Write the output to OUTFILE instead of stdout.\n\n");
printf(" -O FILE, --operational=FILE\n"
" Provide optional data to extend validation of the 'rpc',\n"
@@ -235,6 +233,13 @@
" Load and implement internal \"ietf-yang-library\" YANG module.\n"
" Note that this module includes definitions of mandatory state\n"
" data that can result in unexpected data validation errors.\n\n");
+
+#ifndef NDEBUG
+ printf(" -G GROUPS, --debug=GROUPS\n"
+ " Enable printing of specific debugging message group\n"
+ " (nothing will be printed unless verbosity is set to debug):\n"
+ " <group>[,<group>]* (dict, xpath)\n\n");
+#endif
}
static void
@@ -356,29 +361,30 @@
int opt, opt_index;
struct option options[] = {
- {"default", required_argument, NULL, 'd'},
- {"disable-searchdir", no_argument, NULL, 'D'},
- {"present", no_argument, NULL, 'e'},
+ {"help", no_argument, NULL, 'h'},
+ {"version", no_argument, NULL, 'v'},
+ {"verbose", no_argument, NULL, 'V'},
{"format", required_argument, NULL, 'f'},
+ {"path", required_argument, NULL, 'p'},
+ {"disable-searchdir", no_argument, NULL, 'D'},
{"features", required_argument, NULL, 'F'},
+ {"makeimplemented", no_argument, NULL, 'i'},
+ {"schema-node", required_argument, NULL, 'P'},
+ {"single-node", no_argument, NULL, 'q'},
+ {"submodule", required_argument, NULL, 's'},
+ {"not-strict", no_argument, NULL, 'n'},
+ {"present", no_argument, NULL, 'e'},
+ {"type", required_argument, NULL, 't'},
+ {"default", required_argument, NULL, 'd'},
+ {"list", no_argument, NULL, 'l'},
+ {"tree-line-length", required_argument, NULL, 'L'},
+ {"output", required_argument, NULL, 'o'},
+ {"operational", required_argument, NULL, 'O'},
+ {"merge", no_argument, NULL, 'm'},
+ {"yang-library", no_argument, NULL, 'y'},
#ifndef NDEBUG
{"debug", required_argument, NULL, 'G'},
#endif
- {"help", no_argument, NULL, 'h'},
- {"makeimplemented", no_argument, NULL, 'i'},
- {"list", no_argument, NULL, 'l'},
- {"tree-line-length", required_argument, NULL, 'L'},
- {"merge", no_argument, NULL, 'm'},
- {"yang-library", no_argument, NULL, 'y'},
- {"output", required_argument, NULL, 'o'},
- {"operational", required_argument, NULL, 'O'},
- {"path", required_argument, NULL, 'p'},
- {"schema-node", required_argument, NULL, 'P'},
- {"single-node", no_argument, NULL, 'q'},
- {"not-strict", no_argument, NULL, 'n'},
- {"type", required_argument, NULL, 't'},
- {"version", no_argument, NULL, 'v'},
- {"verbose", no_argument, NULL, 'V'},
{NULL, 0, NULL, 0}
};
@@ -389,93 +395,28 @@
c->line_length = 0;
#ifndef NDEBUG
- while ((opt = getopt_long(argc, argv, "d:Def:F:hilL:myo:p:P:qnt:vV", options, &opt_index)) != -1) {
+ while ((opt = getopt_long(argc, argv, "hvVf:p:DF:iP:qs:net:d:lL:o:Omy", options, &opt_index)) != -1) {
#else
- while ((opt = getopt_long(argc, argv, "d:Def:F:G:hilL:myo:p:P:qnt:vV", options, &opt_index)) != -1) {
+ while ((opt = getopt_long(argc, argv, "hvVf:p:DF:iP:qs:net:d:lL:o:OmyG:", options, &opt_index)) != -1) {
#endif
switch (opt) {
- case 'd': /* --default */
- if (!strcasecmp(optarg, "all")) {
- c->data_print_options = (c->data_print_options & ~LYD_PRINT_WD_MASK) | LYD_PRINT_WD_ALL;
- } else if (!strcasecmp(optarg, "all-tagged")) {
- c->data_print_options = (c->data_print_options & ~LYD_PRINT_WD_MASK) | LYD_PRINT_WD_ALL_TAG;
- } else if (!strcasecmp(optarg, "trim")) {
- c->data_print_options = (c->data_print_options & ~LYD_PRINT_WD_MASK) | LYD_PRINT_WD_TRIM;
- } else if (!strcasecmp(optarg, "implicit-tagged")) {
- c->data_print_options = (c->data_print_options & ~LYD_PRINT_WD_MASK) | LYD_PRINT_WD_IMPL_TAG;
- } else {
- YLMSG_E("Unknown default mode %s\n", optarg);
- help(1);
- return -1;
+ case 'h': /* --help */
+ help(0);
+ return 1;
+
+ case 'v': /* --version */
+ version();
+ return 1;
+
+ case 'V': { /* --verbose */
+ LY_LOG_LEVEL verbosity = ly_log_level(LY_LLERR);
+ ly_log_level(verbosity);
+
+ if (verbosity < LY_LLDBG) {
+ ly_log_level(verbosity + 1);
}
break;
-
- case 'D': /* --disable-search */
- if (options_ctx & LY_CTX_DISABLE_SEARCHDIRS) {
- YLMSG_W("The -D option specified too many times.\n");
- }
- if (options_ctx & LY_CTX_DISABLE_SEARCHDIR_CWD) {
- options_ctx &= ~LY_CTX_DISABLE_SEARCHDIR_CWD;
- options_ctx |= LY_CTX_DISABLE_SEARCHDIRS;
- } else {
- options_ctx |= LY_CTX_DISABLE_SEARCHDIR_CWD;
- }
- break;
-
- case 'p': { /* --path */
- struct stat st;
-
- if (stat(optarg, &st) == -1) {
- YLMSG_E("Unable to use search path (%s) - %s.\n", optarg, strerror(errno));
- return -1;
- }
- if (!S_ISDIR(st.st_mode)) {
- YLMSG_E("Provided search path is not a directory.\n");
- return -1;
- }
-
- if (ly_set_add(&c->searchpaths, optarg, 0, NULL)) {
- YLMSG_E("Storing searchpath failed.\n");
- return -1;
- }
-
- break;
- } /* case 'p' */
-
- case 'i': /* --makeimplemented */
- if (options_ctx & LY_CTX_REF_IMPLEMENTED) {
- options_ctx &= ~LY_CTX_REF_IMPLEMENTED;
- options_ctx |= LY_CTX_ALL_IMPLEMENTED;
- } else {
- options_ctx |= LY_CTX_REF_IMPLEMENTED;
- }
- break;
-
- case 'F': /* --features */
- if (parse_features(optarg, &c->schema_features)) {
- return -1;
- }
- break;
-
- case 'l': /* --list */
- c->list = 1;
- break;
-
- case 'L': /* --tree-line-length */
- c->line_length = atoi(optarg);
- break;
-
- case 'o': /* --output */
- if (c->out) {
- YLMSG_E("Only a single output can be specified.\n");
- return -1;
- } else {
- if (ly_out_new_filepath(optarg, &c->out)) {
- YLMSG_E("Unable open output file %s (%s)\n", optarg, strerror(errno));
- return -1;
- }
- }
- break;
+ } /* case 'V' */
case 'f': /* --format */
if (!strcasecmp(optarg, "yang")) {
@@ -503,6 +444,53 @@
}
break;
+ case 'p': { /* --path */
+ struct stat st;
+
+ if (stat(optarg, &st) == -1) {
+ YLMSG_E("Unable to use search path (%s) - %s.\n", optarg, strerror(errno));
+ return -1;
+ }
+ if (!S_ISDIR(st.st_mode)) {
+ YLMSG_E("Provided search path is not a directory.\n");
+ return -1;
+ }
+
+ if (ly_set_add(&c->searchpaths, optarg, 0, NULL)) {
+ YLMSG_E("Storing searchpath failed.\n");
+ return -1;
+ }
+
+ break;
+ } /* case 'p' */
+
+ case 'D': /* --disable-search */
+ if (options_ctx & LY_CTX_DISABLE_SEARCHDIRS) {
+ YLMSG_W("The -D option specified too many times.\n");
+ }
+ if (options_ctx & LY_CTX_DISABLE_SEARCHDIR_CWD) {
+ options_ctx &= ~LY_CTX_DISABLE_SEARCHDIR_CWD;
+ options_ctx |= LY_CTX_DISABLE_SEARCHDIRS;
+ } else {
+ options_ctx |= LY_CTX_DISABLE_SEARCHDIR_CWD;
+ }
+ break;
+
+ case 'F': /* --features */
+ if (parse_features(optarg, &c->schema_features)) {
+ return -1;
+ }
+ break;
+
+ case 'i': /* --makeimplemented */
+ if (options_ctx & LY_CTX_REF_IMPLEMENTED) {
+ options_ctx &= ~LY_CTX_REF_IMPLEMENTED;
+ options_ctx |= LY_CTX_ALL_IMPLEMENTED;
+ } else {
+ options_ctx |= LY_CTX_REF_IMPLEMENTED;
+ }
+ break;
+
case 'P': /* --schema-node */
c->schema_node_path = optarg;
break;
@@ -511,6 +499,10 @@
c->schema_print_options |= LYS_PRINT_NO_SUBSTMT;
break;
+ case 's': /* --submodule */
+ c->submodule = optarg;
+ break;
+
case 'n': /* --not-strict */
c->data_parse_options &= ~LYD_PARSE_STRICT;
break;
@@ -551,6 +543,42 @@
data_type_set = 1;
break;
+ case 'd': /* --default */
+ if (!strcasecmp(optarg, "all")) {
+ c->data_print_options = (c->data_print_options & ~LYD_PRINT_WD_MASK) | LYD_PRINT_WD_ALL;
+ } else if (!strcasecmp(optarg, "all-tagged")) {
+ c->data_print_options = (c->data_print_options & ~LYD_PRINT_WD_MASK) | LYD_PRINT_WD_ALL_TAG;
+ } else if (!strcasecmp(optarg, "trim")) {
+ c->data_print_options = (c->data_print_options & ~LYD_PRINT_WD_MASK) | LYD_PRINT_WD_TRIM;
+ } else if (!strcasecmp(optarg, "implicit-tagged")) {
+ c->data_print_options = (c->data_print_options & ~LYD_PRINT_WD_MASK) | LYD_PRINT_WD_IMPL_TAG;
+ } else {
+ YLMSG_E("Unknown default mode %s\n", optarg);
+ help(1);
+ return -1;
+ }
+ break;
+
+ case 'l': /* --list */
+ c->list = 1;
+ break;
+
+ case 'L': /* --tree-line-length */
+ c->line_length = atoi(optarg);
+ break;
+
+ case 'o': /* --output */
+ if (c->out) {
+ YLMSG_E("Only a single output can be specified.\n");
+ return -1;
+ } else {
+ if (ly_out_new_filepath(optarg, &c->out)) {
+ YLMSG_E("Unable open output file %s (%s)\n", optarg, strerror(errno));
+ return -1;
+ }
+ }
+ break;
+
case 'O': /* --operational */
if (c->data_operational.path) {
YLMSG_E("The operational datastore (-O) cannot be set multiple times.\n");
@@ -567,24 +595,6 @@
options_ctx &= ~LY_CTX_NO_YANGLIBRARY;
break;
- case 'h': /* --help */
- help(0);
- return 1;
-
- case 'v': /* --version */
- version();
- return 1;
-
- case 'V': { /* --verbose */
- LY_LOG_LEVEL verbosity = ly_log_level(LY_LLERR);
- ly_log_level(verbosity);
-
- if (verbosity < LY_LLDBG) {
- ly_log_level(verbosity + 1);
- }
- break;
- } /* case 'V' */
-
#ifndef NDEBUG
case 'G': { /* --debug */
uint32_t dbg_groups = 0;
@@ -729,6 +739,18 @@
YLMSG_E("Unable to print schema node %s.\n", c.schema_node_path);
goto cleanup;
}
+ } else if (c.submodule) {
+ const struct lysp_submodule *submod = ly_ctx_get_submodule_latest(c.ctx, c.submodule);
+ if (!submod) {
+ YLMSG_E("Unable to find submodule %s.\n", c.submodule);
+ goto cleanup;
+ }
+
+ ret = lys_print_submodule(c.out, submod, c.schema_out_format, c.line_length, c.schema_print_options);
+ if (ret) {
+ YLMSG_E("Unable to print submodule %s.\n", submod->name);
+ goto cleanup;
+ }
} else {
for (uint32_t u = 0; u < c.schema_modules.count; ++u) {
ret = lys_print_module(c.out, (struct lys_module *)c.schema_modules.objs[u], c.schema_out_format,