Skip to content

Commit b8ac025

Browse files
author
Jonathan Corbet
committed
docs: kdoc: rework type prototype parsing
process_proto_type() is using a complex regex and a "while True" loop to split a declaration into chunks and, in the end, count brackets. Switch to using a simpler regex to just do the split directly, and handle each chunk as it comes. The result is, IMO, easier to understand and reason about. The old algorithm would occasionally elide the space between function parameters; see struct rng_alg->generate(), foe example. The only output difference is to not elide that space, which is more correct. Reviewed-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org> Tested-by: Akira Yokosawa <akiyks@gmail.com> Signed-off-by: Jonathan Corbet <corbet@lwn.net> Link: https://lore.kernel.org/r/20250703184403.274408-5-corbet@lwn.net
1 parent 061a1c1 commit b8ac025

1 file changed

Lines changed: 25 additions & 18 deletions

File tree

scripts/lib/kdoc/kdoc_parser.py

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1594,30 +1594,37 @@ def process_proto_type(self, ln, line):
15941594

15951595
# Strip C99-style comments and surrounding whitespace
15961596
line = KernRe(r"//.*$", re.S).sub('', line).strip()
1597+
if not line:
1598+
return # nothing to see here
15971599

15981600
# To distinguish preprocessor directive from regular declaration later.
15991601
if line.startswith('#'):
16001602
line += ";"
1601-
1602-
r = KernRe(r'([^\{\};]*)([\{\};])(.*)')
1603-
while True:
1604-
if r.search(line):
1605-
if self.entry.prototype:
1606-
self.entry.prototype += " "
1607-
self.entry.prototype += r.group(1) + r.group(2)
1608-
1609-
self.entry.brcount += r.group(2).count('{')
1610-
self.entry.brcount -= r.group(2).count('}')
1611-
1612-
if r.group(2) == ';' and self.entry.brcount <= 0:
1603+
#
1604+
# Split the declaration on any of { } or ;, and accumulate pieces
1605+
# until we hit a semicolon while not inside {brackets}
1606+
#
1607+
r = KernRe(r'(.*?)([{};])')
1608+
for chunk in r.split(line):
1609+
if chunk: # Ignore empty matches
1610+
self.entry.prototype += chunk
1611+
#
1612+
# This cries out for a match statement ... someday after we can
1613+
# drop Python 3.9 ...
1614+
#
1615+
if chunk == '{':
1616+
self.entry.brcount += 1
1617+
elif chunk == '}':
1618+
self.entry.brcount -= 1
1619+
elif chunk == ';' and self.entry.brcount <= 0:
16131620
self.dump_declaration(ln, self.entry.prototype)
16141621
self.reset_state(ln)
1615-
break
1616-
1617-
line = r.group(3)
1618-
else:
1619-
self.entry.prototype += line
1620-
break
1622+
return
1623+
#
1624+
# We hit the end of the line while still in the declaration; put
1625+
# in a space to represent the newline.
1626+
#
1627+
self.entry.prototype += ' '
16211628

16221629
def process_proto(self, ln, line):
16231630
"""STATE_PROTO: reading a function/whatever prototype."""

0 commit comments

Comments
 (0)