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