linux-doc.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] kernel-doc: add support for handling global variables
@ 2025-09-07 16:22 Mauro Carvalho Chehab
  2025-09-07 21:34 ` Mauro Carvalho Chehab
                   ` (2 more replies)
  0 siblings, 3 replies; 27+ messages in thread
From: Mauro Carvalho Chehab @ 2025-09-07 16:22 UTC (permalink / raw)
  To: Linux Doc Mailing List
  Cc: Mauro Carvalho Chehab, Jonathan Corbet, Mauro Carvalho Chehab,
	Randy Dunlap, linux-kernel

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-c9c4a3b63c09@infradead.org/T/#m947c25d95cb1d96a394410ab1131dc8e9e5013f1
Suggested-by: Randy Dunlap <rdunlap@infradead.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
---
 scripts/lib/kdoc/kdoc_output.py | 31 +++++++++++++++++++++++++++++++
 scripts/lib/kdoc/kdoc_parser.py | 25 ++++++++++++++++++++++++-
 2 files changed, 55 insertions(+), 1 deletion(-)

diff --git a/scripts/lib/kdoc/kdoc_output.py b/scripts/lib/kdoc/kdoc_output.py
index 1eca9a918558..405a5c407522 100644
--- a/scripts/lib/kdoc/kdoc_output.py
+++ b/scripts/lib/kdoc/kdoc_output.py
@@ -199,6 +199,10 @@ class OutputFormat:
             self.out_enum(fname, name, args)
             return self.data
 
+        if dtype == "global":
+            self.out_global(fname, name, args)
+            return self.data
+
         if dtype == "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"""
 
+    def out_global(self, fname, name, args):
+        """Outputs a global variable"""
+
     def out_typedef(self, fname, name, args):
         """Outputs a typedef"""
 
@@ -472,6 +479,18 @@ class RestFormat(OutputFormat):
         self.lineprefix = oldprefix
         self.out_section(args)
 
+    def out_global(self, fname, name, args):
+        oldprefix = self.lineprefix
+        ln = args.declaration_start_line
+        prototype = args.other_stuff["var_type"]
+
+        self.data += f"

.. c:var:: {prototype}

"
+
+        self.print_lineno(ln)
+        self.lineprefix = "  "
+        self.output_highlight(args.get('purpose', ''))
+        self.data += "
"
+
     def out_typedef(self, fname, name, args):
 
         oldprefix = self.lineprefix
@@ -772,6 +791,18 @@ class ManFormat(OutputFormat):
             self.data += f'.SH "{section}"' + "
"
             self.output_highlight(text)
 
+    def out_global(self, fname, name, args):
+        out_name = self.arg_name(args, name)
+        prototype = args.other_stuff["var_type"]
+
+        self.data += f'.TH "{self.modulename}" 9 "{out_name}" "{self.man_date}" "API Manual" LINUX' + "
"
+
+        self.data += ".SH NAME
"
+        self.data += f"{prototype} \- {args['purpose']}
"
+
+        self.data += ".SH SYNOPSIS
"
+        self.data += f"enum {name}" + " {
"
+
     def out_typedef(self, fname, name, args):
         module = self.modulename
         purpose = args.get('purpose')
diff --git a/scripts/lib/kdoc/kdoc_parser.py b/scripts/lib/kdoc/kdoc_parser.py
index 574972e1f741..e2a3f4574894 100644
--- a/scripts/lib/kdoc/kdoc_parser.py
+++ b/scripts/lib/kdoc/kdoc_parser.py
@@ -64,7 +64,7 @@ type_param = KernRe(r"@(\w*((\.\w+)|(->\w+))*(\.\.\.)?)", cache=False)
 # Tests for the beginning of a kerneldoc block in its various forms.
 #
 doc_block = doc_com + KernRe(r'DOC:\s*(.*)?', cache=False)
