Rename _const functions to use overloading instead
[deliverable/binutils-gdb.git] / gdb / mi / mi-parse.c
CommitLineData
fb40c209 1/* MI Command Set - MI parser.
349c5d5f 2
61baf725 3 Copyright (C) 2000-2017 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>
529480d0 28#include "cli/cli-utils.h"
403cb6b1 29#include "language.h"
fb40c209 30
44d100c3
TT
31static const char mi_no_values[] = "--no-values";
32static const char mi_simple_values[] = "--simple-values";
33static const char mi_all_values[] = "--all-values";
87967e27 34
f870a310
TT
35/* Like parse_escape, but leave the results as a host char, not a
36 target char. */
37
38static int
ee047554 39mi_parse_escape (const char **string_ptr)
f870a310
TT
40{
41 int c = *(*string_ptr)++;
102040f0 42
f870a310
TT
43 switch (c)
44 {
45 case '\n':
46 return -2;
47 case 0:
48 (*string_ptr)--;
49 return 0;
50
51 case '0':
52 case '1':
53 case '2':
54 case '3':
55 case '4':
56 case '5':
57 case '6':
58 case '7':
59 {
60 int i = host_hex_value (c);
61 int count = 0;
102040f0 62
f870a310
TT
63 while (++count < 3)
64 {
65 c = (**string_ptr);
66 if (isdigit (c) && c != '8' && c != '9')
67 {
68 (*string_ptr)++;
69 i *= 8;
70 i += host_hex_value (c);
71 }
72 else
73 {
74 break;
75 }
76 }
77 return i;
78 }
79
80 case 'a':
81 c = '\a';
82 break;
83 case 'b':
84 c = '\b';
85 break;
86 case 'f':
87 c = '\f';
88 break;
89 case 'n':
90 c = '\n';
91 break;
92 case 'r':
93 c = '\r';
94 break;
95 case 't':
96 c = '\t';
97 break;
98 case 'v':
99 c = '\v';
100 break;
101
102 default:
103 break;
104 }
105
106 return c;
107}
108
fb40c209 109static void
ee047554 110mi_parse_argv (const char *args, struct mi_parse *parse)
fb40c209 111{
ee047554 112 const char *chp = args;
fb40c209 113 int argc = 0;
8d749320 114 char **argv = XNEWVEC (char *, argc + 1);
102040f0 115
fb40c209
AC
116 argv[argc] = NULL;
117 while (1)
118 {
119 char *arg;
102040f0 120
2b03b41d 121 /* Skip leading white space. */
f1735a53 122 chp = skip_spaces (chp);
fb40c209
AC
123 /* Three possibilities: EOF, quoted string, or other text. */
124 switch (*chp)
125 {
126 case '\0':
127 parse->argv = argv;
128 parse->argc = argc;
129 return;
130 case '"':
131 {
2b03b41d 132 /* A quoted string. */
fb40c209 133 int len;
ee047554 134 const char *start = chp + 1;
102040f0 135
2b03b41d 136 /* Determine the buffer size. */
fb40c209
AC
137 chp = start;
138 len = 0;
139 while (*chp != '\0' && *chp != '"')
140 {
141 if (*chp == '\\')
142 {
143 chp++;
f870a310 144 if (mi_parse_escape (&chp) <= 0)
fb40c209 145 {
2b03b41d 146 /* Do not allow split lines or "\000". */
fb40c209
AC
147 freeargv (argv);
148 return;
149 }
150 }
151 else
152 chp++;
153 len++;
154 }
2b03b41d 155 /* Insist on a closing quote. */
fb40c209
AC
156 if (*chp != '"')
157 {
158 freeargv (argv);
159 return;
160 }
2b03b41d 161 /* Insist on trailing white space. */
fb40c209
AC
162 if (chp[1] != '\0' && !isspace (chp[1]))
163 {
164 freeargv (argv);
165 return;
166 }
2b03b41d 167 /* Create the buffer and copy characters in. */
224c3ddb 168 arg = XNEWVEC (char, len + 1);
fb40c209
AC
169 chp = start;
170 len = 0;
171 while (*chp != '\0' && *chp != '"')
172 {
173 if (*chp == '\\')
174 {
175 chp++;
f870a310 176 arg[len] = mi_parse_escape (&chp);
fb40c209
AC
177 }
178 else
179 arg[len] = *chp++;
180 len++;
181 }
182 arg[len] = '\0';
2b03b41d 183 chp++; /* That closing quote. */
fb40c209
AC
184 break;
185 }
186 default:
187 {
2b03b41d
SS
188 /* An unquoted string. Accumulate all non-blank
189 characters into a buffer. */
fb40c209 190 int len;
ee047554 191 const char *start = chp;
102040f0 192
fb40c209
AC
193 while (*chp != '\0' && !isspace (*chp))
194 {
195 chp++;
196 }
197 len = chp - start;
224c3ddb 198 arg = XNEWVEC (char, len + 1);
fb40c209
AC
199 strncpy (arg, start, len);
200 arg[len] = '\0';
201 break;
202 }
203 }
2b03b41d 204 /* Append arg to argv. */
224c3ddb 205 argv = XRESIZEVEC (char *, argv, argc + 2);
fb40c209
AC
206 argv[argc++] = arg;
207 argv[argc] = NULL;
208 }
209}
210
4d89769a
TT
211mi_parse::mi_parse ()
212 : op (MI_COMMAND),
213 command (NULL),
214 token (NULL),
215 cmd (NULL),
216 cmd_start (NULL),
217 args (NULL),
218 argv (NULL),
219 argc (0),
220 all (0),
221 thread_group (-1),
222 thread (-1),
223 frame (-1),
224 language (language_unknown)
fb40c209 225{
fb40c209
AC
226}
227
4d89769a 228mi_parse::~mi_parse ()
305aeedc 229{
4d89769a
TT
230 xfree (command);
231 xfree (token);
232 xfree (args);
233 freeargv (argv);
305aeedc 234}
fb40c209 235
4d89769a 236std::unique_ptr<struct mi_parse>
ee047554 237mi_parse (const char *cmd, char **token)
fb40c209 238{
ee047554 239 const char *chp;
305aeedc 240 struct cleanup *cleanup;
102040f0 241
4d89769a 242 std::unique_ptr<struct mi_parse> parse (new struct mi_parse);
305aeedc 243
2b03b41d 244 /* Before starting, skip leading white space. */
f1735a53 245 cmd = skip_spaces (cmd);
fb40c209 246
2b03b41d 247 /* Find/skip any token and then extract it. */
fb40c209
AC
248 for (chp = cmd; *chp >= '0' && *chp <= '9'; chp++)
249 ;
224c3ddb 250 *token = (char *) xmalloc (chp - cmd + 1);
305aeedc
TT
251 memcpy (*token, cmd, (chp - cmd));
252 (*token)[chp - cmd] = '\0';
fb40c209 253
2b03b41d 254 /* This wasn't a real MI command. Return it as a CLI_COMMAND. */
fb40c209
AC
255 if (*chp != '-')
256 {
f1735a53 257 chp = skip_spaces (chp);
fb40c209
AC
258 parse->command = xstrdup (chp);
259 parse->op = CLI_COMMAND;
305aeedc 260
fb40c209
AC
261 return parse;
262 }
263
2b03b41d 264 /* Extract the command. */
fb40c209 265 {
ee047554 266 const char *tmp = chp + 1; /* discard ``-'' */
102040f0 267
fb40c209
AC
268 for (; *chp && !isspace (*chp); chp++)
269 ;
224c3ddb 270 parse->command = (char *) xmalloc (chp - tmp + 1);
fb40c209
AC
271 memcpy (parse->command, tmp, chp - tmp);
272 parse->command[chp - tmp] = '\0';
273 }
274
2b03b41d 275 /* Find the command in the MI table. */
fb40c209
AC
276 parse->cmd = mi_lookup (parse->command);
277 if (parse->cmd == NULL)
2ea126fa
JB
278 throw_error (UNDEFINED_COMMAND_ERROR,
279 _("Undefined MI command: %s"), parse->command);
fb40c209 280
2b03b41d 281 /* Skip white space following the command. */
f1735a53 282 chp = skip_spaces (chp);
fb40c209 283
1e92afda 284 /* Parse the --thread and --frame options, if present. At present,
2b03b41d
SS
285 some important commands, like '-break-*' are implemented by
286 forwarding to the CLI layer directly. We want to parse --thread
287 and --frame here, so as not to leave those option in the string
403cb6b1
JB
288 that will be passed to CLI.
289
290 Same for the --language option. */
291
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;
403cb6b1 299 size_t ls = sizeof ("--language ") - 1;
102040f0 300
a79b8f6e
VP
301 if (strncmp (chp, "--all ", as) == 0)
302 {
303 parse->all = 1;
304 chp += as;
305 }
306 /* See if --all is the last token in the input. */
307 if (strcmp (chp, "--all") == 0)
308 {
309 parse->all = 1;
310 chp += strlen (chp);
311 }
312 if (strncmp (chp, "--thread-group ", tgs) == 0)
313 {
ee047554
KS
314 char *endp;
315
30a7f059 316 option = "--thread-group";
a79b8f6e
VP
317 if (parse->thread_group != -1)
318 error (_("Duplicate '--thread-group' option"));
319 chp += tgs;
320 if (*chp != 'i')
321 error (_("Invalid thread group id"));
322 chp += 1;
ee047554
KS
323 parse->thread_group = strtol (chp, &endp, 10);
324 chp = endp;
a79b8f6e 325 }
8e0e408a 326 else if (strncmp (chp, "--thread ", ts) == 0)
1e92afda 327 {
ee047554
KS
328 char *endp;
329
30a7f059 330 option = "--thread";
1e92afda 331 if (parse->thread != -1)
a79b8f6e 332 error (_("Duplicate '--thread' option"));
1e92afda 333 chp += ts;
ee047554
KS
334 parse->thread = strtol (chp, &endp, 10);
335 chp = endp;
1e92afda
VP
336 }
337 else if (strncmp (chp, "--frame ", fs) == 0)
338 {
ee047554
KS
339 char *endp;
340
30a7f059 341 option = "--frame";
1e92afda 342 if (parse->frame != -1)
a79b8f6e 343 error (_("Duplicate '--frame' option"));
1e92afda 344 chp += fs;
ee047554
KS
345 parse->frame = strtol (chp, &endp, 10);
346 chp = endp;
1e92afda 347 }
403cb6b1
JB
348 else if (strncmp (chp, "--language ", ls) == 0)
349 {
350 char *lang_name;
351 struct cleanup *old_chain;
352
353 option = "--language";
354 chp += ls;
f1735a53 355 lang_name = extract_arg (&chp);
403cb6b1
JB
356 old_chain = make_cleanup (xfree, lang_name);
357
358 parse->language = language_enum (lang_name);
359 if (parse->language == language_unknown
360 || parse->language == language_auto)
361 error (_("Invalid --language argument: %s"), lang_name);
362
363 do_cleanups (old_chain);
364 }
1e92afda
VP
365 else
366 break;
367
368 if (*chp != '\0' && !isspace (*chp))
30a7f059 369 error (_("Invalid value for the '%s' option"), option);
f1735a53 370 chp = skip_spaces (chp);
1e92afda
VP
371 }
372
fb40c209 373 /* For new argv commands, attempt to return the parsed argument
2b03b41d 374 list. */
fb40c209
AC
375 if (parse->cmd->argv_func != NULL)
376 {
4d89769a 377 mi_parse_argv (chp, parse.get ());
fb40c209 378 if (parse->argv == NULL)
305aeedc 379 error (_("Problem parsing arguments: %s %s"), parse->command, chp);
fb40c209
AC
380 }
381
382 /* FIXME: DELETE THIS */
9e22b03a 383 /* For CLI commands, also return the remainder of the
fb40c209 384 command line as a single string. */
9e22b03a
VP
385 if (parse->cmd->cli.cmd != NULL)
386 parse->args = xstrdup (chp);
fb40c209 387
2b03b41d 388 /* Fully parsed, flag as an MI command. */
fb40c209
AC
389 parse->op = MI_COMMAND;
390 return parse;
391}
87967e27
YQ
392
393enum print_values
394mi_parse_print_values (const char *name)
395{
396 if (strcmp (name, "0") == 0
397 || strcmp (name, mi_no_values) == 0)
398 return PRINT_NO_VALUES;
399 else if (strcmp (name, "1") == 0
400 || strcmp (name, mi_all_values) == 0)
401 return PRINT_ALL_VALUES;
402 else if (strcmp (name, "2") == 0
403 || strcmp (name, mi_simple_values) == 0)
404 return PRINT_SIMPLE_VALUES;
405 else
406 error (_("Unknown value for PRINT_VALUES: must be: \
4070 or \"%s\", 1 or \"%s\", 2 or \"%s\""),
408 mi_no_values, mi_all_values, mi_simple_values);
409}
This page took 1.461475 seconds and 4 git commands to generate.