xref: /llvm-project/lldb/source/Interpreter/embedded_interpreter.py (revision 44d937820b451296f80449ac3de296345e80f183)
1import __builtin__
2import code
3import lldb
4import sys
5import traceback
6
7try:
8    import readline
9    import rlcompleter
10except ImportError:
11    have_readline = False
12else:
13    have_readline = True
14    if 'libedit' in readline.__doc__:
15        readline.parse_and_bind('bind ^I rl_complete')
16    else:
17        readline.parse_and_bind('tab: complete')
18
19g_builtin_override_called = False
20
21class LLDBQuitter(object):
22    def __init__(self, name):
23        self.name = name
24    def __repr__(self):
25        self()
26    def __call__(self, code=None):
27        global g_builtin_override_called
28        g_builtin_override_called = True
29        raise SystemExit(-1)
30
31def setquit():
32    '''Redefine builtin functions 'quit()' and 'exit()' to print a message and raise an EOFError exception.'''
33    # This function will be called prior to each interactive
34    # interpreter loop or each single line, so we set the global
35    # g_builtin_override_called to False so we know if a SystemExit
36    # is thrown, we can catch it and tell the difference between
37    # a call to "quit()" or "exit()" and something like
38    # "sys.exit(123)"
39    global g_builtin_override_called
40    g_builtin_override_called = False
41    __builtin__.quit = LLDBQuitter('quit')
42    __builtin__.exit = LLDBQuitter('exit')
43
44# When running one line, we might place the string to run in this string
45# in case it would be hard to correctly escape a string's contents
46
47g_run_one_line_str = None
48
49
50def get_terminal_size(fd):
51    try:
52        import fcntl, termios, struct
53        hw = struct.unpack('hh', fcntl.ioctl(fd, termios.TIOCGWINSZ, '1234'))
54    except:
55        hw = (0,0)
56    return hw
57
58def readfunc_stdio(prompt):
59    sys.stdout.write(prompt)
60    return sys.stdin.readline()
61
62def run_python_interpreter (local_dict):
63    # Pass in the dictionary, for continuity from one session to the next.
64    setquit()
65    try:
66        fd = sys.stdin.fileno();
67        interacted = False
68        if get_terminal_size(fd)[1] == 0:
69            try:
70                import termios
71                old = termios.tcgetattr(fd)
72                if old[3] & termios.ECHO:
73                    # Need to turn off echoing and restore
74                    new = termios.tcgetattr(fd)
75                    new[3] = new[3] & ~termios.ECHO
76                    try:
77                        termios.tcsetattr(fd, termios.TCSADRAIN, new)
78                        interacted = True
79                        code.interact(banner="Python Interactive Interpreter. To exit, type 'quit()', 'exit()'.", readfunc=readfunc_stdio, local=local_dict)
80                    finally:
81                        termios.tcsetattr(fd, termios.TCSADRAIN, old)
82            except:
83                pass
84            # Don't need to turn off echoing
85            if not interacted:
86                code.interact(banner="Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D.", readfunc=readfunc_stdio, local=local_dict)
87        else:
88            # We have a real interactive terminal
89            code.interact(banner="Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D.", local=local_dict)
90    except SystemExit as e:
91        global g_builtin_override_called
92        if not g_builtin_override_called:
93            print 'Script exited with %s' %(e)
94
95def run_one_line (local_dict, input_string):
96    global g_run_one_line_str
97    setquit()
98    try:
99        repl = code.InteractiveConsole(local_dict);
100        if input_string:
101            repl.runsource (input_string)
102        elif g_run_one_line_str:
103            repl.runsource (g_run_one_line_str)
104
105    except SystemExit as e:
106        global g_builtin_override_called
107        if not g_builtin_override_called:
108            print 'Script exited with %s' %(e)
109