ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/mon/src/mon.cpp
Revision: 1.9
Committed: 2000-06-27T14:52:44Z (24 years, 5 months ago) by cebix
Branch: MAIN
Changes since 1.8: +10 -2 lines
Log Message:
- now works on NetBSD

File Contents

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