Skip to content

Commit 518b4ef

Browse files
committed
kernel-doc: fix nested & sub-nested handling (continued)
This is the second patch improving the handling of nested & sub-nested data type handling. With nested arguments are no longer ignored. The patch allows to add documentation for such nested data types. https://www.mail-archive.com/linux-doc@vger.kernel.org/msg15357.html The origin comes from Mauro Carvalho Chehab [1] patching the Perl kernel-doc parser in './scripts' folder of the Linux source tree. This patch here is a bit more elaborated (see discussion at [1]). [1] https://www.mail-archive.com/linux-doc@vger.kernel.org/msg15357.html Reported-by: Mauro Carvalho Chehab <mchehab@s-opensource.com> Signed-off-by: Markus Heiser <markus.heiser@darmarit.de>
1 parent 8d9394a commit 518b4ef

File tree

1 file changed

+39
-63
lines changed

1 file changed

+39
-63
lines changed

linuxdoc/kernel_doc.py

Lines changed: 39 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -630,6 +630,7 @@ def output_struct_decl(
630630
, parametertypes = None # ctx.parametertypes
631631
, sections = None # ctx.sections
632632
, purpose = None # ctx.decl_purpose
633+
, definition = None # ctx.definition
633634
, ):
634635
raise NotImplementedError
635636

@@ -1010,6 +1011,7 @@ def output_struct_decl(
10101011
, parametertypes = None # ctx.parametertypes
10111012
, sections = None # ctx.sections
10121013
, purpose = None # ctx.decl_purpose
1014+
, definition = None # ctx.definition
10131015
, ):
10141016
self.parser.ctx.offset = self.parser.ctx.decl_offset
10151017
self.write_anchor(decl_name)
@@ -1034,32 +1036,20 @@ def output_struct_decl(
10341036
self.write("\n.. code-block:: c\n\n")
10351037
self.write(self.INDENT, decl_type, " ", decl_name, " {\n")
10361038

1037-
for p_name in parameterlist:
1038-
p_type = parametertypes[p_name]
1039-
1040-
if MACRO.match(p_name):
1041-
self.write(self.INDENT, "%s\n" % p_name)
1042-
1043-
elif self.FUNC_PTR.search(p_type):
1044-
# pointer to function
1045-
self.write(
1046-
self.INDENT * 2
1047-
, "%s%s)(%s);\n" % (self.FUNC_PTR[0], p_name, self.FUNC_PTR[1]))
1048-
1049-
elif self.BITFIELD.match(p_type):
1050-
self.write(
1051-
self.INDENT * 2
1052-
, "%s %s%s;\n" % (self.BITFIELD[0], p_name, self.BITFIELD[1]))
1053-
elif p_type.endswith("*"):
1054-
# pointer
1055-
self.write(
1056-
self.INDENT * 2
1057-
, "%s%s;\n" % (p_type, p_name))
1058-
1039+
definition = re.sub(r"(([{;]))", r"\1\n", definition)
1040+
level = 2
1041+
for clause in definition.split('\n'):
1042+
clause = normalize_ws(clause)
1043+
if not clause:
1044+
continue
1045+
if clause[0] == "}" and level > 2:
1046+
level -= 1
1047+
if MACRO.match(clause):
1048+
self.write(self.INDENT, clause[:-1].strip(), '\n')
10591049
else:
1060-
self.write(
1061-
self.INDENT * 2
1062-
, "%s %s;\n" % (p_type, p_name))
1050+
self.write(self.INDENT * level, clause, '\n')
1051+
if clause[-1] == "{":
1052+
level += 1
10631053

10641054
self.write(self.INDENT, "}\n")
10651055

@@ -2188,7 +2178,7 @@ def process_state3_type(self, line):
21882178

21892179
if MACRO.match(line):
21902180
# To distinguish preprocessor directive from regular declaration
2191-
# later.
2181+
# later (drop-semicolon).
21922182
line += ";"
21932183

21942184
m = RE(r"([^{};]*)([{};])(.*)")
@@ -2388,7 +2378,7 @@ def dump_function(self, proto):
23882378
, self.ctx.decl_type
23892379
, self.ctx.sectcheck
23902380
, self.ctx.parameterlist
2391-
, "")
2381+
)
23922382
if hasRetVal:
23932383
self.check_return_section(self.ctx.decl_name, self.ctx.return_type)
23942384

