ba0d611cb570470817c4ad2cb10184ea683e4166
[fw/altos] / s51 / s51-parse.c
1 /*
2  * Copyright © 2008 Keith Packard <keithp@keithp.com>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
17  */
18
19 #include "s51.h"
20
21 struct command_function {
22         char                    *name;
23         char                    *alias;
24         enum command_result     (*func)(FILE *output, int argc, char **argv);
25         char                    *usage;
26         char                    *help;
27 };
28
29 static struct command_function functions[] = {
30         { "help",   "?",  command_help, "help",         "Print this list\n" },
31         { "quit",   "q",  command_quit, "[q]uit",       "Quit\n" },
32         { "di",     "di", command_di,   "di <start> <end>",
33                 "Dump imem\n" },
34         { "ds",     "ds", command_ds,   "ds <start> <end>",
35                 "Dump sprs\n" },
36         { "dx",     "dx", command_dx,   "dx <start> <end>",
37                 "Dump xaddr\n" },
38         { "set",    "t",  command_set,  "se[t] mem <prefix> <start> <end>",
39                 "Set mem {xram|rom|iram|sfr} <start> <end>\n"
40                 "set bit <addr>\n" },
41         { "dump",   "d",  command_dump, "[d]ump <prefix> <start> <end>",
42                 "Dump {xram|rom|iram|sfr} <start> <end>\n" },
43         { "pc",     "p",  command_pc, "[p]c [addr]",
44                 "Get or set pc value\n" },
45         { "break",  "b",  command_break,"[b]reak <addr>",
46                 "Set break point\n" },
47         { "clear",  "c",  command_clear,"[c]lear <addr>",
48                 "Clear break point\n" },
49         { "run",    "r",  command_run, "[r]un [start] [stop]",
50                 "Run with optional start and temp breakpoint addresses\n" },
51         { "next",   "n",  command_next, "[n]ext",
52                 "Step over one instruction, past any call\n" },
53         { "step",   "s",  command_step, "[s]tep",
54                 "Single step\n" },
55         { "load",   "l",  command_load, "[l]oad <file>",
56                 "Load a hex file into memory or flash" },
57         { "halt",   "h",  command_halt, "[h]alt",
58                 "Halt the processor\n" },
59         { "reset","res",command_reset,  "[res]et",
60                 "Reset the CPU\n" },
61 };
62
63 #define NUM_FUNCTIONS (sizeof functions / sizeof functions[0])
64
65 #ifndef FALSE
66 #define FALSE 0
67 #define TRUE 1
68 #endif
69
70 static int
71 string_to_int(char *s, int *v)
72 {
73         char *endptr;
74
75         if (isdigit(s[0]) || s[0] == '-' || s[0] == '+') {
76                 *v = strtol(s, &endptr, 0);
77                 if (endptr == s)
78                         return FALSE;
79         } else if (*s == '\'') {
80                 s++;
81                 if (*s == '\\') {
82                         s++;
83                         switch (*s) {
84                         case 'n':
85                                 *v = '\n';
86                                 break;
87                         case 't':
88                                 *v = '\t';
89                                 break;
90                         default:
91                                 *v = (int) *s;
92                                 break;
93                         }
94                 } else
95                         *v = (int) *s;
96                 s++;
97                 if (*s != '\'')
98                         return FALSE;
99         }
100         else
101                 return FALSE;
102     return TRUE;
103 }
104
105 static struct command_function *
106 command_string_to_function(char *name)
107 {
108         int i;
109         for (i = 0; i < NUM_FUNCTIONS; i++)
110                 if (!strcmp(name, functions[i].name) ||
111                     !strcmp(name, functions[i].alias))
112                         return &functions[i];
113         return NULL;
114 }    
115
116 static int
117 command_split_into_words(char *line, char **argv)
118 {
119         char quotechar;
120         int argc;
121
122         argc = 0;
123         while (*line) {
124                 while (isspace(*line))
125                         line++;
126                 if (!*line)
127                         break;
128                 if (*line == '"') {
129                         quotechar = *line++;
130                         *argv++ = line;
131                         argc++;
132                         while (*line && *line != quotechar)
133                                 line++;
134                         if (*line)
135                                 *line++ = '\0';
136                 } else {
137                         *argv++ = line;
138                         argc++;
139                         while (*line && !isspace(*line))
140                                 line++;
141                         if (*line)
142                                 *line++ = '\0';
143                 }
144         }
145         *argv = 0;
146         return argc;
147 }
148
149 enum command_result
150 command_help(FILE *output, int argc, char **argv)
151 {
152         int i;
153         struct command_function *func;
154
155         if (argc == 1) {
156                 for (i = 0; i < NUM_FUNCTIONS; i++)
157                         fprintf(output, "%-10s%s\n", functions[i].name,
158                                functions[i].usage);
159         } else {
160                 for (i = 1; i < argc; i++) {
161                         func = command_string_to_function(argv[i]);
162                         if (!func) {
163                                 fprintf(output, "%-10s unknown command\n", argv[i]);
164                                 return command_syntax;
165                         }
166                         fprintf(output, "%-10s %s\n%s", func->name,
167                                func->usage, func->help);
168                 }
169         }
170         return command_debug;
171 }
172     
173 static void
174 command_syntax_error(FILE *output, int argc, char **argv)
175 {
176         fprintf(output, "Syntax error in:");
177         while (*argv)
178                 fprintf(output, " %s", *argv++);
179         fprintf(output, "\n");
180 }
181
182 void
183 command_read (FILE *input, FILE *output)
184 {
185         int argc;
186         char line[1024];
187         char *argv[20];
188         enum command_result result;
189         struct command_function *func;
190
191         s51_dbg = ccdbg_open ();
192         if (!s51_dbg) {
193                 perror("ccdbg_open");
194                 exit(1);
195         }
196         ccdbg_debug_mode(s51_dbg);
197         fprintf(output, "Welcome to the non-simulated processor\n");
198         for (;;) {
199                 if (s51_prompt)
200                         fprintf(output, "%s", s51_prompt);
201                 else
202                         putc('\0', output);
203                 fflush(output);
204                 if (!fgets (line, sizeof line, input))
205                         break;
206                 argc = command_split_into_words(line, argv);
207                 if (argc > 0) {
208                         func = command_string_to_function(argv[0]);
209                         if (!func)
210                                 command_syntax_error(output, argc, argv);
211                         else
212                         {
213                                 result = (*func->func)(output, argc, argv);
214                                 switch (result) {
215                                 case command_syntax:
216                                         command_syntax_error(output, argc, argv);
217                                         break;
218                                 case command_error:
219                                         fprintf(output, "Error\n");
220                                         break;
221                                 case command_proceed:
222                                         break;
223                                 default:
224                                         break;
225                                 }
226                         }
227                 }
228         }
229         ccdbg_close(s51_dbg);
230         fprintf(output, "...\n");
231 }
232