linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/2] kernel-doc: Handle function typedefs
@ 2020-10-30 14:47 Paolo Bonzini
  2020-10-30 14:47 ` [PATCH 1/2] kernel-doc: Handle function typedefs that return pointers Paolo Bonzini
  2020-10-30 14:47 ` [PATCH 2/2] kernel-doc: Handle function typedefs without asterisks Paolo Bonzini
  0 siblings, 2 replies; 17+ messages in thread
From: Paolo Bonzini @ 2020-10-30 14:47 UTC (permalink / raw)
  To: linux-kernel, linux-doc, corbet; +Cc: Eduardo Habkost

Hi all,

QEMU has been using kernel-doc for a while and we're very happy with it. :)
These two patches are relatively simple regex changes that were done to
support QEMU header files; they handle function typedefs (i.e. not
function _pointer_ typedefs).

These are basically the only difference between Linux and QEMU kernel-doc,
so I thought I'd just send them out and see what you people think.

Paolo

Eduardo Habkost (2):
  kernel-doc: Handle function typedefs that return pointers
  kernel-doc: Handle function typedefs without asterisks

 scripts/kernel-doc | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

-- 
2.28.0


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

* [PATCH 1/2] kernel-doc: Handle function typedefs that return pointers
  2020-10-30 14:47 [PATCH 0/2] kernel-doc: Handle function typedefs Paolo Bonzini
@ 2020-10-30 14:47 ` Paolo Bonzini
  2020-10-30 14:47 ` [PATCH 2/2] kernel-doc: Handle function typedefs without asterisks Paolo Bonzini
  1 sibling, 0 replies; 17+ messages in thread
From: Paolo Bonzini @ 2020-10-30 14:47 UTC (permalink / raw)
  To: linux-kernel, linux-doc, corbet; +Cc: Eduardo Habkost

From: Eduardo Habkost <ehabkost@redhat.com>

