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): ...@@ -158,7 +158,6 @@ class TestStep(DebugStepperTestCase):
def test_cython_step(self): def test_cython_step(self):
gdb.execute('cy break codefile.spam') gdb.execute('cy break codefile.spam')
libcython.parameters.step_into_c_code.value = False
gdb.execute('run', to_string=True) gdb.execute('run', to_string=True)
self.lineno_equals('def spam(a=0):') self.lineno_equals('def spam(a=0):')
...@@ -171,14 +170,12 @@ class TestStep(DebugStepperTestCase): ...@@ -171,14 +170,12 @@ class TestStep(DebugStepperTestCase):
self.step([('b', 1), ('c', 0)], source_line='c = 2') self.step([('b', 1), ('c', 0)], source_line='c = 2')
self.step([('c', 2)], source_line='int(10)') self.step([('c', 2)], source_line='int(10)')
self.step([], source_line='puts("spam")') self.step([], source_line='puts("spam")')
self.step([], source_line='os.path.join("foo", "bar")')
gdb.execute('cont', to_string=True) gdb.execute('cont', to_string=True)
self.assertEqual(len(gdb.inferiors()), 1) self.assertEqual(len(gdb.inferiors()), 1)
self.assertEqual(gdb.inferiors()[0].pid, 0) self.assertEqual(gdb.inferiors()[0].pid, 0)
def test_c_step(self): def test_c_step(self):
libcython.parameters.step_into_c_code.value = True
self.break_and_run('some_c_function()') self.break_and_run('some_c_function()')
gdb.execute('cy step', to_string=True) gdb.execute('cy step', to_string=True)
self.assertEqual(gdb.selected_frame().name(), 'some_c_function') self.assertEqual(gdb.selected_frame().name(), 'some_c_function')
...@@ -198,7 +195,6 @@ class TestStep(DebugStepperTestCase): ...@@ -198,7 +195,6 @@ class TestStep(DebugStepperTestCase):
class TestNext(DebugStepperTestCase): class TestNext(DebugStepperTestCase):
def test_cython_next(self): def test_cython_next(self):
libcython.parameters.step_into_c_code.value = True
self.break_and_run('c = 2') self.break_and_run('c = 2')
lines = ( lines = (
......
...@@ -277,8 +277,7 @@ class CythonBase(object): ...@@ -277,8 +277,7 @@ class CythonBase(object):
older_frame = frame.older() older_frame = frame.older()
if self.is_cython_function(frame) or self.is_python_function(frame): if self.is_cython_function(frame) or self.is_python_function(frame):
return True return True
elif (parameters.step_into_c_code and elif older_frame and self.is_cython_function(older_frame):
older_frame and self.is_cython_function(older_frame)):
# direct C function call from a Cython function # direct C function call from a Cython function
cython_func = self.get_cython_function(older_frame) cython_func = self.get_cython_function(older_frame)
return name in cython_func.step_into_functions return name in cython_func.step_into_functions
...@@ -506,12 +505,6 @@ class TerminalBackground(CythonParameter): ...@@ -506,12 +505,6 @@ class TerminalBackground(CythonParameter):
Tell cygdb about the user's terminal background (light or dark). 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): class CythonParameters(object):
""" """
Simple container class that might get more functionality in the distant Simple container class that might get more functionality in the distant
...@@ -534,11 +527,6 @@ class CythonParameters(object): ...@@ -534,11 +527,6 @@ class CythonParameters(object):
gdb.COMMAND_FILES, gdb.COMMAND_FILES,
gdb.PARAM_STRING, gdb.PARAM_STRING,
"dark") "dark")
self.step_into_c_code = StepIntoCCode(
'cy_step_into_c_code',
gdb.COMMAND_RUNNING,
gdb.PARAM_BOOLEAN,
True)
parameters = CythonParameters() parameters = CythonParameters()
...@@ -602,6 +590,7 @@ class CyCy(CythonCommand): ...@@ -602,6 +590,7 @@ class CyCy(CythonCommand):
next = CyNext.register(), next = CyNext.register(),
run = CyRun.register(), run = CyRun.register(),
cont = CyCont.register(), cont = CyCont.register(),
finish = CyFinish.register(),
up = CyUp.register(), up = CyUp.register(),
down = CyDown.register(), down = CyDown.register(),
bt = CyBacktrace.register(), bt = CyBacktrace.register(),
...@@ -873,7 +862,7 @@ class CythonCodeStepper(CythonCommand, libpython.GenericCodeStepper): ...@@ -873,7 +862,7 @@ class CythonCodeStepper(CythonCommand, libpython.GenericCodeStepper):
self.finish_executing(gdb.execute(command, to_string=True)) self.finish_executing(gdb.execute(command, to_string=True))
else: else:
super(CythonCodeStepper, self).invoke(args, from_tty) self.step()
class CyStep(CythonCodeStepper): class CyStep(CythonCodeStepper):
...@@ -897,10 +886,8 @@ class CyRun(CythonCodeStepper): ...@@ -897,10 +886,8 @@ class CyRun(CythonCodeStepper):
""" """
name = 'cy run' name = 'cy run'
_command = 'run'
def invoke(self, *args): invoke = CythonCodeStepper.run
self.finish_executing(gdb.execute(self._command, to_string=True))
class CyCont(CyRun): class CyCont(CyRun):
...@@ -910,7 +897,16 @@ class CyCont(CyRun): ...@@ -910,7 +897,16 @@ class CyCont(CyRun):
""" """
name = 'cy cont' 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): class CyUp(CythonCommand):
......
...@@ -1686,6 +1686,72 @@ class GenericCodeStepper(gdb.Command): ...@@ -1686,6 +1686,72 @@ class GenericCodeStepper(gdb.Command):
context. 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): def _step(self):
""" """
Do a single step or step-over. Returns the result of the last gdb Do a single step or step-over. Returns the result of the last gdb
...@@ -1706,10 +1772,7 @@ class GenericCodeStepper(gdb.Command): ...@@ -1706,10 +1772,7 @@ class GenericCodeStepper(gdb.Command):
if self.is_relevant_function(newframe): if self.is_relevant_function(newframe):
result = gdb.execute('next', to_string=True) result = gdb.execute('next', to_string=True)
else: else:
if self._stackdepth(newframe) == 1: result = self._finish()
result = gdb.execute('cont', to_string=True)
else:
result = gdb.execute('finish', to_string=True)
if self.stopped(): if self.stopped():
break break
...@@ -1750,38 +1813,14 @@ class GenericCodeStepper(gdb.Command): ...@@ -1750,38 +1813,14 @@ class GenericCodeStepper(gdb.Command):
return result return result
def stopped(self): def step(self):
return gdb.inferiors()[0].pid == 0 return self.finish_executing(self._step())
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 finish_executing(self, result):
if self.stopped():
print result.strip()
else:
frame = gdb.selected_frame()
output = None
if self.is_relevant_function(frame): def run(self, *args):
output = self.get_source_line(frame) self.finish_executing(gdb.execute('run', to_string=True))
if output is None: def cont(self, *args):
pframe = getattr(self, 'print_stackframe', None) self.finish_executing(gdb.execute('cont', to_string=True))
if pframe:
pframe(frame, index=0)
else:
print result.strip()
else:
print output
class PythonCodeStepper(GenericCodeStepper): class PythonCodeStepper(GenericCodeStepper):
...@@ -1814,10 +1853,32 @@ class PythonCodeStepper(GenericCodeStepper): ...@@ -1814,10 +1853,32 @@ class PythonCodeStepper(GenericCodeStepper):
class PyStep(PythonCodeStepper): class PyStep(PythonCodeStepper):
"Step through Python code." "Step through Python code."
invoke = PythonCodeStepper.step
class PyNext(PythonCodeStepper): class PyNext(PythonCodeStepper):
"Step-over Python code." "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_step = PyStep('py-step', stepinto=True)
py_next = PyNext('py-next', stepinto=False) 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() 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