From nobody Sun Feb 8 21:48:52 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C7DD43939CE; Tue, 3 Feb 2026 14:55:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770130555; cv=none; b=jNwUP3uY2AqaoguYx6f8BCDrKcy4zq8rGWHRcaSuZ9EiFLZlnwStvGShS0UXrBAzGOAfLmEvLnY1lJQ1bWuv22FTO44HSZnolmhQrKbbxplAFSUys9IzuWjw/jQ8QguH+/X/ha8X2f/2OQb/bLBs5CMMRuxJp7TLedCswctknBk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770130555; c=relaxed/simple; bh=IzvIm7KoDEuXLxlxb1Oy6DEqVh4pIaNIXwZ6aUtWm1Y=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=g/S/c88y6G6FHVQr83eU6T6SnyGBoBM7oYOHWGrjiNhBWOsxtfFSL6Q4wuMRH74nji0iw7j8B2OYaZQWXWsKDNNkLhOmnozg4iBBapIcy80Naqr2L9byQyUuNrC4TAoq0SPllIlIiosOONTpFkGtH3wgFrAMOhwZe3YSMRfz72s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=CTsZsSOa; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="CTsZsSOa" Received: by smtp.kernel.org (Postfix) with ESMTPSA id ED8E8C2BCB8; Tue, 3 Feb 2026 14:55:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1770130555; bh=IzvIm7KoDEuXLxlxb1Oy6DEqVh4pIaNIXwZ6aUtWm1Y=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=CTsZsSOaGF/fZuottrRbnuk83otSF512DPG6umuOL8d2mL+KaELLIYEdgSFUU6Zwk y79nZwiO4TK3eSfiLdWZaN4WkPLEBA1xcth75O9703/ayRIlZQ90iv2zgHRVKytJ0g IPPOD/E5g6nYdVAp14K7qQL5Y32MNh5D+zXdsO2wxIQRBTt7AUa0Dv+kljpQDPVC9D Ls9948p8iFEnsfituIvncukdDrKQ3noh7lfFrFFanBH1myZ31XvDD2Mr/7FYORO5w/ 7FCDcqw2s+/0dzeUnSnFaZSqAxkZG5gwp/m2KROGrQO1ifpmRazkSW6g89UA5r0O6d ehCqeK7QiMoSA== Received: from mchehab by mail.kernel.org with local (Exim 4.99.1) (envelope-from ) id 1vnHon-000000027Uy-0h97; Tue, 03 Feb 2026 15:55:53 +0100 From: Mauro Carvalho Chehab To: Jonathan Corbet , Linux Doc Mailing List Cc: Mauro Carvalho Chehab , linux-kernel@vger.kernel.org, Aleksandr Loktionov , Jani Nikula , Mauro Carvalho Chehab , Randy Dunlap , Shuah Khan Subject: [PATCH 14/15] docs: kernel-doc: add support to store output on a YAML file Date: Tue, 3 Feb 2026 15:55:42 +0100 Message-ID: <7648cb5f5a1b501d9ae9a57b4d8dbeb7273d9097.1770128540.git.mchehab+huawei@kernel.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Sender: Mauro Carvalho Chehab Add a command line parameter and library support to optionally store: - KdocItem intermediate format after parsing; - man pages output; - rst output. inside a YAML file. Signed-off-by: Mauro Carvalho Chehab --- tools/docs/kernel-doc | 48 +++++++++++++++++++++++----- tools/lib/python/kdoc/kdoc_files.py | 47 +++++++++++++++++++++++---- tools/lib/python/kdoc/kdoc_parser.py | 27 +++++++++++++++- 3 files changed, 107 insertions(+), 15 deletions(-) diff --git a/tools/docs/kernel-doc b/tools/docs/kernel-doc index 3a932f95bdf5..5382d98aaff4 100755 --- a/tools/docs/kernel-doc +++ b/tools/docs/kernel-doc @@ -240,11 +240,9 @@ def main(): help=3DEXPORT_FILE_DESC) =20 # - # Output format mutually-exclusive group + # Output format # - out_group =3D parser.add_argument_group("Output format selection (mutu= ally exclusive)") - - out_fmt =3D out_group.add_mutually_exclusive_group() + out_fmt =3D parser.add_argument_group("Output format selection (mutual= ly exclusive)") =20 out_fmt.add_argument("-m", "-man", "--man", action=3D"store_true", help=3D"Output troff manual page format.") @@ -253,6 +251,12 @@ def main(): out_fmt.add_argument("-N", "-none", "--none", action=3D"store_true", help=3D"Do not output documentation, only warning= s.") =20 + out_fmt.add_argument("-y", "--yaml-file", "--yaml", + help=3D"Stores kernel-doc output on a yaml file.") + out_fmt.add_argument("-k", "--kdoc-item", "--kdoc", action=3D"store_tr= ue", + help=3D"Store KdocItem inside yaml file. Ued toge= ther with --yaml.") + + # # Output selection mutually-exclusive group # @@ -323,14 +327,42 @@ def main(): from kdoc.kdoc_files import KernelFiles # pylint: disable= =3DC0415 from kdoc.kdoc_output import RestFormat, ManFormat # pylint: disable= =3DC0415 =20 - if args.man: - out_style =3D ManFormat(modulename=3Dargs.modulename) - elif args.none: + yaml_content =3D set() + if args.yaml_file: out_style =3D None + + if args.man: + yaml_content |=3D {"man"} + + if args.rst: + yaml_content |=3D {"rst"} + + if args.kdoc_item or not yaml_content: + yaml_content |=3D {"KdocItem"} + else: - out_style =3D RestFormat() + n_outputs =3D 0 + + if args.man: + out_style =3D ManFormat(modulename=3Dargs.modulename) + n_outputs +=3D 1 + + if args.none: + out_style =3D None + n_outputs +=3D 1 + + if args.rst or n_outputs =3D=3D 0: + n_outputs +=3D 1 + out_style =3D RestFormat() + + if n_outputs > 1: + parser.error("Those arguments are muttually exclusive: --man,= --rst, --none, except when generating a YAML file.") + + else: + out_style =3D RestFormat() =20 kfiles =3D KernelFiles(verbose=3Dargs.verbose, + yaml_file=3Dargs.yaml_file, yaml_content=3Dyaml_c= ontent, out_style=3Dout_style, werror=3Dargs.werror, wreturn=3Dargs.wreturn, wshort_desc=3Dargs.wshort= _desc, wcontents_before_sections=3Dargs.wcontents_before= _sections) diff --git a/tools/lib/python/kdoc/kdoc_files.py b/tools/lib/python/kdoc/kd= oc_files.py index 58f4ee08e226..5a299ed44d62 100644 --- a/tools/lib/python/kdoc/kdoc_files.py +++ b/tools/lib/python/kdoc/kdoc_files.py @@ -16,6 +16,7 @@ import re from kdoc.kdoc_parser import KernelDoc from kdoc.xforms_lists import CTransforms from kdoc.kdoc_output import OutputFormat +from kdoc.kdoc_yaml_file import KDocTestFile =20 =20 class GlobSourceFiles: @@ -152,6 +153,12 @@ class KernelFiles(): =20 If not specified, defaults to use: ``logging.getLogger("kernel-doc= ")`` =20 + ``yaml_file`` + If defined, stores the output inside a YAML file. + + ``yaml_content`` + Defines what will be inside the YAML file. + Note: There are two type of parsers defined here: =20 @@ -181,7 +188,12 @@ class KernelFiles(): if fname in self.files: return =20 - doc =3D KernelDoc(self.config, fname, self.xforms) + if self.test_file: + store_src =3D True + else: + store_src =3D False + + doc =3D KernelDoc(self.config, fname, self.xforms, store_src=3Dsto= re_src) export_table, entries =3D doc.parse_kdoc() =20 self.export_table[fname] =3D export_table @@ -191,6 +203,10 @@ class KernelFiles(): =20 self.results[fname] =3D entries =20 + source =3D doc.get_source() + if source: + self.source[fname] =3D source + def process_export_file(self, fname): """ Parses ``EXPORT_SYMBOL*`` macros from a single Kernel source file. @@ -220,7 +236,7 @@ class KernelFiles(): def __init__(self, verbose=3DFalse, out_style=3DNone, xforms=3DNone, werror=3DFalse, wreturn=3DFalse, wshort_desc=3DFalse, wcontents_before_sections=3DFalse, - logger=3DNone): + yaml_file=3DNone, yaml_content=3DNone, logger=3DNone): """ Initialize startup variables and parse all files. """ @@ -259,6 +275,11 @@ class KernelFiles(): # Override log warning, as we want to count errors self.config.warning =3D self.warning =20 + if yaml_file: + self.test_file =3D KDocTestFile(self.config, yaml_file, yaml_c= ontent) + else: + self.test_file =3D None + if xforms: self.xforms =3D xforms else: @@ -273,6 +294,7 @@ class KernelFiles(): =20 self.errors =3D 0 self.results =3D {} + self.source =3D {} =20 self.files =3D set() self.export_files =3D set() @@ -331,16 +353,29 @@ class KernelFiles(): for s in symbol: function_table.add(s) =20 - self.out_style.set_filter(export, internal, symbol, nosymbol, - function_table, enable_lineno, - no_doc_sections) - if fname not in self.results: self.config.log.warning("No kernel-doc for file %s", fname) continue =20 symbols =3D self.results[fname] =20 + if self.test_file: + self.test_file.set_filter(export, internal, symbol, nosymb= ol, + function_table, enable_lineno, + no_doc_sections) + + self.test_file.output_symbols(fname, symbols, + self.source.get(fname)) + + continue + + self.out_style.set_filter(export, internal, symbol, nosymbol, + function_table, enable_lineno, + no_doc_sections) + msg =3D self.out_style.output_symbols(fname, symbols) if msg: yield fname, msg + + if self.test_file: + self.test_file.write() diff --git a/tools/lib/python/kdoc/kdoc_parser.py b/tools/lib/python/kdoc/k= doc_parser.py index 940c848d4d80..f6748720d899 100644 --- a/tools/lib/python/kdoc/kdoc_parser.py +++ b/tools/lib/python/kdoc/kdoc_parser.py @@ -258,12 +258,13 @@ class KernelDoc: #: String to write when a parameter is not described. undescribed =3D "-- undescribed --" =20 - def __init__(self, config, fname, xforms): + def __init__(self, config, fname, xforms, store_src=3DFalse): """Initialize internal variables""" =20 self.fname =3D fname self.config =3D config self.xforms =3D xforms + self.store_src =3D store_src =20 # Initial state for the state machines self.state =3D state.NORMAL @@ -274,6 +275,9 @@ class KernelDoc: # Place all potential outputs into an array self.entries =3D [] =20 + # When store_src is true, the kernel-doc source content is stored = here + self.source =3D None + # # We need Python 3.7 for its "dicts remember the insertion # order" guarantee @@ -1612,6 +1616,15 @@ class KernelDoc: state.DOCBLOCK: process_docblock, } =20 + def get_source(self): + """ + Return the file content of the lines handled by kernel-doc at the + latest parse_kdoc() run. + + Returns none if KernelDoc() was not initialized with store_src, + """ + return self.source + def parse_kdoc(self): """ Open and process each line of a C source file. @@ -1625,6 +1638,8 @@ class KernelDoc: prev =3D "" prev_ln =3D None export_table =3D set() + self.source =3D [] + self.state =3D state.NORMAL =20 try: with open(self.fname, "r", encoding=3D"utf8", @@ -1651,6 +1666,8 @@ class KernelDoc: ln, state.name[self.state], line) =20 + prev_state =3D self.state + # This is an optimization over the original script. # There, when export_file was used for the same file, # it was read twice. Here, we use the already-existing @@ -1661,6 +1678,14 @@ class KernelDoc: # Hand this line to the appropriate state handler self.state_actions[self.state](self, ln, line) =20 + if self.store_src and prev_state !=3D self.state or se= lf.state !=3D state.NORMAL: + if self.state =3D=3D state.NAME: + # A "/**" was detected. Add a new source eleme= nt + self.source.append({"ln": ln, "data": line + "= \n"}) + else: + # Append to the existing one + self.source[-1]["data"] +=3D line + "\n" + self.emit_unused_warnings() =20 except OSError: --=20 2.52.0