xref: /freebsd-src/contrib/llvm-project/lldb/source/Interpreter/embedded_interpreter.py (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
181ad6265SDimitry Andricimport sys
2*5f757f3fSDimitry Andric
30b57cec5SDimitry Andricif sys.version_info[0] < 3:
40b57cec5SDimitry Andric    import __builtin__ as builtins
50b57cec5SDimitry Andricelse:
60b57cec5SDimitry Andric    import builtins
70b57cec5SDimitry Andricimport code
80b57cec5SDimitry Andricimport lldb
90b57cec5SDimitry Andricimport traceback
100b57cec5SDimitry Andric
110b57cec5SDimitry Andrictry:
120b57cec5SDimitry Andric    import readline
130b57cec5SDimitry Andric    import rlcompleter
140b57cec5SDimitry Andricexcept ImportError:
150b57cec5SDimitry Andric    have_readline = False
160b57cec5SDimitry Andricexcept AttributeError:
170b57cec5SDimitry Andric    # This exception gets hit by the rlcompleter when Linux is using
180b57cec5SDimitry Andric    # the readline suppression import.
190b57cec5SDimitry Andric    have_readline = False
200b57cec5SDimitry Andricelse:
210b57cec5SDimitry Andric    have_readline = True
22*5f757f3fSDimitry Andric    if "libedit" in readline.__doc__:
23*5f757f3fSDimitry Andric        readline.parse_and_bind("bind ^I rl_complete")
240b57cec5SDimitry Andric    else:
25*5f757f3fSDimitry Andric        readline.parse_and_bind("tab: complete")
260b57cec5SDimitry Andric
270b57cec5SDimitry Andric# When running one line, we might place the string to run in this string
280b57cec5SDimitry Andric# in case it would be hard to correctly escape a string's contents
290b57cec5SDimitry Andric
300b57cec5SDimitry Andricg_run_one_line_str = None
310b57cec5SDimitry Andric
320b57cec5SDimitry Andric
330b57cec5SDimitry Andricdef get_terminal_size(fd):
340b57cec5SDimitry Andric    try:
350b57cec5SDimitry Andric        import fcntl
360b57cec5SDimitry Andric        import termios
370b57cec5SDimitry Andric        import struct
38*5f757f3fSDimitry Andric
39*5f757f3fSDimitry Andric        hw = struct.unpack("hh", fcntl.ioctl(fd, termios.TIOCGWINSZ, "1234"))
400b57cec5SDimitry Andric    except:
410b57cec5SDimitry Andric        hw = (0, 0)
420b57cec5SDimitry Andric    return hw
430b57cec5SDimitry Andric
440b57cec5SDimitry Andric
4581ad6265SDimitry Andricclass LLDBExit(SystemExit):
4681ad6265SDimitry Andric    pass
4781ad6265SDimitry Andric
4881ad6265SDimitry Andric
4981ad6265SDimitry Andricdef strip_and_check_exit(line):
5081ad6265SDimitry Andric    line = line.rstrip()
51*5f757f3fSDimitry Andric    if line in ("exit", "quit"):
5281ad6265SDimitry Andric        raise LLDBExit
5381ad6265SDimitry Andric    return line
5481ad6265SDimitry Andric
5581ad6265SDimitry Andric
5681ad6265SDimitry Andricdef readfunc(prompt):
5781ad6265SDimitry Andric    line = input(prompt)
5881ad6265SDimitry Andric    return strip_and_check_exit(line)
5981ad6265SDimitry Andric
6081ad6265SDimitry Andric
610b57cec5SDimitry Andricdef readfunc_stdio(prompt):
620b57cec5SDimitry Andric    sys.stdout.write(prompt)
630b57cec5SDimitry Andric    sys.stdout.flush()
645ffd83dbSDimitry Andric    line = sys.stdin.readline()
655ffd83dbSDimitry Andric    # Readline always includes a trailing newline character unless the file
665ffd83dbSDimitry Andric    # ends with an incomplete line. An empty line indicates EOF.
675ffd83dbSDimitry Andric    if not line:
685ffd83dbSDimitry Andric        raise EOFError
6981ad6265SDimitry Andric    return strip_and_check_exit(line)
700b57cec5SDimitry Andric
710b57cec5SDimitry Andric
720b57cec5SDimitry Andricdef run_python_interpreter(local_dict):
730b57cec5SDimitry Andric    # Pass in the dictionary, for continuity from one session to the next.
740b57cec5SDimitry Andric    try:
750b57cec5SDimitry Andric        fd = sys.stdin.fileno()
760b57cec5SDimitry Andric        interacted = False
770b57cec5SDimitry Andric        if get_terminal_size(fd)[1] == 0:
780b57cec5SDimitry Andric            try:
790b57cec5SDimitry Andric                import termios
80*5f757f3fSDimitry Andric
810b57cec5SDimitry Andric                old = termios.tcgetattr(fd)
820b57cec5SDimitry Andric                if old[3] & termios.ECHO:
830b57cec5SDimitry Andric                    # Need to turn off echoing and restore
840b57cec5SDimitry Andric                    new = termios.tcgetattr(fd)
850b57cec5SDimitry Andric                    new[3] = new[3] & ~termios.ECHO
860b57cec5SDimitry Andric                    try:
870b57cec5SDimitry Andric                        termios.tcsetattr(fd, termios.TCSADRAIN, new)
880b57cec5SDimitry Andric                        interacted = True
890b57cec5SDimitry Andric                        code.interact(
900b57cec5SDimitry Andric                            banner="Python Interactive Interpreter. To exit, type 'quit()', 'exit()'.",
910b57cec5SDimitry Andric                            readfunc=readfunc_stdio,
92*5f757f3fSDimitry Andric                            local=local_dict,
93*5f757f3fSDimitry Andric                        )
940b57cec5SDimitry Andric                    finally:
950b57cec5SDimitry Andric                        termios.tcsetattr(fd, termios.TCSADRAIN, old)
960b57cec5SDimitry Andric            except:
970b57cec5SDimitry Andric                pass
980b57cec5SDimitry Andric            # Don't need to turn off echoing
990b57cec5SDimitry Andric            if not interacted:
1000b57cec5SDimitry Andric                code.interact(
1010b57cec5SDimitry Andric                    banner="Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D.",
1020b57cec5SDimitry Andric                    readfunc=readfunc_stdio,
103*5f757f3fSDimitry Andric                    local=local_dict,
104*5f757f3fSDimitry Andric                )
1050b57cec5SDimitry Andric        else:
1060b57cec5SDimitry Andric            # We have a real interactive terminal
1070b57cec5SDimitry Andric            code.interact(
1080b57cec5SDimitry Andric                banner="Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D.",
10981ad6265SDimitry Andric                readfunc=readfunc,
110*5f757f3fSDimitry Andric                local=local_dict,
111*5f757f3fSDimitry Andric            )
11281ad6265SDimitry Andric    except LLDBExit:
11381ad6265SDimitry Andric        pass
1140b57cec5SDimitry Andric    except SystemExit as e:
11581ad6265SDimitry Andric        if e.code:
116*5f757f3fSDimitry Andric            print("Script exited with code %s" % e.code)
1170b57cec5SDimitry Andric
1180b57cec5SDimitry Andric
1190b57cec5SDimitry Andricdef run_one_line(local_dict, input_string):
1200b57cec5SDimitry Andric    global g_run_one_line_str
1210b57cec5SDimitry Andric    try:
12281ad6265SDimitry Andric        input_string = strip_and_check_exit(input_string)
1230b57cec5SDimitry Andric        repl = code.InteractiveConsole(local_dict)
1240b57cec5SDimitry Andric        if input_string:
12581ad6265SDimitry Andric            # A newline is appended to support one-line statements containing
12681ad6265SDimitry Andric            # control flow. For example "if True: print(1)" silently does
12781ad6265SDimitry Andric            # nothing, but works with a newline: "if True: print(1)\n".
12881ad6265SDimitry Andric            input_string += "\n"
1290b57cec5SDimitry Andric            repl.runsource(input_string)
1300b57cec5SDimitry Andric        elif g_run_one_line_str:
1310b57cec5SDimitry Andric            repl.runsource(g_run_one_line_str)
13281ad6265SDimitry Andric    except LLDBExit:
13381ad6265SDimitry Andric        pass
1340b57cec5SDimitry Andric    except SystemExit as e:
13581ad6265SDimitry Andric        if e.code:
136*5f757f3fSDimitry Andric            print("Script exited with code %s" % e.code)
137