Skip to content

Commit 84ce5b9

Browse files
mchehabJonathan Corbet
authored andcommitted
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 <[email protected]> Signed-off-by: Mauro Carvalho Chehab <[email protected]> Signed-off-by: Jonathan Corbet <[email protected]>
1 parent 7c0d7e8 commit 84ce5b9

File tree

1 file changed

+44
-25
lines changed

1 file changed

+44
-25
lines changed

scripts/kernel-doc

Lines changed: 44 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1030,15 +1030,16 @@ sub dump_struct($$) {
10301030
my $declaration = $members;
10311031

10321032
# Split nested struct/union elements as newer ones
1033-
my $cont = 1;
1034-
while ($cont) {
1035-
$cont = 0;
1036-
while ($members =~ m/(struct|union)([^{};]+){([^{}]*)}([^{}\;]*)\;/) {
1037-
my $newmember = "$1 $4;";
1038-
my $id = $4;
1039-
my $content = $3;
1033+
while ($members =~ m/(struct|union)([^\{\};]+)\{([^\{\}]*)\}([^\{\}\;]*)\;/) {
1034+
my $newmember;
1035+
my $maintype = $1;
1036+
my $ids = $4;
1037+
my $content = $3;
1038+
foreach my $id(split /,/, $ids) {
1039+
$newmember .= "$maintype $id; ";
1040+
10401041
$id =~ s/[:\[].*//;
1041-
$id =~ s/^\*+//;
1042+
$id =~ s/^\s*\**(\S+)\s*/$1/;
10421043
foreach my $arg (split /;/, $content) {
10431044
next if ($arg =~ m/^\s*$/);
10441045
if ($arg =~ m/^([^\(]+\(\*?\s*)([\w\.]*)(\s*\).*)/) {
@@ -1049,30 +1050,48 @@ sub dump_struct($$) {
10491050
next if (!$name);
10501051
if ($id =~ m/^\s*$/) {
10511052
# anonymous struct/union
1052-
$newmember .= "$type$name$extra;";
1053+
$newmember .= "$type$name$extra; ";
10531054
} else {
1054-
$newmember .= "$type$id.$name$extra;";
1055+
$newmember .= "$type$id.$name$extra; ";
10551056
}
10561057
} else {
1057-
my $type = $arg;
1058-
my $name = $arg;
1059-
$type =~ s/\s\S+$//;
1060-
$name =~ s/.*\s+//;
1061-
$name =~ s/[:\[].*//;
1062-
$name =~ s/^\*+//;
1063-
next if (($name =~ m/^\s*$/));
1064-
if ($id =~ m/^\s*$/) {
1065-
# anonymous struct/union
1066-
$newmember .= "$type $name;";
1058+
my $type;
1059+
my $names;
1060+
$arg =~ s/^\s+//;
1061+
$arg =~ s/\s+$//;
1062+
# Handle bitmaps
1063+
$arg =~ s/:\s*\d+\s*//g;
1064+
# Handle arrays
1065+
$arg =~ s/\[\S+\]//g;
1066+
# The type may have multiple words,
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;
10671076
} 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+
}
10691089
}
10701090
}
10711091
}
1072-
$members =~ s/(struct|union)([^{};]+){([^{}]*)}([^{}\;]*)\;/$newmember/;
1073-
$cont = 1;
1074-
};
1075-
};
1092+
}
1093+
$members =~ s/(struct|union)([^\{\};]+)\{([^\{\}]*)}([^\{\}\;]*)\;/$newmember/;
1094+
}
10761095

10771096
# Ignore other nested elements, like enums
10781097
$members =~ s/({[^\{\}]*})//g;

0 commit comments

Comments
 (0)