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