Switch the license of all .c files to GPLv3.
[deliverable/binutils-gdb.git] / gdb / mi / mi-parse.c
1 /* MI Command Set - MI parser.
2
3 Copyright (C) 2000, 2001, 2002, 2007 Free Software Foundation, Inc.
4
5 Contributed by Cygnus Solutions (a Red Hat company).
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
11 the Free Software Foundation; either version 3 of the License, or
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
20 along with this program. If not, see <http://www.gnu.org/licenses/>. */
21
22 #include "defs.h"
23 #include "mi-cmds.h"
24 #include "mi-parse.h"
25
26 #include <ctype.h>
27 #include "gdb_string.h"
28
29 static void
30 mi_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
130 void
131 mi_parse_free (struct mi_parse *parse)
132 {
133 if (parse == NULL)
134 return;
135 if (parse->command != NULL)
136 xfree (parse->command);
137 if (parse->token != NULL)
138 xfree (parse->token);
139 if (parse->args != NULL)
140 xfree (parse->args);
141 if (parse->argv != NULL)
142 freeargv (parse->argv);
143 xfree (parse);
144 }
145
146
147 struct mi_parse *
148 mi_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
223 || parse->cmd->cli.cmd != NULL)
224 {
225 parse->args = xstrdup (chp);
226 }
227
228 /* Fully parsed. */
229 parse->op = MI_COMMAND;
230 return parse;
231 }
This page took 0.045895 seconds and 4 git commands to generate.