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

Merge branch 'kdoc-item2' into docs-mw

The kerneldoc parsing phase gathers all of the information about the
declarations of interest, then passes it through to the output phase as a
dict that is an unstructured blob of information; this organization has its
origins in the Perl version of the program. It results in an interface
that is difficult to reason about, dozen-parameter function calls, and
other ills.

Introduce a new class (KdocItem) to carry this information between the
parser and the output modules, and, step by step, modify the system to use
this class in a more structured way. This could be taken further by
creating a subclass of KdocItem for each declaration type (function,
struct, ...), but that is probably more structure than we need.

The result is (I hope) clearer code, the removal of a bunch of boilerplate,
and no changes to the generated output.

+145 -244
+2 -2
scripts/lib/kdoc/kdoc_files.py
··· 275 275 self.config.log.warning("No kernel-doc for file %s", fname) 276 276 continue 277 277 278 - for name, arg in self.results[fname]: 279 - m = self.out_msg(fname, name, arg) 278 + for arg in self.results[fname]: 279 + m = self.out_msg(fname, arg.name, arg) 280 280 281 281 if m is None: 282 282 ln = arg.get("ln", 0)
+42
scripts/lib/kdoc/kdoc_item.py
··· 1 + # SPDX-License-Identifier: GPL-2.0 2 + # 3 + # A class that will, eventually, encapsulate all of the parsed data that we 4 + # then pass into the output modules. 5 + # 6 + 7 + class KdocItem: 8 + def __init__(self, name, type, start_line, **other_stuff): 9 + self.name = name 10 + self.type = type 11 + self.declaration_start_line = start_line 12 + self.sections = {} 13 + self.sections_start_lines = {} 14 + self.parameterlist = [] 15 + self.parameterdesc_start_lines = [] 16 + self.parameterdescs = {} 17 + self.parametertypes = {} 18 + # 19 + # Just save everything else into our own dict so that the output 20 + # side can grab it directly as before. As we move things into more 21 + # structured data, this will, hopefully, fade away. 22 + # 23 + self.other_stuff = other_stuff 24 + 25 + def get(self, key, default = None): 26 + return self.other_stuff.get(key, default) 27 + 28 + def __getitem__(self, key): 29 + return self.get(key) 30 + 31 + # 32 + # Tracking of section and parameter information. 33 + # 34 + def set_sections(self, sections, start_lines): 35 + self.sections = sections 36 + self.section_start_lines = start_lines 37 + 38 + def set_params(self, names, descs, types, starts): 39 + self.parameterlist = names 40 + self.parameterdescs = descs 41 + self.parametertypes = types 42 + self.parameterdesc_start_lines = starts
+64 -108
scripts/lib/kdoc/kdoc_output.py
··· 124 124 Output warnings for identifiers that will be displayed. 125 125 """ 126 126 127 - warnings = args.get('warnings', []) 128 - 129 - for log_msg in warnings: 127 + for log_msg in args.warnings: 130 128 self.config.warning(log_msg) 131 129 132 130 def check_doc(self, name, args): ··· 182 184 183 185 self.data = "" 184 186 185 - dtype = args.get('type', "") 187 + dtype = args.type 186 188 187 189 if dtype == "doc": 188 190 self.out_doc(fname, name, args) ··· 336 338 starts by putting out the name of the doc section itself, but that 337 339 tends to duplicate a header already in the template file. 338 340 """ 339 - 340 - sectionlist = args.get('sectionlist', []) 341 - sections = args.get('sections', {}) 342 - section_start_lines = args.get('section_start_lines', {}) 343 - 344 - for section in sectionlist: 341 + for section, text in args.sections.items(): 345 342 # Skip sections that are in the nosymbol_table 346 343 if section in self.nosymbol: 347 344 continue ··· 348 355 else: 349 356 self.data += f'{self.lineprefix}**{section}**\n\n' 350 357 351 - self.print_lineno(section_start_lines.get(section, 0)) 352 - self.output_highlight(sections[section]) 358 + self.print_lineno(args.section_start_lines.get(section, 0)) 359 + self.output_highlight(text) 353 360 self.data += "\n" 354 361 self.data += "\n" 355 362 ··· 365 372 366 373 func_macro = args.get('func_macro', False) 367 374 if func_macro: 368 - signature = args['function'] 375 + signature = name 369 376 else: 370 377 if args.get('functiontype'): 371 378 signature = args['functiontype'] + " " 372 - signature += args['function'] + " (" 379 + signature += name + " (" 373 380 374 - parameterlist = args.get('parameterlist', []) 375 - parameterdescs = args.get('parameterdescs', {}) 376 - parameterdesc_start_lines = args.get('parameterdesc_start_lines', {}) 377 - 378 - ln = args.get('declaration_start_line', 0) 379 - 381 + ln = args.declaration_start_line 380 382 count = 0 381 - for parameter in parameterlist: 383 + for parameter in args.parameterlist: 382 384 if count != 0: 383 385 signature += ", " 384 386 count += 1 385 - dtype = args['parametertypes'].get(parameter, "") 387 + dtype = args.parametertypes.get(parameter, "") 386 388 387 389 if function_pointer.search(dtype): 388 390 signature += function_pointer.group(1) + parameter + function_pointer.group(3) ··· 389 401 390 402 self.print_lineno(ln) 391 403 if args.get('typedef') or not args.get('functiontype'): 392 - self.data += f".. c:macro:: {args['function']}\n\n" 404 + self.data += f".. c:macro:: {name}\n\n" 393 405 394 406 if args.get('typedef'): 395 407 self.data += " **Typedef**: " ··· 412 424 # function prototypes apart 413 425 self.lineprefix = " " 414 426 415 - if parameterlist: 427 + if args.parameterlist: 416 428 self.data += ".. container:: kernelindent\n\n" 417 429 self.data += f"{self.lineprefix}**Parameters**\n\n" 418 430 419 - for parameter in parameterlist: 431 + for parameter in args.parameterlist: 420 432 parameter_name = KernRe(r'\[.*').sub('', parameter) 421 - dtype = args['parametertypes'].get(parameter, "") 433 + dtype = args.parametertypes.get(parameter, "") 422 434 423 435 if dtype: 424 436 self.data += f"{self.lineprefix}``{dtype}``\n" 425 437 else: 426 438 self.data += f"{self.lineprefix}``{parameter}``\n" 427 439 428 - self.print_lineno(parameterdesc_start_lines.get(parameter_name, 0)) 440 + self.print_lineno(args.parameterdesc_start_lines.get(parameter_name, 0)) 429 441 430 442 self.lineprefix = " " 431 - if parameter_name in parameterdescs and \ 432 - parameterdescs[parameter_name] != KernelDoc.undescribed: 443 + if parameter_name in args.parameterdescs and \ 444 + args.parameterdescs[parameter_name] != KernelDoc.undescribed: 433 445 434 - self.output_highlight(parameterdescs[parameter_name]) 446 + self.output_highlight(args.parameterdescs[parameter_name]) 435 447 self.data += "\n" 436 448 else: 437 449 self.data += f"{self.lineprefix}*undescribed*\n\n" ··· 443 455 def out_enum(self, fname, name, args): 444 456 445 457 oldprefix = self.lineprefix 446 - name = args.get('enum', '') 447 - parameterlist = args.get('parameterlist', []) 448 - parameterdescs = args.get('parameterdescs', {}) 449 - ln = args.get('declaration_start_line', 0) 458 + ln = args.declaration_start_line 450 459 451 460 self.data += f"\n\n.. c:enum:: {name}\n\n" 452 461 ··· 457 472 self.lineprefix = outer + " " 458 473 self.data += f"{outer}**Constants**\n\n" 459 474 460 - for parameter in parameterlist: 475 + for parameter in args.parameterlist: 461 476 self.data += f"{outer}``{parameter}``\n" 462 477 463 - if parameterdescs.get(parameter, '') != KernelDoc.undescribed: 464 - self.output_highlight(parameterdescs[parameter]) 478 + if args.parameterdescs.get(parameter, '') != KernelDoc.undescribed: 479 + self.output_highlight(args.parameterdescs[parameter]) 465 480 else: 466 481 self.data += f"{self.lineprefix}*undescribed*\n\n" 467 482 self.data += "\n" ··· 472 487 def out_typedef(self, fname, name, args): 473 488 474 489 oldprefix = self.lineprefix 475 - name = args.get('typedef', '') 476 - ln = args.get('declaration_start_line', 0) 490 + ln = args.declaration_start_line 477 491 478 492 self.data += f"\n\n.. c:type:: {name}\n\n" 479 493 ··· 488 504 489 505 def out_struct(self, fname, name, args): 490 506 491 - name = args.get('struct', "") 492 507 purpose = args.get('purpose', "") 493 508 declaration = args.get('definition', "") 494 - dtype = args.get('type', "struct") 495 - ln = args.get('declaration_start_line', 0) 496 - 497 - parameterlist = args.get('parameterlist', []) 498 - parameterdescs = args.get('parameterdescs', {}) 499 - parameterdesc_start_lines = args.get('parameterdesc_start_lines', {}) 509 + dtype = args.type 510 + ln = args.declaration_start_line 500 511 501 512 self.data += f"\n\n.. c:{dtype}:: {name}\n\n" 502 513 ··· 515 536 516 537 self.lineprefix = " " 517 538 self.data += f"{self.lineprefix}**Members**\n\n" 518 - for parameter in parameterlist: 539 + for parameter in args.parameterlist: 519 540 if not parameter or parameter.startswith("#"): 520 541 continue 521 542 522 543 parameter_name = parameter.split("[", maxsplit=1)[0] 523 544 524 - if parameterdescs.get(parameter_name) == KernelDoc.undescribed: 545 + if args.parameterdescs.get(parameter_name) == KernelDoc.undescribed: 525 546 continue 526 547 527 - self.print_lineno(parameterdesc_start_lines.get(parameter_name, 0)) 548 + self.print_lineno(args.parameterdesc_start_lines.get(parameter_name, 0)) 528 549 529 550 self.data += f"{self.lineprefix}``{parameter}``\n" 530 551 531 552 self.lineprefix = " " 532 - self.output_highlight(parameterdescs[parameter_name]) 553 + self.output_highlight(args.parameterdescs[parameter_name]) 533 554 self.lineprefix = " " 534 555 535 556 self.data += "\n" ··· 615 636 self.data += line + "\n" 616 637 617 638 def out_doc(self, fname, name, args): 618 - sectionlist = args.get('sectionlist', []) 619 - sections = args.get('sections', {}) 620 - 621 639 if not self.check_doc(name, args): 622 640 return 623 641 624 642 self.data += f'.TH "{self.modulename}" 9 "{self.modulename}" "{self.man_date}" "API Manual" LINUX' + "\n" 625 643 626 - for section in sectionlist: 644 + for section, text in args.sections.items(): 627 645 self.data += f'.SH "{section}"' + "\n" 628 - self.output_highlight(sections.get(section)) 646 + self.output_highlight(text) 629 647 630 648 def out_function(self, fname, name, args): 631 649 """output function in man""" 632 650 633 - parameterlist = args.get('parameterlist', []) 634 - parameterdescs = args.get('parameterdescs', {}) 635 - sectionlist = args.get('sectionlist', []) 636 - sections = args.get('sections', {}) 637 - 638 - self.data += f'.TH "{args["function"]}" 9 "{args["function"]}" "{self.man_date}" "Kernel Hacker\'s Manual" LINUX' + "\n" 651 + self.data += f'.TH "{name}" 9 "{name}" "{self.man_date}" "Kernel Hacker\'s Manual" LINUX' + "\n" 639 652 640 653 self.data += ".SH NAME\n" 641 - self.data += f"{args['function']} \\- {args['purpose']}\n" 654 + self.data += f"{name} \\- {args['purpose']}\n" 642 655 643 656 self.data += ".SH SYNOPSIS\n" 644 657 if args.get('functiontype', ''): 645 - self.data += f'.B "{args["functiontype"]}" {args["function"]}' + "\n" 658 + self.data += f'.B "{args["functiontype"]}" {name}' + "\n" 646 659 else: 647 - self.data += f'.B "{args["function"]}' + "\n" 660 + self.data += f'.B "{name}' + "\n" 648 661 649 662 count = 0 650 663 parenth = "(" 651 664 post = "," 652 665 653 - for parameter in parameterlist: 654 - if count == len(parameterlist) - 1: 666 + for parameter in args.parameterlist: 667 + if count == len(args.parameterlist) - 1: 655 668 post = ");" 656 669 657 - dtype = args['parametertypes'].get(parameter, "") 670 + dtype = args.parametertypes.get(parameter, "") 658 671 if function_pointer.match(dtype): 659 672 # Pointer-to-function 660 673 self.data += f'".BI "{parenth}{function_pointer.group(1)}" " ") ({function_pointer.group(2)}){post}"' + "\n" ··· 657 686 count += 1 658 687 parenth = "" 659 688 660 - if parameterlist: 689 + if args.parameterlist: 661 690 self.data += ".SH ARGUMENTS\n" 662 691 663 - for parameter in parameterlist: 692 + for parameter in args.parameterlist: 664 693 parameter_name = re.sub(r'\[.*', '', parameter) 665 694 666 695 self.data += f'.IP "{parameter}" 12' + "\n" 667 - self.output_highlight(parameterdescs.get(parameter_name, "")) 696 + self.output_highlight(args.parameterdescs.get(parameter_name, "")) 668 697 669 - for section in sectionlist: 698 + for section, text in args.sections.items(): 670 699 self.data += f'.SH "{section.upper()}"' + "\n" 671 - self.output_highlight(sections[section]) 700 + self.output_highlight(text) 672 701 673 702 def out_enum(self, fname, name, args): 674 - 675 - name = args.get('enum', '') 676 - parameterlist = args.get('parameterlist', []) 677 - sectionlist = args.get('sectionlist', []) 678 - sections = args.get('sections', {}) 679 - 680 - self.data += f'.TH "{self.modulename}" 9 "enum {args["enum"]}" "{self.man_date}" "API Manual" LINUX' + "\n" 703 + self.data += f'.TH "{self.modulename}" 9 "enum {name}" "{self.man_date}" "API Manual" LINUX' + "\n" 681 704 682 705 self.data += ".SH NAME\n" 683 - self.data += f"enum {args['enum']} \\- {args['purpose']}\n" 706 + self.data += f"enum {name} \\- {args['purpose']}\n" 684 707 685 708 self.data += ".SH SYNOPSIS\n" 686 - self.data += f"enum {args['enum']}" + " {\n" 709 + self.data += f"enum {name}" + " {\n" 687 710 688 711 count = 0 689 - for parameter in parameterlist: 712 + for parameter in args.parameterlist: 690 713 self.data += f'.br\n.BI " {parameter}"' + "\n" 691 - if count == len(parameterlist) - 1: 714 + if count == len(args.parameterlist) - 1: 692 715 self.data += "\n};\n" 693 716 else: 694 717 self.data += ", \n.br\n" ··· 691 726 692 727 self.data += ".SH Constants\n" 693 728 694 - for parameter in parameterlist: 729 + for parameter in args.parameterlist: 695 730 parameter_name = KernRe(r'\[.*').sub('', parameter) 696 731 self.data += f'.IP "{parameter}" 12' + "\n" 697 - self.output_highlight(args['parameterdescs'].get(parameter_name, "")) 732 + self.output_highlight(args.parameterdescs.get(parameter_name, "")) 698 733 699 - for section in sectionlist: 734 + for section, text in args.sections.items(): 700 735 self.data += f'.SH "{section}"' + "\n" 701 - self.output_highlight(sections[section]) 736 + self.output_highlight(text) 702 737 703 738 def out_typedef(self, fname, name, args): 704 739 module = self.modulename 705 - typedef = args.get('typedef') 706 740 purpose = args.get('purpose') 707 - sectionlist = args.get('sectionlist', []) 708 - sections = args.get('sections', {}) 709 741 710 - self.data += f'.TH "{module}" 9 "{typedef}" "{self.man_date}" "API Manual" LINUX' + "\n" 742 + self.data += f'.TH "{module}" 9 "{name}" "{self.man_date}" "API Manual" LINUX' + "\n" 711 743 712 744 self.data += ".SH NAME\n" 713 - self.data += f"typedef {typedef} \\- {purpose}\n" 745 + self.data += f"typedef {name} \\- {purpose}\n" 714 746 715 - for section in sectionlist: 747 + for section, text in args.sections.items(): 716 748 self.data += f'.SH "{section}"' + "\n" 717 - self.output_highlight(sections.get(section)) 749 + self.output_highlight(text) 718 750 719 751 def out_struct(self, fname, name, args): 720 752 module = self.modulename 721 - struct_type = args.get('type') 722 - struct_name = args.get('struct') 723 753 purpose = args.get('purpose') 724 754 definition = args.get('definition') 725 - sectionlist = args.get('sectionlist', []) 726 - parameterlist = args.get('parameterlist', []) 727 - sections = args.get('sections', {}) 728 - parameterdescs = args.get('parameterdescs', {}) 729 755 730 - self.data += f'.TH "{module}" 9 "{struct_type} {struct_name}" "{self.man_date}" "API Manual" LINUX' + "\n" 756 + self.data += f'.TH "{module}" 9 "{args.type} {name}" "{self.man_date}" "API Manual" LINUX' + "\n" 731 757 732 758 self.data += ".SH NAME\n" 733 - self.data += f"{struct_type} {struct_name} \\- {purpose}\n" 759 + self.data += f"{args.type} {name} \\- {purpose}\n" 734 760 735 761 # Replace tabs with two spaces and handle newlines 736 762 declaration = definition.replace("\t", " ") 737 763 declaration = KernRe(r"\n").sub('"\n.br\n.BI "', declaration) 738 764 739 765 self.data += ".SH SYNOPSIS\n" 740 - self.data += f"{struct_type} {struct_name} " + "{" + "\n.br\n" 766 + self.data += f"{args.type} {name} " + "{" + "\n.br\n" 741 767 self.data += f'.BI "{declaration}\n' + "};\n.br\n\n" 742 768 743 769 self.data += ".SH Members\n" 744 - for parameter in parameterlist: 770 + for parameter in args.parameterlist: 745 771 if parameter.startswith("#"): 746 772 continue 747 773 748 774 parameter_name = re.sub(r"\[.*", "", parameter) 749 775 750 - if parameterdescs.get(parameter_name) == KernelDoc.undescribed: 776 + if args.parameterdescs.get(parameter_name) == KernelDoc.undescribed: 751 777 continue 752 778 753 779 self.data += f'.IP "{parameter}" 12' + "\n" 754 - self.output_highlight(parameterdescs.get(parameter_name)) 780 + self.output_highlight(args.parameterdescs.get(parameter_name)) 755 781 756 - for section in sectionlist: 782 + for section, text in args.sections.items(): 757 783 self.data += f'.SH "{section}"' + "\n" 758 - self.output_highlight(sections.get(section)) 784 + self.output_highlight(text)
+37 -134
scripts/lib/kdoc/kdoc_parser.py
··· 12 12 documentation comments 13 13 """ 14 14 15 + import sys 15 16 import re 16 17 from pprint import pformat 17 18 18 19 from kdoc_re import NestedMatch, KernRe 19 - 20 + from kdoc_item import KdocItem 20 21 21 22 # 22 23 # Regular expressions used to parse kernel-doc markups at KernelDoc class. ··· 43 42 # @{section-name}: 44 43 # while trying to not match literal block starts like "example::" 45 44 # 45 + known_section_names = 'description|context|returns?|notes?|examples?' 46 + known_sections = KernRe(known_section_names, flags = re.I) 46 47 doc_sect = doc_com + \ 47 - KernRe(r'\s*(\@[.\w]+|\@\.\.\.|description|context|returns?|notes?|examples?)\s*:([^:].*)?$', 48 - flags=re.I, cache=False) 48 + KernRe(r'\s*(\@[.\w]+|\@\.\.\.|' + known_section_names + r')\s*:([^:].*)?$', 49 + flags=re.I, cache=False) 49 50 50 51 doc_content = doc_com_body + KernRe(r'(.*)', cache=False) 51 52 doc_inline_start = KernRe(r'^\s*/\*\*\s*$', cache=False) ··· 118 115 self.config = config 119 116 120 117 self._contents = [] 121 - self.sectcheck = "" 122 - self.struct_actual = "" 123 118 self.prototype = "" 124 119 125 120 self.warnings = [] ··· 128 127 self.parameterdesc_start_lines = {} 129 128 130 129 self.section_start_lines = {} 131 - self.sectionlist = [] 132 130 self.sections = {} 133 131 134 132 self.anon_struct_union = False ··· 189 189 self.parameterdescs[name] = contents 190 190 self.parameterdesc_start_lines[name] = self.new_start_line 191 191 192 - self.sectcheck += name + " " 193 192 self.new_start_line = 0 194 193 195 194 else: ··· 201 202 self.sections[name] += '\n' + contents 202 203 else: 203 204 self.sections[name] = contents 204 - self.sectionlist.append(name) 205 205 self.section_start_lines[name] = self.new_start_line 206 206 self.new_start_line = 0 207 207 ··· 239 241 # Place all potential outputs into an array 240 242 self.entries = [] 241 243 244 + # 245 + # We need Python 3.7 for its "dicts remember the insertion 246 + # order" guarantee 247 + # 248 + if sys.version_info.major == 3 and sys.version_info.minor < 7: 249 + self.emit_msg(0, 250 + 'Python 3.7 or later is required for correct results') 251 + 242 252 def emit_msg(self, ln, msg, warning=True): 243 253 """Emit a message""" 244 254 ··· 277 271 The actual output and output filters will be handled elsewhere 278 272 """ 279 273 280 - # The implementation here is different than the original kernel-doc: 281 - # instead of checking for output filters or actually output anything, 282 - # it just stores the declaration content at self.entries, as the 283 - # output will happen on a separate class. 284 - # 285 - # For now, we're keeping the same name of the function just to make 286 - # easier to compare the source code of both scripts 287 - 288 - args["declaration_start_line"] = self.entry.declaration_start_line 289 - args["type"] = dtype 290 - args["warnings"] = self.entry.warnings 291 - 292 - # TODO: use colletions.OrderedDict to remove sectionlist 293 - 294 - sections = args.get('sections', {}) 295 - sectionlist = args.get('sectionlist', []) 274 + item = KdocItem(name, dtype, self.entry.declaration_start_line, **args) 275 + item.warnings = self.entry.warnings 296 276 297 277 # Drop empty sections 298 278 # TODO: improve empty sections logic to emit warnings 279 + sections = self.entry.sections 299 280 for section in ["Description", "Return"]: 300 - if section in sectionlist: 301 - if not sections[section].rstrip(): 302 - del sections[section] 303 - sectionlist.remove(section) 304 - 305 - self.entries.append((name, args)) 281 + if section in sections and not sections[section].rstrip(): 282 + del sections[section] 283 + item.set_sections(sections, self.entry.section_start_lines) 284 + item.set_params(self.entry.parameterlist, self.entry.parameterdescs, 285 + self.entry.parametertypes, 286 + self.entry.parameterdesc_start_lines) 287 + self.entries.append(item) 306 288 307 289 self.config.log.debug("Output: %s:%s = %s", dtype, name, pformat(args)) 308 290 ··· 376 382 org_arg = KernRe(r'\s\s+').sub(' ', org_arg) 377 383 self.entry.parametertypes[param] = org_arg 378 384 379 - def save_struct_actual(self, actual): 380 - """ 381 - Strip all spaces from the actual param so that it looks like 382 - one string item. 383 - """ 384 - 385 - actual = KernRe(r'\s*').sub("", actual, count=1) 386 - 387 - self.entry.struct_actual += actual + " " 388 385 389 386 def create_parameter_list(self, ln, decl_type, args, 390 387 splitter, declaration_name): ··· 421 436 param = arg 422 437 423 438 dtype = KernRe(r'([^\(]+\(\*?)\s*' + re.escape(param)).sub(r'\1', arg) 424 - self.save_struct_actual(param) 425 439 self.push_parameter(ln, decl_type, param, dtype, 426 440 arg, declaration_name) 427 441 ··· 437 453 438 454 dtype = KernRe(r'([^\(]+\(\*?)\s*' + re.escape(param)).sub(r'\1', arg) 439 455 440 - self.save_struct_actual(param) 441 456 self.push_parameter(ln, decl_type, param, dtype, 442 457 arg, declaration_name) 443 458 ··· 469 486 470 487 param = r.group(1) 471 488 472 - self.save_struct_actual(r.group(2)) 473 489 self.push_parameter(ln, decl_type, r.group(2), 474 490 f"{dtype} {r.group(1)}", 475 491 arg, declaration_name) ··· 480 498 continue 481 499 482 500 if dtype != "": # Skip unnamed bit-fields 483 - self.save_struct_actual(r.group(1)) 484 501 self.push_parameter(ln, decl_type, r.group(1), 485 502 f"{dtype}:{r.group(2)}", 486 503 arg, declaration_name) 487 504 else: 488 - self.save_struct_actual(param) 489 505 self.push_parameter(ln, decl_type, param, dtype, 490 506 arg, declaration_name) 491 507 492 - def check_sections(self, ln, decl_name, decl_type, sectcheck, prmscheck): 508 + def check_sections(self, ln, decl_name, decl_type): 493 509 """ 494 510 Check for errors inside sections, emitting warnings if not found 495 511 parameters are described. 496 512 """ 497 - 498 - sects = sectcheck.split() 499 - prms = prmscheck.split() 500 - err = False 501 - 502 - for sx in range(len(sects)): # pylint: disable=C0200 503 - err = True 504 - for px in range(len(prms)): # pylint: disable=C0200 505 - prm_clean = prms[px] 506 - prm_clean = KernRe(r'\[.*\]').sub('', prm_clean) 507 - prm_clean = attribute.sub('', prm_clean) 508 - 509 - # ignore array size in a parameter string; 510 - # however, the original param string may contain 511 - # spaces, e.g.: addr[6 + 2] 512 - # and this appears in @prms as "addr[6" since the 513 - # parameter list is split at spaces; 514 - # hence just ignore "[..." for the sections check; 515 - prm_clean = KernRe(r'\[.*').sub('', prm_clean) 516 - 517 - if prm_clean == sects[sx]: 518 - err = False 519 - break 520 - 521 - if err: 513 + for section in self.entry.sections: 514 + if section not in self.entry.parameterlist and \ 515 + not known_sections.search(section): 522 516 if decl_type == 'function': 523 517 dname = f"{decl_type} parameter" 524 518 else: 525 519 dname = f"{decl_type} member" 526 - 527 520 self.emit_msg(ln, 528 - f"Excess {dname} '{sects[sx]}' description in '{decl_name}'") 521 + f"Excess {dname} '{section}' description in '{decl_name}'") 529 522 530 523 def check_return_section(self, ln, declaration_name, return_type): 531 524 """ ··· 754 797 755 798 self.create_parameter_list(ln, decl_type, members, ';', 756 799 declaration_name) 757 - self.check_sections(ln, declaration_name, decl_type, 758 - self.entry.sectcheck, self.entry.struct_actual) 800 + self.check_sections(ln, declaration_name, decl_type) 759 801 760 802 # Adjust declaration for better display 761 803 declaration = KernRe(r'([\{;])').sub(r'\1\n', declaration) ··· 790 834 level += 1 791 835 792 836 self.output_declaration(decl_type, declaration_name, 793 - struct=declaration_name, 794 837 definition=declaration, 795 - parameterlist=self.entry.parameterlist, 796 - parameterdescs=self.entry.parameterdescs, 797 - parametertypes=self.entry.parametertypes, 798 - parameterdesc_start_lines=self.entry.parameterdesc_start_lines, 799 - sectionlist=self.entry.sectionlist, 800 - sections=self.entry.sections, 801 - section_start_lines=self.entry.section_start_lines, 802 838 purpose=self.entry.declaration_purpose) 803 839 804 840 def dump_enum(self, ln, proto): ··· 869 921 f"Excess enum value '%{k}' description in '{declaration_name}'") 870 922 871 923 self.output_declaration('enum', declaration_name, 872 - enum=declaration_name, 873 - parameterlist=self.entry.parameterlist, 874 - parameterdescs=self.entry.parameterdescs, 875 - parameterdesc_start_lines=self.entry.parameterdesc_start_lines, 876 - sectionlist=self.entry.sectionlist, 877 - sections=self.entry.sections, 878 - section_start_lines=self.entry.section_start_lines, 879 924 purpose=self.entry.declaration_purpose) 880 925 881 926 def dump_declaration(self, ln, prototype): ··· 878 937 879 938 if self.entry.decl_type == "enum": 880 939 self.dump_enum(ln, prototype) 881 - return 882 - 883 - if self.entry.decl_type == "typedef": 940 + elif self.entry.decl_type == "typedef": 884 941 self.dump_typedef(ln, prototype) 885 - return 886 - 887 - if self.entry.decl_type in ["union", "struct"]: 942 + elif self.entry.decl_type in ["union", "struct"]: 888 943 self.dump_struct(ln, prototype) 889 - return 890 - 891 - self.output_declaration(self.entry.decl_type, prototype, 892 - entry=self.entry) 944 + else: 945 + # This would be a bug 946 + self.emit_message(ln, f'Unknown declaration type: {self.entry.decl_type}') 893 947 894 948 def dump_function(self, ln, prototype): 895 949 """ ··· 1018 1082 f"expecting prototype for {self.entry.identifier}(). Prototype was for {declaration_name}() instead") 1019 1083 return 1020 1084 1021 - prms = " ".join(self.entry.parameterlist) 1022 - self.check_sections(ln, declaration_name, "function", 1023 - self.entry.sectcheck, prms) 1085 + self.check_sections(ln, declaration_name, "function") 1024 1086 1025 1087 self.check_return_section(ln, declaration_name, return_type) 1026 1088 1027 1089 if 'typedef' in return_type: 1028 1090 self.output_declaration(decl_type, declaration_name, 1029 - function=declaration_name, 1030 1091 typedef=True, 1031 1092 functiontype=return_type, 1032 - parameterlist=self.entry.parameterlist, 1033 - parameterdescs=self.entry.parameterdescs, 1034 - parametertypes=self.entry.parametertypes, 1035 - parameterdesc_start_lines=self.entry.parameterdesc_start_lines, 1036 - sectionlist=self.entry.sectionlist, 1037 - sections=self.entry.sections, 1038 - section_start_lines=self.entry.section_start_lines, 1039 1093 purpose=self.entry.declaration_purpose, 1040 1094 func_macro=func_macro) 1041 1095 else: 1042 1096 self.output_declaration(decl_type, declaration_name, 1043 - function=declaration_name, 1044 1097 typedef=False, 1045 1098 functiontype=return_type, 1046 - parameterlist=self.entry.parameterlist, 1047 - parameterdescs=self.entry.parameterdescs, 1048 - parametertypes=self.entry.parametertypes, 1049 - parameterdesc_start_lines=self.entry.parameterdesc_start_lines, 1050 - sectionlist=self.entry.sectionlist, 1051 - sections=self.entry.sections, 1052 - section_start_lines=self.entry.section_start_lines, 1053 1099 purpose=self.entry.declaration_purpose, 1054 1100 func_macro=func_macro) 1055 1101 ··· 1068 1150 self.create_parameter_list(ln, decl_type, args, ',', declaration_name) 1069 1151 1070 1152 self.output_declaration(decl_type, declaration_name, 1071 - function=declaration_name, 1072 1153 typedef=True, 1073 1154 functiontype=return_type, 1074 - parameterlist=self.entry.parameterlist, 1075 - parameterdescs=self.entry.parameterdescs, 1076 - parametertypes=self.entry.parametertypes, 1077 - parameterdesc_start_lines=self.entry.parameterdesc_start_lines, 1078 - sectionlist=self.entry.sectionlist, 1079 - sections=self.entry.sections, 1080 - section_start_lines=self.entry.section_start_lines, 1081 1155 purpose=self.entry.declaration_purpose) 1082 1156 return 1083 1157 ··· 1089 1179 return 1090 1180 1091 1181 self.output_declaration('typedef', declaration_name, 1092 - typedef=declaration_name, 1093 - sectionlist=self.entry.sectionlist, 1094 - sections=self.entry.sections, 1095 - section_start_lines=self.entry.section_start_lines, 1096 1182 purpose=self.entry.declaration_purpose) 1097 1183 return 1098 1184 ··· 1570 1664 1571 1665 if doc_end.search(line): 1572 1666 self.dump_section() 1573 - self.output_declaration("doc", self.entry.identifier, 1574 - sectionlist=self.entry.sectionlist, 1575 - sections=self.entry.sections, 1576 - section_start_lines=self.entry.section_start_lines) 1667 + self.output_declaration("doc", self.entry.identifier) 1577 1668 self.reset_state(ln) 1578 1669 1579 1670 elif doc_content.search(line):