aboutsummaryrefslogtreecommitdiff
path: root/source/Interpreter/embedded_interpreter.py
blob: 8ba539a2b0c93c46c10288c1b78759e797efa576 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
import sys
if sys.version_info[0] < 3:
    import __builtin__ as builtins
else:
    import builtins
import code
import lldb
import traceback

try:
    import readline
    import rlcompleter
except ImportError:
    have_readline = False
except AttributeError:
    # This exception gets hit by the rlcompleter when Linux is using
    # the readline suppression import.
    have_readline = False
else:
    have_readline = True
    if 'libedit' in readline.__doc__:
        readline.parse_and_bind('bind ^I rl_complete')
    else:
        readline.parse_and_bind('tab: complete')

g_builtin_override_called = False

class LLDBQuitter(object):
    def __init__(self, name):
        self.name = name
    def __repr__(self):
        self()
    def __call__(self, code=None):
        global g_builtin_override_called
        g_builtin_override_called = True
        raise SystemExit(-1)

def setquit():
    '''Redefine builtin functions 'quit()' and 'exit()' to print a message and raise an EOFError exception.'''
    # This function will be called prior to each interactive
    # interpreter loop or each single line, so we set the global
    # g_builtin_override_called to False so we know if a SystemExit
    # is thrown, we can catch it and tell the difference between
    # a call to "quit()" or "exit()" and something like
    # "sys.exit(123)"
    global g_builtin_override_called
    g_builtin_override_called = False
    builtins.quit = LLDBQuitter('quit')
    builtins.exit = LLDBQuitter('exit')

# When running one line, we might place the string to run in this string
# in case it would be hard to correctly escape a string's contents

g_run_one_line_str = None


def get_terminal_size(fd):
    try:
        import fcntl, termios, struct
        hw = struct.unpack('hh', fcntl.ioctl(fd, termios.TIOCGWINSZ, '1234'))
    except:
        hw = (0,0)
    return hw

def readfunc_stdio(prompt):
    sys.stdout.write(prompt)
    return sys.stdin.readline().rstrip()

def run_python_interpreter (local_dict):
    # Pass in the dictionary, for continuity from one session to the next.
    setquit()
    try:
        fd = sys.stdin.fileno();
        interacted = False
        if get_terminal_size(fd)[1] == 0:
            try:
                import termios
                old = termios.tcgetattr(fd)
                if old[3] & termios.ECHO:
                    # Need to turn off echoing and restore
                    new = termios.tcgetattr(fd)
                    new[3] = new[3] & ~termios.ECHO
                    try:
                        termios.tcsetattr(fd, termios.TCSADRAIN, new)
                        interacted = True
                        code.interact(banner="Python Interactive Interpreter. To exit, type 'quit()', 'exit()'.", readfunc=readfunc_stdio, local=local_dict)
                    finally:
                        termios.tcsetattr(fd, termios.TCSADRAIN, old)
            except:
                pass
            # Don't need to turn off echoing
            if not interacted:
                code.interact(banner="Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D.", readfunc=readfunc_stdio, local=local_dict)
        else:
            # We have a real interactive terminal
            code.interact(banner="Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D.", local=local_dict)
    except SystemExit as e:
        global g_builtin_override_called
        if not g_builtin_override_called:
            print('Script exited with %s' %(e))

def run_one_line (local_dict, input_string):
    global g_run_one_line_str
    setquit()
    try:
        repl = code.InteractiveConsole(local_dict);
        if input_string:
            repl.runsource (input_string)
        elif g_run_one_line_str:
            repl.runsource (g_run_one_line_str)

    except SystemExit as e:
        global g_builtin_override_called
        if not g_builtin_override_called:
            print('Script exited with %s' %(e))