From nobody Tue Dec 2 01:46:29 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 0292F2857C1; Sat, 22 Nov 2025 12:38:07 +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=1763815088; cv=none; b=TDT+zrBefAJJRde6jpNCZfKHIrCfGFaweVWE5m2FNkgueXRI1iKemkiEYOb3eEys89k2L7Xh4OG5dYvstOTQxgBBdfEXlFfyKZxvVW7J4CyoDpCHDaF9oAGIdiwpO8VCIAZeKQdzVbUFy0ACFPWCweEZXamhOiIAV4Ee8RQyGmQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763815088; c=relaxed/simple; bh=3mMj2/bpTFkS1JYhOQCrsyMcgLS2GZpq30GUkfbjkfo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=dTRZg7158e8rDGgmAs0Qe/ExWAfGQ7Snag7Ugyz2AEME/kTJEsFv61ZjrbifnfCEB3qncbN6YFJy8BYDQJ8kYzt/ztWCkc613SKFsyNkJ0HqKBPoEgnKAfarqBvNJg5ASaz+3yPlNiuAr1bNqN7RU7knSnS9D189zzAulwlJWhg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=UR+EQDcI; 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="UR+EQDcI" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 640EFC116C6; Sat, 22 Nov 2025 12:38:07 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1763815087; bh=3mMj2/bpTFkS1JYhOQCrsyMcgLS2GZpq30GUkfbjkfo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=UR+EQDcI5GIc4YOZwdFEbVBmIdzDu91RkTp+wn/tRu8GEqmfNKQL5VXmHa6GxNWBv mxioVClgGtoUyubs7lMFfC7ZHmei+lj+6tgsX3R8Ik10bq03QRpS5owSw0xKp3LS1a Xvbggl3Xy0a18pOYmW0RBoB6yfTJCMoHz/DLdgiKpyt6MVI8n8C0JG9B6WChAyFpiM DIHZpJSnTJy638RA/amzPEInTjU/bQ9IPf/bshSS7/vYmWIZqENRcGuMH4ty166FLD hGmNDIHxnYagw9j4d+T86qYkoARfMBmgDzbnlDLcYohVPUMMRgHzY8jFnLXUAYig6W NzaeQU3PbKHgQ== Received: from mchehab by mail.kernel.org with local (Exim 4.99) (envelope-from ) id 1vMmsP-00000004pm2-2140; Sat, 22 Nov 2025 13:38:05 +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 v4 1/5] kernel-doc: add support for handling global variables Date: Sat, 22 Nov 2025 13:37:55 +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 --- 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