1*2b2765acSPeter Maydell#!/usr/bin/env python3 2*2b2765acSPeter Maydell# SPDX-License-Identifier: GPL-2.0 3*2b2765acSPeter Maydell# Copyright(c) 2025: Mauro Carvalho Chehab <mchehab@kernel.org>. 4*2b2765acSPeter Maydell# 5*2b2765acSPeter Maydell# pylint: disable=C0103,R0915 6*2b2765acSPeter Maydell# 7*2b2765acSPeter Maydell# Converted from the kernel-doc script originally written in Perl 8*2b2765acSPeter Maydell# under GPLv2, copyrighted since 1998 by the following authors: 9*2b2765acSPeter Maydell# 10*2b2765acSPeter Maydell# Aditya Srivastava <yashsri421@gmail.com> 11*2b2765acSPeter Maydell# Akira Yokosawa <akiyks@gmail.com> 12*2b2765acSPeter Maydell# Alexander A. Klimov <grandmaster@al2klimov.de> 13*2b2765acSPeter Maydell# Alexander Lobakin <aleksander.lobakin@intel.com> 14*2b2765acSPeter Maydell# André Almeida <andrealmeid@igalia.com> 15*2b2765acSPeter Maydell# Andy Shevchenko <andriy.shevchenko@linux.intel.com> 16*2b2765acSPeter Maydell# Anna-Maria Behnsen <anna-maria@linutronix.de> 17*2b2765acSPeter Maydell# Armin Kuster <akuster@mvista.com> 18*2b2765acSPeter Maydell# Bart Van Assche <bart.vanassche@sandisk.com> 19*2b2765acSPeter Maydell# Ben Hutchings <ben@decadent.org.uk> 20*2b2765acSPeter Maydell# Borislav Petkov <bbpetkov@yahoo.de> 21*2b2765acSPeter Maydell# Chen-Yu Tsai <wenst@chromium.org> 22*2b2765acSPeter Maydell# Coco Li <lixiaoyan@google.com> 23*2b2765acSPeter Maydell# Conchúr Navid <conchur@web.de> 24*2b2765acSPeter Maydell# Daniel Santos <daniel.santos@pobox.com> 25*2b2765acSPeter Maydell# Danilo Cesar Lemes de Paula <danilo.cesar@collabora.co.uk> 26*2b2765acSPeter Maydell# Dan Luedtke <mail@danrl.de> 27*2b2765acSPeter Maydell# Donald Hunter <donald.hunter@gmail.com> 28*2b2765acSPeter Maydell# Gabriel Krisman Bertazi <krisman@collabora.co.uk> 29*2b2765acSPeter Maydell# Greg Kroah-Hartman <gregkh@linuxfoundation.org> 30*2b2765acSPeter Maydell# Harvey Harrison <harvey.harrison@gmail.com> 31*2b2765acSPeter Maydell# Horia Geanta <horia.geanta@freescale.com> 32*2b2765acSPeter Maydell# Ilya Dryomov <idryomov@gmail.com> 33*2b2765acSPeter Maydell# Jakub Kicinski <kuba@kernel.org> 34*2b2765acSPeter Maydell# Jani Nikula <jani.nikula@intel.com> 35*2b2765acSPeter Maydell# Jason Baron <jbaron@redhat.com> 36*2b2765acSPeter Maydell# Jason Gunthorpe <jgg@nvidia.com> 37*2b2765acSPeter Maydell# Jérémy Bobbio <lunar@debian.org> 38*2b2765acSPeter Maydell# Johannes Berg <johannes.berg@intel.com> 39*2b2765acSPeter Maydell# Johannes Weiner <hannes@cmpxchg.org> 40*2b2765acSPeter Maydell# Jonathan Cameron <Jonathan.Cameron@huawei.com> 41*2b2765acSPeter Maydell# Jonathan Corbet <corbet@lwn.net> 42*2b2765acSPeter Maydell# Jonathan Neuschäfer <j.neuschaefer@gmx.net> 43*2b2765acSPeter Maydell# Kamil Rytarowski <n54@gmx.com> 44*2b2765acSPeter Maydell# Kees Cook <kees@kernel.org> 45*2b2765acSPeter Maydell# Laurent Pinchart <laurent.pinchart@ideasonboard.com> 46*2b2765acSPeter Maydell# Levin, Alexander (Sasha Levin) <alexander.levin@verizon.com> 47*2b2765acSPeter Maydell# Linus Torvalds <torvalds@linux-foundation.org> 48*2b2765acSPeter Maydell# Lucas De Marchi <lucas.demarchi@profusion.mobi> 49*2b2765acSPeter Maydell# Mark Rutland <mark.rutland@arm.com> 50*2b2765acSPeter Maydell# Markus Heiser <markus.heiser@darmarit.de> 51*2b2765acSPeter Maydell# Martin Waitz <tali@admingilde.org> 52*2b2765acSPeter Maydell# Masahiro Yamada <masahiroy@kernel.org> 53*2b2765acSPeter Maydell# Matthew Wilcox <willy@infradead.org> 54*2b2765acSPeter Maydell# Mauro Carvalho Chehab <mchehab+huawei@kernel.org> 55*2b2765acSPeter Maydell# Michal Wajdeczko <michal.wajdeczko@intel.com> 56*2b2765acSPeter Maydell# Michael Zucchi 57*2b2765acSPeter Maydell# Mike Rapoport <rppt@linux.ibm.com> 58*2b2765acSPeter Maydell# Niklas Söderlund <niklas.soderlund@corigine.com> 59*2b2765acSPeter Maydell# Nishanth Menon <nm@ti.com> 60*2b2765acSPeter Maydell# Paolo Bonzini <pbonzini@redhat.com> 61*2b2765acSPeter Maydell# Pavan Kumar Linga <pavan.kumar.linga@intel.com> 62*2b2765acSPeter Maydell# Pavel Pisa <pisa@cmp.felk.cvut.cz> 63*2b2765acSPeter Maydell# Peter Maydell <peter.maydell@linaro.org> 64*2b2765acSPeter Maydell# Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> 65*2b2765acSPeter Maydell# Randy Dunlap <rdunlap@infradead.org> 66*2b2765acSPeter Maydell# Richard Kennedy <richard@rsk.demon.co.uk> 67*2b2765acSPeter Maydell# Rich Walker <rw@shadow.org.uk> 68*2b2765acSPeter Maydell# Rolf Eike Beer <eike-kernel@sf-tec.de> 69*2b2765acSPeter Maydell# Sakari Ailus <sakari.ailus@linux.intel.com> 70*2b2765acSPeter Maydell# Silvio Fricke <silvio.fricke@gmail.com> 71*2b2765acSPeter Maydell# Simon Huggins 72*2b2765acSPeter Maydell# Tim Waugh <twaugh@redhat.com> 73*2b2765acSPeter Maydell# Tomasz Warniełło <tomasz.warniello@gmail.com> 74*2b2765acSPeter Maydell# Utkarsh Tripathi <utripathi2002@gmail.com> 75*2b2765acSPeter Maydell# valdis.kletnieks@vt.edu <valdis.kletnieks@vt.edu> 76*2b2765acSPeter Maydell# Vegard Nossum <vegard.nossum@oracle.com> 77*2b2765acSPeter Maydell# Will Deacon <will.deacon@arm.com> 78*2b2765acSPeter Maydell# Yacine Belkadi <yacine.belkadi.1@gmail.com> 79*2b2765acSPeter Maydell# Yujie Liu <yujie.liu@intel.com> 80*2b2765acSPeter Maydell 81*2b2765acSPeter Maydell""" 82*2b2765acSPeter Maydellkernel_doc 83*2b2765acSPeter Maydell========== 84*2b2765acSPeter Maydell 85*2b2765acSPeter MaydellPrint formatted kernel documentation to stdout 86*2b2765acSPeter Maydell 87*2b2765acSPeter MaydellRead C language source or header FILEs, extract embedded 88*2b2765acSPeter Maydelldocumentation comments, and print formatted documentation 89*2b2765acSPeter Maydellto standard output. 90*2b2765acSPeter Maydell 91*2b2765acSPeter MaydellThe documentation comments are identified by the "/**" 92*2b2765acSPeter Maydellopening comment mark. 93*2b2765acSPeter Maydell 94*2b2765acSPeter MaydellSee Documentation/doc-guide/kernel-doc.rst for the 95*2b2765acSPeter Maydelldocumentation comment syntax. 96*2b2765acSPeter Maydell""" 97*2b2765acSPeter Maydell 98*2b2765acSPeter Maydellimport argparse 99*2b2765acSPeter Maydellimport logging 100*2b2765acSPeter Maydellimport os 101*2b2765acSPeter Maydellimport sys 102*2b2765acSPeter Maydell 103*2b2765acSPeter Maydell# Import Python modules 104*2b2765acSPeter Maydell 105*2b2765acSPeter MaydellLIB_DIR = "lib/kdoc" 106*2b2765acSPeter MaydellSRC_DIR = os.path.dirname(os.path.realpath(__file__)) 107*2b2765acSPeter Maydell 108*2b2765acSPeter Maydellsys.path.insert(0, os.path.join(SRC_DIR, LIB_DIR)) 109*2b2765acSPeter Maydell 110*2b2765acSPeter Maydellfrom kdoc_files import KernelFiles # pylint: disable=C0413 111*2b2765acSPeter Maydellfrom kdoc_output import RestFormat, ManFormat # pylint: disable=C0413 112*2b2765acSPeter Maydell 113*2b2765acSPeter MaydellDESC = """ 114*2b2765acSPeter MaydellRead C language source or header FILEs, extract embedded documentation comments, 115*2b2765acSPeter Maydelland print formatted documentation to standard output. 116*2b2765acSPeter Maydell 117*2b2765acSPeter MaydellThe documentation comments are identified by the "/**" opening comment mark. 118*2b2765acSPeter Maydell 119*2b2765acSPeter MaydellSee Documentation/doc-guide/kernel-doc.rst for the documentation comment syntax. 120*2b2765acSPeter Maydell""" 121*2b2765acSPeter Maydell 122*2b2765acSPeter MaydellEXPORT_FILE_DESC = """ 123*2b2765acSPeter MaydellSpecify an additional FILE in which to look for EXPORT_SYMBOL information. 124*2b2765acSPeter Maydell 125*2b2765acSPeter MaydellMay be used multiple times. 126*2b2765acSPeter Maydell""" 127*2b2765acSPeter Maydell 128*2b2765acSPeter MaydellEXPORT_DESC = """ 129*2b2765acSPeter MaydellOnly output documentation for the symbols that have been 130*2b2765acSPeter Maydellexported using EXPORT_SYMBOL() and related macros in any input 131*2b2765acSPeter MaydellFILE or -export-file FILE. 132*2b2765acSPeter Maydell""" 133*2b2765acSPeter Maydell 134*2b2765acSPeter MaydellINTERNAL_DESC = """ 135*2b2765acSPeter MaydellOnly output documentation for the symbols that have NOT been 136*2b2765acSPeter Maydellexported using EXPORT_SYMBOL() and related macros in any input 137*2b2765acSPeter MaydellFILE or -export-file FILE. 138*2b2765acSPeter Maydell""" 139*2b2765acSPeter Maydell 140*2b2765acSPeter MaydellFUNCTION_DESC = """ 141*2b2765acSPeter MaydellOnly output documentation for the given function or DOC: section 142*2b2765acSPeter Maydelltitle. All other functions and DOC: sections are ignored. 143*2b2765acSPeter Maydell 144*2b2765acSPeter MaydellMay be used multiple times. 145*2b2765acSPeter Maydell""" 146*2b2765acSPeter Maydell 147*2b2765acSPeter MaydellNOSYMBOL_DESC = """ 148*2b2765acSPeter MaydellExclude the specified symbol from the output documentation. 149*2b2765acSPeter Maydell 150*2b2765acSPeter MaydellMay be used multiple times. 151*2b2765acSPeter Maydell""" 152*2b2765acSPeter Maydell 153*2b2765acSPeter MaydellFILES_DESC = """ 154*2b2765acSPeter MaydellHeader and C source files to be parsed. 155*2b2765acSPeter Maydell""" 156*2b2765acSPeter Maydell 157*2b2765acSPeter MaydellWARN_CONTENTS_BEFORE_SECTIONS_DESC = """ 158*2b2765acSPeter MaydellWarns if there are contents before sections (deprecated). 159*2b2765acSPeter Maydell 160*2b2765acSPeter MaydellThis option is kept just for backward-compatibility, but it does nothing, 161*2b2765acSPeter Maydellneither here nor at the original Perl script. 162*2b2765acSPeter Maydell""" 163*2b2765acSPeter Maydell 164*2b2765acSPeter Maydell 165*2b2765acSPeter Maydellclass MsgFormatter(logging.Formatter): 166*2b2765acSPeter Maydell """Helper class to format warnings on a similar way to kernel-doc.pl""" 167*2b2765acSPeter Maydell 168*2b2765acSPeter Maydell def format(self, record): 169*2b2765acSPeter Maydell record.levelname = record.levelname.capitalize() 170*2b2765acSPeter Maydell return logging.Formatter.format(self, record) 171*2b2765acSPeter Maydell 172*2b2765acSPeter Maydelldef main(): 173*2b2765acSPeter Maydell """Main program""" 174*2b2765acSPeter Maydell 175*2b2765acSPeter Maydell parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter, 176*2b2765acSPeter Maydell description=DESC) 177*2b2765acSPeter Maydell 178*2b2765acSPeter Maydell # Normal arguments 179*2b2765acSPeter Maydell 180*2b2765acSPeter Maydell parser.add_argument("-v", "-verbose", "--verbose", action="store_true", 181*2b2765acSPeter Maydell help="Verbose output, more warnings and other information.") 182*2b2765acSPeter Maydell 183*2b2765acSPeter Maydell parser.add_argument("-d", "-debug", "--debug", action="store_true", 184*2b2765acSPeter Maydell help="Enable debug messages") 185*2b2765acSPeter Maydell 186*2b2765acSPeter Maydell parser.add_argument("-M", "-modulename", "--modulename", 187*2b2765acSPeter Maydell default="Kernel API", 188*2b2765acSPeter Maydell help="Allow setting a module name at the output.") 189*2b2765acSPeter Maydell 190*2b2765acSPeter Maydell parser.add_argument("-l", "-enable-lineno", "--enable_lineno", 191*2b2765acSPeter Maydell action="store_true", 192*2b2765acSPeter Maydell help="Enable line number output (only in ReST mode)") 193*2b2765acSPeter Maydell 194*2b2765acSPeter Maydell # Arguments to control the warning behavior 195*2b2765acSPeter Maydell 196*2b2765acSPeter Maydell parser.add_argument("-Wreturn", "--wreturn", action="store_true", 197*2b2765acSPeter Maydell help="Warns about the lack of a return markup on functions.") 198*2b2765acSPeter Maydell 199*2b2765acSPeter Maydell parser.add_argument("-Wshort-desc", "-Wshort-description", "--wshort-desc", 200*2b2765acSPeter Maydell action="store_true", 201*2b2765acSPeter Maydell help="Warns if initial short description is missing") 202*2b2765acSPeter Maydell 203*2b2765acSPeter Maydell parser.add_argument("-Wcontents-before-sections", 204*2b2765acSPeter Maydell "--wcontents-before-sections", action="store_true", 205*2b2765acSPeter Maydell help=WARN_CONTENTS_BEFORE_SECTIONS_DESC) 206*2b2765acSPeter Maydell 207*2b2765acSPeter Maydell parser.add_argument("-Wall", "--wall", action="store_true", 208*2b2765acSPeter Maydell help="Enable all types of warnings") 209*2b2765acSPeter Maydell 210*2b2765acSPeter Maydell parser.add_argument("-Werror", "--werror", action="store_true", 211*2b2765acSPeter Maydell help="Treat warnings as errors.") 212*2b2765acSPeter Maydell 213*2b2765acSPeter Maydell parser.add_argument("-export-file", "--export-file", action='append', 214*2b2765acSPeter Maydell help=EXPORT_FILE_DESC) 215*2b2765acSPeter Maydell 216*2b2765acSPeter Maydell # Output format mutually-exclusive group 217*2b2765acSPeter Maydell 218*2b2765acSPeter Maydell out_group = parser.add_argument_group("Output format selection (mutually exclusive)") 219*2b2765acSPeter Maydell 220*2b2765acSPeter Maydell out_fmt = out_group.add_mutually_exclusive_group() 221*2b2765acSPeter Maydell 222*2b2765acSPeter Maydell out_fmt.add_argument("-m", "-man", "--man", action="store_true", 223*2b2765acSPeter Maydell help="Output troff manual page format.") 224*2b2765acSPeter Maydell out_fmt.add_argument("-r", "-rst", "--rst", action="store_true", 225*2b2765acSPeter Maydell help="Output reStructuredText format (default).") 226*2b2765acSPeter Maydell out_fmt.add_argument("-N", "-none", "--none", action="store_true", 227*2b2765acSPeter Maydell help="Do not output documentation, only warnings.") 228*2b2765acSPeter Maydell 229*2b2765acSPeter Maydell # Output selection mutually-exclusive group 230*2b2765acSPeter Maydell 231*2b2765acSPeter Maydell sel_group = parser.add_argument_group("Output selection (mutually exclusive)") 232*2b2765acSPeter Maydell sel_mut = sel_group.add_mutually_exclusive_group() 233*2b2765acSPeter Maydell 234*2b2765acSPeter Maydell sel_mut.add_argument("-e", "-export", "--export", action='store_true', 235*2b2765acSPeter Maydell help=EXPORT_DESC) 236*2b2765acSPeter Maydell 237*2b2765acSPeter Maydell sel_mut.add_argument("-i", "-internal", "--internal", action='store_true', 238*2b2765acSPeter Maydell help=INTERNAL_DESC) 239*2b2765acSPeter Maydell 240*2b2765acSPeter Maydell sel_mut.add_argument("-s", "-function", "--symbol", action='append', 241*2b2765acSPeter Maydell help=FUNCTION_DESC) 242*2b2765acSPeter Maydell 243*2b2765acSPeter Maydell # Those are valid for all 3 types of filter 244*2b2765acSPeter Maydell parser.add_argument("-n", "-nosymbol", "--nosymbol", action='append', 245*2b2765acSPeter Maydell help=NOSYMBOL_DESC) 246*2b2765acSPeter Maydell 247*2b2765acSPeter Maydell parser.add_argument("-D", "-no-doc-sections", "--no-doc-sections", 248*2b2765acSPeter Maydell action='store_true', help="Don't outputt DOC sections") 249*2b2765acSPeter Maydell 250*2b2765acSPeter Maydell parser.add_argument("files", metavar="FILE", 251*2b2765acSPeter Maydell nargs="+", help=FILES_DESC) 252*2b2765acSPeter Maydell 253*2b2765acSPeter Maydell args = parser.parse_args() 254*2b2765acSPeter Maydell 255*2b2765acSPeter Maydell if args.wall: 256*2b2765acSPeter Maydell args.wreturn = True 257*2b2765acSPeter Maydell args.wshort_desc = True 258*2b2765acSPeter Maydell args.wcontents_before_sections = True 259*2b2765acSPeter Maydell 260*2b2765acSPeter Maydell logger = logging.getLogger() 261*2b2765acSPeter Maydell 262*2b2765acSPeter Maydell if not args.debug: 263*2b2765acSPeter Maydell logger.setLevel(logging.INFO) 264*2b2765acSPeter Maydell else: 265*2b2765acSPeter Maydell logger.setLevel(logging.DEBUG) 266*2b2765acSPeter Maydell 267*2b2765acSPeter Maydell formatter = MsgFormatter('%(levelname)s: %(message)s') 268*2b2765acSPeter Maydell 269*2b2765acSPeter Maydell handler = logging.StreamHandler() 270*2b2765acSPeter Maydell handler.setFormatter(formatter) 271*2b2765acSPeter Maydell 272*2b2765acSPeter Maydell logger.addHandler(handler) 273*2b2765acSPeter Maydell 274*2b2765acSPeter Maydell python_ver = sys.version_info[:2] 275*2b2765acSPeter Maydell if python_ver < (3,6): 276*2b2765acSPeter Maydell logger.warning("Python 3.6 or later is required by kernel-doc") 277*2b2765acSPeter Maydell 278*2b2765acSPeter Maydell # Return 0 here to avoid breaking compilation 279*2b2765acSPeter Maydell sys.exit(0) 280*2b2765acSPeter Maydell 281*2b2765acSPeter Maydell if python_ver < (3,7): 282*2b2765acSPeter Maydell logger.warning("Python 3.7 or later is required for correct results") 283*2b2765acSPeter Maydell 284*2b2765acSPeter Maydell if args.man: 285*2b2765acSPeter Maydell out_style = ManFormat(modulename=args.modulename) 286*2b2765acSPeter Maydell elif args.none: 287*2b2765acSPeter Maydell out_style = None 288*2b2765acSPeter Maydell else: 289*2b2765acSPeter Maydell out_style = RestFormat() 290*2b2765acSPeter Maydell 291*2b2765acSPeter Maydell kfiles = KernelFiles(verbose=args.verbose, 292*2b2765acSPeter Maydell out_style=out_style, werror=args.werror, 293*2b2765acSPeter Maydell wreturn=args.wreturn, wshort_desc=args.wshort_desc, 294*2b2765acSPeter Maydell wcontents_before_sections=args.wcontents_before_sections) 295*2b2765acSPeter Maydell 296*2b2765acSPeter Maydell kfiles.parse(args.files, export_file=args.export_file) 297*2b2765acSPeter Maydell 298*2b2765acSPeter Maydell for t in kfiles.msg(enable_lineno=args.enable_lineno, export=args.export, 299*2b2765acSPeter Maydell internal=args.internal, symbol=args.symbol, 300*2b2765acSPeter Maydell nosymbol=args.nosymbol, export_file=args.export_file, 301*2b2765acSPeter Maydell no_doc_sections=args.no_doc_sections): 302*2b2765acSPeter Maydell msg = t[1] 303*2b2765acSPeter Maydell if msg: 304*2b2765acSPeter Maydell print(msg) 305*2b2765acSPeter Maydell 306*2b2765acSPeter Maydell error_count = kfiles.errors 307*2b2765acSPeter Maydell if not error_count: 308*2b2765acSPeter Maydell sys.exit(0) 309*2b2765acSPeter Maydell 310*2b2765acSPeter Maydell if args.werror: 311*2b2765acSPeter Maydell print(f"{error_count} warnings as errors") 312*2b2765acSPeter Maydell sys.exit(error_count) 313*2b2765acSPeter Maydell 314*2b2765acSPeter Maydell if args.verbose: 315*2b2765acSPeter Maydell print(f"{error_count} errors") 316*2b2765acSPeter Maydell 317*2b2765acSPeter Maydell if args.none: 318*2b2765acSPeter Maydell sys.exit(0) 319*2b2765acSPeter Maydell 320*2b2765acSPeter Maydell sys.exit(error_count) 321*2b2765acSPeter Maydell 322*2b2765acSPeter Maydell 323*2b2765acSPeter Maydell# Call main method 324*2b2765acSPeter Maydellif __name__ == "__main__": 325*2b2765acSPeter Maydell main() 326