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 "girmodule.h"
40 STATE_FUNCTION_RETURN,
41 STATE_FUNCTION_PARAMETERS,
42 STATE_FUNCTION_PARAMETER, /* 10 */
47 STATE_INTERFACE_PROPERTY, /* 15 */
48 STATE_INTERFACE_FIELD,
52 STATE_BOXED_FIELD, /* 20 */
57 STATE_UNION_FIELD, /* 25 */
58 STATE_NAMESPACE_CONSTANT,
60 STATE_INTERFACE_CONSTANT,
65 typedef struct _ParseContext ParseContext;
69 ParseState prev_state;
71 const char * const*includes;
74 gboolean prefix_aliases;
78 const char *namespace;
79 GIrModule *current_module;
80 GIrNode *current_node;
81 GIrNode *current_typed;
83 GList *type_parameters;
88 start_alias (GMarkupParseContext *context,
89 const gchar *element_name,
90 const gchar **attribute_names,
91 const gchar **attribute_values,
96 firstpass_start_element_handler (GMarkupParseContext *context,
97 const gchar *element_name,
98 const gchar **attribute_names,
99 const gchar **attribute_values,
103 ParseContext *ctx = user_data;
105 if (strcmp (element_name, "alias") == 0)
107 start_alias (context, element_name, attribute_names, attribute_values,
113 firstpass_end_element_handler (GMarkupParseContext *context,
114 const gchar *element_name,
118 ParseContext *ctx = user_data;
122 static GMarkupParser firstpass_parser =
124 firstpass_start_element_handler,
125 firstpass_end_element_handler,
132 locate_gir (const char *name, const char * const* extra_paths)
134 const gchar *const *datadirs;
135 const gchar *const *dir;
139 gboolean firstpass = TRUE;
141 datadirs = g_get_system_data_dirs ();
143 girname = g_strdup_printf ("%s.gir", name);
145 for (dir = datadirs; *dir; dir++)
147 path = g_build_filename (*dir, "gir", girname, NULL);
148 if (g_file_test (path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))
153 if (extra_paths != NULL)
155 for (dir = extra_paths; *dir; dir++)
157 path = g_build_filename (*dir, girname, NULL);
158 if (g_file_test (path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))
168 #define MISSING_ATTRIBUTE(ctx,error,element,attribute) \
170 int line_number, char_number; \
171 g_markup_parse_context_get_position (context, &line_number, &char_number); \
172 g_set_error (error, \
174 G_MARKUP_ERROR_INVALID_CONTENT, \
175 "Line %d, character %d: The attribute '%s' on the element '%s' must be specified", \
176 line_number, char_number, attribute, element); \
180 backtrace_stderr (void)
188 size = backtrace (array, 50);
189 strings = (char**) backtrace_symbols (array, size);
191 fprintf (stderr, "--- BACKTRACE (%zd frames) ---\n", size);
193 for (i = 0; i < size; i++)
194 fprintf (stderr, "%s\n", strings[i]);
196 fprintf (stderr, "--- END BACKTRACE ---\n", size);
204 find_attribute (const gchar *name,
205 const gchar **attribute_names,
206 const gchar **attribute_values)
210 for (i = 0; attribute_names[i] != NULL; i++)
211 if (strcmp (attribute_names[i], name) == 0)
212 return attribute_values[i];
218 state_switch (ParseContext *ctx, ParseState newstate)
220 g_debug ("State: %d", newstate);
221 ctx->prev_state = ctx->state;
222 ctx->state = newstate;
225 static GIrNodeType * parse_type_internal (const gchar *str, gchar **next, gboolean in_glib,
226 gboolean in_gobject);
234 static BasicTypeInfo basic_types[] = {
235 { "none", GI_TYPE_TAG_VOID, 0 },
236 { "any", GI_TYPE_TAG_VOID, 1 },
238 { "bool", GI_TYPE_TAG_BOOLEAN, 0 },
239 { "char", GI_TYPE_TAG_INT8, 0 },
240 { "int8", GI_TYPE_TAG_INT8, 0 },
241 { "uint8", GI_TYPE_TAG_UINT8, 0 },
242 { "int16", GI_TYPE_TAG_INT16, 0 },
243 { "uint16", GI_TYPE_TAG_UINT16, 0 },
244 { "int32", GI_TYPE_TAG_INT32, 0 },
245 { "uint32", GI_TYPE_TAG_UINT32, 0 },
246 { "int64", GI_TYPE_TAG_INT64, 0 },
247 { "uint64", GI_TYPE_TAG_UINT64, 0 },
248 { "int", GI_TYPE_TAG_INT, 0 },
249 { "uint", GI_TYPE_TAG_UINT, 0 },
250 { "long", GI_TYPE_TAG_LONG, 0 },
251 { "ulong", GI_TYPE_TAG_ULONG, 0 },
252 { "ssize_t", GI_TYPE_TAG_SSIZE, 0 },
253 { "ssize", GI_TYPE_TAG_SSIZE, 0 },
254 { "size_t", GI_TYPE_TAG_SIZE, 0 },
255 { "size", GI_TYPE_TAG_SIZE, 0 },
256 { "float", GI_TYPE_TAG_FLOAT, 0 },
257 { "double", GI_TYPE_TAG_DOUBLE, 0 },
258 { "time_t", GI_TYPE_TAG_TIME_T, 0 },
259 { "GType", GI_TYPE_TAG_GTYPE, 0 },
260 { "utf8", GI_TYPE_TAG_UTF8, 1 },
261 { "filename", GI_TYPE_TAG_FILENAME,1 },
264 static const BasicTypeInfo *
265 parse_basic (const char *str)
268 gint n_basic = G_N_ELEMENTS (basic_types);
269 gchar *temporary_type = NULL;
273 for (i = 0; i < n_basic; i++)
275 if (g_str_has_prefix (str, basic_types[i].str))
276 return &(basic_types[i]);
282 parse_type_internal (const gchar *str, char **next, gboolean in_glib,
285 const BasicTypeInfo *basic;
287 char *temporary_type = NULL;
289 type = (GIrNodeType *)g_ir_node_new (G_IR_NODE_TYPE);
291 type->unparsed = g_strdup (str);
293 /* See comment below on GLib.List handling */
294 if (in_gobject && strcmp (str, "Type") == 0)
296 temporary_type = g_strdup ("GLib.Type");
297 str = temporary_type;
300 basic = parse_basic (str);
303 type->is_basic = TRUE;
304 type->tag = basic->tag;
305 type->is_pointer = basic->pointer;
307 str += strlen(basic->str);
311 /* If we're inside GLib, handle "List" etc. by prefixing with
312 * "GLib." so the parsing code below doesn't have to get more
315 if (g_str_has_prefix (str, "List<") ||
316 strcmp (str, "List") == 0)
318 temporary_type = g_strdup_printf ("GLib.List%s", str + 4);
319 str = temporary_type;
321 else if (g_str_has_prefix (str, "SList<") ||
322 strcmp (str, "SList") == 0)
324 temporary_type = g_strdup_printf ("GLib.SList%s", str + 5);
325 str = temporary_type;
327 else if (g_str_has_prefix (str, "HashTable<") ||
328 strcmp (str, "HashTable") == 0)
330 temporary_type = g_strdup_printf ("GLib.HashTable%s", str + 9);
331 str = temporary_type;
333 else if (g_str_has_prefix (str, "Error<") ||
334 strcmp (str, "Error") == 0)
336 temporary_type = g_strdup_printf ("GLib.Error%s", str + 5);
337 str = temporary_type;
342 /* found a basic type */;
343 else if (g_str_has_prefix (str, "GLib.List") ||
344 g_str_has_prefix (str, "GLib.SList"))
346 str += strlen ("GLib.");
347 if (g_str_has_prefix (str, "List"))
349 type->tag = GI_TYPE_TAG_GLIST;
350 type->is_glist = TRUE;
351 type->is_pointer = TRUE;
352 str += strlen ("List");
356 type->tag = GI_TYPE_TAG_GSLIST;
357 type->is_gslist = TRUE;
358 type->is_pointer = TRUE;
359 str += strlen ("SList");
362 else if (g_str_has_prefix (str, "GLib.HashTable"))
364 str += strlen ("GLib.");
366 type->tag = GI_TYPE_TAG_GHASH;
367 type->is_ghashtable = TRUE;
368 type->is_pointer = TRUE;
369 str += strlen ("HashTable");
371 else if (g_str_has_prefix (str, "GLib.Error"))
373 str += strlen ("GLib.");
375 type->tag = GI_TYPE_TAG_ERROR;
376 type->is_error = TRUE;
377 type->is_pointer = TRUE;
378 str += strlen ("Error");
385 end = strchr (str, '>');
386 tmp = g_strndup (str, end - str);
387 type->errors = g_strsplit (tmp, ",", 0);
395 type->tag = GI_TYPE_TAG_INTERFACE;
396 type->is_interface = TRUE;
397 const char *start = str;
399 /* must be an interface type */
400 while (g_ascii_isalnum (*str) ||
407 type->interface = g_strndup (start, str - start);
412 g_assert (type->tag >= 0 && type->tag <= GI_TYPE_TAG_ERROR);
413 g_free (temporary_type);
417 g_ir_node_free ((GIrNode *)type);
418 g_free (temporary_type);
423 resolve_aliases (ParseContext *ctx, const gchar *type)
427 GSList *seen_values = NULL;
429 seen_values = g_slist_prepend (seen_values, (char*)type);
430 while (g_hash_table_lookup_extended (ctx->aliases, type, &orig, &value))
432 g_debug ("Resolved: %s => %s", type, value);
434 if (g_slist_find_custom (seen_values, type,
435 (GCompareFunc)strcmp) != NULL)
437 seen_values = g_slist_prepend (seen_values, (gchar*)type);
439 g_slist_free (seen_values);
444 parse_type (ParseContext *ctx, const gchar *type)
448 const BasicTypeInfo *basic;
449 gboolean in_glib, in_gobject;
450 gboolean matched_special = FALSE;
452 in_glib = strcmp (ctx->namespace, "GLib") == 0;
453 in_gobject = strcmp (ctx->namespace, "GObject") == 0;
455 /* Do not search aliases for basic types */
456 basic = parse_basic (type);
458 type = resolve_aliases (ctx, type);
460 node = parse_type_internal (type, NULL, in_glib, in_gobject);
462 g_debug ("Parsed type: %s => %d", type, node->tag);
464 g_critical ("Failed to parse type: '%s'", type);
470 start_glib_boxed (GMarkupParseContext *context,
471 const gchar *element_name,
472 const gchar **attribute_names,
473 const gchar **attribute_values,
478 const gchar *typename;
479 const gchar *typeinit;
480 const gchar *deprecated;
483 if (!(strcmp (element_name, "glib:boxed") == 0 &&
484 ctx->state == STATE_NAMESPACE))
487 name = find_attribute ("glib:name", attribute_names, attribute_values);
488 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
489 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
490 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
494 MISSING_ATTRIBUTE (context, error, element_name, "glib:name");
497 else if (typename == NULL)
499 MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
502 else if (typeinit == NULL)
504 MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
508 boxed = (GIrNodeBoxed *) g_ir_node_new (G_IR_NODE_BOXED);
510 ((GIrNode *)boxed)->name = g_strdup (name);
511 boxed->gtype_name = g_strdup (typename);
512 boxed->gtype_init = g_strdup (typeinit);
514 boxed->deprecated = TRUE;
516 boxed->deprecated = FALSE;
518 ctx->current_node = (GIrNode *)boxed;
519 ctx->current_module->entries =
520 g_list_append (ctx->current_module->entries, boxed);
522 state_switch (ctx, STATE_BOXED);
528 start_function (GMarkupParseContext *context,
529 const gchar *element_name,
530 const gchar **attribute_names,
531 const gchar **attribute_values,
537 const gchar *deprecated;
538 GIrNodeFunction *function;
539 gboolean found = FALSE;
543 case STATE_NAMESPACE:
544 found = (strcmp (element_name, "function") == 0 ||
545 strcmp (element_name, "callback") == 0);
551 found = strcmp (element_name, "constructor") == 0;
553 case STATE_INTERFACE:
555 strcmp (element_name, "method") == 0 ||
556 strcmp (element_name, "callback") == 0);
565 name = find_attribute ("name", attribute_names, attribute_values);
566 symbol = find_attribute ("c:identifier", attribute_names, attribute_values);
567 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
571 MISSING_ATTRIBUTE (context, error, element_name, "name");
574 else if (strcmp (element_name, "callback") != 0 && symbol == NULL)
576 MISSING_ATTRIBUTE (context, error, element_name, "c:identifier");
580 function = (GIrNodeFunction *) g_ir_node_new (G_IR_NODE_FUNCTION);
582 ((GIrNode *)function)->name = g_strdup (name);
583 function->symbol = g_strdup (symbol);
584 function->parameters = NULL;
586 function->deprecated = TRUE;
588 function->deprecated = FALSE;
590 if (strcmp (element_name, "method") == 0 ||
591 strcmp (element_name, "constructor") == 0)
593 function->is_method = TRUE;
595 if (strcmp (element_name, "constructor") == 0)
596 function->is_constructor = TRUE;
598 function->is_constructor = FALSE;
602 function->is_method = FALSE;
603 function->is_setter = FALSE;
604 function->is_getter = FALSE;
605 function->is_constructor = FALSE;
606 if (strcmp (element_name, "callback") == 0)
607 ((GIrNode *)function)->type = G_IR_NODE_CALLBACK;
610 if (ctx->current_node == NULL)
612 ctx->current_module->entries =
613 g_list_append (ctx->current_module->entries, function);
616 switch (ctx->current_node->type)
618 case G_IR_NODE_INTERFACE:
619 case G_IR_NODE_OBJECT:
621 GIrNodeInterface *iface;
623 iface = (GIrNodeInterface *)ctx->current_node;
624 iface->members = g_list_append (iface->members, function);
627 case G_IR_NODE_BOXED:
631 boxed = (GIrNodeBoxed *)ctx->current_node;
632 boxed->members = g_list_append (boxed->members, function);
635 case G_IR_NODE_STRUCT:
637 GIrNodeStruct *struct_;
639 struct_ = (GIrNodeStruct *)ctx->current_node;
640 struct_->members = g_list_append (struct_->members, function); }
642 case G_IR_NODE_UNION:
644 GIrNodeUnion *union_;
646 union_ = (GIrNodeUnion *)ctx->current_node;
647 union_->members = g_list_append (union_->members, function);
651 g_assert_not_reached ();
654 ctx->current_node = (GIrNode *)function;
655 state_switch (ctx, STATE_FUNCTION);
661 start_parameter (GMarkupParseContext *context,
662 const gchar *element_name,
663 const gchar **attribute_names,
664 const gchar **attribute_values,
669 const gchar *direction;
672 const gchar *optional;
674 const gchar *transfer;
677 if (!(strcmp (element_name, "parameter") == 0 &&
678 ctx->state == STATE_FUNCTION_PARAMETERS))
681 name = find_attribute ("name", attribute_names, attribute_values);
682 direction = find_attribute ("direction", attribute_names, attribute_values);
683 retval = find_attribute ("retval", attribute_names, attribute_values);
684 dipper = find_attribute ("dipper", attribute_names, attribute_values);
685 optional = find_attribute ("optional", attribute_names, attribute_values);
686 nullok = find_attribute ("null-ok", attribute_names, attribute_values);
687 transfer = find_attribute ("transfer", attribute_names, attribute_values);
692 param = (GIrNodeParam *)g_ir_node_new (G_IR_NODE_PARAM);
694 ctx->current_typed = (GIrNode*) param;
695 ctx->current_typed->name = g_strdup (name);
697 state_switch (ctx, STATE_FUNCTION_PARAMETER);
699 if (direction && strcmp (direction, "out") == 0)
704 else if (direction && strcmp (direction, "inout") == 0)
715 if (retval && strcmp (retval, "1") == 0)
716 param->retval = TRUE;
718 param->retval = FALSE;
720 if (dipper && strcmp (dipper, "1") == 0)
721 param->dipper = TRUE;
723 param->dipper = FALSE;
725 if (optional && strcmp (optional, "1") == 0)
726 param->optional = TRUE;
728 param->optional = FALSE;
730 if (nullok && strcmp (nullok, "1") == 0)
731 param->null_ok = TRUE;
733 param->null_ok = FALSE;
735 if (transfer && strcmp (transfer, "none") == 0)
737 param->transfer = FALSE;
738 param->shallow_transfer = FALSE;
740 else if (transfer && strcmp (transfer, "shallow") == 0)
742 param->transfer = FALSE;
743 param->shallow_transfer = TRUE;
749 if (strcmp (transfer, "full") != 0)
750 g_warning ("Unknown transfer %s", transfer);
752 param->transfer = TRUE;
754 else if (param->in && !param->out)
755 param->transfer = FALSE;
757 param->transfer = TRUE;
758 param->shallow_transfer = FALSE;
761 ((GIrNode *)param)->name = g_strdup (name);
763 switch (ctx->current_node->type)
765 case G_IR_NODE_FUNCTION:
766 case G_IR_NODE_CALLBACK:
768 GIrNodeFunction *func;
770 func = (GIrNodeFunction *)ctx->current_node;
771 func->parameters = g_list_append (func->parameters, param);
774 case G_IR_NODE_SIGNAL:
776 GIrNodeSignal *signal;
778 signal = (GIrNodeSignal *)ctx->current_node;
779 signal->parameters = g_list_append (signal->parameters, param);
782 case G_IR_NODE_VFUNC:
786 vfunc = (GIrNodeVFunc *)ctx->current_node;
787 vfunc->parameters = g_list_append (vfunc->parameters, param);
791 g_assert_not_reached ();
798 start_field (GMarkupParseContext *context,
799 const gchar *element_name,
800 const gchar **attribute_names,
801 const gchar **attribute_values,
806 const gchar *readable;
807 const gchar *writable;
819 case STATE_INTERFACE:
825 if (strcmp (element_name, "field") != 0)
828 name = find_attribute ("name", attribute_names, attribute_values);
829 readable = find_attribute ("readable", attribute_names, attribute_values);
830 writable = find_attribute ("writable", attribute_names, attribute_values);
831 bits = find_attribute ("bits", attribute_names, attribute_values);
832 branch = find_attribute ("branch", attribute_names, attribute_values);
833 offset = find_attribute ("offset", attribute_names, attribute_values);
837 MISSING_ATTRIBUTE (context, error, element_name, "name");
841 field = (GIrNodeField *)g_ir_node_new (G_IR_NODE_FIELD);
842 ctx->current_typed = (GIrNode*) field;
843 ((GIrNode *)field)->name = g_strdup (name);
844 if (readable && strcmp (readable, "1") == 0)
845 field->readable = TRUE;
847 field->readable = FALSE;
849 if (writable && strcmp (writable, "1") == 0)
850 field->writable = TRUE;
852 field->writable = FALSE;
855 field->bits = atoi (bits);
860 field->offset = atoi (offset);
864 switch (ctx->current_node->type)
866 case G_IR_NODE_OBJECT:
868 GIrNodeInterface *iface;
870 iface = (GIrNodeInterface *)ctx->current_node;
871 iface->members = g_list_append (iface->members, field);
872 state_switch (ctx, STATE_CLASS_FIELD);
875 case G_IR_NODE_INTERFACE:
877 GIrNodeInterface *iface;
879 iface = (GIrNodeInterface *)ctx->current_node;
880 iface->members = g_list_append (iface->members, field);
881 state_switch (ctx, STATE_INTERFACE_FIELD);
884 case G_IR_NODE_BOXED:
888 boxed = (GIrNodeBoxed *)ctx->current_node;
889 boxed->members = g_list_append (boxed->members, field);
890 state_switch (ctx, STATE_BOXED_FIELD);
893 case G_IR_NODE_STRUCT:
895 GIrNodeStruct *struct_;
897 struct_ = (GIrNodeStruct *)ctx->current_node;
898 struct_->members = g_list_append (struct_->members, field);
899 state_switch (ctx, STATE_STRUCT_FIELD);
902 case G_IR_NODE_UNION:
904 GIrNodeUnion *union_;
906 union_ = (GIrNodeUnion *)ctx->current_node;
907 union_->members = g_list_append (union_->members, field);
910 GIrNodeConstant *constant;
912 constant = (GIrNodeConstant *) g_ir_node_new (G_IR_NODE_CONSTANT);
913 ((GIrNode *)constant)->name = g_strdup (name);
914 constant->value = g_strdup (branch);
915 constant->type = union_->discriminator_type;
916 constant->deprecated = FALSE;
918 union_->discriminators = g_list_append (union_->discriminators, constant);
920 state_switch (ctx, STATE_UNION_FIELD);
924 g_assert_not_reached ();
931 start_alias (GMarkupParseContext *context,
932 const gchar *element_name,
933 const gchar **attribute_names,
934 const gchar **attribute_values,
944 name = find_attribute ("name", attribute_names, attribute_values);
947 MISSING_ATTRIBUTE (context, error, element_name, "name");
951 target = find_attribute ("target", attribute_names, attribute_values);
954 MISSING_ATTRIBUTE (context, error, element_name, "target");
958 value = g_strdup (target);
959 if (ctx->prefix_aliases)
961 key = g_strdup_printf ("%s.%s", ctx->namespace, name);
962 if (!strchr (target, '.'))
964 const BasicTypeInfo *basic = parse_basic (target);
968 /* For non-basic types, re-qualify the interface */
969 value = g_strdup_printf ("%s.%s", ctx->namespace, target);
975 key = g_strdup (name);
978 g_hash_table_insert (ctx->aliases, key, value);
984 start_enum (GMarkupParseContext *context,
985 const gchar *element_name,
986 const gchar **attribute_names,
987 const gchar **attribute_values,
991 if ((strcmp (element_name, "enumeration") == 0 && ctx->state == STATE_NAMESPACE) ||
992 (strcmp (element_name, "bitfield") == 0 && ctx->state == STATE_NAMESPACE))
995 const gchar *typename;
996 const gchar *typeinit;
997 const gchar *deprecated;
999 name = find_attribute ("name", attribute_names, attribute_values);
1000 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
1001 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
1002 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1005 MISSING_ATTRIBUTE (context, error, element_name, "name");
1010 if (strcmp (element_name, "enumeration") == 0)
1011 enum_ = (GIrNodeEnum *) g_ir_node_new (G_IR_NODE_ENUM);
1013 enum_ = (GIrNodeEnum *) g_ir_node_new (G_IR_NODE_FLAGS);
1014 ((GIrNode *)enum_)->name = g_strdup (name);
1015 enum_->gtype_name = g_strdup (typename);
1016 enum_->gtype_init = g_strdup (typeinit);
1018 enum_->deprecated = TRUE;
1020 enum_->deprecated = FALSE;
1022 ctx->current_node = (GIrNode *) enum_;
1023 ctx->current_module->entries =
1024 g_list_append (ctx->current_module->entries, enum_);
1026 state_switch (ctx, STATE_ENUM);
1035 start_property (GMarkupParseContext *context,
1036 const gchar *element_name,
1037 const gchar **attribute_names,
1038 const gchar **attribute_values,
1042 if (strcmp (element_name, "property") == 0 &&
1043 (ctx->state == STATE_CLASS ||
1044 ctx->state == STATE_INTERFACE))
1047 const gchar *readable;
1048 const gchar *writable;
1049 const gchar *construct;
1050 const gchar *construct_only;
1052 name = find_attribute ("name", attribute_names, attribute_values);
1053 readable = find_attribute ("readable", attribute_names, attribute_values);
1054 writable = find_attribute ("writable", attribute_names, attribute_values);
1055 construct = find_attribute ("construct", attribute_names, attribute_values);
1056 construct_only = find_attribute ("construct-only", attribute_names, attribute_values);
1059 MISSING_ATTRIBUTE (context, error, element_name, "name");
1062 GIrNodeProperty *property;
1063 GIrNodeInterface *iface;
1065 property = (GIrNodeProperty *) g_ir_node_new (G_IR_NODE_PROPERTY);
1066 ctx->current_typed = (GIrNode*) property;
1068 ((GIrNode *)property)->name = g_strdup (name);
1070 /* Assume properties are readable */
1071 if (readable == NULL || strcmp (readable, "1") == 0)
1072 property->readable = TRUE;
1074 property->readable = FALSE;
1075 if (writable && strcmp (writable, "1") == 0)
1076 property->writable = TRUE;
1078 property->writable = FALSE;
1079 if (construct && strcmp (construct, "1") == 0)
1080 property->construct = TRUE;
1082 property->construct = FALSE;
1083 if (construct_only && strcmp (construct_only, "1") == 0)
1084 property->construct_only = TRUE;
1086 property->construct_only = FALSE;
1088 iface = (GIrNodeInterface *)ctx->current_node;
1089 iface->members = g_list_append (iface->members, property);
1091 if (ctx->state == STATE_CLASS)
1092 state_switch (ctx, STATE_CLASS_PROPERTY);
1093 else if (ctx->state == STATE_INTERFACE)
1094 state_switch (ctx, STATE_INTERFACE_PROPERTY);
1096 g_assert_not_reached ();
1105 parse_value (const gchar *str)
1109 /* FIXME just a quick hack */
1110 shift_op = strstr (str, "<<");
1116 base = strtol (str, NULL, 10);
1117 shift = strtol (shift_op + 3, NULL, 10);
1119 return base << shift;
1122 return strtol (str, NULL, 10);
1128 start_member (GMarkupParseContext *context,
1129 const gchar *element_name,
1130 const gchar **attribute_names,
1131 const gchar **attribute_values,
1135 if (strcmp (element_name, "member") == 0 &&
1136 ctx->state == STATE_ENUM)
1140 const gchar *deprecated;
1142 name = find_attribute ("name", attribute_names, attribute_values);
1143 value = find_attribute ("value", attribute_names, attribute_values);
1144 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1147 MISSING_ATTRIBUTE (context, error, element_name, "name");
1151 GIrNodeValue *value_;
1153 value_ = (GIrNodeValue *) g_ir_node_new (G_IR_NODE_VALUE);
1155 ((GIrNode *)value_)->name = g_strdup (name);
1157 value_->value = parse_value (value);
1160 value_->deprecated = TRUE;
1162 value_->deprecated = FALSE;
1164 enum_ = (GIrNodeEnum *)ctx->current_node;
1165 enum_->values = g_list_append (enum_->values, value_);
1174 start_constant (GMarkupParseContext *context,
1175 const gchar *element_name,
1176 const gchar **attribute_names,
1177 const gchar **attribute_values,
1181 if (strcmp (element_name, "constant") == 0 &&
1182 (ctx->state == STATE_NAMESPACE ||
1183 ctx->state == STATE_CLASS ||
1184 ctx->state == STATE_INTERFACE))
1188 const gchar *deprecated;
1190 name = find_attribute ("name", attribute_names, attribute_values);
1191 value = find_attribute ("value", attribute_names, attribute_values);
1192 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1195 MISSING_ATTRIBUTE (context, error, element_name, "name");
1196 else if (value == NULL)
1197 MISSING_ATTRIBUTE (context, error, element_name, "value");
1200 GIrNodeConstant *constant;
1202 constant = (GIrNodeConstant *) g_ir_node_new (G_IR_NODE_CONSTANT);
1204 ((GIrNode *)constant)->name = g_strdup (name);
1205 constant->value = g_strdup (value);
1207 ctx->current_typed = (GIrNode*) constant;
1210 constant->deprecated = TRUE;
1212 constant->deprecated = FALSE;
1214 if (ctx->state == STATE_NAMESPACE)
1216 ctx->current_node = (GIrNode *) constant;
1217 ctx->current_module->entries =
1218 g_list_append (ctx->current_module->entries, constant);
1222 GIrNodeInterface *iface;
1224 iface = (GIrNodeInterface *)ctx->current_node;
1225 iface->members = g_list_append (iface->members, constant);
1230 case STATE_NAMESPACE:
1231 state_switch (ctx, STATE_NAMESPACE_CONSTANT);
1234 state_switch (ctx, STATE_CLASS_CONSTANT);
1236 case STATE_INTERFACE:
1237 state_switch (ctx, STATE_INTERFACE_CONSTANT);
1240 g_assert_not_reached ();
1251 start_errordomain (GMarkupParseContext *context,
1252 const gchar *element_name,
1253 const gchar **attribute_names,
1254 const gchar **attribute_values,
1258 if (strcmp (element_name, "errordomain") == 0 &&
1259 ctx->state == STATE_NAMESPACE)
1262 const gchar *getquark;
1264 const gchar *deprecated;
1266 name = find_attribute ("name", attribute_names, attribute_values);
1267 getquark = find_attribute ("get-quark", attribute_names, attribute_values);
1268 codes = find_attribute ("codes", attribute_names, attribute_values);
1269 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1272 MISSING_ATTRIBUTE (context, error, element_name, "name");
1273 else if (getquark == NULL)
1274 MISSING_ATTRIBUTE (context, error, element_name, "getquark");
1275 else if (codes == NULL)
1276 MISSING_ATTRIBUTE (context, error, element_name, "codes");
1279 GIrNodeErrorDomain *domain;
1281 domain = (GIrNodeErrorDomain *) g_ir_node_new (G_IR_NODE_ERROR_DOMAIN);
1283 ((GIrNode *)domain)->name = g_strdup (name);
1284 domain->getquark = g_strdup (getquark);
1285 domain->codes = g_strdup (codes);
1288 domain->deprecated = TRUE;
1290 domain->deprecated = FALSE;
1292 ctx->current_node = (GIrNode *) domain;
1293 ctx->current_module->entries =
1294 g_list_append (ctx->current_module->entries, domain);
1296 state_switch (ctx, STATE_ERRORDOMAIN);
1305 start_interface (GMarkupParseContext *context,
1306 const gchar *element_name,
1307 const gchar **attribute_names,
1308 const gchar **attribute_values,
1312 if (strcmp (element_name, "interface") == 0 &&
1313 ctx->state == STATE_NAMESPACE)
1316 const gchar *typename;
1317 const gchar *typeinit;
1318 const gchar *deprecated;
1320 name = find_attribute ("name", attribute_names, attribute_values);
1321 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
1322 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
1323 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1326 MISSING_ATTRIBUTE (context, error, element_name, "name");
1327 else if (typename == NULL)
1328 MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
1329 else if (typeinit == NULL)
1330 MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
1333 GIrNodeInterface *iface;
1335 iface = (GIrNodeInterface *) g_ir_node_new (G_IR_NODE_INTERFACE);
1336 ((GIrNode *)iface)->name = g_strdup (name);
1337 iface->gtype_name = g_strdup (typename);
1338 iface->gtype_init = g_strdup (typeinit);
1340 iface->deprecated = TRUE;
1342 iface->deprecated = FALSE;
1344 ctx->current_node = (GIrNode *) iface;
1345 ctx->current_module->entries =
1346 g_list_append (ctx->current_module->entries, iface);
1348 state_switch (ctx, STATE_INTERFACE);
1358 start_class (GMarkupParseContext *context,
1359 const gchar *element_name,
1360 const gchar **attribute_names,
1361 const gchar **attribute_values,
1365 if (strcmp (element_name, "class") == 0 &&
1366 ctx->state == STATE_NAMESPACE)
1369 const gchar *parent;
1370 const gchar *typename;
1371 const gchar *typeinit;
1372 const gchar *deprecated;
1374 name = find_attribute ("name", attribute_names, attribute_values);
1375 parent = find_attribute ("parent", attribute_names, attribute_values);
1376 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
1377 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
1378 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1381 MISSING_ATTRIBUTE (context, error, element_name, "name");
1382 else if (typename == NULL)
1383 MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
1384 else if (typeinit == NULL && strcmp (typename, "GObject"))
1385 MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
1388 GIrNodeInterface *iface;
1390 iface = (GIrNodeInterface *) g_ir_node_new (G_IR_NODE_OBJECT);
1391 ((GIrNode *)iface)->name = g_strdup (name);
1392 iface->gtype_name = g_strdup (typename);
1393 iface->gtype_init = g_strdup (typeinit);
1394 iface->parent = g_strdup (parent);
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_CLASS);
1413 start_type (GMarkupParseContext *context,
1414 const gchar *element_name,
1415 const gchar **attribute_names,
1416 const gchar **attribute_values,
1423 GIrNodeType *typenode;
1425 is_array = strcmp (element_name, "array") == 0;
1427 if (!(is_array || (strcmp (element_name, "type") == 0)))
1430 if (ctx->state == STATE_TYPE)
1433 ctx->type_stack = g_list_prepend (ctx->type_stack, ctx->type_parameters);
1434 ctx->type_parameters = NULL;
1436 else if (ctx->state == STATE_FUNCTION_PARAMETER ||
1437 ctx->state == STATE_FUNCTION_RETURN ||
1438 ctx->state == STATE_STRUCT_FIELD ||
1439 ctx->state == STATE_UNION_FIELD ||
1440 ctx->state == STATE_CLASS_PROPERTY ||
1441 ctx->state == STATE_CLASS_FIELD ||
1442 ctx->state == STATE_INTERFACE_FIELD ||
1443 ctx->state == STATE_INTERFACE_PROPERTY ||
1444 ctx->state == STATE_BOXED_FIELD ||
1445 ctx->state == STATE_NAMESPACE_CONSTANT ||
1446 ctx->state == STATE_CLASS_CONSTANT ||
1447 ctx->state == STATE_INTERFACE_CONSTANT
1450 state_switch (ctx, STATE_TYPE);
1451 ctx->type_depth = 1;
1452 ctx->type_stack = NULL;
1453 ctx->type_parameters = NULL;
1456 if (!ctx->current_typed)
1460 G_MARKUP_ERROR_INVALID_CONTENT,
1461 "The element <type> is invalid here");
1471 typenode = (GIrNodeType *)g_ir_node_new (G_IR_NODE_TYPE);
1473 typenode->tag = GI_TYPE_TAG_ARRAY;
1474 typenode->is_pointer = TRUE;
1475 typenode->is_array = TRUE;
1477 zero = find_attribute ("zero-terminated", attribute_names, attribute_values);
1478 len = find_attribute ("length", attribute_names, attribute_values);
1480 typenode->zero_terminated = !(zero && strcmp (zero, "1") != 0);
1481 typenode->has_length = len != NULL;
1482 typenode->length = typenode->has_length ? atoi (len) : -1;
1486 gboolean is_pointer;
1487 name = find_attribute ("name", attribute_names, attribute_values);
1490 MISSING_ATTRIBUTE (context, error, element_name, "name");
1492 ctype = find_attribute ("c:type", attribute_names, attribute_values);
1493 if (ctype != NULL && strchr (ctype, '*'))
1498 typenode = parse_type (ctx, name);
1501 typenode->is_pointer = is_pointer;
1504 ctx->type_parameters = g_list_append (ctx->type_parameters, typenode);
1510 end_type_top (ParseContext *ctx)
1512 GIrNodeType *typenode = (GIrNodeType*)ctx->type_parameters->data;
1514 /* Default to pointer for unspecified containers */
1515 if (typenode->tag == GI_TYPE_TAG_ARRAY ||
1516 typenode->tag == GI_TYPE_TAG_GLIST ||
1517 typenode->tag == GI_TYPE_TAG_GSLIST)
1519 if (typenode->parameter_type1 == NULL)
1520 typenode->parameter_type1 = parse_type (ctx, "any");
1522 else if (typenode->tag == GI_TYPE_TAG_GHASH)
1524 if (typenode->parameter_type1 == NULL)
1526 typenode->parameter_type1 = parse_type (ctx, "any");
1527 typenode->parameter_type2 = parse_type (ctx, "any");
1531 switch (ctx->current_typed->type)
1533 case G_IR_NODE_PARAM:
1535 GIrNodeParam *param = (GIrNodeParam *)ctx->current_typed;
1536 param->type = typenode;
1539 case G_IR_NODE_FIELD:
1541 GIrNodeField *field = (GIrNodeField *)ctx->current_typed;
1542 field->type = typenode;
1545 case G_IR_NODE_PROPERTY:
1547 GIrNodeProperty *property = (GIrNodeProperty *) ctx->current_typed;
1548 property->type = typenode;
1551 case G_IR_NODE_CONSTANT:
1553 GIrNodeConstant *constant = (GIrNodeConstant *)ctx->current_typed;
1554 constant->type = typenode;
1558 g_printerr("current node is %d\n", ctx->current_node->type);
1559 g_assert_not_reached ();
1561 g_list_free (ctx->type_parameters);
1563 ctx->type_depth = 0;
1564 ctx->type_parameters = NULL;
1565 ctx->current_typed = NULL;
1569 end_type_recurse (ParseContext *ctx)
1572 GIrNodeType *parent;
1574 parent = (GIrNodeType *) ((GList*)ctx->type_stack->data)->data;
1576 if (parent->tag == GI_TYPE_TAG_ARRAY ||
1577 parent->tag == GI_TYPE_TAG_GLIST ||
1578 parent->tag == GI_TYPE_TAG_GSLIST)
1580 if (ctx->type_parameters == NULL)
1581 parent->parameter_type1 = parse_type (ctx, "pointer");
1583 parent->parameter_type1 = (GIrNodeType*)ctx->type_parameters->data;
1585 else if (parent->tag == GI_TYPE_TAG_GHASH)
1587 if (ctx->type_parameters == NULL)
1589 parent->parameter_type1 = parse_type (ctx, "pointer");
1590 parent->parameter_type2 = parse_type (ctx, "pointer");
1594 parent->parameter_type1 = (GIrNodeType*) ctx->type_parameters->data;
1595 parent->parameter_type2 = (GIrNodeType*) ctx->type_parameters->next->data;
1598 g_list_free (ctx->type_parameters);
1599 ctx->type_parameters = (GList *)ctx->type_stack->data;
1600 ctx->type_stack = g_list_delete_link (ctx->type_stack, ctx->type_stack);
1604 end_type (ParseContext *ctx)
1606 if (ctx->type_depth == 1)
1609 state_switch (ctx, ctx->prev_state);
1613 end_type_recurse (ctx);
1619 start_return_value (GMarkupParseContext *context,
1620 const gchar *element_name,
1621 const gchar **attribute_names,
1622 const gchar **attribute_values,
1626 if (strcmp (element_name, "return-value") == 0 &&
1627 ctx->state == STATE_FUNCTION)
1629 GIrNodeParam *param;
1631 param = (GIrNodeParam *)g_ir_node_new (G_IR_NODE_PARAM);
1634 param->retval = TRUE;
1636 ctx->current_typed = (GIrNode*) param;
1638 state_switch (ctx, STATE_FUNCTION_RETURN);
1640 switch (ctx->current_node->type)
1642 case G_IR_NODE_FUNCTION:
1643 case G_IR_NODE_CALLBACK:
1645 GIrNodeFunction *func = (GIrNodeFunction *)ctx->current_node;
1646 func->result = param;
1649 case G_IR_NODE_SIGNAL:
1651 GIrNodeSignal *signal = (GIrNodeSignal *)ctx->current_node;
1652 signal->result = param;
1655 case G_IR_NODE_VFUNC:
1657 GIrNodeVFunc *vfunc = (GIrNodeVFunc *)ctx->current_node;
1658 vfunc->result = param;
1662 g_assert_not_reached ();
1672 start_implements (GMarkupParseContext *context,
1673 const gchar *element_name,
1674 const gchar **attribute_names,
1675 const gchar **attribute_values,
1679 GIrNodeInterface *iface;
1682 if (strcmp (element_name, "implements") != 0 ||
1683 !(ctx->state == STATE_CLASS))
1686 state_switch (ctx, STATE_IMPLEMENTS);
1688 name = find_attribute ("name", attribute_names, attribute_values);
1691 MISSING_ATTRIBUTE (context, error, element_name, "name");
1695 iface = (GIrNodeInterface *)ctx->current_node;
1696 iface->interfaces = g_list_append (iface->interfaces, g_strdup (name));
1702 start_glib_signal (GMarkupParseContext *context,
1703 const gchar *element_name,
1704 const gchar **attribute_names,
1705 const gchar **attribute_values,
1709 if (strcmp (element_name, "glib:signal") == 0 &&
1710 (ctx->state == STATE_CLASS ||
1711 ctx->state == STATE_INTERFACE))
1715 const gchar *no_recurse;
1716 const gchar *detailed;
1717 const gchar *action;
1718 const gchar *no_hooks;
1719 const gchar *has_class_closure;
1721 name = find_attribute ("name", attribute_names, attribute_values);
1722 when = find_attribute ("when", attribute_names, attribute_values);
1723 no_recurse = find_attribute ("no-recurse", attribute_names, attribute_values);
1724 detailed = find_attribute ("detailed", attribute_names, attribute_values);
1725 action = find_attribute ("action", attribute_names, attribute_values);
1726 no_hooks = find_attribute ("no-hooks", attribute_names, attribute_values);
1727 has_class_closure = find_attribute ("has-class-closure", attribute_names, attribute_values);
1730 MISSING_ATTRIBUTE (context, error, element_name, "name");
1733 GIrNodeInterface *iface;
1734 GIrNodeSignal *signal;
1736 signal = (GIrNodeSignal *)g_ir_node_new (G_IR_NODE_SIGNAL);
1738 ((GIrNode *)signal)->name = g_strdup (name);
1740 signal->run_first = FALSE;
1741 signal->run_last = FALSE;
1742 signal->run_cleanup = FALSE;
1743 if (when == NULL || strcmp (when, "LAST") == 0)
1744 signal->run_last = TRUE;
1745 else if (strcmp (when, "FIRST") == 0)
1746 signal->run_first = TRUE;
1748 signal->run_cleanup = TRUE;
1750 if (no_recurse && strcmp (no_recurse, "1") == 0)
1751 signal->no_recurse = TRUE;
1753 signal->no_recurse = FALSE;
1754 if (detailed && strcmp (detailed, "1") == 0)
1755 signal->detailed = TRUE;
1757 signal->detailed = FALSE;
1758 if (action && strcmp (action, "1") == 0)
1759 signal->action = TRUE;
1761 signal->action = FALSE;
1762 if (no_hooks && strcmp (no_hooks, "1") == 0)
1763 signal->no_hooks = TRUE;
1765 signal->no_hooks = FALSE;
1766 if (has_class_closure && strcmp (has_class_closure, "1") == 0)
1767 signal->has_class_closure = TRUE;
1769 signal->has_class_closure = FALSE;
1771 iface = (GIrNodeInterface *)ctx->current_node;
1772 iface->members = g_list_append (iface->members, signal);
1774 ctx->current_node = (GIrNode *)signal;
1775 state_switch (ctx, STATE_FUNCTION);
1784 start_vfunc (GMarkupParseContext *context,
1785 const gchar *element_name,
1786 const gchar **attribute_names,
1787 const gchar **attribute_values,
1791 if (strcmp (element_name, "vfunc") == 0 &&
1792 (ctx->state == STATE_CLASS ||
1793 ctx->state == STATE_INTERFACE))
1796 const gchar *must_chain_up;
1797 const gchar *override;
1798 const gchar *is_class_closure;
1799 const gchar *offset;
1801 name = find_attribute ("name", attribute_names, attribute_values);
1802 must_chain_up = find_attribute ("must-chain-up", attribute_names, attribute_values);
1803 override = find_attribute ("override", attribute_names, attribute_values);
1804 is_class_closure = find_attribute ("is-class-closure", attribute_names, attribute_values);
1805 offset = find_attribute ("offset", attribute_names, attribute_values);
1808 MISSING_ATTRIBUTE (context, error, element_name, "name");
1811 GIrNodeInterface *iface;
1812 GIrNodeVFunc *vfunc;
1814 vfunc = (GIrNodeVFunc *)g_ir_node_new (G_IR_NODE_VFUNC);
1816 ((GIrNode *)vfunc)->name = g_strdup (name);
1818 if (must_chain_up && strcmp (must_chain_up, "1") == 0)
1819 vfunc->must_chain_up = TRUE;
1821 vfunc->must_chain_up = FALSE;
1823 if (override && strcmp (override, "always") == 0)
1825 vfunc->must_be_implemented = TRUE;
1826 vfunc->must_not_be_implemented = FALSE;
1828 else if (override && strcmp (override, "never") == 0)
1830 vfunc->must_be_implemented = FALSE;
1831 vfunc->must_not_be_implemented = TRUE;
1835 vfunc->must_be_implemented = FALSE;
1836 vfunc->must_not_be_implemented = FALSE;
1839 if (is_class_closure && strcmp (is_class_closure, "1") == 0)
1840 vfunc->is_class_closure = TRUE;
1842 vfunc->is_class_closure = FALSE;
1845 vfunc->offset = atoi (offset);
1849 iface = (GIrNodeInterface *)ctx->current_node;
1850 iface->members = g_list_append (iface->members, vfunc);
1852 ctx->current_node = (GIrNode *)vfunc;
1853 state_switch (ctx, STATE_FUNCTION);
1863 start_struct (GMarkupParseContext *context,
1864 const gchar *element_name,
1865 const gchar **attribute_names,
1866 const gchar **attribute_values,
1870 if (strcmp (element_name, "record") == 0 &&
1871 ctx->state == STATE_NAMESPACE)
1874 const gchar *deprecated;
1875 const gchar *gtype_name;
1876 const gchar *gtype_init;
1877 GIrNodeStruct *struct_;
1879 name = find_attribute ("name", attribute_names, attribute_values);
1880 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1881 gtype_name = find_attribute ("glib:type-name", attribute_names, attribute_values);
1882 gtype_init = find_attribute ("glib:get-type", attribute_names, attribute_values);
1886 MISSING_ATTRIBUTE (context, error, element_name, "name");
1889 if ((gtype_name == NULL && gtype_init != NULL))
1891 MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
1894 if ((gtype_name != NULL && gtype_init == NULL))
1896 MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
1900 struct_ = (GIrNodeStruct *) g_ir_node_new (G_IR_NODE_STRUCT);
1902 ((GIrNode *)struct_)->name = g_strdup (name);
1904 struct_->deprecated = TRUE;
1906 struct_->deprecated = FALSE;
1908 struct_->gtype_name = g_strdup (gtype_name);
1909 struct_->gtype_init = g_strdup (gtype_init);
1911 ctx->current_node = (GIrNode *)struct_;
1912 ctx->current_module->entries =
1913 g_list_append (ctx->current_module->entries, struct_);
1915 state_switch (ctx, STATE_STRUCT);
1923 start_union (GMarkupParseContext *context,
1924 const gchar *element_name,
1925 const gchar **attribute_names,
1926 const gchar **attribute_values,
1930 if (strcmp (element_name, "union") == 0 &&
1931 ctx->state == STATE_NAMESPACE)
1934 const gchar *deprecated;
1935 const gchar *typename;
1936 const gchar *typeinit;
1938 name = find_attribute ("name", attribute_names, attribute_values);
1939 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1940 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
1941 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
1944 MISSING_ATTRIBUTE (context, error, element_name, "name");
1947 GIrNodeUnion *union_;
1949 union_ = (GIrNodeUnion *) g_ir_node_new (G_IR_NODE_UNION);
1951 ((GIrNode *)union_)->name = g_strdup (name);
1952 union_->gtype_name = g_strdup (typename);
1953 union_->gtype_init = g_strdup (typeinit);
1955 union_->deprecated = TRUE;
1957 union_->deprecated = FALSE;
1959 ctx->current_node = (GIrNode *)union_;
1960 ctx->current_module->entries =
1961 g_list_append (ctx->current_module->entries, union_);
1963 state_switch (ctx, STATE_UNION);
1971 start_discriminator (GMarkupParseContext *context,
1972 const gchar *element_name,
1973 const gchar **attribute_names,
1974 const gchar **attribute_values,
1978 if (strcmp (element_name, "discriminator") == 0 &&
1979 ctx->state == STATE_UNION)
1982 const gchar *offset;
1984 type = find_attribute ("type", attribute_names, attribute_values);
1985 offset = find_attribute ("offset", attribute_names, attribute_values);
1987 MISSING_ATTRIBUTE (context, error, element_name, "type");
1988 else if (offset == NULL)
1989 MISSING_ATTRIBUTE (context, error, element_name, "offset");
1991 ((GIrNodeUnion *)ctx->current_node)->discriminator_type
1992 = parse_type (ctx, type);
1993 ((GIrNodeUnion *)ctx->current_node)->discriminator_offset
2004 parse_include (GMarkupParseContext *context,
2009 ParseContext sub_ctx = { 0 };
2010 GMarkupParseContext *sub_context;
2015 girpath = locate_gir (name, ctx->includes);
2017 if (girpath == NULL)
2021 G_MARKUP_ERROR_INVALID_CONTENT,
2022 "Could not find GIR file '%s'; check XDG_DATA_DIRS or use --includedir",
2027 g_debug ("Parsing include %s", girpath);
2029 if (!g_file_get_contents (girpath, &buffer, &length, error))
2036 sub_ctx.state = STATE_START;
2037 sub_ctx.includes = ctx->includes;
2038 sub_ctx.prefix_aliases = TRUE;
2039 sub_ctx.namespace = name;
2040 sub_ctx.aliases = ctx->aliases;
2041 sub_ctx.type_depth = 0;
2043 context = g_markup_parse_context_new (&firstpass_parser, 0, &sub_ctx, NULL);
2045 if (!g_markup_parse_context_parse (context, buffer, length, error))
2051 if (!g_markup_parse_context_end_parse (context, error))
2057 g_markup_parse_context_free (context);
2061 extern GLogLevelFlags logged_levels;
2064 start_element_handler (GMarkupParseContext *context,
2065 const gchar *element_name,
2066 const gchar **attribute_names,
2067 const gchar **attribute_values,
2071 ParseContext *ctx = user_data;
2072 gint line_number, char_number;
2074 if (logged_levels & G_LOG_LEVEL_DEBUG)
2076 GString *tags = g_string_new ("");
2078 for (i = 0; attribute_names[i]; i++)
2079 g_string_append_printf (tags, "%s=\"%s\" ",
2081 attribute_values[i]);
2085 g_string_insert_c (tags, 0, ' ');
2086 g_string_truncate (tags, tags->len - 1);
2088 g_debug ("<%s%s>", element_name, tags->str);
2089 g_string_free (tags, TRUE);
2092 switch (element_name[0])
2095 if (ctx->state == STATE_NAMESPACE && strcmp (element_name, "alias") == 0)
2097 state_switch (ctx, STATE_ALIAS);
2100 if (start_type (context, element_name,
2101 attribute_names, attribute_values,
2106 if (start_enum (context, element_name,
2107 attribute_names, attribute_values,
2112 if (start_function (context, element_name,
2113 attribute_names, attribute_values,
2116 else if (start_constant (context, element_name,
2117 attribute_names, attribute_values,
2120 else if (start_class (context, element_name,
2121 attribute_names, attribute_values,
2124 else if (strcmp (element_name, "class") == 0 &&
2125 ctx->state == STATE_REQUIRES)
2129 name = find_attribute ("name", attribute_names, attribute_values);
2132 MISSING_ATTRIBUTE (context, error, element_name, "name");
2135 GIrNodeInterface *iface;
2137 iface = (GIrNodeInterface *)ctx->current_node;
2138 iface ->prerequisites = g_list_append (iface->prerequisites, g_strdup (name));
2146 if (start_discriminator (context, element_name,
2147 attribute_names, attribute_values,
2153 if (start_enum (context, element_name,
2154 attribute_names, attribute_values,
2157 else if (start_errordomain (context, element_name,
2158 attribute_names, attribute_values,
2164 if (start_function (context, element_name,
2165 attribute_names, attribute_values,
2168 else if (start_field (context, element_name,
2169 attribute_names, attribute_values,
2175 if (start_glib_boxed (context, element_name,
2176 attribute_names, attribute_values,
2179 else if (start_glib_signal (context, element_name,
2180 attribute_names, attribute_values,
2186 if (strcmp (element_name, "include") == 0 &&
2187 ctx->state == STATE_REPOSITORY)
2191 name = find_attribute ("name", attribute_names, attribute_values);
2195 MISSING_ATTRIBUTE (context, error, element_name, "name");
2199 if (!parse_include (context, ctx, name, error))
2202 ctx->dependencies = g_list_prepend (ctx->dependencies, g_strdup (name));
2205 state_switch (ctx, STATE_INCLUDE);
2208 if (start_interface (context, element_name,
2209 attribute_names, attribute_values,
2212 else if (start_implements (context, element_name,
2213 attribute_names, attribute_values,
2219 if (start_function (context, element_name,
2220 attribute_names, attribute_values,
2223 else if (start_member (context, element_name,
2224 attribute_names, attribute_values,
2230 if (strcmp (element_name, "namespace") == 0 && ctx->state == STATE_REPOSITORY)
2232 const gchar *name, *shared_library;
2234 name = find_attribute ("name", attribute_names, attribute_values);
2235 shared_library = find_attribute ("shared-library", attribute_names, attribute_values);
2238 MISSING_ATTRIBUTE (context, error, element_name, "name");
2241 ctx->current_module = g_ir_module_new (name, shared_library);
2242 ctx->modules = g_list_append (ctx->modules, ctx->current_module);
2243 ctx->current_module->dependencies = ctx->dependencies;
2245 state_switch (ctx, STATE_NAMESPACE);
2252 if (start_property (context, element_name,
2253 attribute_names, attribute_values,
2256 else if (strcmp (element_name, "parameters") == 0 &&
2257 ctx->state == STATE_FUNCTION)
2259 state_switch (ctx, STATE_FUNCTION_PARAMETERS);
2263 else if (start_parameter (context, element_name,
2264 attribute_names, attribute_values,
2271 if (strcmp (element_name, "repository") == 0 && ctx->state == STATE_START)
2273 const gchar *version;
2275 version = find_attribute ("version", attribute_names, attribute_values);
2277 if (version == NULL)
2278 MISSING_ATTRIBUTE (context, error, element_name, "version");
2279 else if (strcmp (version, "1.0") != 0)
2282 G_MARKUP_ERROR_INVALID_CONTENT,
2283 "Unsupported version '%s'",
2286 state_switch (ctx, STATE_REPOSITORY);
2290 else if (start_return_value (context, element_name,
2291 attribute_names, attribute_values,
2294 else if (strcmp (element_name, "requires") == 0 &&
2295 ctx->state == STATE_INTERFACE)
2297 state_switch (ctx, STATE_REQUIRES);
2301 else if (start_struct (context, element_name,
2302 attribute_names, attribute_values,
2308 if (start_union (context, element_name,
2309 attribute_names, attribute_values,
2315 if (start_type (context, element_name,
2316 attribute_names, attribute_values,
2322 if (start_vfunc (context, element_name,
2323 attribute_names, attribute_values,
2329 g_markup_parse_context_get_position (context, &line_number, &char_number);
2331 if (error && *error == NULL)
2334 G_MARKUP_ERROR_UNKNOWN_ELEMENT,
2335 "Unexpected start tag '%s' on line %d char %d; current state=%d",
2337 line_number, char_number, ctx->state);
2342 g_markup_parse_context_get_position (context, &line_number, &char_number);
2344 fprintf (stderr, "Error at line %d, character %d: %s\n", line_number, char_number, (*error)->message);
2345 backtrace_stderr ();
2350 require_one_of_end_elements (GMarkupParseContext *context,
2352 const char *actual_name,
2357 int line_number, char_number;
2358 const char *expected;
2359 gboolean matched = FALSE;
2361 va_start (args, error);
2363 while ((expected = va_arg (args, const char*)) != NULL)
2365 if (strcmp (expected, actual_name) == 0)
2377 g_markup_parse_context_get_position (context, &line_number, &char_number);
2380 G_MARKUP_ERROR_INVALID_CONTENT,
2381 "Unexpected end tag '%s' on line %d char %d; current state=%d",
2383 line_number, char_number, ctx->state);
2389 require_end_element (GMarkupParseContext *context,
2391 const char *expected_name,
2392 const char *actual_name,
2395 return require_one_of_end_elements (context, ctx, actual_name, error, expected_name, NULL);
2399 end_element_handler (GMarkupParseContext *context,
2400 const gchar *element_name,
2404 ParseContext *ctx = user_data;
2406 g_debug ("</%s>", element_name);
2412 /* no need to GError here, GMarkup already catches this */
2415 case STATE_REPOSITORY:
2416 state_switch (ctx, STATE_END);
2420 if (require_end_element (context, ctx, "include", element_name, error))
2422 state_switch (ctx, STATE_REPOSITORY);
2426 case STATE_NAMESPACE:
2427 if (require_end_element (context, ctx, "namespace", element_name, error))
2429 ctx->current_module = NULL;
2430 state_switch (ctx, STATE_REPOSITORY);
2435 if (require_end_element (context, ctx, "alias", element_name, error))
2437 state_switch (ctx, STATE_NAMESPACE);
2441 case STATE_FUNCTION_RETURN:
2442 if (strcmp ("type", element_name) == 0)
2444 if (require_end_element (context, ctx, "return-value", element_name, error))
2446 state_switch (ctx, STATE_FUNCTION);
2450 case STATE_FUNCTION_PARAMETERS:
2451 if (require_end_element (context, ctx, "parameters", element_name, error))
2453 state_switch (ctx, STATE_FUNCTION);
2457 case STATE_FUNCTION_PARAMETER:
2458 if (strcmp ("type", element_name) == 0)
2460 if (require_end_element (context, ctx, "parameter", element_name, error))
2462 state_switch (ctx, STATE_FUNCTION_PARAMETERS);
2466 case STATE_FUNCTION:
2467 if (ctx->current_node == g_list_last (ctx->current_module->entries)->data)
2469 ctx->current_node = NULL;
2470 state_switch (ctx, STATE_NAMESPACE);
2474 ctx->current_node = g_list_last (ctx->current_module->entries)->data;
2475 if (ctx->current_node->type == G_IR_NODE_INTERFACE)
2476 state_switch (ctx, STATE_INTERFACE);
2477 else if (ctx->current_node->type == G_IR_NODE_OBJECT)
2478 state_switch (ctx, STATE_CLASS);
2479 else if (ctx->current_node->type == G_IR_NODE_BOXED)
2480 state_switch (ctx, STATE_BOXED);
2481 else if (ctx->current_node->type == G_IR_NODE_STRUCT)
2482 state_switch (ctx, STATE_STRUCT);
2483 else if (ctx->current_node->type == G_IR_NODE_UNION)
2484 state_switch (ctx, STATE_UNION);
2487 int line_number, char_number;
2488 g_markup_parse_context_get_position (context, &line_number, &char_number);
2491 G_MARKUP_ERROR_INVALID_CONTENT,
2492 "Unexpected end tag '%s' on line %d char %d",
2494 line_number, char_number);
2499 case STATE_CLASS_FIELD:
2500 if (strcmp ("type", element_name) == 0)
2502 if (require_end_element (context, ctx, "field", element_name, error))
2504 state_switch (ctx, STATE_CLASS);
2508 case STATE_CLASS_PROPERTY:
2509 if (strcmp ("type", element_name) == 0)
2511 if (require_end_element (context, ctx, "property", element_name, error))
2513 state_switch (ctx, STATE_CLASS);
2518 if (require_end_element (context, ctx, "class", element_name, error))
2520 ctx->current_node = NULL;
2521 state_switch (ctx, STATE_NAMESPACE);
2525 case STATE_ERRORDOMAIN:
2526 if (require_end_element (context, ctx, "errordomain", element_name, error))
2528 ctx->current_node = NULL;
2529 state_switch (ctx, STATE_NAMESPACE);
2533 case STATE_INTERFACE_PROPERTY:
2534 if (strcmp ("type", element_name) == 0)
2536 if (require_end_element (context, ctx, "property", element_name, error))
2538 state_switch (ctx, STATE_INTERFACE);
2542 case STATE_INTERFACE_FIELD:
2543 if (strcmp ("type", element_name) == 0)
2545 if (require_end_element (context, ctx, "field", element_name, error))
2547 state_switch (ctx, STATE_INTERFACE);
2551 case STATE_INTERFACE:
2552 if (require_end_element (context, ctx, "interface", element_name, error))
2554 ctx->current_node = NULL;
2555 state_switch (ctx, STATE_NAMESPACE);
2560 if (strcmp ("member", element_name) == 0)
2562 else if (require_one_of_end_elements (context, ctx,
2563 element_name, error, "enumeration",
2566 ctx->current_node = NULL;
2567 state_switch (ctx, STATE_NAMESPACE);
2572 if (require_end_element (context, ctx, "glib:boxed", element_name, error))
2574 ctx->current_node = NULL;
2575 state_switch (ctx, STATE_NAMESPACE);
2579 case STATE_BOXED_FIELD:
2580 if (strcmp ("type", element_name) == 0)
2582 if (require_end_element (context, ctx, "field", element_name, error))
2584 state_switch (ctx, STATE_BOXED);
2588 case STATE_STRUCT_FIELD:
2589 if (strcmp ("type", element_name) == 0)
2591 if (require_end_element (context, ctx, "field", element_name, error))
2593 state_switch (ctx, STATE_STRUCT);
2598 if (require_end_element (context, ctx, "record", element_name, error))
2600 ctx->current_node = NULL;
2601 state_switch (ctx, STATE_NAMESPACE);
2605 case STATE_UNION_FIELD:
2606 if (strcmp ("type", element_name) == 0)
2608 if (require_end_element (context, ctx, "field", element_name, error))
2610 state_switch (ctx, STATE_UNION);
2615 if (require_end_element (context, ctx, "union", element_name, error))
2617 ctx->current_node = NULL;
2618 state_switch (ctx, STATE_NAMESPACE);
2621 case STATE_IMPLEMENTS:
2622 if (strcmp ("interface", element_name) == 0)
2624 if (require_end_element (context, ctx, "implements", element_name, error))
2625 state_switch (ctx, STATE_CLASS);
2627 case STATE_REQUIRES:
2628 if (require_end_element (context, ctx, "requires", element_name, error))
2629 state_switch (ctx, STATE_INTERFACE);
2631 case STATE_NAMESPACE_CONSTANT:
2632 case STATE_CLASS_CONSTANT:
2633 case STATE_INTERFACE_CONSTANT:
2634 if (strcmp ("type", element_name) == 0)
2636 if (require_end_element (context, ctx, "constant", element_name, error))
2638 ctx->current_node = NULL;
2641 case STATE_NAMESPACE_CONSTANT:
2642 state_switch (ctx, STATE_NAMESPACE);
2644 case STATE_CLASS_CONSTANT:
2645 state_switch (ctx, STATE_CLASS);
2647 case STATE_INTERFACE_CONSTANT:
2648 state_switch (ctx, STATE_INTERFACE);
2651 g_assert_not_reached ();
2657 if ((strcmp ("type", element_name) == 0) || (strcmp ("array", element_name) == 0))
2663 g_error ("Unhandled state %d in end_element_handler\n", ctx->state);
2668 text_handler (GMarkupParseContext *context,
2674 /* FIXME warn about non-whitespace text */
2678 cleanup (GMarkupParseContext *context,
2682 ParseContext *ctx = user_data;
2684 int line_number, char_number;
2686 for (m = ctx->modules; m; m = m->next)
2687 g_ir_module_free (m->data);
2688 g_list_free (ctx->modules);
2689 ctx->modules = NULL;
2691 ctx->current_module = NULL;
2694 static GMarkupParser parser =
2696 start_element_handler,
2697 end_element_handler,
2704 g_ir_parse_string (const gchar *namespace,
2705 const gchar *const *includes,
2706 const gchar *buffer,
2710 ParseContext ctx = { 0 };
2711 GMarkupParseContext *context;
2713 ctx.state = STATE_START;
2714 ctx.includes = includes;
2715 ctx.prefix_aliases = FALSE;
2716 ctx.namespace = namespace;
2717 ctx.aliases = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
2719 ctx.dependencies = NULL;
2720 ctx.current_module = NULL;
2722 context = g_markup_parse_context_new (&firstpass_parser, 0, &ctx, NULL);
2724 if (!g_markup_parse_context_parse (context, buffer, length, error))
2727 if (!g_markup_parse_context_end_parse (context, error))
2730 g_markup_parse_context_free (context);
2732 context = g_markup_parse_context_new (&parser, 0, &ctx, NULL);
2733 if (!g_markup_parse_context_parse (context, buffer, length, error))
2736 if (!g_markup_parse_context_end_parse (context, error))
2741 g_hash_table_destroy (ctx.aliases);
2743 g_markup_parse_context_free (context);
2749 g_ir_parse_file (const gchar *filename,
2750 const gchar *const *includes,
2759 if (!g_str_has_suffix (filename, ".gir"))
2763 G_MARKUP_ERROR_INVALID_CONTENT,
2764 "Expected filename to end with '.gir'");
2768 g_debug ("[parsing] filename %s", filename);
2770 slash = g_strrstr (filename, "/");
2772 namespace = g_strdup (filename);
2774 namespace = g_strdup (slash+1);
2775 namespace[strlen(namespace)-4] = '\0';
2777 if (!g_file_get_contents (filename, &buffer, &length, error))
2780 modules = g_ir_parse_string (namespace, includes, buffer, length, error);