ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/mon/src/mon.cpp
Revision: 1.1
Committed: 1999-10-04T19:31:09Z (25 years, 2 months ago) by cebix
Branch: MAIN
Branch point for: cebix
Log Message:
Initial revision

File Contents

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