One example that was not being parsed correctly by kernel-doc is:

  typedef Object *(ObjectPropertyResolve)(Object *obj,
                                          void *opaque,
                                          const char *part);

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 scripts/kernel-doc | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/scripts/kernel-doc b/scripts/kernel-doc
index f68d76dd97ba..5b5caa7642f7 100755
--- a/scripts/kernel-doc
+++ b/scripts/kernel-doc
@@ -1302,8 +1302,8 @@ sub dump_typedef($$) {
     $x =~ s@/\*.*?\*/@@gos;	# strip comments.
 
     # Parse function prototypes
-    if ($x =~ /typedef\s+(\w+)\s*\(\*\s*(\w\S+)\s*\)\s*\((.*)\);/ ||
-	$x =~ /typedef\s+(\w+)\s*(\w\S+)\s*\s*\((.*)\);/) {
+    if ($x =~ /typedef\s+(\w+\s*\**)\s*\(\*\s*(\w\S+)\s*\)\s*\((.*)\);/ ||
+	$x =~ /typedef\s+(\w+\s*\**)\s*(\w\S+)\s*\s*\((.*)\);/) {
 
 	# Function typedefs
 	$return_type = $1;
-- 
2.28.0



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

* [PATCH 2/2] kernel-doc: Handle function typedefs without asterisks
  2020-10-30 14:47 [PATCH 0/2] kernel-doc: Handle function typedefs Paolo Bonzini
  2020-10-30 14:47 ` [PATCH 1/2] kernel-doc: Handle function typedefs that return pointers Paolo Bonzini
@ 2020-10-30 14:47 ` Paolo Bonzini
  2020-11-13 22:21   ` Jonathan Corbet
  1 sibling, 1 reply; 17+ messages in thread
From: Paolo Bonzini @ 2020-10-30 14:47 UTC (permalink / raw)
  To: linux-kernel, linux-doc, corbet; +Cc: Eduardo Habkost

From: Eduardo Habkost <ehabkost@redhat.com>

Example of typedef that was not parsed by kernel-doc:

  typedef void (ObjectUnparent)(Object *obj);

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 scripts/kernel-doc | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/scripts/kernel-doc b/scripts/kernel-doc
index 5b5caa7642f7..1a9c918aa653 100755
--- a/scripts/kernel-doc
+++ b/scripts/kernel-doc
@@ -1302,7 +1302,7 @@ sub dump_typedef($$) {
     $x =~ s@/\*.*?\*/@@gos;	# strip comments.
 
     # Parse function prototypes
-    if ($x =~ /typedef\s+(\w+\s*\**)\s*\(\*\s*(\w\S+)\s*\)\s*\((.*)\);/ ||
+    if ($x =~ /typedef\s+(\w+\s*\**)\s*\(\*?\s*(\w\S+)\s*\)\s*\((.*)\);/ ||
 	$x =~ /typedef\s+(\w+\s*\**)\s*(\w\S+)\s*\s*\((.*)\);/) {
 
 	# Function typedefs
-- 
2.28.0


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

* Re: [PATCH 2/2] kernel-doc: Handle function typedefs without asterisks
  2020-10-30 14:47 ` [PATCH 2/2] kernel-doc: Handle function typedefs without asterisks Paolo Bonzini
@ 2020-11-13 22:21   ` Jonathan Corbet
  2020-11-13 22:35     ` Paolo Bonzini
  2020-11-13 22:39     ` Matthew Wilcox
  0 siblings, 2 replies; 17+ messages in thread
From: Jonathan Corbet @ 2020-11-13 22:21 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: linux-kernel, linux-doc, Eduardo Habkost

On Fri, 30 Oct 2020 15:47:13 +0100
Paolo Bonzini <pbonzini@redhat.com> wrote:

> From: Eduardo Habkost <ehabkost@redhat.com>
> 
> Example of typedef that was not parsed by kernel-doc:
> 
>   typedef void (ObjectUnparent)(Object *obj);
> 
> Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

So as you've undoubtedly noticed, reading those kernel-doc regexes is ... a
wee bit on the painful side.  Trying to compare two of them in a patch to
figure out what you have done is even worse.  I suspect we want these
patches, but can you please supply a changelog that describes the change? 

> ---
>  scripts/kernel-doc | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/scripts/kernel-doc b/scripts/kernel-doc
> index 5b5caa7642f7..1a9c918aa653 100755
> --- a/scripts/kernel-doc
> +++ b/scripts/kernel-doc
> @@ -1302,7 +1302,7 @@ sub dump_typedef($$) {
>      $x =~ s@/\*.*?\*/@@gos;	# strip comments.
>  
>      # Parse function prototypes
> -    if ($x =~ /typedef\s+(\w+\s*\**)\s*\(\*\s*(\w\S+)\s*\)\s*\((.*)\);/ ||
> +    if ($x =~ /typedef\s+(\w+\s*\**)\s*\(\*?\s*(\w\S+)\s*\)\s*\((.*)\);/ ||

Here it appears that you are making the "*" before the function-pointer
name optional, right?  It really would help to say so in the changelog.

This is true for the other patch as well.

>  	$x =~ /typedef\s+(\w+\s*\**)\s*(\w\S+)\s*\s*\((.*)\);/) {
>  
>  	# Function typedefs

Thanks,

jon

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

* Re: [PATCH 2/2] kernel-doc: Handle function typedefs without asterisks
  2020-11-13 22:21   ` Jonathan Corbet
@ 2020-11-13 22:35     ` Paolo Bonzini
  2020-11-13 22:39     ` Matthew Wilcox
  1 sibling, 0 replies; 17+ messages in thread
From: Paolo Bonzini @ 2020-11-13 22:35 UTC (permalink / raw)
  To: Jonathan Corbet; +Cc: linux-kernel, linux-doc, Eduardo Habkost

On 13/11/20 23:21, Jonathan Corbet wrote:
>>
>> Signed-off-by: Eduardo Habkost<ehabkost@redhat.com>
>> Signed-off-by: Paolo Bonzini<pbonzini@redhat.com>
> So as you've undoubtedly noticed, reading those kernel-doc regexes is ... a
> wee bit on the painful side.  Trying to compare two of them in a patch to
> figure out what you have done is even worse.  I suspect we want these
> patches, but can you please supply a changelog that describes the change?
> 

Seems like some of Mauro's recent patches take care of the same thing. 
I'm going to update QEMU's kernel-doc, and if there's anything left to 
do I'll resend.

Thanks,

Paolo


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

* Re: [PATCH 2/2] kernel-doc: Handle function typedefs without asterisks
  2020-11-13 22:21   ` Jonathan Corbet
  2020-11-13 22:35     ` Paolo Bonzini
@ 2020-11-13 22:39     ` Matthew Wilcox
  2020-11-17 21:24       ` Eduardo Habkost
  1 sibling, 1 reply; 17+ messages in thread
From: Matthew Wilcox @ 2020-11-13 22:39 UTC (permalink / raw)
  To: Jonathan Corbet; +Cc: Paolo Bonzini, linux-kernel, linux-doc, Eduardo Habkost

On Fri, Nov 13, 2020 at 03:21:06PM -0700, Jonathan Corbet wrote:
> On Fri, 30 Oct 2020 15:47:13 +0100
> Paolo Bonzini <pbonzini@redhat.com> wrote:
> 
> > From: Eduardo Habkost <ehabkost@redhat.com>
> > 
> > Example of typedef that was not parsed by kernel-doc:
> > 
> >   typedef void (ObjectUnparent)(Object *obj);
> > 
> > Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
> > Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> 
> So as you've undoubtedly noticed, reading those kernel-doc regexes is ... a
> wee bit on the painful side.  Trying to compare two of them in a patch to
> figure out what you have done is even worse.  I suspect we want these
> patches, but can you please supply a changelog that describes the change? 

Better ... can we have a test suite for the regexes and make patches to
them include updates to the test suite?  They have clearly passed the
point of human understanding ;-)


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

* Re: [PATCH 2/2] kernel-doc: Handle function typedefs without asterisks
  2020-11-13 22:39     ` Matthew Wilcox
@ 2020-11-17 21:24       ` Eduardo Habkost
  2020-11-17 21:30         ` Matthew Wilcox
  0 siblings, 1 reply; 17+ messages in thread
From: Eduardo Habkost @ 2020-11-17 21:24 UTC (permalink / raw)
  To: Matthew Wilcox; +Cc: Jonathan Corbet, Paolo Bonzini, linux-kernel, linux-doc

On Fri, Nov 13, 2020 at 10:39:12PM +0000, Matthew Wilcox wrote:
> On Fri, Nov 13, 2020 at 03:21:06PM -0700, Jonathan Corbet wrote:
> > On Fri, 30 Oct 2020 15:47:13 +0100
> > Paolo Bonzini <pbonzini@redhat.com> wrote:
> > 
> > > From: Eduardo Habkost <ehabkost@redhat.com>
> > > 
> > > Example of typedef that was not parsed by kernel-doc:
> > > 
> > >   typedef void (ObjectUnparent)(Object *obj);
> > > 
> > > Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
> > > Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> > 
> > So as you've undoubtedly noticed, reading those kernel-doc regexes is ... a
> > wee bit on the painful side.  Trying to compare two of them in a patch to
> > figure out what you have done is even worse.  I suspect we want these
> > patches, but can you please supply a changelog that describes the change? 
> 
> Better ... can we have a test suite for the regexes and make patches to
> them include updates to the test suite?  They have clearly passed the
> point of human understanding ;-)

Would a simple black box test script like this be desirable?

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
 scripts/kernel-doc-test-case.h            |  89 ++++++++++++
 scripts/kernel-doc-test-case.rst.expected | 167 ++++++++++++++++++++++
 scripts/kernel-doc-test.sh                |  15 ++
 3 files changed, 271 insertions(+)
 create mode 100644 scripts/kernel-doc-test-case.h
 create mode 100644 scripts/kernel-doc-test-case.rst.expected
 create mode 100755 scripts/kernel-doc-test.sh

diff --git a/scripts/kernel-doc-test-case.h b/scripts/kernel-doc-test-case.h
new file mode 100644
index 0000000000000..5cea705d85392
--- /dev/null
+++ b/scripts/kernel-doc-test-case.h
@@ -0,0 +1,89 @@
+/**
+ * DOC: kernel-doc test case
+ *
+ * ``kernel-doc-test-case.h`` contains a series of declarations
+ * and kernel-doc comments. The expected kernel-doc output can be
+ * found at ``kernel-doc-test-case.rst.expected``.
+ */
+
+/**
+ * typedef void_func_ptr - pointer to a function
+ * @a: first argument
+ * @b: second argument
+ */
+typedef void (*void_func_ptr)(int a, struct struct_name1 *b);
+
+/**
+ * typedef int_ptr_func_ptr - a pointer to a function returning a pointer
+ * @a: argument
+ */
+typedef int *(*int_ptr_func_ptr)(int a);
+
+/**
+ * typedef func_par - a function, with parenthesis
+ * @a: argument
+ *
+ * A typedef for a function type (not a function pointer), with
+ * parenthesis around the function name.
+ */
+typedef void (func_par)(int a);
+
+/**
+ * struct struct_name1 - a struct
+ * @i: an int field
+ * @j: an int pointer
+ * @u: an union field
+ * @sptr: pointer to a `struct_name1`
+ *
+ * A simple struct with multiple fields.
+ *
+ * Here's a reference to another struct type: &struct struct_name2.
+ */
+struct struct_name1 {
+    int i, *j;
+    union {
+        int i;
+        const char *s;
+    } u;
+    struct struct_name1 *sptr;
+    /**
+     * @field_with_inline_doc: another way to document struct fields
+     *
+     * This field is documented inside the struct definition,
+     * closer to the field declaration instead the doc comment at
+     * the top.
+     */
+    int field_with_inline_doc;
+    /**
+     * @func: a function pointer
+     *
+     * Parsing a function pointer field involves some tricks to handle
+     * the commas properly.
+     */
+    int (*func)(int x, struct struct_name1 *p);
+    /** @bitmap: a bitmap */
+    DECLARE_BITMAP(bitmap, 128);
+};
+
+/**
+ * struct struct_name2 - another struct
+ * @x: first field
+ * @y: second field
+ * @another: another struct
+ *
+ * This struct is defined inside a typedef declaration.
+ */
+typedef struct struct_name2 {
+    int x, y;
+    struct struct_name1 another;
+} struct_name2;
+
+/**
+ * SOME_MACRO - a macro that takes a few arguments
+ * @a: first argument
+ * @b: second argument
+ */
+#define SOME_MACRO(a, b) \
+    { multi_line_macro_definition(a); \
+      second_line(b); \
+    }
diff --git a/scripts/kernel-doc-test-case.rst.expected b/scripts/kernel-doc-test-case.rst.expected
new file mode 100644
index 0000000000000..4f68931121bb7
--- /dev/null
+++ b/scripts/kernel-doc-test-case.rst.expected
@@ -0,0 +1,167 @@
+**kernel-doc test case**
+
+
+``kernel-doc-test-case.h`` contains a series of declarations
+and kernel-doc comments. The expected kernel-doc output can be
+found at ``kernel-doc-test-case.rst.expected``.
+
+.. c:macro:: void_func_ptr
+
+   **Typedef**: pointer to a function
+
+
+**Syntax**
+
+  ``void void_func_ptr (int a, struct struct_name1 *b)``
+
+**Parameters**
+
+``int a``
+  first argument
+
+``struct struct_name1 *b``
+  second argument
+
+
+.. c:macro:: int_ptr_func_ptr
+
+   **Typedef**: a pointer to a function returning a pointer
+
+
+**Syntax**
+
+  ``int * int_ptr_func_ptr (int a)``
+
+**Parameters**
+
+``int a``
+  argument
+
+
+.. c:macro:: func_par
+
+   **Typedef**: a function, with parenthesis
+
+
+**Syntax**
+
+  ``void func_par (int a)``
+
+**Parameters**
+
+``int a``
+  argument
+
+**Description**
+
+A typedef for a function type (not a function pointer), with
+parenthesis around the function name.
+
+
+
+
+.. c:struct:: struct_name1
+
+   a struct
+
+**Definition**
+
+::
+
+  struct struct_name1 {
+    int i, *j;
+    union {
+      int i;
+      const char *s;
+    } u;
+    struct struct_name1 *sptr;
+    int field_with_inline_doc;
+    int (*func)(int x, struct struct_name1 *p);
+    unsigned long bitmap[BITS_TO_LONGS(128)];
+  };
+
+**Members**
+
+``i``
+  an int field
+
+``j``
+  an int pointer
+
+``u``
+  an union field
+
+``sptr``
+  pointer to a `struct_name1`
+
+``field_with_inline_doc``
+  another way to document struct fields
+  
+  This field is documented inside the struct definition,
+  closer to the field declaration instead the doc comment at
+  the top.
+
+``func``
+  a function pointer
+  
+  Parsing a function pointer field involves some tricks to handle
+  the commas properly.
+
+``bitmap``
+  a bitmap 
+
+
+**Description**
+
+A simple struct with multiple fields.
+
+Here's a reference to another struct type: :c:type:`struct struct_name2 <struct_name2>`.
+
+
+
+
+.. c:struct:: struct_name2
+
+   another struct
+
+**Definition**
+
+::
+
+  struct struct_name2 {
+    int x, y;
+    struct struct_name1 another;
+  };
+
+**Members**
+
+``x``
+  first field
+
+``y``
+  second field
+
+``another``
+  another struct
+
+
+**Description**
+
+This struct is defined inside a typedef declaration.
+
+
+.. c:macro:: SOME_MACRO
+
+``SOME_MACRO (a, b)``
+
+   a macro that takes a few arguments
+
+**Parameters**
+
+``a``
+  first argument
+
+``b``
+  second argument
+
+
diff --git a/scripts/kernel-doc-test.sh b/scripts/kernel-doc-test.sh
new file mode 100755
index 0000000000000..4c96592649451
--- /dev/null
+++ b/scripts/kernel-doc-test.sh
@@ -0,0 +1,15 @@
+#!/bin/bash
+set -e
+mydir="$(dirname "$0")"
+kerneldoc="$mydir/kernel-doc"
+
+tmp="$(mktemp -d)"
+trap 'rm -rf "$tmp"' EXIT
+
+"$kerneldoc" -sphinx-version 3.2.1 -rst "$mydir/kernel-doc-test-case.h" > "$tmp/kernel-doc-test-case.rst.actual" 2>&1
+if diff -u "$mydir/kernel-doc-test-case.rst.expected" "$tmp/kernel-doc-test-case.rst.actual";then
+    echo OK
+else
+    echo kernel-doc output mismatch
+    exit 1
+fi
-- 
2.28.0

-- 
Eduardo


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

* Re: [PATCH 2/2] kernel-doc: Handle function typedefs without asterisks
  2020-11-17 21:24       ` Eduardo Habkost
@ 2020-11-17 21:30         ` Matthew Wilcox
  2020-11-17 22:36           ` [RFC] Add kernel-doc test script Eduardo Habkost
  0 siblings, 1 reply; 17+ messages in thread
From: Matthew Wilcox @ 2020-11-17 21:30 UTC (permalink / raw)
  To: Eduardo Habkost; +Cc: Jonathan Corbet, Paolo Bonzini, linux-kernel, linux-doc

On Tue, Nov 17, 2020 at 04:24:52PM -0500, Eduardo Habkost wrote:
> On Fri, Nov 13, 2020 at 10:39:12PM +0000, Matthew Wilcox wrote:
> > Better ... can we have a test suite for the regexes and make patches to
> > them include updates to the test suite?  They have clearly passed the
> > point of human understanding ;-)
> 
> Would a simple black box test script like this be desirable?

I think this is fantastic!  Yes please!

Can I add one more test case?

/**
 * radix_tree_lookup_slot - lookup a slot in a radix tree
 * @root:          radix tree root
 * @index:         index key
 *
 * Returns:  the slot corresponding to the position @index in the
 * radix tree @root. This is useful for update-if-exists operations.
 *
 * This function can be called under rcu_read_lock iff the slot is not
 * modified by radix_tree_replace_slot(), otherwise it must be called
 * exclusive from other writers. Any dereference of the slot must be done
 * using radix_tree_deref_slot().
 */
void __rcu **radix_tree_lookup_slot(const struct radix_tree_root *root,
                                unsigned long index)
{ }

(we used to have a problem with multiple '*' in the return type, and
we've also had problems with adornments like __rcu)


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

* [RFC] Add kernel-doc test script
  2020-11-17 21:30         ` Matthew Wilcox
@ 2020-11-17 22:36           ` Eduardo Habkost
  2020-11-18  0:23             ` Randy Dunlap
                               ` (2 more replies)
  0 siblings, 3 replies; 17+ messages in thread
From: Eduardo Habkost @ 2020-11-17 22:36 UTC (permalink / raw)
  To: Matthew Wilcox; +Cc: Jonathan Corbet, Paolo Bonzini, linux-kernel, linux-doc

Add a kernel-doc test script to tools/testing/kernel-doc.

radix_tree_lookup_slot test case provided by Matthew Wilcox.

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
 tools/testing/kernel-doc/test-case.h          | 111 ++++++++++
 .../testing/kernel-doc/test-case.man.expected | 150 ++++++++++++++
 .../kernel-doc/test-case.none.expected        |   0
 .../kernel-doc/test-case.rst2.expected        | 195 ++++++++++++++++++
 .../kernel-doc/test-case.rst3.expected        | 195 ++++++++++++++++++
 tools/testing/kernel-doc/test.sh              |  90 ++++++++
 6 files changed, 741 insertions(+)
 create mode 100644 tools/testing/kernel-doc/test-case.h
 create mode 100644 tools/testing/kernel-doc/test-case.man.expected
 create mode 100644 tools/testing/kernel-doc/test-case.none.expected
 create mode 100644 tools/testing/kernel-doc/test-case.rst2.expected
 create mode 100644 tools/testing/kernel-doc/test-case.rst3.expected
 create mode 100755 tools/testing/kernel-doc/test.sh

diff --git a/tools/testing/kernel-doc/test-case.h b/tools/testing/kernel-doc/test-case.h
new file mode 100644
index 0000000000000..6d4e1f6b99631
--- /dev/null
+++ b/tools/testing/kernel-doc/test-case.h
@@ -0,0 +1,111 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/**
+ * DOC: kernel-doc test case
+ *
+ * ``test-case.h`` contains a series of declarations and
+ * kernel-doc comments. The expected kernel-doc output can be
+ * found at ``test-case.rst.expected``.
+ */
+
+/**
+ * typedef void_func_ptr - pointer to a function
+ * @a: first argument
+ * @b: second argument
+ */
+typedef void (*void_func_ptr)(int a, struct struct_name1 *b);
+
+/**
+ * typedef int_ptr_func_ptr - a pointer to a function returning a pointer
+ * @a: argument
+ */
+typedef int *(*int_ptr_func_ptr)(int a);
+
+/**
+ * typedef func_par - a function, with parenthesis
+ * @a: argument
+ *
+ * A typedef for a function type (not a function pointer), wit
+ * parenthesis around the function name.
+ */
+typedef void (func_par)(int a);
+
+/**
+ * struct struct_name1 - a struct
+ * @i: an int field
+ * @j: an int pointer
+ * @u: a union field
+ * @sptr: pointer to a `struct_name1`
+ *
+ * A simple struct with multiple fields.
+ *
+ * Here's a reference to another struct type: &struct struct_name2.
+ */
+struct struct_name1 {
+	int i, *j;
+	union {
+		int i;
+		const char *s;
+	} u;
+	struct struct_name1 *sptr;
+	/**
+	 * @field_with_inline_doc: another way to document struct fields
+	 *
+	 * This field is documented inside the struct definition,
+	 * closer to the field declaration instead the doc comment at
+	 * the top.
+	 */
+	int field_with_inline_doc;
+	/**
+	 * @func: a function pointer
+	 *
+	 * Parsing a function pointer field involves some tricks to handle
+	 * the commas properly.
+	 */
+	int (*func)(int x, struct struct_name1 *p);
+	/** @bitmap: a bitmap */
+	DECLARE_BITMAP(bitmap, 128);
+};
+
+/**
+ * struct struct_name2 - another struct
+ * @x: first field
+ * @y: second field
+ * @another: another struct
+ *
+ * This struct is defined inside a typedef declaration.
+ */
+typedef struct struct_name2 {
+	int x, y;
+	struct struct_name1 another;
+} struct_name2;
+
+/**
+ * radix_tree_lookup_slot - lookup a slot in a radix tree
+ * @root:		radix tree root
+ * @index:	 index key
+ *
+ * Returns:  the slot corresponding to the position @index in the
+ * radix tree @root. This is useful for update-if-exists operations.
+ *
+ * This function can be called under rcu_read_lock iff the slot is not
+ * modified by radix_tree_replace_slot(), otherwise it must be called
+ * exclusive from other writers. Any dereference of the slot must be done
+ * using radix_tree_deref_slot().
+ *
+ * We used to have a problem with multiple ``*`` in the return type, and
+ * we've also had problems with adornments like __rcu).
+ */
+void __rcu **radix_tree_lookup_slot(const struct radix_tree_root *root,
+					unsigned long index)
+{ }
+
+/**
+ * SOME_MACRO - a macro that takes a few arguments
+ * @a: first argument
+ * @b: second argument
+ */
+#define SOME_MACRO(a, b) \
+	{ multi_line_macro_definition(a); \
+	  second_line(b); \
+	}
diff --git a/tools/testing/kernel-doc/test-case.man.expected b/tools/testing/kernel-doc/test-case.man.expected
new file mode 100644
index 0000000000000..6be2583469f04
--- /dev/null
+++ b/tools/testing/kernel-doc/test-case.man.expected
@@ -0,0 +1,150 @@
+.TH "Kernel API" 9 "Kernel API" "August 1991" "API Manual" LINUX
+.SH "kernel-doc test case"
+``test-case.h contains a series of declarations and
+kernel-doc comments. The expected kernel-doc output can be
+found at test-case.rst.expected``.
+.TH "void_func_ptr" 9 "void_func_ptr" "August 1991" "Kernel Hacker's Manual" LINUX
+.SH NAME
+void_func_ptr \- pointer to a function
+.SH SYNOPSIS
+.B "void" void_func_ptr
+.BI "(int a "  ","
+.BI "struct struct_name1 *b "  ");"
+.SH ARGUMENTS
+.IP "a" 12
+first argument
+.IP "b" 12
+second argument
+.TH "int_ptr_func_ptr" 9 "int_ptr_func_ptr" "August 1991" "Kernel Hacker's Manual" LINUX
+.SH NAME
+int_ptr_func_ptr \- a pointer to a function returning a pointer
+.SH SYNOPSIS
+.B "int *" int_ptr_func_ptr
+.BI "(int a "  ");"
+.SH ARGUMENTS
+.IP "a" 12
+argument
+.TH "func_par" 9 "func_par" "August 1991" "Kernel Hacker's Manual" LINUX
+.SH NAME
+func_par \- a function, with parenthesis
+.SH SYNOPSIS
+.B "void" func_par
+.BI "(int a "  ");"
+.SH ARGUMENTS
+.IP "a" 12
+argument
+.SH "DESCRIPTION"
+A typedef for a function type (not a function pointer), wit
+parenthesis around the function name.
+.TH "Kernel API" 9 "struct struct_name1" "August 1991" "API Manual" LINUX
+.SH NAME
+struct struct_name1 \- a struct
+.SH SYNOPSIS
+struct struct_name1 {
+.br
+.BI "    int i, *j;"
+.br
+.BI "    union {"
+.br
+.BI "      int i;"
+.br
+.BI "      const char *s;"
+.br
+.BI "    } u;"
+.br
+.BI "    struct struct_name1 *sptr;"
+.br
+.BI "    int field_with_inline_doc;"
+.br
+.BI "    int (*func)(int x, struct struct_name1 *p);"
+.br
+.BI "    unsigned long bitmap[BITS_TO_LONGS(128)];"
+.br
+.BI "
+};
+.br
+
+.SH Members
+.IP "i" 12
+an int field
+.IP "j" 12
+an int pointer
+.IP "u" 12
+a union field
+.IP "sptr" 12
+pointer to a `struct_name1`
+.IP "field_with_inline_doc" 12
+another way to document struct fields
+
+This field is documented inside the struct definition,
+closer to the field declaration instead the doc comment at
+the top.
+.IP "func" 12
+a function pointer
+
+Parsing a function pointer field involves some tricks to handle
+the commas properly.
+.IP "bitmap" 12
+a bitmap 
+.SH "Description"
+A simple struct with multiple fields.
+
+Here's a reference to another struct type: \fIstruct struct_name2\fP.
+.TH "Kernel API" 9 "struct struct_name2" "August 1991" "API Manual" LINUX
+.SH NAME
+struct struct_name2 \- another struct
+.SH SYNOPSIS
+struct struct_name2 {
+.br
+.BI "    int x, y;"
+.br
+.BI "    struct struct_name1 another;"
+.br
+.BI "
+};
+.br
+
+.SH Members
+.IP "x" 12
+first field
+.IP "y" 12
+second field
+.IP "another" 12
+another struct
+.SH "Description"
+This struct is defined inside a typedef declaration.
+.TH "radix_tree_lookup_slot" 9 "radix_tree_lookup_slot" "August 1991" "Kernel Hacker's Manual" LINUX
+.SH NAME
+radix_tree_lookup_slot \- lookup a slot in a radix tree
+.SH SYNOPSIS
+.B "void __rcu **" radix_tree_lookup_slot
+.BI "(const struct radix_tree_root *root "  ","
+.BI "unsigned long index "  ");"
+.SH ARGUMENTS
+.IP "root" 12
+radix tree root
+.IP "index" 12
+index key
+.SH "RETURN"
+the slot corresponding to the position \fIindex\fP in the
+radix tree \fIroot\fP. This is useful for update-if-exists operations.
+.SH "DESCRIPTION"
+This function can be called under rcu_read_lock iff the slot is not
+modified by \fBradix_tree_replace_slot\fP, otherwise it must be called
+exclusive from other writers. Any dereference of the slot must be done
+using \fBradix_tree_deref_slot\fP.
+
+We used to have a problem with multiple ``*`` in the return type, and
+we've also had problems with adornments like __rcu).
+.TH "SOME_MACRO" 9 "SOME_MACRO" "August 1991" "Kernel Hacker's Manual" LINUX
+.SH NAME
+SOME_MACRO \- a macro that takes a few arguments
+.SH SYNOPSIS
+.B "SOME_MACRO
+.BI "(a "  ","
+.BI "b "  ");"
+.SH ARGUMENTS
+.IP "a" 12
+first argument
+.IP "b" 12
+second argument
diff --git a/tools/testing/kernel-doc/test-case.none.expected b/tools/testing/kernel-doc/test-case.none.expected
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git a/tools/testing/kernel-doc/test-case.rst2.expected b/tools/testing/kernel-doc/test-case.rst2.expected
new file mode 100644
index 0000000000000..66ae737a808f2
--- /dev/null
+++ b/tools/testing/kernel-doc/test-case.rst2.expected
@@ -0,0 +1,195 @@
+**kernel-doc test case**
+
+
+``test-case.h`` contains a series of declarations and
+kernel-doc comments. The expected kernel-doc output can be
+found at ``test-case.rst.expected``.
+
+.. c:macro:: void_func_ptr
+
+   **Typedef**: pointer to a function
+
+
+**Syntax**
+
+  ``void void_func_ptr (int a, struct struct_name1 *b)``
+
+**Parameters**
+
+``int a``
+  first argument
+
+``struct struct_name1 *b``
+  second argument
+
+
+.. c:macro:: int_ptr_func_ptr
+
+   **Typedef**: a pointer to a function returning a pointer
+
+
+**Syntax**
+
+  ``int * int_ptr_func_ptr (int a)``
+
+**Parameters**
+
+``int a``
+  argument
+
+
+.. c:macro:: func_par
+
+   **Typedef**: a function, with parenthesis
+
+
+**Syntax**
+
+  ``void func_par (int a)``
+
+**Parameters**
+
+``int a``
+  argument
+
+**Description**
+
+A typedef for a function type (not a function pointer), wit
+parenthesis around the function name.
+
+
+
+
+.. c:struct:: struct_name1
+
+   a struct
+
+**Definition**
+
+::
+
+  struct struct_name1 {
+    int i, *j;
+    union {
+      int i;
+      const char *s;
+    } u;
+    struct struct_name1 *sptr;
+    int field_with_inline_doc;
+    int (*func)(int x, struct struct_name1 *p);
+    unsigned long bitmap[BITS_TO_LONGS(128)];
+  };
+
+**Members**
+
+``i``
+  an int field
+
+``j``
+  an int pointer
+
+``u``
+  a union field
+
+``sptr``
+  pointer to a `struct_name1`
+
+``field_with_inline_doc``
+  another way to document struct fields
+  
+  This field is documented inside the struct definition,
+  closer to the field declaration instead the doc comment at
+  the top.
+
+``func``
+  a function pointer
+  
+  Parsing a function pointer field involves some tricks to handle
+  the commas properly.
+
+``bitmap``
+  a bitmap 
+
+
+**Description**
+
+A simple struct with multiple fields.
+
+Here's a reference to another struct type: :c:type:`struct struct_name2 <struct_name2>`.
+
+
+
+
+.. c:struct:: struct_name2
+
+   another struct
+
+**Definition**
+
+::
+
+  struct struct_name2 {
+    int x, y;
+    struct struct_name1 another;
+  };
+
+**Members**
+
+``x``
+  first field
+
+``y``
+  second field
+
+``another``
+  another struct
+
+
+**Description**
+
+This struct is defined inside a typedef declaration.
+
+
+.. c:function:: void __rcu ** radix_tree_lookup_slot (const struct radix_tree_root *root, unsigned long index)
+
+   lookup a slot in a radix tree
+
+**Parameters**
+
+``const struct radix_tree_root *root``
+  radix tree root
+
+``unsigned long index``
+  index key
+
+**Return**
+
+the slot corresponding to the position **index** in the
+radix tree **root**. This is useful for update-if-exists operations.
+
+**Description**
+
+This function can be called under rcu_read_lock iff the slot is not
+modified by radix_tree_replace_slot(), otherwise it must be called
+exclusive from other writers. Any dereference of the slot must be done
+using radix_tree_deref_slot().
+
+We used to have a problem with multiple ``*`` in the return type, and
+we've also had problems with adornments like __rcu).
+
+
+.. c:macro:: SOME_MACRO
+
+``SOME_MACRO (a, b)``
+
+   a macro that takes a few arguments
+
+**Parameters**
+
+``a``
+  first argument
+
+``b``
+  second argument
+
+
diff --git a/tools/testing/kernel-doc/test-case.rst3.expected b/tools/testing/kernel-doc/test-case.rst3.expected
new file mode 100644
index 0000000000000..66ae737a808f2
--- /dev/null
+++ b/tools/testing/kernel-doc/test-case.rst3.expected
@@ -0,0 +1,195 @@
+**kernel-doc test case**
+
+
+``test-case.h`` contains a series of declarations and
+kernel-doc comments. The expected kernel-doc output can be
+found at ``test-case.rst.expected``.
+
+.. c:macro:: void_func_ptr
+
+   **Typedef**: pointer to a function
+
+
+**Syntax**
+
+  ``void void_func_ptr (int a, struct struct_name1 *b)``
+
+**Parameters**
+
+``int a``
+  first argument
+
+``struct struct_name1 *b``
+  second argument
+
+
+.. c:macro:: int_ptr_func_ptr
+
+   **Typedef**: a pointer to a function returning a pointer
+
+
+**Syntax**
+
+  ``int * int_ptr_func_ptr (int a)``
+
+**Parameters**
+
+``int a``
+  argument
+
+
+.. c:macro:: func_par
+
+   **Typedef**: a function, with parenthesis
+
+
+**Syntax**
+
+  ``void func_par (int a)``
+
+**Parameters**
+
+``int a``
+  argument
+
+**Description**
+
+A typedef for a function type (not a function pointer), wit
+parenthesis around the function name.
+
+
+
+
+.. c:struct:: struct_name1
+
+   a struct
+
+**Definition**
+
+::
+
+  struct struct_name1 {
+    int i, *j;
+    union {
+      int i;
+      const char *s;
+    } u;
+    struct struct_name1 *sptr;
+    int field_with_inline_doc;
+    int (*func)(int x, struct struct_name1 *p);
+    unsigned long bitmap[BITS_TO_LONGS(128)];
+  };
+
+**Members**
+
+``i``
+  an int field
+
+``j``
+  an int pointer
+
+``u``
+  a union field
+
+``sptr``
+  pointer to a `struct_name1`
+
+``field_with_inline_doc``
+  another way to document struct fields
+  
+  This field is documented inside the struct definition,
+  closer to the field declaration instead the doc comment at
+  the top.
+
+``func``
+  a function pointer
+  
+  Parsing a function pointer field involves some tricks to handle
+  the commas properly.
+
+``bitmap``
+  a bitmap 
+
+
+**Description**
+
+A simple struct with multiple fields.
+
+Here's a reference to another struct type: :c:type:`struct struct_name2 <struct_name2>`.
+
+
+
+
+.. c:struct:: struct_name2
+
+   another struct
+
+**Definition**
+
+::
+
+  struct struct_name2 {
+    int x, y;
+    struct struct_name1 another;
+  };
+
+**Members**
+
+``x``
+  first field
+
+``y``
+  second field
+
+``another``
+  another struct
+
+
+**Description**
+
+This struct is defined inside a typedef declaration.
+
+
+.. c:function:: void __rcu ** radix_tree_lookup_slot (const struct radix_tree_root *root, unsigned long index)
+
+   lookup a slot in a radix tree
+
+**Parameters**
+
+``const struct radix_tree_root *root``
+  radix tree root
+
+``unsigned long index``
+  index key
+
+**Return**
+
+the slot corresponding to the position **index** in the
+radix tree **root**. This is useful for update-if-exists operations.
+
+**Description**
+
+This function can be called under rcu_read_lock iff the slot is not
+modified by radix_tree_replace_slot(), otherwise it must be called
+exclusive from other writers. Any dereference of the slot must be done
+using radix_tree_deref_slot().
+
+We used to have a problem with multiple ``*`` in the return type, and
+we've also had problems with adornments like __rcu).
+
+
+.. c:macro:: SOME_MACRO
+
+``SOME_MACRO (a, b)``
+
+   a macro that takes a few arguments
+
+**Parameters**
+
+``a``
+  first argument
+
+``b``
+  second argument
+
+
diff --git a/tools/testing/kernel-doc/test.sh b/tools/testing/kernel-doc/test.sh
new file mode 100755
index 0000000000000..37042c5453823
--- /dev/null
+++ b/tools/testing/kernel-doc/test.sh
@@ -0,0 +1,90 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+# Copyright (c) 2020, Red Hat Inc.
+# Author: Eduardo Habkost <ehabkost@redhat.com>
+#
+# Black box test script for kernel-doc
+
+set -e
+mydir="$(dirname "$0")"
+
+usage()
+{
+    echo "Usage: $0 [--refresh] [--kernel-doc KERNELDOC_BINARY]"
+}
+
+refresh=no
+kerneldoc="$mydir/../../../scripts/kernel-doc"
+while [ "$#" -gt 0 ];do
+    case "$1" in
+        -h|--help)
+            usage
+            exit 0
+        ;;
+        --refresh)
+            refresh=yes
+            shift
+        ;;
+        --kernel-doc)
+            shift
+            kerneldoc="$1"
+            shift
+        ;;
+        *)
+            echo "Invalid argument: $1" >&2
+            usage >&2
+            exit 1
+        ;;
+    esac
+done
+
+tmp="$(mktemp -d)"
+trap 'rm -rf "$tmp"' EXIT
+
+test()
+{
+    local suffix="$1"
+    shift
+
+    if ! "$kerneldoc" "$@" "$mydir/test-case.h" \
+         > "$tmp/test-case.$suffix.actual" \
+         2> "$tmp/test-case.$suffix.stderr" || \
+       [ -s "$tmp/test-case.$suffix.stderr" ];then
+        cat "$tmp/test-case.$suffix.stderr" >&2
+        echo "$suffix: kernel-doc $* failed" >&2
+        return 1
+    fi
+
+    if diff -u "$mydir/test-case.$suffix.expected" \
+               "$tmp/test-case.$suffix.actual";then
+        echo "$suffix: OK" >&2
+    else
+        echo "kernel-doc output mismatch for: $*" >&2
+        if [ "$refresh" = yes ];then
+            cp "$tmp/test-case.$suffix.actual" \
+              "$mydir/test-case.$suffix.expected"
+        fi
+        return 1
+    fi
+}
+
+if [ ! -x "$kerneldoc" ];then
+    echo "kernel-doc is not executable: $kerneldoc" >&2
+    exit 1
+fi
+
+# the -man output includes the build date
+export KBUILD_BUILD_TIMESTAMP=1991-08-25
+
+ok=yes
+
+# don't even try to test other formats if -none fails:
+test none -none || exit 1
+
+test rst2 -rst -sphinx-version 3.0.0 || ok=no
+test rst3 -rst -sphinx-version 3.0.0 || ok=no
+test man -man || ok=no
+
+if [ "$ok" != "yes" ];then
+    exit 1
+fi
-- 
2.28.0


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

