ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/mon/src/mon.cpp
Revision: 1.15
Committed: 2002-01-18T16:03:33Z (22 years, 10 months ago) by cebix
Branch: MAIN
Changes since 1.14: +39 -88 lines
Log Message:
- copyright year bumped to 2002
- in MacOS mode, mon pulls in the lowmem globals as predefined variables
- mon_lowmem.h split into .h/.cpp because it's now used in two places
- variable handling code rewritten to use map<> instead of manually maintained
  linked list

File Contents

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