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