* Re: [RFC] Add kernel-doc test script
  2020-11-17 22:36           ` [RFC] Add kernel-doc test script Eduardo Habkost
@ 2020-11-18  0:23             ` Randy Dunlap
  2020-11-18 13:03               ` Eduardo Habkost
  2020-11-18  8:21             ` Paolo Bonzini
  2020-11-18 16:27             ` Jonathan Corbet
  2 siblings, 1 reply; 17+ messages in thread
From: Randy Dunlap @ 2020-11-18  0:23 UTC (permalink / raw)
  To: Eduardo Habkost, Matthew Wilcox
  Cc: Jonathan Corbet, Paolo Bonzini, linux-kernel, linux-doc

On 11/17/20 2:36 PM, Eduardo Habkost wrote:
> Add a kernel-doc test script to tools/testing/kernel-doc.
> 
> radix_tree_lookup_slot test case provided by Matthew Wilcox.
> 
> Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>

Very good idea.

I have had a kernel-doc test source file for (?) 10-12 years,
while I was the docs maintainer.

I didn't have the "expected" files for comparison.
I just used $web_browser.

> ---
>  tools/testing/kernel-doc/test-case.h          | 111 ++++++++++
>  .../testing/kernel-doc/test-case.man.expected | 150 ++++++++++++++
>  .../kernel-doc/test-case.none.expected        |   0
>  .../kernel-doc/test-case.rst2.expected        | 195 ++++++++++++++++++
>  .../kernel-doc/test-case.rst3.expected        | 195 ++++++++++++++++++
>  tools/testing/kernel-doc/test.sh              |  90 ++++++++
>  6 files changed, 741 insertions(+)
>  create mode 100644 tools/testing/kernel-doc/test-case.h
>  create mode 100644 tools/testing/kernel-doc/test-case.man.expected
>  create mode 100644 tools/testing/kernel-doc/test-case.none.expected
>  create mode 100644 tools/testing/kernel-doc/test-case.rst2.expected
>  create mode 100644 tools/testing/kernel-doc/test-case.rst3.expected
>  create mode 100755 tools/testing/kernel-doc/test.sh

thanks.
-- 
~Randy


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

* Re: [RFC] Add kernel-doc test script
  2020-11-17 22:36           ` [RFC] Add kernel-doc test script Eduardo Habkost
  2020-11-18  0:23             ` Randy Dunlap
@ 2020-11-18  8:21             ` Paolo Bonzini
  2020-11-18 12:05               ` Eduardo Habkost
  2020-11-18 16:27             ` Jonathan Corbet
  2 siblings, 1 reply; 17+ messages in thread
