Пример #1
0
void gdb_mi_record_free(struct gdb_mi_record *record)
{
	if (! record)
		return;
	g_free(record->token);
	g_free(record->klass);
	gdb_mi_result_free(record->first, TRUE);
	g_free(record);
}
Пример #2
0
void gdb_mi_result_free(struct gdb_mi_result *res, gboolean next)
{
	if (! res)
		return;
	g_free(res->var);
	gdb_mi_value_free(res->val);
	if (next)
		gdb_mi_result_free(res->next, next);
	g_free(res);
}
Пример #3
0
void gdb_mi_value_free(struct gdb_mi_value *val)
{
	if (! val)
		return;
	switch (val->type)
	{
		case GDB_MI_VAL_STRING:
			g_free(val->v.string);
			break;

		case GDB_MI_VAL_LIST:
			gdb_mi_result_free(val->v.list, TRUE);
			break;
	}
	g_free(val);
}
Пример #4
0
/* parses: cstring | list | tuple
 * Actually, this is more permissive and allows mixed tuples/lists */
static struct gdb_mi_value *parse_value(const gchar **p)
{
	struct gdb_mi_value *val = g_malloc0(sizeof *val);
	if (**p == '"')
	{
		val->type = GDB_MI_VAL_STRING;
		val->string = parse_cstring(p);
	}
	else if (**p == '{' || **p == '[')
	{
		struct gdb_mi_result *prev = NULL;
		val->type = GDB_MI_VAL_LIST;
		gchar end = **p == '{' ? '}' : ']';
		(*p)++;
		while (**p && **p != end)
		{
			struct gdb_mi_result *item = g_malloc0(sizeof *item);
			while (g_ascii_isspace(**p)) (*p)++;
			if ((item->val = parse_value(p)) ||
				parse_result(item, p))
			{
				if (prev)
					prev->next = item;
				else
					val->list = item;
				prev = item;
			}
			else
			{
				gdb_mi_result_free(item, TRUE);
				break;
			}
			while (g_ascii_isspace(**p)) (*p)++;
			if (**p != ',') break;
			(*p)++;
		}
		if (**p == end)
			(*p)++;
	}
	else
	{
		gdb_mi_value_free(val);
		val = NULL;
	}
	return val;
}
Пример #5
0
void gdb_mi_value_free(struct gdb_mi_value *val)
{
	if (! val)
		return;
	switch (val->type)
	{
		case GDB_MI_VAL_STRING:
			g_free(val->string);
			g_warn_if_fail(val->list == NULL);
			break;

		case GDB_MI_VAL_LIST:
			gdb_mi_result_free(val->list, TRUE);
			g_warn_if_fail(val->string == NULL);
			break;
	}
	g_free(val);
}
Пример #6
0
/* parses: async-record | stream-record | result-record
 * note: post-value data is ignored.
 * 
 * FIXME: that's NOT exactly what the GDB docs call an output, and that's not
 *        exactly what a line could be.  The GDB docs state that a line can
 *        contain more than one stream-record, as it's not terminated by a
 *        newline, and as it defines:
 * 
 *        output ==> 
 *            ( out-of-band-record )* [ result-record ] "(gdb)" nl
 *        out-of-band-record ==>
 *            async-record | stream-record
 *        stream-record ==>
 *            console-stream-output | target-stream-output | log-stream-output
 *        console-stream-output ==>
 *            "~" c-string
 *        target-stream-output ==>
 *            "@" c-string
 *        log-stream-output ==>
 *            "&" c-string
 * 
 *        so as none of the stream-outputs are terminated by a newline, and the
 *        parser here only extracts the first record it will fail with combined
 *        records in one line.
 */
struct gdb_mi_record *gdb_mi_record_parse(const gchar *line)
{
	struct gdb_mi_record *record = g_malloc0(sizeof *record);

	/* FIXME: prompt detection should not really be useful, especially not as a
	 * special case, as the prompt should always follow an (optional) record */
	if (is_prompt(line))
		record->type = GDB_MI_TYPE_PROMPT;
	else
	{
		/* extract token */
		const gchar *token_end = line;
		for (token_end = line; g_ascii_isdigit(*token_end); token_end++)
			;
		if (token_end > line)
		{
			record->token = g_strndup(line, (gsize)(token_end - line));
			line = token_end;
			while (g_ascii_isspace(*line)) line++;
		}

		/* extract record */
		record->type = *line;
		if (*line) ++line;
		while (g_ascii_isspace(*line)) line++;
		switch (record->type)
		{
			case '~':
			case '@':
			case '&':
				/* FIXME: although the syntax description in the docs are clear,
				 * the "GDB/MI Stream Records" section does not agree with it,
				 * widening the input to:
				 * 
				 * > [string-output] is either raw text (with an implicit new
				 * > line) or a quoted C string (which does not contain an
				 * > implicit newline).
				 * 
				 * This adds "raw text" to "c-string"... so? */
				record->klass = parse_cstring(&line);
				break;
			case '^':
			case '*':
			case '+':
			case '=':
			{
				struct gdb_mi_result *prev = NULL;
				record->klass = parse_string(&line);
				while (*line)
				{
					while (g_ascii_isspace(*line)) line++;
					if (*line != ',')
						break;
					else
					{
						struct gdb_mi_result *res = g_malloc0(sizeof *res);
						line++;
						while (g_ascii_isspace(*line)) line++;
						if (!parse_result(res, &line))
						{
							g_warning("failed to parse result");
							gdb_mi_result_free(res, TRUE);
							break;
						}
						if (prev)
							prev->next = res;
						else
							record->first = res;
						prev = res;
					}
				}
				break;
			}
			default:
				/* FIXME: what to do with invalid prefix? */
				record->type = GDB_MI_TYPE_PROMPT;
		}
	}

	return record;
}