ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/mon/src/mon.cpp
Revision: 1.22
Committed: 2003-09-27T20:33:06Z (20 years, 7 months ago) by cebix
Branch: MAIN
Changes since 1.21: +1 -1 lines
Log Message:
2002 -> 2003

File Contents

# Content
1 /*
2 * mon.cpp - cxmon main program
3 *
4 * cxmon (C) 1997-2003 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[INPUT_LENGTH];
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[INPUT_LENGTH]; // Contains the string if mon_token==T_STRING
84 char mon_name[INPUT_LENGTH]; // 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)(void); // 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(void);
105 static void exit_abort(void);
106
107 static void read_line(char *prompt); // Scanner
108 static char get_char(void);
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)(void), 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(void)
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(void)
188 {
189 my_sa.sa_handler = SIG_DFL;
190 sigaction(SIGINT, &my_sa, NULL);
191 }
192
193 bool mon_aborted(void)
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 static char *line_read = NULL;
262
263 if (line_read) {
264 free(line_read);
265 line_read = NULL;
266 }
267
268 line_read = readline(prompt);
269
270 if (line_read) {
271
272 if (*line_read)
273 add_history(line_read);
274
275 strncpy(in_ptr = input, line_read, INPUT_LENGTH);
276 input[INPUT_LENGTH-1] = 0;
277
278 } else {
279
280 // EOF, quit cxmon
281 fprintf(monout, "x\n");
282 input[0] = 'x';
283 input[1] = 0;
284 in_ptr = input;
285 }
286 #else
287 fprintf(monout, prompt);
288 fflush(monout);
289 fgets(in_ptr = input, INPUT_LENGTH, monin);
290 char *s = strchr(input, '\n');
291 if (s != NULL)
292 *s = 0;
293 #endif
294 }
295
296
297 /*
298 * Read a character from the input line
299 */
300
301 static char get_char(void)
302 {
303 return *in_ptr++;
304 }
305
306
307 /*
308 * Stuff back a character into the input line
309 */
310
311 static void put_back(char c)
312 {
313 *(--in_ptr) = c;
314 }
315
316
317 /*
318 * Scanner: Get a token from the input line
319 */
320
321 enum Token mon_get_token(void)
322 {
323 char c;
324
325 // Skip spaces
326 while ((c = get_char()) == ' ') ;
327
328 switch (c) {
329 case 0:
330 return mon_token = T_END;
331 case '(':
332 return mon_token = T_LPAREN;
333 case ')':
334 return mon_token = T_RPAREN;
335 case '.':
336 return mon_token = T_DOT;
337 case ':':
338 return mon_token = T_COLON;
339 case ',':
340 return mon_token = T_COMMA;
341 case '+':
342 return mon_token = T_PLUS;
343 case '-':
344 return mon_token = T_MINUS;
345 case '*':
346 return mon_token = T_MUL;
347 case '/':
348 return mon_token = T_DIV;
349 case '%':
350 return mon_token = T_MOD;
351 case '&':
352 return mon_token = T_AND;
353 case '|':
354 return mon_token = T_OR;
355 case '^':
356 return mon_token = T_EOR;
357 case '<':
358 if (get_char() == '<')
359 return mon_token = T_SHIFTL;
360 else {
361 mon_error("Unrecognized token");
362 return mon_token = T_NULL;
363 }
364 case '>':
365 if (get_char() == '>')
366 return mon_token = T_SHIFTR;
367 else {
368 mon_error("Unrecognized token");
369 return mon_token = T_NULL;
370 }
371 case '~':
372 return mon_token = T_NOT;
373 case '=':
374 return mon_token = T_ASSIGN;
375
376 case '$':
377 if ((mon_token = get_hex_number(mon_number)) == T_NULL)
378 mon_error("'$' must be followed by hexadecimal number");
379 return mon_token;
380 case '_':
381 if ((mon_token = get_dec_number(mon_number)) == T_NULL)
382 mon_error("'_' must be followed by decimal number");
383 return mon_token;
384 case '\'':
385 return mon_token = get_char_number(mon_number);
386 case '"':
387 return mon_token = get_string(mon_string);
388
389 default:
390 if (isalnum(c)) {
391 put_back(c);
392 return mon_token = get_hex_or_name(mon_number, mon_name);
393 }
394 mon_error("Unrecognized token");
395 return mon_token = T_NULL;
396 }
397 }
398
399 static enum Token get_hex_number(uintptr &i)
400 {
401 char c = get_char();
402
403 i = 0;
404 if (!isxdigit(c))
405 return T_NULL;
406
407 do {
408 c = tolower(c);
409 if (c < 'a')
410 i = (i << 4) + (c - '0');
411 else
412 i = (i << 4) + (c - 'a' + 10);
413 c = get_char();
414 } while (isxdigit(c));
415
416 if (isalnum(c))
417 return T_NULL;
418 else {
419 put_back(c);
420 return T_NUMBER;
421 }
422 }
423
424 static enum Token get_dec_number(uintptr &i)
425 {
426 char c = get_char();
427
428 i = 0;
429 if (!isdigit(c))
430 return T_NULL;
431
432 do {
433 i = (i * 10) + (c - '0');
434 c = get_char();
435 } while (isdigit(c));
436
437 if (isalnum(c))
438 return T_NULL;
439 else {
440 put_back(c);
441 return T_NUMBER;
442 }
443 }
444
445 static enum Token get_char_number(uintptr &i)
446 {
447 char c;
448
449 i = 0;
450 while ((c = get_char()) != 0) {
451 if (c == '\'')
452 return T_NUMBER;
453 i = (i << 8) + (uint8)c;
454 }
455
456 mon_error("Unterminated character constant");
457 return T_NULL;
458 }
459
460 static enum Token get_string(char *str)
461 {
462 char c;
463
464 while ((c = get_char()) != 0) {
465 if (c == '"') {
466 *str = 0;
467 return T_STRING;
468 }
469 *str++ = c;
470 }
471
472 mon_error("Unterminated string");
473 return T_NULL;
474 }
475
476 static enum Token get_hex_or_name(uintptr &i, char *name)
477 {
478 char *old_in_ptr = in_ptr;
479 char c;
480
481 // Try hex number first
482 if (get_hex_number(i) == T_NUMBER)
483 return T_NUMBER;
484
485 // Not a hex number, must be a variable name
486 in_ptr = old_in_ptr;
487 c = get_char();
488 do {
489 *name++ = c;
490 c = get_char();
491 } while (isalnum(c));
492
493 *name = 0;
494 put_back(c);
495 return T_NAME;
496 }
497
498
499 /*
500 * expression = eor_expr {OR eor_expr}
501 * true: OK, false: Error
502 */
503
504 bool mon_expression(uintptr *number)
505 {
506 uintptr accu, expr;
507
508 if (!eor_expr(&accu))
509 return false;
510
511 for (;;)
512 switch (mon_token) {
513 case T_OR:
514 mon_get_token();
515 if (!eor_expr(&expr))
516 return false;
517 accu |= expr;
518 break;
519
520 default:
521 *number = accu;
522 return true;
523 }
524 }
525
526
527 /*
528 * eor_expr = and_expr {EOR and_expr}
529 * true: OK, false: Error
530 */
531
532 static bool eor_expr(uintptr *number)
533 {
534 uintptr accu, expr;
535
536 if (!and_expr(&accu))
537 return false;
538
539 for (;;)
540 switch (mon_token) {
541 case T_EOR:
542 mon_get_token();
543 if (!and_expr(&expr))
544 return false;
545 accu ^= expr;
546 break;
547
548 default:
549 *number = accu;
550 return true;
551 }
552 }
553
554
555 /*
556 * and_expr = shift_expr {AND shift_expr}
557 * true: OK, false: Error
558 */
559
560 static bool and_expr(uintptr *number)
561 {
562 uintptr accu, expr;
563
564 if (!shift_expr(&accu))
565 return false;
566
567 for (;;)
568 switch (mon_token) {
569 case T_AND:
570 mon_get_token();
571 if (!shift_expr(&expr))
572 return false;
573 accu &= expr;
574 break;
575
576 default:
577 *number = accu;
578 return true;
579 }
580 }
581
582
583 /*
584 * shift_expr = add_expr {(SHIFTL | SHIFTR) add_expr}
585 * true: OK, false: Error
586 */
587
588 static bool shift_expr(uintptr *number)
589 {
590 uintptr accu, expr;
591
592 if (!add_expr(&accu))
593 return false;
594
595 for (;;)
596 switch (mon_token) {
597 case T_SHIFTL:
598 mon_get_token();
599 if (!add_expr(&expr))
600 return false;
601 accu <<= expr;
602 break;
603
604 case T_SHIFTR:
605 mon_get_token();
606 if (!add_expr(&expr))
607 return false;
608 accu >>= expr;
609 break;
610
611 default:
612 *number = accu;
613 return true;
614 }
615 }
616
617
618 /*
619 * add_expr = mul_expr {(PLUS | MINUS) mul_expr}
620 * true: OK, false: Error
621 */
622
623 static bool add_expr(uintptr *number)
624 {
625 uintptr accu, expr;
626
627 if (!mul_expr(&accu))
628 return false;
629
630 for (;;)
631 switch (mon_token) {
632 case T_PLUS:
633 mon_get_token();
634 if (!mul_expr(&expr))
635 return false;
636 accu += expr;
637 break;
638
639 case T_MINUS:
640 mon_get_token();
641 if (!mul_expr(&expr))
642 return false;
643 accu -= expr;
644 break;
645
646 default:
647 *number = accu;
648 return true;
649 }
650 }
651
652
653 /*
654 * mul_expr = factor {(MUL | DIV | MOD) factor}
655 * true: OK, false: Error
656 */
657
658 static bool mul_expr(uintptr *number)
659 {
660 uintptr accu, fact;
661
662 if (!factor(&accu))
663 return false;
664
665 for (;;)
666 switch (mon_token) {
667 case T_MUL:
668 mon_get_token();
669 if (!factor(&fact))
670 return false;
671 accu *= fact;
672 break;
673
674 case T_DIV:
675 mon_get_token();
676 if (!factor(&fact))
677 return false;
678 if (fact == 0) {
679 mon_error("Division by 0");
680 return false;
681 }
682 accu /= fact;
683 break;
684
685 case T_MOD:
686 mon_get_token();
687 if (!factor(&fact))
688 return false;
689 if (fact == 0) {
690 mon_error("Division by 0");
691 return false;
692 }
693 accu %= fact;
694 break;
695
696 default:
697 *number = accu;
698 return true;
699 }
700 }
701
702
703 /*
704 * factor = NUMBER | NAME | DOT | COLON | (PLUS | MINUS | NOT) factor | LPAREN expression RPAREN
705 * true: OK, false: Error
706 */
707
708 static bool factor(uintptr *number)
709 {
710 switch (mon_token) {
711 case T_NUMBER:
712 *number = mon_number;
713 mon_get_token();
714 return true;
715
716 case T_NAME:{
717 var_map::const_iterator v = vars.find(mon_name);
718 if (v == vars.end())
719 return false;
720 else {
721 *number = v->second;
722 mon_get_token();
723 return true;
724 }
725 }
726
727 case T_DOT:
728 *number = mon_dot_address;
729 mon_get_token();
730 return true;
731
732 case T_COLON:
733 *number = colon_value;
734 mon_get_token();
735 return true;
736
737 case T_PLUS:
738 mon_get_token();
739 return factor(number);
740
741 case T_MINUS:
742 mon_get_token();
743 if (factor(number)) {
744 *number = -*number;
745 return true;
746 } else
747 return false;
748
749 case T_NOT:
750 mon_get_token();
751 if (factor(number)) {
752 *number = ~*number;
753 return true;
754 } else
755 return false;
756
757 case T_LPAREN:
758 mon_get_token();
759 if (mon_expression(number))
760 if (mon_token == T_RPAREN) {
761 mon_get_token();
762 return true;
763 } else {
764 mon_error("Missing ')'");
765 return false;
766 }
767 else {
768 mon_error("Error in expression");
769 return false;
770 }
771
772 case T_END:
773 mon_error("Required argument missing");
774 return false;
775
776 default:
777 mon_error("'(' or number expected");
778 return false;
779 }
780 }
781
782
783 /*
784 * Set/clear/show variables
785 * set [var[=value]]
786 */
787
788 static void set_var(void)
789 {
790 if (mon_token == T_END) {
791
792 // Show all variables
793 if (vars.empty())
794 fprintf(monout, "No variables defined\n");
795 else {
796 var_map::const_iterator v = vars.begin(), end = vars.end();
797 for (v=vars.begin(); v!=end; ++v)
798 fprintf(monout, "%s = %08x\n", v->first.c_str(), v->second);
799 }
800
801 } else if (mon_token == T_NAME) {
802 std::string var_name = mon_name;
803 mon_get_token();
804 if (mon_token == T_ASSIGN) {
805
806 // Set variable
807 uintptr value;
808 mon_get_token();
809 if (!mon_expression(&value))
810 return;
811 if (mon_token != T_END) {
812 mon_error("Too many arguments");
813 return;
814 }
815 vars[var_name] = value;
816
817 } else if (mon_token == T_END) {
818
819 // Clear variable
820 vars.erase(var_name);
821
822 } else
823 mon_error("'=' expected");
824 } else
825 mon_error("Variable name expected");
826 }
827
828
829 /*
830 * Clear all variables
831 * cv
832 */
833
834 static void clear_vars(void)
835 {
836 vars.clear();
837 }
838
839
840 /*
841 * Display help
842 * h
843 */
844
845 static void help_or_hunt(void)
846 {
847 if (mon_token != T_END) {
848 hunt();
849 return;
850 }
851 fprintf(monout, "x Quit mon\n"
852 "h This help text\n");
853 fprintf(monout, cmd_help);
854 }
855
856
857 /*
858 * Display command list
859 * ??
860 */
861
862 static void mon_cmd_list(void)
863 {
864 for (int i=0; i<num_cmds; i++)
865 fprintf(monout, "%s ", cmds[i].name);
866 fprintf(monout, "\n");
867 }
868
869
870 /*
871 * Reallocate buffer
872 * @ [size]
873 */
874
875 static void reallocate(void)
876 {
877 uintptr size;
878
879 if (mon_use_real_mem) {
880 fprintf(monerr, "Cannot reallocate buffer in real mode\n");
881 return;
882 }
883
884 if (mon_token == T_END) {
885 fprintf(monerr, "Buffer size: %08x bytes\n", mon_mem_size);
886 return;
887 }
888
889 if (!mon_expression(&size))
890 return;
891 if (mon_token != T_END) {
892 mon_error("Too many arguments");
893 return;
894 }
895
896 if ((mem = (uint8 *)realloc(mem, size)) != NULL)
897 fprintf(monerr, "Buffer size: %08x bytes\n", mon_mem_size = size);
898 else
899 fprintf(monerr, "Unable to reallocate buffer\n");
900 }
901
902
903 /*
904 * Apply expression to memory
905 * y[b|h|w] start end expression
906 */
907
908 static void apply(int size)
909 {
910 uintptr adr, end_adr, value;
911 char c;
912
913 if (!mon_expression(&adr))
914 return;
915 if (!mon_expression(&end_adr))
916 return;
917 if (!mon_expression(&value))
918 return;
919 if (mon_token != T_END) {
920 mon_error("Too many arguments");
921 return;
922 }
923
924 uint32 (*read_func)(uintptr adr);
925 void (*write_func)(uintptr adr, uint32 val);
926 switch (size) {
927 case 1:
928 read_func = mon_read_byte;
929 write_func = mon_write_byte;
930 break;
931 case 2:
932 read_func = mon_read_half;
933 write_func = mon_write_half;
934 break;
935 case 4:
936 read_func = mon_read_word;
937 write_func = mon_write_word;
938 break;
939 default:
940 abort();
941 break;
942 }
943
944 while (adr<=end_adr) {
945 colon_value = read_func(adr);
946 mon_dot_address = adr;
947
948 in_ptr = input;
949 while ((c = get_char()) == ' ') ;
950 while ((c = get_char()) != ' ') ;
951 while ((c = get_char()) == ' ') ;
952 put_back(c);
953 mon_get_token();
954 mon_expression(&value); // Skip start address
955 mon_expression(&value); // Skip end address
956 mon_expression(&value);
957
958 write_func(adr, value);
959 adr += size;
960 }
961
962 mon_dot_address = adr;
963 }
964
965 static void apply_byte(void)
966 {
967 apply(1);
968 }
969
970 static void apply_half(void)
971 {
972 apply(2);
973 }
974
975 static void apply_word(void)
976 {
977 apply(4);
978 }
979
980
981 /*
982 * Execute command via system() (for ls, rm, etc.)
983 */
984
985 static void mon_exec(void)
986 {
987 system(input);
988 }
989
990
991 /*
992 * Change current directory
993 */
994
995 static void mon_change_dir(void)
996 {
997 char c;
998 in_ptr = input;
999 while ((c = get_char()) == ' ') ;
1000 while ((c = get_char()) != ' ') ;
1001 while ((c = get_char()) == ' ') ;
1002 put_back(c);
1003 if (chdir(in_ptr) != 0)
1004 mon_error("Cannot change directory");
1005 }
1006
1007
1008 /*
1009 * Initialize mon
1010 */
1011
1012 void mon_init(void)
1013 {
1014 cmds = NULL;
1015 num_cmds = 0;
1016 cmd_help = NULL;
1017
1018 mon_add_command("??", mon_cmd_list, "?? Show list of commands\n");
1019 mon_add_command("ver", version, "ver Show version\n");
1020 mon_add_command("?", print_expr, "? expression Calculate expression\n");
1021 mon_add_command("@", reallocate, "@ [size] Reallocate buffer\n");
1022 mon_add_command("i", ascii_dump, "i [start [end]] ASCII memory dump\n");
1023 mon_add_command("m", memory_dump, "m [start [end]] Hex/ASCII memory dump\n");
1024 mon_add_command("b", binary_dump, "b [start [end]] Binary memory dump\n");
1025 mon_add_command("d", disassemble_ppc, "d [start [end]] Disassemble PowerPC code\n");
1026 mon_add_command("d65", disassemble_6502, "d65 [start [end]] Disassemble 6502 code\n");
1027 mon_add_command("d68", disassemble_680x0, "d68 [start [end]] Disassemble 680x0 code\n");
1028 mon_add_command("d80", disassemble_z80, "d80 [start [end]] Disassemble Z80 code\n");
1029 mon_add_command("d86", disassemble_80x86_32, "d86 [start [end]] Disassemble 80x86 (32-bit) code\n");
1030 mon_add_command("d8086", disassemble_80x86_16, "d8086 [start [end]] Disassemble 80x86 (16-bit) code\n");
1031 mon_add_command("d8664", disassemble_x86_64, "d8664 [start [end]] Disassemble x86-64 code\n");
1032 mon_add_command(":", modify, ": start string Modify memory\n");
1033 mon_add_command("f", fill, "f start end string Fill memory\n");
1034 mon_add_command("y", apply_byte, "y[b|h|w] start end expr Apply expression to memory\n");
1035 mon_add_command("yb", apply_byte, NULL);
1036 mon_add_command("yh", apply_half, NULL);
1037 mon_add_command("yw", apply_word, NULL);
1038 mon_add_command("t", transfer, "t start end dest Transfer memory\n");
1039 mon_add_command("c", compare, "c start end dest Compare memory\n");
1040 mon_add_command("h", help_or_hunt, "h start end string Search for byte string\n");
1041 mon_add_command("\\", shell_command, "\\ \"command\" Execute shell command\n");
1042 mon_add_command("ls", mon_exec, "ls [args] List directory contents\n");
1043 mon_add_command("rm", mon_exec, "rm [args] Remove file(s)\n");
1044 mon_add_command("cp", mon_exec, "cp [args] Copy file(s)\n");
1045 mon_add_command("mv", mon_exec, "mv [args] Move file(s)\n");
1046 mon_add_command("cd", mon_change_dir, "cd directory Change current directory\n");
1047 mon_add_command("o", redir_output, "o [\"file\"] Redirect output\n");
1048 mon_add_command("[", load_data, "[ start \"file\" Load data from file\n");
1049 mon_add_command("]", save_data, "] start size \"file\" Save data to file\n");
1050 mon_add_command("set", set_var, "set [var[=value]] Set/clear/show variables\n");
1051 mon_add_command("cv", clear_vars, "cv Clear all variables\n");
1052
1053 mon_read_byte = NULL;
1054 mon_write_byte = NULL;
1055 }
1056
1057
1058 /*
1059 * Deinitialize mon
1060 */
1061
1062 void mon_exit(void)
1063 {
1064 free(cmds);
1065 cmds = NULL;
1066 num_cmds = 0;
1067 cmd_help = NULL;
1068 }
1069
1070
1071 /*
1072 * Main function, read-execute loop
1073 */
1074
1075 void mon(int argc, char **argv)
1076 {
1077 bool done = false, interactive = true;
1078 char c, cmd[INPUT_LENGTH];
1079
1080 // Setup input/output streams
1081 monin = stdin;
1082 monout = stdout;
1083 monerr = stdout;
1084
1085 // Make argc/argv point to the actual arguments
1086 const char *prg_name = argv[0];
1087 if (argc)
1088 argc--; argv++;
1089
1090 // Parse arguments
1091 mon_macos_mode = false;
1092 mon_use_real_mem = false;
1093 while (argc > 0) {
1094 if (strcmp(argv[0], "-h") == 0 || strcmp(argv[0], "--help") == 0) {
1095 printf("Usage: %s [-m] [-r] [command...]\n", prg_name);
1096 exit(0);
1097 } else if (strcmp(argv[0], "-m") == 0)
1098 mon_macos_mode = true;
1099 else if (strcmp(argv[0], "-r") == 0)
1100 mon_use_real_mem = true;
1101 else
1102 break;
1103 argc--; argv++;
1104 }
1105 interactive = (argc == 0);
1106
1107 // Set up memory access functions if not supplied by the user
1108 if (mon_read_byte == NULL) {
1109 if (mon_use_real_mem)
1110 mon_read_byte = mon_read_byte_real;
1111 else
1112 mon_read_byte = mon_read_byte_buffer;
1113 }
1114 if (mon_write_byte == NULL) {
1115 if (mon_use_real_mem)
1116 mon_write_byte = mon_write_byte_real;
1117 else
1118 mon_write_byte = mon_write_byte_buffer;
1119 }
1120
1121 // Allocate buffer
1122 if (!mon_use_real_mem) {
1123 mon_mem_size = 0x100000;
1124 mem = (uint8 *)malloc(mon_mem_size);
1125
1126 // Print banner
1127 if (interactive)
1128 fprintf(monerr, "\n *** cxmon V" VERSION " by Christian Bauer and Marc Hellwig ***\n"
1129 " *** Press 'h' for help ***\n\n");
1130 }
1131
1132 // Clear variables
1133 vars.clear();
1134
1135 // In MacOS mode, pull in the lowmem globals as variables
1136 if (mon_macos_mode) {
1137 const lowmem_info *l = lowmem;
1138 while (l->name) {
1139 vars[l->name] = l->addr;
1140 l++;
1141 }
1142 }
1143
1144 init_abort();
1145
1146 // Read and parse command line
1147 while (!done) {
1148 if (interactive) {
1149 char prompt[16];
1150 sprintf(prompt, "[%0*lx]-> ", 2 * sizeof(mon_dot_address), mon_dot_address);
1151 read_line(prompt);
1152 } else {
1153 if (argc == 0) {
1154 done = true;
1155 break;
1156 } else {
1157 strncpy(in_ptr = input, argv[0], INPUT_LENGTH);
1158 argc--;
1159 argv++;
1160 }
1161 }
1162
1163 // Skip leading spaces
1164 while ((c = get_char()) == ' ') ;
1165
1166 // Read command word
1167 char *p = cmd;
1168 do {
1169 *p++ = c;
1170 c = get_char();
1171 } while (isgraph(c));
1172 *p = 0;
1173 put_back(c);
1174
1175 // Execute command
1176 if (cmd[0] == 0) // Blank line
1177 continue;
1178 if (strcmp(cmd, "x") == 0) { // Exit
1179 done = true;
1180 continue;
1181 }
1182 for (int i=0; i<num_cmds; i++) {
1183 if (strcmp(cmd, cmds[i].name) == 0) {
1184 mon_get_token();
1185 cmds[i].func();
1186 goto cmd_done;
1187 }
1188 }
1189 mon_error("Unknown command");
1190 cmd_done: ;
1191 }
1192
1193 exit_abort();
1194
1195 // Free buffer
1196 if (!mon_use_real_mem)
1197 free(mem);
1198
1199 // Close output file if redirected
1200 if (monout != monerr)
1201 fclose(monout);
1202 }