diff --git a/include/abg-comparison.h b/include/abg-comparison.h index 832632f6..50616c04 100644 --- a/include/abg-comparison.h +++ b/include/abg-comparison.h @@ -168,6 +168,42 @@ public: add_diff(const decl_base_sptr first, const decl_base_sptr second, diff_sptr d); + + void + show_deleted_fns(bool f); + + bool + show_deleted_fns() const; + + void + show_changed_fns(bool f); + + bool + show_changed_fns() const; + + void + show_added_fns(bool f); + + bool + show_added_fns() const; + + void + show_deleted_vars(bool f); + + bool + show_deleted_vars() const; + + void + show_changed_vars(bool f); + + bool + show_changed_vars() const; + + void + show_added_vars(bool f); + + bool + show_added_vars() const; };//end struct diff_context. /// This type encapsulates an edit script (a set of insertions and @@ -978,6 +1014,9 @@ public: edit_script& variable_changes() const; + const diff_context_sptr + context() const; + unsigned length() const; diff --git a/src/abg-comparison.cc b/src/abg-comparison.cc index 57b5eedb..2c30b834 100644 --- a/src/abg-comparison.cc +++ b/src/abg-comparison.cc @@ -78,6 +78,21 @@ decls_diff_map_type; struct diff_context::priv { decls_diff_map_type decls_diff_map; + bool show_deleted_fns_; + bool show_changed_fns_; + bool show_added_fns_; + bool show_deleted_vars_; + bool show_changed_vars_; + bool show_added_vars_; + + priv() + : show_deleted_fns_(true), + show_changed_fns_(true), + show_added_fns_(true), + show_deleted_vars_(true), + show_changed_vars_(true), + show_added_vars_(true) + {} };// end struct diff_context::priv diff_context::diff_context() @@ -142,7 +157,84 @@ diff_context::add_diff(decl_base_sptr first, diff_sptr d) {priv_->decls_diff_map[std::make_pair(first, second)] = d;} -/// +/// Set a flag saying to show the deleted functions. +/// +/// @param f true to show deleted functions. +void +diff_context::show_deleted_fns(bool f) +{priv_->show_deleted_fns_ = f;} + +/// @return true if we want to show the deleted functions, false +/// otherwise. +bool +diff_context::show_deleted_fns() const +{return priv_->show_deleted_fns_;} + +/// Set a flag saying to show the changed functions. +/// +/// @param f true to show the changed functions. +void +diff_context::show_changed_fns(bool f) +{priv_->show_changed_fns_ = f;} + +/// @return true if we want to show the changed functions, false otherwise. +bool +diff_context::show_changed_fns() const +{return priv_->show_changed_fns_;} + +/// Set a flag saying to show the added functions. +/// +/// @param f true to show the added functions. +void +diff_context::show_added_fns(bool f) +{priv_->show_added_fns_ = f;} + +/// @return true if we want to show the added functions, false +/// otherwise. +bool +diff_context::show_added_fns() const +{return priv_->show_added_fns_;} + +/// Set a flag saying to show the deleted variables. +/// +/// @param f true to show the deleted variables. +void +diff_context::show_deleted_vars(bool f) +{priv_->show_deleted_vars_ = f;} + +/// @return true if we want to show the deleted variables, false +/// otherwise. +bool +diff_context::show_deleted_vars() const +{return priv_->show_deleted_vars_;} + +/// Set a flag saying to show the changed variables. +/// +/// @param f true to show the changed variables. +void +diff_context::show_changed_vars(bool f) +{priv_->show_changed_vars_ = f;} + +/// @return true if we want to show the changed variables, false otherwise. +bool +diff_context::show_changed_vars() const +{return priv_->show_changed_vars_;} + +/// Set a flag saying to show the added variables. +/// +/// @param f true to show the added variables. +void +diff_context::show_added_vars(bool f) +{priv_->show_added_vars_ = f;} + +/// @return true if we want to show the added variables, false +/// otherwise. +bool +diff_context::show_added_vars() const +{return priv_->show_added_vars_;} +// + +// /// The private data structure for @ref distinct_diff. struct distinct_diff::priv @@ -3975,7 +4067,7 @@ compute_diff(const translation_unit_sptr first, // struct corpus_diff::priv { - diff_context_sptr ctxt; + diff_context_sptr ctxt_; corpus_sptr first_; corpus_sptr second_; edit_script fns_edit_script_; @@ -3995,6 +4087,9 @@ struct corpus_diff::priv void ensure_lookup_tables_populated(); + + void + emit_corpus_diff_stats(ostream& out, const string& indent); }; // end corpus::priv /// Tests if the lookup tables are empty. @@ -4130,6 +4225,50 @@ corpus_diff::priv::ensure_lookup_tables_populated() } } +/// Emit the summary of the functions & variables that got +/// removed/changed/added. +/// +/// @param out the output stream to emit the stats to. +/// +/// @param indent the indentation string to use in the summary. +void +corpus_diff::priv::emit_corpus_diff_stats(ostream& out, const string& indent) +{ + unsigned total = 0, num_removed = 0, num_added = 0, num_changed = 0; + + /// Report added/removed/changed functions. + num_removed = deleted_fns_.size(); + num_added = added_fns_.size(); + num_changed = changed_fns_.size(); + total = num_removed + num_added + num_changed; + + // function changes summary + out << indent << "Functions changes summary: "; + out << num_removed << " Removed, "; + out << num_changed << " Changed, "; + out << num_added << " Added "; + if (total <= 1) + out << " function\n\n"; + else + out << " functions\n\n"; + + // Report added/removed/changed variables. + num_removed = deleted_vars_.size(); + num_added = added_vars_.size(); + num_changed = changed_vars_.size(); + total = num_removed + num_added + num_changed; + + // variables changes summary + out << indent << "Variables changes summary: "; + out << num_removed << " Removed, "; + out << num_changed << " Changed, "; + out << num_added << " Added "; + if (total <= 1) + out << " variable\n\n"; + else + out << " variables\n\n"; +} + /// Constructor for @ref corpus_diff. /// /// @param first the first corpus of the diff. @@ -4144,7 +4283,7 @@ corpus_diff::corpus_diff(corpus_sptr first, { priv_->first_ = first; priv_->second_ = second; - priv_->ctxt = ctxt; + priv_->ctxt_ = ctxt; } /// @return the first corpus of the diff. @@ -4169,6 +4308,13 @@ edit_script& corpus_diff::variable_changes() const {return priv_->vars_edit_script_;} +/// Getter of the diff context of this diff +/// +/// @return the diff context for this diff. +const diff_context_sptr +corpus_diff::context() const +{return priv_->ctxt_;} + /// @return the length of the changes as recorded by the diff. unsigned corpus_diff::length() const @@ -4207,151 +4353,171 @@ corpus_diff::report(ostream& out, const string& indent) const total = num_removed + num_added + num_changed; const unsigned large_num = 100; - if (num_removed == 1) - out << indent << "1 Removed function:\n\n"; - else if (num_removed > 1) - out << indent << num_removed << " Removed functions:\n\n"; + priv_->emit_corpus_diff_stats(out, indent); - for (string_function_ptr_map::const_iterator i = - priv_->deleted_fns_.begin(); - i != priv_->deleted_fns_.end(); - ++i) + if (context()->show_deleted_fns()) { - out << indent - << " '"; - if (total > large_num) - out << "[D] "; - out << i->second->get_pretty_representation() - << "\n"; - ++removed; - } - if (removed) - out << "\n"; + if (num_removed == 1) + out << indent << "1 Removed function:\n\n"; + else if (num_removed > 1) + out << indent << num_removed << " Removed functions:\n\n"; - if (num_added == 1) - out << indent << "1 Added function:\n"; - else if (num_added > 1) - out << indent << num_added - << " Added functions:\n\n"; - for (string_function_ptr_map::const_iterator i = - priv_->added_fns_.begin(); - i != priv_->added_fns_.end(); - ++i) + for (string_function_ptr_map::const_iterator i = + priv_->deleted_fns_.begin(); + i != priv_->deleted_fns_.end(); + ++i) + { + out << indent + << " '"; + if (total > large_num) + out << "[D] "; + out << i->second->get_pretty_representation() + << "\n"; + ++removed; + } + if (removed) + out << "\n"; + } + + if (context()->show_changed_fns()) { - out - << indent - << " '"; - if (total > large_num) - out << "[A] "; - out << i->second->get_pretty_representation() - << "\n"; - ++added; + if (num_changed == 1) + out << indent << "1 Changed function :\n\n"; + else if (num_changed > 1) + out << indent << num_changed + << " Changed functions:\n\n"; + + for (string_changed_function_ptr_map::const_iterator i = + priv_->changed_fns_.begin(); + i != priv_->changed_fns_.end(); + ++i) + { + out << indent << " '" + << i->second.first->get_pretty_representation() + << "' was changed to '" + << i->second.second->get_pretty_representation() + << "':\n"; + { + function_decl_sptr f(i->second.first, noop_deleter()); + function_decl_sptr s(i->second.second, noop_deleter()); + + diff_sptr diff = compute_diff_for_decls(f, s, context()); + if (diff) + diff->report(out, indent + " "); + } + } + if (priv_->changed_fns_.size()) + out << "\n"; } - if (added) - out << "\n"; - if (num_changed == 1) - out << indent << "1 Changed function :\n\n"; - else if (num_changed > 1) - out << indent << num_changed - << " Changed functions:\n\n"; - - for (string_changed_function_ptr_map::const_iterator i = - priv_->changed_fns_.begin(); - i != priv_->changed_fns_.end(); - ++i) + if (context()->show_added_fns()) { - out << indent << " '" - << i->second.first->get_pretty_representation() - << "' was changed to '" - << i->second.second->get_pretty_representation() - << "':\n"; - { - function_decl_sptr f(i->second.first, noop_deleter()); - function_decl_sptr s(i->second.second, noop_deleter()); - - diff_sptr diff = compute_diff_for_decls(f, s, priv_->ctxt); - if (diff) - diff->report(out, indent + " "); - } + if (num_added == 1) + out << indent << "1 Added function:\n"; + else if (num_added > 1) + out << indent << num_added + << " Added functions:\n\n"; + for (string_function_ptr_map::const_iterator i = + priv_->added_fns_.begin(); + i != priv_->added_fns_.end(); + ++i) + { + out + << indent + << " '"; + if (total > large_num) + out << "[A] "; + out << i->second->get_pretty_representation() + << "\n"; + ++added; + } + if (added) + out << "\n"; } - if (priv_->changed_fns_.size()) - out << "\n"; - /// Report added/removed/changed variables. + // Report added/removed/changed variables. num_removed = priv_->deleted_vars_.size(); num_added = priv_->added_vars_.size(); num_changed = priv_->changed_vars_.size(); total = num_removed + num_added + num_changed; - if (num_removed == 1) - out << indent << "1 Deleted variable:\n"; - else if (num_removed > 1) - out << indent << num_removed - << " Deleted variables:\n\n"; - for (string_var_ptr_map::const_iterator i = - priv_->deleted_vars_.begin(); - i != priv_->deleted_vars_.end(); - ++i) + if (context()->show_deleted_vars()) { - out << indent - << " '"; - if (total > large_num) - out << "[D] "; - out << i->second->get_pretty_representation() - << "\n"; - ++removed; + if (num_removed == 1) + out << indent << "1 Deleted variable:\n"; + else if (num_removed > 1) + out << indent << num_removed + << " Deleted variables:\n\n"; + for (string_var_ptr_map::const_iterator i = + priv_->deleted_vars_.begin(); + i != priv_->deleted_vars_.end(); + ++i) + { + out << indent + << " '"; + if (total > large_num) + out << "[D] "; + out << i->second->get_pretty_representation() + << "\n"; + ++removed; + } + if (removed) + out << "\n"; } - if (removed) - out << "\n"; - if (num_added == 1) - out << indent << "1 Added variable:\n"; - else if (num_added > 1) - out << indent << num_added - << " Added variables:\n"; - for (string_var_ptr_map::const_iterator i = - priv_->added_vars_.begin(); - i != priv_->added_vars_.end(); - ++i) + if (context()->show_changed_vars()) { - out << indent - << " '"; - if (total > large_num) - out << "[A] "; - out << i->second->get_pretty_representation() - << "\n"; - ++added; - } - if (added) - out << "\n"; + if (num_changed == 1) + out << indent << "1 Changed variable:\n"; + else if (num_changed > 1) + out << indent << num_changed + << " Changed variables:\n\n"; + for (string_changed_var_ptr_map::const_iterator i = + priv_->changed_vars_.begin(); + i != priv_->changed_vars_.end(); + ++i) + { + out << indent << " '" + << i->second.first->get_pretty_representation() + << "' was changed to '" + << i->second.second->get_pretty_representation() + << "':\n"; + { + var_decl_sptr f(i->second.first, noop_deleter()); + var_decl_sptr s(i->second.second, noop_deleter()); - if (num_changed == 1) - out << indent << "1 Changed variable:\n"; - else if (num_changed > 1) - out << indent << num_changed - << " Changed variables:\n\n"; - for (string_changed_var_ptr_map::const_iterator i = - priv_->changed_vars_.begin(); - i != priv_->changed_vars_.end(); - ++i) + diff_sptr diff = compute_diff_for_decls(f, s, context()); + if (diff) + diff->report(out, indent + " "); + } + } + if (priv_->changed_vars_.size()) + out << "\n"; + } + + if (context()->show_added_vars()) { - out << indent << " '" - << i->second.first->get_pretty_representation() - << "' was changed to '" - << i->second.second->get_pretty_representation() - << "':\n"; - { - var_decl_sptr f(i->second.first, noop_deleter()); - var_decl_sptr s(i->second.second, noop_deleter()); - - diff_sptr diff = compute_diff_for_decls(f, s, priv_->ctxt); - if (diff) - diff->report(out, indent + " "); - } + if (num_added == 1) + out << indent << "1 Added variable:\n"; + else if (num_added > 1) + out << indent << num_added + << " Added variables:\n"; + for (string_var_ptr_map::const_iterator i = + priv_->added_vars_.begin(); + i != priv_->added_vars_.end(); + ++i) + { + out << indent + << " '"; + if (total > large_num) + out << "[A] "; + out << i->second->get_pretty_representation() + << "\n"; + ++added; + } + if (added) + out << "\n"; } - if (priv_->changed_vars_.size()) - out << "\n"; } /// Compute the diff between two instances fo the @ref corpus diff --git a/tools/bidiff.cc b/tools/bidiff.cc index 83f5aa8c..650cc5a5 100644 --- a/tools/bidiff.cc +++ b/tools/bidiff.cc @@ -48,9 +48,25 @@ struct options string file1; string file2; bool show_symtabs; + bool show_deleted_fns; + bool show_changed_fns; + bool show_added_fns; + bool show_all_fns; + bool show_deleted_vars; + bool show_changed_vars; + bool show_added_vars; + bool show_all_vars; options() - : show_symtabs(false) + : show_symtabs(false), + show_deleted_fns(false), + show_changed_fns(false), + show_added_fns(false), + show_all_fns(true), + show_deleted_vars(false), + show_changed_vars(false), + show_added_vars(false), + show_all_vars(true) {} };//end struct options; @@ -59,8 +75,14 @@ display_usage(const string prog_name, ostream& out) { out << "usage: " << prog_name << "[options] [ ]\n" << " where options can be:\n" - << " --show-symtabs only display the symbol tables of the corpora\n" - << " --help display this message\n"; + << " --symtabs only display the symbol tables of the corpora\n" + << " --deleted-fns display deleted public functions\n" + << " --changed-fns display changed public functions\n" + << " --added-fns display added public functions\n" + << " --deleted-vars display deleted global public variables\n" + << " --changed-vars display changed global public variables\n" + << " --added-vars display added global public variables\n" + << " --help display this message\n"; } /// Parse the command line and set the options accordingly. @@ -91,10 +113,46 @@ parse_command_line(int argc, char* argv[], options& opts) else return false; } - else if (!strcmp(argv[i], "--show-symtabs")) + else if (!strcmp(argv[i], "--symtabs")) opts.show_symtabs = true; else if (!strcmp(argv[i], "--help")) return false; + else if (!strcmp(argv[i], "--deleted-fns")) + { + opts.show_deleted_fns = true; + opts.show_all_fns = false; + opts.show_all_vars = false; + } + else if (!strcmp(argv[i], "--changed-fns")) + { + opts.show_changed_fns = true; + opts.show_all_fns = false; + opts.show_all_vars = false; + } + else if (!strcmp(argv[i], "--added-fns")) + { + opts.show_added_fns = true; + opts.show_all_fns = false; + opts.show_all_vars = false; + } + else if (!strcmp(argv[i], "--deleted-vars")) + { + opts.show_deleted_vars = true; + opts.show_all_fns = false; + opts.show_all_vars = false; + } + else if (!strcmp(argv[i], "--changed-vars")) + { + opts.show_changed_vars = true; + opts.show_all_fns = false; + opts.show_all_vars = false; + } + else if (!strcmp(argv[i], "--added-vars")) + { + opts.show_added_vars = true; + opts.show_all_fns = false; + opts.show_all_vars = false; + } else return false; } @@ -138,6 +196,50 @@ display_symtabs(const corpus_sptr c1, const corpus_sptr c2, ostream& o) o << (*i)->get_pretty_representation() << std::endl; } +using abigail::comparison::diff_context_sptr; +using abigail::comparison::diff_context; + +/// Update the diff context from the @ref options data structure. +/// +/// @param ctxt the diff context to update. +/// +/// @param opts the instance of @ref options to consider. +static void +set_diff_context_from_opts(diff_context_sptr ctxt, + options& opts) +{ + + if (opts.show_all_fns || opts.show_deleted_fns) + ctxt->show_deleted_fns(true); + else + ctxt->show_deleted_fns(false); + + if (opts.show_all_fns || opts.show_changed_fns) + ctxt->show_changed_fns(true); + else + ctxt->show_changed_fns(false); + + if (opts.show_all_fns || opts.show_added_fns) + ctxt->show_added_fns(true); + else + ctxt->show_added_fns(false); + + if (opts.show_all_vars || opts.show_deleted_vars) + ctxt->show_deleted_vars(true); + else + ctxt->show_deleted_vars(false); + + if (opts.show_all_vars || opts.show_changed_vars) + ctxt->show_changed_vars(true); + else + ctxt->show_changed_vars(false); + + if (opts.show_all_vars || opts.show_added_vars) + ctxt->show_added_vars(true); + else + ctxt->show_added_vars(false); +} + int main(int argc, char* argv[]) { @@ -248,7 +350,10 @@ main(int argc, char* argv[]) display_symtabs(c1, c2, cout); return false; } - corpus_diff_sptr changes = compute_diff(c1, c2); + + diff_context_sptr ctxt(new diff_context); + set_diff_context_from_opts(ctxt, opts); + corpus_diff_sptr changes = compute_diff(c1, c2, ctxt); changes->report(cout); }