Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

scripts: kernel-doc: parse next structs/unions

There are several places within the Kernel tree with nested
structs/unions, like this one:

struct ingenic_cgu_clk_info {
const char *name;
enum {
CGU_CLK_NONE = 0,
CGU_CLK_EXT = BIT(0),
CGU_CLK_PLL = BIT(1),
CGU_CLK_GATE = BIT(2),
CGU_CLK_MUX = BIT(3),
CGU_CLK_MUX_GLITCHFREE = BIT(4),
CGU_CLK_DIV = BIT(5),
CGU_CLK_FIXDIV = BIT(6),
CGU_CLK_CUSTOM = BIT(7),
} type;
int parents[4];
union {
struct ingenic_cgu_pll_info pll;
struct {
struct ingenic_cgu_gate_info gate;
struct ingenic_cgu_mux_info mux;
struct ingenic_cgu_div_info div;
struct ingenic_cgu_fixdiv_info fixdiv;
};
struct ingenic_cgu_custom_info custom;
};
};

Currently, such struct is documented as:

**Definition**

::
struct ingenic_cgu_clk_info {
const char * name;
};

**Members**

``name``
name of the clock

With is obvioulsy wrong. It also generates an error:
drivers/clk/ingenic/cgu.h:169: warning: No description found for parameter 'enum'

However, there's nothing wrong with this kernel-doc markup: everything
is documented there.

It makes sense to document all fields there. So, add a
way for the core to parse those structs.

With this patch, all documented fields will properly generate
documentation.

Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
Signed-off-by: Jonathan Corbet <corbet@lwn.net>

authored by

Mauro Carvalho Chehab and committed by
Jonathan Corbet
8ad72163 7c9aa015