From: Paolo Bonzini @ 2020-11-18  8:21 UTC (permalink / raw)
  To: Eduardo Habkost, Matthew Wilcox; +Cc: Jonathan Corbet, linux-kernel, linux-doc

On 17/11/20 23:36, Eduardo Habkost wrote:
> +# the -man output includes the build date
> +export KBUILD_BUILD_TIMESTAMP=1991-08-25

Nice :)

> +ok=yes
> +
> +# don't even try to test other formats if -none fails:
> +test none -none || exit 1
> +
> +test rst2 -rst -sphinx-version 3.0.0 || ok=no

Do you want 3.0.0 here too?

> +test rst3 -rst -sphinx-version 3.0.0 || ok=no
> +test man -man || ok=no

Also since you are at it you might as well rename the function to 
something other than "test", it's a bit confusing due to the "test" 
shell builtin.

Paolo


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

* Re: [RFC] Add kernel-doc test script
  2020-11-18  8:21             ` Paolo Bonzini
@ 2020-11-18 12:05               ` Eduardo Habkost
  0 siblings, 0 replies; 17+ messages in thread
From: Eduardo Habkost @ 2020-11-18 12:05 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: Matthew Wilcox, Jonathan Corbet, linux-kernel, linux-doc

On Wed, Nov 18, 2020 at 09:21:11AM +0100, Paolo Bonzini wrote:
> On 17/11/20 23:36, Eduardo Habkost wrote:
> > +# the -man output includes the build date
> > +export KBUILD_BUILD_TIMESTAMP=1991-08-25
> 
> Nice :)
> 
> > +ok=yes
> > +
> > +# don't even try to test other formats if -none fails:
> > +test none -none || exit 1
> > +
> > +test rst2 -rst -sphinx-version 3.0.0 || ok=no
> 
> Do you want 3.0.0 here too?

Oops!  No!  I'll fix it.

> 
> > +test rst3 -rst -sphinx-version 3.0.0 || ok=no
> > +test man -man || ok=no
> 
> Also since you are at it you might as well rename the function to something
> other than "test", it's a bit confusing due to the "test" shell builtin.

Good point.  I'll do.

-- 
Eduardo


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

* Re: [RFC] Add kernel-doc test script
  2020-11-18  0:23             ` Randy Dunlap
@ 2020-11-18 13:03               ` Eduardo Habkost
  2020-11-18 16:32                 ` Randy Dunlap
  0 siblings, 1 reply; 17+ messages in thread
From: Eduardo Habkost @ 2020-11-18 13:03 UTC (permalink / raw)
  To: Randy Dunlap
  Cc: Matthew Wilcox, Jonathan Corbet, Paolo Bonzini, linux-kernel, linux-doc

On Tue, Nov 17, 2020 at 04:23:49PM -0800, Randy Dunlap wrote:
> On 11/17/20 2:36 PM, Eduardo Habkost wrote:
> > Add a kernel-doc test script to tools/testing/kernel-doc.
> > 
> > radix_tree_lookup_slot test case provided by Matthew Wilcox.
> > 
> > Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
> 
> Very good idea.
> 
> I have had a kernel-doc test source file for (?) 10-12 years,
> while I was the docs maintainer.

Is that test source file recoverable somewhere?  It probably has
useful test cases not included here.

-- 
Eduardo


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

* Re: [RFC] Add kernel-doc test script
  2020-11-17 22:36           ` [RFC] Add kernel-doc test script Eduardo Habkost
  2020-11-18  0:23             ` Randy Dunlap
  2020-11-18  8:21             ` Paolo Bonzini
@ 2020-11-18 16:27             ` Jonathan Corbet
  2 siblings, 0 replies; 17+ messages in thread
From: Jonathan Corbet @ 2020-11-18 16:27 UTC (permalink / raw)
  To: Eduardo Habkost; +Cc: Matthew Wilcox, Paolo Bonzini, linux-kernel, linux-doc

On Tue, 17 Nov 2020 17:36:12 -0500
Eduardo Habkost <ehabkost@redhat.com> wrote:

> Add a kernel-doc test script to tools/testing/kernel-doc.
> 
> radix_tree_lookup_slot test case provided by Matthew Wilcox.
> 
> Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
> ---
>  tools/testing/kernel-doc/test-case.h          | 111 ++++++++++
>  .../testing/kernel-doc/test-case.man.expected | 150 ++++++++++++++
>  .../kernel-doc/test-case.none.expected        |   0
>  .../kernel-doc/test-case.rst2.expected        | 195 ++++++++++++++++++
>  .../kernel-doc/test-case.rst3.expected        | 195 ++++++++++++++++++
>  tools/testing/kernel-doc/test.sh              |  90 ++++++++
>  6 files changed, 741 insertions(+)
>  create mode 100644 tools/testing/kernel-doc/test-case.h
>  create mode 100644 tools/testing/kernel-doc/test-case.man.expected
>  create mode 100644 tools/testing/kernel-doc/test-case.none.expected
>  create mode 100644 tools/testing/kernel-doc/test-case.rst2.expected
>  create mode 100644 tools/testing/kernel-doc/test-case.rst3.expected
>  create mode 100755 tools/testing/kernel-doc/test.sh

Seems like a good thing to have overall.

I do worry a bit that the test will be sensitive to *any* change to
kernel-doc output, including formatting changes that might be deliberate.
But if that turns out to be a problem in the real world, we can deal with
it then.

Thanks,

jon

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

* Re: [RFC] Add kernel-doc test script
  2020-11-18 13:03               ` Eduardo Habkost
