diff --git a/CHANGELOG.md b/CHANGELOG.md index f149f1d5..c653a47b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -43,7 +43,7 @@ Developers may need to change their code * New `yn_iter()` yang iterator replaces `yn_each()` * Use an integer iteratorinstead of yang object * Replace `y1 = NULL; y1 = yn_each(y0, y1)` with `int inext = 0; yn_iter(y0, &inext)` -* Add `keyw`argument to `yang_stats()` +* Add `keyw` argument to `yang_stats()` ### Corrected Busg diff --git a/apps/cli/cli_main.c b/apps/cli/cli_main.c index e447cf97..2148e48c 100644 --- a/apps/cli/cli_main.c +++ b/apps/cli/cli_main.c @@ -521,7 +521,7 @@ usage(clixon_handle h, "\t-h \t\tHelp\n" "\t-V \t\tPrint version and exit\n" "\t-D \tDebug level (see available levels below)\n" - "\t-f \tConfig-file (mandatory)\n" + "\t-f \tConfig-file\n" "\t-E \tExtra configuration file directory\n" "\t-l > \tLog on (s)yslog, std(e)rr, std(o)ut, (n)one or (f)ile (stderr is default)\n" "\t-C \tDump configuration options on stdout after loading. Format is xml|json|text\n" diff --git a/include/clixon_custom.h b/include/clixon_custom.h index 92fc21b7..2c614978 100644 --- a/include/clixon_custom.h +++ b/include/clixon_custom.h @@ -204,3 +204,9 @@ * If not set, reduces memory with 8 bytes per yang-stmt. */ #undef YANG_SPEC_LINENR + +/*! Use ref origin pointer to skip as many derived yang nodes as possible + * + * If set, do not copy some YANG nodes to derived trees (ie augmented or grouped trees) + */ +#define YANG_ORIG_PTR_SKIP diff --git a/lib/clixon/clixon_yang.h b/lib/clixon/clixon_yang.h index bc4ac96c..c4680c14 100644 --- a/lib/clixon/clixon_yang.h +++ b/lib/clixon/clixon_yang.h @@ -90,9 +90,8 @@ * Set by yang_mount_set * Read by ys_free1 */ -#define YANG_FLAG_EXTENDED 0x400 /* Use extended struct to access uncommon fields - * Memory optimization - */ +#define YANG_FLAG_WHEN 0x400 /* Use extended struct to access when-info for + * augment/grouping */ /* * Types @@ -240,6 +239,8 @@ yang_stmt *yang_parent_get(yang_stmt *ys); enum rfc_6020 yang_keyword_get(yang_stmt *ys); char *yang_argument_get(yang_stmt *ys); int yang_argument_set(yang_stmt *ys, char *arg); +yang_stmt *yang_orig_get(yang_stmt *ys); +int yang_orig_set(yang_stmt *ys, yang_stmt *y0); cg_var *yang_cv_get(yang_stmt *ys); int yang_cv_set(yang_stmt *ys, cg_var *cv); cvec *yang_cvec_get(yang_stmt *ys); @@ -271,7 +272,6 @@ int yang_stats(yang_stmt *y, enum rfc_6020 keyw, uint64_t *nrp, size_t *s /* Other functions */ yang_stmt *yspec_new(void); yang_stmt *ys_new(enum rfc_6020 keyw); -yang_stmt *yse_new(enum rfc_6020 keyw); yang_stmt *ys_prune(yang_stmt *yp, int i); int ys_prune_self(yang_stmt *ys); int ys_free1(yang_stmt *ys, int self); diff --git a/lib/clixon/clixon_yang_parse_lib.h b/lib/clixon/clixon_yang_parse_lib.h index 3b7de9b9..25a31ff2 100644 --- a/lib/clixon/clixon_yang_parse_lib.h +++ b/lib/clixon/clixon_yang_parse_lib.h @@ -57,6 +57,7 @@ int yang_file_find_match(clixon_handle h, const char *module, const char yang_stmt *yang_parse_filename(clixon_handle h, const char *filename, yang_stmt *ysp); yang_stmt *yang_parse_module(clixon_handle h, const char *module, const char *revision, yang_stmt *yspec, char *origname); int yang_parse_post(clixon_handle h, yang_stmt *yspec, int modmin); +int yang_parse_optimize_uses(clixon_handle h, yang_stmt *yspec); int yang_spec_parse_module(clixon_handle h, const char *module, const char *revision, yang_stmt *yspec); yang_stmt *yang_parse_str(char *str, const char *name, yang_stmt *yspec); diff --git a/lib/src/clixon_validate_minmax.c b/lib/src/clixon_validate_minmax.c index 3904a998..5958761f 100644 --- a/lib/src/clixon_validate_minmax.c +++ b/lib/src/clixon_validate_minmax.c @@ -796,16 +796,10 @@ xml_yang_validate_minmax(cxobj *xt, goto fail; if (presence && keyw == Y_CONTAINER && yang_find(y, Y_PRESENCE, NULL) == NULL){ - yang_stmt *yc; - int inext; - - inext = 0; - while ((yc = yn_iter(y, &inext)) != NULL) { - if ((ret = xml_yang_validate_minmax(x, presence, xret)) < 0) - goto done; - if (ret == 0) - goto fail; - } + if ((ret = xml_yang_validate_minmax(x, presence, xret)) < 0) + goto done; + if (ret == 0) + goto fail; } yprev = y; } diff --git a/lib/src/clixon_yang.c b/lib/src/clixon_yang.c index 785534fa..0c6810ec 100644 --- a/lib/src/clixon_yang.c +++ b/lib/src/clixon_yang.c @@ -86,7 +86,7 @@ #include "clixon_yang_cardinality.h" #include "clixon_yang_type.h" #include "clixon_yang_schema_mount.h" -#include "clixon_yang_internal.h" /* internal included by this file only, not API*/ +#include "clixon_yang_internal.h" /* internal included by this file only, not API */ #ifdef XML_EXPLICIT_INDEX static int yang_search_index_extension(clixon_handle h, yang_stmt *yext, yang_stmt *ys); @@ -255,6 +255,41 @@ yang_argument_set(yang_stmt *ys, return 0; } +/*! Get original back-pointer if node is grouping or augmented + * + * Defined only if this statement was created as part of a uses/grouping or augment expansion + * @param[in] ys Yang statement node + * @retval y0 Original yang statement node + * @retval NULL Not part of grouping + */ +yang_stmt * +yang_orig_get(yang_stmt *ys) +{ + if (ys->ys_orig) + assert(ys->ys_orig->ys_orig == NULL); + return ys->ys_orig; +} + +/*! Set original back-pointer if any + * + * Will recursively evaluate to set to original node in case of chain of groupings + * @param[in] ys Yang statement node + * @param[in] y0 Original yang statement node + * @retval NULL Not part of grouping + */ +int +yang_orig_set(yang_stmt *ys, + yang_stmt *y0) +{ + if (y0->ys_orig){ + assert(y0->ys_orig->ys_orig == NULL); + yang_orig_set(ys, y0->ys_orig); + } + else + ys->ys_orig = y0; + return 0; +} + /*! Get yang statement CLIgen variable * * See comment under ys_cv for how this is used @@ -449,7 +484,7 @@ yang_when_xpath_get(yang_stmt *ys) { yang_stmt_extended *yse = (yang_stmt_extended *)ys; - if ((ys->ys_flags & YANG_FLAG_EXTENDED) == 0x0) + if ((ys->ys_flags & YANG_FLAG_WHEN) == 0x0) return NULL; else return yse->yse_when_xpath; @@ -475,8 +510,8 @@ yang_when_xpath_set(yang_stmt *ys, clixon_err(OE_YANG, EINVAL, "xpath is NULL"); goto done; } - if ((ys->ys_flags & YANG_FLAG_EXTENDED) == 0x0){ - clixon_err(OE_YANG, EINVAL, "Yang node %s %s must have flag YANG_FLAG_EXTENDED for this operation", + if ((ys->ys_flags & YANG_FLAG_WHEN) == 0x0){ + clixon_err(OE_YANG, EINVAL, "Yang node %s %s must have flag YANG_FLAG_WHEN for this operation", yang_key2str(ys->ys_keyword), ys->ys_argument); goto done; } @@ -502,7 +537,7 @@ yang_when_nsc_get(yang_stmt *ys) { yang_stmt_extended *yse = (yang_stmt_extended *)ys; - if ((ys->ys_flags & YANG_FLAG_EXTENDED) == 0x0) + if ((ys->ys_flags & YANG_FLAG_WHEN) == 0x0) return NULL; else return yse->yse_when_nsc; @@ -524,8 +559,8 @@ yang_when_nsc_set(yang_stmt *ys, int retval = -1; yang_stmt_extended *yse = (yang_stmt_extended *)ys; - if ((ys->ys_flags & YANG_FLAG_EXTENDED) == 0x0){ - clixon_err(OE_YANG, EINVAL, "Yang node %s %s must have flag YANG_FLAG_EXTENDED for this operation", + if ((ys->ys_flags & YANG_FLAG_WHEN) == 0x0){ + clixon_err(OE_YANG, EINVAL, "Yang node %s %s must have flag YANG_FLAG_WHEN for this operation", yang_key2str(ys->ys_keyword), ys->ys_argument); return -1; } @@ -609,7 +644,6 @@ yang_linenum_set(yang_stmt *ys, void * yang_typecache_get(yang_stmt *ys) { - // assert(ys->ys_keyword == Y_TYPE); return ys->ys_typecache; } @@ -623,7 +657,6 @@ int yang_typecache_set(yang_stmt *ys, void *ycache) { - // assert(ys->ys_keyword == Y_TYPE); ys->ys_typecache = ycache; return 0; } @@ -637,12 +670,7 @@ yang_typecache_set(yang_stmt *ys, yang_stmt* yang_mymodule_get(yang_stmt *ys) { - yang_stmt_extended *yse = (yang_stmt_extended *)ys; - - if ((ys->ys_flags & YANG_FLAG_EXTENDED) == 0x0) - return NULL; - else - return yse->yse_mymodule; + return ys->ys_mymodule; } /*! Set mymodule @@ -651,19 +679,13 @@ yang_mymodule_get(yang_stmt *ys) * @param[in] ys YANG statement * @param[in] ymod YANG module * @retval 0 OK + * @retval -1 Error */ int yang_mymodule_set(yang_stmt *ys, yang_stmt *ym) { - yang_stmt_extended *yse = (yang_stmt_extended *)ys; - - if ((ys->ys_flags & YANG_FLAG_EXTENDED) == 0x0){ - clixon_err(OE_YANG, EINVAL, "Yang node %s %s must have flag YANG_FLAG_EXTENDED for this operation", - yang_key2str(ys->ys_keyword), ys->ys_argument); - return -1; - } - yse->yse_mymodule = ym; + ys->ys_mymodule = ym; return 0; } @@ -698,7 +720,7 @@ yang_stats_one(yang_stmt *ys, size_t sz = 0; yang_type_cache *yc; - if (yang_flag_get(ys, YANG_FLAG_EXTENDED) == 0x0) + if (yang_flag_get(ys, YANG_FLAG_WHEN) == 0x0) sz += sizeof(struct yang_stmt_extended); else sz += sizeof(struct yang_stmt); @@ -707,7 +729,7 @@ yang_stats_one(yang_stmt *ys, sz += strlen(ys->ys_argument) + 1; if (ys->ys_cvec) sz += cvec_size(ys->ys_cvec); - if (yang_flag_get(ys, YANG_FLAG_EXTENDED) != 0x0) { + if (yang_flag_get(ys, YANG_FLAG_WHEN) != 0x0) { yang_stmt_extended *yse = (yang_stmt_extended *)ys; if (yse->yse_when_xpath) sz += strlen(yse->yse_when_xpath) + 1; @@ -837,18 +859,7 @@ ys_new_sz(enum rfc_6020 keyw, yang_stmt * ys_new(enum rfc_6020 keyw) { - size_t sz; - yang_stmt *ys; - - if (keyw == Y_UNKNOWN) - sz = sizeof(struct yang_stmt_extended); - else - sz = sizeof(*ys); - if ((ys = ys_new_sz(keyw, sz)) != NULL && - keyw == Y_UNKNOWN){ - yang_flag_set(ys, YANG_FLAG_EXTENDED); - } - return ys; + return ys_new_sz(keyw, sizeof(struct yang_stmt)); } /*! Create new extended yang node/statement @@ -857,13 +868,13 @@ ys_new(enum rfc_6020 keyw) * @retval ys New yang-stmt. Free with ys_free() * @retval NULL Error */ -yang_stmt * +static yang_stmt * yse_new(enum rfc_6020 keyw) { yang_stmt *ys; if ((ys = ys_new_sz(keyw, sizeof(struct yang_stmt_extended))) != NULL) - yang_flag_set(ys, YANG_FLAG_EXTENDED); + yang_flag_set(ys, YANG_FLAG_WHEN); return ys; } @@ -899,7 +910,7 @@ ys_free1(yang_stmt *ys, free(ys->ys_argument); ys->ys_argument = NULL; } - if (yang_flag_get(ys, YANG_FLAG_EXTENDED) != 0x0) { + if (yang_flag_get(ys, YANG_FLAG_WHEN) != 0x0) { yang_stmt_extended *yse = (yang_stmt_extended *)ys; if (yse->yse_when_xpath) free(yse->yse_when_xpath); @@ -1067,22 +1078,77 @@ yn_realloc(yang_stmt *yn) return 0; } +#ifdef YANG_ORIG_PTR_SKIP +/*! Return 1 if yang stmt should be skipped in derived trees + * + * @param[in] keyword YANG keyword + * @retval 1 Yes, use orig-ptr if exists to fetch original object + * @retval 0 No, use existing object + * Comments includes for: + * - nodes that could not be skipped and the failed test + * - nodes that have children in turn + */ +static int +uses_orig_ptr(enum rfc_6020 keyword) +{ + return + // keyword == Y_CONFIG // NO (test_openconfig.sh) + // keyword == Y_DEFAULT // NO (test_augment.sh) + keyword == Y_DESCRIPTION + || keyword == Y_ENUM // children + || keyword == Y_ERROR_APP_TAG + || keyword == Y_ERROR_MESSAGE + || keyword == Y_FRACTION_DIGITS + // || keyword == Y_KEY // NO + || keyword == Y_LENGTH // children + || keyword == Y_MANDATORY + || keyword == Y_MAX_ELEMENTS + || keyword == Y_MIN_ELEMENTS + || keyword == Y_MODIFIER + || keyword == Y_ORDERED_BY + || keyword == Y_PATH + || keyword == Y_PATTERN // children + || keyword == Y_POSITION + || keyword == Y_PREFIX + || keyword == Y_PRESENCE + || keyword == Y_RANGE // children + || keyword == Y_REQUIRE_INSTANCE + || keyword == Y_STATUS + || keyword == Y_UNIQUE + || keyword == Y_UNITS + || keyword == Y_UNKNOWN + || keyword == Y_VALUE + || keyword == Y_YIN_ELEMENT + ; +} +#endif /* YANG_ORIG_PTR_SKIP */ + +/*! Copy single yang statement no children + * + * @param[in] ynew New empty (but created) yang statement (to) + * @param[in] yold Old existing yang statement (from) + * @retval 0 OK + * @retval -1 Error + * @code + * yang_stmt *new = ys_new(Y_LEAF); + * if (ys_cp_one(new, old) < 0) + * err; + * @endcode + * @see ys_cp for recursive copy + */ int ys_cp_one(yang_stmt *ynew, yang_stmt *yold) { - int retval = -1; - char *xpath; - cvec *cvv; - cg_var *cvn; - cg_var *cvo; - size_t sz; + int retval = -1; + cvec *cvv; + cg_var *cvn; + cg_var *cvo; + size_t sz; - if (yang_flag_get(yold, YANG_FLAG_EXTENDED) != 0x0) - sz = sizeof(struct yang_stmt_extended); - else - sz = sizeof(*yold); + sz = sizeof(*yold); memcpy(ynew, yold, sz); + yang_flag_reset(ynew, YANG_FLAG_WHEN); /* Dont inherit WHENs */ ynew->ys_parent = NULL; if (yold->ys_stmt) if ((ynew->ys_stmt = calloc(yold->ys_len, sizeof(yang_stmt *))) == NULL){ @@ -1121,14 +1187,6 @@ ys_cp_one(yang_stmt *ynew, default: break; } - if ((xpath = yang_when_xpath_get(yold)) != NULL){ - if (yang_when_xpath_set(ynew, xpath) < 0) - goto done; - } - if ((cvv = yang_when_nsc_get(yold)) != NULL){ - if (yang_when_nsc_set(ynew, cvv) < 0) - goto done; - } retval = 0; done: return retval; @@ -1153,20 +1211,23 @@ ys_cp(yang_stmt *ynew, { int retval = -1; int i; + int j; yang_stmt *ycn; /* new child */ yang_stmt *yco; /* old child */ if (ys_cp_one(ynew, yold) < 0) goto done; - for (i=0; iys_len; i++){ + for (i=0,j=0; iys_len; i++){ yco = yold->ys_stmt[i]; - if (yang_flag_get(yco, YANG_FLAG_EXTENDED) != 0x0){ - if ((ycn = yse_dup(yco)) == NULL) - goto done; +#ifdef YANG_ORIG_PTR_SKIP + if (uses_orig_ptr(yang_keyword_get(yco))) { + ynew->ys_len--; + continue; } - else if ((ycn = ys_dup(yco)) == NULL) +#endif + if ((ycn = ys_dup(yco)) == NULL) goto done; - ynew->ys_stmt[i] = ycn; + ynew->ys_stmt[j++] = ycn; ycn->ys_parent = ynew; } retval = 0; @@ -1202,18 +1263,37 @@ ys_dup(yang_stmt *old) /*! Create a new extdended yang node and copy the contents recursively from the original. */ yang_stmt * -yse_dup(yang_stmt *old) +yse_dup(yang_stmt *yold) { - yang_stmt *nw; + yang_stmt *ynew; + char *xpath; + cvec *cvv; - if ((nw = yse_new(old->ys_keyword)) == NULL) + if ((ynew = yse_new(yold->ys_keyword)) == NULL) return NULL; - if (ys_cp(nw, old) < 0){ - ys_free(nw); + if (ys_cp(ynew, yold) < 0){ + ys_free(ynew); return NULL; } - yang_flag_set(nw, YANG_FLAG_EXTENDED); - return nw; + yang_flag_set(ynew, YANG_FLAG_WHEN); + if (yang_flag_get(yold, YANG_FLAG_WHEN) != 0x0) { + if ((xpath = yang_when_xpath_get(yold)) != NULL){ + if (yang_when_xpath_set(ynew, xpath) < 0) + goto done; + } + if ((cvv = yang_when_nsc_get(yold)) != NULL){ + if (yang_when_nsc_set(ynew, cvv) < 0) + goto done; + } + } + ok: + return ynew; + done: + if (ynew){ + ys_free(ynew); + ynew = NULL; + } + goto ok; } /*! Replace yold with ynew (insert ynew at the exact place of yold). Keep yold pointer as-is. @@ -1340,7 +1420,14 @@ yang_find(yang_stmt *yn, char *name; yang_stmt *yspec; yang_stmt *ym; - +#ifdef YANG_ORIG_PTR_SKIP + yang_stmt *yorig; + + if ((yorig = yang_orig_get(yn)) != NULL) { + if (uses_orig_ptr(keyword)) + return yang_find(yorig, keyword, argument); + } +#endif for (i=0; iys_len; i++){ ys = yn->ys_stmt[i]; if (keyword == 0 || ys->ys_keyword == keyword){ @@ -1368,7 +1455,6 @@ yang_find(yang_stmt *yn, return yret?yret:yretsub; } - /*! Find child data node with matching argument (container, leaf, list, leaf-list) * * @param[in] yn Yang node, current context node. @@ -2558,7 +2644,6 @@ ys_populate_list(clixon_handle h, if ((ykey = yang_find(ys, Y_KEY, NULL)) == NULL) return 0; - if ((cvv = yang_arg2cvec(ykey, " ")) == NULL) return -1; yang_cvec_set(ys, cvv); @@ -4202,6 +4287,12 @@ yang_sort_subelements(yang_stmt *ys) #endif } +/*! Init yang code + * + * @param[in] h Clixon handle + * @retval 0 OK + * @retval -1 Error + */ int yang_init(clixon_handle h) { diff --git a/lib/src/clixon_yang_internal.h b/lib/src/clixon_yang_internal.h index c335f142..ae72342d 100644 --- a/lib/src/clixon_yang_internal.h +++ b/lib/src/clixon_yang_internal.h @@ -110,17 +110,26 @@ struct yang_stmt { Y_UNIQUE: vector of descendant schema node ids # Y_UNKNOWN: app-dep: yang-mount-points */ - union { /* depends on ys_keyword */ - rpc_callback_t *ysu_action_cb; /* Y_ACTION: Action callback list*/ - char *ysu_filename; /* Y_MODULE/Y_SUBMODULE: For debug/errors: filename */ - yang_type_cache *ysu_typecache; /* Y_TYPE: cache all typedef data except unions */ - int ysu_ref; /* Y_SPEC: Reference count for free: 0 means - * no sharing, 1: two references */ + yang_stmt *ys_mymodule; /* Shortcut to "my" module. Used by: + * 1) Augmented nodes "belong" to the module where the + * augment is declared, which may be different from + * the direct ancestor module + * 2) Unknown nodes "belong" to where the extension is + * declared */ + yang_stmt *ys_orig; /* Pointer to original (for uses/augment copies) */ + union { /* Depends on ys_keyword */ + rpc_callback_t *ysu_action_cb; /* Y_ACTION: Action callback list*/ + char *ysu_filename; /* Y_MODULE/Y_SUBMODULE: For debug/errors: filename */ + yang_type_cache *ysu_typecache; /* Y_TYPE: cache all typedef data except unions */ + int ysu_ref; /* Y_SPEC: Reference count for free: 0 means + * no sharing, 1: two references */ } u; }; /*! An extended yang struct for use of extra fields that consumes more memory * + * See end of struct. The fields that fit here are extended only fot the original object., + * they may not be copied. Currently only tow WHEN fields. * Cannot fit this into the ysu union because keyword is unknown (or at least a set) * @see struct yang_stmt for the original struct * @note First part of this struct MUST resemble yang_stmt fields (in memory). @@ -138,6 +147,13 @@ struct yang_stmt_extended { char *ys_argument; /* String / argument depending on keyword */ cg_var *yse_cv; /* cligen variable. See ys_populate() */ cvec *yse_cvec; /* List of stmt-specific variables */ + yang_stmt *yse_mymodule; /* Shortcut to "my" module. Used by: + * 1) Augmented nodes "belong" to the module where the + * augment is declared, which may be different from + * the direct ancestor module + * 2) Unknown nodes "belong" to where the extension is + * declared */ + yang_stmt *yse_orig; /* Pointer to original (for uses/augment copies) */ union { /* depends on ys_keyword */ rpc_callback_t *ysu_action_cb; /* Y_ACTION: Action callback list*/ char *ysu_filename; /* Y_MODULE/Y_SUBMODULE: For debug/errors: filename */ @@ -145,16 +161,12 @@ struct yang_stmt_extended { int ysu_ref; /* Y_SPEC: Reference count for free: 0 means * no sharing, 1: two references */ } ue; - /* Following fields could be extended only for unknown, grouped and augmented nodes + + /* The following fields are only in extended + * ----------------------------------------- */ char *yse_when_xpath; /* Special conditional for a "when"-associated augment/uses XPath */ cvec *yse_when_nsc; /* Special conditional for a "when"-associated augment/uses namespace ctx */ - yang_stmt *yse_mymodule; /* Shortcut to "my" module. Used by: - * 1) Augmented nodes "belong" to the module where the - * augment is declared, which may be different from - * the direct ancestor module - * 2) Unknown nodes "belong" to where the extension is - * declared */ }; typedef struct yang_stmt_extended yang_stmt_extended; diff --git a/lib/src/clixon_yang_module.c b/lib/src/clixon_yang_module.c index 0108dae2..25dd2f74 100644 --- a/lib/src/clixon_yang_module.c +++ b/lib/src/clixon_yang_module.c @@ -614,7 +614,7 @@ yang_stmt * yang_find_module_by_namespace(yang_stmt *yspec, char *ns) { - yang_stmt *ymod; + yang_stmt *ymod = NULL; int inext; if (ns == NULL) diff --git a/lib/src/clixon_yang_parse_lib.c b/lib/src/clixon_yang_parse_lib.c index ae4c2d1d..2f3178f6 100644 --- a/lib/src/clixon_yang_parse_lib.c +++ b/lib/src/clixon_yang_parse_lib.c @@ -204,6 +204,36 @@ ys_grouping_resolve(yang_stmt *yuses, return retval; } +/*! Recursively add pointer from derived node to original grouping + * + * Cannot use yang_apply since one needs to traverse two trees simultaneously + * @param[in] yp0 Original statement + * @param[in] yp1 Instantiated statement + * @retval 0 Ok + * @retval -1 Error + */ +static int +ys_add_orig_ptr(yang_stmt *yp0, + yang_stmt *yp1) +{ + int retval = -1; + yang_stmt *y0; + yang_stmt *y1; + int inext; + + inext = 0; + while ((y1 = yn_iter(yp1, &inext)) != NULL) { + if ((y0 = yang_find(yp0, yang_keyword_get(y1), yang_argument_get(y1))) == NULL) + continue; + yang_orig_set(y1, y0); + if (ys_add_orig_ptr(y0, y1) < 0) + goto done; + } + retval = 0; + done: + return retval; +} + /*! This is an augment node, augment the original datamodel. * * @param[in] h Clicon handle @@ -233,8 +263,8 @@ yang_augment_node(clixon_handle h, yang_stmt *yc0; yang_stmt *yc; yang_stmt *ymod; - yang_stmt *ywhen; - char *wxpath = NULL; /* xpath of when statement */ + yang_stmt *ywhen = NULL; + char *wxpath; /* xpath of when statement */ cvec *wnsc = NULL; /* namespace context of when statement */ enum rfc_6020 targetkey; enum rfc_6020 childkey; @@ -356,13 +386,27 @@ yang_augment_node(clixon_handle h, default: break; } - if ((yc = yse_dup(yc0)) == NULL) /* Extended */ + /* If expanded by uses / when */ + if (yang_flag_get(yc0, YANG_FLAG_WHEN) != 0x0){ + if ((yc = yse_dup(yc0)) == NULL) + goto done; + } + /* If augment when */ + else if (ywhen) { + if ((yc = yse_dup(yc0)) == NULL) /* Extended */ + goto done; + } + else if ((yc = ys_dup(yc0)) == NULL) goto done; #ifdef YANG_GROUPING_AUGMENT_SKIP /* cornercase: always expand uses under augment */ yang_flag_reset(yc, YANG_FLAG_GROUPING); #endif yang_mymodule_set(yc, ymod); + /* Add backpointer to orig. */ + yang_orig_set(yc, yc0); + if (ys_add_orig_ptr(yc0, yc) < 0) + goto done; if (yn_insert(ytarget, yc) < 0) goto done; /* If there is an associated when statement, add a special when struct to the yang @@ -602,7 +646,7 @@ yang_expand_uses_node(yang_stmt *yn, goto done; } /* Find when statement, if present */ - if ((ywhen = yang_find(ys, Y_WHEN, NULL)) != NULL){ + if ((ywhen = yang_find(ys, Y_WHEN, NULL)) != NULL) { wxpath = yang_argument_get(ywhen); if (xml_nsctx_yang(ywhen, &wnsc) < 0) goto done; @@ -613,7 +657,6 @@ yang_expand_uses_node(yang_stmt *yn, */ if ((ygrouping2 = ys_new(ygrouping->ys_keyword)) == NULL) goto done; - /* Use yse_new() etc for ygrouping2 CHILDREN IF ywhen is set */ if (ys_cp_one(ygrouping2, ygrouping) < 0){ ys_free(ygrouping2); goto done; @@ -625,7 +668,7 @@ yang_expand_uses_node(yang_stmt *yn, for (i=0; iys_len; i++){ yco = ygrouping->ys_stmt[i]; - if (ywhen != NULL){ + if (ywhen != NULL) { if ((ycn = yse_dup(yco)) == NULL) goto done; } @@ -699,6 +742,9 @@ yang_expand_uses_node(yang_stmt *yn, /* Note: prune here to make dangling again after while loop */ if (ys_prune_self(ygrouping2) < 0) goto done; + /* Add backpointer to orig. */ + if (ys_add_orig_ptr(ygrouping, ygrouping2) < 0) + goto done; /* Then copy and insert each child element from ygrouping2 to yn */ k=0; for (j=0; j is not allowed to execute as :clicon on -sudo -g ${CLICON_GROUP} $clixon_netconf 2> /dev/null -if [ $? -eq 0 ]; then - expectpart "$(sudo -g ${CLICON_GROUP} $app)" 0 '^42$' -else - expectpart "$($app)" 0 '^42$' -fi +expectpart "$(sudo -g ${CLICON_GROUP} $app)" 0 '^42$' if [ $RC -ne 0 ]; then new "Kill restconf daemon"