Updated Spanish translation
[anjuta-git-plugin.git] / plugins / gdb / parser.c
blobf5f0a5177353a0ae38038590f61dd6b12b9e462a
1 /*
2 * parser.c Copyright (C) 2002
3 * Etay Meiri <etay-m@bezeqint.net>
4 * Jean-Noel Guiheneuf <jnoel@saudionline.com.sa>
6 * Adapted from kdevelop - gdbparser.cpp Copyright (C) 1999
7 * by John Birch <jb.nz@writeme.com>
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the Free
11 * Software Foundation; either version 2 of the License, or (at your option)
12 * any later version.
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 * for more details.
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc., 59
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
28 #include "parser.h"
30 #include <stdlib.h>
31 #include <libgnome/gnome-i18n.h>
32 #include <string.h>
33 #include <ctype.h>
34 #include <assert.h>
36 static gchar * skip_string (gchar *buf);
38 static gchar *
39 skip_quotes (gchar *buf, gchar quotes)
41 if (buf && *buf == quotes)
43 buf++;
45 while (*buf)
47 if (*buf == '\\')
48 buf++; // skips \" or \' problems
49 else if (*buf == quotes)
50 return buf + 1;
52 buf++;
55 return buf;
58 static gchar *
59 skip_delim (gchar * buf, gchar open, gchar close)
61 if (buf && *buf == open)
63 buf++;
65 while (*buf)
67 if (*buf == open)
68 buf = skip_delim (buf, open, close);
69 else if (*buf == close)
70 return buf + 1;
71 else if (*buf == '\"')
72 buf = skip_string (buf);
73 else if (*buf == '\'')
74 buf = skip_quotes (buf, *buf);
75 else if (*buf)
76 buf++;
79 return buf;
82 static gchar *
83 skip_string (gchar *buf)
85 if (buf && *buf == '\"')
87 buf = skip_quotes (buf, *buf);
88 while (*buf)
90 if ((strncmp (buf, ", \"", 3) == 0) ||
91 (strncmp (buf, ", '", 3) == 0))
92 buf = skip_quotes (buf + 2, *(buf + 2));
94 else if (strncmp (buf, " <", 2) == 0) // take care of
95 // <repeats
96 buf = skip_delim (buf + 1, '<', '>');
97 else
98 break;
101 // If the string is long then it's chopped and has ... after it.
102 while (*buf && *buf == '.')
103 buf++;
105 return buf;
108 static gchar *
109 skip_token_end (gchar * buf)
111 if (buf)
113 switch (*buf)
115 case '"':
116 return skip_string (buf);
117 case '\'':
118 return skip_quotes (buf, *buf);
119 case '{':
120 return skip_delim (buf, '{', '}');
121 case '<':
122 return skip_delim (buf, '<', '>');
123 case '(':
124 return skip_delim (buf, '(', ')');
127 while (*buf && !isspace (*buf) && *buf != ',' && *buf != '}' &&
128 *buf != '=')
129 buf++;
131 return buf;
134 static gchar *
135 skip_token_value (gchar * buf)
137 gchar *end;
139 if (!buf)
140 return NULL;
141 while (TRUE)
143 buf = skip_token_end (buf);
145 end = buf;
146 while (*end && isspace (*end) && *end != '\n')
147 end++;
149 if (*end == 0 || *end == ',' || *end == '\n' || *end == '=' ||
150 *end == '}')
151 break;
153 if (buf == end)
154 break;
156 buf = end;
158 return buf;
161 static gchar *
162 skip_next_token_start (gchar * buf)
164 if (!buf)
165 return NULL;
167 while (*buf &&
168 (isspace (*buf) || *buf == ',' || *buf == '}' || *buf == '='))
169 buf++;
171 return buf;
174 static gchar *
175 skip_next_token (gchar * buf)
177 if (!buf)
178 return NULL;
180 while (*buf &&
181 (isspace (*buf) || *buf == ',' || *buf == '='))
182 buf++;
184 return buf;
187 static IAnjutaDebuggerDataType
188 get_type (gchar **buf)
190 gchar *pos;
192 if (!*buf || !*(*buf = skip_next_token_start (*buf)))
193 return IANJUTA_DEBUGGER_UNKNOWN_TYPE;
195 // A reference, probably from a parameter value.
196 if (**buf == '@')
197 return IANJUTA_DEBUGGER_REFERENCE_TYPE;
199 // Structures and arrays - (but which one is which?)
200 // {void (void)} 0x804a944 <__builtin_new+41> - this is a fn pointer
201 // (void (*)(void)) 0x804a944 <f(E *, char)> - so is this - ugly!!!
202 if (**buf == '{')
204 (*buf)++;
205 if (**buf == '{')
206 return IANJUTA_DEBUGGER_ARRAY_TYPE;
208 if (strncmp (*buf, "<No data fields>}", 17) == 0)
210 (*buf) += 17;
211 return IANJUTA_DEBUGGER_VALUE_TYPE;
214 pos = *buf;
215 while (*pos)
217 switch (*pos)
219 case '=':
220 return IANJUTA_DEBUGGER_STRUCT_TYPE;
221 case '"':
222 pos = skip_string (pos);
223 break;
224 case '\'':
225 pos = skip_quotes (pos, '\'');
226 break;
227 case ',':
228 if (*(pos - 1) == '}')
230 g_warning ("??????\n");
232 return IANJUTA_DEBUGGER_ARRAY_TYPE;
233 case '}':
234 if (*(pos + 1) == ',' || *(pos + 1) == '\n' || !*(pos + 1))
235 return IANJUTA_DEBUGGER_ARRAY_TYPE; // Hmm a single element
236 // array??
237 if (strncmp (pos + 1, " 0x", 3) == 0)
238 return IANJUTA_DEBUGGER_POINTER_TYPE; // What about references?
239 return IANJUTA_DEBUGGER_UNKNOWN_TYPE; // very odd?
240 case '(':
241 pos = skip_delim (pos, '(', ')');
242 break;
243 case '<':
244 pos = skip_delim (pos, '<', '>');
245 break;
246 default:
247 pos++;
248 break;
251 return IANJUTA_DEBUGGER_UNKNOWN_TYPE;
254 // some sort of address. We need to sort out if we have
255 // a 0x888888 "this is a char*" type which we'll term a value
256 // or whether we just have an address
257 if (strncmp (*buf, "0x", 2) == 0)
259 pos = *buf;
260 while (*pos)
262 if (!isspace (*pos))
263 pos++;
264 else if (*(pos + 1) == '\"')
265 return IANJUTA_DEBUGGER_VALUE_TYPE;
266 else
267 break;
269 return IANJUTA_DEBUGGER_POINTER_TYPE;
272 // Pointers and references - references are a bit odd
273 // and cause GDB to fail to produce all the local data
274 // if they haven't been initialised. but that's not our problem!!
275 // (void (*)(void)) 0x804a944 <f(E *, char)> - this is a fn pointer
276 if (**buf == '(')
278 pos = *buf;
279 pos = skip_delim (pos, '(', ')');
280 pos -= 2;
281 switch (*pos)
283 case ')':
284 case '*':
285 return IANJUTA_DEBUGGER_POINTER_TYPE;
286 case '&':
287 return IANJUTA_DEBUGGER_REFERENCE_TYPE;
288 default:
289 /* fix (char * const) - case */
290 while(*pos && (isalpha(*pos) || *pos == ' ')) --pos;
291 switch(*pos)
293 case '*': return IANJUTA_DEBUGGER_POINTER_TYPE;
294 case '&': return IANJUTA_DEBUGGER_REFERENCE_TYPE;
295 default: return IANJUTA_DEBUGGER_UNKNOWN_TYPE;
300 pos = skip_token_value (*buf);
301 if ((strncmp (pos, " = ", 3) == 0) || (*pos == '='))
302 return IANJUTA_DEBUGGER_NAME_TYPE;
304 return IANJUTA_DEBUGGER_VALUE_TYPE;
307 static gchar *
308 get_name (gchar **buf)
310 gchar *start;
312 start = skip_next_token_start (*buf);
313 if (*start)
315 gchar *t;
317 *buf = skip_token_value (start);
318 t = *buf;
319 if (*t == '=')
320 t--;
321 return g_strstrip (g_strndup (start, t - start + 1));
323 else
324 *buf = start;
326 return NULL;
329 static gchar *
330 get_value (gchar **buf)
332 gchar *start;
333 gchar *value;
335 /* g_print("get_value: %s\n",*buf); */
337 start = skip_next_token_start (*buf);
338 *buf = skip_token_value (start);
340 if (*start == '{')
341 return g_strstrip (g_strndup (start + 1, *buf - start - 1));
342 if (*buf == start)
343 return NULL;
344 value = g_strstrip (g_strndup (start, *buf - start));
346 return value;
349 static void
350 parse_parent (IAnjutaDebuggerWatch* parent, gchar **buf)
352 IAnjutaDebuggerDataType type;
353 IAnjutaDebuggerWatch* child;
354 guint idx;
355 gchar *pos;
356 guint i;
358 if (*buf == NULL)
359 return;
361 type = get_type (buf);
362 if (type == IANJUTA_DEBUGGER_NAME_TYPE)
364 parent->name = get_name (buf);
365 type = get_type (buf);
368 parent->type = type;
370 switch (parent->type)
372 case IANJUTA_DEBUGGER_ROOT_TYPE:
373 case IANJUTA_DEBUGGER_UNKNOWN_TYPE:
374 case IANJUTA_DEBUGGER_NAME_TYPE:
375 break;
376 case IANJUTA_DEBUGGER_POINTER_TYPE:
377 case IANJUTA_DEBUGGER_VALUE_TYPE:
378 case IANJUTA_DEBUGGER_REFERENCE_TYPE:
379 parent->value = get_value (buf);
380 break;
381 case IANJUTA_DEBUGGER_ARRAY_TYPE:
382 child = NULL;
383 idx = 0;
385 while (**buf)
387 *buf = skip_next_token (*buf);
389 if (**buf == '\0')
390 return;
391 if (**buf == '}')
393 *buf = *buf + 1;
394 return;
397 if (child == NULL)
399 parent->children = g_new0 (IAnjutaDebuggerWatch, 1);
400 child = parent->children;
402 else
404 child->sibling = g_new0 (IAnjutaDebuggerWatch, 1);
405 child = child->sibling;
407 child->index = idx;
408 parse_parent (child, buf);
410 if (child->value)
412 pos = strstr (child->value, " <repeats");
413 if (pos)
415 if ((i = atoi (pos + 10)))
416 idx += (i - 1);
419 idx++;
422 break;
423 case IANJUTA_DEBUGGER_STRUCT_TYPE:
424 child = NULL;
426 while (**buf)
428 *buf = skip_next_token (*buf);
430 if (**buf == '\0')
431 return;
432 if (**buf == '}')
434 *buf = *buf + 1;
435 return;
438 if (child == NULL)
440 parent->children = g_new0 (IAnjutaDebuggerWatch, 1);
441 child = parent->children;
443 else
445 child->sibling = g_new0 (IAnjutaDebuggerWatch, 1);
446 child = child->sibling;
449 parse_parent (child, buf);
451 return;
456 IAnjutaDebuggerWatch*
457 gdb_watch_parse (const GDBMIValue *mi_results)
459 IAnjutaDebuggerWatch *watch;
460 const GDBMIValue *value = NULL;
462 if (mi_results) value = gdbmi_value_hash_lookup (mi_results, "value");
463 if ((mi_results == NULL) || (value == NULL))
465 watch = g_new0 (IAnjutaDebuggerWatch, 1);
466 watch->value = "?";
468 else
470 gchar *pos;
471 gchar *full_output;
473 /* Concat the answers of gdb */
474 full_output = (char *)gdbmi_value_literal_get (value);
476 pos = full_output;
478 watch = g_new0 (IAnjutaDebuggerWatch, 1);
480 parse_parent (watch, &pos);
483 return watch;
486 void gdb_watch_free (IAnjutaDebuggerWatch* this)
488 if (this->name != NULL) g_free ((char *)this->name);
489 if (this->value != NULL) g_free ((char *)this->value);
491 if (this->children != NULL) gdb_watch_free (this->children);
492 if (this->sibling != NULL) gdb_watch_free (this->sibling);
494 g_free (this);