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

File Contents

# 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     fprintf(monout, "%s = %08lx\n", v->name, v->value);
827    
828     } else if (mon_token == T_NAME) {
829     char var_name[256];
830     strcpy(var_name, mon_name);
831     mon_get_token();
832     if (mon_token == T_ASSIGN) {
833    
834     // Set variable
835     uint32 value;
836     mon_get_token();
837     if (!mon_expression(&value))
838     return;
839     if (mon_token != T_END) {
840     mon_error("Too many arguments");
841     return;
842     }
843     insert_var(var_name)->value = value;
844    
845     } else if (mon_token == T_END) {
846    
847     // Clear variable
848     remove_var(var_name);
849    
850     } else
851     mon_error("'=' expected");
852     } else
853     mon_error("Variable name expected");
854     }
855    
856    
857     /*
858     * Clear all variables
859     * cv
860     */
861    
862     static void clear_vars(void)
863     {
864     Variable *var, *next;
865     for (var=first_var; var; var=next) {
866     free(var->name);
867     next = var->next;
868     free(var);
869     }
870     first_var = NULL;
871     }
872    
873    
874     /*
875     * Display help
876     * h
877     */
878    
879     static void help_or_hunt(void)
880     {
881     if (mon_token != T_END) {
882     hunt();
883     return;
884     }
885     fprintf(monout, "x Quit mon\n"
886     "h This help text\n");
887     fprintf(monout, cmd_help);
888     }
889    
890    
891     /*
892     * Display command list
893     * ??
894     */
895    
896     static void mon_cmd_list(void)
897     {
898     for (int i=0; i<num_cmds; i++)
899     fprintf(monout, "%s ", cmds[i].name);
900     fprintf(monout, "\n");
901     }
902    
903    
904     /*
905     * Reallocate buffer
906     * @ [size]
907     */
908    
909     static void reallocate(void)
910     {
911     uint32 size;
912    
913     if (mon_use_real_mem) {
914     fprintf(monerr, "Cannot reallocate buffer in real mode\n");
915     return;
916     }
917    
918     if (mon_token == T_END) {
919     fprintf(monerr, "Buffer size: %08lx bytes\n", mon_mem_size);
920     return;
921     }
922    
923     if (!mon_expression(&size))
924     return;
925     if (mon_token != T_END) {
926     mon_error("Too many arguments");
927     return;
928     }
929    
930     if ((mem = (uint8 *)realloc(mem, size)) != NULL)
931     fprintf(monerr, "Buffer size: %08lx bytes\n", mon_mem_size = size);
932     else
933     fprintf(monerr, "Unable to reallocate buffer\n");
934     }
935    
936    
937     /*
938     * Apply expression to memory
939     * y[b|h|w] start end expression
940     */
941    
942     static void apply(int size)
943     {
944     uint32 adr, end_adr, value;
945     char c;
946    
947     if (!mon_expression(&adr))
948     return;
949     if (!mon_expression(&end_adr))
950     return;
951     if (!mon_expression(&value))
952     return;
953     if (mon_token != T_END) {
954     mon_error("Too many arguments");
955     return;
956     }
957    
958     uint32 (*read_func)(uint32 adr);
959     void (*write_func)(uint32 adr, uint32 val);
960     switch (size) {
961     case 1:
962     read_func = mon_read_byte;
963     write_func = mon_write_byte;
964     break;
965     case 2:
966     read_func = mon_read_half;
967     write_func = mon_write_half;
968     break;
969     case 4:
970     read_func = mon_read_word;
971     write_func = mon_write_word;
972     break;
973     }
974    
975     while (adr<=end_adr) {
976     colon_value = read_func(adr);
977     mon_dot_address = adr;
978    
979     in_ptr = input;
980     while ((c = get_char()) == ' ') ;
981     while ((c = get_char()) != ' ') ;
982     while ((c = get_char()) == ' ') ;
983     put_back(c);
984     mon_get_token();
985     mon_expression(&value); // Skip start address
986     mon_expression(&value); // Skip end address
987     mon_expression(&value);
988    
989     write_func(adr, value);
990     adr += size;
991     }
992    
993     mon_dot_address = adr;
994     }
995    
996     static void apply_byte(void)
997     {
998     apply(1);
999     }
1000    
1001     static void apply_half(void)
1002     {
1003     apply(2);
1004     }
1005    
1006     static void apply_word(void)
1007     {
1008     apply(4);
1009     }
1010    
1011    
1012     /*
1013     * Execute command via system() (for ls, rm, etc.)
1014     */
1015    
1016     static void mon_exec(void)
1017     {
1018     system(input);
1019     }
1020    
1021    
1022     /*
1023     * Change current directory
1024     */
1025    
1026     static void mon_change_dir(void)
1027     {
1028     char c;
1029     in_ptr = input;
1030     while ((c = get_char()) == ' ') ;
1031     while ((c = get_char()) != ' ') ;
1032     while ((c = get_char()) == ' ') ;
1033     put_back(c);
1034     if (chdir(in_ptr) != 0)
1035     mon_error("Cannot change directory");
1036     }
1037    
1038    
1039     /*
1040     * Initialize mon
1041     */
1042    
1043     void mon_init(void)
1044     {
1045     cmds = NULL;
1046     num_cmds = 0;
1047     cmd_help = NULL;
1048    
1049     mon_add_command("??", mon_cmd_list, "?? Show list of commands\n");
1050     mon_add_command("ver", version, "ver Show version\n");
1051     mon_add_command("?", print_expr, "? expression Calculate expression\n");
1052     mon_add_command("@", reallocate, "@ [size] Reallocate buffer\n");
1053     mon_add_command("i", ascii_dump, "i [start [end]] ASCII memory dump\n");
1054     mon_add_command("m", memory_dump, "m [start [end]] Hex/ASCII memory dump\n");
1055     mon_add_command("d", disassemble_ppc, "d [start [end]] Disassemble PowerPC code\n");
1056     mon_add_command("d65", disassemble_6502, "d65 [start [end]] Disassemble 6502 code\n");
1057     mon_add_command("d68", disassemble_680x0, "d68 [start [end]] Disassemble 680x0 code\n");
1058     mon_add_command("d80", disassemble_8080, "d80 [start [end]] Disassemble 8080 code\n");
1059     mon_add_command("d86", disassemble_80x86, "d86 [start [end]] Disassemble 80x86 code\n");
1060     mon_add_command(":", modify, ": start string Modify memory\n");
1061     mon_add_command("f", fill, "f start end string Fill memory\n");
1062     mon_add_command("y", apply_byte, "y[b|h|w] start end expr Apply expression to memory\n");
1063     mon_add_command("yb", apply_byte, NULL);
1064     mon_add_command("yh", apply_half, NULL);
1065     mon_add_command("yw", apply_word, NULL);
1066     mon_add_command("t", transfer, "t start end dest Transfer memory\n");
1067     mon_add_command("c", compare, "c start end dest Compare memory\n");
1068     mon_add_command("h", help_or_hunt, "h start end string Search for byte string\n");
1069     mon_add_command("\\", shell_command, "\\ \"command\" Execute shell command\n");
1070     mon_add_command("ls", mon_exec, "ls [args] List directory contents\n");
1071     mon_add_command("rm", mon_exec, "rm [args] Remove file(s)\n");
1072     mon_add_command("cp", mon_exec, "cp [args] Copy file(s)\n");
1073     mon_add_command("mv", mon_exec, "mv [args] Move file(s)\n");
1074     mon_add_command("cd", mon_change_dir, "cd directory Change current directory\n");
1075     mon_add_command("o", redir_output, "o [\"file\"] Redirect output\n");
1076     mon_add_command("[", load_data, "[ start \"file\" Load data from file\n");
1077     mon_add_command("]", save_data, "] start size \"file\" Save data to file\n");
1078     mon_add_command("set", set_var, "set [var[=value]] Set/clear/show variables\n");
1079     mon_add_command("cv", clear_vars, "cv Clear all variables\n");
1080     }
1081    
1082    
1083     /*
1084     * Deinitialize mon
1085     */
1086    
1087     void mon_exit(void)
1088     {
1089     free(cmds);
1090     cmds = NULL;
1091     num_cmds = 0;
1092     cmd_help = NULL;
1093     }
1094    
1095    
1096     /*
1097     * Main function, read-execute loop
1098     */
1099    
1100     void mon(int argc, char **argv)
1101     {
1102     bool done = false, interactive = true;
1103     char c, cmd[INPUT_LENGTH];
1104    
1105     // Setup input/output streams
1106     monin = stdin;
1107     monout = stdout;
1108     monerr = stdout;
1109    
1110     if (argc) {
1111     // Access real memory if mon was started as "rmon"
1112     char *prgname = argv[0];
1113     char *lastslash;
1114     if ((lastslash = strrchr(prgname, '/')) != NULL)
1115     prgname = lastslash + 1;
1116     if (strcmp(prgname, "rmon") == 0)
1117     mon_use_real_mem = true;
1118    
1119     // Make argc/argv point to the actual arguments
1120     argc--;
1121     argv++;
1122     interactive = (argc == 0);
1123     }
1124    
1125     // Allocate buffer
1126     if (!mon_use_real_mem) {
1127     mon_mem_size = 0x100000;
1128     mem = (uint8 *)malloc(mon_mem_size);
1129    
1130     // Print banner
1131     if (interactive)
1132 cebix 1.2 fprintf(monerr, "\n *** mon V%d.%d by Christian Bauer and Marc Hellwig ***\n"
1133     " *** Press 'h' for help ***\n\n", VERSION_MAJOR, VERSION_MINOR);
1134 cebix 1.1 }
1135    
1136     init_abort();
1137    
1138     // Read and parse command line
1139     while (!done) {
1140     if (interactive) {
1141     char prompt[16];
1142     sprintf(prompt, "[%08lx]-> ", mon_dot_address);
1143     read_line(prompt);
1144     } else {
1145     if (argc == 0) {
1146     done = true;
1147     break;
1148     } else {
1149     strncpy(in_ptr = input, argv[0], INPUT_LENGTH);
1150     argc--;
1151     argv++;
1152     }
1153     }
1154    
1155     // Skip leading spaces
1156     while ((c = get_char()) == ' ') ;
1157    
1158     // Read command word
1159     char *p = cmd;
1160     do {
1161     *p++ = c;
1162     c = get_char();
1163     } while (isgraph(c));
1164     *p = 0;
1165     put_back(c);
1166    
1167     // Execute command
1168     if (cmd[0] == 0) // Blank line
1169     continue;
1170     if (strcmp(cmd, "x") == 0) { // Exit
1171     done = true;
1172     continue;
1173     }
1174     for (int i=0; i<num_cmds; i++) {
1175     if (strcmp(cmd, cmds[i].name) == 0) {
1176     mon_get_token();
1177     cmds[i].func();
1178     goto cmd_done;
1179     }
1180     }
1181     mon_error("Unknown command");
1182     cmd_done: ;
1183     }
1184    
1185     exit_abort();
1186    
1187     // Free buffer
1188     if (!mon_use_real_mem)
1189     free(mem);
1190    
1191     // Close output file if redirected
1192     if (monout != monerr)
1193     fclose(monout);
1194     }