+114 -53
+46
Documentation/doc-guide/kernel-doc.rst
··· 281 281 The kernel-doc data structure comments describe each member of the structure, 282 282 in order, with the member descriptions. 283 283 284 + Nested structs/unions 285 + ~~~~~~~~~~~~~~~~~~~~~ 286 + 287 + It is possible to document nested structs unions, like:: 288 + 289 + /** 290 + * struct nested_foobar - a struct with nested unions and structs 291 + * @arg1: - first argument of anonymous union/anonymous struct 292 + * @arg2: - second argument of anonymous union/anonymous struct 293 + * @arg3: - third argument of anonymous union/anonymous struct 294 + * @arg4: - fourth argument of anonymous union/anonymous struct 295 + * @bar.st1.arg1 - first argument of struct st1 on union bar 296 + * @bar.st1.arg2 - second argument of struct st1 on union bar 297 + * @bar.st2.arg1 - first argument of struct st2 on union bar 298 + * @bar.st2.arg2 - second argument of struct st2 on union bar 299 + struct nested_foobar { 300 + /* Anonymous union/struct*/ 301 + union { 302 + struct { 303 + int arg1; 304 + int arg2; 305 + } 306 + struct { 307 + void *arg3; 308 + int arg4; 309 + } 310 + } 311 + union { 312 + struct { 313 + int arg1; 314 + int arg2; 315 + } st1; 316 + struct { 317 + void *arg1; 318 + int arg2; 319 + } st2; 320 + } bar; 321 + }; 322 + 323 + .. note:: 324 + 325 + #) When documenting nested structs or unions, if the struct/union ``foo`` 326 + is named, the argument ``bar`` inside it should be documented as 327 + ``@foo.bar:`` 328 + #) When the nested struct/union is anonymous, the argument ``bar`` on it 329 + should be documented as ``@bar:`` 284 330 285 331 Typedef documentation 286 332 ---------------------
+68 -53
scripts/kernel-doc
··· 211 211 my $type_constant = '\b``([^\`]+)``\b'; 212 212 my $type_constant2 = '\%([-_\w]+)'; 213 213 my $type_func = '(\w+)\(\)'; 214 - my $type_param = '\@(\w+(\.\.\.)?)'; 214 + my $type_param = '\@(\w*(\.\w+)*(\.\.\.)?)'; 215 215 my $type_fp_param = '\@(\w+)\(\)'; # Special RST handling for func ptr params 216 216 my $type_env = '(\$\w+)'; 217 217 my $type_enum = '\&(enum\s*([_\w]+))'; ··· 670 670 print ".SH NAME\n"; 671 671 print $args{'type'} . " " . $args{'struct'} . " \\- " . $args{'purpose'} . "\n"; 672 672 673 + my $declaration = $args{'definition'}; 674 + $declaration =~ s/\t/ /g; 675 + $declaration =~ s/\n/"\n.br\n.BI \"/g; 673 676 print ".SH SYNOPSIS\n"; 674 677 print $args{'type'} . " " . $args{'struct'} . " {\n.br\n"; 675 - 676 - foreach my $parameter (@{$args{'parameterlist'}}) { 677 - if ($parameter =~ /^#/) { 678 - print ".BI \"$parameter\"\n.br\n"; 679 - next; 680 - } 681 - my $parameter_name = $parameter; 682 - $parameter_name =~ s/\[.*//; 683 - 684 - ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next; 685 - $type = $args{'parametertypes'}{$parameter}; 686 - if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) { 687 - # pointer-to-function 688 - print ".BI \" " . $1 . "\" " . $parameter . " \") (" . $2 . ")" . "\"\n;\n"; 689 - } elsif ($type =~ m/^(.*?)\s*(:.*)/) { 690 - # bitfield 691 - print ".BI \" " . $1 . "\ \" " . $parameter . $2 . " \"" . "\"\n;\n"; 692 - } else { 693 - $type =~ s/([^\*])$/$1 /; 694 - print ".BI \" " . $type . "\" " . $parameter . " \"" . "\"\n;\n"; 695 - } 696 - print "\n.br\n"; 697 - } 698 - print "};\n.br\n"; 678 + print ".BI \"$declaration\n};\n.br\n\n"; 699 679 700 680 print ".SH Members\n"; 701 681 foreach $parameter (@{$args{'parameterlist'}}) { ··· 913 933 914 934 print "**Definition**\n\n"; 915 935 print "::\n\n"; 916 - print " " . $args{'type'} . " " . $args{'struct'} . " {\n"; 917 - foreach $parameter (@{$args{'parameterlist'}}) { 918 - if ($parameter =~ /^#/) { 919 - print " " . "$parameter\n"; 920 - next; 921 - } 922 - 923 - my $parameter_name = $parameter; 924 - $parameter_name =~ s/\[.*//; 925 - 926 - ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next; 927 - $type = $args{'parametertypes'}{$parameter}; 928 - if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) { 929 - # pointer-to-function 930 - print " $1 $parameter) ($2);\n"; 931 - } elsif ($type =~ m/^(.*?)\s*(:.*)/) { 932 - # bitfield 933 - print " $1 $parameter$2;\n"; 934 - } else { 935 - print " " . $type . " " . $parameter . ";\n"; 936 - } 937 - } 938 - print " };\n\n"; 936 + my $declaration = $args{'definition'}; 937 + $declaration =~ s/\t/ /g; 938 + print " " . $args{'type'} . " " . $args{'struct'} . " {\n$declaration };\n\n"; 939 939 940 940 print "**Members**\n\n"; 941 941 $lineprefix = " "; ··· 1010 1050 $declaration_name = $2; 1011 1051 my $members = $3; 1012 1052 1013 - # ignore embedded structs or unions 1014 - $members =~ s/({.*})//g; 1015 - $nested = $1; 1016 - 1017 1053 # ignore members marked private: 1018 1054 $members =~ s/\/\*\s*private:.*?\/\*\s*public:.*?\*\///gosi; 1019 1055 $members =~ s/\/\*\s*private:.*//gosi; 1020 1056 # strip comments: 1021 1057 $members =~ s/\/\*.*?\*\///gos; 1022 - $nested =~ s/\/\*.*?\*\///gos; 1023 1058 # strip attributes 1024 1059 $members =~ s/__attribute__\s*\(\([a-z,_\*\s\(\)]*\)\)//i; 1025 1060 $members =~ s/__aligned\s*\([^;]*\)//gos; ··· 1028 1073 # replace DECLARE_KFIFO_PTR 1029 1074 $members =~ s/DECLARE_KFIFO_PTR\s*\(([^,)]+),\s*([^,)]+)\)/$2 \*$1/gos; 1030 1075 1076 + my $declaration = $members; 1077 + 1078 + # Split nested struct/union elements as newer ones 1079 + my $cont = 1; 1080 + while ($cont) { 1081 + $cont = 0; 1082 + while ($members =~ m/(struct|union)([^{};]+){([^{}]*)}([^{}\;]*)\;/) { 1083 + my $newmember = "$1 $4;"; 1084 + my $id = $4; 1085 + my $content = $3; 1086 + $id =~ s/[:\[].*//; 1087 + $id =~ s/^\*+//; 1088 + foreach my $arg (split /;/, $content) { 1089 + next if ($arg =~ m/^\s*$/); 1090 + my $type = $arg; 1091 + my $name = $arg; 1092 + $type =~ s/\s\S+$//; 1093 + $name =~ s/.*\s//; 1094 + $name =~ s/[:\[].*//; 1095 + $name =~ s/^\*+//; 1096 + next if (($name =~ m/^\s*$/)); 1097 + if ($id =~ m/^\s*$/) { 1098 + # anonymous struct/union 1099 + $newmember .= "$type $name;"; 1100 + } else { 1101 + $newmember .= "$type $id.$name;"; 1102 + } 1103 + } 1104 + $members =~ s/(struct|union)([^{};]+){([^{}]*)}([^{}\;]*)\;/$newmember/; 1105 + $cont = 1; 1106 + }; 1107 + }; 1108 + 1109 + # Ignore other nested elements, like enums 1110 + $members =~ s/({[^\{\}]*})//g; 1111 + $nested = $decl_type; 1112 + $nested =~ s/\/\*.*?\*\///gos; 1113 + 1031 1114 create_parameterlist($members, ';', $file); 1032 1115 check_sections($file, $declaration_name, $decl_type, $sectcheck, $struct_actual, $nested); 1033 1116 1117 + # Adjust declaration for better display 1118 + $declaration =~ s/([{;])/$1\n/g; 1119 + $declaration =~ s/}\s+;/};/g; 1120 + # Better handle inlined enums 1121 + do {} while ($declaration =~ s/(enum\s+{[^}]+),([^\n])/$1,\n$2/); 1122 + 1123 + my @def_args = split /\n/, $declaration; 1124 + my $level = 1; 1125 + $declaration = ""; 1126 + foreach my $clause (@def_args) { 1127 + $clause =~ s/^\s+//; 1128 + $clause =~ s/\s+$//; 1129 + $clause =~ s/\s+/ /; 1130 + next if (!$clause); 1131 + $level-- if ($clause =~ m/(})/ && $level > 1); 1132 + if (!($clause =~ m/^\s*#/)) { 1133 + $declaration .= "\t" x $level; 1134 + } 1135 + $declaration .= "\t" . $clause . "\n"; 1136 + $level++ if ($clause =~ m/({)/ && !($clause =~m/}/)); 1137 + } 1034 1138 output_declaration($declaration_name, 1035 1139 'struct', 1036 1140 {'struct' => $declaration_name, 1037 1141 'module' => $modulename, 1142 + 'definition' => $declaration, 1038 1143 'parameterlist' => \@parameterlist, 1039 1144 'parameterdescs' => \%parameterdescs, 1040 1145 'parametertypes' => \%parametertypes,