# -*- Python -*- vim: set syntax=python tabstop=4 expandtab cc=80: """ diff - A set of functions for diff-ing two symbol lists. """ from sym_check import util def _symbol_difference(lhs, rhs): lhs_names = set((n['name'] for n in lhs)) rhs_names = set((n['name'] for n in rhs)) diff_names = lhs_names - rhs_names return [n for n in lhs if n['name'] in diff_names] def _find_by_key(sym_list, k): for sym in sym_list: if sym['name'] == k: return sym return None def added_symbols(old, new): return _symbol_difference(new, old) def removed_symbols(old, new): return _symbol_difference(old, new) def changed_symbols(old, new): changed = [] for old_sym in old: if old_sym in new: continue new_sym = _find_by_key(new, old_sym['name']) if (new_sym is not None and not new_sym in old and cmp(old_sym, new_sym) != 0): changed += [(old_sym, new_sym)] return changed def diff(old, new): added = added_symbols(old, new) removed = removed_symbols(old, new) changed = changed_symbols(old, new) return added, removed, changed def report_diff(added_syms, removed_syms, changed_syms, names_only=False, demangle=True): def maybe_demangle(name): return util.demangle_symbol(name) if demangle else name report = '' for sym in added_syms: report += 'Symbol added: %s\n' % maybe_demangle(sym['name']) if not names_only: report += ' %s\n\n' % sym if added_syms and names_only: report += '\n' for sym in removed_syms: report += 'SYMBOL REMOVED: %s\n' % maybe_demangle(sym['name']) if not names_only: report += ' %s\n\n' % sym if removed_syms and names_only: report += '\n' if not names_only: for sym_pair in changed_syms: old_sym, new_sym = sym_pair old_str = '\n OLD SYMBOL: %s' % old_sym new_str = '\n NEW SYMBOL: %s' % new_sym report += ('SYMBOL CHANGED: %s%s%s\n\n' % (maybe_demangle(old_sym['name']), old_str, new_str)) added = bool(len(added_syms) != 0) abi_break = bool(len(removed_syms)) if not names_only: abi_break = abi_break or len(changed_syms) if added or abi_break: report += 'Summary\n' report += ' Added: %d\n' % len(added_syms) report += ' Removed: %d\n' % len(removed_syms) if not names_only: report += ' Changed: %d\n' % len(changed_syms) if not abi_break: report += 'Symbols added.' else: report += 'ABI BREAKAGE: SYMBOLS ADDED OR REMOVED!' else: report += 'Symbols match.' return report, int(abi_break)