* Yang Support of submodule, include and belongs-to.
* Improved unknown handling
* Configure option `CLICON_YANG_DIR` is changed from a single directory to a path of directories
* Note CLIXON_DATADIR (=/usr/local/share/clixon) need to be in the list
This commit is contained in:
parent
56da97cb5b
commit
39a5086218
47 changed files with 977 additions and 469 deletions
|
|
@ -9,10 +9,16 @@
|
|||
* More complete Yang parser
|
||||
* YANG parser cardinality checked (only modules level yet)
|
||||
* See https://github.com/clicon/clixon/issues/84
|
||||
* Support of submodule, include and belongs-to.
|
||||
* Openconfig yang specs parsed: https://github.com/openconfig/public
|
||||
* Improved unknown handling
|
||||
* `CLICON_YANG_DIR` is changed from a single directory to a path of directories
|
||||
* Note CLIXON_DATADIR (=/usr/local/share/clixon) need to be in the list
|
||||
|
||||
### API changes on existing features (you may need to change your code)
|
||||
* Yang parser is stricter (see above) which may break parsing of existing yang specs.
|
||||
* Yang parser functions have changed signatures. Please check the source if you call these functions.
|
||||
* Add `<CLICON_YANG_DIR>/usr/local/share/clixon</CLICON_YANG_DIR>` to your configuration file, or corresponding CLICON_DATADIR directory for Clixon system yang files.
|
||||
|
||||
### Minor changes
|
||||
* XML parser conformance to W3 spec
|
||||
|
|
|
|||
16
README.md
16
README.md
|
|
@ -25,7 +25,7 @@ support.
|
|||
* [Tests](test/)
|
||||
* [Docker](docker/)
|
||||
* [Roadmap](ROADMAP.md)
|
||||
* [Reference manual](http://www.clicon.org/doxygen/index.html) (Note: the link may not be up-to-date. It is better to build your own: `cd doc; make doc`)
|
||||
* [Reference manual](#reference)
|
||||
|
||||
Background
|
||||
==========
|
||||
|
|
@ -124,6 +124,10 @@ However, the following YANG syntax modules are not implemented:
|
|||
- action
|
||||
- belongs-to
|
||||
|
||||
Restrictions on Yang types are as follows:
|
||||
- The range statement does not support multiple values (RFC7895 sec 9.2.4)
|
||||
- Submodules cannot re-use a prefix in an import statement that is already used for another imported module in the module that the submodule belongs to.
|
||||
|
||||
Netconf
|
||||
=======
|
||||
Clixon implements the following NETCONF proposals or standards:
|
||||
|
|
@ -217,7 +221,6 @@ The tests outlines an example of three groups (taken from the RFC): admin, limit
|
|||
* limited: Read access (get and get-config)
|
||||
* guest: No access
|
||||
|
||||
|
||||
Runtime
|
||||
=======
|
||||
|
||||
|
|
@ -225,3 +228,12 @@ Runtime
|
|||
|
||||
The figure shows the SDK runtime of Clixon.
|
||||
|
||||
Reference
|
||||
=========
|
||||
A reference manual can be built using [Doxygen](http://www.doxygen.nl/index.html). You need to install doxygen and graphviz on your system.
|
||||
Build it in the doc directory and point the browser to `.../clixon/doc/html/index.html` as follows:
|
||||
```
|
||||
> cd doc
|
||||
> make doc
|
||||
> make graphs # detailed callgraphs
|
||||
```
|
||||
|
|
@ -264,7 +264,7 @@ nacm_load_external(clicon_handle h)
|
|||
}
|
||||
if ((yspec = yspec_new()) == NULL)
|
||||
goto done;
|
||||
if (yang_parse(h, NULL, "ietf-netconf-acm", CLIXON_DATADIR, NULL, yspec, NULL) < 0)
|
||||
if (yang_parse(h, NULL, "ietf-netconf-acm", NULL, yspec, NULL) < 0)
|
||||
goto done;
|
||||
fd = fileno(f);
|
||||
/* Read configfile */
|
||||
|
|
@ -753,11 +753,10 @@ main(int argc,
|
|||
/* Load main application yang specification either module or specific file
|
||||
* If -y <file> is given, it overrides main module */
|
||||
if (yang_filename){
|
||||
if (yang_spec_parse_file(h, yang_filename, clicon_yang_dir(h), yspec, NULL) < 0)
|
||||
if (yang_spec_parse_file(h, yang_filename, yspec, NULL) < 0)
|
||||
goto done;
|
||||
}
|
||||
else if (yang_spec_parse_module(h, clicon_yang_module_main(h),
|
||||
clicon_yang_dir(h),
|
||||
clicon_yang_module_revision(h),
|
||||
yspec, NULL) < 0)
|
||||
goto done;
|
||||
|
|
@ -770,11 +769,11 @@ main(int argc,
|
|||
goto done;
|
||||
/* Load yang Restconf stream discovery */
|
||||
if (clicon_option_bool(h, "CLICON_STREAM_DISCOVERY_RFC8040") &&
|
||||
yang_spec_parse_module(h, "ietf-restconf-monitoring", CLIXON_DATADIR, NULL, yspec, NULL)< 0)
|
||||
yang_spec_parse_module(h, "ietf-restconf-monitoring", NULL, yspec, NULL)< 0)
|
||||
goto done;
|
||||
/* Load yang Netconf stream discovery */
|
||||
if (clicon_option_bool(h, "CLICON_STREAM_DISCOVERY_RFC5277") &&
|
||||
yang_spec_parse_module(h, "ietf-netconf-notification", CLIXON_DATADIR, NULL, yspec, NULL)< 0)
|
||||
yang_spec_parse_module(h, "ietf-netconf-notification", NULL, yspec, NULL)< 0)
|
||||
goto done;
|
||||
/* Set options: database dir and yangspec (could be hidden in connect?)*/
|
||||
if (xmldb_setopt(h, "dbdir", clicon_xmldb_dir(h)) < 0)
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@
|
|||
#include <assert.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#include <math.h> /* For pow() kludge in cvtype_max2str_dup2 */
|
||||
|
||||
/* cligen */
|
||||
#include <cligen/cligen.h>
|
||||
|
|
@ -169,6 +169,28 @@ static int yang2cli_stmt(clicon_handle h, yang_stmt *ys, cbuf *cb,
|
|||
static int yang2cli_var_union(clicon_handle h, yang_stmt *ys, char *origtype,
|
||||
yang_stmt *ytype, cbuf *cb, char *helptext);
|
||||
|
||||
/*! Patched maxstring to account for DEC64 types
|
||||
* @note kludge to fix overflow error -> Fix the original error in cvtype_max2str
|
||||
* by adding a fraction_digits argument.
|
||||
*/
|
||||
static char *
|
||||
cvtype_max2str_dup2(enum cv_type type,
|
||||
int fraction_digits)
|
||||
{
|
||||
int len;
|
||||
char *str;
|
||||
|
||||
if (type!=CGV_DEC64 || fraction_digits==0)
|
||||
return cvtype_max2str_dup(type);
|
||||
if ((len = cvtype_max2str(type, NULL, 0)) < 0)
|
||||
return NULL;
|
||||
if ((str = (char *)malloc(len+1)) == NULL)
|
||||
return NULL;
|
||||
memset(str, '\0', len+1);
|
||||
len = snprintf(str, len+1, "%" PRId64 ".0", (INT64_MAX/((int)pow(10,fraction_digits))));
|
||||
return str;
|
||||
}
|
||||
|
||||
/*! Generate CLI code for Yang leaf statement to CLIgen variable of specific type
|
||||
* Check for completion (of already existent values), ranges (eg range[min:max]) and
|
||||
* patterns, (eg regexp:"[0.9]*").
|
||||
|
|
@ -282,10 +304,12 @@ yang2cli_var_sub(clicon_handle h,
|
|||
}
|
||||
snprintf(r, 512, "%d", MAXPATHLEN);
|
||||
}
|
||||
else if ((r = cvtype_max2str_dup(cvtype)) == NULL){
|
||||
else {
|
||||
if ((r = cvtype_max2str_dup2(cvtype, fraction_digits)) == NULL){
|
||||
clicon_err(OE_UNIX, errno, "cvtype_max2str");
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
}
|
||||
cprintf(cb, "%s]", r); /* range */
|
||||
free(r);
|
||||
|
|
@ -410,7 +434,7 @@ yang2cli_var(clicon_handle h,
|
|||
cbuf *cb,
|
||||
char *helptext)
|
||||
{
|
||||
int retval = -1;
|
||||
int retval = -1;
|
||||
char *origtype;
|
||||
yang_stmt *yrestype; /* resolved type */
|
||||
char *restype; /* resolved type */
|
||||
|
|
@ -513,10 +537,12 @@ yang2cli_leaf(clicon_handle h,
|
|||
if (helptext)
|
||||
cprintf(cbuf, "(\"%s\")", helptext);
|
||||
cprintf(cbuf, " ");
|
||||
yang2cli_var(h, ys, cbuf, helptext);
|
||||
if (yang2cli_var(h, ys, cbuf, helptext) < 0)
|
||||
goto done;
|
||||
}
|
||||
else
|
||||
yang2cli_var(h, ys, cbuf, helptext);
|
||||
if (yang2cli_var(h, ys, cbuf, helptext) < 0)
|
||||
goto done;
|
||||
if (callback){
|
||||
if (cli_callback_generate(h, ys, cbuf) < 0)
|
||||
goto done;
|
||||
|
|
|
|||
|
|
@ -433,11 +433,10 @@ main(int argc, char **argv)
|
|||
/* Load main application yang specification either module or specific file
|
||||
* If -y <file> is given, it overrides main module */
|
||||
if (yang_filename){
|
||||
if (yang_spec_parse_file(h, yang_filename, clicon_yang_dir(h), yspec, &ymod) < 0)
|
||||
if (yang_spec_parse_file(h, yang_filename, yspec, &ymod) < 0)
|
||||
goto done;
|
||||
}
|
||||
else if (yang_spec_parse_module(h, clicon_yang_module_main(h),
|
||||
clicon_yang_dir(h),
|
||||
clicon_yang_module_revision(h),
|
||||
yspec, &ymod) < 0)
|
||||
goto done;
|
||||
|
|
|
|||
|
|
@ -447,11 +447,10 @@ main(int argc,
|
|||
/* Load main application yang specification either module or specific file
|
||||
* If -y <file> is given, it overrides main module */
|
||||
if (yang_filename){
|
||||
if (yang_spec_parse_file(h, yang_filename, clicon_yang_dir(h), yspec, NULL) < 0)
|
||||
if (yang_spec_parse_file(h, yang_filename, yspec, NULL) < 0)
|
||||
goto done;
|
||||
}
|
||||
else if (yang_spec_parse_module(h, clicon_yang_module_main(h),
|
||||
clicon_yang_dir(h),
|
||||
clicon_yang_module_revision(h),
|
||||
yspec, NULL) < 0)
|
||||
goto done;
|
||||
|
|
|
|||
|
|
@ -32,7 +32,13 @@
|
|||
***** END LICENSE BLOCK *****
|
||||
|
||||
*
|
||||
* Code for handling netconf rpc messages according to RFC 4741 and RFC 5277
|
||||
* Code for handling netconf rpc messages according to RFC 4741,5277,6241
|
||||
* All NETCONF protocol elements are defined in the following namespace:
|
||||
* urn:ietf:params:xml:ns:netconf:base:1.0
|
||||
* YANG defines an XML namespace for NETCONF <edit-config> operations,
|
||||
* <error-info> content, and the <action> element. The name of this
|
||||
* namespace is "urn:ietf:params:xml:ns:yang:1".
|
||||
*
|
||||
*****************************************************************************/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "clixon_config.h" /* generated by config & autoconf */
|
||||
|
|
@ -894,7 +900,7 @@ netconf_application_rpc(clicon_handle h,
|
|||
}
|
||||
cprintf(cb, "/%s:%s", xml_namespace(xn), xml_name(xn));
|
||||
/* Find yang rpc statement, return yang rpc statement if found */
|
||||
if (yang_abs_schema_nodeid(yspec, cbuf_get(cb), Y_RPC, &yrpc) < 0)
|
||||
if (yang_abs_schema_nodeid(yspec, xml_spec(xn), cbuf_get(cb), Y_RPC, &yrpc) < 0)
|
||||
goto done;
|
||||
/* Check if found */
|
||||
if (yrpc != NULL){
|
||||
|
|
|
|||
|
|
@ -517,7 +517,6 @@ main(int argc,
|
|||
char *sockpath;
|
||||
char *path;
|
||||
clicon_handle h;
|
||||
char *yangspec=NULL;
|
||||
char *dir;
|
||||
char *tmp;
|
||||
int logdst = CLICON_LOG_SYSLOG;
|
||||
|
|
@ -619,10 +618,6 @@ main(int argc,
|
|||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
/* Overwrite yang module with -y option */
|
||||
if (yangspec)
|
||||
clicon_option_str_set(h, "CLICON_YANG_MODULE_MAIN", yangspec);
|
||||
|
||||
/* Initialize plugins group */
|
||||
if ((dir = clicon_restconf_dir(h)) != NULL)
|
||||
if (clixon_plugins_load(h, CLIXON_PLUGIN_INIT, dir, NULL) < 0)
|
||||
|
|
@ -635,12 +630,11 @@ main(int argc,
|
|||
/* Load main application yang specification either module or specific file
|
||||
* If -y <file> is given, it overrides main module */
|
||||
if (yang_filename){
|
||||
if (yang_spec_parse_file(h, yang_filename, clicon_yang_dir(h), yspec, NULL) < 0)
|
||||
if (yang_spec_parse_file(h, yang_filename, yspec, NULL) < 0)
|
||||
goto done;
|
||||
}
|
||||
else if (yang_spec_parse_module(h, clicon_yang_module_main(h),
|
||||
clicon_yang_dir(h),
|
||||
clicon_yang_module_revision(h),
|
||||
clicon_yang_module_revision(h),
|
||||
yspec, NULL) < 0)
|
||||
goto done;
|
||||
|
||||
|
|
@ -649,10 +643,10 @@ main(int argc,
|
|||
goto done;
|
||||
/* Add system modules */
|
||||
if (clicon_option_bool(h, "CLICON_STREAM_DISCOVERY_RFC8040") &&
|
||||
yang_spec_parse_module(h, "ietf-restconf-monitoring", CLIXON_DATADIR, NULL, yspec, NULL)< 0)
|
||||
yang_spec_parse_module(h, "ietf-restconf-monitoring", NULL, yspec, NULL)< 0)
|
||||
goto done;
|
||||
if (clicon_option_bool(h, "CLICON_STREAM_DISCOVERY_RFC5277") &&
|
||||
yang_spec_parse_module(h, "ietf-netconf-notification", CLIXON_DATADIR, NULL, yspec, NULL)< 0)
|
||||
yang_spec_parse_module(h, "ietf-netconf-notification", NULL, yspec, NULL)< 0)
|
||||
goto done;
|
||||
/* Call start function in all plugins before we go interactive
|
||||
Pass all args after the standard options to plugin_start
|
||||
|
|
|
|||
11
configure
vendored
11
configure
vendored
|
|
@ -4391,15 +4391,14 @@ fi
|
|||
done
|
||||
|
||||
|
||||
# This is to find clixon system files in the source code and Makefile
|
||||
# CLIXON_DATADIR is where clixon installs the "system" yang files in yang/Makfile
|
||||
# This directory should most probably be included in each application,
|
||||
# so each application designer may need to place CLIXON_DATADIR in their config
|
||||
# (last in yang dir list):
|
||||
# <CLIXON-YANG-DIR>$CLIXON_DATADIR</CLIXON-YANG_DIR>
|
||||
|
||||
CLIXON_DATADIR="${prefix}/share/clixon"
|
||||
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define CLIXON_DATADIR "${CLIXON_DATADIR}"
|
||||
_ACEOF
|
||||
|
||||
|
||||
# Default location for config file
|
||||
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
|
|
|
|||
|
|
@ -199,10 +199,13 @@ AC_CHECK_LIB(dl, dlopen)
|
|||
|
||||
AC_CHECK_FUNCS(inet_aton sigaction sigvec strlcpy strsep strndup alphasort versionsort strverscmp)
|
||||
|
||||
# This is to find clixon system files in the source code and Makefile
|
||||
# CLIXON_DATADIR is where clixon installs the "system" yang files in yang/Makfile
|
||||
# This directory should most probably be included in each application,
|
||||
# so each application designer may need to place CLIXON_DATADIR in their config
|
||||
# (last in yang dir list):
|
||||
# <CLIXON-YANG-DIR>$CLIXON_DATADIR</CLIXON-YANG_DIR>
|
||||
AC_SUBST(CLIXON_DATADIR)
|
||||
CLIXON_DATADIR="${prefix}/share/clixon"
|
||||
AC_DEFINE_UNQUOTED(CLIXON_DATADIR, "${CLIXON_DATADIR}", [Clixon data dir for system yang files etc])
|
||||
|
||||
# Default location for config file
|
||||
AC_DEFINE_UNQUOTED(CLIXON_DEFAULT_CONFIG,"${CLIXON_DEFAULT_CONFIG}",[Location for apps to find default config file])
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ sudo ./datastore_client -d candidate -b /usr/local/var/example -p /home/olof/src
|
|||
#include <clixon/clixon.h>
|
||||
|
||||
/* Command line options to be passed to getopt(3) */
|
||||
#define DATASTORE_OPTS "hDd:p:b:y:m:"
|
||||
#define DATASTORE_OPTS "hDd:p:b:y:"
|
||||
|
||||
/*! usage
|
||||
*/
|
||||
|
|
@ -85,8 +85,7 @@ usage(char *argv0)
|
|||
"\t-d <db>\t\tDatabase name. Default: running. Alt: candidate,startup\n"
|
||||
"\t-b <dir>\tDatabase directory. Mandatory\n"
|
||||
"\t-p <plugin>\tDatastore plugin. Mandatory\n"
|
||||
"\t-y <dir>\tYang directory (where modules are stored). Mandatory\n"
|
||||
"\t-m <module>\tYang module. Mandatory\n"
|
||||
"\t-y <file>\tYang file. Mandatory\n"
|
||||
"and command is either:\n"
|
||||
"\tget [<xpath>]\n"
|
||||
"\tmget <nr> [<xpath>]\n"
|
||||
|
|
@ -115,7 +114,6 @@ main(int argc, char **argv)
|
|||
char *plugin = NULL;
|
||||
char *cmd = NULL;
|
||||
yang_spec *yspec = NULL;
|
||||
char *yangdir = NULL;
|
||||
char *yangmodule = NULL;
|
||||
char *dbdir = NULL;
|
||||
int ret;
|
||||
|
|
@ -158,12 +156,7 @@ main(int argc, char **argv)
|
|||
usage(argv0);
|
||||
dbdir = optarg;
|
||||
break;
|
||||
case 'y': /* Yang directory */
|
||||
if (!optarg)
|
||||
usage(argv0);
|
||||
yangdir = optarg;
|
||||
break;
|
||||
case 'm': /* Yang module */
|
||||
case 'y': /* Yang file */
|
||||
if (!optarg)
|
||||
usage(argv0);
|
||||
yangmodule = optarg;
|
||||
|
|
@ -188,10 +181,6 @@ main(int argc, char **argv)
|
|||
clicon_err(OE_DB, 0, "Missing dbdir -b option");
|
||||
goto done;
|
||||
}
|
||||
if (yangdir == NULL){
|
||||
clicon_err(OE_YANG, 0, "Missing yangdir -y option");
|
||||
goto done;
|
||||
}
|
||||
if (yangmodule == NULL){
|
||||
clicon_err(OE_YANG, 0, "Missing yang module -m option");
|
||||
goto done;
|
||||
|
|
@ -206,7 +195,7 @@ main(int argc, char **argv)
|
|||
if ((yspec = yspec_new()) == NULL)
|
||||
goto done;
|
||||
/* Parse yang spec from given file */
|
||||
if (yang_parse(h, NULL, yangmodule, yangdir, NULL, yspec, NULL) < 0)
|
||||
if (yang_parse(h, yangmodule, NULL, NULL, yspec, NULL) < 0)
|
||||
goto done;
|
||||
/* Set database directory option */
|
||||
if (xmldb_setopt(h, "dbdir", dbdir) < 0)
|
||||
|
|
|
|||
|
|
@ -1367,8 +1367,7 @@ main(int argc,
|
|||
enum operation_type op;
|
||||
char *cmd;
|
||||
char *db;
|
||||
char *yangdir;
|
||||
char *yangmod;
|
||||
char *yangmod; /* yang file */
|
||||
yang_spec *yspec = NULL;
|
||||
clicon_handle h;
|
||||
|
||||
|
|
@ -1381,12 +1380,11 @@ main(int argc,
|
|||
}
|
||||
cmd = argv[1];
|
||||
db = argv[2];
|
||||
yangdir = argv[3];
|
||||
yangmod = argv[4];
|
||||
db_init(db);
|
||||
if ((yspec = yspec_new()) == NULL)
|
||||
goto done
|
||||
if (yang_parse(h, NULL, yangmod, yangdir, NULL, yspec) < 0)
|
||||
if (yang_parse(h, NULL, yangmod, NULL, yspec) < 0)
|
||||
goto done;
|
||||
if (strcmp(cmd, "get")==0){
|
||||
if (argc < 5)
|
||||
|
|
|
|||
24
doc/FAQ.md
24
doc/FAQ.md
|
|
@ -97,13 +97,31 @@ configuration file is /usr/local/etc/clixon.xml. The example
|
|||
configuration file is installed at /usr/local/etc/example.xml. The
|
||||
YANG specification for the configuration file is clixon-config.yang.
|
||||
|
||||
You can change where Clixon looks for the configuration FILE as follows:
|
||||
## How are Clixon configuration files found?
|
||||
|
||||
Clixon by default finds its configuration file at `/usr/local/etc/clixon.xml`. However, you can modify this location as follows:
|
||||
- Provide -f FILE option when starting a program (eg clixon_backend -f FILE)
|
||||
- Provide --with-configfile=FILE when configuring
|
||||
- Provide --with-sysconfig=<dir> when configuring, then FILE is <dir>/clixon.xml
|
||||
- Provide --sysconfig=<dir> when configuring then FILE is <dir>/etc/clixon.xml
|
||||
- Provide --with-sysconfig=<dir> when configuring. Then FILE is <dir>/clixon.xml
|
||||
- Provide --sysconfig=<dir> when configuring. Then FILE is <dir>/etc/clixon.xml
|
||||
- FILE is /usr/local/etc/clixon.xml
|
||||
|
||||
## How are Yang files found?
|
||||
|
||||
Yang files contain the configuration specification. A Clixon
|
||||
application loads yang files and clixon itself loads system yang
|
||||
files. When Yang files are loaded modules are imported and submodules
|
||||
are included.
|
||||
|
||||
The following configuration file options control the loading of Yang files:
|
||||
- `CLICON_YANG_DIR` - A list of directories (yang dir path) where Clixon searches for module and submodules.
|
||||
- `CLICON_YANG_MODULE_MAIN` - Specifies a single module to load. The module is searched for in the yang dir path.
|
||||
- `CLICON_YANG_MODULE_REVISION` : Specifies a revision to the main module.
|
||||
|
||||
Note that the special `CLIXON_DATADIR`, by default `/usr/local/share/clixon` should be included in the yang dir path for Clixon system files to be found.
|
||||
|
||||
Application also has a command-line option `-y` to include a single Yang using absolute file path. This is mainly for debugging.
|
||||
|
||||
## How do I enable Yang features?
|
||||
|
||||
Yang models have features, and parts of a specification can be
|
||||
|
|
|
|||
|
|
@ -44,11 +44,13 @@ all: $(SUBDIRS) doc
|
|||
echo "Build doxygen doc: make doc"
|
||||
|
||||
# Regular doxygen documentation
|
||||
# Need to install doxygen
|
||||
doc:
|
||||
doxygen Doxyfile # generates html dir
|
||||
echo "Build doxygen graphs: make graphs"
|
||||
|
||||
# doxygen documentation with callgraphs
|
||||
# Need to install graphviz
|
||||
graphs:
|
||||
doxygen Doxyfile.graphs # generates html dir + call graphs (takes time)
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
<CLICON_CONFIGFILE>/usr/local/etc/example.xml</CLICON_CONFIGFILE>
|
||||
<CLICON_FEATURE>*:*</CLICON_FEATURE>
|
||||
<CLICON_YANG_DIR>/usr/local/share/example/yang</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_DIR>/usr/local/share/clixon</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_MODULE_MAIN>example</CLICON_YANG_MODULE_MAIN>
|
||||
<CLICON_CLI_MODE>example</CLICON_CLI_MODE>
|
||||
<CLICON_BACKEND_DIR>/usr/local/lib/example/backend</CLICON_BACKEND_DIR>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,5 @@
|
|||
/* include/clixon_config.h.in. Generated from configure.ac by autoheader. */
|
||||
|
||||
/* Clixon data dir for system yang files etc */
|
||||
#undef CLIXON_DATADIR
|
||||
|
||||
/* Location for apps to find default config file */
|
||||
#undef CLIXON_DEFAULT_CONFIG
|
||||
|
||||
|
|
@ -42,6 +39,9 @@
|
|||
/* Define to 1 if you have the `crypt' library (-lcrypt). */
|
||||
#undef HAVE_LIBCRYPT
|
||||
|
||||
/* Define to 1 if you have the `curl' library (-lcurl). */
|
||||
#undef HAVE_LIBCURL
|
||||
|
||||
/* Define to 1 if you have the `dl' library (-ldl). */
|
||||
#undef HAVE_LIBDL
|
||||
|
||||
|
|
@ -133,4 +133,4 @@
|
|||
`char[]'. */
|
||||
#undef YYTEXT_POINTER
|
||||
|
||||
#include "clixon_custom.h"
|
||||
#include <clixon_custom.h>
|
||||
|
|
|
|||
|
|
@ -105,9 +105,6 @@ int clicon_option_del(clicon_handle h, const char *name);
|
|||
static inline char *clicon_configfile(clicon_handle h){
|
||||
return clicon_option_str(h, "CLICON_CONFIGFILE");
|
||||
}
|
||||
static inline char *clicon_yang_dir(clicon_handle h){
|
||||
return clicon_option_str(h, "CLICON_YANG_DIR");
|
||||
}
|
||||
static inline char *clicon_yang_module_main(clicon_handle h){
|
||||
return clicon_option_str(h, "CLICON_YANG_MODULE_MAIN");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -95,6 +95,7 @@ enum rfc_6020{
|
|||
Y_MANDATORY,
|
||||
Y_MAX_ELEMENTS,
|
||||
Y_MIN_ELEMENTS,
|
||||
Y_MODIFIER,
|
||||
Y_MODULE,
|
||||
Y_MUST,
|
||||
Y_NAMESPACE,
|
||||
|
|
@ -193,6 +194,8 @@ struct yang_stmt{
|
|||
|
||||
char *ys_argument; /* String / argument depending on keyword */
|
||||
int ys_flags; /* Flags according to YANG_FLAG_* above */
|
||||
/*--------------here common for all -------*/
|
||||
char *ys_extra; /* For unknown */
|
||||
cg_var *ys_cv; /* cligen variable. See ys_populate()
|
||||
Following stmts have cv:s:
|
||||
leaf: for default value
|
||||
|
|
@ -200,7 +203,7 @@ struct yang_stmt{
|
|||
config: boolean true or false
|
||||
mandatory: boolean true or false
|
||||
fraction-digits for fraction-digits
|
||||
unkown-stmt (argument)
|
||||
unknown-stmt (argument)
|
||||
*/
|
||||
cvec *ys_cvec; /* List of stmt-specific variables
|
||||
Y_RANGE: range_min, range_max
|
||||
|
|
@ -265,11 +268,12 @@ int yang_print_cbuf(cbuf *cb, yang_node *yn, int marginal);
|
|||
int ys_populate(yang_stmt *ys, void *arg);
|
||||
yang_stmt *yang_parse_file(int fd, const char *name, yang_spec *ysp);
|
||||
int yang_parse(clicon_handle h, const char *filename,
|
||||
const char *module, const char *dir,
|
||||
const char *module,
|
||||
const char *revision, yang_spec *ysp, yang_stmt **ymodp);
|
||||
int yang_apply(yang_node *yn, enum rfc_6020 key, yang_applyfn_t fn,
|
||||
void *arg);
|
||||
int yang_abs_schema_nodeid(yang_spec *yspec, char *schema_nodeid,
|
||||
int yang_abs_schema_nodeid(yang_spec *yspec, yang_stmt *ys,
|
||||
char *schema_nodeid,
|
||||
enum rfc_6020 keyword, yang_stmt **yres);
|
||||
int yang_desc_schema_nodeid(yang_node *yn, char *schema_nodeid,
|
||||
enum rfc_6020 keyword, yang_stmt **yres);
|
||||
|
|
@ -277,8 +281,8 @@ cg_var *ys_parse(yang_stmt *ys, enum cv_type cvtype);
|
|||
int ys_parse_sub(yang_stmt *ys, char *extra);
|
||||
int yang_mandatory(yang_stmt *ys);
|
||||
int yang_config(yang_stmt *ys);
|
||||
int yang_spec_parse_module(clicon_handle h, char *module, char *dir, char *revision, yang_spec *yspec, yang_stmt **ymodp);
|
||||
int yang_spec_parse_file(clicon_handle h, char *filename, char *dir, yang_spec *yspec, yang_stmt **ymodp);
|
||||
int yang_spec_parse_module(clicon_handle h, char *module, char *revision, yang_spec *yspec, yang_stmt **ymodp);
|
||||
int yang_spec_parse_file(clicon_handle h, char *filename, yang_spec *yspec, yang_stmt **ymodp);
|
||||
cvec *yang_arg2cvec(yang_stmt *ys, char *delimi);
|
||||
int yang_key_match(yang_node *yn, char *name);
|
||||
|
||||
|
|
|
|||
|
|
@ -988,9 +988,9 @@ netconf_module_load(clicon_handle h)
|
|||
|
||||
yspec = clicon_dbspec_yang(h);
|
||||
/* Load yang spec */
|
||||
if (yang_spec_parse_module(h, "ietf-netconf", CLIXON_DATADIR, NULL, yspec, NULL)< 0)
|
||||
if (yang_spec_parse_module(h, "ietf-netconf", NULL, yspec, NULL)< 0)
|
||||
goto done;
|
||||
if (yang_spec_parse_module(h, "ietf-netconf-notification", CLIXON_DATADIR, NULL, yspec, NULL)< 0)
|
||||
if (yang_spec_parse_module(h, "ietf-netconf-notification", NULL, yspec, NULL)< 0)
|
||||
goto done;
|
||||
if ((xc = clicon_conf_xml(h)) == NULL){
|
||||
clicon_err(OE_CFG, ENOENT, "Clicon configuration not loaded");
|
||||
|
|
|
|||
|
|
@ -178,8 +178,16 @@ parse_configfile(clicon_handle h,
|
|||
__FUNCTION__, name, body);
|
||||
continue;
|
||||
}
|
||||
/* hard-coded exceptions for configure options that are leaf-lists (not leaf)
|
||||
* They must be accessed directly by looping over clicon_conf_xml(h)
|
||||
*/
|
||||
if (strcmp(name,"CLICON_FEATURE")==0)
|
||||
continue;
|
||||
if (strcmp(name,"CLICON_YANG_DIR")==0)
|
||||
continue;
|
||||
/* Used as an arg to this fn */
|
||||
if (strcmp(name,"CLICON_CONFIGFILE")==0)
|
||||
continue;
|
||||
if (hash_add(copt,
|
||||
name,
|
||||
body,
|
||||
|
|
@ -236,14 +244,25 @@ clicon_options_main(clicon_handle h,
|
|||
clicon_err(OE_CFG, 0, "%s: suffix %s not recognized (Run ./configure --with-config-compat?)", configfile, suffix);
|
||||
goto done;
|
||||
}
|
||||
/* Parse clixon yang spec */
|
||||
if (yang_parse(h, NULL, "clixon-config", CLIXON_DATADIR, NULL, yspec, NULL) < 0)
|
||||
goto done;
|
||||
/* Read configfile */
|
||||
/* Read configfile first without yangspec, for bootstrapping */
|
||||
if (parse_configfile(h, configfile, yspec, &xconfig) < 0)
|
||||
goto done;
|
||||
if (xml_rootchild(xconfig, 0, &xconfig) < 0)
|
||||
goto done;
|
||||
/* Set clixon_conf pointer to handle */
|
||||
clicon_conf_xml_set(h, xconfig);
|
||||
/* Parse clixon yang spec */
|
||||
if (yang_parse(h, NULL, "clixon-config", NULL, yspec, NULL) < 0)
|
||||
goto done;
|
||||
clicon_conf_xml_set(h, NULL);
|
||||
if (xconfig)
|
||||
xml_free(xconfig);
|
||||
/* Read configfile second time now with check yang spec */
|
||||
if (parse_configfile(h, configfile, yspec, &xconfig) < 0)
|
||||
goto done;
|
||||
if (xml_rootchild(xconfig, 0, &xconfig) < 0)
|
||||
goto done;
|
||||
/* Set clixon_conf pointer to handle */
|
||||
clicon_conf_xml_set(h, xconfig);
|
||||
/* Specific option handling */
|
||||
if (clicon_option_bool(h, "CLICON_XML_SORT") == 1)
|
||||
|
|
@ -638,7 +657,7 @@ clicon_conf_xml(clicon_handle h)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/*! Set YANG specification for Clixon system options and features
|
||||
/*! Set YANG specification for Clixon system options and features
|
||||
* ys must be a malloced pointer
|
||||
*/
|
||||
int
|
||||
|
|
|
|||
|
|
@ -122,6 +122,7 @@ static const map_str2int ykmap[] = {
|
|||
{"mandatory", Y_MANDATORY},
|
||||
{"max-elements", Y_MAX_ELEMENTS},
|
||||
{"min-elements", Y_MIN_ELEMENTS},
|
||||
{"modifier", Y_MODIFIER},
|
||||
{"module", Y_MODULE},
|
||||
{"must", Y_MUST},
|
||||
{"namespace", Y_NAMESPACE},
|
||||
|
|
@ -206,6 +207,8 @@ ys_free1(yang_stmt *ys)
|
|||
{
|
||||
if (ys->ys_argument)
|
||||
free(ys->ys_argument);
|
||||
if (ys->ys_extra)
|
||||
free(ys->ys_extra);
|
||||
if (ys->ys_cv)
|
||||
cv_free(ys->ys_cv);
|
||||
if (ys->ys_cvec)
|
||||
|
|
@ -233,7 +236,8 @@ ys_free(yang_stmt *ys)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*! Free a yang specification recursively */
|
||||
/*! Free a yang specification recursively
|
||||
*/
|
||||
int
|
||||
yspec_free(yang_spec *yspec)
|
||||
{
|
||||
|
|
@ -294,6 +298,11 @@ ys_cp(yang_stmt *ynew,
|
|||
clicon_err(OE_YANG, errno, "strdup");
|
||||
goto done;
|
||||
}
|
||||
if (yold->ys_extra)
|
||||
if ((ynew->ys_extra = strdup(yold->ys_extra)) == NULL){
|
||||
clicon_err(OE_YANG, errno, "strdup");
|
||||
goto done;
|
||||
}
|
||||
if (yold->ys_cv)
|
||||
if ((ynew->ys_cv = cv_dup(yold->ys_cv)) == NULL){
|
||||
clicon_err(OE_YANG, errno, "cv_dup");
|
||||
|
|
@ -672,7 +681,8 @@ yang_find_topnode(yang_spec *ysp,
|
|||
if (yang_nodeid_split(nodeid, &prefix, &id) < 0)
|
||||
goto done;
|
||||
if (prefix){
|
||||
if ((ymod = yang_find((yang_node*)ysp, Y_MODULE, prefix)) != NULL){
|
||||
if ((ymod = yang_find((yang_node*)ysp, Y_MODULE, prefix)) != NULL ||
|
||||
(ymod = yang_find((yang_node*)ysp, Y_SUBMODULE, prefix)) != NULL){
|
||||
if ((yres = yang_find((yang_node*)ymod, 0, id)) != NULL)
|
||||
goto ok;
|
||||
goto done;
|
||||
|
|
@ -771,7 +781,7 @@ yang_order(yang_stmt *y)
|
|||
int j=0;
|
||||
|
||||
yp = y->ys_parent;
|
||||
if (yp->yn_keyword == Y_MODULE ||yp->yn_keyword == Y_SUBMODULE){
|
||||
if (yp->yn_keyword == Y_MODULE || yp->yn_keyword == Y_SUBMODULE){
|
||||
ypp = yp->yn_parent;
|
||||
for (i=0; i<ypp->yn_len; i++){
|
||||
yn = (yang_node*)ypp->yn_stmt[i];
|
||||
|
|
@ -800,7 +810,8 @@ yang_key2str(int keyword)
|
|||
return (char*)clicon_int2str(ykmap, keyword);
|
||||
}
|
||||
|
||||
/*! Find top module or sub-module given a statement. Ultimate top is yang spec
|
||||
/*! Find top module or sub-module given a statement.
|
||||
* Ultimate top is yang spec, dont return that
|
||||
* The routine recursively finds ancestors.
|
||||
* @param[in] ys Any yang statement in a yang tree
|
||||
* @retval ymod The top module or sub-module
|
||||
|
|
@ -811,14 +822,13 @@ ys_module(yang_stmt *ys)
|
|||
{
|
||||
yang_node *yn;
|
||||
|
||||
#if 1
|
||||
if (ys==NULL || ys->ys_keyword==Y_SPEC)
|
||||
return NULL;
|
||||
#else
|
||||
if (ys==NULL || ys->ys_keyword==Y_SPEC)
|
||||
if (ys->ys_keyword == Y_MODULE || ys->ys_keyword == Y_SUBMODULE)
|
||||
return ys;
|
||||
#endif
|
||||
while (ys != NULL && ys->ys_keyword != Y_MODULE && ys->ys_keyword != Y_SUBMODULE){
|
||||
while (ys != NULL &&
|
||||
ys->ys_keyword != Y_MODULE &&
|
||||
ys->ys_keyword != Y_SUBMODULE){
|
||||
yn = ys->ys_parent;
|
||||
/* Some extra stuff to ensure ys is a stmt */
|
||||
if (yn && yn->yn_keyword == Y_SPEC)
|
||||
|
|
@ -973,7 +983,8 @@ yang_find_module_by_prefix(yang_stmt *ys,
|
|||
}
|
||||
yimport = NULL;
|
||||
while ((yimport = yn_each((yang_node*)my_ymod, yimport)) != NULL) {
|
||||
if (yimport->ys_keyword != Y_IMPORT)
|
||||
if (yimport->ys_keyword != Y_IMPORT &&
|
||||
yimport->ys_keyword != Y_INCLUDE)
|
||||
continue;
|
||||
if ((yprefix = yang_find((yang_node*)yimport, Y_PREFIX, NULL)) != NULL &&
|
||||
strcmp(yprefix->ys_argument, prefix) == 0){
|
||||
|
|
@ -981,9 +992,10 @@ yang_find_module_by_prefix(yang_stmt *ys,
|
|||
}
|
||||
}
|
||||
if (yimport){
|
||||
if ((ymod = yang_find((yang_node*)yspec, Y_MODULE, yimport->ys_argument)) == NULL){
|
||||
if ((ymod = yang_find((yang_node*)yspec, Y_MODULE, yimport->ys_argument)) == NULL &&
|
||||
(ymod = yang_find((yang_node*)yspec, Y_SUBMODULE, yimport->ys_argument)) == NULL){
|
||||
clicon_err(OE_YANG, 0, "No module or sub-module found with prefix %s",
|
||||
yimport->ys_argument);
|
||||
prefix);
|
||||
yimport = NULL;
|
||||
goto done; /* unresolved */
|
||||
}
|
||||
|
|
@ -1411,9 +1423,9 @@ ys_populate_feature(clicon_handle h,
|
|||
cg_var *cv;
|
||||
char *module;
|
||||
char *feature;
|
||||
cxobj *x1;
|
||||
cxobj *xc;
|
||||
|
||||
/* Eg, when parsing the config xml itself */
|
||||
/* get clicon config file in xml form */
|
||||
if ((x = clicon_conf_xml(h)) == NULL)
|
||||
goto ok;
|
||||
if ((ymod = ys_module(ys)) == NULL){
|
||||
|
|
@ -1422,14 +1434,14 @@ ys_populate_feature(clicon_handle h,
|
|||
}
|
||||
module = ymod->ys_argument;
|
||||
feature = ys->ys_argument;
|
||||
x1 = NULL;
|
||||
while ((x1 = xml_child_each(x, x1, CX_ELMNT)) != NULL && found == 0) {
|
||||
xc = NULL;
|
||||
while ((xc = xml_child_each(x, xc, CX_ELMNT)) != NULL && found == 0) {
|
||||
char *m = NULL;
|
||||
char *f = NULL;
|
||||
if (strcmp(xml_name(x1), "CLICON_FEATURE") != 0)
|
||||
if (strcmp(xml_name(xc), "CLICON_FEATURE") != 0)
|
||||
continue;
|
||||
/* get m and f from configuration feature rules */
|
||||
if (yang_nodeid_split(xml_body(x1), &m, &f) < 0)
|
||||
if (yang_nodeid_split(xml_body(xc), &m, &f) < 0)
|
||||
goto done;
|
||||
if (m && f &&
|
||||
(strcmp(m,"*")==0 ||
|
||||
|
|
@ -1454,6 +1466,51 @@ ys_populate_feature(clicon_handle h,
|
|||
return retval;
|
||||
}
|
||||
|
||||
/*! Populate unknown node with extension
|
||||
*/
|
||||
static int
|
||||
ys_populate_unknown(yang_stmt *ys)
|
||||
{
|
||||
int retval = -1;
|
||||
int cvret;
|
||||
char *reason = NULL;
|
||||
yang_stmt *ymod;
|
||||
char *prefix = NULL;
|
||||
char *name;
|
||||
char *extra;
|
||||
|
||||
if ((extra = ys->ys_extra) == NULL)
|
||||
goto ok;
|
||||
/* Find extension, if found, store it as unknown, if not,
|
||||
break for error */
|
||||
prefix = yarg_prefix(ys); /* And this its prefix */
|
||||
name = yarg_id(ys); /* This is the type to resolve */
|
||||
if ((ymod = yang_find_module_by_prefix(ys, prefix)) == NULL)
|
||||
goto ok; /* shouldnt happen */
|
||||
if (yang_find((yang_node*)ymod, Y_EXTENSION, name) == NULL){
|
||||
clicon_err(OE_YANG, errno, "Extension %s:%s not found", prefix, name);
|
||||
goto done;
|
||||
}
|
||||
if ((ys->ys_cv = cv_new(CGV_STRING)) == NULL){
|
||||
clicon_err(OE_YANG, errno, "cv_new");
|
||||
goto done;
|
||||
}
|
||||
if ((cvret = cv_parse1(extra, ys->ys_cv, &reason)) < 0){ /* error */
|
||||
clicon_err(OE_YANG, errno, "parsing cv");
|
||||
goto done;
|
||||
}
|
||||
if (cvret == 0){ /* parsing failed */
|
||||
clicon_err(OE_YANG, errno, "Parsing CV: %s", reason);
|
||||
goto done;
|
||||
}
|
||||
ok:
|
||||
retval = 0;
|
||||
done:
|
||||
if (prefix)
|
||||
free(prefix);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*! Populate with cligen-variables, default values, etc. Sanity checks on complete tree.
|
||||
*
|
||||
* We do this in 2nd pass after complete parsing to be sure to have a complete parse-tree
|
||||
|
|
@ -1495,6 +1552,10 @@ ys_populate(yang_stmt *ys,
|
|||
if (ys_populate_identity(ys, NULL) < 0)
|
||||
goto done;
|
||||
break;
|
||||
case Y_UNKNOWN:
|
||||
if (ys_populate_unknown(ys) < 0)
|
||||
goto done;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
@ -1555,12 +1616,11 @@ yang_augment_node(yang_stmt *ys,
|
|||
yang_stmt *yss = NULL;
|
||||
yang_stmt *yc;
|
||||
int i;
|
||||
|
||||
|
||||
schema_nodeid = ys->ys_argument;
|
||||
clicon_debug(1, "%s %s", __FUNCTION__, schema_nodeid);
|
||||
|
||||
/* Find the target */
|
||||
if (yang_abs_schema_nodeid(ysp, schema_nodeid, -1, &yss) < 0)
|
||||
if (yang_abs_schema_nodeid(ysp, ys, schema_nodeid, -1, &yss) < 0)
|
||||
goto done;
|
||||
if (yss == NULL)
|
||||
goto ok;
|
||||
|
|
@ -1646,14 +1706,15 @@ yang_expand(yang_node *yn)
|
|||
prefix = yarg_prefix(ys); /* And this its prefix */
|
||||
if (ys_grouping_resolve(ys, prefix, name, &ygrouping) < 0)
|
||||
goto done;
|
||||
if (prefix)
|
||||
free(prefix);
|
||||
|
||||
if (ygrouping == NULL){
|
||||
clicon_log(LOG_NOTICE, "%s: Yang error : grouping \"%s\" not found",
|
||||
__FUNCTION__, ys->ys_argument);
|
||||
clicon_log(LOG_NOTICE, "%s: Yang error : grouping \"%s\" not found in module \"%s\"",
|
||||
__FUNCTION__, ys->ys_argument, ys_module(ys)->ys_argument);
|
||||
goto done;
|
||||
break;
|
||||
}
|
||||
if (prefix)
|
||||
free(prefix); /* XXX move up */
|
||||
/* Check mark flag to see if this grouping (itself) has been expanded
|
||||
If not, this needs to be done before we can insert it into
|
||||
the 'uses' place */
|
||||
|
|
@ -1825,48 +1886,69 @@ yang_parse_file(int fd,
|
|||
return ymod; /* top-level (sub)module */
|
||||
}
|
||||
|
||||
/*! No specific revision give. Match a yang file given dir and module
|
||||
/*! No specific revision give. Match a yang file given module
|
||||
* @param[in] h CLICON handle
|
||||
* @param[in] yang_dir Directory where all YANG module files reside
|
||||
* @param[in] dir Directory, if NULL, look in YANG_DIR path
|
||||
* @param[in] module Name of main YANG module.
|
||||
* @param[in] revision Revision or NULL
|
||||
* @param[out] fbuf Buffer containing filename
|
||||
*
|
||||
* @note for bootstrapping, dir may have to be set.
|
||||
* @retval 1 Match found, Most recent entry returned in fbuf
|
||||
* @retval 0 No matching entry found
|
||||
* @retval -1 Error
|
||||
*/
|
||||
static int
|
||||
yang_parse_find_match(const char *yang_dir,
|
||||
const char *module,
|
||||
yang_parse_find_match(clicon_handle h,
|
||||
const char *module,
|
||||
const char *revision,
|
||||
cbuf *fbuf)
|
||||
{
|
||||
int retval = -1;
|
||||
int retval = -1;
|
||||
struct dirent *dp = NULL;
|
||||
int ndp;
|
||||
cbuf *regex = NULL;
|
||||
cxobj *x;
|
||||
cxobj *xc;
|
||||
char *dir;
|
||||
|
||||
/* get clicon config file in xml form */
|
||||
if ((x = clicon_conf_xml(h)) == NULL)
|
||||
goto ok;
|
||||
if ((regex = cbuf_new()) == NULL){
|
||||
clicon_err(OE_YANG, errno, "cbuf_new");
|
||||
goto done;
|
||||
}
|
||||
/* RFC 6020: The name of the file SHOULD be of the form:
|
||||
module-or-submodule-name ['@' revision-date] ( '.yang' / '.yin' )
|
||||
revision-date ::= 4DIGIT "-" 2DIGIT "-" 2DIGIT
|
||||
*/
|
||||
cprintf(regex, "^%s(@[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9])?(.yang)$",
|
||||
module);
|
||||
if ((ndp = clicon_file_dirent(yang_dir,
|
||||
&dp,
|
||||
cbuf_get(regex),
|
||||
S_IFREG)) < 0)
|
||||
goto done;
|
||||
/* Entries are sorted, last entry should be most recent date */
|
||||
if (ndp != 0){
|
||||
cprintf(fbuf, "%s/%s", yang_dir, dp[ndp-1].d_name);
|
||||
retval = 1;
|
||||
}
|
||||
* module-or-submodule-name ['@' revision-date] ( '.yang' / '.yin' )
|
||||
* revision-date ::= 4DIGIT "-" 2DIGIT "-" 2DIGIT
|
||||
*/
|
||||
if (revision)
|
||||
cprintf(regex, "^%s@%s(.yang)$", module, revision);
|
||||
else
|
||||
retval = 0;
|
||||
cprintf(regex, "^%s(@[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9])?(.yang)$",
|
||||
module);
|
||||
xc = NULL;
|
||||
while ((xc = xml_child_each(x, xc, CX_ELMNT)) != NULL) {
|
||||
if (strcmp(xml_name(xc), "CLICON_YANG_DIR") != 0)
|
||||
continue;
|
||||
dir = xml_body(xc);
|
||||
/* get all matching files in this directory */
|
||||
if ((ndp = clicon_file_dirent(dir,
|
||||
&dp,
|
||||
cbuf_get(regex),
|
||||
S_IFREG)) < 0)
|
||||
goto done;
|
||||
/* Entries are sorted, last entry should be most recent date
|
||||
* Found
|
||||
*/
|
||||
if (ndp != 0){
|
||||
cprintf(fbuf, "%s/%s", dir, dp[ndp-1].d_name);
|
||||
retval = 1;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
ok:
|
||||
retval = 0;
|
||||
done:
|
||||
if (regex)
|
||||
cbuf_free(regex);
|
||||
|
|
@ -1875,7 +1957,6 @@ yang_parse_find_match(const char *yang_dir,
|
|||
return retval;
|
||||
}
|
||||
|
||||
|
||||
/*! Open a file, read into a string and invoke yang parsing
|
||||
*
|
||||
* Similar to clicon_yang_str(), just read a file first
|
||||
|
|
@ -1903,7 +1984,6 @@ yang_parse_filename(const char *filename,
|
|||
int fd = -1;
|
||||
struct stat st;
|
||||
|
||||
clicon_log(LOG_DEBUG, "Parsing yang file: %s", filename);
|
||||
if (stat(filename, &st) < 0){
|
||||
clicon_err(OE_YANG, errno, "%s not found", filename);
|
||||
goto done;
|
||||
|
|
@ -1921,8 +2001,8 @@ yang_parse_filename(const char *filename,
|
|||
}
|
||||
|
||||
static yang_stmt *
|
||||
yang_parse_module(const char *module,
|
||||
const char *dir,
|
||||
yang_parse_module(clicon_handle h,
|
||||
const char *module,
|
||||
const char *revision,
|
||||
yang_spec *ysp)
|
||||
{
|
||||
|
|
@ -1934,16 +2014,12 @@ yang_parse_module(const char *module,
|
|||
clicon_err(OE_YANG, errno, "cbuf_new");
|
||||
goto done;
|
||||
}
|
||||
if (revision)
|
||||
cprintf(fbuf, "%s/%s@%s.yang", dir, module, revision);
|
||||
else{
|
||||
/* No specific revision, Match a yang file */
|
||||
if ((nr = yang_parse_find_match(dir, module, fbuf)) < 0)
|
||||
goto done;
|
||||
if (nr == 0){
|
||||
clicon_err(OE_YANG, errno, "No matching %s yang files found in %s (expected module name or absolute filename)", module, dir);
|
||||
goto done;
|
||||
}
|
||||
/* Match a yang file with or without revision in yang-dir list */
|
||||
if ((nr = yang_parse_find_match(h, module, revision, fbuf)) < 0)
|
||||
goto done;
|
||||
if (nr == 0){
|
||||
clicon_err(OE_YANG, errno, "No yang files found matching \"%s\" in the list of CLICON_YANG_DIRs", module);
|
||||
goto done;
|
||||
}
|
||||
if ((ymod = yang_parse_filename(cbuf_get(fbuf), ysp)) == NULL)
|
||||
goto done;
|
||||
|
|
@ -1953,10 +2029,9 @@ yang_parse_module(const char *module,
|
|||
return ymod; /* top-level (sub)module */
|
||||
}
|
||||
|
||||
/*! Parse one yang module then go through (sub)modules and parse them recursively
|
||||
/*! Given a (sub)module, parse all (sub)modules in turn recursively
|
||||
*
|
||||
* @param[in] h CLICON handle
|
||||
* @param[in] yang_dir Directory where all YANG module files reside
|
||||
* @param[in] module Name of main YANG module. Or absolute file name.
|
||||
* @param[in] revision Module revision date or NULL
|
||||
* @param[in] ysp Yang specification. Should have been created by caller using yspec_new
|
||||
|
|
@ -1972,8 +2047,8 @@ yang_parse_module(const char *module,
|
|||
* clixon_yang_parseparse # Actual yang parsing using yacc
|
||||
*/
|
||||
static int
|
||||
yang_parse_recurse(yang_stmt *ymod,
|
||||
const char *dir,
|
||||
yang_parse_recurse(clicon_handle h,
|
||||
yang_stmt *ymod,
|
||||
yang_spec *ysp)
|
||||
{
|
||||
int retval = -1;
|
||||
|
|
@ -1982,21 +2057,29 @@ yang_parse_recurse(yang_stmt *ymod,
|
|||
char *submodule;
|
||||
char *subrevision;
|
||||
yang_stmt *subymod;
|
||||
enum rfc_6020 keyw;
|
||||
|
||||
/* go through all import statements of ysp (or its module) */
|
||||
/* go through all import (modules) and include(submodules) of ysp */
|
||||
while ((yi = yn_each((yang_node*)ymod, yi)) != NULL){
|
||||
if (yi->ys_keyword != Y_IMPORT)
|
||||
keyw = yi->ys_keyword;
|
||||
if (keyw != Y_IMPORT && keyw != Y_INCLUDE)
|
||||
continue;
|
||||
/* common part */
|
||||
submodule = yi->ys_argument;
|
||||
/* Is there a specific revision (or just latest)? */
|
||||
if ((yrev = yang_find((yang_node*)yi, Y_REVISION_DATE, NULL)) != NULL)
|
||||
subrevision = yrev->ys_argument;
|
||||
else
|
||||
subrevision = NULL;
|
||||
if (yang_find((yang_node*)ysp, Y_MODULE, submodule) == NULL){
|
||||
/* if already loaded, ignore, else parse the file */
|
||||
if (yang_find((yang_node*)ysp,
|
||||
keyw=Y_IMPORT?Y_MODULE:Y_SUBMODULE,
|
||||
submodule) == NULL){
|
||||
/* recursive call */
|
||||
if ((subymod = yang_parse_module(submodule, dir, subrevision, ysp)) == NULL)
|
||||
if ((subymod = yang_parse_module(h, submodule, subrevision, ysp)) == NULL)
|
||||
goto done;
|
||||
if (yang_parse_recurse(subymod, dir, ysp) < 0){
|
||||
/* Go through its sub-modules recursively */
|
||||
if (yang_parse_recurse(h, subymod, ysp) < 0){
|
||||
ymod = NULL;
|
||||
goto done;
|
||||
}
|
||||
|
|
@ -2019,7 +2102,8 @@ ys_schemanode_check(yang_stmt *ys,
|
|||
yp = ys->ys_parent;
|
||||
switch (ys->ys_keyword){
|
||||
case Y_AUGMENT:
|
||||
if (yp->yn_keyword == Y_MODULE) /* Not top-level */
|
||||
if (yp->yn_keyword == Y_MODULE || /* Not top-level */
|
||||
yp->yn_keyword == Y_SUBMODULE)
|
||||
break;
|
||||
/* fallthru */
|
||||
case Y_REFINE:
|
||||
|
|
@ -2035,7 +2119,7 @@ ys_schemanode_check(yang_stmt *ys,
|
|||
break;
|
||||
case Y_DEVIATION:
|
||||
yspec = ys_spec(ys);
|
||||
if (yang_abs_schema_nodeid(yspec, ys->ys_argument, -1, &yres) < 0)
|
||||
if (yang_abs_schema_nodeid(yspec, ys, ys->ys_argument, -1, &yres) < 0)
|
||||
goto done;
|
||||
if (yres == NULL){
|
||||
clicon_err(OE_YANG, 0, "schemanode sanity check of %s", ys->ys_argument);
|
||||
|
|
@ -2127,10 +2211,69 @@ yang_features(clicon_handle h,
|
|||
return retval;
|
||||
}
|
||||
|
||||
/*! Merge yang submodule into the module it belongs to
|
||||
* Skip submodule header fields
|
||||
* @param[in] h Clicon handle
|
||||
* @param[in] yspec Yang spec
|
||||
* @param[in] ysubm Yang submodule
|
||||
*/
|
||||
static int
|
||||
yang_merge_submodules(clicon_handle h,
|
||||
yang_spec *yspec,
|
||||
yang_stmt *ysubm)
|
||||
{
|
||||
int retval = -1;
|
||||
yang_stmt *yb; /* belongs-to */
|
||||
yang_stmt *ymod; /* parent yang module */
|
||||
yang_stmt *yc; /* yang child */
|
||||
char *modname;
|
||||
int i;
|
||||
|
||||
assert(ysubm->ys_keyword == Y_SUBMODULE);
|
||||
/* Get parent name (via belongs-to) and find parent module */
|
||||
if ((yb = yang_find((yang_node*)ysubm, Y_BELONGS_TO, NULL)) == NULL){
|
||||
clicon_err(OE_YANG, ENOENT, "submodule %s does not have a mandatory belongs-to statement", ysubm->ys_argument);
|
||||
goto done;
|
||||
}
|
||||
modname = yb->ys_argument;
|
||||
if ((ymod = yang_find((yang_node*)yspec, Y_MODULE, modname)) == NULL){
|
||||
clicon_err(OE_YANG, ENOENT, "Module %s which submodule %s belongs to is not found", modname, ysubm->ys_argument);
|
||||
goto done;
|
||||
}
|
||||
/* Move sub-module statements to modules
|
||||
* skip belongs-to, revision, organization, reference, yang-version)
|
||||
* since main module has its own and may only have one
|
||||
* XXX: use queue,...
|
||||
*/
|
||||
for (i=0; i<ysubm->ys_len; i++){
|
||||
yc = ysubm->ys_stmt[i];
|
||||
if (yc->ys_keyword == Y_BELONGS_TO ||
|
||||
yc->ys_keyword == Y_CONTACT ||
|
||||
yc->ys_keyword == Y_DESCRIPTION ||
|
||||
yc->ys_keyword == Y_ORGANIZATION ||
|
||||
yc->ys_keyword == Y_REVISION ||
|
||||
yc->ys_keyword == Y_REFERENCE ||
|
||||
yc->ys_keyword == Y_YANG_VERSION)
|
||||
ys_free(yc);
|
||||
else{
|
||||
if (yn_insert((yang_node*)ymod, yc) < 0)
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
if (ysubm->ys_stmt){
|
||||
free(ysubm->ys_stmt);
|
||||
ysubm->ys_stmt = NULL;
|
||||
}
|
||||
ysubm->ys_len = 0;
|
||||
ys_free(ysubm);
|
||||
retval = 0;
|
||||
done:
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*! Parse top yang module including all its sub-modules. Expand and populate yang tree
|
||||
*
|
||||
* @param[in] h CLICON handle
|
||||
* @param[in] yang_dir Directory where all YANG module files reside (except mainfile)
|
||||
* @param[in] filename File name containing Yang specification. Overrides module
|
||||
* @param[in] module Name of main YANG module. Or absolute file name.
|
||||
* @param[in] revision Main module revision date string or NULL
|
||||
|
|
@ -2154,7 +2297,6 @@ int
|
|||
yang_parse(clicon_handle h,
|
||||
const char *filename,
|
||||
const char *module,
|
||||
const char *dir,
|
||||
const char *revision,
|
||||
yang_spec *ysp,
|
||||
yang_stmt **ymodp)
|
||||
|
|
@ -2164,63 +2306,89 @@ yang_parse(clicon_handle h,
|
|||
int i;
|
||||
int modnr; /* Existing number of modules */
|
||||
|
||||
/* Apply steps 2.. on new modules, ie ones after modnr. */
|
||||
modnr = ysp->yp_len;
|
||||
if (filename){
|
||||
if ((ymod = yang_parse_filename(filename, ysp)) == NULL)
|
||||
goto done;
|
||||
}
|
||||
else
|
||||
if ((ymod = yang_parse_module(module, dir, revision, ysp)) == NULL)
|
||||
if ((ymod = yang_parse_module(h, module, revision, ysp)) == NULL)
|
||||
goto done;
|
||||
|
||||
/* From here on, apply actions on new modules, ie ones after modnr. */
|
||||
/* Step 1: parse from text to yang parse-tree. */
|
||||
/* 1: Parse from text to yang parse-tree. */
|
||||
/* Iterate through modules */
|
||||
if (yang_parse_recurse(ymod, dir, ysp) < 0)
|
||||
if (yang_parse_recurse(h, ymod, ysp) < 0)
|
||||
goto done;
|
||||
|
||||
/* Check cardinality maybe this should be done after grouping/augment */
|
||||
/* 2. Check cardinality maybe this should be done after grouping/augment */
|
||||
for (i=modnr; i<ysp->yp_len; i++) /* XXX */
|
||||
if (yang_cardinality(h, ysp->yp_stmt[i], ysp->yp_stmt[i]->ys_argument) < 0)
|
||||
goto done;
|
||||
|
||||
/* Step 2: check features: check if enabled and remove disabled features */
|
||||
/* 3: Merge sub-modules with modules - after this step, no submodules exist
|
||||
* In the merge, remove submodule headers
|
||||
*/
|
||||
for (i=modnr; i<ysp->yp_len; i++){
|
||||
if (ysp->yp_stmt[i]->ys_keyword != Y_SUBMODULE)
|
||||
continue;
|
||||
}
|
||||
i = 0;
|
||||
while (i<ysp->yp_len){
|
||||
int j;
|
||||
if (ysp->yp_stmt[i]->ys_keyword != Y_SUBMODULE){
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
if (yang_merge_submodules(h, ysp, ysp->yp_stmt[i]) < 0)
|
||||
goto done;
|
||||
/* shift down one step */
|
||||
for (j=i; j<ysp->yp_len-1; j++)
|
||||
ysp->yp_stmt[j] = ysp->yp_stmt[j+1];
|
||||
ysp->yp_len--;
|
||||
}
|
||||
|
||||
/* 4: Check features: check if enabled and remove disabled features */
|
||||
for (i=modnr; i<ysp->yp_len; i++) /* XXX */
|
||||
if (yang_features(h, ysp->yp_stmt[i]) < 0)
|
||||
goto done;
|
||||
|
||||
/* Step 3: Go through parse tree and populate it with cv types */
|
||||
/* 5: Go through parse tree and populate it with cv types */
|
||||
for (i=modnr; i<ysp->yp_len; i++)
|
||||
if (yang_apply((yang_node*)ysp->yp_stmt[i], -1, ys_populate, (void*)h) < 0)
|
||||
goto done;
|
||||
|
||||
|
||||
/* Step 4: Resolve all types: populate type caches. Requires eg length/range cvecs
|
||||
* from ys_populate step
|
||||
/* 6: Resolve all types: populate type caches. Requires eg length/range cvecs
|
||||
* from ys_populate step.
|
||||
* Must be done using static binding.
|
||||
*/
|
||||
for (i=modnr; i<ysp->yp_len; i++)
|
||||
yang_apply((yang_node*)ysp->yp_stmt[i], Y_TYPE, ys_resolve_type, NULL);
|
||||
if (yang_apply((yang_node*)ysp->yp_stmt[i], Y_TYPE, ys_resolve_type, NULL) < 0)
|
||||
goto done;
|
||||
|
||||
/* Up to here resolving is made in the context they are defined, rather than the
|
||||
context they are used. Like static scoping. After this we expand all
|
||||
grouping/uses and unfold all macros into a single tree as they are used.
|
||||
*/
|
||||
/* Up to here resolving is made in the context they are defined, rather
|
||||
* than the context they are used (except for submodules being merged w
|
||||
* modules). Like static scoping.
|
||||
* After this we expand all grouping/uses and unfold all macros into a
|
||||
*single tree as they are used.
|
||||
*/
|
||||
|
||||
/* Step 5: Macro expansion of all grouping/uses pairs. Expansion needs marking */
|
||||
/* 7: Macro expansion of all grouping/uses pairs. Expansion needs marking */
|
||||
for (i=modnr; i<ysp->yp_len; i++){
|
||||
if (yang_expand((yang_node*)ysp->yp_stmt[i]) < 0)
|
||||
goto done;
|
||||
yang_apply((yang_node*)ysp->yp_stmt[i], -1, ys_flag_reset, (void*)YANG_FLAG_MARK);
|
||||
}
|
||||
|
||||
/* Step 6: Top-level augmentation of all modules XXX: only new modules? */
|
||||
/* 8: Top-level augmentation of all modules XXX: only new modules? */
|
||||
if (yang_augment_spec(ysp) < 0)
|
||||
goto done;
|
||||
|
||||
/* Step 7: sanity check of schemanode references, need more here */
|
||||
/* 9: sanity check of schemanode references, need more here */
|
||||
for (i=modnr; i<ysp->yp_len; i++)
|
||||
if (yang_apply((yang_node*)ysp->yp_stmt[i], -1, ys_schemanode_check, NULL) < 0)
|
||||
goto done;
|
||||
/* Return main module parsed in step 1 */
|
||||
if (ymodp)
|
||||
*ymodp = ymod;
|
||||
retval = 0;
|
||||
|
|
@ -2367,6 +2535,7 @@ schema_nodeid_vec(yang_node *yn,
|
|||
|
||||
/*! Given an absolute schema-nodeid (eg /a/b/c) find matching yang spec
|
||||
* @param[in] yspec Yang specification.
|
||||
* @param[in] yn Original yang stmt (where call is made) if any
|
||||
* @param[in] schema_nodeid Absolute schema-node-id, ie /a/b
|
||||
* @param[in] keyword A schemode of this type, or -1 if any
|
||||
* @param[out] yres Result yang statement node, or NULL if not found
|
||||
|
|
@ -2382,6 +2551,7 @@ schema_nodeid_vec(yang_node *yn,
|
|||
*/
|
||||
int
|
||||
yang_abs_schema_nodeid(yang_spec *yspec,
|
||||
yang_stmt *yn,
|
||||
char *schema_nodeid,
|
||||
enum rfc_6020 keyword,
|
||||
yang_stmt **yres)
|
||||
|
|
@ -2389,7 +2559,7 @@ yang_abs_schema_nodeid(yang_spec *yspec,
|
|||
int retval = -1;
|
||||
char **vec = NULL;
|
||||
int nvec;
|
||||
yang_stmt *ymod;
|
||||
yang_stmt *ymod = NULL;
|
||||
char *id;
|
||||
char *prefix = NULL;
|
||||
yang_stmt *yprefix;
|
||||
|
|
@ -2421,16 +2591,20 @@ yang_abs_schema_nodeid(yang_spec *yspec,
|
|||
}
|
||||
prefix[id-vec[1]] = '\0';
|
||||
id++;
|
||||
ymod = NULL;
|
||||
while ((ymod = yn_each((yang_node*)yspec, ymod)) != NULL) {
|
||||
if ((yprefix = yang_find((yang_node*)ymod, Y_PREFIX, NULL)) != NULL &&
|
||||
strcmp(yprefix->ys_argument, prefix) == 0){
|
||||
break;
|
||||
if (yn) /* Find module using local prefix definition */
|
||||
ymod = yang_find_module_by_prefix(yn, prefix);
|
||||
if (ymod == NULL){ /* Try (global) prefix the module itself uses */
|
||||
ymod = NULL;
|
||||
while ((ymod = yn_each((yang_node*)yspec, ymod)) != NULL) {
|
||||
if ((yprefix = yang_find((yang_node*)ymod, Y_PREFIX, NULL)) != NULL &&
|
||||
strcmp(yprefix->ys_argument, prefix) == 0){
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ymod == NULL){ /* Try with topnode */
|
||||
if (ymod == NULL){ /* Try find id from topnode without prefix XXX remove?*/
|
||||
if ((ys = yang_find_topnode(yspec, id, YC_SCHEMANODE)) == NULL){
|
||||
clicon_err(OE_YANG, 0, "Module with id:%s:%s not found", prefix,id);
|
||||
clicon_err(OE_YANG, 0, "Module with id:\"%s:%s\" not found", prefix,id);
|
||||
goto done;
|
||||
}
|
||||
if ((ymod = ys_module(ys)) == NULL){
|
||||
|
|
@ -2439,7 +2613,7 @@ yang_abs_schema_nodeid(yang_spec *yspec,
|
|||
}
|
||||
if ((yprefix = yang_find((yang_node*)ymod, Y_PREFIX, NULL)) != NULL &&
|
||||
strcmp(yprefix->ys_argument, prefix) != 0){
|
||||
clicon_err(OE_YANG, 0, "Module with id:%s:%s not found", prefix,id);
|
||||
clicon_err(OE_YANG, 0, "Module with id:\"%s:%s\" not found", prefix,id);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
|
@ -2546,12 +2720,7 @@ ys_parse_sub(yang_stmt *ys,
|
|||
char *extra)
|
||||
{
|
||||
int retval = -1;
|
||||
int cvret;
|
||||
char *reason = NULL;
|
||||
yang_stmt *ymod;
|
||||
uint8_t fd;
|
||||
char *prefix = NULL;
|
||||
char *name;
|
||||
|
||||
switch (ys->ys_keyword){
|
||||
case Y_FRACTION_DIGITS:
|
||||
|
|
@ -2563,40 +2732,17 @@ ys_parse_sub(yang_stmt *ys,
|
|||
goto done;
|
||||
}
|
||||
break;
|
||||
case Y_UNKNOWN:
|
||||
case Y_UNKNOWN: /* XXX This code assumes ymod already loaded
|
||||
but it may not be */
|
||||
if (extra == NULL)
|
||||
break;
|
||||
/* Find extension, if found, store it as unknown, if not,
|
||||
break for error */
|
||||
prefix = yarg_prefix(ys); /* And this its prefix */
|
||||
name = yarg_id(ys); /* This is the type to resolve */
|
||||
if ((ymod = yang_find_module_by_prefix(ys, prefix)) == NULL)
|
||||
goto ok; /* shouldnt happen */
|
||||
if (yang_find((yang_node*)ymod, Y_EXTENSION, name) == NULL){
|
||||
clicon_err(OE_YANG, errno, "Extension %s:%s not found", prefix, name);
|
||||
goto done;
|
||||
}
|
||||
if ((ys->ys_cv = cv_new(CGV_STRING)) == NULL){
|
||||
clicon_err(OE_YANG, errno, "cv_new");
|
||||
goto done;
|
||||
}
|
||||
if ((cvret = cv_parse1(extra, ys->ys_cv, &reason)) < 0){ /* error */
|
||||
clicon_err(OE_YANG, errno, "parsing cv");
|
||||
goto done;
|
||||
}
|
||||
if (cvret == 0){ /* parsing failed */
|
||||
clicon_err(OE_YANG, errno, "Parsing CV: %s", reason);
|
||||
goto done;
|
||||
}
|
||||
ys->ys_extra = extra;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
ok:
|
||||
retval = 0;
|
||||
done:
|
||||
if (prefix)
|
||||
free(prefix);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
|
@ -2654,7 +2800,6 @@ yang_config(yang_stmt *ys)
|
|||
int
|
||||
yang_spec_parse_module(clicon_handle h,
|
||||
char *module,
|
||||
char *dir,
|
||||
char *revision,
|
||||
yang_spec *yspec,
|
||||
yang_stmt **ymodp)
|
||||
|
|
@ -2674,11 +2819,7 @@ yang_spec_parse_module(clicon_handle h,
|
|||
clicon_err(OE_YANG, EINVAL, "yang module illegal format");
|
||||
goto done;
|
||||
}
|
||||
if (dir == NULL){
|
||||
clicon_err(OE_YANG, EINVAL, "yang dir not set");
|
||||
goto done;
|
||||
}
|
||||
if (yang_parse(h, NULL, module, dir, revision, yspec, ymodp) < 0)
|
||||
if (yang_parse(h, NULL, module, revision, yspec, ymodp) < 0)
|
||||
goto done;
|
||||
retval = 0;
|
||||
done:
|
||||
|
|
@ -2698,7 +2839,6 @@ yang_spec_parse_module(clicon_handle h,
|
|||
int
|
||||
yang_spec_parse_file(clicon_handle h,
|
||||
char *filename,
|
||||
char *dir,
|
||||
yang_spec *yspec,
|
||||
yang_stmt **ymodp)
|
||||
{
|
||||
|
|
@ -2708,11 +2848,7 @@ yang_spec_parse_file(clicon_handle h,
|
|||
clicon_err(OE_YANG, EINVAL, "yang spec is NULL");
|
||||
goto done;
|
||||
}
|
||||
if (dir == NULL){
|
||||
clicon_err(OE_YANG, EINVAL, "yang dir not set");
|
||||
goto done;
|
||||
}
|
||||
if (yang_parse(h, filename, NULL, dir, NULL, yspec, ymodp) < 0)
|
||||
if (yang_parse(h, filename, NULL, NULL, yspec, ymodp) < 0)
|
||||
goto done;
|
||||
retval = 0;
|
||||
done:
|
||||
|
|
|
|||
|
|
@ -193,7 +193,8 @@ yang_cardinality(clicon_handle h,
|
|||
|
||||
pk = yt->ys_keyword;
|
||||
/* 0) Find parent sub-parts of cardinality vector */
|
||||
ycplist = ycard_find(pk, 0, yclist, 0);
|
||||
if ((ycplist = ycard_find(pk, 0, yclist, 0)) == NULL)
|
||||
goto ok; /* skip */
|
||||
/* 1) For all children, if neither in 0..n, 0..1, 1 or 1..n ->ERROR */
|
||||
i = 0;
|
||||
while (i<yt->ys_len){
|
||||
|
|
@ -231,14 +232,15 @@ yang_cardinality(clicon_handle h,
|
|||
}
|
||||
|
||||
if (0) { /* Notyet */
|
||||
/* 4) Recurse */
|
||||
i = 0;
|
||||
while (i<yt->ys_len){ /* Note, children may be removed */
|
||||
ys = yt->ys_stmt[i++];
|
||||
if (yang_cardinality(h, ys, modname) < 0)
|
||||
goto done;
|
||||
}
|
||||
/* 4) Recurse */
|
||||
i = 0;
|
||||
while (i<yt->ys_len){ /* Note, children may be removed */
|
||||
ys = yt->ys_stmt[i++];
|
||||
if (yang_cardinality(h, ys, modname) < 0)
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
ok:
|
||||
retval = 0;
|
||||
done:
|
||||
return retval;
|
||||
|
|
|
|||
|
|
@ -77,7 +77,6 @@
|
|||
*
|
||||
* Load RFC7895 yang spec, module-set-id, etc.
|
||||
* @param[in] h Clicon handle
|
||||
* @note CLIXON_DATADIR is hardcoded
|
||||
*/
|
||||
int
|
||||
yang_modules_init(clicon_handle h)
|
||||
|
|
@ -94,7 +93,7 @@ yang_modules_init(clicon_handle h)
|
|||
goto done;
|
||||
}
|
||||
/* Ensure revision exists is set */
|
||||
if (yang_spec_parse_module(h, "ietf-yang-library", CLIXON_DATADIR, NULL, yspec, NULL)< 0)
|
||||
if (yang_spec_parse_module(h, "ietf-yang-library", NULL, yspec, NULL)< 0)
|
||||
goto done;
|
||||
/* Find revision */
|
||||
if (yang_modules_revision(h) == NULL){
|
||||
|
|
@ -121,7 +120,8 @@ yang_modules_revision(clicon_handle h)
|
|||
char *revision = NULL;
|
||||
|
||||
yspec = clicon_dbspec_yang(h);
|
||||
if ((ymod = yang_find((yang_node*)yspec, Y_MODULE, "ietf-yang-library")) != NULL){
|
||||
if ((ymod = yang_find((yang_node*)yspec, Y_MODULE, "ietf-yang-library")) != NULL ||
|
||||
(ymod = yang_find((yang_node*)yspec, Y_SUBMODULE, "ietf-yang-library")) != NULL){
|
||||
if ((yrev = yang_find((yang_node*)ymod, Y_REVISION, NULL)) != NULL){
|
||||
revision = yrev->ys_argument;
|
||||
}
|
||||
|
|
@ -172,7 +172,8 @@ yang_modules_state_get(clicon_handle h,
|
|||
char *module = "ietf-yang-library";
|
||||
|
||||
module_set_id = clicon_option_str(h, "CLICON_MODULE_SET_ID");
|
||||
if ((ylib = yang_find((yang_node*)yspec, Y_MODULE, module)) == NULL){
|
||||
if ((ylib = yang_find((yang_node*)yspec, Y_MODULE, module)) == NULL &&
|
||||
(ylib = yang_find((yang_node*)yspec, Y_SUBMODULE, module)) == NULL){
|
||||
clicon_err(OE_YANG, 0, "%s not found", module);
|
||||
goto done;
|
||||
}
|
||||
|
|
@ -189,7 +190,8 @@ yang_modules_state_get(clicon_handle h,
|
|||
|
||||
ymod = NULL;
|
||||
while ((ymod = yn_each((yang_node*)yspec, ymod)) != NULL) {
|
||||
if (ymod->ys_keyword != Y_MODULE)
|
||||
if (ymod->ys_keyword != Y_MODULE &&
|
||||
ymod->ys_keyword != Y_SUBMODULE)
|
||||
continue;
|
||||
cprintf(cb,"<module>");
|
||||
cprintf(cb,"<name>%s</name>", ymod->ys_argument);
|
||||
|
|
|
|||
|
|
@ -42,9 +42,6 @@
|
|||
* identifier_ref = prefix : IDENTIFIER
|
||||
* node_identier = prefix : IDENTIFIER
|
||||
*
|
||||
* Missing top-level statements (will break parser if in yang spec):
|
||||
* - error-app-tag-stmt
|
||||
* - any-data-stmt
|
||||
* Missing args (just strings);
|
||||
* - length-arg-str
|
||||
* - path-arg-str
|
||||
|
|
@ -124,6 +121,7 @@
|
|||
%token K_MANDATORY
|
||||
%token K_MAX_ELEMENTS
|
||||
%token K_MIN_ELEMENTS
|
||||
%token K_MODIFIER
|
||||
%token K_MODULE
|
||||
%token K_MUST
|
||||
%token K_NAMESPACE
|
||||
|
|
@ -369,29 +367,28 @@ file : module_stmt MY_EOF
|
|||
|
||||
/* For extensions */
|
||||
unknown_stmt : ustring ':' ustring ';'
|
||||
{ char *id; if ((id=string_del_join($1, ":", $3)) == NULL) _YYERROR("0");
|
||||
if (ysp_add(_yy, Y_UNKNOWN, id, NULL) == NULL) _YYERROR("0");
|
||||
{ char *id; if ((id=string_del_join($1, ":", $3)) == NULL) _YYERROR("unknown_stmt");
|
||||
if (ysp_add(_yy, Y_UNKNOWN, id, NULL) == NULL) _YYERROR("unknown_stmt");
|
||||
clicon_debug(2,"unknown-stmt -> ustring : ustring");
|
||||
}
|
||||
| ustring ':' ustring ' ' string ';'
|
||||
{ char *id; if ((id=string_del_join($1, ":", $3)) == NULL) _YYERROR("0");
|
||||
if (ysp_add(_yy, Y_UNKNOWN, id, $5) == NULL){ _YYERROR("0"); }
|
||||
{ char *id; if ((id=string_del_join($1, ":", $3)) == NULL) _YYERROR("unknwon_stmt");
|
||||
if (ysp_add(_yy, Y_UNKNOWN, id, $5) == NULL){ _YYERROR("unknwon_stmt"); }
|
||||
clicon_debug(2,"unknown-stmt -> ustring : ustring string");
|
||||
if ($5) free($5);
|
||||
}
|
||||
;
|
||||
|
||||
/* module identifier-arg-str */
|
||||
module_stmt : K_MODULE identifier_str
|
||||
{ if ((_YY->yy_module = ysp_add_push(_yy, Y_MODULE, $2)) == NULL) _YYERROR("1");
|
||||
{ if ((_YY->yy_module = ysp_add_push(_yy, Y_MODULE, $2)) == NULL) _YYERROR("module_stmt");
|
||||
}
|
||||
'{' module_substmts '}'
|
||||
{ if (ystack_pop(_yy) < 0) _YYERROR("2");
|
||||
clicon_debug(2,"module_stmt -> id-arg-str { module-substmts }");}
|
||||
{ if (ystack_pop(_yy) < 0) _YYERROR("module_stmt");
|
||||
clicon_debug(2,"module_stmt -> id-arg-str { module-substmts }");}
|
||||
;
|
||||
|
||||
module_substmts : module_substmts module_substmt
|
||||
{ clicon_debug(2,"module-substmts -> module-substmts module-substm");}
|
||||
{clicon_debug(2,"module-substmts -> module-substmts module-substm");}
|
||||
| module_substmt
|
||||
{ clicon_debug(2,"module-substmts ->");}
|
||||
;
|
||||
|
|
@ -406,10 +403,11 @@ module_substmt : module_header_stmts { clicon_debug(2,"module-substmt -> module-
|
|||
;
|
||||
|
||||
/* submodule */
|
||||
submodule_stmt : K_SUBMODULE identifier_str '{' submodule_substmts '}'
|
||||
{ if ((_YY->yy_module = ysp_add_push(_yy, Y_SUBMODULE, $2)) == NULL) _YYERROR("3");
|
||||
clicon_debug(2,"submodule -> id-arg-str { submodule-stmts }");
|
||||
}
|
||||
submodule_stmt : K_SUBMODULE identifier_str
|
||||
{ if ((_YY->yy_module = ysp_add_push(_yy, Y_SUBMODULE, $2)) == NULL) _YYERROR("submodule_stmt"); }
|
||||
'{' submodule_substmts '}'
|
||||
{ if (ystack_pop(_yy) < 0) _YYERROR("submodule_stmt");
|
||||
clicon_debug(2,"submodule_stmt -> id-arg-str { submodule-substmts }");}
|
||||
;
|
||||
|
||||
submodule_substmts : submodule_substmts submodule_substmt
|
||||
|
|
@ -464,16 +462,16 @@ submodule_header_stmt : yang_version_stmt
|
|||
;
|
||||
|
||||
/* yang-version-stmt = yang-version-keyword yang-version-arg-str */
|
||||
yang_version_stmt : K_YANG_VERSION string ';'
|
||||
{ if (ysp_add(_yy, Y_YANG_VERSION, $2, NULL) == NULL) _YYERROR("83");
|
||||
yang_version_stmt : K_YANG_VERSION string stmtend
|
||||
{ if (ysp_add(_yy, Y_YANG_VERSION, $2, NULL) == NULL) _YYERROR("yang_version_stmt");
|
||||
clicon_debug(2,"yang-version-stmt -> YANG-VERSION string"); }
|
||||
;
|
||||
|
||||
/* import */
|
||||
import_stmt : K_IMPORT identifier_str
|
||||
{ if (ysp_add_push(_yy, Y_IMPORT, $2) == NULL) _YYERROR("81"); }
|
||||
{ if (ysp_add_push(_yy, Y_IMPORT, $2) == NULL) _YYERROR("import_stmt"); }
|
||||
'{' import_substmts '}'
|
||||
{ if (ystack_pop(_yy) < 0) _YYERROR("82");
|
||||
{ if (ystack_pop(_yy) < 0) _YYERROR("import_stmt");
|
||||
clicon_debug(2,"import-stmt -> IMPORT id-arg-str { import-substmts }");}
|
||||
;
|
||||
|
||||
|
|
@ -484,69 +482,79 @@ import_substmts : import_substmts import_substmt
|
|||
;
|
||||
|
||||
import_substmt : prefix_stmt { clicon_debug(2,"import-stmt -> prefix-stmt"); }
|
||||
| revision_date_stmt { clicon_debug(2,"import-stmt -> revision-date-stmt"); }
|
||||
| revision_date_stmt { clicon_debug(2,"import-stmt -> revision-date-stmt"); }
|
||||
| description_stmt { clicon_debug(2,"import-stmt -> description-stmt"); }
|
||||
| reference_stmt { clicon_debug(2,"import-stmt -> reference-stmt"); }
|
||||
;
|
||||
|
||||
include_stmt : K_INCLUDE identifier_str ';'
|
||||
{ if (ysp_add(_yy, Y_INCLUDE, $2, NULL)== NULL) _YYERROR("97");
|
||||
clicon_debug(2,"include-stmt -> id-arg-str"); }
|
||||
| K_INCLUDE identifier_str '{' revision_date_stmt '}'
|
||||
{ if (ysp_add(_yy, Y_INCLUDE, $2, NULL)== NULL) _YYERROR("98");
|
||||
clicon_debug(2,"include-stmt -> id-arg-str { revision-date-stmt }"); }
|
||||
{ if (ysp_add(_yy, Y_INCLUDE, $2, NULL)== NULL) _YYERROR("include_stmt");
|
||||
clicon_debug(2,"include-stmt -> id-str"); }
|
||||
| K_INCLUDE identifier_str '{' include_substmts '}'
|
||||
{ if (ysp_add(_yy, Y_INCLUDE, $2, NULL)== NULL) _YYERROR("include_stmt");
|
||||
clicon_debug(2,"include-stmt -> id-str { include-substmts }"); }
|
||||
;
|
||||
|
||||
include_substmts : include_substmts include_substmt
|
||||
{ clicon_debug(2,"include-substmts -> include-substmts include-substm");}
|
||||
| include_substmt
|
||||
{ clicon_debug(2,"include-substmts ->");}
|
||||
;
|
||||
|
||||
include_substmt : revision_date_stmt { clicon_debug(2,"include-stmt -> revision-date-stmt"); }
|
||||
| description_stmt { clicon_debug(2,"include-stmt -> description-stmt"); }
|
||||
| reference_stmt { clicon_debug(2,"include-stmt -> reference-stmt"); }
|
||||
;
|
||||
|
||||
|
||||
/* namespace-stmt = namespace-keyword sep uri-str */
|
||||
namespace_stmt : K_NAMESPACE string stmtend
|
||||
{ if (ysp_add(_yy, Y_NAMESPACE, $2, NULL)== NULL) _YYERROR("99");
|
||||
{ if (ysp_add(_yy, Y_NAMESPACE, $2, NULL)== NULL) _YYERROR("namespace_stmt");
|
||||
clicon_debug(2,"namespace-stmt -> NAMESPACE string"); }
|
||||
;
|
||||
|
||||
prefix_stmt : K_PREFIX identifier_str ';' /* XXX prefix-arg-str */
|
||||
{ if (ysp_add(_yy, Y_PREFIX, $2, NULL)== NULL) _YYERROR("100");
|
||||
prefix_stmt : K_PREFIX identifier_str stmtend /* XXX prefix-arg-str */
|
||||
{ if (ysp_add(_yy, Y_PREFIX, $2, NULL)== NULL) _YYERROR("prefix_stmt");
|
||||
clicon_debug(2,"prefix-stmt -> PREFIX string ;");}
|
||||
;
|
||||
|
||||
belongs_to_stmt : K_BELONGS_TO identifier_str ';'
|
||||
|
||||
{ if (ysp_add(_yy, Y_BELONGS_TO, $2, NULL)== NULL) _YYERROR("100");
|
||||
clicon_debug(2,"belongs-to-stmt -> BELONGS-TO id-arg-str ;");}
|
||||
| K_BELONGS_TO identifier_str '{' prefix_stmt '}'
|
||||
{ if (ysp_add(_yy, Y_BELONGS_TO, $2, NULL)== NULL) _YYERROR("98");
|
||||
belongs_to_stmt : K_BELONGS_TO identifier_str '{' prefix_stmt '}'
|
||||
{ if (ysp_add(_yy, Y_BELONGS_TO, $2, NULL)== NULL) _YYERROR("belongs_to_stmt");
|
||||
clicon_debug(2,"belongs-to-stmt -> BELONGS-TO id-arg-str { prefix-stmt } ");}
|
||||
;
|
||||
|
||||
organization_stmt: K_ORGANIZATION string ';'
|
||||
{ if (ysp_add(_yy, Y_ORGANIZATION, $2, NULL)== NULL) _YYERROR("102");
|
||||
organization_stmt: K_ORGANIZATION string stmtend
|
||||
{ if (ysp_add(_yy, Y_ORGANIZATION, $2, NULL)== NULL) _YYERROR("belongs_to_stmt");
|
||||
clicon_debug(2,"organization-stmt -> ORGANIZATION string ;");}
|
||||
;
|
||||
|
||||
contact_stmt : K_CONTACT string ';'
|
||||
{ if (ysp_add(_yy, Y_CONTACT, $2, NULL)== NULL) _YYERROR("95");
|
||||
contact_stmt : K_CONTACT string stmtend
|
||||
{ if (ysp_add(_yy, Y_CONTACT, $2, NULL)== NULL) _YYERROR("contact_stmt");
|
||||
clicon_debug(2,"contact-stmt -> CONTACT string"); }
|
||||
;
|
||||
|
||||
description_stmt: K_DESCRIPTION string ';'
|
||||
{ if (ysp_add(_yy, Y_DESCRIPTION, $2, NULL)== NULL) _YYERROR("101");
|
||||
description_stmt : K_DESCRIPTION string stmtend
|
||||
{ if (ysp_add(_yy, Y_DESCRIPTION, $2, NULL)== NULL) _YYERROR("description_stmt");
|
||||
clicon_debug(2,"description-stmt -> DESCRIPTION string ;");}
|
||||
;
|
||||
|
||||
reference_stmt: K_REFERENCE string ';'
|
||||
{ if (ysp_add(_yy, Y_REFERENCE, $2, NULL)== NULL) _YYERROR("105");
|
||||
reference_stmt : K_REFERENCE string stmtend
|
||||
{ if (ysp_add(_yy, Y_REFERENCE, $2, NULL)== NULL) _YYERROR("reference_stmt");
|
||||
clicon_debug(2,"reference-stmt -> REFERENCE string ;");}
|
||||
;
|
||||
|
||||
units_stmt : K_UNITS string ';'
|
||||
{ if (ysp_add(_yy, Y_UNITS, $2, NULL)== NULL) _YYERROR("93");
|
||||
{ if (ysp_add(_yy, Y_UNITS, $2, NULL)== NULL) _YYERROR("units_stmt");
|
||||
clicon_debug(2,"units-stmt -> UNITS string"); }
|
||||
;
|
||||
|
||||
revision_stmt : K_REVISION string ';' /* XXX date-arg-str */
|
||||
{ if (ysp_add(_yy, Y_REVISION, $2, NULL) == NULL) _YYERROR("4");
|
||||
{ if (ysp_add(_yy, Y_REVISION, $2, NULL) == NULL) _YYERROR("revision_stmt");
|
||||
clicon_debug(2,"revision-stmt -> date-arg-str ;"); }
|
||||
| K_REVISION string
|
||||
{ if (ysp_add_push(_yy, Y_REVISION, $2) == NULL) _YYERROR("5"); }
|
||||
{ if (ysp_add_push(_yy, Y_REVISION, $2) == NULL) _YYERROR("revision_stmt"); }
|
||||
'{' revision_substmts '}' /* XXX date-arg-str */
|
||||
{ if (ystack_pop(_yy) < 0) _YYERROR("6");
|
||||
{ if (ystack_pop(_yy) < 0) _YYERROR("revision_stmt");
|
||||
clicon_debug(2,"revision-stmt -> date-arg-str { revision-substmts }"); }
|
||||
;
|
||||
|
||||
|
|
@ -570,19 +578,18 @@ revision_stmts : revision_stmts revision_stmt
|
|||
{ clicon_debug(2,"revision-stmts -> "); }
|
||||
;
|
||||
|
||||
revision_date_stmt : K_REVISION_DATE string ';' /* XXX date-arg-str */
|
||||
{ if (ysp_add(_yy, Y_REVISION_DATE, $2, NULL) == NULL) _YYERROR("96");
|
||||
revision_date_stmt : K_REVISION_DATE string stmtend /* XXX date-arg-str */
|
||||
{ if (ysp_add(_yy, Y_REVISION_DATE, $2, NULL) == NULL) _YYERROR("revision_date_stmt");
|
||||
clicon_debug(2,"revision-date-stmt -> date;"); }
|
||||
;
|
||||
|
||||
/* Extension */
|
||||
extension_stmt: K_EXTENSION identifier_str ';'
|
||||
{ if (ysp_add(_yy, Y_EXTENSION, $2, NULL) == NULL) _YYERROR("59");
|
||||
extension_stmt : K_EXTENSION identifier_str ';'
|
||||
{ if (ysp_add(_yy, Y_EXTENSION, $2, NULL) == NULL) _YYERROR("extension_stmt");
|
||||
clicon_debug(2,"extenstion-stmt -> EXTENSION id-arg-str ;"); }
|
||||
| K_EXTENSION identifier_str
|
||||
{ if (ysp_add_push(_yy, Y_EXTENSION, $2) == NULL) _YYERROR("60"); }
|
||||
{ if (ysp_add_push(_yy, Y_EXTENSION, $2) == NULL) _YYERROR("extension_stmt"); }
|
||||
'{' extension_substmts '}'
|
||||
{ if (ystack_pop(_yy) < 0) _YYERROR("61");
|
||||
{ if (ystack_pop(_yy) < 0) _YYERROR("extension_stmt");
|
||||
clicon_debug(2,"extension-stmt -> FEATURE id-arg-str { extension-substmts }"); }
|
||||
;
|
||||
|
||||
|
|
@ -612,13 +619,13 @@ yin_element_stmt1 : K_YIN_ELEMENT bool_str stmtend {free($2);}
|
|||
|
||||
/* Identity */
|
||||
identity_stmt : K_IDENTITY identifier_str ';'
|
||||
{ if (ysp_add(_yy, Y_IDENTITY, $2, NULL) == NULL) _YYERROR("65");
|
||||
{ if (ysp_add(_yy, Y_IDENTITY, $2, NULL) == NULL) _YYERROR("identity_stmt");
|
||||
clicon_debug(2,"identity-stmt -> IDENTITY string ;"); }
|
||||
|
||||
| K_IDENTITY identifier_str
|
||||
{ if (ysp_add_push(_yy, Y_IDENTITY, $2) == NULL) _YYERROR("66"); }
|
||||
{ if (ysp_add_push(_yy, Y_IDENTITY, $2) == NULL) _YYERROR("identity_stmt"); }
|
||||
'{' identity_substmts '}'
|
||||
{ if (ystack_pop(_yy) < 0) _YYERROR("67");
|
||||
{ if (ystack_pop(_yy) < 0) _YYERROR("identity_stmt");
|
||||
clicon_debug(2,"identity-stmt -> IDENTITY string { identity-substmts }"); }
|
||||
;
|
||||
|
||||
|
|
@ -636,19 +643,19 @@ identity_substmt : base_stmt { clicon_debug(2,"identity-substmt -> base-
|
|||
| { clicon_debug(2,"identity-substmt -> "); }
|
||||
;
|
||||
|
||||
base_stmt : K_BASE identifier_ref_str ';'
|
||||
{ if (ysp_add(_yy, Y_BASE, $2, NULL)== NULL) _YYERROR("90");
|
||||
base_stmt : K_BASE identifier_ref_str stmtend
|
||||
{ if (ysp_add(_yy, Y_BASE, $2, NULL)== NULL) _YYERROR("base_stmt");
|
||||
clicon_debug(2,"base-stmt -> BASE identifier-ref-arg-str"); }
|
||||
;
|
||||
|
||||
/* Feature */
|
||||
feature_stmt : K_FEATURE identifier_str ';'
|
||||
{ if (ysp_add(_yy, Y_FEATURE, $2, NULL) == NULL) _YYERROR("62");
|
||||
{ if (ysp_add(_yy, Y_FEATURE, $2, NULL) == NULL) _YYERROR("feature_stmt");
|
||||
clicon_debug(2,"feature-stmt -> FEATURE id-arg-str ;"); }
|
||||
| K_FEATURE identifier_str
|
||||
{ if (ysp_add_push(_yy, Y_FEATURE, $2) == NULL) _YYERROR("63"); }
|
||||
{ if (ysp_add_push(_yy, Y_FEATURE, $2) == NULL) _YYERROR("feature_stmt"); }
|
||||
'{' feature_substmts '}'
|
||||
{ if (ystack_pop(_yy) < 0) _YYERROR("64");
|
||||
{ if (ystack_pop(_yy) < 0) _YYERROR("feature_stmt");
|
||||
clicon_debug(2,"feature-stmt -> FEATURE id-arg-str { feature-substmts }"); }
|
||||
;
|
||||
|
||||
|
|
@ -669,15 +676,15 @@ feature_substmt : if_feature_stmt { clicon_debug(2,"feature-substmt -> if-fea
|
|||
|
||||
/* if-feature-stmt = if-feature-keyword sep if-feature-expr-str */
|
||||
if_feature_stmt : K_IF_FEATURE string stmtend
|
||||
{ if (ysp_add(_yy, Y_IF_FEATURE, $2, NULL) == NULL) _YYERROR("85");
|
||||
{ if (ysp_add(_yy, Y_IF_FEATURE, $2, NULL) == NULL) _YYERROR("if_feature_stmt");
|
||||
clicon_debug(2,"if-feature-stmt -> IF-FEATURE identifier-ref-arg-str"); }
|
||||
;
|
||||
|
||||
/* Typedef */
|
||||
typedef_stmt : K_TYPEDEF identifier_str
|
||||
{ if (ysp_add_push(_yy, Y_TYPEDEF, $2) == NULL) _YYERROR("46"); }
|
||||
{ if (ysp_add_push(_yy, Y_TYPEDEF, $2) == NULL) _YYERROR("typedef_stmt"); }
|
||||
'{' typedef_substmts '}'
|
||||
{ if (ystack_pop(_yy) < 0) _YYERROR("47");
|
||||
{ if (ystack_pop(_yy) < 0) _YYERROR("typedef_stmt");
|
||||
clicon_debug(2,"typedef-stmt -> TYPEDEF id-arg-str { typedef-substmts }"); }
|
||||
;
|
||||
|
||||
|
|
@ -699,13 +706,13 @@ typedef_substmt : type_stmt { clicon_debug(2,"typedef-substmt -> type-s
|
|||
|
||||
/* Type */
|
||||
type_stmt : K_TYPE identifier_ref_str ';'
|
||||
{ if (ysp_add(_yy, Y_TYPE, $2, NULL) == NULL) _YYERROR("48");
|
||||
{ if (ysp_add(_yy, Y_TYPE, $2, NULL) == NULL) _YYERROR("type_stmt");
|
||||
clicon_debug(2,"type-stmt -> TYPE identifier-ref-arg-str ;");}
|
||||
| K_TYPE identifier_ref_str
|
||||
{ if (ysp_add_push(_yy, Y_TYPE, $2) == NULL) _YYERROR("49");
|
||||
{ if (ysp_add_push(_yy, Y_TYPE, $2) == NULL) _YYERROR("type_stmt");
|
||||
}
|
||||
'{' type_body_stmts '}'
|
||||
{ if (ystack_pop(_yy) < 0) _YYERROR("50");
|
||||
{ if (ystack_pop(_yy) < 0) _YYERROR("type_stmt");
|
||||
clicon_debug(2,"type-stmt -> TYPE identifier-ref-arg-str { type-body-stmts }");}
|
||||
;
|
||||
|
||||
|
|
@ -742,13 +749,13 @@ type_body_stmt/* numerical-restrictions */
|
|||
|
||||
/* range-stmt */
|
||||
range_stmt : K_RANGE string ';' /* XXX range-arg-str */
|
||||
{ if (ysp_add(_yy, Y_RANGE, $2, NULL) == NULL) _YYERROR("68");
|
||||
{ if (ysp_add(_yy, Y_RANGE, $2, NULL) == NULL) _YYERROR("range_stmt");
|
||||
clicon_debug(2,"range-stmt -> RANGE string ;"); }
|
||||
|
||||
| K_RANGE string
|
||||
{ if (ysp_add_push(_yy, Y_RANGE, $2) == NULL) _YYERROR("69"); }
|
||||
{ if (ysp_add_push(_yy, Y_RANGE, $2) == NULL) _YYERROR("range_stmt"); }
|
||||
'{' range_substmts '}'
|
||||
{ if (ystack_pop(_yy) < 0) _YYERROR("70");
|
||||
{ if (ystack_pop(_yy) < 0) _YYERROR("range_stmt");
|
||||
clicon_debug(2,"range-stmt -> RANGE string { range-substmts }"); }
|
||||
;
|
||||
|
||||
|
|
@ -767,7 +774,7 @@ range_substmt : error_message_stmt { clicon_debug(2,"range-substmt -> error-me
|
|||
|
||||
/* fraction-digits-stmt = fraction-digits-keyword fraction-digits-arg-str */
|
||||
fraction_digits_stmt : K_FRACTION_DIGITS string stmtend
|
||||
{ if (ysp_add(_yy, Y_FRACTION_DIGITS, $2, NULL) == NULL) _YYERROR("84");
|
||||
{ if (ysp_add(_yy, Y_FRACTION_DIGITS, $2, NULL) == NULL) _YYERROR("fraction_digits_stmt");
|
||||
clicon_debug(2,"fraction-digits-stmt -> FRACTION-DIGITS string"); }
|
||||
;
|
||||
|
||||
|
|
@ -776,15 +783,22 @@ meta_stmts : meta_stmts meta_stmt { clicon_debug(2,"meta-stmts -> meta-stmts
|
|||
| meta_stmt { clicon_debug(2,"meta-stmts -> meta-stmt"); }
|
||||
;
|
||||
|
||||
meta_stmt : organization_stmt { clicon_debug(2,"meta-stmt -> organization-stmt"); }
|
||||
| contact_stmt { clicon_debug(2,"meta-stmt -> contact-stmt"); }
|
||||
| description_stmt { clicon_debug(2,"meta-stmt -> description-stmt"); }
|
||||
| reference_stmt { clicon_debug(2,"meta-stmt -> reference-stmt"); }
|
||||
;
|
||||
|
||||
|
||||
/* length-stmt */
|
||||
length_stmt : K_LENGTH string ';' /* XXX length-arg-str */
|
||||
{ if (ysp_add(_yy, Y_LENGTH, $2, NULL) == NULL) _YYERROR("53");
|
||||
{ if (ysp_add(_yy, Y_LENGTH, $2, NULL) == NULL) _YYERROR("length_stmt");
|
||||
clicon_debug(2,"length-stmt -> LENGTH string ;"); }
|
||||
|
||||
| K_LENGTH string
|
||||
{ if (ysp_add_push(_yy, Y_LENGTH, $2) == NULL) _YYERROR("54"); }
|
||||
{ if (ysp_add_push(_yy, Y_LENGTH, $2) == NULL) _YYERROR("length_stmt"); }
|
||||
'{' length_substmts '}'
|
||||
{ if (ystack_pop(_yy) < 0) _YYERROR("55");
|
||||
{ if (ystack_pop(_yy) < 0) _YYERROR("length_stmt");
|
||||
clicon_debug(2,"length-stmt -> LENGTH string { length-substmts }"); }
|
||||
;
|
||||
|
||||
|
|
@ -803,13 +817,13 @@ length_substmt : error_message_stmt { clicon_debug(2,"length-substmt -> error-m
|
|||
|
||||
/* Pattern */
|
||||
pattern_stmt : K_PATTERN string ';'
|
||||
{ if (ysp_add(_yy, Y_PATTERN, $2, NULL) == NULL) _YYERROR("56");
|
||||
{ if (ysp_add(_yy, Y_PATTERN, $2, NULL) == NULL) _YYERROR("pattern_stmt");
|
||||
clicon_debug(2,"pattern-stmt -> PATTERN string ;"); }
|
||||
|
||||
| K_PATTERN string
|
||||
{ if (ysp_add_push(_yy, Y_PATTERN, $2) == NULL) _YYERROR("57"); }
|
||||
{ if (ysp_add_push(_yy, Y_PATTERN, $2) == NULL) _YYERROR("pattern_stmt"); }
|
||||
'{' pattern_substmts '}'
|
||||
{ if (ystack_pop(_yy) < 0) _YYERROR("58");
|
||||
{ if (ystack_pop(_yy) < 0) _YYERROR("pattern_stmt");
|
||||
clicon_debug(2,"pattern-stmt -> PATTERN string { pattern-substmts }"); }
|
||||
;
|
||||
|
||||
|
|
@ -819,27 +833,34 @@ pattern_substmts : pattern_substmts pattern_substmt
|
|||
{ clicon_debug(2,"pattern-substmts -> pattern-substmt"); }
|
||||
;
|
||||
|
||||
pattern_substmt : reference_stmt { clicon_debug(2,"pattern-substmt -> reference-stmt"); }
|
||||
| error_message_stmt { clicon_debug(2,"pattern-substmt -> error-message-stmt");}
|
||||
| unknown_stmt { clicon_debug(2,"pattern-substmt -> unknown-stmt");}
|
||||
pattern_substmt : modifier_stmt { clicon_debug(2,"pattern-substmt -> modifier-stmt");}
|
||||
| error_message_stmt { clicon_debug(2,"pattern-substmt -> error-message-stmt");}
|
||||
| error_app_tag_stmt { clicon_debug(2,"pattern-substmt -> error-app-tag-stmt");}
|
||||
| description_stmt { clicon_debug(2,"pattern-substmt -> description-stmt");}
|
||||
| reference_stmt { clicon_debug(2,"pattern-substmt -> reference-stmt"); }
|
||||
| unknown_stmt { clicon_debug(2,"pattern-substmt -> unknown-stmt");}
|
||||
|
||||
| { clicon_debug(2,"pattern-substmt -> "); }
|
||||
;
|
||||
|
||||
default_stmt : K_DEFAULT string ';'
|
||||
{ if (ysp_add(_yy, Y_DEFAULT, $2, NULL)== NULL) _YYERROR("94");
|
||||
modifier_stmt : K_MODIFIER string stmtend
|
||||
{ if (ysp_add(_yy, Y_DEFAULT, $2, NULL)== NULL) _YYERROR("modifier_stmt");
|
||||
clicon_debug(2,"modifier-stmt -> MODIFIER string"); }
|
||||
;
|
||||
|
||||
default_stmt : K_DEFAULT string stmtend
|
||||
{ if (ysp_add(_yy, Y_DEFAULT, $2, NULL)== NULL) _YYERROR("default_stmt");
|
||||
clicon_debug(2,"default-stmt -> DEFAULT string"); }
|
||||
;
|
||||
|
||||
|
||||
|
||||
/* enum-stmt */
|
||||
enum_stmt : K_ENUM string ';'
|
||||
{ if (ysp_add(_yy, Y_ENUM, $2, NULL) == NULL) _YYERROR("71");
|
||||
{ if (ysp_add(_yy, Y_ENUM, $2, NULL) == NULL) _YYERROR("enum_stmt");
|
||||
clicon_debug(2,"enum-stmt -> ENUM string ;"); }
|
||||
| K_ENUM string
|
||||
{ if (ysp_add_push(_yy, Y_ENUM, $2) == NULL) _YYERROR("72"); }
|
||||
{ if (ysp_add_push(_yy, Y_ENUM, $2) == NULL) _YYERROR("enum_stmt"); }
|
||||
'{' enum_substmts '}'
|
||||
{ if (ystack_pop(_yy) < 0) _YYERROR("73");
|
||||
{ if (ystack_pop(_yy) < 0) _YYERROR("enum_stmt");
|
||||
clicon_debug(2,"enum-stmt -> ENUM string { enum-substmts }"); }
|
||||
;
|
||||
|
||||
|
|
@ -857,24 +878,24 @@ enum_substmt : value_stmt { clicon_debug(2,"enum-substmt -> value-stm
|
|||
| { clicon_debug(2,"enum-substmt -> "); }
|
||||
;
|
||||
|
||||
path_stmt : K_PATH string ';' /* XXX: path-arg-str */
|
||||
{ if (ysp_add(_yy, Y_PATH, $2, NULL)== NULL) _YYERROR("91");
|
||||
path_stmt : K_PATH string stmtend /* XXX: path-arg-str */
|
||||
{ if (ysp_add(_yy, Y_PATH, $2, NULL)== NULL) _YYERROR("path_stmt");
|
||||
clicon_debug(2,"path-stmt -> PATH string"); }
|
||||
;
|
||||
|
||||
require_instance_stmt : K_REQUIRE_INSTANCE bool_str ';'
|
||||
{ if (ysp_add(_yy, Y_REQUIRE_INSTANCE, $2, NULL)== NULL) _YYERROR("92");
|
||||
require_instance_stmt : K_REQUIRE_INSTANCE bool_str stmtend
|
||||
{ if (ysp_add(_yy, Y_REQUIRE_INSTANCE, $2, NULL)== NULL) _YYERROR("require_instance_stmt");
|
||||
clicon_debug(2,"require-instance-stmt -> REQUIRE-INSTANCE string"); }
|
||||
;
|
||||
|
||||
/* bit-stmt */
|
||||
bit_stmt : K_BIT identifier_str ';'
|
||||
{ if (ysp_add(_yy, Y_BIT, $2, NULL) == NULL) _YYERROR("74");
|
||||
{ if (ysp_add(_yy, Y_BIT, $2, NULL) == NULL) _YYERROR("bit_stmt");
|
||||
clicon_debug(2,"bit-stmt -> BIT string ;"); }
|
||||
| K_BIT identifier_str
|
||||
{ if (ysp_add_push(_yy, Y_BIT, $2) == NULL) _YYERROR("75"); }
|
||||
{ if (ysp_add_push(_yy, Y_BIT, $2) == NULL) _YYERROR("bit_stmt"); }
|
||||
'{' bit_substmts '}'
|
||||
{ if (ystack_pop(_yy) < 0) _YYERROR("76");
|
||||
{ if (ystack_pop(_yy) < 0) _YYERROR("bit_stmt");
|
||||
clicon_debug(2,"bit-stmt -> BIT string { bit-substmts }"); }
|
||||
;
|
||||
|
||||
|
|
@ -893,50 +914,50 @@ bit_substmt : position_stmt { clicon_debug(2,"bit-substmt -> positition
|
|||
|
||||
/* position-stmt = position-keyword position-value-arg-str */
|
||||
position_stmt : K_POSITION integer_value_str stmtend
|
||||
{ if (ysp_add(_yy, Y_POSITION, $2, NULL) == NULL) _YYERROR("87");
|
||||
{ if (ysp_add(_yy, Y_POSITION, $2, NULL) == NULL) _YYERROR("position_stmt");
|
||||
clicon_debug(2,"position-stmt -> POSITION integer-value"); }
|
||||
;
|
||||
|
||||
/* status-stmt = status-keyword sep status-arg-str XXX: current-keyword*/
|
||||
status_stmt : K_STATUS string stmtend
|
||||
{ if (ysp_add(_yy, Y_STATUS, $2, NULL) == NULL) _YYERROR("88");
|
||||
{ if (ysp_add(_yy, Y_STATUS, $2, NULL) == NULL) _YYERROR("status_stmt");
|
||||
clicon_debug(2,"status-stmt -> STATUS string"); }
|
||||
;
|
||||
|
||||
config_stmt : K_CONFIG bool_str ';'
|
||||
{ if (ysp_add(_yy, Y_CONFIG, $2, NULL) == NULL) _YYERROR("89");
|
||||
config_stmt : K_CONFIG bool_str stmtend
|
||||
{ if (ysp_add(_yy, Y_CONFIG, $2, NULL) == NULL) _YYERROR("config_stmt");
|
||||
clicon_debug(2,"config-stmt -> CONFIG config-arg-str"); }
|
||||
;
|
||||
|
||||
/* mandatory-stmt = mandatory-keyword mandatory-arg-str */
|
||||
mandatory_stmt: K_MANDATORY bool_str ';'
|
||||
mandatory_stmt : K_MANDATORY bool_str stmtend
|
||||
{ yang_stmt *ys;
|
||||
if ((ys = ysp_add(_yy, Y_MANDATORY, $2, NULL))== NULL) _YYERROR("106");
|
||||
if ((ys = ysp_add(_yy, Y_MANDATORY, $2, NULL))== NULL) _YYERROR("mandatory_stmt");
|
||||
clicon_debug(2,"mandatory-stmt -> MANDATORY mandatory-arg-str ;");}
|
||||
;
|
||||
|
||||
presence_stmt: K_PRESENCE string ';'
|
||||
presence_stmt : K_PRESENCE string stmtend
|
||||
{ yang_stmt *ys;
|
||||
if ((ys = ysp_add(_yy, Y_PRESENCE, $2, NULL))== NULL) _YYERROR("107");
|
||||
if ((ys = ysp_add(_yy, Y_PRESENCE, $2, NULL))== NULL) _YYERROR("presence_stmt");
|
||||
clicon_debug(2,"presence-stmt -> PRESENCE string ;");}
|
||||
;
|
||||
|
||||
/* ordered-by-stmt = ordered-by-keyword sep ordered-by-arg-str */
|
||||
ordered_by_stmt: K_ORDERED_BY string stmtend
|
||||
ordered_by_stmt : K_ORDERED_BY string stmtend
|
||||
{ yang_stmt *ys;
|
||||
if ((ys = ysp_add(_yy, Y_ORDERED_BY, $2, NULL))== NULL) _YYERROR("108");
|
||||
if ((ys = ysp_add(_yy, Y_ORDERED_BY, $2, NULL))== NULL) _YYERROR("ordered_by_stmt");
|
||||
clicon_debug(2,"ordered-by-stmt -> ORDERED-BY ordered-by-arg ;");}
|
||||
;
|
||||
|
||||
/* must-stmt */
|
||||
must_stmt : K_MUST string ';'
|
||||
{ if (ysp_add(_yy, Y_MUST, $2, NULL) == NULL) _YYERROR("77");
|
||||
{ if (ysp_add(_yy, Y_MUST, $2, NULL) == NULL) _YYERROR("must_stmt");
|
||||
clicon_debug(2,"must-stmt -> MUST string ;"); }
|
||||
|
||||
| K_MUST string
|
||||
{ if (ysp_add_push(_yy, Y_MUST, $2) == NULL) _YYERROR("78"); }
|
||||
{ if (ysp_add_push(_yy, Y_MUST, $2) == NULL) _YYERROR("must_stmt"); }
|
||||
'{' must_substmts '}'
|
||||
{ if (ystack_pop(_yy) < 0) _YYERROR("79");
|
||||
{ if (ystack_pop(_yy) < 0) _YYERROR("must_stmt");
|
||||
clicon_debug(2,"must-stmt -> MUST string { must-substmts }"); }
|
||||
;
|
||||
|
||||
|
|
@ -947,42 +968,47 @@ must_substmts : must_substmts must_substmt
|
|||
;
|
||||
|
||||
must_substmt : error_message_stmt { clicon_debug(2,"must-substmt -> error-message-stmt"); }
|
||||
| error_app_tag_stmt { clicon_debug(2,"must-substmt -> error-app-tag-stmt"); }
|
||||
| description_stmt { clicon_debug(2,"must-substmt -> description-stmt"); }
|
||||
| reference_stmt { clicon_debug(2,"must-substmt -> reference-stmt"); }
|
||||
| { clicon_debug(2,"must-substmt -> "); }
|
||||
;
|
||||
|
||||
/* error-message-stmt */
|
||||
error_message_stmt : K_ERROR_MESSAGE string ';'
|
||||
{ if (ysp_add(_yy, Y_ERROR_MESSAGE, $2, NULL) == NULL) _YYERROR("80"); }
|
||||
error_message_stmt : K_ERROR_MESSAGE string stmtend
|
||||
{ if (ysp_add(_yy, Y_ERROR_MESSAGE, $2, NULL) == NULL) _YYERROR("error_message_stmt");
|
||||
clicon_debug(2,"error-message-stmt -> ERROR-MESSAGE string"); }
|
||||
;
|
||||
|
||||
/* XXX error-app-tag-stmt */
|
||||
error_app_tag_stmt : K_ERROR_APP_TAG string stmtend
|
||||
{ if (ysp_add(_yy, Y_ERROR_MESSAGE, $2, NULL) == NULL) _YYERROR("error_message_stmt");
|
||||
clicon_debug(2,"error-app-tag-stmt -> ERROR-APP-TAG string"); }
|
||||
;
|
||||
|
||||
/* min-elements-stmt = min-elements-keyword min-value-arg-str */
|
||||
min_elements_stmt: K_MIN_ELEMENTS integer_value_str stmtend
|
||||
{ if (ysp_add(_yy, Y_MIN_ELEMENTS, $2, NULL)== NULL) _YYERROR("103");
|
||||
min_elements_stmt : K_MIN_ELEMENTS integer_value_str stmtend
|
||||
{ if (ysp_add(_yy, Y_MIN_ELEMENTS, $2, NULL)== NULL) _YYERROR("min_elements_stmt");
|
||||
clicon_debug(2,"min-elements-stmt -> MIN-ELEMENTS integer ;");}
|
||||
;
|
||||
|
||||
/* max-elements-stmt = max-elements-keyword ("unbounded"|integer-value)
|
||||
* XXX cannot use integer-value
|
||||
*/
|
||||
max_elements_stmt: K_MAX_ELEMENTS string ';'
|
||||
{ if (ysp_add(_yy, Y_MAX_ELEMENTS, $2, NULL)== NULL) _YYERROR("104");
|
||||
max_elements_stmt : K_MAX_ELEMENTS string stmtend
|
||||
{ if (ysp_add(_yy, Y_MAX_ELEMENTS, $2, NULL)== NULL) _YYERROR("max_elements_stmt");
|
||||
clicon_debug(2,"max-elements-stmt -> MIN-ELEMENTS integer ;");}
|
||||
;
|
||||
|
||||
value_stmt : K_VALUE integer_value_str ';'
|
||||
{ if (ysp_add(_yy, Y_VALUE, $2, NULL) == NULL) _YYERROR("86");
|
||||
value_stmt : K_VALUE integer_value_str stmtend
|
||||
{ if (ysp_add(_yy, Y_VALUE, $2, NULL) == NULL) _YYERROR("value_stmt");
|
||||
clicon_debug(2,"value-stmt -> VALUE integer-value"); }
|
||||
;
|
||||
|
||||
/* Grouping */
|
||||
grouping_stmt : K_GROUPING identifier_str
|
||||
{ if (ysp_add_push(_yy, Y_GROUPING, $2) == NULL) _YYERROR("51"); }
|
||||
{ if (ysp_add_push(_yy, Y_GROUPING, $2) == NULL) _YYERROR("grouping_stmt"); }
|
||||
'{' grouping_substmts '}'
|
||||
{ if (ystack_pop(_yy) < 0) _YYERROR("52");
|
||||
{ if (ystack_pop(_yy) < 0) _YYERROR("grouping_stmt");
|
||||
clicon_debug(2,"grouping-stmt -> GROUPING id-arg-str { grouping-substmts }"); }
|
||||
;
|
||||
|
||||
|
|
@ -1006,12 +1032,12 @@ grouping_substmt : status_stmt { clicon_debug(2,"grouping-substmt -> st
|
|||
|
||||
/* container */
|
||||
container_stmt : K_CONTAINER identifier_str ';'
|
||||
{ if (ysp_add(_yy, Y_CONTAINER, $2, NULL) == NULL) _YYERROR("7");
|
||||
{ if (ysp_add(_yy, Y_CONTAINER, $2, NULL) == NULL) _YYERROR("container_stmt");
|
||||
clicon_debug(2,"container-stmt -> CONTAINER id-arg-str ;");}
|
||||
| K_CONTAINER identifier_str
|
||||
{ if (ysp_add_push(_yy, Y_CONTAINER, $2) == NULL) _YYERROR("8"); }
|
||||
{ if (ysp_add_push(_yy, Y_CONTAINER, $2) == NULL) _YYERROR("container_stmt"); }
|
||||
'{' container_substmts '}'
|
||||
{ if (ystack_pop(_yy) < 0) _YYERROR("9");
|
||||
{ if (ystack_pop(_yy) < 0) _YYERROR("container_stmt");
|
||||
clicon_debug(2,"container-stmt -> CONTAINER id-arg-str { container-substmts }");}
|
||||
;
|
||||
|
||||
|
|
@ -1036,14 +1062,13 @@ container_substmt : when_stmt { clicon_debug(2,"container-substmt -> when-
|
|||
| { clicon_debug(2,"container-substmt ->");}
|
||||
;
|
||||
|
||||
/* leaf */
|
||||
leaf_stmt : K_LEAF identifier_str ';'
|
||||
{ if (ysp_add(_yy, Y_LEAF, $2, NULL) == NULL) _YYERROR("10");
|
||||
{ if (ysp_add(_yy, Y_LEAF, $2, NULL) == NULL) _YYERROR("leaf_stmt");
|
||||
clicon_debug(2,"leaf-stmt -> LEAF id-arg-str ;");}
|
||||
| K_LEAF identifier_str
|
||||
{ if (ysp_add_push(_yy, Y_LEAF, $2) == NULL) _YYERROR("11"); }
|
||||
{ if (ysp_add_push(_yy, Y_LEAF, $2) == NULL) _YYERROR("leaf_stmt"); }
|
||||
'{' leaf_substmts '}'
|
||||
{ if (ystack_pop(_yy) < 0) _YYERROR("12");
|
||||
{ if (ystack_pop(_yy) < 0) _YYERROR("leaf_stmt");
|
||||
clicon_debug(2,"leaf-stmt -> LEAF id-arg-str { lead-substmts }");}
|
||||
;
|
||||
|
||||
|
|
@ -1068,12 +1093,12 @@ leaf_substmt : when_stmt { clicon_debug(2,"leaf-substmt -> when-stmt
|
|||
|
||||
/* leaf-list */
|
||||
leaf_list_stmt : K_LEAF_LIST identifier_str ';'
|
||||
{ if (ysp_add(_yy, Y_LEAF_LIST, $2, NULL) == NULL) _YYERROR("13");
|
||||
{ if (ysp_add(_yy, Y_LEAF_LIST, $2, NULL) == NULL) _YYERROR("leaf_list_stmt");
|
||||
clicon_debug(2,"leaf-list-stmt -> LEAF id-arg-str ;");}
|
||||
| K_LEAF_LIST identifier_str
|
||||
{ if (ysp_add_push(_yy, Y_LEAF_LIST, $2) == NULL) _YYERROR("14"); }
|
||||
{ if (ysp_add_push(_yy, Y_LEAF_LIST, $2) == NULL) _YYERROR("leaf_list_stmt"); }
|
||||
'{' leaf_list_substmts '}'
|
||||
{ if (ystack_pop(_yy) < 0) _YYERROR("15");
|
||||
{ if (ystack_pop(_yy) < 0) _YYERROR("leaf_list_stmt");
|
||||
clicon_debug(2,"leaf-list-stmt -> LEAF-LIST id-arg-str { lead-substmts }");}
|
||||
;
|
||||
|
||||
|
|
@ -1097,14 +1122,13 @@ leaf_list_substmt : when_stmt { clicon_debug(2,"leaf-list-substmt -> when
|
|||
| { clicon_debug(2,"leaf-list-stmt ->"); }
|
||||
;
|
||||
|
||||
/* list */
|
||||
list_stmt : K_LIST identifier_str ';'
|
||||
{ if (ysp_add(_yy, Y_LIST, $2, NULL) == NULL) _YYERROR("16");
|
||||
{ if (ysp_add(_yy, Y_LIST, $2, NULL) == NULL) _YYERROR("list_stmt");
|
||||
clicon_debug(2,"list-stmt -> LIST id-arg-str ;"); }
|
||||
| K_LIST identifier_str
|
||||
{ if (ysp_add_push(_yy, Y_LIST, $2) == NULL) _YYERROR("17"); }
|
||||
{ if (ysp_add_push(_yy, Y_LIST, $2) == NULL) _YYERROR("list_stmt"); }
|
||||
'{' list_substmts '}'
|
||||
{ if (ystack_pop(_yy) < 0) _YYERROR("18");
|
||||
{ if (ystack_pop(_yy) < 0) _YYERROR("list_stmt");
|
||||
clicon_debug(2,"list-stmt -> LIST id-arg-str { list-substmts }"); }
|
||||
;
|
||||
|
||||
|
|
@ -1137,24 +1161,24 @@ list_substmt : when_stmt { clicon_debug(2,"list-substmt -> when-stmt
|
|||
|
||||
/* key-stmt = key-keyword sep key-arg-str */
|
||||
key_stmt : K_KEY string stmtend
|
||||
{ if (ysp_add(_yy, Y_KEY, $2, NULL)== NULL) _YYERROR("109");
|
||||
{ if (ysp_add(_yy, Y_KEY, $2, NULL)== NULL) _YYERROR("key_stmt");
|
||||
clicon_debug(2,"key-stmt -> KEY id-arg-str ;");}
|
||||
;
|
||||
|
||||
/* unique-stmt = unique-keyword unique-arg-str */
|
||||
unique_stmt : K_UNIQUE string stmtend
|
||||
{ if (ysp_add(_yy, Y_UNIQUE, $2, NULL)== NULL) _YYERROR("110");
|
||||
{ if (ysp_add(_yy, Y_UNIQUE, $2, NULL)== NULL) _YYERROR("unique_stmt");
|
||||
clicon_debug(2,"key-stmt -> KEY id-arg-str ;");}
|
||||
;
|
||||
|
||||
/* choice */
|
||||
choice_stmt : K_CHOICE identifier_str ';'
|
||||
{ if (ysp_add(_yy, Y_CHOICE, $2, NULL) == NULL) _YYERROR("19");
|
||||
{ if (ysp_add(_yy, Y_CHOICE, $2, NULL) == NULL) _YYERROR("choice_stmt");
|
||||
clicon_debug(2,"choice-stmt -> CHOICE id-arg-str ;"); }
|
||||
| K_CHOICE identifier_str
|
||||
{ if (ysp_add_push(_yy, Y_CHOICE, $2) == NULL) _YYERROR("20"); }
|
||||
{ if (ysp_add_push(_yy, Y_CHOICE, $2) == NULL) _YYERROR("choice_stmt"); }
|
||||
'{' choice_substmts '}'
|
||||
{ if (ystack_pop(_yy) < 0) _YYERROR("21");
|
||||
{ if (ystack_pop(_yy) < 0) _YYERROR("choice_stmt");
|
||||
clicon_debug(2,"choice-stmt -> CHOICE id-arg-str { choice-substmts }"); }
|
||||
;
|
||||
|
||||
|
|
@ -1180,12 +1204,12 @@ choice_substmt : when_stmt { clicon_debug(2,"choice-substmt -> when-st
|
|||
|
||||
/* case */
|
||||
case_stmt : K_CASE identifier_str ';'
|
||||
{ if (ysp_add(_yy, Y_CASE, $2, NULL) == NULL) _YYERROR("22");
|
||||
{ if (ysp_add(_yy, Y_CASE, $2, NULL) == NULL) _YYERROR("case_stmt");
|
||||
clicon_debug(2,"case-stmt -> CASE id-arg-str ;"); }
|
||||
| K_CASE identifier_str
|
||||
{ if (ysp_add_push(_yy, Y_CASE, $2) == NULL) _YYERROR("23"); }
|
||||
{ if (ysp_add_push(_yy, Y_CASE, $2) == NULL) _YYERROR("case_stmt"); }
|
||||
'{' case_substmts '}'
|
||||
{ if (ystack_pop(_yy) < 0) _YYERROR("24");
|
||||
{ if (ystack_pop(_yy) < 0) _YYERROR("case_stmt");
|
||||
clicon_debug(2,"case-stmt -> CASE id-arg-str { case-substmts }"); }
|
||||
;
|
||||
|
||||
|
|
@ -1206,23 +1230,23 @@ case_substmt : when_stmt { clicon_debug(2,"case-substmt -> when-stmt
|
|||
;
|
||||
|
||||
anydata_stmt : K_ANYDATA identifier_str ';'
|
||||
{ if (ysp_add(_yy, Y_ANYDATA, $2, NULL) == NULL) _YYERROR("25");
|
||||
{ if (ysp_add(_yy, Y_ANYDATA, $2, NULL) == NULL) _YYERROR("anydata_stmt");
|
||||
clicon_debug(2,"anydata-stmt -> ANYDATA id-arg-str ;"); }
|
||||
| K_ANYDATA identifier_str
|
||||
{ if (ysp_add_push(_yy, Y_ANYDATA, $2) == NULL) _YYERROR("26"); }
|
||||
{ if (ysp_add_push(_yy, Y_ANYDATA, $2) == NULL) _YYERROR("anydata_stmt"); }
|
||||
'{' anyxml_substmts '}'
|
||||
{ if (ystack_pop(_yy) < 0) _YYERROR("27");
|
||||
{ if (ystack_pop(_yy) < 0) _YYERROR("anydata_stmt");
|
||||
clicon_debug(2,"anydata-stmt -> ANYDATA id-arg-str { anyxml-substmts }"); }
|
||||
;
|
||||
|
||||
/* anyxml */
|
||||
anyxml_stmt : K_ANYXML identifier_str ';'
|
||||
{ if (ysp_add(_yy, Y_ANYXML, $2, NULL) == NULL) _YYERROR("25");
|
||||
{ if (ysp_add(_yy, Y_ANYXML, $2, NULL) == NULL) _YYERROR("anyxml_stmt");
|
||||
clicon_debug(2,"anyxml-stmt -> ANYXML id-arg-str ;"); }
|
||||
| K_ANYXML identifier_str
|
||||
{ if (ysp_add_push(_yy, Y_ANYXML, $2) == NULL) _YYERROR("26"); }
|
||||
{ if (ysp_add_push(_yy, Y_ANYXML, $2) == NULL) _YYERROR("anyxml_stmt"); }
|
||||
'{' anyxml_substmts '}'
|
||||
{ if (ystack_pop(_yy) < 0) _YYERROR("27");
|
||||
{ if (ystack_pop(_yy) < 0) _YYERROR("anyxml_stmt");
|
||||
clicon_debug(2,"anyxml-stmt -> ANYXML id-arg-str { anyxml-substmts }"); }
|
||||
;
|
||||
|
||||
|
|
@ -1245,12 +1269,12 @@ anyxml_substmt : when_stmt { clicon_debug(2,"anyxml-substmt -> when-st
|
|||
|
||||
/* uses-stmt = uses-keyword identifier-ref-arg-str */
|
||||
uses_stmt : K_USES identifier_ref_str ';'
|
||||
{ if (ysp_add(_yy, Y_USES, $2, NULL) == NULL) _YYERROR("28");
|
||||
{ if (ysp_add(_yy, Y_USES, $2, NULL) == NULL) _YYERROR("uses_stmt");
|
||||
clicon_debug(2,"uses-stmt -> USES id-arg-str ;"); }
|
||||
| K_USES identifier_ref_str
|
||||
{ if (ysp_add_push(_yy, Y_USES, $2) == NULL) _YYERROR("29"); }
|
||||
{ if (ysp_add_push(_yy, Y_USES, $2) == NULL) _YYERROR("uses_stmt"); }
|
||||
'{' uses_substmts '}'
|
||||
{ if (ystack_pop(_yy) < 0) _YYERROR("30");
|
||||
{ if (ystack_pop(_yy) < 0) _YYERROR("uses_stmt");
|
||||
clicon_debug(2,"uses-stmt -> USES id-arg-str { uses-substmts }"); }
|
||||
;
|
||||
|
||||
|
|
@ -1273,12 +1297,12 @@ uses_substmt : when_stmt { clicon_debug(2,"uses-substmt -> when-stmt
|
|||
|
||||
/* refine-stmt = refine-keyword sep refine-arg-str */
|
||||
refine_stmt : K_REFINE desc_schema_node_str ';'
|
||||
{ if (ysp_add(_yy, Y_REFINE, $2, NULL) == NULL) _YYERROR("31");
|
||||
{ if (ysp_add(_yy, Y_REFINE, $2, NULL) == NULL) _YYERROR("refine_stmt");
|
||||
clicon_debug(2,"refine-stmt -> REFINE id-arg-str ;"); }
|
||||
| K_REFINE desc_schema_node_str
|
||||
{ if (ysp_add_push(_yy, Y_REFINE, $2) == NULL) _YYERROR("32"); }
|
||||
{ if (ysp_add_push(_yy, Y_REFINE, $2) == NULL) _YYERROR("refine_stmt"); }
|
||||
'{' refine_substmts '}'
|
||||
{ if (ystack_pop(_yy) < 0) _YYERROR("33");
|
||||
{ if (ystack_pop(_yy) < 0) _YYERROR("refine_stmt");
|
||||
clicon_debug(2,"refine-stmt -> REFINE id-arg-str { refine-substmts }"); }
|
||||
;
|
||||
|
||||
|
|
@ -1297,9 +1321,9 @@ refine_substmt : must_stmt { clicon_debug(2,"refine-substmt -> must-stmt");
|
|||
|
||||
/* uses-augment-stmt = augment-keyword augment-arg-str */
|
||||
uses_augment_stmt : K_AUGMENT desc_schema_node_str
|
||||
{ if (ysp_add_push(_yy, Y_AUGMENT, $2) == NULL) _YYERROR("34"); }
|
||||
{ if (ysp_add_push(_yy, Y_AUGMENT, $2) == NULL) _YYERROR("uses_augment_stmt"); }
|
||||
'{' augment_substmts '}'
|
||||
{ if (ystack_pop(_yy) < 0) _YYERROR("35");
|
||||
{ if (ystack_pop(_yy) < 0) _YYERROR("uses_augment_stmt");
|
||||
clicon_debug(2,"uses-augment-stmt -> AUGMENT desc-schema-node-str { augment-substmts }"); }
|
||||
|
||||
|
||||
|
|
@ -1307,9 +1331,9 @@ uses_augment_stmt : K_AUGMENT desc_schema_node_str
|
|||
* XXX abs-schema-nodeid-str is too difficult, it needs the + semantics
|
||||
*/
|
||||
augment_stmt : K_AUGMENT string
|
||||
{ if (ysp_add_push(_yy, Y_AUGMENT, $2) == NULL) _YYERROR("34"); }
|
||||
{ if (ysp_add_push(_yy, Y_AUGMENT, $2) == NULL) _YYERROR("augment_stmt"); }
|
||||
'{' augment_substmts '}'
|
||||
{ if (ystack_pop(_yy) < 0) _YYERROR("35");
|
||||
{ if (ystack_pop(_yy) < 0) _YYERROR("augment_stmt");
|
||||
clicon_debug(2,"augment-stmt -> AUGMENT abs-schema-node-str { augment-substmts }"); }
|
||||
;
|
||||
|
||||
|
|
@ -1333,12 +1357,12 @@ augment_substmt : when_stmt { clicon_debug(2,"augment-substmt -> when-s
|
|||
|
||||
/* when */
|
||||
when_stmt : K_WHEN string ';'
|
||||
{ if (ysp_add(_yy, Y_WHEN, $2, NULL) == NULL) _YYERROR("36");
|
||||
{ if (ysp_add(_yy, Y_WHEN, $2, NULL) == NULL) _YYERROR("when_stmt");
|
||||
clicon_debug(2,"when-stmt -> WHEN string ;"); }
|
||||
| K_WHEN string
|
||||
{ if (ysp_add_push(_yy, Y_WHEN, $2) == NULL) _YYERROR("37"); }
|
||||
{ if (ysp_add_push(_yy, Y_WHEN, $2) == NULL) _YYERROR("when_stmt"); }
|
||||
'{' when_substmts '}'
|
||||
{ if (ystack_pop(_yy) < 0) _YYERROR("38");
|
||||
{ if (ystack_pop(_yy) < 0) _YYERROR("when_stmt");
|
||||
clicon_debug(2,"when-stmt -> WHEN string { when-substmts }"); }
|
||||
;
|
||||
|
||||
|
|
@ -1355,12 +1379,12 @@ when_substmt : description_stmt { clicon_debug(2,"when-substmt -> description-s
|
|||
|
||||
/* rpc */
|
||||
rpc_stmt : K_RPC identifier_str ';'
|
||||
{ if (ysp_add(_yy, Y_RPC, $2, NULL) == NULL) _YYERROR("39");
|
||||
{ if (ysp_add(_yy, Y_RPC, $2, NULL) == NULL) _YYERROR("rpc_stmt");
|
||||
clicon_debug(2,"rpc-stmt -> RPC id-arg-str ;"); }
|
||||
| K_RPC identifier_str
|
||||
{ if (ysp_add_push(_yy, Y_RPC, $2) == NULL) _YYERROR("40"); }
|
||||
{ if (ysp_add_push(_yy, Y_RPC, $2) == NULL) _YYERROR("rpc_stmt"); }
|
||||
'{' rpc_substmts '}'
|
||||
{ if (ystack_pop(_yy) < 0) _YYERROR("41");
|
||||
{ if (ystack_pop(_yy) < 0) _YYERROR("rpc_stmt");
|
||||
clicon_debug(2,"rpc-stmt -> RPC id-arg-str { rpc-substmts }"); }
|
||||
;
|
||||
|
||||
|
|
@ -1383,23 +1407,23 @@ rpc_substmt : if_feature_stmt { clicon_debug(2,"rpc-substmt -> if-feature-stm
|
|||
|
||||
/* action */
|
||||
action_stmt : K_ACTION identifier_str ';'
|
||||
{ if (ysp_add(_yy, Y_ACTION, $2, NULL) == NULL) _YYERROR("39");
|
||||
{ if (ysp_add(_yy, Y_ACTION, $2, NULL) == NULL) _YYERROR("action_stmt");
|
||||
clicon_debug(2,"action-stmt -> ACTION id-arg-str ;"); }
|
||||
| K_ACTION identifier_str
|
||||
{ if (ysp_add_push(_yy, Y_ACTION, $2) == NULL) _YYERROR("40"); }
|
||||
{ if (ysp_add_push(_yy, Y_ACTION, $2) == NULL) _YYERROR("action_stmt"); }
|
||||
'{' rpc_substmts '}'
|
||||
{ if (ystack_pop(_yy) < 0) _YYERROR("41");
|
||||
{ if (ystack_pop(_yy) < 0) _YYERROR("action_stmt");
|
||||
clicon_debug(2,"action-stmt -> ACTION id-arg-str { rpc-substmts }"); }
|
||||
;
|
||||
|
||||
/* notification */
|
||||
notification_stmt : K_NOTIFICATION identifier_str ';'
|
||||
{ if (ysp_add(_yy, Y_NOTIFICATION, $2, NULL) == NULL) _YYERROR("46");
|
||||
{ if (ysp_add(_yy, Y_NOTIFICATION, $2, NULL) == NULL) _YYERROR("notification_stmt");
|
||||
clicon_debug(2,"notification-stmt -> NOTIFICATION id-arg-str ;"); }
|
||||
| K_NOTIFICATION identifier_str
|
||||
{ if (ysp_add_push(_yy, Y_NOTIFICATION, $2) == NULL) _YYERROR("47"); }
|
||||
{ if (ysp_add_push(_yy, Y_NOTIFICATION, $2) == NULL) _YYERROR("notification_stmt"); }
|
||||
'{' notification_substmts '}'
|
||||
{ if (ystack_pop(_yy) < 0) _YYERROR("48");
|
||||
{ if (ystack_pop(_yy) < 0) _YYERROR("notification_stmt");
|
||||
clicon_debug(2,"notification-stmt -> NOTIFICATION id-arg-str { notification-substmts }"); }
|
||||
;
|
||||
|
||||
|
|
@ -1427,9 +1451,9 @@ notification_substmt : if_feature_stmt { clicon_debug(2,"notification-substmt -
|
|||
|
||||
*/
|
||||
deviation_stmt : K_DEVIATION string
|
||||
{ if (ysp_add_push(_yy, Y_DEVIATION, $2) == NULL) _YYERROR("47"); }
|
||||
{ if (ysp_add_push(_yy, Y_DEVIATION, $2) == NULL) _YYERROR("deviation_stmt"); }
|
||||
'{' deviation_substmts '}'
|
||||
{ if (ystack_pop(_yy) < 0) _YYERROR("48");
|
||||
{ if (ystack_pop(_yy) < 0) _YYERROR("deviation_stmt");
|
||||
clicon_debug(2,"deviation-stmt -> DEVIATION id-arg-str { notification-substmts }"); }
|
||||
;
|
||||
|
||||
|
|
@ -1444,14 +1468,10 @@ deviation_substmt : description_stmt { clicon_debug(2,"deviation-substmt -> des
|
|||
| deviate_not_supported_stmt { clicon_debug(2,"deviation-substmt -> deviate-not-supported-stmt"); }
|
||||
;
|
||||
|
||||
deviate_not_supported_stmt : K_DEVIATE string { clicon_debug(2,"deviate-not-supported-stmt -> DEVIATE string"); }
|
||||
deviate_not_supported_stmt : K_DEVIATE string stmtend
|
||||
{ clicon_debug(2,"deviate-not-supported-stmt -> DEVIATE string"); }
|
||||
;
|
||||
|
||||
meta_stmt : organization_stmt { clicon_debug(2,"meta-stmt -> organization-stmt"); }
|
||||
| contact_stmt { clicon_debug(2,"meta-stmt -> contact-stmt"); }
|
||||
| description_stmt { clicon_debug(2,"meta-stmt -> description-stmt"); }
|
||||
| reference_stmt { clicon_debug(2,"meta-stmt -> reference-stmt"); }
|
||||
;
|
||||
|
||||
/* body */
|
||||
body_stmts : body_stmts body_stmt { clicon_debug(2,"body-stmts -> body-stmts body-stmt"); }
|
||||
|
|
@ -1492,9 +1512,9 @@ short_case_stmt : container_stmt { clicon_debug(2,"short-case-substmt -> conta
|
|||
|
||||
/* input */
|
||||
input_stmt : K_INPUT
|
||||
{ if (ysp_add_push(_yy, Y_INPUT, NULL) == NULL) _YYERROR("42"); }
|
||||
{ if (ysp_add_push(_yy, Y_INPUT, NULL) == NULL) _YYERROR("input_stmt"); }
|
||||
'{' input_substmts '}'
|
||||
{ if (ystack_pop(_yy) < 0) _YYERROR("43");
|
||||
{ if (ystack_pop(_yy) < 0) _YYERROR("input_stmt");
|
||||
clicon_debug(2,"input-stmt -> INPUT { input-substmts }"); }
|
||||
;
|
||||
|
||||
|
|
@ -1512,15 +1532,12 @@ input_substmt : typedef_stmt { clicon_debug(2,"input-substmt -> typedef-
|
|||
|
||||
/* output */
|
||||
output_stmt : K_OUTPUT /* XXX reuse input-substatements since they are same */
|
||||
{ if (ysp_add_push(_yy, Y_OUTPUT, NULL) == NULL) _YYERROR("44"); }
|
||||
{ if (ysp_add_push(_yy, Y_OUTPUT, NULL) == NULL) _YYERROR("output_stmt"); }
|
||||
'{' input_substmts '}'
|
||||
{ if (ystack_pop(_yy) < 0) _YYERROR("45");
|
||||
{ if (ystack_pop(_yy) < 0) _YYERROR("output_stmt");
|
||||
clicon_debug(2,"output-stmt -> OUTPUT { input-substmts }"); }
|
||||
;
|
||||
|
||||
|
||||
|
||||
|
||||
string : qstrings { $$=$1; clicon_debug(2,"string -> qstrings (%s)", $1); }
|
||||
| ustring { $$=$1; clicon_debug(2,"string -> ustring (%s)", $1); }
|
||||
;
|
||||
|
|
@ -1554,12 +1571,11 @@ ustring : ustring CHAR
|
|||
{$$=$1; }
|
||||
;
|
||||
|
||||
|
||||
abs_schema_nodeid : abs_schema_nodeid '/' node_identifier
|
||||
{ if (($$=string_del_join($1, "/", $3)) == NULL) _YYERROR("0");
|
||||
{ if (($$=string_del_join($1, "/", $3)) == NULL) _YYERROR("abs_schema_nodeid");
|
||||
clicon_debug(2,"absolute-schema-nodeid -> absolute-schema-nodeid / node-identifier"); }
|
||||
| '/' node_identifier
|
||||
{ if (($$=string_del_join(NULL, "/", $2)) == NULL) _YYERROR("0");
|
||||
{ if (($$=string_del_join(NULL, "/", $2)) == NULL) _YYERROR("abs_schema_nodeid");
|
||||
clicon_debug(2,"absolute-schema-nodeid -> / node-identifier"); }
|
||||
;
|
||||
|
||||
|
|
@ -1572,7 +1588,7 @@ desc_schema_node_str : desc_schema_nodeid
|
|||
desc_schema_nodeid : node_identifier
|
||||
{ $$= $1; clicon_debug(2,"descendant-schema-nodeid -> node_identifier"); }
|
||||
| node_identifier abs_schema_nodeid
|
||||
{ if (($$=string_del_join($1, " ", $2)) == NULL) _YYERROR("0");clicon_debug(2,"descendant-schema-nodeid -> node_identifier abs_schema_nodeid"); }
|
||||
{ if (($$=string_del_join($1, " ", $2)) == NULL) _YYERROR("desc_schema_nodeid");clicon_debug(2,"descendant-schema-nodeid -> node_identifier abs_schema_nodeid"); }
|
||||
;
|
||||
|
||||
identifier_str : '"' IDENTIFIER '"' { $$ = $2;
|
||||
|
|
@ -1602,7 +1618,7 @@ bool_str : '"' BOOL '"' { $$ = $2;
|
|||
node_identifier : IDENTIFIER
|
||||
{ $$=$1; clicon_debug(2,"identifier-ref-arg-str -> string"); }
|
||||
| IDENTIFIER ':' IDENTIFIER
|
||||
{ if (($$=string_del_join($1, ":", $3)) == NULL) _YYERROR("112");
|
||||
{ if (($$=string_del_join($1, ":", $3)) == NULL) _YYERROR("node_identifier");
|
||||
clicon_debug(2,"identifier-ref-arg-str -> prefix : string"); }
|
||||
;
|
||||
|
||||
|
|
|
|||
|
|
@ -150,7 +150,7 @@ yang_type_cache_set(yang_type_cache **ycache0,
|
|||
return retval;
|
||||
}
|
||||
|
||||
/*! Get individual fields (direct/destrucively) from yang type cache. */
|
||||
/*! Get individual fields (direct/destructively) from yang type cache. */
|
||||
int
|
||||
yang_type_cache_get(yang_type_cache *ycache,
|
||||
yang_stmt **resolved,
|
||||
|
|
@ -227,19 +227,17 @@ ys_resolve_type(yang_stmt *ys,
|
|||
yang_stmt *resolved = NULL;
|
||||
|
||||
assert(ys->ys_keyword == Y_TYPE);
|
||||
/* Recursively resolve ys -> resolve with restrictions(options, etc)
|
||||
* Note that the resolved type could be ys itself.
|
||||
*/
|
||||
if (yang_type_resolve((yang_stmt*)ys->ys_parent, ys, &resolved,
|
||||
&options, &mincv, &maxcv, &pattern, &fraction) < 0)
|
||||
goto done;
|
||||
|
||||
if (resolved && strcmp(resolved->ys_argument, "union")==0)
|
||||
;
|
||||
/* skip unions since they may have different sets of options, mincv, etc
|
||||
* You would have to resolve all sub-types also recursively
|
||||
*/
|
||||
else
|
||||
if (yang_type_cache_set(&ys->ys_typecache,
|
||||
resolved, options, mincv, maxcv, pattern, fraction) < 0)
|
||||
goto done;
|
||||
/* Cache the resolve locally */
|
||||
if (yang_type_cache_set(&ys->ys_typecache,
|
||||
resolved, options, mincv, maxcv, pattern, fraction) < 0)
|
||||
goto done;
|
||||
retval = 0;
|
||||
done:
|
||||
return retval;
|
||||
|
|
@ -660,10 +658,12 @@ ys_cv_validate_union_one(yang_stmt *ys,
|
|||
clicon_err(OE_UNIX, errno, "cv_new");
|
||||
goto done;
|
||||
}
|
||||
if (cv_parse(val, cvt) <0){
|
||||
if ((retval = cv_parse1(val, cvt, reason)) < 0){
|
||||
clicon_err(OE_UNIX, errno, "cv_parse");
|
||||
goto done;
|
||||
}
|
||||
if (retval == 0)
|
||||
goto done;
|
||||
if ((retval = cv_validate1(cvt, cvtype, options, range_min, range_max,
|
||||
pattern, yrt, restype, reason)) < 0)
|
||||
goto done;
|
||||
|
|
@ -688,16 +688,32 @@ ys_cv_validate_union(yang_stmt *ys,
|
|||
{
|
||||
int retval = 1; /* valid */
|
||||
yang_stmt *yt = NULL;
|
||||
char *reason1 = NULL; /* saved reason */
|
||||
|
||||
while ((yt = yn_each((yang_node*)yrestype, yt)) != NULL){
|
||||
if (yt->ys_keyword != Y_TYPE)
|
||||
continue;
|
||||
if ((retval = ys_cv_validate_union_one(ys, reason, yt, type, val)) < 0)
|
||||
goto done;
|
||||
/* If validation failed, save reason, reset error and continue,
|
||||
* save latest reason if noithing validates.
|
||||
*/
|
||||
if (retval == 0 && reason && *reason != NULL){
|
||||
if (reason1)
|
||||
free(reason1);
|
||||
reason1 = *reason;
|
||||
*reason = NULL;
|
||||
}
|
||||
if (retval == 1) /* Enough that one type validates value */
|
||||
break;
|
||||
}
|
||||
done:
|
||||
if (retval == 0 && reason1){
|
||||
*reason = reason1;
|
||||
reason1 = NULL;
|
||||
}
|
||||
if (reason1)
|
||||
free(reason1);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
|
@ -908,7 +924,7 @@ resolve_restrictions(yang_stmt *yrange,
|
|||
}
|
||||
|
||||
/*! Recursively resolve a yang type to built-in type with optional restrictions
|
||||
* @param[in] ys yang-stmt from where the current search is based
|
||||
* @param[in] ys (original) type yang-stmt where the current search is based
|
||||
* @param[in] ytype yang-stmt object containing currently resolving type
|
||||
* @param[out] yrestype resolved type. return built-in type or NULL. mandatory
|
||||
* @param[out] options pointer to flags field of optional values. optional
|
||||
|
|
@ -945,14 +961,14 @@ yang_type_resolve(yang_stmt *ys,
|
|||
char *prefix = NULL;
|
||||
int retval = -1;
|
||||
yang_node *yn;
|
||||
yang_stmt *ymod;
|
||||
yang_stmt *yrmod; /* module where resolved type is looked for */
|
||||
|
||||
if (options)
|
||||
*options = 0x0;
|
||||
*yrestype = NULL; /* Initialization of resolved type that may not be necessary */
|
||||
type = yarg_id(ytype); /* This is the type to resolve */
|
||||
prefix = yarg_prefix(ytype); /* And this its prefix */
|
||||
/* Cache does not work for eg string length 32 */
|
||||
/* Cache does not work for eg string length 32? */
|
||||
if (!yang_builtin(type) && ytype->ys_typecache != NULL){
|
||||
if (yang_type_cache_get(ytype->ys_typecache,
|
||||
yrestype, options, mincv, maxcv, pattern, fraction) < 0)
|
||||
|
|
@ -974,11 +990,12 @@ yang_type_resolve(yang_stmt *ys,
|
|||
|
||||
/* Not basic type. Now check if prefix which means we look in other module */
|
||||
if (prefix){ /* Go to top and find import that matches */
|
||||
if ((ymod = yang_find_module_by_prefix(ys, prefix)) == NULL){
|
||||
clicon_err(OE_DB, 0, "Type not resolved: %s:%s", prefix, type);
|
||||
if ((yrmod = yang_find_module_by_prefix(ytype, prefix)) == NULL){
|
||||
clicon_err(OE_DB, 0, "Type not resolved: \"%s:%s\" in module %s",
|
||||
prefix, type, ys_module(ys)->ys_argument);
|
||||
goto done;
|
||||
}
|
||||
if ((rytypedef = yang_find((yang_node*)ymod, Y_TYPEDEF, type)) == NULL)
|
||||
if ((rytypedef = yang_find((yang_node*)yrmod, Y_TYPEDEF, type)) == NULL)
|
||||
goto ok; /* unresolved */
|
||||
}
|
||||
else
|
||||
|
|
|
|||
16
test/lib.sh
16
test/lib.sh
|
|
@ -78,14 +78,24 @@ expectfn(){
|
|||
expect2=
|
||||
fi
|
||||
ret=$($cmd)
|
||||
r=$?
|
||||
# echo "cmd:\"$cmd\""
|
||||
# echo "retval:\"$retval\""
|
||||
# echo "ret:\"$ret\""
|
||||
if [ $? -ne $retval ]; then
|
||||
echo -e "\e[31m\nError in Test$testnr [$testname]:"
|
||||
# echo "r:\"$r\""
|
||||
if [ $r != $retval ]; then
|
||||
echo -e "\e[31m\nError ($r != $retval) in Test$testnr [$testname]:"
|
||||
echo -e "\e[0m:"
|
||||
exit -1
|
||||
fi
|
||||
fi
|
||||
if [ $r != 0 ]; then
|
||||
return
|
||||
fi
|
||||
# if [ $ret -ne $retval ]; then
|
||||
# echo -e "\e[31m\nError in Test$testnr [$testname]:"
|
||||
# echo -e "\e[0m:"
|
||||
# exit -1
|
||||
# fi
|
||||
# Match if both are empty string
|
||||
if [ -z "$ret" -a -z "$expect" ]; then
|
||||
return
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ cat <<EOF > $cfg
|
|||
<config>
|
||||
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
|
||||
<CLICON_YANG_DIR>/usr/local/share/$APPNAME/yang</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_DIR>/usr/local/share/clixon</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_MODULE_MAIN>$APPNAME</CLICON_YANG_MODULE_MAIN>
|
||||
<CLICON_BACKEND_DIR>/usr/local/lib/$APPNAME/backend</CLICON_BACKEND_DIR>
|
||||
<CLICON_CLISPEC_DIR>/usr/local/lib/$APPNAME/clispec</CLICON_CLISPEC_DIR>
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ run(){
|
|||
fi
|
||||
rm -rf $mydir/*
|
||||
|
||||
conf="-d candidate -b $mydir -p ../datastore/$name/$name.so -y $dir -m ietf-ip"
|
||||
conf="-d candidate -b $mydir -p ../datastore/$name/$name.so -y $dir/ietf-ip.yang"
|
||||
|
||||
new "datastore $name init"
|
||||
expectfn "$datastore $conf init" 0 ""
|
||||
|
|
@ -144,7 +144,7 @@ run(){
|
|||
expectfn "$datastore $conf put create <config><x><y><a>1</a><b>3</b><c>newentry</c></y></x></config>" 0 ""
|
||||
|
||||
new "datastore other db init"
|
||||
expectfn "$datastore -d kalle -b $mydir -p ../datastore/$name/$name.so -y $dir -m ietf-ip init" 0 ""
|
||||
expectfn "$datastore -d kalle -b $mydir -p ../datastore/$name/$name.so -y $dir/ietf-ip.yang init" 0 ""
|
||||
|
||||
new "datastore other db copy"
|
||||
expectfn "$datastore $conf copy kalle" 0 ""
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ cat <<EOF > $cfg
|
|||
<CLICON_FEATURE>ietf-routing:router-id</CLICON_FEATURE>
|
||||
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
|
||||
<CLICON_YANG_DIR>/usr/local/share/$APPNAME/yang</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_DIR>/usr/local/share/clixon</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_MODULE_MAIN>$APPNAME</CLICON_YANG_MODULE_MAIN>
|
||||
<CLICON_CLISPEC_DIR>/usr/local/lib/$APPNAME/clispec</CLICON_CLISPEC_DIR>
|
||||
<CLICON_CLI_DIR>/usr/local/lib/$APPNAME/cli</CLICON_CLI_DIR>
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ cat <<EOF > $cfg
|
|||
<config>
|
||||
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
|
||||
<CLICON_YANG_DIR>$dir</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_DIR>/usr/local/share/clixon</CLICON_YANG_DIR>
|
||||
<CLICON_CLISPEC_DIR>/usr/local/lib/$APPNAME/clispec</CLICON_CLISPEC_DIR>
|
||||
<CLICON_BACKEND_DIR>/usr/local/lib/$APPNAME/backend</CLICON_BACKEND_DIR>
|
||||
<CLICON_BACKEND_REGEXP>example_backend.so$</CLICON_BACKEND_REGEXP>
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ cat <<EOF > $cfg
|
|||
<config>
|
||||
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
|
||||
<CLICON_YANG_DIR>/usr/local/share/$APPNAME/yang</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_DIR>/usr/local/share/clixon</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_MODULE_MAIN>example</CLICON_YANG_MODULE_MAIN>
|
||||
<CLICON_CLISPEC_DIR>/usr/local/lib/$APPNAME/clispec</CLICON_CLISPEC_DIR>
|
||||
<CLICON_CLI_DIR>/usr/local/lib/$APPNAME/cli</CLICON_CLI_DIR>
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ cat <<EOF > $cfg
|
|||
<config>
|
||||
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
|
||||
<CLICON_YANG_DIR>/usr/local/share/$APPNAME/yang</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_DIR>/usr/local/share/clixon</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_MODULE_MAIN>$APPNAME</CLICON_YANG_MODULE_MAIN>
|
||||
<CLICON_CLISPEC_DIR>/usr/local/lib/$APPNAME/clispec</CLICON_CLISPEC_DIR>
|
||||
<CLICON_CLI_DIR>/usr/local/lib/$APPNAME/cli</CLICON_CLI_DIR>
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ cat <<EOF > $cfg
|
|||
<config>
|
||||
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
|
||||
<CLICON_YANG_DIR>/usr/local/share/clixon</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_DIR>/usr/local/share/clixon</CLICON_YANG_DIR>
|
||||
<CLICON_CLISPEC_DIR>/usr/local/lib/$APPNAME/clispec</CLICON_CLISPEC_DIR>
|
||||
<CLICON_RESTCONF_DIR>/usr/local/lib/$APPNAME/restconf</CLICON_RESTCONF_DIR>
|
||||
<CLICON_CLI_DIR>/usr/local/lib/$APPNAME/cli</CLICON_CLI_DIR>
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ cat <<EOF > $cfg
|
|||
<config>
|
||||
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
|
||||
<CLICON_YANG_DIR>/usr/local/share/example/yang</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_DIR>/usr/local/share/clixon</CLICON_YANG_DIR>
|
||||
<CLICON_CLISPEC_DIR>/usr/local/lib/$APPNAME/clispec</CLICON_CLISPEC_DIR>
|
||||
<CLICON_BACKEND_DIR>/usr/local/lib/$APPNAME/backend</CLICON_BACKEND_DIR>
|
||||
<CLICON_BACKEND_REGEXP>example_backend.so$</CLICON_BACKEND_REGEXP>
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ cat <<EOF > $cfg
|
|||
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
|
||||
<CLICON_MODULE_SET_ID>42</CLICON_MODULE_SET_ID>
|
||||
<CLICON_YANG_DIR>/usr/local/share/$APPNAME/yang</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_DIR>/usr/local/share/clixon</CLICON_YANG_DIR>
|
||||
<CLICON_CLISPEC_DIR>/usr/local/lib/$APPNAME/clispec</CLICON_CLISPEC_DIR>
|
||||
<CLICON_BACKEND_DIR>/usr/local/lib/$APPNAME/backend</CLICON_BACKEND_DIR>
|
||||
<CLICON_BACKEND_REGEXP>example_backend.so$</CLICON_BACKEND_REGEXP>
|
||||
|
|
@ -200,7 +201,6 @@ expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><edit-config><target><can
|
|||
#new "netconf get CDATA"
|
||||
#expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><get-config><source><candidate/></source><filter type=\"xpath\" select=\"/interfaces/interface[name='eth/0/0']/description\" /></get-config></rpc>]]>]]>" "<rpc-reply><data><interfaces><interface><name>eth/0/0</name><description><![CDATA[myeth&]]></description><enabled>true</enabled></interface></interfaces></data></rpc-reply>]]>]]>"
|
||||
|
||||
|
||||
new "netconf discard-changes"
|
||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><discard-changes/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||
|
||||
|
|
|
|||
|
|
@ -1,24 +1,104 @@
|
|||
#!/bin/bash
|
||||
# Parse yang openconfig tests
|
||||
# Note that the openconfig test suites are patched to counter CLixon issues as follows:
|
||||
# - release/models/mpls/openconfig-mpls-te.yang
|
||||
# issue: https://github.com/clicon/clixon/issues/60
|
||||
# - release/models/wifi/types/openconfig-wifi-types.yang
|
||||
# issue: https://github.com/clicon/clixon/issues/59
|
||||
#
|
||||
#PROG="valgrind --leak-check=full --show-leak-kinds=all ../util/clixon_util_yang"
|
||||
PROG=../util/clixon_util_yang
|
||||
OPENCONFIG=~/syssrc/openconfig
|
||||
OPENCONFIG=public
|
||||
OCDIR=$OPENCONFIG/release/models
|
||||
|
||||
# Clone openconfig dir if not there
|
||||
if [ ! -d public ]; then
|
||||
git clone https://github.com/openconfig/public
|
||||
else
|
||||
(cd public; git pull)
|
||||
fi
|
||||
|
||||
# include err() and new() functions and creates $dir
|
||||
. ./lib.sh
|
||||
|
||||
# Openconfig
|
||||
# Files not parseable:
|
||||
# - openconfig-access-points.yang
|
||||
# - openconfig-access-points.yang
|
||||
new "Openconfig"
|
||||
# Yang specifics: multi-keys and empty type
|
||||
APPNAME=example
|
||||
# include err() and new() functions and creates $dir
|
||||
. ./lib.sh
|
||||
|
||||
cfg=$dir/conf_yang.xml
|
||||
fyang=$dir/test.yang
|
||||
|
||||
cat <<EOF > $cfg
|
||||
<config>
|
||||
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
|
||||
<CLICON_YANG_DIR>$OCDIR</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_DIR>$OCDIR/acl</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_DIR>$OCDIR/aft</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_DIR>$OCDIR/bfd</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_DIR>$OCDIR/bgp</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_DIR>$OCDIR/catalog</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_DIR>$OCDIR/interfaces</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_DIR>$OCDIR/isis</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_DIR>$OCDIR/lacp</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_DIR>$OCDIR/lldp</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_DIR>$OCDIR/local-routing</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_DIR>$OCDIR/mpls</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_DIR>$OCDIR/multicast</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_DIR>$OCDIR/network-instance</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_DIR>$OCDIR/openflow</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_DIR>$OCDIR/optical-transport</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_DIR>$OCDIR/ospf</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_DIR>$OCDIR/platform</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_DIR>$OCDIR/policy</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_DIR>$OCDIR/policy-forwarding</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_DIR>$OCDIR/probes</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_DIR>$OCDIR/qos</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_DIR>$OCDIR/relay-agent</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_DIR>$OCDIR/rib</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_DIR>$OCDIR/segment-routing</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_DIR>$OCDIR/stp</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_DIR>$OCDIR/system</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_DIR>$OCDIR/telemetry</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_DIR>$OCDIR/types</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_DIR>$OCDIR/vlan</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_DIR>$OCDIR/wifi</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_DIR>$OCDIR/wifi/access-points</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_DIR>$OCDIR/wifi/ap-manager</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_DIR>$OCDIR/wifi/mac</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_DIR>$OCDIR/wifi/phy</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_DIR>$OCDIR/wifi/types</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_DIR>/usr/local/share/$APPNAME/yang</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_DIR>/usr/local/share/clixon</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_MODULE_MAIN>$APPNAME</CLICON_YANG_MODULE_MAIN>
|
||||
<CLICON_CLISPEC_DIR>/usr/local/lib/$APPNAME/clispec</CLICON_CLISPEC_DIR>
|
||||
<CLICON_CLI_DIR>/usr/local/lib/$APPNAME/cli</CLICON_CLI_DIR>
|
||||
<CLICON_CLI_MODE>$APPNAME</CLICON_CLI_MODE>
|
||||
<CLICON_SOCK>/usr/local/var/$APPNAME/$APPNAME.sock</CLICON_SOCK>
|
||||
<CLICON_BACKEND_PIDFILE>/usr/local/var/$APPNAME/$APPNAME.pidfile</CLICON_BACKEND_PIDFILE>
|
||||
<CLICON_CLI_GENMODEL_COMPLETION>1</CLICON_CLI_GENMODEL_COMPLETION>
|
||||
<CLICON_XMLDB_DIR>/usr/local/var/$APPNAME</CLICON_XMLDB_DIR>
|
||||
<CLICON_XMLDB_PLUGIN>/usr/local/lib/xmldb/text.so</CLICON_XMLDB_PLUGIN>
|
||||
<CLICON_MODULE_LIBRARY_RFC7895>true</CLICON_MODULE_LIBRARY_RFC7895>
|
||||
</config>
|
||||
EOF
|
||||
|
||||
files=$(find $OPENCONFIG -name "*.yang")
|
||||
# Just cound nr of modules (exclude submodule)
|
||||
let m=0; # Nr of modules
|
||||
for f in $files; do
|
||||
new "$f"
|
||||
YANG=$(cat $f)
|
||||
# NYI
|
||||
expecteof "$PROG" 0 "$YANG" "module"
|
||||
if [ -n "$(head -1 $f|grep '^module')" ]; then
|
||||
let m++;
|
||||
fi
|
||||
done
|
||||
echo "Number of modules:$m"
|
||||
for f in $files; do
|
||||
if [ -n "$(head -1 $f|grep '^module')" ]; then
|
||||
new "cli $f"
|
||||
expectfn "$clixon_cli -1f $cfg -y $f show version" 0 "3."
|
||||
fi
|
||||
|
||||
done
|
||||
|
||||
rm -rf $dir
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ cat <<EOF > $cfg
|
|||
<config>
|
||||
<CLICON_CONFIGFILE>/tmp/conf_yang.xml</CLICON_CONFIGFILE>
|
||||
<CLICON_YANG_DIR>/usr/local/share/$APPNAME/yang</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_DIR>/usr/local/share/clixon</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_MODULE_MAIN>example</CLICON_YANG_MODULE_MAIN>
|
||||
<CLICON_CLISPEC_DIR>/usr/local/lib/$APPNAME/clispec</CLICON_CLISPEC_DIR>
|
||||
<CLICON_CLI_DIR>/usr/local/lib/$APPNAME/cli</CLICON_CLI_DIR>
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ fyang=$dir/scaling.yang
|
|||
fconfig=$dir/config
|
||||
|
||||
cat <<EOF > $fyang
|
||||
module ietf-ip{
|
||||
module scaling{
|
||||
yang-version 1.1;
|
||||
namespace "urn:example:clixon";
|
||||
prefix ip;
|
||||
|
|
@ -47,8 +47,9 @@ EOF
|
|||
cat <<EOF > $cfg
|
||||
<config>
|
||||
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
|
||||
<CLICON_YANG_DIR>$fyang</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_MODULE_MAIN>ietf-ip</CLICON_YANG_MODULE_MAIN>
|
||||
<CLICON_YANG_DIR>$dir</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_DIR>/usr/local/share/clixon</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_MODULE_MAIN>scaling</CLICON_YANG_MODULE_MAIN>
|
||||
<CLICON_SOCK>/usr/local/var/$APPNAME/$APPNAME.sock</CLICON_SOCK>
|
||||
<CLICON_BACKEND_PIDFILE>/usr/local/var/$APPNAME/$APPNAME.pidfile</CLICON_BACKEND_PIDFILE>
|
||||
<CLICON_RESTCONF_PRETTY>false</CLICON_RESTCONF_PRETTY>
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ cat <<EOF > $cfg
|
|||
<config>
|
||||
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
|
||||
<CLICON_YANG_DIR>/usr/local/share/$APPNAME/yang</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_DIR>/usr/local/share/clixon</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_MODULE_MAIN>example</CLICON_YANG_MODULE_MAIN>
|
||||
<CLICON_CLISPEC_DIR>/usr/local/lib/$APPNAME/clispec</CLICON_CLISPEC_DIR>
|
||||
<CLICON_BACKEND_DIR>/usr/local/lib/$APPNAME/backend</CLICON_BACKEND_DIR>
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ cat <<EOF > $cfg
|
|||
<config>
|
||||
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
|
||||
<CLICON_YANG_DIR>/usr/local/var</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_DIR>/usr/local/share/clixon</CLICON_YANG_DIR>
|
||||
<CLICON_RESTCONF_PRETTY>false</CLICON_RESTCONF_PRETTY>
|
||||
<CLICON_SOCK>/usr/local/var/$APPNAME/$APPNAME.sock</CLICON_SOCK>
|
||||
<CLICON_BACKEND_PIDFILE>$dir/restconf.pidfile</CLICON_BACKEND_PIDFILE>
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ cat <<EOF > $cfg
|
|||
<config>
|
||||
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
|
||||
<CLICON_YANG_DIR>/usr/local/share/$APPNAME/yang</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_DIR>/usr/local/share/clixon</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_MODULE_MAIN>example</CLICON_YANG_MODULE_MAIN>
|
||||
<CLICON_CLI_MODE>$APPNAME</CLICON_CLI_MODE>
|
||||
<CLICON_BACKEND_DIR>/usr/local/lib/$APPNAME/backend</CLICON_BACKEND_DIR>
|
||||
|
|
|
|||
|
|
@ -25,8 +25,7 @@ UTIL=../util/clixon_util_stream
|
|||
NCWAIT=5 # Wait (netconf valgrind may need more time)
|
||||
|
||||
if [ ! -x $UTIL ]; then
|
||||
echo "$UTIL not found. To build: (cd ../util; make clixon_util_stream)"
|
||||
exit 1
|
||||
(cd ../util; make clixon_util_stream)
|
||||
fi
|
||||
DATE=$(date +"%Y-%m-%d")
|
||||
# include err() and new() functions and creates $dir
|
||||
|
|
|
|||
|
|
@ -7,11 +7,15 @@ APPNAME=example
|
|||
|
||||
cfg=$dir/conf_yang.xml
|
||||
fyang=$dir/type.yang
|
||||
fyang2=$dir/example2.yang
|
||||
fyang3=$dir/example3.yang
|
||||
|
||||
cat <<EOF > $cfg
|
||||
<config>
|
||||
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
|
||||
<CLICON_YANG_DIR>$dir</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_DIR>/usr/local/share/$APPNAME/yang</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_DIR>/usr/local/share/clixon</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_MODULE_MAIN>example</CLICON_YANG_MODULE_MAIN>
|
||||
<CLICON_CLISPEC_DIR>/usr/local/lib/$APPNAME/clispec</CLICON_CLISPEC_DIR>
|
||||
<CLICON_CLI_DIR>/usr/local/lib/$APPNAME/cli</CLICON_CLI_DIR>
|
||||
|
|
@ -21,14 +25,59 @@ cat <<EOF > $cfg
|
|||
<CLICON_CLI_GENMODEL_COMPLETION>1</CLICON_CLI_GENMODEL_COMPLETION>
|
||||
<CLICON_XMLDB_DIR>/usr/local/var/$APPNAME</CLICON_XMLDB_DIR>
|
||||
<CLICON_XMLDB_PLUGIN>/usr/local/lib/xmldb/text.so</CLICON_XMLDB_PLUGIN>
|
||||
<CLICON_XMLDB_CACHE>false</CLICON_XMLDB_CACHE>
|
||||
</config>
|
||||
EOF
|
||||
|
||||
# transitive type, exists in fyang3, referenced from fyang2, but not declared in fyang
|
||||
cat <<EOF > $fyang3
|
||||
module example3{
|
||||
prefix ex3;
|
||||
namespace "urn:example:example3";
|
||||
typedef w{
|
||||
type union{
|
||||
type int32{
|
||||
range "4..44";
|
||||
}
|
||||
}
|
||||
}
|
||||
typedef u{
|
||||
type union {
|
||||
type w;
|
||||
type enumeration {
|
||||
enum "bounded";
|
||||
enum "unbounded";
|
||||
}
|
||||
}
|
||||
}
|
||||
typedef t{
|
||||
type string{
|
||||
pattern '[a-z][0-9]*';
|
||||
}
|
||||
}
|
||||
}
|
||||
EOF
|
||||
cat <<EOF > $fyang2
|
||||
module example2{
|
||||
import example3 { prefix ex3; }
|
||||
namespace "urn:example:example2";
|
||||
prefix ex2;
|
||||
grouping gr2 {
|
||||
leaf talle{
|
||||
type ex3:t;
|
||||
}
|
||||
leaf ulle{
|
||||
type ex3:u;
|
||||
}
|
||||
}
|
||||
}
|
||||
EOF
|
||||
cat <<EOF > $fyang
|
||||
module example{
|
||||
yang-version 1.1;
|
||||
namespace "urn:example:clixon";
|
||||
prefix ex;
|
||||
import example2 { prefix ex2; }
|
||||
typedef ab {
|
||||
type string {
|
||||
pattern
|
||||
|
|
@ -136,6 +185,10 @@ module example{
|
|||
leaf mbits{
|
||||
type mybits;
|
||||
}
|
||||
container c{
|
||||
description "transitive type- exists in ex3";
|
||||
uses ex2:gr2;
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
|
|
@ -151,6 +204,50 @@ if [ $? -ne 0 ]; then
|
|||
err
|
||||
fi
|
||||
|
||||
new "cli set transitive string"
|
||||
expectfn "$clixon_cli -1f $cfg -l o -y $fyang set c talle x99" 0 "^$"
|
||||
|
||||
new "cli set transitive string error"
|
||||
expectfn "$clixon_cli -1f $cfg -l o -y $fyang set c talle 9xx" 255 "^$"
|
||||
|
||||
new "netconf set transitive string error"
|
||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><edit-config><target><candidate/></target><config><c><talle>9xx</talle></c></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>"
|
||||
|
||||
new "netconf validate should fail"
|
||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply><rpc-error><error-tag>operation-failed</error-tag><error-type>application</error-type><error-severity>error</error-severity><error-message>validation of talle failed regexp match fail"
|
||||
|
||||
new "netconf discard-changes"
|
||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><discard-changes/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||
|
||||
new "cli set transitive union int"
|
||||
expectfn "$clixon_cli -1f $cfg -l o -y $fyang set c ulle 33" 0 "^$"
|
||||
|
||||
new "cli validate"
|
||||
expectfn "$clixon_cli -1f $cfg -l o -y $fyang -l o validate" 0 "^$"
|
||||
|
||||
new "cli set transitive union string"
|
||||
expectfn "$clixon_cli -1f $cfg -l o -y $fyang set c ulle unbounded" 0 "^$"
|
||||
|
||||
new "cli validate"
|
||||
expectfn "$clixon_cli -1f $cfg -l o -y $fyang -l o validate" 0 "^$"
|
||||
|
||||
new "cli set transitive union error. should fail"
|
||||
expectfn "$clixon_cli -1f $cfg -l o -y $fyang set c ulle kalle" 255 ""
|
||||
|
||||
new "cli set transitive union error int"
|
||||
expectfn "$clixon_cli -1f $cfg -l o -y $fyang set c ulle 55" 255 ""
|
||||
|
||||
new "netconf set transitive union error int"
|
||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><edit-config><target><candidate/></target><config><c><ulle>55</ulle></c></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>"
|
||||
|
||||
new "netconf validate should fail"
|
||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply><rpc-error><error-tag>operation-failed</error-tag><error-type>application</error-type><error-severity>error</error-severity><error-message>validation of ulle failed"
|
||||
|
||||
new "netconf discard-changes"
|
||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><discard-changes/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||
|
||||
#-----------
|
||||
|
||||
new "cli set ab"
|
||||
expectfn "$clixon_cli -1f $cfg -l o -y $fyang set list a.b.a.b" 0 "^$"
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ cat <<EOF > $cfg
|
|||
<config>
|
||||
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
|
||||
<CLICON_YANG_DIR>/usr/local/share/$APPNAME/yang</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_DIR>/usr/local/share/clixon</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_MODULE_MAIN>$APPNAME</CLICON_YANG_MODULE_MAIN>
|
||||
<CLICON_CLISPEC_DIR>/usr/local/lib/$APPNAME/clispec</CLICON_CLISPEC_DIR>
|
||||
<CLICON_CLI_DIR>/usr/local/lib/$APPNAME/cli</CLICON_CLI_DIR>
|
||||
|
|
|
|||
|
|
@ -6,12 +6,16 @@ APPNAME=example
|
|||
|
||||
cfg=$dir/conf_yang.xml
|
||||
fyang=$dir/test.yang
|
||||
fsubmod=$dir/example-types.yang
|
||||
fyangerr=$dir/err.yang
|
||||
|
||||
# <CLICON_YANG_DIR>/usr/local/share/$APPNAME/yang</CLICON_YANG_DIR>
|
||||
cat <<EOF > $cfg
|
||||
<config>
|
||||
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
|
||||
<CLICON_YANG_DIR>/usr/local/share/$APPNAME/yang</CLICON_YANG_DIR>
|
||||
|
||||
<CLICON_YANG_DIR>$dir</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_DIR>/usr/local/share/clixon</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_MODULE_MAIN>$APPNAME</CLICON_YANG_MODULE_MAIN>
|
||||
<CLICON_CLISPEC_DIR>/usr/local/lib/$APPNAME/clispec</CLICON_CLISPEC_DIR>
|
||||
<CLICON_CLI_DIR>/usr/local/lib/$APPNAME/cli</CLICON_CLI_DIR>
|
||||
|
|
@ -30,6 +34,7 @@ module $APPNAME{
|
|||
yang-version 1.1;
|
||||
prefix ex;
|
||||
namespace "urn:example:clixon";
|
||||
include example-types;
|
||||
extension c-define {
|
||||
description "Example from RFC 6020";
|
||||
argument "name";
|
||||
|
|
@ -85,6 +90,41 @@ module $APPNAME{
|
|||
type string;
|
||||
}
|
||||
}
|
||||
list mylist{ /* uses submodule */
|
||||
key x;
|
||||
leaf x{
|
||||
type string;
|
||||
}
|
||||
uses ex:subm-group;
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
# Submodule Example from rfc7950 sec 7.2.3
|
||||
cat <<EOF > $fsubmod
|
||||
submodule example-types {
|
||||
yang-version 1.1;
|
||||
belongs-to $APPNAME {
|
||||
prefix "sys";
|
||||
}
|
||||
import ietf-yang-types {
|
||||
prefix "yang";
|
||||
}
|
||||
organization "Example Inc.";
|
||||
contact "Joe L. User";
|
||||
description
|
||||
"This submodule defines common Example types.";
|
||||
revision "2007-06-09" {
|
||||
description "Initial revision.";
|
||||
}
|
||||
grouping subm-group {
|
||||
description "Defined in submodule";
|
||||
container subm-container{
|
||||
leaf subm-leaf{
|
||||
type string;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
|
|
@ -128,7 +168,8 @@ new "netconf get config"
|
|||
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><get-config><source><candidate/></source></get-config></rpc>]]>]]>" "^<rpc-reply><data><x><f><e/><e>a</e></f></x></data></rpc-reply>]]>]]>$"
|
||||
|
||||
new "netconf discard-changes"
|
||||
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><discard-changes/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><discard-changes/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||
|
||||
|
||||
#new "cli not defined extension"
|
||||
#new "netconf not defined extension"
|
||||
|
|
@ -182,7 +223,7 @@ new "netconf get presence only"
|
|||
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><get-config><source><candidate/></source><filter type="xpath" select="/x/nopresence"/></get-config></rpc>]]>]]>' "^<rpc-reply><data/></rpc-reply>]]>]]>$"
|
||||
|
||||
new "netconf discard-changes"
|
||||
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><discard-changes/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><discard-changes/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||
|
||||
new "netconf anyxml"
|
||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><edit-config><target><candidate/></target><config><x><any><foo><bar a=\"nisse\"/></foo></any></x></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||
|
|
@ -191,7 +232,7 @@ new "netconf validate anyxml"
|
|||
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||
|
||||
new "netconf delete candidate"
|
||||
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><delete-config><target><candidate/></target></delete-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><delete-config><target><candidate/></target></delete-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||
|
||||
# Check 3-keys
|
||||
new "netconf add one 3-key entry"
|
||||
|
|
@ -218,6 +259,25 @@ expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><edit-config><target><can
|
|||
new "netconf check delete"
|
||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><get-config><source><candidate/></source></get-config></rpc>]]>]]>' '<rpc-reply><data><x><y><a>1</a><b>2</b><c>1</c><val>two</val></y></x></data></rpc-reply>]]>]]>'
|
||||
|
||||
# clear db for next test
|
||||
new "netconf delete candidate"
|
||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><delete-config><target><candidate/></target></delete-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||
|
||||
new "netconf commit empty candidate"
|
||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><commit/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||
|
||||
new "netconfig config submodule"
|
||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><edit-config><target><candidate/></target><config><mylist><x>a</x><subm-container><subm-leaf>foo</subm-leaf></subm-container></mylist></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||
|
||||
new "netconf submodule get config"
|
||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><get-config><source><candidate/></source></get-config></rpc>]]>]]>" "^<rpc-reply><data><mylist><x>a</x><subm-container><subm-leaf>foo</subm-leaf></subm-container></mylist></data></rpc-reply>]]>]]>$"
|
||||
|
||||
new "netconf submodule validate"
|
||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||
|
||||
new "netconf submodule discard-changes"
|
||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><discard-changes/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||
|
||||
new "Kill backend"
|
||||
# Check if premature kill
|
||||
pid=`pgrep -u root -f clixon_backend`
|
||||
|
|
|
|||
|
|
@ -31,6 +31,8 @@
|
|||
|
||||
***** END LICENSE BLOCK *****
|
||||
|
||||
* Parse a SINGLE yang file - no dependencies - utility function only useful
|
||||
* for basic syntactic checks.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
|
|
|
|||
|
|
@ -133,11 +133,14 @@ module clixon-config {
|
|||
description
|
||||
"Location of configuration-file for default values (this file)";
|
||||
}
|
||||
leaf CLICON_YANG_DIR {
|
||||
leaf-list CLICON_YANG_DIR {
|
||||
type string;
|
||||
mandatory true;
|
||||
description
|
||||
"Location of YANG module and submodule files.";
|
||||
"Yang directory path for finding module and submodule files.
|
||||
A list of these options should be in the configuration.
|
||||
When loading a Yang module, Clixon searches this list in the order
|
||||
they appear. Ensure that CLIXON_DATADIR(default
|
||||
/usr/local/share/clixon) is present in the path";
|
||||
}
|
||||
leaf CLICON_YANG_MODULE_MAIN {
|
||||
type string;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue