From nobody Tue Dec 2 01:26:47 2025 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 419432F7465; Mon, 24 Nov 2025 09:57:56 +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=1763978276; cv=none; b=h7rBR2aJmbqnX3/VJxcSr6qADkq4+E4X9L2tU34M/dt9CtrlweEuN17jZwMn6o19JlNOglU4JO1dENer+Ldku8j3SmlFvzon2o3BoEdNlG8EkSCT0zubU/zfPiozroJTQnxfGcobFxV6y02KMle0gX2J7N4k94lcPlPpk66Lswo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763978276; c=relaxed/simple; bh=3mMj2/bpTFkS1JYhOQCrsyMcgLS2GZpq30GUkfbjkfo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=M8GmIFoAAp6sxsJc0ooumrf4FrOZboGmh1eLMdJ/SN+QIqTv64C98FUt3jvq0QSvBrGEmvORDz91dNwWOdLO+XZYtgKAfoeOmHFyuxy+Sqn6TeYbp6jcjRMXyr9zkMRbFtXcbLhd/4YQLNC9li+2zj9awmSO8ucEzMIbAmS0IuE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=sRjkr/9y; 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="sRjkr/9y" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D9983C4CEF1; Mon, 24 Nov 2025 09:57:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1763978275; bh=3mMj2/bpTFkS1JYhOQCrsyMcgLS2GZpq30GUkfbjkfo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=sRjkr/9y/S3J3nn0oRA1BYaYl+/9FpdqkM5DZvharGOT2C3VGHgsC1TZJWXR5y8Qo T+zueOrYe4A6gph7oFdJmBUZPTiFYZrx5hzHEIJfFtjG/t+EqhdUMeQa4aai/bc2SO IYYelnnwYAtvjH933HONP8CNYuu0WK0W9dvON4LutrNWpj4QqPDK/6HODFGyhguzjM c4A0pQfeCKMW1LHSc5UDhyOdmECMC7yXz8zIQanbm+HMxyrfkEC0Qh7fMlfZd0sT0f lHCeUtVH0BGUEMLBpZOKC3CKS12K6AFvHviYdqlKnhjuHUeTEVFX30+XFU/tZ+nDQr 4paur02+oYAHg== Received: from mchehab by mail.kernel.org with local (Exim 4.99) (envelope-from ) id 1vNTKU-000000013c0-0WII; Mon, 24 Nov 2025 10:57:54 +0100 From: Mauro Carvalho Chehab To: Linux Doc Mailing List , "Jonathan Corbet" Cc: Mauro Carvalho Chehab , "Mauro Carvalho Chehab" , "Randy Dunlap" , linux-kernel@vger.kernel.org Subject: [PATCH v5 1/5] kernel-doc: add support for handling global variables Date: Mon, 24 Nov 2025 10:57:42 +0100 Message-ID: X-Mailer: git-send-email 2.51.1 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-Transfer-Encoding: quoted-printable Sender: Mauro Carvalho Chehab Content-Type: text/plain; charset="utf-8" Specially on kAPI, sometimes it is desirable to be able to describe global variables that are part of kAPI. Documenting vars with Sphinx is simple, as we don't need to parse a data struct. All we need is the variable declaration and use natice C domain ::c:var: to format it for us. Add support for it. Link: https://lore.kernel.org/linux-doc/491c3022-cef8-4860-a945-c9c4a3b63c0= 9@infradead.org/T/#m947c25d95cb1d96a394410ab1131dc8e9e5013f1 Suggested-by: Randy Dunlap Signed-off-by: Mauro Carvalho Chehab Acked-by: Randy Dunlap Tested-by: Randy Dunlap --- tools/lib/python/kdoc/kdoc_output.py | 47 +++++++++++++++++++++++ tools/lib/python/kdoc/kdoc_parser.py | 56 +++++++++++++++++++++++++++- 2 files changed, 102 insertions(+), 1 deletion(-) diff --git a/tools/lib/python/kdoc/kdoc_output.py b/tools/lib/python/kdoc/k= doc_output.py index 14378953301b..8d811c2afaab 100644 --- a/tools/lib/python/kdoc/kdoc_output.py +++ b/tools/lib/python/kdoc/kdoc_output.py @@ -199,6 +199,10 @@ class OutputFormat: self.out_enum(fname, name, args) return self.data =20 + if dtype =3D=3D "var": + self.out_var(fname, name, args) + return self.data + if dtype =3D=3D "typedef": self.out_typedef(fname, name, args) return self.data @@ -227,6 +231,9 @@ class OutputFormat: def out_enum(self, fname, name, args): """Outputs an enum""" =20 + def out_var(self, fname, name, args): + """Outputs a variable""" + def out_typedef(self, fname, name, args): """Outputs a typedef""" =20 @@ -472,6 +479,25 @@ class RestFormat(OutputFormat): self.lineprefix =3D oldprefix self.out_section(args) =20 + def out_var(self, fname, name, args): + oldprefix =3D self.lineprefix + ln =3D args.declaration_start_line + full_proto =3D args.other_stuff["full_proto"] + + self.lineprefix =3D " " + + self.data +=3D f"\n\n.. c:macro:: {name}\n\n{self.lineprefix}{full= _proto}\n\n" + + self.print_lineno(ln) + self.output_highlight(args.get('purpose', '')) + self.data +=3D "\n" + + if args.other_stuff["default_val"]: + self.data +=3D f'{self.lineprefix}**Initialization**\n\n' + self.output_highlight(f'default: ``{args.other_stuff["default_= val"]}``') + + self.out_section(args) + def out_typedef(self, fname, name, args): =20 oldprefix =3D self.lineprefix @@ -773,6 +799,27 @@ class ManFormat(OutputFormat): self.data +=3D f'.SH "{section}"' + "\n" self.output_highlight(text) =20 + def out_var(self, fname, name, args): + out_name =3D self.arg_name(args, name) + prototype =3D args.other_stuff["var_type"] + full_proto =3D args.other_stuff["full_proto"] + + self.data +=3D f'.TH "{self.modulename}" 9 "{out_name}" "{self.man= _date}" "API Manual" LINUX' + "\n" + + self.data +=3D ".SH NAME\n" + self.data +=3D f"{prototype} \\- {args['purpose']}\n" + + self.data +=3D ".SH SYNOPSIS\n" + self.data +=3D f"{full_proto}\n" + + if args.other_stuff["default_val"]: + self.data +=3D f'.SH "Initialization"' + "\n" + self.output_highlight(f'default: {args.other_stuff["default_va= l"]}') + + for section, text in args.sections.items(): + self.data +=3D f'.SH "{section}"' + "\n" + self.output_highlight(text) + def out_typedef(self, fname, name, args): module =3D self.modulename purpose =3D args.get('purpose') diff --git a/tools/lib/python/kdoc/kdoc_parser.py b/tools/lib/python/kdoc/k= doc_parser.py index c0cc714d4d6f..edb0fb5330e0 100644 --- a/tools/lib/python/kdoc/kdoc_parser.py +++ b/tools/lib/python/kdoc/kdoc_parser.py @@ -64,7 +64,7 @@ type_param =3D KernRe(r"@(\w*((\.\w+)|(->\w+))*(\.\.\.)?)= ", cache=3DFalse) # Tests for the beginning of a kerneldoc block in its various forms. # doc_block =3D doc_com + KernRe(r'DOC:\s*(.*)?', cache=3DFalse) -doc_begin_data =3D KernRe(r"^\s*\*?\s*(struct|union|enum|typedef)\b\s*(\w*= )", cache =3D False) +doc_begin_data =3D KernRe(r"^\s*\*?\s*(struct|union|enum|typedef|var)\b\s*= (\w*)", cache =3D False) doc_begin_func =3D KernRe(str(doc_com) + # initial " * ' r"(?:\w+\s*\*\s*)?" + # type (not captured) r'(?:define\s+)?' + # possible "define" (not cap= tured) @@ -924,6 +924,58 @@ class KernelDoc: self.output_declaration('enum', declaration_name, purpose=3Dself.entry.declaration_purpose) =20 + def dump_var(self, ln, proto): + """ + Store variables that are part of kAPI. + """ + VAR_ATTRIBS =3D [ + "extern", + ] + OPTIONAL_VAR_ATTR =3D "^(?:" + "|".join(VAR_ATTRIBS) + ")?" + + sub_prefixes =3D [ + (KernRe(r"__read_mostly"), ""), + (KernRe(r"__ro_after_init"), ""), + (KernRe(r"(?://.*)$"), ""), + (KernRe(r"(?:/\*.*\*/)"), ""), + (KernRe(r";$"), ""), + (KernRe(r"=3D.*"), ""), + ] + + # + # Store the full prototype before modifying it + # + full_proto =3D proto + + # + # Drop comments and macros to have a pure C prototype + # + for search, sub in sub_prefixes: + proto =3D search.sub(sub, proto) + + proto =3D proto.rstrip() + + # + # Variable name is at the end of the declaration + # + + r=3D KernRe(OPTIONAL_VAR_ATTR + r"\w.*\s+(?:\*+)?([\w_]+)\s*[\d\]\= []*\s*(=3D.*)?") + if not r.match(proto): + self.emit_msg(ln,f"{proto}: can't parse variable") + return + + var_type =3D r.group(0) + declaration_name =3D r.group(1) + default_val =3D r.group(2) + if default_val: + default_val =3D default_val.lstrip("=3D").strip() + + self.output_declaration("var", declaration_name, + full_proto=3Dfull_proto, + var_type=3Dvar_type, + default_val=3Ddefault_val, + purpose=3Dself.entry.declaration_purpose) + def dump_declaration(self, ln, prototype): """ Stores a data declaration inside self.entries array. @@ -935,6 +987,8 @@ class KernelDoc: self.dump_typedef(ln, prototype) elif self.entry.decl_type in ["union", "struct"]: self.dump_struct(ln, prototype) + elif self.entry.decl_type =3D=3D "var": + self.dump_var(ln, prototype) else: # This would be a bug self.emit_message(ln, f'Unknown declaration type: {self.entry.= decl_type}') --=20 2.51.1