ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/mon/src/mon.cpp
Revision: 1.8
Committed: 2000-06-10T19:07:36Z (24 years, 5 months ago) by hellwig
Branch: MAIN
Changes since 1.7: +4 -0 lines
Log Message:
- changes for SheepShaver

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