llvm-project/lldb/source/Interpreter/embedded_interpreter.py

113 lines
3.8 KiB
Python

import __builtin__
import code
import lldb
import sys
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
__builtin__.quit = LLDBQuitter('quit')
__builtin__.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, termios, 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)
return sys.stdin.readline()
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)