1# -*- Python -*- vim: set syntax=python tabstop=4 expandtab cc=80: 2""" 3diff - A set of functions for diff-ing two symbol lists. 4""" 5 6from sym_check import util 7 8 9def _symbol_difference(lhs, rhs): 10 lhs_names = set((n['name'] for n in lhs)) 11 rhs_names = set((n['name'] for n in rhs)) 12 diff_names = lhs_names - rhs_names 13 return [n for n in lhs if n['name'] in diff_names] 14 15 16def _find_by_key(sym_list, k): 17 for sym in sym_list: 18 if sym['name'] == k: 19 return sym 20 return None 21 22 23def added_symbols(old, new): 24 return _symbol_difference(new, old) 25 26 27def removed_symbols(old, new): 28 return _symbol_difference(old, new) 29 30 31def changed_symbols(old, new): 32 changed = [] 33 for old_sym in old: 34 if old_sym in new: 35 continue 36 new_sym = _find_by_key(new, old_sym['name']) 37 if (new_sym is not None and not new_sym in old 38 and cmp(old_sym, new_sym) != 0): 39 changed += [(old_sym, new_sym)] 40 return changed 41 42 43def diff(old, new): 44 added = added_symbols(old, new) 45 removed = removed_symbols(old, new) 46 changed = changed_symbols(old, new) 47 return added, removed, changed 48 49 50def report_diff(added_syms, removed_syms, changed_syms, names_only=False, 51 demangle=True): 52 def maybe_demangle(name): 53 return util.demangle_symbol(name) if demangle else name 54 55 report = '' 56 for sym in added_syms: 57 report += 'Symbol added: %s\n' % maybe_demangle(sym['name']) 58 if not names_only: 59 report += ' %s\n\n' % sym 60 if added_syms and names_only: 61 report += '\n' 62 for sym in removed_syms: 63 report += 'SYMBOL REMOVED: %s\n' % maybe_demangle(sym['name']) 64 if not names_only: 65 report += ' %s\n\n' % sym 66 if removed_syms and names_only: 67 report += '\n' 68 if not names_only: 69 for sym_pair in changed_syms: 70 old_sym, new_sym = sym_pair 71 old_str = '\n OLD SYMBOL: %s' % old_sym 72 new_str = '\n NEW SYMBOL: %s' % new_sym 73 report += ('SYMBOL CHANGED: %s%s%s\n\n' % 74 (maybe_demangle(old_sym['name']), 75 old_str, new_str)) 76 77 added = bool(len(added_syms) != 0) 78 abi_break = bool(len(removed_syms)) 79 if not names_only: 80 abi_break = abi_break or len(changed_syms) 81 if added or abi_break: 82 report += 'Summary\n' 83 report += ' Added: %d\n' % len(added_syms) 84 report += ' Removed: %d\n' % len(removed_syms) 85 if not names_only: 86 report += ' Changed: %d\n' % len(changed_syms) 87 if not abi_break: 88 report += 'Symbols added.' 89 else: 90 report += 'ABI BREAKAGE: SYMBOLS ADDED OR REMOVED!' 91 else: 92 report += 'Symbols match.' 93 return report, int(abi_break) 94