linux-doc.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3 0/8] Collect documentation-related tools under /tools/docs
@ 2025-10-24 20:08 Jonathan Corbet
  2025-10-24 20:08 ` [PATCH v3 1/8] docs: Move the "features" tools to tools/docs Jonathan Corbet
                   ` (10 more replies)
  0 siblings, 11 replies; 21+ messages in thread
From: Jonathan Corbet @ 2025-10-24 20:08 UTC (permalink / raw)
  To: linux-doc
  Cc: linux-kernel, Mauro Carvalho Chehab, Akira Yokosawa, Randy Dunlap,
	Jani Nikula, Jonathan Corbet

Our documentation-related tools are spread out over various directories;
several are buried in the scripts/ dumping ground.  That makes them harder
to discover and harder to maintain.

Recent work has started accumulating our documentation-related tools in
/tools/docs.  This series completes that task, moving the rest of our
various utilities there, hopefully fixing up all of the relevant references
in the process.

At the end, rather than move the old, Perl kernel-doc, I simply removed it.

The big elephant lurking in this small room is the home for Python modules;
I left them under scripts/lib, but that is an even less appropriate place
than it was before.  I would propose either tools/python or lib/python;
thoughts on that matter welcome.

Changes in v3:
  - Now with more caffeine! Properly based on docs-next.

Changes in v2:
  - Rebase on top of all of Mauro's changes (the most painful rebase I've
    ever done, I think).
  - Land everything in /tools/docs/ rather than /tools/doc/

v2: https://lore.kernel.org/lkml/20251023161027.697135-1-corbet@lwn.net/
v1: https://lore.kernel.org/lkml/20250813213218.198582-1-corbet@lwn.net/


Jonathan Corbet (8):
  docs: Move the "features" tools to tools/docs
  docs: move checktransupdate.py to tools/docs
  docs: move scripts/documentation-file-ref-check to tools/docs
  docs: move get_abi.py to tools/docs
  docs: move test_doc_build.py to tools/docs
  docs: move kernel-doc to tools/docs
  docs: move find-unused-docs.sh to tools/docs
  docs: remove kernel-doc.pl

 Documentation/Kconfig                         |    2 +-
 Documentation/Makefile                        |    6 +-
 Documentation/conf.py                         |    2 +-
 Documentation/doc-guide/checktransupdate.rst  |    6 +-
 Documentation/doc-guide/contributing.rst      |    2 +-
 Documentation/doc-guide/kernel-doc.rst        |    6 +-
 Documentation/doc-guide/sphinx.rst            |    2 +-
 Documentation/kbuild/kbuild.rst               |    2 +-
 Documentation/process/coding-style.rst        |    2 +-
 Documentation/sphinx/kernel_abi.py            |    2 +-
 Documentation/sphinx/kernel_feat.py           |    4 +-
 .../it_IT/doc-guide/kernel-doc.rst            |    8 +-
 .../sp_SP/process/coding-style.rst            |    2 +-
 .../zh_CN/doc-guide/checktransupdate.rst      |    6 +-
 .../zh_CN/doc-guide/contributing.rst          |    2 +-
 .../zh_CN/doc-guide/kernel-doc.rst            |   10 +-
 Documentation/translations/zh_CN/how-to.rst   |    2 +-
 .../translations/zh_CN/kbuild/kbuild.rst      |    2 +-
 .../zh_CN/process/coding-style.rst            |    2 +-
 .../zh_TW/process/coding-style.rst            |    2 +-
 MAINTAINERS                                   |    5 -
 Makefile                                      |    2 +-
 drivers/gpu/drm/i915/Makefile                 |    2 +-
 scripts/kernel-doc                            |    1 -
 scripts/kernel-doc.pl                         | 2439 -----------------
 {scripts => tools/docs}/checktransupdate.py   |    8 +-
 .../docs}/documentation-file-ref-check        |    2 +-
 .../docs}/features-refresh.sh                 |    0
 {scripts => tools/docs}/find-unused-docs.sh   |    8 +-
 {scripts => tools/docs}/get_abi.py            |    0
 {scripts => tools/docs}/get_feat.pl           |    2 +-
 .../kernel-doc.py => tools/docs/kernel-doc    |    0
 .../features => tools/docs}/list-arch.sh      |    2 +-
 tools/docs/sphinx-pre-install                 |    2 +-
 {scripts => tools/docs}/test_doc_build.py     |    0
 35 files changed, 50 insertions(+), 2495 deletions(-)
 delete mode 120000 scripts/kernel-doc
 delete mode 100755 scripts/kernel-doc.pl
 rename {scripts => tools/docs}/checktransupdate.py (97%)
 rename {scripts => tools/docs}/documentation-file-ref-check (99%)
 rename {Documentation/features/scripts => tools/docs}/features-refresh.sh (100%)
 rename {scripts => tools/docs}/find-unused-docs.sh (79%)
 rename {scripts => tools/docs}/get_abi.py (100%)
 rename {scripts => tools/docs}/get_feat.pl (99%)
 rename scripts/kernel-doc.py => tools/docs/kernel-doc (100%)
 rename {Documentation/features => tools/docs}/list-arch.sh (83%)
 rename {scripts => tools/docs}/test_doc_build.py (100%)

-- 
2.51.0


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

* [PATCH v3 1/8] docs: Move the "features" tools to tools/docs
  2025-10-24 20:08 [PATCH v3 0/8] Collect documentation-related tools under /tools/docs Jonathan Corbet
@ 2025-10-24 20:08 ` Jonathan Corbet
  2025-10-24 20:08 ` [PATCH v3 2/8] docs: move checktransupdate.py " Jonathan Corbet
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 21+ messages in thread
From: Jonathan Corbet @ 2025-10-24 20:08 UTC (permalink / raw)
  To: linux-doc
  Cc: linux-kernel, Mauro Carvalho Chehab, Akira Yokosawa, Randy Dunlap,
	Jani Nikula, Jonathan Corbet, Jani Nikula

The scripts for managing the features docs are found in three different
directories; unite them all under tools/docs and update references as
needed.

Acked-by: Jani Nikula <jani.nikula@intel.com>
Signed-off-by: Jonathan Corbet <corbet@lwn.net>
---
 Documentation/sphinx/kernel_feat.py                           | 4 ++--
 .../features/scripts => tools/docs}/features-refresh.sh       | 0
 {scripts => tools/docs}/get_feat.pl                           | 2 +-
 {Documentation/features => tools/docs}/list-arch.sh           | 2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)
 rename {Documentation/features/scripts => tools/docs}/features-refresh.sh (100%)
 rename {scripts => tools/docs}/get_feat.pl (99%)
 rename {Documentation/features => tools/docs}/list-arch.sh (83%)

diff --git a/Documentation/sphinx/kernel_feat.py b/Documentation/sphinx/kernel_feat.py
index aaac76892ceb..81c67ef23d8d 100644
--- a/Documentation/sphinx/kernel_feat.py
+++ b/Documentation/sphinx/kernel_feat.py
@@ -13,7 +13,7 @@
     :license:    GPL Version 2, June 1991 see Linux/COPYING for details.
 
     The ``kernel-feat`` (:py:class:`KernelFeat`) directive calls the
-    scripts/get_feat.pl script to parse the Kernel ABI files.
+    tools/docs/get_feat.pl script to parse the Kernel ABI files.
 
     Overview of directive's argument and options.
 
