Added byline
[anjuta.git] / plugins / gdb / gdbmi.c
blobf9d656894bda4f3ef7c16db635be3a7fd71a6d89
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3 * gdbmi.c
4 * Copyright (C) Naba Kumar 2005 <naba@gnome.org>
5 *
6 * gdbmi.c is free software.
7 *
8 * You may redistribute it and/or modify it under the terms of the
9 * GNU General Public License, as published by the Free Software
10 * Foundation; either version 2, or (at your option) any later version.
12 * gdbmi.c 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.
15 * See the GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with main.c. See the file "COPYING". If not,
19 * write to: The Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
24 /* GDB MI parser */
25 #include <stdio.h>
26 #include <ctype.h>
27 #include <string.h>
28 #include <gmodule.h>
29 #include "gdbmi.h"
31 #define GDBMI_DUMP_INDENT_SIZE 4
33 struct _GDBMIValue
35 GDBMIDataType type;
36 gchar *name;
37 union {
38 GHashTable *hash;
39 GQueue *list;
40 GString *literal;
41 } data;
44 struct _GDBMIForeachHashData
46 GFunc user_callback;
47 gpointer user_data;
50 static guint GDBMI_deleted_hash_value = 0;
52 void
53 gdbmi_value_free (GDBMIValue *val)
55 g_return_if_fail (val != NULL);
57 if (val->type == GDBMI_DATA_LITERAL)
59 g_string_free (val->data.literal, TRUE);
61 else if (val->type == GDBMI_DATA_LIST)
63 gdbmi_value_foreach (val, (GFunc)gdbmi_value_free, NULL);
64 g_queue_free (val->data.list);
66 else
68 g_hash_table_destroy (val->data.hash);
70 g_free (val->name);
71 g_free (val);
74 GDBMIValue *
75 gdbmi_value_new (GDBMIDataType data_type, const gchar *name)
77 GDBMIValue *val = g_new0 (GDBMIValue, 1);
79 val->type = data_type;
80 if (name)
81 val->name = g_strdup (name);
83 switch (data_type)
85 case GDBMI_DATA_HASH:
86 val->data.hash =
87 g_hash_table_new_full (g_str_hash, g_str_equal,
88 (GDestroyNotify)g_free,
89 (GDestroyNotify)gdbmi_value_free);
90 break;
91 case GDBMI_DATA_LIST:
92 val->data.list = g_queue_new ();
93 break;
94 case GDBMI_DATA_LITERAL:
95 val->data.literal = g_string_new (NULL);
96 break;
97 default:
98 g_warning ("Unknow MI data type. Should not reach here");
99 return NULL;
101 return val;
104 GDBMIValue*
105 gdbmi_value_literal_new (const gchar *name, const gchar *data)
107 GDBMIValue* val;
108 val = gdbmi_value_new (GDBMI_DATA_LITERAL, name);
109 gdbmi_value_literal_set (val, data);
110 return val;
113 const gchar*
114 gdbmi_value_get_name (const GDBMIValue *val)
116 g_return_val_if_fail (val != NULL, NULL);
117 return val->name;
120 GDBMIDataType
121 gdbmi_value_get_type (const GDBMIValue *val)
123 return val->type;
126 void
127 gdbmi_value_set_name (GDBMIValue *val, const gchar *name)
129 g_return_if_fail (val != NULL);
130 g_return_if_fail (name != NULL);
131 g_free (val->name);
132 val->name = g_strdup (name);
135 gint
136 gdbmi_value_get_size (const GDBMIValue* val)
138 g_return_val_if_fail (val != NULL, 0);
140 if (val->type == GDBMI_DATA_LITERAL)
142 if (val->data.literal->str)
143 return 1;
144 else
145 return 0;
147 else if (val->type == GDBMI_DATA_LIST)
148 return g_queue_get_length (val->data.list);
149 else if (val->type == GDBMI_DATA_HASH)
150 return g_hash_table_size (val->data.hash);
151 else
152 return 0;
155 static void
156 gdbmi_value_hash_foreach (const gchar *key, GDBMIValue* val,
157 struct _GDBMIForeachHashData *hash_data)
159 hash_data->user_callback (val, hash_data->user_data);
162 void
163 gdbmi_value_foreach (const GDBMIValue* val, GFunc func, gpointer user_data)
165 g_return_if_fail (val != NULL);
166 g_return_if_fail (func != NULL);
168 if (val->type == GDBMI_DATA_LIST)
170 g_queue_foreach (val->data.list, func, user_data);
172 else if (val->type == GDBMI_DATA_HASH)
174 struct _GDBMIForeachHashData hash_data = {NULL, NULL};
176 hash_data.user_callback = func;
177 hash_data.user_data = user_data;
178 g_hash_table_foreach (val->data.hash, (GHFunc)gdbmi_value_hash_foreach,
179 &hash_data);
181 else
183 g_warning ("Can not do foreach for GDBMIValue this type");
187 /* Literal operations */
188 void
189 gdbmi_value_literal_set (GDBMIValue* val, const gchar *data)
191 g_return_if_fail (val != NULL);
192 g_return_if_fail (val->type == GDBMI_DATA_LITERAL);
193 g_string_assign (val->data.literal, data);
196 const gchar*
197 gdbmi_value_literal_get (const GDBMIValue* val)
199 g_return_val_if_fail (val != NULL, NULL);
200 g_return_val_if_fail (val->type == GDBMI_DATA_LITERAL, NULL);
201 return val->data.literal->str;
204 /* Hash operations */
205 void
206 gdbmi_value_hash_insert (GDBMIValue* val, const gchar *key, GDBMIValue *value)
208 gpointer orig_key;
209 gpointer orig_value;
211 g_return_if_fail (val != NULL);
212 g_return_if_fail (key != NULL);
213 g_return_if_fail (value != NULL);
214 g_return_if_fail (val->type == GDBMI_DATA_HASH);
216 /* GDBMI hash table could contains several data with the same
217 * key (output of -thread-list-ids)
218 * Keep old value under a random name, we get them using
219 * foreach function */
220 if (g_hash_table_lookup_extended (val->data.hash, key, &orig_key, &orig_value))
222 /* Key already exist, remove it and insert value with
223 * another name */
224 g_hash_table_steal (val->data.hash, key);
225 g_free (orig_key);
226 gchar *new_key = g_strdup_printf("[%d]", GDBMI_deleted_hash_value++);
227 g_hash_table_insert (val->data.hash, new_key, orig_value);
230 g_hash_table_insert (val->data.hash, g_strdup (key), value);
233 const GDBMIValue*
234 gdbmi_value_hash_lookup (const GDBMIValue* val, const gchar *key)
236 g_return_val_if_fail (val != NULL, NULL);
237 g_return_val_if_fail (key != NULL, NULL);
238 g_return_val_if_fail (val->type == GDBMI_DATA_HASH, NULL);
240 return g_hash_table_lookup (val->data.hash, key);
243 /* List operations */
244 void
245 gdbmi_value_list_append (GDBMIValue* val, GDBMIValue *value)
247 g_return_if_fail (val != NULL);
248 g_return_if_fail (value != NULL);
249 g_return_if_fail (val->type == GDBMI_DATA_LIST);
251 g_queue_push_tail (val->data.list, value);
254 const GDBMIValue*
255 gdbmi_value_list_get_nth (const GDBMIValue* val, gint idx)
257 g_return_val_if_fail (val != NULL, NULL);
258 g_return_val_if_fail (val->type == GDBMI_DATA_LIST, NULL);
260 if (idx >= 0)
261 return g_queue_peek_nth (val->data.list, idx);
262 else
263 return g_queue_peek_tail (val->data.list);
266 static void
267 gdbmi_value_dump_foreach (const GDBMIValue *val, gpointer indent_level)
269 gdbmi_value_dump (val, GPOINTER_TO_INT (indent_level));
272 G_MODULE_EXPORT void
273 gdbmi_value_dump (const GDBMIValue *val, gint indent_level)
275 gint i, next_indent;
277 g_return_if_fail (val != NULL);
279 for (i = 0; i < indent_level; i++)
280 printf (" ");
282 next_indent = indent_level + GDBMI_DUMP_INDENT_SIZE;
283 if (val->type == GDBMI_DATA_LITERAL)
285 gchar *v;
287 v = g_strescape (val->data.literal->str, NULL);
288 if (val->name)
289 printf ("%s = \"%s\",\n", val->name, v);
290 else
291 printf ("\"%s\",\n", v);
292 g_free (v);
294 else if (val->type == GDBMI_DATA_LIST)
296 if (val->name)
297 printf ("%s = [\n", val->name);
298 else
299 printf ("[\n");
300 gdbmi_value_foreach (val, (GFunc)gdbmi_value_dump_foreach,
301 GINT_TO_POINTER (next_indent));
302 for (i = 0; i < indent_level; i++)
303 printf (" ");
304 printf ("],\n");
306 else if (val->type == GDBMI_DATA_HASH)
308 if (val->name)
309 printf ("%s = {\n", val->name);
310 else
311 printf ("{\n");
312 gdbmi_value_foreach (val, (GFunc)gdbmi_value_dump_foreach,
313 GINT_TO_POINTER (next_indent));
314 for (i = 0; i < indent_level; i++)
315 printf (" ");
316 printf ("},\n");
320 static GDBMIValue*
321 gdbmi_value_parse_real (gchar **ptr)
323 GDBMIValue *val = NULL;
325 if (**ptr == '\0')
327 /* End of stream */
328 g_warning ("Parse error: Reached end of stream");
330 else if (**ptr == '"')
332 /* Value is literal */
333 gboolean escaped;
334 GString *buff;
335 gchar *p;
336 gchar *value, *compressed_value;
337 gint i;
339 *ptr = g_utf8_next_char (*ptr);
340 escaped = FALSE;
341 buff = g_string_new ("");
342 while (escaped || **ptr != '"')
344 if (**ptr == '\0')
346 g_warning ("Parse error: Invalid literal value");
347 return NULL;
349 if (escaped)
351 escaped = FALSE;
353 else if (**ptr == '\\')
355 escaped = TRUE;
357 p = g_utf8_next_char (*ptr);
358 for (i = 0; i < (p - *ptr); i++)
359 g_string_append_c (buff, *(*ptr + i));
360 *ptr = p;
362 /* Get pass the closing quote */
363 *ptr = g_utf8_next_char (*ptr);
365 value = g_string_free (buff, FALSE);
366 compressed_value = g_strcompress (value);
367 val = gdbmi_value_literal_new (NULL, compressed_value);
368 g_free (value);
369 g_free (compressed_value);
371 else if (isalpha (**ptr))
373 /* Value is assignment */
374 gchar *name;
375 gchar *p;
377 /* Get assignment name */
378 p = *ptr;
379 while (**ptr != '=')
381 if (**ptr == '\0')
383 g_warning ("Parse error: Invalid assignment name");
384 return NULL;
386 *ptr = g_utf8_next_char (*ptr);
388 name = g_strndup (p, *ptr - p);
390 /* Skip pass assignment operator */
391 *ptr = g_utf8_next_char (*ptr);
393 /* Retrieve assignment value */
394 val = gdbmi_value_parse_real (ptr);
395 if (val)
397 gdbmi_value_set_name (val, name);
399 else
401 g_warning ("Parse error: From parent");
403 g_free (name);
405 else if (**ptr == '{')
407 /* Value is hash */
408 gboolean error = FALSE;
410 *ptr = g_utf8_next_char (*ptr);
411 val = gdbmi_value_new (GDBMI_DATA_HASH, NULL);
412 while (**ptr != '}')
414 GDBMIValue *element;
415 element = gdbmi_value_parse_real (ptr);
416 if (element == NULL)
418 g_warning ("Parse error: From parent");
419 error = TRUE;
420 break;
422 if (gdbmi_value_get_name(element) == NULL)
424 g_warning ("Parse error: Hash element has no name => '%s'",
425 *ptr);
426 error = TRUE;
427 gdbmi_value_free (element);
428 break;
430 if (**ptr != ',' && **ptr != '}')
432 g_warning ("Parse error: Invalid element separator => '%s'",
433 *ptr);
434 error = TRUE;
435 gdbmi_value_free (element);
436 break;
438 gdbmi_value_hash_insert (val, gdbmi_value_get_name (element),
439 element);
441 /* Get pass the comma separator */
442 if (**ptr == ',')
443 *ptr = g_utf8_next_char (*ptr);
445 if (error)
447 gdbmi_value_free (val);
448 val = NULL;
450 /* Get pass the closing hash */
451 *ptr = g_utf8_next_char (*ptr);
453 else if (**ptr == '[')
455 /* Value is list */
456 gboolean error = FALSE;
458 *ptr = g_utf8_next_char (*ptr);
459 val = gdbmi_value_new (GDBMI_DATA_LIST, NULL);
460 while (**ptr != ']')
462 GDBMIValue *element;
463 element = gdbmi_value_parse_real (ptr);
464 if (element == NULL)
466 g_warning ("Parse error: From parent");
467 error = TRUE;
468 break;
470 if (**ptr != ',' && **ptr != ']')
472 g_warning ("Parse error: Invalid element separator => '%s'",
473 *ptr);
474 error = TRUE;
475 gdbmi_value_free (element);
476 break;
478 gdbmi_value_list_append (val, element);
480 /* Get pass the comma separator */
481 if (**ptr == ',')
482 *ptr = g_utf8_next_char (*ptr);
484 if (error)
486 gdbmi_value_free (val);
487 val = NULL;
489 /* Get pass the closing list */
490 *ptr = g_utf8_next_char (*ptr);
492 else
494 /* Should not be here -- Error */
495 g_warning ("Parse error: Should not be here => '%s'", *ptr);
497 return val;
500 G_MODULE_EXPORT GDBMIValue*
501 gdbmi_value_parse (const gchar *message)
503 GDBMIValue *val;
504 gchar *msg, *ptr;
506 g_return_val_if_fail (message != NULL, NULL);
508 if (strcasecmp(message, "^error") == 0)
510 g_warning ("GDB reported error without any error message");
511 return NULL; /* No message */
514 val = NULL;
515 if (strchr (message, ','))
517 msg = g_strconcat ("{", strchr (message, ',') + 1, "}", NULL);
518 ptr = msg;
519 val = gdbmi_value_parse_real (&ptr);
520 g_free (msg);
522 return val;