Changed YANG uses/grouping to keep uses statement and flag it with YANG_FLAG_USES_EXP

Updated yang code headers
This commit is contained in:
Olof hagsand 2023-07-18 14:47:42 +02:00
parent e0cbc10fad
commit d48442960e
4 changed files with 172 additions and 146 deletions

View file

@ -72,6 +72,7 @@ Developers may need to change their code
### Minor features
* Changed YANG uses/grouping to keep uses statement and flag it with YANG_FLAG_USES_EXP
* Removed extras/ and build-root/ build code since they are not properly maintained
* Refactored cli-syntax code to use cligen pt_head instead (long overdue)
* Modified backend exit strategy so that 2nd ^C actually exits

View file

@ -70,6 +70,19 @@
* Transformed to ANYDATA but some code may need to check
* why it is an ANYDATA
*/
#define YANG_FLAG_GROUPING 0x80 /* Mark node as uses/grouping expansion:
* 1) for uses: this uses is expanded
* 2) for grouping: all uses below are expanded
* 3) other nodes: expanded from previous uses
* container x {
* ...
* uses y; YANG_FLAG_GROUPING (1)
* leaf z; YANG_FLAG_GROUPING (3)
* ...
* group y { YANG_FLAG_GROUPING (2)
* leaf z;
* }
*/
/*
* Types

View file

@ -180,6 +180,7 @@ static int yang_type_cache_cp(yang_stmt *ynew, yang_stmt *yold);
*/
/*! Get Number of children yang statements
*
* @param[in] ys Yang statement node
*/
int
@ -189,6 +190,7 @@ yang_len_get(yang_stmt *ys)
}
/*! Get Specific Yang statement child
*
* @param[in] ys Yang statement node
* @param[in] i Return this child
*/
@ -200,6 +202,7 @@ yang_child_i(yang_stmt *ys,
}
/*! Get yang statement parent
*
* @param[in] ys Yang statement node
*/
yang_stmt *
@ -209,6 +212,7 @@ yang_parent_get(yang_stmt *ys)
}
/*! Get yang statement keyword
*
* @param[in] ys Yang statement node
*/
enum rfc_6020
@ -218,6 +222,7 @@ yang_keyword_get(yang_stmt *ys)
}
/*! Get yang statement context-dependent argument
*
* @param[in] ys Yang statement node
*/
char*
@ -236,6 +241,7 @@ yang_argument_get(yang_stmt *ys)
* 2d. type: leafref types: derived instances.
*/
/*! Set yang argument, not not copied
*
* @param[in] ys Yang statement node
* @param[in] arg Argument, note must be malloced
* Typically only done at parsing / initiation
@ -249,6 +255,7 @@ yang_argument_set(yang_stmt *ys,
}
/*! Get yang statement CLIgen variable
*
* @param[in] ys Yang statement node
*/
cg_var*
@ -258,6 +265,7 @@ yang_cv_get(yang_stmt *ys)
}
/*! Set yang statement CLIgen variable
*
* @param[in] ys Yang statement node
* @param[in] cv cligen variable
* @note: Frees on replace, not if cv is NULL. This is for some ys_cp/ys_dup cases, which means
@ -274,6 +282,7 @@ yang_cv_set(yang_stmt *ys,
}
/*! Get yang statement CLIgen variable vector
*
* @param[in] ys Yang statement node
* @note To add entries, use yang_cvec_add(), since this function may return NULL
*/
@ -284,6 +293,7 @@ yang_cvec_get(yang_stmt *ys)
}
/*! Set yang statement CLIgen variable vector
*
* @param[in] ys Yang statement node
* @param[in] cvec CLIgen vector
* @retval 0 OK
@ -334,6 +344,7 @@ yang_cvec_add(yang_stmt *ys,
}
/*! Get yang stmt flags, used for internal algorithms
*
* @param[in] ys Yang statement
* @param[in] flag Flags value(s) to get, see YANG_FLAG_*
* @retval value Flags value masked by "flag" parameter, see YANG_FLAG_*
@ -346,6 +357,7 @@ yang_flag_get(yang_stmt *ys,
}
/*! Set yang stmt flags, used for internal algorithms
*
* @param[in] ys Yang statement
* @param[in] flag Flag value(s) to set, see YANG_FLAG_*
*/
@ -358,6 +370,7 @@ yang_flag_set(yang_stmt *ys,
}
/*! Reset yang stmt flags, used for internal algorithms
*
* @param[in] ys Yang statement
* @param[in] flag Flag value(s) to reset, see YANG_FLAG_*
*/
@ -376,7 +389,7 @@ yang_flag_reset(yang_stmt *ys,
* @param[in] ys Yang statement
* @retval xpath xpath should evaluate to true at validation
* @retval NULL Not set
* Note xpath context is PARENT which is different from when actual when child which is
* @note xpath context is PARENT which is different from when actual when child which is
* child itself
*/
char*
@ -525,6 +538,7 @@ yang_stats_global(uint64_t *nr)
}
/*! Return the alloced memory of a single YANG obj
*
* @param[in] y YANG object
* @param[out] szp Size of this YANG obj
* @retval 0 OK
@ -566,6 +580,7 @@ yang_stats_one(yang_stmt *y,
}
/*! Return statistics of an YANG-stmt tree recursively
*
* @param[in] yt YANG object
* @param[out] nrp Number of YANG objects recursively
* @param[out] szp Size of this YANG stmt recursively
@ -604,6 +619,7 @@ yang_stats(yang_stmt *yt,
/* stats end */
/*! Create new yang specification
*
* @retval yspec Free with ys_free()
* @retval NULL Error
*/
@ -623,6 +639,7 @@ yspec_new(void)
}
/*! Create new yang node/statement
*
* @retval ys Free with ys_free()
* @retval NULL Error
*/
@ -703,10 +720,11 @@ ys_free1(yang_stmt *ys,
}
/*! Remove child i from parent yp (dont free)
*
* @param[in] yp Parent node
* @param[in] i Order of child to remove
* @retval NULL No such node, nothing done
* @retval yc returned orphaned yang node
* @retval NULL No such node, nothing done
* @see ys_free Deallocate yang node
* @see ys_prune_self Prune child itself
* @note Do not call this in a loop of yang children (unless you know what you are doing)
@ -733,7 +751,8 @@ ys_prune(yang_stmt *yp,
return yc;
}
/*! Remove yang node from parent (dont free
/*! Remove yang node from parent (dont free)
*
* @param[in] ys Yang node to remove
* @retval 0 OK
* @retval -1 Error
@ -769,6 +788,7 @@ ys_prune_self(yang_stmt *ys)
}
/*! Free all yang children tree recursively
*
* @param[in] ys Yang node to its children recursively
*/
static int
@ -790,6 +810,7 @@ ys_freechildren(yang_stmt *ys)
}
/*! Free a yang statement tree recursively
*
* @param[in] ys Yang node to remove and all its children recursively
* @note does not remove yang node from tree
* @see ys_prune Remove from parent
@ -802,7 +823,8 @@ ys_free(yang_stmt *ys)
return 0;
}
/*! Allocate larger yang statement vector adding empty field last */
/*! Allocate larger yang statement vector adding empty field last
*/
static int
yn_realloc(yang_stmt *yn)
{
@ -817,6 +839,7 @@ yn_realloc(yang_stmt *yn)
}
/*! Copy yang statement recursively from old to new
*
* @param[in] ynew New empty (but created) yang statement (to)
* @param[in] yold Old existing yang statement (from)
* @retval 0 OK
@ -893,6 +916,7 @@ ys_cp(yang_stmt *ynew,
}
/*! Create a new yang node and copy the contents recursively from the original. *
*
* @param[in] old Old existing yang statement (from)
* @retval NULL Error
* @retval nw New created yang statement
@ -1190,6 +1214,7 @@ yang_find_datanode(yang_stmt *yn,
}
/*! Find child schema node with matching argument (container, leaf, etc)
*
* @param[in] yn Yang node, current context node.
* @param[in] argument if NULL, match any(first) argument.
* @note XXX unify code with yang_find_datanode?
@ -1270,8 +1295,8 @@ yang_find_schemanode(yang_stmt *yn,
/*! Given a yang statement, or module itself, find the prefix associated to this module
*
* @param[in] ys Yang statement in module tree (or module itself)
* @retval NULL No prefix found. This is an error
* @retval prefix OK: Prefix as char* pointer into yang tree
* @retval NULL No prefix found. This is an error
* @code
* char *myprefix;
* myprefix = yang_find_myprefix(ys);
@ -1303,8 +1328,8 @@ yang_find_myprefix(yang_stmt *ys)
/*! Given a yang statement, find the namespace URI associated to this module
*
* @param[in] ys Yang statement in module tree (or module itself)
* @retval NULL Error: No namespace found. This is an error
* @retval ns Namspace URI as char* pointer into yang tree
* @retval NULL Error: No namespace found. This is an error
* @code
* char *myns = yang_find_mynamespace(ys);
* @endcode
@ -1329,15 +1354,16 @@ yang_find_mynamespace(yang_stmt *ys)
}
/*! Given a yang statement and namespace, find local prefix valid in module
*
* This is useful if you want to make a "reverse" lookup, you know the
* (global) namespace of a module, but you do not know the local prefix
* used to access it in XML.
* @param[in] ys Yang statement in module tree (or module itself)
* @param[in] ns Namespace URI as char* pointer into yang tree
* @param[out] prefix Local prefix to access module with (direct pointer)
* @retval -1 Error
* @retval 0 Not found
* @retval 1 Found
* @retval 0 Not found
* @retval -1 Error
* @note prefix NULL is not returned, if own module, then return its prefix
* @code
* char *prefix = NULL;
@ -1404,9 +1430,9 @@ yang_find_prefix_by_namespace(yang_stmt *ys,
* @param[in] ys Yang statement in module tree (or module itself)
* @param[in] prefix Local prefix to access module with (direct pointer)
* @param[out] ns Namespace URI as char* pointer into yang tree
* @retval -1 Error
* @retval 0 Not found
* @retval 1 Found
* @retval 0 Not found
* @retval -1 Error
* @note prefix NULL is not returned, if own module, then return its prefix
* @code
* char *ns = NULL;
@ -1515,11 +1541,12 @@ yang_choice(yang_stmt *y)
}
/*! Find matching y in yp:s children, "yang order" of y when y is choice
*
* @param[in] yp Choice node
* @param[in] y Yang datanode to find
* @param[out] index Index of y in yp:s list of children
* @retval 0 not found (must be datanode)
* @retval 1 found
* @retval 0 not found (must be datanode)
* @see order1 the main function
* There are two distinct cases, either (1) the choice has case statements, or
* (2) it uses shortcut mode without case statements.
@ -1571,6 +1598,7 @@ yang_order1_choice(yang_stmt *yp,
}
/*! Find matching y in yp:s children, return "yang order" of y or -1 if not found
*
* @param[in] yp Parent
* @param[in] y Yang datanode to find
* @param[out] index Index of y in yp:s list of children
@ -1609,6 +1637,7 @@ yang_order1(yang_stmt *yp,
}
/*! Return order of yang statement y in parents child vector
*
* @param[in] y Find position of this data-node
* @param[out] index Index of y in yp:s list of children
* @retval >=0 Order of child with specified argument
@ -1664,6 +1693,7 @@ yang_order(yang_stmt *y)
}
/*! Map from YANG keywords ints to strings
*
* @param[in] int Integer representation of YANG keywords
* @retval str String representation of YANG keywords
*/
@ -1674,6 +1704,7 @@ yang_key2str(int keyword)
}
/*! Map from yang keyword strings to ints
*
* @param[in] str String representation of YANG keywords
* @retval int Integer representation of YANG keywords
*/
@ -1684,6 +1715,7 @@ yang_str2key(char *str)
}
/*! Find top data node among all modules by namespace in xml tree
*
* @param[in] yspec Yang specification
* @param[in] xt XML node
* @param[out] ymod Yang module (NULL if not found)
@ -1722,6 +1754,7 @@ ys_module_by_xml(yang_stmt *yspec,
}
/*! Find the top module or sub-module given a statement from within a yang tree
*
* Ultimate top is yang spec, dont return that
* The routine recursively finds ancestors.
* @param[in] ys Any yang statement in a yang tree
@ -1757,6 +1790,7 @@ ys_module(yang_stmt *ys)
}
/*! Find real top module given a statement in a yang tree
*
* With "real" top module means that if sub-module is the top-node,
* the module that the sub-module belongs-to is found recursively
* @param[in] ys Any yang statement in a yang tree
@ -1807,6 +1841,7 @@ ys_real_module(yang_stmt *ys,
}
/*! Find top of tree, the yang specification from within the tree
*
* @param[in] ys Any yang statement in a yang tree
* @retval yspec The top yang specification
* @see ys_module
@ -1826,7 +1861,8 @@ ys_spec(yang_stmt *ys)
return (yang_stmt*)ys;
}
/*! 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
quotedstring(char *s)
{
@ -1840,6 +1876,7 @@ quotedstring(char *s)
}
/*! Print yang specification to file
*
* @param[in] f File to print to.
* @param[in] yn Yang node to print
* @param[in] fn Callback to make print function
@ -1870,6 +1907,7 @@ yang_print_cb(FILE *f,
}
/*! Print yang specification to file
*
* @param[in] f File to print to.
* @param[in] yn Yang node to print
* @see yang_print_cbuf
@ -1882,6 +1920,7 @@ yang_print(FILE *f,
}
/*! Print yang top-level modules only
*
* @param[in] f File to print to.
* @param[in] yn Yang node to print
* @see yang_print_cbuf
@ -1944,6 +1983,7 @@ yang_spec_dump(yang_stmt *yspec,
}
/*! Print yang specification to cligen buf
*
* @param[in] cb Cligen buffer. This is where the pretty print is.
* @param[in] yn Yang node to print
* @param[in] marginal Tab indentation, mainly for recursion.
@ -2266,6 +2306,7 @@ ys_populate_leaf(clicon_handle h,
}
/*! Populate list yang statement
*
* @param[in] h Clicon handle
* @param[in] ys The yang statement (type) to populate.
*/
@ -2286,6 +2327,7 @@ ys_populate_list(clicon_handle h,
}
/*! Set range or length boundary for built-in yang types
*
* Help functions to range and length statements
*/
static int
@ -2459,6 +2501,7 @@ ys_populate_length(clicon_handle h,
}
/*! Sanity check yang type statement
*
* XXX: Replace with generic parent/child type-check
* @param[in] h Clicon handle
* @param[in] ys The yang statement (type) to populate.
@ -2582,8 +2625,8 @@ ys_populate_identity(clicon_handle h,
* @param[in] yspec yang specification
* @param[in] module Name of module
* @param[in] feature Name of feature
* @retval 0 Not found or not set
* @retval 1 Found and set
* @retval 0 Not found or not set
* XXX: should the in-param be h, ymod, or yspec?
*/
int
@ -2671,6 +2714,7 @@ ys_populate_feature(clicon_handle h,
}
/*! Populate the unique statement with a cvec
*
* @param[in] h Clicon handle
* @param[in] ys The yang statement (unique) to populate.
*/
@ -2774,11 +2818,11 @@ ys_populate_unknown(clicon_handle h,
}
/*! Populate modules / submodules
* @param[in] h Clicon handle
* @param[in] ys The yang statement (module/submodule) to populate.
*
* Check RFC 7950: 7.1.4: All prefixes, including the prefix for the module itself,
* MUST be unique within the module or submodule.
* @param[in] h Clicon handle
* @param[in] ys The yang statement (module/submodule) to populate.
*/
static int
ys_populate_module_submodule(clicon_handle h,
@ -2888,6 +2932,7 @@ ys_populate(yang_stmt *ys,
}
/*! Run after grouping expand and augment
*
* @see ys_populate run before grouping expand and augment
*/
int
@ -2918,11 +2963,12 @@ ys_populate2(yang_stmt *ys,
}
/*! Find feature and if-feature nodes, check features and remove disabled nodes
*
* @param[in] h Clixon handle
* @param[in] yt Yang statement
* @retval -1 Error
* @retval 0 Feature not enabled: remove yt
* @retval 1 OK
* @retval 0 Feature not enabled: remove yt
* @retval -1 Error
* @note On return 0 the over-lying function need to remove yt from its parent
* @note cannot use yang_apply here since child-list is modified (destructive)
* @note if-features is parsed in full context here, previous restricted pass in ys_parse_sub
@ -3004,9 +3050,9 @@ yang_features(clicon_handle h,
* @param[in] fn Callback
* @param[in] depth Depth argument: where to start. If <=0 call the calling node yn, if 1 start with its children, etc
* @param[in] arg Argument
* @retval -1 Error, aborted at first error encounter
* @retval 0 OK, all nodes traversed
* @retval n OK, aborted at first encounter of first match
* @retval 0 OK, all nodes traversed
* @retval -1 Error, aborted at first error encounter
* @code
* int ys_fn(yang_stmt *ys, void *arg)
* {
@ -3053,6 +3099,7 @@ yang_apply(yang_stmt *yn,
}
/*! Check if a node is a yang "data node"
*
* @param[in] ys Yang statement node
* @retval 0 Yang node is NOT a data node
* @retval !=0 Yang node IS a data noed
@ -3082,8 +3129,8 @@ yang_datanode(yang_stmt *ys)
* @param[in] cvv Schema-node path encoded as a name/value pair list.
* @param[in] nsc Namespace context from yang for the prefixes (names) of cvv
* @param[out] yres Result yang statement node, or NULL if not found
* @retval -1 Error, with clicon_err called
* @retval 0 OK
* @retval -1 Error, with clicon_err called
* A schema node identifier consists of a path of identifiers, separated by slashes ("/").
* References to identifiers defined in external modules MUST be
* qualified with appropriate prefixes, and references to identifiers
@ -3162,11 +3209,12 @@ schema_nodeid_iterate(yang_stmt *yn,
}
/*! Given an absolute schema-nodeid (eg /a/b/c) find matching yang spec
*
* @param[in] yn Original yang stmt (where call is made)
* @param[in] schema_nodeid Absolute schema-node-id, ie /a/b
* @param[out] yres Result yang statement node, or NULL if not found
* @retval -1 Error, with clicon_err called
* @retval 0 OK , with result in yres
* @retval -1 Error, with clicon_err called
* Assume schema nodeid:s have prefixes, (actually the first).
* @see RFC7950 6.5
* o schema node: A node in the schema tree. One of action, container,
@ -3255,6 +3303,7 @@ yang_abs_schema_nodeid(yang_stmt *yn,
}
/*! Given a descendant schema-nodeid (eg a/b/c) find matching yang spec
*
* @param[in] yn Yang node (must be part of yspec tree, cannot be "dangling")
* @param[in] schema_nodeid Descendant schema-node-id, ie a/b
* @param[in] keyword A schemode of this type, or -1 if any
@ -3329,9 +3378,10 @@ yang_desc_schema_nodeid(yang_stmt *yn,
}
/*! Return config state of this node
*
* @param[in] ys Yang statement
* @retval 0 If node has a config sub-statement and it is false
* @retval 1 If node has not config sub-statement or it is true
* @retval 0 If node has a config sub-statement and it is false
* @see yang_config_ancestor which also takes ancestors into account, which you should normally do.
*/
int
@ -3351,8 +3401,8 @@ yang_config(yang_stmt *ys)
*
* config statement is default true.
* @param[in] ys Yang statement
* @retval 0 Node or one of its ancestor has config false or is RPC or notification
* @retval 1 Neither node nor any of its ancestors has config false
* @retval 0 Node or one of its ancestor has config false or is RPC or notification
*/
int
yang_config_ancestor(yang_stmt *ys)
@ -3391,8 +3441,8 @@ yang_config_ancestor(yang_stmt *ys)
*
* @param[in] ys Yang statement
* @param[in] delimiter Delimiter character (eg ' ' or ',')
* @retval NULL Error
* @retval cvec Vector of strings. Free with cvec_free()
* @retval NULL Error
* @code
* cvec *cvv;
* cg_var *cv = NULL;
@ -3442,10 +3492,9 @@ yang_arg2cvec(yang_stmt *ys,
* @param[in] yn Yang list node with sub-statements (look for a key child)
* @param[in] name Check if this name (eg "b") is a key in the yang key statement
* @param[out] lastkey If 1 this is the last key in a multi-key list
*
* @retval -1 Error
* @retval 0 No match
* @retval 1 Yes match
* @retval 0 No match
* @retval -1 Error
*/
int
yang_key_match(yang_stmt *yn,
@ -3487,6 +3536,7 @@ yang_key_match(yang_stmt *yn,
}
/*! Set type cache for yang type
*
* @param[in] rxmode Kludge to know which regexp engine is used
* @see yang_type_cache_regexp_set where cache is extended w compiled regexps
*/
@ -3530,6 +3580,7 @@ yang_type_cache_set(yang_stmt *ys,
}
/*! Extend yang type cache with compiled regexps
*
* Compiled Regexps are computed in validate code - after initial cache set
* @param[in] regexps
*/
@ -3556,10 +3607,11 @@ yang_type_cache_regexp_set(yang_stmt *ytype,
}
/*! Get individual fields (direct/destructively) from yang type cache.
*
* @param[out] patterns Initialized cvec of regexp patterns strings
* @retval -1 Error
* @retval 0 No cache
* @retval 1 OK
* @retval 0 No cache
* @retval -1 Error
*/
int
yang_type_cache_get(yang_stmt *ytype,
@ -3844,6 +3896,7 @@ yang_init(clicon_handle h)
#ifdef XML_EXPLICIT_INDEX
/*! Mark element as search_index in list
*
* @retval 0 OK
* @retval -1 Error
*/
@ -3910,8 +3963,8 @@ yang_search_index_extension(clicon_handle h,
* 3) no other data node children
* @param[in] ys Yang node
* @param[in] subkeyw Expected keyword of single child (typically Y_LIST)
* @retval 0 No, node does not have single child of specified type
* @retval 1 Yes, node has single child of specified type
* @retval 0 No, node does not have single child of specified type
* @see https://github.com/openconfig/ygot/blob/master/docs/design.md#openconfig-path-compression 2nd clause
*/
int
@ -3951,6 +4004,7 @@ yang_single_child_type(yang_stmt *ys,
}
/*! Get action callback list
*
* XXX rc shouldnt really be void* but the type definitions in .h file got complicated
*/
void *
@ -3960,6 +4014,7 @@ yang_action_cb_get(yang_stmt *ys)
}
/*! Add an action callback to YANG node
*
* XXX rc shouldnt really be void* but the type definitions in .h file got complicated
*/
int

View file

@ -148,6 +148,7 @@ ys_grouping_module_resolve(yang_stmt *ymod,
}
/*! Resolve a grouping name from a point in the yang tree
*
* @param[in] ys Yang statement of "uses" statement doing the lookup
* @param[in] prefix Prefix of grouping to look for
* @param[in] name Name of grouping to look for
@ -409,6 +410,7 @@ yang_augment_module(clicon_handle h,
}
/*! Given a refine node, perform the refinement action on the target refine node
*
* The RFC is somewhat complicate in the rules for refine.
* Most nodes will be replaced, but some are added
* @param[in] yr Refine node
@ -477,6 +479,7 @@ ys_do_refine(yang_stmt *yr,
}
/*! Check if Yang node y is a leaf in yang node list yp
*
* Could be made to a generic function used elsewhere as well
* @param[in] y Yang leaf
* @param[in] yp Yang list parent
@ -507,8 +510,10 @@ ys_iskey(yang_stmt *y,
}
/*! Helper function to yang_expand_grouping
*
* @param[in] yn Yang parent node of uses ststement
* @param[in] ys Uses statement
* @param[in] i
* @retval 0 OK
* @retval -1 Error
*/
@ -555,12 +560,12 @@ yang_expand_uses_node(yang_stmt *yn,
goto done;
}
} while((yp = yang_parent_get(yp)) != NULL);
if (yang_flag_get(ygrouping, YANG_FLAG_MARK) == 0){
if (yang_flag_get(ygrouping, YANG_FLAG_GROUPING) == 0){
/* Check mark flag to see if this grouping has been expanded before,
* here below in the traverse section
* A mark could be completely normal (several uses) or it could be a recursion.
*/
yang_flag_set(ygrouping, YANG_FLAG_MARK); /* Mark as (being) expanded */
yang_flag_set(ygrouping, YANG_FLAG_GROUPING); /* Mark as (being) expanded */
if (yang_expand_grouping(ygrouping) < 0)
goto done;
}
@ -584,18 +589,22 @@ yang_expand_uses_node(yang_stmt *yn,
* yn is parent: the children of ygrouping replaces ys.
* Is there a case when glen == 0? YES AND THIS BREAKS
*/
if (glen != 1){
if (glen > 0){
int oldbuflen = yn->ys_len;
/* size of existing elements up from i+1 (not uses-stmt) */
size = (yang_len_get(yn) - i - 1)*sizeof(struct yang_stmt *);
yn->ys_len += glen - 1;
if (glen && (yn->ys_stmt = realloc(yn->ys_stmt, (yang_len_get(yn))*sizeof(yang_stmt *))) == 0){
yn->ys_len += glen;
if ((yn->ys_stmt = realloc(yn->ys_stmt, (yang_len_get(yn))*sizeof(yang_stmt *))) == 0){
clicon_err(OE_YANG, errno, "realloc");
goto done;
}
/* Then move all existing elements up from i+1 (not uses-stmt) */
/* Here, glen last elements are not initialized.
* Zeroed here but will be assigned later in the "j" loop below
*/
memset(&yn->ys_stmt[oldbuflen], 0, glen*sizeof(yang_stmt *));
/* Move existing elements if any */
if (size)
memmove(&yn->ys_stmt[i+glen],
&yn->ys_stmt[i+1],
size);
memmove(&yn->ys_stmt[i+glen+1], &yn->ys_stmt[i+1], size);
}
/* Find when statement, if present */
if ((ywhen = yang_find(ys, Y_WHEN, NULL)) != NULL){
@ -604,6 +613,7 @@ yang_expand_uses_node(yang_stmt *yn,
goto done;
}
/* Note: yang_desc_schema_nodeid() requires ygrouping2 to be in yspec tree,
* due to correct module prefixes etc.
* cannot be dangling, insert into tree here and then prune immediately after while loop
*/
if (yn_insert(yang_parent_get(ygrouping), ygrouping2) < 0)
@ -667,16 +677,13 @@ yang_expand_uses_node(yang_stmt *yn,
/* This is for extensions that allow list keys to be optional, see restconf_main_extension_cb */
if (yang_flag_get(ys, YANG_FLAG_NOKEY))
yang_flag_set(yg, YANG_FLAG_NOKEY);
yn->ys_stmt[i+k] = yg;
yn->ys_stmt[i+k+1] = yg;
yg->ys_parent = yn;
k++;
}
/* Remove 'uses' node */
ys_free(ys);
/* Remove the grouping copy */
ygrouping2->ys_len = 0; /* Cant do with get access function */
ys_free(ygrouping2);
retval = 0;
done:
if (wnsc)
@ -689,8 +696,8 @@ yang_expand_uses_node(yang_stmt *yn,
}
/*! Macro expansion of grouping/uses done in step 2 of yang parsing
* RFC7950:
* Identifiers appearing inside the grouping are resolved
*
* RFC7950: Identifiers appearing inside the grouping are resolved
* relative to the scope in which the grouping is defined, not where it is
* used. Prefix mappings, type names, grouping names, and extension usage are
* evaluated in the hierarchy where the "grouping" statement appears.
@ -715,29 +722,35 @@ yang_expand_grouping(yang_stmt *yn)
ys = yn->ys_stmt[i];
switch (yang_keyword_get(ys)){
case Y_USES:
if (yang_flag_get(ys, YANG_FLAG_GROUPING) == 0){
if (yang_expand_uses_node(yn, ys, i) < 0)
goto done;
break; /* Note same child is re-iterated since it may be changed */
yang_flag_set(ys, YANG_FLAG_GROUPING);
}
break;
default:
i++;
break;
}
i++;
}
/* Second pass since length may have changed */
for (i=0; i<yang_len_get(yn); i++){
ys = yn->ys_stmt[i];
if (yang_keyword_get(ys) == Y_GROUPING){
/* Check mark flag to see if this grouping has been expanded before, here or in the
* 'uses' section
/* This is for expanding uses under groupings in place, not after expansio n
* Check mark flag to see if this grouping has been expanded before, here or in the
* 'uses' section.
* A mark could be completely normal (several uses) or it could be a recursion.
*/
if (yang_flag_get(ys, YANG_FLAG_MARK) == 0){
yang_flag_set(ys, YANG_FLAG_MARK); /* Mark as (being) expanded */
if (yang_flag_get(ys, YANG_FLAG_GROUPING) == 0){
yang_flag_set(ys, YANG_FLAG_GROUPING); /* Mark as (being) expanded */
if (yang_expand_grouping(ys) < 0)
goto done;
}
}
else{
else
{
if (yang_expand_grouping(ys) < 0)
goto done;
}
@ -811,6 +824,7 @@ yang_parse_str(char *str,
}
/*! Parse yang spec from an open file descriptor
*
* @param[in] fd File descriptor containing the YANG file as ASCII characters
* @param[in] name For debug, eg filename
* @param[in] yspec Yang specification. Should have been created by caller using yspec_new
@ -863,6 +877,7 @@ yang_parse_file(FILE *fp,
}
/*! Given a yang filename, extract the revision as an integer as YYYYMMDD
*
* @param[in] filename Filename on the form: name [+ @rev ] + .yang
* @param[out] basep "Base" filename, stripped: [+ @rev ] + .yang (malloced)
* @param[out] revp Revision as YYYYMMDD (0 if not found)
@ -901,6 +916,7 @@ filename2revision(const char *filename,
}
/*! No specific revision give. Match a yang file given module
*
* @param[in] h CLICON handle
* @param[in] module Name of main YANG module.
* @param[in] revision Revision or NULL
@ -1213,71 +1229,8 @@ yang_parse_recurse(clicon_handle h,
return retval; /* top-level (sub)module */
}
/*!
* @param[in] ys Yang statement
* @param[in] dummy Necessary for called in yang_apply
* @see yang_applyfn_t
*/
static int
ys_schemanode_check(yang_stmt *ys,
void *dummy)
{
int retval = -1;
yang_stmt *yres = NULL;
yang_stmt *yp;
char *arg;
enum rfc_6020 keyword;
char **vec = NULL;
char *v;
int nvec;
int i;
yp = yang_parent_get(ys);
arg = yang_argument_get(ys);
keyword = yang_keyword_get(ys);
switch (yang_keyword_get(ys)){
case Y_AUGMENT:
if (yang_keyword_get(yp) == Y_MODULE || /* Not top-level */
yang_keyword_get(yp) == Y_SUBMODULE)
break;
/* fallthru */
case Y_REFINE:
if (yang_desc_schema_nodeid(yp, arg, &yres) < 0)
goto done;
if (yres == NULL){
clicon_err(OE_YANG, 0, "schemanode sanity check of %s %s",
yang_key2str(keyword), arg);
goto done;
}
break;
case Y_UNIQUE:{
/* Unique: Sec 7.8.3 It takes as an argument a string that contains a space-
separated list of schema node identifiers */
if ((vec = clicon_strsep(arg, " \t\n", &nvec)) == NULL)
goto done;
for (i=0; i<nvec; i++){
v = vec[i];
if (yang_desc_schema_nodeid(yp, v, &yres) < 0)
goto done;
if (yres == NULL){
clicon_err(OE_YANG, 0, "schemanode sanity check of %s %s",
yang_key2str(yang_keyword_get(ys)), v);
goto done;
}
}
break;
}
default:
break;
}
retval = 0;
done:
if (vec)
free(vec);
return retval;
}
/*! Check lists: config lists MUST have keys
*
* @param[in] h Clicon handle
* @param[in] ys Yang statement
* Verify the following rule:
@ -1333,6 +1286,7 @@ ys_list_check(clicon_handle h,
}
/*! Depth-first topological sort
*
* Topological sort of a DAG
* @param[in] yn Yang module node
* @param[out] ylist Result list of sorted nodes with "least significant" first
@ -1402,6 +1356,7 @@ ys_visit(struct yang_stmt *yn,
}
/*! Sort module/submodules according to import/include order and cycle detect
*
* Topological sort of a DAG
* @param[in] yspec Yang specification.
* @param[in] modmin Start of interval of yspec:s module children
@ -1421,7 +1376,6 @@ yang_sort_modules(yang_stmt *yspec,
int i;
struct yang_stmt *yn;
for (i=modmin; i<modmax; i++){
yn = yang_child_i(yspec, i);
/* select an unmarked node n */
@ -1518,13 +1472,15 @@ yang_parse_post(clicon_handle h,
* single tree as they are used.
*/
/* 6: Macro expansion of all grouping/uses pairs. Expansion needs marking */
/* 6: Macro expansion of all uses/grouping pairs.
* All uses expansion is made "in-place", ie not after expansion.
* Exanded nodes are marked with "GROUPING" flag
* This alters the original YANG: after this all YANG uses have been expanded
*/
for (i=0; i<ylen; i++){
if (yang_expand_grouping(ylist[i]) < 0)
goto done;
yang_apply(ylist[i], -1, (yang_applyfn_t*)yang_flag_reset, 1, (void*)YANG_FLAG_MARK);
}
/* 7: Top-level augmentation of all modules.
* Note: Clixon does not implement augment in USES
* Note: There is an ordering problem, where an augment in one module depends on an augment in
@ -1552,9 +1508,6 @@ yang_parse_post(clicon_handle h,
/* 10: sanity checks of expanded yangs need more here */
for (i=0; i<ylen; i++){
/* Check schemanode references */
if (yang_apply(ylist[i], -1, ys_schemanode_check, 1, NULL) < 0)
goto done;
/* Check list key values */
if (ys_list_check(h, ylist[i]) < 0)
goto done;
@ -1571,6 +1524,7 @@ yang_parse_post(clicon_handle h,
}
/*! Parse yang specification and its dependencies recursively given module
*
* @param[in] h clicon handle
* @param[in] module Module name, or absolute filename (including dir)
* @param[in] revision Revision, or NULL
@ -1616,6 +1570,7 @@ yang_spec_parse_module(clicon_handle h,
}
/*! Parse yang specification and its dependencies recursively given filename
*
* @param[in] h clicon handle
* @param[in] filename Actual filename (including dir and revision)
* @param[in] yspec Modules parse are added to this yangspec
@ -1662,6 +1617,7 @@ yang_spec_parse_file(clicon_handle h,
}
/*! Load all yang modules in directory
*
* @param[in] h Clicon handle
* @param[in] dir Load all yang modules in this directory
* @param[in] yspec Modules parse are added to this yangspec
@ -1791,6 +1747,7 @@ yang_spec_load_dir(clicon_handle h,
}
/*! parse yang date-arg string and return a uint32 useful for arithmetics
*
* @param[in] datearg yang revision string as "YYYY-MM-DD"
* @param[out] dateint Integer version as YYYYMMDD
* @retval 0 OK