mirror of https://github.com/torvalds/linux.git
226 lines
7.5 KiB
Python
Executable File
226 lines
7.5 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
# pylint: disable=R0902,R0911,R0912,R0914,R0915
|
|
# Copyright(c) 2025: Mauro Carvalho Chehab <mchehab@kernel.org>.
|
|
# SPDX-License-Identifier: GPL-2.0
|
|
|
|
|
|
"""
|
|
Parse the Linux Feature files and produce a ReST book.
|
|
"""
|
|
|
|
import argparse
|
|
import os
|
|
import subprocess
|
|
import sys
|
|
|
|
from pprint import pprint
|
|
|
|
LIB_DIR = "../../tools/lib/python"
|
|
SRC_DIR = os.path.dirname(os.path.realpath(__file__))
|
|
|
|
sys.path.insert(0, os.path.join(SRC_DIR, LIB_DIR))
|
|
|
|
from feat.parse_features import ParseFeature # pylint: disable=C0413
|
|
|
|
SRCTREE = os.path.join(os.path.dirname(os.path.realpath(__file__)), "../..")
|
|
DEFAULT_DIR = "Documentation/features"
|
|
|
|
|
|
class GetFeature:
|
|
"""Helper class to parse feature parsing parameters"""
|
|
|
|
@staticmethod
|
|
def get_current_arch():
|
|
"""Detects the current architecture"""
|
|
|
|
proc = subprocess.run(["uname", "-m"], check=True,
|
|
capture_output=True, text=True)
|
|
|
|
arch = proc.stdout.strip()
|
|
if arch in ["x86_64", "i386"]:
|
|
arch = "x86"
|
|
elif arch == "s390x":
|
|
arch = "s390"
|
|
|
|
return arch
|
|
|
|
def run_parser(self, args):
|
|
"""Execute the feature parser"""
|
|
|
|
feat = ParseFeature(args.directory, args.debug, args.enable_fname)
|
|
data = feat.parse()
|
|
|
|
if args.debug > 2:
|
|
pprint(data)
|
|
|
|
return feat
|
|
|
|
def run_rest(self, args):
|
|
"""
|
|
Generate tables in ReST format. Three types of tables are
|
|
supported, depending on the calling arguments:
|
|
|
|
- neither feature nor arch is passed: generates a full matrix;
|
|
- arch provided: generates a table of supported tables for the
|
|
guiven architecture, eventually filtered by feature;
|
|
- only feature provided: generates a table with feature details,
|
|
showing what architectures it is implemented.
|
|
"""
|
|
|
|
feat = self.run_parser(args)
|
|
|
|
if args.arch:
|
|
rst = feat.output_arch_table(args.arch, args.feat)
|
|
elif args.feat:
|
|
rst = feat.output_feature(args.feat)
|
|
else:
|
|
rst = feat.output_matrix()
|
|
|
|
print(rst)
|
|
|
|
def run_current(self, args):
|
|
"""
|
|
Instead of using a --arch parameter, get feature for the current
|
|
architecture.
|
|
"""
|
|
|
|
args.arch = self.get_current_arch()
|
|
|
|
self.run_rest(args)
|
|
|
|
def run_list(self, args):
|
|
"""
|
|
Generate a list of features for a given architecture, in a format
|
|
parseable by other scripts. The output format is not ReST.
|
|
"""
|
|
|
|
if not args.arch:
|
|
args.arch = self.get_current_arch()
|
|
|
|
feat = self.run_parser(args)
|
|
msg = feat.list_arch_features(args.arch, args.feat)
|
|
|
|
print(msg)
|
|
|
|
def parse_arch(self, parser):
|
|
"""Add a --arch parsing argument"""
|
|
|
|
parser.add_argument("--arch",
|
|
help="Output features for an specific"
|
|
" architecture, optionally filtering for a "
|
|
"single specific feature.")
|
|
|
|
def parse_feat(self, parser):
|
|
"""Add a --feat parsing argument"""
|
|
|
|
parser.add_argument("--feat", "--feature",
|
|
help="Output features for a single specific "
|
|
"feature.")
|
|
|
|
|
|
def current_args(self, subparsers):
|
|
"""Implementscurrent argparse subparser"""
|
|
|
|
parser = subparsers.add_parser("current",
|
|
formatter_class=argparse.RawTextHelpFormatter,
|
|
description="Output table in ReST "
|
|
"compatible ASCII format "
|
|
"with features for this "
|
|
"machine's architecture")
|
|
|
|
self.parse_feat(parser)
|
|
parser.set_defaults(func=self.run_current)
|
|
|
|
def rest_args(self, subparsers):
|
|
"""Implement rest argparse subparser"""
|
|
|
|
parser = subparsers.add_parser("rest",
|
|
formatter_class=argparse.RawTextHelpFormatter,
|
|
description="Output table(s) in ReST "
|
|
"compatible ASCII format "
|
|
"with features in ReST "
|
|
"markup language. The "
|
|
"output is affected by "
|
|
"--arch or --feat/--feature"
|
|
" flags.")
|
|
|
|
self.parse_arch(parser)
|
|
self.parse_feat(parser)
|
|
parser.set_defaults(func=self.run_rest)
|
|
|
|
def list_args(self, subparsers):
|
|
"""Implement list argparse subparser"""
|
|
|
|
parser = subparsers.add_parser("list",
|
|
formatter_class=argparse.RawTextHelpFormatter,
|
|
description="List features for this "
|
|
"machine's architecture, "
|
|
"using an easier to parse "
|
|
"format. The output is "
|
|
"affected by --arch flag.")
|
|
|
|
self.parse_arch(parser)
|
|
self.parse_feat(parser)
|
|
parser.set_defaults(func=self.run_list)
|
|
|
|
def validate_args(self, subparsers):
|
|
"""Implement validate argparse subparser"""
|
|
|
|
parser = subparsers.add_parser("validate",
|
|
formatter_class=argparse.RawTextHelpFormatter,
|
|
description="Validate the contents of "
|
|
"the files under "
|
|
f"{DEFAULT_DIR}.")
|
|
|
|
parser.set_defaults(func=self.run_parser)
|
|
|
|
def parser(self):
|
|
"""
|
|
Create an arparse with common options and several subparsers
|
|
"""
|
|
parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter)
|
|
|
|
parser.add_argument("-d", "--debug", action="count", default=0,
|
|
help="Put the script in verbose mode, useful for "
|
|
"debugging. Can be called multiple times, to "
|
|
"increase verbosity.")
|
|
|
|
parser.add_argument("--directory", "--dir", default=DEFAULT_DIR,
|
|
help="Changes the location of the Feature files. "
|
|
f"By default, it uses the {DEFAULT_DIR} "
|
|
"directory.")
|
|
|
|
parser.add_argument("--enable-fname", action="store_true",
|
|
help="Prints the file name of the feature files. "
|
|
"This can be used in order to track "
|
|
"dependencies during documentation build.")
|
|
|
|
subparsers = parser.add_subparsers()
|
|
|
|
self.current_args(subparsers)
|
|
self.rest_args(subparsers)
|
|
self.list_args(subparsers)
|
|
self.validate_args(subparsers)
|
|
|
|
args = parser.parse_args()
|
|
|
|
return args
|
|
|
|
|
|
def main():
|
|
"""Main program"""
|
|
|
|
feat = GetFeature()
|
|
|
|
args = feat.parser()
|
|
|
|
if "func" in args:
|
|
args.func(args)
|
|
else:
|
|
sys.exit(f"Please specify a valid command for {sys.argv[0]}")
|
|
|
|
|
|
# Call main method
|
|
if __name__ == "__main__":
|
|
main()
|