diff options
Diffstat (limited to 'lldb/source/Interpreter/embedded_interpreter.py')
-rw-r--r-- | lldb/source/Interpreter/embedded_interpreter.py | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/lldb/source/Interpreter/embedded_interpreter.py b/lldb/source/Interpreter/embedded_interpreter.py new file mode 100644 index 000000000000..8a1195d83c6f --- /dev/null +++ b/lldb/source/Interpreter/embedded_interpreter.py @@ -0,0 +1,134 @@ +import sys +if sys.version_info[0] < 3: + import __builtin__ as builtins +else: + import builtins +import code +import lldb +import traceback + +try: + import readline + import rlcompleter +except ImportError: + have_readline = False +except AttributeError: + # This exception gets hit by the rlcompleter when Linux is using + # the readline suppression import. + have_readline = False +else: + have_readline = True + if 'libedit' in readline.__doc__: + readline.parse_and_bind('bind ^I rl_complete') + else: + readline.parse_and_bind('tab: complete') + +g_builtin_override_called = False + + +class LLDBQuitter(object): + + def __init__(self, name): + self.name = name + + def __repr__(self): + self() + + def __call__(self, code=None): + global g_builtin_override_called + g_builtin_override_called = True + raise SystemExit(-1) + + +def setquit(): + '''Redefine builtin functions 'quit()' and 'exit()' to print a message and raise an EOFError exception.''' + # This function will be called prior to each interactive + # interpreter loop or each single line, so we set the global + # g_builtin_override_called to False so we know if a SystemExit + # is thrown, we can catch it and tell the difference between + # a call to "quit()" or "exit()" and something like + # "sys.exit(123)" + global g_builtin_override_called + g_builtin_override_called = False + builtins.quit = LLDBQuitter('quit') + builtins.exit = LLDBQuitter('exit') + +# When running one line, we might place the string to run in this string +# in case it would be hard to correctly escape a string's contents + +g_run_one_line_str = None + + +def get_terminal_size(fd): + try: + import fcntl + import termios + import struct + hw = struct.unpack('hh', fcntl.ioctl(fd, termios.TIOCGWINSZ, '1234')) + except: + hw = (0, 0) + return hw + + +def readfunc_stdio(prompt): + sys.stdout.write(prompt) + sys.stdout.flush() + return sys.stdin.readline().rstrip() + + +def run_python_interpreter(local_dict): + # Pass in the dictionary, for continuity from one session to the next. + setquit() + try: + fd = sys.stdin.fileno() + interacted = False + if get_terminal_size(fd)[1] == 0: + try: + import termios + old = termios.tcgetattr(fd) + if old[3] & termios.ECHO: + # Need to turn off echoing and restore + new = termios.tcgetattr(fd) + new[3] = new[3] & ~termios.ECHO + try: + termios.tcsetattr(fd, termios.TCSADRAIN, new) + interacted = True + code.interact( + banner="Python Interactive Interpreter. To exit, type 'quit()', 'exit()'.", + readfunc=readfunc_stdio, + local=local_dict) + finally: + termios.tcsetattr(fd, termios.TCSADRAIN, old) + except: + pass + # Don't need to turn off echoing + if not interacted: + code.interact( + banner="Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D.", + readfunc=readfunc_stdio, + local=local_dict) + else: + # We have a real interactive terminal + code.interact( + banner="Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D.", + local=local_dict) + except SystemExit as e: + global g_builtin_override_called + if not g_builtin_override_called: + print('Script exited with %s' % (e)) + + +def run_one_line(local_dict, input_string): + global g_run_one_line_str + setquit() + try: + repl = code.InteractiveConsole(local_dict) + if input_string: + repl.runsource(input_string) + elif g_run_one_line_str: + repl.runsource(g_run_one_line_str) + + except SystemExit as e: + global g_builtin_override_called + if not g_builtin_override_called: + print('Script exited with %s' % (e)) |