/******************************************************************** * FUNCTION output_pattern_diff * * Output the differences report for one pattern clause and * any of its sub-clauses, within a leaf, leaf-list, or * typedef definition * * INPUTS: * cp == parameter block to use * oldpat == old internal pattern * newpat == new internal pattern * patnum == index number of pattern in the Q [1 .. N] * *********************************************************************/ static void output_pattern_diff (yangdiff_diffparms_t *cp, const typ_pattern_t *oldpat, const typ_pattern_t *newpat, uint32 patnum) { const ncx_errinfo_t *olderr, *newerr; const xmlChar *oldstr, *newstr; xmlChar buff[NCX_MAX_NUMLEN+16], *p; oldstr = (oldpat) ? oldpat->pat_str : NULL; newstr = (newpat) ? newpat->pat_str : NULL; olderr = (oldpat) ? &oldpat->pat_errinfo : NULL; newerr = (newpat) ? &newpat->pat_errinfo : NULL; p = buff; p += xml_strcpy(p, YANG_K_PATTERN); *p++ = ' '; *p++ = '['; p += (uint32)sprintf((char *)p, "%u", patnum); *p++ = ']'; *p = 0; if (!oldstr && newstr) { /* pattern added in new revision */ output_diff(cp, buff, oldstr, newstr, FALSE); indent_in(cp); output_errinfo_diff(cp, olderr, newerr); indent_out(cp); } else if (oldstr && !newstr) { /* pattern removed in new revision */ output_diff(cp, buff, oldstr, newstr, FALSE); indent_in(cp); output_errinfo_diff(cp, olderr, newerr); indent_out(cp); } else if (oldstr && newstr) { /* check if pattern changed */ if (xml_strcmp(oldstr, newstr)) { output_diff(cp, buff, oldstr, newstr, FALSE); indent_in(cp); output_errinfo_diff(cp, olderr, newerr); indent_out(cp); } else if (errinfo_changed(olderr, newerr)) { output_mstart_line(cp, buff, oldstr, FALSE); indent_in(cp); output_errinfo_diff(cp, olderr, newerr); indent_out(cp); } } } /* output_pattern_diff */
/******************************************************************** * FUNCTION output_typedefQ_diff * * Output the differences report for a Q of typedef definitions * Not always called for top-level typedefs; Can be called * for nested typedefs * * INPUTS: * cp == parameter block to use * oldQ == Q of old typ_template_t to use * newQ == Q of new typ_template_t to use * *********************************************************************/ void output_typedefQ_diff (yangdiff_diffparms_t *cp, dlq_hdr_t *oldQ, dlq_hdr_t *newQ) { typ_template_t *oldtyp, *newtyp; /* borrowing the 'used' flag for marking matched typedefs * first set all these flags to FALSE */ for (newtyp = (typ_template_t *)dlq_firstEntry(newQ); newtyp != NULL; newtyp = (typ_template_t *)dlq_nextEntry(newtyp)) { newtyp->used = FALSE; } /* look through the old type Q for matching types in the new type Q */ for (oldtyp = (typ_template_t *)dlq_firstEntry(oldQ); oldtyp != NULL; oldtyp = (typ_template_t *)dlq_nextEntry(oldtyp)) { /* find this revision in the new module */ newtyp = ncx_find_type_que(newQ, oldtyp->name); if (newtyp) { output_one_typedef_diff(cp, oldtyp, newtyp); newtyp->used = TRUE; } else { /* typedef was removed from the new module */ output_diff(cp, YANG_K_TYPEDEF, oldtyp->name, NULL, TRUE); } } /* look for typedefs that were added in the new module */ for (newtyp = (typ_template_t *)dlq_firstEntry(newQ); newtyp != NULL; newtyp = (typ_template_t *)dlq_nextEntry(newtyp)) { if (!newtyp->used) { /* this typedef was added in the new version */ output_diff(cp, YANG_K_TYPEDEF, NULL, newtyp->name, TRUE); } } } /* output_typedefQ_diff */
void unified_difft::output(std::ostream &os) const { goto_programt empty; for(const std::pair<irep_idt, differencest> &p : differences_map) { goto_functionst::function_mapt::const_iterator f1= old_goto_functions.function_map.find(p.first); goto_functionst::function_mapt::const_iterator f2= new_goto_functions.function_map.find(p.first); output_diff( p.first, f1==old_goto_functions.function_map.end()?empty:f1->second.body, f2==new_goto_functions.function_map.end()?empty:f2->second.body, p.second, os); } }
/******************************************************************** * FUNCTION output_union_diff * * Output the differences report for one union sub-clauses * within a leaf, leaf-list, or typedef definition * * INPUTS: * cp == parameter block to use * oldtypdef == old internal typedef * newtypdef == new internal typedef *********************************************************************/ static void output_union_diff (yangdiff_diffparms_t *cp, typ_def_t *oldtypdef, typ_def_t *newtypdef) { typ_unionnode_t *oldval, *newval, *curnew; dlq_hdr_t *oldQ, *newQ; typ_def_t *olddef, *newdef; uint32 oldid, newid; char oldnum[NCX_MAX_NUMLEN]; char newnum[NCX_MAX_NUMLEN]; olddef = typ_get_base_typdef(oldtypdef); newdef = typ_get_base_typdef(newtypdef); oldQ = &olddef->def.simple.unionQ, newQ = &newdef->def.simple.unionQ; if (!unQ_changed(cp, oldQ, newQ)) { return; } oldid = 0; newid = 0; /* clear the seen flag to be safe */ for (newval = (typ_unionnode_t *)dlq_firstEntry(newQ); newval != NULL; newval = (typ_unionnode_t *)dlq_nextEntry(newval)) { newval->seen = FALSE; } /* start the diff output */ output_mstart_line(cp, YANG_K_UNION, NULL, FALSE); if (cp->edifftype == YANGDIFF_DT_TERSE) { return; } indent_in(cp); /* check for matching unionnode entries */ for (oldval = (typ_unionnode_t *)dlq_firstEntry(oldQ); oldval != NULL; oldval = (typ_unionnode_t *)dlq_nextEntry(oldval), oldid++) { curnew = NULL; sprintf(oldnum, "[%u]", oldid); olddef = typ_get_unionnode_ptr(oldval); /* first try the corresponded entry if available */ newval = unQ_match_id(oldid, newQ); if (newval) { curnew = newval; newid = oldid; sprintf(newnum, "[%u]", newid); newdef = typ_get_unionnode_ptr(newval); /* if the corresponding entry did not change * then this is a match and continue to next type */ if (!type_changed(cp, olddef, newdef)) { newval->seen = TRUE; continue; } } /* did not match the corresponding entry, * so see if the typdef moved in the new union */ newval = unQ_match(cp, oldval, newQ, &newid); if (newval) { newval->seen = TRUE; if (oldid != newid) { sprintf(newnum, "[%u]", newid); /* old union node was moved in new version */ output_diff(cp, YANG_K_TYPE, (const xmlChar *)oldnum, (const xmlChar *)newnum, TRUE); } } else if (curnew) { /* type node was changed in the new union */ curnew->seen = TRUE; newdef = typ_get_unionnode_ptr(curnew); sprintf(newnum, "[%u]", oldid); output_one_type_diff(cp, olddef, newdef); } else { /* old union node was removed in new version */ output_diff(cp, YANG_K_TYPE, (const xmlChar *)oldnum, NULL, TRUE); } } indent_out(cp); /* check for new entries */ newid = 0; for (newval = (typ_unionnode_t *)dlq_firstEntry(newQ); newval != NULL; newval = (typ_unionnode_t *)dlq_nextEntry(newval)) { if (!newval->seen) { sprintf(newnum, "[%u]", newid); output_diff(cp, YANG_K_TYPE, NULL, (const xmlChar *)newnum, TRUE); } newid++; } } /* output_union_diff */
/******************************************************************** * FUNCTION output_eb_type_diff * * Output the differences report for one enum or bits sub-clauses * within a leaf, leaf-list, or typedef definition * * INPUTS: * cp == parameter block to use * name == type name to use * oldtypdef == old internal typedef * newtypdef == new internal typedef * isbits == TRUE if NCX_BT_BITS * FALSE if NCX_BT_ENUM *********************************************************************/ static void output_eb_type_diff (yangdiff_diffparms_t *cp, typ_def_t *oldtypdef, typ_def_t *newtypdef, boolean isbits) { typ_enum_t *oldval, *newval; dlq_hdr_t *oldQ, *newQ; typ_def_t *oldbase, *newbase; const xmlChar *kw; xmlChar oldnum[NCX_MAX_NUMLEN]; xmlChar newnum[NCX_MAX_NUMLEN]; yangdiff_cdb_t cdb[4]; boolean isrev; uint32 chcount, i; oldbase = typ_get_base_typdef(oldtypdef); newbase = typ_get_base_typdef(newtypdef); oldQ = &oldbase->def.simple.valQ; newQ = &newbase->def.simple.valQ; isrev = (cp->edifftype==YANGDIFF_DT_REVISION) ? TRUE : FALSE; kw = isbits ? YANG_K_BIT : YANG_K_ENUM; /* clear the seen flag to find new enums/bits */ for (newval = (typ_enum_t *)dlq_firstEntry(newQ); newval != NULL; newval = (typ_enum_t *)dlq_nextEntry(newval)) { newval->flags &= ~TYP_FL_SEEN; } /* check for matching entries */ for (oldval = (typ_enum_t *)dlq_firstEntry(oldQ); oldval != NULL; oldval = (typ_enum_t *)dlq_nextEntry(oldval)) { chcount = 0; newval = typ_find_enumdef(newQ, oldval->name); if (newval) { if (isbits) { sprintf((char *)oldnum, "%u", oldval->pos); sprintf((char *)newnum, "%u", newval->pos); chcount += str_field_changed(YANG_K_POSITION, oldnum, newnum, isrev, &cdb[0]); } else { sprintf((char *)oldnum, "%d", oldval->val); sprintf((char *)newnum, "%d", newval->val); chcount += str_field_changed(YANG_K_VALUE, oldnum, newnum, isrev, &cdb[0]); } chcount += status_field_changed(YANG_K_STATUS, oldval->status, newval->status, isrev, &cdb[1]); chcount += str_field_changed(YANG_K_DESCRIPTION, oldval->descr, newval->descr, isrev, &cdb[2]); chcount += str_field_changed(YANG_K_REFERENCE, oldval->ref, newval->ref, isrev, &cdb[3]); newval->flags |= TYP_FL_SEEN; if (chcount) { output_mstart_line(cp, kw, oldval->name, isbits); if (cp->edifftype != YANGDIFF_DT_TERSE) { indent_in(cp); for (i=0; i<4; i++) { output_cdb_line(cp, &cdb[i]); } indent_out(cp); } } } else { /* removed name in new version */ output_diff(cp, kw, oldval->name, NULL, isbits); } } /* check for new entries */ for (newval = (typ_enum_t *)dlq_firstEntry(newQ); newval != NULL; newval = (typ_enum_t *)dlq_nextEntry(newval)) { if ((newval->flags & TYP_FL_SEEN) == 0) { output_diff(cp, kw, NULL, newval->name, isbits); } } } /* output_eb_type_diff */
/******************************************************************** * FUNCTION output_one_type_diff * * Output the differences report for one type section * within a leaf, leaf-list, or typedef definition * * type_changed should be called first to determine * if the type actually changed. Otherwise a 'M typedef foo' * output line will result and be a false positive * * INPUTS: * cp == parameter block to use * oldtypdef == old internal typedef * newtypdef == new internal typedef * *********************************************************************/ void output_one_type_diff (yangdiff_diffparms_t *cp, typ_def_t *oldtypdef, typ_def_t *newtypdef) { xmlChar *p, *oldp, *newp; const xmlChar *oldname, *newname; const xmlChar *oldpath, *newpath; yangdiff_cdb_t typcdb[5]; ncx_btype_t oldbtyp, newbtyp; ncx_tclass_t oldclass, newclass; boolean isrev; isrev = (cp->edifftype==YANGDIFF_DT_REVISION) ? TRUE : FALSE; oldclass = oldtypdef->tclass; newclass = newtypdef->tclass; oldname = typ_get_name(oldtypdef); newname = typ_get_name(newtypdef); oldbtyp = typ_get_basetype(oldtypdef); newbtyp = typ_get_basetype(newtypdef); if (oldbtyp == NCX_BT_LEAFREF) { oldpath = typ_get_leafref_path(oldtypdef); } else { oldpath = NULL; } if (newbtyp==NCX_BT_LEAFREF) { newpath = typ_get_leafref_path(newtypdef); } else { newpath = NULL; } /* check if there is a module prefix involved * in the change. This may be a false positive * if the prefix simply changed * create YANG QNames for the type change record * use the scratch buffer cp->buff for both strings */ p = cp->buff; if (oldtypdef->prefix) { oldp = p; p += xml_strcpy(p, oldtypdef->prefix); *p++ = ':'; p += xml_strcpy(p, oldname); if (oldtypdef->tclass==NCX_CL_NAMED) { *p++ = ' '; *p++ = '('; p += xml_strcpy(p, (const xmlChar *) tk_get_btype_sym(oldbtyp)); *p++ = ')'; *p = 0; } p++; /* leave last NULL char in place */ oldname = oldp; } if (newtypdef->prefix) { newp = p; p += xml_strcpy(p, newtypdef->prefix); *p++ = ':'; p += xml_strcpy(p, newname); if (newtypdef->tclass==NCX_CL_NAMED) { *p++ = ' '; *p++ = '('; p += xml_strcpy(p, (const xmlChar *) tk_get_btype_sym(newbtyp)); *p++ = ')'; *p = 0; } newname = newp; } /* Print the type name change set only if it really * changed; otherwise force an M line to be printed */ if (str_field_changed(YANG_K_TYPE, oldname, newname, isrev, &typcdb[0])) { output_cdb_line(cp, &typcdb[0]); } else { output_mstart_line(cp, YANG_K_TYPE, NULL, FALSE); } /* check invalid change of builtin type */ if (oldbtyp != newbtyp) { /* need to figure out what type changes are really allowed */ if (!((typ_is_number(oldbtyp) && typ_is_number(newbtyp)) || (typ_is_string(oldbtyp) && typ_is_string(newbtyp)))) { /* ses_putstr(cp->scb, (const xmlChar *)" (invalid)"); */ return; } } /* check if that is all the data requested */ if (cp->edifftype == YANGDIFF_DT_TERSE) { return; } /* check corner-case, no sub-fields to compare */ if (oldclass==NCX_CL_BASE && newclass==NCX_CL_BASE) { /* type field is a plain builtin like 'int32;' */ return; } /* in all modes except 'normal', indent 1 level and * show the specific sub-clauses that have changed */ indent_in(cp); /* special case -- check leafref here */ if (oldpath || newpath) { output_diff(cp, YANG_K_PATH, oldpath, newpath, FALSE); } if (typ_is_number(oldbtyp)) { output_range_diff(cp, YANG_K_RANGE, oldtypdef, newtypdef); } else if (typ_is_string(oldbtyp)) { output_range_diff(cp, YANG_K_LENGTH, oldtypdef, newtypdef); output_patternQ_diff(cp, oldtypdef, newtypdef); } else { switch (oldbtyp) { case NCX_BT_ENUM: output_eb_type_diff(cp, oldtypdef, newtypdef, FALSE); break; case NCX_BT_BITS: output_eb_type_diff(cp, oldtypdef, newtypdef, TRUE); break; case NCX_BT_UNION: output_union_diff(cp, oldtypdef, newtypdef); break; default: ; } } indent_out(cp); } /* output_one_type_diff */