diff options
| author | Mauro Carvalho Chehab <mchehab@s-opensource.com> | 2017-12-18 07:30:17 -0500 |
|---|---|---|
| committer | Jonathan Corbet <corbet@lwn.net> | 2017-12-21 15:41:47 -0500 |
| commit | 84ce5b987783d362ee4e737b653d6e2feacfa40c (patch) | |
| tree | 2fcc939ad7626ef6e0fdfeac68b07cb513ef1e02 /scripts/kernel-doc | |
| parent | 7c0d7e87a16fe615e7913a3d56ce7bd26104ef0b (diff) | |
scripts: kernel-doc: improve nested logic to handle multiple identifiers
It is possible to use nested structs like:
struct {
struct {
void *arg1;
} st1, st2, *st3, st4;
};
Handling it requires to split each parameter. Change the logic
to allow such definitions.
In order to test the new nested logic, the following file
was used to test
<code>
struct foo { int a; }; /* Just to avoid errors if compiled */
/**
* struct my_struct - a struct with nested unions and structs
* @arg1: first argument of anonymous union/anonymous struct
* @arg2: second argument of anonymous union/anonymous struct
* @arg1b: first argument of anonymous union/anonymous struct
* @arg2b: second argument of anonymous union/anonymous struct
* @arg3: third argument of anonymous union/anonymous struct
* @arg4: fourth argument of anonymous union/anonymous struct
* @bar.st1.arg1: first argument of struct st1 on union bar
* @bar.st1.arg2: second argument of struct st1 on union bar
* @bar.st1.bar1: bar1 at st1
* @bar.st1.bar2: bar2 at st1
* @bar.st2.arg1: first argument of struct st2 on union bar
* @bar.st2.arg2: second argument of struct st2 on union bar
* @bar.st3.arg2: second argument of struct st3 on union bar
* @f1: nested function on anonimous union/struct
* @bar.st2.f2: nested function on named union/struct
*/
struct my_struct {
/* Anonymous union/struct*/
union {
struct {
char arg1 : 1;
char arg2 : 3;
};
struct {
int arg1b;
int arg2b;
};
struct {
void *arg3;
int arg4;
int (*f1)(char foo, int bar);
};
};
union {
struct {
int arg1;
int arg2;
struct foo bar1, *bar2;
} st1; /* bar.st1 is undocumented, cause a warning */
struct {
void *arg1; /* bar.st3.arg1 is undocumented, cause a warning */
int arg2;
int (*f2)(char foo, int bar); /* bar.st3.fn2 is undocumented, cause a warning */
} st2, st3, *st4;
int (*f3)(char foo, int bar); /* f3 is undocumented, cause a warning */
} bar; /* bar is undocumented, cause a warning */
/* private: */
int undoc_privat; /* is undocumented but private, no warning */
/* public: */
int undoc_public; /* is undocumented, cause a warning */
};
</code>
It produces the following warnings, as expected:
test2.h:57: warning: Function parameter or member 'bar' not described in 'my_struct'
test2.h:57: warning: Function parameter or member 'bar.st1' not described in 'my_struct'
test2.h:57: warning: Function parameter or member 'bar.st2' not described in 'my_struct'
test2.h:57: warning: Function parameter or member 'bar.st3' not described in 'my_struct'
test2.h:57: warning: Function parameter or member 'bar.st3.arg1' not described in 'my_struct'
test2.h:57: warning: Function parameter or member 'bar.st3.f2' not described in 'my_struct'
test2.h:57: warning: Function parameter or member 'bar.st4' not described in 'my_struct'
test2.h:57: warning: Function parameter or member 'bar.st4.arg1' not described in 'my_struct'
test2.h:57: warning: Function parameter or member 'bar.st4.arg2' not described in 'my_struct'
test2.h:57: warning: Function parameter or member 'bar.st4.f2' not described in 'my_struct'
test2.h:57: warning: Function parameter or member 'bar.f3' not described in 'my_struct'
test2.h:57: warning: Function parameter or member 'undoc_public' not described in 'my_struct'
Suggested-by: Markus Heiser <markus.heiser@darmarit.de>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
Signed-off-by: Jonathan Corbet <corbet@lwn.net>
Diffstat (limited to 'scripts/kernel-doc')
| -rwxr-xr-x | scripts/kernel-doc | 69 |
1 files changed, 44 insertions, 25 deletions
diff --git a/scripts/kernel-doc b/scripts/kernel-doc index 5d03c9086323..0bda21d9d3f2 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc | |||
| @@ -1030,15 +1030,16 @@ sub dump_struct($$) { | |||
| 1030 | my $declaration = $members; | 1030 | my $declaration = $members; |
| 1031 | 1031 | ||
| 1032 | # Split nested struct/union elements as newer ones | 1032 | # Split nested struct/union elements as newer ones |
| 1033 | my $cont = 1; | 1033 | while ($members =~ m/(struct|union)([^\{\};]+)\{([^\{\}]*)\}([^\{\}\;]*)\;/) { |
| 1034 | while ($cont) { | 1034 | my $newmember; |
| 1035 | $cont = 0; | 1035 | my $maintype = $1; |
| 1036 | while ($members =~ m/(struct|union)([^{};]+){([^{}]*)}([^{}\;]*)\;/) { | 1036 | my $ids = $4; |
| 1037 | my $newmember = "$1 $4;"; | 1037 | my $content = $3; |
| 1038 | my $id = $4; | 1038 | foreach my $id(split /,/, $ids) { |
| 1039 | my $content = $3; | 1039 | $newmember .= "$maintype $id; "; |
| 1040 | |||
| 1040 | $id =~ s/[:\[].*//; | 1041 | $id =~ s/[:\[].*//; |
| 1041 | $id =~ s/^\*+//; | 1042 | $id =~ s/^\s*\**(\S+)\s*/$1/; |
| 1042 | foreach my $arg (split /;/, $content) { | 1043 | foreach my $arg (split /;/, $content) { |
| 1043 | next if ($arg =~ m/^\s*$/); | 1044 | next if ($arg =~ m/^\s*$/); |
| 1044 | if ($arg =~ m/^([^\(]+\(\*?\s*)([\w\.]*)(\s*\).*)/) { | 1045 | if ($arg =~ m/^([^\(]+\(\*?\s*)([\w\.]*)(\s*\).*)/) { |
| @@ -1049,30 +1050,48 @@ sub dump_struct($$) { | |||
| 1049 | next if (!$name); | 1050 | next if (!$name); |
| 1050 | if ($id =~ m/^\s*$/) { | 1051 | if ($id =~ m/^\s*$/) { |
| 1051 | # anonymous struct/union | 1052 | # anonymous struct/union |
| 1052 | $newmember .= "$type$name$extra;"; | 1053 | $newmember .= "$type$name$extra; "; |
| 1053 | } else { | 1054 | } else { |
| 1054 | $newmember .= "$type$id.$name$extra;"; | 1055 | $newmember .= "$type$id.$name$extra; "; |
| 1055 | } | 1056 | } |
| 1056 | } else { | 1057 | } else { |
| 1057 | my $type = $arg; | 1058 | my $type; |
| 1058 | my $name = $arg; | 1059 | my $names; |
| 1059 | $type =~ s/\s\S+$//; | 1060 | $arg =~ s/^\s+//; |
| 1060 | $name =~ s/.*\s+//; | 1061 | $arg =~ s/\s+$//; |
| 1061 | $name =~ s/[:\[].*//; | 1062 | # Handle bitmaps |
| 1062 | $name =~ s/^\*+//; | 1063 | $arg =~ s/:\s*\d+\s*//g; |
| 1063 | next if (($name =~ m/^\s*$/)); | 1064 | # Handle arrays |
| 1064 | if ($id =~ m/^\s*$/) { | 1065 | $arg =~ s/\[\S+\]//g; |
| 1065 | # anonymous struct/union | 1066 | # The type may have multiple words, |
| 1066 | $newmember .= "$type $name;"; | 1067 | # and multiple IDs can be defined, like: |
| 1068 | # const struct foo, *bar, foobar | ||
| 1069 | # So, we remove spaces when parsing the | ||
| 1070 | # names, in order to match just names | ||
| 1071 | # and commas for the names | ||
| 1072 | $arg =~ s/\s*,\s*/,/g; | ||
| 1073 | if ($arg =~ m/(.*)\s+([\S+,]+)/) { | ||
| 1074 | $type = $1; | ||
| 1075 | $names = $2; | ||
| 1067 | } else { | 1076 | } else { |
| 1068 | $newmember .= "$type $id.$name;"; | 1077 | $newmember .= "$arg; "; |
| 1078 | next; | ||
| 1079 | } | ||
| 1080 | foreach my $name (split /,/, $names) { | ||
| 1081 | $name =~ s/^\s*\**(\S+)\s*/$1/; | ||
| 1082 | next if (($name =~ m/^\s*$/)); | ||
| 1083 | if ($id =~ m/^\s*$/) { | ||
| 1084 | # anonymous struct/union | ||
| 1085 | $newmember .= "$type $name; "; | ||
| 1086 | } else { | ||
| 1087 | $newmember .= "$type $id.$name; "; | ||
| 1088 | } | ||
| 1069 | } | 1089 | } |
| 1070 | } | 1090 | } |
| 1071 | } | 1091 | } |
| 1072 | $members =~ s/(struct|union)([^{};]+){([^{}]*)}([^{}\;]*)\;/$newmember/; | 1092 | } |
| 1073 | $cont = 1; | 1093 | $members =~ s/(struct|union)([^\{\};]+)\{([^\{\}]*)}([^\{\}\;]*)\;/$newmember/; |
| 1074 | }; | 1094 | } |
| 1075 | }; | ||
| 1076 | 1095 | ||
| 1077 | # Ignore other nested elements, like enums | 1096 | # Ignore other nested elements, like enums |
| 1078 | $members =~ s/({[^\{\}]*})//g; | 1097 | $members =~ s/({[^\{\}]*})//g; |
