ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/mon/src/mon.cpp
Revision: 1.23
Committed: 2004-02-12T16:42:35Z (20 years, 3 months ago) by cebix
Branch: MAIN
Changes since 1.22: +140 -85 lines
Log Message:
- removed INPUT_LENGTH; stuff is now handled dynamically
- f(void) -> f()

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;
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 static char *line_read = NULL;
262
263 if (input)
264 free(input);
265 input = readline(prompt);
266
267 if (input) {
268 if (*input)
269 add_history(input);
270 } else {
271 // EOF, quit cxmon
272 input = (char *)malloc(2);
273 input[0] = 'x';
274 input[1] = 0;
275 fprintf(monout, "x\n");
276 }
277
278 in_ptr = input;
279 #else
280 #define INPUT_LENGTH 256
281 if (!input)
282 input = (char *)malloc(INPUT_LENGTH);
283 fprintf(monout, prompt);
284 fflush(monout);
285 fgets(in_ptr = input, INPUT_LENGTH, monin);
286 char *s = strchr(input, '\n');
287 if (s != NULL)
288 *s = 0;
289 #endif
290 }
291
292
293 /*
294 * Read a character from the input line
295 */
296
297 static char get_char()
298 {
299 return *in_ptr++;
300 }
301
302
303 /*
304 * Stuff back a character into the input line
305 */
306
307 static void put_back(char c)
308 {
309 *(--in_ptr) = c;
310 }
311
312
313 /*
314 * Scanner: Get a token from the input line
315 */
316
317 enum Token mon_get_token()
318 {
319 char c = get_char();
320
321 // Skip spaces
322 while (isspace(c))
323 c = get_char();
324
325 switch (c) {
326 case 0:
327 return mon_token = T_END;
328 case '(':
329 return mon_token = T_LPAREN;
330 case ')':
331 return mon_token = T_RPAREN;
332 case '.':
333 return mon_token = T_DOT;
334 case ':':
335 return mon_token = T_COLON;
336 case ',':
337 return mon_token = T_COMMA;
338 case '+':
339 return mon_token = T_PLUS;
340 case '-':
341 return mon_token = T_MINUS;
342 case '*':
343 return mon_token = T_MUL;
344 case '/':
345 return mon_token = T_DIV;
346 case '%':
347 return mon_token = T_MOD;
348 case '&':
349 return mon_token = T_AND;
350 case '|':
351 return mon_token = T_OR;
352 case '^':
353 return mon_token = T_EOR;
354 case '<':
355 if (get_char() == '<')
356 return mon_token = T_SHIFTL;
357 else {
358 mon_error("Unrecognized token");
359 return mon_token = T_NULL;
360 }
361 case '>':
362 if (get_char() == '>')
363 return mon_token = T_SHIFTR;
364 else {
365 mon_error("Unrecognized token");
366 return mon_token = T_NULL;
367 }
368 case '~':
369 return mon_token = T_NOT;
370 case '=':
371 return mon_token = T_ASSIGN;
372
373 case '$':
374 if ((mon_token = get_hex_number(mon_number)) == T_NULL)
375 mon_error("'$' must be followed by hexadecimal number");
376 return mon_token;
377 case '_':
378 if ((mon_token = get_dec_number(mon_number)) == T_NULL)
379 mon_error("'_' must be followed by decimal number");
380 return mon_token;
381 case '\'':
382 return mon_token = get_char_number(mon_number);
383 case '"':
384 return mon_token = get_string(mon_string);
385
386 default:
387 if (isalnum(c)) {
388 put_back(c);
389 return mon_token = get_hex_or_name(mon_number, mon_name);
390 }
391 mon_error("Unrecognized token");
392 return mon_token = T_NULL;
393 }
394 }
395
396 static enum Token get_hex_number(uintptr &i)
397 {
398 char c = get_char();
399
400 i = 0;
401 if (!isxdigit(c))
402 return T_NULL;
403
404 do {
405 c = tolower(c);
406 if (c < 'a')
407 i = (i << 4) + (c - '0');
408 else
409 i = (i << 4) + (c - 'a' + 10);
410 c = get_char();
411 } while (isxdigit(c));
412
413 if (isalnum(c))
414 return T_NULL;
415 else {
416 put_back(c);
417 return T_NUMBER;
418 }
419 }
420
421 static enum Token get_dec_number(uintptr &i)
422 {
423 char c = get_char();
424
425 i = 0;
426 if (!isdigit(c))
427 return T_NULL;
428
429 do {
430 i = (i * 10) + (c - '0');
431 c = get_char();
432 } while (isdigit(c));
433
434 if (isalnum(c))
435 return T_NULL;
436 else {
437 put_back(c);
438 return T_NUMBER;
439 }
440 }
441
442 static enum Token get_char_number(uintptr &i)
443 {
444 char c;
445
446 i = 0;
447 while ((c = get_char()) != 0) {
448 if (c == '\'')
449 return T_NUMBER;
450 i = (i << 8) + (uint8)c;
451 }
452
453 mon_error("Unterminated character constant");
454 return T_NULL;
455 }
456
457 static enum Token get_string(char *&str)
458 {
459 // Remember start of string
460 char *old_in_ptr = in_ptr;
461
462 // Determine string length
463 char c;
464 unsigned n = 0;
465 while ((c = get_char()) != 0) {
466 n++;
467 if (c == '"')
468 break;
469 }
470 if (c == 0) {
471 mon_error("Unterminated string");
472 return T_NULL;
473 }
474
475 // Allocate new buffer (n: size needed including terminating 0)
476 str = (char *)realloc(str, n);
477
478 // Copy string to buffer
479 char *p = str;
480 in_ptr = old_in_ptr;
481 while (--n)
482 *p++ = get_char();
483 *p++ = 0;
484 get_char(); // skip closing '"'
485 return T_STRING;
486 }
487
488 static enum Token get_hex_or_name(uintptr &i, char *&name)
489 {
490 // Remember start of token
491 char *old_in_ptr = in_ptr;
492
493 // Try hex number first
494 if (get_hex_number(i) == T_NUMBER)
495 return T_NUMBER;
496
497 // Not a hex number, must be a variable name; determine its length
498 in_ptr = old_in_ptr;
499 char c = get_char();
500 unsigned n = 1;
501 do {
502 n++;
503 c = get_char();
504 } while (isalnum(c));
505
506 // Allocate new buffer (n: size needed including terminating 0)
507 name = (char *)realloc(name, n);
508
509 // Copy name to buffer
510 in_ptr = old_in_ptr;
511 char *p = name;
512 while (--n)
513 *p++ = get_char();
514 *p = 0;
515 return T_NAME;
516 }
517
518
519 /*
520 * expression = eor_expr {OR eor_expr}
521 * true: OK, false: Error
522 */
523
524 bool mon_expression(uintptr *number)
525 {
526 uintptr accu, expr;
527
528 if (!eor_expr(&accu))
529 return false;
530
531 for (;;)
532 switch (mon_token) {
533 case T_OR:
534 mon_get_token();
535 if (!eor_expr(&expr))
536 return false;
537 accu |= expr;
538 break;
539
540 default:
541 *number = accu;
542 return true;
543 }
544 }
545
546
547 /*
548 * eor_expr = and_expr {EOR and_expr}
549 * true: OK, false: Error
550 */
551
552 static bool eor_expr(uintptr *number)
553 {
554 uintptr accu, expr;
555
556 if (!and_expr(&accu))
557 return false;
558
559 for (;;)
560 switch (mon_token) {
561 case T_EOR:
562 mon_get_token();
563 if (!and_expr(&expr))
564 return false;
565 accu ^= expr;
566 break;
567
568 default:
569 *number = accu;
570 return true;
571 }
572 }
573
574
575 /*
576 * and_expr = shift_expr {AND shift_expr}
577 * true: OK, false: Error
578 */
579
580 static bool and_expr(uintptr *number)
581 {
582 uintptr accu, expr;
583
584 if (!shift_expr(&accu))
585 return false;
586
587 for (;;)
588 switch (mon_token) {
589 case T_AND:
590 mon_get_token();
591 if (!shift_expr(&expr))
592 return false;
593 accu &= expr;
594 break;
595
596 default:
597 *number = accu;
598 return true;
599 }
600 }
601
602
603 /*
604 * shift_expr = add_expr {(SHIFTL | SHIFTR) add_expr}
605 * true: OK, false: Error
606 */
607
608 static bool shift_expr(uintptr *number)
609 {
610 uintptr accu, expr;
611
612 if (!add_expr(&accu))
613 return false;
614
615 for (;;)
616 switch (mon_token) {
617 case T_SHIFTL:
618 mon_get_token();
619 if (!add_expr(&expr))
620 return false;
621 accu <<= expr;
622 break;
623
624 case T_SHIFTR:
625 mon_get_token();
626 if (!add_expr(&expr))
627 return false;
628 accu >>= expr;
629 break;
630
631 default:
632 *number = accu;
633 return true;
634 }
635 }
636
637
638 /*
639 * add_expr = mul_expr {(PLUS | MINUS) mul_expr}
640 * true: OK, false: Error
641 */
642
643 static bool add_expr(uintptr *number)
644 {
645 uintptr accu, expr;
646
647 if (!mul_expr(&accu))
648 return false;
649
650 for (;;)
651 switch (mon_token) {
652 case T_PLUS:
653 mon_get_token();
654 if (!mul_expr(&expr))
655 return false;
656 accu += expr;
657 break;
658
659 case T_MINUS:
660 mon_get_token();
661 if (!mul_expr(&expr))
662 return false;
663 accu -= expr;
664 break;
665
666 default:
667 *number = accu;
668 return true;
669 }
670 }
671
672
673 /*
674 * mul_expr = factor {(MUL | DIV | MOD) factor}
675 * true: OK, false: Error
676 */
677
678 static bool mul_expr(uintptr *number)
679 {
680 uintptr accu, fact;
681
682 if (!factor(&accu))
683 return false;
684
685 for (;;)
686 switch (mon_token) {
687 case T_MUL:
688 mon_get_token();
689 if (!factor(&fact))
690 return false;
691 accu *= fact;
692 break;
693
694 case T_DIV:
695 mon_get_token();
696 if (!factor(&fact))
697 return false;
698 if (fact == 0) {
699 mon_error("Division by 0");
700 return false;
701 }
702 accu /= fact;
703 break;
704
705 case T_MOD:
706 mon_get_token();
707 if (!factor(&fact))
708 return false;
709 if (fact == 0) {
710 mon_error("Division by 0");
711 return false;
712 }
713 accu %= fact;
714 break;
715
716 default:
717 *number = accu;
718 return true;
719 }
720 }
721
722
723 /*
724 * factor = NUMBER | NAME | DOT | COLON | (PLUS | MINUS | NOT) factor | LPAREN expression RPAREN
725 * true: OK, false: Error
726 */
727
728 static bool factor(uintptr *number)
729 {
730 switch (mon_token) {
731 case T_NUMBER:
732 *number = mon_number;
733 mon_get_token();
734 return true;
735
736 case T_NAME:{
737 var_map::const_iterator v = vars.find(mon_name);
738 if (v == vars.end())
739 return false;
740 else {
741 *number = v->second;
742 mon_get_token();
743 return true;
744 }
745 }
746
747 case T_DOT:
748 *number = mon_dot_address;
749 mon_get_token();
750 return true;
751
752 case T_COLON:
753 *number = colon_value;
754 mon_get_token();
755 return true;
756
757 case T_PLUS:
758 mon_get_token();
759 return factor(number);
760
761 case T_MINUS:
762 mon_get_token();
763 if (factor(number)) {
764 *number = -*number;
765 return true;
766 } else
767 return false;
768
769 case T_NOT:
770 mon_get_token();
771 if (factor(number)) {
772 *number = ~*number;
773 return true;
774 } else
775 return false;
776
777 case T_LPAREN:
778 mon_get_token();
779 if (mon_expression(number))
780 if (mon_token == T_RPAREN) {
781 mon_get_token();
782 return true;
783 } else {
784 mon_error("Missing ')'");
785 return false;
786 }
787 else {
788 mon_error("Error in expression");
789 return false;
790 }
791
792 case T_END:
793 mon_error("Required argument missing");
794 return false;
795
796 default:
797 mon_error("'(' or number expected");
798 return false;
799 }
800 }
801
802
803 /*
804 * Set/clear/show variables
805 * set [var[=value]]
806 */
807
808 static void set_var()
809 {
810 if (mon_token == T_END) {
811
812 // Show all variables
813 if (vars.empty())
814 fprintf(monout, "No variables defined\n");
815 else {
816 var_map::const_iterator v = vars.begin(), end = vars.end();
817 for (v=vars.begin(); v!=end; ++v)
818 fprintf(monout, "%s = %08x\n", v->first.c_str(), v->second);
819 }
820
821 } else if (mon_token == T_NAME) {
822 std::string var_name = mon_name;
823 mon_get_token();
824 if (mon_token == T_ASSIGN) {
825
826 // Set variable
827 uintptr value;
828 mon_get_token();
829 if (!mon_expression(&value))
830 return;
831 if (mon_token != T_END) {
832 mon_error("Too many arguments");
833 return;
834 }
835 vars[var_name] = value;
836
837 } else if (mon_token == T_END) {
838
839 // Clear variable
840 vars.erase(var_name);
841
842 } else
843 mon_error("'=' expected");
844 } else
845 mon_error("Variable name expected");
846 }
847
848
849 /*
850 * Clear all variables
851 * cv
852 */
853
854 static void clear_vars()
855 {
856 vars.clear();
857 }
858
859
860 /*
861 * Display help
862 * h
863 */
864
865 static void help_or_hunt()
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()
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()
896 {
897 uintptr 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: %08x 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: %08x 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 uintptr 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)(uintptr adr);
945 void (*write_func)(uintptr 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 default:
960 abort();
961 break;
962 }
963
964 while (adr<=end_adr) {
965 colon_value = read_func(adr);
966 mon_dot_address = adr;
967
968 in_ptr = input;
969 while ((c = get_char()) == ' ') ;
970 while ((c = get_char()) != ' ') ;
971 while ((c = get_char()) == ' ') ;
972 put_back(c);
973 mon_get_token();
974 mon_expression(&value); // Skip start address
975 mon_expression(&value); // Skip end address
976 mon_expression(&value);
977
978 write_func(adr, value);
979 adr += size;
980 }
981
982 mon_dot_address = adr;
983 }
984
985 static void apply_byte()
986 {
987 apply(1);
988 }
989
990 static void apply_half()
991 {
992 apply(2);
993 }
994
995 static void apply_word()
996 {
997 apply(4);
998 }
999
1000
1001 /*
1002 * Execute command via system() (for ls, rm, etc.)
1003 */
1004
1005 static void mon_exec()
1006 {
1007 system(input);
1008 }
1009
1010
1011 /*
1012 * Change current directory
1013 */
1014
1015 void mon_change_dir()
1016 {
1017 in_ptr = input;
1018 char c = get_char();
1019 while (isspace(c))
1020 c = get_char();
1021 while (isgraph(c))
1022 c = get_char();
1023 while (isspace(c))
1024 c = get_char();
1025 put_back(c);
1026 if (chdir(in_ptr) != 0)
1027 mon_error("Cannot change directory");
1028 }
1029
1030
1031 /*
1032 * Initialize mon
1033 */
1034
1035 void mon_init()
1036 {
1037 cmds = NULL;
1038 num_cmds = 0;
1039 cmd_help = NULL;
1040
1041 mon_add_command("??", mon_cmd_list, "?? Show list of commands\n");
1042 mon_add_command("ver", version, "ver Show version\n");
1043 mon_add_command("?", print_expr, "? expression Calculate expression\n");
1044 mon_add_command("@", reallocate, "@ [size] Reallocate buffer\n");
1045 mon_add_command("i", ascii_dump, "i [start [end]] ASCII memory dump\n");
1046 mon_add_command("m", memory_dump, "m [start [end]] Hex/ASCII memory dump\n");
1047 mon_add_command("b", binary_dump, "b [start [end]] Binary memory dump\n");
1048 mon_add_command("d", disassemble_ppc, "d [start [end]] Disassemble PowerPC code\n");
1049 mon_add_command("d65", disassemble_6502, "d65 [start [end]] Disassemble 6502 code\n");
1050 mon_add_command("d68", disassemble_680x0, "d68 [start [end]] Disassemble 680x0 code\n");
1051 mon_add_command("d80", disassemble_z80, "d80 [start [end]] Disassemble Z80 code\n");
1052 mon_add_command("d86", disassemble_80x86_32, "d86 [start [end]] Disassemble 80x86 (32-bit) code\n");
1053 mon_add_command("d8086", disassemble_80x86_16, "d8086 [start [end]] Disassemble 80x86 (16-bit) code\n");
1054 mon_add_command("d8664", disassemble_x86_64, "d8664 [start [end]] Disassemble x86-64 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]-> ", 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 }