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