#!/usr/bin/env python3 # This file is part of Elixir, a source code cross-referencer. # # Copyright (C) 2017 Mikaƫl Bouillot # # # Elixir is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # Elixir is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with Elixir. If not, see . import subprocess, os CURRENT_DIR = os.path.dirname(os.path.abspath(__file__)) def script(*args): args = (os.path.join(CURRENT_DIR, 'script.sh'),) + args # subprocess.run was introduced in Python 3.5 # fall back to subprocess.check_output if it's not available if hasattr(subprocess, 'run'): p = subprocess.run(args, stdout=subprocess.PIPE) p = p.stdout else: p = subprocess.check_output(args) return p # Invoke ./script.sh with the given arguments # Returns the list of output lines def scriptLines(*args): p = script(*args) p = p.split(b'\n') del p[-1] return p def unescape(bstr): subs = ( ('\1','\n'), ) for a,b in subs: a = a.encode() b = b.encode() bstr = bstr.replace(a, b) return bstr # List of tokens which we don't want to consider as identifiers # Typically for very frequent variable names and things redefined by #define # TODO: allow to have per project blacklists blacklist = ( b'if', b'else', b'endif', b'dev', b'i', b'ret', b'err', b'flags', b'h', b'data', b'const', b'skb', b'len', b'name', b'priv', b'p', b'val', b'info', b'buf', b'rc', b'type', b'out', b'cmd', b'port', b'size', b'page', b'tp', b'pdev', b'state', b'addr', b'rdev', b'sk', b'count', b'hw', b'lock', b'error', b'reg', b's', b'id', b'tmp', b'codec', b'req', b'bp', b'c', b'chip', b'r', b'n', b'value', b'start', b'index', b'res', b'regs', b'j', b'base', b'irq', b'x', b'net', b'mode', b'vcpu', b'host', b'spec', b'card', b'sb', b'mask', b'list', b'ops', b'next', b'ctx', b'event', b'q', b'attr', b'cpu', b'desc', b'msg', b't', b'entry', b'arg', b'idx', b'end', b'root', b'struct', b'static', b'define', b'NULL', b'sizeof', b'status', b'adapter', b'inline', b'offset', b'failed', b'retval', b'buffer', b'length', b'result', b'extern', b'driver', b'ptr', b'return', ) def isIdent(bstr): if len(bstr) < 2: return False elif bstr in blacklist: return False else: return True def autoBytes(arg): if type(arg) is str: arg = arg.encode() elif type(arg) is int: arg = str(arg).encode() return arg def getDataDir(): try: dir=os.environ['LXR_DATA_DIR'] except KeyError: print(argv[0] + ': LXR_DATA_DIR needs to be set') exit(1) return dir def currentProject(): return os.path.basename(os.path.dirname(getDataDir())) def getFileFamily(filename): name, ext = os.path.splitext(filename) if ext.lower() in ['.c', '.cc', '.cpp', '.c++', '.cxx', '.h', '.s'] : return 'C' # C file family and ASM elif ext.lower() in ['.dts', '.dtsi'] : return 'D' # Devicetree files elif name.lower()[:7] in ['kconfig'] and not ext.lower() in ['.rst']: # Some files are named like Kconfig-nommu so we only check the first 7 letters # We also exclude documentation files that can be named kconfig return 'K' # Kconfig files else : return None compatibility_list = { 'C' : ['C', 'K'], 'K' : ['K'], 'D' : ['D'] } # Check if families are compatible # First argument can be a list of different families # Second argument is the key for chossing the right array in the compatibility list def compatibleFamily(file_family, requested_family): return any(item in file_family for item in compatibility_list[requested_family])