ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/mon/src/mon.cpp
Revision: 1.4
Committed: 1999-10-05T18:19:55Z (25 years, 2 months ago) by cebix
Branch: MAIN
Changes since 1.3: +9 -0 lines
Log Message:
- should now compile on systems without libreadline

File Contents

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