mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-08-21 16:38:54 +02:00
Fix type parsing for both GLib case and GLib.List
* girepository/girparser.c: Rewrite type parsing to handle both GLib parsing case as well as correctly handling GLib.List and friends. Don't try to treat e.g. ListStore as a List. svn path=/trunk/; revision=527
This commit is contained in:
220
girparser.c
220
girparser.c
@@ -216,20 +216,10 @@ state_switch (ParseContext *ctx, ParseState newstate)
|
|||||||
ctx->state = newstate;
|
ctx->state = newstate;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GIrNodeType * parse_type_internal (gchar *str, gchar **rest);
|
static GIrNodeType * parse_type_internal (const gchar *str, gchar **next, gboolean in_glib);
|
||||||
|
|
||||||
static GIrNodeType *
|
static GIrNodeType *
|
||||||
create_pointer ()
|
parse_type_internal (const gchar *str, char **next, gboolean in_glib)
|
||||||
{
|
|
||||||
char *pointer = g_strdup ("any");
|
|
||||||
char *pointer_rest;
|
|
||||||
GIrNodeType *ret = parse_type_internal (pointer, &pointer_rest);
|
|
||||||
g_free (pointer);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static GIrNodeType *
|
|
||||||
parse_type_internal (gchar *str, gchar **rest)
|
|
||||||
{
|
{
|
||||||
gint i;
|
gint i;
|
||||||
|
|
||||||
@@ -304,175 +294,186 @@ parse_type_internal (gchar *str, gchar **rest)
|
|||||||
};
|
};
|
||||||
|
|
||||||
gint n_basic = G_N_ELEMENTS (basic);
|
gint n_basic = G_N_ELEMENTS (basic);
|
||||||
gchar *start, *end;
|
gchar *temporary_type = NULL;
|
||||||
|
const gchar *start;
|
||||||
|
const gchar *end;
|
||||||
|
|
||||||
GIrNodeType *type;
|
GIrNodeType *type;
|
||||||
|
|
||||||
type = (GIrNodeType *)g_ir_node_new (G_IR_NODE_TYPE);
|
type = (GIrNodeType *)g_ir_node_new (G_IR_NODE_TYPE);
|
||||||
|
|
||||||
str = g_strstrip (str);
|
|
||||||
|
|
||||||
type->unparsed = g_strdup (str);
|
type->unparsed = g_strdup (str);
|
||||||
|
|
||||||
*rest = str;
|
if (in_glib)
|
||||||
|
{
|
||||||
|
if (g_str_has_prefix (str, "List<") ||
|
||||||
|
strcmp (str, "List") == 0)
|
||||||
|
{
|
||||||
|
temporary_type = g_strdup_printf ("GLib.List%s", str + 4);
|
||||||
|
str = temporary_type;
|
||||||
|
}
|
||||||
|
else if (g_str_has_prefix (str, "SList<") ||
|
||||||
|
strcmp (str, "SList") == 0)
|
||||||
|
{
|
||||||
|
temporary_type = g_strdup_printf ("GLib.SList%s", str + 5);
|
||||||
|
str = temporary_type;
|
||||||
|
}
|
||||||
|
else if (g_str_has_prefix (str, "HashTable<") ||
|
||||||
|
strcmp (str, "HashTable") == 0)
|
||||||
|
{
|
||||||
|
temporary_type = g_strdup_printf ("GLib.HashTable%s", str + 9);
|
||||||
|
str = temporary_type;
|
||||||
|
}
|
||||||
|
else if (g_str_has_prefix (str, "Error<") ||
|
||||||
|
strcmp (str, "Error") == 0)
|
||||||
|
{
|
||||||
|
temporary_type = g_strdup_printf ("GLib.Error%s", str + 5);
|
||||||
|
str = temporary_type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < n_basic; i++)
|
for (i = 0; i < n_basic; i++)
|
||||||
{
|
{
|
||||||
if (g_str_has_prefix (*rest, basic[i].str))
|
if (g_str_has_prefix (str, basic[i].str))
|
||||||
{
|
{
|
||||||
type->is_basic = TRUE;
|
type->is_basic = TRUE;
|
||||||
type->tag = basic[i].tag;
|
type->tag = basic[i].tag;
|
||||||
type->is_pointer = basic[i].pointer;
|
type->is_pointer = basic[i].pointer;
|
||||||
|
|
||||||
*rest += strlen(basic[i].str);
|
str += strlen(basic[i].str);
|
||||||
*rest = g_strchug (*rest);
|
if (*str == '*' && !type->is_pointer)
|
||||||
if (**rest == '*' && !type->is_pointer)
|
|
||||||
{
|
{
|
||||||
type->is_pointer = TRUE;
|
type->is_pointer = TRUE;
|
||||||
(*rest)++;
|
str++;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i < n_basic)
|
if (i < n_basic)
|
||||||
/* found a basic type */;
|
/* found a basic type */;
|
||||||
else if (g_str_has_prefix (*rest, "GLib.List") ||
|
else if (g_str_has_prefix (str, "GLib.List") ||
|
||||||
g_str_has_prefix (*rest, "GLib.SList") ||
|
g_str_has_prefix (str, "GLib.SList"))
|
||||||
g_str_has_prefix (*rest, "List") ||
|
|
||||||
g_str_has_prefix (*rest, "SList"))
|
|
||||||
{
|
{
|
||||||
if (g_str_has_prefix (*rest, "GLib."))
|
str += strlen ("GLib.");
|
||||||
*rest += strlen ("GLib.");
|
if (g_str_has_prefix (str, "List"))
|
||||||
if (g_str_has_prefix (*rest, "List"))
|
|
||||||
{
|
{
|
||||||
type->tag = GI_TYPE_TAG_GLIST;
|
type->tag = GI_TYPE_TAG_GLIST;
|
||||||
type->is_glist = TRUE;
|
type->is_glist = TRUE;
|
||||||
type->is_pointer = TRUE;
|
type->is_pointer = TRUE;
|
||||||
*rest += strlen ("List");
|
str += strlen ("List");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
type->tag = GI_TYPE_TAG_GSLIST;
|
type->tag = GI_TYPE_TAG_GSLIST;
|
||||||
type->is_gslist = TRUE;
|
type->is_gslist = TRUE;
|
||||||
type->is_pointer = TRUE;
|
type->is_pointer = TRUE;
|
||||||
*rest += strlen ("SList");
|
str += strlen ("SList");
|
||||||
}
|
}
|
||||||
|
|
||||||
*rest = g_strchug (*rest);
|
if (*str == '<')
|
||||||
|
|
||||||
if (**rest == '<')
|
|
||||||
{
|
{
|
||||||
(*rest)++;
|
(str)++;
|
||||||
|
char *rest;
|
||||||
type->parameter_type1 = parse_type_internal (*rest, rest);
|
|
||||||
|
type->parameter_type1 = parse_type_internal (str, &rest, in_glib);
|
||||||
if (type->parameter_type1 == NULL)
|
if (type->parameter_type1 == NULL)
|
||||||
goto error;
|
goto error;
|
||||||
|
str = rest;
|
||||||
|
|
||||||
*rest = g_strchug (*rest);
|
if (str[0] != '>')
|
||||||
|
|
||||||
if ((*rest)[0] != '>')
|
|
||||||
goto error;
|
goto error;
|
||||||
(*rest)++;
|
(str)++;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
type->parameter_type1 = create_pointer ();
|
type->parameter_type1 = parse_type_internal ("any", NULL, in_glib);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (g_str_has_prefix (*rest, "HashTable") ||
|
else if (g_str_has_prefix (str, "GLib.HashTable"))
|
||||||
g_str_has_prefix (*rest, "GLib.HashTable"))
|
|
||||||
{
|
{
|
||||||
if (g_str_has_prefix (*rest, "GLib."))
|
str += strlen ("GLib.");
|
||||||
*rest += strlen ("GLib.");
|
|
||||||
|
|
||||||
type->tag = GI_TYPE_TAG_GHASH;
|
type->tag = GI_TYPE_TAG_GHASH;
|
||||||
type->is_ghashtable = TRUE;
|
type->is_ghashtable = TRUE;
|
||||||
type->is_pointer = TRUE;
|
type->is_pointer = TRUE;
|
||||||
*rest += strlen ("HashTable");
|
str += strlen ("HashTable");
|
||||||
|
|
||||||
*rest = g_strchug (*rest);
|
if (*str == '<')
|
||||||
|
|
||||||
if (**rest == '<')
|
|
||||||
{
|
{
|
||||||
(*rest)++;
|
char *rest;
|
||||||
|
(str)++;
|
||||||
|
|
||||||
type->parameter_type1 = parse_type_internal (*rest, rest);
|
type->parameter_type1 = parse_type_internal (str, &rest, in_glib);
|
||||||
if (type->parameter_type1 == NULL)
|
if (type->parameter_type1 == NULL)
|
||||||
goto error;
|
goto error;
|
||||||
|
str = rest;
|
||||||
|
|
||||||
*rest = g_strchug (*rest);
|
if (str[0] != ',')
|
||||||
|
|
||||||
if ((*rest)[0] != ',')
|
|
||||||
goto error;
|
goto error;
|
||||||
(*rest)++;
|
(str)++;
|
||||||
|
|
||||||
type->parameter_type2 = parse_type_internal (*rest, rest);
|
type->parameter_type2 = parse_type_internal (str, &rest, in_glib);
|
||||||
if (type->parameter_type2 == NULL)
|
if (type->parameter_type2 == NULL)
|
||||||
goto error;
|
goto error;
|
||||||
|
str = rest;
|
||||||
|
|
||||||
if ((*rest)[0] != '>')
|
if ((str)[0] != '>')
|
||||||
goto error;
|
goto error;
|
||||||
(*rest)++;
|
(str)++;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
type->parameter_type1 = create_pointer ();
|
type->parameter_type1 = parse_type_internal ("any", NULL, in_glib);
|
||||||
type->parameter_type2 = create_pointer ();
|
type->parameter_type2 = parse_type_internal ("any", NULL, in_glib);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (g_str_has_prefix (*rest, "GLib.Error")
|
else if (g_str_has_prefix (str, "GLib.Error"))
|
||||||
|| g_str_has_prefix (*rest, "Error"))
|
|
||||||
{
|
{
|
||||||
if (g_str_has_prefix (*rest, "GLib."))
|
str += strlen ("GLib.");
|
||||||
*rest += strlen ("GLib.");
|
|
||||||
|
|
||||||
type->tag = GI_TYPE_TAG_ERROR;
|
type->tag = GI_TYPE_TAG_ERROR;
|
||||||
type->is_error = TRUE;
|
type->is_error = TRUE;
|
||||||
type->is_pointer = TRUE;
|
type->is_pointer = TRUE;
|
||||||
*rest += strlen ("GError");
|
str += strlen ("Error");
|
||||||
|
|
||||||
*rest = g_strchug (*rest);
|
if (*str == '<')
|
||||||
|
|
||||||
if (**rest == '<')
|
|
||||||
{
|
{
|
||||||
(*rest)++;
|
(str)++;
|
||||||
|
char *tmp;
|
||||||
|
|
||||||
end = strchr (*rest, '>');
|
end = strchr (str, '>');
|
||||||
str = g_strndup (*rest, end - *rest);
|
tmp = g_strndup (str, end - str);
|
||||||
type->errors = g_strsplit (str, ",", 0);
|
type->errors = g_strsplit (tmp, ",", 0);
|
||||||
g_free (str);
|
g_free (tmp);
|
||||||
|
|
||||||
*rest = end + 1;
|
str = end;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
type->tag = GI_TYPE_TAG_INTERFACE;
|
type->tag = GI_TYPE_TAG_INTERFACE;
|
||||||
type->is_interface = TRUE;
|
type->is_interface = TRUE;
|
||||||
start = *rest;
|
start = str;
|
||||||
|
|
||||||
/* must be an interface type */
|
/* must be an interface type */
|
||||||
while (g_ascii_isalnum (**rest) ||
|
while (g_ascii_isalnum (*str) ||
|
||||||
**rest == '.' ||
|
*str == '.' ||
|
||||||
**rest == '-' ||
|
*str == '-' ||
|
||||||
**rest == '_' ||
|
*str == '_' ||
|
||||||
**rest == ':')
|
*str == ':')
|
||||||
(*rest)++;
|
(str)++;
|
||||||
|
|
||||||
type->interface = g_strndup (start, *rest - start);
|
type->interface = g_strndup (start, str - start);
|
||||||
|
|
||||||
*rest = g_strchug (*rest);
|
if (*str == '*')
|
||||||
if (**rest == '*')
|
|
||||||
{
|
{
|
||||||
type->is_pointer = TRUE;
|
type->is_pointer = TRUE;
|
||||||
(*rest)++;
|
(str)++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*rest = g_strchug (*rest);
|
if (g_str_has_prefix (str, "["))
|
||||||
if (g_str_has_prefix (*rest, "["))
|
|
||||||
{
|
{
|
||||||
GIrNodeType *array;
|
GIrNodeType *array;
|
||||||
|
|
||||||
@@ -488,15 +489,13 @@ parse_type_internal (gchar *str, gchar **rest)
|
|||||||
array->has_length = FALSE;
|
array->has_length = FALSE;
|
||||||
array->length = 0;
|
array->length = 0;
|
||||||
|
|
||||||
if (!g_str_has_prefix (*rest, "[]"))
|
if (!g_str_has_prefix (str, "[]"))
|
||||||
{
|
{
|
||||||
gchar *end, *str, **opts;
|
gchar *end, *tmp, **opts;
|
||||||
|
|
||||||
end = strchr (*rest, ']');
|
end = strchr (str, ']');
|
||||||
str = g_strndup (*rest + 1, (end - *rest) - 1);
|
tmp = g_strndup (str + 1, (end - str) - 1);
|
||||||
opts = g_strsplit (str, ",", 0);
|
opts = g_strsplit (tmp, ",", 0);
|
||||||
|
|
||||||
*rest = end + 1;
|
|
||||||
|
|
||||||
for (i = 0; opts[i]; i++)
|
for (i = 0; opts[i]; i++)
|
||||||
{
|
{
|
||||||
@@ -515,19 +514,24 @@ parse_type_internal (gchar *str, gchar **rest)
|
|||||||
g_strfreev (vals);
|
g_strfreev (vals);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_free (str);
|
g_free (tmp);
|
||||||
g_strfreev (opts);
|
g_strfreev (opts);
|
||||||
|
|
||||||
|
str = end;
|
||||||
}
|
}
|
||||||
|
|
||||||
type = array;
|
type = array;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (next)
|
||||||
|
*next = (char*)str;
|
||||||
g_assert (type->tag >= 0 && type->tag <= GI_TYPE_TAG_ERROR);
|
g_assert (type->tag >= 0 && type->tag <= GI_TYPE_TAG_ERROR);
|
||||||
|
g_free (temporary_type);
|
||||||
return type;
|
return type;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
g_ir_node_free ((GIrNode *)type);
|
g_ir_node_free ((GIrNode *)type);
|
||||||
|
g_free (temporary_type);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -556,14 +560,18 @@ static GIrNodeType *
|
|||||||
parse_type (ParseContext *ctx, const gchar *type)
|
parse_type (ParseContext *ctx, const gchar *type)
|
||||||
{
|
{
|
||||||
gchar *str;
|
gchar *str;
|
||||||
gchar *rest;
|
|
||||||
GIrNodeType *node;
|
GIrNodeType *node;
|
||||||
|
gboolean in_glib;
|
||||||
|
gboolean matched_special = FALSE;
|
||||||
|
|
||||||
|
in_glib = strcmp (ctx->namespace, "GLib") == 0;
|
||||||
|
|
||||||
type = resolve_aliases (ctx, type);
|
type = resolve_aliases (ctx, type);
|
||||||
str = g_strdup (type);
|
node = parse_type_internal (type, NULL, in_glib);
|
||||||
node = parse_type_internal (str, &rest);
|
if (node)
|
||||||
g_free (str);
|
g_debug ("Parsed type: %s => %d", type, node->tag);
|
||||||
g_debug ("Parsed type: %s => %d", type, node->tag);
|
else
|
||||||
|
g_critical ("Failed to parse type: '%s'", type);
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user