a7390436d83c8d1f8930566a6e72d1ea35632a77
[deliverable/binutils-gdb.git] / gdb / mi / mi-parse.c
1 /* MI Command Set - MI parser.
2 Copyright (C) 2000, Free Software Foundation, Inc.
3 Contributed by Cygnus Solutions (a Red Hat company).
4
5 This file is part of GDB.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
21
22 #include "defs.h"
23 #include "mi-cmds.h"
24 #include "mi-parse.h"
25
26 #include <ctype.h>
27 #include <string.h>
28
29 #undef XMALLOC
30 #define XMALLOC(TYPE) ((TYPE*) xmalloc (sizeof (TYPE)))
31
32 static void
33 mi_parse_argv (char *args, struct mi_parse *parse)
34 {
35 char *chp = args;
36 int argc = 0;
37 char **argv = xmalloc ((argc + 1) * sizeof (char *));
38 argv[argc] = NULL;
39 while (1)
40 {
41 char *arg;
42 /* skip leading white space */
43 while (isspace (*chp))
44 chp++;
45 /* Three possibilities: EOF, quoted string, or other text. */
46 switch (*chp)
47 {
48 case '\0':
49 parse->argv = argv;
50 parse->argc = argc;
51 return;
52 case '"':
53 {
54 /* A quoted string. */
55 int len;
56 char *start = chp + 1;
57 /* Determine the buffer size. */
58 chp = start;
59 len = 0;
60 while (*chp != '\0' && *chp != '"')
61 {
62 if (*chp == '\\')
63 {
64 chp++;
65 if (parse_escape (&chp) <= 0)
66 {
67 /* Do not allow split lines or "\000" */
68 freeargv (argv);
69 return;
70 }
71 }
72 else
73 chp++;
74 len++;
75 }
76 /* Insist on a closing quote. */
77 if (*chp != '"')
78 {
79 freeargv (argv);
80 return;
81 }
82 /* Insist on trailing white space. */
83 if (chp[1] != '\0' && !isspace (chp[1]))
84 {
85 freeargv (argv);
86 return;
87 }
88 /* create the buffer. */
89 arg = xmalloc ((len + 1) * sizeof (char));
90 /* And copy the characters in. */
91 chp = start;
92 len = 0;
93 while (*chp != '\0' && *chp != '"')
94 {
95 if (*chp == '\\')
96 {
97 chp++;
98 arg[len] = parse_escape (&chp);
99 }
100 else
101 arg[len] = *chp++;
102 len++;
103 }
104 arg[len] = '\0';
105 chp++; /* that closing quote. */
106 break;
107 }
108 default:
109 {
110 /* An unquoted string. Accumulate all non blank
111 characters into a buffer. */
112 int len;
113 char *start = chp;
114 while (*chp != '\0' && !isspace (*chp))
115 {
116 chp++;
117 }
118 len = chp - start;
119 arg = xmalloc ((len + 1) * sizeof (char));
120 strncpy (arg, start, len);
121 arg[len] = '\0';
122 break;
123 }
124 }
125 /* Append arg to argv. */
126 argv = xrealloc (argv, (argc + 2) * sizeof (char *));
127 argv[argc++] = arg;
128 argv[argc] = NULL;
129 }
130 }
131
132
133 void
134 mi_parse_free (struct mi_parse *parse)
135 {
136 if (parse == NULL)
137 return;
138 if (parse->command != NULL)
139 free (parse->command);
140 if (parse->token != NULL)
141 free (parse->token);
142 if (parse->args != NULL)
143 free (parse->args);
144 if (parse->argv != NULL)
145 freeargv (parse->argv);
146 free (parse);
147 }
148
149
150 struct mi_parse *
151 mi_parse (char *cmd)
152 {
153 char *chp;
154 struct mi_parse *parse = XMALLOC (struct mi_parse);
155 memset (parse, 0, sizeof (*parse));
156
157 /* Before starting, skip leading white space. */
158 while (isspace (*cmd))
159 cmd++;
160
161 /* Find/skip any token and then extract it. */
162 for (chp = cmd; *chp >= '0' && *chp <= '9'; chp++)
163 ;
164 parse->token = xmalloc ((chp - cmd + 1) * sizeof (char *));
165 memcpy (parse->token, cmd, (chp - cmd));
166 parse->token[chp - cmd] = '\0';
167
168 /* This wasn't a real MI command. Return it as a CLI_COMMAND. */
169 if (*chp != '-')
170 {
171 while (isspace (*chp))
172 chp++;
173 parse->command = xstrdup (chp);
174 parse->op = CLI_COMMAND;
175 return parse;
176 }
177
178 /* Extract the command. */
179 {
180 char *tmp = chp + 1; /* discard ``-'' */
181 for (; *chp && !isspace (*chp); chp++)
182 ;
183 parse->command = xmalloc ((chp - tmp + 1) * sizeof (char *));
184 memcpy (parse->command, tmp, chp - tmp);
185 parse->command[chp - tmp] = '\0';
186 }
187
188 /* Find the command in the MI table. */
189 parse->cmd = mi_lookup (parse->command);
190 if (parse->cmd == NULL)
191 {
192 /* FIXME: This should be a function call. */
193 fprintf_unfiltered
194 (raw_stdout,
195 "%s^error,msg=\"Undefined MI command: %s\"\n",
196 parse->token, parse->command);
197 mi_parse_free (parse);
198 return NULL;
199 }
200
201 /* Skip white space following the command. */
202 while (isspace (*chp))
203 chp++;
204
205 /* For new argv commands, attempt to return the parsed argument
206 list. */
207 if (parse->cmd->argv_func != NULL)
208 {
209 mi_parse_argv (chp, parse);
210 if (parse->argv == NULL)
211 {
212 /* FIXME: This should be a function call. */
213 fprintf_unfiltered
214 (raw_stdout,
215 "%s^error,msg=\"Problem parsing arguments: %s %s\"\n",
216 parse->token, parse->command, chp);
217 mi_parse_free (parse);
218 return NULL;
219 }
220 }
221
222 /* FIXME: DELETE THIS */
223 /* For CLI and old ARGS commands, also return the remainder of the
224 command line as a single string. */
225 if (parse->cmd->args_func != NULL
226 || parse->cmd->cli != NULL)
227 {
228 parse->args = xstrdup (chp);
229 }
230
231 /* Fully parsed. */
232 parse->op = MI_COMMAND;
233 return parse;
234 }
235
236 void
237 _initialize_mi_parse (void)
238 {
239 }
This page took 0.04885 seconds and 3 git commands to generate.