This source file includes following definitions.
- adrhash
- getbps
- addbps
- delbps
- listbps
- freebpslist
- freebps
- monargstok
- monlinetok
- stracmp
- warn_ignore_arg
- mon_break
- mon_dump
- monitorcmd
- free_moncmdline
- monquit
- monitor
1 #include <readline/readline.h>
2 #include <readline/history.h>
3 #include "monitor.h"
4
5
6
7
8 static BPSLIST *bps[BPSTABSIZE];
9
10
11
12
13 static char *monitor_prompt = "(comet2 monitor) ";
14
15 unsigned adrhash(WORD adr)
16 {
17 HKEY *key[1];
18 unsigned h;
19 key[0] = malloc_chk(sizeof(HKEY), "adrhash.key");
20 key[0]->type = INT;
21 key[0]->val.i = adr;
22 h = hash(1, key, BPSTABSIZE);
23 FREE(key[0]);
24 return h;
25 }
26
27 bool getbps(WORD adr)
28 {
29 BPSLIST *p = NULL;
30
31 for(p = bps[adrhash(adr)]; p != NULL; p = p->next) {
32 if(p->adr == adr) {
33 return true;
34 }
35 }
36 return false;
37 }
38
39 bool addbps(WORD adr)
40 {
41 BPSLIST *p = NULL;
42 unsigned h = 0;
43
44
45 if(getbps(adr) == true) {
46 fprintf(stderr, "%04X: Breakpoint is already defined.\n", adr);
47 return false;
48 }
49
50 p = malloc_chk(sizeof(BPSLIST), "bps.next");
51
52 p->adr = adr;
53
54 p->next = bps[h = adrhash(adr)];
55 bps[h] = p;
56 return true;
57 }
58
59 bool delbps(WORD adr)
60 {
61 BPSLIST *p = NULL;
62 BPSLIST *q = NULL;
63 unsigned h = 0;
64 bool res = false;
65
66 p = bps[h = adrhash(adr)];
67 if(p != NULL) {
68 if(p->adr == adr) {
69 if(p->next == NULL) {
70 FREE(bps[h]);
71 } else {
72 bps[h] = p->next;
73 FREE(p);
74 }
75 res = true;
76 } else {
77 for(; p->next != NULL; p = p->next) {
78 q = p->next;
79 if(q->adr == adr) {
80 p->next = q->next;
81 FREE(q);
82 res = true;
83 break;
84 }
85 }
86 }
87 }
88 return res;
89 }
90
91 void listbps()
92 {
93 int cnt = 0;
94 BPSLIST *p = NULL;
95
96 fprintf(stdout, "List of breakpoints\n");
97 for(int i = 0; i < BPSTABSIZE; i++) {
98 for(p = bps[i]; p != NULL; p = p->next) {
99 fprintf(stdout, "#%04X\n", p->adr);
100 cnt++;
101 }
102 }
103 if(cnt == 0) {
104 fprintf(stdout, "(No breakpoints.)\n");
105 }
106 }
107
108 void freebpslist(BPSLIST *head)
109 {
110 BPSLIST *p = NULL;
111 BPSLIST *q = NULL;
112 for(p = head; p != NULL; p = q) {
113 q = p->next;
114 FREE(p);
115 }
116 }
117
118 void freebps()
119 {
120 for(int i = 0; i < BPSTABSIZE; i++) {
121 freebpslist(bps[i]);
122 bps[i] = NULL;
123 }
124 }
125
126 MONARGS *monargstok(const char *str)
127 {
128 MONARGS *args = malloc_chk(sizeof(MONARGS), "args");
129 char *tok = NULL;
130 char *p = NULL;
131 char sepc = ' ';
132
133 args->argc = 0;
134 if(!str || !str[0]) {
135 return args;
136 }
137 tok = p = strdup_chk(str, "argstok.p");
138 do {
139 int i = strcspn(p, " ");
140 sepc = p[i];
141 args->argv[(args->argc)++] = strndup_chk(p, i, "args->argv[]");
142 p += i + 1;
143 } while(sepc == ' ');
144 FREE(tok);
145 return args;
146 }
147
148 MONCMDLINE *monlinetok(const char *line)
149 {
150 char *tokens = NULL;
151 char *p = NULL;
152 int i = 0;
153 MONCMDLINE *moncmdl = NULL;
154
155 if(!line[0] || line[0] == '\n') {
156 return NULL;
157 }
158 p = tokens = strdup_chk(line, "tokens");
159
160 strip_casl2_comment(p);
161
162 strip_end(p);
163
164 moncmdl = malloc_chk(sizeof(MONCMDLINE), "moncmdl");
165
166 i = strcspn(p, " \t\n");
167 moncmdl->cmd = strndup_chk(p, i, "moncmdl->cmd");
168
169 p += i;
170 while(*p == ' ' || *p == '\t') {
171 p++;
172 }
173
174 if(strcspn(p, "\n") > 0) {
175 moncmdl->args = monargstok(p);
176 } else {
177 moncmdl->args = malloc_chk(sizeof(MONARGS), "moncmdl.args");
178 moncmdl->args->argc = 0;
179 }
180 FREE(tokens);
181 return moncmdl;
182 }
183
184 bool stracmp(char *str1, int str2c, char *str2v[])
185 {
186 int i;
187 if(str1 == NULL) {
188 return false;
189 }
190 for(i = 0; i < str2c; i++) {
191 if(strcmp(str1, str2v[i]) == 0) {
192 return true;
193 }
194 }
195 return false;
196 }
197
198 void warn_ignore_arg(int argc, char *argv[])
199 {
200 int i;
201 fprintf(stderr, "Info: arguments '");
202 for(i = 0; i < argc; i++) {
203 if(i > 0) {
204 fprintf(stderr, " ");
205 }
206 fprintf(stderr, "%s", argv[i]);
207 }
208 fprintf(stderr, "' are ignored.\n");
209 }
210
211 void mon_break(int argc, char *argv[])
212 {
213 WORD w;
214 int i = 0;
215 if(stracmp(argv[0], 2, (char* []){"l", "list"})) {
216 i++;
217 listbps();
218 } else if(stracmp(argv[0], 2, (char* []){"r", "reset"})) {
219 i++;
220 freebps();
221 fprintf(stdout, "All breakpoints are deleted.\n");
222 } else {
223 if(argc > 1) {
224 if((w = nh2word(argv[1])) == 0x0) {
225 fprintf(stderr, "%s: address error\n", argv[1]);
226 }
227 }
228 if(stracmp(argv[0], 2, (char* []){"a", "add"})) {
229 i += 2;
230 if(addbps(w) == true) {
231 fprintf(stdout, "#%04X: breakpoint added\n", w);
232 } else {
233 fprintf(stdout, "No breakpoint added\n");
234 }
235 } else if(stracmp(argv[0], 2, (char* []){"d", "del"})) {
236 i += 2;
237 if(delbps(w) == true) {
238 fprintf(stdout, "#%04X: breakpoint deleted\n", w);
239 } else {
240 fprintf(stdout, "No breakpoint deleted\n");
241 }
242 } else if(stracmp(argv[0], 3, (char* []){"?", "h", "help"})) {
243 i++;
244 fprintf(stdout, "breakpoint manipulate:\n");
245 fprintf(stdout, " b[reak] a[dd] <address>\n");
246 fprintf(stdout, " b[reak] d[el] <address>\n");
247 fprintf(stdout, " b[reak] l[ist]\n");
248 fprintf(stdout, " b[reak] r[eset]\n");
249 } else {
250 fprintf(stderr, "%s: Not breakpoint manipulate command. see `b ?'.\n", argv[0]);
251 }
252 if(argc > i) {
253 warn_ignore_arg(argc - i, argv + i);
254 }
255 }
256 }
257
258 void mon_dump(int argc, char *argv[])
259 {
260 int i = 0;
261 WORD dump_start = 0, dump_end = 0x40;
262 if(stracmp(argv[0], 2, (char* []){"a", "auto"})) {
263 execmode.dump = true;
264 } else if(stracmp(argv[0], 2, (char* []){"no", "noauto"})) {
265 execmode.dump = false;
266 } else {
267 if(argc > i) {
268 dump_start = nh2word(argv[i++]);
269 if(argc > i) {
270 if(argv[i][0] =='+') {
271 dump_end = dump_start + nh2word(argv[i] + 1);
272 } else {
273 dump_end = nh2word(argv[i]) + 1;
274 }
275 } else {
276 dump_end += dump_start;
277 }
278 }
279 dumpmemory(dump_start, dump_end);
280 execmode.dump_start = dump_start;
281 execmode.dump_end = dump_end;
282 }
283 if(argc > ++i) {
284 warn_ignore_arg(argc - i, argv + i);
285 }
286 }
287
288 MONCMDTYPE monitorcmd(char *cmd, MONARGS *args)
289 {
290 MONCMDTYPE cmdtype = MONREPEAT;
291 if(stracmp(cmd, 2, (char* []){"a", "assemble"})) {
292 if(args->argc == 0) {
293 fprintf(stderr, "Error: Input file name.\n");
294 } else if(args->argc == 1) {
295 assemble(1, (char* []){args->argv[0]}, 0);
296 } else {
297 assemble(1, (char* []){args->argv[0]}, nh2word(args->argv[1]));
298 }
299 } else if(stracmp(cmd, 2, (char* []){"b", "break"})) {
300 mon_break(args->argc, args->argv);
301 } else if(stracmp(cmd, 2, (char* []){"c", "continue"})) {
302 execmode.step = false;
303 cmdtype = MONNEXT;
304 } else if(stracmp(cmd, 2, (char* []){"d", "dump"})) {
305 mon_dump(args->argc, args->argv);
306 } else if(stracmp(cmd, 2, (char* []){"l", "load"})) {
307 execptr->end = loadassemble(args->argv[0], nh2word(args->argv[1]));
308 } else if(stracmp(cmd, 2, (char* []){"n", "next"})) {
309 execmode.step = true;
310 cmdtype = MONNEXT;
311 } else if(stracmp(cmd, 2, (char* []){"q", "quit"})) {
312 fprintf(stdout, "Quit: COMET II monitor\n");
313 cmdtype = MONQUIT;
314 } else if(stracmp(cmd, 2, (char* []){"r", "reverse"})) {
315 if(args->argc == 2) {
316 disassemble_memory(nh2word(args->argv[0]), nh2word(args->argv[1]));
317 }
318 } else if(stracmp(cmd, 1, (char* []){"reset"})) {
319 fprintf(stdout, "Reset COMET II CPU.\n");
320 comet2_reset();
321 } else if(stracmp(cmd, 1, (char* []){"resetall"})) {
322 fprintf(stdout, "Reset COMET II CPU and memory.\n");
323 comet2_resetall();
324 } else if(stracmp(cmd, 2, (char* []){"t", "trace"})) {
325 if(args->argc > 0 && stracmp(args->argv[0], 2, (char* []){"a", "auto"})) {
326 execmode.logical = false;
327 execmode.trace = true;
328 } else if(args->argc > 0 && stracmp(args->argv[0], 2, (char* []){"no", "noauto"})) {
329 execmode.trace = false;
330 } else {
331 fprintf(stdout, "#%04X: Register::::\n", sys->cpu->pr);
332 dspregister();
333 }
334 } else if(stracmp(cmd, 2, (char* []){"T", "tracelogical"})) {
335 if(args->argc > 0 && stracmp(args->argv[0], 2, (char* []){"a", "auto"})) {
336 execmode.logical = true;
337 execmode.trace = true;
338 } else if(args->argc > 0 && stracmp(args->argv[0], 2, (char* []){"no", "noauto"})) {
339 execmode.trace = false;
340 } else {
341 fprintf(stdout, "#%04X: Register::::\n", sys->cpu->pr);
342 dspregister();
343 }
344 } else if(stracmp(cmd, 3, (char* []){"?", "h", "help"})) {
345 fprintf(stdout, "!<system command> -- Run a system command.\n");
346 fprintf(stdout, "b[reak] -- Manipulate Breakpoints. See details, `b ?'.\n");
347 fprintf(stdout, "c[ontinue] -- Continue running your program.\n");
348 fprintf(stdout, "d[ump] -- Display memory dump. `d[ump] a[uto]/n[oauto]' set auto/noauto display.\n");
349 fprintf(stdout, "l[oad] -- Load object from a file to the memory. `l[oad] <filepath> <address>' if address is omitted, load to address 0.\n");
350 fprintf(stdout, "n[ext] -- Go next instruction.\n");
351 fprintf(stdout, "q[uit] -- Quit running your program.\n");
352 fprintf(stdout, "reset -- Reset COMET II CPU.\n");
353 fprintf(stdout, "resetall -- Reset COMET II CPU and memory.\n");
354 fprintf(stdout, "r[everse] -- Disassemble memory. `r[everse] <start address> <end address>.\n");
355 fprintf(stdout, "s[ave] -- Save object from the memory to a file. `s[ave] <filepath> [<start address1> [<end address>]]' if <start address> and <end address> is omitted, save the whole memory. if <end address> is omitted, save the memory after <start address>.\n");
356 fprintf(stdout, "t[race] -- Display CPU register. `t[race] a[uto]/n[oauto]' set auto/noauto display. \n");
357 fprintf(stdout, "T[race] -- Display CPU register as logical value. `t[race] a[uto]/n[oauto]' set auto/noauto display. \n");
358 fprintf(stdout, "?/h[elp] -- Display this help.\n");
359 }
360 return cmdtype;
361 }
362
363 void free_moncmdline(MONCMDLINE *moncmdl)
364 {
365 int i;
366 assert(moncmdl != NULL);
367 if(moncmdl->args != NULL) {
368 for(i = 0; i < moncmdl->args->argc; i++) {
369 FREE(moncmdl->args->argv[i]);
370 }
371 FREE(moncmdl->args);
372 }
373 if(moncmdl->cmd != NULL) {
374 FREE(moncmdl->cmd);
375 }
376 if(moncmdl != NULL) {
377 FREE(moncmdl);
378 }
379 }
380
381 int monquit()
382 {
383 int stat = 0;
384 comet2_shutdown();
385 freebps();
386 free_cmdtable(HASH_CMDTYPE);
387 free_cmdtable(HASH_CODE);
388 if(cerr->num > 0) {
389 stat = 1;
390 }
391 freecerr();
392 return stat;
393 }
394
395 void monitor()
396 {
397 static char *buf = NULL;
398 static char *last_buf = NULL;
399 MONCMDLINE *moncmdl = NULL;
400 MONCMDTYPE cmdtype = MONREPEAT;
401
402 do {
403 buf = readline(monitor_prompt);
404
405 if(buf == NULL) {
406 FREE(buf);
407 FREE(last_buf);
408 exit(monquit());
409 }
410
411 if(buf[0] == '\0') {
412 if(last_buf == NULL) {
413
414 FREE(buf);
415 fprintf(stdout, ">\n");
416 } else {
417 buf = strdup_chk(last_buf, "monitor.buf_repeat");
418 cmdtype = MONREPEAT;
419 }
420 } else {
421 strip_end(buf);
422
423 add_history(buf);
424 last_buf = strdup_chk(buf, "monitor.last_buf");
425 }
426
427 fprintf(stdout, "> %s\n", buf);
428
429 if(buf[0] == '!') {
430 system(buf + 1);
431 } else if((moncmdl = monlinetok(buf)) != NULL) {
432 cmdtype = monitorcmd(moncmdl->cmd, moncmdl->args);
433 free_moncmdline(moncmdl);
434 }
435 if(cmdtype == MONQUIT) {
436 FREE(buf);
437 FREE(last_buf);
438 exit(monquit());
439 }
440 } while(cmdtype == MONREPEAT);
441 FREE(buf);
442 FREE(last_buf);
443 }