@@ -2426,7 +2416,8 @@ def dump_union(self, proto):
24262416
, parameterdescs = self.ctx.parameterdescs
24272417
, parametertypes = self.ctx.parametertypes
24282418
, sections = self.ctx.sections
2429-
, purpose = self.ctx.decl_purpose )
2419+
, purpose = self.ctx.decl_purpose
2420+
, definition = self.ctx.definition )
24302421

24312422
def dump_struct(self, proto):
24322423

@@ -2447,14 +2438,14 @@ def dump_struct(self, proto):
24472438
, parameterdescs = self.ctx.parameterdescs
24482439
, parametertypes = self.ctx.parametertypes
24492440
, sections = self.ctx.sections
2450-
, purpose = self.ctx.decl_purpose )
2441+
, purpose = self.ctx.decl_purpose
2442+
, definition = self.ctx.definition)
24512443

24522444
def prepare_struct_union(self, proto):
24532445
self.debug("prepare_struct_union(): '%(proto)s'", proto=proto)
24542446

24552447
retVal = False
24562448
members = ""
2457-
nested = ""
24582449

24592450
if C_STRUCT_UNION.match(proto):
24602451

@@ -2464,32 +2455,14 @@ def prepare_struct_union(self, proto):
24642455
% (C_STRUCT_UNION[0], self.ctx.decl_type, proto))
24652456
return False
24662457

2458+
24672459
self.ctx.decl_name = C_STRUCT_UNION[1]
2468-
members = C_STRUCT_UNION[2]
2469-
2470-
if "{" in members:
2471-
# ignore embedded structs or unions
2472-
m = members
2473-
members = ""
2474-
c = 0
2475-
for x in m:
2476-
if x == "{":
2477-
c += 1
2478-
if c == 0:
2479-
members += x
2480-
else:
2481-
nested += x
2482-
if x == "}":
2483-
c -= 1
2460+
self.ctx.definition = members = C89_comments.sub("", C_STRUCT_UNION[2])
24842461

24852462
# ignore members marked private:
24862463
members = re.sub(r"/\*\s*private:.*?/\*\s*public:.*?\*/", "", members, flags=re.I)
24872464
members = re.sub(r"/\*\s*private:.*", "", members, flags=re.I)
24882465

2489-
# strip comments:
2490-
members = C89_comments.sub("", members)
2491-
nested = C89_comments.sub("", nested)
2492-
24932466
# strip kmemcheck_bitfield_{begin,end}.*;
24942467
members = re.sub(r"kmemcheck_bitfield_.*?;", "", members)
24952468

@@ -2508,12 +2481,19 @@ def prepare_struct_union(self, proto):
25082481
, r"unsigned long \1[1 << ((\2) - 1)]"
25092482
, members )
25102483

2484+
# Split nested struct/union elements as newer ones
2485+
NESTED = RE(r"(struct|union)\s+{([^{}]*)}(\s*[^\s;]\s*)")
2486+
while NESTED.search(members):
2487+
members = NESTED.sub(r'\1 \3 \2 ', members)
2488+
2489+
# ignore other nested elements, like enums
2490+
members = re.sub(r"({[^\{\}]*})", '', members)
25112491
self.create_parameterlist(members, ';')
25122492
self.check_sections(self.ctx.decl_name
25132493
, self.ctx.decl_type
25142494
, self.ctx.sectcheck
25152495
, self.ctx.parameterlist # self.ctx.struct_actual.split(" ")
2516-
, nested)
2496+
)
25172497
retVal = True
25182498

