ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/mon/src/mon.cpp
Revision: 1.15
Committed: 2002-01-18T16:03:33Z (22 years, 10 months ago) by cebix
Branch: MAIN
Changes since 1.14: +39 -88 lines
Log Message:
- copyright year bumped to 2002
- in MacOS mode, mon pulls in the lowmem globals as predefined variables
- mon_lowmem.h split into .h/.cpp because it's now used in two places
- variable handling code rewritten to use map<> instead of manually maintained
  linked list

File Contents

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