xref: /linux-6.15/scripts/get_abi.py (revision ee34f830)
1#!/usr/bin/env python3
2# pylint: disable=R0903
3# Copyright(c) 2025: Mauro Carvalho Chehab <[email protected]>.
4# SPDX-License-Identifier: GPL-2.0
5
6"""
7Parse ABI documentation and produce results from it.
8"""
9
10import argparse
11import logging
12import os
13import sys
14
15# Import Python modules
16
17LIB_DIR = "lib/abi"
18SRC_DIR = os.path.dirname(os.path.realpath(__file__))
19
20sys.path.insert(0, os.path.join(SRC_DIR, LIB_DIR))
21
22from abi_parser import AbiParser                # pylint: disable=C0413
23from helpers import ABI_DIR, DEBUG_HELP         # pylint: disable=C0413
24
25# Command line classes
26
27
28REST_DESC = """
29Produce output in ReST format.
30
31The output is done on two sections:
32
33- Symbols: show all parsed symbols in alphabetic order;
34- Files: cross reference the content of each file with the symbols on it.
35"""
36
37class AbiRest:
38    """Initialize an argparse subparser for rest output"""
39
40    def __init__(self, subparsers):
41        """Initialize argparse subparsers"""
42
43        parser = subparsers.add_parser("rest",
44                                       formatter_class=argparse.RawTextHelpFormatter,
45                                       description=REST_DESC)
46
47        parser.add_argument("--enable-lineno",  action="store_true",
48                            help="enable lineno")
49        parser.add_argument("--raw", action="store_true",
50                            help="output text as contained in the ABI files. "
51                                 "It not used, output will contain dynamically"
52                                 " generated cross references when possible.")
53        parser.add_argument("--no-file", action="store_true",
54                            help="Don't the files section")
55        parser.add_argument("--show-hints", help="Show-hints")
56
57        parser.set_defaults(func=self.run)
58
59    def run(self, args):
60        """Run subparser"""
61
62        parser = AbiParser(args.dir, debug=args.debug)
63        parser.parse_abi()
64        parser.check_issues()
65
66        for msg in parser.doc(args.enable_lineno, args.raw, not args.no_file):
67            print(msg)
68
69class AbiValidate:
70    """Initialize an argparse subparser for ABI validation"""
71
72    def __init__(self, subparsers):
73        """Initialize argparse subparsers"""
74
75        parser = subparsers.add_parser("validate",
76                                       formatter_class=argparse.ArgumentDefaultsHelpFormatter,
77                                       description="list events")
78
79        parser.set_defaults(func=self.run)
80
81    def run(self, args):
82        """Run subparser"""
83
84        parser = AbiParser(args.dir, debug=args.debug)
85        parser.parse_abi()
86        parser.check_issues()
87
88
89class AbiSearch:
90    """Initialize an argparse subparser for ABI search"""
91
92    def __init__(self, subparsers):
93        """Initialize argparse subparsers"""
94
95        parser = subparsers.add_parser("search",
96                                       formatter_class=argparse.ArgumentDefaultsHelpFormatter,
97                                       description="Search ABI using a regular expression")
98
99        parser.add_argument("expression",
100                            help="Case-insensitive search pattern for the ABI symbol")
101
102        parser.set_defaults(func=self.run)
103
104    def run(self, args):
105        """Run subparser"""
106
107        parser = AbiParser(args.dir, debug=args.debug)
108        parser.parse_abi()
109        parser.search_symbols(args.expression)
110
111
112def main():
113    """Main program"""
114
115    parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter)
116
117    parser.add_argument("-d", "--debug", type=int, default=0, help="debug level")
118    parser.add_argument("-D", "--dir", default=ABI_DIR, help=DEBUG_HELP)
119
120    subparsers = parser.add_subparsers()
121
122    AbiRest(subparsers)
123    AbiValidate(subparsers)
124    AbiSearch(subparsers)
125
126    args = parser.parse_args()
127
128    if args.debug:
129        level = logging.DEBUG
130    else:
131        level = logging.INFO
132
133    logging.basicConfig(level=level, format="[%(levelname)s] %(message)s")
134
135    if "func" in args:
136        args.func(args)
137    else:
138        sys.exit(f"Please specify a valid command for {sys.argv[0]}")
139
140
141# Call main method
142if __name__ == "__main__":
143    main()
144