@@ -85,7 +85,7 @@ class KernelFeat(Directive):
         srctree = os.path.abspath(os.environ["srctree"])
 
         args = [
-            os.path.join(srctree, 'scripts/get_feat.pl'),
+            os.path.join(srctree, 'tools/docs/get_feat.pl'),
             'rest',
             '--enable-fname',
             '--dir',
diff --git a/Documentation/features/scripts/features-refresh.sh b/tools/docs/features-refresh.sh
similarity index 100%
rename from Documentation/features/scripts/features-refresh.sh
rename to tools/docs/features-refresh.sh
diff --git a/scripts/get_feat.pl b/tools/docs/get_feat.pl
similarity index 99%
rename from scripts/get_feat.pl
rename to tools/docs/get_feat.pl
index 40fb28c8424e..d75e7c85dc85 100755
--- a/scripts/get_feat.pl
+++ b/tools/docs/get_feat.pl
@@ -18,7 +18,7 @@ my $enable_fname;
 my $basename = abs_path($0);
 $basename =~ s,/[^/]+$,/,;
 
-my $prefix=$basename . "../Documentation/features";
+my $prefix=$basename . "../../Documentation/features";
 
 # Used only at for full features output. The script will auto-adjust
 # such values for the minimal possible values
diff --git a/Documentation/features/list-arch.sh b/tools/docs/list-arch.sh
similarity index 83%
rename from Documentation/features/list-arch.sh
rename to tools/docs/list-arch.sh
index ac8ff7f6f859..96fe83b7058b 100755
--- a/Documentation/features/list-arch.sh
+++ b/tools/docs/list-arch.sh
@@ -8,4 +8,4 @@
 
 ARCH=${1:-$(uname -m | sed 's/x86_64/x86/' | sed 's/i386/x86/' | sed 's/s390x/s390/')}
 
-$(dirname $0)/../../scripts/get_feat.pl list --arch $ARCH
+$(dirname $0)/get_feat.pl list --arch $ARCH
-- 
2.51.0


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

* [PATCH v3 2/8] docs: move checktransupdate.py to tools/docs
  2025-10-24 20:08 [PATCH v3 0/8] Collect documentation-related tools under /tools/docs Jonathan Corbet
  2025-10-24 20:08 ` [PATCH v3 1/8] docs: Move the "features" tools to tools/docs Jonathan Corbet
@ 2025-10-24 20:08 ` Jonathan Corbet
  2025-10-24 20:08 ` [PATCH v3 3/8] docs: move scripts/documentation-file-ref-check " Jonathan Corbet
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 21+ messages in thread
From: Jonathan Corbet @ 2025-10-24 20:08 UTC (permalink / raw)
  To: linux-doc
  Cc: linux-kernel, Mauro Carvalho Chehab, Akira Yokosawa, Randy Dunlap,
	Jani Nikula, Jonathan Corbet, Alex Shi, Yanteng Si, Dongliang Mu,
	Jani Nikula

The checktranslate.py tool currently languishes in scripts/; move it to
tools/docs and update references accordingly.

Cc: Alex Shi <alexs@kernel.org>
Cc: Yanteng Si <si.yanteng@linux.dev>
Cc: Dongliang Mu <dzm91@hust.edu.cn>
Acked-by: Jani Nikula <jani.nikula@intel.com>
Signed-off-by: Jonathan Corbet <corbet@lwn.net>
---
 Documentation/doc-guide/checktransupdate.rst              | 6 +++---
 .../translations/zh_CN/doc-guide/checktransupdate.rst     | 6 +++---
 Documentation/translations/zh_CN/how-to.rst               | 2 +-
 MAINTAINERS                                               | 1 -
 {scripts => tools/docs}/checktransupdate.py               | 8 ++++----
 5 files changed, 11 insertions(+), 12 deletions(-)
 rename {scripts => tools/docs}/checktransupdate.py (97%)

diff --git a/Documentation/doc-guide/checktransupdate.rst b/Documentation/doc-guide/checktransupdate.rst
index dfaf9d373747..7b25375cc6d9 100644
--- a/Documentation/doc-guide/checktransupdate.rst
+++ b/Documentation/doc-guide/checktransupdate.rst
@@ -27,15 +27,15 @@ Usage
 
 ::
 
-   ./scripts/checktransupdate.py --help
+   tools/docs/checktransupdate.py --help
 
 Please refer to the output of argument parser for usage details.
 
 Samples
 
--  ``./scripts/checktransupdate.py -l zh_CN``
+-  ``tools/docs/checktransupdate.py -l zh_CN``
    This will print all the files that need to be updated in the zh_CN locale.
--  ``./scripts/checktransupdate.py Documentation/translations/zh_CN/dev-tools/testing-overview.rst``
+-  ``tools/docs/checktransupdate.py Documentation/translations/zh_CN/dev-tools/testing-overview.rst``
    This will only print the status of the specified file.
 
 Then the output is something like:
diff --git a/Documentation/translations/zh_CN/doc-guide/checktransupdate.rst b/Documentation/translations/zh_CN/doc-guide/checktransupdate.rst
index d20b4ce66b9f..dbfd65398077 100644
--- a/Documentation/translations/zh_CN/doc-guide/checktransupdate.rst
+++ b/Documentation/translations/zh_CN/doc-guide/checktransupdate.rst
@@ -28,15 +28,15 @@
 
 ::
 
-    ./scripts/checktransupdate.py --help
+    tools/docs/checktransupdate.py --help
 
 具体用法请参考参数解析器的输出
 
 示例
 
--  ``./scripts/checktransupdate.py -l zh_CN``
+-  ``tools/docs/checktransupdate.py -l zh_CN``
    这将打印 zh_CN 语言中需要更新的所有文件。
--  ``./scripts/checktransupdate.py Documentation/translations/zh_CN/dev-tools/testing-overview.rst``
+-  ``tools/docs/checktransupdate.py Documentation/translations/zh_CN/dev-tools/testing-overview.rst``
    这将只打印指定文件的状态。
 
 然后输出类似如下的内容:
diff --git a/Documentation/translations/zh_CN/how-to.rst b/Documentation/translations/zh_CN/how-to.rst
index 714664fec308..7ae5d8765888 100644
--- a/Documentation/translations/zh_CN/how-to.rst
+++ b/Documentation/translations/zh_CN/how-to.rst
@@ -437,7 +437,7 @@ git email 默认会抄送给您一份,所以您可以切换为审阅者的角
 对于首次参与 Linux 内核中文文档翻译的新手,建议您在 linux 目录中运行以下命令:
 ::
 
-	./script/checktransupdate.py -l zh_CN``
+	tools/docs/checktransupdate.py -l zh_CN``
 
 该命令会列出需要翻译或更新的英文文档,结果同时保存在 checktransupdate.log 中。
 
diff --git a/MAINTAINERS b/MAINTAINERS
index 5aa6d769b254..cd187b9f1dc2 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7411,7 +7411,6 @@ S:	Maintained
 P:	Documentation/doc-guide/maintainer-profile.rst
 T:	git git://git.lwn.net/linux.git docs-next
 F:	Documentation/
-F:	scripts/checktransupdate.py
 F:	scripts/documentation-file-ref-check
 F:	scripts/get_abi.py
 F:	scripts/kernel-doc*
diff --git a/scripts/checktransupdate.py b/tools/docs/checktransupdate.py
similarity index 97%
rename from scripts/checktransupdate.py
rename to tools/docs/checktransupdate.py
index e39529e46c3d..e894652369a5 100755
--- a/scripts/checktransupdate.py
+++ b/tools/docs/checktransupdate.py
@@ -9,9 +9,9 @@ commit to find the latest english commit from the translation commit
 differences occur, report the file and commits that need to be updated.
 
 The usage is as follows:
-- ./scripts/checktransupdate.py -l zh_CN
+- tools/docs/checktransupdate.py -l zh_CN
 This will print all the files that need to be updated or translated in the zh_CN locale.
-- ./scripts/checktransupdate.py Documentation/translations/zh_CN/dev-tools/testing-overview.rst
+- tools/docs/checktransupdate.py Documentation/translations/zh_CN/dev-tools/testing-overview.rst
 This will only print the status of the specified file.
 
 The output is something like:
@@ -168,7 +168,7 @@ def check_per_file(file_path):
 def valid_locales(locale):
     """Check if the locale is valid or not"""
     script_path = os.path.dirname(os.path.abspath(__file__))
-    linux_path = os.path.join(script_path, "..")
+    linux_path = os.path.join(script_path, "../..")
     if not os.path.isdir(f"{linux_path}/Documentation/translations/{locale}"):
         raise ArgumentTypeError("Invalid locale: {locale}")
     return locale
@@ -232,7 +232,7 @@ def config_logging(log_level, log_file="checktransupdate.log"):
 def main():
     """Main function of the script"""
     script_path = os.path.dirname(os.path.abspath(__file__))
-    linux_path = os.path.join(script_path, "..")
+    linux_path = os.path.join(script_path, "../..")
 
     parser = ArgumentParser(description="Check the translation update")
     parser.add_argument(
-- 
2.51.0


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

* [PATCH v3 3/8] docs: move scripts/documentation-file-ref-check to tools/docs
  2025-10-24 20:08 [PATCH v3 0/8] Collect documentation-related tools under /tools/docs Jonathan Corbet
  2025-10-24 20:08 ` [PATCH v3 1/8] docs: Move the "features" tools to tools/docs Jonathan Corbet
  2025-10-24 20:08 ` [PATCH v3 2/8] docs: move checktransupdate.py " Jonathan Corbet
@ 2025-10-24 20:08 ` Jonathan Corbet
  2025-10-24 20:08 ` [PATCH v3 4/8] docs: move get_abi.py " Jonathan Corbet
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 21+ messages in thread
From: Jonathan Corbet @ 2025-10-24 20:08 UTC (permalink / raw)
  To: linux-doc
  Cc: linux-kernel, Mauro Carvalho Chehab, Akira Yokosawa, Randy Dunlap,
	Jani Nikula, Jonathan Corbet, Jani Nikula

Add this script to the growing collection of documentation tools.

Acked-by: Jani Nikula <jani.nikula@intel.com>
Signed-off-by: Jonathan Corbet <corbet@lwn.net>
---
 Documentation/Makefile                               | 4 ++--
 MAINTAINERS                                          | 2 --
 {scripts => tools/docs}/documentation-file-ref-check | 2 +-
 tools/docs/sphinx-pre-install                        | 2 +-
 4 files changed, 4 insertions(+), 6 deletions(-)
 rename {scripts => tools/docs}/documentation-file-ref-check (99%)

diff --git a/Documentation/Makefile b/Documentation/Makefile
index 65d184eab739..1476aa1701ce 100644
--- a/Documentation/Makefile
+++ b/Documentation/Makefile
@@ -8,7 +8,7 @@ subdir- := devicetree/bindings
 ifneq ($(MAKECMDGOALS),cleandocs)
 # Check for broken documentation file references
 ifeq ($(CONFIG_WARN_MISSING_DOCUMENTS),y)
-$(shell $(srctree)/scripts/documentation-file-ref-check --warn)
+$(shell $(srctree)/tools/docs/documentation-file-ref-check --warn)
 endif
 
 # Check for broken ABI files
@@ -78,7 +78,7 @@ htmldocs-redirects: $(srctree)/Documentation/.renames.txt
 	@tools/docs/gen-redirects.py --output $(BUILDDIR) < $<
 
 refcheckdocs:
-	$(Q)cd $(srctree);scripts/documentation-file-ref-check
+	$(Q)cd $(srctree); tools/docs/documentation-file-ref-check
 
 cleandocs:
 	$(Q)rm -rf $(BUILDDIR)
diff --git a/MAINTAINERS b/MAINTAINERS
index cd187b9f1dc2..fc1da52433b6 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7411,7 +7411,6 @@ S:	Maintained
 P:	Documentation/doc-guide/maintainer-profile.rst
 T:	git git://git.lwn.net/linux.git docs-next
 F:	Documentation/
-F:	scripts/documentation-file-ref-check
 F:	scripts/get_abi.py
 F:	scripts/kernel-doc*
 F:	scripts/lib/abi/*
@@ -7451,7 +7450,6 @@ M:	Mauro Carvalho Chehab <mchehab@kernel.org>
 L:	linux-doc@vger.kernel.org
 S:	Maintained
 F:	Documentation/sphinx/parse-headers.pl
-F:	scripts/documentation-file-ref-check
 F:	tools/docs/sphinx-pre-install
 
 DOCUMENTATION/ITALIAN
diff --git a/scripts/documentation-file-ref-check b/tools/docs/documentation-file-ref-check
similarity index 99%
rename from scripts/documentation-file-ref-check
rename to tools/docs/documentation-file-ref-check
index 408b1dbe7884..0cad42f6943b 100755
--- a/scripts/documentation-file-ref-check
+++ b/tools/docs/documentation-file-ref-check
@@ -17,7 +17,7 @@ my %false_positives = (
 );
 
 my $scriptname = $0;
-$scriptname =~ s,.*/([^/]+/),$1,;
+$scriptname =~ s,tools/docs/([^/]+/),$1,;
 
 # Parse arguments
 my $help = 0;
diff --git a/tools/docs/sphinx-pre-install b/tools/docs/sphinx-pre-install
index 698989584b6a..647e1f60357f 100755
--- a/tools/docs/sphinx-pre-install
+++ b/tools/docs/sphinx-pre-install
@@ -313,7 +313,7 @@ class MissingCheckers(AncillaryMethods):
         Right now, we still need Perl for doc build, as it is required
         by some tools called at docs or kernel build time, like:
 
-            scripts/documentation-file-ref-check
+            tools/docs/documentation-file-ref-check
 
         Also, checkpatch is on Perl.
         """
-- 
2.51.0


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

* [PATCH v3 4/8] docs: move get_abi.py to tools/docs
  2025-10-24 20:08 [PATCH v3 0/8] Collect documentation-related tools under /tools/docs Jonathan Corbet
                   ` (2 preceding siblings ...)
  2025-10-24 20:08 ` [PATCH v3 3/8] docs: move scripts/documentation-file-ref-check " Jonathan Corbet
@ 2025-10-24 20:08 ` Jonathan Corbet
  2025-10-24 20:08 ` [PATCH v3 5/8] docs: move test_doc_build.py " Jonathan Corbet
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 21+ messages in thread
From: Jonathan Corbet @ 2025-10-24 20:08 UTC (permalink / raw)
  To: linux-doc
  Cc: linux-kernel, Mauro Carvalho Chehab, Akira Yokosawa, Randy Dunlap,
	Jani Nikula, Jonathan Corbet, Jani Nikula

Move this tool out of scripts/ to join the other documentation tools; fix
up a couple of erroneous references in the process.

It's worth noting that this script will fail badly unless one has a
PYTHONPATH referencing scripts/lib/abi.

Acked-by: Jani Nikula <jani.nikula@intel.com>
Signed-off-by: Jonathan Corbet <corbet@lwn.net>
---
 Documentation/Kconfig              | 2 +-
 Documentation/Makefile             | 2 +-
 Documentation/sphinx/kernel_abi.py | 2 +-
 MAINTAINERS                        | 1 -
 {scripts => tools/docs}/get_abi.py | 0
 5 files changed, 3 insertions(+), 4 deletions(-)
 rename {scripts => tools/docs}/get_abi.py (100%)

diff --git a/Documentation/Kconfig b/Documentation/Kconfig
index 3a0e7ac0c4e3..8b6c4b84b218 100644
--- a/Documentation/Kconfig
+++ b/Documentation/Kconfig
@@ -19,7 +19,7 @@ config WARN_ABI_ERRORS
 	  described at Documentation/ABI/README. Yet, as they're manually
 	  written, it would be possible that some of those files would
 	  have errors that would break them for being parsed by
-	  scripts/get_abi.pl. Add a check to verify them.
+	  tools/docs/get_abi.py. Add a check to verify them.
 
 	  If unsure, select 'N'.
 
diff --git a/Documentation/Makefile b/Documentation/Makefile
index 1476aa1701ce..734ec9c9a62c 100644
--- a/Documentation/Makefile
+++ b/Documentation/Makefile
@@ -13,7 +13,7 @@ endif
 
 # Check for broken ABI files
 ifeq ($(CONFIG_WARN_ABI_ERRORS),y)
-$(shell $(srctree)/scripts/get_abi.py --dir $(srctree)/Documentation/ABI validate)
+$(shell $(srctree)/tools/docs/get_abi.py --dir $(srctree)/Documentation/ABI validate)
 endif
 endif
 
diff --git a/Documentation/sphinx/kernel_abi.py b/Documentation/sphinx/kernel_abi.py
index 4c4375201b9e..32e39fb8bc3b 100644
--- a/Documentation/sphinx/kernel_abi.py
+++ b/Documentation/sphinx/kernel_abi.py
@@ -14,7 +14,7 @@
     :license:    GPL Version 2, June 1991 see Linux/COPYING for details.
 
     The ``kernel-abi`` (:py:class:`KernelCmd`) directive calls the
-    scripts/get_abi.py script to parse the Kernel ABI files.
+    AbiParser class to parse the Kernel ABI files.
 
     Overview of directive's argument and options.
 
diff --git a/MAINTAINERS b/MAINTAINERS
index fc1da52433b6..5c632cd3902c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7411,7 +7411,6 @@ S:	Maintained
 P:	Documentation/doc-guide/maintainer-profile.rst
 T:	git git://git.lwn.net/linux.git docs-next
 F:	Documentation/
-F:	scripts/get_abi.py
 F:	scripts/kernel-doc*
 F:	scripts/lib/abi/*
 F:	scripts/lib/kdoc/*
diff --git a/scripts/get_abi.py b/tools/docs/get_abi.py
similarity index 100%
rename from scripts/get_abi.py
rename to tools/docs/get_abi.py
-- 
2.51.0


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

* [PATCH v3 5/8] docs: move test_doc_build.py to tools/docs
  2025-10-24 20:08 [PATCH v3 0/8] Collect documentation-related tools under /tools/docs Jonathan Corbet
                   ` (3 preceding siblings ...)
  2025-10-24 20:08 ` [PATCH v3 4/8] docs: move get_abi.py " Jonathan Corbet
@ 2025-10-24 20:08 ` Jonathan Corbet
  2025-10-24 20:08 ` [PATCH v3 6/8] docs: move kernel-doc " Jonathan Corbet
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 21+ messages in thread
From: Jonathan Corbet @ 2025-10-24 20:08 UTC (permalink / raw)
  To: linux-doc
  Cc: linux-kernel, Mauro Carvalho Chehab, Akira Yokosawa, Randy Dunlap,
	Jani Nikula, Jonathan Corbet, Jani Nikula

Add this tool to tools/docs.

Acked-by: Jani Nikula <jani.nikula@intel.com>
Signed-off-by: Jonathan Corbet <corbet@lwn.net>
---
 Documentation/doc-guide/sphinx.rst        | 2 +-
 {scripts => tools/docs}/test_doc_build.py | 0
 2 files changed, 1 insertion(+), 1 deletion(-)
 rename {scripts => tools/docs}/test_doc_build.py (100%)

diff --git a/Documentation/doc-guide/sphinx.rst b/Documentation/doc-guide/sphinx.rst
index 932f68c53075..51c370260f3b 100644
--- a/Documentation/doc-guide/sphinx.rst
+++ b/Documentation/doc-guide/sphinx.rst
@@ -149,7 +149,7 @@ a venv with it with, and install minimal requirements with::
 
 A more comprehensive test can be done by using:
 
-	scripts/test_doc_build.py
+	tools/docs/test_doc_build.py
 
 Such script create one Python venv per supported version,
 optionally building documentation for a range of Sphinx versions.
diff --git a/scripts/test_doc_build.py b/tools/docs/test_doc_build.py
similarity index 100%
rename from scripts/test_doc_build.py
rename to tools/docs/test_doc_build.py
-- 
2.51.0


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

* [PATCH v3 6/8] docs: move kernel-doc to tools/docs
  2025-10-24 20:08 [PATCH v3 0/8] Collect documentation-related tools under /tools/docs Jonathan Corbet
                   ` (4 preceding siblings ...)
  2025-10-24 20:08 ` [PATCH v3 5/8] docs: move test_doc_build.py " Jonathan Corbet
@ 2025-10-24 20:08 ` Jonathan Corbet
  2025-10-25  7:14   ` kernel test robot
  2025-10-24 20:08 ` [PATCH v3 7/8] docs: move find-unused-docs.sh " Jonathan Corbet
                   ` (4 subsequent siblings)
  10 siblings, 1 reply; 21+ messages in thread
From: Jonathan Corbet @ 2025-10-24 20:08 UTC (permalink / raw)
  To: linux-doc
  Cc: linux-kernel, Mauro Carvalho Chehab, Akira Yokosawa, Randy Dunlap,
	Jani Nikula, Jonathan Corbet, Jani Nikula

Move kernel-doc to join the rest of the tools, and update references
throughout the tree.

Acked-by: Jani Nikula <jani.nikula@intel.com>
Signed-off-by: Jonathan Corbet <corbet@lwn.net>
---
 Documentation/conf.py                                  |  2 +-
 Documentation/doc-guide/kernel-doc.rst                 |  6 +++---
 Documentation/kbuild/kbuild.rst                        |  2 +-
 Documentation/process/coding-style.rst                 |  2 +-
 .../translations/it_IT/doc-guide/kernel-doc.rst        |  8 ++++----
 .../translations/sp_SP/process/coding-style.rst        |  2 +-
 .../translations/zh_CN/doc-guide/kernel-doc.rst        | 10 +++++-----
 Documentation/translations/zh_CN/kbuild/kbuild.rst     |  2 +-
 .../translations/zh_CN/process/coding-style.rst        |  2 +-
 .../translations/zh_TW/process/coding-style.rst        |  2 +-
 MAINTAINERS                                            |  1 -
 Makefile                                               |  2 +-
 drivers/gpu/drm/i915/Makefile                          |  2 +-
 scripts/find-unused-docs.sh                            |  2 +-
 scripts/kernel-doc                                     |  1 -
 scripts/kernel-doc.py => tools/docs/kernel-doc         |  0
 16 files changed, 22 insertions(+), 24 deletions(-)
 delete mode 120000 scripts/kernel-doc
 rename scripts/kernel-doc.py => tools/docs/kernel-doc (100%)

diff --git a/Documentation/conf.py b/Documentation/conf.py
index 1ea2ae5c6276..8e3df5db858e 100644
--- a/Documentation/conf.py
+++ b/Documentation/conf.py
@@ -582,7 +582,7 @@ pdf_documents = [
 # kernel-doc extension configuration for running Sphinx directly (e.g. by Read
 # the Docs). In a normal build, these are supplied from the Makefile via command
 # line arguments.
-kerneldoc_bin = "../scripts/kernel-doc.py"
+kerneldoc_bin = "../tools/docs/kernel-doc.py"
 kerneldoc_srctree = ".."
 
 def setup(app):
diff --git a/Documentation/doc-guide/kernel-doc.rst b/Documentation/doc-guide/kernel-doc.rst
index 4370cc8fbcf5..d754d52bee8c 100644
--- a/Documentation/doc-guide/kernel-doc.rst
+++ b/Documentation/doc-guide/kernel-doc.rst
@@ -54,7 +54,7 @@ Running the ``kernel-doc`` tool with increased verbosity and without actual
 output generation may be used to verify proper formatting of the
 documentation comments. For example::
 
-	scripts/kernel-doc -v -none drivers/foo/bar.c
+	tools/docs/kernel-doc -v -none drivers/foo/bar.c
 
 The documentation format is verified by the kernel build when it is
 requested to perform extra gcc checks::
@@ -349,7 +349,7 @@ differentiated by whether the macro name is immediately followed by a
 left parenthesis ('(') for function-like macros or not followed by one
 for object-like macros.
 
-Function-like macros are handled like functions by ``scripts/kernel-doc``.
+Function-like macros are handled like functions by ``tools/docs/kernel-doc``.
 They may have a parameter list. Object-like macros have do not have a
 parameter list.
 
@@ -571,7 +571,7 @@ from the source file.
 
 The kernel-doc extension is included in the kernel source tree, at
 ``Documentation/sphinx/kerneldoc.py``. Internally, it uses the
-``scripts/kernel-doc`` script to extract the documentation comments from the
+``tools/docs/kernel-doc`` script to extract the documentation comments from the
 source.
 
 .. _kernel_doc:
diff --git a/Documentation/kbuild/kbuild.rst b/Documentation/kbuild/kbuild.rst
index 3388a10f2dcc..32840878adbd 100644
--- a/Documentation/kbuild/kbuild.rst
+++ b/Documentation/kbuild/kbuild.rst
@@ -180,7 +180,7 @@ architecture.
 KDOCFLAGS
 ---------
 Specify extra (warning/error) flags for kernel-doc checks during the build,
-see scripts/kernel-doc for which flags are supported. Note that this doesn't
+see tools/docs/kernel-doc for which flags are supported. Note that this doesn't
 (currently) apply to documentation builds.
 
 ARCH
diff --git a/Documentation/process/coding-style.rst b/Documentation/process/coding-style.rst
index d1a8e5465ed9..531ae288f3c3 100644
--- a/Documentation/process/coding-style.rst
+++ b/Documentation/process/coding-style.rst
@@ -614,7 +614,7 @@ it.
 
 When commenting the kernel API functions, please use the kernel-doc format.
 See the files at :ref:`Documentation/doc-guide/ <doc_guide>` and
-``scripts/kernel-doc`` for details. Note that the danger of over-commenting
+``tools/docs/kernel-doc`` for details. Note that the danger of over-commenting
 applies to kernel-doc comments all the same. Do not add boilerplate
 kernel-doc which simply reiterates what's obvious from the signature
 of the function.
diff --git a/Documentation/translations/it_IT/doc-guide/kernel-doc.rst b/Documentation/translations/it_IT/doc-guide/kernel-doc.rst
index aa0e31d353d6..bac959b8b7b9 100644
--- a/Documentation/translations/it_IT/doc-guide/kernel-doc.rst
+++ b/Documentation/translations/it_IT/doc-guide/kernel-doc.rst
@@ -80,7 +80,7 @@ Al fine di verificare che i commenti siano formattati correttamente, potete
 eseguire il programma ``kernel-doc`` con un livello di verbosità alto e senza
 che questo produca alcuna documentazione. Per esempio::
 
-	scripts/kernel-doc -v -none drivers/foo/bar.c
+	tools/docs/kernel-doc -v -none drivers/foo/bar.c
 
 Il formato della documentazione è verificato della procedura di generazione
 del kernel quando viene richiesto di effettuare dei controlli extra con GCC::
@@ -378,7 +378,7 @@ distinguono in base al fatto che il nome della macro simile a funzione sia
 immediatamente seguito da una parentesi sinistra ('(') mentre in quelle simili a
 oggetti no.
 
-Le macro simili a funzioni sono gestite come funzioni da ``scripts/kernel-doc``.
+Le macro simili a funzioni sono gestite come funzioni da ``tools/docs/kernel-doc``.
 Possono avere un elenco di parametri. Le macro simili a oggetti non hanno un
 elenco di parametri.
 
@@ -595,7 +595,7 @@ documentazione presenti nel file sorgente (*source*).
 
 L'estensione kernel-doc fa parte dei sorgenti del kernel, la si può trovare
 in ``Documentation/sphinx/kerneldoc.py``. Internamente, viene utilizzato
-lo script ``scripts/kernel-doc`` per estrarre i commenti di documentazione
+lo script ``tools/docs/kernel-doc`` per estrarre i commenti di documentazione
 dai file sorgenti.
 
 Come utilizzare kernel-doc per generare pagine man
@@ -604,4 +604,4 @@ Come utilizzare kernel-doc per generare pagine man
 Se volete utilizzare kernel-doc solo per generare delle pagine man, potete
 farlo direttamente dai sorgenti del kernel::
 
-  $ scripts/kernel-doc -man $(git grep -l '/\*\*' -- :^Documentation :^tools) | scripts/split-man.pl /tmp/man
+  $ tools/docs/kernel-doc -man $(git grep -l '/\*\*' -- :^Documentation :^tools) | scripts/split-man.pl /tmp/man
diff --git a/Documentation/translations/sp_SP/process/coding-style.rst b/Documentation/translations/sp_SP/process/coding-style.rst
index 025223be9706..7d63aa8426e6 100644
--- a/Documentation/translations/sp_SP/process/coding-style.rst
+++ b/Documentation/translations/sp_SP/process/coding-style.rst
@@ -633,7 +633,7 @@ posiblemente POR QUÉ hace esto.
 
 Al comentar las funciones de la API del kernel, utilice el formato
 kernel-doc. Consulte los archivos en :ref:`Documentation/doc-guide/ <doc_guide>`
-y ``scripts/kernel-doc`` para más detalles.
+y ``tools/docs/kernel-doc`` para más detalles.
 
 El estilo preferido para comentarios largos (de varias líneas) es:
 
diff --git a/Documentation/translations/zh_CN/doc-guide/kernel-doc.rst b/Documentation/translations/zh_CN/doc-guide/kernel-doc.rst
index ccfb9b8329c2..fb2bbaaa85c1 100644
--- a/Documentation/translations/zh_CN/doc-guide/kernel-doc.rst
+++ b/Documentation/translations/zh_CN/doc-guide/kernel-doc.rst
@@ -43,7 +43,7 @@ kernel-doc注释用 ``/**`` 作为开始标记。 ``kernel-doc`` 工具将提取
 用详细模式和不生成实际输出来运行 ``kernel-doc`` 工具,可以验证文档注释的格式
 是否正确。例如::
 
-	scripts/kernel-doc -v -none drivers/foo/bar.c
+	tools/docs/kernel-doc -v -none drivers/foo/bar.c
 
 当请求执行额外的gcc检查时,内核构建将验证文档格式::
 
@@ -473,7 +473,7 @@ doc: *title*
 如果没有选项,kernel-doc指令将包含源文件中的所有文档注释。
 
 kernel-doc扩展包含在内核源代码树中,位于 ``Documentation/sphinx/kerneldoc.py`` 。
-在内部,它使用 ``scripts/kernel-doc`` 脚本从源代码中提取文档注释。
+在内部,它使用 ``tools/docs/kernel-doc`` 脚本从源代码中提取文档注释。
 
 .. _kernel_doc_zh:
 
@@ -482,18 +482,18 @@ kernel-doc扩展包含在内核源代码树中,位于 ``Documentation/sphinx/k
 
 如果您只想使用kernel-doc生成手册页,可以从内核git树这样做::
 
-  $ scripts/kernel-doc -man \
+  $ tools/docs/kernel-doc -man \
     $(git grep -l '/\*\*' -- :^Documentation :^tools) \
     | scripts/split-man.pl /tmp/man
 
 一些旧版本的git不支持路径排除语法的某些变体。
 以下命令之一可能适用于这些版本::
 
-  $ scripts/kernel-doc -man \
+  $ tools/docs/kernel-doc -man \
     $(git grep -l '/\*\*' -- . ':!Documentation' ':!tools') \
     | scripts/split-man.pl /tmp/man
 
-  $ scripts/kernel-doc -man \
+  $ tools/docs/kernel-doc -man \
     $(git grep -l '/\*\*' -- . ":(exclude)Documentation" ":(exclude)tools") \
     | scripts/split-man.pl /tmp/man
 
diff --git a/Documentation/translations/zh_CN/kbuild/kbuild.rst b/Documentation/translations/zh_CN/kbuild/kbuild.rst
index e5e2aebe1ebc..9c7062b65a99 100644
--- a/Documentation/translations/zh_CN/kbuild/kbuild.rst
+++ b/Documentation/translations/zh_CN/kbuild/kbuild.rst
@@ -158,7 +158,7 @@ UTS_MACHINE 变量(在某些架构中还包括内核配置)来猜测正确
 KDOCFLAGS
 ---------
 指定在构建过程中用于 kernel-doc 检查的额外(警告/错误)标志,查看
-scripts/kernel-doc 了解支持的标志。请注意,这目前不适用于文档构建。
+tools/docs/kernel-doc 了解支持的标志。请注意,这目前不适用于文档构建。
 
 ARCH
 ----
diff --git a/Documentation/translations/zh_CN/process/coding-style.rst b/Documentation/translations/zh_CN/process/coding-style.rst
index 0484d0c65c25..5a342a024c01 100644
--- a/Documentation/translations/zh_CN/process/coding-style.rst
+++ b/Documentation/translations/zh_CN/process/coding-style.rst
@@ -545,7 +545,7 @@ Linux 里这是提倡的做法,因为这样可以很简单的给读者提供
 也可以加上它做这些事情的原因。
 
 当注释内核 API 函数时,请使用 kernel-doc 格式。详见
-Documentation/translations/zh_CN/doc-guide/index.rst 和 scripts/kernel-doc 。
+Documentation/translations/zh_CN/doc-guide/index.rst 和 tools/docs/kernel-doc 。
 
 长 (多行) 注释的首选风格是:
 
diff --git a/Documentation/translations/zh_TW/process/coding-style.rst b/Documentation/translations/zh_TW/process/coding-style.rst
index 311c6f6bad0b..e2ba97b3d8bb 100644
--- a/Documentation/translations/zh_TW/process/coding-style.rst
+++ b/Documentation/translations/zh_TW/process/coding-style.rst
@@ -548,7 +548,7 @@ Linux 裏這是提倡的做法,因爲這樣可以很簡單的給讀者提供
 也可以加上它做這些事情的原因。
 
 當註釋內核 API 函數時,請使用 kernel-doc 格式。詳見
-Documentation/translations/zh_CN/doc-guide/index.rst 和 scripts/kernel-doc 。
+Documentation/translations/zh_CN/doc-guide/index.rst 和 tools/docs/kernel-doc 。
 
 長 (多行) 註釋的首選風格是:
 
diff --git a/MAINTAINERS b/MAINTAINERS
index 5c632cd3902c..3bd5a0647e94 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7411,7 +7411,6 @@ S:	Maintained
 P:	Documentation/doc-guide/maintainer-profile.rst
 T:	git git://git.lwn.net/linux.git docs-next
 F:	Documentation/
-F:	scripts/kernel-doc*
 F:	scripts/lib/abi/*
 F:	scripts/lib/kdoc/*
 F:	tools/docs/*
diff --git a/Makefile b/Makefile
index 9ce6f6f52ea8..d6ff0af5cca6 100644
--- a/Makefile
+++ b/Makefile
@@ -460,7 +460,7 @@ HOSTPKG_CONFIG	= pkg-config
 
 # the KERNELDOC macro needs to be exported, as scripts/Makefile.build
 # has a logic to call it
-KERNELDOC       = $(srctree)/scripts/kernel-doc.py
+KERNELDOC       = $(srctree)/tools/docs/kernel-doc.py
 export KERNELDOC
 
 KBUILD_USERHOSTCFLAGS := -Wall -Wmissing-prototypes -Wstrict-prototypes \
diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index e58c0c158b3a..4a339ffac9f3 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -428,7 +428,7 @@ always-$(CONFIG_DRM_I915_WERROR) += \
 
 quiet_cmd_hdrtest = HDRTEST $(patsubst %.hdrtest,%.h,$@)
       cmd_hdrtest = $(CC) $(filter-out $(CFLAGS_GCOV), $(c_flags)) -S -o /dev/null -x c /dev/null -include $<; \
-		$(srctree)/scripts/kernel-doc -none -Werror $<; touch $@
+		$(srctree)/tools/docs/kernel-doc -none -Werror $<; touch $@
 
 $(obj)/%.hdrtest: $(src)/%.h FORCE
 	$(call if_changed_dep,hdrtest)
diff --git a/scripts/find-unused-docs.sh b/scripts/find-unused-docs.sh
index d6d397fbf917..1fb265a0ffd0 100755
--- a/scripts/find-unused-docs.sh
+++ b/scripts/find-unused-docs.sh
@@ -54,7 +54,7 @@ for file in `find $1 -name '*.c'`; do
 	if [[ ${FILES_INCLUDED[$file]+_} ]]; then
 	continue;
 	fi
-	str=$(PYTHONDONTWRITEBYTECODE=1 scripts/kernel-doc -export "$file" 2>/dev/null)
+	str=$(PYTHONDONTWRITEBYTECODE=1 tools/docs/kernel-doc -export "$file" 2>/dev/null)
 	if [[ -n "$str" ]]; then
 	echo "$file"
 	fi
diff --git a/scripts/kernel-doc b/scripts/kernel-doc
deleted file mode 120000
index 3b6ef807791a..000000000000
--- a/scripts/kernel-doc
+++ /dev/null
@@ -1 +0,0 @@
-kernel-doc.py
\ No newline at end of file
diff --git a/scripts/kernel-doc.py b/tools/docs/kernel-doc
similarity index 100%
rename from scripts/kernel-doc.py
rename to tools/docs/kernel-doc
-- 
2.51.0


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

* [PATCH v3 7/8] docs: move find-unused-docs.sh to tools/docs
  2025-10-24 20:08 [PATCH v3 0/8] Collect documentation-related tools under /tools/docs Jonathan Corbet
                   ` (5 preceding siblings ...)
  2025-10-24 20:08 ` [PATCH v3 6/8] docs: move kernel-doc " Jonathan Corbet
@ 2025-10-24 20:08 ` Jonathan Corbet
  2025-10-24 20:08 ` [PATCH v3 8/8] docs: remove kernel-doc.pl Jonathan Corbet
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 21+ messages in thread
From: Jonathan Corbet @ 2025-10-24 20:08 UTC (permalink / raw)
  To: linux-doc
  Cc: linux-kernel, Mauro Carvalho Chehab, Akira Yokosawa, Randy Dunlap,
	Jani Nikula, Jonathan Corbet, Jani Nikula

...and update references accordingly.

Acked-by: Jani Nikula <jani.nikula@intel.com>
Signed-off-by: Jonathan Corbet <corbet@lwn.net>
---
 Documentation/doc-guide/contributing.rst                    | 2 +-
 Documentation/translations/zh_CN/doc-guide/contributing.rst | 2 +-
 {scripts => tools/docs}/find-unused-docs.sh                 | 6 +++---
 3 files changed, 5 insertions(+), 5 deletions(-)
 rename {scripts => tools/docs}/find-unused-docs.sh (85%)

diff --git a/Documentation/doc-guide/contributing.rst b/Documentation/doc-guide/contributing.rst
index 662c7a840cd5..f8047e633113 100644
--- a/Documentation/doc-guide/contributing.rst
+++ b/Documentation/doc-guide/contributing.rst
@@ -152,7 +152,7 @@ generate links to that documentation.  Adding ``kernel-doc`` directives to
 the documentation to bring those comments in can help the community derive
 the full value of the work that has gone into creating them.
 
-The ``scripts/find-unused-docs.sh`` tool can be used to find these
+The ``tools/docs/find-unused-docs.sh`` tool can be used to find these
 overlooked comments.
 
 Note that the most value comes from pulling in the documentation for
diff --git a/Documentation/translations/zh_CN/doc-guide/contributing.rst b/Documentation/translations/zh_CN/doc-guide/contributing.rst
index 394a13b438b0..b0c8ba782b16 100644
--- a/Documentation/translations/zh_CN/doc-guide/contributing.rst
+++ b/Documentation/translations/zh_CN/doc-guide/contributing.rst
@@ -124,7 +124,7 @@ C代码编译器发出的警告常常会被视为误报,从而导致出现了
 这使得这些信息更难找到,例如使Sphinx无法生成指向该文档的链接。将 ``kernel-doc``
 指令添加到文档中以引入这些注释可以帮助社区获得为编写注释所做工作的全部价值。
 
-``scripts/find-unused-docs.sh`` 工具可以用来找到这些被忽略的评论。
+``tools/docs/find-unused-docs.sh`` 工具可以用来找到这些被忽略的评论。
 
 请注意,将导出的函数和数据结构引入文档是最有价值的。许多子系统还具有供内部
 使用的kernel-doc注释;除非这些注释放在专门针对相关子系统开发人员的文档中,
diff --git a/scripts/find-unused-docs.sh b/tools/docs/find-unused-docs.sh
similarity index 85%
rename from scripts/find-unused-docs.sh
rename to tools/docs/find-unused-docs.sh
index 1fb265a0ffd0..2f2195a77c60 100755
--- a/scripts/find-unused-docs.sh
+++ b/tools/docs/find-unused-docs.sh
@@ -5,10 +5,10 @@
 # This script detects files with kernel-doc comments for exported functions
 # that are not included in documentation.
 #
-# usage: Run 'scripts/find-unused-docs.sh directory' from top level of kernel
+# usage: Run 'tools/docs/find-unused-docs.sh directory' from top level of kernel
 # 	 tree.
 #
-# example: $scripts/find-unused-docs.sh drivers/scsi
+# example: $tools/docs/find-unused-docs.sh drivers/scsi
 #
 # Licensed under the terms of the GNU GPL License
 
@@ -18,7 +18,7 @@ if ! [ -d "Documentation" ]; then
 fi
 
 if [ "$#" -ne 1 ]; then
-	echo "Usage: scripts/find-unused-docs.sh directory"
+	echo "Usage: tools/docs/find-unused-docs.sh directory"
 	exit 1
 fi
 
-- 
2.51.0


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

* [PATCH v3 8/8] docs: remove kernel-doc.pl
  2025-10-24 20:08 [PATCH v3 0/8] Collect documentation-related tools under /tools/docs Jonathan Corbet
                   ` (6 preceding siblings ...)
  2025-10-24 20:08 ` [PATCH v3 7/8] docs: move find-unused-docs.sh " Jonathan Corbet
@ 2025-10-24 20:08 ` Jonathan Corbet
  2025-10-25  2:33 ` [PATCH v3 0/8] Collect documentation-related tools under /tools/docs Mauro Carvalho Chehab
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 21+ messages in thread
From: Jonathan Corbet @ 2025-10-24 20:08 UTC (permalink / raw)
  To: linux-doc
  Cc: linux-kernel, Mauro Carvalho Chehab, Akira Yokosawa, Randy Dunlap,
	Jani Nikula, Jonathan Corbet, Jani Nikula

We've been using the Python version and nobody has missed this one.  All
credit goes to Mauro Carvalho Chehab for creating the replacement.

Acked-by: Jani Nikula <jani.nikula@intel.com>
Signed-off-by: Jonathan Corbet <corbet@lwn.net>
---
 scripts/kernel-doc.pl | 2439 -----------------------------------------
 1 file changed, 2439 deletions(-)
 delete mode 100755 scripts/kernel-doc.pl

diff --git a/scripts/kernel-doc.pl b/scripts/kernel-doc.pl
deleted file mode 100755
index 5db23cbf4eb2..000000000000
--- a/scripts/kernel-doc.pl
+++ /dev/null
@@ -1,2439 +0,0 @@
-#!/usr/bin/env perl
-# SPDX-License-Identifier: GPL-2.0
-# vim: softtabstop=4
-
-use warnings;
-use strict;
-
-## Copyright (c) 1998 Michael Zucchi, All Rights Reserved        ##
-## Copyright (C) 2000, 1  Tim Waugh <twaugh@redhat.com>          ##
-## Copyright (C) 2001  Simon Huggins                             ##
-## Copyright (C) 2005-2012  Randy Dunlap                         ##
-## Copyright (C) 2012  Dan Luedtke                               ##
-## 								 ##
-## #define enhancements by Armin Kuster <akuster@mvista.com>	 ##
-## Copyright (c) 2000 MontaVista Software, Inc.			 ##
-#
-# Copyright (C) 2022 Tomasz Warniełło (POD)
-
-use Pod::Usage qw/pod2usage/;
-
-=head1 NAME
-
-kernel-doc - Print formatted kernel documentation to stdout
-
-=head1 SYNOPSIS
-
- kernel-doc [-h] [-v] [-Werror] [-Wall] [-Wreturn] [-Wshort-desc[ription]] [-Wcontents-before-sections]
-   [ -man |
-     -rst [-enable-lineno] |
-     -none
-   ]
-   [
-     -export |
-     -internal |
-     [-function NAME] ... |
-     [-nosymbol NAME] ...
-   ]
-   [-no-doc-sections]
-   [-export-file FILE] ...
-   FILE ...
-
-Run `kernel-doc -h` for details.
-
-=head1 DESCRIPTION
-
-Read C language source or header FILEs, extract embedded documentation comments,
-and print formatted documentation to standard output.
-
-The documentation comments are identified by the "/**" opening comment mark.
-
-See Documentation/doc-guide/kernel-doc.rst for the documentation comment syntax.
-
-=cut
-
-# more perldoc at the end of the file
-
-## init lots of data
-
-my $errors = 0;
-my $warnings = 0;
-my $anon_struct_union = 0;
-
-# match expressions used to find embedded type information
-my $type_constant = '\b``([^\`]+)``\b';
-my $type_constant2 = '\%([-_*\w]+)';
-my $type_func = '(\w+)\(\)';
-my $type_param = '\@(\w*((\.\w+)|(->\w+))*(\.\.\.)?)';
-my $type_param_ref = '([\!~\*]?)\@(\w*((\.\w+)|(->\w+))*(\.\.\.)?)';
-my $type_fp_param = '\@(\w+)\(\)';  # Special RST handling for func ptr params
-my $type_fp_param2 = '\@(\w+->\S+)\(\)';  # Special RST handling for structs with func ptr params
-my $type_env = '(\$\w+)';
-my $type_enum = '\&(enum\s*([_\w]+))';
-my $type_struct = '\&(struct\s*([_\w]+))';
-my $type_typedef = '\&(typedef\s*([_\w]+))';
-my $type_union = '\&(union\s*([_\w]+))';
-my $type_member = '\&([_\w]+)(\.|->)([_\w]+)';
-my $type_fallback = '\&([_\w]+)';
-my $type_member_func = $type_member . '\(\)';
-
-# Output conversion substitutions.
-#  One for each output format
-
-# these are pretty rough
-my @highlights_man = (
-    [$type_constant, "\$1"],
-    [$type_constant2, "\$1"],
-    [$type_func, "\\\\fB\$1\\\\fP"],
-    [$type_enum, "\\\\fI\$1\\\\fP"],
-    [$type_struct, "\\\\fI\$1\\\\fP"],
-    [$type_typedef, "\\\\fI\$1\\\\fP"],
-    [$type_union, "\\\\fI\$1\\\\fP"],
-    [$type_param, "\\\\fI\$1\\\\fP"],
-    [$type_param_ref, "\\\\fI\$1\$2\\\\fP"],
-    [$type_member, "\\\\fI\$1\$2\$3\\\\fP"],
-    [$type_fallback, "\\\\fI\$1\\\\fP"]
-  );
-my $blankline_man = "";
-
-# rst-mode
-my @highlights_rst = (
-    [$type_constant, "``\$1``"],
-    [$type_constant2, "``\$1``"],
-
-    # Note: need to escape () to avoid func matching later
-    [$type_member_func, "\\:c\\:type\\:`\$1\$2\$3\\\\(\\\\) <\$1>`"],
-    [$type_member, "\\:c\\:type\\:`\$1\$2\$3 <\$1>`"],
-    [$type_fp_param, "**\$1\\\\(\\\\)**"],
-    [$type_fp_param2, "**\$1\\\\(\\\\)**"],
-    [$type_func, "\$1()"],
-    [$type_enum, "\\:c\\:type\\:`\$1 <\$2>`"],
-    [$type_struct, "\\:c\\:type\\:`\$1 <\$2>`"],
-    [$type_typedef, "\\:c\\:type\\:`\$1 <\$2>`"],
-    [$type_union, "\\:c\\:type\\:`\$1 <\$2>`"],
-
-    # in rst this can refer to any type
-    [$type_fallback, "\\:c\\:type\\:`\$1`"],
-    [$type_param_ref, "**\$1\$2**"]
-  );
-my $blankline_rst = "\n";
-
-# read arguments
-if ($#ARGV == -1) {
-    pod2usage(
-        -message => "No arguments!\n",
-        -exitval => 1,
-        -verbose => 99,
-        -sections => 'SYNOPSIS',
-        -output => \*STDERR,
-      );
-}
-
-my $kernelversion;
-
-my $dohighlight = "";
-
-my $verbose = 0;
-my $Werror = 0;
-my $Wreturn = 0;
-my $Wshort_desc = 0;
-my $output_mode = "rst";
-my $output_preformatted = 0;
-my $no_doc_sections = 0;
-my $enable_lineno = 0;
-my @highlights = @highlights_rst;
-my $blankline = $blankline_rst;
-my $modulename = "Kernel API";
-
-use constant {
-    OUTPUT_ALL          => 0, # output all symbols and doc sections
-    OUTPUT_INCLUDE      => 1, # output only specified symbols
-    OUTPUT_EXPORTED     => 2, # output exported symbols
-    OUTPUT_INTERNAL     => 3, # output non-exported symbols
-};
-my $output_selection = OUTPUT_ALL;
-my $show_not_found = 0;	# No longer used
-
-my @export_file_list;
-
-my @build_time;
-if (defined($ENV{'KBUILD_BUILD_TIMESTAMP'}) &&
-    (my $seconds = `date -d "${ENV{'KBUILD_BUILD_TIMESTAMP'}}" +%s`) ne '') {
-    @build_time = gmtime($seconds);
-} else {
-    @build_time = localtime;
-}
-
-my $man_date = ('January', 'February', 'March', 'April', 'May', 'June',
-                'July', 'August', 'September', 'October',
-                'November', 'December')[$build_time[4]] .
-    " " . ($build_time[5]+1900);
-
-# Essentially these are globals.
-# They probably want to be tidied up, made more localised or something.
-# CAVEAT EMPTOR!  Some of the others I localised may not want to be, which
-# could cause "use of undefined value" or other bugs.
-my ($function, %function_table, %parametertypes, $declaration_purpose);
-my %nosymbol_table = ();
-my $declaration_start_line;
-my ($type, $declaration_name, $return_type);
-my ($newsection, $newcontents, $prototype, $brcount);
-
-if (defined($ENV{'KBUILD_VERBOSE'}) && $ENV{'KBUILD_VERBOSE'} =~ '1') {
-    $verbose = 1;
-}
-
-if (defined($ENV{'KCFLAGS'})) {
-    my $kcflags = "$ENV{'KCFLAGS'}";
-
-    if ($kcflags =~ /(\s|^)-Werror(\s|$)/) {
-        $Werror = 1;
-    }
-}
-
-# reading this variable is for backwards compat just in case
-# someone was calling it with the variable from outside the
-# kernel's build system
-if (defined($ENV{'KDOC_WERROR'})) {
-    $Werror = "$ENV{'KDOC_WERROR'}";
-}
-# other environment variables are converted to command-line
-# arguments in cmd_checkdoc in the build system
-
-# Generated docbook code is inserted in a template at a point where
-# docbook v3.1 requires a non-zero sequence of RefEntry's; see:
-# https://www.oasis-open.org/docbook/documentation/reference/html/refentry.html
-# We keep track of number of generated entries and generate a dummy
-# if needs be to ensure the expanded template can be postprocessed
-# into html.
-my $section_counter = 0;
-
-my $lineprefix="";
-
-# Parser states
-use constant {
-    STATE_NORMAL        => 0,        # normal code
-    STATE_NAME          => 1,        # looking for function name
-    STATE_BODY_MAYBE    => 2,        # body - or maybe more description
-    STATE_BODY          => 3,        # the body of the comment
-    STATE_BODY_WITH_BLANK_LINE => 4, # the body, which has a blank line
-    STATE_PROTO         => 5,        # scanning prototype
-    STATE_DOCBLOCK      => 6,        # documentation block
-    STATE_INLINE        => 7,        # gathering doc outside main block
-};
-my $state;
-my $leading_space;
-
-# Inline documentation state
-use constant {
-    STATE_INLINE_NA     => 0, # not applicable ($state != STATE_INLINE)
-    STATE_INLINE_NAME   => 1, # looking for member name (@foo:)
-    STATE_INLINE_TEXT   => 2, # looking for member documentation
-    STATE_INLINE_END    => 3, # done
-    STATE_INLINE_ERROR  => 4, # error - Comment without header was found.
-                              # Spit a warning as it's not
-                              # proper kernel-doc and ignore the rest.
-};
-my $inline_doc_state;
-
-#declaration types: can be
-# 'function', 'struct', 'union', 'enum', 'typedef'
-my $decl_type;
-
-# Name of the kernel-doc identifier for non-DOC markups
-my $identifier;
-
-my $doc_start = '^/\*\*\s*$'; # Allow whitespace at end of comment start.
-my $doc_end = '\*/';
-my $doc_com = '\s*\*\s*';
-my $doc_com_body = '\s*\* ?';
-my $doc_decl = $doc_com . '(\w+)';
-# @params and a strictly limited set of supported section names
-# Specifically:
-#   Match @word:
-#	  @...:
-#         @{section-name}:
-# while trying to not match literal block starts like "example::"
-#
-my $doc_sect = $doc_com .
-    '\s*(\@[.\w]+|\@\.\.\.|description|context|returns?|notes?|examples?)\s*:([^:].*)?$';
-my $doc_content = $doc_com_body . '(.*)';
-my $doc_block = $doc_com . 'DOC:\s*(.*)?';
-my $doc_inline_start = '^\s*/\*\*\s*$';
-my $doc_inline_sect = '\s*\*\s*(@\s*[\w][\w\.]*\s*):(.*)';
-my $doc_inline_end = '^\s*\*/\s*$';
-my $doc_inline_oneline = '^\s*/\*\*\s*(@[\w\s]+):\s*(.*)\s*\*/\s*$';
-my $export_symbol = '^\s*EXPORT_SYMBOL(_GPL)?\s*\(\s*(\w+)\s*\)\s*;';
-my $export_symbol_ns = '^\s*EXPORT_SYMBOL_NS(_GPL)?\s*\(\s*(\w+)\s*,\s*"\S+"\)\s*;';
-my $function_pointer = qr{([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)};
-my $attribute = qr{__attribute__\s*\(\([a-z0-9,_\*\s\(\)]*\)\)}i;
-
-my %parameterdescs;
-my %parameterdesc_start_lines;
-my @parameterlist;
-my %sections;
-my @sectionlist;
-my %section_start_lines;
-my $sectcheck;
-my $struct_actual;
-
-my $contents = "";
-my $new_start_line = 0;
-
-# the canonical section names. see also $doc_sect above.
-my $section_default = "Description";	# default section
-my $section_intro = "Introduction";
-my $section = $section_default;
-my $section_context = "Context";
-my $section_return = "Return";
-
-my $undescribed = "-- undescribed --";
-
-reset_state();
-
-while ($ARGV[0] =~ m/^--?(.*)/) {
-    my $cmd = $1;
-    shift @ARGV;
-    if ($cmd eq "man") {
-        $output_mode = "man";
-        @highlights = @highlights_man;
-        $blankline = $blankline_man;
-    } elsif ($cmd eq "rst") {
-        $output_mode = "rst";
-        @highlights = @highlights_rst;
-        $blankline = $blankline_rst;
-    } elsif ($cmd eq "none") {
-        $output_mode = "none";
-    } elsif ($cmd eq "module") { # not needed for XML, inherits from calling document
-        $modulename = shift @ARGV;
-    } elsif ($cmd eq "function") { # to only output specific functions
-        $output_selection = OUTPUT_INCLUDE;
-        $function = shift @ARGV;
-        $function_table{$function} = 1;
-    } elsif ($cmd eq "nosymbol") { # Exclude specific symbols
-        my $symbol = shift @ARGV;
-        $nosymbol_table{$symbol} = 1;
-    } elsif ($cmd eq "export") { # only exported symbols
-        $output_selection = OUTPUT_EXPORTED;
-        %function_table = ();
-    } elsif ($cmd eq "internal") { # only non-exported symbols
-        $output_selection = OUTPUT_INTERNAL;
-        %function_table = ();
-    } elsif ($cmd eq "export-file") {
-        my $file = shift @ARGV;
-        push(@export_file_list, $file);
-    } elsif ($cmd eq "v") {
-        $verbose = 1;
-    } elsif ($cmd eq "Werror") {
-        $Werror = 1;
-    } elsif ($cmd eq "Wreturn") {
-        $Wreturn = 1;
-    } elsif ($cmd eq "Wshort-desc" or $cmd eq "Wshort-description") {
-        $Wshort_desc = 1;
-    } elsif ($cmd eq "Wall") {
-        $Wreturn = 1;
-        $Wshort_desc = 1;
-    } elsif (($cmd eq "h") || ($cmd eq "help")) {
-        pod2usage(-exitval => 0, -verbose => 2);
-    } elsif ($cmd eq 'no-doc-sections') {
-        $no_doc_sections = 1;
-    } elsif ($cmd eq 'enable-lineno') {
-        $enable_lineno = 1;
-    } elsif ($cmd eq 'show-not-found') {
-        $show_not_found = 1;  # A no-op but don't fail
-    } else {
-        # Unknown argument
-        pod2usage(
-            -message => "Argument unknown!\n",
-            -exitval => 1,
-            -verbose => 99,
-            -sections => 'SYNOPSIS',
-            -output => \*STDERR,
-            );
-    }
-    if ($#ARGV < 0){
-        pod2usage(
-            -message => "FILE argument missing\n",
-            -exitval => 1,
-            -verbose => 99,
-            -sections => 'SYNOPSIS',
-            -output => \*STDERR,
-            );
-    }
-}
-
-# continue execution near EOF;
-
-sub findprog($)
-{
-    foreach(split(/:/, $ENV{PATH})) {
-        return "$_/$_[0]" if(-x "$_/$_[0]");
-    }
-}
-
-# get kernel version from env
-sub get_kernel_version() {
-    my $version = 'unknown kernel version';
-
-    if (defined($ENV{'KERNELVERSION'})) {
-        $version = $ENV{'KERNELVERSION'};
-    }
-    return $version;
-}
-
-#
-sub print_lineno {
-    my $lineno = shift;
-    if ($enable_lineno && defined($lineno)) {
-        print ".. LINENO " . $lineno . "\n";
-    }
-}
-
-sub emit_warning {
-    my $location = shift;
-    my $msg = shift;
-    print STDERR "$location: warning: $msg";
-    ++$warnings;
-}
-##
-# dumps section contents to arrays/hashes intended for that purpose.
-#
-sub dump_section {
-    my $file = shift;
-    my $name = shift;
-    my $contents = join "\n", @_;
-
-    if ($name =~ m/$type_param/) {
-        $name = $1;
-        $parameterdescs{$name} = $contents;
-        $sectcheck = $sectcheck . $name . " ";
-        $parameterdesc_start_lines{$name} = $new_start_line;
-        $new_start_line = 0;
-    } elsif ($name eq "@\.\.\.") {
-        $name = "...";
-        $parameterdescs{$name} = $contents;
-        $sectcheck = $sectcheck . $name . " ";
-        $parameterdesc_start_lines{$name} = $new_start_line;
-        $new_start_line = 0;
-    } else {
-        if (defined($sections{$name}) && ($sections{$name} ne "")) {
-            # Only warn on user specified duplicate section names.
-            if ($name ne $section_default) {
-                emit_warning("${file}:$.", "duplicate section name '$name'\n");
-            }
-            $sections{$name} .= $contents;
-        } else {
-            $sections{$name} = $contents;
-            push @sectionlist, $name;
-            $section_start_lines{$name} = $new_start_line;
-            $new_start_line = 0;
-        }
-    }
-}
-
-##
-# dump DOC: section after checking that it should go out
-#
-sub dump_doc_section {
-    my $file = shift;
-    my $name = shift;
-    my $contents = join "\n", @_;
-
-    if ($no_doc_sections) {
-        return;
-    }
-
-    return if (defined($nosymbol_table{$name}));
-
-    if (($output_selection == OUTPUT_ALL) ||
-        (($output_selection == OUTPUT_INCLUDE) &&
-         defined($function_table{$name})))
-    {
-        dump_section($file, $name, $contents);
-        output_blockhead({'sectionlist' => \@sectionlist,
-                          'sections' => \%sections,
-                          'module' => $modulename,
-                          'content-only' => ($output_selection != OUTPUT_ALL), });
-    }
-}
-
-##
-# output function
-#
-# parameterdescs, a hash.
-#  function => "function name"
-#  parameterlist => @list of parameters
-#  parameterdescs => %parameter descriptions
-#  sectionlist => @list of sections
-#  sections => %section descriptions
-#
-
-sub output_highlight {
-    my $contents = join "\n",@_;
-    my $line;
-
-#   DEBUG
-#   if (!defined $contents) {
-#	use Carp;
-#	confess "output_highlight got called with no args?\n";
-#   }
-
-#   print STDERR "contents b4:$contents\n";
-    eval $dohighlight;
-    die $@ if $@;
-#   print STDERR "contents af:$contents\n";
-
-    foreach $line (split "\n", $contents) {
-        if (! $output_preformatted) {
-            $line =~ s/^\s*//;
-        }
-        if ($line eq ""){
-            if (! $output_preformatted) {
-                print $lineprefix, $blankline;
-            }
-        } else {
-            if ($output_mode eq "man" && substr($line, 0, 1) eq ".") {
-                print "\\&$line";
-            } else {
-                print $lineprefix, $line;
-            }
-        }
-        print "\n";
-    }
-}
-
-##
-# output function in man
-sub output_function_man(%) {
-    my %args = %{$_[0]};
-    my ($parameter, $section);
-    my $count;
-    my $func_macro = $args{'func_macro'};
-    my $paramcount = $#{$args{'parameterlist'}}; # -1 is empty
-
-    print ".TH \"$args{'function'}\" 9 \"$args{'function'}\" \"$man_date\" \"Kernel Hacker's Manual\" LINUX\n";
-
-    print ".SH NAME\n";
-    print $args{'function'} . " \\- " . $args{'purpose'} . "\n";
-
-    print ".SH SYNOPSIS\n";
-    if ($args{'functiontype'} ne "") {
-        print ".B \"" . $args{'functiontype'} . "\" " . $args{'function'} . "\n";
-    } else {
-        print ".B \"" . $args{'function'} . "\n";
-    }
-    $count = 0;
-    my $parenth = "(";
-    my $post = ",";
-    foreach my $parameter (@{$args{'parameterlist'}}) {
-        if ($count == $#{$args{'parameterlist'}}) {
-            $post = ");";
-        }
-        $type = $args{'parametertypes'}{$parameter};
-        if ($type =~ m/$function_pointer/) {
-            # pointer-to-function
-            print ".BI \"" . $parenth . $1 . "\" " . " \") (" . $2 . ")" . $post . "\"\n";
-        } else {
-            $type =~ s/([^\*])$/$1 /;
-            print ".BI \"" . $parenth . $type . "\" " . " \"" . $post . "\"\n";
-        }
-        $count++;
-        $parenth = "";
-    }
-
-    $paramcount = $#{$args{'parameterlist'}}; # -1 is empty
-    if ($paramcount >= 0) {
-    	print ".SH ARGUMENTS\n";
-	}
-    foreach $parameter (@{$args{'parameterlist'}}) {
-        my $parameter_name = $parameter;
-        $parameter_name =~ s/\[.*//;
-
-        print ".IP \"" . $parameter . "\" 12\n";
-        output_highlight($args{'parameterdescs'}{$parameter_name});
-    }
-    foreach $section (@{$args{'sectionlist'}}) {
-        print ".SH \"", uc $section, "\"\n";
-        output_highlight($args{'sections'}{$section});
-    }
-}
-
-##
-# output enum in man
-sub output_enum_man(%) {
-    my %args = %{$_[0]};
-    my ($parameter, $section);
-    my $count;
-
-    print ".TH \"$args{'module'}\" 9 \"enum $args{'enum'}\" \"$man_date\" \"API Manual\" LINUX\n";
-
-    print ".SH NAME\n";
-    print "enum " . $args{'enum'} . " \\- " . $args{'purpose'} . "\n";
-
-    print ".SH SYNOPSIS\n";
-    print "enum " . $args{'enum'} . " {\n";
-    $count = 0;
-    foreach my $parameter (@{$args{'parameterlist'}}) {
-        print ".br\n.BI \"    $parameter\"\n";
-        if ($count == $#{$args{'parameterlist'}}) {
-            print "\n};\n";
-            last;
-        } else {
-            print ", \n.br\n";
-        }
-        $count++;
-    }
-
-    print ".SH Constants\n";
-    foreach $parameter (@{$args{'parameterlist'}}) {
-        my $parameter_name = $parameter;
-        $parameter_name =~ s/\[.*//;
-
-        print ".IP \"" . $parameter . "\" 12\n";
-        output_highlight($args{'parameterdescs'}{$parameter_name});
-    }
-    foreach $section (@{$args{'sectionlist'}}) {
-        print ".SH \"$section\"\n";
-        output_highlight($args{'sections'}{$section});
-    }
-}
-
-##
-# output struct in man
-sub output_struct_man(%) {
-    my %args = %{$_[0]};
-    my ($parameter, $section);
-
-    print ".TH \"$args{'module'}\" 9 \"" . $args{'type'} . " " . $args{'struct'} . "\" \"$man_date\" \"API Manual\" LINUX\n";
-
-    print ".SH NAME\n";
-    print $args{'type'} . " " . $args{'struct'} . " \\- " . $args{'purpose'} . "\n";
-
-    my $declaration = $args{'definition'};
-    $declaration =~ s/\t/  /g;
-    $declaration =~ s/\n/"\n.br\n.BI \"/g;
-    print ".SH SYNOPSIS\n";
-    print $args{'type'} . " " . $args{'struct'} . " {\n.br\n";
-    print ".BI \"$declaration\n};\n.br\n\n";
-
-    print ".SH Members\n";
-    foreach $parameter (@{$args{'parameterlist'}}) {
-        ($parameter =~ /^#/) && next;
-
-        my $parameter_name = $parameter;
-        $parameter_name =~ s/\[.*//;
-
-        ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
-        print ".IP \"" . $parameter . "\" 12\n";
-        output_highlight($args{'parameterdescs'}{$parameter_name});
-    }
-    foreach $section (@{$args{'sectionlist'}}) {
-        print ".SH \"$section\"\n";
-        output_highlight($args{'sections'}{$section});
-    }
-}
-
-##
-# output typedef in man
-sub output_typedef_man(%) {
-    my %args = %{$_[0]};
-    my ($parameter, $section);
-
-    print ".TH \"$args{'module'}\" 9 \"$args{'typedef'}\" \"$man_date\" \"API Manual\" LINUX\n";
-
-    print ".SH NAME\n";
-    print "typedef " . $args{'typedef'} . " \\- " . $args{'purpose'} . "\n";
-
-    foreach $section (@{$args{'sectionlist'}}) {
-        print ".SH \"$section\"\n";
-        output_highlight($args{'sections'}{$section});
-    }
-}
-
-sub output_blockhead_man(%) {
-    my %args = %{$_[0]};
-    my ($parameter, $section);
-    my $count;
-
-    print ".TH \"$args{'module'}\" 9 \"$args{'module'}\" \"$man_date\" \"API Manual\" LINUX\n";
-
-    foreach $section (@{$args{'sectionlist'}}) {
-        print ".SH \"$section\"\n";
-        output_highlight($args{'sections'}{$section});
-    }
-}
-
-##
-# output in restructured text
-#
-
-#
-# This could use some work; it's used to output the DOC: sections, and
-# starts by putting out the name of the doc section itself, but that tends
-# to duplicate a header already in the template file.
-#
-sub output_blockhead_rst(%) {
-    my %args = %{$_[0]};
-    my ($parameter, $section);
-
-    foreach $section (@{$args{'sectionlist'}}) {
-        next if (defined($nosymbol_table{$section}));
-
-        if ($output_selection != OUTPUT_INCLUDE) {
-            print ".. _$section:\n\n";
-            print "**$section**\n\n";
-        }
-        print_lineno($section_start_lines{$section});
-        output_highlight_rst($args{'sections'}{$section});
-        print "\n";
-    }
-}
-
-#
-# Apply the RST highlights to a sub-block of text.
-#
-sub highlight_block($) {
-    # The dohighlight kludge requires the text be called $contents
-    my $contents = shift;
-    eval $dohighlight;
-    die $@ if $@;
-    return $contents;
-}
-
-#
-# Regexes used only here.
-#
-my $sphinx_literal = '^[^.].*::$';
-my $sphinx_cblock = '^\.\.\ +code-block::';
-
-sub output_highlight_rst {
-    my $input = join "\n",@_;
-    my $output = "";
-    my $line;
-    my $in_literal = 0;
-    my $litprefix;
-    my $block = "";
-
-    foreach $line (split "\n",$input) {
-        #
-        # If we're in a literal block, see if we should drop out
-        # of it.  Otherwise pass the line straight through unmunged.
-        #
-        if ($in_literal) {
-            if (! ($line =~ /^\s*$/)) {
-                #
-                # If this is the first non-blank line in a literal
-                # block we need to figure out what the proper indent is.
-                #
-                if ($litprefix eq "") {
-                    $line =~ /^(\s*)/;
-                    $litprefix = '^' . $1;
-                    $output .= $line . "\n";
-                } elsif (! ($line =~ /$litprefix/)) {
-                    $in_literal = 0;
-                } else {
-                    $output .= $line . "\n";
-                }
-            } else {
-                $output .= $line . "\n";
-            }
-        }
-        #
-        # Not in a literal block (or just dropped out)
-        #
-        if (! $in_literal) {
-            $block .= $line . "\n";
-            if (($line =~ /$sphinx_literal/) || ($line =~ /$sphinx_cblock/)) {
-                $in_literal = 1;
-                $litprefix = "";
-                $output .= highlight_block($block);
-                $block = ""
-            }
-        }
-    }
-
-    if ($block) {
-        $output .= highlight_block($block);
-    }
-
-    $output =~ s/^\n+//g;
-    $output =~ s/\n+$//g;
-
-    foreach $line (split "\n", $output) {
-        print $lineprefix . $line . "\n";
-    }
-}
-
-sub output_function_rst(%) {
-    my %args = %{$_[0]};
-    my ($parameter, $section);
-    my $oldprefix = $lineprefix;
-
-    my $signature = "";
-    my $func_macro = $args{'func_macro'};
-    my $paramcount = $#{$args{'parameterlist'}}; # -1 is empty
-
-	if ($func_macro) {
-        $signature = $args{'function'};
-	} else {
-		if ($args{'functiontype'}) {
-        	$signature = $args{'functiontype'} . " ";
-		}
-		$signature .= $args{'function'} . " (";
-    }
-
-    my $count = 0;
-    foreach my $parameter (@{$args{'parameterlist'}}) {
-        if ($count ne 0) {
-            $signature .= ", ";
-        }
-        $count++;
-        $type = $args{'parametertypes'}{$parameter};
-
-        if ($type =~ m/$function_pointer/) {
-            # pointer-to-function
-            $signature .= $1 . $parameter . ") (" . $2 . ")";
-        } else {
-            $signature .= $type;
-        }
-    }
-
-    if (!$func_macro) {
-    	$signature .= ")";
-    }
-
-    if ($args{'typedef'} || $args{'functiontype'} eq "") {
-        print ".. c:macro:: ". $args{'function'} . "\n\n";
-
-        if ($args{'typedef'}) {
-            print_lineno($declaration_start_line);
-            print "   **Typedef**: ";
-            $lineprefix = "";
-            output_highlight_rst($args{'purpose'});
-            print "\n\n**Syntax**\n\n";
-            print "  ``$signature``\n\n";
-        } else {
-            print "``$signature``\n\n";
-        }
-    } else {
-        print ".. c:function:: $signature\n\n";
-    }
-
-    if (!$args{'typedef'}) {
-        print_lineno($declaration_start_line);
-        $lineprefix = "   ";
-        output_highlight_rst($args{'purpose'});
-        print "\n";
-    }
-
-    #
-    # Put our descriptive text into a container (thus an HTML <div>) to help
-    # set the function prototypes apart.
-    #
-    $lineprefix = "  ";
-	if ($paramcount >= 0) {
-    	print ".. container:: kernelindent\n\n";
-   		print $lineprefix . "**Parameters**\n\n";
-    }
-    foreach $parameter (@{$args{'parameterlist'}}) {
-        my $parameter_name = $parameter;
-        $parameter_name =~ s/\[.*//;
-        $type = $args{'parametertypes'}{$parameter};
-
-        if ($type ne "") {
-            print $lineprefix . "``$type``\n";
-        } else {
-            print $lineprefix . "``$parameter``\n";
-        }
-
-        print_lineno($parameterdesc_start_lines{$parameter_name});
-
-        $lineprefix = "    ";
-        if (defined($args{'parameterdescs'}{$parameter_name}) &&
-            $args{'parameterdescs'}{$parameter_name} ne $undescribed) {
-            output_highlight_rst($args{'parameterdescs'}{$parameter_name});
-        } else {
-            print $lineprefix . "*undescribed*\n";
-        }
-        $lineprefix = "  ";
-        print "\n";
-    }
-
-    output_section_rst(@_);
-    $lineprefix = $oldprefix;
-}
-
-sub output_section_rst(%) {
-    my %args = %{$_[0]};
-    my $section;
-    my $oldprefix = $lineprefix;
-
-    foreach $section (@{$args{'sectionlist'}}) {
-        print $lineprefix . "**$section**\n\n";
-        print_lineno($section_start_lines{$section});
-        output_highlight_rst($args{'sections'}{$section});
-        print "\n";
-    }
-    print "\n";
-}
-
-sub output_enum_rst(%) {
-    my %args = %{$_[0]};
-    my ($parameter);
-    my $oldprefix = $lineprefix;
-    my $count;
-    my $outer;
-
-    my $name = $args{'enum'};
-    print "\n\n.. c:enum:: " . $name . "\n\n";
-
-    print_lineno($declaration_start_line);
-    $lineprefix = "  ";
-    output_highlight_rst($args{'purpose'});
-    print "\n";
-
-    print ".. container:: kernelindent\n\n";
-    $outer = $lineprefix . "  ";
-    $lineprefix = $outer . "  ";
-    print $outer . "**Constants**\n\n";
-    foreach $parameter (@{$args{'parameterlist'}}) {
-        print $outer . "``$parameter``\n";
-
-        if ($args{'parameterdescs'}{$parameter} ne $undescribed) {
-            output_highlight_rst($args{'parameterdescs'}{$parameter});
-        } else {
-            print $lineprefix . "*undescribed*\n";
-        }
-        print "\n";
-    }
-    print "\n";
-    $lineprefix = $oldprefix;
-    output_section_rst(@_);
-}
-
-sub output_typedef_rst(%) {
-    my %args = %{$_[0]};
-    my ($parameter);
-    my $oldprefix = $lineprefix;
-    my $name;
-
-    $name = $args{'typedef'};
-
-    print "\n\n.. c:type:: " . $name . "\n\n";
-    print_lineno($declaration_start_line);
-    $lineprefix = "   ";
-    output_highlight_rst($args{'purpose'});
-    print "\n";
-
-    $lineprefix = $oldprefix;
-    output_section_rst(@_);
-}
-
-sub output_struct_rst(%) {
-    my %args = %{$_[0]};
-    my ($parameter);
-    my $oldprefix = $lineprefix;
-
-    my $name = $args{'struct'};
-    if ($args{'type'} eq 'union') {
-        print "\n\n.. c:union:: " . $name . "\n\n";
-    } else {
-        print "\n\n.. c:struct:: " . $name . "\n\n";
-    }
-
-    print_lineno($declaration_start_line);
-    $lineprefix = "  ";
-    output_highlight_rst($args{'purpose'});
-    print "\n";
-
-    print ".. container:: kernelindent\n\n";
-    print $lineprefix . "**Definition**::\n\n";
-    my $declaration = $args{'definition'};
-    $lineprefix = $lineprefix . "  ";
-    $declaration =~ s/\t/$lineprefix/g;
-    print $lineprefix . $args{'type'} . " " . $args{'struct'} . " {\n$declaration" . $lineprefix . "};\n\n";
-
-    $lineprefix = "  ";
-    print $lineprefix . "**Members**\n\n";
-    foreach $parameter (@{$args{'parameterlist'}}) {
-        ($parameter =~ /^#/) && next;
-
-        my $parameter_name = $parameter;
-        $parameter_name =~ s/\[.*//;
-
-        ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
-        $type = $args{'parametertypes'}{$parameter};
-        print_lineno($parameterdesc_start_lines{$parameter_name});
-        print $lineprefix . "``" . $parameter . "``\n";
-        $lineprefix = "    ";
-        output_highlight_rst($args{'parameterdescs'}{$parameter_name});
-        $lineprefix = "  ";
-        print "\n";
-    }
-    print "\n";
-
-    $lineprefix = $oldprefix;
-    output_section_rst(@_);
-}
-
-## none mode output functions
-
-sub output_function_none(%) {
-}
-
-sub output_enum_none(%) {
-}
-
-sub output_typedef_none(%) {
-}
-
-sub output_struct_none(%) {
-}
-
-sub output_blockhead_none(%) {
-}
-
-##
-# generic output function for all types (function, struct/union, typedef, enum);
-# calls the generated, variable output_ function name based on
-# functype and output_mode
-sub output_declaration {
-    no strict 'refs';
-    my $name = shift;
-    my $functype = shift;
-    my $func = "output_${functype}_$output_mode";
-
-    return if (defined($nosymbol_table{$name}));
-
-    if (($output_selection == OUTPUT_ALL) ||
-        (($output_selection == OUTPUT_INCLUDE ||
-          $output_selection == OUTPUT_EXPORTED) &&
-         defined($function_table{$name})) ||
-        ($output_selection == OUTPUT_INTERNAL &&
-         !($functype eq "function" && defined($function_table{$name}))))
-    {
-        &$func(@_);
-        $section_counter++;
-    }
-}
-
-##
-# generic output function - calls the right one based on current output mode.
-sub output_blockhead {
-    no strict 'refs';
-    my $func = "output_blockhead_" . $output_mode;
-    &$func(@_);
-    $section_counter++;
-}
-
-##
-# takes a declaration (struct, union, enum, typedef) and
-# invokes the right handler. NOT called for functions.
-sub dump_declaration($$) {
-    no strict 'refs';
-    my ($prototype, $file) = @_;
-    my $func = "dump_" . $decl_type;
-    &$func(@_);
-}
-
-sub dump_union($$) {
-    dump_struct(@_);
-}
-
-sub dump_struct($$) {
-    my $x = shift;
-    my $file = shift;
-    my $decl_type;
-    my $members;
-    my $type = qr{struct|union};
-    # For capturing struct/union definition body, i.e. "{members*}qualifiers*"
-    my $qualifiers = qr{$attribute|__packed|__aligned|____cacheline_aligned_in_smp|____cacheline_aligned};
-    my $definition_body = qr{\{(.*)\}\s*$qualifiers*};
-    my $struct_members = qr{($type)([^\{\};]+)\{([^\{\}]*)\}([^\{\}\;]*)\;};
-
-    if ($x =~ /($type)\s+(\w+)\s*$definition_body/) {
-        $decl_type = $1;
-        $declaration_name = $2;
-        $members = $3;
-    } elsif ($x =~ /typedef\s+($type)\s*$definition_body\s*(\w+)\s*;/) {
-        $decl_type = $1;
-        $declaration_name = $3;
-        $members = $2;
-    }
-
-    if ($members) {
-        if ($identifier ne $declaration_name) {
-            emit_warning("${file}:$.", "expecting prototype for $decl_type $identifier. Prototype was for $decl_type $declaration_name instead\n");
-            return;
-        }
-
-        # ignore members marked private:
-        $members =~ s/\/\*\s*private:.*?\/\*\s*public:.*?\*\///gosi;
-        $members =~ s/\/\*\s*private:.*//gosi;
-        # strip comments:
-        $members =~ s/\/\*.*?\*\///gos;
-        # strip attributes
-        $members =~ s/\s*$attribute/ /gi;
-        $members =~ s/\s*__aligned\s*\([^;]*\)/ /gos;
-        $members =~ s/\s*__counted_by\s*\([^;]*\)/ /gos;
-        $members =~ s/\s*__counted_by_(le|be)\s*\([^;]*\)/ /gos;
-        $members =~ s/\s*__packed\s*/ /gos;
-        $members =~ s/\s*CRYPTO_MINALIGN_ATTR/ /gos;
-        $members =~ s/\s*____cacheline_aligned_in_smp/ /gos;
-        $members =~ s/\s*____cacheline_aligned/ /gos;
-        # unwrap struct_group():
-        # - first eat non-declaration parameters and rewrite for final match
-        # - then remove macro, outer parens, and trailing semicolon
-        $members =~ s/\bstruct_group\s*\(([^,]*,)/STRUCT_GROUP(/gos;
-        $members =~ s/\bstruct_group_attr\s*\(([^,]*,){2}/STRUCT_GROUP(/gos;
-        $members =~ s/\bstruct_group_tagged\s*\(([^,]*),([^,]*),/struct $1 $2; STRUCT_GROUP(/gos;
-        $members =~ s/\b__struct_group\s*\(([^,]*,){3}/STRUCT_GROUP(/gos;
-        $members =~ s/\bSTRUCT_GROUP(\(((?:(?>[^)(]+)|(?1))*)\))[^;]*;/$2/gos;
-
-        my $args = qr{([^,)]+)};
-        # replace DECLARE_BITMAP
-        $members =~ s/__ETHTOOL_DECLARE_LINK_MODE_MASK\s*\(([^\)]+)\)/DECLARE_BITMAP($1, __ETHTOOL_LINK_MODE_MASK_NBITS)/gos;
-        $members =~ s/DECLARE_PHY_INTERFACE_MASK\s*\(([^\)]+)\)/DECLARE_BITMAP($1, PHY_INTERFACE_MODE_MAX)/gos;
-        $members =~ s/DECLARE_BITMAP\s*\($args,\s*$args\)/unsigned long $1\[BITS_TO_LONGS($2)\]/gos;
-        # replace DECLARE_HASHTABLE
-        $members =~ s/DECLARE_HASHTABLE\s*\($args,\s*$args\)/unsigned long $1\[1 << (($2) - 1)\]/gos;
-        # replace DECLARE_KFIFO
-        $members =~ s/DECLARE_KFIFO\s*\($args,\s*$args,\s*$args\)/$2 \*$1/gos;
-        # replace DECLARE_KFIFO_PTR
-        $members =~ s/DECLARE_KFIFO_PTR\s*\($args,\s*$args\)/$2 \*$1/gos;
-        # replace DECLARE_FLEX_ARRAY
-        $members =~ s/(?:__)?DECLARE_FLEX_ARRAY\s*\($args,\s*$args\)/$1 $2\[\]/gos;
-        #replace DEFINE_DMA_UNMAP_ADDR
-        $members =~ s/DEFINE_DMA_UNMAP_ADDR\s*\($args\)/dma_addr_t $1/gos;
-        #replace DEFINE_DMA_UNMAP_LEN
-        $members =~ s/DEFINE_DMA_UNMAP_LEN\s*\($args\)/__u32 $1/gos;
-        my $declaration = $members;
-
-        # Split nested struct/union elements as newer ones
-        while ($members =~ m/$struct_members/) {
-            my $newmember;
-            my $maintype = $1;
-            my $ids = $4;
-            my $content = $3;
-            foreach my $id(split /,/, $ids) {
-                $newmember .= "$maintype $id; ";
-
-                $id =~ s/[:\[].*//;
-                $id =~ s/^\s*\**(\S+)\s*/$1/;
-                foreach my $arg (split /;/, $content) {
-                    next if ($arg =~ m/^\s*$/);
-                    if ($arg =~ m/^([^\(]+\(\*?\s*)([\w\.]*)(\s*\).*)/) {
-                        # pointer-to-function
-                        my $type = $1;
-                        my $name = $2;
-                        my $extra = $3;
-                        next if (!$name);
-                        if ($id =~ m/^\s*$/) {
-                            # anonymous struct/union
-                            $newmember .= "$type$name$extra; ";
-                        } else {
-                            $newmember .= "$type$id.$name$extra; ";
-                        }
-                    } else {
-                        my $type;
-                        my $names;
-                        $arg =~ s/^\s+//;
-                        $arg =~ s/\s+$//;
-                        # Handle bitmaps
-                        $arg =~ s/:\s*\d+\s*//g;
-                        # Handle arrays
-                        $arg =~ s/\[.*\]//g;
-                        # The type may have multiple words,
-                        # and multiple IDs can be defined, like:
-                        #    const struct foo, *bar, foobar
-                        # So, we remove spaces when parsing the
-                        # names, in order to match just names
-                        # and commas for the names
-                        $arg =~ s/\s*,\s*/,/g;
-                        if ($arg =~ m/(.*)\s+([\S+,]+)/) {
-                            $type = $1;
-                            $names = $2;
-                        } else {
-                            $newmember .= "$arg; ";
-                            next;
-                        }
-                        foreach my $name (split /,/, $names) {
-                            $name =~ s/^\s*\**(\S+)\s*/$1/;
-                            next if (($name =~ m/^\s*$/));
-                            if ($id =~ m/^\s*$/) {
-                                # anonymous struct/union
-                                $newmember .= "$type $name; ";
-                            } else {
-                                $newmember .= "$type $id.$name; ";
-                            }
-                        }
-                    }
-                }
-            }
-            $members =~ s/$struct_members/$newmember/;
-        }
-
-        # Ignore other nested elements, like enums
-        $members =~ s/(\{[^\{\}]*\})//g;
-
-        create_parameterlist($members, ';', $file, $declaration_name);
-        check_sections($file, $declaration_name, $decl_type, $sectcheck, $struct_actual);
-
-        # Adjust declaration for better display
-        $declaration =~ s/([\{;])/$1\n/g;
-        $declaration =~ s/\}\s+;/};/g;
-        # Better handle inlined enums
-        do {} while ($declaration =~ s/(enum\s+\{[^\}]+),([^\n])/$1,\n$2/);
-
-        my @def_args = split /\n/, $declaration;
-        my $level = 1;
-        $declaration = "";
-        foreach my $clause (@def_args) {
-            $clause =~ s/^\s+//;
-            $clause =~ s/\s+$//;
-            $clause =~ s/\s+/ /;
-            next if (!$clause);
-            $level-- if ($clause =~ m/(\})/ && $level > 1);
-            if (!($clause =~ m/^\s*#/)) {
-                $declaration .= "\t" x $level;
-            }
-            $declaration .= "\t" . $clause . "\n";
-            $level++ if ($clause =~ m/(\{)/ && !($clause =~m/\}/));
-        }
-        output_declaration($declaration_name,
-                   'struct',
-                   {'struct' => $declaration_name,
-                    'module' => $modulename,
-                    'definition' => $declaration,
-                    'parameterlist' => \@parameterlist,
-                    'parameterdescs' => \%parameterdescs,
-                    'parametertypes' => \%parametertypes,
-                    'sectionlist' => \@sectionlist,
-                    'sections' => \%sections,
-                    'purpose' => $declaration_purpose,
-                    'type' => $decl_type
-                   });
-    } else {
-        print STDERR "${file}:$.: error: Cannot parse struct or union!\n";
-        ++$errors;
-    }
-}
-
-
-sub show_warnings($$) {
-    my $functype = shift;
-    my $name = shift;
-
-    return 0 if (defined($nosymbol_table{$name}));
-
-    return 1 if ($output_selection == OUTPUT_ALL);
-
-    if ($output_selection == OUTPUT_EXPORTED) {
-        if (defined($function_table{$name})) {
-            return 1;
-        } else {
-            return 0;
-        }
-    }
-    if ($output_selection == OUTPUT_INTERNAL) {
-        if (!($functype eq "function" && defined($function_table{$name}))) {
-            return 1;
-        } else {
-            return 0;
-        }
-    }
-    if ($output_selection == OUTPUT_INCLUDE) {
-        if (defined($function_table{$name})) {
-            return 1;
-        } else {
-            return 0;
-        }
-    }
-    die("Please add the new output type at show_warnings()");
-}
-
-sub dump_enum($$) {
-    my $x = shift;
-    my $file = shift;
-    my $members;
-
-    # ignore members marked private:
-    $x =~ s/\/\*\s*private:.*?\/\*\s*public:.*?\*\///gosi;
-    $x =~ s/\/\*\s*private:.*}/}/gosi;
-
-    $x =~ s@/\*.*?\*/@@gos;	# strip comments.
-    # strip #define macros inside enums
-    $x =~ s@#\s*((define|ifdef|if)\s+|endif)[^;]*;@@gos;
-
-    if ($x =~ /typedef\s+enum\s*\{(.*)\}\s*(\w*)\s*;/) {
-        $declaration_name = $2;
-        $members = $1;
-    } elsif ($x =~ /enum\s+(\w*)\s*\{(.*)\}/) {
-        $declaration_name = $1;
-        $members = $2;
-    }
-
-    if ($members) {
-        if ($identifier ne $declaration_name) {
-            if ($identifier eq "") {
-                emit_warning("${file}:$.", "wrong kernel-doc identifier on line:\n");
-            } else {
-                emit_warning("${file}:$.", "expecting prototype for enum $identifier. Prototype was for enum $declaration_name instead\n");
-            }
-            return;
-        }
-        $declaration_name = "(anonymous)" if ($declaration_name eq "");
-
-        my %_members;
-
-        $members =~ s/\s+$//;
-        $members =~ s/\([^;]*?[\)]//g;
-
-        foreach my $arg (split ',', $members) {
-            $arg =~ s/^\s*(\w+).*/$1/;
-            push @parameterlist, $arg;
-            if (!$parameterdescs{$arg}) {
-                $parameterdescs{$arg} = $undescribed;
-                if (show_warnings("enum", $declaration_name)) {
-                    emit_warning("${file}:$.", "Enum value '$arg' not described in enum '$declaration_name'\n");
-                }
-            }
-            $_members{$arg} = 1;
-        }
-
-        while (my ($k, $v) = each %parameterdescs) {
-            if (!exists($_members{$k})) {
-                if (show_warnings("enum", $declaration_name)) {
-                    emit_warning("${file}:$.", "Excess enum value '$k' description in '$declaration_name'\n");
-                }
-            }
-        }
-
-        output_declaration($declaration_name,
-                           'enum',
-                           {'enum' => $declaration_name,
-                            'module' => $modulename,
-                            'parameterlist' => \@parameterlist,
-                            'parameterdescs' => \%parameterdescs,
-                            'sectionlist' => \@sectionlist,
-                            'sections' => \%sections,
-                            'purpose' => $declaration_purpose
-                           });
-    } else {
-        print STDERR "${file}:$.: error: Cannot parse enum!\n";
-        ++$errors;
-    }
-}
-
-my $typedef_type = qr { ((?:\s+[\w\*]+\b){0,7}\s+(?:\w+\b|\*+))\s* }x;
-my $typedef_ident = qr { \*?\s*(\w\S+)\s* }x;
-my $typedef_args = qr { \s*\((.*)\); }x;
-
-my $typedef1 = qr { typedef$typedef_type\($typedef_ident\)$typedef_args }x;
-my $typedef2 = qr { typedef$typedef_type$typedef_ident$typedef_args }x;
-
-sub dump_typedef($$) {
-    my $x = shift;
-    my $file = shift;
-
-    $x =~ s@/\*.*?\*/@@gos;	# strip comments.
-
-    # Parse function typedef prototypes
-    if ($x =~ $typedef1 || $x =~ $typedef2) {
-        $return_type = $1;
-        $declaration_name = $2;
-        my $args = $3;
-        $return_type =~ s/^\s+//;
-
-        if ($identifier ne $declaration_name) {
-            emit_warning("${file}:$.", "expecting prototype for typedef $identifier. Prototype was for typedef $declaration_name instead\n");
-            return;
-        }
-
-        create_parameterlist($args, ',', $file, $declaration_name);
-
-        output_declaration($declaration_name,
-                           'function',
-                           {'function' => $declaration_name,
-                            'typedef' => 1,
-                            'module' => $modulename,
-                            'functiontype' => $return_type,
-                            'parameterlist' => \@parameterlist,
-                            'parameterdescs' => \%parameterdescs,
-                            'parametertypes' => \%parametertypes,
-                            'sectionlist' => \@sectionlist,
-                            'sections' => \%sections,
-                            'purpose' => $declaration_purpose
-                           });
-        return;
-    }
-
-    while (($x =~ /\(*.\)\s*;$/) || ($x =~ /\[*.\]\s*;$/)) {
-        $x =~ s/\(*.\)\s*;$/;/;
-        $x =~ s/\[*.\]\s*;$/;/;
-    }
-
-    if ($x =~ /typedef.*\s+(\w+)\s*;/) {
-        $declaration_name = $1;
-
-        if ($identifier ne $declaration_name) {
-            emit_warning("${file}:$.", "expecting prototype for typedef $identifier. Prototype was for typedef $declaration_name instead\n");
-            return;
-        }
-
-        output_declaration($declaration_name,
-                           'typedef',
-                           {'typedef' => $declaration_name,
-                            'module' => $modulename,
-                            'sectionlist' => \@sectionlist,
-                            'sections' => \%sections,
-                            'purpose' => $declaration_purpose
-                           });
-    } else {
-        print STDERR "${file}:$.: error: Cannot parse typedef!\n";
-        ++$errors;
-    }
-}
-
-sub save_struct_actual($) {
-    my $actual = shift;
-
-    # strip all spaces from the actual param so that it looks like one string item
-    $actual =~ s/\s*//g;
-    $struct_actual = $struct_actual . $actual . " ";
-}
-
-sub create_parameterlist($$$$) {
-    my $args = shift;
-    my $splitter = shift;
-    my $file = shift;
-    my $declaration_name = shift;
-    my $type;
-    my $param;
-
-    # temporarily replace commas inside function pointer definition
-    my $arg_expr = qr{\([^\),]+};
-    while ($args =~ /$arg_expr,/) {
-        $args =~ s/($arg_expr),/$1#/g;
-    }
-
-    foreach my $arg (split($splitter, $args)) {
-        # strip comments
-        $arg =~ s/\/\*.*\*\///;
-        # ignore argument attributes
-        $arg =~ s/\sPOS0?\s/ /;
-        # strip leading/trailing spaces
-        $arg =~ s/^\s*//;
-        $arg =~ s/\s*$//;
-        $arg =~ s/\s+/ /;
-
-        if ($arg =~ /^#/) {
-            # Treat preprocessor directive as a typeless variable just to fill
-            # corresponding data structures "correctly". Catch it later in
-            # output_* subs.
-            push_parameter($arg, "", "", $file);
-        } elsif ($arg =~ m/\(.+\)\s*\(/) {
-            # pointer-to-function
-            $arg =~ tr/#/,/;
-            $arg =~ m/[^\(]+\(\*?\s*([\w\[\]\.]*)\s*\)/;
-            $param = $1;
-            $type = $arg;
-            $type =~ s/([^\(]+\(\*?)\s*$param/$1/;
-            save_struct_actual($param);
-            push_parameter($param, $type, $arg, $file, $declaration_name);
-        } elsif ($arg =~ m/\(.+\)\s*\[/) {
-            # array-of-pointers
-            $arg =~ tr/#/,/;
-            $arg =~ m/[^\(]+\(\s*\*\s*([\w\[\]\.]*?)\s*(\s*\[\s*[\w]+\s*\]\s*)*\)/;
-            $param = $1;
-            $type = $arg;
-            $type =~ s/([^\(]+\(\*?)\s*$param/$1/;
-            save_struct_actual($param);
-            push_parameter($param, $type, $arg, $file, $declaration_name);
-        } elsif ($arg) {
-            $arg =~ s/\s*:\s*/:/g;
-            $arg =~ s/\s*\[/\[/g;
-
-            my @args = split('\s*,\s*', $arg);
-            if ($args[0] =~ m/\*/) {
-                $args[0] =~ s/(\*+)\s*/ $1/;
-            }
-
-            my @first_arg;
-            if ($args[0] =~ /^(.*\s+)(.*?\[.*\].*)$/) {
-                shift @args;
-                push(@first_arg, split('\s+', $1));
-                push(@first_arg, $2);
-            } else {
-                @first_arg = split('\s+', shift @args);
-            }
-
-            unshift(@args, pop @first_arg);
-            $type = join " ", @first_arg;
-
-            foreach $param (@args) {
-                if ($param =~ m/^(\*+)\s*(.*)/) {
-                    save_struct_actual($2);
-
-                    push_parameter($2, "$type $1", $arg, $file, $declaration_name);
-                } elsif ($param =~ m/(.*?):(\w+)/) {
-                    if ($type ne "") { # skip unnamed bit-fields
-                        save_struct_actual($1);
-                        push_parameter($1, "$type:$2", $arg, $file, $declaration_name)
-                    }
-                } else {
-                    save_struct_actual($param);
-                    push_parameter($param, $type, $arg, $file, $declaration_name);
-                }
-            }
-        }
-    }
-}
-
-sub push_parameter($$$$$) {
-    my $param = shift;
-    my $type = shift;
-    my $org_arg = shift;
-    my $file = shift;
-    my $declaration_name = shift;
-
-    if (($anon_struct_union == 1) && ($type eq "") &&
-        ($param eq "}")) {
-        return;        # ignore the ending }; from anon. struct/union
-    }
-
-    $anon_struct_union = 0;
-    $param =~ s/[\[\)].*//;
-
-    if ($type eq "" && $param =~ /\.\.\.$/)
-    {
-        if (!$param =~ /\w\.\.\.$/) {
-            # handles unnamed variable parameters
-            $param = "...";
-        } elsif ($param =~ /\w\.\.\.$/) {
-            # for named variable parameters of the form `x...`, remove the dots
-            $param =~ s/\.\.\.$//;
-        }
-        if (!defined $parameterdescs{$param} || $parameterdescs{$param} eq "") {
-            $parameterdescs{$param} = "variable arguments";
-        }
-    }
-    elsif ($type eq "" && ($param eq "" or $param eq "void"))
-    {
-        $param="void";
-        $parameterdescs{void} = "no arguments";
-    }
-    elsif ($type eq "" && ($param eq "struct" or $param eq "union"))
-    # handle unnamed (anonymous) union or struct:
-    {
-        $type = $param;
-        $param = "{unnamed_" . $param . "}";
-        $parameterdescs{$param} = "anonymous\n";
-        $anon_struct_union = 1;
-    }
-    elsif ($param =~ "__cacheline_group" )
-    # handle cache group enforcing variables: they do not need be described in header files
-    {
-        return; # ignore __cacheline_group_begin and __cacheline_group_end
-    }
-
-    # warn if parameter has no description
-    # (but ignore ones starting with # as these are not parameters
-    # but inline preprocessor statements);
-    # Note: It will also ignore void params and unnamed structs/unions
-    if (!defined $parameterdescs{$param} && $param !~ /^#/) {
-        $parameterdescs{$param} = $undescribed;
-
-        if (show_warnings($type, $declaration_name) && $param !~ /\./) {
-            emit_warning("${file}:$.", "Function parameter or struct member '$param' not described in '$declaration_name'\n");
-        }
-    }
-
-    # strip spaces from $param so that it is one continuous string
-    # on @parameterlist;
-    # this fixes a problem where check_sections() cannot find
-    # a parameter like "addr[6 + 2]" because it actually appears
-    # as "addr[6", "+", "2]" on the parameter list;
-    # but it's better to maintain the param string unchanged for output,
-    # so just weaken the string compare in check_sections() to ignore
-    # "[blah" in a parameter string;
-    ###$param =~ s/\s*//g;
-    push @parameterlist, $param;
-    $org_arg =~ s/\s\s+/ /g;
-    $parametertypes{$param} = $org_arg;
-}
-
-sub check_sections($$$$$) {
-    my ($file, $decl_name, $decl_type, $sectcheck, $prmscheck) = @_;
-    my @sects = split ' ', $sectcheck;
-    my @prms = split ' ', $prmscheck;
-    my $err;
-    my ($px, $sx);
-    my $prm_clean;        # strip trailing "[array size]" and/or beginning "*"
-
-    foreach $sx (0 .. $#sects) {
-        $err = 1;
-        foreach $px (0 .. $#prms) {
-            $prm_clean = $prms[$px];
-            $prm_clean =~ s/\[.*\]//;
-            $prm_clean =~ s/$attribute//i;
-            # ignore array size in a parameter string;
-            # however, the original param string may contain
-            # spaces, e.g.:  addr[6 + 2]
-            # and this appears in @prms as "addr[6" since the
-            # parameter list is split at spaces;
-            # hence just ignore "[..." for the sections check;
-            $prm_clean =~ s/\[.*//;
-
-            ##$prm_clean =~ s/^\**//;
-            if ($prm_clean eq $sects[$sx]) {
-                $err = 0;
-                last;
-            }
-        }
-        if ($err) {
-            if ($decl_type eq "function") {
-                emit_warning("${file}:$.",
-                    "Excess function parameter " .
-                    "'$sects[$sx]' " .
-                    "description in '$decl_name'\n");
-            } elsif (($decl_type eq "struct") or
-                          ($decl_type eq "union")) {
-                emit_warning("${file}:$.",
-                    "Excess $decl_type member " .
-                    "'$sects[$sx]' " .
-                    "description in '$decl_name'\n");
-            }
-        }
-    }
-}
-
-##
-# Checks the section describing the return value of a function.
-sub check_return_section {
-    my $file = shift;
-    my $declaration_name = shift;
-    my $return_type = shift;
-
-    # Ignore an empty return type (It's a macro)
-    # Ignore functions with a "void" return type. (But don't ignore "void *")
-    if (($return_type eq "") || ($return_type =~ /void\s*\w*\s*$/)) {
-        return;
-    }
-
-    if (!defined($sections{$section_return}) ||
-        $sections{$section_return} eq "")
-    {
-        emit_warning("${file}:$.",
-                     "No description found for return value of " .
-                     "'$declaration_name'\n");
-    }
-}
-
-##
-# takes a function prototype and the name of the current file being
-# processed and spits out all the details stored in the global
-# arrays/hashes.
-sub dump_function($$) {
-    my $prototype = shift;
-    my $file = shift;
-    my $func_macro = 0;
-
-    print_lineno($new_start_line);
-
-    $prototype =~ s/^static +//;
-    $prototype =~ s/^extern +//;
-    $prototype =~ s/^asmlinkage +//;
-    $prototype =~ s/^inline +//;
-    $prototype =~ s/^__inline__ +//;
-    $prototype =~ s/^__inline +//;
-    $prototype =~ s/^__always_inline +//;
-    $prototype =~ s/^noinline +//;
-    $prototype =~ s/^__FORTIFY_INLINE +//;
-    $prototype =~ s/__init +//;
-    $prototype =~ s/__init_or_module +//;
-    $prototype =~ s/__deprecated +//;
-    $prototype =~ s/__flatten +//;
-    $prototype =~ s/__meminit +//;
-    $prototype =~ s/__must_check +//;
-    $prototype =~ s/__weak +//;
-    $prototype =~ s/__sched +//;
-    $prototype =~ s/_noprof//;
-    $prototype =~ s/__printf\s*\(\s*\d*\s*,\s*\d*\s*\) +//;
-    $prototype =~ s/__(?:re)?alloc_size\s*\(\s*\d+\s*(?:,\s*\d+\s*)?\) +//;
-    $prototype =~ s/__diagnose_as\s*\(\s*\S+\s*(?:,\s*\d+\s*)*\) +//;
-    $prototype =~ s/DECL_BUCKET_PARAMS\s*\(\s*(\S+)\s*,\s*(\S+)\s*\)/$1, $2/;
-    my $define = $prototype =~ s/^#\s*define\s+//; #ak added
-    $prototype =~ s/__attribute_const__ +//;
-    $prototype =~ s/__attribute__\s*\(\(
-            (?:
-                 [\w\s]++          # attribute name
-                 (?:\([^)]*+\))?   # attribute arguments
-                 \s*+,?            # optional comma at the end
-            )+
-          \)\)\s+//x;
-
-    # Yes, this truly is vile.  We are looking for:
-    # 1. Return type (may be nothing if we're looking at a macro)
-    # 2. Function name
-    # 3. Function parameters.
-    #
-    # All the while we have to watch out for function pointer parameters
-    # (which IIRC is what the two sections are for), C types (these
-    # regexps don't even start to express all the possibilities), and
-    # so on.
-    #
-    # If you mess with these regexps, it's a good idea to check that
-    # the following functions' documentation still comes out right:
-    # - parport_register_device (function pointer parameters)
-    # - atomic_set (macro)
-    # - pci_match_device, __copy_to_user (long return type)
-    my $name = qr{[a-zA-Z0-9_~:]+};
-    my $prototype_end1 = qr{[^\(]*};
-    my $prototype_end2 = qr{[^\{]*};
-    my $prototype_end = qr{\(($prototype_end1|$prototype_end2)\)};
-    my $type1 = qr{[\w\s]+};
-    my $type2 = qr{$type1\*+};
-
-    if ($define && $prototype =~ m/^()($name)\s+/) {
-        # This is an object-like macro, it has no return type and no parameter
-        # list.
-        # Function-like macros are not allowed to have spaces between
-        # declaration_name and opening parenthesis (notice the \s+).
-        $return_type = $1;
-        $declaration_name = $2;
-        $func_macro = 1;
-    } elsif ($prototype =~ m/^()($name)\s*$prototype_end/ ||
-        $prototype =~ m/^($type1)\s+($name)\s*$prototype_end/ ||
-        $prototype =~ m/^($type2+)\s*($name)\s*$prototype_end/)  {
-        $return_type = $1;
-        $declaration_name = $2;
-        my $args = $3;
-
-        create_parameterlist($args, ',', $file, $declaration_name);
-    } else {
-        emit_warning("${file}:$.", "cannot understand function prototype: '$prototype'\n");
-        return;
-    }
-
-    if ($identifier ne $declaration_name) {
-        emit_warning("${file}:$.", "expecting prototype for $identifier(). Prototype was for $declaration_name() instead\n");
-        return;
-    }
-
-    my $prms = join " ", @parameterlist;
-    check_sections($file, $declaration_name, "function", $sectcheck, $prms);
-
-    # This check emits a lot of warnings at the moment, because many
-    # functions don't have a 'Return' doc section. So until the number
-    # of warnings goes sufficiently down, the check is only performed in
-    # -Wreturn mode.
-    # TODO: always perform the check.
-    if ($Wreturn && !$func_macro) {
-        check_return_section($file, $declaration_name, $return_type);
-    }
-
-    # The function parser can be called with a typedef parameter.
-    # Handle it.
-    if ($return_type =~ /typedef/) {
-        output_declaration($declaration_name,
-                           'function',
-                           {'function' => $declaration_name,
-                            'typedef' => 1,
-                            'module' => $modulename,
-                            'functiontype' => $return_type,
-                            'parameterlist' => \@parameterlist,
-                            'parameterdescs' => \%parameterdescs,
-                            'parametertypes' => \%parametertypes,
-                            'sectionlist' => \@sectionlist,
-                            'sections' => \%sections,
-                            'purpose' => $declaration_purpose,
-							'func_macro' => $func_macro
-                           });
-    } else {
-        output_declaration($declaration_name,
-                           'function',
-                           {'function' => $declaration_name,
-                            'module' => $modulename,
-                            'functiontype' => $return_type,
-                            'parameterlist' => \@parameterlist,
-                            'parameterdescs' => \%parameterdescs,
-                            'parametertypes' => \%parametertypes,
-                            'sectionlist' => \@sectionlist,
-                            'sections' => \%sections,
-                            'purpose' => $declaration_purpose,
-							'func_macro' => $func_macro
-                           });
-    }
-}
-
-sub reset_state {
-    $function = "";
-    %parameterdescs = ();
-    %parametertypes = ();
-    @parameterlist = ();
-    %sections = ();
-    @sectionlist = ();
-    $sectcheck = "";
-    $struct_actual = "";
-    $prototype = "";
-
-    $state = STATE_NORMAL;
-    $inline_doc_state = STATE_INLINE_NA;
-}
-
-sub tracepoint_munge($) {
-    my $file = shift;
-    my $tracepointname = 0;
-    my $tracepointargs = 0;
-
-    if ($prototype =~ m/TRACE_EVENT\((.*?),/) {
-        $tracepointname = $1;
-    }
-    if ($prototype =~ m/DEFINE_SINGLE_EVENT\((.*?),/) {
-        $tracepointname = $1;
-    }
-    if ($prototype =~ m/DEFINE_EVENT\((.*?),(.*?),/) {
-        $tracepointname = $2;
-    }
-    $tracepointname =~ s/^\s+//; #strip leading whitespace
-    if ($prototype =~ m/TP_PROTO\((.*?)\)/) {
-        $tracepointargs = $1;
-    }
-    if (($tracepointname eq 0) || ($tracepointargs eq 0)) {
-        emit_warning("${file}:$.", "Unrecognized tracepoint format: \n".
-                 "$prototype\n");
-    } else {
-        $prototype = "static inline void trace_$tracepointname($tracepointargs)";
-        $identifier = "trace_$identifier";
-    }
-}
-
-sub syscall_munge() {
-    my $void = 0;
-
-    $prototype =~ s@[\r\n]+@ @gos; # strip newlines/CR's
-##    if ($prototype =~ m/SYSCALL_DEFINE0\s*\(\s*(a-zA-Z0-9_)*\s*\)/) {
-    if ($prototype =~ m/SYSCALL_DEFINE0/) {
-        $void = 1;
-##        $prototype = "long sys_$1(void)";
-    }
-
-    $prototype =~ s/SYSCALL_DEFINE.*\(/long sys_/; # fix return type & func name
-    if ($prototype =~ m/long (sys_.*?),/) {
-        $prototype =~ s/,/\(/;
-    } elsif ($void) {
-        $prototype =~ s/\)/\(void\)/;
-    }
-
-    # now delete all of the odd-number commas in $prototype
-    # so that arg types & arg names don't have a comma between them
-    my $count = 0;
-    my $len = length($prototype);
-    if ($void) {
-        $len = 0;    # skip the for-loop
-    }
-    for (my $ix = 0; $ix < $len; $ix++) {
-        if (substr($prototype, $ix, 1) eq ',') {
-            $count++;
-            if ($count % 2 == 1) {
-                substr($prototype, $ix, 1) = ' ';
-            }
-        }
-    }
-}
-
-sub process_proto_function($$) {
-    my $x = shift;
-    my $file = shift;
-
-    $x =~ s@\/\/.*$@@gos; # strip C99-style comments to end of line
-
-    if ($x =~ /^#/ && $x !~ /^#\s*define/) {
-        # do nothing
-    } elsif ($x =~ /([^\{]*)/) {
-        $prototype .= $1;
-    }
-
-    if (($x =~ /\{/) || ($x =~ /\#\s*define/) || ($x =~ /;/)) {
-        $prototype =~ s@/\*.*?\*/@@gos;        # strip comments.
-        $prototype =~ s@[\r\n]+@ @gos; # strip newlines/cr's.
-        $prototype =~ s@^\s+@@gos; # strip leading spaces
-
-        # Handle prototypes for function pointers like:
-        # int (*pcs_config)(struct foo)
-        $prototype =~ s@^(\S+\s+)\(\s*\*(\S+)\)@$1$2@gos;
-
-        if ($prototype =~ /SYSCALL_DEFINE/) {
-            syscall_munge();
-        }
-        if ($prototype =~ /TRACE_EVENT/ || $prototype =~ /DEFINE_EVENT/ ||
-            $prototype =~ /DEFINE_SINGLE_EVENT/)
-        {
-            tracepoint_munge($file);
-        }
-        dump_function($prototype, $file);
-        reset_state();
-    }
-}
-
-sub process_proto_type($$) {
-    my $x = shift;
-    my $file = shift;
-
-    $x =~ s@[\r\n]+@ @gos; # strip newlines/cr's.
-    $x =~ s@^\s+@@gos; # strip leading spaces
-    $x =~ s@\s+$@@gos; # strip trailing spaces
-    $x =~ s@\/\/.*$@@gos; # strip C99-style comments to end of line
-
-    if ($x =~ /^#/) {
-        # To distinguish preprocessor directive from regular declaration later.
-        $x .= ";";
-    }
-
-    while (1) {
-        if ( $x =~ /([^\{\};]*)([\{\};])(.*)/ ) {
-            if( length $prototype ) {
-                $prototype .= " "
-            }
-            $prototype .= $1 . $2;
-            ($2 eq '{') && $brcount++;
-            ($2 eq '}') && $brcount--;
-            if (($2 eq ';') && ($brcount == 0)) {
-                dump_declaration($prototype, $file);
-                reset_state();
-                last;
-            }
-            $x = $3;
-        } else {
-            $prototype .= $x;
-            last;
-        }
-    }
-}
-
-
-sub map_filename($) {
-    my $file;
-    my ($orig_file) = @_;
-
-    if (defined($ENV{'SRCTREE'})) {
-        $file = "$ENV{'SRCTREE'}" . "/" . $orig_file;
-    } else {
-        $file = $orig_file;
-    }
-
-    return $file;
-}
-
-sub process_export_file($) {
-    my ($orig_file) = @_;
-    my $file = map_filename($orig_file);
-
-    if (!open(IN,"<$file")) {
-        print STDERR "Error: Cannot open file $file\n";
-        ++$errors;
-        return;
-    }
-
-    while (<IN>) {
-        if (/$export_symbol/) {
-            next if (defined($nosymbol_table{$2}));
-            $function_table{$2} = 1;
-        }
-        if (/$export_symbol_ns/) {
-            next if (defined($nosymbol_table{$2}));
-            $function_table{$2} = 1;
-        }
-    }
-
-    close(IN);
-}
-
-#
-# Parsers for the various processing states.
-#
-# STATE_NORMAL: looking for the /** to begin everything.
-#
-sub process_normal() {
-    if (/$doc_start/o) {
-        $state = STATE_NAME;        # next line is always the function name
-        $declaration_start_line = $. + 1;
-    }
-}
-
-#
-# STATE_NAME: Looking for the "name - description" line
-#
-sub process_name($$) {
-    my $file = shift;
-    my $descr;
-
-    if (/$doc_block/o) {
-        $state = STATE_DOCBLOCK;
-        $contents = "";
-        $new_start_line = $.;
-
-        if ( $1 eq "" ) {
-            $section = $section_intro;
-        } else {
-            $section = $1;
-        }
-    } elsif (/$doc_decl/o) {
-        $identifier = $1;
-        my $is_kernel_comment = 0;
-        my $decl_start = qr{$doc_com};
-        # test for pointer declaration type, foo * bar() - desc
-        my $fn_type = qr{\w+\s*\*\s*};
-        my $parenthesis = qr{\(\w*\)};
-        my $decl_end = qr{[-:].*};
-        if (/^$decl_start([\w\s]+?)$parenthesis?\s*$decl_end?$/) {
-            $identifier = $1;
-        }
-        if ($identifier =~ m/^(struct|union|enum|typedef)\b\s*(\S*)/) {
-            $decl_type = $1;
-            $identifier = $2;
-            $is_kernel_comment = 1;
-        }
-        # Look for foo() or static void foo() - description; or misspelt
-        # identifier
-        elsif (/^$decl_start$fn_type?(\w+)\s*$parenthesis?\s*$decl_end?$/ ||
-            /^$decl_start$fn_type?(\w+[^-:]*)$parenthesis?\s*$decl_end$/) {
-            $identifier = $1;
-            $decl_type = 'function';
-            $identifier =~ s/^define\s+//;
-            $is_kernel_comment = 1;
-        }
-        $identifier =~ s/\s+$//;
-
-        $state = STATE_BODY;
-        # if there's no @param blocks need to set up default section
-        # here
-        $contents = "";
-        $section = $section_default;
-        $new_start_line = $. + 1;
-        if (/[-:](.*)/) {
-            # strip leading/trailing/multiple spaces
-            $descr= $1;
-            $descr =~ s/^\s*//;
-            $descr =~ s/\s*$//;
-            $descr =~ s/\s+/ /g;
-            $declaration_purpose = $descr;
-            $state = STATE_BODY_MAYBE;
-        } else {
-            $declaration_purpose = "";
-        }
-
-        if (!$is_kernel_comment) {
-            emit_warning("${file}:$.", "This comment starts with '/**', but isn't a kernel-doc comment. Refer Documentation/doc-guide/kernel-doc.rst\n$_");
-            $state = STATE_NORMAL;
-        }
-
-        if (($declaration_purpose eq "") && $Wshort_desc) {
-            emit_warning("${file}:$.", "missing initial short description on line:\n$_");
-        }
-
-        if ($identifier eq "" && $decl_type ne "enum") {
-            emit_warning("${file}:$.", "wrong kernel-doc identifier on line:\n$_");
-            $state = STATE_NORMAL;
-        }
-
-        if ($verbose) {
-            print STDERR "${file}:$.: info: Scanning doc for $decl_type $identifier\n";
-        }
-    } else {
-        emit_warning("${file}:$.", "Cannot understand $_ on line $. - I thought it was a doc line\n");
-        $state = STATE_NORMAL;
-    }
-}
-
-
-#
-# STATE_BODY and STATE_BODY_MAYBE: the bulk of a kerneldoc comment.
-#
-sub process_body($$) {
-    my $file = shift;
-
-    if ($state == STATE_BODY_WITH_BLANK_LINE && /^\s*\*\s?\S/) {
-        dump_section($file, $section, $contents);
-        $section = $section_default;
-        $new_start_line = $.;
-        $contents = "";
-    }
-
-    if (/$doc_sect/i) { # case insensitive for supported section names
-        $newsection = $1;
-        $newcontents = $2;
-
-        # map the supported section names to the canonical names
-        if ($newsection =~ m/^description$/i) {
-            $newsection = $section_default;
-        } elsif ($newsection =~ m/^context$/i) {
-            $newsection = $section_context;
-        } elsif ($newsection =~ m/^returns?$/i) {
-            $newsection = $section_return;
-        } elsif ($newsection =~ m/^\@return$/) {
-            # special: @return is a section, not a param description
-            $newsection = $section_return;
-        }
-
-        if (($contents ne "") && ($contents ne "\n")) {
-            dump_section($file, $section, $contents);
-            $section = $section_default;
-        }
-
-        $state = STATE_BODY;
-        $contents = $newcontents;
-        $new_start_line = $.;
-        while (substr($contents, 0, 1) eq " ") {
-            $contents = substr($contents, 1);
-        }
-        if ($contents ne "") {
-            $contents .= "\n";
-        }
-        $section = $newsection;
-        $leading_space = undef;
-    } elsif (/$doc_end/) {
-        if (($contents ne "") && ($contents ne "\n")) {
-            dump_section($file, $section, $contents);
-            $section = $section_default;
-            $contents = "";
-        }
-        # look for doc_com + <text> + doc_end:
-        if ($_ =~ m'\s*\*\s*[a-zA-Z_0-9:\.]+\*/') {
-            emit_warning("${file}:$.", "suspicious ending line: $_");
-        }
-
-        $prototype = "";
-        $state = STATE_PROTO;
-        $brcount = 0;
-        $new_start_line = $. + 1;
-    } elsif (/$doc_content/) {
-        if ($1 eq "") {
-            if ($section eq $section_context) {
-                dump_section($file, $section, $contents);
-                $section = $section_default;
-                $contents = "";
-                $new_start_line = $.;
-                $state = STATE_BODY;
-            } else {
-                if ($section ne $section_default) {
-                    $state = STATE_BODY_WITH_BLANK_LINE;
-                } else {
-                    $state = STATE_BODY;
-                }
-                $contents .= "\n";
-            }
-        } elsif ($state == STATE_BODY_MAYBE) {
-            # Continued declaration purpose
-            chomp($declaration_purpose);
-            $declaration_purpose .= " " . $1;
-            $declaration_purpose =~ s/\s+/ /g;
-        } else {
-            my $cont = $1;
-            if ($section =~ m/^@/ || $section eq $section_context) {
-                if (!defined $leading_space) {
-                    if ($cont =~ m/^(\s+)/) {
-                        $leading_space = $1;
-                    } else {
-                        $leading_space = "";
-                    }
-                }
-                $cont =~ s/^$leading_space//;
-            }
-            $contents .= $cont . "\n";
-        }
-    } else {
-        # i dont know - bad line?  ignore.
-        emit_warning("${file}:$.", "bad line: $_");
-    }
-}
-
-
-#
-# STATE_PROTO: reading a function/whatever prototype.
-#
-sub process_proto($$) {
-    my $file = shift;
-
-    if (/$doc_inline_oneline/) {
-        $section = $1;
-        $contents = $2;
-        if ($contents ne "") {
-            $contents .= "\n";
-            dump_section($file, $section, $contents);
-            $section = $section_default;
-            $contents = "";
-        }
-    } elsif (/$doc_inline_start/) {
-        $state = STATE_INLINE;
-        $inline_doc_state = STATE_INLINE_NAME;
-    } elsif ($decl_type eq 'function') {
-        process_proto_function($_, $file);
-    } else {
-        process_proto_type($_, $file);
-    }
-}
-
-#
-# STATE_DOCBLOCK: within a DOC: block.
-#
-sub process_docblock($$) {
-    my $file = shift;
-
-    if (/$doc_end/) {
-        dump_doc_section($file, $section, $contents);
-        $section = $section_default;
-        $contents = "";
-        $function = "";
-        %parameterdescs = ();
-        %parametertypes = ();
-        @parameterlist = ();
-        %sections = ();
-        @sectionlist = ();
-        $prototype = "";
-        $state = STATE_NORMAL;
-    } elsif (/$doc_content/) {
-        if ( $1 eq "" )        {
-            $contents .= $blankline;
-        } else {
-            $contents .= $1 . "\n";
-        }
-    }
-}
-
-#
-# STATE_INLINE: docbook comments within a prototype.
-#
-sub process_inline($$) {
-    my $file = shift;
-
-    # First line (state 1) needs to be a @parameter
-    if ($inline_doc_state == STATE_INLINE_NAME && /$doc_inline_sect/o) {
-        $section = $1;
-        $contents = $2;
-        $new_start_line = $.;
-        if ($contents ne "") {
-            while (substr($contents, 0, 1) eq " ") {
-                $contents = substr($contents, 1);
-            }
-            $contents .= "\n";
-        }
-        $inline_doc_state = STATE_INLINE_TEXT;
-        # Documentation block end */
-    } elsif (/$doc_inline_end/) {
-        if (($contents ne "") && ($contents ne "\n")) {
-            dump_section($file, $section, $contents);
-            $section = $section_default;
-            $contents = "";
-        }
-        $state = STATE_PROTO;
-        $inline_doc_state = STATE_INLINE_NA;
-        # Regular text
-    } elsif (/$doc_content/) {
-        if ($inline_doc_state == STATE_INLINE_TEXT) {
-            $contents .= $1 . "\n";
-            # nuke leading blank lines
-            if ($contents =~ /^\s*$/) {
-                $contents = "";
-            }
-        } elsif ($inline_doc_state == STATE_INLINE_NAME) {
-            $inline_doc_state = STATE_INLINE_ERROR;
-            emit_warning("${file}:$.", "Incorrect use of kernel-doc format: $_");
-        }
-    }
-}
-
-
-sub process_file($) {
-    my $file;
-    my ($orig_file) = @_;
-
-    $file = map_filename($orig_file);
-
-    if (!open(IN_FILE,"<$file")) {
-        print STDERR "Error: Cannot open file $file\n";
-        ++$errors;
-        return;
-    }
-
-    $. = 1;
-
-    $section_counter = 0;
-    while (<IN_FILE>) {
-        while (!/^ \*/ && s/\\\s*$//) {
-            $_ .= <IN_FILE>;
-        }
-        # Replace tabs by spaces
-        while ($_ =~ s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e) {};
-        # Hand this line to the appropriate state handler
-        if ($state == STATE_NORMAL) {
-            process_normal();
-        } elsif ($state == STATE_NAME) {
-            process_name($file, $_);
-        } elsif ($state == STATE_BODY || $state == STATE_BODY_MAYBE ||
-                 $state == STATE_BODY_WITH_BLANK_LINE) {
-            process_body($file, $_);
-        } elsif ($state == STATE_INLINE) { # scanning for inline parameters
-            process_inline($file, $_);
-        } elsif ($state == STATE_PROTO) {
-            process_proto($file, $_);
-        } elsif ($state == STATE_DOCBLOCK) {
-            process_docblock($file, $_);
-        }
-    }
-
-    # Make sure we got something interesting.
-    if (!$section_counter && $output_mode ne "none") {
-        if ($output_selection == OUTPUT_INCLUDE) {
-            emit_warning("${file}:1", "'$_' not found\n")
-                for keys %function_table;
-        } else {
-            emit_warning("${file}:1", "no structured comments found\n");
-        }
-    }
-    close IN_FILE;
-}
-
-$kernelversion = get_kernel_version();
-
-# generate a sequence of code that will splice in highlighting information
-# using the s// operator.
-for (my $k = 0; $k < @highlights; $k++) {
-    my $pattern = $highlights[$k][0];
-    my $result = $highlights[$k][1];
-#   print STDERR "scanning pattern:$pattern, highlight:($result)\n";
-    $dohighlight .=  "\$contents =~ s:$pattern:$result:gs;\n";
-}
-
-if ($output_selection == OUTPUT_EXPORTED ||
-    $output_selection == OUTPUT_INTERNAL) {
-
-    push(@export_file_list, @ARGV);
-
-    foreach (@export_file_list) {
-        chomp;
-        process_export_file($_);
-    }
-}
-
-foreach (@ARGV) {
-    chomp;
-    process_file($_);
-}
-if ($verbose && $errors) {
-    print STDERR "$errors errors\n";
-}
-if ($verbose && $warnings) {
-    print STDERR "$warnings warnings\n";
-}
-
-if ($Werror && $warnings) {
-    print STDERR "$warnings warnings as Errors\n";
-    exit($warnings);
-} else {
-    exit($output_mode eq "none" ? 0 : $errors)
-}
-
-__END__
-
-=head1 OPTIONS
-
-=head2 Output format selection (mutually exclusive):
-
-=over 8
-
-=item -man
-
-Output troff manual page format.
-
-=item -rst
-
-Output reStructuredText format. This is the default.
-
-=item -none
-
-Do not output documentation, only warnings.
-
-=back
-
-=head2 Output format modifiers
-
-=head3 reStructuredText only
-
-=head2 Output selection (mutually exclusive):
-
-=over 8
-
-=item -export
-
-Only output documentation for the symbols that have been exported using
-EXPORT_SYMBOL() and related macros in any input FILE or -export-file FILE.
-
-=item -internal
-
-Only output documentation for the symbols that have NOT been exported using
-EXPORT_SYMBOL() and related macros in any input FILE or -export-file FILE.
-
-=item -function NAME
-
-Only output documentation for the given function or DOC: section title.
-All other functions and DOC: sections are ignored.
-
-May be specified multiple times.
-
-=item -nosymbol NAME
-
-Exclude the specified symbol from the output documentation.
-
-May be specified multiple times.
-
-=back
-
-=head2 Output selection modifiers:
-
-=over 8
-
-=item -no-doc-sections
-
-Do not output DOC: sections.
-
-=item -export-file FILE
-
-Specify an additional FILE in which to look for EXPORT_SYMBOL information.
-
-To be used with -export or -internal.
-
-May be specified multiple times.
-
-=back
-
-=head3 reStructuredText only
-
-=over 8
-
-=item -enable-lineno
-
-Enable output of .. LINENO lines.
-
-=back
-
-=head2 Other parameters:
-
-=over 8
-
-=item -h, -help
-
-Print this help.
-
-=item -v
-
-Verbose output, more warnings and other information.
-
-=item -Werror
-
-Treat warnings as errors.
-
-=back
-
-=cut
-- 
2.51.0


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

* Re: [PATCH v3 0/8] Collect documentation-related tools under /tools/docs
  2025-10-24 20:08 [PATCH v3 0/8] Collect documentation-related tools under /tools/docs Jonathan Corbet
                   ` (7 preceding siblings ...)
  2025-10-24 20:08 ` [PATCH v3 8/8] docs: remove kernel-doc.pl Jonathan Corbet
@ 2025-10-25  2:33 ` Mauro Carvalho Chehab
  2025-10-25 15:14 ` Akira Yokosawa
  2025-10-26 21:44 ` Randy Dunlap
  10 siblings, 0 replies; 21+ messages in thread
From: Mauro Carvalho Chehab @ 2025-10-25  2:33 UTC (permalink / raw)
  To: Jonathan Corbet
  Cc: linux-doc, linux-kernel, Akira Yokosawa, Randy Dunlap,
	Jani Nikula

Em Fri, 24 Oct 2025 14:08:21 -0600
Jonathan Corbet <corbet@lwn.net> escreveu:

> Our documentation-related tools are spread out over various directories;
> several are buried in the scripts/ dumping ground.  That makes them harder
> to discover and harder to maintain.
> 
> Recent work has started accumulating our documentation-related tools in
> /tools/docs.  This series completes that task, moving the rest of our
> various utilities there, hopefully fixing up all of the relevant references
> in the process.
> 
> At the end, rather than move the old, Perl kernel-doc, I simply removed it.

LGTM.

For the entire series:

Reviewed-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>

> 
> The big elephant lurking in this small room is the home for Python modules;
> I left them under scripts/lib, but that is an even less appropriate place
> than it was before.  I would propose either tools/python or lib/python;
> thoughts on that matter welcome.

Agreed that it should be moved out of scripts/lib. Besides that,
I don't care much about its location. My personal preference would
be (with no particular order):

	- tools/python_lib
	- tools/lib_python
	- tools/lib_py
	- tools/lib

(lib/python works for me as well)

Or, if we don't aim to share code with docs and non-docs python
code, we can use:

	- tools/docs/lib

> 
> Changes in v3:
>   - Now with more caffeine! Properly based on docs-next.
> 
> Changes in v2:
>   - Rebase on top of all of Mauro's changes (the most painful rebase I've
>     ever done, I think).
>   - Land everything in /tools/docs/ rather than /tools/doc/
> 
> v2: https://lore.kernel.org/lkml/20251023161027.697135-1-corbet@lwn.net/
> v1: https://lore.kernel.org/lkml/20250813213218.198582-1-corbet@lwn.net/
> 
> 
> Jonathan Corbet (8):
>   docs: Move the "features" tools to tools/docs
>   docs: move checktransupdate.py to tools/docs
>   docs: move scripts/documentation-file-ref-check to tools/docs
>   docs: move get_abi.py to tools/docs
>   docs: move test_doc_build.py to tools/docs
>   docs: move kernel-doc to tools/docs
>   docs: move find-unused-docs.sh to tools/docs
>   docs: remove kernel-doc.pl
> 
>  Documentation/Kconfig                         |    2 +-
>  Documentation/Makefile                        |    6 +-
>  Documentation/conf.py                         |    2 +-
>  Documentation/doc-guide/checktransupdate.rst  |    6 +-
>  Documentation/doc-guide/contributing.rst      |    2 +-
>  Documentation/doc-guide/kernel-doc.rst        |    6 +-
>  Documentation/doc-guide/sphinx.rst            |    2 +-
>  Documentation/kbuild/kbuild.rst               |    2 +-
>  Documentation/process/coding-style.rst        |    2 +-
>  Documentation/sphinx/kernel_abi.py            |    2 +-
>  Documentation/sphinx/kernel_feat.py           |    4 +-
>  .../it_IT/doc-guide/kernel-doc.rst            |    8 +-
>  .../sp_SP/process/coding-style.rst            |    2 +-
>  .../zh_CN/doc-guide/checktransupdate.rst      |    6 +-
>  .../zh_CN/doc-guide/contributing.rst          |    2 +-
>  .../zh_CN/doc-guide/kernel-doc.rst            |   10 +-
>  Documentation/translations/zh_CN/how-to.rst   |    2 +-
>  .../translations/zh_CN/kbuild/kbuild.rst      |    2 +-
>  .../zh_CN/process/coding-style.rst            |    2 +-
>  .../zh_TW/process/coding-style.rst            |    2 +-
>  MAINTAINERS                                   |    5 -
>  Makefile                                      |    2 +-
>  drivers/gpu/drm/i915/Makefile                 |    2 +-
>  scripts/kernel-doc                            |    1 -
>  scripts/kernel-doc.pl                         | 2439 -----------------
>  {scripts => tools/docs}/checktransupdate.py   |    8 +-
>  .../docs}/documentation-file-ref-check        |    2 +-
>  .../docs}/features-refresh.sh                 |    0
>  {scripts => tools/docs}/find-unused-docs.sh   |    8 +-
>  {scripts => tools/docs}/get_abi.py            |    0
>  {scripts => tools/docs}/get_feat.pl           |    2 +-
>  .../kernel-doc.py => tools/docs/kernel-doc    |    0
>  .../features => tools/docs}/list-arch.sh      |    2 +-
>  tools/docs/sphinx-pre-install                 |    2 +-
>  {scripts => tools/docs}/test_doc_build.py     |    0
>  35 files changed, 50 insertions(+), 2495 deletions(-)
>  delete mode 120000 scripts/kernel-doc
>  delete mode 100755 scripts/kernel-doc.pl
>  rename {scripts => tools/docs}/checktransupdate.py (97%)
>  rename {scripts => tools/docs}/documentation-file-ref-check (99%)
>  rename {Documentation/features/scripts => tools/docs}/features-refresh.sh (100%)
>  rename {scripts => tools/docs}/find-unused-docs.sh (79%)
>  rename {scripts => tools/docs}/get_abi.py (100%)
>  rename {scripts => tools/docs}/get_feat.pl (99%)
>  rename scripts/kernel-doc.py => tools/docs/kernel-doc (100%)
>  rename {Documentation/features => tools/docs}/list-arch.sh (83%)
>  rename {scripts => tools/docs}/test_doc_build.py (100%)
> 

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

