This is the last functional change to the generated python module being done by modify-python-lldb.py. The remaining code just deals with reformatting of comments. llvm-svn: 357755
169 lines
5.6 KiB
Python
169 lines
5.6 KiB
Python
#
|
|
# modify-python-lldb.py
|
|
#
|
|
# This script modifies the lldb module (which was automatically generated via
|
|
# running swig) to support iteration and/or equality operations for certain lldb
|
|
# objects, implements truth value testing for certain lldb objects, and adds a
|
|
# global variable 'debugger_unique_id' which is initialized to 0.
|
|
#
|
|
# As a cleanup step, it also removes the 'residues' from the autodoc features of
|
|
# swig. For an example, take a look at SBTarget.h header file, where we take
|
|
# advantage of the already existing doxygen C++-docblock and make it the Python
|
|
# docstring for the same method. The 'residues' in this context include the
|
|
# '#endif', the '#ifdef SWIG', the c comment marker, the trailing blank (SPC's)
|
|
# line, and the doxygen comment start marker.
|
|
#
|
|
# In addition to the 'residues' removal during the cleanup step, it also
|
|
# transforms the 'char' data type (which was actually 'char *' but the 'autodoc'
|
|
# feature of swig removes ' *' from it) into 'str' (as a Python str type).
|
|
#
|
|
# It also calls SBDebugger.Initialize() to initialize the lldb debugger
|
|
# subsystem.
|
|
#
|
|
|
|
# System modules
|
|
import sys
|
|
import re
|
|
if sys.version_info.major >= 3:
|
|
import io as StringIO
|
|
else:
|
|
import StringIO
|
|
|
|
# import use_lldb_suite so we can find third-party and helper modules
|
|
import use_lldb_suite
|
|
|
|
# Third party modules
|
|
import six
|
|
|
|
# LLDB modules
|
|
|
|
if len(sys.argv) != 2:
|
|
output_name = "./lldb.py"
|
|
else:
|
|
output_name = sys.argv[1] + "/lldb.py"
|
|
|
|
# print "output_name is '" + output_name + "'"
|
|
|
|
#
|
|
# Residues to be removed.
|
|
#
|
|
c_endif_swig = "#endif"
|
|
c_ifdef_swig = "#ifdef SWIG"
|
|
c_comment_marker = "//------------"
|
|
# The pattern for recognizing the doxygen comment block line.
|
|
doxygen_comment_start = re.compile("^\s*(/// ?)")
|
|
# The demarcation point for turning on/off residue removal state.
|
|
# When bracketed by the lines, the CLEANUP_DOCSTRING state (see below) is ON.
|
|
toggle_docstring_cleanup_line = ' """'
|
|
|
|
|
|
def char_to_str_xform(line):
|
|
"""This transforms the 'char', i.e, 'char *' to 'str', Python string."""
|
|
line = line.replace(' char', ' str')
|
|
line = line.replace('char ', 'str ')
|
|
# Special case handling of 'char **argv' and 'char **envp'.
|
|
line = line.replace('str argv', 'list argv')
|
|
line = line.replace('str envp', 'list envp')
|
|
return line
|
|
|
|
#
|
|
# The one-liner docstring also needs char_to_str transformation, btw.
|
|
#
|
|
TWO_SPACES = ' ' * 2
|
|
EIGHT_SPACES = ' ' * 8
|
|
one_liner_docstring_pattern = re.compile(
|
|
'^(%s|%s)""".*"""$' %
|
|
(TWO_SPACES, EIGHT_SPACES))
|
|
|
|
class NewContent(StringIO.StringIO):
|
|
"""Simple facade to keep track of the previous line to be committed."""
|
|
|
|
def __init__(self):
|
|
StringIO.StringIO.__init__(self)
|
|
self.prev_line = None
|
|
|
|
def add_line(self, a_line):
|
|
"""Add a line to the content, if there is a previous line, commit it."""
|
|
if self.prev_line is not None:
|
|
self.write(self.prev_line + "\n")
|
|
self.prev_line = a_line
|
|
|
|
def del_line(self):
|
|
"""Forget about the previous line, do not commit it."""
|
|
self.prev_line = None
|
|
|
|
def del_blank_line(self):
|
|
"""Forget about the previous line if it is a blank line."""
|
|
if self.prev_line is not None and not self.prev_line.strip():
|
|
self.prev_line = None
|
|
|
|
def finish(self):
|
|
"""Call this when you're finished with populating content."""
|
|
if self.prev_line is not None:
|
|
self.write(self.prev_line + "\n")
|
|
self.prev_line = None
|
|
|
|
# The new content will have the iteration protocol defined for our lldb
|
|
# objects.
|
|
new_content = NewContent()
|
|
|
|
with open(output_name, 'r') as f_in:
|
|
content = f_in.read()
|
|
|
|
# These define the states of our finite state machine.
|
|
NORMAL = 1
|
|
CLEANUP_DOCSTRING = 8
|
|
|
|
# Our FSM begins its life in the NORMAL state. The state CLEANUP_DOCSTRING can
|
|
# be entered from the NORMAL. While in this state, the FSM is fixing/cleaning
|
|
# the Python docstrings generated by the swig docstring features.
|
|
state = NORMAL
|
|
|
|
for line in content.splitlines():
|
|
# If ' """' is the sole line, prepare to transition to the
|
|
# CLEANUP_DOCSTRING state or out of it.
|
|
|
|
if line == toggle_docstring_cleanup_line:
|
|
if state & CLEANUP_DOCSTRING:
|
|
# Special handling of the trailing blank line right before the '"""'
|
|
# end docstring marker.
|
|
new_content.del_blank_line()
|
|
state ^= CLEANUP_DOCSTRING
|
|
else:
|
|
state |= CLEANUP_DOCSTRING
|
|
|
|
if (state & CLEANUP_DOCSTRING):
|
|
# Cleanse the lldb.py of the autodoc'ed residues.
|
|
if c_ifdef_swig in line or c_endif_swig in line:
|
|
continue
|
|
# As well as the comment marker line.
|
|
if c_comment_marker in line:
|
|
continue
|
|
|
|
# Also remove the '\a ' and '\b 'substrings.
|
|
line = line.replace('\a ', '')
|
|
line = line.replace('\b ', '')
|
|
# And the leading '///' substring.
|
|
doxygen_comment_match = doxygen_comment_start.match(line)
|
|
if doxygen_comment_match:
|
|
line = line.replace(doxygen_comment_match.group(1), '', 1)
|
|
|
|
line = char_to_str_xform(line)
|
|
|
|
# Note that the transition out of CLEANUP_DOCSTRING is handled at the
|
|
# beginning of this function already.
|
|
|
|
# This deals with one-liner docstring, for example, SBThread.GetName:
|
|
# """GetName(self) -> char""".
|
|
if one_liner_docstring_pattern.match(line):
|
|
line = char_to_str_xform(line)
|
|
|
|
# Pass the original line of content to new_content.
|
|
new_content.add_line(line)
|
|
|
|
# We are finished with recording new content.
|
|
new_content.finish()
|
|
|
|
with open(output_name, 'w') as f_out:
|
|
f_out.write(new_content.getvalue())
|