yang type resolution fix

This commit is contained in:
Olof hagsand 2017-06-24 21:40:05 +02:00
parent abd3eee17d
commit 3bd6c1bf32
4 changed files with 83 additions and 81 deletions

View file

@ -159,7 +159,7 @@ api_data_get_gen(clicon_handle h,
cxobj *xerr; cxobj *xerr;
cbuf *cbj = NULL;; cbuf *cbj = NULL;;
int code; int code;
char *reason_phrase; const char *reason_phrase;
clicon_debug(1, "%s", __FUNCTION__); clicon_debug(1, "%s", __FUNCTION__);
yspec = clicon_dbspec_yang(h); yspec = clicon_dbspec_yang(h);

View file

@ -199,7 +199,7 @@ char *ytype_prefix(yang_stmt *ys);
char *ytype_id(yang_stmt *ys); char *ytype_id(yang_stmt *ys);
yang_stmt *ys_module(yang_stmt *ys); yang_stmt *ys_module(yang_stmt *ys);
yang_spec *ys_spec(yang_stmt *ys); yang_spec *ys_spec(yang_stmt *ys);
yang_stmt *ys_module_import(yang_stmt *ymod, char *prefix); yang_stmt *yang_find_module_by_prefix(yang_stmt *ys, char *prefix);
yang_stmt *yang_find(yang_node *yn, int keyword, char *argument); yang_stmt *yang_find(yang_node *yn, int keyword, char *argument);
yang_stmt *yang_find_syntax(yang_node *yn, char *argument); yang_stmt *yang_find_syntax(yang_node *yn, char *argument);
yang_stmt *yang_find_topnode(yang_spec *ysp, char *name); yang_stmt *yang_find_topnode(yang_spec *ysp, char *name);

View file

@ -615,29 +615,63 @@ ytype_prefix(yang_stmt *ys)
return prefix; return prefix;
} }
/*! Given a module and a prefix, find the import statement fo that prefix
/*! Given a yang statement and a prefix, return yang module to that prefix
* Note, not the other module but the proxy import statement only * Note, not the other module but the proxy import statement only
* @param[in] ytop yang module * @param[in] ys A yang statement
* @param[in] prefix prefix
* @retval ymod Yang module statement if found
* @retval NULL not found
*/ */
yang_stmt * yang_stmt *
ys_module_import(yang_stmt *ymod, yang_find_module_by_prefix(yang_stmt *ys,
char *prefix) char *prefix)
{ {
yang_stmt *yimport = NULL; yang_stmt *yimport;
yang_stmt *yprefix; yang_stmt *yprefix;
yang_stmt *my_ymod;
yang_stmt *ymod = NULL;
yang_spec *yspec;
assert(ymod->ys_keyword == Y_MODULE || ymod->ys_keyword == Y_SUBMODULE); if ((my_ymod = ys_module(ys)) == NULL){
while ((yimport = yn_each((yang_node*)ymod, yimport)) != NULL) { clicon_err(OE_YANG, 0, "My yang module not found");
goto done;
}
if ((yspec = ys_spec(my_ymod)) == NULL){
clicon_err(OE_YANG, 0, "My yang spec not found");
goto done;
}
if (my_ymod->ys_keyword != Y_MODULE &&
my_ymod->ys_keyword != Y_SUBMODULE){
clicon_err(OE_YANG, 0, "%s not module or sub-module", my_ymod->ys_argument);
goto done;
}
if ((yprefix = yang_find((yang_node*)my_ymod, Y_PREFIX, NULL)) != NULL &&
strcmp(yprefix->ys_argument, prefix) == 0){
ymod = my_ymod;
goto done;
}
yimport = NULL;
while ((yimport = yn_each((yang_node*)my_ymod, yimport)) != NULL) {
if (yimport->ys_keyword != Y_IMPORT) if (yimport->ys_keyword != Y_IMPORT)
continue; continue;
if ((yprefix = yang_find((yang_node*)yimport, Y_PREFIX, NULL)) != NULL && if ((yprefix = yang_find((yang_node*)yimport, Y_PREFIX, NULL)) != NULL &&
strcmp(yprefix->ys_argument, prefix) == 0) strcmp(yprefix->ys_argument, prefix) == 0){
return yimport; break;
} }
return NULL; }
if (yimport){
if ((ymod = yang_find((yang_node*)yspec, Y_MODULE, yimport->ys_argument)) == NULL){
clicon_err(OE_YANG, 0, "No module or sub-module found with prefix %s",
yimport->ys_argument);
yimport = NULL;
goto done; /* unresolved */
}
}
done:
return ymod;
} }
/*! string is quoted if it contains space or tab, needs double '' */ /*! string is quoted if it contains space or tab, needs double '' */
static int inline static int inline
quotedstring(char *s) quotedstring(char *s)
@ -1036,22 +1070,13 @@ ys_grouping_resolve(yang_stmt *ys,
yang_stmt **ygrouping0) yang_stmt **ygrouping0)
{ {
int retval = -1; int retval = -1;
yang_stmt *yimport;
yang_spec *yspec;
yang_stmt *ymodule; yang_stmt *ymodule;
yang_stmt *ygrouping = NULL; yang_stmt *ygrouping = NULL;
yang_node *yn; yang_node *yn;
yang_stmt *ymod;
/* find the grouping associated with argument and expand(?) */ /* find the grouping associated with argument and expand(?) */
if (prefix){ /* Go to top and find import that matches */ if (prefix){ /* Go to top and find import that matches */
ymod = ys_module(ys); if ((ymodule = yang_find_module_by_prefix(ys, prefix)) != NULL)
if ((yimport = ys_module_import(ymod, prefix)) == NULL){
clicon_err(OE_DB, 0, "Prefix %s not defined not found", prefix);
goto done;
}
yspec = ys_spec(ys);
if ((ymodule = yang_find((yang_node*)yspec, Y_MODULE, yimport->ys_argument)) != NULL)
ygrouping = yang_find((yang_node*)ymodule, Y_GROUPING, name); ygrouping = yang_find((yang_node*)ymodule, Y_GROUPING, name);
} }
else else
@ -1067,7 +1092,7 @@ ys_grouping_resolve(yang_stmt *ys,
} }
*ygrouping0 = ygrouping; *ygrouping0 = ygrouping;
retval = 0; retval = 0;
done: // done:
return retval; return retval;
} }
@ -1246,8 +1271,8 @@ yang_expand(yang_node *yn)
* @param str String of yang statements * @param str String of yang statements
* @param name Log string, typically filename * @param name Log string, typically filename
* @param ysp Yang specification. Should ave been created by caller using yspec_new * @param ysp Yang specification. Should ave been created by caller using yspec_new
* @retval 0 Everything OK * @retval ymod Top-level yang (sub)module
* @retval -1 Error encountered * @retval NULL Error encountered
* Calling order: * Calling order:
* yang_parse # Parse top-level yang module. Expand and populate yang tree * yang_parse # Parse top-level yang module. Expand and populate yang tree
* yang_parse1 # Parse one yang module, go through its (sub)modules and parse them * yang_parse1 # Parse one yang module, go through its (sub)modules and parse them
@ -1263,7 +1288,7 @@ yang_parse_str(clicon_handle h,
yang_spec *yspec) yang_spec *yspec)
{ {
struct clicon_yang_yacc_arg yy = {0,}; struct clicon_yang_yacc_arg yy = {0,};
yang_stmt *ym = NULL; yang_stmt *ymod = NULL;
yy.yy_handle = h; yy.yy_handle = h;
yy.yy_name = (char*)name; yy.yy_name = (char*)name;
@ -1292,10 +1317,10 @@ yang_parse_str(clicon_handle h,
if (yang_scan_exit(&yy) < 0) if (yang_scan_exit(&yy) < 0)
goto done; goto done;
} }
ym = yy.yy_module; ymod = yy.yy_module;
done: done:
ystack_pop(&yy); ystack_pop(&yy);
return ym; return ymod; /* top-level (sub)module */
} }
/*! Read an opened file into a string and call yang string parsing /*! Read an opened file into a string and call yang string parsing
@ -1306,8 +1331,8 @@ yang_parse_str(clicon_handle h,
* @param f Open file handle * @param f Open file handle
* @param name Log string, typically filename * @param name Log string, typically filename
* @param ysp Yang specification. Should ave been created by caller using yspec_new * @param ysp Yang specification. Should ave been created by caller using yspec_new
* @retval 0 Everything OK * @retval ymod Top-level yang (sub)module
* @retval -1 Error encountered * @retval NULL Error encountered
* The database symbols are inserted in alphabetical order. * The database symbols are inserted in alphabetical order.
* Calling order: * Calling order:
@ -1329,7 +1354,7 @@ yang_parse_file(clicon_handle h,
int i; int i;
int c; int c;
int len; int len;
yang_stmt *ymodule = NULL; yang_stmt *ymod = NULL;
clicon_debug(1, "Yang parse file: %s", name); clicon_debug(1, "Yang parse file: %s", name);
len = 1024; /* any number is fine */ len = 1024; /* any number is fine */
@ -1353,12 +1378,12 @@ yang_parse_file(clicon_handle h,
} }
buf[i++] = (char)(c&0xff); buf[i++] = (char)(c&0xff);
} /* read a line */ } /* read a line */
if ((ymodule = yang_parse_str(h, buf, name, ysp)) < 0) if ((ymod = yang_parse_str(h, buf, name, ysp)) < 0)
goto done; goto done;
done: done:
if (buf) if (buf)
free(buf); free(buf);
return ymodule; 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 dir and module
@ -1416,8 +1441,8 @@ yang_parse_find_match(clicon_handle h,
* @param module Name of main YANG module. More modules may be parsed if imported * @param module Name of main YANG module. More modules may be parsed if imported
* @param revision Optional module revision date * @param revision Optional module revision date
* @param ysp Yang specification. Should ave been created by caller using yspec_new * @param ysp Yang specification. Should ave been created by caller using yspec_new
* @retval 0 Everything OK * @retval ymod Top-level yang (sub)module
* @retval -1 Error encountered * @retval NULL Error encountered
* module-or-submodule-name ['@' revision-date] ( '.yang' / '.yin' ) * module-or-submodule-name ['@' revision-date] ( '.yang' / '.yin' )
* Calling order: * Calling order:
* yang_parse # Parse top-level yang module. Expand and populate yang tree * yang_parse # Parse top-level yang module. Expand and populate yang tree
@ -1437,7 +1462,7 @@ yang_parse2(clicon_handle h,
FILE *f = NULL; FILE *f = NULL;
cbuf *fbuf = NULL; cbuf *fbuf = NULL;
char *filename; char *filename;
yang_stmt *ys = NULL; yang_stmt *ymod = NULL;
struct stat st; struct stat st;
int nr; int nr;
@ -1465,14 +1490,14 @@ yang_parse2(clicon_handle h,
clicon_err(OE_UNIX, errno, "fopen(%s)", filename); clicon_err(OE_UNIX, errno, "fopen(%s)", filename);
goto done; goto done;
} }
if ((ys = yang_parse_file(h, f, filename, ysp)) == NULL) if ((ymod = yang_parse_file(h, f, filename, ysp)) == NULL)
goto done; goto done;
done: done:
if (fbuf) if (fbuf)
cbuf_free(fbuf); cbuf_free(fbuf);
if (f) if (f)
fclose(f); fclose(f);
return ys; return ymod; /* top-level (sub)module */
} }
/*! Parse one yang module then go through (sub)modules and parse them recursively /*! Parse one yang module then go through (sub)modules and parse them recursively
@ -1481,9 +1506,9 @@ yang_parse2(clicon_handle h,
* @param yang_dir Directory where all YANG module files reside * @param yang_dir Directory where all YANG module files reside
* @param module Name of main YANG module. More modules may be parsed if imported * @param module Name of main YANG module. More modules may be parsed if imported
* @param revision Optional module revision date * @param revision Optional module revision date
* @param ysp Yang specification. Should ave been created by caller using yspec_new * @param ysp Yang specification. Should have been created by caller using yspec_new
* @retval 0 Everything OK * @retval ymod Top-level yang (sub)module
* @retval -1 Error encountered * @retval NULL Error encountered
* Find a yang module file, and then recursively parse all its imported modules. * Find a yang module file, and then recursively parse all its imported modules.
* Calling order: * Calling order:
* yang_parse # Parse top-level yang module. Expand and populate yang tree * yang_parse # Parse top-level yang module. Expand and populate yang tree
@ -1501,15 +1526,15 @@ yang_parse1(clicon_handle h,
yang_spec *ysp) yang_spec *ysp)
{ {
yang_stmt *yi = NULL; /* import */ yang_stmt *yi = NULL; /* import */
yang_stmt *ys; yang_stmt *ymod;
yang_stmt *yrev; yang_stmt *yrev;
char *modname; char *modname;
char *subrevision; char *subrevision;
if ((ys = yang_parse2(h, yang_dir, module, revision, ysp)) == NULL) if ((ymod = yang_parse2(h, yang_dir, module, revision, ysp)) == NULL)
goto done; goto done;
/* go through all import statements of ysp (or its module) */ /* go through all import statements of ysp (or its module) */
while ((yi = yn_each((yang_node*)ys, yi)) != NULL){ while ((yi = yn_each((yang_node*)ymod, yi)) != NULL){
if (yi->ys_keyword != Y_IMPORT) if (yi->ys_keyword != Y_IMPORT)
continue; continue;
modname = yi->ys_argument; modname = yi->ys_argument;
@ -1519,12 +1544,12 @@ yang_parse1(clicon_handle h,
subrevision = NULL; subrevision = NULL;
if (yang_find((yang_node*)ysp, Y_MODULE, modname) == NULL) if (yang_find((yang_node*)ysp, Y_MODULE, modname) == NULL)
if (yang_parse1(h, yang_dir, modname, subrevision, ysp) == NULL){ if (yang_parse1(h, yang_dir, modname, subrevision, ysp) == NULL){
ys = NULL; ymod = NULL;
goto done; goto done;
} }
} }
done: done:
return ys; return ymod; /* top-level (sub)module */
} }
/*! Parse top yang module including all its sub-modules. Expand and populate yang tree /*! Parse top yang module including all its sub-modules. Expand and populate yang tree
@ -1554,22 +1579,22 @@ yang_parse(clicon_handle h,
yang_spec *ysp) yang_spec *ysp)
{ {
int retval = -1; int retval = -1;
yang_stmt *ys; yang_stmt *ymod; /* Top-level yang (sub)module */
/* Step 1: parse from text to yang parse-tree. */ /* Step 1: parse from text to yang parse-tree. */
if ((ys = yang_parse1(h, yang_dir, module, revision, ysp)) == NULL) if ((ymod = yang_parse1(h, yang_dir, module, revision, ysp)) == NULL)
goto done; goto done;
/* Add top module name as dbspec-name */ /* Add top module name as dbspec-name */
clicon_dbspec_name_set(h, ys->ys_argument); clicon_dbspec_name_set(h, ymod->ys_argument);
#ifdef YANG_TYPE_CACHE #ifdef YANG_TYPE_CACHE
/* Resolve all types */ /* Resolve all types */
yang_apply((yang_node*)ys, ys_resolve_type, NULL); yang_apply((yang_node*)ysp, ys_resolve_type, NULL);
#endif #endif
/* Step 2: Macro expansion of all grouping/uses pairs. Expansion needs marking */ /* Step 2: Macro expansion of all grouping/uses pairs. Expansion needs marking */
if (yang_expand((yang_node*)ysp) < 0) if (yang_expand((yang_node*)ysp) < 0)
goto done; goto done;
yang_apply((yang_node*)ys, ys_flag_reset, (void*)YANG_FLAG_MARK); yang_apply((yang_node*)ymod, ys_flag_reset, (void*)YANG_FLAG_MARK);
/* Step 4: Go through parse tree and populate it with cv types */ /* Step 4: Go through parse tree and populate it with cv types */
if (yang_apply((yang_node*)ysp, ys_populate, NULL) < 0) if (yang_apply((yang_node*)ysp, ys_populate, NULL) < 0)
goto done; goto done;
@ -1678,8 +1703,6 @@ yang_xpath_abs(yang_node *yn,
int nvec; int nvec;
yang_node *ys = NULL; yang_node *ys = NULL;
yang_stmt *ymod; yang_stmt *ymod;
yang_spec *yspec;
yang_stmt *yimport;
char *id; char *id;
char *prefix = NULL; char *prefix = NULL;
@ -1716,16 +1739,9 @@ yang_xpath_abs(yang_node *yn,
} }
prefix[id-vec[1]] = '\0'; prefix[id-vec[1]] = '\0';
id++; id++;
if ((yimport = ys_module_import(ymod, prefix)) == NULL){ if ((ymod = yang_find_module_by_prefix((yang_stmt*)yn, prefix)) == NULL)
clicon_err(OE_DB, 0, "Prefix %s not defined not found", prefix);
goto done; goto done;
} }
yspec = ys_spec(ymod);
if ((ymod = yang_find((yang_node*)yspec, Y_MODULE, yimport->ys_argument)) == NULL){
clicon_err(OE_DB, 0, "Module referred to with prefix %s not found", prefix);
goto done;
}
}
ys = yang_xpath_vec((yang_node*)ymod, vec+1, nvec-1); ys = yang_xpath_vec((yang_node*)ymod, vec+1, nvec-1);
done: done:
if (vec) if (vec)

