/******************************************************************** * 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_one_typedef_diff * * Output the differences report for one typedef definition * * INPUTS: * cp == parameter block to use * oldtyp == old typedef * newtyp == new typedef * *********************************************************************/ static void output_one_typedef_diff (yangdiff_diffparms_t *cp, typ_template_t *oldtyp, typ_template_t *newtyp) { yangdiff_cdb_t typcdb[5]; uint32 changecnt, i; boolean isrev, tchanged; isrev = (cp->edifftype==YANGDIFF_DT_REVISION) ? TRUE : FALSE; tchanged = FALSE; changecnt = 0; if (type_changed(cp, &oldtyp->typdef, &newtyp->typdef)) { tchanged = TRUE; changecnt++; } changecnt += str_field_changed(YANG_K_UNITS, oldtyp->units, newtyp->units, isrev, &typcdb[0]); changecnt += str_field_changed(YANG_K_DEFAULT, oldtyp->defval, newtyp->defval, isrev, &typcdb[1]); changecnt += status_field_changed(YANG_K_STATUS, oldtyp->status, newtyp->status, isrev, &typcdb[2]); changecnt += str_field_changed(YANG_K_DESCRIPTION, oldtyp->descr, newtyp->descr, isrev, &typcdb[3]); changecnt += str_field_changed(YANG_K_REFERENCE, oldtyp->ref, newtyp->ref, isrev, &typcdb[4]); if (changecnt == 0) { return; } /* generate the diff output, based on the requested format */ output_mstart_line(cp, YANG_K_TYPEDEF, oldtyp->name, TRUE); if (cp->edifftype == YANGDIFF_DT_TERSE) { return; } indent_in(cp); for (i=0; i<5; i++) { if (typcdb[i].changed) { output_cdb_line(cp, &typcdb[i]); } } if (tchanged) { output_one_type_diff(cp, &oldtyp->typdef, &newtyp->typdef); } indent_out(cp); } /* output_one_typedef_diff */
/******************************************************************** * FUNCTION output_range_diff * * Output the differences report for one range or length * clause and any sub-clauses, * within a leaf, leaf-list, or typedef definition * * Only the top-level typedef is checked, instead of * following the type chain looking for the first rangedef. * This prevents chain mis-alignment false positives * * Only the top-level rangedef is relevant for validation, * since each refinement must be a valid subset of its parent * range definition * * INPUTS: * cp == parameter block to use * keyword == range or length keyword * oldtypdef == old internal typedef * newtypdef == new internal typedef * *********************************************************************/ static void output_range_diff (yangdiff_diffparms_t *cp, const xmlChar *keyword, typ_def_t *oldtypdef, typ_def_t *newtypdef) { typ_range_t *oldrange, *newrange; const xmlChar *oldstr, *newstr; ncx_errinfo_t *olderr, *newerr; yangdiff_cdb_t cdb; boolean isrev; isrev = (cp->edifftype==YANGDIFF_DT_REVISION) ? TRUE : FALSE; oldrange = typ_get_range_con(oldtypdef); oldstr = oldrange ? oldrange->rangestr : NULL; newrange = typ_get_range_con(newtypdef); newstr = newrange ? newrange->rangestr : NULL; olderr = typ_get_range_errinfo(oldtypdef); newerr = typ_get_range_errinfo(newtypdef); if (str_field_changed(keyword, oldstr, newstr, isrev, &cdb)) { output_cdb_line(cp, &cdb); indent_in(cp); output_errinfo_diff(cp, olderr, newerr); indent_out(cp); } } /* output_range_diff */
/* * Output a string that should not be split across lines. If it would * make current line too long, first output a newline and current * (nested group) indentation, then continuation indentation, then * output string. */ void lput(const char *cp) { size_t nn = strlen(cp); if (nn+linep > max_line_len && nn > 2) { (void) fputs("\n", stdout); indent_out(); (void) fputs(LINEPIND, stdout); linep = (int)strlen(LINEPIND) + indent_get(); } (void) fputs(cp,stdout); linep += nn; }
void lput2( const char *cp, /* string to print */ bool_t first_item, /* identify first item in list */ bool_t wrap /* line wrap control: true=enable, * false=stay on same line */ ) { static int linep; /* current line position (number of */ /* chars); saved between calls */ int len_prefix = strlen (CDL_COMMENT_PREFIX); bool_t make_newline; size_t len1 = strlen(cp); /* length of input string */ assert (len1 > 0); /* (1) Single space or newline/indent sequence, as needed. */ linep = linep + 1 + len1; /* new line position, without newline */ /* add 1 extra for preceeding space */ make_newline = (wrap && (first_item || linep > max_line_len + 2)); /* NEVER new line in no-wrap mode */ if (make_newline) { /* start new line, if needed */ printf ("\n"); indent_out(); /* same exact indentation as pr_att */ printf ("\t\t"); /* (possible problem here) */ printf (" "); /* add indent for CDL comment */ linep = 16 + 2 + len1; /* recompute new line position */ /* with newline + indents */ } else { printf (" "); /* always one space, if not newline */ } /* (2) Add CDL comment prefix, if needed. */ if (len_prefix > 0) { if (first_item || make_newline) { printf (CDL_COMMENT_PREFIX); linep = linep + len_prefix; } } /* (3) Output caller's string value. */ printf ("%s", cp); }
static char *def_array_type(CTX *ctx, struct ir_array_type *at) { char *m = get_mangle(ctx, at); if (m) return m; assert(ctx->writing_types); m = talloc_strdup(ctx, MANGLE_PREFIX "arr_"); m = talloc_asprintf_append_buffer(m, "%d_", at->dimension); mangle_append_sub(&m, def_type(ctx, at->item_type)); add_mangle(ctx, at, m); if (!check_redef(ctx, m)) { wf(ctx, "typedef struct %s {", m); indent_in(ctx); wf(ctx, "%s a[%d];", def_type(ctx, at->item_type), at->dimension); indent_out(ctx); wf(ctx, "} %s;", m); } return m; }
/* * Prints brief annotation for a row of data values */ static void annotate_brief( const ncvar_t *vp, /* variable */ const size_t *cor, /* corner coordinates */ size_t vdims[] /* variable dimension sizes */ ) { int vrank = vp->ndims; int id; printf ("// "); print_name(vp->name); printf("("); switch (formatting_specs.data_lang) { case LANG_C: /* print brief comment with C variable indices */ for (id = 0; id < vrank-1; id++) printf("%lu,", (unsigned long)cor[id]); if (vdims[vrank-1] == 1) printf("0"); else printf(" 0-%lu", (unsigned long)vdims[vrank-1]-1); break; case LANG_F: /* print brief comment with Fortran variable indices */ if (vdims[vrank-1] == 1) printf("1"); else printf("1-%lu ", (unsigned long)vdims[vrank-1]); for (id = vrank-2; id >=0 ; id--) { printf(",%lu", (unsigned long)(1 + cor[id])); } break; } printf(")\n"); indent_out(); printf(" "); set_indent(4 + indent_get()); }
static void write_struct(CTX *ctx, struct ir_struct_type *st, char *name) { assert(ctx->writing_types); wf(ctx, "struct %s;", name); wf(ctx, "typedef struct %s %s;", name, name); // Make sure all types are written out first. for (int n = 0; n < st->members_count; n++) { struct ir_struct_member *m = st->members[n]; def_type(ctx, m->type); } set_loc(ctx, st->loc); wf(ctx, "struct %s {", name); indent_in(ctx); for (int n = 0; n < st->members_count; n++) { struct ir_struct_member *m = st->members[n]; struct name_temp t; char *mname = member_name(m, &t); set_loc(ctx, m->loc); wf(ctx, "%s %s;", def_type(ctx, m->type), mname); } indent_out(ctx); wf(ctx, "};"); set_no_loc(ctx); }
static void gen_fn(CTX *ctx, struct ir_function *fn, char *name, bool visible) { assert(!ctx->writing_types); if (!fn->parent) fn_complete_nested_calls(fn); for (int n = 0; n < fn->nested_functions_count; n++) { struct ir_function *nfn = fn->nested_functions[n]; ctx->writing_types = true; char *nname = def_nested_fn(ctx, nfn); ctx->writing_types = false; gen_fn(ctx, nfn, nname, false); } fn_remove_global_ssa(fn); fn_verify(fn); //dump_fn(stderr, fn); for (int b = 0; b < fn->blocks_count; b++) { for (struct ir_inst *in = fn->blocks[b]->first; in; in = in->next) in->scratch1_i = -1; } // add all C types and function declarations needed for this function ctx->writing_types = true; do_fn_types(ctx, fn->type); for (int n = 0; n < fn->vars_count; n++) def_type(ctx, fn->vars[n]->type); for (int b = 0; b < fn->blocks_count; b++) { struct ir_bb *bb = fn->blocks[b]; for (struct ir_inst *in = bb->first; in; in = in->next) { def_type(ctx, in->result_type); if (in->op == IR_OP_CALL || in->op == IR_OP_FN_PTR) { def_fn(ctx, in->fn); } } } ctx->writing_types = false; set_loc(ctx, fn->loc); if (!visible) fprintf(ctx->f, "static "); write_fn_type(ctx, fn->type, false, name); wf(ctx, " {"); indent_in(ctx); for (int n = 0; n < fn->vars_count; n++) { struct ir_var *v = fn->vars[n]; set_loc(ctx, v->loc); indent(ctx); P(ctx, "%s V%d", type(ctx, v->type), n); // void values are never assigned to (to avoid clashes with C's void); // since they have only one value, there's no need to. Initialize them // to avoid C warnings, though. if (type_is_void(v->type)) P(ctx, " = {0}"); P(ctx, ";\n"); } indent(ctx); P(ctx, "goto B%d;\n", fn->entry->index); for (int b = 0; b < fn->blocks_count; b++) { struct ir_bb *bb = fn->blocks[b]; indent(ctx); P(ctx, "B%d: {\n", b); indent_in(ctx); ctx->reg = 0; for (struct ir_inst *in = bb->first; in; in = in->next) gen_inst(ctx, in); indent_out(ctx); wf(ctx, "}"); } indent_out(ctx); wf(ctx, "}"); }
/* Output the data for a single variable, in CDL syntax. */ int vardata( const ncvar_t *vp, /* variable */ size_t vdims[], /* variable dimension sizes */ int ncid, /* netcdf id */ int varid /* variable id */ ) { size_t *cor; /* corner coordinates */ size_t *edg; /* edges of hypercube */ size_t *add; /* "odometer" increment to next "row" */ void *vals; int id; int ir; size_t nels; size_t ncols; size_t nrows; int vrank = vp->ndims; cor = (size_t *) emalloc((1 + vrank) * sizeof(size_t)); edg = (size_t *) emalloc((1 + vrank) * sizeof(size_t)); add = (size_t *) emalloc((1 + vrank) * sizeof(size_t)); nels = 1; if(vrank == 0) { /*scalar*/ cor[0] = 0; edg[0] = 1; } else { for (id = 0; id < vrank; id++) { cor[id] = 0; edg[id] = 1; nels *= vdims[id]; /* total number of values for variable */ } } printf("\n"); indent_out(); printf(" "); print_name(vp->name); if (vrank <= 1) { printf(" = "); set_indent ((int)strlen(vp->name) + 4 + indent_get()); } else { printf(" =\n "); set_indent (2 + indent_get()); } if (vrank == 0) { ncols = 1; } else { ncols = vdims[vrank-1]; /* size of "row" along last dimension */ edg[vrank-1] = ncols; for (id = 0; id < vrank; id++) add[id] = 0; if (vrank > 1) add[vrank-2] = 1; } nrows = nels/ncols; /* number of "rows" */ vals = emalloc(ncols * vp->tinfo->size); /* Test if we should treat array of chars as a string */ if(vp->type == NC_CHAR && (vp->fmt == 0 || STREQ(vp->fmt,"%s") || STREQ(vp->fmt,""))) { for (ir = 0; ir < nrows; ir++) { if (vrank > 0) { if (formatting_specs.brief_data_cmnts != false && vrank > 1 && ncols > 0) { annotate_brief(vp, cor, vdims); } } NC_CHECK(nc_get_vara(ncid, varid, cor, edg, vals)); pr_tvals(vp, ncols, (ir == nrows-1), (char *) vals, cor); if (ir < nrows-1) if (!upcorner(vdims, vp->ndims, cor, add)) error("vardata: odometer overflowed!"); set_indent(2); } } else { int level = 0; int rank = vp->ndims; int marks_pending = 0; NC_CHECK(print_rows(level, ncid, varid, vp, ncols, rank, vdims, cor, edg, vals, marks_pending)); } free(vals); free(cor); free(edg); free(add); return 0; }
/* Output the data for a single variable, in CDL syntax. */ int vardata( const ncvar_t *vp, /* variable */ size_t vdims[], /* variable dimension sizes */ int ncid, /* netcdf id */ int varid, /* variable id */ const fspec_t *fsp /* formatting specs */ ) { size_t cor[NC_MAX_DIMS]; /* corner coordinates */ size_t edg[NC_MAX_DIMS]; /* edges of hypercube */ size_t add[NC_MAX_DIMS]; /* "odometer" increment to next "row" */ size_t gulp; void *vals; int id; int ir; size_t nels; size_t ncols; size_t nrows; int vrank = vp->ndims; nels = 1; for (id = 0; id < vrank; id++) { cor[id] = 0; edg[id] = 1; nels *= vdims[id]; /* total number of values for variable */ } printf("\n"); indent_out(); /* printf(" %s = ", vp->name); */ /* or */ /* printf(" %s =\n ", vp->name); */ printf(" "); print_name(vp->name); if (vrank <= 1) { printf(" = "); set_indent ((int)strlen(vp->name) + 4 + indent_get()); } else { printf(" =\n "); set_indent (2 + indent_get()); } if (vrank < 1) { ncols = 1; } else { ncols = vdims[vrank-1]; /* size of "row" along last dimension */ edg[vrank-1] = vdims[vrank-1]; for (id = 0; id < vrank; id++) add[id] = 0; if (vrank > 1) add[vrank-2] = 1; } nrows = nels/ncols; /* number of "rows" */ gulp = ncols < VALBUFSIZ ? ncols : VALBUFSIZ; vals = emalloc(gulp * vp->tinfo->size); for (ir = 0; ir < nrows; ir++) { /* * rather than just printing a whole row at once (which might * exceed the capacity of some platforms), we break each row * into smaller chunks, if necessary. */ size_t corsav = 0; int left = (int)ncols; boolean lastrow; if (vrank > 0) { corsav = cor[vrank-1]; if (fsp->brief_data_cmnts != false && vrank > 1 && left > 0) { /* print brief comment with indices range */ /* printf("// %s(",vp->name); */ printf("// "); printf(vp->name); printf("("); switch (fsp->data_lang) { case LANG_C: /* print brief comment with C variable indices */ for (id = 0; id < vrank-1; id++) printf("%lu,", (unsigned long)cor[id]); if (vdims[vrank-1] == 1) printf("0"); else printf(" 0-%lu", (unsigned long)vdims[vrank-1]-1); break; case LANG_F: /* print brief comment with Fortran variable indices */ if (vdims[vrank-1] == 1) printf("1"); else printf("1-%lu ", (unsigned long)vdims[vrank-1]); for (id = vrank-2; id >=0 ; id--) { printf(",%lu", (unsigned long)(1 + cor[id])); } break; } printf(")\n"); indent_out(); printf(" "); set_indent(4 + indent_get()); } } lastrow = (boolean)(ir == nrows-1); while (left > 0) { size_t toget = left < gulp ? left : gulp; if (vrank > 0) edg[vrank-1] = toget; NC_CHECK(nc_get_vara(ncid, varid, cor, edg, vals) ); /* Test if we should treat array of chars as a string */ if(vp->type == NC_CHAR && (vp->fmt == 0 || STREQ(vp->fmt,"%s") || STREQ(vp->fmt,""))) { pr_tvals(vp, toget, left > toget, lastrow, (char *) vals, fsp, cor); } else { pr_any_vals(vp, toget, left > toget, lastrow, vals, fsp, cor); } left -= toget; if (vrank > 0) cor[vrank-1] += toget; } if (vrank > 0) cor[vrank-1] = corsav; if (ir < nrows-1) if (!upcorner(vdims,vp->ndims,cor,add)) error("vardata: odometer overflowed!"); set_indent(2); } free(vals); return 0; }
// sort in place, i.e. A will be reordered void merge_sort(int16_t *A, int16_t A_len) { indent_in(); indent(); Serial.print("Entering merge sort: array addr "); Serial.print( (int) A ); Serial.print(" len "); Serial.println( A_len); mem_info(""); assert_free_mem_ok(128, "merge_sort"); if ( A_len < 2 ) { indent_out(); return; } if ( A_len == 2 ) { if ( A[0] > A[1] ) { int temp = A[0]; A[0] = A[1]; A[1] = temp; } indent_out(); return; } // split A in half, sort left, sort right, then merge // left half is: A[0], ..., A[split_point-1] // right half is: A[split_point], ..., A[A_len-1] int split_point = A_len / 2; indent(); Serial.println("Doing left sort"); merge_sort(A, split_point); mem_info("After left sort"); indent(); Serial.println("Doing right sort"); merge_sort(A+split_point, A_len-split_point); mem_info("After right sort"); // don't need the merging arrat S until this point int *S = (int *) malloc( A_len * sizeof(int) ); assert_malloc_ok(S, "Cannot get merge buffer"); mem_info("Doing merge"); merge(A, split_point, A+split_point, A_len-split_point, S); for (int i=0; i < A_len; i++) { A[i] = S[i]; } // now we are done with it free(S); mem_info("After free"); indent_out(); }
/* Output the data for a single variable, in CDL syntax. */ int vardata( const ncvar_t *vp, /* variable */ size_t vdims[], /* variable dimension sizes */ int ncid, /* netcdf id */ int varid /* variable id */ ) { size_t *cor; /* corner coordinates */ size_t *edg; /* edges of hypercube */ size_t *add; /* "odometer" increment to next "row" */ void *vals; int id; size_t nels; size_t ncols; size_t nrows; int vrank = vp->ndims; int level = 0; int marks_pending = 0; cor = (size_t *) emalloc((1 + vrank) * sizeof(size_t)); edg = (size_t *) emalloc((1 + vrank) * sizeof(size_t)); add = (size_t *) emalloc((1 + vrank) * sizeof(size_t)); nels = 1; if(vrank == 0) { /*scalar*/ cor[0] = 0; edg[0] = 1; } else { for (id = 0; id < vrank; id++) { cor[id] = 0; edg[id] = 1; nels *= vdims[id]; /* total number of values for variable */ } } printf("\n"); indent_out(); printf(" "); print_name(vp->name); if (vrank <= 1) { printf(" = "); set_indent ((int)strlen(vp->name) + 4 + indent_get()); } else { printf(" =\n "); set_indent (2 + indent_get()); } if (vrank == 0) { ncols = 1; } else { ncols = vdims[vrank-1]; /* size of "row" along last dimension */ edg[vrank-1] = ncols; for (id = 0; id < vrank; id++) add[id] = 0; if (vrank > 1) add[vrank-2] = 1; } nrows = nels/ncols; /* number of "rows" */ vals = emalloc(ncols * vp->tinfo->size); NC_CHECK(print_rows(level, ncid, varid, vp, vdims, cor, edg, vals, marks_pending)); free(vals); free(cor); free(edg); free(add); return 0; }
/******************************************************************** * 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 */