@ 2020-11-18 16:32                 ` Randy Dunlap
  2020-11-18 16:57                   ` Eduardo Habkost
  0 siblings, 1 reply; 17+ messages in thread
From: Randy Dunlap @ 2020-11-18 16:32 UTC (permalink / raw)
  To: Eduardo Habkost
  Cc: Matthew Wilcox, Jonathan Corbet, Paolo Bonzini, linux-kernel, linux-doc

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

On 11/18/20 5:03 AM, Eduardo Habkost wrote:
> On Tue, Nov 17, 2020 at 04:23:49PM -0800, Randy Dunlap wrote:
>> On 11/17/20 2:36 PM, Eduardo Habkost wrote:
>>> Add a kernel-doc test script to tools/testing/kernel-doc.
>>>
>>> radix_tree_lookup_slot test case provided by Matthew Wilcox.
>>>
>>> Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
>>
>> Very good idea.
>>
>> I have had a kernel-doc test source file for (?) 10-12 years,
>> while I was the docs maintainer.
> 
> Is that test source file recoverable somewhere?  It probably has
> useful test cases not included here.

Sure.  Of course, it may be out of date by quite a bit.
I last updated it in 2016:
-rw-r--r-- 1 rdunlap users  41737 Jun 17  2016 megatest.c

(attached)

-- 
~Randy


