ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/mon/src/mon.cpp
Revision: 1.1
Committed: 1999-10-04T19:31:09Z (25 years, 1 month ago) by cebix
Branch: MAIN
Branch point for: cebix
Log Message:
Initial revision

File Contents

# Content
1 /*
2 * mon.cpp - Machine language monitor
3 *
4 * (C) 1997-1999 Christian Bauer
5 */
6
7 #include <sys/types.h>
8 #include <netinet/in.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <signal.h>
13 #include <ctype.h>
14 #include <unistd.h>
15 #include <errno.h>
16
17 extern "C" {
18 extern char *readline(char *prompt);
19 extern void add_history(char *str);
20 }
21
22 #include "mon.h"
23 #include "mon_cmd.h"
24
25
26 // Buffer we're operating on
27 bool mon_use_real_mem = false;
28 uint32 mon_mem_size;
29 static uint8 *mem;
30
31
32 // Streams for input, output and error messages
33 FILE *monin, *monout, *monerr;
34
35 // Input line
36 static char input[INPUT_LENGTH];
37 static char *in_ptr;
38 char *mon_args_ptr;
39
40 // Current address, value of '.' in expressions
41 uint32 mon_dot_address;
42
43 // Current value of ':' in expression
44 static uint32 colon_value;
45
46
47 // Scanner variables
48 enum Token mon_token; // Last token read
49 uint32 mon_number; // Contains the number if mon_token==T_NUMBER
50 char mon_string[INPUT_LENGTH]; // Contains the string if mon_token==T_STRING
51 char mon_name[INPUT_LENGTH]; // Contains the variable name if mon_token==T_NAME
52
53
54 // List of installed commands
55 struct CmdSpec {
56 const char *name; // Name of command
57 void (*func)(void); // Function that executes this command
58 };
59
60 static CmdSpec *cmds; // Array of CmdSpecs
61 static int num_cmds; // Number of installed commands
62 static char *cmd_help; // Help text for commands
63
64
65 // List of variables
66 struct Variable {
67 Variable *next; // Pointer to next variable (must be first element of struct)
68 char *name; // Variable name
69 uint32 value; // Variable value
70 };
71
72 static Variable *first_var; // Pointer to first variable
73
74
75 // Prototypes
76 static void init_abort(void);
77 static void exit_abort(void);
78
79 static void read_line(char *prompt); // Scanner
80 static char get_char(void);
81 static void put_back(char c);
82 static enum Token get_hex_number(uint32 &i);
83 static enum Token get_dec_number(uint32 &i);
84 static enum Token get_char_number(uint32 &i);
85 static enum Token get_string(char *str);
86 static enum Token get_hex_or_name(uint32 &i, char *name);
87
88 static bool eor_expr(uint32 *number); // Parser
89 static bool and_expr(uint32 *number);
90 static bool shift_expr(uint32 *number);
91 static bool add_expr(uint32 *number);
92 static bool mul_expr(uint32 *number);
93 static bool factor(uint32 *number);
94 static Variable *lookup_var(const char *s);
95 static Variable *insert_var(const char *s);
96 static void remove_var(const char *s);
97
98
99 /*
100 * Add command to mon
101 */
102
103 void mon_add_command(const char *name, void (*func)(void), const char *help_text)
104 {
105 num_cmds++;
106 if (cmds)
107 cmds = (CmdSpec *)realloc(cmds, num_cmds * sizeof(CmdSpec));
108 else
109 cmds = (CmdSpec *)malloc(sizeof(CmdSpec));
110 cmds[num_cmds - 1].name = name;
111 cmds[num_cmds - 1].func = func;
112 if (help_text) {
113 if (cmd_help) {
114 cmd_help = (char *)realloc(cmd_help, strlen(cmd_help) + strlen(help_text) + 1);
115 strcat(cmd_help, help_text);
116 } else
117 cmd_help = strdup(help_text);
118 }
119 }
120
121
122 /*
123 * Print error message
124 */
125
126 void mon_error(const char *s)
127 {
128 fprintf(monerr, "*** %s\n", s);
129 }
130
131
132 /*
133 * CTRL-C pressed?
134 */
135
136 static bool was_aborted;
137 static struct sigaction my_sa;
138
139 #ifdef __BEOS__
140 static void handle_abort(int sig, void *arg, vregs *r)
141 #else
142 static void handle_abort(int sig)
143 #endif
144 {
145 was_aborted = true;
146 }
147
148 static void init_abort(void)
149 {
150 was_aborted = false;
151 sigemptyset(&my_sa.sa_mask);
152 #ifdef __BEOS__
153 my_sa.sa_handler = (__signal_func_ptr)handle_abort;
154 my_sa.sa_userdata = 0;
155 #else
156 my_sa.sa_handler = handle_abort;
157 #endif
158 my_sa.sa_flags = 0;
159 sigaction(SIGINT, &my_sa, NULL);
160 }
161
162 static void exit_abort(void)
163 {
164 my_sa.sa_handler = SIG_DFL;
165 sigaction(SIGINT, &my_sa, NULL);
166 }
167
168 bool mon_aborted(void)
169 {
170 bool ret = was_aborted;
171 was_aborted = false;
172 return ret;
173 }
174
175
176 /*
177 * Access to buffer
178 */
179
180 uint32 mon_read_byte(uint32 adr)
181 {
182 if (mon_use_real_mem)
183 return *(uint8 *)adr;
184 else
185 return mem[adr % mon_mem_size];
186 }
187
188 void mon_write_byte(uint32 adr, uint32 b)
189 {
190 if (mon_use_real_mem)
191 *(uint8 *)adr = b;
192 else
193 mem[adr % mon_mem_size] = b;
194 }
195
196 uint32 mon_read_half(uint32 adr)
197 {
198 if (mon_use_real_mem)
199 return ntohs(*(uint16 *)adr);
200 else
201 return mem[adr % mon_mem_size] << 8 | mem[(adr+1) % mon_mem_size];
202 }
203
204 void mon_write_half(uint32 adr, uint32 w)
205 {
206 if (mon_use_real_mem)
207 *(uint16 *)adr = htons(w);
208 else {
209 mem[adr % mon_mem_size] = w >> 8;
210 mem[(adr+1) % mon_mem_size] = w;
211 }
212 }
213
214 uint32 mon_read_word(uint32 adr)
215 {
216 if (mon_use_real_mem)
217 return ntohl(*(uint32 *)adr);
218 else
219 return mon_read_byte(adr) << 24 | mon_read_byte(adr+1) << 16 | mon_read_byte(adr+2) << 8 | mon_read_byte(adr+3);
220 }
221
222 void mon_write_word(uint32 adr, uint32 l)
223 {
224 if (mon_use_real_mem)
225 *(uint32 *)adr = htonl(l);
226 else {
227 mem[adr % mon_mem_size] = l >> 24;
228 mem[(adr+1) % mon_mem_size] = l >> 16;
229 mem[(adr+2) % mon_mem_size] = l >> 8;
230 mem[(adr+3) % mon_mem_size] = l;
231 }
232 }
233
234
235 /*
236 * Read a line from the keyboard
237 */
238
239 static void read_line(char *prompt)
240 {
241 static char *line_read = NULL;
242
243 if (line_read) {
244 free(line_read);
245 line_read = NULL;
246 }
247
248 line_read = readline(prompt);
249
250 if (line_read && *line_read)
251 add_history(line_read);
252
253 strncpy(in_ptr = input, line_read, INPUT_LENGTH);
254 input[INPUT_LENGTH-1] = 0;
255 }
256
257
258 /*
259 * Read a character from the input line
260 */
261
262 static char get_char(void)
263 {
264 return *in_ptr++;
265 }
266
267
268 /*
269 * Stuff back a character into the input line
270 */
271
272 static void put_back(char c)
273 {
274 *(--in_ptr) = c;
275 }
276
277
278 /*
279 * Scanner: Get a token from the input line
280 */
281
282 enum Token mon_get_token(void)
283 {
284 char c;
285
286 // Skip spaces
287 while ((c = get_char()) == ' ') ;
288
289 switch (c) {
290 case 0:
291 return mon_token = T_END;
292 case '(':
293 return mon_token = T_LPAREN;
294 case ')':
295 return mon_token = T_RPAREN;
296 case '.':
297 return mon_token = T_DOT;
298 case ':':
299 return mon_token = T_COLON;
300 case ',':
301 return mon_token = T_COMMA;
302 case '+':
303 return mon_token = T_PLUS;
304 case '-':
305 return mon_token = T_MINUS;
306 case '*':
307 return mon_token = T_MUL;
308 case '/':
309 return mon_token = T_DIV;
310 case '%':
311 return mon_token = T_MOD;
312 case '&':
313 return mon_token = T_AND;
314 case '|':
315 return mon_token = T_OR;
316 case '^':
317 return mon_token = T_EOR;
318 case '<':
319 if (get_char() == '<')
320 return mon_token = T_SHIFTL;
321 else {
322 mon_error("Unrecognized token");
323 return mon_token = T_NULL;
324 }
325 case '>':
326 if (get_char() == '>')
327 return mon_token = T_SHIFTR;
328 else {
329 mon_error("Unrecognized token");
330 return mon_token = T_NULL;
331 }
332 case '~':
333 return mon_token = T_NOT;
334 case '=':
335 return mon_token = T_ASSIGN;
336
337 case '$':
338 if ((mon_token = get_hex_number(mon_number)) == T_NULL)
339 mon_error("'$' must be followed by hexadecimal number");
340 return mon_token;
341 case '_':
342 if ((mon_token = get_dec_number(mon_number)) == T_NULL)
343 mon_error("'_' must be followed by decimal number");
344 return mon_token;
345 case '\'':
346 return mon_token = get_char_number(mon_number);
347 case '"':
348 return mon_token = get_string(mon_string);
349
350 default:
351 if (isalnum(c)) {
352 put_back(c);
353 return mon_token = get_hex_or_name(mon_number, mon_name);
354 }
355 mon_error("Unrecognized token");
356 return mon_token = T_NULL;
357 }
358 }
359
360 static enum Token get_hex_number(uint32 &i)
361 {
362 char c = get_char();
363
364 i = 0;
365 if (!isxdigit(c))
366 return T_NULL;
367
368 do {
369 if (c < 'a')
370 i = (i << 4) + (c - '0');
371 else
372 i = (i << 4) + (c - 'a' + 10);
373 c = get_char();
374 } while (isxdigit(c));
375
376 if (isalnum(c))
377 return T_NULL;
378 else {
379 put_back(c);
380 return T_NUMBER;
381 }
382 }
383
384 static enum Token get_dec_number(uint32 &i)
385 {
386 char c = get_char();
387
388 i = 0;
389 if (!isdigit(c))
390 return T_NULL;
391
392 do {
393 i = (i * 10) + (c - '0');
394 c = get_char();
395 } while (isdigit(c));
396
397 if (isalnum(c))
398 return T_NULL;
399 else {
400 put_back(c);
401 return T_NUMBER;
402 }
403 }
404
405 static enum Token get_char_number(uint32 &i)
406 {
407 char c;
408
409 i = 0;
410 while ((c = get_char()) != 0) {
411 if (c == '\'')
412 return T_NUMBER;
413 i = (i << 8) + (uint8)c;
414 }
415
416 mon_error("Unterminated character constant");
417 return T_NULL;
418 }
419
420 static enum Token get_string(char *str)
421 {
422 char c;
423
424 while ((c = get_char()) != 0) {
425 if (c == '"') {
426 *str = 0;
427 return T_STRING;
428 }
429 *str++ = c;
430 }
431
432 mon_error("Unterminated string");
433 return T_NULL;
434 }
435
436 static enum Token get_hex_or_name(uint32 &i, char *name)
437 {
438 char *old_in_ptr = in_ptr;
439 char c;
440
441 // Try hex number first
442 if (get_hex_number(i) == T_NUMBER)
443 return T_NUMBER;
444
445 // Not a hex number, must be a variable name
446 in_ptr = old_in_ptr;
447 c = get_char();
448 do {
449 *name++ = c;
450 c = get_char();
451 } while (isalnum(c));
452
453 *name = 0;
454 put_back(c);
455 return T_NAME;
456 }
457
458
459 /*
460 * expression = eor_expr {OR eor_expr}
461 * true: OK, false: Error
462 */
463
464 bool mon_expression(uint32 *number)
465 {
466 uint32 accu, expr;
467
468 if (!eor_expr(&accu))
469 return false;
470
471 for (;;)
472 switch (mon_token) {
473 case T_OR:
474 mon_get_token();
475 if (!eor_expr(&expr))
476 return false;
477 accu |= expr;
478 break;
479
480 default:
481 *number = accu;
482 return true;
483 }
484 }
485
486
487 /*
488 * eor_expr = and_expr {EOR and_expr}
489 * true: OK, false: Error
490 */
491
492 static bool eor_expr(uint32 *number)
493 {
494 uint32 accu, expr;
495
496 if (!and_expr(&accu))
497 return false;
498
499 for (;;)
500 switch (mon_token) {
501 case T_EOR:
502 mon_get_token();
503 if (!and_expr(&expr))
504 return false;
505 accu ^= expr;
506 break;
507
508 default:
509 *number = accu;
510 return true;
511 }
512 }
513
514
515 /*
516 * and_expr = shift_expr {AND shift_expr}
517 * true: OK, false: Error
518 */
519
520 static bool and_expr(uint32 *number)
521 {
522 uint32 accu, expr;
523
524 if (!shift_expr(&accu))
525 return false;
526
527 for (;;)
528 switch (mon_token) {
529 case T_AND:
530 mon_get_token();
531 if (!shift_expr(&expr))
532 return false;
533 accu &= expr;
534 break;
535
536 default:
537 *number = accu;
538 return true;
539 }
540 }
541
542
543 /*
544 * shift_expr = add_expr {(SHIFTL | SHIFTR) add_expr}
545 * true: OK, false: Error
546 */
547
548 static bool shift_expr(uint32 *number)
549 {
550 uint32 accu, expr;
551
552 if (!add_expr(&accu))
553 return false;
554
555 for (;;)
556 switch (mon_token) {
557 case T_SHIFTL:
558 mon_get_token();
559 if (!add_expr(&expr))
560 return false;
561 accu <<= expr;
562 break;
563
564 case T_SHIFTR:
565 mon_get_token();
566 if (!add_expr(&expr))
567 return false;
568 accu >>= expr;
569 break;
570
571 default:
572 *number = accu;
573 return true;
574 }
575 }
576
577
578 /*
579 * add_expr = mul_expr {(PLUS | MINUS) mul_expr}
580 * true: OK, false: Error
581 */
582
583 static bool add_expr(uint32 *number)
584 {
585 uint32 accu, expr;
586
587 if (!mul_expr(&accu))
588 return false;
589
590 for (;;)
591 switch (mon_token) {
592 case T_PLUS:
593 mon_get_token();
594 if (!mul_expr(&expr))
595 return false;
596 accu += expr;
597 break;
598
599 case T_MINUS:
600 mon_get_token();
601 if (!mul_expr(&expr))
602 return false;
603 accu -= expr;
604 break;
605
606 default:
607 *number = accu;
608 return true;
609 }
610 }
611
612
613 /*
614 * mul_expr = factor {(MUL | DIV | MOD) factor}
615 * true: OK, false: Error
616 */
617
618 static bool mul_expr(uint32 *number)
619 {
620 uint32 accu, fact;
621
622 if (!factor(&accu))
623 return false;
624
625 for (;;)
626 switch (mon_token) {
627 case T_MUL:
628 mon_get_token();
629 if (!factor(&fact))
630 return false;
631 accu *= fact;
632 break;
633
634 case T_DIV:
635 mon_get_token();
636 if (!factor(&fact))
637 return false;
638 if (fact == 0) {
639 mon_error("Division by 0");
640 return false;
641 }
642 accu /= fact;
643 break;
644
645 case T_MOD:
646 mon_get_token();
647 if (!factor(&fact))
648 return false;
649 if (fact == 0) {
650 mon_error("Division by 0");
651 return false;
652 }
653 accu %= fact;
654 break;
655
656 default:
657 *number = accu;
658 return true;
659 }
660 }
661
662
663 /*
664 * factor = NUMBER | NAME | DOT | COLON | (PLUS | MINUS | NOT) factor | LPAREN expression RPAREN
665 * true: OK, false: Error
666 */
667
668 static bool factor(uint32 *number)
669 {
670 switch (mon_token) {
671 case T_NUMBER:
672 *number = mon_number;
673 mon_get_token();
674 return true;
675
676 case T_NAME:{
677 Variable *var;
678 if ((var = lookup_var(mon_name)) != NULL) {
679 *number = var->value;
680 mon_get_token();
681 return true;
682 } else
683 return false;
684 }
685
686 case T_DOT:
687 *number = mon_dot_address;
688 mon_get_token();
689 return true;
690
691 case T_COLON:
692 *number = colon_value;
693 mon_get_token();
694 return true;
695
696 case T_PLUS:
697 mon_get_token();
698 return factor(number);
699
700 case T_MINUS:
701 mon_get_token();
702 if (factor(number)) {
703 *number = -*number;
704 return true;
705 } else
706 return false;
707
708 case T_NOT:
709 mon_get_token();
710 if (factor(number)) {
711 *number = ~*number;
712 return true;
713 } else
714 return false;
715
716 case T_LPAREN:
717 mon_get_token();
718 if (mon_expression(number))
719 if (mon_token == T_RPAREN) {
720 mon_get_token();
721 return true;
722 } else {
723 mon_error("Missing ')'");
724 return false;
725 }
726 else {
727 mon_error("Error in expression");
728 return false;
729 }
730
731 case T_END:
732 mon_error("Required argument missing");
733 return false;
734
735 default:
736 mon_error("'(' or number expected");
737 return false;
738 }
739 }
740
741
742 /*
743 * Lookup the value of a variable
744 */
745
746 static Variable *lookup_var(const char *s)
747 {
748 // Lookup variable
749 for (Variable *var=first_var; var; var=var->next)
750 if (!strcmp(s, var->name))
751 return var;
752
753 // Not found, error
754 mon_error("Undefined variable");
755 return NULL;
756 }
757
758
759 /*
760 * Insert new variable (or redefine old)
761 */
762
763 static Variable *insert_var(const char *s)
764 {
765 // Lookup variable
766 for (Variable *var=first_var; var; var=var->next)
767 if (!strcmp(s, var->name))
768 return var;
769
770 // Insert new variable
771 Variable *var = new Variable;
772 var->name = strdup(s);
773 var->next = first_var;
774 first_var = var;
775 return var;
776 }
777
778
779 /*
780 * Remove variable
781 */
782
783 static void remove_var(const char *s)
784 {
785 Variable *var, *prev = (Variable *)&first_var;
786
787 // Lookup variable and remove it
788 for (var=prev->next; var; prev=var, var=var->next)
789 if (!strcmp(s, var->name)) {
790 prev->next = var->next;
791 free(var->name);
792 free(var);
793 return;
794 }
795 }
796
797
798 /*
799 * Set/clear/show variables
800 * set [var[=value]]
801 */
802
803 static void set_var(void)
804 {
805 if (mon_token == T_END) {
806
807 // Show all variables
808 if (first_var == NULL)
809 fprintf(monout, "No variables defined\n");
810 else
811 for (Variable *v=first_var; v; v=v->next)
812 fprintf(monout, "%s = %08lx\n", v->name, v->value);
813
814 } else if (mon_token == T_NAME) {
815 char var_name[256];
816 strcpy(var_name, mon_name);
817 mon_get_token();
818 if (mon_token == T_ASSIGN) {
819
820 // Set variable
821 uint32 value;
822 mon_get_token();
823 if (!mon_expression(&value))
824 return;
825 if (mon_token != T_END) {
826 mon_error("Too many arguments");
827 return;
828 }
829 insert_var(var_name)->value = value;
830
831 } else if (mon_token == T_END) {
832
833 // Clear variable
834 remove_var(var_name);
835
836 } else
837 mon_error("'=' expected");
838 } else
839 mon_error("Variable name expected");
840 }
841
842
843 /*
844 * Clear all variables
845 * cv
846 */
847
848 static void clear_vars(void)
849 {
850 Variable *var, *next;
851 for (var=first_var; var; var=next) {
852 free(var->name);
853 next = var->next;
854 free(var);
855 }
856 first_var = NULL;
857 }
858
859
860 /*
861 * Display help
862 * h
863 */
864
865 static void help_or_hunt(void)
866 {
867 if (mon_token != T_END) {
868 hunt();
869 return;
870 }
871 fprintf(monout, "x Quit mon\n"
872 "h This help text\n");
873 fprintf(monout, cmd_help);
874 }
875
876
877 /*
878 * Display command list
879 * ??
880 */
881
882 static void mon_cmd_list(void)
883 {
884 for (int i=0; i<num_cmds; i++)
885 fprintf(monout, "%s ", cmds[i].name);
886 fprintf(monout, "\n");
887 }
888
889
890 /*
891 * Reallocate buffer
892 * @ [size]
893 */
894
895 static void reallocate(void)
896 {
897 uint32 size;
898
899 if (mon_use_real_mem) {
900 fprintf(monerr, "Cannot reallocate buffer in real mode\n");
901 return;
902 }
903
904 if (mon_token == T_END) {
905 fprintf(monerr, "Buffer size: %08lx bytes\n", mon_mem_size);
906 return;
907 }
908
909 if (!mon_expression(&size))
910 return;
911 if (mon_token != T_END) {
912 mon_error("Too many arguments");
913 return;
914 }
915
916 if ((mem = (uint8 *)realloc(mem, size)) != NULL)
917 fprintf(monerr, "Buffer size: %08lx bytes\n", mon_mem_size = size);
918 else
919 fprintf(monerr, "Unable to reallocate buffer\n");
920 }
921
922
923 /*
924 * Apply expression to memory
925 * y[b|h|w] start end expression
926 */
927
928 static void apply(int size)
929 {
930 uint32 adr, end_adr, value;
931 char c;
932
933 if (!mon_expression(&adr))
934 return;
935 if (!mon_expression(&end_adr))
936 return;
937 if (!mon_expression(&value))
938 return;
939 if (mon_token != T_END) {
940 mon_error("Too many arguments");
941 return;
942 }
943
944 uint32 (*read_func)(uint32 adr);
945 void (*write_func)(uint32 adr, uint32 val);
946 switch (size) {
947 case 1:
948 read_func = mon_read_byte;
949 write_func = mon_write_byte;
950 break;
951 case 2:
952 read_func = mon_read_half;
953 write_func = mon_write_half;
954 break;
955 case 4:
956 read_func = mon_read_word;
957 write_func = mon_write_word;
958 break;
959 }
960
961 while (adr<=end_adr) {
962 colon_value = read_func(adr);
963 mon_dot_address = adr;
964
965 in_ptr = input;
966 while ((c = get_char()) == ' ') ;
967 while ((c = get_char()) != ' ') ;
968 while ((c = get_char()) == ' ') ;
969 put_back(c);
970 mon_get_token();
971 mon_expression(&value); // Skip start address
972 mon_expression(&value); // Skip end address
973 mon_expression(&value);
974
975 write_func(adr, value);
976 adr += size;
977 }
978
979 mon_dot_address = adr;
980 }
981
982 static void apply_byte(void)
983 {
984 apply(1);
985 }
986
987 static void apply_half(void)
988 {
989 apply(2);
990 }
991
992 static void apply_word(void)
993 {
994 apply(4);
995 }
996
997
998 /*
999 * Execute command via system() (for ls, rm, etc.)
1000 */
1001
1002 static void mon_exec(void)
1003 {
1004 system(input);
1005 }
1006
1007
1008 /*
1009 * Change current directory
1010 */
1011
1012 static void mon_change_dir(void)
1013 {
1014 char c;
1015 in_ptr = input;
1016 while ((c = get_char()) == ' ') ;
1017 while ((c = get_char()) != ' ') ;
1018 while ((c = get_char()) == ' ') ;
1019 put_back(c);
1020 if (chdir(in_ptr) != 0)
1021 mon_error("Cannot change directory");
1022 }
1023
1024
1025 /*
1026 * Initialize mon
1027 */
1028
1029 void mon_init(void)
1030 {
1031 cmds = NULL;
1032 num_cmds = 0;
1033 cmd_help = NULL;
1034
1035 mon_add_command("??", mon_cmd_list, "?? Show list of commands\n");
1036 mon_add_command("ver", version, "ver Show version\n");
1037 mon_add_command("?", print_expr, "? expression Calculate expression\n");
1038 mon_add_command("@", reallocate, "@ [size] Reallocate buffer\n");
1039 mon_add_command("i", ascii_dump, "i [start [end]] ASCII memory dump\n");
1040 mon_add_command("m", memory_dump, "m [start [end]] Hex/ASCII memory dump\n");
1041 mon_add_command("d", disassemble_ppc, "d [start [end]] Disassemble PowerPC code\n");
1042 mon_add_command("d65", disassemble_6502, "d65 [start [end]] Disassemble 6502 code\n");
1043 mon_add_command("d68", disassemble_680x0, "d68 [start [end]] Disassemble 680x0 code\n");
1044 mon_add_command("d80", disassemble_8080, "d80 [start [end]] Disassemble 8080 code\n");
1045 mon_add_command("d86", disassemble_80x86, "d86 [start [end]] Disassemble 80x86 code\n");
1046 mon_add_command(":", modify, ": start string Modify memory\n");
1047 mon_add_command("f", fill, "f start end string Fill memory\n");
1048 mon_add_command("y", apply_byte, "y[b|h|w] start end expr Apply expression to memory\n");
1049 mon_add_command("yb", apply_byte, NULL);
1050 mon_add_command("yh", apply_half, NULL);
1051 mon_add_command("yw", apply_word, NULL);
1052 mon_add_command("t", transfer, "t start end dest Transfer memory\n");
1053 mon_add_command("c", compare, "c start end dest Compare memory\n");
1054 mon_add_command("h", help_or_hunt, "h start end string Search for byte string\n");
1055 mon_add_command("\\", shell_command, "\\ \"command\" Execute shell command\n");
1056 mon_add_command("ls", mon_exec, "ls [args] List directory contents\n");
1057 mon_add_command("rm", mon_exec, "rm [args] Remove file(s)\n");
1058 mon_add_command("cp", mon_exec, "cp [args] Copy file(s)\n");
1059 mon_add_command("mv", mon_exec, "mv [args] Move file(s)\n");
1060 mon_add_command("cd", mon_change_dir, "cd directory Change current directory\n");
1061 mon_add_command("o", redir_output, "o [\"file\"] Redirect output\n");
1062 mon_add_command("[", load_data, "[ start \"file\" Load data from file\n");
1063 mon_add_command("]", save_data, "] start size \"file\" Save data to file\n");
1064 mon_add_command("set", set_var, "set [var[=value]] Set/clear/show variables\n");
1065 mon_add_command("cv", clear_vars, "cv Clear all variables\n");
1066 }
1067
1068
1069 /*
1070 * Deinitialize mon
1071 */
1072
1073 void mon_exit(void)
1074 {
1075 free(cmds);
1076 cmds = NULL;
1077 num_cmds = 0;
1078 cmd_help = NULL;
1079 }
1080
1081
1082 /*
1083 * Main function, read-execute loop
1084 */
1085
1086 void mon(int argc, char **argv)
1087 {
1088 bool done = false, interactive = true;
1089 char c, cmd[INPUT_LENGTH];
1090
1091 // Setup input/output streams
1092 monin = stdin;
1093 monout = stdout;
1094 monerr = stdout;
1095
1096 if (argc) {
1097 // Access real memory if mon was started as "rmon"
1098 char *prgname = argv[0];
1099 char *lastslash;
1100 if ((lastslash = strrchr(prgname, '/')) != NULL)
1101 prgname = lastslash + 1;
1102 if (strcmp(prgname, "rmon") == 0)
1103 mon_use_real_mem = true;
1104
1105 // Make argc/argv point to the actual arguments
1106 argc--;
1107 argv++;
1108 interactive = (argc == 0);
1109 }
1110
1111 // Allocate buffer
1112 if (!mon_use_real_mem) {
1113 mon_mem_size = 0x100000;
1114 mem = (uint8 *)malloc(mon_mem_size);
1115
1116 // Print banner
1117 if (interactive)
1118 fprintf(monerr, "\n *** mon V%d.%d by Christian Bauer ***\n"
1119 " *** Press 'h' for help ***\n\n", MON_VERSION, MON_REVISION);
1120 }
1121
1122 init_abort();
1123
1124 // Read and parse command line
1125 while (!done) {
1126 if (interactive) {
1127 char prompt[16];
1128 sprintf(prompt, "[%08lx]-> ", mon_dot_address);
1129 read_line(prompt);
1130 } else {
1131 if (argc == 0) {
1132 done = true;
1133 break;
1134 } else {
1135 strncpy(in_ptr = input, argv[0], INPUT_LENGTH);
1136 argc--;
1137 argv++;
1138 }
1139 }
1140
1141 // Skip leading spaces
1142 while ((c = get_char()) == ' ') ;
1143
1144 // Read command word
1145 char *p = cmd;
1146 do {
1147 *p++ = c;
1148 c = get_char();
1149 } while (isgraph(c));
1150 *p = 0;
1151 put_back(c);
1152
1153 // Execute command
1154 if (cmd[0] == 0) // Blank line
1155 continue;
1156 if (strcmp(cmd, "x") == 0) { // Exit
1157 done = true;
1158 continue;
1159 }
1160 for (int i=0; i<num_cmds; i++) {
1161 if (strcmp(cmd, cmds[i].name) == 0) {
1162 mon_get_token();
1163 cmds[i].func();
1164 goto cmd_done;
1165 }
1166 }
1167 mon_error("Unknown command");
1168 cmd_done: ;
1169 }
1170
1171 exit_abort();
1172
1173 // Free buffer
1174 if (!mon_use_real_mem)
1175 free(mem);
1176
1177 // Close output file if redirected
1178 if (monout != monerr)
1179 fclose(monout);
1180 }