]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/mi/mi-parse.c
Switch the license of all .c files to GPLv3.
[thirdparty/binutils-gdb.git] / gdb / mi / mi-parse.c
CommitLineData
fb40c209 1/* MI Command Set - MI parser.
349c5d5f 2
6aba47ca 3 Copyright (C) 2000, 2001, 2002, 2007 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));
153
154 /* Before starting, skip leading white space. */
155 while (isspace (*cmd))
156 cmd++;
157
158 /* Find/skip any token and then extract it. */
159 for (chp = cmd; *chp >= '0' && *chp <= '9'; chp++)
160 ;
161 parse->token = xmalloc ((chp - cmd + 1) * sizeof (char *));
162 memcpy (parse->token, cmd, (chp - cmd));
163 parse->token[chp - cmd] = '\0';
164
165 /* This wasn't a real MI command. Return it as a CLI_COMMAND. */
166 if (*chp != '-')
167 {
168 while (isspace (*chp))
169 chp++;
170 parse->command = xstrdup (chp);
171 parse->op = CLI_COMMAND;
172 return parse;
173 }
174
175 /* Extract the command. */
176 {
177 char *tmp = chp + 1; /* discard ``-'' */
178 for (; *chp && !isspace (*chp); chp++)
179 ;
180 parse->command = xmalloc ((chp - tmp + 1) * sizeof (char *));
181 memcpy (parse->command, tmp, chp - tmp);
182 parse->command[chp - tmp] = '\0';
183 }
184
185 /* Find the command in the MI table. */
186 parse->cmd = mi_lookup (parse->command);
187 if (parse->cmd == NULL)
188 {
189 /* FIXME: This should be a function call. */
190 fprintf_unfiltered
191 (raw_stdout,
192 "%s^error,msg=\"Undefined MI command: %s\"\n",
193 parse->token, parse->command);
194 mi_parse_free (parse);
195 return NULL;
196 }
197
198 /* Skip white space following the command. */
199 while (isspace (*chp))
200 chp++;
201
202 /* For new argv commands, attempt to return the parsed argument
203 list. */
204 if (parse->cmd->argv_func != NULL)
205 {
206 mi_parse_argv (chp, parse);
207 if (parse->argv == NULL)
208 {
209 /* FIXME: This should be a function call. */
210 fprintf_unfiltered
211 (raw_stdout,
212 "%s^error,msg=\"Problem parsing arguments: %s %s\"\n",
213 parse->token, parse->command, chp);
214 mi_parse_free (parse);
215 return NULL;
216 }
217 }
218
219 /* FIXME: DELETE THIS */
220 /* For CLI and old ARGS commands, also return the remainder of the
221 command line as a single string. */
222 if (parse->cmd->args_func != NULL
b2af646b 223 || parse->cmd->cli.cmd != NULL)
fb40c209
AC
224 {
225 parse->args = xstrdup (chp);
226 }
227
228 /* Fully parsed. */
229 parse->op = MI_COMMAND;
230 return parse;
231}