Implement =thread-selected notification.
[deliverable/binutils-gdb.git] / gdb / mi / mi-parse.c
CommitLineData
fb40c209 1/* MI Command Set - MI parser.
349c5d5f 2
9b254dd1 3 Copyright (C) 2000, 2001, 2002, 2007, 2008 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"
25
26#include <ctype.h>
27b82ed2 27#include "gdb_string.h"
fb40c209 28
fb40c209
AC
29static void
30mi_parse_argv (char *args, struct mi_parse *parse)
31{
32 char *chp = args;
33 int argc = 0;
34 char **argv = xmalloc ((argc + 1) * sizeof (char *));
35 argv[argc] = NULL;
36 while (1)
37 {
38 char *arg;
39 /* skip leading white space */
40 while (isspace (*chp))
41 chp++;
42 /* Three possibilities: EOF, quoted string, or other text. */
43 switch (*chp)
44 {
45 case '\0':
46 parse->argv = argv;
47 parse->argc = argc;
48 return;
49 case '"':
50 {
51 /* A quoted string. */
52 int len;
53 char *start = chp + 1;
54 /* Determine the buffer size. */
55 chp = start;
56 len = 0;
57 while (*chp != '\0' && *chp != '"')
58 {
59 if (*chp == '\\')
60 {
61 chp++;
62 if (parse_escape (&chp) <= 0)
63 {
64 /* Do not allow split lines or "\000" */
65 freeargv (argv);
66 return;
67 }
68 }
69 else
70 chp++;
71 len++;
72 }
73 /* Insist on a closing quote. */
74 if (*chp != '"')
75 {
76 freeargv (argv);
77 return;
78 }
79 /* Insist on trailing white space. */
80 if (chp[1] != '\0' && !isspace (chp[1]))
81 {
82 freeargv (argv);
83 return;
84 }
85 /* create the buffer. */
86 arg = xmalloc ((len + 1) * sizeof (char));
87 /* And copy the characters in. */
88 chp = start;
89 len = 0;
90 while (*chp != '\0' && *chp != '"')
91 {
92 if (*chp == '\\')
93 {
94 chp++;
95 arg[len] = parse_escape (&chp);
96 }
97 else
98 arg[len] = *chp++;
99 len++;
100 }
101 arg[len] = '\0';
102 chp++; /* that closing quote. */
103 break;
104 }
105 default:
106 {
107 /* An unquoted string. Accumulate all non blank
108 characters into a buffer. */
109 int len;
110 char *start = chp;
111 while (*chp != '\0' && !isspace (*chp))
112 {
113 chp++;
114 }
115 len = chp - start;
116 arg = xmalloc ((len + 1) * sizeof (char));
117 strncpy (arg, start, len);
118 arg[len] = '\0';
119 break;
120 }
121 }
122 /* Append arg to argv. */
123 argv = xrealloc (argv, (argc + 2) * sizeof (char *));
124 argv[argc++] = arg;
125 argv[argc] = NULL;
126 }
127}
128
129
130void
131mi_parse_free (struct mi_parse *parse)
132{
133 if (parse == NULL)
134 return;
135 if (parse->command != NULL)
b8c9b27d 136 xfree (parse->command);
fb40c209 137 if (parse->token != NULL)
b8c9b27d 138 xfree (parse->token);
fb40c209 139 if (parse->args != NULL)
b8c9b27d 140 xfree (parse->args);
fb40c209
AC
141 if (parse->argv != NULL)
142 freeargv (parse->argv);
b8c9b27d 143 xfree (parse);
fb40c209
AC
144}
145
146
147struct mi_parse *
148mi_parse (char *cmd)
149{
150 char *chp;
151 struct mi_parse *parse = XMALLOC (struct mi_parse);
152 memset (parse, 0, sizeof (*parse));
1e92afda
VP
153 parse->thread = -1;
154 parse->frame = -1;
fb40c209
AC
155
156 /* Before starting, skip leading white space. */
157 while (isspace (*cmd))
158 cmd++;
159
160 /* Find/skip any token and then extract it. */
161 for (chp = cmd; *chp >= '0' && *chp <= '9'; chp++)
162 ;
163 parse->token = xmalloc ((chp - cmd + 1) * sizeof (char *));
164 memcpy (parse->token, cmd, (chp - cmd));
165 parse->token[chp - cmd] = '\0';
166
167 /* This wasn't a real MI command. Return it as a CLI_COMMAND. */
168 if (*chp != '-')
169 {
170 while (isspace (*chp))
171 chp++;
172 parse->command = xstrdup (chp);
173 parse->op = CLI_COMMAND;
174 return parse;
175 }
176
177 /* Extract the command. */
178 {
179 char *tmp = chp + 1; /* discard ``-'' */
180 for (; *chp && !isspace (*chp); chp++)
181 ;
182 parse->command = xmalloc ((chp - tmp + 1) * sizeof (char *));
183 memcpy (parse->command, tmp, chp - tmp);
184 parse->command[chp - tmp] = '\0';
185 }
186
187 /* Find the command in the MI table. */
188 parse->cmd = mi_lookup (parse->command);
189 if (parse->cmd == NULL)
190 {
191 /* FIXME: This should be a function call. */
192 fprintf_unfiltered
193 (raw_stdout,
194 "%s^error,msg=\"Undefined MI command: %s\"\n",
195 parse->token, parse->command);
196 mi_parse_free (parse);
197 return NULL;
198 }
199
200 /* Skip white space following the command. */
201 while (isspace (*chp))
202 chp++;
203
1e92afda
VP
204 /* Parse the --thread and --frame options, if present. At present,
205 some important commands, like '-break-*' are implemented by forwarding
206 to the CLI layer directly. We want to parse --thread and --frame
207 here, so as not to leave those option in the string that will be passed
208 to CLI. */
209 for (;;)
210 {
211 char *start = chp;
212 size_t ts = sizeof ("--thread ") - 1;
213 size_t fs = sizeof ("--frame ") - 1;
214 if (strncmp (chp, "--thread ", ts) == 0)
215 {
216 if (parse->thread != -1)
217 error ("Duplicate '--thread' option");
218 chp += ts;
219 parse->thread = strtol (chp, &chp, 10);
220 }
221 else if (strncmp (chp, "--frame ", fs) == 0)
222 {
223 if (parse->frame != -1)
224 error ("Duplicate '--frame' option");
225 chp += fs;
226 parse->frame = strtol (chp, &chp, 10);
227 }
228 else
229 break;
230
231 if (*chp != '\0' && !isspace (*chp))
232 error ("Invalid value for the '%s' option",
233 start[2] == 't' ? "--thread" : "--frame");
234 while (isspace (*chp))
235 chp++;
236 }
237
fb40c209
AC
238 /* For new argv commands, attempt to return the parsed argument
239 list. */
240 if (parse->cmd->argv_func != NULL)
241 {
242 mi_parse_argv (chp, parse);
243 if (parse->argv == NULL)
244 {
245 /* FIXME: This should be a function call. */
246 fprintf_unfiltered
247 (raw_stdout,
248 "%s^error,msg=\"Problem parsing arguments: %s %s\"\n",
249 parse->token, parse->command, chp);
250 mi_parse_free (parse);
251 return NULL;
252 }
253 }
254
255 /* FIXME: DELETE THIS */
9e22b03a 256 /* For CLI commands, also return the remainder of the
fb40c209 257 command line as a single string. */
9e22b03a
VP
258 if (parse->cmd->cli.cmd != NULL)
259 parse->args = xstrdup (chp);
fb40c209
AC
260
261 /* Fully parsed. */
262 parse->op = MI_COMMAND;
263 return parse;
264}
This page took 0.648923 seconds and 4 git commands to generate.