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.entriesLines 1501–1731 of 1731. Previous lines
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