-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathusercode.py
More file actions
executable file
·212 lines (145 loc) · 6.37 KB
/
Copy pathusercode.py
File metadata and controls
executable file
·212 lines (145 loc) · 6.37 KB
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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
#!/usr/bin/env python2
"""
UserCode simulator
by Kyle Temkin <ktemkin@binghamton.edu>
(c) Binghamton University, 2012
Licensed under the GPL, the GNU Public License, V3.0
"""
import sys
import argparse
import readline
from Computers.Exceptions import UserCodeException
from Computers.Freescale.HCS08 import MC9S08QG8;
active = ''
prompt = '{active}>'
""" Interactive mode command prompt. """
def main():
"""
"""
global active, prompt
#create a new argument parser, which parses the command line arguments
parser = argparse.ArgumentParser(description='Runs abstract pieces of a user code on one of various turing-equivalent machiness.')
#if an input file is specified, use it; otherwise, default to the standard input
#parser.add_argument('codefile', metavar='codefile', nargs='?', type=argparse.FileType('r'), default=sys.stdin, help='The file containing the user code to be executed.')
parser.add_argument('--system', '-s', type=str, default='hcs08', help='The system on which the user code will be executed.')
parser.add_argument('--prompt', '-p', type=str, help='Specifies the prompt string. Global variables (such as "active") can be referenced using python formatting notation.')
parser.add_argument('--noprompt', action='store_true', help='If set, the prompt will be an empty string.')
#parse this argument's processes
args = parser.parse_args()
#if the user has specified a prompt, use it
if args.prompt:
prompt = args.prompt
if args.noprompt:
prompt = ''
#if a generic HCS08 is specified, choose the MC9S08QG8
if args.system in ('hcs08', 'MC9S08QG8'):
system = MC9S08QG8();
#set the active system title
active = system.shorthand()
#run the mainloop indefinitely
mainloop(system)
def mainloop(system):
#initialize the blacklist, whitelist, and requiredlist
blacklist = whitelist = requiredlist = None
#until we're manually interrupted, run interactive mode indefinitely
while True:
try:
#get a command from the user
command, argument = get_command()
#if the q command was offered, quit the program
if command in ('q', 'quit', 'x', 'exit'):
quit()
#upon the 'code' command, read in the user code
elif command in ('c', 'code'):
read_program(system, argument, blacklist, whitelist, requiredlist)
print "Loaded."
#step, when requested
elif command in ('s', 'step'):
#if the system isn't halted, step
if not system.halted():
system.step()
print "Stepped."
#if the system is halted (which may have occurred as a result of the step)
if system.halted():
print 'Halted.'
elif command in ('cc', 'cont', 'continue'):
#TODO: handle breakpoints
breakpoint = lambda x: False
system.run_until(breakpoint)
print "Halted."
#print a serialized version of the system's state
elif command in ('g', 'getstate'):
print system.serialize_state()
elif command in ('l', 'loadstate'):
system.unserialize_state(argument)
print "Loaded."
#reset the system, when requested
elif command in ('r', 'reset'):
system.reset()
#set the system blacklist (interpreted by the system)
elif command in ('bl', 'blacklist'):
blacklist = argument
print "Updated."
#set the system whitelist (interpeted by the system)
elif command in ('wl', 'whitelist'):
whitelist = argument
print "Updated."
#set the system require-list (interpreted by the system)
elif command in ('rl', 'require'):
requiredlist = argument
print "Updated."
#pass system specific commands to the target system
elif command in ('sys', 'system'):
system.handle_system_command(argument)
#pass through runtime limits
elif command in ('rtl', 'runlimit'):
try:
limit = int(argument)
system.limit_runtime(limit)
print 'Limited.'
except TypeError as e:
print 'Not understood; limit unchanged.'
#simple handshaking command
elif command in ('ping', 'pn'):
print "Pong.";
#flush the stdout
sys.stdout.flush()
#catch any errors in the user code, and display them nicely, here
except UserCodeException as e:
print 'ERROR:', e.message
sys.stdout.flush()
def read_program(system, terminator, blacklist=None, whitelist=None, requiredlist=None):
"""
Handles reading a program from the standard input, then passes the code to the system, to process.
Program is considered over when the 'terminator' sequence appears on a line by itself. The terminator should be chosen so it does not appear in the program.
"""
#create an empty buffer, which will store lines of code
program = []
#and keep track of the most recently entered line
last = None
#read until break
while True:
#read a single line from the standard input
last = raw_input()
#if we've recieved the terminating line, stop reading
if last == terminator:
break;
#otherwise add the line to the program, and continue
program.append(last)
#pass the program code into the system
system.load_program(program, blacklist, whitelist, requiredlist)
def get_command():
"""
Recieves a command from the user or IPC socket.
"""
#evaluate the prompt string to get the current prompt
current_prompt = prompt.format(**globals())
#prompt the user for input using the current prompt
command = raw_input(current_prompt)
#partition the prompt into a command and (optional) arguments
command = command.partition(' ')
#and return the command and arguments
return command[0], command[2]
#if this is being called as a library, call main
if __name__ == '__main__':
main()