* Yang Configure options changed

* `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
  * CLICON_YANG_MAIN_FILE Provides a filename with a single module filename.
  * CLICON_YANG_MAIN_DIR Provides a directory where all yang modules should be loaded.
* Change all @datamodel:tree to @datamodel in all CLI specification files
  * If you generate CLI code from the model (CLIXON_CLI_GENMODEL).
  * For backward compatibility, define CLICON_CLI_MODEL_TREENAME_PATCH in clixon_custom.h
* Removed return value ymodp from yang parse functions (eg yang_parse()).
* New config option: CLICON_CLI_MODEL_TREENAME defining name of generated syntax tree if CLIXON_CLI_GENMODEL is set.
This commit is contained in:
Olof hagsand 2018-12-03 21:16:35 +01:00
parent d09a8c08aa
commit ac1aa44fc4
21 changed files with 309 additions and 140 deletions

View file

@ -46,7 +46,7 @@
#include <limits.h>
#include <ctype.h>
#include <unistd.h>
#define __USE_GNU /* strverscmp */
#define __USE_GNU /* strverscmp */
#include <string.h>
#include <arpa/inet.h>
#include <regex.h>
@ -56,6 +56,7 @@
#include <syslog.h>
#include <assert.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <netinet/in.h>
/* cligen */
@ -416,7 +417,7 @@ yn_each(yang_node *yn,
yang_stmt *
yang_find(yang_node *yn,
int keyword,
char *argument)
const char *argument)
{
yang_stmt *ys = NULL;
int i;
@ -1939,7 +1940,6 @@ yang_parse_find_match(clicon_handle h,
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);
@ -2278,7 +2278,6 @@ yang_merge_submodules(clicon_handle h,
* @param[in] module Name of main YANG module. Or absolute file name.
* @param[in] revision Main module revision date string or NULL
* @param[in,out] ysp Yang specification. Should have been created by caller using yspec_new
* @param[out] ymodp Yang module of first, topmost Yang module, if given.
* @retval 0 Everything OK
* @retval -1 Error encountered
* The database symbols are inserted in alphabetical order.
@ -2298,72 +2297,89 @@ yang_parse(clicon_handle h,
const char *filename,
const char *module,
const char *revision,
yang_spec *ysp,
yang_stmt **ymodp)
yang_spec *yspec)
{
int retval = -1;
yang_stmt *ymod = NULL; /* Top-level yang (sub)module */
int i;
int modnr; /* Existing number of modules */
char *base = NULL;;
/* Apply steps 2.. on new modules, ie ones after modnr. */
modnr = ysp->yp_len;
modnr = yspec->yp_len;
if (filename){
if ((ymod = yang_parse_filename(filename, ysp)) == NULL)
/* Find module, and do not load file if module already exists */
if (basename(filename) == NULL){
clicon_err(OE_YANG, errno, "No basename");
goto done;
}
if ((base = strdup(basename(filename))) == NULL){
clicon_err(OE_YANG, errno, "strdup");
goto done;
}
if (index(base, '@') != NULL)
*index(base, '@') = '\0';
if (yang_find((yang_node*)yspec, Y_MODULE, base) != NULL)
goto ok;
if ((ymod = yang_parse_filename(filename, yspec)) == NULL)
goto done;
}
else
if ((ymod = yang_parse_module(h, module, revision, ysp)) == NULL)
else {
/* Do not load module if it already exists */
if (yang_find((yang_node*)yspec, Y_MODULE, module) != NULL)
goto ok;
if ((ymod = yang_parse_module(h, module, revision, yspec)) == NULL)
goto done;
}
/* 1: Parse from text to yang parse-tree. */
/* Iterate through modules */
if (yang_parse_recurse(h, ymod, ysp) < 0)
if (yang_parse_recurse(h, ymod, yspec) < 0)
goto done;
/* 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)
for (i=modnr; i<yspec->yp_len; i++) /* XXX */
if (yang_cardinality(h, yspec->yp_stmt[i], yspec->yp_stmt[i]->ys_argument) < 0)
goto done;
/* 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)
for (i=modnr; i<yspec->yp_len; i++){
if (yspec->yp_stmt[i]->ys_keyword != Y_SUBMODULE)
continue;
}
i = 0;
while (i<ysp->yp_len){
while (i<yspec->yp_len){
int j;
if (ysp->yp_stmt[i]->ys_keyword != Y_SUBMODULE){
if (yspec->yp_stmt[i]->ys_keyword != Y_SUBMODULE){
i++;
continue;
}
if (yang_merge_submodules(h, ysp, ysp->yp_stmt[i]) < 0)
if (yang_merge_submodules(h, yspec, yspec->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--;
for (j=i; j<yspec->yp_len-1; j++)
yspec->yp_stmt[j] = yspec->yp_stmt[j+1];
yspec->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)
for (i=modnr; i<yspec->yp_len; i++) /* XXX */
if (yang_features(h, yspec->yp_stmt[i]) < 0)
goto done;
/* 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)
for (i=modnr; i<yspec->yp_len; i++)
if (yang_apply((yang_node*)yspec->yp_stmt[i], -1, ys_populate, (void*)h) < 0)
goto done;
/* 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++)
if (yang_apply((yang_node*)ysp->yp_stmt[i], Y_TYPE, ys_resolve_type, NULL) < 0)
for (i=modnr; i<yspec->yp_len; i++)
if (yang_apply((yang_node*)yspec->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
@ -2374,25 +2390,26 @@ yang_parse(clicon_handle h,
*/
/* 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)
for (i=modnr; i<yspec->yp_len; i++){
if (yang_expand((yang_node*)yspec->yp_stmt[i]) < 0)
goto done;
yang_apply((yang_node*)ysp->yp_stmt[i], -1, ys_flag_reset, (void*)YANG_FLAG_MARK);
yang_apply((yang_node*)yspec->yp_stmt[i], -1, ys_flag_reset, (void*)YANG_FLAG_MARK);
}
/* 8: Top-level augmentation of all modules XXX: only new modules? */
if (yang_augment_spec(ysp) < 0)
if (yang_augment_spec(yspec) < 0)
goto done;
/* 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)
for (i=modnr; i<yspec->yp_len; i++)
if (yang_apply((yang_node*)yspec->yp_stmt[i], -1, ys_schemanode_check, NULL) < 0)
goto done;
/* Return main module parsed in step 1 */
if (ymodp)
*ymodp = ymod;
ok:
retval = 0;
done:
done:
if (base)
free(base);
return retval;
}
@ -2792,7 +2809,6 @@ yang_config(yang_stmt *ys)
* @param[in] dir Directory where to look for modules and sub-modules
* @param[in] revision Revision, or NULL
* @param[in,out] yspec Modules parse are added to this yangspec
* @param[out] ymodp Yang module of first, topmost Yang module, if given.
* @retval 0 OK
* @retval -1 Error
* @see yang_spec_parse_file
@ -2801,8 +2817,7 @@ int
yang_spec_parse_module(clicon_handle h,
char *module,
char *revision,
yang_spec *yspec,
yang_stmt **ymodp)
yang_spec *yspec)
{
int retval = -1;
@ -2819,7 +2834,7 @@ yang_spec_parse_module(clicon_handle h,
clicon_err(OE_YANG, EINVAL, "yang module illegal format");
goto done;
}
if (yang_parse(h, NULL, module, revision, yspec, ymodp) < 0)
if (yang_parse(h, NULL, module, revision, yspec) < 0)
goto done;
retval = 0;
done:
@ -2831,7 +2846,6 @@ yang_spec_parse_module(clicon_handle h,
* @param[in] filename Actual filename (including dir and revision)
* @param[in] dir Directory for sub-modules
* @param[in,out] yspec Modules parse are added to this yangspec
* @param[out] ymodp Yang module of first, topmost Yang module, if given.
* @retval 0 OK
* @retval -1 Error
* @see yang_spec_parse_module for yang dir,module,revision instead of actual filename
@ -2839,8 +2853,7 @@ yang_spec_parse_module(clicon_handle h,
int
yang_spec_parse_file(clicon_handle h,
char *filename,
yang_spec *yspec,
yang_stmt **ymodp)
yang_spec *yspec)
{
int retval = -1;
@ -2848,13 +2861,62 @@ yang_spec_parse_file(clicon_handle h,
clicon_err(OE_YANG, EINVAL, "yang spec is NULL");
goto done;
}
if (yang_parse(h, filename, NULL, NULL, yspec, ymodp) < 0)
if (yang_parse(h, filename, NULL, NULL, yspec) < 0)
goto done;
retval = 0;
done:
return retval;
}
/*! Load all yang modules in directory
* @param[in] h Clicon handle
* @param[in] dir Load all yang modules in this directory
* @param[in,out] yspec Modules parse are added to this yangspec
* @retval 0 OK
* @retval -1 Error
*/
int
yang_spec_load_dir(clicon_handle h,
char *dir,
yang_spec *yspec)
{
int retval = -1;
int ndp;
struct dirent *dp = NULL;
int i;
char filename[MAXPATHLEN];
char *base;
char *b;
int j;
int len;
/* Get plugin objects names from plugin directory */
if((ndp = clicon_file_dirent(dir, &dp, "(.yang)$", S_IFREG)) < 0)
goto done;
/* Load all yang files */
for (i = 0; i < ndp; i++) {
base = dp[i].d_name;
/* Entries are sorted, see if later entry exists (include @), if so skip
* this one and take last.
*/
if ((b = index(base, '@')) != NULL)
len = b-base;
else
len = strlen(base);
for (j = (i+1); j < ndp; j++)
if (strncmp(base, dp[j].d_name, len) == 0)
break;
if (j<ndp) /* exists later entry */
continue;
snprintf(filename, MAXPATHLEN-1, "%s/%s", dir, dp[i].d_name);
if (yang_parse(h, filename, NULL, NULL, yspec) < 0)
goto done;
}
retval = 0;
done:
return retval;
}
/*! Given a yang node, translate the argument string to a cv vector
*
* @param[in] ys Yang statement