diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0a2a0329..db93bd3a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -42,12 +42,19 @@ Expected: July 2020
### API changes on existing protocol/config features (For users)
- * Restconf FCGI (eg via nginx) have changed reply message syntax as follows (due to refactoring and common code with evhtp):
+ * Restconf FCGI (eg via nginx) have changed reply message syntax slightly as follows (due to refactoring and common code with evhtp):
* Bodies in error reyruns including html code have been removed
* Some (extra) CRLF:s have been removed
### C/CLI-API changes on existing features (For developers)
+* Added new cli show functions to work with cligen_output for cligen pageing to work. To acheive this, add a callback function as follows:
+ * xml2txt(...) --> xml2txt_cb(..., cligen_output)
+ * xml2cli(...) --> xml2cli_cb(..., cligen_output)
+ * clicon_xml2file(...) --> clicon_xml2file_cb(..., cligen_output)
+ * xml2json(...) --> xml2json_cb(..., cligen_output)
+ * yang_print(...) --> yang_print_cb(..., cligen_output)
+
* Added prefix for cli_show_config/cli_show_auto so that it can produce parseable output
* Replaced the global variable `debug` with access function: `clicon_debug_get()`.
* Due to name collision with libevent, all clixon event functions prepended with `clixon_`. You need to rename your event functions as follows:
diff --git a/apps/cli/cli_common.c b/apps/cli/cli_common.c
index 3ab4115b..b9016e92 100644
--- a/apps/cli/cli_common.c
+++ b/apps/cli/cli_common.c
@@ -652,10 +652,10 @@ compare_xmls(cxobj *xc1,
xc = NULL;
if (astext)
while ((xc = xml_child_each(xc1, xc, -1)) != NULL)
- xml2txt(f, xc, 0);
+ xml2txt_cb(f, xc, cligen_output);
else
while ((xc = xml_child_each(xc1, xc, -1)) != NULL)
- xml_print(f, xc);
+ clicon_xml2file_cb(f, xc, 0, 1, cligen_output);
fclose(f);
close(fd);
@@ -669,10 +669,10 @@ compare_xmls(cxobj *xc1,
xc = NULL;
if (astext)
while ((xc = xml_child_each(xc2, xc, -1)) != NULL)
- xml2txt(f, xc, 0);
+ xml2txt_cb(f, xc, cligen_output);
else
while ((xc = xml_child_each(xc2, xc, -1)) != NULL)
- xml_print(f, xc);
+ clicon_xml2file_cb(f, xc, 0, 1, cligen_output);
fclose(f);
close(fd);
@@ -1002,15 +1002,15 @@ cli_notification_cb(int s,
while ((x = xml_child_each(xe, x, -1)) != NULL) {
switch (format){
case FORMAT_XML:
- if (clicon_xml2file(stdout, x, 0, 1) < 0)
+ if (clicon_xml2file_cb(stdout, x, 0, 1, cligen_output) < 0)
goto done;
break;
case FORMAT_TEXT:
- if (xml2txt(stdout, x, 0) < 0)
+ if (xml2txt_cb(stdout, x, cligen_output) < 0)
goto done;
break;
case FORMAT_JSON:
- if (xml2json(stdout, x, 1) < 0)
+ if (xml2json_cb(stdout, x, 1, cligen_output) < 0)
goto done;
break;
default:
diff --git a/apps/cli/cli_show.c b/apps/cli/cli_show.c
index 11146ba0..9c230aae 100644
--- a/apps/cli/cli_show.c
+++ b/apps/cli/cli_show.c
@@ -395,19 +395,19 @@ show_yang(clicon_handle h,
cvec *cvv,
cvec *argv)
{
- yang_stmt *yn;
- char *str = NULL;
- yang_stmt *yspec;
+ yang_stmt *yn;
+ char *str = NULL;
+ yang_stmt *yspec;
- yspec = clicon_dbspec_yang(h);
- if (cvec_len(argv) > 0){
- str = cv_string_get(cvec_i(argv, 0));
- yn = yang_find(yspec, 0, str);
- }
- else
- yn = yspec;
- yang_print(stdout, yn);
- return 0;
+ yspec = clicon_dbspec_yang(h);
+ if (cvec_len(argv) > 0){
+ str = cv_string_get(cvec_i(argv, 0));
+ yn = yang_find(yspec, 0, str);
+ }
+ else
+ yn = yspec;
+ yang_print_cb(stdout, yn, cligen_output); /* Doesnt use cligen_output */
+ return 0;
}
/*! Show configuration and state internal function
@@ -506,15 +506,15 @@ cli_show_config1(clicon_handle h,
case FORMAT_XML:
xc = NULL; /* Dont print xt itself */
while ((xc = xml_child_each(xt, xc, -1)) != NULL)
- clicon_xml2file(stdout, xc, 0, 1);
+ clicon_xml2file_cb(stdout, xc, 0, 1, cligen_output);
break;
case FORMAT_JSON:
- xml2json(stdout, xt, 1);
+ xml2json_cb(stdout, xt, 1, cligen_output);
break;
case FORMAT_TEXT:
xc = NULL; /* Dont print xt itself */
while ((xc = xml_child_each(xt, xc, -1)) != NULL)
- xml2txt(stdout, xc, 0); /* tree-formed text */
+ xml2txt_cb(stdout, xc, cligen_output); /* tree-formed text */
break;
case FORMAT_CLI:
/* get CLI generatade mode: VARS|ALL */
@@ -522,14 +522,14 @@ cli_show_config1(clicon_handle h,
goto done;
xc = NULL; /* Dont print xt itself */
while ((xc = xml_child_each(xt, xc, CX_ELMNT)) != NULL)
- xml2cli(stdout, xc, prefix, gt); /* cli syntax */
+ xml2cli_cb(stdout, xc, prefix, gt, cligen_output); /* cli syntax */
break;
case FORMAT_NETCONF:
- fprintf(stdout, "\n");
+ cligen_output(stdout, "\n");
xc = NULL; /* Dont print xt itself */
while ((xc = xml_child_each(xt, xc, -1)) != NULL)
- clicon_xml2file(stdout, xc, 2, 1);
- fprintf(stdout, "]]>]]>\n");
+ clicon_xml2file_cb(stdout, xc, 2, 1, cligen_output);
+ cligen_output(stdout, "]]>]]>\n");
break;
}
retval = 0;
@@ -763,15 +763,15 @@ cli_show_auto1(clicon_handle h,
clicon_xml2file(stdout, xp, 0, 1);
break;
case FORMAT_JSON:
- xml2json(stdout, xp, 1);
+ xml2json_cb(stdout, xp, 1, cligen_output);
break;
case FORMAT_TEXT:
- xml2txt(stdout, xp, 0); /* tree-formed text */
+ xml2txt_cb(stdout, xp, cligen_output); /* tree-formed text */
break;
case FORMAT_CLI:
if ((gt = clicon_cli_genmodel_type(h)) == GT_ERR)
goto done;
- xml2cli(stdout, xp, prefix, gt); /* cli syntax */
+ xml2cli_cb(stdout, xp, prefix, gt, cligen_output); /* cli syntax */
break;
case FORMAT_NETCONF:
fprintf(stdout, "\n");
diff --git a/example/main/example_cli.c b/example/main/example_cli.c
index 80400688..4038ff7b 100644
--- a/example/main/example_cli.c
+++ b/example/main/example_cli.c
@@ -74,7 +74,7 @@ mycallback(clicon_handle h, cvec *cvv, cvec *argv)
nsc,
&xret) < 0)
goto done;
- xml_print(stdout, xret);
+ clicon_xml2file_cb(stdout, xret, 0, 1, cligen_output);
retval = 0;
done:
if (nsc)
@@ -117,11 +117,11 @@ example_client_rpc(clicon_handle h,
goto done;
}
/* Print result */
- clicon_xml2file(stdout, xml_child_i(xret, 0), 0, 0);
+ clicon_xml2file_cb(stdout, xml_child_i(xret, 0), 0, 0, cligen_output);
fprintf(stdout,"\n");
/* pretty-print:
- xml2txt(stdout, xml_child_i(xret, 0), 0);
+ xml2txt_cb(stdout, xml_child_i(xret, 0), cligen_output);
*/
retval = 0;
done:
diff --git a/lib/clixon/clixon_handle.h b/lib/clixon/clixon_handle.h
index 7da96fad..20f2dbcd 100644
--- a/lib/clixon/clixon_handle.h
+++ b/lib/clixon/clixon_handle.h
@@ -53,6 +53,20 @@ typedef void *clicon_handle;
/* The dynamicically loadable plugin object handle (should be in clixon_plugin.h) */
typedef void *plghndl_t;
+/*! Indirect output functions to print with something else than fprintf
+ * @param[in] h Clicon handle
+ * @param[in] xn Request:
+ * @param[out] cbret Return xml tree, eg ..., 0 -> {"a":["0"]} and not {"a":"0"}
+ * @code
+ * if (xml2json(stderr, xn, 0) < 0)
+ * goto err;
+ * @endcode
+ */
+int
+xml2json_cb(FILE *f,
+ cxobj *x,
+ int pretty,
+ clicon_output_cb *fn)
+{
+ int retval = 1;
+ cbuf *cb = NULL;
+
+ if ((cb = cbuf_new()) ==NULL){
+ clicon_err(OE_XML, errno, "cbuf_new");
+ goto done;
+ }
+ if (xml2json_cbuf(cb, x, pretty) < 0)
+ goto done;
+ (*fn)(f, "%s", cbuf_get(cb));
+ retval = 0;
+ done:
+ if (cb)
+ cbuf_free(cb);
+ return retval;
+}
+
/*! Translate from xml tree to JSON and print to file
* @param[in] f File to print to
* @param[in] x XML tree to translate from
@@ -1026,23 +1063,10 @@ xml2json(FILE *f,
cxobj *x,
int pretty)
{
- int retval = 1;
- cbuf *cb = NULL;
-
- if ((cb = cbuf_new()) ==NULL){
- clicon_err(OE_XML, errno, "cbuf_new");
- goto done;
- }
- if (xml2json_cbuf(cb, x, pretty) < 0)
- goto done;
- fprintf(f, "%s", cbuf_get(cb));
- retval = 0;
- done:
- if (cb)
- cbuf_free(cb);
- return retval;
+ return xml2json_cb(f, x, pretty, fprintf);
}
+
/*! Print an XML tree structure to an output stream as JSON
*
* @param[in] f UNIX output stream
@@ -1050,9 +1074,9 @@ xml2json(FILE *f,
*/
int
json_print(FILE *f,
- cxobj *xn)
+ cxobj *x)
{
- return xml2json(f, xn, 1);
+ return xml2json_cb(f, x, 1, fprintf);
}
/*! Translate a vector of xml objects to JSON File.
diff --git a/lib/src/clixon_xml_io.c b/lib/src/clixon_xml_io.c
index cb4d3982..1cfedd1b 100644
--- a/lib/src/clixon_xml_io.c
+++ b/lib/src/clixon_xml_io.c
@@ -96,15 +96,17 @@
* @param[in] xn clicon xml tree
* @param[in] level how many spaces to insert before each line
* @param[in] prettyprint insert \n and spaces tomake the xml more readable.
+ * @param[in] fn Callback to make print function
* @see clicon_xml2cbuf
* One can use clicon_xml2cbuf to get common code, but using fprintf is
* much faster than using cbuf and then printing that,...
*/
int
-clicon_xml2file(FILE *f,
- cxobj *x,
- int level,
- int prettyprint)
+xml2file_recurse(FILE *f,
+ cxobj *x,
+ int level,
+ int prettyprint,
+ clicon_output_cb *fn)
{
int retval = -1;
char *name;
@@ -125,19 +127,19 @@ clicon_xml2file(FILE *f,
break;
if (xml_chardata_encode(&encstr, "%s", val) < 0)
goto done;
- fprintf(f, "%s", encstr);
+ (*fn)(f, "%s", encstr);
break;
case CX_ATTR:
- fprintf(f, " ");
+ (*fn)(f, " ");
if (namespace)
- fprintf(f, "%s:", namespace);
- fprintf(f, "%s=\"%s\"", name, xml_value(x));
+ (*fn)(f, "%s:", namespace);
+ (*fn)(f, "%s=\"%s\"", name, xml_value(x));
break;
case CX_ELMNT:
- fprintf(f, "%*s<", prettyprint?(level*XML_INDENT):0, "");
+ (*fn)(f, "%*s<", prettyprint?(level*XML_INDENT):0, "");
if (namespace)
- fprintf(f, "%s:", namespace);
- fprintf(f, "%s", name);
+ (*fn)(f, "%s:", namespace);
+ (*fn)(f, "%s", name);
hasbody = 0;
haselement = 0;
xc = NULL;
@@ -145,7 +147,7 @@ clicon_xml2file(FILE *f,
while ((xc = xml_child_each(x, xc, -1)) != NULL) {
switch (xml_type(xc)){
case CX_ATTR:
- if (clicon_xml2file(f, xc, level+1, prettyprint) <0)
+ if (xml2file_recurse(f, xc, level+1, prettyprint, fn) <0)
goto done;
break;
case CX_BODY:
@@ -162,26 +164,26 @@ clicon_xml2file(FILE *f,
* Ie, no CX_BODY or CX_ELMNT child.
*/
if (hasbody==0 && haselement==0)
- fprintf(f, "/>");
+ (*fn)(f, "/>");
else{
- fprintf(f, ">");
+ (*fn)(f, ">");
if (prettyprint && hasbody == 0)
- fprintf(f, "\n");
+ (*fn)(f, "\n");
xc = NULL;
while ((xc = xml_child_each(x, xc, -1)) != NULL) {
if (xml_type(xc) != CX_ATTR)
- if (clicon_xml2file(f, xc, level+1, prettyprint) <0)
+ if (xml2file_recurse(f, xc, level+1, prettyprint, fn) <0)
goto done;
}
if (prettyprint && hasbody==0)
- fprintf(f, "%*s", level*XML_INDENT, "");
- fprintf(f, "");
+ (*fn)(f, "%*s", level*XML_INDENT, "");
+ (*fn)(f, "");
if (namespace)
- fprintf(f, "%s:", namespace);
- fprintf(f, "%s>", name);
+ (*fn)(f, "%s:", namespace);
+ (*fn)(f, "%s>", name);
}
if (prettyprint)
- fprintf(f, "\n");
+ (*fn)(f, "\n");
break;
default:
break;
@@ -194,6 +196,42 @@ clicon_xml2file(FILE *f,
return retval;
}
+/*! Print an XML tree structure to an output stream and encode chars "<>&"
+ *
+ * @param[in] f UNIX output stream
+ * @param[in] xn clicon xml tree
+ * @param[in] level how many spaces to insert before each line
+ * @param[in] prettyprint insert \n and spaces tomake the xml more readable.
+ * @see clicon_xml2cbuf print to a cbuf string
+ * @see clicon_xml2cbuf_cb print using a callback
+ */
+int
+clicon_xml2file(FILE *f,
+ cxobj *x,
+ int level,
+ int prettyprint)
+{
+ return xml2file_recurse(f, x, level, prettyprint, fprintf);
+}
+
+/*! Print an XML tree structure to an output stream and encode chars "<>&"
+ *
+ * @param[in] f UNIX output stream
+ * @param[in] xn clicon xml tree
+ * @param[in] level how many spaces to insert before each line
+ * @param[in] prettyprint insert \n and spaces tomake the xml more readable.
+ * @see clicon_xml2cbuf
+ */
+int
+clicon_xml2file_cb(FILE *f,
+ cxobj *x,
+ int level,
+ int prettyprint,
+ clicon_output_cb *fn)
+{
+ return xml2file_recurse(f, x, level, prettyprint, fn);
+}
+
/*! Print an XML tree structure to an output stream
*
* Uses clicon_xml2file internally
@@ -201,13 +239,13 @@ clicon_xml2file(FILE *f,
* @param[in] f UNIX output stream
* @param[in] xn clicon xml tree
* @see clicon_xml2cbuf
- * @see clicon_xml2file
+ * @see clicon_xml2cbuf_cb print using a callback
*/
int
xml_print(FILE *f,
- cxobj *xn)
+ cxobj *x)
{
- return clicon_xml2file(f, xn, 0, 1);
+ return xml2file_recurse(f, x, 0, 1, fprintf);
}
/*! Print an XML tree structure to a cligen buffer and encode chars "<>&"
diff --git a/lib/src/clixon_xml_map.c b/lib/src/clixon_xml_map.c
index 8a9a441c..29cb67f1 100644
--- a/lib/src/clixon_xml_map.c
+++ b/lib/src/clixon_xml_map.c
@@ -129,19 +129,26 @@ tleaf(cxobj *x)
return (xml_child_nr_notype(xc, CX_ATTR) == 0);
}
-/*! Translate XML -> TEXT
+/*! Translate XML to a "pseudo-code" textual format using a callback - internal function
+ * @param[in] f File to print to
+ * @param[in] x XML object to print
+ * @param[in] fn Callback to make print function
* @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,
- cxobj *x,
- int level)
+static int
+xml2txt_recurse(FILE *f,
+ cxobj *x,
+ clicon_output_cb *fn,
+ int level)
{
cxobj *xc = NULL;
int children=0;
int retval = -1;
+ if (f == NULL || x == NULL || fn == NULL){
+ clicon_err(OE_XML, EINVAL, "f, x or fn is NULL");
+ goto done;
+ }
xc = NULL; /* count children (elements and bodies, not attributes) */
while ((xc = xml_child_each(x, xc, -1)) != NULL)
if (xml_type(xc) == CX_ELMNT || xml_type(xc) == CX_BODY)
@@ -149,48 +156,76 @@ xml2txt(FILE *f,
if (!children){ /* If no children print line */
switch (xml_type(x)){
case CX_BODY:
- fprintf(f, "%s;\n", xml_value(x));
+ (*fn)(f, "%s;\n", xml_value(x));
break;
case CX_ELMNT:
- fprintf(f, "%*s;\n", 4*level, xml_name(x));
+ (*fn)(f, "%*s;\n", 4*level, xml_name(x));
break;
default:
break;
}
goto ok;
}
- fprintf(f, "%*s", 4*level, "");
- fprintf(f, "%s ", xml_name(x));
+ (*fn)(f, "%*s", 4*level, "");
+ (*fn)(f, "%s ", xml_name(x));
if (!tleaf(x))
- fprintf(f, "{\n");
+ (*fn)(f, "{\n");
xc = NULL;
while ((xc = xml_child_each(x, xc, -1)) != NULL){
if (xml_type(xc) == CX_ELMNT || xml_type(xc) == CX_BODY)
- if (xml2txt(f, xc, level+1) < 0)
+ if (xml2txt_recurse(f, xc, fn, level+1) < 0)
break;
}
if (!tleaf(x))
- fprintf(f, "%*s}\n", 4*level, "");
+ (*fn)(f, "%*s}\n", 4*level, "");
ok:
retval = 0;
- // done:
+ done:
return retval;
}
+/*! Translate XML to a "pseudo-code" textual format using a callback
+ * @param[in] f File to print to
+ * @param[in] x XML object to print
+ * @param[in] fn Callback to make print function
+ */
+int
+xml2txt_cb(FILE *f,
+ cxobj *x,
+ clicon_output_cb *fn)
+{
+ return xml2txt_recurse(f, x, fn, 0);
+}
+
+/*! Translate XML to a "pseudo-code" textual format using stdio file
+ * @param[in] f File to print to
+ * @param[in] x XML object to print
+ * @param[in] level print 4 spaces per level in front of each line
+ * @see xml2txt_cb
+ */
+int
+xml2txt(FILE *f,
+ cxobj *x,
+ int level)
+{
+ return xml2txt_recurse(f, x, fprintf, 0);
+}
+
/*! Translate from XML to CLI commands
* Howto: join strings and pass them down.
* Identify unique/index keywords for correct set syntax.
- * Args:
- * @param[in] f Where to print cli commands
- * @param[in] x XML Parse-tree (to translate)
- * @param[in] prepend0 Print this text in front of all commands.
- * @param[in] gt option to steer cli syntax
+ * @param[in] f Where to print cli commands
+ * @param[in] x XML Parse-tree (to translate)
+ * @param[in] prepend Print this text in front of all commands.
+ * @param[in] gt option to steer cli syntax
+ * @param[in] fn Callback to make print function
*/
int
-xml2cli(FILE *f,
- cxobj *x,
- char *prepend0,
- enum genmodel_type gt)
+xml2cli_recurse(FILE *f,
+ cxobj *x,
+ char *prepend,
+ enum genmodel_type gt,
+ clicon_output_cb *fn)
{
int retval = -1;
cxobj *xe = NULL;
@@ -204,17 +239,17 @@ xml2cli(FILE *f,
if ((ys = xml_spec(x)) == NULL)
goto ok;
if (yang_keyword_get(ys) == Y_LEAF || yang_keyword_get(ys) == Y_LEAF_LIST){
- if (prepend0)
- fprintf(f, "%s", prepend0);
+ if (prepend)
+ (*fn)(f, "%s", prepend);
if (gt == GT_ALL || gt == GT_VARS || gt == GT_HIDE)
- fprintf(f, "%s ", xml_name(x));
+ (*fn)(f, "%s ", xml_name(x));
if ((body = xml_body(x)) != NULL){
if (index(body, ' '))
- fprintf(f, "\"%s\"", body);
+ (*fn)(f, "\"%s\"", body);
else
- fprintf(f, "%s", body);
+ (*fn)(f, "%s", body);
}
- fprintf(f, "\n");
+ (*fn)(f, "\n");
goto ok;
}
/* Create prepend variable string */
@@ -222,8 +257,8 @@ xml2cli(FILE *f,
clicon_err(OE_PLUGIN, errno, "cbuf_new");
goto done;
}
- if (prepend0)
- cprintf(cbpre, "%s", prepend0);
+ if (prepend)
+ cprintf(cbpre, "%s", prepend);
/* If non-presence container && HIDE mode && only child is
* a list, then skip container keyword
@@ -251,11 +286,11 @@ xml2cli(FILE *f,
if ((match = yang_key_match(ys, xml_name(xe))) < 0)
goto done;
if (match){
- fprintf(f, "%s\n", cbuf_get(cbpre));
+ (*fn)(f, "%s\n", cbuf_get(cbpre));
continue; /* Not key itself */
}
}
- if (xml2cli(f, xe, cbuf_get(cbpre), gt) < 0)
+ if (xml2cli_recurse(f, xe, cbuf_get(cbpre), gt, fn) < 0)
goto done;
}
ok:
@@ -266,6 +301,43 @@ xml2cli(FILE *f,
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] f Where to print cli commands
+ * @param[in] x XML Parse-tree (to translate)
+ * @param[in] prepend Print this text in front of all commands.
+ * @param[in] gt option to steer cli syntax
+ * @param[in] fn Callback to make print function
+ */
+int
+xml2cli_cb(FILE *f,
+ cxobj *x,
+ char *prepend,
+ enum genmodel_type gt,
+ clicon_output_cb *fn)
+{
+ return xml2cli_recurse(f, x, prepend, gt, fn);
+}
+
+/*! Translate from XML to CLI commands
+ * Howto: join strings and pass them down.
+ * Identify unique/index keywords for correct set syntax.
+ * Args:
+ * @param[in] f Where to print cli commands
+ * @param[in] x XML Parse-tree (to translate)
+ * @param[in] prepend Print this text in front of all commands.
+ * @param[in] gt option to steer cli syntax
+ */
+int
+xml2cli(FILE *f,
+ cxobj *x,
+ char *prepend,
+ enum genmodel_type gt)
+{
+ return xml2cli_recurse(f, x, prepend, gt, fprintf);
+}
+
/*! Translate a single xml node to a cligen variable vector. Note not recursive
* @param[in] xt XML tree containing one top node
* @param[in] ys Yang spec containing type specification of top-node of xt
diff --git a/lib/src/clixon_yang.c b/lib/src/clixon_yang.c
index db23a747..9bbfffcd 100644
--- a/lib/src/clixon_yang.c
+++ b/lib/src/clixon_yang.c
@@ -1245,13 +1245,15 @@ quotedstring(char *s)
}
/*! Print yang specification to file
- * @param[in] f File to print to.
- * @param[in] yn Yang node to print
+ * @param[in] f File to print to.
+ * @param[in] yn Yang node to print
+ * @param[in] fn Callback to make print function
* @see yang_print_cbuf
*/
int
-yang_print(FILE *f,
- yang_stmt *yn)
+yang_print_cb(FILE *f,
+ yang_stmt *yn,
+ clicon_output_cb *fn)
{
int retval = -1;
cbuf *cb = NULL;
@@ -1262,7 +1264,7 @@ yang_print(FILE *f,
}
if (yang_print_cbuf(cb, yn, 0) < 0)
goto done;
- fprintf(f, "%s", cbuf_get(cb));
+ (*fn)(f, "%s", cbuf_get(cb));
if (cb)
cbuf_free(cb);
retval = 0;
@@ -1270,6 +1272,18 @@ yang_print(FILE *f,
return retval;
}
+/*! Print yang specification to file
+ * @param[in] f File to print to.
+ * @param[in] yn Yang node to print
+ * @see yang_print_cbuf
+ */
+int
+yang_print(FILE *f,
+ yang_stmt *yn)
+{
+ return yang_print_cb(f, yn, fprintf);
+}
+
/*! Print yang specification to cligen buf
* @param[in] cb Cligen buffer. This is where the pretty print is.
* @param[in] yn Yang node to print