ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/mon/src/mon.cpp
Revision: 1.7
Committed: 2000-04-24T13:20:40Z (24 years, 7 months ago) by cebix
Branch: MAIN
Changes since 1.6: +1 -1 lines
Log Message:
- banned formatted properly

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