CLI show compare example function
Improved diff algorithm for XML and TEXT/curly, replaced UNIX diff with structural in-mem algorithm Fixed: ["show compare" and "show compare | display cli" differs #23](https://github.com/clicon/clixon-controller/issues/23) Changed parameters of example clispec function `compare_dbs()` Added show2cbuf functions for TEXT/CLI Renamed clixon_txt2file to clixon_text2file
This commit is contained in:
parent
45f41e3e4d
commit
2603b6f139
19 changed files with 1170 additions and 193 deletions
|
|
@ -557,7 +557,7 @@ cli_show_common(clicon_handle h,
|
|||
cligen_output(stdout, "\n");
|
||||
break;
|
||||
case FORMAT_TEXT: /* XXX does not handle multiple leaf-list */
|
||||
if (clixon_txt2file(stdout, xp, 0, cligen_output, skiptop, 1) < 0)
|
||||
if (clixon_text2file(stdout, xp, 0, cligen_output, skiptop, 1) < 0)
|
||||
goto done;
|
||||
break;
|
||||
case FORMAT_CLI:
|
||||
|
|
@ -1299,7 +1299,7 @@ cli_pagination(clicon_handle h,
|
|||
goto done;
|
||||
break;
|
||||
case FORMAT_TEXT:
|
||||
if (clixon_txt2file(stdout, xc, 0, cligen_output, 0, 1) < 0)
|
||||
if (clixon_text2file(stdout, xc, 0, cligen_output, 0, 1) < 0)
|
||||
goto done;
|
||||
break;
|
||||
case FORMAT_CLI:
|
||||
|
|
@ -1341,6 +1341,134 @@ cli_pagination(clicon_handle h,
|
|||
return retval;
|
||||
}
|
||||
|
||||
/*! Translate to CLI commands in cbuf
|
||||
*
|
||||
* Howto: join strings and pass them down.
|
||||
* Identify unique/index keywords for correct set syntax.
|
||||
* @param[in] h Clicon handle
|
||||
* @param[in,out] cb Cligen buffer to write to
|
||||
* @param[in] xn XML Parse-tree (to translate)
|
||||
* @param[in] prepend Print this text in front of all commands.
|
||||
* @retval 0 OK
|
||||
* @retval -1 Error
|
||||
* @see clixon_cli2file
|
||||
*/
|
||||
static int
|
||||
cli2cbuf(clicon_handle h,
|
||||
cbuf *cb,
|
||||
cxobj *xn,
|
||||
char *prepend)
|
||||
{
|
||||
int retval = -1;
|
||||
cxobj *xe = NULL;
|
||||
cbuf *cbpre = NULL;
|
||||
yang_stmt *ys;
|
||||
int match;
|
||||
char *body;
|
||||
int compress = 0;
|
||||
autocli_listkw_t listkw;
|
||||
int exist = 0;
|
||||
char *name;
|
||||
|
||||
if (autocli_list_keyword(h, &listkw) < 0)
|
||||
goto done;
|
||||
if (xml_type(xn)==CX_ATTR)
|
||||
goto ok;
|
||||
if ((ys = xml_spec(xn)) == NULL)
|
||||
goto ok;
|
||||
if (yang_extension_value(ys, "hide-show", CLIXON_AUTOCLI_NS, &exist, NULL) < 0)
|
||||
goto done;
|
||||
if (exist)
|
||||
goto ok;
|
||||
exist = 0;
|
||||
if (yang_extension_value(ys, "alias", CLIXON_AUTOCLI_NS, &exist, &name) < 0)
|
||||
goto done;
|
||||
if (!exist)
|
||||
name = xml_name(xn);
|
||||
/* If leaf/leaf-list or presence container, then print line */
|
||||
if (yang_keyword_get(ys) == Y_LEAF ||
|
||||
yang_keyword_get(ys) == Y_LEAF_LIST){
|
||||
if (prepend)
|
||||
cprintf(cb, "%s", prepend);
|
||||
if (listkw != AUTOCLI_LISTKW_NONE)
|
||||
cprintf(cb, "%s ", name);
|
||||
if ((body = xml_body(xn)) != NULL){
|
||||
if (index(body, ' '))
|
||||
cprintf(cb, "\"%s\"", body);
|
||||
else
|
||||
cprintf(cb, "%s", body);
|
||||
}
|
||||
cprintf(cb, "\n");
|
||||
goto ok;
|
||||
}
|
||||
/* Create prepend variable string */
|
||||
if ((cbpre = cbuf_new()) == NULL){
|
||||
clicon_err(OE_PLUGIN, errno, "cbuf_new");
|
||||
goto done;
|
||||
}
|
||||
if (prepend)
|
||||
cprintf(cbpre, "%s", prepend);
|
||||
|
||||
/* If non-presence container && HIDE mode && only child is
|
||||
* a list, then skip container keyword
|
||||
* See also yang2cli_container */
|
||||
if (autocli_compress(h, ys, &compress) < 0)
|
||||
goto done;
|
||||
if (!compress)
|
||||
cprintf(cbpre, "%s ", xml_name(xn));
|
||||
|
||||
/* If list then first loop through keys */
|
||||
if (yang_keyword_get(ys) == Y_LIST){
|
||||
xe = NULL;
|
||||
while ((xe = xml_child_each(xn, xe, -1)) != NULL){
|
||||
if ((match = yang_key_match(ys, xml_name(xe), NULL)) < 0)
|
||||
goto done;
|
||||
if (!match)
|
||||
continue;
|
||||
if (listkw == AUTOCLI_LISTKW_ALL)
|
||||
cprintf(cbpre, "%s ", xml_name(xe));
|
||||
cprintf(cbpre, "%s ", xml_body(xe));
|
||||
}
|
||||
}
|
||||
else if ((yang_keyword_get(ys) == Y_CONTAINER) &&
|
||||
yang_find(ys, Y_PRESENCE, NULL) != NULL){
|
||||
/* If presence container, then print as leaf (but continue to children) */
|
||||
if (prepend)
|
||||
cprintf(cb, "%s", prepend);
|
||||
if (listkw != AUTOCLI_LISTKW_NONE)
|
||||
cprintf(cb, "%s ", xml_name(xn));
|
||||
if ((body = xml_body(xn)) != NULL){
|
||||
if (index(body, ' '))
|
||||
cprintf(cb, "\"%s\"", body);
|
||||
else
|
||||
cprintf(cb, "%s", body);
|
||||
}
|
||||
cprintf(cb, "\n");
|
||||
}
|
||||
|
||||
/* For lists, print cbpre before its elements */
|
||||
if (yang_keyword_get(ys) == Y_LIST)
|
||||
cprintf(cb, "%s\n", cbuf_get(cbpre));
|
||||
/* Then loop through all other (non-keys) */
|
||||
xe = NULL;
|
||||
while ((xe = xml_child_each(xn, xe, -1)) != NULL){
|
||||
if (yang_keyword_get(ys) == Y_LIST){
|
||||
if ((match = yang_key_match(ys, xml_name(xe), NULL)) < 0)
|
||||
goto done;
|
||||
if (match)
|
||||
continue; /* Not key itself */
|
||||
}
|
||||
if (cli2cbuf(h, cb, xe, cbuf_get(cbpre)) < 0)
|
||||
goto done;
|
||||
}
|
||||
ok:
|
||||
retval = 0;
|
||||
done:
|
||||
if (cbpre)
|
||||
cbuf_free(cbpre);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*! Translate from XML to CLI commands, internal
|
||||
*
|
||||
* Howto: join strings and pass them down.
|
||||
|
|
@ -1352,7 +1480,7 @@ cli_pagination(clicon_handle h,
|
|||
* @param[in] fn Callback to make print function
|
||||
*/
|
||||
static int
|
||||
xml2cli1(clicon_handle h,
|
||||
cli2file(clicon_handle h,
|
||||
FILE *f,
|
||||
cxobj *xn,
|
||||
char *prepend,
|
||||
|
|
@ -1457,7 +1585,7 @@ xml2cli1(clicon_handle h,
|
|||
if (match)
|
||||
continue; /* Not key itself */
|
||||
}
|
||||
if (xml2cli1(h, f, xe, cbuf_get(cbpre), fn) < 0)
|
||||
if (cli2file(h, f, xe, cbuf_get(cbpre), fn) < 0)
|
||||
goto done;
|
||||
}
|
||||
ok:
|
||||
|
|
@ -1480,6 +1608,7 @@ xml2cli1(clicon_handle h,
|
|||
* @param[in] skiptop 0: Include top object 1: Skip top-object, only children,
|
||||
* @retval 0 OK
|
||||
* @retval -1 Error
|
||||
* @see clixon_cli2cbuf
|
||||
*/
|
||||
int
|
||||
clixon_cli2file(clicon_handle h,
|
||||
|
|
@ -1497,11 +1626,50 @@ clixon_cli2file(clicon_handle h,
|
|||
if (skiptop){
|
||||
xc = NULL;
|
||||
while ((xc = xml_child_each(xn, xc, CX_ELMNT)) != NULL)
|
||||
if (xml2cli1(h, f, xc, prepend, fn) < 0)
|
||||
if (cli2file(h, f, xc, prepend, fn) < 0)
|
||||
goto done;
|
||||
}
|
||||
else {
|
||||
if (xml2cli1(h, f, xn, prepend, fn) < 0)
|
||||
if (cli2file(h, f, xn, prepend, fn) < 0)
|
||||
goto done;
|
||||
}
|
||||
retval = 0;
|
||||
done:
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*! Translate from XML to CLI commands
|
||||
*
|
||||
* Howto: join strings and pass them down.
|
||||
* Identify unique/index keywords for correct set syntax.
|
||||
* @param[in] h Clicon handle
|
||||
* @param[in] f Output FILE (eg stdout)
|
||||
* @param[in] xn XML Parse-tree (to translate)
|
||||
* @param[in] prepend Print this text in front of all commands.
|
||||
* @param[in] fn File print function (if NULL, use fprintf)
|
||||
* @param[in] skiptop 0: Include top object 1: Skip top-object, only children,
|
||||
* @retval 0 OK
|
||||
* @retval -1 Error
|
||||
* @see clixon_cli2file
|
||||
*/
|
||||
int
|
||||
clixon_cli2cbuf(clicon_handle h,
|
||||
cbuf *cb,
|
||||
cxobj *xn,
|
||||
char *prepend,
|
||||
int skiptop)
|
||||
{
|
||||
int retval = 1;
|
||||
cxobj *xc;
|
||||
|
||||
if (skiptop){
|
||||
xc = NULL;
|
||||
while ((xc = xml_child_each(xn, xc, CX_ELMNT)) != NULL)
|
||||
if (cli2cbuf(h, cb, xc, prepend) < 0)
|
||||
goto done;
|
||||
}
|
||||
else {
|
||||
if (cli2cbuf(h, cb, xn, prepend) < 0)
|
||||
goto done;
|
||||
}
|
||||
retval = 0;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue