Commit ad032f3f authored by Mark Florisson's avatar Mark Florisson

Add 'cy finish', 'py-finish', 'py-run' and 'py-cont' commands.

parent 8977d45b
......@@ -158,7 +158,6 @@ class TestStep(DebugStepperTestCase):
def test_cython_step(self):
gdb.execute('cy break codefile.spam')
libcython.parameters.step_into_c_code.value = False
gdb.execute('run', to_string=True)
self.lineno_equals('def spam(a=0):')
......@@ -171,14 +170,12 @@ class TestStep(DebugStepperTestCase):
self.step([('b', 1), ('c', 0)], source_line='c = 2')
self.step([('c', 2)], source_line='int(10)')
self.step([], source_line='puts("spam")')
self.step([], source_line='os.path.join("foo", "bar")')
gdb.execute('cont', to_string=True)
self.assertEqual(len(gdb.inferiors()), 1)
self.assertEqual(gdb.inferiors()[0].pid, 0)
def test_c_step(self):
libcython.parameters.step_into_c_code.value = True
self.break_and_run('some_c_function()')
gdb.execute('cy step', to_string=True)
self.assertEqual(gdb.selected_frame().name(), 'some_c_function')
......@@ -198,7 +195,6 @@ class TestStep(DebugStepperTestCase):
class TestNext(DebugStepperTestCase):
def test_cython_next(self):
libcython.parameters.step_into_c_code.value = True
self.break_and_run('c = 2')
lines = (
......
......@@ -277,8 +277,7 @@ class CythonBase(object):
older_frame = frame.older()
if self.is_cython_function(frame) or self.is_python_function(frame):
return True
elif (parameters.step_into_c_code and
older_frame and self.is_cython_function(older_frame)):
elif older_frame and self.is_cython_function(older_frame):
# direct C function call from a Cython function
cython_func = self.get_cython_function(older_frame)
return name in cython_func.step_into_functions
......@@ -506,12 +505,6 @@ class TerminalBackground(CythonParameter):
Tell cygdb about the user's terminal background (light or dark).
"""
class StepIntoCCode(CythonParameter):
"""
Tells cygdb whether to step into C functions called directly from Cython
code.
"""
class CythonParameters(object):
"""
Simple container class that might get more functionality in the distant
......@@ -534,11 +527,6 @@ class CythonParameters(object):
gdb.COMMAND_FILES,
gdb.PARAM_STRING,
"dark")
self.step_into_c_code = StepIntoCCode(
'cy_step_into_c_code',
gdb.COMMAND_RUNNING,
gdb.PARAM_BOOLEAN,
True)
parameters = CythonParameters()
......@@ -602,6 +590,7 @@ class CyCy(CythonCommand):
next = CyNext.register(),
run = CyRun.register(),
cont = CyCont.register(),
finish = CyFinish.register(),
up = CyUp.register(),
down = CyDown.register(),
bt = CyBacktrace.register(),
......@@ -873,7 +862,7 @@ class CythonCodeStepper(CythonCommand, libpython.GenericCodeStepper):
self.finish_executing(gdb.execute(command, to_string=True))
else:
super(CythonCodeStepper, self).invoke(args, from_tty)
self.step()
class CyStep(CythonCodeStepper):
......@@ -897,10 +886,8 @@ class CyRun(CythonCodeStepper):
"""
name = 'cy run'
_command = 'run'
def invoke(self, *args):
self.finish_executing(gdb.execute(self._command, to_string=True))
invoke = CythonCodeStepper.run
class CyCont(CyRun):
......@@ -910,7 +897,16 @@ class CyCont(CyRun):
"""
name = 'cy cont'
_command = 'cont'
invoke = CythonCodeStepper.cont
class CyFinish(CyRun):
"""
Execute until the function returns.
"""
name = 'cy finish'
invoke = CythonCodeStepper.finish
class CyUp(CythonCommand):
......
......@@ -1686,6 +1686,72 @@ class GenericCodeStepper(gdb.Command):
context.
"""
def stopped(self):
return gdb.inferiors()[0].pid == 0
def _stackdepth(self, frame):
depth = 0
while frame:
frame = frame.older()
depth += 1
return depth
def finish_executing(self, result):
"""
After doing some kind of code running in the inferior, print the line
of source code or the result of the last executed gdb command (passed
in as the `result` argument).
"""
if self.stopped():
print result.strip()
else:
frame = gdb.selected_frame()
output = None
if self.is_relevant_function(frame):
output = self.get_source_line(frame)
if output is None:
pframe = getattr(self, 'print_stackframe', None)
if pframe:
pframe(frame, index=0)
else:
print result.strip()
else:
print output
def _finish(self):
"""
Execute until the function returns (or until something else makes it
stop)
"""
if gdb.selected_frame().older() is not None:
return gdb.execute('finish', to_string=True)
else:
# outermost frame, continue
return gdb.execute('cont', to_string=True)
def finish(self, *args):
"""
Execute until the function returns to a relevant caller.
"""
while True:
result = self._finish()
try:
frame = gdb.selected_frame()
except RuntimeError:
break
hitbp = re.search(r'Breakpoint (\d+)', result)
is_relavant = self.is_relevant_function(frame)
if hitbp or is_relavant or self.stopped():
break
self.finish_executing(result)
def _step(self):
"""
Do a single step or step-over. Returns the result of the last gdb
......@@ -1706,10 +1772,7 @@ class GenericCodeStepper(gdb.Command):
if self.is_relevant_function(newframe):
result = gdb.execute('next', to_string=True)
else:
if self._stackdepth(newframe) == 1:
result = gdb.execute('cont', to_string=True)
else:
result = gdb.execute('finish', to_string=True)
result = self._finish()
if self.stopped():
break
......@@ -1749,39 +1812,15 @@ class GenericCodeStepper(gdb.Command):
self.disable_breakpoints()
return result
def stopped(self):
return gdb.inferiors()[0].pid == 0
def _stackdepth(self, frame):
depth = 0
while frame:
frame = frame.older()
depth += 1
return depth
def invoke(self, args, from_tty):
self.finish_executing(self._step())
def step(self):
return self.finish_executing(self._step())
def run(self, *args):
self.finish_executing(gdb.execute('run', to_string=True))
def finish_executing(self, result):
if self.stopped():
print result.strip()
else:
frame = gdb.selected_frame()
output = None
if self.is_relevant_function(frame):
output = self.get_source_line(frame)
if output is None:
pframe = getattr(self, 'print_stackframe', None)
if pframe:
pframe(frame, index=0)
else:
print result.strip()
else:
print output
def cont(self, *args):
self.finish_executing(gdb.execute('cont', to_string=True))
class PythonCodeStepper(GenericCodeStepper):
......@@ -1813,11 +1852,33 @@ class PythonCodeStepper(GenericCodeStepper):
class PyStep(PythonCodeStepper):
"Step through Python code."
invoke = PythonCodeStepper.step
class PyNext(PythonCodeStepper):
"Step-over Python code."
invoke = PythonCodeStepper.step
class PyFinish(PythonCodeStepper):
"Execute until function returns to a caller."
invoke = PythonCodeStepper.finish
class PyRun(PythonCodeStepper):
"Run the program."
invoke = PythonCodeStepper.run
class PyCont(PythonCodeStepper):
invoke = PythonCodeStepper.cont
py_step = PyStep('py-step', stepinto=True)
py_next = PyNext('py-next', stepinto=False)
py_finish = PyFinish('py-finish')
py_run = PyRun('py-run')
py_cont = PyCont('py-cont')
py_step.init_breakpoints()
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment