Make serial test simpler
[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 static struct command_function functions[] = {
22         { "help",   "?",  command_help, "help",         "Print this list\n" },
23         { "quit",   "q",  command_quit, "[q]uit",       "Quit\n" },
24         { "di",     "di", command_di,   "di <start> <end>",
25                 "Dump imem\n" },
26         { "ds",     "ds", command_ds,   "ds <start> <end>",
27                 "Dump sprs\n" },
28         { "dx",     "dx", command_dx,   "dx <start> <end>",
29                 "Dump xaddr\n" },
30         { "set",    "t",  command_set,  "se[t] mem <prefix> <address> <data> ...",
31                 "Set mem {xram|rom|iram|sfr}\n"
32                 "set bit <addr>\n" },
33         { "dump",   "d",  command_dump, "[d]ump <prefix> <start> <end>",
34                 "Dump {xram|rom|iram|sfr} <start> <end>\n" },
35         { "file", "file", command_file, "file <filename>",
36                 "Pretend to load executable from <filename>\n" },
37         { "pc",     "p",  command_pc, "[p]c [addr]",
38                 "Get or set pc value\n" },
39         { "break",  "b",  command_break,"[b]reak <addr>",
40                 "Set break point\n" },
41         { "clear",  "c",  command_clear,"[c]lear <addr>",
42                 "Clear break point\n" },
43         { "run",    "r",  command_run, "[r]un [start] [stop]",
44                 "Run with optional start and temp breakpoint addresses\n" },
45         { "go",     "g",  command_run, "[g]o [start] [stop]",
46                 "Run with optional start and temp breakpoint addresses\n" },
47         { "next",   "n",  command_next, "[n]ext",
48                 "Step over one instruction, past any call\n" },
49         { "step",   "s",  command_step, "[s]tep",
50                 "Single step\n" },
51         { "load",   "l",  command_load, "[l]oad <file>",
52                 "Load a hex file into memory or flash" },
53         { "halt",   "h",  command_halt, "[h]alt",
54                 "Halt the processor\n" },
55         { "reset","res",command_reset,  "[res]et",
56                 "Reset the CPU\n" },
57         { "status","status",command_status, "status",
58                 "Display CC1111 debug status\n" },
59         { "info",   "i",  command_info, "[i]info",
60                 "Get information\n" },
61         { "stop",  "stop", command_stop, "stop",
62                 "Ignored\n" },
63         { NULL, NULL, NULL, NULL, NULL },
64 };
65
66 #ifndef FALSE
67 #define FALSE 0
68 #define TRUE 1
69 #endif
70
71 static int
72 string_to_int(char *s, int *v)
73 {
74         char *endptr;
75
76         if (isdigit(s[0]) || s[0] == '-' || s[0] == '+') {
77                 *v = strtol(s, &endptr, 0);
78                 if (endptr == s)
79                         return FALSE;
80         } else if (*s == '\'') {
81                 s++;
82                 if (*s == '\\') {
83                         s++;
84                         switch (*s) {
85                         case 'n':
86                                 *v = '\n';
87                                 break;
88                         case 't':
89                                 *v = '\t';
90                                 break;
91                         default:
92                                 *v = (int) *s;
93                                 break;
94                         }
95                 } else
96                         *v = (int) *s;
97                 s++;
98                 if (*s != '\'')
99                         return FALSE;
100         }
101         else
102                 return FALSE;
103     return TRUE;
104 }
105
106 struct command_function *
107 command_string_to_function(struct command_function *functions, char *name)
108 {
109         int i;
110         for (i = 0; functions[i].name; i++)
111                 if (!strcmp(name, functions[i].name) ||
112                     !strcmp(name, functions[i].alias))
113                         return &functions[i];
114         return NULL;
115 }    
116
117 enum command_result
118 command_function_help(struct command_function *functions, int argc, char **argv)
119 {
120         int i;
121         struct command_function *func;
122
123         if (argc == 1) {
124                 for (i = 0; functions[i].name; i++)
125                         s51_printf("%-10s%s\n", functions[i].name,
126                                functions[i].usage);
127         } else {
128                 for (i = 1; i < argc; i++) {
129                         func = command_string_to_function(functions, argv[i]);
130                         if (!func) {
131                                 s51_printf("%-10s unknown command\n", argv[i]);
132                                 return command_syntax;
133                         }
134                         s51_printf("%-10s %s\n%s", func->name,
135                                func->usage, func->help);
136                 }
137         }
138         return command_debug;
139 }
140
141 static int
142 command_split_into_words(char *line, char **argv)
143 {
144         char quotechar;
145         int argc;
146
147         argc = 0;
148         while (*line) {
149                 while (isspace(*line))
150                         line++;
151                 if (!*line)
152                         break;
153                 if (*line == '"') {
154                         quotechar = *line++;
155                         *argv++ = line;
156                         argc++;
157                         while (*line && *line != quotechar)
158                                 line++;
159                         if (*line)
160                                 *line++ = '\0';
161                 } else {
162                         *argv++ = line;
163                         argc++;
164                         while (*line && !isspace(*line))
165                                 line++;
166                         if (*line)
167                                 *line++ = '\0';
168                 }
169         }
170         *argv = 0;
171         return argc;
172 }
173
174 enum command_result
175 command_help(int argc, char **argv)
176 {
177         return command_function_help(functions, argc, argv);
178 }
179     
180 void
181 command_syntax_error(int argc, char **argv)
182 {
183         s51_printf("Syntax error in:");
184         while (*argv)
185                 s51_printf(" %s", *argv++);
186         s51_printf("\n");
187 }
188
189 void
190 command_read (void)
191 {
192         int argc;
193         char line[1024];
194         char *argv[20];
195         enum command_result result;
196         struct command_function *func;
197
198         s51_dbg = ccdbg_open ();
199         if (!s51_dbg) {
200                 perror("ccdbg_open");
201                 exit(1);
202         }
203         ccdbg_debug_mode(s51_dbg);
204         ccdbg_halt(s51_dbg);
205         s51_printf("Welcome to the non-simulated processor\n");
206         for (;;) {
207                 if (s51_read_line (line, sizeof line) == 0)
208                         break;
209                 s51_interrupted = 0;
210                 argc = command_split_into_words(line, argv);
211                 if (argc > 0) {
212                         func = command_string_to_function(functions, argv[0]);
213                         if (!func)
214                                 command_syntax_error(argc, argv);
215                         else
216                         {
217                                 result = (*func->func)(argc, argv);
218                                 if (s51_interrupted)
219                                         result = command_interrupt;
220                                 switch (result) {
221                                 case command_syntax:
222                                         command_syntax_error(argc, argv);
223                                         break;
224                                 case command_error:
225                                         s51_printf("Error\n");
226                                         break;
227                                 case command_success:
228                                         break;
229                                 case command_interrupt:
230                                         ccdbg_halt(s51_dbg);
231                                         s51_printf("Interrupted\n");
232                                         break;
233                                 default:
234                                         break;
235                                 }
236                         }
237                 }
238         }
239         ccdbg_close(s51_dbg);
240         s51_printf("...\n");
241 }
242