ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/mon/src/mon.cpp
Revision: 1.4
Committed: 1999-10-05T18:19:55Z (25 years, 2 months ago) by cebix
Branch: MAIN
Changes since 1.3: +9 -0 lines
Log Message:
- should now compile on systems without libreadline

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