yanglint UPDATE choise/case completion
yanglint print -f info -P now supports choice and case schema nodes.
diff --git a/tools/lint/common.c b/tools/lint/common.c
index 9033b9d..4d1f60f 100644
--- a/tools/lint/common.c
+++ b/tools/lint/common.c
@@ -781,3 +781,89 @@
ly_set_free(set, NULL);
return ret;
}
+
+const struct lysc_node *
+find_schema_path(const struct ly_ctx *ctx, const char *schema_path)
+{
+ const char *end, *module_name_end;
+ char *module_name = NULL;
+ const struct lysc_node *node = NULL, *parent_node = NULL, *parent_node_tmp;
+ const struct lys_module *module;
+ size_t node_name_len;
+ ly_bool found_exact_match = 0;
+
+ /* iterate over each '/' in the path */
+ while (schema_path) {
+ /* example: schema_path = /listen/endpoint
+ * end == NULL for endpoint, end exists for listen */
+ end = strchr(schema_path + 1, '/');
+ if (end) {
+ node_name_len = end - schema_path - 1;
+ } else {
+ node_name_len = strlen(schema_path + 1);
+ }
+
+ /* ex: schema_path = /ietf-interfaces:interfaces/interface/ietf-ip:ipv4 */
+ module_name_end = strchr(schema_path, ':');
+ if (module_name_end) {
+ if (!end || (module_name_end < end)) {
+ /* only get module's name, if it is in the current scope */
+ free(module_name);
+ module_name = strndup(schema_path + 1, module_name_end - schema_path - 1);
+ if (!module_name) {
+ YLMSG_E("Memory allocation failed (%s:%d, %s)", __FILE__, __LINE__, strerror(errno));
+ parent_node = NULL;
+ goto cleanup;
+ }
+ schema_path = module_name_end;
+ }
+
+ if (module_name_end < end) {
+ /* recalculate the length of the node's name, because the module prefix mustn't be compared later */
+ if (end) {
+ node_name_len = end - module_name_end - 1;
+ } else {
+ node_name_len = strlen(module_name_end + 1);
+ }
+ }
+ }
+
+ module = ly_ctx_get_module_implemented(ctx, module_name);
+ if (!module) {
+ /* unknown module name */
+ parent_node = NULL;
+ goto cleanup;
+ }
+
+ /* iterate over the node's siblings / module's top level containers */
+ while ((node = lys_getnext(node, parent_node, module->compiled, LYS_GETNEXT_WITHCASE | LYS_GETNEXT_WITHCHOICE))) {
+ if (end && !strncmp(node->name, schema_path + 1, node_name_len) && (node->name[node_name_len] == '\0')) {
+ /* check if the whole node's name matches and it's not just a common prefix */
+ parent_node = node;
+ break;
+ } else if (!strncmp(node->name, schema_path + 1, node_name_len)) {
+ /* do the same here, however if there is no exact match, use the last node with the same prefix */
+ if (strlen(node->name) == node_name_len) {
+ parent_node = node;
+ found_exact_match = 1;
+ break;
+ } else {
+ parent_node_tmp = node;
+ }
+ }
+ }
+
+ if (!end && !found_exact_match) {
+ /* no exact match */
+ parent_node = parent_node_tmp;
+ }
+ found_exact_match = 0;
+
+ /* next iter */
+ schema_path = strchr(schema_path + 1, '/');
+ }
+
+cleanup:
+ free(module_name);
+ return parent_node;
+}