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)
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
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
31 #include <libgnome/gnome-i18n.h>
36 static gchar
* skip_string (gchar
*buf
);
39 skip_quotes (gchar
*buf
, gchar quotes
)
41 if (buf
&& *buf
== quotes
)
48 buf
++; // skips \" or \' problems
49 else if (*buf
== quotes
)
59 skip_delim (gchar
* buf
, gchar open
, gchar close
)
61 if (buf
&& *buf
== open
)
68 buf
= skip_delim (buf
, open
, close
);
69 else if (*buf
== close
)
71 else if (*buf
== '\"')
72 buf
= skip_string (buf
);
73 else if (*buf
== '\'')
74 buf
= skip_quotes (buf
, *buf
);
83 skip_string (gchar
*buf
)
85 if (buf
&& *buf
== '\"')
87 buf
= skip_quotes (buf
, *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
96 buf
= skip_delim (buf
+ 1, '<', '>');
101 // If the string is long then it's chopped and has ... after it.
102 while (*buf
&& *buf
== '.')
109 skip_token_end (gchar
* buf
)
116 return skip_string (buf
);
118 return skip_quotes (buf
, *buf
);
120 return skip_delim (buf
, '{', '}');
122 return skip_delim (buf
, '<', '>');
124 return skip_delim (buf
, '(', ')');
127 while (*buf
&& !isspace (*buf
) && *buf
!= ',' && *buf
!= '}' &&
135 skip_token_value (gchar
* buf
)
143 buf
= skip_token_end (buf
);
146 while (*end
&& isspace (*end
) && *end
!= '\n')
149 if (*end
== 0 || *end
== ',' || *end
== '\n' || *end
== '=' ||
162 skip_next_token_start (gchar
* buf
)
168 (isspace (*buf
) || *buf
== ',' || *buf
== '}' || *buf
== '='))
175 skip_next_token (gchar
* buf
)
181 (isspace (*buf
) || *buf
== ',' || *buf
== '='))
187 static IAnjutaDebuggerDataType
188 get_type (gchar
**buf
)
192 if (!*buf
|| !*(*buf
= skip_next_token_start (*buf
)))
193 return IANJUTA_DEBUGGER_UNKNOWN_TYPE
;
195 // A reference, probably from a parameter value.
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!!!
206 return IANJUTA_DEBUGGER_ARRAY_TYPE
;
208 if (strncmp (*buf
, "<No data fields>}", 17) == 0)
211 return IANJUTA_DEBUGGER_VALUE_TYPE
;
220 return IANJUTA_DEBUGGER_STRUCT_TYPE
;
222 pos
= skip_string (pos
);
225 pos
= skip_quotes (pos
, '\'');
228 if (*(pos
- 1) == '}')
230 g_warning ("??????\n");
232 return IANJUTA_DEBUGGER_ARRAY_TYPE
;
234 if (*(pos
+ 1) == ',' || *(pos
+ 1) == '\n' || !*(pos
+ 1))
235 return IANJUTA_DEBUGGER_ARRAY_TYPE
; // Hmm a single element
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?
241 pos
= skip_delim (pos
, '(', ')');
244 pos
= skip_delim (pos
, '<', '>');
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)
264 else if (*(pos
+ 1) == '\"')
265 return IANJUTA_DEBUGGER_VALUE_TYPE
;
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
279 pos
= skip_delim (pos
, '(', ')');
285 return IANJUTA_DEBUGGER_POINTER_TYPE
;
287 return IANJUTA_DEBUGGER_REFERENCE_TYPE
;
289 /* fix (char * const) - case */
290 while(*pos
&& (isalpha(*pos
) || *pos
== ' ')) --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
;
308 get_name (gchar
**buf
)
312 start
= skip_next_token_start (*buf
);
317 *buf
= skip_token_value (start
);
321 return g_strstrip (g_strndup (start
, t
- start
+ 1));
330 get_value (gchar
**buf
)
335 /* g_print("get_value: %s\n",*buf); */
337 start
= skip_next_token_start (*buf
);
338 *buf
= skip_token_value (start
);
341 return g_strstrip (g_strndup (start
+ 1, *buf
- start
- 1));
344 value
= g_strstrip (g_strndup (start
, *buf
- start
));
350 parse_parent (IAnjutaDebuggerWatch
* parent
, gchar
**buf
)
352 IAnjutaDebuggerDataType type
;
353 IAnjutaDebuggerWatch
* child
;
361 type
= get_type (buf
);
362 if (type
== IANJUTA_DEBUGGER_NAME_TYPE
)
364 parent
->name
= get_name (buf
);
365 type
= get_type (buf
);
370 switch (parent
->type
)
372 case IANJUTA_DEBUGGER_ROOT_TYPE
:
373 case IANJUTA_DEBUGGER_UNKNOWN_TYPE
:
374 case IANJUTA_DEBUGGER_NAME_TYPE
:
376 case IANJUTA_DEBUGGER_POINTER_TYPE
:
377 case IANJUTA_DEBUGGER_VALUE_TYPE
:
378 case IANJUTA_DEBUGGER_REFERENCE_TYPE
:
379 parent
->value
= get_value (buf
);
381 case IANJUTA_DEBUGGER_ARRAY_TYPE
:
387 *buf
= skip_next_token (*buf
);
399 parent
->children
= g_new0 (IAnjutaDebuggerWatch
, 1);
400 child
= parent
->children
;
404 child
->sibling
= g_new0 (IAnjutaDebuggerWatch
, 1);
405 child
= child
->sibling
;
408 parse_parent (child
, buf
);
412 pos
= strstr (child
->value
, " <repeats");
415 if ((i
= atoi (pos
+ 10)))
423 case IANJUTA_DEBUGGER_STRUCT_TYPE
:
428 *buf
= skip_next_token (*buf
);
440 parent
->children
= g_new0 (IAnjutaDebuggerWatch
, 1);
441 child
= parent
->children
;
445 child
->sibling
= g_new0 (IAnjutaDebuggerWatch
, 1);
446 child
= child
->sibling
;
449 parse_parent (child
, buf
);
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);
473 /* Concat the answers of gdb */
474 full_output
= (char *)gdbmi_value_literal_get (value
);
478 watch
= g_new0 (IAnjutaDebuggerWatch
, 1);
480 parse_parent (watch
, &pos
);
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
);