summaryrefslogtreecommitdiffstats
path: root/lldb/source/Interpreter/embedded_interpreter.py
diff options
context:
space:
mode:
authorGreg Clayton <gclayton@apple.com>2014-01-27 23:43:24 +0000
committerGreg Clayton <gclayton@apple.com>2014-01-27 23:43:24 +0000
commit44d937820b451296f80449ac3de296345e80f183 (patch)
tree00d14538eded9f7e8bd075128d6ad5fd5ac1caed /lldb/source/Interpreter/embedded_interpreter.py
parentf1cb16e481a60dbac58affcf8c8e423dac3937cb (diff)
downloadbcm5719-llvm-44d937820b451296f80449ac3de296345e80f183.tar.gz
bcm5719-llvm-44d937820b451296f80449ac3de296345e80f183.zip
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
Diffstat (limited to 'lldb/source/Interpreter/embedded_interpreter.py')
-rw-r--r--lldb/source/Interpreter/embedded_interpreter.py183
1 files changed, 94 insertions, 89 deletions
diff --git a/lldb/source/Interpreter/embedded_interpreter.py b/lldb/source/Interpreter/embedded_interpreter.py
index 06b70ebeb8b..bc0dd6d5ae4 100644
--- a/lldb/source/Interpreter/embedded_interpreter.py
+++ b/lldb/source/Interpreter/embedded_interpreter.py
@@ -1,103 +1,108 @@
-import readline
+import __builtin__
import code
+import lldb
import sys
import traceback
-class SimpleREPL(code.InteractiveConsole):
- def __init__(self, prompt, dict):
- code.InteractiveConsole.__init__(self,dict)
- self.prompt = prompt
- self.loop_exit = False
- self.dict = dict
+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')
- def interact(self):
- try:
- sys.ps1
- except AttributeError:
- sys.ps1 = ">>> "
- try:
- sys.ps2
- except AttributeError:
- sys.ps2 = "... "
+g_builtin_override_called = False
- while not self.loop_exit:
- try:
- self.read_py_command()
- except (SystemExit, EOFError):
- # EOF while in Python just breaks out to top level.
- self.write('\n')
- self.loop_exit = True
- break
- except KeyboardInterrupt:
- self.write("\nKeyboardInterrupt\n")
- self.resetbuffer()
- more = 0
- except:
- traceback.print_exc()
+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 process_input (self, in_str):
- # Canonicalize the format of the input string
- temp_str = in_str
- temp_str.strip(' \t')
- words = temp_str.split()
- temp_str = ('').join(words)
+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')
- # Check the input string to see if it was the quit
- # command. If so, intercept it, so that it doesn't
- # close stdin on us!
- if (temp_str.lower() == "quit()" or temp_str.lower() == "exit()"):
- self.loop_exit = True
- in_str = "raise SystemExit "
- return in_str
+# 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
- def my_raw_input (self, prompt):
- stream = sys.stdout
- stream.write (prompt)
- stream.flush ()
- try:
- line = sys.stdin.readline()
- except KeyboardInterrupt:
- line = " \n"
- except (SystemExit, EOFError):
- line = "quit()\n"
- if not line:
- raise EOFError
- if line[-1] == '\n':
- line = line[:-1]
- return line
+g_run_one_line_str = None
- def read_py_command(self):
- # Read off a complete Python command.
- more = 0
- while 1:
- if more:
- prompt = sys.ps2
- else:
- prompt = sys.ps1
- line = self.my_raw_input(prompt)
- # Can be None if sys.stdin was redefined
- encoding = getattr(sys.stdin, "encoding", None)
- if encoding and not isinstance(line, unicode):
- line = line.decode(encoding)
- line = self.process_input (line)
- more = self.push(line)
- if not more:
- break
- def one_line (self, input):
- line = self.process_input (input)
- more = self.push(line)
- if more:
- self.write ("Input not a complete line.\n")
- self.resetbuffer()
- more = 0
+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 run_python_interpreter (dict):
- # Pass in the dictionary, for continuity from one session to the next.
- repl = SimpleREPL('>>> ', dict)
- repl.interact()
+def readfunc_stdio(prompt):
+ sys.stdout.write(prompt)
+ return sys.stdin.readline()
-def run_one_line (dict, input_string):
- repl = SimpleREPL ('', dict)
- repl.one_line (input_string)
+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)
OpenPOWER on IntegriCloud