25192499
else:
@@ -2557,8 +2537,7 @@ def dump_enum(self, proto):
25572537
self.check_sections(self.ctx.decl_name
25582538
, self.ctx.decl_type
25592539
, self.ctx.sectcheck
2560-
, self.ctx.parameterlist
2561-
, "")
2540+
, self.ctx.parameterlist )
25622541

25632542
self.output_decl(
25642543
self.ctx.decl_name, "enum_decl"
@@ -2601,8 +2580,7 @@ def dump_typedef(self, proto):
26012580
self.check_sections(self.ctx.decl_name
26022581
, self.ctx.decl_type
26032582
, self.ctx.sectcheck
2604-
, self.ctx.parameterlist
2605-
, "")
2583+
, self.ctx.parameterlist )
26062584
self.output_decl(
26072585
self.ctx.decl_name, "function_decl"
26082586
, function = self.ctx.decl_name
@@ -2634,8 +2612,7 @@ def dump_typedef(self, proto):
26342612
self.check_sections(self.ctx.decl_name
26352613
, self.ctx.decl_type
26362614
, self.ctx.sectcheck
2637-
, self.ctx.parameterlist
2638-
, "")
2615+
, self.ctx.parameterlist )
26392616
self.output_decl(
26402617
self.ctx.decl_name, "typedef_decl"
26412618
, typedef = self.ctx.decl_name
@@ -2661,7 +2638,6 @@ def create_parameterlist(self, parameter, splitchar):
26612638

26622639
self.debug("create_parameterlist(): params='%(y)s'", y=parameter)
26632640
for c, p in enumerate(parameter.split(splitchar)):
2664-
26652641
p = C99_comments.sub("", p)
26662642
p = p.strip()
26672643

@@ -2772,7 +2748,7 @@ def push_parameter(self, p_name, p_type):
27722748
# handle unnamed (anonymous) union or struct:
27732749
p_type = p_name
27742750
p_name = "{unnamed_" + p_name + "}"
2775-
self.ctx.parameterdescs[p_name] = "anonymous\n"
2751+
self.ctx.parameterdescs[p_name] = "anonymous"
27762752
self.anon_struct_union = True
27772753

27782754
self.debug(
@@ -2826,10 +2802,10 @@ def push_parameter(self, p_name, p_type):
28262802

28272803

28282804
def check_sections(self, decl_name, decl_type
2829-
, sectcheck, parameterlist, nested):
2805+
, sectcheck, parameterlist):
28302806
self.debug("check_sections(): decl_name='%(n)s' / decl_type='%(t)s' /"
2831-
" sectcheck=%(sc)s / parameterlist=%(pl)s / nested='%(nested)s'"
2832-
, n=decl_name, t=decl_type, sc=sectcheck, pl=parameterlist, nested=nested)
2807+
" sectcheck=%(sc)s / parameterlist=%(pl)s"
2808+
, n=decl_name, t=decl_type, sc=sectcheck, pl=parameterlist)
28332809

28342810
for sect in sectcheck:
28352811
sub_sect = re.sub(r"\..*", "", sect) # take @foo.bar sections as "foo" sub-section
@@ -2846,7 +2822,7 @@ def check_sections(self, decl_name, decl_type
28462822
"excess function parameter '%(sect)s' description in '%(decl_name)s'"
28472823
, sect = sect, decl_name = decl_name
28482824
, line_no = self.ctx.decl_offset )
2849-
elif not re.search(r"\b(" + sect + ")[^a-zA-Z0-9]", nested):
2825+
else:
28502826
self.warn(
28512827
"excess %(decl_type)s member '%(sect)s' description in '%(decl_name)s'"
28522828
, decl_type = decl_type, decl_name = decl_name, sect = sect

0 commit comments

Comments
 (0)