* Re: [PATCH v3 6/8] docs: move kernel-doc to tools/docs
  2025-10-24 20:08 ` [PATCH v3 6/8] docs: move kernel-doc " Jonathan Corbet
@ 2025-10-25  7:14   ` kernel test robot
  0 siblings, 0 replies; 21+ messages in thread
From: kernel test robot @ 2025-10-25  7:14 UTC (permalink / raw)
  To: Jonathan Corbet, linux-doc
  Cc: oe-kbuild-all, linux-kernel, Mauro Carvalho Chehab, linux-media,
	Akira Yokosawa, Randy Dunlap, Jani Nikula, Jonathan Corbet

Hi Jonathan,

kernel test robot noticed the following build errors:

[auto build test ERROR on lwn/docs-next]
[also build test ERROR on next-20251024]
[cannot apply to drm-i915/for-linux-next drm-i915/for-linux-next-fixes linus/master v6.18-rc2]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Jonathan-Corbet/docs-Move-the-features-tools-to-tools-docs/20251025-041303
base:   git://git.lwn.net/linux.git docs-next
patch link:    https://lore.kernel.org/r/20251024200834.20644-7-corbet%40lwn.net
patch subject: [PATCH v3 6/8] docs: move kernel-doc to tools/docs
config: parisc-randconfig-r071-20251025 (https://download.01.org/0day-ci/archive/20251025/202510251428.mk24iI0r-lkp@intel.com/config)
compiler: hppa-linux-gcc (GCC) 11.5.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251025/202510251428.mk24iI0r-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202510251428.mk24iI0r-lkp@intel.com/

All errors (new ones prefixed by >>):

>> /bin/sh: 1: tools/docs/kernel-doc.py: not found
   make[3]: *** [scripts/Makefile.build:287: scripts/mod/empty.o] Error 127
   make[3]: *** Deleting file 'scripts/mod/empty.o'
   make[3]: Target 'scripts/mod/' not remade because of errors.
   make[2]: *** [Makefile:1279: prepare0] Error 2
   make[2]: Target 'prepare' not remade because of errors.
   make[1]: *** [Makefile:248: __sub-make] Error 2
   make[1]: Target 'prepare' not remade because of errors.
   make: *** [Makefile:248: __sub-make] Error 2
   make: Target 'prepare' not remade because of errors.

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

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

* Re: [PATCH v3 0/8] Collect documentation-related tools under /tools/docs
  2025-10-24 20:08 [PATCH v3 0/8] Collect documentation-related tools under /tools/docs Jonathan Corbet
                   ` (8 preceding siblings ...)
  2025-10-25  2:33 ` [PATCH v3 0/8] Collect documentation-related tools under /tools/docs Mauro Carvalho Chehab
@ 2025-10-25 15:14 ` Akira Yokosawa
  2025-10-26 10:34   ` Mauro Carvalho Chehab
  2025-10-26 21:44 ` Randy Dunlap
  10 siblings, 1 reply; 21+ messages in thread
From: Akira Yokosawa @ 2025-10-25 15:14 UTC (permalink / raw)
  To: Jonathan Corbet, linux-doc, Mauro Carvalho Chehab
  Cc: linux-kernel, Randy Dunlap, Jani Nikula, Akira Yokosawa

On Fri, 24 Oct 2025 14:08:21 -0600, Jonathan Corbet wrote:
> Our documentation-related tools are spread out over various directories;
> several are buried in the scripts/ dumping ground.  That makes them harder
> to discover and harder to maintain.
> 
> Recent work has started accumulating our documentation-related tools in
> /tools/docs.  This series completes that task, moving the rest of our
> various utilities there, hopefully fixing up all of the relevant references
> in the process.
> 
> At the end, rather than move the old, Perl kernel-doc, I simply removed it.
> 
> The big elephant lurking in this small room is the home for Python modules;
> I left them under scripts/lib, but that is an even less appropriate place
> than it was before.  I would propose either tools/python or lib/python;
> thoughts on that matter welcome.
> 
> Changes in v3:
>   - Now with more caffeine! Properly based on docs-next.

:-) :-)

WRT the build error from test robot, it looks to me like we need these
final touches:

diff --git a/Documentation/conf.py b/Documentation/conf.py
index 8e3df5db858e..fbd8e3ae23ea 100644
--- a/Documentation/conf.py
+++ b/Documentation/conf.py
@@ -582,7 +582,7 @@ pdf_documents = [
 # kernel-doc extension configuration for running Sphinx directly (e.g. by Read
 # the Docs). In a normal build, these are supplied from the Makefile via command
 # line arguments.
-kerneldoc_bin = "../tools/docs/kernel-doc.py"
+kerneldoc_bin = "../tools/docs/kernel-doc"
 kerneldoc_srctree = ".."
 
 def setup(app):
diff --git a/Documentation/sphinx/kerneldoc.py b/Documentation/sphinx/kerneldoc.py
index 2586b4d4e494..3c815b40026b 100644
--- a/Documentation/sphinx/kerneldoc.py
+++ b/Documentation/sphinx/kerneldoc.py
@@ -289,13 +289,8 @@ def setup_kfiles(app):
 
     kerneldoc_bin = app.env.config.kerneldoc_bin
 
-    if kerneldoc_bin and kerneldoc_bin.endswith("kernel-doc.py"):
-        print("Using Python kernel-doc")
-        out_style = RestFormat()
-        kfiles = KernelFiles(out_style=out_style, logger=logger)
-    else:
-        print(f"Using {kerneldoc_bin}")
-
+    out_style = RestFormat()
+    kfiles = KernelFiles(out_style=out_style, logger=logger)
 
 def setup(app):
     app.add_config_value('kerneldoc_bin', None, 'env')
diff --git a/Makefile b/Makefile
index d6ff0af5cca6..33b1db1cc0cf 100644
--- a/Makefile
+++ b/Makefile
@@ -460,7 +460,7 @@ HOSTPKG_CONFIG	= pkg-config
 
 # the KERNELDOC macro needs to be exported, as scripts/Makefile.build
 # has a logic to call it
-KERNELDOC       = $(srctree)/tools/docs/kernel-doc.py
+KERNELDOC       = $(srctree)/tools/docs/kernel-doc
 export KERNELDOC
 
 KBUILD_USERHOSTCFLAGS := -Wall -Wmissing-prototypes -Wstrict-prototypes \

-----------------------------------------------------------------

The change in Documentation/sphinx/kerneldoc.py is needed because

    kerneldoc_bin == ".../kernel-doc.py"

indicated loading it as python lib into the extension, while

    kerneldoc_bin == ".../kernel-doc"

indicated invoking it as a script.

Now that we don't have kernel-doc.py, loading python lib looks to me
as a natural choice.

Mauro, what do you think?

Hope this helps,
Akira


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

* Re: [PATCH v3 0/8] Collect documentation-related tools under /tools/docs
  2025-10-25 15:14 ` Akira Yokosawa
@ 2025-10-26 10:34   ` Mauro Carvalho Chehab
  2025-10-26 21:53     ` Randy Dunlap
                       ` (2 more replies)
  0 siblings, 3 replies; 21+ messages in thread
From: Mauro Carvalho Chehab @ 2025-10-26 10:34 UTC (permalink / raw)
  To: Akira Yokosawa
  Cc: Jonathan Corbet, linux-doc, linux-kernel, Randy Dunlap,
	Jani Nikula

Em Sun, 26 Oct 2025 00:14:23 +0900
Akira Yokosawa <akiyks@gmail.com> escreveu:

> On Fri, 24 Oct 2025 14:08:21 -0600, Jonathan Corbet wrote:
> > Our documentation-related tools are spread out over various directories;
> > several are buried in the scripts/ dumping ground.  That makes them harder
> > to discover and harder to maintain.
> > 
> > Recent work has started accumulating our documentation-related tools in
> > /tools/docs.  This series completes that task, moving the rest of our
> > various utilities there, hopefully fixing up all of the relevant references
> > in the process.
> > 
> > At the end, rather than move the old, Perl kernel-doc, I simply removed it.
> > 
> > The big elephant lurking in this small room is the home for Python modules;
> > I left them under scripts/lib, but that is an even less appropriate place
> > than it was before.  I would propose either tools/python or lib/python;
> > thoughts on that matter welcome.
> > 
> > Changes in v3:
> >   - Now with more caffeine! Properly based on docs-next.  
> 
> :-) :-)
> 
> WRT the build error from test robot, it looks to me like we need these
> final touches:
> 
> diff --git a/Documentation/conf.py b/Documentation/conf.py
> index 8e3df5db858e..fbd8e3ae23ea 100644
> --- a/Documentation/conf.py
> +++ b/Documentation/conf.py
> @@ -582,7 +582,7 @@ pdf_documents = [
>  # kernel-doc extension configuration for running Sphinx directly (e.g. by Read
>  # the Docs). In a normal build, these are supplied from the Makefile via command
>  # line arguments.
> -kerneldoc_bin = "../tools/docs/kernel-doc.py"
> +kerneldoc_bin = "../tools/docs/kernel-doc"
>  kerneldoc_srctree = ".."
>  
>  def setup(app):
> diff --git a/Documentation/sphinx/kerneldoc.py b/Documentation/sphinx/kerneldoc.py
> index 2586b4d4e494..3c815b40026b 100644
> --- a/Documentation/sphinx/kerneldoc.py
> +++ b/Documentation/sphinx/kerneldoc.py
> @@ -289,13 +289,8 @@ def setup_kfiles(app):
>  
>      kerneldoc_bin = app.env.config.kerneldoc_bin
>  
> -    if kerneldoc_bin and kerneldoc_bin.endswith("kernel-doc.py"):
> -        print("Using Python kernel-doc")
> -        out_style = RestFormat()
> -        kfiles = KernelFiles(out_style=out_style, logger=logger)
> -    else:
> -        print(f"Using {kerneldoc_bin}")
> -
> +    out_style = RestFormat()
> +    kfiles = KernelFiles(out_style=out_style, logger=logger)

Patch is incomplete, as it doesn't drop the logic which forks
kernel-doc script run, but see below.

>  def setup(app):
>      app.add_config_value('kerneldoc_bin', None, 'env')
> diff --git a/Makefile b/Makefile
> index d6ff0af5cca6..33b1db1cc0cf 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -460,7 +460,7 @@ HOSTPKG_CONFIG	= pkg-config
>  
>  # the KERNELDOC macro needs to be exported, as scripts/Makefile.build
>  # has a logic to call it
> -KERNELDOC       = $(srctree)/tools/docs/kernel-doc.py
> +KERNELDOC       = $(srctree)/tools/docs/kernel-doc
>  export KERNELDOC
>  
>  KBUILD_USERHOSTCFLAGS := -Wall -Wmissing-prototypes -Wstrict-prototypes \
> 
> -----------------------------------------------------------------
> 
> The change in Documentation/sphinx/kerneldoc.py is needed because
> 
>     kerneldoc_bin == ".../kernel-doc.py"
> 
> indicated loading it as python lib into the extension, while
> 
>     kerneldoc_bin == ".../kernel-doc"
> 
> indicated invoking it as a script.
> 
> Now that we don't have kernel-doc.py, loading python lib looks to me
> as a natural choice.
> 
> Mauro, what do you think?

Good point. I'm not sure about this. Yeah, on normal cases, we
just want to run kernel-doc classes, instead of actually
executing its binary. Yet, for debugging purposes, it might
still be interesting to run it as separate processes.

See, right now, if KERNELDOC is not used, it will use imported
Python classes, running them directly without creating processes.
So, it won't actually call ".../kernel-doc". On such case, in
practice, it will actually ignore KERNELDOC when building docs.

Now, (after this series), if one runs:

	KERNELDOC=tools/docs/kernel-doc make htmldocs

it will run kernel-doc script as a process. This might be useful
for debugging purposes.

Also, please notice that KERNELDOC is used on several files:

	$ git grep -l KERNELDOC
	Makefile
	drivers/gpu/drm/Makefile
	drivers/gpu/drm/i915/Makefile
	include/drm/Makefile
	scripts/Makefile.build
	tools/docs/sphinx-build-wrapper

IMHO, we have some alternatives here:

1. completely drop support for KERNELDOC variable.
   On such case, we need to drop from the script:

	- kerneldoc_bin
	- run_cmd() function
	- remove KERNELDOC from Makefiles and sphinx-build-wrapper

2. keep it as is, which would help debugging (and eventually
   would allow testing two different implementations of kernel-doc
   without needing to bisect);

3. change the core of the logic to be something like:

	# kerneldoc_bin = env.config.kerneldoc_bin
	kerneldoc_bin = os.environ.get("KERNELDOC")

	if not kerneldoc_bin:
	   out_style = RestFormat()
	   kfiles = KernelFiles(out_style=out_style, logger=logger)
	else:
	    print(f"Generating C documentation by running {kerneldoc_bin} binary")

   this would still allow using KERNELDOC to point to a binary
   that will handle C files executed as a separate process.

   Please notice that the current code does:

	kerneldoc_bin = env.config.kerneldoc_bin

   This requires an extra logic at the wrapper tool, as this needs
   to be passed via -D command line option to sphinx-build. That's
   the reason why several Makefiles also use KERNELDOC env var.

   If we're willing to adopt this solution, I would simplify
   the wrapper and the makefiles to not touching KERNELDOC var
   anymore.

For (2) and (3), I would document KERNELDOC somewhere.

My personal preference would be (3), but I don't have strong
feelings.

Regards,
Mauro

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

* Re: [PATCH v3 0/8] Collect documentation-related tools under /tools/docs
  2025-10-24 20:08 [PATCH v3 0/8] Collect documentation-related tools under /tools/docs Jonathan Corbet
                   ` (9 preceding siblings ...)
  2025-10-25 15:14 ` Akira Yokosawa
@ 2025-10-26 21:44 ` Randy Dunlap
  10 siblings, 0 replies; 21+ messages in thread
From: Randy Dunlap @ 2025-10-26 21:44 UTC (permalink / raw)
  To: Jonathan Corbet, linux-doc
  Cc: linux-kernel, Mauro Carvalho Chehab, Akira Yokosawa, Jani Nikula



On 10/24/25 1:08 PM, Jonathan Corbet wrote:
> The big elephant lurking in this small room is the home for Python modules;
> I left them under scripts/lib, but that is an even less appropriate place
> than it was before.  I would propose either tools/python or lib/python;
> thoughts on that matter welcome.

I agree with Jani-- not lib/.
if that helps.

-- 
~Randy


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

* Re: [PATCH v3 0/8] Collect documentation-related tools under /tools/docs
  2025-10-26 10:34   ` Mauro Carvalho Chehab
@ 2025-10-26 21:53     ` Randy Dunlap
  2025-11-07 10:30       ` Mauro Carvalho Chehab
  2025-10-27  1:59     ` Akira Yokosawa
  2025-10-27 17:04     ` Jonathan Corbet
  2 siblings, 1 reply; 21+ messages in thread
From: Randy Dunlap @ 2025-10-26 21:53 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Akira Yokosawa
  Cc: Jonathan Corbet, linux-doc, linux-kernel, Jani Nikula

Hi,

On 10/26/25 3:34 AM, Mauro Carvalho Chehab wrote:
> Em Sun, 26 Oct 2025 00:14:23 +0900
> Akira Yokosawa <akiyks@gmail.com> escreveu:
> 
>> On Fri, 24 Oct 2025 14:08:21 -0600, Jonathan Corbet wrote:
>>> Our documentation-related tools are spread out over various directories;
>>> several are buried in the scripts/ dumping ground.  That makes them harder
>>> to discover and harder to maintain.
>>>
>>> Recent work has started accumulating our documentation-related tools in
>>> /tools/docs.  This series completes that task, moving the rest of our
>>> various utilities there, hopefully fixing up all of the relevant references
>>> in the process.
>>>
>>> At the end, rather than move the old, Perl kernel-doc, I simply removed it.
>>>
>>> The big elephant lurking in this small room is the home for Python modules;
>>> I left them under scripts/lib, but that is an even less appropriate place
>>> than it was before.  I would propose either tools/python or lib/python;
>>> thoughts on that matter welcome.
>>>
>>> Changes in v3:
>>>   - Now with more caffeine! Properly based on docs-next.  
>>
>> :-) :-)
>>
>> WRT the build error from test robot, it looks to me like we need these
>> final touches:
>>
>> diff --git a/Documentation/conf.py b/Documentation/conf.py
>> index 8e3df5db858e..fbd8e3ae23ea 100644
>> --- a/Documentation/conf.py
>> +++ b/Documentation/conf.py
>> @@ -582,7 +582,7 @@ pdf_documents = [
>>  # kernel-doc extension configuration for running Sphinx directly (e.g. by Read
>>  # the Docs). In a normal build, these are supplied from the Makefile via command
>>  # line arguments.
>> -kerneldoc_bin = "../tools/docs/kernel-doc.py"
>> +kerneldoc_bin = "../tools/docs/kernel-doc"
>>  kerneldoc_srctree = ".."
>>  
>>  def setup(app):
>> diff --git a/Documentation/sphinx/kerneldoc.py b/Documentation/sphinx/kerneldoc.py
>> index 2586b4d4e494..3c815b40026b 100644
>> --- a/Documentation/sphinx/kerneldoc.py
>> +++ b/Documentation/sphinx/kerneldoc.py
>> @@ -289,13 +289,8 @@ def setup_kfiles(app):
>>  
>>      kerneldoc_bin = app.env.config.kerneldoc_bin
>>  
>> -    if kerneldoc_bin and kerneldoc_bin.endswith("kernel-doc.py"):
>> -        print("Using Python kernel-doc")
>> -        out_style = RestFormat()
>> -        kfiles = KernelFiles(out_style=out_style, logger=logger)
>> -    else:
>> -        print(f"Using {kerneldoc_bin}")
>> -
>> +    out_style = RestFormat()
>> +    kfiles = KernelFiles(out_style=out_style, logger=logger)
> 
> Patch is incomplete, as it doesn't drop the logic which forks
> kernel-doc script run, but see below.
> 
>>  def setup(app):
>>      app.add_config_value('kerneldoc_bin', None, 'env')
>> diff --git a/Makefile b/Makefile
>> index d6ff0af5cca6..33b1db1cc0cf 100644
>> --- a/Makefile
>> +++ b/Makefile
>> @@ -460,7 +460,7 @@ HOSTPKG_CONFIG	= pkg-config
>>  
>>  # the KERNELDOC macro needs to be exported, as scripts/Makefile.build
>>  # has a logic to call it
>> -KERNELDOC       = $(srctree)/tools/docs/kernel-doc.py
>> +KERNELDOC       = $(srctree)/tools/docs/kernel-doc
>>  export KERNELDOC
>>  
>>  KBUILD_USERHOSTCFLAGS := -Wall -Wmissing-prototypes -Wstrict-prototypes \
>>
>> -----------------------------------------------------------------
>>
>> The change in Documentation/sphinx/kerneldoc.py is needed because
>>
>>     kerneldoc_bin == ".../kernel-doc.py"
>>
>> indicated loading it as python lib into the extension, while
>>
>>     kerneldoc_bin == ".../kernel-doc"
>>
>> indicated invoking it as a script.
>>
>> Now that we don't have kernel-doc.py, loading python lib looks to me
>> as a natural choice.
>>
>> Mauro, what do you think?
> 
> Good point. I'm not sure about this. Yeah, on normal cases, we
> just want to run kernel-doc classes, instead of actually
> executing its binary. Yet, for debugging purposes, it might
> still be interesting to run it as separate processes.
> 
> See, right now, if KERNELDOC is not used, it will use imported
> Python classes, running them directly without creating processes.
> So, it won't actually call ".../kernel-doc". On such case, in
> practice, it will actually ignore KERNELDOC when building docs.
> 
> Now, (after this series), if one runs:
> 
> 	KERNELDOC=tools/docs/kernel-doc make htmldocs
> 
> it will run kernel-doc script as a process. This might be useful
> for debugging purposes.
> 
> Also, please notice that KERNELDOC is used on several files:
> 
> 	$ git grep -l KERNELDOC
> 	Makefile
> 	drivers/gpu/drm/Makefile
> 	drivers/gpu/drm/i915/Makefile
> 	include/drm/Makefile
> 	scripts/Makefile.build
> 	tools/docs/sphinx-build-wrapper
> 
> IMHO, we have some alternatives here:
> 
> 1. completely drop support for KERNELDOC variable.
>    On such case, we need to drop from the script:
> 
> 	- kerneldoc_bin
> 	- run_cmd() function
> 	- remove KERNELDOC from Makefiles and sphinx-build-wrapper

No, please don't drop that feature.

I'm confused by the terminology. What does "bin" or "kerneldoc_bin"
mean here?  Is there some kernel-doc binary?

> 2. keep it as is, which would help debugging (and eventually
>    would allow testing two different implementations of kernel-doc
>    without needing to bisect);
> 
> 3. change the core of the logic to be something like:
> 
> 	# kerneldoc_bin = env.config.kerneldoc_bin
> 	kerneldoc_bin = os.environ.get("KERNELDOC")
> 
> 	if not kerneldoc_bin:
> 	   out_style = RestFormat()
> 	   kfiles = KernelFiles(out_style=out_style, logger=logger)
> 	else:
> 	    print(f"Generating C documentation by running {kerneldoc_bin} binary")
> 
>    this would still allow using KERNELDOC to point to a binary
>    that will handle C files executed as a separate process.
> 
>    Please notice that the current code does:
> 
> 	kerneldoc_bin = env.config.kerneldoc_bin
> 
>    This requires an extra logic at the wrapper tool, as this needs
>    to be passed via -D command line option to sphinx-build. That's
>    the reason why several Makefiles also use KERNELDOC env var.
> 
>    If we're willing to adopt this solution, I would simplify
>    the wrapper and the makefiles to not touching KERNELDOC var
>    anymore.
> 
> For (2) and (3), I would document KERNELDOC somewhere.
> 
> My personal preference would be (3), but I don't have strong
> feelings.


Thanks.
-- 
~Randy


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

* Re: [PATCH v3 0/8] Collect documentation-related tools under /tools/docs
  2025-10-26 10:34   ` Mauro Carvalho Chehab
  2025-10-26 21:53     ` Randy Dunlap
@ 2025-10-27  1:59     ` Akira Yokosawa
  2025-10-27 17:04     ` Jonathan Corbet
  2 siblings, 0 replies; 21+ messages in thread
From: Akira Yokosawa @ 2025-10-27  1:59 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Jonathan Corbet
  Cc: linux-doc, linux-kernel, Randy Dunlap, Jani Nikula,
	Akira Yokosawa

On Sun, 26 Oct 2025 07:34:05 -0300, Mauro Carvalho Chehab wrote:
> Em Sun, 26 Oct 2025 00:14:23 +0900
> Akira Yokosawa <akiyks@gmail.com> escreveu:
> 
>> On Fri, 24 Oct 2025 14:08:21 -0600, Jonathan Corbet wrote:
>>> Our documentation-related tools are spread out over various directories;
>>> several are buried in the scripts/ dumping ground.  That makes them harder
>>> to discover and harder to maintain.
>>>
>>> Recent work has started accumulating our documentation-related tools in
>>> /tools/docs.  This series completes that task, moving the rest of our
>>> various utilities there, hopefully fixing up all of the relevant references
>>> in the process.
>>>
>>> At the end, rather than move the old, Perl kernel-doc, I simply removed it.
>>>
>>> The big elephant lurking in this small room is the home for Python modules;
>>> I left them under scripts/lib, but that is an even less appropriate place
>>> than it was before.  I would propose either tools/python or lib/python;
>>> thoughts on that matter welcome.
>>>
>>> Changes in v3:
>>>   - Now with more caffeine! Properly based on docs-next.  
>>
>> :-) :-)
>>
>> WRT the build error from test robot, it looks to me like we need these
>> final touches:
>>
>> diff --git a/Documentation/conf.py b/Documentation/conf.py
>> index 8e3df5db858e..fbd8e3ae23ea 100644
>> --- a/Documentation/conf.py
>> +++ b/Documentation/conf.py
>> @@ -582,7 +582,7 @@ pdf_documents = [
>>  # kernel-doc extension configuration for running Sphinx directly (e.g. by Read
>>  # the Docs). In a normal build, these are supplied from the Makefile via command
>>  # line arguments.
>> -kerneldoc_bin = "../tools/docs/kernel-doc.py"
>> +kerneldoc_bin = "../tools/docs/kernel-doc"
>>  kerneldoc_srctree = ".."
>>  
>>  def setup(app):
>> diff --git a/Documentation/sphinx/kerneldoc.py b/Documentation/sphinx/kerneldoc.py
>> index 2586b4d4e494..3c815b40026b 100644
>> --- a/Documentation/sphinx/kerneldoc.py
>> +++ b/Documentation/sphinx/kerneldoc.py
>> @@ -289,13 +289,8 @@ def setup_kfiles(app):
>>  
>>      kerneldoc_bin = app.env.config.kerneldoc_bin
>>  
>> -    if kerneldoc_bin and kerneldoc_bin.endswith("kernel-doc.py"):
>> -        print("Using Python kernel-doc")
>> -        out_style = RestFormat()
>> -        kfiles = KernelFiles(out_style=out_style, logger=logger)
>> -    else:
>> -        print(f"Using {kerneldoc_bin}")
>> -
>> +    out_style = RestFormat()
>> +    kfiles = KernelFiles(out_style=out_style, logger=logger)
> 
> Patch is incomplete, as it doesn't drop the logic which forks
> kernel-doc script run, but see below.
> 
>>  def setup(app):
>>      app.add_config_value('kerneldoc_bin', None, 'env')
>> diff --git a/Makefile b/Makefile
>> index d6ff0af5cca6..33b1db1cc0cf 100644
>> --- a/Makefile
>> +++ b/Makefile
>> @@ -460,7 +460,7 @@ HOSTPKG_CONFIG	= pkg-config
>>  
>>  # the KERNELDOC macro needs to be exported, as scripts/Makefile.build
>>  # has a logic to call it
>> -KERNELDOC       = $(srctree)/tools/docs/kernel-doc.py
>> +KERNELDOC       = $(srctree)/tools/docs/kernel-doc
>>  export KERNELDOC
>>  
>>  KBUILD_USERHOSTCFLAGS := -Wall -Wmissing-prototypes -Wstrict-prototypes \
>>
>> -----------------------------------------------------------------
>>
>> The change in Documentation/sphinx/kerneldoc.py is needed because
>>
>>     kerneldoc_bin == ".../kernel-doc.py"
>>
>> indicated loading it as python lib into the extension, while
>>
>>     kerneldoc_bin == ".../kernel-doc"
>>
>> indicated invoking it as a script.
>>
>> Now that we don't have kernel-doc.py, loading python lib looks to me
>> as a natural choice.
>>
>> Mauro, what do you think?
> 
> Good point. I'm not sure about this. Yeah, on normal cases, we
> just want to run kernel-doc classes, instead of actually
> executing its binary. Yet, for debugging purposes, it might
> still be interesting to run it as separate processes.
> 
> See, right now, if KERNELDOC is not used, it will use imported
> Python classes, running them directly without creating processes.
> So, it won't actually call ".../kernel-doc". On such case, in
> practice, it will actually ignore KERNELDOC when building docs.
> 
> Now, (after this series), if one runs:
> 
> 	KERNELDOC=tools/docs/kernel-doc make htmldocs
> 
> it will run kernel-doc script as a process. This might be useful
> for debugging purposes.
> 
> Also, please notice that KERNELDOC is used on several files:
> 
> 	$ git grep -l KERNELDOC
> 	Makefile
> 	drivers/gpu/drm/Makefile
> 	drivers/gpu/drm/i915/Makefile
> 	include/drm/Makefile
> 	scripts/Makefile.build
> 	tools/docs/sphinx-build-wrapper
> 
> IMHO, we have some alternatives here:
> 
> 1. completely drop support for KERNELDOC variable.
>    On such case, we need to drop from the script:
> 
> 	- kerneldoc_bin
> 	- run_cmd() function
> 	- remove KERNELDOC from Makefiles and sphinx-build-wrapper
> 
> 2. keep it as is, which would help debugging (and eventually
>    would allow testing two different implementations of kernel-doc
>    without needing to bisect);
> 

So, as far as the build regression reported by the build bot is
concerned, I think 2. is good enough.

Probably, Jon included the rename of:

 scripts/kernel-doc                                     |  1 -
 scripts/kernel-doc.py => tools/docs/kernel-doc         |  0
 16 files changed, 22 insertions(+), 24 deletions(-)
 delete mode 120000 scripts/kernel-doc
 rename scripts/kernel-doc.py => tools/docs/kernel-doc (100%)

in 6/8 considering it the right thing to do.

Let's keep the symlink of kernel-doc --> kernel-doc.py, at least for the
time being.

Further tweaks and cleanups around KERNELDOC can wait.

       Thanks, Akira


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

* Re: [PATCH v3 0/8] Collect documentation-related tools under /tools/docs
  2025-10-26 10:34   ` Mauro Carvalho Chehab
  2025-10-26 21:53     ` Randy Dunlap
  2025-10-27  1:59     ` Akira Yokosawa
@ 2025-10-27 17:04     ` Jonathan Corbet
  2025-10-28 23:15       ` Jonathan Corbet
  2025-11-07 10:34       ` Mauro Carvalho Chehab
  2 siblings, 2 replies; 21+ messages in thread
From: Jonathan Corbet @ 2025-10-27 17:04 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Akira Yokosawa
  Cc: linux-doc, linux-kernel, Randy Dunlap, Jani Nikula

Mauro Carvalho Chehab <mchehab+huawei@kernel.org> writes:

> Patch is incomplete, as it doesn't drop the logic which forks
> kernel-doc script run, but see below.

So I clearly hadn't fully understood how this works.  Before I went and
broke things, the logic seemed to be:

  If the kerneldoc_bin environment variable is "kernel-doc.py"
  	don't actually run kernel-doc.py, build it internally instead
  else
  	run whatever program the variable points to

  ...
  set kerneldoc_bin to "kernel-doc.py" by default

This seems ... a bit obscure.  Given that:

> 3. change the core of the logic to be something like:
> 
> 	# kerneldoc_bin = env.config.kerneldoc_bin
> 	kerneldoc_bin = os.environ.get("KERNELDOC")
> 
> 	if not kerneldoc_bin:
> 	   out_style = RestFormat()
> 	   kfiles = KernelFiles(out_style=out_style, logger=logger)
> 	else:
> 	    print(f"Generating C documentation by running {kerneldoc_bin} binary")
> 
>    this would still allow using KERNELDOC to point to a binary
>    that will handle C files executed as a separate process.

This seems like an obvious improvement, and one that, perhaps, should go
in ahead of my current series in the perhaps vain hope that we're
finally getting to the end of the list of things I can find to break...

I can send a patch around in the next couple of days if you don't beat
me to it.

jon

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

* Re: [PATCH v3 0/8] Collect documentation-related tools under /tools/docs
  2025-10-27 17:04     ` Jonathan Corbet
@ 2025-10-28 23:15       ` Jonathan Corbet
  2025-11-07 10:27         ` Mauro Carvalho Chehab
  2025-11-07 10:34       ` Mauro Carvalho Chehab
  1 sibling, 1 reply; 21+ messages in thread
From: Jonathan Corbet @ 2025-10-28 23:15 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Akira Yokosawa
  Cc: linux-doc, linux-kernel, Randy Dunlap, Jani Nikula

Jonathan Corbet <corbet@lwn.net> writes:

>> 3. change the core of the logic to be something like:
>> 
>> 	# kerneldoc_bin = env.config.kerneldoc_bin
>> 	kerneldoc_bin = os.environ.get("KERNELDOC")
>> 
>> 	if not kerneldoc_bin:
>> 	   out_style = RestFormat()
>> 	   kfiles = KernelFiles(out_style=out_style, logger=logger)
>> 	else:
>> 	    print(f"Generating C documentation by running {kerneldoc_bin} binary")
>> 
>>    this would still allow using KERNELDOC to point to a binary
>>    that will handle C files executed as a separate process.
>
> This seems like an obvious improvement, and one that, perhaps, should go
> in ahead of my current series in the perhaps vain hope that we're
> finally getting to the end of the list of things I can find to break...
>
> I can send a patch around in the next couple of days if you don't beat
> me to it.

So I have that change working just fine ... only one problem.

For this to work, we have to take out the definition of KERNELDOC in the
top-level Makefile, otherwise we'll never go the import path.  But there
are a few other Makefiles, mostly in the DRM area, that need that
definition.  So I have the docs build working, but I've broken other
things, and I think people are getting tired of me breaking things.

Possible solutions:

- Add a new FORCE_KDOC environment variable that is used instead of
  KERNELDOC to set the program to run in the docs build.

- Keep the current logic that special-cases setting KERNELDOC to
  scripts/kernel-doc.py and really runs in the imported mode in that
  case.

- Go into retirement and let it be somebody else's problem

Anybody have any other great ideas?

Thanks,

jon

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

* Re: [PATCH v3 0/8] Collect documentation-related tools under /tools/docs
  2025-10-28 23:15       ` Jonathan Corbet
@ 2025-11-07 10:27         ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 21+ messages in thread
From: Mauro Carvalho Chehab @ 2025-11-07 10:27 UTC (permalink / raw)
  To: Jonathan Corbet
  Cc: Akira Yokosawa, linux-doc, linux-kernel, Randy Dunlap,
	Jani Nikula

Em Tue, 28 Oct 2025 17:15:26 -0600
Jonathan Corbet <corbet@lwn.net> escreveu:

> Jonathan Corbet <corbet@lwn.net> writes:
> 
> >> 3. change the core of the logic to be something like:
> >> 
> >> 	# kerneldoc_bin = env.config.kerneldoc_bin
> >> 	kerneldoc_bin = os.environ.get("KERNELDOC")
> >> 
> >> 	if not kerneldoc_bin:
> >> 	   out_style = RestFormat()
> >> 	   kfiles = KernelFiles(out_style=out_style, logger=logger)
> >> 	else:
> >> 	    print(f"Generating C documentation by running {kerneldoc_bin} binary")
> >> 
> >>    this would still allow using KERNELDOC to point to a binary
> >>    that will handle C files executed as a separate process.  
> >
> > This seems like an obvious improvement, and one that, perhaps, should go
> > in ahead of my current series in the perhaps vain hope that we're
> > finally getting to the end of the list of things I can find to break...
> >
> > I can send a patch around in the next couple of days if you don't beat
> > me to it.  
> 
> So I have that change working just fine ... only one problem.
> 
> For this to work, we have to take out the definition of KERNELDOC in the
> top-level Makefile, otherwise we'll never go the import path.  But there
> are a few other Makefiles, mostly in the DRM area, that need that
> definition.

True, DRM makefiles run kernel-doc to check for warnings within the
DRM subsystem. 

>  So I have the docs build working, but I've broken other
> things, and I think people are getting tired of me breaking things.
> 
> Possible solutions:
> 
> - Add a new FORCE_KDOC environment variable that is used instead of
>   KERNELDOC to set the program to run in the docs build.

Works for me.

> - Keep the current logic that special-cases setting KERNELDOC to
>   scripts/kernel-doc.py and really runs in the imported mode in that
>   case.

Not sure if I got what you meant. Do you mean not running the classes
but always run exec() syscall? This will likely affect build time,
and prevent further speedup optimizations. It will also duplicate
warnings if we drop the output filter logic for warnings.

> 
> - Go into retirement and let it be somebody else's problem
> 
> Anybody have any other great ideas?
> 
> Thanks,
> 
> jon

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

* Re: [PATCH v3 0/8] Collect documentation-related tools under /tools/docs
  2025-10-26 21:53     ` Randy Dunlap
@ 2025-11-07 10:30       ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 21+ messages in thread
From: Mauro Carvalho Chehab @ 2025-11-07 10:30 UTC (permalink / raw)
  To: Randy Dunlap
  Cc: Akira Yokosawa, Jonathan Corbet, linux-doc, linux-kernel,
	Jani Nikula

Em Sun, 26 Oct 2025 14:53:32 -0700
Randy Dunlap <rdunlap@infradead.org> escreveu:

> Hi,
> 
> On 10/26/25 3:34 AM, Mauro Carvalho Chehab wrote:
> > Em Sun, 26 Oct 2025 00:14:23 +0900
> > Akira Yokosawa <akiyks@gmail.com> escreveu:
> >   
> >> On Fri, 24 Oct 2025 14:08:21 -0600, Jonathan Corbet wrote:  
> >>> Our documentation-related tools are spread out over various directories;
> >>> several are buried in the scripts/ dumping ground.  That makes them harder
> >>> to discover and harder to maintain.
> >>>
> >>> Recent work has started accumulating our documentation-related tools in
> >>> /tools/docs.  This series completes that task, moving the rest of our
> >>> various utilities there, hopefully fixing up all of the relevant references
> >>> in the process.
> >>>
> >>> At the end, rather than move the old, Perl kernel-doc, I simply removed it.
> >>>
> >>> The big elephant lurking in this small room is the home for Python modules;
> >>> I left them under scripts/lib, but that is an even less appropriate place
> >>> than it was before.  I would propose either tools/python or lib/python;
> >>> thoughts on that matter welcome.
> >>>
> >>> Changes in v3:
> >>>   - Now with more caffeine! Properly based on docs-next.    
> >>
> >> :-) :-)
> >>
> >> WRT the build error from test robot, it looks to me like we need these
> >> final touches:
> >>
> >> diff --git a/Documentation/conf.py b/Documentation/conf.py
> >> index 8e3df5db858e..fbd8e3ae23ea 100644
> >> --- a/Documentation/conf.py
> >> +++ b/Documentation/conf.py
> >> @@ -582,7 +582,7 @@ pdf_documents = [
> >>  # kernel-doc extension configuration for running Sphinx directly (e.g. by Read
> >>  # the Docs). In a normal build, these are supplied from the Makefile via command
> >>  # line arguments.
> >> -kerneldoc_bin = "../tools/docs/kernel-doc.py"
> >> +kerneldoc_bin = "../tools/docs/kernel-doc"
> >>  kerneldoc_srctree = ".."
> >>  
> >>  def setup(app):
> >> diff --git a/Documentation/sphinx/kerneldoc.py b/Documentation/sphinx/kerneldoc.py
> >> index 2586b4d4e494..3c815b40026b 100644
> >> --- a/Documentation/sphinx/kerneldoc.py
> >> +++ b/Documentation/sphinx/kerneldoc.py
> >> @@ -289,13 +289,8 @@ def setup_kfiles(app):
> >>  
> >>      kerneldoc_bin = app.env.config.kerneldoc_bin
> >>  
> >> -    if kerneldoc_bin and kerneldoc_bin.endswith("kernel-doc.py"):
> >> -        print("Using Python kernel-doc")
> >> -        out_style = RestFormat()
> >> -        kfiles = KernelFiles(out_style=out_style, logger=logger)
> >> -    else:
> >> -        print(f"Using {kerneldoc_bin}")
> >> -
> >> +    out_style = RestFormat()
> >> +    kfiles = KernelFiles(out_style=out_style, logger=logger)  
> > 
> > Patch is incomplete, as it doesn't drop the logic which forks
> > kernel-doc script run, but see below.
> >   
> >>  def setup(app):
> >>      app.add_config_value('kerneldoc_bin', None, 'env')
> >> diff --git a/Makefile b/Makefile
> >> index d6ff0af5cca6..33b1db1cc0cf 100644
> >> --- a/Makefile
> >> +++ b/Makefile
> >> @@ -460,7 +460,7 @@ HOSTPKG_CONFIG	= pkg-config
> >>  
> >>  # the KERNELDOC macro needs to be exported, as scripts/Makefile.build
> >>  # has a logic to call it
> >> -KERNELDOC       = $(srctree)/tools/docs/kernel-doc.py
> >> +KERNELDOC       = $(srctree)/tools/docs/kernel-doc
> >>  export KERNELDOC
> >>  
> >>  KBUILD_USERHOSTCFLAGS := -Wall -Wmissing-prototypes -Wstrict-prototypes \
> >>
> >> -----------------------------------------------------------------
> >>
> >> The change in Documentation/sphinx/kerneldoc.py is needed because
> >>
> >>     kerneldoc_bin == ".../kernel-doc.py"
> >>
> >> indicated loading it as python lib into the extension, while
> >>
> >>     kerneldoc_bin == ".../kernel-doc"
> >>
> >> indicated invoking it as a script.
> >>
> >> Now that we don't have kernel-doc.py, loading python lib looks to me
> >> as a natural choice.
> >>
> >> Mauro, what do you think?  
> > 
> > Good point. I'm not sure about this. Yeah, on normal cases, we
> > just want to run kernel-doc classes, instead of actually
> > executing its binary. Yet, for debugging purposes, it might
> > still be interesting to run it as separate processes.
> > 
> > See, right now, if KERNELDOC is not used, it will use imported
> > Python classes, running them directly without creating processes.
> > So, it won't actually call ".../kernel-doc". On such case, in
> > practice, it will actually ignore KERNELDOC when building docs.
> > 
> > Now, (after this series), if one runs:
> > 
> > 	KERNELDOC=tools/docs/kernel-doc make htmldocs
> > 
> > it will run kernel-doc script as a process. This might be useful
> > for debugging purposes.
> > 
> > Also, please notice that KERNELDOC is used on several files:
> > 
> > 	$ git grep -l KERNELDOC
> > 	Makefile
> > 	drivers/gpu/drm/Makefile
> > 	drivers/gpu/drm/i915/Makefile
> > 	include/drm/Makefile
> > 	scripts/Makefile.build
> > 	tools/docs/sphinx-build-wrapper
> > 
> > IMHO, we have some alternatives here:
> > 
> > 1. completely drop support for KERNELDOC variable.
> >    On such case, we need to drop from the script:
> > 
> > 	- kerneldoc_bin
> > 	- run_cmd() function
> > 	- remove KERNELDOC from Makefiles and sphinx-build-wrapper  
> 
> No, please don't drop that feature.
> 
> I'm confused by the terminology. What does "bin" or "kerneldoc_bin"
> mean here?  Is there some kernel-doc binary?

kerneldoc_bin is the name of a variable at the Python script.
It points to KERNELDOC env.

> 
> > 2. keep it as is, which would help debugging (and eventually
> >    would allow testing two different implementations of kernel-doc
> >    without needing to bisect);
> > 
> > 3. change the core of the logic to be something like:
> > 
> > 	# kerneldoc_bin = env.config.kerneldoc_bin
> > 	kerneldoc_bin = os.environ.get("KERNELDOC")
> > 
> > 	if not kerneldoc_bin:
> > 	   out_style = RestFormat()
> > 	   kfiles = KernelFiles(out_style=out_style, logger=logger)
> > 	else:
> > 	    print(f"Generating C documentation by running {kerneldoc_bin} binary")
> > 
> >    this would still allow using KERNELDOC to point to a binary
> >    that will handle C files executed as a separate process.
> > 
> >    Please notice that the current code does:
> > 
> > 	kerneldoc_bin = env.config.kerneldoc_bin
> > 
> >    This requires an extra logic at the wrapper tool, as this needs
> >    to be passed via -D command line option to sphinx-build. That's
> >    the reason why several Makefiles also use KERNELDOC env var.
> > 
> >    If we're willing to adopt this solution, I would simplify
> >    the wrapper and the makefiles to not touching KERNELDOC var
> >    anymore.
> > 
> > For (2) and (3), I would document KERNELDOC somewhere.
> > 
> > My personal preference would be (3), but I don't have strong
> > feelings.  
> 
> 
> Thanks.

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

* Re: [PATCH v3 0/8] Collect documentation-related tools under /tools/docs
  2025-10-27 17:04     ` Jonathan Corbet
  2025-10-28 23:15       ` Jonathan Corbet
@ 2025-11-07 10:34       ` Mauro Carvalho Chehab
  1 sibling, 0 replies; 21+ messages in thread
From: Mauro Carvalho Chehab @ 2025-11-07 10:34 UTC (permalink / raw)
  To: Jonathan Corbet
  Cc: Akira Yokosawa, linux-doc, linux-kernel, Randy Dunlap,
	Jani Nikula

Em Mon, 27 Oct 2025 11:04:27 -0600
Jonathan Corbet <corbet@lwn.net> escreveu:

> Mauro Carvalho Chehab <mchehab+huawei@kernel.org> writes:
> 
> > Patch is incomplete, as it doesn't drop the logic which forks
> > kernel-doc script run, but see below.  
> 
> So I clearly hadn't fully understood how this works.  Before I went and
> broke things, the logic seemed to be:
> 
>   If the kerneldoc_bin environment variable is "kernel-doc.py"
>   	don't actually run kernel-doc.py, build it internally instead
>   else
>   	run whatever program the variable points to
> 
>   ...
>   set kerneldoc_bin to "kernel-doc.py" by default
> 
> This seems ... a bit obscure. 

Yes, but it was the best alternative I found back then :-)

