xref: /openbsd-src/gnu/llvm/lldb/source/Interpreter/embedded_interpreter.py (revision f6aab3d83b51b91c24247ad2c2573574de475a82)
1*f6aab3d8Srobertimport sys
2061da546Spatrickif sys.version_info[0] < 3:
3061da546Spatrick    import __builtin__ as builtins
4061da546Spatrickelse:
5061da546Spatrick    import builtins
6061da546Spatrickimport code
7061da546Spatrickimport lldb
8061da546Spatrickimport traceback
9061da546Spatrick
10061da546Spatricktry:
11061da546Spatrick    import readline
12061da546Spatrick    import rlcompleter
13061da546Spatrickexcept ImportError:
14061da546Spatrick    have_readline = False
15061da546Spatrickexcept AttributeError:
16061da546Spatrick    # This exception gets hit by the rlcompleter when Linux is using
17061da546Spatrick    # the readline suppression import.
18061da546Spatrick    have_readline = False
19061da546Spatrickelse:
20061da546Spatrick    have_readline = True
21061da546Spatrick    if 'libedit' in readline.__doc__:
22061da546Spatrick        readline.parse_and_bind('bind ^I rl_complete')
23061da546Spatrick    else:
24061da546Spatrick        readline.parse_and_bind('tab: complete')
25061da546Spatrick
26061da546Spatrick# When running one line, we might place the string to run in this string
27061da546Spatrick# in case it would be hard to correctly escape a string's contents
28061da546Spatrick
29061da546Spatrickg_run_one_line_str = None
30061da546Spatrick
31061da546Spatrick
32061da546Spatrickdef get_terminal_size(fd):
33061da546Spatrick    try:
34061da546Spatrick        import fcntl
35061da546Spatrick        import termios
36061da546Spatrick        import struct
37061da546Spatrick        hw = struct.unpack('hh', fcntl.ioctl(fd, termios.TIOCGWINSZ, '1234'))
38061da546Spatrick    except:
39061da546Spatrick        hw = (0, 0)
40061da546Spatrick    return hw
41061da546Spatrick
42061da546Spatrick
43*f6aab3d8Srobertclass LLDBExit(SystemExit):
44*f6aab3d8Srobert    pass
45*f6aab3d8Srobert
46*f6aab3d8Srobert
47*f6aab3d8Srobertdef strip_and_check_exit(line):
48*f6aab3d8Srobert    line = line.rstrip()
49*f6aab3d8Srobert    if line in ('exit', 'quit'):
50*f6aab3d8Srobert        raise LLDBExit
51*f6aab3d8Srobert    return line
52*f6aab3d8Srobert
53*f6aab3d8Srobert
54*f6aab3d8Srobertdef readfunc(prompt):
55*f6aab3d8Srobert    line = input(prompt)
56*f6aab3d8Srobert    return strip_and_check_exit(line)
57*f6aab3d8Srobert
58*f6aab3d8Srobert
59061da546Spatrickdef readfunc_stdio(prompt):
60061da546Spatrick    sys.stdout.write(prompt)
61061da546Spatrick    sys.stdout.flush()
62dda28197Spatrick    line = sys.stdin.readline()
63dda28197Spatrick    # Readline always includes a trailing newline character unless the file
64dda28197Spatrick    # ends with an incomplete line. An empty line indicates EOF.
65dda28197Spatrick    if not line:
66dda28197Spatrick        raise EOFError
67*f6aab3d8Srobert    return strip_and_check_exit(line)
68061da546Spatrick
69061da546Spatrick
70061da546Spatrickdef run_python_interpreter(local_dict):
71061da546Spatrick    # Pass in the dictionary, for continuity from one session to the next.
72061da546Spatrick    try:
73061da546Spatrick        fd = sys.stdin.fileno()
74061da546Spatrick        interacted = False
75061da546Spatrick        if get_terminal_size(fd)[1] == 0:
76061da546Spatrick            try:
77061da546Spatrick                import termios
78061da546Spatrick                old = termios.tcgetattr(fd)
79061da546Spatrick                if old[3] & termios.ECHO:
80061da546Spatrick                    # Need to turn off echoing and restore
81061da546Spatrick                    new = termios.tcgetattr(fd)
82061da546Spatrick                    new[3] = new[3] & ~termios.ECHO
83061da546Spatrick                    try:
84061da546Spatrick                        termios.tcsetattr(fd, termios.TCSADRAIN, new)
85061da546Spatrick                        interacted = True
86061da546Spatrick                        code.interact(
87061da546Spatrick                            banner="Python Interactive Interpreter. To exit, type 'quit()', 'exit()'.",
88061da546Spatrick                            readfunc=readfunc_stdio,
89061da546Spatrick                            local=local_dict)
90061da546Spatrick                    finally:
91061da546Spatrick                        termios.tcsetattr(fd, termios.TCSADRAIN, old)
92061da546Spatrick            except:
93061da546Spatrick                pass
94061da546Spatrick            # Don't need to turn off echoing
95061da546Spatrick            if not interacted:
96061da546Spatrick                code.interact(
97061da546Spatrick                    banner="Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D.",
98061da546Spatrick                    readfunc=readfunc_stdio,
99061da546Spatrick                    local=local_dict)
100061da546Spatrick        else:
101061da546Spatrick            # We have a real interactive terminal
102061da546Spatrick            code.interact(
103061da546Spatrick                banner="Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D.",
104*f6aab3d8Srobert                readfunc=readfunc,
105061da546Spatrick                local=local_dict)
106*f6aab3d8Srobert    except LLDBExit:
107*f6aab3d8Srobert        pass
108061da546Spatrick    except SystemExit as e:
109*f6aab3d8Srobert        if e.code:
110*f6aab3d8Srobert            print('Script exited with code %s' % e.code)
111061da546Spatrick
112061da546Spatrick
113061da546Spatrickdef run_one_line(local_dict, input_string):
114061da546Spatrick    global g_run_one_line_str
115061da546Spatrick    try:
116*f6aab3d8Srobert        input_string = strip_and_check_exit(input_string)
117061da546Spatrick        repl = code.InteractiveConsole(local_dict)
118061da546Spatrick        if input_string:
119*f6aab3d8Srobert            # A newline is appended to support one-line statements containing
120*f6aab3d8Srobert            # control flow. For example "if True: print(1)" silently does
121*f6aab3d8Srobert            # nothing, but works with a newline: "if True: print(1)\n".
122*f6aab3d8Srobert            input_string += "\n"
123061da546Spatrick            repl.runsource(input_string)
124061da546Spatrick        elif g_run_one_line_str:
125061da546Spatrick            repl.runsource(g_run_one_line_str)
126*f6aab3d8Srobert    except LLDBExit:
127*f6aab3d8Srobert        pass
128061da546Spatrick    except SystemExit as e:
129*f6aab3d8Srobert        if e.code:
130*f6aab3d8Srobert            print('Script exited with code %s' % e.code)
131