1*b6acf807SRob Herring#!/usr/bin/env python3 2*b6acf807SRob Herring# SPDX-License-Identifier: GPL-2.0-only 3*b6acf807SRob Herring 4*b6acf807SRob Herringimport os 5*b6acf807SRob Herringimport glob 6*b6acf807SRob Herringimport re 7*b6acf807SRob Herringimport argparse 8*b6acf807SRob Herring 9*b6acf807SRob Herring 10*b6acf807SRob Herringdef parse_of_declare_macros(data): 11*b6acf807SRob Herring """ Find all compatible strings in OF_DECLARE() style macros """ 12*b6acf807SRob Herring compat_list = [] 13*b6acf807SRob Herring # CPU_METHOD_OF_DECLARE does not have a compatible string 14*b6acf807SRob Herring for m in re.finditer(r'(?<!CPU_METHOD_)(IRQCHIP|OF)_(DECLARE|MATCH)(_DRIVER)?\(.*?\)', data): 15*b6acf807SRob Herring try: 16*b6acf807SRob Herring compat = re.search(r'"(.*?)"', m[0])[1] 17*b6acf807SRob Herring except: 18*b6acf807SRob Herring # Fails on compatible strings in #define, so just skip 19*b6acf807SRob Herring continue 20*b6acf807SRob Herring compat_list += [compat] 21*b6acf807SRob Herring 22*b6acf807SRob Herring return compat_list 23*b6acf807SRob Herring 24*b6acf807SRob Herring 25*b6acf807SRob Herringdef parse_of_device_id(data): 26*b6acf807SRob Herring """ Find all compatible strings in of_device_id structs """ 27*b6acf807SRob Herring compat_list = [] 28*b6acf807SRob Herring for m in re.finditer(r'of_device_id\s+[a-zA-Z0-9_]+\[\]\s*=\s*({.*?);', data): 29*b6acf807SRob Herring compat_list += re.findall(r'\.compatible\s+=\s+"([a-zA-Z0-9_\-,]+)"', m[1]) 30*b6acf807SRob Herring 31*b6acf807SRob Herring return compat_list 32*b6acf807SRob Herring 33*b6acf807SRob Herring 34*b6acf807SRob Herringdef parse_compatibles(file): 35*b6acf807SRob Herring with open(file, 'r', encoding='utf-8') as f: 36*b6acf807SRob Herring data = f.read().replace('\n', '') 37*b6acf807SRob Herring 38*b6acf807SRob Herring compat_list = parse_of_declare_macros(data) 39*b6acf807SRob Herring compat_list += parse_of_device_id(data) 40*b6acf807SRob Herring 41*b6acf807SRob Herring return compat_list 42*b6acf807SRob Herring 43*b6acf807SRob Herringdef print_compat(filename, compatibles): 44*b6acf807SRob Herring if not compatibles: 45*b6acf807SRob Herring return 46*b6acf807SRob Herring if show_filename: 47*b6acf807SRob Herring compat_str = ' '.join(compatibles) 48*b6acf807SRob Herring print(filename + ": compatible(s): " + compat_str) 49*b6acf807SRob Herring else: 50*b6acf807SRob Herring print(*compatibles, sep='\n') 51*b6acf807SRob Herring 52*b6acf807SRob Herringshow_filename = False 53*b6acf807SRob Herring 54*b6acf807SRob Herringif __name__ == "__main__": 55*b6acf807SRob Herring ap = argparse.ArgumentParser() 56*b6acf807SRob Herring ap.add_argument("cfile", type=str, nargs='*', help="C source files or directories to parse") 57*b6acf807SRob Herring ap.add_argument('-H', '--with-filename', help="Print filename with compatibles", action="store_true") 58*b6acf807SRob Herring args = ap.parse_args() 59*b6acf807SRob Herring 60*b6acf807SRob Herring show_filename = args.with_filename 61*b6acf807SRob Herring 62*b6acf807SRob Herring for f in args.cfile: 63*b6acf807SRob Herring if os.path.isdir(f): 64*b6acf807SRob Herring for filename in glob.iglob(f + "/**/*.c", recursive=True): 65*b6acf807SRob Herring compat_list = parse_compatibles(filename) 66*b6acf807SRob Herring print_compat(filename, compat_list) 67*b6acf807SRob Herring else: 68*b6acf807SRob Herring compat_list = parse_compatibles(f) 69*b6acf807SRob Herring print_compat(f, compat_list) 70