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