]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/gdb/gdb/mi/mi-parse.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / gdb / gdb / mi / mi-parse.c
1 /* MI Command Set - MI parser.
2
3    Copyright 2000, 2001, 2002 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 2 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, write to the Free Software
21    Foundation, Inc., 59 Temple Place - Suite 330,
22    Boston, MA 02111-1307, USA.  */
23
24 #include "defs.h"
25 #include "mi-cmds.h"
26 #include "mi-parse.h"
27
28 #include <ctype.h>
29 #include "gdb_string.h"
30
31 static void
32 mi_parse_argv (char *args, struct mi_parse *parse)
33 {
34   char *chp = args;
35   int argc = 0;
36   char **argv = xmalloc ((argc + 1) * sizeof (char *));
37   argv[argc] = NULL;
38   while (1)
39     {
40       char *arg;
41       /* skip leading white space */
42       while (isspace (*chp))
43         chp++;
44       /* Three possibilities: EOF, quoted string, or other text. */
45       switch (*chp)
46         {
47         case '\0':
48           parse->argv = argv;
49           parse->argc = argc;
50           return;
51         case '"':
52           {
53             /* A quoted string. */
54             int len;
55             char *start = chp + 1;
56             /* Determine the buffer size. */
57             chp = start;
58             len = 0;
59             while (*chp != '\0' && *chp != '"')
60               {
61                 if (*chp == '\\')
62                   {
63                     chp++;
64                     if (parse_escape (&chp) <= 0)
65                       {
66                         /* Do not allow split lines or "\000" */
67                         freeargv (argv);
68                         return;
69                       }
70                   }
71                 else
72                   chp++;
73                 len++;
74               }
75             /* Insist on a closing quote. */
76             if (*chp != '"')
77               {
78                 freeargv (argv);
79                 return;
80               }
81             /* Insist on trailing white space. */
82             if (chp[1] != '\0' && !isspace (chp[1]))
83               {
84                 freeargv (argv);
85                 return;
86               }
87             /* create the buffer. */
88             arg = xmalloc ((len + 1) * sizeof (char));
89             /* And copy the characters in. */
90             chp = start;
91             len = 0;
92             while (*chp != '\0' && *chp != '"')
93               {
94                 if (*chp == '\\')
95                   {
96                     chp++;
97                     arg[len] = parse_escape (&chp);
98                   }
99                 else
100                   arg[len] = *chp++;
101                 len++;
102               }
103             arg[len] = '\0';
104             chp++;              /* that closing quote. */
105             break;
106           }
107         default:
108           {
109             /* An unquoted string.  Accumulate all non blank
110                characters into a buffer. */
111             int len;
112             char *start = chp;
113             while (*chp != '\0' && !isspace (*chp))
114               {
115                 chp++;
116               }
117             len = chp - start;
118             arg = xmalloc ((len + 1) * sizeof (char));
119             strncpy (arg, start, len);
120             arg[len] = '\0';
121             break;
122           }
123         }
124       /* Append arg to argv. */
125       argv = xrealloc (argv, (argc + 2) * sizeof (char *));
126       argv[argc++] = arg;
127       argv[argc] = NULL;
128     }
129 }
130
131
132 void
133 mi_parse_free (struct mi_parse *parse)
134 {
135   if (parse == NULL)
136     return;
137   if (parse->command != NULL)
138     xfree (parse->command);
139   if (parse->token != NULL)
140     xfree (parse->token);
141   if (parse->args != NULL)
142     xfree (parse->args);
143   if (parse->argv != NULL)
144     freeargv (parse->argv);
145   xfree (parse);
146 }
147
148
149 struct mi_parse *
150 mi_parse (char *cmd)
151 {
152   char *chp;
153   struct mi_parse *parse = XMALLOC (struct mi_parse);
154   memset (parse, 0, sizeof (*parse));
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
204   /* For new argv commands, attempt to return the parsed argument
205      list. */
206   if (parse->cmd->argv_func != NULL)
207     {
208       mi_parse_argv (chp, parse);
209       if (parse->argv == NULL)
210         {
211           /* FIXME: This should be a function call. */
212           fprintf_unfiltered
213             (raw_stdout,
214              "%s^error,msg=\"Problem parsing arguments: %s %s\"\n",
215              parse->token, parse->command, chp);
216           mi_parse_free (parse);
217           return NULL;
218         }
219     }
220
221   /* FIXME: DELETE THIS */
222   /* For CLI and old ARGS commands, also return the remainder of the
223      command line as a single string. */
224   if (parse->cmd->args_func != NULL
225       || parse->cmd->cli.cmd != NULL)
226     {
227       parse->args = xstrdup (chp);
228     }
229
230   /* Fully parsed. */
231   parse->op = MI_COMMAND;
232   return parse;
233 }