ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/mon/src/mon.cpp
Revision: 1.14
Committed: 2000-10-15T15:07:12Z (23 years, 6 months ago) by cebix
Branch: MAIN
Changes since 1.13: +5 -5 lines
Log Message:
- extended to 8080 disassembler to a Z80 disassembler
- program renamed to "cxmon"

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