ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/mon/src/mon.cpp
Revision: 1.27
Committed: 2007-06-07T09:51:56Z (17 years, 5 months ago) by gbeauche
Branch: MAIN
Changes since 1.26: +2 -0 lines
Log Message:
Add MIPS disassembler invoked as "dm" and "dmel" (little-endian) for now.

File Contents

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