Regards,
Mauro

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

end of thread, other threads:[~2025-11-07 10:34 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-10-24 20:08 [PATCH v3 0/8] Collect documentation-related tools under /tools/docs Jonathan Corbet
2025-10-24 20:08 ` [PATCH v3 1/8] docs: Move the "features" tools to tools/docs Jonathan Corbet
2025-10-24 20:08 ` [PATCH v3 2/8] docs: move checktransupdate.py " Jonathan Corbet
2025-10-24 20:08 ` [PATCH v3 3/8] docs: move scripts/documentation-file-ref-check " Jonathan Corbet
2025-10-24 20:08 ` [PATCH v3 4/8] docs: move get_abi.py " Jonathan Corbet
2025-10-24 20:08 ` [PATCH v3 5/8] docs: move test_doc_build.py " Jonathan Corbet
2025-10-24 20:08 ` [PATCH v3 6/8] docs: move kernel-doc " Jonathan Corbet
2025-10-25  7:14   ` kernel test robot
2025-10-24 20:08 ` [PATCH v3 7/8] docs: move find-unused-docs.sh " Jonathan Corbet
2025-10-24 20:08 ` [PATCH v3 8/8] docs: remove kernel-doc.pl Jonathan Corbet
2025-10-25  2:33 ` [PATCH v3 0/8] Collect documentation-related tools under /tools/docs Mauro Carvalho Chehab
2025-10-25 15:14 ` Akira Yokosawa
2025-10-26 10:34   ` Mauro Carvalho Chehab
2025-10-26 21:53     ` Randy Dunlap
2025-11-07 10:30       ` Mauro Carvalho Chehab
2025-10-27  1:59     ` Akira Yokosawa
2025-10-27 17:04     ` Jonathan Corbet
2025-10-28 23:15       ` Jonathan Corbet
2025-11-07 10:27         ` Mauro Carvalho Chehab
2025-11-07 10:34       ` Mauro Carvalho Chehab
2025-10-26 21:44 ` Randy Dunlap

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).