ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/mon/src/mon.cpp
Revision: 1.3
Committed: 1999-10-05T14:43:41Z (24 years, 7 months ago) by cebix
Branch: MAIN
Changes since 1.2: +7 -4 lines
Log Message:
- fixed some compiler warnings
- sorted mon_atraps.h

File Contents

# User Rev Content
1 cebix 1.1 /*
2 cebix 1.2 * mon.cpp - mon main program
3 cebix 1.1 *
4 cebix 1.2 * 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 cebix 1.1 */
20    
21 cebix 1.2 #include "sysdeps.h"
22    
23     #ifdef HAVE_READLINE_READLINE_H
24     extern "C" {
25     #include <readline/readline.h>
26     }
27     #endif
28 cebix 1.1
29 cebix 1.2 #ifdef HAVE_READLINE_HISTORY_H
30 cebix 1.1 extern "C" {
31 cebix 1.2 #include <readline/history.h>
32 cebix 1.1 }
33 cebix 1.2 #endif
34 cebix 1.1
35     #include "mon.h"
36     #include "mon_cmd.h"
37 cebix 1.2 #include "version.h"
38 cebix 1.1
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 cebix 1.3 fprintf(monout, "%s = %08x\n", v->name, v->value);
827 cebix 1.1
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 cebix 1.3 fprintf(monerr, "Buffer size: %08x bytes\n", mon_mem_size);
920 cebix 1.1 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 cebix 1.3 fprintf(monerr, "Buffer size: %08x bytes\n", mon_mem_size = size);
932 cebix 1.1 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 cebix 1.3 default:
974     abort();
975     break;
976 cebix 1.1 }
977    
978     while (adr<=end_adr) {
979     colon_value = read_func(adr);
980     mon_dot_address = adr;
981    
982     in_ptr = input;
983     while ((c = get_char()) == ' ') ;
984     while ((c = get_char()) != ' ') ;
985     while ((c = get_char()) == ' ') ;
986     put_back(c);
987     mon_get_token();
988     mon_expression(&value); // Skip start address
989     mon_expression(&value); // Skip end address
990     mon_expression(&value);
991    
992     write_func(adr, value);
993     adr += size;
994     }
995    
996     mon_dot_address = adr;
997     }
998    
999     static void apply_byte(void)
1000     {
1001     apply(1);
1002     }
1003    
1004     static void apply_half(void)
1005     {
1006     apply(2);
1007     }
1008    
1009     static void apply_word(void)
1010     {
1011     apply(4);
1012     }
1013    
1014    
1015     /*
1016     * Execute command via system() (for ls, rm, etc.)
1017     */
1018    
1019     static void mon_exec(void)
1020     {
1021     system(input);
1022     }
1023    
1024    
1025     /*
1026     * Change current directory
1027     */
1028    
1029     static void mon_change_dir(void)
1030     {
1031     char c;
1032     in_ptr = input;
1033     while ((c = get_char()) == ' ') ;
1034     while ((c = get_char()) != ' ') ;
1035     while ((c = get_char()) == ' ') ;
1036     put_back(c);
1037     if (chdir(in_ptr) != 0)
1038     mon_error("Cannot change directory");
1039     }
1040    
1041    
1042     /*
1043     * Initialize mon
1044     */
1045    
1046     void mon_init(void)
1047     {
1048     cmds = NULL;
1049     num_cmds = 0;
1050     cmd_help = NULL;
1051    
1052     mon_add_command("??", mon_cmd_list, "?? Show list of commands\n");
1053     mon_add_command("ver", version, "ver Show version\n");
1054     mon_add_command("?", print_expr, "? expression Calculate expression\n");
1055     mon_add_command("@", reallocate, "@ [size] Reallocate buffer\n");
1056     mon_add_command("i", ascii_dump, "i [start [end]] ASCII memory dump\n");
1057     mon_add_command("m", memory_dump, "m [start [end]] Hex/ASCII memory dump\n");
1058     mon_add_command("d", disassemble_ppc, "d [start [end]] Disassemble PowerPC code\n");
1059     mon_add_command("d65", disassemble_6502, "d65 [start [end]] Disassemble 6502 code\n");
1060     mon_add_command("d68", disassemble_680x0, "d68 [start [end]] Disassemble 680x0 code\n");
1061     mon_add_command("d80", disassemble_8080, "d80 [start [end]] Disassemble 8080 code\n");
1062     mon_add_command("d86", disassemble_80x86, "d86 [start [end]] Disassemble 80x86 code\n");
1063     mon_add_command(":", modify, ": start string Modify memory\n");
1064     mon_add_command("f", fill, "f start end string Fill memory\n");
1065     mon_add_command("y", apply_byte, "y[b|h|w] start end expr Apply expression to memory\n");
1066     mon_add_command("yb", apply_byte, NULL);
1067     mon_add_command("yh", apply_half, NULL);
1068     mon_add_command("yw", apply_word, NULL);
1069     mon_add_command("t", transfer, "t start end dest Transfer memory\n");
1070     mon_add_command("c", compare, "c start end dest Compare memory\n");
1071     mon_add_command("h", help_or_hunt, "h start end string Search for byte string\n");
1072     mon_add_command("\\", shell_command, "\\ \"command\" Execute shell command\n");
1073     mon_add_command("ls", mon_exec, "ls [args] List directory contents\n");
1074     mon_add_command("rm", mon_exec, "rm [args] Remove file(s)\n");
1075     mon_add_command("cp", mon_exec, "cp [args] Copy file(s)\n");
1076     mon_add_command("mv", mon_exec, "mv [args] Move file(s)\n");
1077     mon_add_command("cd", mon_change_dir, "cd directory Change current directory\n");
1078     mon_add_command("o", redir_output, "o [\"file\"] Redirect output\n");
1079     mon_add_command("[", load_data, "[ start \"file\" Load data from file\n");
1080     mon_add_command("]", save_data, "] start size \"file\" Save data to file\n");
1081     mon_add_command("set", set_var, "set [var[=value]] Set/clear/show variables\n");
1082     mon_add_command("cv", clear_vars, "cv Clear all variables\n");
1083     }
1084    
1085    
1086     /*
1087     * Deinitialize mon
1088     */
1089    
1090     void mon_exit(void)
1091     {
1092     free(cmds);
1093     cmds = NULL;
1094     num_cmds = 0;
1095     cmd_help = NULL;
1096     }
1097    
1098    
1099     /*
1100     * Main function, read-execute loop
1101     */
1102    
1103     void mon(int argc, char **argv)
1104     {
1105     bool done = false, interactive = true;
1106     char c, cmd[INPUT_LENGTH];
1107    
1108     // Setup input/output streams
1109     monin = stdin;
1110     monout = stdout;
1111     monerr = stdout;
1112    
1113     if (argc) {
1114     // Access real memory if mon was started as "rmon"
1115     char *prgname = argv[0];
1116     char *lastslash;
1117     if ((lastslash = strrchr(prgname, '/')) != NULL)
1118     prgname = lastslash + 1;
1119     if (strcmp(prgname, "rmon") == 0)
1120     mon_use_real_mem = true;
1121    
1122     // Make argc/argv point to the actual arguments
1123     argc--;
1124     argv++;
1125     interactive = (argc == 0);
1126     }
1127    
1128     // Allocate buffer
1129     if (!mon_use_real_mem) {
1130     mon_mem_size = 0x100000;
1131     mem = (uint8 *)malloc(mon_mem_size);
1132    
1133     // Print banner
1134     if (interactive)
1135 cebix 1.2 fprintf(monerr, "\n *** mon V%d.%d by Christian Bauer and Marc Hellwig ***\n"
1136     " *** Press 'h' for help ***\n\n", VERSION_MAJOR, VERSION_MINOR);
1137 cebix 1.1 }
1138    
1139     init_abort();
1140    
1141     // Read and parse command line
1142     while (!done) {
1143     if (interactive) {
1144     char prompt[16];
1145 cebix 1.3 sprintf(prompt, "[%08x]-> ", mon_dot_address);
1146 cebix 1.1 read_line(prompt);
1147     } else {
1148     if (argc == 0) {
1149     done = true;
1150     break;
1151     } else {
1152     strncpy(in_ptr = input, argv[0], INPUT_LENGTH);
1153     argc--;
1154     argv++;
1155     }
1156     }
1157    
1158     // Skip leading spaces
1159     while ((c = get_char()) == ' ') ;
1160    
1161     // Read command word
1162     char *p = cmd;
1163     do {
1164     *p++ = c;
1165     c = get_char();
1166     } while (isgraph(c));
1167     *p = 0;
1168     put_back(c);
1169    
1170     // Execute command
1171     if (cmd[0] == 0) // Blank line
1172     continue;
1173     if (strcmp(cmd, "x") == 0) { // Exit
1174     done = true;
1175     continue;
1176     }
1177     for (int i=0; i<num_cmds; i++) {
1178     if (strcmp(cmd, cmds[i].name) == 0) {
1179     mon_get_token();
1180     cmds[i].func();
1181     goto cmd_done;
1182     }
1183     }
1184     mon_error("Unknown command");
1185     cmd_done: ;
1186     }
1187    
1188     exit_abort();
1189    
1190     // Free buffer
1191     if (!mon_use_real_mem)
1192     free(mem);
1193    
1194     // Close output file if redirected
1195     if (monout != monerr)
1196     fclose(monout);
1197     }