aboutsummaryrefslogtreecommitdiffstats
path: root/scripts/kernel-doc
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@s-opensource.com>2017-12-18 07:30:17 -0500
committerJonathan Corbet <corbet@lwn.net>2017-12-21 15:41:47 -0500
commit84ce5b987783d362ee4e737b653d6e2feacfa40c (patch)
tree2fcc939ad7626ef6e0fdfeac68b07cb513ef1e02 /scripts/kernel-doc
parent7c0d7e87a16fe615e7913a3d56ce7bd26104ef0b (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-xscripts/kernel-doc69
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;