1 /* GObject introspection: A parser for the XML GIR format
3 * Copyright (C) 2008 Philip Van Hoof
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
26 #include "girparser.h"
27 #include "girmodule.h"
41 STATE_FUNCTION_RETURN,
42 STATE_FUNCTION_PARAMETERS,
43 STATE_FUNCTION_PARAMETER, /* 10 */
48 STATE_INTERFACE_PROPERTY, /* 15 */
49 STATE_INTERFACE_FIELD,
53 STATE_BOXED_FIELD, /* 20 */
58 STATE_UNION_FIELD, /* 25 */
59 STATE_NAMESPACE_CONSTANT,
61 STATE_INTERFACE_CONSTANT,
66 typedef struct _ParseContext ParseContext;
70 ParseState prev_state;
72 const char * const*includes;
75 GList *include_modules;
76 gboolean prefix_aliases;
79 GHashTable *disguised_structures;
81 const char *namespace;
82 GIrModule *current_module;
83 GIrNode *current_node;
84 GIrNode *current_typed;
87 GList *type_parameters;
91 static void start_element_handler (GMarkupParseContext *context,
92 const gchar *element_name,
93 const gchar **attribute_names,
94 const gchar **attribute_values,
97 static void end_element_handler (GMarkupParseContext *context,
98 const gchar *element_name,
101 static void text_handler (GMarkupParseContext *context,
106 static void cleanup (GMarkupParseContext *context,
110 static GMarkupParser parser =
112 start_element_handler,
120 start_alias (GMarkupParseContext *context,
121 const gchar *element_name,
122 const gchar **attribute_names,
123 const gchar **attribute_values,
127 static const gchar *find_attribute (const gchar *name,
128 const gchar **attribute_names,
129 const gchar **attribute_values);
132 firstpass_start_element_handler (GMarkupParseContext *context,
133 const gchar *element_name,
134 const gchar **attribute_names,
135 const gchar **attribute_values,
139 ParseContext *ctx = user_data;
141 if (strcmp (element_name, "alias") == 0)
143 start_alias (context, element_name, attribute_names, attribute_values,
146 else if (strcmp (element_name, "record") == 0)
149 const gchar *disguised;
151 name = find_attribute ("name", attribute_names, attribute_values);
152 disguised = find_attribute ("disguised", attribute_names, attribute_values);
154 if (disguised && strcmp (disguised, "1") == 0)
158 if (ctx->prefix_aliases)
160 key = g_strdup_printf ("%s.%s", ctx->namespace, name);
164 key = g_strdup (name);
167 g_hash_table_replace (ctx->disguised_structures, key, GINT_TO_POINTER (1));
173 firstpass_end_element_handler (GMarkupParseContext *context,
174 const gchar *element_name,
180 static GMarkupParser firstpass_parser =
182 firstpass_start_element_handler,
183 firstpass_end_element_handler,
190 locate_gir (const char *name, const char *version, const char * const* extra_paths)
192 const gchar *const *datadirs;
193 const gchar *const *dir;
197 datadirs = g_get_system_data_dirs ();
199 girname = g_strdup_printf ("%s-%s.gir", name, version);
201 for (dir = datadirs; *dir; dir++)
203 path = g_build_filename (*dir, "gir", girname, NULL);
204 if (g_file_test (path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))
209 if (extra_paths != NULL)
211 for (dir = extra_paths; *dir; dir++)
213 path = g_build_filename (*dir, girname, NULL);
214 if (g_file_test (path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))
224 #define MISSING_ATTRIBUTE(ctx,error,element,attribute) \
226 int line_number, char_number; \
227 g_markup_parse_context_get_position (context, &line_number, &char_number); \
228 g_set_error (error, \
230 G_MARKUP_ERROR_INVALID_CONTENT, \
231 "Line %d, character %d: The attribute '%s' on the element '%s' must be specified", \
232 line_number, char_number, attribute, element); \
236 backtrace_stderr (void)
238 #if defined(HAVE_BACKTRACE) && defined(HAVE_BACKTRACE_SYMBOLS)
244 size = backtrace (array, 50);
245 strings = (char**) backtrace_symbols (array, size);
247 fprintf (stderr, "--- BACKTRACE (%zd frames) ---\n", size);
249 for (i = 0; i < size; i++)
250 fprintf (stderr, "%s\n", strings[i]);
252 fprintf (stderr, "--- END BACKTRACE ---\n", size);
260 find_attribute (const gchar *name,
261 const gchar **attribute_names,
262 const gchar **attribute_values)
266 for (i = 0; attribute_names[i] != NULL; i++)
267 if (strcmp (attribute_names[i], name) == 0)
268 return attribute_values[i];
274 state_switch (ParseContext *ctx, ParseState newstate)
276 g_debug ("State: %d", newstate);
277 ctx->prev_state = ctx->state;
278 ctx->state = newstate;
281 static GIrNodeType * parse_type_internal (const gchar *str, gchar **next, gboolean in_glib,
282 gboolean in_gobject);
290 static BasicTypeInfo basic_types[] = {
291 { "none", GI_TYPE_TAG_VOID, 0 },
292 { "any", GI_TYPE_TAG_VOID, 1 },
294 { "bool", GI_TYPE_TAG_BOOLEAN, 0 },
295 { "char", GI_TYPE_TAG_INT8, 0 },
296 { "int8", GI_TYPE_TAG_INT8, 0 },
297 { "uint8", GI_TYPE_TAG_UINT8, 0 },
298 { "int16", GI_TYPE_TAG_INT16, 0 },
299 { "uint16", GI_TYPE_TAG_UINT16, 0 },
300 { "int32", GI_TYPE_TAG_INT32, 0 },
301 { "uint32", GI_TYPE_TAG_UINT32, 0 },
302 { "int64", GI_TYPE_TAG_INT64, 0 },
303 { "uint64", GI_TYPE_TAG_UINT64, 0 },
304 { "int", GI_TYPE_TAG_INT, 0 },
305 { "uint", GI_TYPE_TAG_UINT, 0 },
306 { "long", GI_TYPE_TAG_LONG, 0 },
307 { "ulong", GI_TYPE_TAG_ULONG, 0 },
308 { "ssize_t", GI_TYPE_TAG_SSIZE, 0 },
309 { "ssize", GI_TYPE_TAG_SSIZE, 0 },
310 { "size_t", GI_TYPE_TAG_SIZE, 0 },
311 { "size", GI_TYPE_TAG_SIZE, 0 },
312 { "float", GI_TYPE_TAG_FLOAT, 0 },
313 { "double", GI_TYPE_TAG_DOUBLE, 0 },
314 { "time_t", GI_TYPE_TAG_TIME_T, 0 },
315 { "GType", GI_TYPE_TAG_GTYPE, 0 },
316 { "utf8", GI_TYPE_TAG_UTF8, 1 },
317 { "filename", GI_TYPE_TAG_FILENAME,1 },
320 static const BasicTypeInfo *
321 parse_basic (const char *str)
324 gint n_basic = G_N_ELEMENTS (basic_types);
326 for (i = 0; i < n_basic; i++)
328 if (g_str_has_prefix (str, basic_types[i].str))
329 return &(basic_types[i]);
335 parse_type_internal (const gchar *str, char **next, gboolean in_glib,
338 const BasicTypeInfo *basic;
340 char *temporary_type = NULL;
342 type = (GIrNodeType *)g_ir_node_new (G_IR_NODE_TYPE);
344 type->unparsed = g_strdup (str);
346 /* See comment below on GLib.List handling */
347 if (in_gobject && strcmp (str, "Type") == 0)
349 temporary_type = g_strdup ("GLib.Type");
350 str = temporary_type;
353 basic = parse_basic (str);
356 type->is_basic = TRUE;
357 type->tag = basic->tag;
358 type->is_pointer = basic->pointer;
360 str += strlen(basic->str);
364 /* If we're inside GLib, handle "List" etc. by prefixing with
365 * "GLib." so the parsing code below doesn't have to get more
368 if (g_str_has_prefix (str, "List<") ||
369 strcmp (str, "List") == 0)
371 temporary_type = g_strdup_printf ("GLib.List%s", str + 4);
372 str = temporary_type;
374 else if (g_str_has_prefix (str, "SList<") ||
375 strcmp (str, "SList") == 0)
377 temporary_type = g_strdup_printf ("GLib.SList%s", str + 5);
378 str = temporary_type;
380 else if (g_str_has_prefix (str, "HashTable<") ||
381 strcmp (str, "HashTable") == 0)
383 temporary_type = g_strdup_printf ("GLib.HashTable%s", str + 9);
384 str = temporary_type;
386 else if (g_str_has_prefix (str, "Error<") ||
387 strcmp (str, "Error") == 0)
389 temporary_type = g_strdup_printf ("GLib.Error%s", str + 5);
390 str = temporary_type;
395 /* found a basic type */;
396 else if (g_str_has_prefix (str, "GLib.List") ||
397 g_str_has_prefix (str, "GLib.SList"))
399 str += strlen ("GLib.");
400 if (g_str_has_prefix (str, "List"))
402 type->tag = GI_TYPE_TAG_GLIST;
403 type->is_glist = TRUE;
404 type->is_pointer = TRUE;
405 str += strlen ("List");
409 type->tag = GI_TYPE_TAG_GSLIST;
410 type->is_gslist = TRUE;
411 type->is_pointer = TRUE;
412 str += strlen ("SList");
415 else if (g_str_has_prefix (str, "GLib.HashTable"))
417 str += strlen ("GLib.");
419 type->tag = GI_TYPE_TAG_GHASH;
420 type->is_ghashtable = TRUE;
421 type->is_pointer = TRUE;
422 str += strlen ("HashTable");
424 else if (g_str_has_prefix (str, "GLib.Error"))
426 str += strlen ("GLib.");
428 type->tag = GI_TYPE_TAG_ERROR;
429 type->is_error = TRUE;
430 type->is_pointer = TRUE;
431 str += strlen ("Error");
438 end = strchr (str, '>');
439 tmp = g_strndup (str, end - str);
440 type->errors = g_strsplit (tmp, ",", 0);
448 type->tag = GI_TYPE_TAG_INTERFACE;
449 type->is_interface = TRUE;
450 const char *start = str;
452 /* must be an interface type */
453 while (g_ascii_isalnum (*str) ||
460 type->interface = g_strndup (start, str - start);
465 g_assert (type->tag >= 0 && type->tag <= GI_TYPE_TAG_ERROR);
466 g_free (temporary_type);
470 g_ir_node_free ((GIrNode *)type);
471 g_free (temporary_type);
476 resolve_aliases (ParseContext *ctx, const gchar *type)
480 GSList *seen_values = NULL;
482 seen_values = g_slist_prepend (seen_values, (char*)type);
483 while (g_hash_table_lookup_extended (ctx->aliases, type, &orig, &value))
485 g_debug ("Resolved: %s => %s", type, (char*)value);
487 if (g_slist_find_custom (seen_values, type,
488 (GCompareFunc)strcmp) != NULL)
490 seen_values = g_slist_prepend (seen_values, (gchar*)type);
492 g_slist_free (seen_values);
497 parse_type (ParseContext *ctx, const gchar *type)
500 const BasicTypeInfo *basic;
501 gboolean in_glib, in_gobject;
503 in_glib = strcmp (ctx->namespace, "GLib") == 0;
504 in_gobject = strcmp (ctx->namespace, "GObject") == 0;
506 /* Do not search aliases for basic types */
507 basic = parse_basic (type);
509 type = resolve_aliases (ctx, type);
511 node = parse_type_internal (type, NULL, in_glib, in_gobject);
513 g_debug ("Parsed type: %s => %d", type, node->tag);
515 g_critical ("Failed to parse type: '%s'", type);
521 start_glib_boxed (GMarkupParseContext *context,
522 const gchar *element_name,
523 const gchar **attribute_names,
524 const gchar **attribute_values,
529 const gchar *typename;
530 const gchar *typeinit;
531 const gchar *deprecated;
534 if (!(strcmp (element_name, "glib:boxed") == 0 &&
535 ctx->state == STATE_NAMESPACE))
538 name = find_attribute ("glib:name", attribute_names, attribute_values);
539 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
540 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
541 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
545 MISSING_ATTRIBUTE (context, error, element_name, "glib:name");
548 else if (typename == NULL)
550 MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
553 else if (typeinit == NULL)
555 MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
559 boxed = (GIrNodeBoxed *) g_ir_node_new (G_IR_NODE_BOXED);
561 ((GIrNode *)boxed)->name = g_strdup (name);
562 boxed->gtype_name = g_strdup (typename);
563 boxed->gtype_init = g_strdup (typeinit);
565 boxed->deprecated = TRUE;
567 boxed->deprecated = FALSE;
569 ctx->current_node = (GIrNode *)boxed;
570 ctx->current_module->entries =
571 g_list_append (ctx->current_module->entries, boxed);
573 state_switch (ctx, STATE_BOXED);
579 start_function (GMarkupParseContext *context,
580 const gchar *element_name,
581 const gchar **attribute_names,
582 const gchar **attribute_values,
588 const gchar *deprecated;
590 GIrNodeFunction *function;
591 gboolean found = FALSE;
595 case STATE_NAMESPACE:
596 found = (strcmp (element_name, "function") == 0 ||
597 strcmp (element_name, "callback") == 0);
603 found = strcmp (element_name, "constructor") == 0;
605 case STATE_INTERFACE:
607 strcmp (element_name, "method") == 0 ||
608 strcmp (element_name, "callback") == 0);
617 name = find_attribute ("name", attribute_names, attribute_values);
618 symbol = find_attribute ("c:identifier", attribute_names, attribute_values);
619 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
620 throws = find_attribute ("throws", attribute_names, attribute_values);
624 MISSING_ATTRIBUTE (context, error, element_name, "name");
627 else if (strcmp (element_name, "callback") != 0 && symbol == NULL)
629 MISSING_ATTRIBUTE (context, error, element_name, "c:identifier");
633 function = (GIrNodeFunction *) g_ir_node_new (G_IR_NODE_FUNCTION);
635 ((GIrNode *)function)->name = g_strdup (name);
636 function->symbol = g_strdup (symbol);
637 function->parameters = NULL;
639 function->deprecated = TRUE;
641 function->deprecated = FALSE;
643 if (strcmp (element_name, "method") == 0 ||
644 strcmp (element_name, "constructor") == 0)
646 function->is_method = TRUE;
648 if (strcmp (element_name, "constructor") == 0)
649 function->is_constructor = TRUE;
651 function->is_constructor = FALSE;
655 function->is_method = FALSE;
656 function->is_setter = FALSE;
657 function->is_getter = FALSE;
658 function->is_constructor = FALSE;
659 if (strcmp (element_name, "callback") == 0)
660 ((GIrNode *)function)->type = G_IR_NODE_CALLBACK;
663 if (throws && strcmp (throws, "1") == 0)
664 function->throws = TRUE;
666 function->throws = FALSE;
668 if (ctx->current_node == NULL)
670 ctx->current_module->entries =
671 g_list_append (ctx->current_module->entries, function);
674 switch (ctx->current_node->type)
676 case G_IR_NODE_INTERFACE:
677 case G_IR_NODE_OBJECT:
679 GIrNodeInterface *iface;
681 iface = (GIrNodeInterface *)ctx->current_node;
682 iface->members = g_list_append (iface->members, function);
685 case G_IR_NODE_BOXED:
689 boxed = (GIrNodeBoxed *)ctx->current_node;
690 boxed->members = g_list_append (boxed->members, function);
693 case G_IR_NODE_STRUCT:
695 GIrNodeStruct *struct_;
697 struct_ = (GIrNodeStruct *)ctx->current_node;
698 struct_->members = g_list_append (struct_->members, function); }
700 case G_IR_NODE_UNION:
702 GIrNodeUnion *union_;
704 union_ = (GIrNodeUnion *)ctx->current_node;
705 union_->members = g_list_append (union_->members, function);
709 g_assert_not_reached ();
712 ctx->current_node = (GIrNode *)function;
713 state_switch (ctx, STATE_FUNCTION);
719 parse_param_transfer (GIrNodeParam *param, const gchar *transfer)
721 if (transfer == NULL)
723 g_warning ("required attribute 'transfer-ownership' missing");
725 else if (strcmp (transfer, "none") == 0)
727 param->transfer = FALSE;
728 param->shallow_transfer = FALSE;
730 else if (strcmp (transfer, "container") == 0)
732 param->transfer = FALSE;
733 param->shallow_transfer = TRUE;
735 else if (strcmp (transfer, "full") == 0)
737 param->transfer = TRUE;
738 param->shallow_transfer = FALSE;
742 g_warning ("Unknown transfer-ownership value: %s", transfer);
747 start_parameter (GMarkupParseContext *context,
748 const gchar *element_name,
749 const gchar **attribute_names,
750 const gchar **attribute_values,
755 const gchar *direction;
758 const gchar *optional;
759 const gchar *allow_none;
760 const gchar *transfer;
763 if (!(strcmp (element_name, "parameter") == 0 &&
764 ctx->state == STATE_FUNCTION_PARAMETERS))
767 name = find_attribute ("name", attribute_names, attribute_values);
768 direction = find_attribute ("direction", attribute_names, attribute_values);
769 retval = find_attribute ("retval", attribute_names, attribute_values);
770 dipper = find_attribute ("dipper", attribute_names, attribute_values);
771 optional = find_attribute ("optional", attribute_names, attribute_values);
772 allow_none = find_attribute ("allow-none", attribute_names, attribute_values);
773 transfer = find_attribute ("transfer-ownership", attribute_names, attribute_values);
778 param = (GIrNodeParam *)g_ir_node_new (G_IR_NODE_PARAM);
780 ctx->current_typed = (GIrNode*) param;
781 ctx->current_typed->name = g_strdup (name);
783 state_switch (ctx, STATE_FUNCTION_PARAMETER);
785 if (direction && strcmp (direction, "out") == 0)
790 else if (direction && strcmp (direction, "inout") == 0)
801 if (retval && strcmp (retval, "1") == 0)
802 param->retval = TRUE;
804 param->retval = FALSE;
806 if (dipper && strcmp (dipper, "1") == 0)
807 param->dipper = TRUE;
809 param->dipper = FALSE;
811 if (optional && strcmp (optional, "1") == 0)
812 param->optional = TRUE;
814 param->optional = FALSE;
816 if (allow_none && strcmp (allow_none, "1") == 0)
817 param->allow_none = TRUE;
819 param->allow_none = FALSE;
821 parse_param_transfer (param, transfer);
823 ((GIrNode *)param)->name = g_strdup (name);
825 switch (ctx->current_node->type)
827 case G_IR_NODE_FUNCTION:
828 case G_IR_NODE_CALLBACK:
830 GIrNodeFunction *func;
832 func = (GIrNodeFunction *)ctx->current_node;
833 func->parameters = g_list_append (func->parameters, param);
836 case G_IR_NODE_SIGNAL:
838 GIrNodeSignal *signal;
840 signal = (GIrNodeSignal *)ctx->current_node;
841 signal->parameters = g_list_append (signal->parameters, param);
844 case G_IR_NODE_VFUNC:
848 vfunc = (GIrNodeVFunc *)ctx->current_node;
849 vfunc->parameters = g_list_append (vfunc->parameters, param);
853 g_assert_not_reached ();
860 start_field (GMarkupParseContext *context,
861 const gchar *element_name,
862 const gchar **attribute_names,
863 const gchar **attribute_values,
868 const gchar *readable;
869 const gchar *writable;
881 case STATE_INTERFACE:
887 if (strcmp (element_name, "field") != 0)
890 name = find_attribute ("name", attribute_names, attribute_values);
891 readable = find_attribute ("readable", attribute_names, attribute_values);
892 writable = find_attribute ("writable", attribute_names, attribute_values);
893 bits = find_attribute ("bits", attribute_names, attribute_values);
894 branch = find_attribute ("branch", attribute_names, attribute_values);
895 offset = find_attribute ("offset", attribute_names, attribute_values);
899 MISSING_ATTRIBUTE (context, error, element_name, "name");
903 field = (GIrNodeField *)g_ir_node_new (G_IR_NODE_FIELD);
904 ctx->current_typed = (GIrNode*) field;
905 ((GIrNode *)field)->name = g_strdup (name);
906 /* Fields are assumed to be read-only.
907 * (see also girwriter.py and generate.c)
909 field->readable = readable == NULL || strcmp (readable, "0") == 0;
910 field->writable = writable != NULL && strcmp (writable, "1") == 0;
913 field->bits = atoi (bits);
918 field->offset = atoi (offset);
922 switch (ctx->current_node->type)
924 case G_IR_NODE_OBJECT:
926 GIrNodeInterface *iface;
928 iface = (GIrNodeInterface *)ctx->current_node;
929 iface->members = g_list_append (iface->members, field);
930 state_switch (ctx, STATE_CLASS_FIELD);
933 case G_IR_NODE_INTERFACE:
935 GIrNodeInterface *iface;
937 iface = (GIrNodeInterface *)ctx->current_node;
938 iface->members = g_list_append (iface->members, field);
939 state_switch (ctx, STATE_INTERFACE_FIELD);
942 case G_IR_NODE_BOXED:
946 boxed = (GIrNodeBoxed *)ctx->current_node;
947 boxed->members = g_list_append (boxed->members, field);
948 state_switch (ctx, STATE_BOXED_FIELD);
951 case G_IR_NODE_STRUCT:
953 GIrNodeStruct *struct_;
955 struct_ = (GIrNodeStruct *)ctx->current_node;
956 struct_->members = g_list_append (struct_->members, field);
957 state_switch (ctx, STATE_STRUCT_FIELD);
960 case G_IR_NODE_UNION:
962 GIrNodeUnion *union_;
964 union_ = (GIrNodeUnion *)ctx->current_node;
965 union_->members = g_list_append (union_->members, field);
968 GIrNodeConstant *constant;
970 constant = (GIrNodeConstant *) g_ir_node_new (G_IR_NODE_CONSTANT);
971 ((GIrNode *)constant)->name = g_strdup (name);
972 constant->value = g_strdup (branch);
973 constant->type = union_->discriminator_type;
974 constant->deprecated = FALSE;
976 union_->discriminators = g_list_append (union_->discriminators, constant);
978 state_switch (ctx, STATE_UNION_FIELD);
982 g_assert_not_reached ();
989 start_alias (GMarkupParseContext *context,
990 const gchar *element_name,
991 const gchar **attribute_names,
992 const gchar **attribute_values,
1001 name = find_attribute ("name", attribute_names, attribute_values);
1004 MISSING_ATTRIBUTE (context, error, element_name, "name");
1008 target = find_attribute ("target", attribute_names, attribute_values);
1011 MISSING_ATTRIBUTE (context, error, element_name, "target");
1015 value = g_strdup (target);
1016 if (ctx->prefix_aliases)
1018 key = g_strdup_printf ("%s.%s", ctx->namespace, name);
1019 if (!strchr (target, '.'))
1021 const BasicTypeInfo *basic = parse_basic (target);
1025 /* For non-basic types, re-qualify the interface */
1026 value = g_strdup_printf ("%s.%s", ctx->namespace, target);
1032 key = g_strdup (name);
1034 g_hash_table_insert (ctx->aliases, key, value);
1040 start_enum (GMarkupParseContext *context,
1041 const gchar *element_name,
1042 const gchar **attribute_names,
1043 const gchar **attribute_values,
1047 if ((strcmp (element_name, "enumeration") == 0 && ctx->state == STATE_NAMESPACE) ||
1048 (strcmp (element_name, "bitfield") == 0 && ctx->state == STATE_NAMESPACE))
1051 const gchar *typename;
1052 const gchar *typeinit;
1053 const gchar *deprecated;
1055 name = find_attribute ("name", attribute_names, attribute_values);
1056 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
1057 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
1058 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1061 MISSING_ATTRIBUTE (context, error, element_name, "name");
1066 if (strcmp (element_name, "enumeration") == 0)
1067 enum_ = (GIrNodeEnum *) g_ir_node_new (G_IR_NODE_ENUM);
1069 enum_ = (GIrNodeEnum *) g_ir_node_new (G_IR_NODE_FLAGS);
1070 ((GIrNode *)enum_)->name = g_strdup (name);
1071 enum_->gtype_name = g_strdup (typename);
1072 enum_->gtype_init = g_strdup (typeinit);
1074 enum_->deprecated = TRUE;
1076 enum_->deprecated = FALSE;
1078 ctx->current_node = (GIrNode *) enum_;
1079 ctx->current_module->entries =
1080 g_list_append (ctx->current_module->entries, enum_);
1082 state_switch (ctx, STATE_ENUM);
1091 start_property (GMarkupParseContext *context,
1092 const gchar *element_name,
1093 const gchar **attribute_names,
1094 const gchar **attribute_values,
1098 if (strcmp (element_name, "property") == 0 &&
1099 (ctx->state == STATE_CLASS ||
1100 ctx->state == STATE_INTERFACE))
1103 const gchar *readable;
1104 const gchar *writable;
1105 const gchar *construct;
1106 const gchar *construct_only;
1108 name = find_attribute ("name", attribute_names, attribute_values);
1109 readable = find_attribute ("readable", attribute_names, attribute_values);
1110 writable = find_attribute ("writable", attribute_names, attribute_values);
1111 construct = find_attribute ("construct", attribute_names, attribute_values);
1112 construct_only = find_attribute ("construct-only", attribute_names, attribute_values);
1115 MISSING_ATTRIBUTE (context, error, element_name, "name");
1118 GIrNodeProperty *property;
1119 GIrNodeInterface *iface;
1121 property = (GIrNodeProperty *) g_ir_node_new (G_IR_NODE_PROPERTY);
1122 ctx->current_typed = (GIrNode*) property;
1124 ((GIrNode *)property)->name = g_strdup (name);
1126 /* Assume properties are readable */
1127 if (readable == NULL || strcmp (readable, "1") == 0)
1128 property->readable = TRUE;
1130 property->readable = FALSE;
1131 if (writable && strcmp (writable, "1") == 0)
1132 property->writable = TRUE;
1134 property->writable = FALSE;
1135 if (construct && strcmp (construct, "1") == 0)
1136 property->construct = TRUE;
1138 property->construct = FALSE;
1139 if (construct_only && strcmp (construct_only, "1") == 0)
1140 property->construct_only = TRUE;
1142 property->construct_only = FALSE;
1144 iface = (GIrNodeInterface *)ctx->current_node;
1145 iface->members = g_list_append (iface->members, property);
1147 if (ctx->state == STATE_CLASS)
1148 state_switch (ctx, STATE_CLASS_PROPERTY);
1149 else if (ctx->state == STATE_INTERFACE)
1150 state_switch (ctx, STATE_INTERFACE_PROPERTY);
1152 g_assert_not_reached ();
1161 parse_value (const gchar *str)
1165 /* FIXME just a quick hack */
1166 shift_op = strstr (str, "<<");
1172 base = strtol (str, NULL, 10);
1173 shift = strtol (shift_op + 3, NULL, 10);
1175 return base << shift;
1178 return strtol (str, NULL, 10);
1184 start_member (GMarkupParseContext *context,
1185 const gchar *element_name,
1186 const gchar **attribute_names,
1187 const gchar **attribute_values,
1191 if (strcmp (element_name, "member") == 0 &&
1192 ctx->state == STATE_ENUM)
1196 const gchar *deprecated;
1198 name = find_attribute ("name", attribute_names, attribute_values);
1199 value = find_attribute ("value", attribute_names, attribute_values);
1200 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1203 MISSING_ATTRIBUTE (context, error, element_name, "name");
1207 GIrNodeValue *value_;
1209 value_ = (GIrNodeValue *) g_ir_node_new (G_IR_NODE_VALUE);
1211 ((GIrNode *)value_)->name = g_strdup (name);
1213 value_->value = parse_value (value);
1216 value_->deprecated = TRUE;
1218 value_->deprecated = FALSE;
1220 enum_ = (GIrNodeEnum *)ctx->current_node;
1221 enum_->values = g_list_append (enum_->values, value_);
1230 start_constant (GMarkupParseContext *context,
1231 const gchar *element_name,
1232 const gchar **attribute_names,
1233 const gchar **attribute_values,
1237 if (strcmp (element_name, "constant") == 0 &&
1238 (ctx->state == STATE_NAMESPACE ||
1239 ctx->state == STATE_CLASS ||
1240 ctx->state == STATE_INTERFACE))
1244 const gchar *deprecated;
1246 name = find_attribute ("name", attribute_names, attribute_values);
1247 value = find_attribute ("value", attribute_names, attribute_values);
1248 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1251 MISSING_ATTRIBUTE (context, error, element_name, "name");
1252 else if (value == NULL)
1253 MISSING_ATTRIBUTE (context, error, element_name, "value");
1256 GIrNodeConstant *constant;
1258 constant = (GIrNodeConstant *) g_ir_node_new (G_IR_NODE_CONSTANT);
1260 ((GIrNode *)constant)->name = g_strdup (name);
1261 constant->value = g_strdup (value);
1263 ctx->current_typed = (GIrNode*) constant;
1266 constant->deprecated = TRUE;
1268 constant->deprecated = FALSE;
1270 if (ctx->state == STATE_NAMESPACE)
1272 ctx->current_node = (GIrNode *) constant;
1273 ctx->current_module->entries =
1274 g_list_append (ctx->current_module->entries, constant);
1278 GIrNodeInterface *iface;
1280 iface = (GIrNodeInterface *)ctx->current_node;
1281 iface->members = g_list_append (iface->members, constant);
1286 case STATE_NAMESPACE:
1287 state_switch (ctx, STATE_NAMESPACE_CONSTANT);
1290 state_switch (ctx, STATE_CLASS_CONSTANT);
1292 case STATE_INTERFACE:
1293 state_switch (ctx, STATE_INTERFACE_CONSTANT);
1296 g_assert_not_reached ();
1307 start_errordomain (GMarkupParseContext *context,
1308 const gchar *element_name,
1309 const gchar **attribute_names,
1310 const gchar **attribute_values,
1314 if (strcmp (element_name, "errordomain") == 0 &&
1315 ctx->state == STATE_NAMESPACE)
1318 const gchar *getquark;
1320 const gchar *deprecated;
1322 name = find_attribute ("name", attribute_names, attribute_values);
1323 getquark = find_attribute ("get-quark", attribute_names, attribute_values);
1324 codes = find_attribute ("codes", attribute_names, attribute_values);
1325 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1328 MISSING_ATTRIBUTE (context, error, element_name, "name");
1329 else if (getquark == NULL)
1330 MISSING_ATTRIBUTE (context, error, element_name, "getquark");
1331 else if (codes == NULL)
1332 MISSING_ATTRIBUTE (context, error, element_name, "codes");
1335 GIrNodeErrorDomain *domain;
1337 domain = (GIrNodeErrorDomain *) g_ir_node_new (G_IR_NODE_ERROR_DOMAIN);
1339 ((GIrNode *)domain)->name = g_strdup (name);
1340 domain->getquark = g_strdup (getquark);
1341 domain->codes = g_strdup (codes);
1344 domain->deprecated = TRUE;
1346 domain->deprecated = FALSE;
1348 ctx->current_node = (GIrNode *) domain;
1349 ctx->current_module->entries =
1350 g_list_append (ctx->current_module->entries, domain);
1352 state_switch (ctx, STATE_ERRORDOMAIN);
1361 start_interface (GMarkupParseContext *context,
1362 const gchar *element_name,
1363 const gchar **attribute_names,
1364 const gchar **attribute_values,
1368 if (strcmp (element_name, "interface") == 0 &&
1369 ctx->state == STATE_NAMESPACE)
1372 const gchar *typename;
1373 const gchar *typeinit;
1374 const gchar *deprecated;
1376 name = find_attribute ("name", attribute_names, attribute_values);
1377 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
1378 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
1379 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1382 MISSING_ATTRIBUTE (context, error, element_name, "name");
1383 else if (typename == NULL)
1384 MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
1385 else if (typeinit == NULL)
1386 MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
1389 GIrNodeInterface *iface;
1391 iface = (GIrNodeInterface *) g_ir_node_new (G_IR_NODE_INTERFACE);
1392 ((GIrNode *)iface)->name = g_strdup (name);
1393 iface->gtype_name = g_strdup (typename);
1394 iface->gtype_init = g_strdup (typeinit);
1396 iface->deprecated = TRUE;
1398 iface->deprecated = FALSE;
1400 ctx->current_node = (GIrNode *) iface;
1401 ctx->current_module->entries =
1402 g_list_append (ctx->current_module->entries, iface);
1404 state_switch (ctx, STATE_INTERFACE);
1414 start_class (GMarkupParseContext *context,
1415 const gchar *element_name,
1416 const gchar **attribute_names,
1417 const gchar **attribute_values,
1421 if (strcmp (element_name, "class") == 0 &&
1422 ctx->state == STATE_NAMESPACE)
1425 const gchar *parent;
1426 const gchar *typename;
1427 const gchar *typeinit;
1428 const gchar *deprecated;
1429 const gchar *abstract;
1431 name = find_attribute ("name", attribute_names, attribute_values);
1432 parent = find_attribute ("parent", attribute_names, attribute_values);
1433 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
1434 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
1435 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1436 abstract = find_attribute ("abstract", attribute_names, attribute_values);
1439 MISSING_ATTRIBUTE (context, error, element_name, "name");
1440 else if (typename == NULL)
1441 MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
1442 else if (typeinit == NULL && strcmp (typename, "GObject"))
1443 MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
1446 GIrNodeInterface *iface;
1448 iface = (GIrNodeInterface *) g_ir_node_new (G_IR_NODE_OBJECT);
1449 ((GIrNode *)iface)->name = g_strdup (name);
1450 iface->gtype_name = g_strdup (typename);
1451 iface->gtype_init = g_strdup (typeinit);
1452 iface->parent = g_strdup (parent);
1454 iface->deprecated = TRUE;
1456 iface->deprecated = FALSE;
1458 iface->abstract = abstract && strcmp (abstract, "1") == 0;
1460 ctx->current_node = (GIrNode *) iface;
1461 ctx->current_module->entries =
1462 g_list_append (ctx->current_module->entries, iface);
1464 state_switch (ctx, STATE_CLASS);
1473 start_type (GMarkupParseContext *context,
1474 const gchar *element_name,
1475 const gchar **attribute_names,
1476 const gchar **attribute_values,
1483 gboolean is_varargs;
1484 GIrNodeType *typenode;
1486 is_array = strcmp (element_name, "array") == 0;
1487 is_varargs = strcmp (element_name, "varargs") == 0;
1489 if (!(is_array || is_varargs || (strcmp (element_name, "type") == 0)))
1492 if (ctx->state == STATE_TYPE)
1495 ctx->type_stack = g_list_prepend (ctx->type_stack, ctx->type_parameters);
1496 ctx->type_parameters = NULL;
1498 else if (ctx->state == STATE_FUNCTION_PARAMETER ||
1499 ctx->state == STATE_FUNCTION_RETURN ||
1500 ctx->state == STATE_STRUCT_FIELD ||
1501 ctx->state == STATE_UNION_FIELD ||
1502 ctx->state == STATE_CLASS_PROPERTY ||
1503 ctx->state == STATE_CLASS_FIELD ||
1504 ctx->state == STATE_INTERFACE_FIELD ||
1505 ctx->state == STATE_INTERFACE_PROPERTY ||
1506 ctx->state == STATE_BOXED_FIELD ||
1507 ctx->state == STATE_NAMESPACE_CONSTANT ||
1508 ctx->state == STATE_CLASS_CONSTANT ||
1509 ctx->state == STATE_INTERFACE_CONSTANT
1512 state_switch (ctx, STATE_TYPE);
1513 ctx->type_depth = 1;
1516 switch (ctx->current_node->type)
1518 case G_IR_NODE_FUNCTION:
1519 case G_IR_NODE_CALLBACK:
1521 GIrNodeFunction *func = (GIrNodeFunction *)ctx->current_node;
1522 func->is_varargs = TRUE;
1525 case G_IR_NODE_VFUNC:
1527 GIrNodeVFunc *vfunc = (GIrNodeVFunc *)ctx->current_node;
1528 vfunc->is_varargs = TRUE;
1531 /* list others individually rather than with default: so that compiler
1532 * warns if new node types are added without adding them to the switch
1534 case G_IR_NODE_INVALID:
1535 case G_IR_NODE_ENUM:
1536 case G_IR_NODE_FLAGS:
1537 case G_IR_NODE_CONSTANT:
1538 case G_IR_NODE_ERROR_DOMAIN:
1539 case G_IR_NODE_PARAM:
1540 case G_IR_NODE_TYPE:
1541 case G_IR_NODE_PROPERTY:
1542 case G_IR_NODE_SIGNAL:
1543 case G_IR_NODE_VALUE:
1544 case G_IR_NODE_FIELD:
1545 case G_IR_NODE_XREF:
1546 case G_IR_NODE_STRUCT:
1547 case G_IR_NODE_BOXED:
1548 case G_IR_NODE_OBJECT:
1549 case G_IR_NODE_INTERFACE:
1550 case G_IR_NODE_UNION:
1551 g_assert_not_reached ();
1555 ctx->type_stack = NULL;
1556 ctx->type_parameters = NULL;
1559 if (!ctx->current_typed)
1563 G_MARKUP_ERROR_INVALID_CONTENT,
1564 "The element <type> is invalid here");
1577 typenode = (GIrNodeType *)g_ir_node_new (G_IR_NODE_TYPE);
1579 typenode->tag = GI_TYPE_TAG_ARRAY;
1580 typenode->is_pointer = TRUE;
1581 typenode->is_array = TRUE;
1583 zero = find_attribute ("zero-terminated", attribute_names, attribute_values);
1584 len = find_attribute ("length", attribute_names, attribute_values);
1585 size = find_attribute ("fixed-size", attribute_names, attribute_values);
1587 typenode->zero_terminated = !(zero && strcmp (zero, "1") != 0);
1588 typenode->has_length = len != NULL;
1589 typenode->length = typenode->has_length ? atoi (len) : -1;
1591 typenode->has_size = size != NULL;
1592 typenode->size = typenode->has_size ? atoi (size) : -1;
1596 gboolean is_pointer;
1597 name = find_attribute ("name", attribute_names, attribute_values);
1600 MISSING_ATTRIBUTE (context, error, element_name, "name");
1602 ctype = find_attribute ("c:type", attribute_names, attribute_values);
1603 if (ctype != NULL && strchr (ctype, '*'))
1608 typenode = parse_type (ctx, name);
1610 /* A 'disguised' structure is one where the c:type is a typedef that
1611 * doesn't look like a pointer, but is internally.
1613 if (typenode->tag == GI_TYPE_TAG_INTERFACE &&
1614 g_hash_table_lookup (ctx->disguised_structures, typenode->interface) != NULL)
1618 typenode->is_pointer = is_pointer;
1621 ctx->type_parameters = g_list_append (ctx->type_parameters, typenode);
1627 end_type_top (ParseContext *ctx)
1629 GIrNodeType *typenode;
1631 if (!ctx->type_parameters)
1634 typenode = (GIrNodeType*)ctx->type_parameters->data;
1636 /* Default to pointer for unspecified containers */
1637 if (typenode->tag == GI_TYPE_TAG_ARRAY ||
1638 typenode->tag == GI_TYPE_TAG_GLIST ||
1639 typenode->tag == GI_TYPE_TAG_GSLIST)
1641 if (typenode->parameter_type1 == NULL)
1642 typenode->parameter_type1 = parse_type (ctx, "any");
1644 else if (typenode->tag == GI_TYPE_TAG_GHASH)
1646 if (typenode->parameter_type1 == NULL)
1648 typenode->parameter_type1 = parse_type (ctx, "any");
1649 typenode->parameter_type2 = parse_type (ctx, "any");
1653 switch (ctx->current_typed->type)
1655 case G_IR_NODE_PARAM:
1657 GIrNodeParam *param = (GIrNodeParam *)ctx->current_typed;
1658 param->type = typenode;
1661 case G_IR_NODE_FIELD:
1663 GIrNodeField *field = (GIrNodeField *)ctx->current_typed;
1664 field->type = typenode;
1667 case G_IR_NODE_PROPERTY:
1669 GIrNodeProperty *property = (GIrNodeProperty *) ctx->current_typed;
1670 property->type = typenode;
1673 case G_IR_NODE_CONSTANT:
1675 GIrNodeConstant *constant = (GIrNodeConstant *)ctx->current_typed;
1676 constant->type = typenode;
1680 g_printerr("current node is %d\n", ctx->current_node->type);
1681 g_assert_not_reached ();
1683 g_list_free (ctx->type_parameters);
1686 ctx->type_depth = 0;
1687 ctx->type_parameters = NULL;
1688 ctx->current_typed = NULL;
1692 end_type_recurse (ParseContext *ctx)
1694 GIrNodeType *parent;
1695 GIrNodeType *param = NULL;
1697 parent = (GIrNodeType *) ((GList*)ctx->type_stack->data)->data;
1698 if (ctx->type_parameters)
1699 param = (GIrNodeType *) ctx->type_parameters->data;
1701 if (parent->tag == GI_TYPE_TAG_ARRAY ||
1702 parent->tag == GI_TYPE_TAG_GLIST ||
1703 parent->tag == GI_TYPE_TAG_GSLIST)
1705 g_assert (param != NULL);
1707 if (parent->parameter_type1 == NULL)
1708 parent->parameter_type1 = param;
1710 g_assert_not_reached ();
1712 else if (parent->tag == GI_TYPE_TAG_GHASH)
1714 g_assert (param != NULL);
1716 if (parent->parameter_type1 == NULL)
1717 parent->parameter_type1 = param;
1718 else if (parent->parameter_type2 == NULL)
1719 parent->parameter_type2 = param;
1721 g_assert_not_reached ();
1723 g_list_free (ctx->type_parameters);
1724 ctx->type_parameters = (GList *)ctx->type_stack->data;
1725 ctx->type_stack = g_list_delete_link (ctx->type_stack, ctx->type_stack);
1729 end_type (ParseContext *ctx)
1731 if (ctx->type_depth == 1)
1734 state_switch (ctx, ctx->prev_state);
1738 end_type_recurse (ctx);
1744 start_return_value (GMarkupParseContext *context,
1745 const gchar *element_name,
1746 const gchar **attribute_names,
1747 const gchar **attribute_values,
1751 if (strcmp (element_name, "return-value") == 0 &&
1752 ctx->state == STATE_FUNCTION)
1754 GIrNodeParam *param;
1755 const gchar *transfer;
1757 param = (GIrNodeParam *)g_ir_node_new (G_IR_NODE_PARAM);
1760 param->retval = TRUE;
1762 ctx->current_typed = (GIrNode*) param;
1764 state_switch (ctx, STATE_FUNCTION_RETURN);
1766 transfer = find_attribute ("transfer-ownership", attribute_names, attribute_values);
1767 parse_param_transfer (param, transfer);
1769 switch (ctx->current_node->type)
1771 case G_IR_NODE_FUNCTION:
1772 case G_IR_NODE_CALLBACK:
1774 GIrNodeFunction *func = (GIrNodeFunction *)ctx->current_node;
1775 func->result = param;
1778 case G_IR_NODE_SIGNAL:
1780 GIrNodeSignal *signal = (GIrNodeSignal *)ctx->current_node;
1781 signal->result = param;
1784 case G_IR_NODE_VFUNC:
1786 GIrNodeVFunc *vfunc = (GIrNodeVFunc *)ctx->current_node;
1787 vfunc->result = param;
1791 g_assert_not_reached ();
1801 start_implements (GMarkupParseContext *context,
1802 const gchar *element_name,
1803 const gchar **attribute_names,
1804 const gchar **attribute_values,
1808 GIrNodeInterface *iface;
1811 if (strcmp (element_name, "implements") != 0 ||
1812 !(ctx->state == STATE_CLASS))
1815 state_switch (ctx, STATE_IMPLEMENTS);
1817 name = find_attribute ("name", attribute_names, attribute_values);
1820 MISSING_ATTRIBUTE (context, error, element_name, "name");
1824 iface = (GIrNodeInterface *)ctx->current_node;
1825 iface->interfaces = g_list_append (iface->interfaces, g_strdup (name));
1831 start_glib_signal (GMarkupParseContext *context,
1832 const gchar *element_name,
1833 const gchar **attribute_names,
1834 const gchar **attribute_values,
1838 if (strcmp (element_name, "glib:signal") == 0 &&
1839 (ctx->state == STATE_CLASS ||
1840 ctx->state == STATE_INTERFACE))
1844 const gchar *no_recurse;
1845 const gchar *detailed;
1846 const gchar *action;
1847 const gchar *no_hooks;
1848 const gchar *has_class_closure;
1850 name = find_attribute ("name", attribute_names, attribute_values);
1851 when = find_attribute ("when", attribute_names, attribute_values);
1852 no_recurse = find_attribute ("no-recurse", attribute_names, attribute_values);
1853 detailed = find_attribute ("detailed", attribute_names, attribute_values);
1854 action = find_attribute ("action", attribute_names, attribute_values);
1855 no_hooks = find_attribute ("no-hooks", attribute_names, attribute_values);
1856 has_class_closure = find_attribute ("has-class-closure", attribute_names, attribute_values);
1859 MISSING_ATTRIBUTE (context, error, element_name, "name");
1862 GIrNodeInterface *iface;
1863 GIrNodeSignal *signal;
1865 signal = (GIrNodeSignal *)g_ir_node_new (G_IR_NODE_SIGNAL);
1867 ((GIrNode *)signal)->name = g_strdup (name);
1869 signal->run_first = FALSE;
1870 signal->run_last = FALSE;
1871 signal->run_cleanup = FALSE;
1872 if (when == NULL || strcmp (when, "LAST") == 0)
1873 signal->run_last = TRUE;
1874 else if (strcmp (when, "FIRST") == 0)
1875 signal->run_first = TRUE;
1877 signal->run_cleanup = TRUE;
1879 if (no_recurse && strcmp (no_recurse, "1") == 0)
1880 signal->no_recurse = TRUE;
1882 signal->no_recurse = FALSE;
1883 if (detailed && strcmp (detailed, "1") == 0)
1884 signal->detailed = TRUE;
1886 signal->detailed = FALSE;
1887 if (action && strcmp (action, "1") == 0)
1888 signal->action = TRUE;
1890 signal->action = FALSE;
1891 if (no_hooks && strcmp (no_hooks, "1") == 0)
1892 signal->no_hooks = TRUE;
1894 signal->no_hooks = FALSE;
1895 if (has_class_closure && strcmp (has_class_closure, "1") == 0)
1896 signal->has_class_closure = TRUE;
1898 signal->has_class_closure = FALSE;
1900 iface = (GIrNodeInterface *)ctx->current_node;
1901 iface->members = g_list_append (iface->members, signal);
1903 ctx->current_node = (GIrNode *)signal;
1904 state_switch (ctx, STATE_FUNCTION);
1913 start_vfunc (GMarkupParseContext *context,
1914 const gchar *element_name,
1915 const gchar **attribute_names,
1916 const gchar **attribute_values,
1920 if (strcmp (element_name, "vfunc") == 0 &&
1921 (ctx->state == STATE_CLASS ||
1922 ctx->state == STATE_INTERFACE))
1925 const gchar *must_chain_up;
1926 const gchar *override;
1927 const gchar *is_class_closure;
1928 const gchar *offset;
1930 name = find_attribute ("name", attribute_names, attribute_values);
1931 must_chain_up = find_attribute ("must-chain-up", attribute_names, attribute_values);
1932 override = find_attribute ("override", attribute_names, attribute_values);
1933 is_class_closure = find_attribute ("is-class-closure", attribute_names, attribute_values);
1934 offset = find_attribute ("offset", attribute_names, attribute_values);
1937 MISSING_ATTRIBUTE (context, error, element_name, "name");
1940 GIrNodeInterface *iface;
1941 GIrNodeVFunc *vfunc;
1943 vfunc = (GIrNodeVFunc *)g_ir_node_new (G_IR_NODE_VFUNC);
1945 ((GIrNode *)vfunc)->name = g_strdup (name);
1947 if (must_chain_up && strcmp (must_chain_up, "1") == 0)
1948 vfunc->must_chain_up = TRUE;
1950 vfunc->must_chain_up = FALSE;
1952 if (override && strcmp (override, "always") == 0)
1954 vfunc->must_be_implemented = TRUE;
1955 vfunc->must_not_be_implemented = FALSE;
1957 else if (override && strcmp (override, "never") == 0)
1959 vfunc->must_be_implemented = FALSE;
1960 vfunc->must_not_be_implemented = TRUE;
1964 vfunc->must_be_implemented = FALSE;
1965 vfunc->must_not_be_implemented = FALSE;
1968 if (is_class_closure && strcmp (is_class_closure, "1") == 0)
1969 vfunc->is_class_closure = TRUE;
1971 vfunc->is_class_closure = FALSE;
1974 vfunc->offset = atoi (offset);
1978 iface = (GIrNodeInterface *)ctx->current_node;
1979 iface->members = g_list_append (iface->members, vfunc);
1981 ctx->current_node = (GIrNode *)vfunc;
1982 state_switch (ctx, STATE_FUNCTION);
1992 start_struct (GMarkupParseContext *context,
1993 const gchar *element_name,
1994 const gchar **attribute_names,
1995 const gchar **attribute_values,
1999 if (strcmp (element_name, "record") == 0 &&
2000 ctx->state == STATE_NAMESPACE)
2003 const gchar *deprecated;
2004 const gchar *disguised;
2005 const gchar *gtype_name;
2006 const gchar *gtype_init;
2007 GIrNodeStruct *struct_;
2009 name = find_attribute ("name", attribute_names, attribute_values);
2010 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
2011 disguised = find_attribute ("disguised", attribute_names, attribute_values);
2012 gtype_name = find_attribute ("glib:type-name", attribute_names, attribute_values);
2013 gtype_init = find_attribute ("glib:get-type", attribute_names, attribute_values);
2017 MISSING_ATTRIBUTE (context, error, element_name, "name");
2020 if ((gtype_name == NULL && gtype_init != NULL))
2022 MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
2025 if ((gtype_name != NULL && gtype_init == NULL))
2027 MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
2031 struct_ = (GIrNodeStruct *) g_ir_node_new (G_IR_NODE_STRUCT);
2033 ((GIrNode *)struct_)->name = g_strdup (name);
2035 struct_->deprecated = TRUE;
2037 struct_->deprecated = FALSE;
2039 if (disguised && strcmp (disguised, "1") == 0)
2040 struct_->disguised = TRUE;
2042 struct_->gtype_name = g_strdup (gtype_name);
2043 struct_->gtype_init = g_strdup (gtype_init);
2045 ctx->current_node = (GIrNode *)struct_;
2046 ctx->current_module->entries =
2047 g_list_append (ctx->current_module->entries, struct_);
2049 state_switch (ctx, STATE_STRUCT);
2057 start_union (GMarkupParseContext *context,
2058 const gchar *element_name,
2059 const gchar **attribute_names,
2060 const gchar **attribute_values,
2064 if (strcmp (element_name, "union") == 0 &&
2065 ctx->state == STATE_NAMESPACE)
2068 const gchar *deprecated;
2069 const gchar *typename;
2070 const gchar *typeinit;
2072 name = find_attribute ("name", attribute_names, attribute_values);
2073 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
2074 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
2075 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
2078 MISSING_ATTRIBUTE (context, error, element_name, "name");
2081 GIrNodeUnion *union_;
2083 union_ = (GIrNodeUnion *) g_ir_node_new (G_IR_NODE_UNION);
2085 ((GIrNode *)union_)->name = g_strdup (name);
2086 union_->gtype_name = g_strdup (typename);
2087 union_->gtype_init = g_strdup (typeinit);
2089 union_->deprecated = TRUE;
2091 union_->deprecated = FALSE;
2093 ctx->current_node = (GIrNode *)union_;
2094 ctx->current_module->entries =
2095 g_list_append (ctx->current_module->entries, union_);
2097 state_switch (ctx, STATE_UNION);
2105 start_discriminator (GMarkupParseContext *context,
2106 const gchar *element_name,
2107 const gchar **attribute_names,
2108 const gchar **attribute_values,
2112 if (strcmp (element_name, "discriminator") == 0 &&
2113 ctx->state == STATE_UNION)
2116 const gchar *offset;
2118 type = find_attribute ("type", attribute_names, attribute_values);
2119 offset = find_attribute ("offset", attribute_names, attribute_values);
2121 MISSING_ATTRIBUTE (context, error, element_name, "type");
2122 else if (offset == NULL)
2123 MISSING_ATTRIBUTE (context, error, element_name, "offset");
2125 ((GIrNodeUnion *)ctx->current_node)->discriminator_type
2126 = parse_type (ctx, type);
2127 ((GIrNodeUnion *)ctx->current_node)->discriminator_offset
2138 parse_include (GMarkupParseContext *context,
2141 const char *version,
2144 ParseContext sub_ctx = { 0 };
2148 gboolean success = FALSE;
2151 for (l = ctx->include_modules; l; l = l->next)
2153 GIrModule *m = l->data;
2155 if (strcmp (m->name, name) == 0)
2157 if (strcmp (m->version, version) == 0)
2165 G_MARKUP_ERROR_INVALID_CONTENT,
2166 "Module '%s' imported with conflicting versions '%s' and '%s'",
2167 name, m->version, version);
2173 girpath = locate_gir (name, version, ctx->includes);
2175 if (girpath == NULL)
2179 G_MARKUP_ERROR_INVALID_CONTENT,
2180 "Could not find GIR file '%s.gir'; check XDG_DATA_DIRS or use --includedir",
2185 g_debug ("Parsing include %s", girpath);
2187 if (!g_file_get_contents (girpath, &buffer, &length, error))
2194 sub_ctx.state = STATE_START;
2195 sub_ctx.includes = ctx->includes;
2196 sub_ctx.prefix_aliases = TRUE;
2197 sub_ctx.namespace = name;
2198 sub_ctx.aliases = ctx->aliases;
2199 sub_ctx.disguised_structures = ctx->disguised_structures;
2200 sub_ctx.type_depth = 0;
2202 context = g_markup_parse_context_new (&firstpass_parser, 0, &sub_ctx, NULL);
2204 if (!g_markup_parse_context_parse (context, buffer, length, error))
2207 if (!g_markup_parse_context_end_parse (context, error))
2210 g_markup_parse_context_free (context);
2212 context = g_markup_parse_context_new (&parser, 0, &sub_ctx, NULL);
2213 if (!g_markup_parse_context_parse (context, buffer, length, error))
2216 if (!g_markup_parse_context_end_parse (context, error))
2222 ctx->include_modules = g_list_concat (ctx->include_modules,
2225 g_markup_parse_context_free (context);
2231 extern GLogLevelFlags logged_levels;
2234 start_element_handler (GMarkupParseContext *context,
2235 const gchar *element_name,
2236 const gchar **attribute_names,
2237 const gchar **attribute_values,
2241 ParseContext *ctx = user_data;
2242 gint line_number, char_number;
2244 if (logged_levels & G_LOG_LEVEL_DEBUG)
2246 GString *tags = g_string_new ("");
2248 for (i = 0; attribute_names[i]; i++)
2249 g_string_append_printf (tags, "%s=\"%s\" ",
2251 attribute_values[i]);
2255 g_string_insert_c (tags, 0, ' ');
2256 g_string_truncate (tags, tags->len - 1);
2258 g_debug ("<%s%s>", element_name, tags->str);
2259 g_string_free (tags, TRUE);
2262 switch (element_name[0])
2265 if (ctx->state == STATE_NAMESPACE && strcmp (element_name, "alias") == 0)
2267 state_switch (ctx, STATE_ALIAS);
2270 if (start_type (context, element_name,
2271 attribute_names, attribute_values,
2276 if (start_enum (context, element_name,
2277 attribute_names, attribute_values,
2282 if (start_function (context, element_name,
2283 attribute_names, attribute_values,
2286 else if (start_constant (context, element_name,
2287 attribute_names, attribute_values,
2290 else if (start_class (context, element_name,
2291 attribute_names, attribute_values,
2294 else if (strcmp (element_name, "class") == 0 &&
2295 ctx->state == STATE_REQUIRES)
2299 name = find_attribute ("name", attribute_names, attribute_values);
2302 MISSING_ATTRIBUTE (context, error, element_name, "name");
2305 GIrNodeInterface *iface;
2307 iface = (GIrNodeInterface *)ctx->current_node;
2308 iface ->prerequisites = g_list_append (iface->prerequisites, g_strdup (name));
2316 if (start_discriminator (context, element_name,
2317 attribute_names, attribute_values,
2323 if (start_enum (context, element_name,
2324 attribute_names, attribute_values,
2327 else if (start_errordomain (context, element_name,
2328 attribute_names, attribute_values,
2334 if (start_function (context, element_name,
2335 attribute_names, attribute_values,
2338 else if (start_field (context, element_name,
2339 attribute_names, attribute_values,
2345 if (start_glib_boxed (context, element_name,
2346 attribute_names, attribute_values,
2349 else if (start_glib_signal (context, element_name,
2350 attribute_names, attribute_values,
2356 if (strcmp (element_name, "include") == 0 &&
2357 ctx->state == STATE_REPOSITORY)
2360 const gchar *version;
2362 name = find_attribute ("name", attribute_names, attribute_values);
2363 version = find_attribute ("version", attribute_names, attribute_values);
2367 MISSING_ATTRIBUTE (context, error, element_name, "name");
2370 if (version == NULL)
2372 MISSING_ATTRIBUTE (context, error, element_name, "version");
2376 if (!parse_include (context, ctx, name, version, error))
2379 ctx->dependencies = g_list_prepend (ctx->dependencies,
2380 g_strdup_printf ("%s-%s", name, version));
2383 state_switch (ctx, STATE_INCLUDE);
2386 if (start_interface (context, element_name,
2387 attribute_names, attribute_values,
2390 else if (start_implements (context, element_name,
2391 attribute_names, attribute_values,
2397 if (start_function (context, element_name,
2398 attribute_names, attribute_values,
2401 else if (start_member (context, element_name,
2402 attribute_names, attribute_values,
2408 if (strcmp (element_name, "namespace") == 0 && ctx->state == STATE_REPOSITORY)
2410 const gchar *name, *version, *shared_library;
2412 name = find_attribute ("name", attribute_names, attribute_values);
2413 version = find_attribute ("version", attribute_names, attribute_values);
2414 shared_library = find_attribute ("shared-library", attribute_names, attribute_values);
2417 MISSING_ATTRIBUTE (context, error, element_name, "name");
2418 else if (version == NULL)
2419 MISSING_ATTRIBUTE (context, error, element_name, "version");
2422 ctx->current_module = g_ir_module_new (name, version, shared_library);
2423 ctx->modules = g_list_append (ctx->modules, ctx->current_module);
2424 ctx->current_module->dependencies = ctx->dependencies;
2425 ctx->current_module->include_modules = g_list_copy (ctx->include_modules);
2427 state_switch (ctx, STATE_NAMESPACE);
2434 if (start_property (context, element_name,
2435 attribute_names, attribute_values,
2438 else if (strcmp (element_name, "parameters") == 0 &&
2439 ctx->state == STATE_FUNCTION)
2441 state_switch (ctx, STATE_FUNCTION_PARAMETERS);
2445 else if (start_parameter (context, element_name,
2446 attribute_names, attribute_values,
2453 if (strcmp (element_name, "repository") == 0 && ctx->state == STATE_START)
2455 const gchar *version;
2457 version = find_attribute ("version", attribute_names, attribute_values);
2459 if (version == NULL)
2460 MISSING_ATTRIBUTE (context, error, element_name, "version");
2461 else if (strcmp (version, "1.0") != 0)
2464 G_MARKUP_ERROR_INVALID_CONTENT,
2465 "Unsupported version '%s'",
2468 state_switch (ctx, STATE_REPOSITORY);
2472 else if (start_return_value (context, element_name,
2473 attribute_names, attribute_values,
2476 else if (strcmp (element_name, "requires") == 0 &&
2477 ctx->state == STATE_INTERFACE)
2479 state_switch (ctx, STATE_REQUIRES);
2483 else if (start_struct (context, element_name,
2484 attribute_names, attribute_values,
2490 if (start_union (context, element_name,
2491 attribute_names, attribute_values,
2497 if (start_type (context, element_name,
2498 attribute_names, attribute_values,
2504 if (start_vfunc (context, element_name,
2505 attribute_names, attribute_values,
2508 if (start_type (context, element_name,
2509 attribute_names, attribute_values,
2515 g_markup_parse_context_get_position (context, &line_number, &char_number);
2517 if (error && *error == NULL)
2520 G_MARKUP_ERROR_UNKNOWN_ELEMENT,
2521 "Unexpected start tag '%s' on line %d char %d; current state=%d",
2523 line_number, char_number, ctx->state);
2528 g_markup_parse_context_get_position (context, &line_number, &char_number);
2530 fprintf (stderr, "Error at line %d, character %d: %s\n", line_number, char_number, (*error)->message);
2531 backtrace_stderr ();
2536 require_one_of_end_elements (GMarkupParseContext *context,
2538 const char *actual_name,
2543 int line_number, char_number;
2544 const char *expected;
2545 gboolean matched = FALSE;
2547 va_start (args, error);
2549 while ((expected = va_arg (args, const char*)) != NULL)
2551 if (strcmp (expected, actual_name) == 0)
2563 g_markup_parse_context_get_position (context, &line_number, &char_number);
2566 G_MARKUP_ERROR_INVALID_CONTENT,
2567 "Unexpected end tag '%s' on line %d char %d; current state=%d",
2569 line_number, char_number, ctx->state);
2575 require_end_element (GMarkupParseContext *context,
2577 const char *expected_name,
2578 const char *actual_name,
2581 return require_one_of_end_elements (context, ctx, actual_name, error, expected_name, NULL);
2585 end_element_handler (GMarkupParseContext *context,
2586 const gchar *element_name,
2590 ParseContext *ctx = user_data;
2592 g_debug ("</%s>", element_name);
2598 /* no need to GError here, GMarkup already catches this */
2601 case STATE_REPOSITORY:
2602 state_switch (ctx, STATE_END);
2606 if (require_end_element (context, ctx, "include", element_name, error))
2608 state_switch (ctx, STATE_REPOSITORY);
2612 case STATE_NAMESPACE:
2613 if (require_end_element (context, ctx, "namespace", element_name, error))
2615 ctx->current_module = NULL;
2616 state_switch (ctx, STATE_REPOSITORY);
2621 if (require_end_element (context, ctx, "alias", element_name, error))
2623 state_switch (ctx, STATE_NAMESPACE);
2627 case STATE_FUNCTION_RETURN:
2628 if (strcmp ("type", element_name) == 0)
2630 if (require_end_element (context, ctx, "return-value", element_name, error))
2632 state_switch (ctx, STATE_FUNCTION);
2636 case STATE_FUNCTION_PARAMETERS:
2637 if (require_end_element (context, ctx, "parameters", element_name, error))
2639 state_switch (ctx, STATE_FUNCTION);
2643 case STATE_FUNCTION_PARAMETER:
2644 if (strcmp ("type", element_name) == 0)
2646 if (require_end_element (context, ctx, "parameter", element_name, error))
2648 state_switch (ctx, STATE_FUNCTION_PARAMETERS);
2652 case STATE_FUNCTION:
2654 gboolean current_is_toplevel;
2655 GList *last = g_list_last (ctx->current_module->entries);
2657 current_is_toplevel = ctx->current_node == last->data;
2659 if (current_is_toplevel)
2661 ctx->current_node = NULL;
2662 state_switch (ctx, STATE_NAMESPACE);
2666 ctx->current_node = g_list_last (ctx->current_module->entries)->data;
2667 if (ctx->current_node->type == G_IR_NODE_INTERFACE)
2668 state_switch (ctx, STATE_INTERFACE);
2669 else if (ctx->current_node->type == G_IR_NODE_OBJECT)
2670 state_switch (ctx, STATE_CLASS);
2671 else if (ctx->current_node->type == G_IR_NODE_BOXED)
2672 state_switch (ctx, STATE_BOXED);
2673 else if (ctx->current_node->type == G_IR_NODE_STRUCT)
2674 state_switch (ctx, STATE_STRUCT);
2675 else if (ctx->current_node->type == G_IR_NODE_UNION)
2676 state_switch (ctx, STATE_UNION);
2679 int line_number, char_number;
2680 g_markup_parse_context_get_position (context, &line_number, &char_number);
2683 G_MARKUP_ERROR_INVALID_CONTENT,
2684 "Unexpected end tag '%s' on line %d char %d",
2686 line_number, char_number);
2692 case STATE_CLASS_FIELD:
2693 if (strcmp ("type", element_name) == 0)
2695 if (require_end_element (context, ctx, "field", element_name, error))
2697 state_switch (ctx, STATE_CLASS);
2701 case STATE_CLASS_PROPERTY:
2702 if (strcmp ("type", element_name) == 0)
2704 if (require_end_element (context, ctx, "property", element_name, error))
2706 state_switch (ctx, STATE_CLASS);
2711 if (require_end_element (context, ctx, "class", element_name, error))
2713 ctx->current_node = NULL;
2714 state_switch (ctx, STATE_NAMESPACE);
2718 case STATE_ERRORDOMAIN:
2719 if (require_end_element (context, ctx, "errordomain", element_name, error))
2721 ctx->current_node = NULL;
2722 state_switch (ctx, STATE_NAMESPACE);
2726 case STATE_INTERFACE_PROPERTY:
2727 if (strcmp ("type", element_name) == 0)
2729 if (require_end_element (context, ctx, "property", element_name, error))
2731 state_switch (ctx, STATE_INTERFACE);
2735 case STATE_INTERFACE_FIELD:
2736 if (strcmp ("type", element_name) == 0)
2738 if (require_end_element (context, ctx, "field", element_name, error))
2740 state_switch (ctx, STATE_INTERFACE);
2744 case STATE_INTERFACE:
2745 if (require_end_element (context, ctx, "interface", element_name, error))
2747 ctx->current_node = NULL;
2748 state_switch (ctx, STATE_NAMESPACE);
2753 if (strcmp ("member", element_name) == 0)
2755 else if (require_one_of_end_elements (context, ctx,
2756 element_name, error, "enumeration",
2759 ctx->current_node = NULL;
2760 state_switch (ctx, STATE_NAMESPACE);
2765 if (require_end_element (context, ctx, "glib:boxed", element_name, error))
2767 ctx->current_node = NULL;
2768 state_switch (ctx, STATE_NAMESPACE);
2772 case STATE_BOXED_FIELD:
2773 if (strcmp ("type", element_name) == 0)
2775 if (require_end_element (context, ctx, "field", element_name, error))
2777 state_switch (ctx, STATE_BOXED);
2781 case STATE_STRUCT_FIELD:
2782 if (strcmp ("type", element_name) == 0)
2784 if (require_end_element (context, ctx, "field", element_name, error))
2786 state_switch (ctx, STATE_STRUCT);
2791 if (require_end_element (context, ctx, "record", element_name, error))
2793 ctx->current_node = NULL;
2794 state_switch (ctx, STATE_NAMESPACE);
2798 case STATE_UNION_FIELD:
2799 if (strcmp ("type", element_name) == 0)
2801 if (require_end_element (context, ctx, "field", element_name, error))
2803 state_switch (ctx, STATE_UNION);
2808 if (require_end_element (context, ctx, "union", element_name, error))
2810 ctx->current_node = NULL;
2811 state_switch (ctx, STATE_NAMESPACE);
2814 case STATE_IMPLEMENTS:
2815 if (strcmp ("interface", element_name) == 0)
2817 if (require_end_element (context, ctx, "implements", element_name, error))
2818 state_switch (ctx, STATE_CLASS);
2820 case STATE_REQUIRES:
2821 if (require_end_element (context, ctx, "requires", element_name, error))
2822 state_switch (ctx, STATE_INTERFACE);
2824 case STATE_NAMESPACE_CONSTANT:
2825 case STATE_CLASS_CONSTANT:
2826 case STATE_INTERFACE_CONSTANT:
2827 if (strcmp ("type", element_name) == 0)
2829 if (require_end_element (context, ctx, "constant", element_name, error))
2831 ctx->current_node = NULL;
2834 case STATE_NAMESPACE_CONSTANT:
2835 state_switch (ctx, STATE_NAMESPACE);
2837 case STATE_CLASS_CONSTANT:
2838 state_switch (ctx, STATE_CLASS);
2840 case STATE_INTERFACE_CONSTANT:
2841 state_switch (ctx, STATE_INTERFACE);
2844 g_assert_not_reached ();
2850 if ((strcmp ("type", element_name) == 0) || (strcmp ("array", element_name) == 0) ||
2851 (strcmp ("varargs", element_name) == 0))
2857 g_error ("Unhandled state %d in end_element_handler\n", ctx->state);
2862 text_handler (GMarkupParseContext *context,
2868 /* FIXME warn about non-whitespace text */
2872 cleanup (GMarkupParseContext *context,
2876 ParseContext *ctx = user_data;
2879 for (m = ctx->modules; m; m = m->next)
2880 g_ir_module_free (m->data);
2881 g_list_free (ctx->modules);
2882 ctx->modules = NULL;
2884 ctx->current_module = NULL;
2888 post_filter_varargs_functions (GList *list)
2896 GIrNode *node = iter->data;
2900 if (node->type == G_IR_NODE_FUNCTION)
2902 if (((GIrNodeFunction*)node)->is_varargs)
2904 list = g_list_delete_link (list, link);
2912 post_filter (GIrModule *module)
2916 module->entries = post_filter_varargs_functions (module->entries);
2917 iter = module->entries;
2920 GIrNode *node = iter->data;
2924 if (node->type == G_IR_NODE_OBJECT ||
2925 node->type == G_IR_NODE_INTERFACE)
2927 GIrNodeInterface *iface = (GIrNodeInterface*)node;
2928 iface->members = post_filter_varargs_functions (iface->members);
2930 else if (node->type == G_IR_NODE_BOXED)
2932 GIrNodeBoxed *boxed = (GIrNodeBoxed*)node;
2933 boxed->members = post_filter_varargs_functions (boxed->members);
2935 else if (node->type == G_IR_NODE_STRUCT)
2937 GIrNodeStruct *iface = (GIrNodeStruct*)node;
2938 iface->members = post_filter_varargs_functions (iface->members);
2940 else if (node->type == G_IR_NODE_UNION)
2942 GIrNodeUnion *iface = (GIrNodeUnion*)node;
2943 iface->members = post_filter_varargs_functions (iface->members);
2949 g_ir_parse_string (const gchar *namespace,
2950 const gchar *const *includes,
2951 const gchar *buffer,
2955 ParseContext ctx = { 0 };
2956 GMarkupParseContext *context;
2958 ctx.state = STATE_START;
2959 ctx.includes = includes;
2960 ctx.prefix_aliases = FALSE;
2961 ctx.namespace = namespace;
2962 ctx.aliases = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
2963 ctx.disguised_structures = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
2965 ctx.dependencies = NULL;
2966 ctx.current_module = NULL;
2968 context = g_markup_parse_context_new (&firstpass_parser, 0, &ctx, NULL);
2970 if (!g_markup_parse_context_parse (context, buffer, length, error))
2973 if (!g_markup_parse_context_end_parse (context, error))
2976 g_markup_parse_context_free (context);
2978 context = g_markup_parse_context_new (&parser, 0, &ctx, NULL);
2979 if (!g_markup_parse_context_parse (context, buffer, length, error))
2982 if (!g_markup_parse_context_end_parse (context, error))
2987 g_hash_table_destroy (ctx.aliases);
2988 g_hash_table_destroy (ctx.disguised_structures);
2990 g_markup_parse_context_free (context);
2996 g_ir_parse_file (const gchar *filename,
2997 const gchar *const *includes,
3007 if (!g_str_has_suffix (filename, ".gir"))
3011 G_MARKUP_ERROR_INVALID_CONTENT,
3012 "Expected filename to end with '.gir'");
3016 g_debug ("[parsing] filename %s", filename);
3018 slash = g_strrstr (filename, "/");
3020 namespace = g_strdup (filename);
3022 namespace = g_strdup (slash+1);
3023 namespace[strlen(namespace)-4] = '\0';
3025 if (!g_file_get_contents (filename, &buffer, &length, error))
3028 modules = g_ir_parse_string (namespace, includes, buffer, length, error);
3030 for (iter = modules; iter; iter = iter->next)
3032 post_filter ((GIrModule*)iter->data);