View file

@ -223,8 +223,9 @@ ys_resolve_type(yang_stmt *ys, void *arg)
if (ys->ys_keyword != Y_TYPE) if (ys->ys_keyword != Y_TYPE)
return 0; return 0;
yang_type_resolve((yang_stmt*)ys->ys_parent, ys, &resolved, if (yang_type_resolve((yang_stmt*)ys->ys_parent, ys, &resolved,
&options, &mincv, &maxcv, &pattern, &fraction); &options, &mincv, &maxcv, &pattern, &fraction) < 0)
goto done;
if (yang_type_cache_set(&ys->ys_typecache, if (yang_type_cache_set(&ys->ys_typecache,
resolved, options, mincv, maxcv, pattern, fraction) < 0) resolved, options, mincv, maxcv, pattern, fraction) < 0)
goto done; goto done;
@ -721,12 +722,9 @@ yang_find_identity(yang_stmt *ys, char *identity)
{ {
char *id; char *id;
char *prefix = NULL; char *prefix = NULL;
yang_stmt *yimport;
yang_spec *yspec;
yang_stmt *ymodule; yang_stmt *ymodule;
yang_stmt *yid = NULL; yang_stmt *yid = NULL;
yang_node *yn; yang_node *yn;
yang_stmt *ymod;
if ((id = strchr(identity, ':')) == NULL) if ((id = strchr(identity, ':')) == NULL)
id = identity; id = identity;
@ -737,12 +735,8 @@ yang_find_identity(yang_stmt *ys, char *identity)
} }
/* No, now check if identityref is derived from base */ /* No, now check if identityref is derived from base */
if (prefix){ /* Go to top and find import that matches */ if (prefix){ /* Go to top and find import that matches */
ymod = ys_module(ys); if ((ymodule = yang_find_module_by_prefix(ys, prefix)) == NULL)
if ((yimport = ys_module_import(ymod, prefix)) == NULL)
goto done; goto done;
yspec = ys_spec(ys);
if ((ymodule = yang_find((yang_node*)yspec, Y_MODULE, yimport->ys_argument)) == NULL)
goto done; /* unresolved */
yid = yang_find((yang_node*)ymodule, Y_IDENTITY, id); yid = yang_find((yang_node*)ymodule, Y_IDENTITY, id);
} }
else{ else{
@ -834,12 +828,10 @@ yang_type_resolve(yang_stmt *ys,
yang_stmt *ylength; yang_stmt *ylength;
yang_stmt *ypattern; yang_stmt *ypattern;
yang_stmt *yfraction; yang_stmt *yfraction;
yang_stmt *yimport;
char *type; char *type;
char *prefix = NULL; char *prefix = NULL;
int retval = -1; int retval = -1;
yang_node *yn; yang_node *yn;
yang_spec *yspec;
yang_stmt *ymod; yang_stmt *ymod;
if (options) if (options)
@ -868,14 +860,8 @@ yang_type_resolve(yang_stmt *ys,
/* Not basic type. Now check if prefix which means we look in other module */ /* 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 (prefix){ /* Go to top and find import that matches */
ymod = ys_module(ys); if ((ymod = yang_find_module_by_prefix(ys, prefix)) == NULL)
if ((yimport = ys_module_import(ymod, prefix)) == NULL){
clicon_err(OE_DB, 0, "Prefix %s not defined not found", prefix);
goto done; goto done;
}
yspec = ys_spec(ys);
if ((ymod = yang_find((yang_node*)yspec, Y_MODULE, yimport->ys_argument)) == NULL)
goto ok; /* unresolved */
if ((rytypedef = yang_find((yang_node*)ymod, Y_TYPEDEF, type)) == NULL) if ((rytypedef = yang_find((yang_node*)ymod, Y_TYPEDEF, type)) == NULL)
goto ok; /* unresolved */ goto ok; /* unresolved */
} }