diff options
| author | Jani Nikula <jani.nikula@intel.com> | 2025-06-09 12:40:46 +0300 | 
|---|---|---|
| committer | Jani Nikula <jani.nikula@intel.com> | 2025-06-09 12:40:46 +0300 | 
| commit | 34c55367af96f62e89221444f04487440ebc6487 (patch) | |
| tree | fdb36ba67d7dea09455b55037e26043b7e051ef9 /Documentation/sphinx/kerneldoc.py | |
| parent | 7247efca0dcbc8ac6147db9200ed1549c0662465 (diff) | |
| parent | 19272b37aa4f83ca52bdf9c16d5d81bdd1354494 (diff) | |
| download | linux-34c55367af96f62e89221444f04487440ebc6487.tar.xz | |
Merge drm/drm-next into drm-intel-next
Sync to v6.16-rc1, among other things to get the fixed size GENMASK_U*()
and BIT_U*() macros.
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Diffstat (limited to 'Documentation/sphinx/kerneldoc.py')
| -rw-r--r-- | Documentation/sphinx/kerneldoc.py | 219 | 
1 files changed, 184 insertions, 35 deletions
diff --git a/Documentation/sphinx/kerneldoc.py b/Documentation/sphinx/kerneldoc.py index 39ddae6ae7dd..b818d4c77924 100644 --- a/Documentation/sphinx/kerneldoc.py +++ b/Documentation/sphinx/kerneldoc.py @@ -40,8 +40,40 @@ from docutils.parsers.rst import directives, Directive  import sphinx  from sphinx.util.docutils import switch_source_input  from sphinx.util import logging +from pprint import pformat + +srctree = os.path.abspath(os.environ["srctree"]) +sys.path.insert(0, os.path.join(srctree, "scripts/lib/kdoc")) + +from kdoc_files import KernelFiles +from kdoc_output import RestFormat  __version__  = '1.0' +kfiles = None +logger = logging.getLogger(__name__) + +def cmd_str(cmd): +    """ +    Helper function to output a command line that can be used to produce +    the same records via command line. Helpful to debug troubles at the +    script. +    """ + +    cmd_line = "" + +    for w in cmd: +        if w == "" or " " in w: +            esc_cmd = "'" + w + "'" +        else: +            esc_cmd = w + +        if cmd_line: +            cmd_line += " " + esc_cmd +            continue +        else: +            cmd_line = esc_cmd + +    return cmd_line  class KernelDocDirective(Directive):      """Extract kernel-doc comments from the specified file""" @@ -56,19 +88,48 @@ class KernelDocDirective(Directive):          'functions': directives.unchanged,      }      has_content = False -    logger = logging.getLogger('kerneldoc') +    verbose = 0 + +    parse_args = {} +    msg_args = {} + +    def handle_args(self): -    def run(self):          env = self.state.document.settings.env          cmd = [env.config.kerneldoc_bin, '-rst', '-enable-lineno']          filename = env.config.kerneldoc_srctree + '/' + self.arguments[0] + +        # Arguments used by KernelFiles.parse() function +        self.parse_args = { +            "file_list": [filename], +            "export_file": [] +        } + +        # Arguments used by KernelFiles.msg() function +        self.msg_args = { +            "enable_lineno": True, +            "export": False, +            "internal": False, +            "symbol": [], +            "nosymbol": [], +            "no_doc_sections": False +        } +          export_file_patterns = [] +        verbose = os.environ.get("V") +        if verbose: +            try: +                self.verbose = int(verbose) +            except ValueError: +                pass +          # Tell sphinx of the dependency          env.note_dependency(os.path.abspath(filename)) -        tab_width = self.options.get('tab-width', self.state.document.settings.tab_width) +        self.tab_width = self.options.get('tab-width', +                                          self.state.document.settings.tab_width)          # 'function' is an alias of 'identifiers'          if 'functions' in self.options: @@ -77,80 +138,166 @@ class KernelDocDirective(Directive):          # FIXME: make this nicer and more robust against errors          if 'export' in self.options:              cmd += ['-export'] +            self.msg_args["export"] = True              export_file_patterns = str(self.options.get('export')).split()          elif 'internal' in self.options:              cmd += ['-internal'] +            self.msg_args["internal"] = True              export_file_patterns = str(self.options.get('internal')).split()          elif 'doc' in self.options: -            cmd += ['-function', str(self.options.get('doc'))] +            func = str(self.options.get('doc')) +            cmd += ['-function', func] +            self.msg_args["symbol"].append(func)          elif 'identifiers' in self.options:              identifiers = self.options.get('identifiers').split()              if identifiers:                  for i in identifiers: +                    i = i.rstrip("\\").strip() +                    if not i: +                        continue +                      cmd += ['-function', i] +                    self.msg_args["symbol"].append(i)              else:                  cmd += ['-no-doc-sections'] +                self.msg_args["no_doc_sections"] = True          if 'no-identifiers' in self.options:              no_identifiers = self.options.get('no-identifiers').split()              if no_identifiers:                  for i in no_identifiers: +                    i = i.rstrip("\\").strip() +                    if not i: +                        continue +                      cmd += ['-nosymbol', i] +                    self.msg_args["nosymbol"].append(i)          for pattern in export_file_patterns: +            pattern = pattern.rstrip("\\").strip() +            if not pattern: +                continue +              for f in glob.glob(env.config.kerneldoc_srctree + '/' + pattern):                  env.note_dependency(os.path.abspath(f))                  cmd += ['-export-file', f] +                self.parse_args["export_file"].append(f) + +            # Export file is needed by both parse and msg, as kernel-doc +            # cache exports. +            self.msg_args["export_file"] = self.parse_args["export_file"]          cmd += [filename] -        try: -            self.logger.verbose("calling kernel-doc '%s'" % (" ".join(cmd))) +        return cmd + +    def run_cmd(self, cmd): +        """ +        Execute an external kernel-doc command. +        """ + +        env = self.state.document.settings.env +        node = nodes.section() + +        p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) +        out, err = p.communicate() -            p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) -            out, err = p.communicate() +        out, err = codecs.decode(out, 'utf-8'), codecs.decode(err, 'utf-8') -            out, err = codecs.decode(out, 'utf-8'), codecs.decode(err, 'utf-8') +        if p.returncode != 0: +            sys.stderr.write(err) -            if p.returncode != 0: -                sys.stderr.write(err) +            logger.warning("kernel-doc '%s' failed with return code %d" +                                % (" ".join(cmd), p.returncode)) +            return [nodes.error(None, nodes.paragraph(text = "kernel-doc missing"))] +        elif env.config.kerneldoc_verbosity > 0: +            sys.stderr.write(err) + +        filenames = self.parse_args["file_list"] +        for filename in filenames: +            self.parse_msg(filename, node, out, cmd) + +        return node.children + +    def parse_msg(self, filename, node, out, cmd): +        """ +        Handles a kernel-doc output for a given file +        """ + +        env = self.state.document.settings.env -                self.logger.warning("kernel-doc '%s' failed with return code %d" -                                    % (" ".join(cmd), p.returncode)) -                return [nodes.error(None, nodes.paragraph(text = "kernel-doc missing"))] -            elif env.config.kerneldoc_verbosity > 0: -                sys.stderr.write(err) +        lines = statemachine.string2lines(out, self.tab_width, +                                            convert_whitespace=True) +        result = ViewList() + +        lineoffset = 0; +        line_regex = re.compile(r"^\.\. LINENO ([0-9]+)$") +        for line in lines: +            match = line_regex.search(line) +            if match: +                # sphinx counts lines from 0 +                lineoffset = int(match.group(1)) - 1 +                # we must eat our comments since the upset the markup +            else: +                doc = str(env.srcdir) + "/" + env.docname + ":" + str(self.lineno) +                result.append(line, doc + ": " + filename, lineoffset) +                lineoffset += 1 + +        self.do_parse(result, node) + +    def run_kdoc(self, cmd, kfiles): +        """ +        Execute kernel-doc classes directly instead of running as a separate +        command. +        """ + +        env = self.state.document.settings.env -            lines = statemachine.string2lines(out, tab_width, convert_whitespace=True) -            result = ViewList() +        node = nodes.section() -            lineoffset = 0; -            line_regex = re.compile(r"^\.\. LINENO ([0-9]+)$") -            for line in lines: -                match = line_regex.search(line) -                if match: -                    # sphinx counts lines from 0 -                    lineoffset = int(match.group(1)) - 1 -                    # we must eat our comments since the upset the markup -                else: -                    doc = str(env.srcdir) + "/" + env.docname + ":" + str(self.lineno) -                    result.append(line, doc + ": " + filename, lineoffset) -                    lineoffset += 1 +        kfiles.parse(**self.parse_args) +        filenames = self.parse_args["file_list"] -            node = nodes.section() -            self.do_parse(result, node) +        for filename, out in kfiles.msg(**self.msg_args, filenames=filenames): +            self.parse_msg(filename, node, out, cmd) -            return node.children +        return node.children + +    def run(self): +        global kfiles + +        cmd = self.handle_args() +        if self.verbose >= 1: +            logger.info(cmd_str(cmd)) + +        try: +            if kfiles: +                return self.run_kdoc(cmd, kfiles) +            else: +                return self.run_cmd(cmd)          except Exception as e:  # pylint: disable=W0703 -            self.logger.warning("kernel-doc '%s' processing failed with: %s" % -                                (" ".join(cmd), str(e))) +            logger.warning("kernel-doc '%s' processing failed with: %s" % +                           (cmd_str(cmd), pformat(e)))              return [nodes.error(None, nodes.paragraph(text = "kernel-doc missing"))]      def do_parse(self, result, node):          with switch_source_input(self.state, result):              self.state.nested_parse(result, 0, node, match_titles=1) +def setup_kfiles(app): +    global kfiles + +    kerneldoc_bin = app.env.config.kerneldoc_bin + +    if kerneldoc_bin and kerneldoc_bin.endswith("kernel-doc.py"): +        print("Using Python kernel-doc") +        out_style = RestFormat() +        kfiles = KernelFiles(out_style=out_style, logger=logger) +    else: +        print(f"Using {kerneldoc_bin}") + +  def setup(app):      app.add_config_value('kerneldoc_bin', None, 'env')      app.add_config_value('kerneldoc_srctree', None, 'env') @@ -158,6 +305,8 @@ def setup(app):      app.add_directive('kernel-doc', KernelDocDirective) +    app.connect('builder-inited', setup_kfiles) +      return dict(          version = __version__,          parallel_read_safe = True,  | 
