* Renamed clixon-clispec.yang to clixon-autocli.yang
* First version of clixon-autocli.yang semantics * Default rules for module exclusion, list-keywords, completion, treeref-state * Specialized rules for compress and exclusion of modules * See [autocli documentation](https://clixon-docs.readthedocs.io/en/latest/cli.html#autocli) * Obsoleted and moved autocli config options from clixon-config.yang to clixon-autocli.yang as follows: * `CLICON_CLI_GENMODEL`, use: `autocli/module-default=false` instead * Removed `clicon_cli_genmodel()` * `CLICON_CLI_GENMODEL_TYPE`, use `autocli/list-keyword-default` and compress rules instead) * Removed `clicon_cli_genmodel_type()` * `CLICON_CLI_GENMODEL_COMPLETION`, use `autocli/completion-default` instead * Removed `clicon_cli_genmodel_completion()` * `CLICON_CLI_AUTOCLI_EXCLUDE`, use `autocli/rule/operation=exclude` instead * `CLICON_CLI_MODEL_TREENAME`, use constant `AUTOCLI_TREENAME` instead * Removed `clicon_cli_model_treename()` * New YANG functions: yang_single_child_type, yang_find_namespace_by_prefix, yang_str2key * Changed return values of yang_find_prefix_by_namespace * Merged `cli_cli2xml()` into `cli2xml()`
This commit is contained in:
parent
dec05e2cae
commit
081e6871b3
45 changed files with 1804 additions and 900 deletions
|
|
@ -1267,23 +1267,27 @@ yang_find_mynamespace(yang_stmt *ys)
|
|||
* (global) namespace of a module, but you do not know the local prefix
|
||||
* used to access it in XML.
|
||||
* @param[in] ys Yang statement in module tree (or module itself)
|
||||
* @param[in] ns Namspace URI as char* pointer into yang tree
|
||||
* @param[in] ns Namespace URI as char* pointer into yang tree
|
||||
* @param[out] prefix Local prefix to access module with (direct pointer)
|
||||
* @retval 0 not found
|
||||
* @retval -1 found
|
||||
* @retval -1 Error
|
||||
* @retval 0 Not found
|
||||
* @retval 1 Found
|
||||
* @note prefix NULL is not returned, if own module, then return its prefix
|
||||
* @code
|
||||
* char *prefix = NULL;
|
||||
* if (yang_find_prefix_by_namespace(ys, "urn:example:clixon", &prefix) < 0)
|
||||
* if ((found = yang_find_prefix_by_namespace(ys, "urn:example:clixon", &prefix)) < 0)
|
||||
* err;
|
||||
* if (found)
|
||||
* // use prefix
|
||||
* @endcode
|
||||
* @see yang_find_module_by_namespace
|
||||
*/
|
||||
int
|
||||
yang_find_prefix_by_namespace(yang_stmt *ys,
|
||||
char *ns,
|
||||
char **prefix)
|
||||
{
|
||||
int retval = 0; /* not found */
|
||||
int retval = -1;
|
||||
yang_stmt *my_ymod; /* My module */
|
||||
char *myns; /* My ns */
|
||||
yang_stmt *yspec;
|
||||
|
|
@ -1293,6 +1297,10 @@ yang_find_prefix_by_namespace(yang_stmt *ys,
|
|||
yang_stmt *yprefix;
|
||||
|
||||
clicon_debug(2, "%s", __FUNCTION__);
|
||||
if (prefix == NULL){
|
||||
clicon_err(OE_YANG, EINVAL, "prefix is NULL");
|
||||
goto done;
|
||||
}
|
||||
/* First check if namespace is my own module */
|
||||
myns = yang_find_mynamespace(ys);
|
||||
if (strcmp(myns, ns) == 0){
|
||||
|
|
@ -1316,10 +1324,55 @@ yang_find_prefix_by_namespace(yang_stmt *ys,
|
|||
}
|
||||
}
|
||||
notfound:
|
||||
retval = 0; /* not found */
|
||||
done:
|
||||
return retval;
|
||||
found:
|
||||
assert(*prefix);
|
||||
return 1;
|
||||
retval = 1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*! Given a yang statement and local prefi valid in module , find namespace
|
||||
*
|
||||
* @param[in] ys Yang statement in module tree (or module itself)
|
||||
* @param[in] prefix Local prefix to access module with (direct pointer)
|
||||
* @param[out] ns Namespace URI as char* pointer into yang tree
|
||||
* @retval -1 Error
|
||||
* @retval 0 Not found
|
||||
* @retval 1 Found
|
||||
* @note prefix NULL is not returned, if own module, then return its prefix
|
||||
* @code
|
||||
* char *ns = NULL;
|
||||
* if ((found = yang_find_namespace_by_prefix(ys, "ex", &ns)) < 0)
|
||||
* err;
|
||||
* if (found)
|
||||
* // use ns *
|
||||
* @endcode
|
||||
* @see yang_find_module_by_prefix
|
||||
*/
|
||||
int
|
||||
yang_find_namespace_by_prefix(yang_stmt *ys,
|
||||
char *prefix,
|
||||
char **ns)
|
||||
{
|
||||
int retval = -1;
|
||||
yang_stmt *ym;
|
||||
|
||||
if (ns == NULL){
|
||||
clicon_err(OE_YANG, EINVAL, "ns is NULL");
|
||||
goto done;
|
||||
}
|
||||
if ((ym = yang_find_module_by_prefix(ys, prefix)) == NULL)
|
||||
goto notfound;
|
||||
if ((*ns = yang_find_mynamespace(ym)) == NULL)
|
||||
goto notfound;
|
||||
retval = 1; /* found */
|
||||
done:
|
||||
return retval;
|
||||
notfound:
|
||||
retval = 0;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*! Return topmost yang root node directly under module/submodule
|
||||
|
|
@ -1505,6 +1558,12 @@ yang_key2str(int keyword)
|
|||
return (char*)clicon_int2str(ykmap, keyword);
|
||||
}
|
||||
|
||||
int
|
||||
yang_str2key(char *str)
|
||||
{
|
||||
return clicon_str2int(ykmap, str);
|
||||
}
|
||||
|
||||
/*! Find top data node among all modules by namespace in xml tree
|
||||
* @param[in] yspec Yang specification
|
||||
* @param[in] xt XML node
|
||||
|
|
@ -3392,53 +3451,6 @@ yang_arg2cvec(yang_stmt *ys,
|
|||
return cvv;
|
||||
}
|
||||
|
||||
/*! Check if yang is subject to generated cli GT_HIDE boolean
|
||||
* The yang should be:
|
||||
* 1) a non-presence container
|
||||
* 2) parent of a (single) list XXX: or could multiple lists work?
|
||||
* 3) no other data node children
|
||||
* @retval 0 No, does not satisfy the GT_HIDE condition
|
||||
* @retval 1 Yes, satisfies the GT_HIDE condition
|
||||
* @see clixon-config.yang HIDE enumeration type
|
||||
*/
|
||||
int
|
||||
yang_container_cli_hide(yang_stmt *ys,
|
||||
enum genmodel_type gt)
|
||||
{
|
||||
yang_stmt *yc = NULL;
|
||||
int i;
|
||||
enum rfc_6020 keyw;
|
||||
|
||||
keyw = yang_keyword_get(ys);
|
||||
/* HIDE mode */
|
||||
if (gt != GT_HIDE && gt != GT_OC_COMPRESS)
|
||||
return 0;
|
||||
/* A container */
|
||||
if (yang_keyword_get(ys) != Y_CONTAINER)
|
||||
return 0;
|
||||
/* Non-presence */
|
||||
if (yang_find(ys, Y_PRESENCE, NULL) != NULL)
|
||||
return 0;
|
||||
/* Ensure a single list child and no other data nodes */
|
||||
i = 0; /* Number of list nodes */
|
||||
while ((yc = yn_each(ys, yc)) != NULL) {
|
||||
keyw = yang_keyword_get(yc);
|
||||
/* case/choice could hide anything so disqualify those */
|
||||
if (keyw == Y_CASE || keyw == Y_CHOICE)
|
||||
break;
|
||||
if (!yang_datanode(yc)) /* Allowed, check next */
|
||||
continue;
|
||||
if (keyw != Y_LIST) /* Another datanode than list */
|
||||
break;
|
||||
if (i++>0) /* More than one list (or could this work?) */
|
||||
break;
|
||||
}
|
||||
if (yc != NULL) /* break from loop */
|
||||
return 0;
|
||||
if (i != 1) /* List found */
|
||||
return 0;
|
||||
return 1; /* Passed all tests: yes you can hide this keyword */
|
||||
}
|
||||
|
||||
/*! Check if yang node yn has key-stmt as child which matches name
|
||||
*
|
||||
|
|
@ -3719,9 +3731,9 @@ yang_anydata_add(yang_stmt *yp,
|
|||
|
||||
/*! Find extension argument and return if extension exists and its argument value
|
||||
*
|
||||
* @param[in] ys Yang statement
|
||||
* @param[in] ys Yang statement where unknown statement may occur referncing to extension
|
||||
* @param[in] name Name of the extension
|
||||
* @param[in] ns The namespace
|
||||
* @param[in] ns The namespace of the module where the extension is defined
|
||||
* @param[out] exist The extension exists.
|
||||
* @param[out] value clispec operator (hide/none) - direct pointer into yang, dont free
|
||||
* @retval 0 OK: Look in exist and value for return value
|
||||
|
|
@ -3751,6 +3763,7 @@ yang_extension_value(yang_stmt *ys,
|
|||
cg_var *cv;
|
||||
char *prefix = NULL;
|
||||
cbuf *cb = NULL;
|
||||
int ret;
|
||||
|
||||
if ((cb = cbuf_new()) == NULL){
|
||||
clicon_err(OE_UNIX, errno, "cbuf_new");
|
||||
|
|
@ -3762,7 +3775,9 @@ yang_extension_value(yang_stmt *ys,
|
|||
continue;
|
||||
if ((ymod = ys_module(yext)) == NULL)
|
||||
continue;
|
||||
if (yang_find_prefix_by_namespace(ymod, ns, &prefix) < 0)
|
||||
if ((ret = yang_find_prefix_by_namespace(ymod, ns, &prefix)) < 0)
|
||||
goto done;
|
||||
if (ret == 0) /* not found */
|
||||
goto ok;
|
||||
cbuf_reset(cb);
|
||||
cprintf(cb, "%s:%s", prefix, name);
|
||||
|
|
@ -3901,3 +3916,53 @@ yang_search_index_extension(clicon_handle h,
|
|||
}
|
||||
|
||||
#endif /* XML_EXPLICIT_INDEX */
|
||||
|
||||
/*! Check if yang node has a single child of specific type
|
||||
*
|
||||
* Mainly used for condition for CLI compression
|
||||
* The yang should be:
|
||||
* 1) If container it should be non-presence
|
||||
* 2) parent of a (single) specified type
|
||||
* 3) no other data node children
|
||||
* @param[in] ys Yang node
|
||||
* @param[in] subkeyw Expected keyword of single child (typically Y_LIST)
|
||||
* @retval 0 No, node does not have single child of specified type
|
||||
* @retval 1 Yes, node has single child of specified type
|
||||
* @see https://github.com/openconfig/ygot/blob/master/docs/design.md#openconfig-path-compression 2nd clause
|
||||
*/
|
||||
int
|
||||
yang_single_child_type(yang_stmt *ys,
|
||||
enum rfc_6020 subkeyw)
|
||||
|
||||
{
|
||||
yang_stmt *yc = NULL;
|
||||
int i;
|
||||
enum rfc_6020 keyw;
|
||||
|
||||
/* Match parent */
|
||||
/* If container, check it is Non-presence */
|
||||
if (yang_keyword_get(ys) == Y_CONTAINER){
|
||||
if (yang_find(ys, Y_PRESENCE, NULL) != NULL)
|
||||
return 0;
|
||||
}
|
||||
/* Ensure a single list child and no other data nodes */
|
||||
i = 0; /* Number of list nodes */
|
||||
while ((yc = yn_each(ys, yc)) != NULL) {
|
||||
keyw = yang_keyword_get(yc);
|
||||
/* case/choice could hide anything so disqualify those */
|
||||
if (keyw == Y_CASE || keyw == Y_CHOICE)
|
||||
break;
|
||||
if (!yang_datanode(yc)) /* Allowed, check next */
|
||||
continue;
|
||||
if (keyw != subkeyw) /* Another datanode than subkeyw */
|
||||
break;
|
||||
if (i++>0) /* More than one list (or could this work?) */
|
||||
break;
|
||||
}
|
||||
if (yc != NULL) /* break from loop */
|
||||
return 0;
|
||||
if (i != 1) /* List found */
|
||||
return 0;
|
||||
return 1; /* Passed all tests: yes you can hide this keyword */
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue