ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/mon/src/mon.cpp
Revision: 1.8
Committed: 2000-06-10T19:07:36Z (24 years, 5 months ago) by hellwig
Branch: MAIN
Changes since 1.7: +4 -0 lines
Log Message:
- changes for SheepShaver

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