|  | #!/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() |