Add more commands to s51 assembly-language debugger
[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         { "status","status",command_status, "status",
62                 "Display CC1111 debug status\n" },
63 };
64
65 #define NUM_FUNCTIONS (sizeof functions / sizeof functions[0])
66
67 #ifndef FALSE
68 #define FALSE 0
69 #define TRUE 1
70 #endif
71
72 static int
73 string_to_int(char *s, int *v)
74 {
75         char *endptr;
76
77         if (isdigit(s[0]) || s[0] == '-' || s[0] == '+') {
78                 *v = strtol(s, &endptr, 0);
79                 if (endptr == s)
80                         return FALSE;
81         } else if (*s == '\'') {
82                 s++;
83                 if (*s == '\\') {
84                         s++;
85                         switch (*s) {
86                         case 'n':
87                                 *v = '\n';
88                                 break;
89                         case 't':
90                                 *v = '\t';
91                                 break;
92                         default:
93                                 *v = (int) *s;
94                                 break;
95                         }
96                 } else
97                         *v = (int) *s;
98                 s++;
99                 if (*s != '\'')
100                         return FALSE;
101         }
102         else
103                 return FALSE;
104     return TRUE;
105 }
106
107 static struct command_function *
108 command_string_to_function(char *name)
109 {
110         int i;
111         for (i = 0; i < NUM_FUNCTIONS; i++)
112                 if (!strcmp(name, functions[i].name) ||
113                     !strcmp(name, functions[i].alias))
114                         return &functions[i];
115         return NULL;
116 }    
117
118 static int
119 command_split_into_words(char *line, char **argv)
120 {
121         char quotechar;
122         int argc;
123
124         argc = 0;
125         while (*line) {
126                 while (isspace(*line))
127                         line++;
128                 if (!*line)
129                         break;
130                 if (*line == '"') {
131                         quotechar = *line++;
132                         *argv++ = line;
133                         argc++;
134                         while (*line && *line != quotechar)
135                                 line++;
136                         if (*line)
137                                 *line++ = '\0';
138                 } else {
139                         *argv++ = line;
140                         argc++;
141                         while (*line && !isspace(*line))
142                                 line++;
143                         if (*line)
144                                 *line++ = '\0';
145                 }
146         }
147         *argv = 0;
148         return argc;
149 }
150
151 enum command_result
152 command_help(FILE *output, int argc, char **argv)
153 {
154         int i;
155         struct command_function *func;
156
157         if (argc == 1) {
158                 for (i = 0; i < NUM_FUNCTIONS; i++)
159                         fprintf(output, "%-10s%s\n", functions[i].name,
160                                functions[i].usage);
161         } else {
162                 for (i = 1; i < argc; i++) {
163                         func = command_string_to_function(argv[i]);
164                         if (!func) {
165                                 fprintf(output, "%-10s unknown command\n", argv[i]);
166                                 return command_syntax;
167                         }
168                         fprintf(output, "%-10s %s\n%s", func->name,
169                                func->usage, func->help);
170                 }
171         }
172         return command_debug;
173 }
174     
175 static void
176 command_syntax_error(FILE *output, int argc, char **argv)
177 {
178         fprintf(output, "Syntax error in:");
179         while (*argv)
180                 fprintf(output, " %s", *argv++);
181         fprintf(output, "\n");
182 }
183
184 void
185 command_read (FILE *input, FILE *output)
186 {
187         int argc;
188         char line[1024];
189         char *argv[20];
190         enum command_result result;
191         struct command_function *func;
192
193         s51_dbg = ccdbg_open ();
194         if (!s51_dbg) {
195                 perror("ccdbg_open");
196                 exit(1);
197         }
198         ccdbg_debug_mode(s51_dbg);
199         fprintf(output, "Welcome to the non-simulated processor\n");
200         for (;;) {
201                 if (s51_prompt)
202                         fprintf(output, "%s", s51_prompt);
203                 else
204                         putc('\0', output);
205                 fflush(output);
206                 if (!fgets (line, sizeof line, input))
207                         break;
208                 argc = command_split_into_words(line, argv);
209                 if (argc > 0) {
210                         func = command_string_to_function(argv[0]);
211                         if (!func)
212                                 command_syntax_error(output, argc, argv);
213                         else
214                         {
215                                 result = (*func->func)(output, argc, argv);
216                                 switch (result) {
217                                 case command_syntax:
218                                         command_syntax_error(output, argc, argv);
219                                         break;
220                                 case command_error:
221                                         fprintf(output, "Error\n");
222                                         break;
223                                 case command_proceed:
224                                         break;
225                                 default:
226                                         break;
227                                 }
228                         }
229                 }
230         }
231         ccdbg_close(s51_dbg);
232         fprintf(output, "...\n");
233 }
234