ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/mon/src/mon.cpp
Revision: 1.7
Committed: 2000-04-24T13:20:40Z (24 years, 7 months ago) by cebix
Branch: MAIN
Changes since 1.6: +1 -1 lines
Log Message:
- banned formatted properly

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