Files
llvm-project/lldb/source/Interpreter/embedded_interpreter.py
Greg Clayton 44d937820b Merging the iohandler branch back into main.
The many many benefits include:
1 - Input/Output/Error streams are now handled as real streams not a push style input
2 - auto completion in python embedded interpreter
3 - multi-line input for "script" and "expression" commands now allow you to edit previous/next lines using up and down arrow keys and this makes multi-line input actually a viable thing to use
4 - it is now possible to use curses to drive LLDB (please try the "gui" command)

We will need to deal with and fix any buildbot failures and tests and arise now that input/output and error are correctly hooked up in all cases.

llvm-svn: 200263
2014-01-27 23:43:24 +00:00

109 lines
3.7 KiB
Python

import __builtin__
import code
import lldb
import sys
import traceback
try:
import readline
import rlcompleter
except ImportError:
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)