ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/mon/src/mon.cpp
Revision: 1.2
Committed: 1999-10-04T21:16:02Z (25 years, 2 months ago) by cebix
Branch: MAIN
Changes since 1.1: +29 -15 lines
Log Message:
- GPL'ified sources
- added provisions for autoconf stuff

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