1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
2 * GObject introspection: A parser for the XML GIR format
4 * Copyright (C) 2005 Matthias Clasen
5 * Copyright (C) 2008 Philip Van Hoof
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library 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. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
28 #include "girparser.h"
29 #include "girmodule.h"
31 #include "gitypelib-internal.h"
34 /* This is a "major" version in the sense that it's only bumped
35 * for incompatible changes.
37 #define SUPPORTED_GIR_VERSION "1.2"
42 GList *parsed_modules; /* All previously parsed modules */
52 STATE_PACKAGE, /* 5 */
57 STATE_FUNCTION_RETURN, /* 10 */
58 STATE_FUNCTION_PARAMETERS,
59 STATE_FUNCTION_PARAMETER,
62 STATE_CLASS_PROPERTY, /* 15 */
64 STATE_INTERFACE_PROPERTY,
65 STATE_INTERFACE_FIELD,
67 STATE_PREREQUISITE, /* 20 */
74 STATE_NAMESPACE_CONSTANT,
76 STATE_INTERFACE_CONSTANT,
84 typedef struct _ParseContext ParseContext;
91 ParseState prev_state;
94 GList *include_modules;
97 GHashTable *disguised_structures;
99 const char *file_path;
100 const char *namespace;
101 const char *c_prefix;
102 GIrModule *current_module;
105 GIrNode *current_typed;
107 GList *type_parameters;
109 gboolean in_embedded_type;
111 #define CURRENT_NODE(ctx) ((GIrNode *)((ctx)->node_stack->data))
113 static void start_element_handler (GMarkupParseContext *context,
114 const gchar *element_name,
115 const gchar **attribute_names,
116 const gchar **attribute_values,
119 static void end_element_handler (GMarkupParseContext *context,
120 const gchar *element_name,
123 static void text_handler (GMarkupParseContext *context,
128 static void cleanup (GMarkupParseContext *context,
131 static void state_switch (ParseContext *ctx, ParseState newstate);
134 static GMarkupParser markup_parser =
136 start_element_handler,
144 start_alias (GMarkupParseContext *context,
145 const gchar *element_name,
146 const gchar **attribute_names,
147 const gchar **attribute_values,
151 start_type (GMarkupParseContext *context,
152 const gchar *element_name,
153 const gchar **attribute_names,
154 const gchar **attribute_values,
158 static const gchar *find_attribute (const gchar *name,
159 const gchar **attribute_names,
160 const gchar **attribute_values);
164 _g_ir_parser_new (void)
166 GIrParser *parser = g_slice_new0 (GIrParser);
172 _g_ir_parser_free (GIrParser *parser)
176 if (parser->includes)
177 g_strfreev (parser->includes);
179 for (l = parser->parsed_modules; l; l = l->next)
180 _g_ir_module_free (l->data);
182 g_slice_free (GIrParser, parser);
186 _g_ir_parser_set_includes (GIrParser *parser,
187 const gchar *const *includes)
189 if (parser->includes)
190 g_strfreev (parser->includes);
192 parser->includes = g_strdupv ((char **)includes);
196 firstpass_start_element_handler (GMarkupParseContext *context,
197 const gchar *element_name,
198 const gchar **attribute_names,
199 const gchar **attribute_values,
203 ParseContext *ctx = user_data;
205 if (strcmp (element_name, "alias") == 0)
207 start_alias (context, element_name, attribute_names, attribute_values,
210 else if (ctx->state == STATE_ALIAS && strcmp (element_name, "type") == 0)
212 start_type (context, element_name, attribute_names, attribute_values,
215 else if (strcmp (element_name, "record") == 0)
218 const gchar *disguised;
220 name = find_attribute ("name", attribute_names, attribute_values);
221 disguised = find_attribute ("disguised", attribute_names, attribute_values);
223 if (disguised && strcmp (disguised, "1") == 0)
227 key = g_strdup_printf ("%s.%s", ctx->namespace, name);
228 g_hash_table_replace (ctx->disguised_structures, key, GINT_TO_POINTER (1));
234 firstpass_end_element_handler (GMarkupParseContext *context,
235 const gchar *element_name,
239 ParseContext *ctx = user_data;
240 if (strcmp (element_name, "alias") == 0)
242 state_switch (ctx, STATE_NAMESPACE);
243 g_free (ctx->current_alias);
244 ctx->current_alias = NULL;
246 else if (strcmp (element_name, "type") == 0 && ctx->state == STATE_TYPE)
247 state_switch (ctx, ctx->prev_state);
250 static GMarkupParser firstpass_parser =
252 firstpass_start_element_handler,
253 firstpass_end_element_handler,
260 locate_gir (GIrParser *parser,
263 const gchar *const *datadirs;
264 const gchar *const *dir;
267 datadirs = g_get_system_data_dirs ();
269 if (parser->includes != NULL)
271 for (dir = (const gchar *const *)parser->includes; *dir; dir++)
273 path = g_build_filename (*dir, girname, NULL);
274 if (g_file_test (path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))
280 for (dir = datadirs; *dir; dir++)
282 path = g_build_filename (*dir, GIR_SUFFIX, girname, NULL);
283 if (g_file_test (path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))
289 path = g_build_filename (GIR_DIR, girname, NULL);
290 if (g_file_test (path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))
296 #define MISSING_ATTRIBUTE(context,error,element,attribute) \
298 int line_number, char_number; \
299 g_markup_parse_context_get_position (context, &line_number, &char_number); \
300 g_set_error (error, \
302 G_MARKUP_ERROR_INVALID_CONTENT, \
303 "Line %d, character %d: The attribute '%s' on the element '%s' must be specified", \
304 line_number, char_number, attribute, element); \
308 find_attribute (const gchar *name,
309 const gchar **attribute_names,
310 const gchar **attribute_values)
314 for (i = 0; attribute_names[i] != NULL; i++)
315 if (strcmp (attribute_names[i], name) == 0)
316 return attribute_values[i];
322 state_switch (ParseContext *ctx, ParseState newstate)
324 g_assert (ctx->state != newstate);
325 ctx->prev_state = ctx->state;
326 ctx->state = newstate;
330 pop_node (ParseContext *ctx)
332 g_assert (ctx->node_stack != 0);
334 GSList *top = ctx->node_stack;
335 GIrNode *node = top->data;
337 g_debug ("popping node %d %s", node->type, node->name);
338 ctx->node_stack = top->next;
339 g_slist_free_1 (top);
344 push_node (ParseContext *ctx, GIrNode *node)
346 g_assert (node != NULL);
347 g_debug ("pushing node %d %s", node->type, node->name);
348 ctx->node_stack = g_slist_prepend (ctx->node_stack, node);
351 static GIrNodeType * parse_type_internal (GIrModule *module,
352 const gchar *str, gchar **next, gboolean in_glib,
353 gboolean in_gobject);
361 static IntegerAliasInfo integer_aliases[] = {
362 { "gchar", SIZEOF_CHAR, 0 },
363 { "gshort", SIZEOF_SHORT, 1 },
364 { "gushort", SIZEOF_SHORT, 0 },
365 { "gint", SIZEOF_INT, 1 },
366 { "guint", SIZEOF_INT, 0 },
367 { "glong", SIZEOF_LONG, 1 },
368 { "gulong", SIZEOF_LONG, 0 },
369 { "gssize", GLIB_SIZEOF_SIZE_T, 1 },
370 { "gsize", GLIB_SIZEOF_SIZE_T, 0 },
371 { "gintptr", GLIB_SIZEOF_SIZE_T, 1 },
372 { "guintptr", GLIB_SIZEOF_SIZE_T, 0 },
381 #define BASIC_TYPE_FIXED_OFFSET 3
383 static BasicTypeInfo basic_types[] = {
384 { "none", GI_TYPE_TAG_VOID, 0 },
385 { "gpointer", GI_TYPE_TAG_VOID, 1 },
387 { "gboolean", GI_TYPE_TAG_BOOLEAN, 0 },
388 { "gint8", GI_TYPE_TAG_INT8, 0 }, /* Start of BASIC_TYPE_FIXED_OFFSET */
389 { "guint8", GI_TYPE_TAG_UINT8, 0 },
390 { "gint16", GI_TYPE_TAG_INT16, 0 },
391 { "guint16", GI_TYPE_TAG_UINT16, 0 },
392 { "gint32", GI_TYPE_TAG_INT32, 0 },
393 { "guint32", GI_TYPE_TAG_UINT32, 0 },
394 { "gint64", GI_TYPE_TAG_INT64, 0 },
395 { "guint64", GI_TYPE_TAG_UINT64, 0 },
396 { "gfloat", GI_TYPE_TAG_FLOAT, 0 },
397 { "gdouble", GI_TYPE_TAG_DOUBLE, 0 },
398 { "GType", GI_TYPE_TAG_GTYPE, 0 },
399 { "utf8", GI_TYPE_TAG_UTF8, 1 },
400 { "filename", GI_TYPE_TAG_FILENAME,1 },
401 { "gunichar", GI_TYPE_TAG_UNICHAR, 0 },
404 static const BasicTypeInfo *
405 parse_basic (const char *str)
408 guint n_basic = G_N_ELEMENTS (basic_types);
410 for (i = 0; i < n_basic; i++)
412 if (strcmp (str, basic_types[i].str) == 0)
413 return &(basic_types[i]);
415 for (i = 0; i < G_N_ELEMENTS (integer_aliases); i++)
417 if (strcmp (str, integer_aliases[i].str) == 0)
419 switch (integer_aliases[i].size)
422 if (integer_aliases[i].is_signed)
423 return &basic_types[BASIC_TYPE_FIXED_OFFSET];
425 return &basic_types[BASIC_TYPE_FIXED_OFFSET+1];
427 case sizeof(guint16):
428 if (integer_aliases[i].is_signed)
429 return &basic_types[BASIC_TYPE_FIXED_OFFSET+2];
431 return &basic_types[BASIC_TYPE_FIXED_OFFSET+3];
433 case sizeof(guint32):
434 if (integer_aliases[i].is_signed)
435 return &basic_types[BASIC_TYPE_FIXED_OFFSET+4];
437 return &basic_types[BASIC_TYPE_FIXED_OFFSET+5];
439 case sizeof(guint64):
440 if (integer_aliases[i].is_signed)
441 return &basic_types[BASIC_TYPE_FIXED_OFFSET+6];
443 return &basic_types[BASIC_TYPE_FIXED_OFFSET+7];
446 g_assert_not_reached ();
454 parse_type_internal (GIrModule *module,
455 const gchar *str, char **next, gboolean in_glib,
458 const BasicTypeInfo *basic;
460 char *temporary_type = NULL;
462 type = (GIrNodeType *)_g_ir_node_new (G_IR_NODE_TYPE, module);
464 type->unparsed = g_strdup (str);
466 /* See comment below on GLib.List handling */
467 if (in_gobject && strcmp (str, "Type") == 0)
469 temporary_type = g_strdup ("GLib.Type");
470 str = temporary_type;
473 basic = parse_basic (str);
476 type->is_basic = TRUE;
477 type->tag = basic->tag;
478 type->is_pointer = basic->pointer;
480 str += strlen(basic->str);
484 /* If we're inside GLib, handle "List" etc. by prefixing with
485 * "GLib." so the parsing code below doesn't have to get more
488 if (g_str_has_prefix (str, "List<") ||
489 strcmp (str, "List") == 0)
491 temporary_type = g_strdup_printf ("GLib.List%s", str + 4);
492 str = temporary_type;
494 else if (g_str_has_prefix (str, "SList<") ||
495 strcmp (str, "SList") == 0)
497 temporary_type = g_strdup_printf ("GLib.SList%s", str + 5);
498 str = temporary_type;
500 else if (g_str_has_prefix (str, "HashTable<") ||
501 strcmp (str, "HashTable") == 0)
503 temporary_type = g_strdup_printf ("GLib.HashTable%s", str + 9);
504 str = temporary_type;
506 else if (g_str_has_prefix (str, "Error<") ||
507 strcmp (str, "Error") == 0)
509 temporary_type = g_strdup_printf ("GLib.Error%s", str + 5);
510 str = temporary_type;
515 /* found a basic type */;
516 else if (g_str_has_prefix (str, "GLib.List") ||
517 g_str_has_prefix (str, "GLib.SList"))
519 str += strlen ("GLib.");
520 if (g_str_has_prefix (str, "List"))
522 type->tag = GI_TYPE_TAG_GLIST;
523 type->is_glist = TRUE;
524 type->is_pointer = TRUE;
525 str += strlen ("List");
529 type->tag = GI_TYPE_TAG_GSLIST;
530 type->is_gslist = TRUE;
531 type->is_pointer = TRUE;
532 str += strlen ("SList");
535 else if (g_str_has_prefix (str, "GLib.HashTable"))
537 str += strlen ("GLib.");
539 type->tag = GI_TYPE_TAG_GHASH;
540 type->is_ghashtable = TRUE;
541 type->is_pointer = TRUE;
542 str += strlen ("HashTable");
544 else if (g_str_has_prefix (str, "GLib.Error"))
546 str += strlen ("GLib.");
548 type->tag = GI_TYPE_TAG_ERROR;
549 type->is_error = TRUE;
550 type->is_pointer = TRUE;
551 str += strlen ("Error");
558 end = strchr (str, '>');
559 tmp = g_strndup (str, end - str);
560 type->errors = g_strsplit (tmp, ",", 0);
568 type->tag = GI_TYPE_TAG_INTERFACE;
569 type->is_interface = TRUE;
570 const char *start = str;
572 /* must be an interface type */
573 while (g_ascii_isalnum (*str) ||
580 type->interface = g_strndup (start, str - start);
585 g_assert (type->tag >= 0 && type->tag < GI_TYPE_TAG_N_TYPES);
586 g_free (temporary_type);
590 _g_ir_node_free ((GIrNode *)type);
591 g_free (temporary_type);
596 resolve_aliases (ParseContext *ctx, const gchar *type)
600 GSList *seen_values = NULL;
604 if (strchr (type, '.') == NULL)
606 prefixed = g_strdup_printf ("%s.%s", ctx->namespace, type);
615 seen_values = g_slist_prepend (seen_values, (char*)lookup);
616 while (g_hash_table_lookup_extended (ctx->current_module->aliases, lookup, &orig, &value))
618 g_debug ("Resolved: %s => %s\n", lookup, (char*)value);
620 if (g_slist_find_custom (seen_values, lookup,
621 (GCompareFunc)strcmp) != NULL)
623 seen_values = g_slist_prepend (seen_values, (gchar*)lookup);
625 g_slist_free (seen_values);
627 if (lookup == prefixed)
636 is_disguised_structure (ParseContext *ctx, const gchar *type)
642 if (strchr (type, '.') == NULL)
644 prefixed = g_strdup_printf ("%s.%s", ctx->namespace, type);
653 result = g_hash_table_lookup (ctx->current_module->disguised_structures,
662 parse_type (ParseContext *ctx, const gchar *type)
665 const BasicTypeInfo *basic;
666 gboolean in_glib, in_gobject;
668 in_glib = strcmp (ctx->namespace, "GLib") == 0;
669 in_gobject = strcmp (ctx->namespace, "GObject") == 0;
671 /* Do not search aliases for basic types */
672 basic = parse_basic (type);
674 type = resolve_aliases (ctx, type);
676 node = parse_type_internal (ctx->current_module, type, NULL, in_glib, in_gobject);
678 g_debug ("Parsed type: %s => %d", type, node->tag);
680 g_critical ("Failed to parse type: '%s'", type);
686 introspectable_prelude (GMarkupParseContext *context,
687 const gchar **attribute_names,
688 const gchar **attribute_values,
690 ParseState new_state)
692 const gchar *introspectable_arg;
693 const gchar *shadowed_by;
694 gboolean introspectable;
696 g_assert (ctx->state != STATE_PASSTHROUGH);
698 introspectable_arg = find_attribute ("introspectable", attribute_names, attribute_values);
699 shadowed_by = find_attribute ("shadowed-by", attribute_names, attribute_values);
701 introspectable = !(introspectable_arg && atoi (introspectable_arg) == 0) && shadowed_by == NULL;
704 state_switch (ctx, new_state);
707 state_switch (ctx, STATE_PASSTHROUGH);
708 ctx->unknown_depth = 1;
711 return introspectable;
715 start_glib_boxed (GMarkupParseContext *context,
716 const gchar *element_name,
717 const gchar **attribute_names,
718 const gchar **attribute_values,
723 const gchar *typename;
724 const gchar *typeinit;
725 const gchar *deprecated;
728 if (!(strcmp (element_name, "glib:boxed") == 0 &&
729 ctx->state == STATE_NAMESPACE))
732 if (!introspectable_prelude (context, attribute_names, attribute_values, ctx, STATE_BOXED))
735 name = find_attribute ("glib:name", attribute_names, attribute_values);
736 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
737 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
738 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
742 MISSING_ATTRIBUTE (context, error, element_name, "glib:name");
745 else if (typename == NULL)
747 MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
750 else if (typeinit == NULL)
752 MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
756 boxed = (GIrNodeBoxed *) _g_ir_node_new (G_IR_NODE_BOXED,
757 ctx->current_module);
759 ((GIrNode *)boxed)->name = g_strdup (name);
760 boxed->gtype_name = g_strdup (typename);
761 boxed->gtype_init = g_strdup (typeinit);
763 boxed->deprecated = TRUE;
765 boxed->deprecated = FALSE;
767 push_node (ctx, (GIrNode *)boxed);
768 ctx->current_module->entries =
769 g_list_append (ctx->current_module->entries, boxed);
775 start_function (GMarkupParseContext *context,
776 const gchar *element_name,
777 const gchar **attribute_names,
778 const gchar **attribute_values,
783 const gchar *shadows;
785 const gchar *deprecated;
787 GIrNodeFunction *function;
788 gboolean found = FALSE;
789 gboolean in_embedded_type;
793 case STATE_NAMESPACE:
794 found = (strcmp (element_name, "function") == 0 ||
795 strcmp (element_name, "callback") == 0);
801 found = strcmp (element_name, "constructor") == 0;
803 case STATE_INTERFACE:
805 strcmp (element_name, "function") == 0 ||
806 strcmp (element_name, "method") == 0 ||
807 strcmp (element_name, "callback") == 0);
810 found = strcmp (element_name, "function") == 0;
812 case STATE_STRUCT_FIELD:
813 found = (found || strcmp (element_name, "callback") == 0);
822 in_embedded_type = ctx->state == STATE_STRUCT_FIELD;
824 if (!introspectable_prelude (context, attribute_names, attribute_values, ctx, STATE_FUNCTION))
827 ctx->in_embedded_type = in_embedded_type;
829 name = find_attribute ("name", attribute_names, attribute_values);
830 shadows = find_attribute ("shadows", attribute_names, attribute_values);
831 symbol = find_attribute ("c:identifier", attribute_names, attribute_values);
832 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
833 throws = find_attribute ("throws", attribute_names, attribute_values);
837 MISSING_ATTRIBUTE (context, error, element_name, "name");
840 else if (strcmp (element_name, "callback") != 0 && symbol == NULL)
842 MISSING_ATTRIBUTE (context, error, element_name, "c:identifier");
849 function = (GIrNodeFunction *) _g_ir_node_new (G_IR_NODE_FUNCTION,
850 ctx->current_module);
852 ((GIrNode *)function)->name = g_strdup (name);
853 function->symbol = g_strdup (symbol);
854 function->parameters = NULL;
856 function->deprecated = TRUE;
858 function->deprecated = FALSE;
860 if (strcmp (element_name, "method") == 0 ||
861 strcmp (element_name, "constructor") == 0)
863 function->is_method = TRUE;
865 if (strcmp (element_name, "constructor") == 0)
866 function->is_constructor = TRUE;
868 function->is_constructor = FALSE;
872 function->is_method = FALSE;
873 function->is_setter = FALSE;
874 function->is_getter = FALSE;
875 function->is_constructor = FALSE;
876 if (strcmp (element_name, "callback") == 0)
877 ((GIrNode *)function)->type = G_IR_NODE_CALLBACK;
880 if (throws && strcmp (throws, "1") == 0)
881 function->throws = TRUE;
883 function->throws = FALSE;
885 if (ctx->node_stack == NULL)
887 ctx->current_module->entries =
888 g_list_append (ctx->current_module->entries, function);
890 else if (ctx->current_typed)
894 field = (GIrNodeField *)ctx->current_typed;
895 field->callback = function;
898 switch (CURRENT_NODE (ctx)->type)
900 case G_IR_NODE_INTERFACE:
901 case G_IR_NODE_OBJECT:
903 GIrNodeInterface *iface;
905 iface = (GIrNodeInterface *)CURRENT_NODE (ctx);
906 iface->members = g_list_append (iface->members, function);
909 case G_IR_NODE_BOXED:
913 boxed = (GIrNodeBoxed *)CURRENT_NODE (ctx);
914 boxed->members = g_list_append (boxed->members, function);
917 case G_IR_NODE_STRUCT:
919 GIrNodeStruct *struct_;
921 struct_ = (GIrNodeStruct *)CURRENT_NODE (ctx);
922 struct_->members = g_list_append (struct_->members, function); }
924 case G_IR_NODE_UNION:
926 GIrNodeUnion *union_;
928 union_ = (GIrNodeUnion *)CURRENT_NODE (ctx);
929 union_->members = g_list_append (union_->members, function);
933 case G_IR_NODE_FLAGS:
937 enum_ = (GIrNodeEnum *)CURRENT_NODE (ctx);
938 enum_->methods = g_list_append (enum_->methods, function);
942 g_assert_not_reached ();
945 push_node(ctx, (GIrNode *)function);
951 parse_property_transfer (GIrNodeProperty *property,
952 const gchar *transfer,
955 if (transfer == NULL)
958 GIrNodeInterface *iface = (GIrNodeInterface *)CURRENT_NODE (ctx);
960 g_debug ("required attribute 'transfer-ownership' is missing from "
961 "property '%s' in type '%s.%s'. Assuming 'none'\n",
962 property->node.name, ctx->namespace, iface->node.name);
966 if (strcmp (transfer, "none") == 0)
968 property->transfer = FALSE;
969 property->shallow_transfer = FALSE;
971 else if (strcmp (transfer, "container") == 0)
973 property->transfer = FALSE;
974 property->shallow_transfer = TRUE;
976 else if (strcmp (transfer, "full") == 0)
978 property->transfer = TRUE;
979 property->shallow_transfer = FALSE;
983 GIrNodeInterface *iface = (GIrNodeInterface *)CURRENT_NODE (ctx);
985 g_warning ("Unknown transfer-ownership value: '%s' for property '%s' in "
986 "type '%s.%s'", transfer, property->node.name, ctx->namespace,
992 parse_param_transfer (GIrNodeParam *param, const gchar *transfer, const gchar *name,
995 if (transfer == NULL)
997 g_set_error (error, G_MARKUP_ERROR,
998 G_MARKUP_ERROR_INVALID_CONTENT,
999 "required attribute 'transfer-ownership' missing");
1002 else if (strcmp (transfer, "none") == 0)
1004 param->transfer = FALSE;
1005 param->shallow_transfer = FALSE;
1007 else if (strcmp (transfer, "container") == 0)
1009 param->transfer = FALSE;
1010 param->shallow_transfer = TRUE;
1012 else if (strcmp (transfer, "full") == 0)
1014 param->transfer = TRUE;
1015 param->shallow_transfer = FALSE;
1019 g_set_error (error, G_MARKUP_ERROR,
1020 G_MARKUP_ERROR_INVALID_CONTENT,
1021 "invalid value for 'transfer-ownership': %s", transfer);
1028 start_parameter (GMarkupParseContext *context,
1029 const gchar *element_name,
1030 const gchar **attribute_names,
1031 const gchar **attribute_values,
1036 const gchar *direction;
1037 const gchar *retval;
1038 const gchar *optional;
1039 const gchar *caller_allocates;
1040 const gchar *allow_none;
1041 const gchar *transfer;
1043 const gchar *closure;
1044 const gchar *destroy;
1046 GIrNodeParam *param;
1048 if (!(strcmp (element_name, "parameter") == 0 &&
1049 ctx->state == STATE_FUNCTION_PARAMETERS))
1052 name = find_attribute ("name", attribute_names, attribute_values);
1053 direction = find_attribute ("direction", attribute_names, attribute_values);
1054 retval = find_attribute ("retval", attribute_names, attribute_values);
1055 optional = find_attribute ("optional", attribute_names, attribute_values);
1056 allow_none = find_attribute ("allow-none", attribute_names, attribute_values);
1057 caller_allocates = find_attribute ("caller-allocates", attribute_names, attribute_values);
1058 transfer = find_attribute ("transfer-ownership", attribute_names, attribute_values);
1059 scope = find_attribute ("scope", attribute_names, attribute_values);
1060 closure = find_attribute ("closure", attribute_names, attribute_values);
1061 destroy = find_attribute ("destroy", attribute_names, attribute_values);
1062 skip = find_attribute ("skip", attribute_names, attribute_values);
1067 param = (GIrNodeParam *)_g_ir_node_new (G_IR_NODE_PARAM,
1068 ctx->current_module);
1070 ctx->current_typed = (GIrNode*) param;
1071 ctx->current_typed->name = g_strdup (name);
1073 state_switch (ctx, STATE_FUNCTION_PARAMETER);
1075 if (direction && strcmp (direction, "out") == 0)
1079 if (caller_allocates == NULL)
1080 param->caller_allocates = FALSE;
1082 param->caller_allocates = strcmp (caller_allocates, "1") == 0;
1084 else if (direction && strcmp (direction, "inout") == 0)
1088 param->caller_allocates = FALSE;
1094 param->caller_allocates = FALSE;
1097 if (retval && strcmp (retval, "1") == 0)
1098 param->retval = TRUE;
1100 param->retval = FALSE;
1102 if (optional && strcmp (optional, "1") == 0)
1103 param->optional = TRUE;
1105 param->optional = FALSE;
1107 if (allow_none && strcmp (allow_none, "1") == 0)
1108 param->allow_none = TRUE;
1110 param->allow_none = FALSE;
1112 if (skip && strcmp (skip, "1") == 0)
1115 param->skip = FALSE;
1117 if (!parse_param_transfer (param, transfer, name, error))
1120 if (scope && strcmp (scope, "call") == 0)
1121 param->scope = GI_SCOPE_TYPE_CALL;
1122 else if (scope && strcmp (scope, "async") == 0)
1123 param->scope = GI_SCOPE_TYPE_ASYNC;
1124 else if (scope && strcmp (scope, "notified") == 0)
1125 param->scope = GI_SCOPE_TYPE_NOTIFIED;
1127 param->scope = GI_SCOPE_TYPE_INVALID;
1129 param->closure = closure ? atoi (closure) : -1;
1130 param->destroy = destroy ? atoi (destroy) : -1;
1132 ((GIrNode *)param)->name = g_strdup (name);
1134 switch (CURRENT_NODE (ctx)->type)
1136 case G_IR_NODE_FUNCTION:
1137 case G_IR_NODE_CALLBACK:
1139 GIrNodeFunction *func;
1141 func = (GIrNodeFunction *)CURRENT_NODE (ctx);
1142 func->parameters = g_list_append (func->parameters, param);
1145 case G_IR_NODE_SIGNAL:
1147 GIrNodeSignal *signal;
1149 signal = (GIrNodeSignal *)CURRENT_NODE (ctx);
1150 signal->parameters = g_list_append (signal->parameters, param);
1153 case G_IR_NODE_VFUNC:
1155 GIrNodeVFunc *vfunc;
1157 vfunc = (GIrNodeVFunc *)CURRENT_NODE (ctx);
1158 vfunc->parameters = g_list_append (vfunc->parameters, param);
1162 g_assert_not_reached ();
1169 start_field (GMarkupParseContext *context,
1170 const gchar *element_name,
1171 const gchar **attribute_names,
1172 const gchar **attribute_values,
1177 const gchar *readable;
1178 const gchar *writable;
1180 const gchar *branch;
1181 GIrNodeField *field;
1182 ParseState target_state;
1183 gboolean introspectable;
1188 target_state = STATE_CLASS_FIELD;
1191 target_state = STATE_BOXED_FIELD;
1194 target_state = STATE_STRUCT_FIELD;
1197 target_state = STATE_UNION_FIELD;
1199 case STATE_INTERFACE:
1200 target_state = STATE_INTERFACE_FIELD;
1206 if (strcmp (element_name, "field") != 0)
1209 g_assert (ctx->state != STATE_PASSTHROUGH);
1211 /* We handle introspectability specially here; we replace with just gpointer
1214 introspectable = introspectable_prelude (context, attribute_names, attribute_values, ctx, target_state);
1216 name = find_attribute ("name", attribute_names, attribute_values);
1217 readable = find_attribute ("readable", attribute_names, attribute_values);
1218 writable = find_attribute ("writable", attribute_names, attribute_values);
1219 bits = find_attribute ("bits", attribute_names, attribute_values);
1220 branch = find_attribute ("branch", attribute_names, attribute_values);
1224 MISSING_ATTRIBUTE (context, error, element_name, "name");
1228 field = (GIrNodeField *)_g_ir_node_new (G_IR_NODE_FIELD,
1229 ctx->current_module);
1232 ctx->current_typed = (GIrNode*) field;
1236 field->type = parse_type (ctx, "gpointer");
1239 ((GIrNode *)field)->name = g_strdup (name);
1240 /* Fields are assumed to be read-only.
1241 * (see also girwriter.py and generate.c)
1243 field->readable = readable == NULL || strcmp (readable, "0") == 0;
1244 field->writable = writable != NULL && strcmp (writable, "1") == 0;
1247 field->bits = atoi (bits);
1251 switch (CURRENT_NODE (ctx)->type)
1253 case G_IR_NODE_OBJECT:
1255 GIrNodeInterface *iface;
1257 iface = (GIrNodeInterface *)CURRENT_NODE (ctx);
1258 iface->members = g_list_append (iface->members, field);
1261 case G_IR_NODE_INTERFACE:
1263 GIrNodeInterface *iface;
1265 iface = (GIrNodeInterface *)CURRENT_NODE (ctx);
1266 iface->members = g_list_append (iface->members, field);
1269 case G_IR_NODE_BOXED:
1271 GIrNodeBoxed *boxed;
1273 boxed = (GIrNodeBoxed *)CURRENT_NODE (ctx);
1274 boxed->members = g_list_append (boxed->members, field);
1277 case G_IR_NODE_STRUCT:
1279 GIrNodeStruct *struct_;
1281 struct_ = (GIrNodeStruct *)CURRENT_NODE (ctx);
1282 struct_->members = g_list_append (struct_->members, field);
1285 case G_IR_NODE_UNION:
1287 GIrNodeUnion *union_;
1289 union_ = (GIrNodeUnion *)CURRENT_NODE (ctx);
1290 union_->members = g_list_append (union_->members, field);
1293 GIrNodeConstant *constant;
1295 constant = (GIrNodeConstant *) _g_ir_node_new (G_IR_NODE_CONSTANT,
1296 ctx->current_module);
1297 ((GIrNode *)constant)->name = g_strdup (name);
1298 constant->value = g_strdup (branch);
1299 constant->type = union_->discriminator_type;
1300 constant->deprecated = FALSE;
1302 union_->discriminators = g_list_append (union_->discriminators, constant);
1307 g_assert_not_reached ();
1314 start_alias (GMarkupParseContext *context,
1315 const gchar *element_name,
1316 const gchar **attribute_names,
1317 const gchar **attribute_values,
1323 name = find_attribute ("name", attribute_names, attribute_values);
1326 MISSING_ATTRIBUTE (context, error, element_name, "name");
1330 ctx->current_alias = g_strdup (name);
1331 state_switch (ctx, STATE_ALIAS);
1337 start_enum (GMarkupParseContext *context,
1338 const gchar *element_name,
1339 const gchar **attribute_names,
1340 const gchar **attribute_values,
1345 const gchar *typename;
1346 const gchar *typeinit;
1347 const gchar *deprecated;
1348 const gchar *error_domain;
1351 if (!((strcmp (element_name, "enumeration") == 0 && ctx->state == STATE_NAMESPACE) ||
1352 (strcmp (element_name, "bitfield") == 0 && ctx->state == STATE_NAMESPACE)))
1355 if (!introspectable_prelude (context, attribute_names, attribute_values, ctx, STATE_ENUM))
1358 name = find_attribute ("name", attribute_names, attribute_values);
1359 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
1360 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
1361 error_domain = find_attribute ("glib:error-domain", attribute_names, attribute_values);
1362 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1366 MISSING_ATTRIBUTE (context, error, element_name, "name");
1370 if (strcmp (element_name, "enumeration") == 0)
1371 enum_ = (GIrNodeEnum *) _g_ir_node_new (G_IR_NODE_ENUM,
1372 ctx->current_module);
1374 enum_ = (GIrNodeEnum *) _g_ir_node_new (G_IR_NODE_FLAGS,
1375 ctx->current_module);
1376 ((GIrNode *)enum_)->name = g_strdup (name);
1377 enum_->gtype_name = g_strdup (typename);
1378 enum_->gtype_init = g_strdup (typeinit);
1379 enum_->error_domain = g_strdup (error_domain);
1382 enum_->deprecated = TRUE;
1384 enum_->deprecated = FALSE;
1386 push_node (ctx, (GIrNode *) enum_);
1387 ctx->current_module->entries =
1388 g_list_append (ctx->current_module->entries, enum_);
1394 start_property (GMarkupParseContext *context,
1395 const gchar *element_name,
1396 const gchar **attribute_names,
1397 const gchar **attribute_values,
1401 ParseState target_state;
1403 const gchar *readable;
1404 const gchar *writable;
1405 const gchar *construct;
1406 const gchar *construct_only;
1407 const gchar *transfer;
1408 GIrNodeProperty *property;
1409 GIrNodeInterface *iface;
1411 if (!(strcmp (element_name, "property") == 0 &&
1412 (ctx->state == STATE_CLASS ||
1413 ctx->state == STATE_INTERFACE)))
1416 if (ctx->state == STATE_CLASS)
1417 target_state = STATE_CLASS_PROPERTY;
1418 else if (ctx->state == STATE_INTERFACE)
1419 target_state = STATE_INTERFACE_PROPERTY;
1421 g_assert_not_reached ();
1423 if (!introspectable_prelude (context, attribute_names, attribute_values, ctx, target_state))
1427 name = find_attribute ("name", attribute_names, attribute_values);
1428 readable = find_attribute ("readable", attribute_names, attribute_values);
1429 writable = find_attribute ("writable", attribute_names, attribute_values);
1430 construct = find_attribute ("construct", attribute_names, attribute_values);
1431 construct_only = find_attribute ("construct-only", attribute_names, attribute_values);
1432 transfer = find_attribute ("transfer-ownership", attribute_names, attribute_values);
1436 MISSING_ATTRIBUTE (context, error, element_name, "name");
1440 property = (GIrNodeProperty *) _g_ir_node_new (G_IR_NODE_PROPERTY,
1441 ctx->current_module);
1442 ctx->current_typed = (GIrNode*) property;
1444 ((GIrNode *)property)->name = g_strdup (name);
1446 /* Assume properties are readable */
1447 if (readable == NULL || strcmp (readable, "1") == 0)
1448 property->readable = TRUE;
1450 property->readable = FALSE;
1451 if (writable && strcmp (writable, "1") == 0)
1452 property->writable = TRUE;
1454 property->writable = FALSE;
1455 if (construct && strcmp (construct, "1") == 0)
1456 property->construct = TRUE;
1458 property->construct = FALSE;
1459 if (construct_only && strcmp (construct_only, "1") == 0)
1460 property->construct_only = TRUE;
1462 property->construct_only = FALSE;
1464 parse_property_transfer (property, transfer, ctx);
1466 iface = (GIrNodeInterface *)CURRENT_NODE (ctx);
1467 iface->members = g_list_append (iface->members, property);
1473 parse_value (const gchar *str)
1477 /* FIXME just a quick hack */
1478 shift_op = strstr (str, "<<");
1484 base = g_ascii_strtoll (str, NULL, 10);
1485 shift = g_ascii_strtoll (shift_op + 3, NULL, 10);
1487 return base << shift;
1490 return g_ascii_strtoll (str, NULL, 10);
1496 start_member (GMarkupParseContext *context,
1497 const gchar *element_name,
1498 const gchar **attribute_names,
1499 const gchar **attribute_values,
1505 const gchar *deprecated;
1506 const gchar *c_identifier;
1508 GIrNodeValue *value_;
1510 if (!(strcmp (element_name, "member") == 0 &&
1511 ctx->state == STATE_ENUM))
1514 name = find_attribute ("name", attribute_names, attribute_values);
1515 value = find_attribute ("value", attribute_names, attribute_values);
1516 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1517 c_identifier = find_attribute ("c:identifier", attribute_names, attribute_values);
1521 MISSING_ATTRIBUTE (context, error, element_name, "name");
1525 value_ = (GIrNodeValue *) _g_ir_node_new (G_IR_NODE_VALUE,
1526 ctx->current_module);
1528 ((GIrNode *)value_)->name = g_strdup (name);
1530 value_->value = parse_value (value);
1533 value_->deprecated = TRUE;
1535 value_->deprecated = FALSE;
1537 g_hash_table_insert (((GIrNode *)value_)->attributes,
1538 g_strdup ("c:identifier"),
1539 g_strdup (c_identifier));
1541 enum_ = (GIrNodeEnum *)CURRENT_NODE (ctx);
1542 enum_->values = g_list_append (enum_->values, value_);
1548 start_constant (GMarkupParseContext *context,
1549 const gchar *element_name,
1550 const gchar **attribute_names,
1551 const gchar **attribute_values,
1555 ParseState prev_state;
1556 ParseState target_state;
1559 const gchar *deprecated;
1560 GIrNodeConstant *constant;
1562 if (!(strcmp (element_name, "constant") == 0 &&
1563 (ctx->state == STATE_NAMESPACE ||
1564 ctx->state == STATE_CLASS ||
1565 ctx->state == STATE_INTERFACE)))
1570 case STATE_NAMESPACE:
1571 target_state = STATE_NAMESPACE_CONSTANT;
1574 target_state = STATE_CLASS_CONSTANT;
1576 case STATE_INTERFACE:
1577 target_state = STATE_INTERFACE_CONSTANT;
1580 g_assert_not_reached ();
1583 prev_state = ctx->state;
1585 if (!introspectable_prelude (context, attribute_names, attribute_values, ctx, target_state))
1588 name = find_attribute ("name", attribute_names, attribute_values);
1589 value = find_attribute ("value", attribute_names, attribute_values);
1590 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1594 MISSING_ATTRIBUTE (context, error, element_name, "name");
1597 else if (value == NULL)
1599 MISSING_ATTRIBUTE (context, error, element_name, "value");
1603 constant = (GIrNodeConstant *) _g_ir_node_new (G_IR_NODE_CONSTANT,
1604 ctx->current_module);
1606 ((GIrNode *)constant)->name = g_strdup (name);
1607 constant->value = g_strdup (value);
1609 ctx->current_typed = (GIrNode*) constant;
1612 constant->deprecated = TRUE;
1614 constant->deprecated = FALSE;
1616 if (prev_state == STATE_NAMESPACE)
1618 push_node (ctx, (GIrNode *) constant);
1619 ctx->current_module->entries =
1620 g_list_append (ctx->current_module->entries, constant);
1624 GIrNodeInterface *iface;
1626 iface = (GIrNodeInterface *)CURRENT_NODE (ctx);
1627 iface->members = g_list_append (iface->members, constant);
1634 start_interface (GMarkupParseContext *context,
1635 const gchar *element_name,
1636 const gchar **attribute_names,
1637 const gchar **attribute_values,
1642 const gchar *typename;
1643 const gchar *typeinit;
1644 const gchar *deprecated;
1645 const gchar *glib_type_struct;
1646 GIrNodeInterface *iface;
1648 if (!(strcmp (element_name, "interface") == 0 &&
1649 ctx->state == STATE_NAMESPACE))
1652 if (!introspectable_prelude (context, attribute_names, attribute_values, ctx, STATE_INTERFACE))
1655 name = find_attribute ("name", attribute_names, attribute_values);
1656 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
1657 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
1658 glib_type_struct = find_attribute ("glib:type-struct", attribute_names, attribute_values);
1659 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1663 MISSING_ATTRIBUTE (context, error, element_name, "name");
1666 else if (typename == NULL)
1668 MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
1671 else if (typeinit == NULL)
1673 MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
1677 iface = (GIrNodeInterface *) _g_ir_node_new (G_IR_NODE_INTERFACE,
1678 ctx->current_module);
1679 ((GIrNode *)iface)->name = g_strdup (name);
1680 iface->gtype_name = g_strdup (typename);
1681 iface->gtype_init = g_strdup (typeinit);
1682 iface->glib_type_struct = g_strdup (glib_type_struct);
1684 iface->deprecated = TRUE;
1686 iface->deprecated = FALSE;
1688 push_node (ctx, (GIrNode *) iface);
1689 ctx->current_module->entries =
1690 g_list_append (ctx->current_module->entries, iface);
1696 start_class (GMarkupParseContext *context,
1697 const gchar *element_name,
1698 const gchar **attribute_names,
1699 const gchar **attribute_values,
1704 const gchar *parent;
1705 const gchar *glib_type_struct;
1706 const gchar *typename;
1707 const gchar *typeinit;
1708 const gchar *deprecated;
1709 const gchar *abstract;
1710 const gchar *fundamental;
1711 const gchar *ref_func;
1712 const gchar *unref_func;
1713 const gchar *set_value_func;
1714 const gchar *get_value_func;
1715 GIrNodeInterface *iface;
1717 if (!(strcmp (element_name, "class") == 0 &&
1718 ctx->state == STATE_NAMESPACE))
1721 if (!introspectable_prelude (context, attribute_names, attribute_values, ctx, STATE_CLASS))
1724 name = find_attribute ("name", attribute_names, attribute_values);
1725 parent = find_attribute ("parent", attribute_names, attribute_values);
1726 glib_type_struct = find_attribute ("glib:type-struct", attribute_names, attribute_values);
1727 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
1728 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
1729 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1730 abstract = find_attribute ("abstract", attribute_names, attribute_values);
1731 fundamental = find_attribute ("glib:fundamental", attribute_names, attribute_values);
1732 ref_func = find_attribute ("glib:ref-func", attribute_names, attribute_values);
1733 unref_func = find_attribute ("glib:unref-func", attribute_names, attribute_values);
1734 set_value_func = find_attribute ("glib:set-value-func", attribute_names, attribute_values);
1735 get_value_func = find_attribute ("glib:get-value-func", attribute_names, attribute_values);
1739 MISSING_ATTRIBUTE (context, error, element_name, "name");
1742 else if (typename == NULL)
1744 MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
1747 else if (typeinit == NULL && strcmp (typename, "GObject"))
1749 MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
1753 iface = (GIrNodeInterface *) _g_ir_node_new (G_IR_NODE_OBJECT,
1754 ctx->current_module);
1755 ((GIrNode *)iface)->name = g_strdup (name);
1756 iface->gtype_name = g_strdup (typename);
1757 iface->gtype_init = g_strdup (typeinit);
1758 iface->parent = g_strdup (parent);
1759 iface->glib_type_struct = g_strdup (glib_type_struct);
1761 iface->deprecated = TRUE;
1763 iface->deprecated = FALSE;
1765 iface->abstract = abstract && strcmp (abstract, "1") == 0;
1768 iface->fundamental = TRUE;
1770 iface->ref_func = g_strdup (ref_func);
1772 iface->unref_func = g_strdup (unref_func);
1774 iface->set_value_func = g_strdup (set_value_func);
1776 iface->get_value_func = g_strdup (get_value_func);
1778 push_node (ctx, (GIrNode *) iface);
1779 ctx->current_module->entries =
1780 g_list_append (ctx->current_module->entries, iface);
1786 start_type (GMarkupParseContext *context,
1787 const gchar *element_name,
1788 const gchar **attribute_names,
1789 const gchar **attribute_values,
1795 gboolean in_alias = FALSE;
1797 gboolean is_varargs;
1798 GIrNodeType *typenode;
1800 is_array = strcmp (element_name, "array") == 0;
1801 is_varargs = strcmp (element_name, "varargs") == 0;
1803 if (!(is_array || is_varargs || (strcmp (element_name, "type") == 0)))
1806 if (ctx->state == STATE_TYPE)
1809 ctx->type_stack = g_list_prepend (ctx->type_stack, ctx->type_parameters);
1810 ctx->type_parameters = NULL;
1812 else if (ctx->state == STATE_FUNCTION_PARAMETER ||
1813 ctx->state == STATE_FUNCTION_RETURN ||
1814 ctx->state == STATE_STRUCT_FIELD ||
1815 ctx->state == STATE_UNION_FIELD ||
1816 ctx->state == STATE_CLASS_PROPERTY ||
1817 ctx->state == STATE_CLASS_FIELD ||
1818 ctx->state == STATE_INTERFACE_FIELD ||
1819 ctx->state == STATE_INTERFACE_PROPERTY ||
1820 ctx->state == STATE_BOXED_FIELD ||
1821 ctx->state == STATE_NAMESPACE_CONSTANT ||
1822 ctx->state == STATE_CLASS_CONSTANT ||
1823 ctx->state == STATE_INTERFACE_CONSTANT ||
1824 ctx->state == STATE_ALIAS
1827 if (ctx->state == STATE_ALIAS)
1829 state_switch (ctx, STATE_TYPE);
1830 ctx->type_depth = 1;
1831 ctx->type_stack = NULL;
1832 ctx->type_parameters = NULL;
1835 name = find_attribute ("name", attribute_names, attribute_values);
1837 if (in_alias && ctx->current_alias)
1844 MISSING_ATTRIBUTE (context, error, element_name, "name");
1848 key = g_strdup_printf ("%s.%s", ctx->namespace, ctx->current_alias);
1849 if (!strchr (name, '.'))
1851 const BasicTypeInfo *basic = parse_basic (name);
1854 /* For non-basic types, re-qualify the interface */
1855 value = g_strdup_printf ("%s.%s", ctx->namespace, name);
1859 value = g_strdup (name);
1863 value = g_strdup (name);
1865 g_hash_table_replace (ctx->aliases, key, value);
1869 else if (!ctx->current_module || in_alias)
1872 if (!ctx->current_typed)
1876 G_MARKUP_ERROR_INVALID_CONTENT,
1877 "The element <type> is invalid here");
1890 typenode = (GIrNodeType *)_g_ir_node_new (G_IR_NODE_TYPE,
1891 ctx->current_module);
1893 typenode->tag = GI_TYPE_TAG_ARRAY;
1894 typenode->is_pointer = TRUE;
1895 typenode->is_array = TRUE;
1897 if (name && strcmp (name, "GLib.Array") == 0) {
1898 typenode->array_type = GI_ARRAY_TYPE_ARRAY;
1899 } else if (name && strcmp (name, "GLib.ByteArray") == 0) {
1900 typenode->array_type = GI_ARRAY_TYPE_BYTE_ARRAY;
1901 } else if (name && strcmp (name, "GLib.PtrArray") == 0) {
1902 typenode->array_type = GI_ARRAY_TYPE_PTR_ARRAY;
1904 typenode->array_type = GI_ARRAY_TYPE_C;
1907 if (typenode->array_type == GI_ARRAY_TYPE_C) {
1908 zero = find_attribute ("zero-terminated", attribute_names, attribute_values);
1909 len = find_attribute ("length", attribute_names, attribute_values);
1910 size = find_attribute ("fixed-size", attribute_names, attribute_values);
1912 typenode->has_length = len != NULL;
1913 typenode->length = typenode->has_length ? atoi (len) : -1;
1915 typenode->has_size = size != NULL;
1916 typenode->size = typenode->has_size ? atoi (size) : -1;
1919 typenode->zero_terminated = strcmp(zero, "1") == 0;
1921 /* If neither zero-terminated nor length nor fixed-size is given, assume zero-terminated. */
1922 typenode->zero_terminated = !(typenode->has_length || typenode->has_size);
1924 if (typenode->has_size && ctx->current_typed->type == G_IR_NODE_FIELD)
1925 typenode->is_pointer = FALSE;
1927 typenode->zero_terminated = FALSE;
1928 typenode->has_length = FALSE;
1929 typenode->length = -1;
1930 typenode->has_size = FALSE;
1931 typenode->size = -1;
1940 MISSING_ATTRIBUTE (context, error, element_name, "name");
1945 ctype = find_attribute ("c:type", attribute_names, attribute_values);
1948 const char *cp = ctype + strlen(ctype) - 1;
1949 while (cp > ctype && *cp-- == '*')
1952 if (g_str_has_prefix (ctype, "gpointer")
1953 || g_str_has_prefix (ctype, "gconstpointer"))
1957 if (ctx->current_typed->type == G_IR_NODE_PARAM &&
1958 ((GIrNodeParam *)ctx->current_typed)->out &&
1962 typenode = parse_type (ctx, name);
1964 /* A 'disguised' structure is one where the c:type is a typedef that
1965 * doesn't look like a pointer, but is internally.
1967 if (typenode->tag == GI_TYPE_TAG_INTERFACE &&
1968 is_disguised_structure (ctx, typenode->interface))
1971 if (pointer_depth > 0)
1972 typenode->is_pointer = TRUE;
1975 ctx->type_parameters = g_list_append (ctx->type_parameters, typenode);
1981 end_type_top (ParseContext *ctx)
1983 GIrNodeType *typenode;
1985 if (!ctx->type_parameters)
1988 typenode = (GIrNodeType*)ctx->type_parameters->data;
1990 /* Default to pointer for unspecified containers */
1991 if (typenode->tag == GI_TYPE_TAG_ARRAY ||
1992 typenode->tag == GI_TYPE_TAG_GLIST ||
1993 typenode->tag == GI_TYPE_TAG_GSLIST)
1995 if (typenode->parameter_type1 == NULL)
1996 typenode->parameter_type1 = parse_type (ctx, "gpointer");
1998 else if (typenode->tag == GI_TYPE_TAG_GHASH)
2000 if (typenode->parameter_type1 == NULL)
2002 typenode->parameter_type1 = parse_type (ctx, "gpointer");
2003 typenode->parameter_type2 = parse_type (ctx, "gpointer");
2007 switch (ctx->current_typed->type)
2009 case G_IR_NODE_PARAM:
2011 GIrNodeParam *param = (GIrNodeParam *)ctx->current_typed;
2012 param->type = typenode;
2015 case G_IR_NODE_FIELD:
2017 GIrNodeField *field = (GIrNodeField *)ctx->current_typed;
2018 field->type = typenode;
2021 case G_IR_NODE_PROPERTY:
2023 GIrNodeProperty *property = (GIrNodeProperty *) ctx->current_typed;
2024 property->type = typenode;
2027 case G_IR_NODE_CONSTANT:
2029 GIrNodeConstant *constant = (GIrNodeConstant *)ctx->current_typed;
2030 constant->type = typenode;
2034 g_printerr("current node is %d\n", CURRENT_NODE (ctx)->type);
2035 g_assert_not_reached ();
2037 g_list_free (ctx->type_parameters);
2040 ctx->type_depth = 0;
2041 ctx->type_parameters = NULL;
2042 ctx->current_typed = NULL;
2046 end_type_recurse (ParseContext *ctx)
2048 GIrNodeType *parent;
2049 GIrNodeType *param = NULL;
2051 parent = (GIrNodeType *) ((GList*)ctx->type_stack->data)->data;
2052 if (ctx->type_parameters)
2053 param = (GIrNodeType *) ctx->type_parameters->data;
2055 if (parent->tag == GI_TYPE_TAG_ARRAY ||
2056 parent->tag == GI_TYPE_TAG_GLIST ||
2057 parent->tag == GI_TYPE_TAG_GSLIST)
2059 g_assert (param != NULL);
2061 if (parent->parameter_type1 == NULL)
2062 parent->parameter_type1 = param;
2064 g_assert_not_reached ();
2066 else if (parent->tag == GI_TYPE_TAG_GHASH)
2068 g_assert (param != NULL);
2070 if (parent->parameter_type1 == NULL)
2071 parent->parameter_type1 = param;
2072 else if (parent->parameter_type2 == NULL)
2073 parent->parameter_type2 = param;
2075 g_assert_not_reached ();
2077 g_list_free (ctx->type_parameters);
2078 ctx->type_parameters = (GList *)ctx->type_stack->data;
2079 ctx->type_stack = g_list_delete_link (ctx->type_stack, ctx->type_stack);
2083 end_type (ParseContext *ctx)
2085 if (ctx->type_depth == 1)
2088 state_switch (ctx, ctx->prev_state);
2092 end_type_recurse (ctx);
2098 start_doc (GMarkupParseContext *context,
2099 const gchar *element_name,
2100 const gchar **attribute_names,
2101 const gchar **attribute_values,
2105 if (strcmp (element_name, "doc") != 0)
2108 state_switch (ctx, STATE_DOC);
2114 start_attribute (GMarkupParseContext *context,
2115 const gchar *element_name,
2116 const gchar **attribute_names,
2117 const gchar **attribute_values,
2125 if (strcmp (element_name, "attribute") != 0 || ctx->node_stack == NULL)
2128 name = find_attribute ("name", attribute_names, attribute_values);
2129 value = find_attribute ("value", attribute_names, attribute_values);
2133 MISSING_ATTRIBUTE (context, error, element_name, "name");
2138 MISSING_ATTRIBUTE (context, error, element_name, "value");
2142 state_switch (ctx, STATE_ATTRIBUTE);
2144 curnode = CURRENT_NODE (ctx);
2146 if (ctx->current_typed && ctx->current_typed->type == G_IR_NODE_PARAM)
2148 g_hash_table_insert (ctx->current_typed->attributes, g_strdup (name), g_strdup (value));
2152 g_hash_table_insert (curnode->attributes, g_strdup (name), g_strdup (value));
2159 start_return_value (GMarkupParseContext *context,
2160 const gchar *element_name,
2161 const gchar **attribute_names,
2162 const gchar **attribute_values,
2166 GIrNodeParam *param;
2167 const gchar *transfer;
2170 if (!(strcmp (element_name, "return-value") == 0 &&
2171 ctx->state == STATE_FUNCTION))
2174 param = (GIrNodeParam *)_g_ir_node_new (G_IR_NODE_PARAM,
2175 ctx->current_module);
2178 param->retval = TRUE;
2180 ctx->current_typed = (GIrNode*) param;
2182 state_switch (ctx, STATE_FUNCTION_RETURN);
2184 skip = find_attribute ("skip", attribute_names, attribute_values);
2185 if (skip && strcmp (skip, "1") == 0)
2188 param->skip = FALSE;
2190 transfer = find_attribute ("transfer-ownership", attribute_names, attribute_values);
2191 if (!parse_param_transfer (param, transfer, NULL, error))
2194 switch (CURRENT_NODE (ctx)->type)
2196 case G_IR_NODE_FUNCTION:
2197 case G_IR_NODE_CALLBACK:
2199 GIrNodeFunction *func = (GIrNodeFunction *)CURRENT_NODE (ctx);
2200 func->result = param;
2203 case G_IR_NODE_SIGNAL:
2205 GIrNodeSignal *signal = (GIrNodeSignal *)CURRENT_NODE (ctx);
2206 signal->result = param;
2209 case G_IR_NODE_VFUNC:
2211 GIrNodeVFunc *vfunc = (GIrNodeVFunc *)CURRENT_NODE (ctx);
2212 vfunc->result = param;
2216 g_assert_not_reached ();
2223 start_implements (GMarkupParseContext *context,
2224 const gchar *element_name,
2225 const gchar **attribute_names,
2226 const gchar **attribute_values,
2230 GIrNodeInterface *iface;
2233 if (strcmp (element_name, "implements") != 0 ||
2234 !(ctx->state == STATE_CLASS))
2237 state_switch (ctx, STATE_IMPLEMENTS);
2239 name = find_attribute ("name", attribute_names, attribute_values);
2242 MISSING_ATTRIBUTE (context, error, element_name, "name");
2246 iface = (GIrNodeInterface *)CURRENT_NODE (ctx);
2247 iface->interfaces = g_list_append (iface->interfaces, g_strdup (name));
2253 start_glib_signal (GMarkupParseContext *context,
2254 const gchar *element_name,
2255 const gchar **attribute_names,
2256 const gchar **attribute_values,
2262 const gchar *no_recurse;
2263 const gchar *detailed;
2264 const gchar *action;
2265 const gchar *no_hooks;
2266 const gchar *has_class_closure;
2267 GIrNodeInterface *iface;
2268 GIrNodeSignal *signal;
2270 if (!(strcmp (element_name, "glib:signal") == 0 &&
2271 (ctx->state == STATE_CLASS ||
2272 ctx->state == STATE_INTERFACE)))
2275 if (!introspectable_prelude (context, attribute_names, attribute_values, ctx, STATE_FUNCTION))
2278 name = find_attribute ("name", attribute_names, attribute_values);
2279 when = find_attribute ("when", attribute_names, attribute_values);
2280 no_recurse = find_attribute ("no-recurse", attribute_names, attribute_values);
2281 detailed = find_attribute ("detailed", attribute_names, attribute_values);
2282 action = find_attribute ("action", attribute_names, attribute_values);
2283 no_hooks = find_attribute ("no-hooks", attribute_names, attribute_values);
2284 has_class_closure = find_attribute ("has-class-closure", attribute_names, attribute_values);
2288 MISSING_ATTRIBUTE (context, error, element_name, "name");
2291 signal = (GIrNodeSignal *)_g_ir_node_new (G_IR_NODE_SIGNAL,
2292 ctx->current_module);
2294 ((GIrNode *)signal)->name = g_strdup (name);
2296 signal->run_first = FALSE;
2297 signal->run_last = FALSE;
2298 signal->run_cleanup = FALSE;
2299 if (when == NULL || strcmp (when, "LAST") == 0)
2300 signal->run_last = TRUE;
2301 else if (strcmp (when, "FIRST") == 0)
2302 signal->run_first = TRUE;
2304 signal->run_cleanup = TRUE;
2306 if (no_recurse && strcmp (no_recurse, "1") == 0)
2307 signal->no_recurse = TRUE;
2309 signal->no_recurse = FALSE;
2310 if (detailed && strcmp (detailed, "1") == 0)
2311 signal->detailed = TRUE;
2313 signal->detailed = FALSE;
2314 if (action && strcmp (action, "1") == 0)
2315 signal->action = TRUE;
2317 signal->action = FALSE;
2318 if (no_hooks && strcmp (no_hooks, "1") == 0)
2319 signal->no_hooks = TRUE;
2321 signal->no_hooks = FALSE;
2322 if (has_class_closure && strcmp (has_class_closure, "1") == 0)
2323 signal->has_class_closure = TRUE;
2325 signal->has_class_closure = FALSE;
2327 iface = (GIrNodeInterface *)CURRENT_NODE (ctx);
2328 iface->members = g_list_append (iface->members, signal);
2330 push_node (ctx, (GIrNode *)signal);
2336 start_vfunc (GMarkupParseContext *context,
2337 const gchar *element_name,
2338 const gchar **attribute_names,
2339 const gchar **attribute_values,
2344 const gchar *must_chain_up;
2345 const gchar *override;
2346 const gchar *is_class_closure;
2347 const gchar *offset;
2348 const gchar *invoker;
2349 const gchar *throws;
2350 GIrNodeInterface *iface;
2351 GIrNodeVFunc *vfunc;
2353 if (!(strcmp (element_name, "virtual-method") == 0 &&
2354 (ctx->state == STATE_CLASS ||
2355 ctx->state == STATE_INTERFACE)))
2358 if (!introspectable_prelude (context, attribute_names, attribute_values, ctx, STATE_FUNCTION))
2361 name = find_attribute ("name", attribute_names, attribute_values);
2362 must_chain_up = find_attribute ("must-chain-up", attribute_names, attribute_values);
2363 override = find_attribute ("override", attribute_names, attribute_values);
2364 is_class_closure = find_attribute ("is-class-closure", attribute_names, attribute_values);
2365 offset = find_attribute ("offset", attribute_names, attribute_values);
2366 invoker = find_attribute ("invoker", attribute_names, attribute_values);
2367 throws = find_attribute ("throws", attribute_names, attribute_values);
2371 MISSING_ATTRIBUTE (context, error, element_name, "name");
2375 vfunc = (GIrNodeVFunc *)_g_ir_node_new (G_IR_NODE_VFUNC,
2376 ctx->current_module);
2378 ((GIrNode *)vfunc)->name = g_strdup (name);
2380 if (must_chain_up && strcmp (must_chain_up, "1") == 0)
2381 vfunc->must_chain_up = TRUE;
2383 vfunc->must_chain_up = FALSE;
2385 if (override && strcmp (override, "always") == 0)
2387 vfunc->must_be_implemented = TRUE;
2388 vfunc->must_not_be_implemented = FALSE;
2390 else if (override && strcmp (override, "never") == 0)
2392 vfunc->must_be_implemented = FALSE;
2393 vfunc->must_not_be_implemented = TRUE;
2397 vfunc->must_be_implemented = FALSE;
2398 vfunc->must_not_be_implemented = FALSE;
2401 if (is_class_closure && strcmp (is_class_closure, "1") == 0)
2402 vfunc->is_class_closure = TRUE;
2404 vfunc->is_class_closure = FALSE;
2406 if (throws && strcmp (throws, "1") == 0)
2407 vfunc->throws = TRUE;
2409 vfunc->throws = FALSE;
2412 vfunc->offset = atoi (offset);
2414 vfunc->offset = 0xFFFF;
2416 vfunc->invoker = g_strdup (invoker);
2418 iface = (GIrNodeInterface *)CURRENT_NODE (ctx);
2419 iface->members = g_list_append (iface->members, vfunc);
2421 push_node (ctx, (GIrNode *)vfunc);
2427 start_struct (GMarkupParseContext *context,
2428 const gchar *element_name,
2429 const gchar **attribute_names,
2430 const gchar **attribute_values,
2435 const gchar *deprecated;
2436 const gchar *disguised;
2437 const gchar *gtype_name;
2438 const gchar *gtype_init;
2439 const gchar *gtype_struct;
2440 const gchar *foreign;
2441 GIrNodeStruct *struct_;
2443 if (!(strcmp (element_name, "record") == 0 &&
2444 (ctx->state == STATE_NAMESPACE ||
2445 ctx->state == STATE_UNION ||
2446 ctx->state == STATE_STRUCT ||
2447 ctx->state == STATE_CLASS)))
2450 if (!introspectable_prelude (context, attribute_names, attribute_values, ctx, STATE_STRUCT))
2453 name = find_attribute ("name", attribute_names, attribute_values);
2454 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
2455 disguised = find_attribute ("disguised", attribute_names, attribute_values);
2456 gtype_name = find_attribute ("glib:type-name", attribute_names, attribute_values);
2457 gtype_init = find_attribute ("glib:get-type", attribute_names, attribute_values);
2458 gtype_struct = find_attribute ("glib:is-gtype-struct-for", attribute_names, attribute_values);
2459 foreign = find_attribute ("foreign", attribute_names, attribute_values);
2461 if (name == NULL && ctx->node_stack == NULL)
2463 MISSING_ATTRIBUTE (context, error, element_name, "name");
2466 if ((gtype_name == NULL && gtype_init != NULL))
2468 MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
2471 if ((gtype_name != NULL && gtype_init == NULL))
2473 MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
2477 struct_ = (GIrNodeStruct *) _g_ir_node_new (G_IR_NODE_STRUCT,
2478 ctx->current_module);
2480 ((GIrNode *)struct_)->name = g_strdup (name ? name : "");
2482 struct_->deprecated = TRUE;
2484 struct_->deprecated = FALSE;
2486 if (disguised && strcmp (disguised, "1") == 0)
2487 struct_->disguised = TRUE;
2489 struct_->is_gtype_struct = gtype_struct != NULL;
2491 struct_->gtype_name = g_strdup (gtype_name);
2492 struct_->gtype_init = g_strdup (gtype_init);
2494 struct_->foreign = (g_strcmp0 (foreign, "1") == 0);
2496 if (ctx->node_stack == NULL)
2497 ctx->current_module->entries =
2498 g_list_append (ctx->current_module->entries, struct_);
2499 push_node (ctx, (GIrNode *)struct_);
2504 start_union (GMarkupParseContext *context,
2505 const gchar *element_name,
2506 const gchar **attribute_names,
2507 const gchar **attribute_values,
2512 const gchar *deprecated;
2513 const gchar *typename;
2514 const gchar *typeinit;
2515 GIrNodeUnion *union_;
2517 if (!(strcmp (element_name, "union") == 0 &&
2518 (ctx->state == STATE_NAMESPACE ||
2519 ctx->state == STATE_UNION ||
2520 ctx->state == STATE_STRUCT ||
2521 ctx->state == STATE_CLASS)))
2524 if (!introspectable_prelude (context, attribute_names, attribute_values, ctx, STATE_UNION))
2527 name = find_attribute ("name", attribute_names, attribute_values);
2528 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
2529 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
2530 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
2532 if (name == NULL && ctx->node_stack == NULL)
2534 MISSING_ATTRIBUTE (context, error, element_name, "name");
2538 union_ = (GIrNodeUnion *) _g_ir_node_new (G_IR_NODE_UNION,
2539 ctx->current_module);
2541 ((GIrNode *)union_)->name = g_strdup (name ? name : "");
2542 union_->gtype_name = g_strdup (typename);
2543 union_->gtype_init = g_strdup (typeinit);
2545 union_->deprecated = TRUE;
2547 union_->deprecated = FALSE;
2549 if (ctx->node_stack == NULL)
2550 ctx->current_module->entries =
2551 g_list_append (ctx->current_module->entries, union_);
2552 push_node (ctx, (GIrNode *)union_);
2557 start_discriminator (GMarkupParseContext *context,
2558 const gchar *element_name,
2559 const gchar **attribute_names,
2560 const gchar **attribute_values,
2565 const gchar *offset;
2566 if (!(strcmp (element_name, "discriminator") == 0 &&
2567 ctx->state == STATE_UNION))
2570 type = find_attribute ("type", attribute_names, attribute_values);
2571 offset = find_attribute ("offset", attribute_names, attribute_values);
2574 MISSING_ATTRIBUTE (context, error, element_name, "type");
2577 else if (offset == NULL)
2579 MISSING_ATTRIBUTE (context, error, element_name, "offset");
2583 ((GIrNodeUnion *)CURRENT_NODE (ctx))->discriminator_type
2584 = parse_type (ctx, type);
2585 ((GIrNodeUnion *)CURRENT_NODE (ctx))->discriminator_offset
2592 parse_include (GMarkupParseContext *context,
2595 const char *version)
2597 GError *error = NULL;
2600 gchar *girpath, *girname;
2604 for (l = ctx->parser->parsed_modules; l; l = l->next)
2606 GIrModule *m = l->data;
2608 if (strcmp (m->name, name) == 0)
2610 if (strcmp (m->version, version) == 0)
2612 ctx->include_modules = g_list_prepend (ctx->include_modules, m);
2618 g_printerr ("Module '%s' imported with conflicting versions '%s' and '%s'\n",
2619 name, m->version, version);
2625 girname = g_strdup_printf ("%s-%s.gir", name, version);
2626 girpath = locate_gir (ctx->parser, girname);
2628 if (girpath == NULL)
2630 g_printerr ("Could not find GIR file '%s'; check XDG_DATA_DIRS or use --includedir\n",
2637 g_debug ("Parsing include %s\n", girpath);
2639 if (!g_file_get_contents (girpath, &buffer, &length, &error))
2641 g_printerr ("%s: %s\n", girpath, error->message);
2642 g_clear_error (&error);
2647 module = _g_ir_parser_parse_string (ctx->parser, name, girpath, buffer, length, &error);
2651 int line_number, char_number;
2652 g_markup_parse_context_get_position (context, &line_number, &char_number);
2653 g_printerr ("%s:%d:%d: error: %s\n", girpath, line_number, char_number, error->message);
2654 g_clear_error (&error);
2660 ctx->include_modules = g_list_append (ctx->include_modules,
2666 extern GLogLevelFlags logged_levels;
2669 start_element_handler (GMarkupParseContext *context,
2670 const gchar *element_name,
2671 const gchar **attribute_names,
2672 const gchar **attribute_values,
2676 ParseContext *ctx = user_data;
2677 gint line_number, char_number;
2679 if (logged_levels & G_LOG_LEVEL_DEBUG)
2681 GString *tags = g_string_new ("");
2683 for (i = 0; attribute_names[i]; i++)
2684 g_string_append_printf (tags, "%s=\"%s\" ",
2686 attribute_values[i]);
2690 g_string_insert_c (tags, 0, ' ');
2691 g_string_truncate (tags, tags->len - 1);
2693 g_debug ("<%s%s>", element_name, tags->str);
2694 g_string_free (tags, TRUE);
2697 if (ctx->state == STATE_PASSTHROUGH)
2699 ctx->unknown_depth += 1;
2703 switch (element_name[0])
2706 if (ctx->state == STATE_NAMESPACE && strcmp (element_name, "alias") == 0)
2708 state_switch (ctx, STATE_ALIAS);
2711 if (start_type (context, element_name,
2712 attribute_names, attribute_values,
2715 else if (start_attribute (context, element_name,
2716 attribute_names, attribute_values,
2721 if (start_enum (context, element_name,
2722 attribute_names, attribute_values,
2727 if (start_function (context, element_name,
2728 attribute_names, attribute_values,
2731 else if (start_constant (context, element_name,
2732 attribute_names, attribute_values,
2735 else if (start_class (context, element_name,
2736 attribute_names, attribute_values,
2742 if (start_discriminator (context, element_name,
2743 attribute_names, attribute_values,
2746 else if (start_doc (context, element_name, attribute_names,
2747 attribute_values, ctx, error))
2752 if (start_enum (context, element_name,
2753 attribute_names, attribute_values,
2759 if (start_function (context, element_name,
2760 attribute_names, attribute_values,
2763 else if (start_field (context, element_name,
2764 attribute_names, attribute_values,
2770 if (start_glib_boxed (context, element_name,
2771 attribute_names, attribute_values,
2774 else if (start_glib_signal (context, element_name,
2775 attribute_names, attribute_values,
2781 if (strcmp (element_name, "include") == 0 &&
2782 ctx->state == STATE_REPOSITORY)
2785 const gchar *version;
2787 name = find_attribute ("name", attribute_names, attribute_values);
2788 version = find_attribute ("version", attribute_names, attribute_values);
2792 MISSING_ATTRIBUTE (context, error, element_name, "name");
2795 if (version == NULL)
2797 MISSING_ATTRIBUTE (context, error, element_name, "version");
2801 if (!parse_include (context, ctx, name, version))
2805 G_MARKUP_ERROR_INVALID_CONTENT,
2806 "Failed to parse included gir %s-%s",
2812 ctx->dependencies = g_list_prepend (ctx->dependencies,
2813 g_strdup_printf ("%s-%s", name, version));
2816 state_switch (ctx, STATE_INCLUDE);
2819 if (start_interface (context, element_name,
2820 attribute_names, attribute_values,
2823 else if (start_implements (context, element_name,
2824 attribute_names, attribute_values,
2827 else if (strcmp (element_name, "c:include") == 0)
2829 state_switch (ctx, STATE_C_INCLUDE);
2835 if (start_function (context, element_name,
2836 attribute_names, attribute_values,
2839 else if (start_member (context, element_name,
2840 attribute_names, attribute_values,
2846 if (strcmp (element_name, "namespace") == 0 && ctx->state == STATE_REPOSITORY)
2848 const gchar *name, *version, *shared_library, *cprefix;
2850 if (ctx->current_module != NULL)
2854 G_MARKUP_ERROR_INVALID_CONTENT,
2855 "Only one <namespace/> element is currently allowed per <repository/>");
2859 name = find_attribute ("name", attribute_names, attribute_values);
2860 version = find_attribute ("version", attribute_names, attribute_values);
2861 shared_library = find_attribute ("shared-library", attribute_names, attribute_values);
2862 cprefix = find_attribute ("c:identifier-prefixes", attribute_names, attribute_values);
2865 MISSING_ATTRIBUTE (context, error, element_name, "name");
2866 else if (version == NULL)
2867 MISSING_ATTRIBUTE (context, error, element_name, "version");
2872 if (strcmp (name, ctx->namespace) != 0)
2875 G_MARKUP_ERROR_INVALID_CONTENT,
2876 "<namespace/> name element '%s' doesn't match file name '%s'",
2877 name, ctx->namespace);
2879 ctx->current_module = _g_ir_module_new (name, version, shared_library, cprefix);
2881 ctx->current_module->aliases = ctx->aliases;
2882 ctx->aliases = NULL;
2883 ctx->current_module->disguised_structures = ctx->disguised_structures;
2884 ctx->disguised_structures = NULL;
2886 for (l = ctx->include_modules; l; l = l->next)
2887 _g_ir_module_add_include_module (ctx->current_module, l->data);
2889 g_list_free (ctx->include_modules);
2890 ctx->include_modules = NULL;
2892 ctx->modules = g_list_append (ctx->modules, ctx->current_module);
2893 ctx->current_module->dependencies = ctx->dependencies;
2895 state_switch (ctx, STATE_NAMESPACE);
2902 if (start_property (context, element_name,
2903 attribute_names, attribute_values,
2906 else if (strcmp (element_name, "parameters") == 0 &&
2907 ctx->state == STATE_FUNCTION)
2909 state_switch (ctx, STATE_FUNCTION_PARAMETERS);
2913 else if (start_parameter (context, element_name,
2914 attribute_names, attribute_values,
2917 else if (strcmp (element_name, "prerequisite") == 0 &&
2918 ctx->state == STATE_INTERFACE)
2922 name = find_attribute ("name", attribute_names, attribute_values);
2924 state_switch (ctx, STATE_PREREQUISITE);
2927 MISSING_ATTRIBUTE (context, error, element_name, "name");
2930 GIrNodeInterface *iface;
2932 iface = (GIrNodeInterface *)CURRENT_NODE(ctx);
2933 iface->prerequisites = g_list_append (iface->prerequisites, g_strdup (name));
2937 else if (strcmp (element_name, "package") == 0 &&
2938 ctx->state == STATE_REPOSITORY)
2940 state_switch (ctx, STATE_PACKAGE);
2946 if (strcmp (element_name, "repository") == 0 && ctx->state == STATE_START)
2948 const gchar *version;
2950 version = find_attribute ("version", attribute_names, attribute_values);
2952 if (version == NULL)
2953 MISSING_ATTRIBUTE (context, error, element_name, "version");
2954 else if (strcmp (version, SUPPORTED_GIR_VERSION) != 0)
2957 G_MARKUP_ERROR_INVALID_CONTENT,
2958 "Unsupported version '%s'",
2961 state_switch (ctx, STATE_REPOSITORY);
2965 else if (start_return_value (context, element_name,
2966 attribute_names, attribute_values,
2969 else if (start_struct (context, element_name,
2970 attribute_names, attribute_values,
2976 if (start_union (context, element_name,
2977 attribute_names, attribute_values,
2983 if (start_type (context, element_name,
2984 attribute_names, attribute_values,
2990 if (start_vfunc (context, element_name,
2991 attribute_names, attribute_values,
2994 if (start_type (context, element_name,
2995 attribute_names, attribute_values,
3001 if (*error == NULL && ctx->state != STATE_PASSTHROUGH)
3003 g_markup_parse_context_get_position (context, &line_number, &char_number);
3004 if (!g_str_has_prefix (element_name, "c:"))
3005 g_printerr ("%s:%d:%d: warning: element %s from state %d is unknown, ignoring\n",
3006 ctx->file_path, line_number, char_number, element_name,
3008 state_switch (ctx, STATE_PASSTHROUGH);
3009 ctx->unknown_depth = 1;
3015 g_markup_parse_context_get_position (context, &line_number, &char_number);
3017 g_printerr ("%s:%d:%d: error: %s\n", ctx->file_path, line_number, char_number, (*error)->message);
3022 require_one_of_end_elements (GMarkupParseContext *context,
3024 const char *actual_name,
3029 int line_number, char_number;
3030 const char *expected;
3031 gboolean matched = FALSE;
3033 va_start (args, error);
3035 while ((expected = va_arg (args, const char*)) != NULL)
3037 if (strcmp (expected, actual_name) == 0)
3049 g_markup_parse_context_get_position (context, &line_number, &char_number);
3052 G_MARKUP_ERROR_INVALID_CONTENT,
3053 "Unexpected end tag '%s' on line %d char %d; current state=%d (prev=%d)",
3055 line_number, char_number, ctx->state, ctx->prev_state);
3060 state_switch_end_struct_or_union (GMarkupParseContext *context,
3062 const gchar *element_name,
3066 if (ctx->node_stack == NULL)
3068 state_switch (ctx, STATE_NAMESPACE);
3072 if (CURRENT_NODE (ctx)->type == G_IR_NODE_STRUCT)
3073 state_switch (ctx, STATE_STRUCT);
3074 else if (CURRENT_NODE (ctx)->type == G_IR_NODE_UNION)
3075 state_switch (ctx, STATE_UNION);
3076 else if (CURRENT_NODE (ctx)->type == G_IR_NODE_OBJECT)
3077 state_switch (ctx, STATE_CLASS);
3080 int line_number, char_number;
3081 g_markup_parse_context_get_position (context, &line_number, &char_number);
3084 G_MARKUP_ERROR_INVALID_CONTENT,
3085 "Unexpected end tag '%s' on line %d char %d",
3087 line_number, char_number);
3095 require_end_element (GMarkupParseContext *context,
3097 const char *expected_name,
3098 const char *actual_name,
3101 return require_one_of_end_elements (context, ctx, actual_name, error, expected_name, NULL);
3105 end_element_handler (GMarkupParseContext *context,
3106 const gchar *element_name,
3110 ParseContext *ctx = user_data;
3112 g_debug ("</%s>", element_name);
3118 /* no need to GError here, GMarkup already catches this */
3121 case STATE_REPOSITORY:
3122 state_switch (ctx, STATE_END);
3126 if (require_end_element (context, ctx, "include", element_name, error))
3128 state_switch (ctx, STATE_REPOSITORY);
3132 case STATE_C_INCLUDE:
3133 if (require_end_element (context, ctx, "c:include", element_name, error))
3135 state_switch (ctx, STATE_REPOSITORY);
3140 if (require_end_element (context, ctx, "package", element_name, error))
3142 state_switch (ctx, STATE_REPOSITORY);
3146 case STATE_NAMESPACE:
3147 if (require_end_element (context, ctx, "namespace", element_name, error))
3149 ctx->current_module = NULL;
3150 state_switch (ctx, STATE_REPOSITORY);
3155 if (require_end_element (context, ctx, "alias", element_name, error))
3157 g_free (ctx->current_alias);
3158 ctx->current_alias = NULL;
3159 state_switch (ctx, STATE_NAMESPACE);
3163 case STATE_FUNCTION_RETURN:
3164 if (strcmp ("type", element_name) == 0)
3166 if (require_end_element (context, ctx, "return-value", element_name, error))
3168 state_switch (ctx, STATE_FUNCTION);
3172 case STATE_FUNCTION_PARAMETERS:
3173 if (require_end_element (context, ctx, "parameters", element_name, error))
3175 state_switch (ctx, STATE_FUNCTION);
3179 case STATE_FUNCTION_PARAMETER:
3180 if (strcmp ("type", element_name) == 0)
3182 if (require_end_element (context, ctx, "parameter", element_name, error))
3184 state_switch (ctx, STATE_FUNCTION_PARAMETERS);
3188 case STATE_FUNCTION:
3191 if (ctx->node_stack == NULL)
3193 state_switch (ctx, STATE_NAMESPACE);
3197 g_debug("case STATE_FUNCTION %d", CURRENT_NODE (ctx)->type);
3198 if (ctx->in_embedded_type)
3200 ctx->in_embedded_type = FALSE;
3201 state_switch (ctx, STATE_STRUCT_FIELD);
3203 else if (CURRENT_NODE (ctx)->type == G_IR_NODE_INTERFACE)
3204 state_switch (ctx, STATE_INTERFACE);
3205 else if (CURRENT_NODE (ctx)->type == G_IR_NODE_OBJECT)
3206 state_switch (ctx, STATE_CLASS);
3207 else if (CURRENT_NODE (ctx)->type == G_IR_NODE_BOXED)
3208 state_switch (ctx, STATE_BOXED);
3209 else if (CURRENT_NODE (ctx)->type == G_IR_NODE_STRUCT)
3210 state_switch (ctx, STATE_STRUCT);
3211 else if (CURRENT_NODE (ctx)->type == G_IR_NODE_UNION)
3212 state_switch (ctx, STATE_UNION);
3213 else if (CURRENT_NODE (ctx)->type == G_IR_NODE_ENUM ||
3214 CURRENT_NODE (ctx)->type == G_IR_NODE_FLAGS)
3215 state_switch (ctx, STATE_ENUM);
3218 int line_number, char_number;
3219 g_markup_parse_context_get_position (context, &line_number, &char_number);
3222 G_MARKUP_ERROR_INVALID_CONTENT,
3223 "Unexpected end tag '%s' on line %d char %d",
3225 line_number, char_number);
3231 case STATE_CLASS_FIELD:
3232 if (strcmp ("type", element_name) == 0)
3234 if (require_end_element (context, ctx, "field", element_name, error))
3236 state_switch (ctx, STATE_CLASS);
3240 case STATE_CLASS_PROPERTY:
3241 if (strcmp ("type", element_name) == 0)
3243 if (require_end_element (context, ctx, "property", element_name, error))
3245 state_switch (ctx, STATE_CLASS);
3250 if (require_end_element (context, ctx, "class", element_name, error))
3253 state_switch (ctx, STATE_NAMESPACE);
3257 case STATE_INTERFACE_PROPERTY:
3258 if (strcmp ("type", element_name) == 0)
3260 if (require_end_element (context, ctx, "property", element_name, error))
3262 state_switch (ctx, STATE_INTERFACE);
3266 case STATE_INTERFACE_FIELD:
3267 if (strcmp ("type", element_name) == 0)
3269 if (require_end_element (context, ctx, "field", element_name, error))
3271 state_switch (ctx, STATE_INTERFACE);
3275 case STATE_INTERFACE:
3276 if (require_end_element (context, ctx, "interface", element_name, error))
3279 state_switch (ctx, STATE_NAMESPACE);
3284 if (strcmp ("member", element_name) == 0)
3286 else if (strcmp ("function", element_name) == 0)
3288 else if (require_one_of_end_elements (context, ctx,
3289 element_name, error, "enumeration",
3293 state_switch (ctx, STATE_NAMESPACE);
3298 if (require_end_element (context, ctx, "glib:boxed", element_name, error))
3301 state_switch (ctx, STATE_NAMESPACE);
3305 case STATE_BOXED_FIELD:
3306 if (strcmp ("type", element_name) == 0)
3308 if (require_end_element (context, ctx, "field", element_name, error))
3310 state_switch (ctx, STATE_BOXED);
3314 case STATE_STRUCT_FIELD:
3315 if (strcmp ("type", element_name) == 0)
3317 if (require_end_element (context, ctx, "field", element_name, error))
3319 state_switch (ctx, STATE_STRUCT);
3324 if (require_end_element (context, ctx, "record", element_name, error))
3326 state_switch_end_struct_or_union (context, ctx, element_name, error);
3330 case STATE_UNION_FIELD:
3331 if (strcmp ("type", element_name) == 0)
3333 if (require_end_element (context, ctx, "field", element_name, error))
3335 state_switch (ctx, STATE_UNION);
3340 if (require_end_element (context, ctx, "union", element_name, error))
3342 state_switch_end_struct_or_union (context, ctx, element_name, error);
3345 case STATE_IMPLEMENTS:
3346 if (strcmp ("interface", element_name) == 0)
3348 if (require_end_element (context, ctx, "implements", element_name, error))
3349 state_switch (ctx, STATE_CLASS);
3351 case STATE_PREREQUISITE:
3352 if (require_end_element (context, ctx, "prerequisite", element_name, error))
3353 state_switch (ctx, STATE_INTERFACE);
3355 case STATE_NAMESPACE_CONSTANT:
3356 case STATE_CLASS_CONSTANT:
3357 case STATE_INTERFACE_CONSTANT:
3358 if (strcmp ("type", element_name) == 0)
3360 if (require_end_element (context, ctx, "constant", element_name, error))
3364 case STATE_NAMESPACE_CONSTANT:
3366 state_switch (ctx, STATE_NAMESPACE);
3368 case STATE_CLASS_CONSTANT:
3369 state_switch (ctx, STATE_CLASS);
3371 case STATE_INTERFACE_CONSTANT:
3372 state_switch (ctx, STATE_INTERFACE);
3375 g_assert_not_reached ();
3381 if ((strcmp ("type", element_name) == 0) || (strcmp ("array", element_name) == 0) ||
3382 (strcmp ("varargs", element_name) == 0))
3387 case STATE_ATTRIBUTE:
3388 if (strcmp ("attribute", element_name) == 0)
3390 state_switch (ctx, ctx->prev_state);
3395 if (strcmp ("doc", element_name) == 0)
3397 state_switch (ctx, ctx->prev_state);
3401 case STATE_PASSTHROUGH:
3402 ctx->unknown_depth -= 1;
3403 g_assert (ctx->unknown_depth >= 0);
3404 if (ctx->unknown_depth == 0)
3405 state_switch (ctx, ctx->prev_state);
3408 g_error ("Unhandled state %d in end_element_handler\n", ctx->state);
3413 text_handler (GMarkupParseContext *context,
3419 /* FIXME warn about non-whitespace text */
3423 cleanup (GMarkupParseContext *context,
3427 ParseContext *ctx = user_data;
3430 for (m = ctx->modules; m; m = m->next)
3431 _g_ir_module_free (m->data);
3432 g_list_free (ctx->modules);
3433 ctx->modules = NULL;
3435 ctx->current_module = NULL;
3439 * _g_ir_parser_parse_string:
3440 * @parser: a #GIrParser
3441 * @namespace: the namespace of the string
3442 * @filename: (allow-none): Path to parsed file, or %NULL
3443 * @buffer: the data containing the XML
3444 * @length: length of the data
3445 * @error: return location for a #GError, or %NULL
3447 * Parse a string that holds a complete GIR XML file, and return a list of a
3448 * a #GirModule for each <namespace/> element within the file.
3450 * Returns: (transfer none): a new #GirModule
3453 _g_ir_parser_parse_string (GIrParser *parser,
3454 const gchar *namespace,
3455 const gchar *filename,
3456 const gchar *buffer,
3460 ParseContext ctx = { 0 };
3461 GMarkupParseContext *context;
3463 ctx.parser = parser;
3464 ctx.state = STATE_START;
3465 ctx.file_path = filename;
3466 ctx.namespace = namespace;
3467 ctx.include_modules = NULL;
3468 ctx.aliases = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
3469 ctx.disguised_structures = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
3471 ctx.dependencies = NULL;
3472 ctx.current_module = NULL;
3474 context = g_markup_parse_context_new (&firstpass_parser, 0, &ctx, NULL);
3476 if (!g_markup_parse_context_parse (context, buffer, length, error))
3479 if (!g_markup_parse_context_end_parse (context, error))
3482 g_markup_parse_context_free (context);
3484 ctx.state = STATE_START;
3485 context = g_markup_parse_context_new (&markup_parser, 0, &ctx, NULL);
3486 if (!g_markup_parse_context_parse (context, buffer, length, error))
3489 if (!g_markup_parse_context_end_parse (context, error))
3492 parser->parsed_modules = g_list_concat (g_list_copy (ctx.modules),
3493 parser->parsed_modules);
3497 if (ctx.modules == NULL)
3499 /* An error occurred before we created a module, so we haven't
3500 * transferred ownership of these hash tables to the module.
3502 if (ctx.aliases != NULL)
3503 g_hash_table_destroy (ctx.aliases);
3504 if (ctx.disguised_structures != NULL)
3505 g_hash_table_destroy (ctx.disguised_structures);
3506 g_list_free (ctx.include_modules);
3509 g_markup_parse_context_free (context);
3512 return ctx.modules->data;
3514 if (error && *error == NULL)
3517 G_MARKUP_ERROR_INVALID_CONTENT,
3518 "Expected namespace element in the gir file");
3523 * _g_ir_parser_parse_file:
3524 * @parser: a #GIrParser
3525 * @filename: filename to parse
3526 * @error: return location for a #GError, or %NULL
3528 * Parse GIR XML file, and return a list of a a #GirModule for each
3529 * <namespace/> element within the file.
3531 * Returns: (transfer container): a newly allocated list of #GIrModule. The modules themselves
3532 * are owned by the #GIrParser and will be freed along with the parser.
3535 _g_ir_parser_parse_file (GIrParser *parser,
3536 const gchar *filename,
3546 if (!g_str_has_suffix (filename, ".gir"))
3550 G_MARKUP_ERROR_INVALID_CONTENT,
3551 "Expected filename to end with '.gir'");
3555 g_debug ("[parsing] filename %s", filename);
3557 slash = g_strrstr (filename, "/");
3559 namespace = g_strdup (filename);
3561 namespace = g_strdup (slash+1);
3562 namespace[strlen(namespace)-4] = '\0';
3564 /* Remove version */
3565 dash = strstr (namespace, "-");
3569 if (!g_file_get_contents (filename, &buffer, &length, error))
3572 module = _g_ir_parser_parse_string (parser, namespace, filename, buffer, length, error);