-doc_begin_data = KernRe(r"^\s*\*?\s*(struct|union|enum|typedef)\b\s*(\w*)", cache = False)
+doc_begin_data = KernRe(r"^\s*\*?\s*(struct|union|enum|typedef|global)\b\s*(\w*)", cache = False)
 doc_begin_func = KernRe(str(doc_com) +			# initial " * '
                         r"(?:\w+\s*\*\s*)?" + 		# type (not captured)
                         r'(?:define\s+)?' + 		# possible "define" (not captured)
@@ -886,6 +886,27 @@ class KernelDoc:
         self.output_declaration('enum', declaration_name,
                                 purpose=self.entry.declaration_purpose)
 
+    def dump_global(self, ln, proto):
+        """
+        Stores global variables that are part of kAPI.
+        """
+        VAR_ATTRIBS = [
+            "extern",
+        ]
+        OPTIONAL_VAR_ATTR = "^(?:" + "|".join(VAR_ATTRIBS) + ")?"
+
+        r= KernRe(OPTIONAL_VAR_ATTR + r"(\w.*)\s+([\w_]+)[\d\]\[]*\s*;(?:#.*)?$")
+        if not r.match(proto):
+           self.emit_msg(ln,f"{proto}: can't parse variable")
+           return
+
+        declaration_name = r.group(2)
+        var_type = r.group(0)
+
+        self.output_declaration("global", declaration_name,
+                                var_type=var_type,
+                                purpose=self.entry.declaration_purpose)
+
     def dump_declaration(self, ln, prototype):
         """
         Stores a data declaration inside self.entries array.
@@ -897,6 +918,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 == "global":
+            self.dump_global(ln, prototype)
         else:
             # This would be a bug
             self.emit_message(ln, f'Unknown declaration type: {self.entry.decl_type}')
-- 
2.51.0


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* Re: [PATCH] kernel-doc: add support for handling global variables
  2025-09-07 16:22 [PATCH] kernel-doc: add support for handling global variables Mauro Carvalho Chehab
@ 2025-09-07 21:34 ` Mauro Carvalho Chehab
  2025-09-09  6:22   ` Randy Dunlap
  2025-09-09  7:27 ` Randy Dunlap
  2025-09-10  9:24 ` Jani Nikula
  2 siblings, 1 reply; 27+ messages in thread
From: Mauro Carvalho Chehab @ 2025-09-07 21:34 UTC (permalink / raw)
  To: Linux Doc Mailing List, Randy Dunlap; +Cc: Jonathan Corbet, linux-kernel

Em Sun,  7 Sep 2025 18:22:22 +0200
Mauro Carvalho Chehab <mchehab+huawei@kernel.org> escreveu:

> 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-c9c4a3b63c09@infradead.org/T/#m947c25d95cb1d96a394410ab1131dc8e9e5013f1
> Suggested-by: Randy Dunlap <rdunlap@infradead.org>
> Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>

Btw, this is still at RFC level, as, for the final version we need:

- to document this new kernel-doc feature;
- to suppress (or keep) the end ";";
- do some cleanups/improvements at the regex to ensure that it is generic
  enough. For instance, the way it was defineded, it doesn't handle yet
  variables with assigned values like:
	extern int foo = 5;
- if it has a default non-zero value, should it be documented or not,
  and, if so, how;
- to decide if we add "extern" to all outputs, to none of them or if we
  just follow what is at the documented declaration (the current
  implementation does the latter;
- to decide weather use "global"/"var" or something else.

Also, it would be interesting to have a real case where we want
to document kAPI variables.

Randy,

if you have some real case examples, perhaps you could pick this patch
and add on a patch series after taking the above into consideration.

> ---
>  scripts/lib/kdoc/kdoc_output.py | 31 +++++++++++++++++++++++++++++++
>  scripts/lib/kdoc/kdoc_parser.py | 25 ++++++++++++++++++++++++-
>  2 files changed, 55 insertions(+), 1 deletion(-)
> 
> diff --git a/scripts/lib/kdoc/kdoc_output.py b/scripts/lib/kdoc/kdoc_output.py
> index 1eca9a918558..405a5c407522 100644
> --- a/scripts/lib/kdoc/kdoc_output.py
> +++ b/scripts/lib/kdoc/kdoc_output.py
> @@ -199,6 +199,10 @@ class OutputFormat:
>              self.out_enum(fname, name, args)
>              return self.data
>  
> +        if dtype == "global":
> +            self.out_global(fname, name, args)
> +            return self.data
> +
>          if dtype == "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"""
>  
> +    def out_global(self, fname, name, args):
> +        """Outputs a global variable"""
> +
>      def out_typedef(self, fname, name, args):
>          """Outputs a typedef"""
>  
> @@ -472,6 +479,18 @@ class RestFormat(OutputFormat):
>          self.lineprefix = oldprefix
>          self.out_section(args)
>  
> +    def out_global(self, fname, name, args):
> +        oldprefix = self.lineprefix
> +        ln = args.declaration_start_line
> +        prototype = args.other_stuff["var_type"]
> +
> +        self.data += f"
> 
> .. c:var:: {prototype}
> 
> "
> +
> +        self.print_lineno(ln)
> +        self.lineprefix = "  "
> +        self.output_highlight(args.get('purpose', ''))
> +        self.data += "
> "
> +
>      def out_typedef(self, fname, name, args):
>  
>          oldprefix = self.lineprefix
> @@ -772,6 +791,18 @@ class ManFormat(OutputFormat):
>              self.data += f'.SH "{section}"' + "
> "
>              self.output_highlight(text)
>  
> +    def out_global(self, fname, name, args):
> +        out_name = self.arg_name(args, name)
> +        prototype = args.other_stuff["var_type"]
> +
> +        self.data += f'.TH "{self.modulename}" 9 "{out_name}" "{self.man_date}" "API Manual" LINUX' + "
> "
> +
> +        self.data += ".SH NAME
> "
> +        self.data += f"{prototype} \- {args['purpose']}
> "
> +
> +        self.data += ".SH SYNOPSIS
> "
> +        self.data += f"enum {name}" + " {
> "
> +
>      def out_typedef(self, fname, name, args):
>          module = self.modulename
>          purpose = args.get('purpose')
> diff --git a/scripts/lib/kdoc/kdoc_parser.py b/scripts/lib/kdoc/kdoc_parser.py
> index 574972e1f741..e2a3f4574894 100644
> --- a/scripts/lib/kdoc/kdoc_parser.py
> +++ b/scripts/lib/kdoc/kdoc_parser.py
> @@ -64,7 +64,7 @@ type_param = KernRe(r"@(\w*((\.\w+)|(->\w+))*(\.\.\.)?)", cache=False)
>  # Tests for the beginning of a kerneldoc block in its various forms.
>  #
>  doc_block = doc_com + KernRe(r'DOC:\s*(.*)?', cache=False)
> -doc_begin_data = KernRe(r"^\s*\*?\s*(struct|union|enum|typedef)\b\s*(\w*)", cache = False)
> +doc_begin_data = KernRe(r"^\s*\*?\s*(struct|union|enum|typedef|global)\b\s*(\w*)", cache = False)
>  doc_begin_func = KernRe(str(doc_com) +			# initial " * '
>                          r"(?:\w+\s*\*\s*)?" + 		# type (not captured)
>                          r'(?:define\s+)?' + 		# possible "define" (not captured)
> @@ -886,6 +886,27 @@ class KernelDoc:
>          self.output_declaration('enum', declaration_name,
>                                  purpose=self.entry.declaration_purpose)
>  
> +    def dump_global(self, ln, proto):
> +        """
> +        Stores global variables that are part of kAPI.
> +        """
> +        VAR_ATTRIBS = [
> +            "extern",
> +        ]
> +        OPTIONAL_VAR_ATTR = "^(?:" + "|".join(VAR_ATTRIBS) + ")?"
> +
> +        r= KernRe(OPTIONAL_VAR_ATTR + r"(\w.*)\s+([\w_]+)[\d\]\[]*\s*;(?:#.*)?$")
> +        if not r.match(proto):
> +           self.emit_msg(ln,f"{proto}: can't parse variable")
> +           return
> +
> +        declaration_name = r.group(2)
> +        var_type = r.group(0)
> +
> +        self.output_declaration("global", declaration_name,
> +                                var_type=var_type,
> +                                purpose=self.entry.declaration_purpose)
> +
>      def dump_declaration(self, ln, prototype):
>          """
>          Stores a data declaration inside self.entries array.
> @@ -897,6 +918,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 == "global":
> +            self.dump_global(ln, prototype)
>          else:
>              # This would be a bug
>              self.emit_message(ln, f'Unknown declaration type: {self.entry.decl_type}')



Thanks,
Mauro

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH] kernel-doc: add support for handling global variables
  2025-09-07 21:34 ` Mauro Carvalho Chehab
@ 2025-09-09  6:22   ` Randy Dunlap
  2025-09-09 20:12     ` Mauro Carvalho Chehab
  0 siblings, 1 reply; 27+ messages in thread
From: Randy Dunlap @ 2025-09-09  6:22 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Linux Doc Mailing List
  Cc: Jonathan Corbet, linux-kernel



On 9/7/25 2:34 PM, Mauro Carvalho Chehab wrote:
> Em Sun,  7 Sep 2025 18:22:22 +0200
> Mauro Carvalho Chehab <mchehab+huawei@kernel.org> escreveu:
> 
>> 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-c9c4a3b63c09@infradead.org/T/#m947c25d95cb1d96a394410ab1131dc8e9e5013f1
>> Suggested-by: Randy Dunlap <rdunlap@infradead.org>
>> Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
> 
> Btw, this is still at RFC level, as, for the final version we need:
> 
> - to document this new kernel-doc feature;

Yes, I thought of that one.

> - to suppress (or keep) the end ";";

I'll need to see it, but I expect I would prefer to suppress it.

> - do some cleanups/improvements at the regex to ensure that it is generic
>   enough. For instance, the way it was defineded, it doesn't handle yet
>   variables with assigned values like:
> 	extern int foo = 5;
> - if it has a default non-zero value, should it be documented or not,
>   and, if so, how;

I think I came up with some examples (test cases) like these without even
knowing that you had singled them out as possible issues.

> - to decide if we add "extern" to all outputs, to none of them or if we
>   just follow what is at the documented declaration (the current
>   implementation does the latter;

Follow what is documented for now (as you have it).

> - to decide weather use "global"/"var" or something else.

Just stick with "global". It's fine.

> Also, it would be interesting to have a real case where we want
> to document kAPI variables.
> 
> Randy,
> 
> if you have some real case examples, perhaps you could pick this patch
> and add on a patch series after taking the above into consideration.

I just searched for some real case examples and came up with around 6 from
various source files. I put them into one source file that I will include
in a Documentation/ .rst file for testing and let you know how that goes.

Sorry for the delay. I've had some other things going on.

Thanks for working on the feature.

-- 
~Randy


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH] kernel-doc: add support for handling global variables
  2025-09-07 16:22 [PATCH] kernel-doc: add support for handling global variables Mauro Carvalho Chehab
  2025-09-07 21:34 ` Mauro Carvalho Chehab
@ 2025-09-09  7:27 ` Randy Dunlap
  2025-09-09 15:57   ` Randy Dunlap
                     ` (2 more replies)
  2025-09-10  9:24 ` Jani Nikula
  2 siblings, 3 replies; 27+ messages in thread
From: Randy Dunlap @ 2025-09-09  7:27 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Linux Doc Mailing List
  Cc: Jonathan Corbet, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 6377 bytes --]

Hi Mauro,

I have a few patch nits below, then some testing info.


On 9/7/25 9:22 AM, Mauro Carvalho Chehab wrote:
> 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-c9c4a3b63c09@infradead.org/T/#m947c25d95cb1d96a394410ab1131dc8e9e5013f1
> Suggested-by: Randy Dunlap <rdunlap@infradead.org>
> Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
> ---
>  scripts/lib/kdoc/kdoc_output.py | 31 +++++++++++++++++++++++++++++++
>  scripts/lib/kdoc/kdoc_parser.py | 25 ++++++++++++++++++++++++-
>  2 files changed, 55 insertions(+), 1 deletion(-)
> 
> diff --git a/scripts/lib/kdoc/kdoc_output.py b/scripts/lib/kdoc/kdoc_output.py
> index 1eca9a918558..405a5c407522 100644
> --- a/scripts/lib/kdoc/kdoc_output.py
> +++ b/scripts/lib/kdoc/kdoc_output.py
> @@ -199,6 +199,10 @@ class OutputFormat:
>              self.out_enum(fname, name, args)
>              return self.data
>  
> +        if dtype == "global":
> +            self.out_global(fname, name, args)
> +            return self.data
> +
>          if dtype == "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"""
>  
> +    def out_global(self, fname, name, args):
> +        """Outputs a global variable"""
> +
>      def out_typedef(self, fname, name, args):
>          """Outputs a typedef"""
>  
> @@ -472,6 +479,18 @@ class RestFormat(OutputFormat):
>          self.lineprefix = oldprefix
>          self.out_section(args)
>  
> +    def out_global(self, fname, name, args):
> +        oldprefix = self.lineprefix
> +        ln = args.declaration_start_line
> +        prototype = args.other_stuff["var_type"]
> +
> +        self.data += f"
> 
> .. c:var:: {prototype}
> 
> "

Are the 5 lines above supposed to be on one line?  Did git send-email split that up for you?
There are a few others like this below.
patch(1) complains when I try to apply the patch from this email.

> +
> +        self.print_lineno(ln)
> +        self.lineprefix = "  "
> +        self.output_highlight(args.get('purpose', ''))
> +        self.data += "
> "
> +
>      def out_typedef(self, fname, name, args):
>  
>          oldprefix = self.lineprefix
> @@ -772,6 +791,18 @@ class ManFormat(OutputFormat):
>              self.data += f'.SH "{section}"' + "
> "
>              self.output_highlight(text)
>  
> +    def out_global(self, fname, name, args):
> +        out_name = self.arg_name(args, name)
> +        prototype = args.other_stuff["var_type"]
> +
> +        self.data += f'.TH "{self.modulename}" 9 "{out_name}" "{self.man_date}" "API Manual" LINUX' + "
> "
> +
> +        self.data += ".SH NAME
> "
> +        self.data += f"{prototype} \- {args['purpose']}

Python complains about the "\-" above. Other places nearby use "\\-"
so I changed it to that instead. Hope that's OK.

> "
> +
> +        self.data += ".SH SYNOPSIS
> "
> +        self.data += f"enum {name}" + " {
> "
> +
>      def out_typedef(self, fname, name, args):
>          module = self.modulename
>          purpose = args.get('purpose')
> diff --git a/scripts/lib/kdoc/kdoc_parser.py b/scripts/lib/kdoc/kdoc_parser.py
> index 574972e1f741..e2a3f4574894 100644
> --- a/scripts/lib/kdoc/kdoc_parser.py
> +++ b/scripts/lib/kdoc/kdoc_parser.py
> @@ -64,7 +64,7 @@ type_param = KernRe(r"@(\w*((\.\w+)|(->\w+))*(\.\.\.)?)", cache=False)
>  # Tests for the beginning of a kerneldoc block in its various forms.
>  #
>  doc_block = doc_com + KernRe(r'DOC:\s*(.*)?', cache=False)
> -doc_begin_data = KernRe(r"^\s*\*?\s*(struct|union|enum|typedef)\b\s*(\w*)", cache = False)
> +doc_begin_data = KernRe(r"^\s*\*?\s*(struct|union|enum|typedef|global)\b\s*(\w*)", cache = False)
>  doc_begin_func = KernRe(str(doc_com) +			# initial " * '
>                          r"(?:\w+\s*\*\s*)?" + 		# type (not captured)
>                          r'(?:define\s+)?' + 		# possible "define" (not captured)
> @@ -886,6 +886,27 @@ class KernelDoc:
>          self.output_declaration('enum', declaration_name,
>                                  purpose=self.entry.declaration_purpose)
>  
> +    def dump_global(self, ln, proto):
> +        """
> +        Stores global variables that are part of kAPI.
> +        """
> +        VAR_ATTRIBS = [
> +            "extern",
> +        ]
> +        OPTIONAL_VAR_ATTR = "^(?:" + "|".join(VAR_ATTRIBS) + ")?"
> +
> +        r= KernRe(OPTIONAL_VAR_ATTR + r"(\w.*)\s+([\w_]+)[\d\]\[]*\s*;(?:#.*)?$")
> +        if not r.match(proto):
> +           self.emit_msg(ln,f"{proto}: can't parse variable")
> +           return
> +
> +        declaration_name = r.group(2)
> +        var_type = r.group(0)
> +
> +        self.output_declaration("global", declaration_name,
> +                                var_type=var_type,
> +                                purpose=self.entry.declaration_purpose)
> +
>      def dump_declaration(self, ln, prototype):
>          """
>          Stores a data declaration inside self.entries array.
> @@ -897,6 +918,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 == "global":
> +            self.dump_global(ln, prototype)
>          else:
>              # This would be a bug
>              self.emit_message(ln, f'Unknown declaration type: {self.entry.decl_type}')
So, I grabbed some global data from 6-8 places in the kernel and put them intoinit/kdoc-globals-test.c. Then I modified Documentation/core-api/kernel-api.rst
like this at the end of that file:

+
+Kernel Globals
+==========================
+
+.. kernel-doc:: init/kdoc-globals-test.c
+   :identifiers:

The html output says
"Kernel Globals"
but nothing else.

My test files are attached. I dumbed down (simplified) a few
of the globals from fancy types to just unsigned long, but that
didn't help the output results any.

What's happening?
Thanks.

-- 
~Randy

[-- Attachment #2: kdoc-globals-test.patch --]
[-- Type: text/x-patch, Size: 3407 bytes --]

---
 Documentation/core-api/kernel-api.rst |    6 +
 init/kdoc-globals-test.c              |   96 ++++++++++++++++++++++++
 2 files changed, 102 insertions(+)

--- /dev/null
+++ linux-next-20250908/init/kdoc-globals-test.c
@@ -0,0 +1,96 @@
+// kdoc-globals-test.c:
+// test kernel-doc "global" keyword.
+
+// from init/do_mounts.c:
+/**
+ * global ROOT_DEV - system root device
+ *
+ * @ROOT_DEV is either the successful root device or the root device
+ * that failed boot in the boot failure message.
+ */
+unsigned long ROOT_DEV;
+//dev_t ROOT_DEV;
+
+// from init/main.c:
+/**
+ * global system_state - system state used during boot or suspend/hibernate/resume
+ *
+ * @system_state can be used during boot to determine if it is safe to
+ * make certain calls to other parts of the kernel. It can also be used
+ * during suspend/hibernate or resume to determine the order of actions
+ * that need to be executed. The numerical values of system_state are
+ * sometimes used in numerical ordering tests, so the relative values
+ * must not be altered.
+ */
+enum system_states system_state __read_mostly;
+
+/**
+ * global saved_command_line - kernel's command line, saved from use at
+ * any later time in the kernel.
+ */
+char *saved_command_line __ro_after_init;
+
+/**
+ * global loop_per_jiffy - calculated loop count needed to consume one jiffy
+ * of time
+ */
+unsigned long loops_per_jiffy = (1<<12);
+
+// from init/calibrate.c:
+/**
+ * global preset_lpj - lpj (loops per jiffy) value set from kernel
+ * command line using "lpj=VALUE"
+ *
+ * See Documentation/admin-guide/kernel-parameters.txt ("lpj=") for details.
+ */
+unsigned long preset_lpj;
+
+// from init/version.c:
+/**
+ * global linux_proc_banner - text used from /proc/version file
+ *
+ * * first %s is sysname (e.g., "Linux")
+ * * second %s is release
+ * * third %s is version
+ */
+char linux_proc_banner[];
+#if 0
+const char linux_proc_banner[] =
+	"%s version %s"
+	" (" LINUX_COMPILE_BY "@" LINUX_COMPILE_HOST ")"
+	" (" LINUX_COMPILER ") %s\n";
+#endif
+
+// from init/version-timestamp.c:
+/**
+ * global linux_banner - Linux boot banner, usually printed at boot time
+ */
+const char linux_banner[];
+#if 0
+const char linux_banner[] =
+	"Linux version " UTS_RELEASE " (" LINUX_COMPILE_BY "@"
+	LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION "\n";
+#endif
+
+// from block/genhd.c:
+/**
+ * global diskseq - unique sequence number for block device instances
+ *
+ * Allows userspace to associate uevents to the lifetime of a device
+ */
+static atomic64_t diskseq;
+
+// from net/core/rtnetlink.c:
+/**
+ * global rtnl_mutex - historical global lock for networking control operations.
+ *
+ * @rtnl_mutex is used to serialize rtnetlink requests
+ * and protect all kernel internal data structures related to networking.
+ *
+ * See Documentation/networking/netdevices.rst for details.
+ * Often known as the rtnl_lock, although rtnl_lock is a kernel function.
+ */
+unsigned long rtnl_mutex;
+//static DEFINE_MUTEX(rtnl_mutex);
+
+// end test.
--- linux-next-20250908.orig/Documentation/core-api/kernel-api.rst
+++ linux-next-20250908/Documentation/core-api/kernel-api.rst
@@ -428,3 +428,9 @@ Read-Copy Update (RCU)
 .. kernel-doc:: include/linux/rcuref.h
 
 .. kernel-doc:: include/linux/rcutree.h
+
+Kernel Globals
+==========================
+
+.. kernel-doc:: init/kdoc-globals-test.c
+   :identifiers:

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH] kernel-doc: add support for handling global variables
  2025-09-09  7:27 ` Randy Dunlap
@ 2025-09-09 15:57   ` Randy Dunlap
  2025-09-09 16:18     ` Mauro Carvalho Chehab
  2025-09-09 19:58   ` Mauro Carvalho Chehab
  2025-11-17  9:45   ` Mauro Carvalho Chehab
  2 siblings, 1 reply; 27+ messages in thread
From: Randy Dunlap @ 2025-09-09 15:57 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Linux Doc Mailing List
  Cc: Jonathan Corbet, linux-kernel

Hi Mauro,

On 9/9/25 12:27 AM, Randy Dunlap wrote:
> Hi Mauro,
> 
> I have a few patch nits below, then some testing info.
> 
> 
> On 9/7/25 9:22 AM, Mauro Carvalho Chehab wrote:
>> 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-c9c4a3b63c09@infradead.org/T/#m947c25d95cb1d96a394410ab1131dc8e9e5013f1
>> Suggested-by: Randy Dunlap <rdunlap@infradead.org>
>> Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
>> ---
>>  scripts/lib/kdoc/kdoc_output.py | 31 +++++++++++++++++++++++++++++++
>>  scripts/lib/kdoc/kdoc_parser.py | 25 ++++++++++++++++++++++++-
>>  2 files changed, 55 insertions(+), 1 deletion(-)
>>


> So, I grabbed some global data from 6-8 places in the kernel and put them intoinit/kdoc-globals-test.c. Then I modified Documentation/core-api/kernel-api.rst
> like this at the end of that file:
> 
> +
> +Kernel Globals
> +==========================
> +
> +.. kernel-doc:: init/kdoc-globals-test.c
> +   :identifiers:
> 
> The html output says
> "Kernel Globals"
> but nothing else.
> 
> My test files are attached. I dumbed down (simplified) a few
> of the globals from fancy types to just unsigned long, but that
> didn't help the output results any.
> 
> What's happening?
> Thanks.
> 

My problems here could be from a patch mis-merge.
Maybe your patch was against a tree or previous patches that I don't have.

You could supply an updated patch or I can just wait until all
the patches are synchronized for further testing.
Or you could just take my sample and keep testing it.

Thanks.

-- 
~Randy


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH] kernel-doc: add support for handling global variables
  2025-09-09 15:57   ` Randy Dunlap
@ 2025-09-09 16:18     ` Mauro Carvalho Chehab
  2025-09-09 18:20       ` Randy Dunlap
  0 siblings, 1 reply; 27+ messages in thread
From: Mauro Carvalho Chehab @ 2025-09-09 16:18 UTC (permalink / raw)
  To: Randy Dunlap
  Cc: Mauro Carvalho Chehab, Linux Doc Mailing List, Jonathan Corbet,
	linux-kernel

On Tue, Sep 09, 2025 at 08:57:07AM -0700, Randy Dunlap wrote:
> Hi Mauro,
> 
> On 9/9/25 12:27 AM, Randy Dunlap wrote:
> > Hi Mauro,
> > 
> > I have a few patch nits below, then some testing info.
> > 
> > 
> > On 9/7/25 9:22 AM, Mauro Carvalho Chehab wrote:
> >> 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-c9c4a3b63c09@infradead.org/T/#m947c25d95cb1d96a394410ab1131dc8e9e5013f1
> >> Suggested-by: Randy Dunlap <rdunlap@infradead.org>
> >> Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
> >> ---
> >>  scripts/lib/kdoc/kdoc_output.py | 31 +++++++++++++++++++++++++++++++
> >>  scripts/lib/kdoc/kdoc_parser.py | 25 ++++++++++++++++++++++++-
> >>  2 files changed, 55 insertions(+), 1 deletion(-)
> >>
> 
> 
> > So, I grabbed some global data from 6-8 places in the kernel and put them intoinit/kdoc-globals-test.c. Then I modified Documentation/core-api/kernel-api.rst
> > like this at the end of that file:
> > 
> > +
> > +Kernel Globals
> > +==========================
> > +
> > +.. kernel-doc:: init/kdoc-globals-test.c
> > +   :identifiers:
> > 
> > The html output says
> > "Kernel Globals"
> > but nothing else.
> > 
> > My test files are attached. I dumbed down (simplified) a few
> > of the globals from fancy types to just unsigned long, but that
> > didn't help the output results any.
> > 
> > What's happening?
> > Thanks.
> > 
> 
> My problems here could be from a patch mis-merge.
> Maybe your patch was against a tree or previous patches that I don't have.
> 
> You could supply an updated patch or I can just wait until all
> the patches are synchronized for further testing.
> Or you could just take my sample and keep testing it.

I applied it after my sphinx-build-wrapper patch series,
but it doesn't touch kernel-doc. I did a rebase just to make
sure, on the top of docs-next branch from Jon's tree, e.g. 
on the top of:

    git://git.lwn.net/linux.git docs-next

e.g. applying it after:

    7e5a0fe4e8ae ("doc: filesystems: proc: remove stale information from intro")

Patch applied cleanly.

Notice that it probably depends on some changes that Jon
applied for kernel-doc after -rc1.

If you prefer, the patch is here at global_vars branch:

https://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-docs.git/log/?h=global_vars

-- 
Thanks,
Mauro

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH] kernel-doc: add support for handling global variables
  2025-09-09 16:18     ` Mauro Carvalho Chehab
@ 2025-09-09 18:20       ` Randy Dunlap
  2025-09-09 20:37         ` Mauro Carvalho Chehab
  0 siblings, 1 reply; 27+ messages in thread
From: Randy Dunlap @ 2025-09-09 18:20 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: Linux Doc Mailing List, Jonathan Corbet, linux-kernel



On 9/9/25 9:18 AM, Mauro Carvalho Chehab wrote:
> On Tue, Sep 09, 2025 at 08:57:07AM -0700, Randy Dunlap wrote:
>> Hi Mauro,
>>
>> On 9/9/25 12:27 AM, Randy Dunlap wrote:
>>> Hi Mauro,
>>>
>>> I have a few patch nits below, then some testing info.
>>>
>>>
>>> On 9/7/25 9:22 AM, Mauro Carvalho Chehab wrote:
>>>> 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-c9c4a3b63c09@infradead.org/T/#m947c25d95cb1d96a394410ab1131dc8e9e5013f1
>>>> Suggested-by: Randy Dunlap <rdunlap@infradead.org>
>>>> Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
>>>> ---
>>>>  scripts/lib/kdoc/kdoc_output.py | 31 +++++++++++++++++++++++++++++++
>>>>  scripts/lib/kdoc/kdoc_parser.py | 25 ++++++++++++++++++++++++-
>>>>  2 files changed, 55 insertions(+), 1 deletion(-)
>>>>
>>
>>
>>> So, I grabbed some global data from 6-8 places in the kernel and put them intoinit/kdoc-globals-test.c. Then I modified Documentation/core-api/kernel-api.rst
>>> like this at the end of that file:
>>>
>>> +
>>> +Kernel Globals
>>> +==========================
>>> +
>>> +.. kernel-doc:: init/kdoc-globals-test.c
>>> +   :identifiers:
>>>
>>> The html output says
>>> "Kernel Globals"
>>> but nothing else.
>>>
>>> My test files are attached. I dumbed down (simplified) a few
>>> of the globals from fancy types to just unsigned long, but that
>>> didn't help the output results any.
>>>
>>> What's happening?
>>> Thanks.
>>>
>>
>> My problems here could be from a patch mis-merge.
>> Maybe your patch was against a tree or previous patches that I don't have.
>>
>> You could supply an updated patch or I can just wait until all
>> the patches are synchronized for further testing.
>> Or you could just take my sample and keep testing it.
> 
> I applied it after my sphinx-build-wrapper patch series,
> but it doesn't touch kernel-doc. I did a rebase just to make
> sure, on the top of docs-next branch from Jon's tree, e.g. 
> on the top of:
> 
>     git://git.lwn.net/linux.git docs-next
> 
> e.g. applying it after:
> 
>     7e5a0fe4e8ae ("doc: filesystems: proc: remove stale information from intro")
> 
> Patch applied cleanly.
> 
> Notice that it probably depends on some changes that Jon
> applied for kernel-doc after -rc1.
> 
> If you prefer, the patch is here at global_vars branch:
> 
> https://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-docs.git/log/?h=global_vars

Yes, this is much better.

For the simplified global data, it's very good. It produces
2 complaints but the html output is still good:

linux-next-20250909/Documentation/core-api/kernel-api:435: ../init/kdoc-globals-test.c:10: WARNING: Invalid C declaration: Expected end of definition. [error at 32]
  enum system_states system_state __read_mostly;
  --------------------------------^
linux-next-20250909/Documentation/core-api/kernel-api:435: ../init/kdoc-globals-test.c:20: WARNING: Invalid C declaration: Expected end of definition. [error at 25]
  char *saved_command_line __ro_after_init;
  -------------------------^

I suspect that this is not a surprise to you.

For the non-simplified global data, a few of the global items are
completely omitted from the html output. This is the html production:

Kernel Globals
dev_t ROOT_DEV;
system root device

enum system_states system_state __read_mostly;
system state used during boot or suspend/hibernate/resume

char *saved_command_line __ro_after_init;
kernel’s command line, saved from use at any later time in the kernel.

unsigned long preset_lpj;
lpj (loops per jiffy) value set from kernel command line using “lpj=VALUE”

static atomic64_t diskseq;
unique sequence number for block device instances


so these are completely missing/dropped: (they have
initializers or use DEFINE_MUTEX())

/**
 * global loop_per_jiffy - calculated loop count needed to consume one jiffy
 * of time
 */
unsigned long loops_per_jiffy = (1<<12);

// from init/version.c:
/**
 * global linux_proc_banner - text used from /proc/version file
 *
 * * first %s is sysname (e.g., "Linux")
 * * second %s is release
 * * third %s is version
 */
const char linux_proc_banner[] =
	"%s version %s"
	" (" LINUX_COMPILE_BY "@" LINUX_COMPILE_HOST ")"
	" (" LINUX_COMPILER ") %s\n";
//char linux_proc_banner[];

// from init/version-timestamp.c:
/**
 * global linux_banner - Linux boot banner, usually printed at boot time
 */
const char linux_banner[] =
	"Linux version " UTS_RELEASE " (" LINUX_COMPILE_BY "@"
	LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION "\n";
//const char linux_banner[];

// from net/core/rtnetlink.c:
/**
 * global rtnl_mutex - historical global lock for networking control operations.
 *
 * @rtnl_mutex is used to serialize rtnetlink requests
 * and protect all kernel internal data structures related to networking.
 *
 * See Documentation/networking/netdevices.rst for details.
 * Often known as the rtnl_lock, although rtnl_lock is a kernel function.
 */
static DEFINE_MUTEX(rtnl_mutex);


It's looking good. Thanks.

-- 
~Randy


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH] kernel-doc: add support for handling global variables
  2025-09-09  7:27 ` Randy Dunlap
  2025-09-09 15:57   ` Randy Dunlap
@ 2025-09-09 19:58   ` Mauro Carvalho Chehab
  2025-09-09 20:09     ` Mauro Carvalho Chehab
  2025-09-09 21:06     ` Randy Dunlap
  2025-11-17  9:45   ` Mauro Carvalho Chehab
  2 siblings, 2 replies; 27+ messages in thread
From: Mauro Carvalho Chehab @ 2025-09-09 19:58 UTC (permalink / raw)
  To: Randy Dunlap; +Cc: Linux Doc Mailing List, Jonathan Corbet, linux-kernel

Em Tue, 9 Sep 2025 00:27:20 -0700
Randy Dunlap <rdunlap@infradead.org> escreveu:

> Hi Mauro,
> 
> I have a few patch nits below, then some testing info.
> 
> 
> On 9/7/25 9:22 AM, Mauro Carvalho Chehab wrote:
> > 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-c9c4a3b63c09@infradead.org/T/#m947c25d95cb1d96a394410ab1131dc8e9e5013f1
> > Suggested-by: Randy Dunlap <rdunlap@infradead.org>
> > Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
> > ---
> >  scripts/lib/kdoc/kdoc_output.py | 31 +++++++++++++++++++++++++++++++
> >  scripts/lib/kdoc/kdoc_parser.py | 25 ++++++++++++++++++++++++-
> >  2 files changed, 55 insertions(+), 1 deletion(-)
> > 
> > diff --git a/scripts/lib/kdoc/kdoc_output.py b/scripts/lib/kdoc/kdoc_output.py
> > index 1eca9a918558..405a5c407522 100644
> > --- a/scripts/lib/kdoc/kdoc_output.py
> > +++ b/scripts/lib/kdoc/kdoc_output.py
> > @@ -199,6 +199,10 @@ class OutputFormat:
> >              self.out_enum(fname, name, args)
> >              return self.data
> >  
> > +        if dtype == "global":
> > +            self.out_global(fname, name, args)
> > +            return self.data
> > +
> >          if dtype == "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"""
> >  
> > +    def out_global(self, fname, name, args):
> > +        """Outputs a global variable"""
> > +
> >      def out_typedef(self, fname, name, args):
> >          """Outputs a typedef"""
> >  
> > @@ -472,6 +479,18 @@ class RestFormat(OutputFormat):
> >          self.lineprefix = oldprefix
> >          self.out_section(args)
> >  
> > +    def out_global(self, fname, name, args):
> > +        oldprefix = self.lineprefix
> > +        ln = args.declaration_start_line
> > +        prototype = args.other_stuff["var_type"]
> > +
> > +        self.data += f"
> > 
> > .. c:var:: {prototype}
> > 
> > "  
> 
> Are the 5 lines above supposed to be on one line?  Did git send-email split that up for you?
> There are a few others like this below.
> patch(1) complains when I try to apply the patch from this email.

Weird. I'm testing a new mailbomb script... perhaps it is
causing those issues. Yeah, the code snippet is:

+    def out_global(self, fname, name, args):
+        oldprefix = self.lineprefix
+        ln = args.declaration_start_line
+        prototype = args.other_stuff["var_type"]
+
+        self.data += f"\n\n.. c:var:: {prototype}\n\n"
+
+        self.print_lineno(ln)
+        self.lineprefix = "  "
+        self.output_highlight(args.get('purpose', ''))
+        self.data += "\n"

It sounds the mailbomb script replaced "\n" with a new line :-(

> > +        self.print_lineno(ln)
> > +        self.lineprefix = "  "
> > +        self.output_highlight(args.get('purpose', ''))
> > +        self.data += "
> > "
> > +
> >      def out_typedef(self, fname, name, args):
> >  
> >          oldprefix = self.lineprefix
> > @@ -772,6 +791,18 @@ class ManFormat(OutputFormat):
> >              self.data += f'.SH "{section}"' + "
> > "
> >              self.output_highlight(text)
> >  
> > +    def out_global(self, fname, name, args):
> > +        out_name = self.arg_name(args, name)
> > +        prototype = args.other_stuff["var_type"]
> > +
> > +        self.data += f'.TH "{self.modulename}" 9 "{out_name}" "{self.man_date}" "API Manual" LINUX' + "
> > "
> > +
> > +        self.data += ".SH NAME
> > "
> > +        self.data += f"{prototype} \- {args['purpose']}  
> 
> Python complains about the "\-" above. Other places nearby use "\\-"
> so I changed it to that instead. Hope that's OK.
> 

Yes. Again, mailbomb script mangled it. The original code is:

+        self.data += f"{prototype} \\- {args['purpose']}\n"

I'm pasting the full patch at the end.

> > "
> > +
> > +        self.data += ".SH SYNOPSIS
> > "
> > +        self.data += f"enum {name}" + " {
> > "
> > +
> >      def out_typedef(self, fname, name, args):
> >          module = self.modulename
> >          purpose = args.get('purpose')
> > diff --git a/scripts/lib/kdoc/kdoc_parser.py b/scripts/lib/kdoc/kdoc_parser.py
> > index 574972e1f741..e2a3f4574894 100644
> > --- a/scripts/lib/kdoc/kdoc_parser.py
> > +++ b/scripts/lib/kdoc/kdoc_parser.py
> > @@ -64,7 +64,7 @@ type_param = KernRe(r"@(\w*((\.\w+)|(->\w+))*(\.\.\.)?)", cache=False)
> >  # Tests for the beginning of a kerneldoc block in its various forms.
> >  #
> >  doc_block = doc_com + KernRe(r'DOC:\s*(.*)?', cache=False)
> > -doc_begin_data = KernRe(r"^\s*\*?\s*(struct|union|enum|typedef)\b\s*(\w*)", cache = False)
> > +doc_begin_data = KernRe(r"^\s*\*?\s*(struct|union|enum|typedef|global)\b\s*(\w*)", cache = False)
> >  doc_begin_func = KernRe(str(doc_com) +			# initial " * '
> >                          r"(?:\w+\s*\*\s*)?" + 		# type (not captured)
> >                          r'(?:define\s+)?' + 		# possible "define" (not captured)
> > @@ -886,6 +886,27 @@ class KernelDoc:
> >          self.output_declaration('enum', declaration_name,
> >                                  purpose=self.entry.declaration_purpose)
> >  
> > +    def dump_global(self, ln, proto):
> > +        """
> > +        Stores global variables that are part of kAPI.
> > +        """
> > +        VAR_ATTRIBS = [
> > +            "extern",
> > +        ]
> > +        OPTIONAL_VAR_ATTR = "^(?:" + "|".join(VAR_ATTRIBS) + ")?"
> > +
> > +        r= KernRe(OPTIONAL_VAR_ATTR + r"(\w.*)\s+([\w_]+)[\d\]\[]*\s*;(?:#.*)?$")
> > +        if not r.match(proto):
> > +           self.emit_msg(ln,f"{proto}: can't parse variable")
> > +           return
> > +
> > +        declaration_name = r.group(2)
> > +        var_type = r.group(0)
> > +
> > +        self.output_declaration("global", declaration_name,
> > +                                var_type=var_type,
> > +                                purpose=self.entry.declaration_purpose)
> > +
> >      def dump_declaration(self, ln, prototype):
> >          """
> >          Stores a data declaration inside self.entries array.
> > @@ -897,6 +918,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 == "global":
> > +            self.dump_global(ln, prototype)
> >          else:
> >              # This would be a bug
> >              self.emit_message(ln, f'Unknown declaration type: {self.entry.decl_type}')  
> So, I grabbed some global data from 6-8 places in the kernel and put them intoinit/kdoc-globals-test.c. Then I modified Documentation/core-api/kernel-api.rst
> like this at the end of that file:
> 
> +
> +Kernel Globals
> +==========================
> +
> +.. kernel-doc:: init/kdoc-globals-test.c
> +   :identifiers:
> 
> The html output says
> "Kernel Globals"
> but nothing else.

I usually don't add :identifiers: on kernel-doc entries. If you use
identifiers, you need to explicitly tell what symbols you want.

As a reference, kerneldoc.py logic for identifiers is:

	if 'identifiers' in self.options:                                                                                                                                                                      
            identifiers = self.options.get('identifiers').split()                                                                                                                                                
            if identifiers:
                for i in identifiers:
                    i = i.rstrip("\\").strip()
                    if not i:
                        continue

                    cmd += ['-function', i]
                    self.msg_args["symbol"].append(i)

without it, it will pick the entire set of symbols. 

> My test files are attached. I dumbed down (simplified) a few
> of the globals from fancy types to just unsigned long, but that
> didn't help the output results any.

Looking on your attachment, you can either drop :identifiers:
or list all of them:

	.. kernel-doc:: init/kdoc-globals-test.c
	   :identifiers: ROOT_DEV loop_per_jiffy
	   :identifiers: preset_lpj

(here, it should only show those 3 symbols)

see, having this:

	.. kernel-doc:: init/kdoc-globals-test.c
	   :identifiers: ROOT_DEV 

will run:

	$ ./scripts/kernel-doc init/kdoc-globals-test.c -function ROOT_DEV 


	.. c:var:: unsigned long ROOT_DEV;

	  system root device




> What's happening?
> Thanks.





Thanks,
Mauro

---


From 80f85eacc306e62de8c9c68712c653ba290c2ff2 Mon Sep 17 00:00:00 2001
From: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
Date: Sat, 6 Sep 2025 23:30:43 +0200
Subject: [PATCH] kernel-doc: add support for handling global variables

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-c9c4a3b63c09@infradead.org/T/#m947c25d95cb1d96a394410ab1131dc8e9e5013f1
Suggested-by: Randy Dunlap <rdunlap@infradead.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>

diff --git a/scripts/lib/kdoc/kdoc_output.py b/scripts/lib/kdoc/kdoc_output.py
index 1eca9a918558..405a5c407522 100644
--- a/scripts/lib/kdoc/kdoc_output.py
+++ b/scripts/lib/kdoc/kdoc_output.py
@@ -199,6 +199,10 @@ class OutputFormat:
             self.out_enum(fname, name, args)
             return self.data
 
+        if dtype == "global":
+            self.out_global(fname, name, args)
+            return self.data
+
         if dtype == "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"""
 
+    def out_global(self, fname, name, args):
+        """Outputs a global variable"""
+
     def out_typedef(self, fname, name, args):
         """Outputs a typedef"""
 
@@ -472,6 +479,18 @@ class RestFormat(OutputFormat):
         self.lineprefix = oldprefix
         self.out_section(args)
 
+    def out_global(self, fname, name, args):
+        oldprefix = self.lineprefix
+        ln = args.declaration_start_line
+        prototype = args.other_stuff["var_type"]
+
+        self.data += f"\n\n.. c:var:: {prototype}\n\n"
+
+        self.print_lineno(ln)
+        self.lineprefix = "  "
+        self.output_highlight(args.get('purpose', ''))
+        self.data += "\n"
+
     def out_typedef(self, fname, name, args):
 
         oldprefix = self.lineprefix
@@ -772,6 +791,18 @@ class ManFormat(OutputFormat):
             self.data += f'.SH "{section}"' + "\n"
             self.output_highlight(text)
 
+    def out_global(self, fname, name, args):
+        out_name = self.arg_name(args, name)
+        prototype = args.other_stuff["var_type"]
+
+        self.data += f'.TH "{self.modulename}" 9 "{out_name}" "{self.man_date}" "API Manual" LINUX' + "\n"
+
+        self.data += ".SH NAME\n"
+        self.data += f"{prototype} \\- {args['purpose']}\n"
+
+        self.data += ".SH SYNOPSIS\n"
+        self.data += f"enum {name}" + " {\n"
+
     def out_typedef(self, fname, name, args):
         module = self.modulename
         purpose = args.get('purpose')
diff --git a/scripts/lib/kdoc/kdoc_parser.py b/scripts/lib/kdoc/kdoc_parser.py
index 574972e1f741..e2a3f4574894 100644
--- a/scripts/lib/kdoc/kdoc_parser.py
+++ b/scripts/lib/kdoc/kdoc_parser.py
@@ -64,7 +64,7 @@ type_param = KernRe(r"@(\w*((\.\w+)|(->\w+))*(\.\.\.)?)", cache=False)
 # Tests for the beginning of a kerneldoc block in its various forms.
 #
 doc_block = doc_com + KernRe(r'DOC:\s*(.*)?', cache=False)
-doc_begin_data = KernRe(r"^\s*\*?\s*(struct|union|enum|typedef)\b\s*(\w*)", cache = False)
+doc_begin_data = KernRe(r"^\s*\*?\s*(struct|union|enum|typedef|global)\b\s*(\w*)", cache = False)
 doc_begin_func = KernRe(str(doc_com) +			# initial " * '
                         r"(?:\w+\s*\*\s*)?" + 		# type (not captured)
                         r'(?:define\s+)?' + 		# possible "define" (not captured)
@@ -886,6 +886,27 @@ class KernelDoc:
         self.output_declaration('enum', declaration_name,
                                 purpose=self.entry.declaration_purpose)
 
+    def dump_global(self, ln, proto):
+        """
+        Stores global variables that are part of kAPI.
+        """
+        VAR_ATTRIBS = [
+            "extern",
+        ]
+        OPTIONAL_VAR_ATTR = "^(?:" + "|".join(VAR_ATTRIBS) + ")?"
+
+        r= KernRe(OPTIONAL_VAR_ATTR + r"(\w.*)\s+([\w_]+)[\d\]\[]*\s*;(?:#.*)?$")
+        if not r.match(proto):
+           self.emit_msg(ln,f"{proto}: can't parse variable")
+           return
+
+        declaration_name = r.group(2)
+        var_type = r.group(0)
+
+        self.output_declaration("global", declaration_name,
+                                var_type=var_type,
+                                purpose=self.entry.declaration_purpose)
+
     def dump_declaration(self, ln, prototype):
         """
         Stores a data declaration inside self.entries array.
@@ -897,6 +918,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 == "global":
+            self.dump_global(ln, prototype)
         else:
             # This would be a bug
             self.emit_message(ln, f'Unknown declaration type: {self.entry.decl_type}')

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* Re: [PATCH] kernel-doc: add support for handling global variables
  2025-09-09 19:58   ` Mauro Carvalho Chehab
@ 2025-09-09 20:09     ` Mauro Carvalho Chehab
  2025-09-09 21:06     ` Randy Dunlap
  1 sibling, 0 replies; 27+ messages in thread
From: Mauro Carvalho Chehab @ 2025-09-09 20:09 UTC (permalink / raw)
  To: Randy Dunlap; +Cc: Linux Doc Mailing List, Jonathan Corbet, linux-kernel

Em Tue, 9 Sep 2025 21:58:24 +0200
Mauro Carvalho Chehab <mchehab+huawei@kernel.org> escreveu:

> Em Tue, 9 Sep 2025 00:27:20 -0700
> Randy Dunlap <rdunlap@infradead.org> escreveu:
> 
> > Hi Mauro,
> > 
> > I have a few patch nits below, then some testing info.
> > 

> see, having this:
> 
> 	.. kernel-doc:: init/kdoc-globals-test.c
> 	   :identifiers: ROOT_DEV 
> 
> will run:
> 
> 	$ ./scripts/kernel-doc init/kdoc-globals-test.c -function ROOT_DEV 
> 
> 
> 	.. c:var:: unsigned long ROOT_DEV;
> 
> 	  system root device
> 

On a side note, looking at the description you wrote for this:

	+/**
	+ * global ROOT_DEV - system root device
	+ *
	+ * @ROOT_DEV is either the successful root device or the root device
	+ * that failed boot in the boot failure message.
	+ */
	+unsigned long ROOT_DEV;

the output logic is not picking the description, while it should.
The description is there: we just need to add them to the output
data. It should be stored as "Description" inside sections.

The code to output it should be similar to:

	# For ReST
	self.out_section(args)

	# For man page:
	for section, text in args.sections.items():
            self.data += f'.SH "{section}"' + "\n"
            self.output_highlight(text)





Thanks,
Mauro

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH] kernel-doc: add support for handling global variables
  2025-09-09  6:22   ` Randy Dunlap
@ 2025-09-09 20:12     ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 27+ messages in thread
From: Mauro Carvalho Chehab @ 2025-09-09 20:12 UTC (permalink / raw)
  To: Randy Dunlap; +Cc: Linux Doc Mailing List, Jonathan Corbet, linux-kernel

Em Mon, 8 Sep 2025 23:22:13 -0700
Randy Dunlap <rdunlap@infradead.org> escreveu:

> On 9/7/25 2:34 PM, Mauro Carvalho Chehab wrote:
> > Em Sun,  7 Sep 2025 18:22:22 +0200
> > Mauro Carvalho Chehab <mchehab+huawei@kernel.org> escreveu:
> >   
> >> 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-c9c4a3b63c09@infradead.org/T/#m947c25d95cb1d96a394410ab1131dc8e9e5013f1
> >> Suggested-by: Randy Dunlap <rdunlap@infradead.org>
> >> Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>  
> > 
> > Btw, this is still at RFC level, as, for the final version we need:
> > 
> > - to document this new kernel-doc feature;  
> 
> Yes, I thought of that one.
> 
> > - to suppress (or keep) the end ";";  
> 
> I'll need to see it, but I expect I would prefer to suppress it.

Ok. Yeah, that's probably the better.

> > - do some cleanups/improvements at the regex to ensure that it is generic
> >   enough. For instance, the way it was defineded, it doesn't handle yet
> >   variables with assigned values like:
> > 	extern int foo = 5;
> > - if it has a default non-zero value, should it be documented or not,
> >   and, if so, how;  
> 
> I think I came up with some examples (test cases) like these without even
> knowing that you had singled them out as possible issues.

Sounds good. Yeah, having some real-case scenarios will help discovering
what else we need for the regex and for the output.

> > - to decide if we add "extern" to all outputs, to none of them or if we
> >   just follow what is at the documented declaration (the current
> >   implementation does the latter;  
> 
> Follow what is documented for now (as you have it).

Ok.

> > - to decide weather use "global"/"var" or something else.  
> 
> Just stick with "global". It's fine.

Ok.

> > Also, it would be interesting to have a real case where we want
> > to document kAPI variables.
> > 
> > Randy,
> > 
> > if you have some real case examples, perhaps you could pick this patch
> > and add on a patch series after taking the above into consideration.  
> 
> I just searched for some real case examples and came up with around 6 from
> various source files. I put them into one source file that I will include
> in a Documentation/ .rst file for testing and let you know how that goes.
> 
> Sorry for the delay. I've had some other things going on.

No problem. Take your time.

> Thanks for working on the feature.

Anytime.

Thanks,
Mauro

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH] kernel-doc: add support for handling global variables
  2025-09-09 18:20       ` Randy Dunlap
@ 2025-09-09 20:37         ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 27+ messages in thread
From: Mauro Carvalho Chehab @ 2025-09-09 20:37 UTC (permalink / raw)
  To: Randy Dunlap; +Cc: Linux Doc Mailing List, Jonathan Corbet, linux-kernel

Em Tue, 9 Sep 2025 11:20:31 -0700
Randy Dunlap <rdunlap@infradead.org> escreveu:

> On 9/9/25 9:18 AM, Mauro Carvalho Chehab wrote:
> > On Tue, Sep 09, 2025 at 08:57:07AM -0700, Randy Dunlap wrote:  
> >> Hi Mauro,
> >>
> >> On 9/9/25 12:27 AM, Randy Dunlap wrote:  
> >>> Hi Mauro,
> >>>
> >>> I have a few patch nits below, then some testing info.
> >>>
> >>>
> >>> On 9/7/25 9:22 AM, Mauro Carvalho Chehab wrote:  
> >>>> 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-c9c4a3b63c09@infradead.org/T/#m947c25d95cb1d96a394410ab1131dc8e9e5013f1
> >>>> Suggested-by: Randy Dunlap <rdunlap@infradead.org>
> >>>> Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
> >>>> ---
> >>>>  scripts/lib/kdoc/kdoc_output.py | 31 +++++++++++++++++++++++++++++++
> >>>>  scripts/lib/kdoc/kdoc_parser.py | 25 ++++++++++++++++++++++++-
> >>>>  2 files changed, 55 insertions(+), 1 deletion(-)
> >>>>  
> >>
> >>  
> >>> So, I grabbed some global data from 6-8 places in the kernel and put them intoinit/kdoc-globals-test.c. Then I modified Documentation/core-api/kernel-api.rst
> >>> like this at the end of that file:
> >>>
> >>> +
> >>> +Kernel Globals
> >>> +==========================
> >>> +
> >>> +.. kernel-doc:: init/kdoc-globals-test.c
> >>> +   :identifiers:
> >>>
> >>> The html output says
> >>> "Kernel Globals"
> >>> but nothing else.
> >>>
> >>> My test files are attached. I dumbed down (simplified) a few
> >>> of the globals from fancy types to just unsigned long, but that
> >>> didn't help the output results any.
> >>>
> >>> What's happening?
> >>> Thanks.
> >>>  
> >>
> >> My problems here could be from a patch mis-merge.
> >> Maybe your patch was against a tree or previous patches that I don't have.
> >>
> >> You could supply an updated patch or I can just wait until all
> >> the patches are synchronized for further testing.
> >> Or you could just take my sample and keep testing it.  
> > 
> > I applied it after my sphinx-build-wrapper patch series,
> > but it doesn't touch kernel-doc. I did a rebase just to make
> > sure, on the top of docs-next branch from Jon's tree, e.g. 
> > on the top of:
> > 
> >     git://git.lwn.net/linux.git docs-next
> > 
> > e.g. applying it after:
> > 
> >     7e5a0fe4e8ae ("doc: filesystems: proc: remove stale information from intro")
> > 
> > Patch applied cleanly.
> > 
> > Notice that it probably depends on some changes that Jon
> > applied for kernel-doc after -rc1.
> > 
> > If you prefer, the patch is here at global_vars branch:
> > 
> > https://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-docs.git/log/?h=global_vars  
> 
> Yes, this is much better.
> 
> For the simplified global data, it's very good. It produces
> 2 complaints but the html output is still good:
> 
> linux-next-20250909/Documentation/core-api/kernel-api:435: ../init/kdoc-globals-test.c:10: WARNING: Invalid C declaration: Expected end of definition. [error at 32]
>   enum system_states system_state __read_mostly;
>   --------------------------------^
> linux-next-20250909/Documentation/core-api/kernel-api:435: ../init/kdoc-globals-test.c:20: WARNING: Invalid C declaration: Expected end of definition. [error at 25]
>   char *saved_command_line __ro_after_init;
>   -------------------------^
> 
> I suspect that this is not a surprise to you.

Not a surprise. The C domain parser is very strict with regards to 
C syntax.

On the above examples, __read_mostly and __ro_after_init are
macros. Sphinx has no clue about what to do with them. 

We'll need something similar to what we do on structs and functions
to strip things like this:

	sub_prefixes = [
...
            (r"__deprecated +", "", 0),
            (r"__flatten +", "", 0),
            (r"__meminit +", "", 0),
...
        ]

        for search, sub, flags in sub_prefixes:
            prototype = KernRe(search, flags).sub(sub, prototype)

to strip them for the prototype that will be used for .. :c::var.

I guess we have three alternatives here:

1. use the simplified version only, after being converted into a pure
   C code without macros;

2. use simplified version for :c::var: and print the complete one
   ourselves (this is how structs are printed);

3. use another c domain type that would just get a name. Then
   output ourselves the var prototype, captured as-is.

IMHO, from the above, (3) is better, but looking at:

	https://www.sphinx-doc.org/en/master/usage/domains/c.html

It would likely mean we'll need to use :c:macro:

> For the non-simplified global data, a few of the global items are
> completely omitted from the html output. This is the html production:
> 
> Kernel Globals
> dev_t ROOT_DEV;
> system root device
> 
> enum system_states system_state __read_mostly;
> system state used during boot or suspend/hibernate/resume
> 
> char *saved_command_line __ro_after_init;
> kernel’s command line, saved from use at any later time in the kernel.
> 
> unsigned long preset_lpj;
> lpj (loops per jiffy) value set from kernel command line using “lpj=VALUE”
> 
> static atomic64_t diskseq;
> unique sequence number for block device instances
> 
> 
> so these are completely missing/dropped: (they have
> initializers or use DEFINE_MUTEX())

Yeah, the regex is not capturing initializers nor handling macros.
We'll need to improve it.

things like DEFINE_MUTEX() would require either a sub pattern or
some regexes to detect them.

> 
> /**
>  * global loop_per_jiffy - calculated loop count needed to consume one jiffy
>  * of time
>  */
> unsigned long loops_per_jiffy = (1<<12);
> 
> // from init/version.c:
> /**
>  * global linux_proc_banner - text used from /proc/version file
>  *
>  * * first %s is sysname (e.g., "Linux")
>  * * second %s is release
>  * * third %s is version
>  */
> const char linux_proc_banner[] =
> 	"%s version %s"
> 	" (" LINUX_COMPILE_BY "@" LINUX_COMPILE_HOST ")"
> 	" (" LINUX_COMPILER ") %s\n";
> //char linux_proc_banner[];
> 
> // from init/version-timestamp.c:
> /**
>  * global linux_banner - Linux boot banner, usually printed at boot time
>  */
> const char linux_banner[] =
> 	"Linux version " UTS_RELEASE " (" LINUX_COMPILE_BY "@"
> 	LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION "\n";
> //const char linux_banner[];
> 
> // from net/core/rtnetlink.c:
> /**
>  * global rtnl_mutex - historical global lock for networking control operations.
>  *
>  * @rtnl_mutex is used to serialize rtnetlink requests
>  * and protect all kernel internal data structures related to networking.
>  *
>  * See Documentation/networking/netdevices.rst for details.
>  * Often known as the rtnl_lock, although rtnl_lock is a kernel function.
>  */
> static DEFINE_MUTEX(rtnl_mutex);
> 
> 
> It's looking good. Thanks.

Agreed.

Thanks,
Mauro

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH] kernel-doc: add support for handling global variables
  2025-09-09 19:58   ` Mauro Carvalho Chehab
  2025-09-09 20:09     ` Mauro Carvalho Chehab
@ 2025-09-09 21:06     ` Randy Dunlap
  2025-09-09 23:09       ` Mauro Carvalho Chehab
  1 sibling, 1 reply; 27+ messages in thread
From: Randy Dunlap @ 2025-09-09 21:06 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: Linux Doc Mailing List, Jonathan Corbet, linux-kernel



On 9/9/25 12:58 PM, Mauro Carvalho Chehab wrote:
> Em Tue, 9 Sep 2025 00:27:20 -0700
> Randy Dunlap <rdunlap@infradead.org> escreveu:
> 
>> Hi Mauro,
>>


>> So, I grabbed some global data from 6-8 places in the kernel and put them intoinit/kdoc-globals-test.c. Then I modified Documentation/core-api/kernel-api.rst
>> like this at the end of that file:
>>
>> +
>> +Kernel Globals
>> +==========================
>> +
>> +.. kernel-doc:: init/kdoc-globals-test.c
>> +   :identifiers:
>>
>> The html output says
>> "Kernel Globals"
>> but nothing else.
> 
> I usually don't add :identifiers: on kernel-doc entries. If you use
> identifiers, you need to explicitly tell what symbols you want.

Well, it worked/works without using having any identifiers listed, and
the docs in Documentation/doc-guide/kernel-doc.rst says that they are
optional:

identifiers: *[ function/type ...]*
  Include documentation for each *function* and *type* in *source*.
  If no *function* is specified, the documentation for all functions
  and types in the *source* will be included.
  *type* can be a struct, union, enum, or typedef identifier.


> As a reference, kerneldoc.py logic for identifiers is:
> 
> 	if 'identifiers' in self.options:                                                                                                                                                                      
>             identifiers = self.options.get('identifiers').split()                                                                                                                                                
>             if identifiers:
>                 for i in identifiers:
>                     i = i.rstrip("\\").strip()
>                     if not i:
>                         continue
> 
>                     cmd += ['-function', i]
>                     self.msg_args["symbol"].append(i)
> 
> without it, it will pick the entire set of symbols. 

Yeah, that's exactly what I want, so I don't see a problem.


>> My test files are attached. I dumbed down (simplified) a few
>> of the globals from fancy types to just unsigned long, but that
>> didn't help the output results any.
> 
> Looking on your attachment, you can either drop :identifiers:
> or list all of them:
> 
> 	.. kernel-doc:: init/kdoc-globals-test.c
> 	   :identifiers: ROOT_DEV loop_per_jiffy
> 	   :identifiers: preset_lpj
> 
> (here, it should only show those 3 symbols)
> 
> see, having this:
> 
> 	.. kernel-doc:: init/kdoc-globals-test.c
> 	   :identifiers: ROOT_DEV 
> 
> will run:
> 
> 	$ ./scripts/kernel-doc init/kdoc-globals-test.c -function ROOT_DEV 
> 
> 
> 	.. c:var:: unsigned long ROOT_DEV;
> 
> 	  system root device


Yes, I understand how to use explicit identifiers.  :)
Thanks.
-- 
~Randy


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH] kernel-doc: add support for handling global variables
  2025-09-09 21:06     ` Randy Dunlap
@ 2025-09-09 23:09       ` Mauro Carvalho Chehab
  2025-09-09 23:49         ` Randy Dunlap
  0 siblings, 1 reply; 27+ messages in thread
From: Mauro Carvalho Chehab @ 2025-09-09 23:09 UTC (permalink / raw)
  To: Randy Dunlap; +Cc: Linux Doc Mailing List, Jonathan Corbet, linux-kernel

Em Tue, 9 Sep 2025 14:06:43 -0700
Randy Dunlap <rdunlap@infradead.org> escreveu:

> On 9/9/25 12:58 PM, Mauro Carvalho Chehab wrote:
> > Em Tue, 9 Sep 2025 00:27:20 -0700
> > Randy Dunlap <rdunlap@infradead.org> escreveu:

> >> +.. kernel-doc:: init/kdoc-globals-test.c
> >> +   :identifiers:
> >>
> >> The html output says
> >> "Kernel Globals"
> >> but nothing else.  
> > 
> > I usually don't add :identifiers: on kernel-doc entries. If you use
> > identifiers, you need to explicitly tell what symbols you want.  
> 
> Well, it worked/works without using having any identifiers listed, and
> the docs in Documentation/doc-guide/kernel-doc.rst says that they are
> optional:
> 
> identifiers: *[ function/type ...]*
>   Include documentation for each *function* and *type* in *source*.
>   If no *function* is specified, the documentation for all functions
>   and types in the *source* will be included.
>   *type* can be a struct, union, enum, or typedef identifier.

Hmm.. looking the entire logic:

        elif 'identifiers' in self.options:
            identifiers = self.options.get('identifiers').split()
            if identifiers:
                for i in identifiers:
                    i = i.rstrip("\\").strip()
                    if not i:
                        continue

                    cmd += ['-function', i]
                    self.msg_args["symbol"].append(i)
            else:
                cmd += ['-no-doc-sections']
                self.msg_args["no_doc_sections"] = True

I suspect that an empty identifier could be raising an exception.

The right logic should be, instead:

-        elif 'identifiers' in self.options:
-            identifiers = self.options.get('identifiers').split()
-            if identifiers:
-                for i in identifiers:
+        elif 'identifiers' in self.options:
+            identifiers = self.options.get('identifiers')
+            if identifiers:
+                for i in identifiers.split():

(tests needed)

Thanks,
Mauro

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH] kernel-doc: add support for handling global variables
  2025-09-09 23:09       ` Mauro Carvalho Chehab
@ 2025-09-09 23:49         ` Randy Dunlap
  2025-09-09 23:50           ` Randy Dunlap
  0 siblings, 1 reply; 27+ messages in thread
From: Randy Dunlap @ 2025-09-09 23:49 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: Linux Doc Mailing List, Jonathan Corbet, linux-kernel



On 9/9/25 4:09 PM, Mauro Carvalho Chehab wrote:
> Em Tue, 9 Sep 2025 14:06:43 -0700
> Randy Dunlap <rdunlap@infradead.org> escreveu:
> 
>> On 9/9/25 12:58 PM, Mauro Carvalho Chehab wrote:
>>> Em Tue, 9 Sep 2025 00:27:20 -0700
>>> Randy Dunlap <rdunlap@infradead.org> escreveu:
> 
>>>> +.. kernel-doc:: init/kdoc-globals-test.c
>>>> +   :identifiers:
>>>>
>>>> The html output says
>>>> "Kernel Globals"
>>>> but nothing else.  
>>>
>>> I usually don't add :identifiers: on kernel-doc entries. If you use
>>> identifiers, you need to explicitly tell what symbols you want.  
>>
>> Well, it worked/works without using having any identifiers listed, and
>> the docs in Documentation/doc-guide/kernel-doc.rst says that they are
>> optional:
>>
>> identifiers: *[ function/type ...]*
>>   Include documentation for each *function* and *type* in *source*.
>>   If no *function* is specified, the documentation for all functions
>>   and types in the *source* will be included.
>>   *type* can be a struct, union, enum, or typedef identifier.
> 
> Hmm.. looking the entire logic:
> 
>         elif 'identifiers' in self.options:
>             identifiers = self.options.get('identifiers').split()
>             if identifiers:
>                 for i in identifiers:
>                     i = i.rstrip("\\").strip()
>                     if not i:
>                         continue
> 
>                     cmd += ['-function', i]
>                     self.msg_args["symbol"].append(i)
>             else:
>                 cmd += ['-no-doc-sections']
>                 self.msg_args["no_doc_sections"] = True
> 
> I suspect that an empty identifier could be raising an exception.
> 
> The right logic should be, instead:
> 
> -        elif 'identifiers' in self.options:
> -            identifiers = self.options.get('identifiers').split()
> -            if identifiers:
> -                for i in identifiers:
> +        elif 'identifiers' in self.options:
> +            identifiers = self.options.get('identifiers')
> +            if identifiers:
> +                for i in identifiers.split():
> 
> (tests needed)

Sheesh, I can't find that code so that I can patch it.
(in today's linux-next 20250909)

Anyway, does this take away something that currently works?

thanks.
-- 
~Randy


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH] kernel-doc: add support for handling global variables
  2025-09-09 23:49         ` Randy Dunlap
@ 2025-09-09 23:50           ` Randy Dunlap
  2025-09-10  0:02             ` Randy Dunlap
  0 siblings, 1 reply; 27+ messages in thread
From: Randy Dunlap @ 2025-09-09 23:50 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: Linux Doc Mailing List, Jonathan Corbet, linux-kernel



On 9/9/25 4:49 PM, Randy Dunlap wrote:
> 
> 
> On 9/9/25 4:09 PM, Mauro Carvalho Chehab wrote:
>> Em Tue, 9 Sep 2025 14:06:43 -0700
>> Randy Dunlap <rdunlap@infradead.org> escreveu:
>>
>>> On 9/9/25 12:58 PM, Mauro Carvalho Chehab wrote:
>>>> Em Tue, 9 Sep 2025 00:27:20 -0700
>>>> Randy Dunlap <rdunlap@infradead.org> escreveu:
>>
>>>>> +.. kernel-doc:: init/kdoc-globals-test.c
>>>>> +   :identifiers:
>>>>>
>>>>> The html output says
>>>>> "Kernel Globals"
>>>>> but nothing else.  
>>>>
>>>> I usually don't add :identifiers: on kernel-doc entries. If you use
>>>> identifiers, you need to explicitly tell what symbols you want.  
>>>
>>> Well, it worked/works without using having any identifiers listed, and
>>> the docs in Documentation/doc-guide/kernel-doc.rst says that they are
>>> optional:
>>>
>>> identifiers: *[ function/type ...]*
>>>   Include documentation for each *function* and *type* in *source*.
>>>   If no *function* is specified, the documentation for all functions
>>>   and types in the *source* will be included.
>>>   *type* can be a struct, union, enum, or typedef identifier.
>>
>> Hmm.. looking the entire logic:
>>
>>         elif 'identifiers' in self.options:
>>             identifiers = self.options.get('identifiers').split()
>>             if identifiers:
>>                 for i in identifiers:
>>                     i = i.rstrip("\\").strip()
>>                     if not i:
>>                         continue
>>
>>                     cmd += ['-function', i]
>>                     self.msg_args["symbol"].append(i)
>>             else:
>>                 cmd += ['-no-doc-sections']
>>                 self.msg_args["no_doc_sections"] = True
>>
>> I suspect that an empty identifier could be raising an exception.
>>
>> The right logic should be, instead:
>>
>> -        elif 'identifiers' in self.options:
>> -            identifiers = self.options.get('identifiers').split()
>> -            if identifiers:
>> -                for i in identifiers:
>> +        elif 'identifiers' in self.options:
>> +            identifiers = self.options.get('identifiers')
>> +            if identifiers:
>> +                for i in identifiers.split():
>>
>> (tests needed)
> 
> Sheesh, I can't find that code so that I can patch it.
> (in today's linux-next 20250909)

oops, I was looking in scripts/ and not in Documentation/.
got it.

> Anyway, does this take away something that currently works?
> 
> thanks.

-- 
~Randy


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH] kernel-doc: add support for handling global variables
  2025-09-09 23:50           ` Randy Dunlap
@ 2025-09-10  0:02             ` Randy Dunlap
  2025-09-10  4:23               ` Mauro Carvalho Chehab
  0 siblings, 1 reply; 27+ messages in thread
From: Randy Dunlap @ 2025-09-10  0:02 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: Linux Doc Mailing List, Jonathan Corbet, linux-kernel



On 9/9/25 4:50 PM, Randy Dunlap wrote:
> 
> 
> On 9/9/25 4:49 PM, Randy Dunlap wrote:
>>
>>
>> On 9/9/25 4:09 PM, Mauro Carvalho Chehab wrote:
>>> Em Tue, 9 Sep 2025 14:06:43 -0700
>>> Randy Dunlap <rdunlap@infradead.org> escreveu:
>>>
>>>> On 9/9/25 12:58 PM, Mauro Carvalho Chehab wrote:
>>>>> Em Tue, 9 Sep 2025 00:27:20 -0700
>>>>> Randy Dunlap <rdunlap@infradead.org> escreveu:
>>>
>>>>>> +.. kernel-doc:: init/kdoc-globals-test.c
>>>>>> +   :identifiers:
>>>>>>
>>>>>> The html output says
>>>>>> "Kernel Globals"
>>>>>> but nothing else.  
>>>>>
>>>>> I usually don't add :identifiers: on kernel-doc entries. If you use
>>>>> identifiers, you need to explicitly tell what symbols you want.  
>>>>
>>>> Well, it worked/works without using having any identifiers listed, and
>>>> the docs in Documentation/doc-guide/kernel-doc.rst says that they are
>>>> optional:
>>>>
>>>> identifiers: *[ function/type ...]*
>>>>   Include documentation for each *function* and *type* in *source*.
>>>>   If no *function* is specified, the documentation for all functions
>>>>   and types in the *source* will be included.
>>>>   *type* can be a struct, union, enum, or typedef identifier.
>>>
>>> Hmm.. looking the entire logic:
>>>
>>>         elif 'identifiers' in self.options:
>>>             identifiers = self.options.get('identifiers').split()
>>>             if identifiers:
>>>                 for i in identifiers:
>>>                     i = i.rstrip("\\").strip()
>>>                     if not i:
>>>                         continue
>>>
>>>                     cmd += ['-function', i]
>>>                     self.msg_args["symbol"].append(i)
>>>             else:
>>>                 cmd += ['-no-doc-sections']
>>>                 self.msg_args["no_doc_sections"] = True
>>>
>>> I suspect that an empty identifier could be raising an exception.

and it's being caught and ignored (not printed)?

>>> The right logic should be, instead:
>>>
>>> -        elif 'identifiers' in self.options:
>>> -            identifiers = self.options.get('identifiers').split()
>>> -            if identifiers:
>>> -                for i in identifiers:
>>> +        elif 'identifiers' in self.options:
>>> +            identifiers = self.options.get('identifiers')
>>> +            if identifiers:
>>> +                for i in identifiers.split():
>>>
>>> (tests needed)
>>
>> Sheesh, I can't find that code so that I can patch it.
>> (in today's linux-next 20250909)
> 
> oops, I was looking in scripts/ and not in Documentation/.
> got it.
> 
>> Anyway, does this take away something that currently works?

The output looks the same with this patch AFAICT.
-- 
~Randy


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH] kernel-doc: add support for handling global variables
  2025-09-10  0:02             ` Randy Dunlap
@ 2025-09-10  4:23               ` Mauro Carvalho Chehab
  2025-09-10  5:59                 ` Randy Dunlap
  0 siblings, 1 reply; 27+ messages in thread
From: Mauro Carvalho Chehab @ 2025-09-10  4:23 UTC (permalink / raw)
  To: Randy Dunlap; +Cc: Linux Doc Mailing List, Jonathan Corbet, linux-kernel

Em Tue, 9 Sep 2025 17:02:00 -0700
Randy Dunlap <rdunlap@infradead.org> escreveu:

> On 9/9/25 4:50 PM, Randy Dunlap wrote:
> > 
> > 
> > On 9/9/25 4:49 PM, Randy Dunlap wrote:  
> >>
> >>
> >> On 9/9/25 4:09 PM, Mauro Carvalho Chehab wrote:  
> >>> Em Tue, 9 Sep 2025 14:06:43 -0700
> >>> Randy Dunlap <rdunlap@infradead.org> escreveu:
> >>>  
> >>>> On 9/9/25 12:58 PM, Mauro Carvalho Chehab wrote:  
> >>>>> Em Tue, 9 Sep 2025 00:27:20 -0700
> >>>>> Randy Dunlap <rdunlap@infradead.org> escreveu:  
> >>>  
> >>>>>> +.. kernel-doc:: init/kdoc-globals-test.c
> >>>>>> +   :identifiers:
> >>>>>>
> >>>>>> The html output says
> >>>>>> "Kernel Globals"
> >>>>>> but nothing else.    
> >>>>>
> >>>>> I usually don't add :identifiers: on kernel-doc entries. If you use
> >>>>> identifiers, you need to explicitly tell what symbols you want.    
> >>>>
> >>>> Well, it worked/works without using having any identifiers listed, and
> >>>> the docs in Documentation/doc-guide/kernel-doc.rst says that they are
> >>>> optional:
> >>>>
> >>>> identifiers: *[ function/type ...]*
> >>>>   Include documentation for each *function* and *type* in *source*.
> >>>>   If no *function* is specified, the documentation for all functions
> >>>>   and types in the *source* will be included.
> >>>>   *type* can be a struct, union, enum, or typedef identifier.  
> >>>
> >>> Hmm.. looking the entire logic:
> >>>
> >>>         elif 'identifiers' in self.options:
> >>>             identifiers = self.options.get('identifiers').split()
> >>>             if identifiers:
> >>>                 for i in identifiers:
> >>>                     i = i.rstrip("\\").strip()
> >>>                     if not i:
> >>>                         continue
> >>>
> >>>                     cmd += ['-function', i]
> >>>                     self.msg_args["symbol"].append(i)
> >>>             else:
> >>>                 cmd += ['-no-doc-sections']
> >>>                 self.msg_args["no_doc_sections"] = True
> >>>
> >>> I suspect that an empty identifier could be raising an exception.  
> 
> and it's being caught and ignored (not printed)?

there is a try/except block to capture exceptions. It is supposed to
print something, though:

        try:
            if kfiles:
                return self.run_kdoc(cmd, kfiles)
            else:
                return self.run_cmd(cmd)

        except Exception as e:  # pylint: disable=W0703
            logger.warning("kernel-doc '%s' processing failed with: %s" %
                           (cmd_str(cmd), pformat(e)))
            return [nodes.error(None, nodes.paragraph(text = "kernel-doc missing"))]

> >>> The right logic should be, instead:
> >>>
> >>> -        elif 'identifiers' in self.options:
> >>> -            identifiers = self.options.get('identifiers').split()
> >>> -            if identifiers:
> >>> -                for i in identifiers:
> >>> +        elif 'identifiers' in self.options:
> >>> +            identifiers = self.options.get('identifiers')
> >>> +            if identifiers:
> >>> +                for i in identifiers.split():
> >>>
> >>> (tests needed)  
> >>
> >> Sheesh, I can't find that code so that I can patch it.
> >> (in today's linux-next 20250909)  
> > 
> > oops, I was looking in scripts/ and not in Documentation/.
> > got it.
> >   
> >> Anyway, does this take away something that currently works?  
> 
> The output looks the same with this patch AFAICT.

run it in verbose mode to see what command line was passed to
the file:

	$ make SPHINXDIRS=your_test_dir V=1 htmldocs

This should be printing how the kernel-doc.py command line would be(*):

	scripts/kernel-doc.py -rst -enable-lineno ./include/linux/peci.h
	./include/linux/peci.h:20 Scanning doc for struct peci_controller_ops
	./include/linux/peci.h:32 Scanning doc for struct peci_controller
	./include/linux/peci.h:58 Scanning doc for struct peci_device
	./include/linux/peci.h:88 Scanning doc for struct peci_request

(*) the kerneldoc.py extension doesn't call kernel-doc.py, but instead
    run directly the Python classes from the library. Yet, to help one
    to debug it, the command line is displayed.

for instance, on a more complex kernel-doc tags case:

	$ make SPHINXDIRS=driver-api/cxl/ V=1 htmldocs 2>&1 |grep scripts/kernel-doc.py
	scripts/kernel-doc.py -rst -enable-lineno -function 'cxl pci' ./drivers/cxl/pci.c
	scripts/kernel-doc.py -rst -enable-lineno -internal ./drivers/cxl/pci.c
	scripts/kernel-doc.py -rst -enable-lineno -function 'cxl mem' ./drivers/cxl/mem.c
	scripts/kernel-doc.py -rst -enable-lineno -internal ./drivers/cxl/cxlmem.h
	scripts/kernel-doc.py -rst -enable-lineno -no-doc-sections ./drivers/cxl/core/memdev.c
	scripts/kernel-doc.py -rst -enable-lineno -function 'cxl port' ./drivers/cxl/port.c
	scripts/kernel-doc.py -rst -enable-lineno -function 'cxl objects' ./drivers/cxl/cxl.h
	scripts/kernel-doc.py -rst -enable-lineno -internal ./drivers/cxl/cxl.h
	scripts/kernel-doc.py -rst -enable-lineno -function add_cxl_resources ./drivers/cxl/acpi.c
	scripts/kernel-doc.py -rst -enable-lineno -function 'cxl core hdm' ./drivers/cxl/core/hdm.c
	scripts/kernel-doc.py -rst -enable-lineno -no-doc-sections ./drivers/cxl/core/hdm.c
	scripts/kernel-doc.py -rst -enable-lineno -no-doc-sections ./drivers/cxl/core/cdat.c
	scripts/kernel-doc.py -rst -enable-lineno -function 'cxl core' ./drivers/cxl/core/port.c
	scripts/kernel-doc.py -rst -enable-lineno -no-doc-sections ./drivers/cxl/core/port.c
	scripts/kernel-doc.py -rst -enable-lineno -function 'cxl core pci' ./drivers/cxl/core/pci.c
	scripts/kernel-doc.py -rst -enable-lineno -no-doc-sections ./drivers/cxl/core/pci.c
	scripts/kernel-doc.py -rst -enable-lineno -function 'cxl pmem' ./drivers/cxl/core/pmem.c
	scripts/kernel-doc.py -rst -enable-lineno -no-doc-sections ./drivers/cxl/core/pmem.c
	scripts/kernel-doc.py -rst -enable-lineno -function 'cxl registers' ./drivers/cxl/core/regs.c
	scripts/kernel-doc.py -rst -enable-lineno -no-doc-sections ./drivers/cxl/core/regs.c
	scripts/kernel-doc.py -rst -enable-lineno -function 'cxl mbox' ./drivers/cxl/core/mbox.c
	scripts/kernel-doc.py -rst -enable-lineno -no-doc-sections ./drivers/cxl/core/mbox.c
	scripts/kernel-doc.py -rst -enable-lineno -function 'cxl features' ./drivers/cxl/core/features.c
	scripts/kernel-doc.py -rst -enable-lineno -function 'cxl core region' ./drivers/cxl/core/region.c
	scripts/kernel-doc.py -rst -enable-lineno -no-doc-sections ./drivers/cxl/core/region.c
	scripts/kernel-doc.py -rst -enable-lineno -function UAPI ./include/uapi/linux/cxl_mem.h
	scripts/kernel-doc.py -rst -enable-lineno -internal ./include/uapi/linux/cxl_mem.h


Thanks,
Mauro

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH] kernel-doc: add support for handling global variables
  2025-09-10  4:23               ` Mauro Carvalho Chehab
@ 2025-09-10  5:59                 ` Randy Dunlap
  2025-09-10  6:13                   ` Randy Dunlap
  0 siblings, 1 reply; 27+ messages in thread
From: Randy Dunlap @ 2025-09-10  5:59 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: Linux Doc Mailing List, Jonathan Corbet, linux-kernel

Hi Mauro,

On 9/9/25 9:23 PM, Mauro Carvalho Chehab wrote:
> Em Tue, 9 Sep 2025 17:02:00 -0700
> Randy Dunlap <rdunlap@infradead.org> escreveu:
> 
>> On 9/9/25 4:50 PM, Randy Dunlap wrote:
>>>
>>>
>>> On 9/9/25 4:49 PM, Randy Dunlap wrote:  
>>>>
>>>>
>>>> On 9/9/25 4:09 PM, Mauro Carvalho Chehab wrote:  
>>>>> Em Tue, 9 Sep 2025 14:06:43 -0700
>>>>> Randy Dunlap <rdunlap@infradead.org> escreveu:
>>>>>  
>>>>>> On 9/9/25 12:58 PM, Mauro Carvalho Chehab wrote:  
>>>>>>> Em Tue, 9 Sep 2025 00:27:20 -0700
>>>>>>> Randy Dunlap <rdunlap@infradead.org> escreveu:  
>>>>>  
>>>>>>>> +.. kernel-doc:: init/kdoc-globals-test.c
>>>>>>>> +   :identifiers:
>>>>>>>>
>>>>>>>> The html output says
>>>>>>>> "Kernel Globals"
>>>>>>>> but nothing else.    
>>>>>>>
>>>>>>> I usually don't add :identifiers: on kernel-doc entries. If you use
>>>>>>> identifiers, you need to explicitly tell what symbols you want.    
>>>>>>
>>>>>> Well, it worked/works without using having any identifiers listed, and
>>>>>> the docs in Documentation/doc-guide/kernel-doc.rst says that they are
>>>>>> optional:
>>>>>>
>>>>>> identifiers: *[ function/type ...]*
>>>>>>   Include documentation for each *function* and *type* in *source*.
>>>>>>   If no *function* is specified, the documentation for all functions
>>>>>>   and types in the *source* will be included.
>>>>>>   *type* can be a struct, union, enum, or typedef identifier.  
>>>>>


>>>>> I suspect that an empty identifier could be raising an exception.  
>>
>> and it's being caught and ignored (not printed)?
> 
> there is a try/except block to capture exceptions. It is supposed to
> print something, though:
> 
>         try:
>             if kfiles:
>                 return self.run_kdoc(cmd, kfiles)
>             else:
>                 return self.run_cmd(cmd)
> 
>         except Exception as e:  # pylint: disable=W0703
>             logger.warning("kernel-doc '%s' processing failed with: %s" %
>                            (cmd_str(cmd), pformat(e)))
>             return [nodes.error(None, nodes.paragraph(text = "kernel-doc missing"))]
> 


>>>> Anyway, does this take away something that currently works?  
>>
>> The output looks the same with this patch AFAICT.
> 
> run it in verbose mode to see what command line was passed to
> the file:
> 
> 	$ make SPHINXDIRS=your_test_dir V=1 htmldocs
> 
> This should be printing how the kernel-doc.py command line would be(*):
> 
> 	scripts/kernel-doc.py -rst -enable-lineno ./include/linux/peci.h
> 	./include/linux/peci.h:20 Scanning doc for struct peci_controller_ops
> 	./include/linux/peci.h:32 Scanning doc for struct peci_controller
> 	./include/linux/peci.h:58 Scanning doc for struct peci_device
> 	./include/linux/peci.h:88 Scanning doc for struct peci_request
> 
> (*) the kerneldoc.py extension doesn't call kernel-doc.py, but instead
>     run directly the Python classes from the library. Yet, to help one
>     to debug it, the command line is displayed.

I see. Thanks.

I get this if I list all of them (on 2 separate identifiers lines):

../scripts/kernel-doc.py -rst -enable-lineno -function ROOT_DEV -function system_state -function saved_command_line -function diskseq ../init/kdoc-globals-test.c
../init/kdoc-globals-test.c:5 Scanning doc for global ROOT_DEV
../init/kdoc-globals-test.c:15 Scanning doc for global system_state
../init/kdoc-globals-test.c:27 Scanning doc for global saved_command_line
../init/kdoc-globals-test.c:33 Scanning doc for global loops_per_jiffy
../init/kdoc-globals-test.c:40 Scanning doc for global preset_lpj
../init/kdoc-globals-test.c:49 Scanning doc for global linux_proc_banner
../init/kdoc-globals-test.c:63 Scanning doc for global linux_banner
../init/kdoc-globals-test.c:72 Scanning doc for global diskseq
../init/kdoc-globals-test.c:80 Scanning doc for global rtnl_mutex
../scripts/kernel-doc.py -rst -enable-lineno -function loops_per_jiffy -function preset_lpj -function linux_proc_banner -function linux_banner ../init/kdoc-globals-test.c

or this is I don't use the identifiers line at all:

../scripts/kernel-doc.py -rst -enable-lineno ../init/kdoc-globals-test.c
../init/kdoc-globals-test.c:5 Scanning doc for global ROOT_DEV
../init/kdoc-globals-test.c:15 Scanning doc for global system_state
../init/kdoc-globals-test.c:27 Scanning doc for global saved_command_line
../init/kdoc-globals-test.c:33 Scanning doc for global loops_per_jiffy
../init/kdoc-globals-test.c:40 Scanning doc for global preset_lpj
../init/kdoc-globals-test.c:49 Scanning doc for global linux_proc_banner
../init/kdoc-globals-test.c:63 Scanning doc for global linux_banner
../init/kdoc-globals-test.c:72 Scanning doc for global diskseq
../init/kdoc-globals-test.c:80 Scanning doc for global rtnl_mutex


And then both of them report these warnings (already discussed):

Documentation/core-api/kernel-api:435: ../init/kdoc-globals-test.c:10: WARNING: Invalid C declaration: Expected end of definition. [error at 32]
  enum system_states system_state __read_mostly;
  --------------------------------^
Documentation/core-api/kernel-api:435: ../init/kdoc-globals-test.c:20: WARNING: Invalid C declaration: Expected end of definition. [error at 25]
  char *saved_command_line __ro_after_init;
  -------------------------^

and the 3 globals with initialization values are skipped/omitted.

So to get "all identifiers," I should just omit the :identifiers:
line completely. kernel-doc.rst could use some clarification on that
point.

Thanks.
-- 
~Randy


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH] kernel-doc: add support for handling global variables
  2025-09-10  5:59                 ` Randy Dunlap
@ 2025-09-10  6:13                   ` Randy Dunlap
  2025-09-10  8:54                     ` Mauro Carvalho Chehab
  0 siblings, 1 reply; 27+ messages in thread
From: Randy Dunlap @ 2025-09-10  6:13 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: Linux Doc Mailing List, Jonathan Corbet, linux-kernel



On 9/9/25 10:59 PM, Randy Dunlap wrote:
> Hi Mauro,
> 
> On 9/9/25 9:23 PM, Mauro Carvalho Chehab wrote:
>> Em Tue, 9 Sep 2025 17:02:00 -0700
>> Randy Dunlap <rdunlap@infradead.org> escreveu:
>>
>>> On 9/9/25 4:50 PM, Randy Dunlap wrote:
>>>>
>>>>
>>>> On 9/9/25 4:49 PM, Randy Dunlap wrote:  
>>>>>
>>>>>
>>>>> On 9/9/25 4:09 PM, Mauro Carvalho Chehab wrote:  
>>>>>> Em Tue, 9 Sep 2025 14:06:43 -0700
>>>>>> Randy Dunlap <rdunlap@infradead.org> escreveu:
>>>>>>  
>>>>>>> On 9/9/25 12:58 PM, Mauro Carvalho Chehab wrote:  
>>>>>>>> Em Tue, 9 Sep 2025 00:27:20 -0700
>>>>>>>> Randy Dunlap <rdunlap@infradead.org> escreveu:  
>>>>>>  
>>>>>>>>> +.. kernel-doc:: init/kdoc-globals-test.c
>>>>>>>>> +   :identifiers:
>>>>>>>>>
>>>>>>>>> The html output says
>>>>>>>>> "Kernel Globals"
>>>>>>>>> but nothing else.    
>>>>>>>>
>>>>>>>> I usually don't add :identifiers: on kernel-doc entries. If you use
>>>>>>>> identifiers, you need to explicitly tell what symbols you want.    
>>>>>>>
>>>>>>> Well, it worked/works without using having any identifiers listed, and
>>>>>>> the docs in Documentation/doc-guide/kernel-doc.rst says that they are
>>>>>>> optional:
>>>>>>>
>>>>>>> identifiers: *[ function/type ...]*
>>>>>>>   Include documentation for each *function* and *type* in *source*.
>>>>>>>   If no *function* is specified, the documentation for all functions
>>>>>>>   and types in the *source* will be included.
>>>>>>>   *type* can be a struct, union, enum, or typedef identifier.  
>>>>>>



>>>>> Anyway, does this take away something that currently works?  
>>>
>>> The output looks the same with this patch AFAICT.
>>
>> run it in verbose mode to see what command line was passed to
>> the file:
>>
>> 	$ make SPHINXDIRS=your_test_dir V=1 htmldocs
>>
>> This should be printing how the kernel-doc.py command line would be(*):
>>
>> 	scripts/kernel-doc.py -rst -enable-lineno ./include/linux/peci.h
>> 	./include/linux/peci.h:20 Scanning doc for struct peci_controller_ops
>> 	./include/linux/peci.h:32 Scanning doc for struct peci_controller
>> 	./include/linux/peci.h:58 Scanning doc for struct peci_device
>> 	./include/linux/peci.h:88 Scanning doc for struct peci_request
>>
>> (*) the kerneldoc.py extension doesn't call kernel-doc.py, but instead
>>     run directly the Python classes from the library. Yet, to help one
>>     to debug it, the command line is displayed.
> 
> I see. Thanks.
> 
> I get this if I list all of them (on 2 separate identifiers lines):
> 
> ../scripts/kernel-doc.py -rst -enable-lineno -function ROOT_DEV -function system_state -function saved_command_line -function diskseq ../init/kdoc-globals-test.c
> ../init/kdoc-globals-test.c:5 Scanning doc for global ROOT_DEV
> ../init/kdoc-globals-test.c:15 Scanning doc for global system_state
> ../init/kdoc-globals-test.c:27 Scanning doc for global saved_command_line
> ../init/kdoc-globals-test.c:33 Scanning doc for global loops_per_jiffy
> ../init/kdoc-globals-test.c:40 Scanning doc for global preset_lpj
> ../init/kdoc-globals-test.c:49 Scanning doc for global linux_proc_banner
> ../init/kdoc-globals-test.c:63 Scanning doc for global linux_banner
> ../init/kdoc-globals-test.c:72 Scanning doc for global diskseq
> ../init/kdoc-globals-test.c:80 Scanning doc for global rtnl_mutex
> ../scripts/kernel-doc.py -rst -enable-lineno -function loops_per_jiffy -function preset_lpj -function linux_proc_banner -function linux_banner ../init/kdoc-globals-test.c
> 
> or this is I don't use the identifiers line at all:
> 
> ../scripts/kernel-doc.py -rst -enable-lineno ../init/kdoc-globals-test.c
> ../init/kdoc-globals-test.c:5 Scanning doc for global ROOT_DEV
> ../init/kdoc-globals-test.c:15 Scanning doc for global system_state
> ../init/kdoc-globals-test.c:27 Scanning doc for global saved_command_line
> ../init/kdoc-globals-test.c:33 Scanning doc for global loops_per_jiffy
> ../init/kdoc-globals-test.c:40 Scanning doc for global preset_lpj
> ../init/kdoc-globals-test.c:49 Scanning doc for global linux_proc_banner
> ../init/kdoc-globals-test.c:63 Scanning doc for global linux_banner
> ../init/kdoc-globals-test.c:72 Scanning doc for global diskseq
> ../init/kdoc-globals-test.c:80 Scanning doc for global rtnl_mutex
> 
> 
> And then both of them report these warnings (already discussed):
> 
> Documentation/core-api/kernel-api:435: ../init/kdoc-globals-test.c:10: WARNING: Invalid C declaration: Expected end of definition. [error at 32]
>   enum system_states system_state __read_mostly;
>   --------------------------------^
> Documentation/core-api/kernel-api:435: ../init/kdoc-globals-test.c:20: WARNING: Invalid C declaration: Expected end of definition. [error at 25]
>   char *saved_command_line __ro_after_init;
>   -------------------------^
> 
> and the 3 globals with initialization values are skipped/omitted.
> 
> So to get "all identifiers," I should just omit the :identifiers:
> line completely. kernel-doc.rst could use some clarification on that
> point.


Oh darn, the html output is different:

when I omit the :identifiers: line, I see:

Kernel Globals
dev_t ROOT_DEV;
system root device

enum system_states system_state __read_mostly;
system state used during boot or suspend/hibernate/resume

char *saved_command_line __ro_after_init;
kernel’s command line, saved from use at any later time in the kernel.

unsigned long preset_lpj;
lpj (loops per jiffy) value set from kernel command line using “lpj=VALUE”

static atomic64_t diskseq;
unique sequence number for block device instances

and when I list all 8 identifiers (on 2 separate lines), I see:

Kernel Globals
dev_t ROOT_DEV;
system root device

static atomic64_t diskseq;
unique sequence number for block device instances

unsigned long preset_lpj;
lpj (loops per jiffy) value set from kernel command line using “lpj=VALUE”

so for some reason, system_state, saved_command_line, and diskseq are
skipped/omitted when I list all 8 identifiers.


-- 
~Randy


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH] kernel-doc: add support for handling global variables
  2025-09-10  6:13                   ` Randy Dunlap
@ 2025-09-10  8:54                     ` Mauro Carvalho Chehab
  2025-11-15  0:50                       ` Randy Dunlap
  0 siblings, 1 reply; 27+ messages in thread
From: Mauro Carvalho Chehab @ 2025-09-10  8:54 UTC (permalink / raw)
  To: Randy Dunlap; +Cc: Linux Doc Mailing List, Jonathan Corbet, linux-kernel

Em Tue, 9 Sep 2025 23:13:24 -0700
Randy Dunlap <rdunlap@infradead.org> escreveu:

> On 9/9/25 10:59 PM, Randy Dunlap wrote:
> > Hi Mauro,
> > 
> > On 9/9/25 9:23 PM, Mauro Carvalho Chehab wrote:  
> >> Em Tue, 9 Sep 2025 17:02:00 -0700
> >> Randy Dunlap <rdunlap@infradead.org> escreveu:
> >>  
> >>> On 9/9/25 4:50 PM, Randy Dunlap wrote:  
> >>>>
> >>>>
> >>>> On 9/9/25 4:49 PM, Randy Dunlap wrote:    
> >>>>>
> >>>>>
> >>>>> On 9/9/25 4:09 PM, Mauro Carvalho Chehab wrote:    
> >>>>>> Em Tue, 9 Sep 2025 14:06:43 -0700
> >>>>>> Randy Dunlap <rdunlap@infradead.org> escreveu:
> >>>>>>    
> >>>>>>> On 9/9/25 12:58 PM, Mauro Carvalho Chehab wrote:    
> >>>>>>>> Em Tue, 9 Sep 2025 00:27:20 -0700
> >>>>>>>> Randy Dunlap <rdunlap@infradead.org> escreveu:    
> >>>>>>    
> >>>>>>>>> +.. kernel-doc:: init/kdoc-globals-test.c
> >>>>>>>>> +   :identifiers:
> >>>>>>>>>
> >>>>>>>>> The html output says
> >>>>>>>>> "Kernel Globals"
> >>>>>>>>> but nothing else.      
> >>>>>>>>
> >>>>>>>> I usually don't add :identifiers: on kernel-doc entries. If you use
> >>>>>>>> identifiers, you need to explicitly tell what symbols you want.      
> >>>>>>>
> >>>>>>> Well, it worked/works without using having any identifiers listed, and
> >>>>>>> the docs in Documentation/doc-guide/kernel-doc.rst says that they are
> >>>>>>> optional:
> >>>>>>>
> >>>>>>> identifiers: *[ function/type ...]*
> >>>>>>>   Include documentation for each *function* and *type* in *source*.
> >>>>>>>   If no *function* is specified, the documentation for all functions
> >>>>>>>   and types in the *source* will be included.
> >>>>>>>   *type* can be a struct, union, enum, or typedef identifier.    
> >>>>>>  
> 
> 
> 
> >>>>> Anyway, does this take away something that currently works?    
> >>>
> >>> The output looks the same with this patch AFAICT.  
> >>
> >> run it in verbose mode to see what command line was passed to
> >> the file:
> >>
> >> 	$ make SPHINXDIRS=your_test_dir V=1 htmldocs
> >>
> >> This should be printing how the kernel-doc.py command line would be(*):
> >>
> >> 	scripts/kernel-doc.py -rst -enable-lineno ./include/linux/peci.h
> >> 	./include/linux/peci.h:20 Scanning doc for struct peci_controller_ops
> >> 	./include/linux/peci.h:32 Scanning doc for struct peci_controller
> >> 	./include/linux/peci.h:58 Scanning doc for struct peci_device
> >> 	./include/linux/peci.h:88 Scanning doc for struct peci_request
> >>
> >> (*) the kerneldoc.py extension doesn't call kernel-doc.py, but instead
> >>     run directly the Python classes from the library. Yet, to help one
> >>     to debug it, the command line is displayed.  
> > 
> > I see. Thanks.
> > 
> > I get this if I list all of them (on 2 separate identifiers lines):
> > 
> > ../scripts/kernel-doc.py -rst -enable-lineno -function ROOT_DEV -function system_state -function saved_command_line -function diskseq ../init/kdoc-globals-test.c
> > ../init/kdoc-globals-test.c:5 Scanning doc for global ROOT_DEV
> > ../init/kdoc-globals-test.c:15 Scanning doc for global system_state
> > ../init/kdoc-globals-test.c:27 Scanning doc for global saved_command_line
> > ../init/kdoc-globals-test.c:33 Scanning doc for global loops_per_jiffy
> > ../init/kdoc-globals-test.c:40 Scanning doc for global preset_lpj
> > ../init/kdoc-globals-test.c:49 Scanning doc for global linux_proc_banner
> > ../init/kdoc-globals-test.c:63 Scanning doc for global linux_banner
> > ../init/kdoc-globals-test.c:72 Scanning doc for global diskseq
> > ../init/kdoc-globals-test.c:80 Scanning doc for global rtnl_mutex
> > ../scripts/kernel-doc.py -rst -enable-lineno -function loops_per_jiffy -function preset_lpj -function linux_proc_banner -function linux_banner ../init/kdoc-globals-test.c
> > 
> > or this is I don't use the identifiers line at all:
> > 
> > ../scripts/kernel-doc.py -rst -enable-lineno ../init/kdoc-globals-test.c
> > ../init/kdoc-globals-test.c:5 Scanning doc for global ROOT_DEV
> > ../init/kdoc-globals-test.c:15 Scanning doc for global system_state
> > ../init/kdoc-globals-test.c:27 Scanning doc for global saved_command_line
> > ../init/kdoc-globals-test.c:33 Scanning doc for global loops_per_jiffy
> > ../init/kdoc-globals-test.c:40 Scanning doc for global preset_lpj
> > ../init/kdoc-globals-test.c:49 Scanning doc for global linux_proc_banner
> > ../init/kdoc-globals-test.c:63 Scanning doc for global linux_banner
> > ../init/kdoc-globals-test.c:72 Scanning doc for global diskseq
> > ../init/kdoc-globals-test.c:80 Scanning doc for global rtnl_mutex
> > 
> > 
> > And then both of them report these warnings (already discussed):
> > 
> > Documentation/core-api/kernel-api:435: ../init/kdoc-globals-test.c:10: WARNING: Invalid C declaration: Expected end of definition. [error at 32]
> >   enum system_states system_state __read_mostly;
> >   --------------------------------^
> > Documentation/core-api/kernel-api:435: ../init/kdoc-globals-test.c:20: WARNING: Invalid C declaration: Expected end of definition. [error at 25]
> >   char *saved_command_line __ro_after_init;
> >   -------------------------^
> > 
> > and the 3 globals with initialization values are skipped/omitted.
> > 
> > So to get "all identifiers," I should just omit the :identifiers:
> > line completely. kernel-doc.rst could use some clarification on that
> > point.  
> 
> 
> Oh darn, the html output is different:
> 
> when I omit the :identifiers: line, I see:
> 
> Kernel Globals
> dev_t ROOT_DEV;
> system root device
> 
> enum system_states system_state __read_mostly;
> system state used during boot or suspend/hibernate/resume
> 
> char *saved_command_line __ro_after_init;
> kernel’s command line, saved from use at any later time in the kernel.
> 
> unsigned long preset_lpj;
> lpj (loops per jiffy) value set from kernel command line using “lpj=VALUE”
> 
> static atomic64_t diskseq;
> unique sequence number for block device instances
> 
> and when I list all 8 identifiers (on 2 separate lines), I see:
> 
> Kernel Globals
> dev_t ROOT_DEV;
> system root device
> 
> static atomic64_t diskseq;
> unique sequence number for block device instances
> 
> unsigned long preset_lpj;
> lpj (loops per jiffy) value set from kernel command line using “lpj=VALUE”
> 
> so for some reason, system_state, saved_command_line, and diskseq are
> skipped/omitted when I list all 8 identifiers.

It is because of the regex we're using:

+        VAR_ATTRIBS = [
+            "extern",
+        ]
+        OPTIONAL_VAR_ATTR = "^(?:" + "|".join(VAR_ATTRIBS) + ")?"
+
+        r= KernRe(OPTIONAL_VAR_ATTR + r"(\w.*)\s+([\w_]+)[\d\]\[]*\s*;(?:#.*)?$")
...
+        declaration_name = r.group(2)
+	 var_type = r.group(0)

the above stores the entire line as var_type, and the last string
as declaration_name. The output logic will use var_type as function
prototype, and declaration_name as the key to check for identifiers.

Here:

	enum system_states system_state __read_mostly;
	char *saved_command_line __ro_after_init;

the regex would pick __read_mostly and __ro_after_init as 
identifiers.

Once we fix the regex to pick the actual var name, both ways should work
equally.

Btw, the best way to test complex regular expressions is, IMHO, to use:

	https://regex101.com/

Don't forget to select first <Python> as the default is pcre2.

there, you can place the regex on the top and several test strings and
see if everything is working.

Anyway, I did some changes at the code for it to better parse your
examples. I'm also storing two additional fields captured at parsing
time:

1. full_proto: the prototype before any transformation;
2. default_val: if not None, contains the initialized value.

Right now, I'm using only default_val ato output, but, with both,
we can play with printing them or not at kdoc_output logic.

Thanks,
Mauro

[PATCH v2] kernel-doc: add support for handling global variables

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-c9c4a3b63c09@infradead.org/T/#m947c25d95cb1d96a394410ab1131dc8e9e5013f1
Suggested-by: Randy Dunlap <rdunlap@infradead.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>

diff --git a/scripts/lib/kdoc/kdoc_output.py b/scripts/lib/kdoc/kdoc_output.py
index 1eca9a918558..469f01a74724 100644
--- a/scripts/lib/kdoc/kdoc_output.py
+++ b/scripts/lib/kdoc/kdoc_output.py
@@ -199,6 +199,10 @@ class OutputFormat:
             self.out_enum(fname, name, args)
             return self.data
 
+        if dtype == "global":
+            self.out_global(fname, name, args)
+            return self.data
+
         if dtype == "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"""
 
+    def out_global(self, fname, name, args):
+        """Outputs a global variable"""
+
     def out_typedef(self, fname, name, args):
         """Outputs a typedef"""
 
@@ -472,6 +479,24 @@ class RestFormat(OutputFormat):
         self.lineprefix = oldprefix
         self.out_section(args)
 
+    def out_global(self, fname, name, args):
+        oldprefix = self.lineprefix
+        ln = args.declaration_start_line
+        prototype = args.other_stuff["var_type"]
+
+        self.data += f"\n\n.. c:var:: {prototype}\n\n"
+
+        self.print_lineno(ln)
+        self.lineprefix = "  "
+        self.output_highlight(args.get('purpose', ''))
+        self.data += "\n"
+
+        if args.other_stuff["default_val"]:
+            self.data += 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):
 
         oldprefix = self.lineprefix
@@ -772,6 +797,26 @@ class ManFormat(OutputFormat):
             self.data += f'.SH "{section}"' + "\n"
             self.output_highlight(text)
 
+    def out_global(self, fname, name, args):
+        out_name = self.arg_name(args, name)
+        prototype = args.other_stuff["var_type"]
+
+        self.data += f'.TH "{self.modulename}" 9 "{out_name}" "{self.man_date}" "API Manual" LINUX' + "\n"
+
+        self.data += ".SH NAME\n"
+        self.data += f"{prototype} \\- {args['purpose']}\n"
+
+        self.data += ".SH SYNOPSIS\n"
+        self.data += f"enum {name}" + " {\n"
+
+        if args.other_stuff["default_val"]:
+            self.data += f'.SH "Initialization"' + "\n"
+            self.output_highlight(f'default: {args.other_stuff["default_val"]}')
+
+        for section, text in args.sections.items():
+            self.data += f'.SH "{section}"' + "\n"
+            self.output_highlight(text)
+
     def out_typedef(self, fname, name, args):
         module = self.modulename
         purpose = args.get('purpose')
diff --git a/scripts/lib/kdoc/kdoc_parser.py b/scripts/lib/kdoc/kdoc_parser.py
index 574972e1f741..93a2fcebec28 100644
--- a/scripts/lib/kdoc/kdoc_parser.py
+++ b/scripts/lib/kdoc/kdoc_parser.py
@@ -64,7 +64,7 @@ type_param = KernRe(r"@(\w*((\.\w+)|(->\w+))*(\.\.\.)?)", cache=False)
 # Tests for the beginning of a kerneldoc block in its various forms.
 #
 doc_block = doc_com + KernRe(r'DOC:\s*(.*)?', cache=False)
-doc_begin_data = KernRe(r"^\s*\*?\s*(struct|union|enum|typedef)\b\s*(\w*)", cache = False)
+doc_begin_data = KernRe(r"^\s*\*?\s*(struct|union|enum|typedef|global)\b\s*(\w*)", cache = False)
 doc_begin_func = KernRe(str(doc_com) +			# initial " * '
                         r"(?:\w+\s*\*\s*)?" + 		# type (not captured)
                         r'(?:define\s+)?' + 		# possible "define" (not captured)
@@ -886,6 +886,57 @@ class KernelDoc:
         self.output_declaration('enum', declaration_name,
                                 purpose=self.entry.declaration_purpose)
 
+    def dump_global(self, ln, proto):
+        """
+        Stores global variables that are part of kAPI.
+        """
+        VAR_ATTRIBS = [
+            "extern",
+        ]
+        OPTIONAL_VAR_ATTR = "^(?:" + "|".join(VAR_ATTRIBS) + ")?"
+
+        sub_prefixes = [
+            (KernRe(r"__read_mostly"), ""),
+            (KernRe(r"__ro_after_init"), ""),
+            (KernRe(r"(?://.*)$"), ""),
+            (KernRe(r"(?:/\*.*\*/)"), ""),
+            (KernRe(r";$"), ""),
+        ]
+
+        #
+        # Store the full prototype before modifying it
+        #
+        full_proto = proto
+
+        #
+        # Drop comments and macros to have a pure C prototype
+        #
+        for search, sub in sub_prefixes:
+            proto = search.sub(sub, proto)
+
+        proto = proto.rstrip()
+
+        #
+        # Variable name is at the end of the declaration
+        #
+
+        r= KernRe(OPTIONAL_VAR_ATTR + r"\w.*\s+([\w_]+)\s*[\d\]\[]*\s*(=.*)?")
+        if not r.match(proto):
+           self.emit_msg(ln,f"{proto}: can't parse variable")
+           return
+
+        var_type = r.group(0)
+        declaration_name = r.group(1)
+        default_val = r.group(2)
+        if default_val:
+            default_val = default_val.lstrip("=").strip()
+
+        self.output_declaration("global", declaration_name,
+                                full_proto=full_proto,
+                                var_type=var_type,
+                                default_val=default_val,
+                                purpose=self.entry.declaration_purpose)
+
     def dump_declaration(self, ln, prototype):
         """
         Stores a data declaration inside self.entries array.
@@ -897,6 +948,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 == "global":
+            self.dump_global(ln, prototype)
         else:
             # This would be a bug
             self.emit_message(ln, f'Unknown declaration type: {self.entry.decl_type}')


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* Re: [PATCH] kernel-doc: add support for handling global variables
  2025-09-07 16:22 [PATCH] kernel-doc: add support for handling global variables Mauro Carvalho Chehab
  2025-09-07 21:34 ` Mauro Carvalho Chehab
  2025-09-09  7:27 ` Randy Dunlap
@ 2025-09-10  9:24 ` Jani Nikula
  2025-09-10 12:13   ` Mauro Carvalho Chehab
  2 siblings, 1 reply; 27+ messages in thread
From: Jani Nikula @ 2025-09-10  9:24 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Linux Doc Mailing List
  Cc: Mauro Carvalho Chehab, Jonathan Corbet, Mauro Carvalho Chehab,
	Randy Dunlap, linux-kernel

On Sun, 07 Sep 2025, Mauro Carvalho Chehab <mchehab+huawei@kernel.org> wrote:
> 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.

Bikeshedding on "global", it sort of implies visibility or linkage, but
here it means "variable".

You could document variables that are static, global to the module, or
exported to the entire kernel. And you could document functions that are
global (for some meaning of global).

I didn't look into kernel-doc, but can't you figure the type out from
the source, instead of having to tell it? And if you can't, why not just
make it "var" (matching Sphinx) or "variable"?


BR,
Jani.

>
> Link: https://lore.kernel.org/linux-doc/491c3022-cef8-4860-a945-c9c4a3b63c09@infradead.org/T/#m947c25d95cb1d96a394410ab1131dc8e9e5013f1
> Suggested-by: Randy Dunlap <rdunlap@infradead.org>
> Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
> ---
>  scripts/lib/kdoc/kdoc_output.py | 31 +++++++++++++++++++++++++++++++
>  scripts/lib/kdoc/kdoc_parser.py | 25 ++++++++++++++++++++++++-
>  2 files changed, 55 insertions(+), 1 deletion(-)
>
> diff --git a/scripts/lib/kdoc/kdoc_output.py b/scripts/lib/kdoc/kdoc_output.py
> index 1eca9a918558..405a5c407522 100644
> --- a/scripts/lib/kdoc/kdoc_output.py
> +++ b/scripts/lib/kdoc/kdoc_output.py
> @@ -199,6 +199,10 @@ class OutputFormat:
>              self.out_enum(fname, name, args)
>              return self.data
>  
> +        if dtype == "global":
> +            self.out_global(fname, name, args)
> +            return self.data
> +
>          if dtype == "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"""
>  
> +    def out_global(self, fname, name, args):
> +        """Outputs a global variable"""
> +
>      def out_typedef(self, fname, name, args):
>          """Outputs a typedef"""
>  
> @@ -472,6 +479,18 @@ class RestFormat(OutputFormat):
>          self.lineprefix = oldprefix
>          self.out_section(args)
>  
> +    def out_global(self, fname, name, args):
> +        oldprefix = self.lineprefix
> +        ln = args.declaration_start_line
> +        prototype = args.other_stuff["var_type"]
> +
> +        self.data += f"
>
> .. c:var:: {prototype}
>
> "
> +
> +        self.print_lineno(ln)
> +        self.lineprefix = "  "
> +        self.output_highlight(args.get('purpose', ''))
> +        self.data += "
> "
> +
>      def out_typedef(self, fname, name, args):
>  
>          oldprefix = self.lineprefix
> @@ -772,6 +791,18 @@ class ManFormat(OutputFormat):
>              self.data += f'.SH "{section}"' + "
> "
>              self.output_highlight(text)
>  
> +    def out_global(self, fname, name, args):
> +        out_name = self.arg_name(args, name)
> +        prototype = args.other_stuff["var_type"]
> +
> +        self.data += f'.TH "{self.modulename}" 9 "{out_name}" "{self.man_date}" "API Manual" LINUX' + "
> "
> +
> +        self.data += ".SH NAME
> "
> +        self.data += f"{prototype} \- {args['purpose']}
> "
> +
> +        self.data += ".SH SYNOPSIS
> "
> +        self.data += f"enum {name}" + " {
> "
> +
>      def out_typedef(self, fname, name, args):
>          module = self.modulename
>          purpose = args.get('purpose')
> diff --git a/scripts/lib/kdoc/kdoc_parser.py b/scripts/lib/kdoc/kdoc_parser.py
> index 574972e1f741..e2a3f4574894 100644
> --- a/scripts/lib/kdoc/kdoc_parser.py
> +++ b/scripts/lib/kdoc/kdoc_parser.py
> @@ -64,7 +64,7 @@ type_param = KernRe(r"@(\w*((\.\w+)|(->\w+))*(\.\.\.)?)", cache=False)
>  # Tests for the beginning of a kerneldoc block in its various forms.
>  #
>  doc_block = doc_com + KernRe(r'DOC:\s*(.*)?', cache=False)
> -doc_begin_data = KernRe(r"^\s*\*?\s*(struct|union|enum|typedef)\b\s*(\w*)", cache = False)
> +doc_begin_data = KernRe(r"^\s*\*?\s*(struct|union|enum|typedef|global)\b\s*(\w*)", cache = False)
>  doc_begin_func = KernRe(str(doc_com) +			# initial " * '
>                          r"(?:\w+\s*\*\s*)?" + 		# type (not captured)
>                          r'(?:define\s+)?' + 		# possible "define" (not captured)
> @@ -886,6 +886,27 @@ class KernelDoc:
>          self.output_declaration('enum', declaration_name,
>                                  purpose=self.entry.declaration_purpose)
>  
> +    def dump_global(self, ln, proto):
> +        """
> +        Stores global variables that are part of kAPI.
> +        """
> +        VAR_ATTRIBS = [
> +            "extern",
> +        ]
> +        OPTIONAL_VAR_ATTR = "^(?:" + "|".join(VAR_ATTRIBS) + ")?"
> +
> +        r= KernRe(OPTIONAL_VAR_ATTR + r"(\w.*)\s+([\w_]+)[\d\]\[]*\s*;(?:#.*)?$")
> +        if not r.match(proto):
> +           self.emit_msg(ln,f"{proto}: can't parse variable")
> +           return
> +
> +        declaration_name = r.group(2)
> +        var_type = r.group(0)
> +
> +        self.output_declaration("global", declaration_name,
> +                                var_type=var_type,
> +                                purpose=self.entry.declaration_purpose)
> +
>      def dump_declaration(self, ln, prototype):
>          """
>          Stores a data declaration inside self.entries array.
> @@ -897,6 +918,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 == "global":
> +            self.dump_global(ln, prototype)
>          else:
>              # This would be a bug
>              self.emit_message(ln, f'Unknown declaration type: {self.entry.decl_type}')

-- 
Jani Nikula, Intel

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH] kernel-doc: add support for handling global variables
  2025-09-10  9:24 ` Jani Nikula
@ 2025-09-10 12:13   ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 27+ messages in thread
From: Mauro Carvalho Chehab @ 2025-09-10 12:13 UTC (permalink / raw)
  To: Jani Nikula
  Cc: Linux Doc Mailing List, Jonathan Corbet, Randy Dunlap,
	linux-kernel

Em Wed, 10 Sep 2025 12:24:47 +0300
Jani Nikula <jani.nikula@linux.intel.com> escreveu:

> On Sun, 07 Sep 2025, Mauro Carvalho Chehab <mchehab+huawei@kernel.org> wrote:
> > 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.  
> 
> Bikeshedding on "global", it sort of implies visibility or linkage, but
> here it means "variable".
> 
> You could document variables that are static, global to the module, or
> exported to the entire kernel. And you could document functions that are
> global (for some meaning of global).
> 
> I didn't look into kernel-doc, but can't you figure the type out from
> the source, instead of having to tell it? And if you can't, why not just
> make it "var" (matching Sphinx) or "variable"?

I don't have a strong opinion here. I ended picking "global" just as a
sort of declaration of intent, in the sense that this is aimed to be
used for kAPI vars.

Now, "var" has certainly an appeal, as it matches Sphinx.

> 
> 
> BR,
> Jani.
> 
> >
> > Link: https://lore.kernel.org/linux-doc/491c3022-cef8-4860-a945-c9c4a3b63c09@infradead.org/T/#m947c25d95cb1d96a394410ab1131dc8e9e5013f1
> > Suggested-by: Randy Dunlap <rdunlap@infradead.org>
> > Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
> > ---
> >  scripts/lib/kdoc/kdoc_output.py | 31 +++++++++++++++++++++++++++++++
> >  scripts/lib/kdoc/kdoc_parser.py | 25 ++++++++++++++++++++++++-
> >  2 files changed, 55 insertions(+), 1 deletion(-)
> >
> > diff --git a/scripts/lib/kdoc/kdoc_output.py b/scripts/lib/kdoc/kdoc_output.py
> > index 1eca9a918558..405a5c407522 100644
> > --- a/scripts/lib/kdoc/kdoc_output.py
> > +++ b/scripts/lib/kdoc/kdoc_output.py
> > @@ -199,6 +199,10 @@ class OutputFormat:
> >              self.out_enum(fname, name, args)
> >              return self.data
> >  
> > +        if dtype == "global":
> > +            self.out_global(fname, name, args)
> > +            return self.data
> > +
> >          if dtype == "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"""
> >  
> > +    def out_global(self, fname, name, args):
> > +        """Outputs a global variable"""
> > +
> >      def out_typedef(self, fname, name, args):
> >          """Outputs a typedef"""
> >  
> > @@ -472,6 +479,18 @@ class RestFormat(OutputFormat):
> >          self.lineprefix = oldprefix
> >          self.out_section(args)
> >  
> > +    def out_global(self, fname, name, args):
> > +        oldprefix = self.lineprefix
> > +        ln = args.declaration_start_line
> > +        prototype = args.other_stuff["var_type"]
> > +
> > +        self.data += f"
> >
> > .. c:var:: {prototype}
> >
> > "
> > +
> > +        self.print_lineno(ln)
> > +        self.lineprefix = "  "
> > +        self.output_highlight(args.get('purpose', ''))
> > +        self.data += "
> > "
> > +
> >      def out_typedef(self, fname, name, args):
> >  
> >          oldprefix = self.lineprefix
> > @@ -772,6 +791,18 @@ class ManFormat(OutputFormat):
> >              self.data += f'.SH "{section}"' + "
> > "
> >              self.output_highlight(text)
> >  
> > +    def out_global(self, fname, name, args):
> > +        out_name = self.arg_name(args, name)
> > +        prototype = args.other_stuff["var_type"]
> > +
> > +        self.data += f'.TH "{self.modulename}" 9 "{out_name}" "{self.man_date}" "API Manual" LINUX' + "
> > "
> > +
> > +        self.data += ".SH NAME
> > "
> > +        self.data += f"{prototype} \- {args['purpose']}
> > "
> > +
> > +        self.data += ".SH SYNOPSIS
> > "
> > +        self.data += f"enum {name}" + " {
> > "
> > +
> >      def out_typedef(self, fname, name, args):
> >          module = self.modulename
> >          purpose = args.get('purpose')
> > diff --git a/scripts/lib/kdoc/kdoc_parser.py b/scripts/lib/kdoc/kdoc_parser.py
> > index 574972e1f741..e2a3f4574894 100644
> > --- a/scripts/lib/kdoc/kdoc_parser.py
> > +++ b/scripts/lib/kdoc/kdoc_parser.py
> > @@ -64,7 +64,7 @@ type_param = KernRe(r"@(\w*((\.\w+)|(->\w+))*(\.\.\.)?)", cache=False)
> >  # Tests for the beginning of a kerneldoc block in its various forms.
> >  #
> >  doc_block = doc_com + KernRe(r'DOC:\s*(.*)?', cache=False)
> > -doc_begin_data = KernRe(r"^\s*\*?\s*(struct|union|enum|typedef)\b\s*(\w*)", cache = False)
> > +doc_begin_data = KernRe(r"^\s*\*?\s*(struct|union|enum|typedef|global)\b\s*(\w*)", cache = False)
> >  doc_begin_func = KernRe(str(doc_com) +			# initial " * '
> >                          r"(?:\w+\s*\*\s*)?" + 		# type (not captured)
> >                          r'(?:define\s+)?' + 		# possible "define" (not captured)
> > @@ -886,6 +886,27 @@ class KernelDoc:
> >          self.output_declaration('enum', declaration_name,
> >                                  purpose=self.entry.declaration_purpose)
> >  
> > +    def dump_global(self, ln, proto):
> > +        """
> > +        Stores global variables that are part of kAPI.
> > +        """
> > +        VAR_ATTRIBS = [
> > +            "extern",
> > +        ]
> > +        OPTIONAL_VAR_ATTR = "^(?:" + "|".join(VAR_ATTRIBS) + ")?"
> > +
> > +        r= KernRe(OPTIONAL_VAR_ATTR + r"(\w.*)\s+([\w_]+)[\d\]\[]*\s*;(?:#.*)?$")
> > +        if not r.match(proto):
> > +           self.emit_msg(ln,f"{proto}: can't parse variable")
> > +           return
> > +
> > +        declaration_name = r.group(2)
> > +        var_type = r.group(0)
> > +
> > +        self.output_declaration("global", declaration_name,
> > +                                var_type=var_type,
> > +                                purpose=self.entry.declaration_purpose)
> > +
> >      def dump_declaration(self, ln, prototype):
> >          """
> >          Stores a data declaration inside self.entries array.
> > @@ -897,6 +918,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 == "global":
> > +            self.dump_global(ln, prototype)
> >          else:
> >              # This would be a bug
> >              self.emit_message(ln, f'Unknown declaration type: {self.entry.decl_type}')  
> 



Thanks,
Mauro

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH] kernel-doc: add support for handling global variables
  2025-09-10  8:54                     ` Mauro Carvalho Chehab
@ 2025-11-15  0:50                       ` Randy Dunlap
  2025-11-16 10:28                         ` Mauro Carvalho Chehab
  0 siblings, 1 reply; 27+ messages in thread
From: Randy Dunlap @ 2025-11-15  0:50 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: Linux Doc Mailing List, Jonathan Corbet, linux-kernel,
	Jani Nikula

Hi,

I would still like to see this done. (more below)

On 9/10/25 1:54 AM, Mauro Carvalho Chehab wrote:


> Anyway, I did some changes at the code for it to better parse your
> examples. I'm also storing two additional fields captured at parsing
> time:
> 
> 1. full_proto: the prototype before any transformation;
> 2. default_val: if not None, contains the initialized value.
> 
> Right now, I'm using only default_val ato output, but, with both,
> we can play with printing them or not at kdoc_output logic.
> 
> Thanks,
> Mauro
> 
> [PATCH v2] kernel-doc: add support for handling global variables
> 
> 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-c9c4a3b63c09@infradead.org/T/#m947c25d95cb1d96a394410ab1131dc8e9e5013f1
> Suggested-by: Randy Dunlap <rdunlap@infradead.org>
> Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
> 
> diff --git a/scripts/lib/kdoc/kdoc_output.py b/scripts/lib/kdoc/kdoc_output.py
> index 1eca9a918558..469f01a74724 100644
> --- a/scripts/lib/kdoc/kdoc_output.py
> +++ b/scripts/lib/kdoc/kdoc_output.py
> @@ -199,6 +199,10 @@ class OutputFormat:
>              self.out_enum(fname, name, args)
>              return self.data
>  
> +        if dtype == "global":
> +            self.out_global(fname, name, args)
> +            return self.data
> +
>          if dtype == "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"""
>  
> +    def out_global(self, fname, name, args):
> +        """Outputs a global variable"""
> +
>      def out_typedef(self, fname, name, args):
>          """Outputs a typedef"""
>  
> @@ -472,6 +479,24 @@ class RestFormat(OutputFormat):
>          self.lineprefix = oldprefix
>          self.out_section(args)
>  
> +    def out_global(self, fname, name, args):
> +        oldprefix = self.lineprefix
> +        ln = args.declaration_start_line
> +        prototype = args.other_stuff["var_type"]
> +
> +        self.data += f"\n\n.. c:var:: {prototype}\n\n"
> +
> +        self.print_lineno(ln)
> +        self.lineprefix = "  "
> +        self.output_highlight(args.get('purpose', ''))
> +        self.data += "\n"
> +
> +        if args.other_stuff["default_val"]:
> +            self.data += 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):
>  
>          oldprefix = self.lineprefix
> @@ -772,6 +797,26 @@ class ManFormat(OutputFormat):
>              self.data += f'.SH "{section}"' + "\n"
>              self.output_highlight(text)
>  
> +    def out_global(self, fname, name, args):
> +        out_name = self.arg_name(args, name)
> +        prototype = args.other_stuff["var_type"]
> +
> +        self.data += f'.TH "{self.modulename}" 9 "{out_name}" "{self.man_date}" "API Manual" LINUX' + "\n"
> +
> +        self.data += ".SH NAME\n"
> +        self.data += f"{prototype} \\- {args['purpose']}\n"
> +
> +        self.data += ".SH SYNOPSIS\n"
> +        self.data += f"enum {name}" + " {\n"
> +
> +        if args.other_stuff["default_val"]:
> +            self.data += f'.SH "Initialization"' + "\n"
> +            self.output_highlight(f'default: {args.other_stuff["default_val"]}')
> +
> +        for section, text in args.sections.items():
> +            self.data += f'.SH "{section}"' + "\n"
> +            self.output_highlight(text)
> +
>      def out_typedef(self, fname, name, args):
>          module = self.modulename
>          purpose = args.get('purpose')
> diff --git a/scripts/lib/kdoc/kdoc_parser.py b/scripts/lib/kdoc/kdoc_parser.py
> index 574972e1f741..93a2fcebec28 100644
> --- a/scripts/lib/kdoc/kdoc_parser.py
> +++ b/scripts/lib/kdoc/kdoc_parser.py
> @@ -64,7 +64,7 @@ type_param = KernRe(r"@(\w*((\.\w+)|(->\w+))*(\.\.\.)?)", cache=False)
>  # Tests for the beginning of a kerneldoc block in its various forms.
>  #
>  doc_block = doc_com + KernRe(r'DOC:\s*(.*)?', cache=False)
> -doc_begin_data = KernRe(r"^\s*\*?\s*(struct|union|enum|typedef)\b\s*(\w*)", cache = False)
> +doc_begin_data = KernRe(r"^\s*\*?\s*(struct|union|enum|typedef|global)\b\s*(\w*)", cache = False)
>  doc_begin_func = KernRe(str(doc_com) +			# initial " * '
>                          r"(?:\w+\s*\*\s*)?" + 		# type (not captured)
>                          r'(?:define\s+)?' + 		# possible "define" (not captured)
> @@ -886,6 +886,57 @@ class KernelDoc:
>          self.output_declaration('enum', declaration_name,
>                                  purpose=self.entry.declaration_purpose)
>  
> +    def dump_global(self, ln, proto):
> +        """
> +        Stores global variables that are part of kAPI.
> +        """
> +        VAR_ATTRIBS = [
> +            "extern",
> +        ]
> +        OPTIONAL_VAR_ATTR = "^(?:" + "|".join(VAR_ATTRIBS) + ")?"
> +
> +        sub_prefixes = [
> +            (KernRe(r"__read_mostly"), ""),
> +            (KernRe(r"__ro_after_init"), ""),
> +            (KernRe(r"(?://.*)$"), ""),
> +            (KernRe(r"(?:/\*.*\*/)"), ""),
> +            (KernRe(r";$"), ""),
> +        ]
> +
> +        #
> +        # Store the full prototype before modifying it
> +        #
> +        full_proto = proto
> +
> +        #
> +        # Drop comments and macros to have a pure C prototype
> +        #
> +        for search, sub in sub_prefixes:
> +            proto = search.sub(sub, proto)
> +
> +        proto = proto.rstrip()
> +
> +        #
> +        # Variable name is at the end of the declaration
> +        #
> +
> +        r= KernRe(OPTIONAL_VAR_ATTR + r"\w.*\s+([\w_]+)\s*[\d\]\[]*\s*(=.*)?")
> +        if not r.match(proto):
> +           self.emit_msg(ln,f"{proto}: can't parse variable")
> +           return
> +
> +        var_type = r.group(0)
> +        declaration_name = r.group(1)
> +        default_val = r.group(2)
> +        if default_val:
> +            default_val = default_val.lstrip("=").strip()
> +
> +        self.output_declaration("global", declaration_name,
> +                                full_proto=full_proto,
> +                                var_type=var_type,
> +                                default_val=default_val,
> +                                purpose=self.entry.declaration_purpose)
> +
>      def dump_declaration(self, ln, prototype):
>          """
>          Stores a data declaration inside self.entries array.
> @@ -897,6 +948,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 == "global":
> +            self.dump_global(ln, prototype)
>          else:
>              # This would be a bug
>              self.emit_message(ln, f'Unknown declaration type: {self.entry.decl_type}')
> 

The v2 patch certainly is better with the new regexes to ignore.
I have a few minor changes that I would like to add (in a trivial patch below).
And there are still a few cases that are not handled correctly.
(see my kdoc-globals-test.patch from 9/9/2025)

Also, changing to "var" instead of "global" is good IMO.
---
 scripts/lib/kdoc/kdoc_output.py |    2 +-
 scripts/lib/kdoc/kdoc_parser.py |    1 +
 2 files changed, 2 insertions(+), 1 deletion(-)

--- linux-next-20251114.orig/scripts/lib/kdoc/kdoc_output.py
+++ linux-next-20251114/scripts/lib/kdoc/kdoc_output.py
@@ -808,7 +808,7 @@ class ManFormat(OutputFormat):
         self.data += f"{prototype} \\- {args['purpose']}\n"
 
         self.data += ".SH SYNOPSIS\n"
-        self.data += f"enum {name}" + " {\n"
+        self.data += f"{prototype}" + ";\n"
 
         if args.other_stuff["default_val"]:
             self.data += f'.SH "Initialization"' + "\n"
--- linux-next-20251114.orig/scripts/lib/kdoc/kdoc_parser.py
+++ linux-next-20251114/scripts/lib/kdoc/kdoc_parser.py
@@ -939,6 +939,7 @@ class KernelDoc:
             (KernRe(r"(?://.*)$"), ""),
             (KernRe(r"(?:/\*.*\*/)"), ""),
             (KernRe(r";$"), ""),
+            (KernRe(r"=.*"), ""),
         ]
 
         #
-- 
~Randy


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH] kernel-doc: add support for handling global variables
  2025-11-15  0:50                       ` Randy Dunlap
@ 2025-11-16 10:28                         ` Mauro Carvalho Chehab
  2025-11-16 19:46                           ` Randy Dunlap
  0 siblings, 1 reply; 27+ messages in thread
From: Mauro Carvalho Chehab @ 2025-11-16 10:28 UTC (permalink / raw)
  To: Randy Dunlap
  Cc: Linux Doc Mailing List, Jonathan Corbet, linux-kernel,
	Jani Nikula

Em Fri, 14 Nov 2025 16:50:57 -0800
Randy Dunlap <rdunlap@infradead.org> escreveu:

> The v2 patch certainly is better with the new regexes to ignore.
> I have a few minor changes that I would like to add (in a trivial patch below).

See my comments below.

> And there are still a few cases that are not handled correctly.
> (see my kdoc-globals-test.patch from 9/9/2025)

Where is it?


> Also, changing to "var" instead of "global" is good IMO.

I'll send a v3 with the rename in a few.

> ---
>  scripts/lib/kdoc/kdoc_output.py |    2 +-
>  scripts/lib/kdoc/kdoc_parser.py |    1 +
>  2 files changed, 2 insertions(+), 1 deletion(-)
> 
> --- linux-next-20251114.orig/scripts/lib/kdoc/kdoc_output.py
> +++ linux-next-20251114/scripts/lib/kdoc/kdoc_output.py
> @@ -808,7 +808,7 @@ class ManFormat(OutputFormat):
>          self.data += f"{prototype} \\- {args['purpose']}\n"
>  
>          self.data += ".SH SYNOPSIS\n"
> -        self.data += f"enum {name}" + " {\n"
> +        self.data += f"{prototype}" + ";\n"

This one should probably be a separate patch from you after the
patch, as it is related to enum, and not var tag.

>  
>          if args.other_stuff["default_val"]:
>              self.data += f'.SH "Initialization"' + "\n"
> --- linux-next-20251114.orig/scripts/lib/kdoc/kdoc_parser.py
> +++ linux-next-20251114/scripts/lib/kdoc/kdoc_parser.py
> @@ -939,6 +939,7 @@ class KernelDoc:
>              (KernRe(r"(?://.*)$"), ""),
>              (KernRe(r"(?:/\*.*\*/)"), ""),
>              (KernRe(r";$"), ""),
> +            (KernRe(r"=.*"), ""),

Makes sense. I'll add it to the v3.

My suggestion is that, once I sent v3, you pick it at the beginning
on your series and then add your changes on separate patches
after that, including the one using "{prototype}" for enum.


Thanks,
Mauro

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH] kernel-doc: add support for handling global variables
  2025-11-16 10:28                         ` Mauro Carvalho Chehab
@ 2025-11-16 19:46                           ` Randy Dunlap
  0 siblings, 0 replies; 27+ messages in thread
From: Randy Dunlap @ 2025-11-16 19:46 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: Linux Doc Mailing List, Jonathan Corbet, linux-kernel,
	Jani Nikula



On 11/16/25 2:28 AM, Mauro Carvalho Chehab wrote:
> Em Fri, 14 Nov 2025 16:50:57 -0800
> Randy Dunlap <rdunlap@infradead.org> escreveu:
> 
>> The v2 patch certainly is better with the new regexes to ignore.
>> I have a few minor changes that I would like to add (in a trivial patch below).
> 
> See my comments below.
> 
>> And there are still a few cases that are not handled correctly.
>> (see my kdoc-globals-test.patch from 9/9/2025)
> 
> Where is it?
> 

in this message:
https://lore.kernel.org/linux-doc/d85e3f24-dbcd-4f28-b31f-a77661fc66fb@infradead.org/


-- 
~Randy


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH] kernel-doc: add support for handling global variables
  2025-09-09  7:27 ` Randy Dunlap
  2025-09-09 15:57   ` Randy Dunlap
  2025-09-09 19:58   ` Mauro Carvalho Chehab
@ 2025-11-17  9:45   ` Mauro Carvalho Chehab
  2025-11-17 17:45     ` Randy Dunlap
  2 siblings, 1 reply; 27+ messages in thread
From: Mauro Carvalho Chehab @ 2025-11-17  9:45 UTC (permalink / raw)
  To: Randy Dunlap; +Cc: Linux Doc Mailing List, Jonathan Corbet, linux-kernel

Em Tue, 9 Sep 2025 00:27:20 -0700
Randy Dunlap <rdunlap@infradead.org> escreveu:

> Hi Mauro,
> 
> I have a few patch nits below, then some testing info.
> 
> 
> On 9/7/25 9:22 AM, Mauro Carvalho Chehab wrote:
> > 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-c9c4a3b63c09@infradead.org/T/#m947c25d95cb1d96a394410ab1131dc8e9e5013f1
> > Suggested-by: Randy Dunlap <rdunlap@infradead.org>
> > Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
> > ---
> >  scripts/lib/kdoc/kdoc_output.py | 31 +++++++++++++++++++++++++++++++
> >  scripts/lib/kdoc/kdoc_parser.py | 25 ++++++++++++++++++++++++-
> >  2 files changed, 55 insertions(+), 1 deletion(-)
> > 
> > diff --git a/scripts/lib/kdoc/kdoc_output.py b/scripts/lib/kdoc/kdoc_output.py
> > index 1eca9a918558..405a5c407522 100644
> > --- a/scripts/lib/kdoc/kdoc_output.py
> > +++ b/scripts/lib/kdoc/kdoc_output.py
> > @@ -199,6 +199,10 @@ class OutputFormat:
> >              self.out_enum(fname, name, args)
> >              return self.data
> >  
> > +        if dtype == "global":
> > +            self.out_global(fname, name, args)
> > +            return self.data
> > +
> >          if dtype == "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"""
> >  
> > +    def out_global(self, fname, name, args):
> > +        """Outputs a global variable"""
> > +
> >      def out_typedef(self, fname, name, args):
> >          """Outputs a typedef"""
> >  
> > @@ -472,6 +479,18 @@ class RestFormat(OutputFormat):
> >          self.lineprefix = oldprefix
> >          self.out_section(args)
> >  
> > +    def out_global(self, fname, name, args):
> > +        oldprefix = self.lineprefix
> > +        ln = args.declaration_start_line
> > +        prototype = args.other_stuff["var_type"]
> > +
> > +        self.data += f"
> > 
> > .. c:var:: {prototype}
> > 
> > "  
> 
> Are the 5 lines above supposed to be on one line?  Did git send-email split that up for you?
> There are a few others like this below.
> patch(1) complains when I try to apply the patch from this email.

This was a problem with my the mailbomb script I wrote in Python.
I was unable to make it transparent to encoding. Also, it replaced
\n with new lines.

I ended rolling back to my old Perl script.

> 
> > +
> > +        self.print_lineno(ln)
> > +        self.lineprefix = "  "
> > +        self.output_highlight(args.get('purpose', ''))
> > +        self.data += "
> > "
> > +
> >      def out_typedef(self, fname, name, args):
> >  
> >          oldprefix = self.lineprefix
> > @@ -772,6 +791,18 @@ class ManFormat(OutputFormat):
> >              self.data += f'.SH "{section}"' + "
> > "
> >              self.output_highlight(text)
> >  
> > +    def out_global(self, fname, name, args):
> > +        out_name = self.arg_name(args, name)
> > +        prototype = args.other_stuff["var_type"]
> > +
> > +        self.data += f'.TH "{self.modulename}" 9 "{out_name}" "{self.man_date}" "API Manual" LINUX' + "
> > "
> > +
> > +        self.data += ".SH NAME
> > "
> > +        self.data += f"{prototype} \- {args['purpose']}  
> 
> Python complains about the "\-" above. Other places nearby use "\\-"

Again, this was due to the mailbomb script not being transparent.

> so I changed it to that instead. Hope that's OK.

Yeah, \\ is the right way.

> 
> > "
> > +
> > +        self.data += ".SH SYNOPSIS
> > "
> > +        self.data += f"enum {name}" + " {
> > "
> > +
> >      def out_typedef(self, fname, name, args):
> >          module = self.modulename
> >          purpose = args.get('purpose')
> > diff --git a/scripts/lib/kdoc/kdoc_parser.py b/scripts/lib/kdoc/kdoc_parser.py
> > index 574972e1f741..e2a3f4574894 100644
> > --- a/scripts/lib/kdoc/kdoc_parser.py
> > +++ b/scripts/lib/kdoc/kdoc_parser.py
> > @@ -64,7 +64,7 @@ type_param = KernRe(r"@(\w*((\.\w+)|(->\w+))*(\.\.\.)?)", cache=False)
> >  # Tests for the beginning of a kerneldoc block in its various forms.
> >  #
> >  doc_block = doc_com + KernRe(r'DOC:\s*(.*)?', cache=False)
> > -doc_begin_data = KernRe(r"^\s*\*?\s*(struct|union|enum|typedef)\b\s*(\w*)", cache = False)
> > +doc_begin_data = KernRe(r"^\s*\*?\s*(struct|union|enum|typedef|global)\b\s*(\w*)", cache = False)
> >  doc_begin_func = KernRe(str(doc_com) +			# initial " * '
> >                          r"(?:\w+\s*\*\s*)?" + 		# type (not captured)
> >                          r'(?:define\s+)?' + 		# possible "define" (not captured)
> > @@ -886,6 +886,27 @@ class KernelDoc:
> >          self.output_declaration('enum', declaration_name,
> >                                  purpose=self.entry.declaration_purpose)
> >  
> > +    def dump_global(self, ln, proto):
> > +        """
> > +        Stores global variables that are part of kAPI.
> > +        """
> > +        VAR_ATTRIBS = [
> > +            "extern",
> > +        ]
> > +        OPTIONAL_VAR_ATTR = "^(?:" + "|".join(VAR_ATTRIBS) + ")?"
> > +
> > +        r= KernRe(OPTIONAL_VAR_ATTR + r"(\w.*)\s+([\w_]+)[\d\]\[]*\s*;(?:#.*)?$")
> > +        if not r.match(proto):
> > +           self.emit_msg(ln,f"{proto}: can't parse variable")
> > +           return
> > +
> > +        declaration_name = r.group(2)
> > +        var_type = r.group(0)
> > +
> > +        self.output_declaration("global", declaration_name,
> > +                                var_type=var_type,
> > +                                purpose=self.entry.declaration_purpose)
> > +
> >      def dump_declaration(self, ln, prototype):
> >          """
> >          Stores a data declaration inside self.entries array.
> > @@ -897,6 +918,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 == "global":
> > +            self.dump_global(ln, prototype)
> >          else:
> >              # This would be a bug
> >              self.emit_message(ln, f'Unknown declaration type: {self.entry.decl_type}')  
> So, I grabbed some global data from 6-8 places in the kernel and put them intoinit/kdoc-globals-test.c. Then I modified Documentation/core-api/kernel-api.rst
> like this at the end of that file:
> 
> +
> +Kernel Globals
> +==========================
> +
> +.. kernel-doc:: init/kdoc-globals-test.c
> +   :identifiers:
> 
> The html output says
> "Kernel Globals"
> but nothing else.

With the version I sent yesterday, after replacing:

	global -> var

the symbols are there.

Thanks,
Mauro

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH] kernel-doc: add support for handling global variables
  2025-11-17  9:45   ` Mauro Carvalho Chehab
@ 2025-11-17 17:45     ` Randy Dunlap
  0 siblings, 0 replies; 27+ messages in thread
From: Randy Dunlap @ 2025-11-17 17:45 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: Linux Doc Mailing List, Jonathan Corbet, linux-kernel



On 11/17/25 1:45 AM, Mauro Carvalho Chehab wrote:

>> So, I grabbed some global data from 6-8 places in the kernel and put them intoinit/kdoc-globals-test.c. Then I modified Documentation/core-api/kernel-api.rst
>> like this at the end of that file:
>>
>> +
>> +Kernel Globals
>> +==========================
>> +
>> +.. kernel-doc:: init/kdoc-globals-test.c
>> +   :identifiers:
>>
>> The html output says
>> "Kernel Globals"
>> but nothing else.
> 
> With the version I sent yesterday, after replacing:
> 
> 	global -> var
> 
> the symbols are there.

Great, thanks. I'll look at it later today.

-- 
~Randy


^ permalink raw reply	[flat|nested] 27+ messages in thread

end of thread, other threads:[~2025-11-17 17:45 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-09-07 16:22 [PATCH] kernel-doc: add support for handling global variables Mauro Carvalho Chehab
2025-09-07 21:34 ` Mauro Carvalho Chehab
2025-09-09  6:22   ` Randy Dunlap
2025-09-09 20:12     ` Mauro Carvalho Chehab
2025-09-09  7:27 ` Randy Dunlap
2025-09-09 15:57   ` Randy Dunlap
2025-09-09 16:18     ` Mauro Carvalho Chehab
2025-09-09 18:20       ` Randy Dunlap
2025-09-09 20:37         ` Mauro Carvalho Chehab
2025-09-09 19:58   ` Mauro Carvalho Chehab
2025-09-09 20:09     ` Mauro Carvalho Chehab
2025-09-09 21:06     ` Randy Dunlap
2025-09-09 23:09       ` Mauro Carvalho Chehab
2025-09-09 23:49         ` Randy Dunlap
2025-09-09 23:50           ` Randy Dunlap
2025-09-10  0:02             ` Randy Dunlap
2025-09-10  4:23               ` Mauro Carvalho Chehab
2025-09-10  5:59                 ` Randy Dunlap
2025-09-10  6:13                   ` Randy Dunlap
2025-09-10  8:54                     ` Mauro Carvalho Chehab
2025-11-15  0:50                       ` Randy Dunlap
2025-11-16 10:28                         ` Mauro Carvalho Chehab
2025-11-16 19:46                           ` Randy Dunlap
2025-11-17  9:45   ` Mauro Carvalho Chehab
2025-11-17 17:45     ` Randy Dunlap
2025-09-10  9:24 ` Jani Nikula
2025-09-10 12:13   ` Mauro Carvalho Chehab

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).