* breakpoint.c (catch_syscall_split_args): Use skip_spaces.
[deliverable/binutils-gdb.git] / gdb / mi / mi-parse.c
CommitLineData
fb40c209 1/* MI Command Set - MI parser.
349c5d5f 2
28e7fd62 3 Copyright (C) 2000-2013 Free Software Foundation, Inc.
349c5d5f 4
ab91fdd5 5 Contributed by Cygnus Solutions (a Red Hat company).
fb40c209
AC
6
7 This file is part of GDB.
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
a9762ec7 11 the Free Software Foundation; either version 3 of the License, or
fb40c209
AC
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
a9762ec7 20 along with this program. If not, see <http://www.gnu.org/licenses/>. */
fb40c209
AC
21
22#include "defs.h"
23#include "mi-cmds.h"
24#include "mi-parse.h"
f870a310 25#include "charset.h"
fb40c209
AC
26
27#include <ctype.h>
27b82ed2 28#include "gdb_string.h"
529480d0 29#include "cli/cli-utils.h"
fb40c209 30
f870a310
TT
31/* Like parse_escape, but leave the results as a host char, not a
32 target char. */
33
34static int
35mi_parse_escape (char **string_ptr)
36{
37 int c = *(*string_ptr)++;
102040f0 38
f870a310
TT
39 switch (c)
40 {
41 case '\n':
42 return -2;
43 case 0:
44 (*string_ptr)--;
45 return 0;
46
47 case '0':
48 case '1':
49 case '2':
50 case '3':
51 case '4':
52 case '5':
53 case '6':
54 case '7':
55 {
56 int i = host_hex_value (c);
57 int count = 0;
102040f0 58
f870a310
TT
59 while (++count < 3)
60 {
61 c = (**string_ptr);
62 if (isdigit (c) && c != '8' && c != '9')
63 {
64 (*string_ptr)++;
65 i *= 8;
66 i += host_hex_value (c);
67 }
68 else
69 {
70 break;
71 }
72 }
73 return i;
74 }
75
76 case 'a':
77 c = '\a';
78 break;
79 case 'b':
80 c = '\b';
81 break;
82 case 'f':
83 c = '\f';
84 break;
85 case 'n':
86 c = '\n';
87 break;
88 case 'r':
89 c = '\r';
90 break;
91 case 't':
92 c = '\t';
93 break;
94 case 'v':
95 c = '\v';
96 break;
97
98 default:
99 break;
100 }
101
102 return c;
103}
104
fb40c209
AC
105static void
106mi_parse_argv (char *args, struct mi_parse *parse)
107{
108 char *chp = args;
109 int argc = 0;
110 char **argv = xmalloc ((argc + 1) * sizeof (char *));
102040f0 111
fb40c209
AC
112 argv[argc] = NULL;
113 while (1)
114 {
115 char *arg;
102040f0 116
2b03b41d 117 /* Skip leading white space. */
529480d0 118 chp = skip_spaces (chp);
fb40c209
AC
119 /* Three possibilities: EOF, quoted string, or other text. */
120 switch (*chp)
121 {
122 case '\0':
123 parse->argv = argv;
124 parse->argc = argc;
125 return;
126 case '"':
127 {
2b03b41d 128 /* A quoted string. */
fb40c209
AC
129 int len;
130 char *start = chp + 1;
102040f0 131
2b03b41d 132 /* Determine the buffer size. */
fb40c209
AC
133 chp = start;
134 len = 0;
135 while (*chp != '\0' && *chp != '"')
136 {
137 if (*chp == '\\')
138 {
139 chp++;
f870a310 140 if (mi_parse_escape (&chp) <= 0)
fb40c209 141 {
2b03b41d 142 /* Do not allow split lines or "\000". */
fb40c209
AC
143 freeargv (argv);
144 return;
145 }
146 }
147 else
148 chp++;
149 len++;
150 }
2b03b41d 151 /* Insist on a closing quote. */
fb40c209
AC
152 if (*chp != '"')
153 {
154 freeargv (argv);
155 return;
156 }
2b03b41d 157 /* Insist on trailing white space. */
fb40c209
AC
158 if (chp[1] != '\0' && !isspace (chp[1]))
159 {
160 freeargv (argv);
161 return;
162 }
2b03b41d 163 /* Create the buffer and copy characters in. */
fb40c209 164 arg = xmalloc ((len + 1) * sizeof (char));
fb40c209
AC
165 chp = start;
166 len = 0;
167 while (*chp != '\0' && *chp != '"')
168 {
169 if (*chp == '\\')
170 {
171 chp++;
f870a310 172 arg[len] = mi_parse_escape (&chp);
fb40c209
AC
173 }
174 else
175 arg[len] = *chp++;
176 len++;
177 }
178 arg[len] = '\0';
2b03b41d 179 chp++; /* That closing quote. */
fb40c209
AC
180 break;
181 }
182 default:
183 {
2b03b41d
SS
184 /* An unquoted string. Accumulate all non-blank
185 characters into a buffer. */
fb40c209
AC
186 int len;
187 char *start = chp;
102040f0 188
fb40c209
AC
189 while (*chp != '\0' && !isspace (*chp))
190 {
191 chp++;
192 }
193 len = chp - start;
194 arg = xmalloc ((len + 1) * sizeof (char));
195 strncpy (arg, start, len);
196 arg[len] = '\0';
197 break;
198 }
199 }
2b03b41d 200 /* Append arg to argv. */
fb40c209
AC
201 argv = xrealloc (argv, (argc + 2) * sizeof (char *));
202 argv[argc++] = arg;
203 argv[argc] = NULL;
204 }
205}
206
fb40c209
AC
207void
208mi_parse_free (struct mi_parse *parse)
209{
210 if (parse == NULL)
211 return;
212 if (parse->command != NULL)
b8c9b27d 213 xfree (parse->command);
fb40c209 214 if (parse->token != NULL)
b8c9b27d 215 xfree (parse->token);
fb40c209 216 if (parse->args != NULL)
b8c9b27d 217 xfree (parse->args);
fb40c209
AC
218 if (parse->argv != NULL)
219 freeargv (parse->argv);
b8c9b27d 220 xfree (parse);
fb40c209
AC
221}
222
305aeedc
TT
223/* A cleanup that calls mi_parse_free. */
224
225static void
226mi_parse_cleanup (void *arg)
227{
228 mi_parse_free (arg);
229}
fb40c209
AC
230
231struct mi_parse *
305aeedc 232mi_parse (char *cmd, char **token)
fb40c209
AC
233{
234 char *chp;
235 struct mi_parse *parse = XMALLOC (struct mi_parse);
305aeedc 236 struct cleanup *cleanup;
102040f0 237
fb40c209 238 memset (parse, 0, sizeof (*parse));
a79b8f6e
VP
239 parse->all = 0;
240 parse->thread_group = -1;
1e92afda
VP
241 parse->thread = -1;
242 parse->frame = -1;
fb40c209 243
305aeedc
TT
244 cleanup = make_cleanup (mi_parse_cleanup, parse);
245
2b03b41d 246 /* Before starting, skip leading white space. */
529480d0 247 cmd = skip_spaces (cmd);
fb40c209 248
2b03b41d 249 /* Find/skip any token and then extract it. */
fb40c209
AC
250 for (chp = cmd; *chp >= '0' && *chp <= '9'; chp++)
251 ;
38a714bb 252 *token = xmalloc (chp - cmd + 1);
305aeedc
TT
253 memcpy (*token, cmd, (chp - cmd));
254 (*token)[chp - cmd] = '\0';
fb40c209 255
2b03b41d 256 /* This wasn't a real MI command. Return it as a CLI_COMMAND. */
fb40c209
AC
257 if (*chp != '-')
258 {
529480d0 259 chp = skip_spaces (chp);
fb40c209
AC
260 parse->command = xstrdup (chp);
261 parse->op = CLI_COMMAND;
305aeedc
TT
262
263 discard_cleanups (cleanup);
264
fb40c209
AC
265 return parse;
266 }
267
2b03b41d 268 /* Extract the command. */
fb40c209
AC
269 {
270 char *tmp = chp + 1; /* discard ``-'' */
102040f0 271
fb40c209
AC
272 for (; *chp && !isspace (*chp); chp++)
273 ;
38a714bb 274 parse->command = xmalloc (chp - tmp + 1);
fb40c209
AC
275 memcpy (parse->command, tmp, chp - tmp);
276 parse->command[chp - tmp] = '\0';
277 }
278
2b03b41d 279 /* Find the command in the MI table. */
fb40c209
AC
280 parse->cmd = mi_lookup (parse->command);
281 if (parse->cmd == NULL)
305aeedc 282 error (_("Undefined MI command: %s"), parse->command);
fb40c209 283
2b03b41d 284 /* Skip white space following the command. */
529480d0 285 chp = skip_spaces (chp);
fb40c209 286
1e92afda 287 /* Parse the --thread and --frame options, if present. At present,
2b03b41d
SS
288 some important commands, like '-break-*' are implemented by
289 forwarding to the CLI layer directly. We want to parse --thread
290 and --frame here, so as not to leave those option in the string
291 that will be passed to CLI. */
1e92afda
VP
292 for (;;)
293 {
30a7f059 294 const char *option;
a79b8f6e
VP
295 size_t as = sizeof ("--all ") - 1;
296 size_t tgs = sizeof ("--thread-group ") - 1;
1e92afda
VP
297 size_t ts = sizeof ("--thread ") - 1;
298 size_t fs = sizeof ("--frame ") - 1;
102040f0 299
a79b8f6e
VP
300 if (strncmp (chp, "--all ", as) == 0)
301 {
302 parse->all = 1;
303 chp += as;
304 }
305 /* See if --all is the last token in the input. */
306 if (strcmp (chp, "--all") == 0)
307 {
308 parse->all = 1;
309 chp += strlen (chp);
310 }
311 if (strncmp (chp, "--thread-group ", tgs) == 0)
312 {
30a7f059 313 option = "--thread-group";
a79b8f6e
VP
314 if (parse->thread_group != -1)
315 error (_("Duplicate '--thread-group' option"));
316 chp += tgs;
317 if (*chp != 'i')
318 error (_("Invalid thread group id"));
319 chp += 1;
320 parse->thread_group = strtol (chp, &chp, 10);
321 }
8e0e408a 322 else if (strncmp (chp, "--thread ", ts) == 0)
1e92afda 323 {
30a7f059 324 option = "--thread";
1e92afda 325 if (parse->thread != -1)
a79b8f6e 326 error (_("Duplicate '--thread' option"));
1e92afda
VP
327 chp += ts;
328 parse->thread = strtol (chp, &chp, 10);
329 }
330 else if (strncmp (chp, "--frame ", fs) == 0)
331 {
30a7f059 332 option = "--frame";
1e92afda 333 if (parse->frame != -1)
a79b8f6e 334 error (_("Duplicate '--frame' option"));
1e92afda
VP
335 chp += fs;
336 parse->frame = strtol (chp, &chp, 10);
337 }
338 else
339 break;
340
341 if (*chp != '\0' && !isspace (*chp))
30a7f059 342 error (_("Invalid value for the '%s' option"), option);
529480d0 343 chp = skip_spaces (chp);
1e92afda
VP
344 }
345
fb40c209 346 /* For new argv commands, attempt to return the parsed argument
2b03b41d 347 list. */
fb40c209
AC
348 if (parse->cmd->argv_func != NULL)
349 {
350 mi_parse_argv (chp, parse);
351 if (parse->argv == NULL)
305aeedc 352 error (_("Problem parsing arguments: %s %s"), parse->command, chp);
fb40c209
AC
353 }
354
355 /* FIXME: DELETE THIS */
9e22b03a 356 /* For CLI commands, also return the remainder of the
fb40c209 357 command line as a single string. */
9e22b03a
VP
358 if (parse->cmd->cli.cmd != NULL)
359 parse->args = xstrdup (chp);
fb40c209 360
305aeedc
TT
361 discard_cleanups (cleanup);
362
2b03b41d 363 /* Fully parsed, flag as an MI command. */
fb40c209
AC
364 parse->op = MI_COMMAND;
365 return parse;
366}
This page took 1.045146 seconds and 4 git commands to generate.