xref: /linux-6.15/scripts/get_abi.py (revision aea5e52d)
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 t in parser.doc(args.raw, not args.no_file):
67            if args.enable_lineno:
68                print (f".. LINENO {t[1]}#{t[2]}\n\n")
69
70            print(t[0])
71
72class AbiValidate:
73    """Initialize an argparse subparser for ABI validation"""
74
75    def __init__(self, subparsers):
76        """Initialize argparse subparsers"""
77
78        parser = subparsers.add_parser("validate",
79                                       formatter_class=argparse.ArgumentDefaultsHelpFormatter,
80                                       description="list events")
81
82        parser.set_defaults(func=self.run)
83
84    def run(self, args):
85        """Run subparser"""
86
87        parser = AbiParser(args.dir, debug=args.debug)
88        parser.parse_abi()
89        parser.check_issues()
90
91
92class AbiSearch:
93    """Initialize an argparse subparser for ABI search"""
94
95    def __init__(self, subparsers):
96        """Initialize argparse subparsers"""
97
98        parser = subparsers.add_parser("search",
99                                       formatter_class=argparse.ArgumentDefaultsHelpFormatter,
100                                       description="Search ABI using a regular expression")
101
102        parser.add_argument("expression",
103                            help="Case-insensitive search pattern for the ABI symbol")
104
105        parser.set_defaults(func=self.run)
106
107    def run(self, args):
108        """Run subparser"""
109
110        parser = AbiParser(args.dir, debug=args.debug)
111        parser.parse_abi()
112        parser.search_symbols(args.expression)
113
114
115def main():
116    """Main program"""
117
118    parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter)
119
120    parser.add_argument("-d", "--debug", type=int, default=0, help="debug level")
121    parser.add_argument("-D", "--dir", default=ABI_DIR, help=DEBUG_HELP)
122
123    subparsers = parser.add_subparsers()
124
125    AbiRest(subparsers)
126    AbiValidate(subparsers)
127    AbiSearch(subparsers)
128
129    args = parser.parse_args()
130
131    if args.debug:
132        level = logging.DEBUG
133    else:
134        level = logging.INFO
135
136    logging.basicConfig(level=level, format="[%(levelname)s] %(message)s")
137
138    if "func" in args:
139        args.func(args)
140    else:
141        sys.exit(f"Please specify a valid command for {sys.argv[0]}")
142
143
144# Call main method
145if __name__ == "__main__":
146    main()
147