1731 lines · 63.0 KB · Python
RawDownload
        r = KernRe(r'DEFINE_EVENT\((.*?),(.*?),')        if r.search(proto):            tracepointname = r.group(2)         if tracepointname:            tracepointname = tracepointname.lstrip()         r = KernRe(r'TP_PROTO\((.*?)\)')        if r.search(proto):            tracepointargs = r.group(1)         if not tracepointname or not tracepointargs:            self.emit_msg(ln,                          f"Unrecognized tracepoint format:\n{proto}\n")        else:            proto = f"static inline void trace_{tracepointname}({tracepointargs})"            self.entry.identifier = f"trace_{self.entry.identifier}"         return proto     def process_proto_function(self, ln, line, source):        """Ancillary routine to process a function prototype."""         # strip C99-style comments to end of line        line = KernRe(r"//.*$", re.S).sub('', line)        #        # Soak up the line's worth of prototype text, stopping at { or ; if present.        #        if KernRe(r'\s*#\s*define').match(line):            self.entry.prototype = line        elif not line.startswith('#'):   # skip other preprocessor stuff            r = KernRe(r'([^\{]*)')            if r.match(line):                self.entry.prototype += r.group(1) + " "        #        # If we now have the whole prototype, clean it up and declare victory.        #        if '{' in line or ';' in line or KernRe(r'\s*#\s*define').match(line):            # strip comments and surrounding spaces            self.entry.prototype = KernRe(r'/\*.*\*/').sub('', self.entry.prototype).strip()            #            # Handle self.entry.prototypes for function pointers like:            #       int (*pcs_config)(struct foo)            # by turning it into            #	    int pcs_config(struct foo)            #            r = KernRe(r'^(\S+\s+)\(\s*\*(\S+)\)')            self.entry.prototype = r.sub(r'\1\2', self.entry.prototype)            #            # Handle special declaration syntaxes            #            if 'SYSCALL_DEFINE' in self.entry.prototype:                self.entry.prototype = self.syscall_munge(ln,                                                          self.entry.prototype)            else:                r = KernRe(r'TRACE_EVENT|DEFINE_EVENT|DEFINE_SINGLE_EVENT')                if r.search(self.entry.prototype):                    self.entry.prototype = self.tracepoint_munge(ln,                                                                 self.entry.prototype)            #            # ... and we're done            #            self.dump_function(ln, self.entry.prototype, source)            self.reset_state(ln)     def process_proto_type(self, ln, line, source):        """        Ancillary routine to process a type.        """         # Strip C99-style comments and surrounding whitespace        line = KernRe(r"//.*$", re.S).sub('', line).strip()        if not line:            return # nothing to see here         # To distinguish preprocessor directive from regular declaration later.        if line.startswith('#'):            line += ";"        #        # Split the declaration on any of { } or ;, and accumulate pieces        # until we hit a semicolon while not inside {brackets}        #        r = KernRe(r'(.*?)([{};])')        for chunk in r.split(line):            if chunk:  # Ignore empty matches                self.entry.prototype += chunk                #                # This cries out for a match statement ... someday after we can                # drop Python 3.9 ...                #                if chunk == '{':                    self.entry.brcount += 1                elif chunk == '}':                    self.entry.brcount -= 1                elif chunk == ';' and self.entry.brcount <= 0:                    self.dump_declaration(ln, self.entry.prototype, source)                    self.reset_state(ln)                    return        #        # We hit the end of the line while still in the declaration; put        # in a space to represent the newline.        #        self.entry.prototype += ' '     def process_proto(self, ln, line, source):        """STATE_PROTO: reading a function/whatever prototype."""         if doc_inline_oneline.search(line):            self.entry.begin_section(ln, doc_inline_oneline.group(1))            self.entry.add_text(doc_inline_oneline.group(2))            self.dump_section()         elif doc_inline_start.search(line):            self.state = state.INLINE_NAME         elif self.entry.decl_type == 'function':            self.process_proto_function(ln, line, source)         else:            self.process_proto_type(ln, line, source)     def process_docblock(self, ln, line, source):        """STATE_DOCBLOCK: within a ``DOC:`` block."""         if doc_end.search(line):            self.dump_section()            self.output_declaration("doc", self.entry.identifier,                                    source=source)            self.reset_state(ln)         elif doc_content.search(line):            self.entry.add_text(doc_content.group(1))     def parse_export(self):        """        Parses ``EXPORT_SYMBOL*`` macros from a single Kernel source file.        """         export_table = set()         try:            with open(self.fname, "r", encoding="utf8",                      errors="backslashreplace") as fp:                 for line in fp:                    self.process_export(export_table, line)         except IOError:            return None         return export_table     #: The state/action table telling us which function to invoke in each state.    state_actions = {        state.NORMAL:			process_normal,        state.NAME:			process_name,        state.BODY:			process_body,        state.DECLARATION:		process_decl,        state.SPECIAL_SECTION:		process_special,        state.INLINE_NAME:		process_inline_name,        state.INLINE_TEXT:		process_inline_text,        state.PROTO:			process_proto,        state.DOCBLOCK:			process_docblock,        }     def parse_kdoc(self):        """        Open and process each line of a C source file.        The parsing is controlled via a state machine, and the line is passed        to a different process function depending on the state. The process        function may update the state as needed.         Besides parsing kernel-doc tags, it also parses export symbols.        """         prev = ""        prev_ln = None        export_table = set()        self.state = state.NORMAL        source = ""         try:            with open(self.fname, "r", encoding="utf8",                      errors="backslashreplace") as fp:                for ln, line in enumerate(fp):                     line = line.expandtabs().strip("\n")                     # Group continuation lines on prototypes                    if self.state == state.PROTO:                        if line.endswith("\\"):                            prev += line.rstrip("\\")                            if not prev_ln:                                prev_ln = ln                            continue                         if prev:                            ln = prev_ln                            line = prev + line                            prev = ""                            prev_ln = None                     self.config.log.debug("%d %s: %s",                                          ln, state.name[self.state],                                          line)                     if self.store_src:                        if source and self.state == state.NORMAL:                            source = ""                        elif self.state != state.NORMAL:                            source += line + "\n"                     # This is an optimization over the original script.                    # There, when export_file was used for the same file,                    # it was read twice. Here, we use the already-existing                    # loop to parse exported symbols as well.                    #                    if (self.state != state.NORMAL) or \                       not self.process_export(export_table, line):                        prev_state = self.state                        # Hand this line to the appropriate state handler                        self.state_actions[self.state](self, ln, line, source)                        if prev_state == state.NORMAL and self.state != state.NORMAL:                            source += line + "\n"             self.emit_unused_warnings()         except OSError:            self.config.log.error(f"Error: Cannot open file {self.fname}")         return export_table, self.entries

Lines 1501–1731 of 1731. Previous lines