[-- Attachment #2: megatest.c --]
[-- Type: text/x-csrc, Size: 41737 bytes --]

/**
 * struct my_struct - short description
 * @a: first member
 * @b: second member
 *
 * Longer description
 */
struct my_struct {
    int a;
    int b;
/* private: */
    int c;
};

struct scan_channel;
/**
 * struct scan_params - describes scan parameters
 * @n_channels: number of items in @channels array or -1 to indicate all
 *      channels should be scanned (in that case @channels will be %NULL)
 * @active: when n_channels is -1 this determines active/passive scanning.
 * @phymode: when n_channels is -1 this determines PHY mode to scan. It is
 *      not possible to scan different PHY modes in one request w/o giving
 *      a channel list.
 * @channels: array containing @n_channels &scan_channel items
 */
struct scan_params {
	int n_channels;
	int active;
	int phymode;
	struct scan_channel *channels;
};

/**
 * typedef __kernel_fd_set - set of file descriptor bits
 * @fds_bits: bitmask for all file descriptors, used in poll/select
 */
typedef struct {
	unsigned long fds_bits [__FDSET_LONGS]; // what prints this out?
} __kernel_fd_set;

/**
 * typedef __kernel_sighandler_t - Type of a signal handler.
 */
typedef void (*__kernel_sighandler_t)(int);

/**
 * typedef __kernel_key_t - Type of a SYSV IPC key.
 */
typedef int __kernel_key_t;


/**
 * typedef cpumask_var_t - type of a struct cpumask on-stack array
 */
typedef struct cpumask cpumask_var_t[1];

/**
 * typedef note_buf_t - type for kexec kernel crash note buffer
 */
typedef u32 note_buf_t[KEXEC_NOTE_BYTES/4];

/**
 * typedef nfs4_verifier - struct for NFS4 verifier data
 */
typedef struct { char data[NFS4_VERIFIER_SIZE]; } nfs4_verifier;

/**
 * typedef match_table_t - type for file options parser match_token table
 */
typedef struct match_token match_table_t[];


/**
 * struct acpi_interrupt_flags - with bitfields
 * @polarity: active high or active low
 * @trigger: edge or level triggered
 * @reserved: not used
 */
struct acpi_interrupt_flags {
	u16			polarity:2;
	u16			trigger:2;
	u16			reserved:12;
} __attribute__ ((packed));

/**
 * typedef phys_drive_t - physical device information
 * @type	: Type of the device
 * @cur_status	: current status of the device
 * @tag_depth	: Level of tagging
 * @sync_neg	: sync negotiation - ENABLE or DISBALE
 * @size	: configurable size in terms of 512 byte
 */
typedef struct {
	uint8_t		type;
	uint8_t		cur_status;
	uint8_t		tag_depth;
	uint8_t		sync_neg;
	uint32_t	size;
}__attribute__ ((packed)) phys_drive_t;

/**
 * mraid_mm_open - open routine for char node interface
 * @inode	: unused, but never the same as &filep
 * @filep	: unused, but never the same as &inodep
 *
 * Allow ioctl operations by apps only if they have superuser privilege.
 * Returns %0 on success, -%EACCES on error.
 * Never uses $ENV variables.
 */
static int // strip C99-comment
mraid_mm_open(struct inode *inode, struct file *filep)
// drop entire line
{
}

/**
 * megaraid_queue_command - generic queue entry point for all LLDs
 * @scp		: pointer to the scsi command to be executed
 * @done	: callback routine to be called after the cmd has be completed
 *
 * Queue entry point for mailbox based controllers.
 */
static int
megaraid_queue_command(struct scsi_cmnd *scp, void (* done)(struct scsi_cmnd *))
{
}

struct sub_channels {
	unsigned int	flags;
	int		max_size;
	int		cur_size;
};

/**
 * struct channels - struct for testing kernel-doc
 * @n_sub_channels: number of &struct sub_channels pointers included
 * @flags: flags for all channels
 * @reserved: not yet used
 * @sub_channels: the sub-channels
 */
struct channels {
	int n_sub_channels;
	unsigned int flags;
	int reserved;
	struct sub_channels *sub_channels;
};

/**
 * clk_get - lookup and obtain a reference to a clock producer.
 * @dev: device for clock "consumer"
 * @id: clock consumer ID
 *
 * Returns a &struct clk corresponding to the clock producer, or
 * valid IS_ERR() condition containing errno.  The implementation
 * uses @dev and @id to determine the clock consumer, and thereby
 * the clock producer.  (IOW, @id may be identical strings, but
 * clk_get may return different clock producers depending on @dev.)
 *
 * Drivers must assume that the clock source is not enabled.
 *
 * Returns %NULL if a reference is not obtained.  (for kernel-doc testing only.)
 * However, if $CLKTEST is non-%NULL, some random value is returned.
 */
struct clk *clk_get(struct device *dev, const char *id);

/** 
 *	struct sk_buff - socket buffer
 *	@next: Next buffer in list
 *	@prev: Previous buffer in list
 *	@sk: Socket we are owned by
 *	@tstamp: Time we arrived
 *	@dev: Device we arrived on/are leaving by
 *	@iif: ifindex of device we arrived on
 *	@transport_header: Transport layer header
 *	@network_header: Network layer header
 *	@mac_header: Link layer header
 *	@dst: destination entry
 *	@sp: the security path, used for xfrm
 *	@cb: Control buffer. Free for use by every layer. Put private vars here
 *	@len: Length of actual data
 *	@data_len: Data length
 *	@mac_len: Length of link layer header
 *	@csum: Checksum (must include start/offset pair)
 *	@csum_start: Offset from skb->head where checksumming should start
 *	@csum_offset: Offset from csum_start where checksum should be stored
 *	@local_df: allow local fragmentation
 *	@cloned: Head may be cloned (check refcnt to be sure)
 *	@nohdr: Payload reference only, must not modify header
 *	@pkt_type: Packet class
 *	@fclone: skbuff clone status
 *	@ip_summed: Driver fed us an IP checksum
 *	@priority: Packet queueing priority
 *	@users: User count - see {datagram,tcp}.c
 *	@protocol: Packet protocol from driver
 *	@truesize: Buffer size 
 *	@head: Head of buffer
 *	@data: Data head pointer
 *	@tail: Tail pointer
 *	@end: End pointer
 *	@destructor: Destruct function
 *	@mark: Generic packet mark
 *	@nfct: Associated connection, if any
 *	@ipvs_property: skbuff is owned by ipvs
 *	@nfctinfo: Relationship of this skb to the connection
 *	@nfct_reasm: netfilter conntrack re-assembly pointer
 *	@nf_bridge: Saved data about a bridged frame - see br_netfilter.c
 *	@tc_index: Traffic control index
 *	@tc_verd: traffic control verdict
 *	@dma_cookie: a cookie to one of several possible DMA operations
 *		done by skb DMA functions
 *	@secmark: security marking
 */

struct sk_buff {
	/* These two members must be first. */
	struct sk_buff		*next;
	struct sk_buff		*prev;

	struct sock		*sk;
	ktime_t			tstamp;
	struct net_device	*dev;
	int			iif;
	/* 4 byte hole on 64 bit*/

	struct  dst_entry	*dst;
	struct	sec_path	*sp;

	/*
	 * This is the control buffer. It is free to use for every
	 * layer. Please put your private variables there. If you
	 * want to keep them across layers you have to do a skb_clone()
	 * first. This is owned by whoever has the skb queued ATM.
	 */
	char			cb[48];

	unsigned int		len,
				data_len,
				mac_len;
	union {		// fields inside structs/unions are not listed
		__wsum		csum;
		struct {
			__u16	csum_start;
			__u16	csum_offset;
		};
	};
	__u32			priority;
	__u8			local_df:1,
				cloned:1,
				ip_summed:2,
				nohdr:1,
				nfctinfo:3;
	__u8			pkt_type:3,
				fclone:2,
				ipvs_property:1;
	__be16			protocol;

	void			(*destructor)(struct sk_buff *skb);
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
	struct nf_conntrack	*nfct;
	struct sk_buff		*nfct_reasm;
#endif
#ifdef CONFIG_BRIDGE_NETFILTER
	struct nf_bridge_info	*nf_bridge;
#endif
#ifdef CONFIG_NET_SCHED
	__u16			tc_index;	/* traffic control index */
#ifdef CONFIG_NET_CLS_ACT
	__u16			tc_verd;	/* traffic control verdict */
#endif
#endif
#ifdef CONFIG_NET_DMA
	dma_cookie_t		dma_cookie;
#endif
#ifdef CONFIG_NETWORK_SECMARK
	__u32			secmark;
#endif

	__u32			mark;

	// layers headers:
	sk_buff_data_t		transport_header;
	sk_buff_data_t		network_header;
	sk_buff_data_t		mac_header;
	/* These elements must be at the end, see alloc_skb() for details.  */
	sk_buff_data_t		tail;
	sk_buff_data_t		end;
	unsigned char		*head,
				*data;
	unsigned int		truesize;
	atomic_t		users;
};

/**
 * struct anon_test - test anon struct/union ending lines
 * @last_field: last field in the struct
 */
struct anon_test {
	union {		// fields inside structs/unions are not listed
		__wsum		csum;
		__wsum		zeta;
		__u32		beta;
	};
	int			last_field;
};

/**
 * struct anon_test2 - test anon struct/union ending lines
 * @some_field: some field in the struct
 */
struct anon_test2 {
	int			some_field;
	union {		// fields inside structs/unions are not listed
		__wsum		csum;
		__wsum		zeta;
		__u32		beta;
	};
};

/**
 * el1_probe - probe for a 3c501
 * @unit: device number
 *
 * This can be called from two places. The network layer will probe using
 * a device structure passed in with the probe information completed. For a
 * modular driver we use #init_module to fill in our own structure and probe
 * for it.
 *
 * Returns 0 on success. ENXIO if asked not to probe and ENODEV if asked to
 * probe and failing to find anything.
 */
struct net_device * __init el1_probe(int unit)
{
}

/**
 *	parport_register_device - register a device on a parallel port
 *	@port: port to which the device is attached
 *	@name: a name to refer to the device
 *	@pf: preemption callback
 *	@kf: kick callback (wake-up)
 *	@irq_func: interrupt handler
 *	@flags: registration flags
 *	@handle: data for callback functions
 *
 *	This function, called by parallel port device drivers,
 *	declares that a device is connected to a port, and tells the
 *	system all it needs to know.
 *
 *	The @name is allocated by the caller and must not be
 *	deallocated until the caller calls @parport_unregister_device
 *	for that device.
 *
 *	The preemption callback function, @pf, is called when this
 *	device driver has claimed access to the port but another
 *	device driver wants to use it.  It is given @handle as its
 *	parameter, and should return zero if it is willing for the
 *	system to release the port to another driver on its behalf.
 *	If it wants to keep control of the port it should return
 *	non-zero, and no action will be taken.  It is good manners for
 *	the driver to try to release the port at the earliest
 *	opportunity after its preemption callback rejects a preemption
 *	attempt.  Note that if a preemption callback is happy for
 *	preemption to go ahead, there is no need to release the port;
 *	it is done automatically.  This function may not block, as it
 *	may be called from interrupt context.  If the device driver
 *	does not support preemption, @pf can be %NULL.
 *
 *	The wake-up ("kick") callback function, @kf, is called when
 *	the port is available to be claimed for exclusive access; that
 *	is, parport_claim() is guaranteed to succeed when called from
 *	inside the wake-up callback function.  If the driver wants to
 *	claim the port it should do so; otherwise, it need not take
 *	any action.  This function may not block, as it may be called
 *	from interrupt context.  If the device driver does not want to
 *	be explicitly invited to claim the port in this way, @kf can
 *	be %NULL.
 *
 *	The interrupt handler, @irq_func, is called when an interrupt
 *	arrives from the parallel port.  Note that if a device driver
 *	wants to use interrupts it should use parport_enable_irq(),
 *	and can also check the irq member of the parport structure
 *	representing the port.
 *
 *	The parallel port (lowlevel) driver is the one that has called
 *	request_irq() and whose interrupt handler is called first.
 *	This handler does whatever needs to be done to the hardware to
 *	acknowledge the interrupt (for PC-style ports there is nothing
 *	special to be done).  It then tells the IEEE 1284 code about
 *	the interrupt, which may involve reacting to an IEEE 1284
 *	event depending on the current IEEE 1284 phase.  After this,
 *	it calls @irq_func.  Needless to say, @irq_func will be called
 *	from interrupt context, and may not block.
 *
 *	The %PARPORT_DEV_EXCL flag is for preventing port sharing, and
 *	so should only be used when sharing the port with other device
 *	drivers is impossible and would lead to incorrect behaviour.
 *	Use it sparingly!  Normally, @flags will be zero.
 *
 *	This function returns a pointer to a structure that represents
 *	the device on the port, or %NULL if there is not enough memory
 *	to allocate space for that structure.
 **/
struct pardevice *
parport_register_device(struct parport *port, const char *name,
			int (*pf)(void *), void (*kf)(void *),
			void (*irq_func)(int, void *), 
			int flags, void *handle)
{
}


/**
 * atomic_set - set atomic variable
 * @v: pointer of type atomic_t
 * @i: required value
 * 
 * Atomically sets the value of @v to @i.
 */ 
#define atomic_set(v,i)		(((v)->counter) = (i))

/**
 * atomic_set_varargs - set atomic variable
 * @v: pointer of type atomic_t
 * @i: required value
 * @...: more varargs
 * 
 * Atomically sets the value of @v to @i.
 */ 
#define atomic_set_varargs(v,i, ...)		(((v)->counter) = (i))


/**
 * ntfs_debug - write a debug level message to syslog
 * @f:		a printf format string containing the message
 * @...:	the variables to substitute into @f
 *
 * ntfs_debug() writes a DEBUG level message to the syslog but only if the
 * driver was compiled with -DDEBUG. Otherwise, the call turns into a NOP.
 */
static void ntfs_debug(const char *f, ...);


/**
 * __copy_to_user: - Copy a block of data into user space, with less checking.
 * @to:   Destination address, in user space.
 * @from: Source address, in kernel space.
 * @n:    Number of bytes to copy.
 *
 * Context: User context only.  This function may sleep.
 *
 * Copy data from kernel space to user space.  Caller must check
 * the specified block with access_ok() before calling this function.
 *
 * Returns number of bytes that could not be copied.
 * On success, this will be zero.
 */
static __always_inline unsigned long __must_check
__copy_to_user(void __user *to, const void *from, unsigned long n)
{
}


/**
 * pci_match_device - Tell if a PCI device structure has a matching PCI device id structure
 * @drv: the PCI driver to match against
 * @dev: the PCI device structure to match against
 *
 * Used by a driver to check whether a PCI device present in the
 * system is in its list of supported devices.  Returns the matching
 * pci_device_id structure or %NULL if there is no match.
 */
const struct pci_device_id *pci_match_device(struct pci_driver *drv,
					     struct pci_dev *dev)
{
}

/**
 * shost_for_each_device - iterate over all devices of a host
 * @sdev: the &struct scsi_device to use as a cursor
 * @shost: the &struct scsi_host to iterate over
 *
 * Iterator that returns each device attached to @shost.  This loop
 * takes a reference on each device and releases it at the end.  If
 * you break out of the loop, you must call scsi_device_put(sdev).
 */
#define shost_for_each_device(sdev, shost) \
	for ((sdev) = __scsi_iterate_devices((shost), NULL); \
	     (sdev); \
	     (sdev) = __scsi_iterate_devices((shost), (sdev)))

/**
 * __shost_for_each_device - iterate over all devices of a host (UNLOCKED)
 * @sdev: the &struct scsi_device to use as a cursor
 * @shost: the &struct scsi_host to iterate over
 *
 * Iterator that returns each device attached to @shost.  It does _not_
 * take a reference on the scsi_device, so the whole loop must be
 * protected by shost->host_lock.
 *
 * Note: The only reason to use this is because you need to access the
 * device list in interrupt context.  Otherwise you really want to use
 * shost_for_each_device instead.
 */
#define __shost_for_each_device(sdev, shost) \
	list_for_each_entry((sdev), &((shost)->__devices), siblings)

//BAD: TBD: try to detect this:
/**
 * scsi_devinfo: set up the dynamic device list.
 *
 * The short function description above is in invalid format and
 * is probably missing in the generated output.
 */
int scsi_devinfo(void)
{
}

/**
 * scsi_init_devinfo - set up the dynamic device list.
 *
 * Description:
 *
 * blank line1 above & below here should be kept as is, not deleted.
 *
 * 	Init all devinfo list entries and then add
 * 	scsi_static_device_list entries to the scsi device info list.
 *
 * blank line2 above & below here should be kept as is, not deleted.
 *
 **/
int __init scsi_init_devinfo(void)
{
}

/**
 *	vunmap  -  release virtual mapping obtained by vmap()
 *	@addr:		memory base address
 *
 *	Free the virtually contiguous memory area starting at @addr,
 *	which was created from the page array passed to vmap().
 *
 *	Must not be called in interrupt context.
 *
 *	Returns a pointer to the array of pointers to page structs
 */
struct page **vunmap(const void *addr)
{
	BUG_ON(in_interrupt());
	return __vunmap(addr, 0);
}

/**
 * blk_end_io - Generic end_io function to complete a request.
 * @rq:           the request being processed
 * @error:        0 for success, < 0 for error
 * @nr_bytes:     number of bytes to complete @rq
 * @bidi_bytes:   number of bytes to complete @rq->next_rq
 * @drv_callback: function called between completion of bios in the request
 *                and completion of the request.
 *                If the callback returns non 0, this helper returns without
 *                completion of the request.
 *
 * Description:
 *     Ends I/O on a number of bytes attached to @rq and @rq->next_rq.
 *     If @rq has leftover, sets it up for the next range of segments.
 *
 * Return:
 *     0 - we are done with this request
 *     1 - this request is not freed yet, it still has pending buffers.
 **/
static int blk_end_io(struct request *rq, int error, unsigned int nr_bytes,
		      unsigned int bidi_bytes,
		      int (drv_callback)(struct request *))
{
}

/**
 * func_with_dup_note_sections - any old function
 *
 * Note: each "section" (as indicated by "word:") should have a unique section-word
 * identifier.
 *
 * Note1: teach kernel-doc to notice when it clobbers a previous section contents.
 */
static void func_with_dup_note_sections(void)
{
}

/**
 * func_name_short_desc_test() -- any old function
 *
 * Note2: Just see how the output looks when () and -- are used.
 */
static void func_name_short_desc_test(void)
{
}

/**
 * notify_cpu_starting(cpu) - call the CPU_STARTING notifiers
 * @cpu: cpu that just started
 *
 * Note3: test for func prm name included.
 */
static void notify_cpu_starting(unsigned int cpu)
{
}

/**
 * struct foobar - documented
 *
 * This is a struct whose members are all private.
 */
struct foobar {
/* private: */
	int foo;
	int bar;
/* public: */
};

/**
 * struct skb_shared_hwtstamps - hardware time stamps
 * @hwtstamp:	hardware time stamp transformed into duration
 *		since arbitrary point in time
 * @syststamp:	hwtstamp transformed to system time base
 *
 * Software time stamps generated by ktime_get_real() are stored in
 * skb->tstamp. The relation between the different kinds of time
 * stamps is as follows:
 *
 * syststamp and tstamp can be compared against each other in
 * arbitrary combinations.  The accuracy of a
 * syststamp/tstamp/"syststamp from other device" comparison is
 * limited by the accuracy of the transformation into system time
 * base. This depends on the device driver and its underlying
 * hardware.
 *
 * hwtstamps can only be compared against other hwtstamps from
 * the same device.
 *
 * This structure is attached to packets as part of the
 * &skb_shared_info. Use skb_hwtstamps() to get a pointer.
 */
struct skb_shared_hwtstamps {
	ktime_t	hwtstamp;
	ktime_t	syststamp;
};

/**
 * struct usb_function - describes one function of a configuration
 * @name: For diagnostics, identifies the function.
 * @strings: tables of strings, keyed by identifiers assigned during bind()
 *	and by language IDs provided in control requests
 * @descriptors: Table of full (or low) speed descriptors, using interface and
 *	string identifiers assigned during @bind().  If this pointer is null,
 *	the function will not be available at full speed (or at low speed).
 * @hs_descriptors: Table of high speed descriptors, using interface and
 *	string identifiers assigned during @bind().  If this pointer is null,
 *	the function will not be available at high speed.
 * @config: assigned when @usb_add_function() is called; this is the
 *	configuration with which this function is associated.
 * @bind: Before the gadget can register, all of its functions bind() to the
 *	available resources including string and interface identifiers used
 *	in interface or class descriptors; endpoints; I/O buffers; and so on.
 * @unbind: Reverses @bind; called as a side effect of unregistering the
 *	driver which added this function.
 * @set_alt: (REQUIRED) Reconfigures altsettings; function drivers may
 *	initialize usb_ep.driver data at this time (when it is used).
 *	Note that setting an interface to its current altsetting resets
 *	interface state, and that all interfaces have a disabled state.
 * @get_alt: Returns the active altsetting.  If this is not provided,
 *	then only altsetting zero is supported.
 * @disable: (REQUIRED) Indicates the function should be disabled.  Reasons
 *	include host resetting or reconfiguring the gadget, and disconnection.
 * @setup: Used for interface-specific control requests.
 * @suspend: Notifies functions when the host stops sending USB traffic.
 * @resume: Notifies functions when the host restarts USB traffic.
 *
 * A single USB function uses one or more interfaces, and should in most
 * cases support operation at both full and high speeds.  Each function is
 * associated by @usb_add_function() with a one configuration; that function
 * causes @bind() to be called so resources can be allocated as part of
 * setting up a gadget driver.  Those resources include endpoints, which
 * should be allocated using @usb_ep_autoconfig().
 *
 * To support dual speed operation, a function driver provides descriptors
 * for both high and full speed operation.  Except in rare cases that don't
 * involve bulk endpoints, each speed needs different endpoint descriptors.
 *
 * Function drivers choose their own strategies for managing instance data.
 * The simplest strategy just declares it "static', which means the function
 * can only be activated once.  If the function needs to be exposed in more
 * than one configuration at a given speed, it needs to support multiple
 * usb_function structures (one for each configuration).
 *
 * A more complex strategy might encapsulate a @usb_function structure inside
 * a driver-specific instance structure to allows multiple activations.  An
 * example of multiple activations might be a CDC ACM function that supports
 * two or more distinct instances within the same configuration, providing
 * several independent logical data links to a USB host.
 */
struct usb_function {
	const char			*name;
	struct usb_gadget_strings	**strings;
	struct usb_descriptor_header	**descriptors;
	struct usb_descriptor_header	**hs_descriptors;

	struct usb_configuration	*config;

	/* REVISIT:  bind() functions can be marked __init, which
	 * makes trouble for section mismatch analysis.  See if
	 * we can't restructure things to avoid mismatching.
	 * Related:  unbind() may kfree() but bind() won't...
	 */

	/* configuration management:  bind/unbind */
	int			(*bind)(struct usb_configuration *,
					struct usb_function *);
	void			(*unbind)(struct usb_configuration *,
					struct usb_function *);

	/* runtime state management */
	int			(*set_alt)(struct usb_function *,
					unsigned interface, unsigned alt);
	int			(*get_alt)(struct usb_function *,
					unsigned interface);
	void			(*disable)(struct usb_function *);
	int			(*setup)(struct usb_function *,
					const struct usb_ctrlrequest *);
	void			(*suspend)(struct usb_function *);
	void			(*resume)(struct usb_function *);

	/* private: allow trailing text here, but not leading text before "private:" */
	/* internals */
	struct list_head		list;
};

/**
 * struct urb - USB Request Block
 * @urb_list: For use by current owner of the URB.
 * @anchor_list: membership in the list of an anchor
 * @anchor: to anchor URBs to a common mooring
 * @ep: Points to the endpoint's data structure.  Will eventually
 *	replace @pipe.
 * @pipe: Holds endpoint number, direction, type, and more.
 *	Create these values with the eight macros available;
 *	usb_{snd,rcv}TYPEpipe(dev,endpoint), where the TYPE is "ctrl"
 *	(control), "bulk", "int" (interrupt), or "iso" (isochronous).
 *	For example usb_sndbulkpipe() or usb_rcvintpipe().  Endpoint
 *	numbers range from zero to fifteen.  Note that "in" endpoint two
 *	is a different endpoint (and pipe) from "out" endpoint two.
 *	The current configuration controls the existence, type, and
 *	maximum packet size of any given endpoint.
 * @dev: Identifies the USB device to perform the request.
 * @status: This is read in non-iso completion functions to get the
 *	status of the particular request.  ISO requests only use it
 *	to tell whether the URB was unlinked; detailed status for
 *	each frame is in the fields of the iso_frame-desc.
 * @transfer_flags: A variety of flags may be used to affect how URB
 *	submission, unlinking, or operation are handled.  Different
 *	kinds of URB can use different flags.
 * @transfer_buffer:  This identifies the buffer to (or from) which
 * 	the I/O request will be performed (unless URB_NO_TRANSFER_DMA_MAP
 *	is set).  This buffer must be suitable for DMA; allocate it with
 *	kmalloc() or equivalent.  For transfers to "in" endpoints, contents
 *	of this buffer will be modified.  This buffer is used for the data
 *	stage of control transfers.
 * @transfer_dma: When transfer_flags includes URB_NO_TRANSFER_DMA_MAP,
 *	the device driver is saying that it provided this DMA address,
 *	which the host controller driver should use in preference to the
 *	transfer_buffer.
 * @transfer_buffer_length: How big is transfer_buffer.  The transfer may
 *	be broken up into chunks according to the current maximum packet
 *	size for the endpoint, which is a function of the configuration
 *	and is encoded in the pipe.  When the length is zero, neither
 *	transfer_buffer nor transfer_dma is used.
 * @actual_length: This is read in non-iso completion functions, and
 *	it tells how many bytes (out of transfer_buffer_length) were
 *	transferred.  It will normally be the same as requested, unless
 *	either an error was reported or a short read was performed.
 *	The URB_SHORT_NOT_OK transfer flag may be used to make such
 *	short reads be reported as errors.
 * @setup_packet: Only used for control transfers, this points to eight bytes
 *	of setup data.  Control transfers always start by sending this data
 *	to the device.  Then transfer_buffer is read or written, if needed.
 * @setup_dma: For control transfers with URB_NO_SETUP_DMA_MAP set, the
 *	device driver has provided this DMA address for the setup packet.
 *	The host controller driver should use this in preference to
 *	setup_packet.
 * @start_frame: Returns the initial frame for isochronous transfers.
 * @number_of_packets: Lists the number of ISO transfer buffers.
 * @interval: Specifies the polling interval for interrupt or isochronous
 *	transfers.  The units are frames (milliseconds) for for full and low
 *	speed devices, and microframes (1/8 millisecond) for highspeed ones.
 * @error_count: Returns the number of ISO transfers that reported errors.
 * @context: For use in completion functions.  This normally points to
 *	request-specific driver context.
 * @complete: Completion handler. This URB is passed as the parameter to the
 *	completion function.  The completion function may then do what
 *	it likes with the URB, including resubmitting or freeing it.
 * @iso_frame_desc: Used to provide arrays of ISO transfer buffers and to
 *	collect the transfer status for each buffer.
 */
struct urb {
	/* private: usb core and host controller only fields in the urb */
	struct kref kref;		/* reference count of the URB */
	void *hcpriv;			/* private data for host controller */
	atomic_t use_count;		/* concurrent submissions counter */
	atomic_t reject;		/* submissions will fail */
	int unlinked;			/* unlink error code */

	/* public: documented fields in the urb that can be used by drivers */
	struct list_head urb_list;	/* list head for use by the urb's
					 * current owner */
	struct list_head anchor_list;	/* the URB may be anchored */
	struct usb_anchor *anchor;
	struct usb_device *dev; 	/* (in) pointer to associated device */
	struct usb_host_endpoint *ep;	/* (internal) pointer to endpoint */
	unsigned int pipe;		/* (in) pipe information */
	int status;			/* (return) non-ISO status */
	unsigned int transfer_flags;	/* (in) URB_SHORT_NOT_OK | ...*/
	void *transfer_buffer;		/* (in) associated data buffer */
	dma_addr_t transfer_dma;	/* (in) dma addr for transfer_buffer */
	u32 transfer_buffer_length;	/* (in) data buffer length */
	u32 actual_length;		/* (return) actual transfer length */
	unsigned char *setup_packet;	/* (in) setup packet (control only) */
	dma_addr_t setup_dma;		/* (in) dma addr for setup_packet */
	int start_frame;		/* (modify) start frame (ISO) */
	int number_of_packets;		/* (in) number of ISO packets */
	int interval;			/* (modify) transfer interval
					 * (INT/ISO) */
	int error_count;		/* (return) number of ISO errors */
	void *context;			/* (in) context for completion */
	usb_complete_t complete;	/* (in) completion routine */
	struct usb_iso_packet_descriptor iso_frame_desc[0];
					/* (in) ISO ONLY */
};

/**
  *	struct sock - network layer representation of sockets
  *	@__sk_common: shared layout with inet_timewait_sock
  *	@sk_shutdown: mask of %SEND_SHUTDOWN and/or %RCV_SHUTDOWN
  *	@sk_userlocks: %SO_SNDBUF and %SO_RCVBUF settings
  *	@sk_lock:	synchronizer
  *	@sk_rcvbuf: size of receive buffer in bytes
  *	@sk_sleep: sock wait queue
  *	@sk_dst_cache: destination cache
  *	@sk_dst_lock: destination cache lock
  *	@sk_policy: flow policy
  *	@sk_rmem_alloc: receive queue bytes committed
  *	@sk_receive_queue: incoming packets
  *	@sk_wmem_alloc: transmit queue bytes committed
  *	@sk_write_queue: Packet sending queue
  *	@sk_async_wait_queue: DMA copied packets
  *	@sk_omem_alloc: "o" is "option" or "other"
  *	@sk_wmem_queued: persistent queue size
  *	@sk_forward_alloc: space allocated forward
  *	@sk_allocation: allocation mode
  *	@sk_sndbuf: size of send buffer in bytes
  *	@sk_flags: %SO_LINGER (l_onoff), %SO_BROADCAST, %SO_KEEPALIVE,
  *		   %SO_OOBINLINE settings, %SO_TIMESTAMPING settings
  *	@sk_no_check: %SO_NO_CHECK setting, wether or not checkup packets
  *	@sk_route_caps: route capabilities (e.g. %NETIF_F_TSO)
  *	@sk_gso_type: GSO type (e.g. %SKB_GSO_TCPV4)
  *	@sk_gso_max_size: Maximum GSO segment size to build
  *	@sk_lingertime: %SO_LINGER l_linger setting
  *	@sk_backlog: always used with the per-socket spinlock held
  *	@sk_callback_lock: used with the callbacks in the end of this struct
  *	@sk_error_queue: rarely used
  *	@sk_prot_creator: sk_prot of original sock creator (see ipv6_setsockopt,
  *			  IPV6_ADDRFORM for instance)
  *	@sk_err: last error
  *	@sk_err_soft: errors that don't cause failure but are the cause of a
  *		      persistent failure not just 'timed out'
  *	@sk_drops: raw/udp drops counter
  *	@sk_ack_backlog: current listen backlog
  *	@sk_max_ack_backlog: listen backlog set in listen()
  *	@sk_priority: %SO_PRIORITY setting
  *	@sk_type: socket type (%SOCK_STREAM, etc)
  *	@sk_protocol: which protocol this socket belongs in this network family
  *	@sk_peercred: %SO_PEERCRED setting
  *	@sk_rcvlowat: %SO_RCVLOWAT setting
  *	@sk_rcvtimeo: %SO_RCVTIMEO setting
  *	@sk_sndtimeo: %SO_SNDTIMEO setting
  *	@sk_filter: socket filtering instructions
  *	@sk_protinfo: private area, net family specific, when not using slab
  *	@sk_timer: sock cleanup timer
  *	@sk_stamp: time stamp of last packet received
  *	@sk_socket: Identd and reporting IO signals
  *	@sk_user_data: RPC layer private data
  *	@sk_sndmsg_page: cached page for sendmsg
  *	@sk_sndmsg_off: cached offset for sendmsg
  *	@sk_send_head: front of stuff to transmit
  *	@sk_security: used by security modules
  *	@sk_mark: generic packet mark
  *	@sk_write_pending: a write to stream socket waits to start
  *	@sk_state_change: callback to indicate change in the state of the sock
  *	@sk_data_ready: callback to indicate there is data to be processed
  *	@sk_write_space: callback to indicate there is bf sending space available
  *	@sk_error_report: callback to indicate errors (e.g. %MSG_ERRQUEUE)
  *	@sk_backlog_rcv: callback to process the backlog
  *	@sk_destruct: called at sock freeing time, i.e. when all refcnt == 0
 */
struct sock {
	/*
	 * Now struct inet_timewait_sock also uses sock_common, so please just
	 * don't add nothing before this first member (__sk_common) --acme
	 */
	struct sock_common	__sk_common;
#define sk_family		__sk_common.skc_family
#define sk_state		__sk_common.skc_state
#define sk_reuse		__sk_common.skc_reuse
#define sk_bound_dev_if		__sk_common.skc_bound_dev_if
#define sk_node			__sk_common.skc_node
#define sk_nulls_node		__sk_common.skc_nulls_node
#define sk_bind_node		__sk_common.skc_bind_node
#define sk_refcnt		__sk_common.skc_refcnt
#define sk_hash			__sk_common.skc_hash
#define sk_prot			__sk_common.skc_prot
#define sk_net			__sk_common.skc_net
	kmemcheck_bitfield_begin(flags);
	unsigned char		sk_shutdown : 2,
				sk_no_check : 2,
				sk_userlocks : 4;
	kmemcheck_bitfield_end(flags);
	unsigned char		sk_protocol;
	unsigned short		sk_type;
	int			sk_rcvbuf;
	socket_lock_t		sk_lock;
	/*
	 * The backlog queue is special, it is always used with
	 * the per-socket spinlock held and requires low latency
	 * access. Therefore we special case it's implementation.
	 */
	struct {
		struct sk_buff *head;
		struct sk_buff *tail;
	} sk_backlog;
	wait_queue_head_t	*sk_sleep;
	struct dst_entry	*sk_dst_cache;
#ifdef CONFIG_XFRM
	struct xfrm_policy	*sk_policy[2];
#endif
	rwlock_t		sk_dst_lock;
	atomic_t		sk_rmem_alloc;
	atomic_t		sk_wmem_alloc;
	atomic_t		sk_omem_alloc;
	int			sk_sndbuf;
	struct sk_buff_head	sk_receive_queue;
	struct sk_buff_head	sk_write_queue;
#ifdef CONFIG_NET_DMA
	struct sk_buff_head	sk_async_wait_queue;
#endif
	int			sk_wmem_queued;
	int			sk_forward_alloc;
	gfp_t			sk_allocation;
	int			sk_route_caps;
	int			sk_gso_type;
	unsigned int		sk_gso_max_size;
	int			sk_rcvlowat;
	unsigned long 		sk_flags;
	unsigned long	        sk_lingertime;
	struct sk_buff_head	sk_error_queue;
	struct proto		*sk_prot_creator;
	rwlock_t		sk_callback_lock;
	int			sk_err,
				sk_err_soft;
	atomic_t		sk_drops;
	unsigned short		sk_ack_backlog;
	unsigned short		sk_max_ack_backlog;
	__u32			sk_priority;
	struct ucred		sk_peercred;
	long			sk_rcvtimeo;
	long			sk_sndtimeo;
	struct sk_filter      	*sk_filter;
	void			*sk_protinfo;
	struct timer_list	sk_timer;
	ktime_t			sk_stamp;
	struct socket		*sk_socket;
	void			*sk_user_data;
	struct page		*sk_sndmsg_page;
	struct sk_buff		*sk_send_head;
	__u32			sk_sndmsg_off;
	int			sk_write_pending;
#ifdef CONFIG_SECURITY
	void			*sk_security;
#endif
	__u32			sk_mark;
	/* XXX 4 bytes hole on 64 bit */
	void			(*sk_state_change)(struct sock *sk);
	void			(*sk_data_ready)(struct sock *sk, int bytes);
	void			(*sk_write_space)(struct sock *sk);
	void			(*sk_error_report)(struct sock *sk);
  	int			(*sk_backlog_rcv)(struct sock *sk,
						  struct sk_buff *skb);  
	void                    (*sk_destruct)(struct sock *sk);
};

/**
 * is_etherdev_addr - Tell if given Ethernet address belongs to the device.
 * @dev: Pointer to a device structure
 * @addr: Pointer to a six-byte array containing the Ethernet address
 *
 * Compare passed address with all addresses of the device. Return true if the
 * address if one of the device addresses.
 *
 * Note that this function calls compare_ether_addr_64bits() so take care of
 * the right padding.
 */
static inline bool is_etherdev_addr(const struct net_device *dev,
				    const u8 addr[6 + 2])
{
	struct netdev_hw_addr *ha;
	int res = 1;

	rcu_read_lock();
	for_each_dev_addr(dev, ha) {
		res = compare_ether_addr_64bits(addr, ha->addr);
		if (!res)
			break;
	}
	rcu_read_unlock();
	return !res;
}

/**
 * flex_array_shrink - free unused second-level pages
 *
 * Frees all second-level pages that consist solely of unused
 * elements.  Returns the number of pages freed.
 *
 * Locking must be provided by the caller.
 */
int flex_array_shrink(struct flex_array *fa)
{
}

/* weird kernel-doc error from Johannes Berg on: */
#define FOO 10
/**
 * struct foo - test kernel-doc struct errors
 * @a: some field with attributes
 * @b: some field with other attributes
 */
struct foo {
	u8 a[0]
                __attribute__((__aligned(sizeof(void *))));
	u8 b[0]
                __attribute__((__aligned__(FOO)));
};

/**
 *	dev_alloc_name - allocate a name for a device
 *	@dev: device
 *	@name: name format string
 *
 *	Passed a format string - eg "lt%d" it will try and find a suitable
 *	id. It scans list of devices to build up a free map, then chooses
 *	the first empty slot. The caller must hold the dev_base or rtnl lock
 *	while allocating the name and adding the device in order to avoid
 *	duplicates.
 *	Limited to bits_per_byte * page size devices (ie 32K on most platforms).
 *	Returns the number of the unit assigned or a negative errno code.
 */
int dev_alloc_name(struct net_device *dev, const char *name)
{
}

/**
 * struct - i/q coordinate.
 *
 * @i: real part of coordinate (in phase).
 * @q: imaginary part of coordinate (quadrature).
 */
struct cordic_iq {
	s32 i;
	s32 q;
};

/**
 * struct nand_flash_dev - NAND Flash Device ID Structure
 * @name: a human-readable name of the NAND chip
 * @dev_id: the device ID (the second byte of the full chip ID array)
 * @mfr_id: manufecturer ID part of the full chip ID array (refers the same
 *          memory address as @id[0])
 * @dev_id: device ID part of the full chip ID array (refers the same memory
 *          address as @id[1])
 * @id: full device ID array
 * @pagesize: size of the NAND page in bytes; if 0, then the real page size (as
 *            well as the eraseblock size) is determined from the extended NAND
 *            chip ID array)
 * @chipsize: total chip size in MiB
 * @erasesize: eraseblock size in bytes (determined from the extended ID if 0)
 * @options: stores various chip bit options
 * @id_len: The valid length of the @id.
 * @oobsize: OOB size
 * @ecc: ecc parameters from datasheet
 * @ecc.strength_ds: The ECC correctability from the datasheet, same as the
 *                   @ecc_strength_ds in nand_chip{}.
 * @ecc.step_ds: The ECC step required by the @ecc.strength_ds, same as the
 *               @ecc_step_ds in nand_chip{}, also from the datasheet.
 *               For example, the "4bit ECC for each 512Byte" can be set with
 *               NAND_ECC_INFO(4, 512).
 * WITHOUT named nested unions/structs;
 */
struct nand_flash_dev {
	char *name;
	union {
		struct {
			uint8_t mfr_id;
			uint8_t dev_id;
		};
		uint8_t id[NAND_MAX_ID_LEN];
	};
	unsigned int pagesize;
	unsigned int chipsize;
	unsigned int erasesize;
	unsigned int options;
	uint16_t id_len;
	uint16_t oobsize;
	struct {
		uint16_t strength_ds;
		uint16_t step_ds;
	} ecc;
};

/**
 * struct nand_flash_device - NAND Flash Device ID Structure
 * @name: a human-readable name of the NAND chip
 * @dev_id: the device ID (the second byte of the full chip ID array)
 * @mfr_id: manufecturer ID part of the full chip ID array (refers the same
 *          memory address as @id[0])
 * @dev_id: device ID part of the full chip ID array (refers the same memory
 *          address as @id[1])
 * @id: full device ID array
 * @pagesize: size of the NAND page in bytes; if 0, then the real page size (as
 *            well as the eraseblock size) is determined from the extended NAND
 *            chip ID array)
 * @chipsize: total chip size in MiB
 * @erasesize: eraseblock size in bytes (determined from the extended ID if 0)
 * @options: stores various chip bit options
 * @id_len: The valid length of the @id.
 * @oobsize: OOB size
 * @ecc: ecc parameters from datasheet
 * @ecc.strength_ds: The ECC correctability from the datasheet, same as the
 *                   @ecc_strength_ds in nand_chip{}.
 * @ecc.step_ds: The ECC step required by the @ecc.strength_ds, same as the
 *               @ecc_step_ds in nand_chip{}, also from the datasheet.
 *               For example, the "4bit ECC for each 512Byte" can be set with
 *               NAND_ECC_INFO(4, 512).
 * WITH named nested unions/structs;
 */
struct nand_flash_device {
	char *name;
	union u_ids_ary {
		struct nand_ids {
			uint8_t mfr_id;
			uint8_t dev_id;
		} ids;
		uint8_t id[NAND_MAX_ID_LEN];
	} ids_ary;
	unsigned int pagesize;
	unsigned int chipsize;
	unsigned int erasesize;
	unsigned int options;
	uint16_t id_len;
	uint16_t oobsize;
	struct ecc_ds {
		uint16_t strength_ds;
		uint16_t step_ds;
	} ecc;
};

/**
 * crc32_le_generic() - Calculate bitwise little-endian Ethernet AUTODIN II
 *			CRC32/CRC32C
 * @crc: seed value for computation.  ~0 for Ethernet, sometimes 0 for other
 *	 uses, or the previous crc32/crc32c value if computing incrementally.
 * @p: pointer to buffer over which CRC32/CRC32C is run
 * @len: length of buffer @p
 * @tab: little-endian Ethernet table
 * @polynomial: CRC32/CRC32c LE polynomial
 */
static inline u32 __pure crc32_le_generic(u32 crc, unsigned char const *p,
					  size_t len, const u32 (*tab)[256],
					  u32 polynomial)
{
	return crc;
}

/**
 * strreplace - Replace all occurrences of character in string.
 * @s: The string to operate on.
 * @old: The character being replaced.
 * @new: The character @old is replaced with.
 *
 * Returns pointer to the nul byte at the end of @s.
 */
char *strreplace(char *s, char old, char new)
{
	for (; *s; ++s)
		if (*s == old)
			*s = new;
	return s;
}

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

* Re: [RFC] Add kernel-doc test script
  2020-11-18 16:32                 ` Randy Dunlap
@ 2020-11-18 16:57                   ` Eduardo Habkost
  2020-11-18 16:58                     ` Randy Dunlap
  0 siblings, 1 reply; 17+ messages in thread
From: Eduardo Habkost @ 2020-11-18 16:57 UTC (permalink / raw)
  To: Randy Dunlap
  Cc: Matthew Wilcox, Jonathan Corbet, Paolo Bonzini, linux-kernel, linux-doc

On Wed, Nov 18, 2020 at 08:32:35AM -0800, Randy Dunlap wrote:
> On 11/18/20 5:03 AM, Eduardo Habkost wrote:
> > On Tue, Nov 17, 2020 at 04:23:49PM -0800, Randy Dunlap wrote:
> >> On 11/17/20 2:36 PM, Eduardo Habkost wrote:
> >>> Add a kernel-doc test script to tools/testing/kernel-doc.
> >>>
> >>> radix_tree_lookup_slot test case provided by Matthew Wilcox.
> >>>
> >>> Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
> >>
> >> Very good idea.
> >>
> >> I have had a kernel-doc test source file for (?) 10-12 years,
> >> while I was the docs maintainer.
> > 
> > Is that test source file recoverable somewhere?  It probably has
> > useful test cases not included here.
> 
> Sure.  Of course, it may be out of date by quite a bit.
> I last updated it in 2016:
> -rw-r--r-- 1 rdunlap users  41737 Jun 17  2016 megatest.c
> 
> (attached)
> 

Thanks!  Are the contents licensed under GPL 2.0?

-- 
Eduardo


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

* Re: [RFC] Add kernel-doc test script
  2020-11-18 16:57                   ` Eduardo Habkost
@ 2020-11-18 16:58                     ` Randy Dunlap
  0 siblings, 0 replies; 17+ messages in thread
From: Randy Dunlap @ 2020-11-18 16:58 UTC (permalink / raw)
  To: Eduardo Habkost
  Cc: Matthew Wilcox, Jonathan Corbet, Paolo Bonzini, linux-kernel, linux-doc

On 11/18/20 8:57 AM, Eduardo Habkost wrote:
> On Wed, Nov 18, 2020 at 08:32:35AM -0800, Randy Dunlap wrote:
>> On 11/18/20 5:03 AM, Eduardo Habkost wrote:
>>> On Tue, Nov 17, 2020 at 04:23:49PM -0800, Randy Dunlap wrote:
>>>> On 11/17/20 2:36 PM, Eduardo Habkost wrote:
>>>>> Add a kernel-doc test script to tools/testing/kernel-doc.
>>>>>
>>>>> radix_tree_lookup_slot test case provided by Matthew Wilcox.
>>>>>
>>>>> Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
>>>>
>>>> Very good idea.
>>>>
>>>> I have had a kernel-doc test source file for (?) 10-12 years,
>>>> while I was the docs maintainer.
>>>
>>> Is that test source file recoverable somewhere?  It probably has
>>> useful test cases not included here.
>>
>> Sure.  Of course, it may be out of date by quite a bit.
>> I last updated it in 2016:
>> -rw-r--r-- 1 rdunlap users  41737 Jun 17  2016 megatest.c
>>
>> (attached)
>>
> 
> Thanks!  Are the contents licensed under GPL 2.0?

Sure!

-- 
~Randy


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

end of thread, other threads:[~2020-11-18 16:59 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-10-30 14:47 [PATCH 0/2] kernel-doc: Handle function typedefs Paolo Bonzini
2020-10-30 14:47 ` [PATCH 1/2] kernel-doc: Handle function typedefs that return pointers Paolo Bonzini
2020-10-30 14:47 ` [PATCH 2/2] kernel-doc: Handle function typedefs without asterisks Paolo Bonzini
2020-11-13 22:21   ` Jonathan Corbet
2020-11-13 22:35     ` Paolo Bonzini
2020-11-13 22:39     ` Matthew Wilcox
2020-11-17 21:24       ` Eduardo Habkost
2020-11-17 21:30         ` Matthew Wilcox
2020-11-17 22:36           ` [RFC] Add kernel-doc test script Eduardo Habkost
2020-11-18  0:23             ` Randy Dunlap
2020-11-18 13:03               ` Eduardo Habkost
2020-11-18 16:32                 ` Randy Dunlap
2020-11-18 16:57                   ` Eduardo Habkost
2020-11-18 16:58                     ` Randy Dunlap
2020-11-18  8:21             ` Paolo Bonzini
2020-11-18 12:05               ` Eduardo Habkost
2020-11-18 16:27             ` Jonathan Corbet

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