1#!/usr/bin/env python3
2#
3# Copyright (c) 2022 Kumar Gala <galak@kernel.org>
4#
5# SPDX-License-Identifier: Apache-2.0
6
7import argparse
8import os
9import sys
10import re
11
12import yaml
13try:
14    # Use the C LibYAML parser if available, rather than the Python parser.
15    from yaml import CSafeLoader as SafeLoader
16except ImportError:
17    from yaml import SafeLoader     # type: ignore
18
19sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'python-devicetree',
20                                'src'))
21
22def binding_paths(bindings_dirs):
23    # Returns a list with the paths to all bindings (.yaml files) in
24    # 'bindings_dirs'
25
26    binding_paths = []
27
28    for bindings_dir in bindings_dirs:
29        for root, _, filenames in os.walk(bindings_dir):
30            for filename in filenames:
31                if filename.endswith(".yaml") or filename.endswith(".yml"):
32                    binding_paths.append(os.path.join(root, filename))
33
34    return binding_paths
35
36def parse_args():
37    # Returns parsed command-line arguments
38
39    parser = argparse.ArgumentParser(allow_abbrev=False)
40    parser.add_argument("--kconfig-out", required=True,
41                        help="path to write the Kconfig file")
42    parser.add_argument("--bindings-dirs", nargs='+', required=True,
43                        help="directory with bindings in YAML format, "
44                        "we allow multiple")
45
46    return parser.parse_args()
47
48def printfile(s):
49    print(s, file=kconfig_file)
50
51def str2ident(s):
52    # Converts 's' to a form suitable for (part of) an identifier
53
54    return re.sub('[-,.@/+]', '_', s.upper())
55
56def compat2kconfig(compat):
57    compat_ident = str2ident(compat)
58
59    printfile(f'')
60    printfile(f'DT_COMPAT_{compat_ident} := {compat}')
61    printfile(f'')
62    printfile(f'config DT_HAS_{compat_ident}_ENABLED')
63    printfile(f'\tdef_bool $(dt_compat_enabled,$(DT_COMPAT_{compat_ident}))')
64
65def main():
66    global kconfig_file
67    args = parse_args()
68
69    compat_list = []
70
71    for binding_path in binding_paths(args.bindings_dirs):
72        with open(binding_path, encoding="utf-8") as f:
73            contents = f.read()
74
75            try:
76                # Parsed PyYAML output (Python lists/dictionaries/strings/etc.,
77                # representing the file)
78                raw = yaml.load(contents, Loader=SafeLoader)
79            except yaml.YAMLError as e:
80                print(f"WARNING: '{binding_path}' appears in binding "
81                      f"directories but isn't valid YAML: {e}")
82                continue
83        if raw is None or 'compatible' not in raw:
84            continue
85
86        compat_list.append(raw['compatible'])
87
88    # Remove any duplicates and sort the list
89    compat_list = sorted(set(compat_list))
90
91    with open(args.kconfig_out, "w", encoding="utf-8") as kconfig_file:
92        printfile(f'# Generated devicetree Kconfig')
93        printfile(f'#')
94        printfile(f'# SPDX-License-Identifier: Apache-2.0')
95
96        for c in compat_list:
97            compat2kconfig(c)
98
99
100if __name__ == "__main__":
101    main()
102