| #!/usr/bin/env python3 | 
 | # -*- coding: utf-8 -*- | 
 | # | 
 | # Copyright (C) 2017-2020  The Project X-Ray Authors. | 
 | # | 
 | # Use of this source code is governed by a ISC-style | 
 | # license that can be found in the LICENSE file or at | 
 | # https://opensource.org/licenses/ISC | 
 | # | 
 | # SPDX-License-Identifier: ISC | 
 |  | 
 | import sys, os, re | 
 | from prjxray.util import OpenSafeFile, parse_db_lines, write_db_lines | 
 |  | 
 |  | 
 | def index_masks(fn_in, groups_in): | 
 |     """Return a dictionary with the bits active in each group for the specified list of groups""" | 
 |     # Only analyze the given groups | 
 |     groups = {} | 
 |     for group in groups_in: | 
 |         groups[group] = set() | 
 |  | 
 |     # Index bits | 
 |     for line, (tag, bits, mode) in parse_db_lines(fn_in): | 
 |         assert not mode, "Unresolved tag: %s" % (line, ) | 
 |         prefix = tag[0:tag.rfind(".")] | 
 |         group = groups.get(prefix, None) | 
 |         # Drop groups we aren't interested in | 
 |         if group is None: | 
 |             continue | 
 |         for bit in bits: | 
 |             bit = bit.replace("!", "") | 
 |             group.add(bit) | 
 |  | 
 |     # Verify we were able to find all groups | 
 |     for groupk, groupv in groups.items(): | 
 |         assert len(groupv), "Bad group %s" % groupk | 
 |  | 
 |     return groups | 
 |  | 
 |  | 
 | def apply_masks(fn_in, groups): | 
 |     """Add 0 entries ("!") to .db entries based on groups definition""" | 
 |     new_db = {} | 
 |     for line, (tag, bits, mode) in parse_db_lines(fn_in): | 
 |         assert not mode, "Unresolved tag: %s" % (line, ) | 
 |         prefix = tag[0:tag.rfind(".")] | 
 |         group = groups.get(prefix, None) | 
 |         if group: | 
 |             bits = set(bits) | 
 |             for bit in group: | 
 |                 if bit not in bits: | 
 |                     bits.add("!" + bit) | 
 |             bits = frozenset(bits) | 
 |         new_db[tag] = bits | 
 |     return new_db | 
 |  | 
 |  | 
 | def load_groups(fn): | 
 |     ret = [] | 
 |     with OpenSafeFile(fn, "r") as f: | 
 |         for l in f: | 
 |             ret.append(l.strip()) | 
 |     return ret | 
 |  | 
 |  | 
 | def run(fn_in, fn_out, groups_fn, verbose=False): | 
 |     groups_in = load_groups(groups_fn) | 
 |     groups = index_masks(fn_in, groups_in) | 
 |     new_db = apply_masks(fn_in, groups) | 
 |     write_db_lines(fn_out, new_db) | 
 |  | 
 |  | 
 | def main(): | 
 |     import argparse | 
 |  | 
 |     parser = argparse.ArgumentParser(description='Create multi-bit entries') | 
 |     parser.add_argument('--verbose', action='store_true', help='') | 
 |     parser.add_argument( | 
 |         '--groups-fn', | 
 |         default="groups.grp", | 
 |         help='File containing one group per line to parse') | 
 |     parser.add_argument('fn_in', help='') | 
 |     parser.add_argument('fn_out', help='') | 
 |     args = parser.parse_args() | 
 |  | 
 |     run(args.fn_in, args.fn_out, args.groups_fn, verbose=args.verbose) | 
 |  | 
 |  | 
 | if __name__ == '__main__': | 
 |     main() |