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
26# When running one line, we might place the string to run in this string
27# in case it would be hard to correctly escape a string's contents
28
29g_run_one_line_str = None
30
31
32def get_terminal_size(fd):
33    try:
34        import fcntl
35        import termios
36        import struct
37        hw = struct.unpack('hh', fcntl.ioctl(fd, termios.TIOCGWINSZ, '1234'))
38    except:
39        hw = (0, 0)
40    return hw
41
42
43class LLDBExit(SystemExit):
44    pass
45
46
47def strip_and_check_exit(line):
48    line = line.rstrip()
49    if line in ('exit', 'quit'):
50        raise LLDBExit
51    return line
52
53
54def readfunc(prompt):
55    line = input(prompt)
56    return strip_and_check_exit(line)
57
58
59def readfunc_stdio(prompt):
60    sys.stdout.write(prompt)
61    sys.stdout.flush()
62    line = sys.stdin.readline()
63    # Readline always includes a trailing newline character unless the file
64    # ends with an incomplete line. An empty line indicates EOF.
65    if not line:
66        raise EOFError
67    return strip_and_check_exit(line)
68
69
70def run_python_interpreter(local_dict):
71    # Pass in the dictionary, for continuity from one session to the next.
72    try:
73        fd = sys.stdin.fileno()
74        interacted = False
75        if get_terminal_size(fd)[1] == 0:
76            try:
77                import termios
78                old = termios.tcgetattr(fd)
79                if old[3] & termios.ECHO:
80                    # Need to turn off echoing and restore
81                    new = termios.tcgetattr(fd)
82                    new[3] = new[3] & ~termios.ECHO
83                    try:
84                        termios.tcsetattr(fd, termios.TCSADRAIN, new)
85                        interacted = True
86                        code.interact(
87                            banner="Python Interactive Interpreter. To exit, type 'quit()', 'exit()'.",
88                            readfunc=readfunc_stdio,
89                            local=local_dict)
90                    finally:
91                        termios.tcsetattr(fd, termios.TCSADRAIN, old)
92            except:
93                pass
94            # Don't need to turn off echoing
95            if not interacted:
96                code.interact(
97                    banner="Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D.",
98                    readfunc=readfunc_stdio,
99                    local=local_dict)
100        else:
101            # We have a real interactive terminal
102            code.interact(
103                banner="Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D.",
104                readfunc=readfunc,
105                local=local_dict)
106    except LLDBExit:
107        pass
108    except SystemExit as e:
109        if e.code:
110            print('Script exited with code %s' % e.code)
111
112
113def run_one_line(local_dict, input_string):
114    global g_run_one_line_str
115    try:
116        input_string = strip_and_check_exit(input_string)
117        repl = code.InteractiveConsole(local_dict)
118        if input_string:
119            # A newline is appended to support one-line statements containing
120            # control flow. For example "if True: print(1)" silently does
121            # nothing, but works with a newline: "if True: print(1)\n".
122            input_string += "\n"
123            repl.runsource(input_string)
124        elif g_run_one_line_str:
125            repl.runsource(g_run_one_line_str)
126    except LLDBExit:
127        pass
128    except SystemExit as e:
129        if e.code:
130            print('Script exited with code %s' % e.code)
131