Text syntax parser/loader
Leaf-list syntax using: "id [ leaf leaf ...]" syntax for output and input Variables using \n\r in text Added clixon_xvec_merge()
This commit is contained in:
parent
820ed5686b
commit
87719c623c
10 changed files with 257 additions and 66 deletions
|
|
@ -40,7 +40,7 @@ Planned: July 2022
|
||||||
|
|
||||||
### New features
|
### New features
|
||||||
|
|
||||||
* Text syntax parser/loader
|
* Text syntax parser and loader
|
||||||
* Added new text syntax parsing and loading from CLI
|
* Added new text syntax parsing and loading from CLI
|
||||||
* Text output format changed:
|
* Text output format changed:
|
||||||
* Namespace/modulename added to top-level
|
* Namespace/modulename added to top-level
|
||||||
|
|
|
||||||
|
|
@ -163,3 +163,10 @@
|
||||||
* If not set, client will exit
|
* If not set, client will exit
|
||||||
*/
|
*/
|
||||||
#define PROTO_RESTART_RECONNECT
|
#define PROTO_RESTART_RECONNECT
|
||||||
|
|
||||||
|
/*! Text output keys as identifiers instead of ordinary leafs
|
||||||
|
* Ie: list a { val 42; } If defined
|
||||||
|
* instead of list { keyname a; val 42; } If undefined
|
||||||
|
* Problem is, Parser is YANG unaware therefore doe not know "keyname"
|
||||||
|
*/
|
||||||
|
#undef TEXT_LIST_KEYS
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,7 @@ cxobj *clixon_xvec_i(clixon_xvec *xv, int i);
|
||||||
int clixon_xvec_extract(clixon_xvec *xv, cxobj ***xvcec, int *xlen, int *xmax);
|
int clixon_xvec_extract(clixon_xvec *xv, cxobj ***xvcec, int *xlen, int *xmax);
|
||||||
int clixon_xvec_append(clixon_xvec *xv, cxobj *x);
|
int clixon_xvec_append(clixon_xvec *xv, cxobj *x);
|
||||||
int clixon_xvec_prepend(clixon_xvec *xv, cxobj *x);
|
int clixon_xvec_prepend(clixon_xvec *xv, cxobj *x);
|
||||||
|
int clixon_xvec_merge(clixon_xvec *xv0, clixon_xvec *xv1);
|
||||||
int clixon_xvec_insert_pos(clixon_xvec *xv, cxobj *x, int i);
|
int clixon_xvec_insert_pos(clixon_xvec *xv, cxobj *x, int i);
|
||||||
int clixon_xvec_rm_pos(clixon_xvec *xv, int i);
|
int clixon_xvec_rm_pos(clixon_xvec *xv, int i);
|
||||||
int clixon_xvec_print(FILE *f, clixon_xvec *xv);
|
int clixon_xvec_print(FILE *f, clixon_xvec *xv);
|
||||||
|
|
|
||||||
|
|
@ -100,25 +100,33 @@ tleaf(cxobj *x)
|
||||||
* @param[in] xn XML object to print
|
* @param[in] xn XML object to print
|
||||||
* @param[in] fn Callback to make print function
|
* @param[in] fn Callback to make print function
|
||||||
* @param[in] f File to print to
|
* @param[in] f File to print to
|
||||||
* @param[in] level print 4 spaces per level in front of each line
|
* @param[in] level Print 4 spaces per level in front of each line
|
||||||
* @see xml2txt XXX why are these different?
|
* @param[in,out] leaflist Leaflist state for []
|
||||||
|
* leaflist state:
|
||||||
|
* 0: No leaflist
|
||||||
|
* 1: In leaflist
|
||||||
*/
|
*/
|
||||||
int
|
static int
|
||||||
xml2txt(cxobj *xn,
|
xml2txt1(cxobj *xn,
|
||||||
clicon_output_cb *fn,
|
clicon_output_cb *fn,
|
||||||
FILE *f,
|
FILE *f,
|
||||||
int level)
|
int level,
|
||||||
|
int *leaflist)
|
||||||
{
|
{
|
||||||
cxobj *xc = NULL;
|
cxobj *xc = NULL;
|
||||||
int children=0;
|
int children=0;
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
int exist = 0;
|
int exist = 0;
|
||||||
yang_stmt *yn;
|
yang_stmt *yn;
|
||||||
yang_stmt *yp;
|
yang_stmt *yp = NULL;
|
||||||
yang_stmt *ymod;
|
yang_stmt *ymod;
|
||||||
yang_stmt *ypmod;
|
yang_stmt *ypmod;
|
||||||
char *prefix = NULL;
|
char *prefix = NULL;
|
||||||
char *value;
|
char *value;
|
||||||
|
#ifdef TEXT_LIST_KEYS
|
||||||
|
cg_var *cvi;
|
||||||
|
cvec *cvk = NULL; /* vector of index keys */
|
||||||
|
#endif
|
||||||
|
|
||||||
if (xn == NULL || fn == NULL){
|
if (xn == NULL || fn == NULL){
|
||||||
clicon_err(OE_XML, EINVAL, "xn or fn is NULL");
|
clicon_err(OE_XML, EINVAL, "xn or fn is NULL");
|
||||||
|
|
@ -141,41 +149,85 @@ xml2txt(cxobj *xn,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
prefix = yang_argument_get(ymod);
|
prefix = yang_argument_get(ymod);
|
||||||
|
#ifdef TEXT_LIST_KEYS
|
||||||
|
if (yang_keyword_get(yn) == Y_LIST){
|
||||||
|
if ((cvk = yang_cvec_get(yn)) == NULL){
|
||||||
|
clicon_err(OE_YANG, 0, "No keys");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
xc = NULL; /* count children (elements and bodies, not attributes) */
|
xc = NULL; /* count children (elements and bodies, not attributes) */
|
||||||
while ((xc = xml_child_each(xn, xc, -1)) != NULL)
|
while ((xc = xml_child_each(xn, xc, -1)) != NULL)
|
||||||
if (xml_type(xc) == CX_ELMNT || xml_type(xc) == CX_BODY)
|
if (xml_type(xc) == CX_ELMNT || xml_type(xc) == CX_BODY)
|
||||||
children++;
|
children++;
|
||||||
if (!children){ /* If no children print line */
|
if (children == 0){ /* If no children print line */
|
||||||
switch (xml_type(xn)){
|
switch (xml_type(xn)){
|
||||||
case CX_BODY:
|
case CX_BODY:
|
||||||
value = xml_value(xn);
|
value = xml_value(xn);
|
||||||
/* Add quotes if string contains spaces */
|
/* Add quotes if string contains spaces */
|
||||||
if (index(value, ' ') != NULL)
|
if (*leaflist)
|
||||||
|
(*fn)(f, "%*s%s\n", 4*level, "", xml_value(xn));
|
||||||
|
else if (index(value, ' ') != NULL)
|
||||||
(*fn)(f, "\"%s\";\n", xml_value(xn));
|
(*fn)(f, "\"%s\";\n", xml_value(xn));
|
||||||
else
|
else
|
||||||
(*fn)(f, "%s;\n", xml_value(xn));
|
(*fn)(f, "%s;\n", xml_value(xn));
|
||||||
break;
|
break;
|
||||||
case CX_ELMNT:
|
case CX_ELMNT:
|
||||||
(*fn)(f, "%*s%s;\n", 4*level, "", xml_name(xn));
|
(*fn)(f, "%*s%s", 4*level, "", xml_name(xn));
|
||||||
|
#ifdef TEXT_LIST_KEYS
|
||||||
|
cvi = NULL; /* Lists only */
|
||||||
|
while ((cvi = cvec_each(cvk, cvi)) != NULL) {
|
||||||
|
if ((xc = xml_find_type(xn, NULL, cv_string_get(cvi), CX_ELMNT)) != NULL)
|
||||||
|
(*fn)(f, " %s", xml_body(xc));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
(*fn)(f, ";\n");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
goto ok;
|
goto ok;
|
||||||
}
|
}
|
||||||
|
if (*leaflist == 0){
|
||||||
(*fn)(f, "%*s", 4*level, "");
|
(*fn)(f, "%*s", 4*level, "");
|
||||||
if (prefix)
|
if (prefix)
|
||||||
(*fn)(f, "%s:", prefix);
|
(*fn)(f, "%s:", prefix);
|
||||||
(*fn)(f, "%s ", xml_name(xn));
|
(*fn)(f, "%s", xml_name(xn));
|
||||||
if (!tleaf(xn))
|
}
|
||||||
(*fn)(f, "{\n");
|
#ifdef TEXT_LIST_KEYS
|
||||||
|
cvi = NULL; /* Lists only */
|
||||||
|
while ((cvi = cvec_each(cvk, cvi)) != NULL) {
|
||||||
|
if ((xc = xml_find_type(xn, NULL, cv_string_get(cvi), CX_ELMNT)) != NULL)
|
||||||
|
(*fn)(f, " %s", xml_body(xc));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (yn && yang_keyword_get(yn) == Y_LEAF_LIST && *leaflist)
|
||||||
|
;
|
||||||
|
else if (yn && yang_keyword_get(yn) == Y_LEAF_LIST && *leaflist == 0){
|
||||||
|
*leaflist = 1;
|
||||||
|
(*fn)(f, " [\n");
|
||||||
|
}
|
||||||
|
else if (!tleaf(xn))
|
||||||
|
(*fn)(f, " {\n");
|
||||||
|
else
|
||||||
|
(*fn)(f, " ");
|
||||||
xc = NULL;
|
xc = NULL;
|
||||||
while ((xc = xml_child_each(xn, xc, -1)) != NULL){
|
while ((xc = xml_child_each(xn, xc, -1)) != NULL){
|
||||||
if (xml_type(xc) == CX_ELMNT || xml_type(xc) == CX_BODY)
|
if (xml_type(xc) == CX_ELMNT || xml_type(xc) == CX_BODY){
|
||||||
if (xml2txt(xc, fn, f, level+1) < 0)
|
#ifdef TEXT_LIST_KEYS
|
||||||
|
if (yang_key_match(yn, xml_name(xc), NULL))
|
||||||
|
continue; /* Skip keys, already printed */
|
||||||
|
#endif
|
||||||
|
if (xml2txt1(xc, fn, f, level+1, leaflist) < 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (yn && yang_keyword_get(yn) != Y_LEAF_LIST && *leaflist != 0){
|
||||||
|
*leaflist = 0;
|
||||||
|
(*fn)(f, "%*s\n", 4*(level+1), "]");
|
||||||
|
}
|
||||||
if (!tleaf(xn))
|
if (!tleaf(xn))
|
||||||
(*fn)(f, "%*s}\n", 4*level, "");
|
(*fn)(f, "%*s}\n", 4*level, "");
|
||||||
ok:
|
ok:
|
||||||
|
|
@ -184,6 +236,23 @@ xml2txt(cxobj *xn,
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Translate XML to a "pseudo-code" textual format using a callback
|
||||||
|
* @param[in] xn XML object to print
|
||||||
|
* @param[in] fn Callback to make print function
|
||||||
|
* @param[in] f File to print to
|
||||||
|
* @param[in] level Print 4 spaces per level in front of each line
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
xml2txt(cxobj *xn,
|
||||||
|
clicon_output_cb *fn,
|
||||||
|
FILE *f,
|
||||||
|
int level)
|
||||||
|
{
|
||||||
|
int leaflist = 0;
|
||||||
|
|
||||||
|
return xml2txt1(xn, fn, f, level, &leaflist);
|
||||||
|
}
|
||||||
|
|
||||||
/*! Parse a string containing text syntax and return an XML tree
|
/*! Parse a string containing text syntax and return an XML tree
|
||||||
*
|
*
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -100,8 +100,11 @@ int clixon_text_syntax_parsewrap(void)
|
||||||
<COMMENT><<EOF>> { return MY_EOF; }
|
<COMMENT><<EOF>> { return MY_EOF; }
|
||||||
<COMMENT>[^\n]+
|
<COMMENT>[^\n]+
|
||||||
|
|
||||||
|
<STRING>\n { _TS->ts_linenum++;
|
||||||
|
clixon_text_syntax_parselval.string = strdup(yytext);
|
||||||
|
return TOKEN;}
|
||||||
<STRING>\" { BEGIN(_TS->ts_lex_state); return *yytext; }
|
<STRING>\" { BEGIN(_TS->ts_lex_state); return *yytext; }
|
||||||
<STRING>[^\n\r\"]+ { clixon_text_syntax_parselval.string = strdup(yytext);
|
<STRING>[^\n\"]+ { clixon_text_syntax_parselval.string = strdup(yytext);
|
||||||
return TOKEN; }
|
return TOKEN; }
|
||||||
<STRING>. { return -1; }
|
<STRING>. { return -1; }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,7 @@
|
||||||
%type <stack> stmt
|
%type <stack> stmt
|
||||||
%type <stack> id
|
%type <stack> id
|
||||||
%type <string> value
|
%type <string> value
|
||||||
|
%type <stack> leaflist
|
||||||
|
|
||||||
%start top
|
%start top
|
||||||
|
|
||||||
|
|
@ -80,7 +81,7 @@
|
||||||
#include "clixon_text_syntax_parse.h"
|
#include "clixon_text_syntax_parse.h"
|
||||||
|
|
||||||
/* Enable for debugging, steals some cycles otherwise */
|
/* Enable for debugging, steals some cycles otherwise */
|
||||||
#if 0
|
#if 1
|
||||||
#define _PARSE_DEBUG(s) clicon_debug(1,(s))
|
#define _PARSE_DEBUG(s) clicon_debug(1,(s))
|
||||||
#else
|
#else
|
||||||
#define _PARSE_DEBUG(s)
|
#define _PARSE_DEBUG(s)
|
||||||
|
|
@ -99,22 +100,21 @@ clixon_text_syntax_parseerror(void *arg,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static cxobj*
|
||||||
text_add_value(cxobj *xn,
|
text_add_value(cxobj *xn,
|
||||||
char *value)
|
char *value)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
|
||||||
cxobj *xb = NULL;
|
cxobj *xb = NULL;
|
||||||
|
|
||||||
if ((xb = xml_new("body", xn, CX_BODY)) == NULL)
|
if ((xb = xml_new("body", xn, CX_BODY)) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
if (xml_value_set(xb, value) < 0){
|
if (xml_value_set(xb, value) < 0){
|
||||||
xml_free(xb);
|
xml_free(xb);
|
||||||
|
xb = NULL;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
retval = 0;
|
|
||||||
done:
|
done:
|
||||||
return retval;
|
return xb;
|
||||||
}
|
}
|
||||||
|
|
||||||
static cxobj*
|
static cxobj*
|
||||||
|
|
@ -151,17 +151,64 @@ text_create_node(clixon_text_syntax_yacc *ts,
|
||||||
return xn;
|
return xn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char*
|
||||||
|
strjoin(char *str0,
|
||||||
|
char *str1)
|
||||||
|
{
|
||||||
|
size_t len0;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
len0 = strlen(str0);
|
||||||
|
len = len0 + strlen(str1) + 1;
|
||||||
|
if ((str0 = realloc(str0, len)) == NULL){
|
||||||
|
clicon_err(OE_YANG, errno, "realloc");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
strcpy(str0+len0, str1);
|
||||||
|
return str0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Given a vector of XML bodies, transform it to a vector of ELEMENT entries
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
text_leaflist_create(clixon_xvec *xvec0,
|
||||||
|
cxobj *x1,
|
||||||
|
clixon_xvec *xvec1)
|
||||||
|
{
|
||||||
|
int retval = -1;
|
||||||
|
cxobj *xb;
|
||||||
|
cxobj *x2;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i=0; i<clixon_xvec_len(xvec1); i++){
|
||||||
|
xb = clixon_xvec_i(xvec1, i);
|
||||||
|
if ((x2 = xml_dup(x1)) == NULL)
|
||||||
|
goto done;
|
||||||
|
if (xml_addsub(x2, xb) < 0)
|
||||||
|
goto done;
|
||||||
|
if (clixon_xvec_append(xvec0, x2) < 0)
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
retval = 0;
|
||||||
|
done:
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
%}
|
%}
|
||||||
|
|
||||||
%%
|
%%
|
||||||
|
|
||||||
top : stmt MY_EOF { _PARSE_DEBUG("top->stmt");
|
top : stmt MY_EOF { _PARSE_DEBUG("top->stmt");
|
||||||
if (xml_addsub(_TS->ts_xtop, $1) < 0) YYERROR;
|
// if (xml_addsub(_TS->ts_xtop, $1) < 0) YYERROR;
|
||||||
|
if (clixon_child_xvec_append(_TS->ts_xtop, $1) < 0) YYERROR;
|
||||||
|
clixon_xvec_free($1);
|
||||||
YYACCEPT; }
|
YYACCEPT; }
|
||||||
;
|
;
|
||||||
|
|
||||||
stmts : stmts stmt { _PARSE_DEBUG("stmts->stmts stmt");
|
stmts : stmts stmt { _PARSE_DEBUG("stmts->stmts stmt");
|
||||||
if (clixon_xvec_append($1, $2) < 0) YYERROR;
|
// if (clixon_xvec_append($1, $2) < 0) YYERROR;
|
||||||
|
if (clixon_xvec_merge($1, $2) < 0) YYERROR;
|
||||||
|
clixon_xvec_free($2);
|
||||||
$$ = $1;
|
$$ = $1;
|
||||||
}
|
}
|
||||||
| { _PARSE_DEBUG("stmts->stmt");
|
| { _PARSE_DEBUG("stmts->stmt");
|
||||||
|
|
@ -170,34 +217,57 @@ stmts : stmts stmt { _PARSE_DEBUG("stmts->stmts stmt");
|
||||||
;
|
;
|
||||||
|
|
||||||
stmt : id value ';' { _PARSE_DEBUG("stmt-> id value ;");
|
stmt : id value ';' { _PARSE_DEBUG("stmt-> id value ;");
|
||||||
if (text_add_value($1, $2) < 0) YYERROR;
|
if (text_add_value($1, $2) == NULL) YYERROR;
|
||||||
$$ = $1;
|
free($2);
|
||||||
|
if (($$ = clixon_xvec_new()) == NULL) YYERROR;
|
||||||
|
if (clixon_xvec_append($$, $1) < 0) YYERROR;
|
||||||
}
|
}
|
||||||
| id '"' value '"' ';' { _PARSE_DEBUG("stmt-> id \" value \" ;");
|
| id '"' value '"' ';' { _PARSE_DEBUG("stmt-> id \" value \" ;");
|
||||||
if (text_add_value($1, $3) < 0) YYERROR;
|
if (text_add_value($1, $3) == NULL) YYERROR;
|
||||||
$$ = $1;
|
free($3);
|
||||||
|
if (($$ = clixon_xvec_new()) == NULL) YYERROR;
|
||||||
|
if (clixon_xvec_append($$, $1) < 0) YYERROR;
|
||||||
}
|
}
|
||||||
| id '{' stmts '}' { _PARSE_DEBUG("stmt-> id { stmts }");
|
| id '{' stmts '}' { _PARSE_DEBUG("stmt-> id { stmts }");
|
||||||
if (clixon_child_xvec_append($1, $3) < 0) YYERROR;
|
if (clixon_child_xvec_append($1, $3) < 0) YYERROR;
|
||||||
clixon_xvec_free($3);
|
clixon_xvec_free($3);
|
||||||
$$ = $1;
|
if (($$ = clixon_xvec_new()) == NULL) YYERROR;
|
||||||
|
if (clixon_xvec_append($$, $1) < 0) YYERROR;
|
||||||
|
}
|
||||||
|
| id '[' leaflist ']'
|
||||||
|
{ _PARSE_DEBUG("stmt-> id [ leaflist ]");
|
||||||
|
if (($$ = clixon_xvec_new()) == NULL) YYERROR;
|
||||||
|
if (text_leaflist_create($$, $1, $3) < 0) YYERROR;
|
||||||
|
xml_free($1);
|
||||||
|
clixon_xvec_free($3);
|
||||||
}
|
}
|
||||||
|
|
||||||
| id '[' values ']' { _PARSE_DEBUG("stmt-> id [ values ]"); }
|
|
||||||
;
|
;
|
||||||
|
|
||||||
id : TOKEN { _PARSE_DEBUG("id->TOKEN");
|
id : TOKEN { _PARSE_DEBUG("id->TOKEN");
|
||||||
if (($$ = text_create_node(_TS, $1)) == NULL) YYERROR;;
|
if (($$ = text_create_node(_TS, $1)) == NULL) YYERROR;
|
||||||
|
free($1);
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
values : values TOKEN { _PARSE_DEBUG("values->values TOKEN"); }
|
value : value TOKEN { _PARSE_DEBUG("value->value TOKEN");
|
||||||
| { _PARSE_DEBUG("values->"); }
|
$$ = strjoin($1, $2); free($2);}
|
||||||
|
| TOKEN { _PARSE_DEBUG("value->TOKEN");
|
||||||
|
$$ = $1; }
|
||||||
;
|
;
|
||||||
|
|
||||||
value : TOKEN { _PARSE_DEBUG("value->TOKEN"); $$ = $1; }
|
leaflist : leaflist TOKEN { _PARSE_DEBUG("leaflist->leaflist TOKEN");
|
||||||
|
cxobj* x;
|
||||||
|
if ((x = text_add_value(NULL, $2)) == NULL) YYERROR;;
|
||||||
|
free($2);
|
||||||
|
if (clixon_xvec_append($1, x) < 0) YYERROR;
|
||||||
|
$$ = $1;
|
||||||
|
}
|
||||||
|
| { _PARSE_DEBUG("leaflist->");
|
||||||
|
if (($$ = clixon_xvec_new()) == NULL) YYERROR;
|
||||||
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
%%
|
%%
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1056,7 +1056,6 @@ clixon_child_xvec_append(cxobj *xn,
|
||||||
for (i=0; i<clixon_xvec_len(xv); i++){
|
for (i=0; i<clixon_xvec_len(xv); i++){
|
||||||
xc = clixon_xvec_i(xv, i);
|
xc = clixon_xvec_i(xv, i);
|
||||||
if (xml_addsub(xn, xc) < 0)
|
if (xml_addsub(xn, xc) < 0)
|
||||||
// if (xml_child_append(xn, xc) < 0)
|
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
|
||||||
|
|
@ -261,6 +261,36 @@ clixon_xvec_append(clixon_xvec *xv,
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Append a second clixon-xvec into a first
|
||||||
|
*
|
||||||
|
* @param[in,out] xv0 XML tree vector
|
||||||
|
* @param[in] xv1 XML tree (append this to vector)
|
||||||
|
* @retval 0 OK, with xv0 with new entries from xv1
|
||||||
|
* @retval -1 Error
|
||||||
|
* @code
|
||||||
|
* if (clixon_xvec_merge(xv0, xv1) < 0)
|
||||||
|
* err;
|
||||||
|
* @endcode
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
clixon_xvec_merge(clixon_xvec *xv0,
|
||||||
|
clixon_xvec *xv1)
|
||||||
|
{
|
||||||
|
int retval = -1;
|
||||||
|
cxobj *x;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i=0; i<clixon_xvec_len(xv1); i++){
|
||||||
|
x = clixon_xvec_i(xv1, i);
|
||||||
|
if (clixon_xvec_inc(xv0) < 0)
|
||||||
|
goto done;
|
||||||
|
xv0->xv_vec[xv0->xv_len-1] = x;
|
||||||
|
}
|
||||||
|
retval = 0;
|
||||||
|
done:
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
/*! Prepend a new xml tree to an existing xml vector first in the list
|
/*! Prepend a new xml tree to an existing xml vector first in the list
|
||||||
*
|
*
|
||||||
* @param[in] xv XML tree vector
|
* @param[in] xv XML tree vector
|
||||||
|
|
|
||||||
|
|
@ -16,13 +16,19 @@ module example{
|
||||||
/* Generic config data */
|
/* Generic config data */
|
||||||
container table{
|
container table{
|
||||||
list parameter{
|
list parameter{
|
||||||
key name;
|
key "name index";
|
||||||
leaf name{
|
leaf name{
|
||||||
type string;
|
type string;
|
||||||
}
|
}
|
||||||
|
leaf index{
|
||||||
|
type int32;
|
||||||
|
}
|
||||||
leaf value{
|
leaf value{
|
||||||
type string;
|
type string;
|
||||||
}
|
}
|
||||||
|
leaf-list array{
|
||||||
|
type string;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -32,11 +38,17 @@ cat <<EOF > $dir/x1.xml
|
||||||
<table xmlns="urn:example:clixon">
|
<table xmlns="urn:example:clixon">
|
||||||
<parameter>
|
<parameter>
|
||||||
<name>a</name>
|
<name>a</name>
|
||||||
<value>foo bar</value>
|
<index>0</index>
|
||||||
|
<value>foo bar\n
|
||||||
|
description</value>
|
||||||
</parameter>
|
</parameter>
|
||||||
<parameter>
|
<parameter>
|
||||||
<name>b</name>
|
<name>b</name>
|
||||||
|
<index>17</index>
|
||||||
<value>bar:fie</value>
|
<value>bar:fie</value>
|
||||||
|
<array>bar</array>
|
||||||
|
<array>fie</array>
|
||||||
|
<array>foo</array>
|
||||||
</parameter>
|
</parameter>
|
||||||
</table>
|
</table>
|
||||||
EOF
|
EOF
|
||||||
|
|
@ -45,11 +57,19 @@ cat <<EOF > $dir/x1.txt
|
||||||
example:table {
|
example:table {
|
||||||
parameter {
|
parameter {
|
||||||
name a;
|
name a;
|
||||||
value "foo bar";
|
index 0;
|
||||||
|
value "foo bar\n
|
||||||
|
description";
|
||||||
}
|
}
|
||||||
parameter {
|
parameter {
|
||||||
name b;
|
name b;
|
||||||
|
index 17;
|
||||||
value bar:fie;
|
value bar:fie;
|
||||||
|
array [
|
||||||
|
bar
|
||||||
|
fie
|
||||||
|
foo
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
|
|
|
||||||
|
|
@ -326,14 +326,6 @@ main(int argc,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Dump data structures (for debug) */
|
|
||||||
if (clicon_debug_get()){
|
|
||||||
cbuf_reset(cb);
|
|
||||||
xmltree2cbuf(cb, xt, 0);
|
|
||||||
fprintf(stderr, "%s\n", cbuf_get(cb));
|
|
||||||
cbuf_reset(cb);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 3. Validate data (if yspec) */
|
/* 3. Validate data (if yspec) */
|
||||||
if (validate){
|
if (validate){
|
||||||
if (validate_tree(h, xt, yspec) < 0)
|
if (validate_tree(h, xt, yspec) < 0)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue