diff --git a/CHANGELOG.md b/CHANGELOG.md
index 01675118..e56752d8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -103,6 +103,7 @@ enables saved files to be used as datastore without any editing. Thanks Matt.
* Added cli_show_version()
### Corrected Bugs
+* Showing syntax using CLI commands was broekn and is fixed.
* Fixed issue https://github.com/clicon/clixon/issues/18 RPC response issues reported by Stephen Jones at Netgate
* Fixed issue https://github.com/clicon/clixon/issues/17 special character in strings can break RPCs reported by David Cornejo at Netgate.
* This was a large rewright of XML parsing and output due to CharData not correctly encoded according to https://www.w3.org/TR/2008/REC-xml-20081126.
diff --git a/lib/clixon/clixon_options.h b/lib/clixon/clixon_options.h
index f6854d15..1f95c73a 100644
--- a/lib/clixon/clixon_options.h
+++ b/lib/clixon/clixon_options.h
@@ -50,7 +50,6 @@
/*! Controls how keywords a generated in CLI syntax / prints from object model
* Example YANG:
- * list a {a.b[] $!x $y:
* list a {
* key x;
* leaf x;
@@ -63,7 +62,7 @@
enum genmodel_type{
GT_ERR =-1, /* Error */
GT_NONE=0, /* No extra keywords */
- GT_VARS, /* Keywords on non-index variables */
+ GT_VARS, /* Keywords on non-key variables */
GT_ALL, /* Keywords on all variables */
};
diff --git a/lib/src/clixon_xml_map.c b/lib/src/clixon_xml_map.c
index 917131f7..8524a413 100644
--- a/lib/src/clixon_xml_map.c
+++ b/lib/src/clixon_xml_map.c
@@ -89,19 +89,6 @@
#include "clixon_xml_sort.h"
#include "clixon_xml_map.h"
-/*
- * A node is a leaf if it contains a body.
- */
-static cxobj *
-leaf(cxobj *xn)
-{
- cxobj *xc = NULL;
-
- while ((xc = xml_child_each(xn, xc, CX_BODY)) != NULL)
- break;
- return xc;
-}
-
/*! x is element and has eactly one child which in turn has none */
static int
tleaf(cxobj *x)
@@ -118,6 +105,7 @@ tleaf(cxobj *x)
/*! Translate XML -> TEXT
* @param[in] level print 4 spaces per level in front of each line
+ * XXX rewrite using YANG and remove encrypted password KLUDGE
*/
int
xml2txt(FILE *f,
@@ -184,69 +172,60 @@ xml2cli(FILE *f,
{
int retval = -1;
cxobj *xe = NULL;
- char *term;
- int bool;
- int nr;
- int i;
- cbuf *cbpre;
- // yang_stmt *ys;
+ cbuf *cbpre = NULL;
+ yang_stmt *ys;
+ int match;
+ char *body;
- // ys = yang_spec(x);
+ ys = xml_spec(x);
+ if (ys->ys_keyword == Y_LEAF || ys->ys_keyword == Y_LEAF_LIST){
+ if (prepend0)
+ fprintf(f, "%s", prepend0);
+ body = xml_body(x);
+ if (gt == GT_ALL || gt == GT_VARS)
+ fprintf(f, "%s ", xml_name(x));
+ if (index(body, ' '))
+ fprintf(f, "\"%s\"", body);
+ else
+ fprintf(f, "%s", body);
+ fprintf(f, "\n");
+ goto ok;
+ }
/* Create prepend variable string */
if ((cbpre = cbuf_new()) == NULL){
clicon_err(OE_PLUGIN, errno, "cbuf_new");
goto done;
}
- nr = xml_child_nr(x);
- if (!nr){
- if (xml_type(x) == CX_BODY)
- term = xml_value(x);
- else
- term = xml_name(x);
- if (prepend0)
- fprintf(f, "%s ", prepend0);
- if (index(term, ' '))
- fprintf(f, "\"%s\"\n", term);
- else
- fprintf(f, "%s\n", term);
- retval = 0;
- goto done;
- }
if (prepend0)
cprintf(cbpre, "%s", prepend0);
- /* bool determines when to print a variable keyword:
- !leaf T for all (ie parameter)
- index GT_NONE F
- index GT_VARS F
- index GT_ALL T
- !index GT_NONE F
- !index GT_VARS T
- !index GT_ALL T
- */
- bool = !leaf(x) || gt == GT_ALL || (gt == GT_VARS);
-// bool = (!x->xn_index || gt == GT_ALL);
- if (bool){
- if (cbuf_len(cbpre))
- cprintf(cbpre, " ");
- cprintf(cbpre, "%s", xml_name(x));
- }
- xe = NULL;
- /* First child is unique, then add that, before looping. */
- i = 0;
- while ((xe = xml_child_each(x, xe, -1)) != NULL){
- /* Dont call this if it is index and there are other following */
- if (0 && i < nr-1)
- ;
- else
- if (xml2cli(f, xe, cbuf_get(cbpre), gt) < 0)
+ cprintf(cbpre, "%s ", xml_name(x));
+
+ if (ys->ys_keyword == Y_LIST){
+ /* If list then first loop through keys */
+ xe = NULL;
+ while ((xe = xml_child_each(x, xe, -1)) != NULL){
+ if ((match = yang_key_match((yang_node*)ys, xml_name(xe))) < 0)
goto done;
- if (0){ /* assume index is first, otherwise need one more while */
+ if (!match)
+ continue;
if (gt == GT_ALL)
- cprintf(cbpre, " %s", xml_name(xe));
- cprintf(cbpre, " %s", xml_value(xml_child_i(xe, 0)));
+ cprintf(cbpre, "%s ", xml_name(xe));
+ cprintf(cbpre, "%s ", xml_body(xe));
}
- i++;
}
+ /* Then loop through all other (non-keys) */
+ xe = NULL;
+ while ((xe = xml_child_each(x, xe, -1)) != NULL){
+ if (ys->ys_keyword == Y_LIST){
+ if ((match = yang_key_match((yang_node*)ys, xml_name(xe))) < 0)
+ goto done;
+ if (match)
+ continue;
+ }
+ if (xml2cli(f, xe, cbuf_get(cbpre), gt) < 0)
+ goto done;
+ }
+ ok:
retval = 0;
done:
if (cbpre)
diff --git a/test/test_cli.sh b/test/test_cli.sh
index 51a2ea5e..ec71a707 100755
--- a/test/test_cli.sh
+++ b/test/test_cli.sh
@@ -58,7 +58,7 @@ new "cli configure"
expectfn "$clixon_cli -1 -f $cfg set interfaces interface eth/0/0" "^$"
new "cli show configuration"
-expectfn "$clixon_cli -1 -f $cfg show conf cli" "^interfaces interface name eth/0/0" "interfaces interface enabled true$"
+expectfn "$clixon_cli -1 -f $cfg show conf cli" "^interfaces interface eth/0/0 enabled true"
new "cli configure using encoded chars data <&"
expectfn "$clixon_cli -1 -f $cfg set interfaces interface eth/0/0 description \"foo<&bar\"" ""
@@ -101,7 +101,8 @@ new "cli load"
expectfn "$clixon_cli -1 -f $cfg -l o load /tmp/foo" "^$"
new "cli check load"
-expectfn "$clixon_cli -1 -f $cfg -l o show conf cli" "^interfaces interface name eth/0/0" "interfaces interface enabled true$"
+expectfn "$clixon_cli -1 -f $cfg -l o show conf cli" "^interfaces interface name eth/0/0 type bgp
+interfaces interface eth/0/0 ipv4 enabled true"
new "cli debug"
expectfn "$clixon_cli -1 -f $cfg -l o debug level 1" "^$"
diff --git a/test/test_netconf.sh b/test/test_netconf.sh
index 7b66e88e..b6fc58ac 100755
--- a/test/test_netconf.sh
+++ b/test/test_netconf.sh
@@ -144,7 +144,8 @@ new "netconf get replaced config"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "]]>]]>" "^eth& t< > trueeth1ethtrueeth2ethtrue]]>]]>$"
new "cli show configuration eth& - encoding tests"
-expectfn "$clixon_cli -1 -f $cfg -y $fyang show conf cli" "interfaces interface name eth&"
+expectfn "$clixon_cli -1 -f $cfg -y $fyang show conf cli" "interfaces interface eth& type t<>
+interfaces interface eth& enabled true"
new "netconf discard-changes"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "]]>]]>" "^]]>]]>$"
diff --git a/yang/clixon-config@2018-02-12.yang b/yang/clixon-config@2018-02-12.yang
index 58ff73f8..84dc8622 100644
--- a/yang/clixon-config@2018-02-12.yang
+++ b/yang/clixon-config@2018-02-12.yang
@@ -82,6 +82,22 @@ module clixon-config {
}
}
}
+ typedef cli_genmodel_type{
+ description
+ "How to generate CLI from YANG model,
+ eg list a{ key x; leaf x; leaf y;}";
+ type enumeration{
+ enum NONE{
+ description "No extra keywords: a ";
+ }
+ enum VARS{
+ description "Keywords on non-key variables: a y ";
+ }
+ enum ALL{
+ description "Keywords on all variables: a x y ";
+ }
+ }
+ }
typedef nacm_mode{
description
"Mode of RFC8341 Network Configuration Access Control Model.
@@ -204,7 +220,7 @@ module clixon-config {
description "Generate code for CLI completion of existing db symbols";
}
leaf CLICON_CLI_GENMODEL_TYPE {
- type string;
+ type cli_genmodel_type;
default "VARS";
description "How to generate and show CLI syntax: VARS|ALL";
}