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