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