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;
84 GList *type_parameters;
89 start_alias (GMarkupParseContext *context,
90 const gchar *element_name,
91 const gchar **attribute_names,
92 const gchar **attribute_values,
97 firstpass_start_element_handler (GMarkupParseContext *context,
98 const gchar *element_name,
99 const gchar **attribute_names,
100 const gchar **attribute_values,
104 ParseContext *ctx = user_data;
106 if (strcmp (element_name, "alias") == 0)
108 start_alias (context, element_name, attribute_names, attribute_values,
114 firstpass_end_element_handler (GMarkupParseContext *context,
115 const gchar *element_name,
119 ParseContext *ctx = user_data;
123 static GMarkupParser firstpass_parser =
125 firstpass_start_element_handler,
126 firstpass_end_element_handler,
133 locate_gir (const char *name, const char * const* extra_paths)
135 const gchar *const *datadirs;
136 const gchar *const *dir;
140 gboolean firstpass = TRUE;
142 datadirs = g_get_system_data_dirs ();
144 girname = g_strdup_printf ("%s.gir", name);
146 for (dir = datadirs; *dir; dir++)
148 path = g_build_filename (*dir, "gir", girname, NULL);
149 if (g_file_test (path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))
154 if (extra_paths != NULL)
156 for (dir = extra_paths; *dir; dir++)
158 path = g_build_filename (*dir, girname, NULL);
159 if (g_file_test (path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))
169 #define MISSING_ATTRIBUTE(ctx,error,element,attribute) \
171 int line_number, char_number; \
172 g_markup_parse_context_get_position (context, &line_number, &char_number); \
173 g_set_error (error, \
175 G_MARKUP_ERROR_INVALID_CONTENT, \
176 "Line %d, character %d: The attribute '%s' on the element '%s' must be specified", \
177 line_number, char_number, attribute, element); \
181 backtrace_stderr (void)
189 size = backtrace (array, 50);
190 strings = (char**) backtrace_symbols (array, size);
192 fprintf (stderr, "--- BACKTRACE (%zd frames) ---\n", size);
194 for (i = 0; i < size; i++)
195 fprintf (stderr, "%s\n", strings[i]);
197 fprintf (stderr, "--- END BACKTRACE ---\n", size);
205 find_attribute (const gchar *name,
206 const gchar **attribute_names,
207 const gchar **attribute_values)
211 for (i = 0; attribute_names[i] != NULL; i++)
212 if (strcmp (attribute_names[i], name) == 0)
213 return attribute_values[i];
219 state_switch (ParseContext *ctx, ParseState newstate)
221 g_debug ("State: %d", newstate);
222 ctx->prev_state = ctx->state;
223 ctx->state = newstate;
226 static GIrNodeType * parse_type_internal (const gchar *str, gchar **next, gboolean in_glib,
227 gboolean in_gobject);
235 static BasicTypeInfo basic_types[] = {
236 { "none", GI_TYPE_TAG_VOID, 0 },
237 { "any", GI_TYPE_TAG_VOID, 1 },
239 { "bool", GI_TYPE_TAG_BOOLEAN, 0 },
240 { "char", GI_TYPE_TAG_INT8, 0 },
241 { "int8", GI_TYPE_TAG_INT8, 0 },
242 { "uint8", GI_TYPE_TAG_UINT8, 0 },
243 { "int16", GI_TYPE_TAG_INT16, 0 },
244 { "uint16", GI_TYPE_TAG_UINT16, 0 },
245 { "int32", GI_TYPE_TAG_INT32, 0 },
246 { "uint32", GI_TYPE_TAG_UINT32, 0 },
247 { "int64", GI_TYPE_TAG_INT64, 0 },
248 { "uint64", GI_TYPE_TAG_UINT64, 0 },
249 { "int", GI_TYPE_TAG_INT, 0 },
250 { "uint", GI_TYPE_TAG_UINT, 0 },
251 { "long", GI_TYPE_TAG_LONG, 0 },
252 { "ulong", GI_TYPE_TAG_ULONG, 0 },
253 { "ssize_t", GI_TYPE_TAG_SSIZE, 0 },
254 { "ssize", GI_TYPE_TAG_SSIZE, 0 },
255 { "size_t", GI_TYPE_TAG_SIZE, 0 },
256 { "size", GI_TYPE_TAG_SIZE, 0 },
257 { "float", GI_TYPE_TAG_FLOAT, 0 },
258 { "double", GI_TYPE_TAG_DOUBLE, 0 },
259 { "time_t", GI_TYPE_TAG_TIME_T, 0 },
260 { "GType", GI_TYPE_TAG_GTYPE, 0 },
261 { "utf8", GI_TYPE_TAG_UTF8, 1 },
262 { "filename", GI_TYPE_TAG_FILENAME,1 },
265 static const BasicTypeInfo *
266 parse_basic (const char *str)
269 gint n_basic = G_N_ELEMENTS (basic_types);
270 gchar *temporary_type = NULL;
274 for (i = 0; i < n_basic; i++)
276 if (g_str_has_prefix (str, basic_types[i].str))
277 return &(basic_types[i]);
283 parse_type_internal (const gchar *str, char **next, gboolean in_glib,
286 const BasicTypeInfo *basic;
288 char *temporary_type = NULL;
290 type = (GIrNodeType *)g_ir_node_new (G_IR_NODE_TYPE);
292 type->unparsed = g_strdup (str);
294 /* See comment below on GLib.List handling */
295 if (in_gobject && strcmp (str, "Type") == 0)
297 temporary_type = g_strdup ("GLib.Type");
298 str = temporary_type;
301 basic = parse_basic (str);
304 type->is_basic = TRUE;
305 type->tag = basic->tag;
306 type->is_pointer = basic->pointer;
308 str += strlen(basic->str);
312 /* If we're inside GLib, handle "List" etc. by prefixing with
313 * "GLib." so the parsing code below doesn't have to get more
316 if (g_str_has_prefix (str, "List<") ||
317 strcmp (str, "List") == 0)
319 temporary_type = g_strdup_printf ("GLib.List%s", str + 4);
320 str = temporary_type;
322 else if (g_str_has_prefix (str, "SList<") ||
323 strcmp (str, "SList") == 0)
325 temporary_type = g_strdup_printf ("GLib.SList%s", str + 5);
326 str = temporary_type;
328 else if (g_str_has_prefix (str, "HashTable<") ||
329 strcmp (str, "HashTable") == 0)
331 temporary_type = g_strdup_printf ("GLib.HashTable%s", str + 9);
332 str = temporary_type;
334 else if (g_str_has_prefix (str, "Error<") ||
335 strcmp (str, "Error") == 0)
337 temporary_type = g_strdup_printf ("GLib.Error%s", str + 5);
338 str = temporary_type;
343 /* found a basic type */;
344 else if (g_str_has_prefix (str, "GLib.List") ||
345 g_str_has_prefix (str, "GLib.SList"))
347 str += strlen ("GLib.");
348 if (g_str_has_prefix (str, "List"))
350 type->tag = GI_TYPE_TAG_GLIST;
351 type->is_glist = TRUE;
352 type->is_pointer = TRUE;
353 str += strlen ("List");
357 type->tag = GI_TYPE_TAG_GSLIST;
358 type->is_gslist = TRUE;
359 type->is_pointer = TRUE;
360 str += strlen ("SList");
363 else if (g_str_has_prefix (str, "GLib.HashTable"))
365 str += strlen ("GLib.");
367 type->tag = GI_TYPE_TAG_GHASH;
368 type->is_ghashtable = TRUE;
369 type->is_pointer = TRUE;
370 str += strlen ("HashTable");
372 else if (g_str_has_prefix (str, "GLib.Error"))
374 str += strlen ("GLib.");
376 type->tag = GI_TYPE_TAG_ERROR;
377 type->is_error = TRUE;
378 type->is_pointer = TRUE;
379 str += strlen ("Error");
386 end = strchr (str, '>');
387 tmp = g_strndup (str, end - str);
388 type->errors = g_strsplit (tmp, ",", 0);
396 type->tag = GI_TYPE_TAG_INTERFACE;
397 type->is_interface = TRUE;
398 const char *start = str;
400 /* must be an interface type */
401 while (g_ascii_isalnum (*str) ||
408 type->interface = g_strndup (start, str - start);
413 g_assert (type->tag >= 0 && type->tag <= GI_TYPE_TAG_ERROR);
414 g_free (temporary_type);
418 g_ir_node_free ((GIrNode *)type);
419 g_free (temporary_type);
424 resolve_aliases (ParseContext *ctx, const gchar *type)
428 GSList *seen_values = NULL;
430 seen_values = g_slist_prepend (seen_values, (char*)type);
431 while (g_hash_table_lookup_extended (ctx->aliases, type, &orig, &value))
433 g_debug ("Resolved: %s => %s", type, value);
435 if (g_slist_find_custom (seen_values, type,
436 (GCompareFunc)strcmp) != NULL)
438 seen_values = g_slist_prepend (seen_values, (gchar*)type);
440 g_slist_free (seen_values);
445 parse_type (ParseContext *ctx, const gchar *type)
449 const BasicTypeInfo *basic;
450 gboolean in_glib, in_gobject;
451 gboolean matched_special = FALSE;
453 in_glib = strcmp (ctx->namespace, "GLib") == 0;
454 in_gobject = strcmp (ctx->namespace, "GObject") == 0;
456 /* Do not search aliases for basic types */
457 basic = parse_basic (type);
459 type = resolve_aliases (ctx, type);
461 node = parse_type_internal (type, NULL, in_glib, in_gobject);
463 g_debug ("Parsed type: %s => %d", type, node->tag);
465 g_critical ("Failed to parse type: '%s'", type);
471 start_glib_boxed (GMarkupParseContext *context,
472 const gchar *element_name,
473 const gchar **attribute_names,
474 const gchar **attribute_values,
479 const gchar *typename;
480 const gchar *typeinit;
481 const gchar *deprecated;
484 if (!(strcmp (element_name, "glib:boxed") == 0 &&
485 ctx->state == STATE_NAMESPACE))
488 name = find_attribute ("glib:name", attribute_names, attribute_values);
489 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
490 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
491 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
495 MISSING_ATTRIBUTE (context, error, element_name, "glib:name");
498 else if (typename == NULL)
500 MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
503 else if (typeinit == NULL)
505 MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
509 boxed = (GIrNodeBoxed *) g_ir_node_new (G_IR_NODE_BOXED);
511 ((GIrNode *)boxed)->name = g_strdup (name);
512 boxed->gtype_name = g_strdup (typename);
513 boxed->gtype_init = g_strdup (typeinit);
515 boxed->deprecated = TRUE;
517 boxed->deprecated = FALSE;
519 ctx->current_node = (GIrNode *)boxed;
520 ctx->current_module->entries =
521 g_list_append (ctx->current_module->entries, boxed);
523 state_switch (ctx, STATE_BOXED);
529 start_function (GMarkupParseContext *context,
530 const gchar *element_name,
531 const gchar **attribute_names,
532 const gchar **attribute_values,
538 const gchar *deprecated;
539 GIrNodeFunction *function;
540 gboolean found = FALSE;
544 case STATE_NAMESPACE:
545 found = (strcmp (element_name, "function") == 0 ||
546 strcmp (element_name, "callback") == 0);
552 found = strcmp (element_name, "constructor") == 0;
554 case STATE_INTERFACE:
556 strcmp (element_name, "method") == 0 ||
557 strcmp (element_name, "callback") == 0);
566 name = find_attribute ("name", attribute_names, attribute_values);
567 symbol = find_attribute ("c:identifier", attribute_names, attribute_values);
568 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
572 MISSING_ATTRIBUTE (context, error, element_name, "name");
575 else if (strcmp (element_name, "callback") != 0 && symbol == NULL)
577 MISSING_ATTRIBUTE (context, error, element_name, "c:identifier");
581 function = (GIrNodeFunction *) g_ir_node_new (G_IR_NODE_FUNCTION);
583 ((GIrNode *)function)->name = g_strdup (name);
584 function->symbol = g_strdup (symbol);
585 function->parameters = NULL;
587 function->deprecated = TRUE;
589 function->deprecated = FALSE;
591 if (strcmp (element_name, "method") == 0 ||
592 strcmp (element_name, "constructor") == 0)
594 function->is_method = TRUE;
596 if (strcmp (element_name, "constructor") == 0)
597 function->is_constructor = TRUE;
599 function->is_constructor = FALSE;
603 function->is_method = FALSE;
604 function->is_setter = FALSE;
605 function->is_getter = FALSE;
606 function->is_constructor = FALSE;
607 if (strcmp (element_name, "callback") == 0)
608 ((GIrNode *)function)->type = G_IR_NODE_CALLBACK;
611 if (ctx->current_node == NULL)
613 ctx->current_module->entries =
614 g_list_append (ctx->current_module->entries, function);
617 switch (ctx->current_node->type)
619 case G_IR_NODE_INTERFACE:
620 case G_IR_NODE_OBJECT:
622 GIrNodeInterface *iface;
624 iface = (GIrNodeInterface *)ctx->current_node;
625 iface->members = g_list_append (iface->members, function);
628 case G_IR_NODE_BOXED:
632 boxed = (GIrNodeBoxed *)ctx->current_node;
633 boxed->members = g_list_append (boxed->members, function);
636 case G_IR_NODE_STRUCT:
638 GIrNodeStruct *struct_;
640 struct_ = (GIrNodeStruct *)ctx->current_node;
641 struct_->members = g_list_append (struct_->members, function); }
643 case G_IR_NODE_UNION:
645 GIrNodeUnion *union_;
647 union_ = (GIrNodeUnion *)ctx->current_node;
648 union_->members = g_list_append (union_->members, function);
652 g_assert_not_reached ();
655 ctx->current_node = (GIrNode *)function;
656 state_switch (ctx, STATE_FUNCTION);
662 parse_param_transfer (GIrNodeParam *param, const gchar *transfer)
664 if (transfer && strcmp (transfer, "none") == 0)
666 param->transfer = FALSE;
667 param->shallow_transfer = FALSE;
669 else if (transfer && strcmp (transfer, "container") == 0)
671 param->transfer = FALSE;
672 param->shallow_transfer = TRUE;
678 if (strcmp (transfer, "full") != 0)
679 g_warning ("Unknown transfer %s", transfer);
681 param->transfer = TRUE;
683 else if (param->in && !param->out)
684 param->transfer = FALSE;
686 param->transfer = TRUE;
687 param->shallow_transfer = FALSE;
692 start_parameter (GMarkupParseContext *context,
693 const gchar *element_name,
694 const gchar **attribute_names,
695 const gchar **attribute_values,
700 const gchar *direction;
703 const gchar *optional;
705 const gchar *transfer;
708 if (!(strcmp (element_name, "parameter") == 0 &&
709 ctx->state == STATE_FUNCTION_PARAMETERS))
712 name = find_attribute ("name", attribute_names, attribute_values);
713 direction = find_attribute ("direction", attribute_names, attribute_values);
714 retval = find_attribute ("retval", attribute_names, attribute_values);
715 dipper = find_attribute ("dipper", attribute_names, attribute_values);
716 optional = find_attribute ("optional", attribute_names, attribute_values);
717 nullok = find_attribute ("null-ok", attribute_names, attribute_values);
718 transfer = find_attribute ("transfer", attribute_names, attribute_values);
723 param = (GIrNodeParam *)g_ir_node_new (G_IR_NODE_PARAM);
725 ctx->current_typed = (GIrNode*) param;
726 ctx->current_typed->name = g_strdup (name);
728 state_switch (ctx, STATE_FUNCTION_PARAMETER);
730 if (direction && strcmp (direction, "out") == 0)
735 else if (direction && strcmp (direction, "inout") == 0)
746 if (retval && strcmp (retval, "1") == 0)
747 param->retval = TRUE;
749 param->retval = FALSE;
751 if (dipper && strcmp (dipper, "1") == 0)
752 param->dipper = TRUE;
754 param->dipper = FALSE;
756 if (optional && strcmp (optional, "1") == 0)
757 param->optional = TRUE;
759 param->optional = FALSE;
761 if (nullok && strcmp (nullok, "1") == 0)
762 param->null_ok = TRUE;
764 param->null_ok = FALSE;
766 parse_param_transfer (param, transfer);
768 ((GIrNode *)param)->name = g_strdup (name);
770 switch (ctx->current_node->type)
772 case G_IR_NODE_FUNCTION:
773 case G_IR_NODE_CALLBACK:
775 GIrNodeFunction *func;
777 func = (GIrNodeFunction *)ctx->current_node;
778 func->parameters = g_list_append (func->parameters, param);
781 case G_IR_NODE_SIGNAL:
783 GIrNodeSignal *signal;
785 signal = (GIrNodeSignal *)ctx->current_node;
786 signal->parameters = g_list_append (signal->parameters, param);
789 case G_IR_NODE_VFUNC:
793 vfunc = (GIrNodeVFunc *)ctx->current_node;
794 vfunc->parameters = g_list_append (vfunc->parameters, param);
798 g_assert_not_reached ();
805 start_field (GMarkupParseContext *context,
806 const gchar *element_name,
807 const gchar **attribute_names,
808 const gchar **attribute_values,
813 const gchar *readable;
814 const gchar *writable;
826 case STATE_INTERFACE:
832 if (strcmp (element_name, "field") != 0)
835 name = find_attribute ("name", attribute_names, attribute_values);
836 readable = find_attribute ("readable", attribute_names, attribute_values);
837 writable = find_attribute ("writable", attribute_names, attribute_values);
838 bits = find_attribute ("bits", attribute_names, attribute_values);
839 branch = find_attribute ("branch", attribute_names, attribute_values);
840 offset = find_attribute ("offset", attribute_names, attribute_values);
844 MISSING_ATTRIBUTE (context, error, element_name, "name");
848 field = (GIrNodeField *)g_ir_node_new (G_IR_NODE_FIELD);
849 ctx->current_typed = (GIrNode*) field;
850 ((GIrNode *)field)->name = g_strdup (name);
851 if (readable && strcmp (readable, "1") == 0)
852 field->readable = TRUE;
854 field->readable = FALSE;
856 if (writable && strcmp (writable, "1") == 0)
857 field->writable = TRUE;
859 field->writable = FALSE;
862 field->bits = atoi (bits);
867 field->offset = atoi (offset);
871 switch (ctx->current_node->type)
873 case G_IR_NODE_OBJECT:
875 GIrNodeInterface *iface;
877 iface = (GIrNodeInterface *)ctx->current_node;
878 iface->members = g_list_append (iface->members, field);
879 state_switch (ctx, STATE_CLASS_FIELD);
882 case G_IR_NODE_INTERFACE:
884 GIrNodeInterface *iface;
886 iface = (GIrNodeInterface *)ctx->current_node;
887 iface->members = g_list_append (iface->members, field);
888 state_switch (ctx, STATE_INTERFACE_FIELD);
891 case G_IR_NODE_BOXED:
895 boxed = (GIrNodeBoxed *)ctx->current_node;
896 boxed->members = g_list_append (boxed->members, field);
897 state_switch (ctx, STATE_BOXED_FIELD);
900 case G_IR_NODE_STRUCT:
902 GIrNodeStruct *struct_;
904 struct_ = (GIrNodeStruct *)ctx->current_node;
905 struct_->members = g_list_append (struct_->members, field);
906 state_switch (ctx, STATE_STRUCT_FIELD);
909 case G_IR_NODE_UNION:
911 GIrNodeUnion *union_;
913 union_ = (GIrNodeUnion *)ctx->current_node;
914 union_->members = g_list_append (union_->members, field);
917 GIrNodeConstant *constant;
919 constant = (GIrNodeConstant *) g_ir_node_new (G_IR_NODE_CONSTANT);
920 ((GIrNode *)constant)->name = g_strdup (name);
921 constant->value = g_strdup (branch);
922 constant->type = union_->discriminator_type;
923 constant->deprecated = FALSE;
925 union_->discriminators = g_list_append (union_->discriminators, constant);
927 state_switch (ctx, STATE_UNION_FIELD);
931 g_assert_not_reached ();
938 start_alias (GMarkupParseContext *context,
939 const gchar *element_name,
940 const gchar **attribute_names,
941 const gchar **attribute_values,
951 name = find_attribute ("name", attribute_names, attribute_values);
954 MISSING_ATTRIBUTE (context, error, element_name, "name");
958 target = find_attribute ("target", attribute_names, attribute_values);
961 MISSING_ATTRIBUTE (context, error, element_name, "target");
965 value = g_strdup (target);
966 if (ctx->prefix_aliases)
968 key = g_strdup_printf ("%s.%s", ctx->namespace, name);
969 if (!strchr (target, '.'))
971 const BasicTypeInfo *basic = parse_basic (target);
975 /* For non-basic types, re-qualify the interface */
976 value = g_strdup_printf ("%s.%s", ctx->namespace, target);
982 key = g_strdup (name);
985 g_hash_table_insert (ctx->aliases, key, value);
991 start_enum (GMarkupParseContext *context,
992 const gchar *element_name,
993 const gchar **attribute_names,
994 const gchar **attribute_values,
998 if ((strcmp (element_name, "enumeration") == 0 && ctx->state == STATE_NAMESPACE) ||
999 (strcmp (element_name, "bitfield") == 0 && ctx->state == STATE_NAMESPACE))
1002 const gchar *typename;
1003 const gchar *typeinit;
1004 const gchar *deprecated;
1006 name = find_attribute ("name", attribute_names, attribute_values);
1007 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
1008 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
1009 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1012 MISSING_ATTRIBUTE (context, error, element_name, "name");
1017 if (strcmp (element_name, "enumeration") == 0)
1018 enum_ = (GIrNodeEnum *) g_ir_node_new (G_IR_NODE_ENUM);
1020 enum_ = (GIrNodeEnum *) g_ir_node_new (G_IR_NODE_FLAGS);
1021 ((GIrNode *)enum_)->name = g_strdup (name);
1022 enum_->gtype_name = g_strdup (typename);
1023 enum_->gtype_init = g_strdup (typeinit);
1025 enum_->deprecated = TRUE;
1027 enum_->deprecated = FALSE;
1029 ctx->current_node = (GIrNode *) enum_;
1030 ctx->current_module->entries =
1031 g_list_append (ctx->current_module->entries, enum_);
1033 state_switch (ctx, STATE_ENUM);
1042 start_property (GMarkupParseContext *context,
1043 const gchar *element_name,
1044 const gchar **attribute_names,
1045 const gchar **attribute_values,
1049 if (strcmp (element_name, "property") == 0 &&
1050 (ctx->state == STATE_CLASS ||
1051 ctx->state == STATE_INTERFACE))
1054 const gchar *readable;
1055 const gchar *writable;
1056 const gchar *construct;
1057 const gchar *construct_only;
1059 name = find_attribute ("name", attribute_names, attribute_values);
1060 readable = find_attribute ("readable", attribute_names, attribute_values);
1061 writable = find_attribute ("writable", attribute_names, attribute_values);
1062 construct = find_attribute ("construct", attribute_names, attribute_values);
1063 construct_only = find_attribute ("construct-only", attribute_names, attribute_values);
1066 MISSING_ATTRIBUTE (context, error, element_name, "name");
1069 GIrNodeProperty *property;
1070 GIrNodeInterface *iface;
1072 property = (GIrNodeProperty *) g_ir_node_new (G_IR_NODE_PROPERTY);
1073 ctx->current_typed = (GIrNode*) property;
1075 ((GIrNode *)property)->name = g_strdup (name);
1077 /* Assume properties are readable */
1078 if (readable == NULL || strcmp (readable, "1") == 0)
1079 property->readable = TRUE;
1081 property->readable = FALSE;
1082 if (writable && strcmp (writable, "1") == 0)
1083 property->writable = TRUE;
1085 property->writable = FALSE;
1086 if (construct && strcmp (construct, "1") == 0)
1087 property->construct = TRUE;
1089 property->construct = FALSE;
1090 if (construct_only && strcmp (construct_only, "1") == 0)
1091 property->construct_only = TRUE;
1093 property->construct_only = FALSE;
1095 iface = (GIrNodeInterface *)ctx->current_node;
1096 iface->members = g_list_append (iface->members, property);
1098 if (ctx->state == STATE_CLASS)
1099 state_switch (ctx, STATE_CLASS_PROPERTY);
1100 else if (ctx->state == STATE_INTERFACE)
1101 state_switch (ctx, STATE_INTERFACE_PROPERTY);
1103 g_assert_not_reached ();
1112 parse_value (const gchar *str)
1116 /* FIXME just a quick hack */
1117 shift_op = strstr (str, "<<");
1123 base = strtol (str, NULL, 10);
1124 shift = strtol (shift_op + 3, NULL, 10);
1126 return base << shift;
1129 return strtol (str, NULL, 10);
1135 start_member (GMarkupParseContext *context,
1136 const gchar *element_name,
1137 const gchar **attribute_names,
1138 const gchar **attribute_values,
1142 if (strcmp (element_name, "member") == 0 &&
1143 ctx->state == STATE_ENUM)
1147 const gchar *deprecated;
1149 name = find_attribute ("name", attribute_names, attribute_values);
1150 value = find_attribute ("value", attribute_names, attribute_values);
1151 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1154 MISSING_ATTRIBUTE (context, error, element_name, "name");
1158 GIrNodeValue *value_;
1160 value_ = (GIrNodeValue *) g_ir_node_new (G_IR_NODE_VALUE);
1162 ((GIrNode *)value_)->name = g_strdup (name);
1164 value_->value = parse_value (value);
1167 value_->deprecated = TRUE;
1169 value_->deprecated = FALSE;
1171 enum_ = (GIrNodeEnum *)ctx->current_node;
1172 enum_->values = g_list_append (enum_->values, value_);
1181 start_constant (GMarkupParseContext *context,
1182 const gchar *element_name,
1183 const gchar **attribute_names,
1184 const gchar **attribute_values,
1188 if (strcmp (element_name, "constant") == 0 &&
1189 (ctx->state == STATE_NAMESPACE ||
1190 ctx->state == STATE_CLASS ||
1191 ctx->state == STATE_INTERFACE))
1195 const gchar *deprecated;
1197 name = find_attribute ("name", attribute_names, attribute_values);
1198 value = find_attribute ("value", attribute_names, attribute_values);
1199 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1202 MISSING_ATTRIBUTE (context, error, element_name, "name");
1203 else if (value == NULL)
1204 MISSING_ATTRIBUTE (context, error, element_name, "value");
1207 GIrNodeConstant *constant;
1209 constant = (GIrNodeConstant *) g_ir_node_new (G_IR_NODE_CONSTANT);
1211 ((GIrNode *)constant)->name = g_strdup (name);
1212 constant->value = g_strdup (value);
1214 ctx->current_typed = (GIrNode*) constant;
1217 constant->deprecated = TRUE;
1219 constant->deprecated = FALSE;
1221 if (ctx->state == STATE_NAMESPACE)
1223 ctx->current_node = (GIrNode *) constant;
1224 ctx->current_module->entries =
1225 g_list_append (ctx->current_module->entries, constant);
1229 GIrNodeInterface *iface;
1231 iface = (GIrNodeInterface *)ctx->current_node;
1232 iface->members = g_list_append (iface->members, constant);
1237 case STATE_NAMESPACE:
1238 state_switch (ctx, STATE_NAMESPACE_CONSTANT);
1241 state_switch (ctx, STATE_CLASS_CONSTANT);
1243 case STATE_INTERFACE:
1244 state_switch (ctx, STATE_INTERFACE_CONSTANT);
1247 g_assert_not_reached ();
1258 start_errordomain (GMarkupParseContext *context,
1259 const gchar *element_name,
1260 const gchar **attribute_names,
1261 const gchar **attribute_values,
1265 if (strcmp (element_name, "errordomain") == 0 &&
1266 ctx->state == STATE_NAMESPACE)
1269 const gchar *getquark;
1271 const gchar *deprecated;
1273 name = find_attribute ("name", attribute_names, attribute_values);
1274 getquark = find_attribute ("get-quark", attribute_names, attribute_values);
1275 codes = find_attribute ("codes", attribute_names, attribute_values);
1276 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1279 MISSING_ATTRIBUTE (context, error, element_name, "name");
1280 else if (getquark == NULL)
1281 MISSING_ATTRIBUTE (context, error, element_name, "getquark");
1282 else if (codes == NULL)
1283 MISSING_ATTRIBUTE (context, error, element_name, "codes");
1286 GIrNodeErrorDomain *domain;
1288 domain = (GIrNodeErrorDomain *) g_ir_node_new (G_IR_NODE_ERROR_DOMAIN);
1290 ((GIrNode *)domain)->name = g_strdup (name);
1291 domain->getquark = g_strdup (getquark);
1292 domain->codes = g_strdup (codes);
1295 domain->deprecated = TRUE;
1297 domain->deprecated = FALSE;
1299 ctx->current_node = (GIrNode *) domain;
1300 ctx->current_module->entries =
1301 g_list_append (ctx->current_module->entries, domain);
1303 state_switch (ctx, STATE_ERRORDOMAIN);
1312 start_interface (GMarkupParseContext *context,
1313 const gchar *element_name,
1314 const gchar **attribute_names,
1315 const gchar **attribute_values,
1319 if (strcmp (element_name, "interface") == 0 &&
1320 ctx->state == STATE_NAMESPACE)
1323 const gchar *typename;
1324 const gchar *typeinit;
1325 const gchar *deprecated;
1327 name = find_attribute ("name", attribute_names, attribute_values);
1328 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
1329 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
1330 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1333 MISSING_ATTRIBUTE (context, error, element_name, "name");
1334 else if (typename == NULL)
1335 MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
1336 else if (typeinit == NULL)
1337 MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
1340 GIrNodeInterface *iface;
1342 iface = (GIrNodeInterface *) g_ir_node_new (G_IR_NODE_INTERFACE);
1343 ((GIrNode *)iface)->name = g_strdup (name);
1344 iface->gtype_name = g_strdup (typename);
1345 iface->gtype_init = g_strdup (typeinit);
1347 iface->deprecated = TRUE;
1349 iface->deprecated = FALSE;
1351 ctx->current_node = (GIrNode *) iface;
1352 ctx->current_module->entries =
1353 g_list_append (ctx->current_module->entries, iface);
1355 state_switch (ctx, STATE_INTERFACE);
1365 start_class (GMarkupParseContext *context,
1366 const gchar *element_name,
1367 const gchar **attribute_names,
1368 const gchar **attribute_values,
1372 if (strcmp (element_name, "class") == 0 &&
1373 ctx->state == STATE_NAMESPACE)
1376 const gchar *parent;
1377 const gchar *typename;
1378 const gchar *typeinit;
1379 const gchar *deprecated;
1381 name = find_attribute ("name", attribute_names, attribute_values);
1382 parent = find_attribute ("parent", attribute_names, attribute_values);
1383 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
1384 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
1385 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1388 MISSING_ATTRIBUTE (context, error, element_name, "name");
1389 else if (typename == NULL)
1390 MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
1391 else if (typeinit == NULL && strcmp (typename, "GObject"))
1392 MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
1395 GIrNodeInterface *iface;
1397 iface = (GIrNodeInterface *) g_ir_node_new (G_IR_NODE_OBJECT);
1398 ((GIrNode *)iface)->name = g_strdup (name);
1399 iface->gtype_name = g_strdup (typename);
1400 iface->gtype_init = g_strdup (typeinit);
1401 iface->parent = g_strdup (parent);
1403 iface->deprecated = TRUE;
1405 iface->deprecated = FALSE;
1407 ctx->current_node = (GIrNode *) iface;
1408 ctx->current_module->entries =
1409 g_list_append (ctx->current_module->entries, iface);
1411 state_switch (ctx, STATE_CLASS);
1420 start_type (GMarkupParseContext *context,
1421 const gchar *element_name,
1422 const gchar **attribute_names,
1423 const gchar **attribute_values,
1430 gboolean is_varargs;
1431 GIrNodeType *typenode;
1433 is_array = strcmp (element_name, "array") == 0;
1434 is_varargs = strcmp (element_name, "varargs") == 0;
1436 if (!(is_array || is_varargs || (strcmp (element_name, "type") == 0)))
1439 if (ctx->state == STATE_TYPE)
1442 ctx->type_stack = g_list_prepend (ctx->type_stack, ctx->type_parameters);
1443 ctx->type_parameters = NULL;
1445 else if (ctx->state == STATE_FUNCTION_PARAMETER ||
1446 ctx->state == STATE_FUNCTION_RETURN ||
1447 ctx->state == STATE_STRUCT_FIELD ||
1448 ctx->state == STATE_UNION_FIELD ||
1449 ctx->state == STATE_CLASS_PROPERTY ||
1450 ctx->state == STATE_CLASS_FIELD ||
1451 ctx->state == STATE_INTERFACE_FIELD ||
1452 ctx->state == STATE_INTERFACE_PROPERTY ||
1453 ctx->state == STATE_BOXED_FIELD ||
1454 ctx->state == STATE_NAMESPACE_CONSTANT ||
1455 ctx->state == STATE_CLASS_CONSTANT ||
1456 ctx->state == STATE_INTERFACE_CONSTANT
1459 state_switch (ctx, STATE_TYPE);
1460 ctx->type_depth = 1;
1463 switch (ctx->current_node->type)
1465 case G_IR_NODE_FUNCTION:
1466 case G_IR_NODE_CALLBACK:
1468 GIrNodeFunction *func = (GIrNodeFunction *)ctx->current_node;
1469 func->is_varargs = TRUE;
1472 case G_IR_NODE_VFUNC:
1474 GIrNodeVFunc *vfunc = (GIrNodeVFunc *)ctx->current_node;
1475 vfunc->is_varargs = TRUE;
1480 ctx->type_stack = NULL;
1481 ctx->type_parameters = NULL;
1484 if (!ctx->current_typed)
1488 G_MARKUP_ERROR_INVALID_CONTENT,
1489 "The element <type> is invalid here");
1502 typenode = (GIrNodeType *)g_ir_node_new (G_IR_NODE_TYPE);
1504 typenode->tag = GI_TYPE_TAG_ARRAY;
1505 typenode->is_pointer = TRUE;
1506 typenode->is_array = TRUE;
1508 zero = find_attribute ("zero-terminated", attribute_names, attribute_values);
1509 len = find_attribute ("length", attribute_names, attribute_values);
1511 typenode->zero_terminated = !(zero && strcmp (zero, "1") != 0);
1512 typenode->has_length = len != NULL;
1513 typenode->length = typenode->has_length ? atoi (len) : -1;
1517 gboolean is_pointer;
1518 name = find_attribute ("name", attribute_names, attribute_values);
1521 MISSING_ATTRIBUTE (context, error, element_name, "name");
1523 ctype = find_attribute ("c:type", attribute_names, attribute_values);
1524 if (ctype != NULL && strchr (ctype, '*'))
1529 typenode = parse_type (ctx, name);
1532 typenode->is_pointer = is_pointer;
1535 ctx->type_parameters = g_list_append (ctx->type_parameters, typenode);
1541 end_type_top (ParseContext *ctx)
1543 GIrNodeType *typenode;
1545 if (!ctx->type_parameters)
1548 typenode = (GIrNodeType*)ctx->type_parameters->data;
1550 /* Default to pointer for unspecified containers */
1551 if (typenode->tag == GI_TYPE_TAG_ARRAY ||
1552 typenode->tag == GI_TYPE_TAG_GLIST ||
1553 typenode->tag == GI_TYPE_TAG_GSLIST)
1555 if (typenode->parameter_type1 == NULL)
1556 typenode->parameter_type1 = parse_type (ctx, "any");
1558 else if (typenode->tag == GI_TYPE_TAG_GHASH)
1560 if (typenode->parameter_type1 == NULL)
1562 typenode->parameter_type1 = parse_type (ctx, "any");
1563 typenode->parameter_type2 = parse_type (ctx, "any");
1567 switch (ctx->current_typed->type)
1569 case G_IR_NODE_PARAM:
1571 GIrNodeParam *param = (GIrNodeParam *)ctx->current_typed;
1572 param->type = typenode;
1575 case G_IR_NODE_FIELD:
1577 GIrNodeField *field = (GIrNodeField *)ctx->current_typed;
1578 field->type = typenode;
1581 case G_IR_NODE_PROPERTY:
1583 GIrNodeProperty *property = (GIrNodeProperty *) ctx->current_typed;
1584 property->type = typenode;
1587 case G_IR_NODE_CONSTANT:
1589 GIrNodeConstant *constant = (GIrNodeConstant *)ctx->current_typed;
1590 constant->type = typenode;
1594 g_printerr("current node is %d\n", ctx->current_node->type);
1595 g_assert_not_reached ();
1597 g_list_free (ctx->type_parameters);
1600 ctx->type_depth = 0;
1601 ctx->type_parameters = NULL;
1602 ctx->current_typed = NULL;
1606 end_type_recurse (ParseContext *ctx)
1609 GIrNodeType *parent;
1611 parent = (GIrNodeType *) ((GList*)ctx->type_stack->data)->data;
1613 if (parent->tag == GI_TYPE_TAG_ARRAY ||
1614 parent->tag == GI_TYPE_TAG_GLIST ||
1615 parent->tag == GI_TYPE_TAG_GSLIST)
1617 if (ctx->type_parameters == NULL)
1618 parent->parameter_type1 = parse_type (ctx, "pointer");
1620 parent->parameter_type1 = (GIrNodeType*)ctx->type_parameters->data;
1622 else if (parent->tag == GI_TYPE_TAG_GHASH)
1624 if (ctx->type_parameters == NULL)
1626 parent->parameter_type1 = parse_type (ctx, "pointer");
1627 parent->parameter_type2 = parse_type (ctx, "pointer");
1631 parent->parameter_type1 = (GIrNodeType*) ctx->type_parameters->data;
1632 parent->parameter_type2 = (GIrNodeType*) ctx->type_parameters->next->data;
1635 g_list_free (ctx->type_parameters);
1636 ctx->type_parameters = (GList *)ctx->type_stack->data;
1637 ctx->type_stack = g_list_delete_link (ctx->type_stack, ctx->type_stack);
1641 end_type (ParseContext *ctx)
1643 if (ctx->type_depth == 1)
1646 state_switch (ctx, ctx->prev_state);
1650 end_type_recurse (ctx);
1656 start_return_value (GMarkupParseContext *context,
1657 const gchar *element_name,
1658 const gchar **attribute_names,
1659 const gchar **attribute_values,
1663 if (strcmp (element_name, "return-value") == 0 &&
1664 ctx->state == STATE_FUNCTION)
1666 GIrNodeParam *param;
1667 const gchar *transfer;
1669 param = (GIrNodeParam *)g_ir_node_new (G_IR_NODE_PARAM);
1672 param->retval = TRUE;
1674 ctx->current_typed = (GIrNode*) param;
1676 state_switch (ctx, STATE_FUNCTION_RETURN);
1678 transfer = find_attribute ("transfer-ownership", attribute_names, attribute_values);
1679 parse_param_transfer (param, transfer);
1681 switch (ctx->current_node->type)
1683 case G_IR_NODE_FUNCTION:
1684 case G_IR_NODE_CALLBACK:
1686 GIrNodeFunction *func = (GIrNodeFunction *)ctx->current_node;
1687 func->result = param;
1690 case G_IR_NODE_SIGNAL:
1692 GIrNodeSignal *signal = (GIrNodeSignal *)ctx->current_node;
1693 signal->result = param;
1696 case G_IR_NODE_VFUNC:
1698 GIrNodeVFunc *vfunc = (GIrNodeVFunc *)ctx->current_node;
1699 vfunc->result = param;
1703 g_assert_not_reached ();
1713 start_implements (GMarkupParseContext *context,
1714 const gchar *element_name,
1715 const gchar **attribute_names,
1716 const gchar **attribute_values,
1720 GIrNodeInterface *iface;
1723 if (strcmp (element_name, "implements") != 0 ||
1724 !(ctx->state == STATE_CLASS))
1727 state_switch (ctx, STATE_IMPLEMENTS);
1729 name = find_attribute ("name", attribute_names, attribute_values);
1732 MISSING_ATTRIBUTE (context, error, element_name, "name");
1736 iface = (GIrNodeInterface *)ctx->current_node;
1737 iface->interfaces = g_list_append (iface->interfaces, g_strdup (name));
1743 start_glib_signal (GMarkupParseContext *context,
1744 const gchar *element_name,
1745 const gchar **attribute_names,
1746 const gchar **attribute_values,
1750 if (strcmp (element_name, "glib:signal") == 0 &&
1751 (ctx->state == STATE_CLASS ||
1752 ctx->state == STATE_INTERFACE))
1756 const gchar *no_recurse;
1757 const gchar *detailed;
1758 const gchar *action;
1759 const gchar *no_hooks;
1760 const gchar *has_class_closure;
1762 name = find_attribute ("name", attribute_names, attribute_values);
1763 when = find_attribute ("when", attribute_names, attribute_values);
1764 no_recurse = find_attribute ("no-recurse", attribute_names, attribute_values);
1765 detailed = find_attribute ("detailed", attribute_names, attribute_values);
1766 action = find_attribute ("action", attribute_names, attribute_values);
1767 no_hooks = find_attribute ("no-hooks", attribute_names, attribute_values);
1768 has_class_closure = find_attribute ("has-class-closure", attribute_names, attribute_values);
1771 MISSING_ATTRIBUTE (context, error, element_name, "name");
1774 GIrNodeInterface *iface;
1775 GIrNodeSignal *signal;
1777 signal = (GIrNodeSignal *)g_ir_node_new (G_IR_NODE_SIGNAL);
1779 ((GIrNode *)signal)->name = g_strdup (name);
1781 signal->run_first = FALSE;
1782 signal->run_last = FALSE;
1783 signal->run_cleanup = FALSE;
1784 if (when == NULL || strcmp (when, "LAST") == 0)
1785 signal->run_last = TRUE;
1786 else if (strcmp (when, "FIRST") == 0)
1787 signal->run_first = TRUE;
1789 signal->run_cleanup = TRUE;
1791 if (no_recurse && strcmp (no_recurse, "1") == 0)
1792 signal->no_recurse = TRUE;
1794 signal->no_recurse = FALSE;
1795 if (detailed && strcmp (detailed, "1") == 0)
1796 signal->detailed = TRUE;
1798 signal->detailed = FALSE;
1799 if (action && strcmp (action, "1") == 0)
1800 signal->action = TRUE;
1802 signal->action = FALSE;
1803 if (no_hooks && strcmp (no_hooks, "1") == 0)
1804 signal->no_hooks = TRUE;
1806 signal->no_hooks = FALSE;
1807 if (has_class_closure && strcmp (has_class_closure, "1") == 0)
1808 signal->has_class_closure = TRUE;
1810 signal->has_class_closure = FALSE;
1812 iface = (GIrNodeInterface *)ctx->current_node;
1813 iface->members = g_list_append (iface->members, signal);
1815 ctx->current_node = (GIrNode *)signal;
1816 state_switch (ctx, STATE_FUNCTION);
1825 start_vfunc (GMarkupParseContext *context,
1826 const gchar *element_name,
1827 const gchar **attribute_names,
1828 const gchar **attribute_values,
1832 if (strcmp (element_name, "vfunc") == 0 &&
1833 (ctx->state == STATE_CLASS ||
1834 ctx->state == STATE_INTERFACE))
1837 const gchar *must_chain_up;
1838 const gchar *override;
1839 const gchar *is_class_closure;
1840 const gchar *offset;
1842 name = find_attribute ("name", attribute_names, attribute_values);
1843 must_chain_up = find_attribute ("must-chain-up", attribute_names, attribute_values);
1844 override = find_attribute ("override", attribute_names, attribute_values);
1845 is_class_closure = find_attribute ("is-class-closure", attribute_names, attribute_values);
1846 offset = find_attribute ("offset", attribute_names, attribute_values);
1849 MISSING_ATTRIBUTE (context, error, element_name, "name");
1852 GIrNodeInterface *iface;
1853 GIrNodeVFunc *vfunc;
1855 vfunc = (GIrNodeVFunc *)g_ir_node_new (G_IR_NODE_VFUNC);
1857 ((GIrNode *)vfunc)->name = g_strdup (name);
1859 if (must_chain_up && strcmp (must_chain_up, "1") == 0)
1860 vfunc->must_chain_up = TRUE;
1862 vfunc->must_chain_up = FALSE;
1864 if (override && strcmp (override, "always") == 0)
1866 vfunc->must_be_implemented = TRUE;
1867 vfunc->must_not_be_implemented = FALSE;
1869 else if (override && strcmp (override, "never") == 0)
1871 vfunc->must_be_implemented = FALSE;
1872 vfunc->must_not_be_implemented = TRUE;
1876 vfunc->must_be_implemented = FALSE;
1877 vfunc->must_not_be_implemented = FALSE;
1880 if (is_class_closure && strcmp (is_class_closure, "1") == 0)
1881 vfunc->is_class_closure = TRUE;
1883 vfunc->is_class_closure = FALSE;
1886 vfunc->offset = atoi (offset);
1890 iface = (GIrNodeInterface *)ctx->current_node;
1891 iface->members = g_list_append (iface->members, vfunc);
1893 ctx->current_node = (GIrNode *)vfunc;
1894 state_switch (ctx, STATE_FUNCTION);
1904 start_struct (GMarkupParseContext *context,
1905 const gchar *element_name,
1906 const gchar **attribute_names,
1907 const gchar **attribute_values,
1911 if (strcmp (element_name, "record") == 0 &&
1912 ctx->state == STATE_NAMESPACE)
1915 const gchar *deprecated;
1916 const gchar *gtype_name;
1917 const gchar *gtype_init;
1918 GIrNodeStruct *struct_;
1920 name = find_attribute ("name", attribute_names, attribute_values);
1921 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1922 gtype_name = find_attribute ("glib:type-name", attribute_names, attribute_values);
1923 gtype_init = find_attribute ("glib:get-type", attribute_names, attribute_values);
1927 MISSING_ATTRIBUTE (context, error, element_name, "name");
1930 if ((gtype_name == NULL && gtype_init != NULL))
1932 MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
1935 if ((gtype_name != NULL && gtype_init == NULL))
1937 MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
1941 struct_ = (GIrNodeStruct *) g_ir_node_new (G_IR_NODE_STRUCT);
1943 ((GIrNode *)struct_)->name = g_strdup (name);
1945 struct_->deprecated = TRUE;
1947 struct_->deprecated = FALSE;
1949 struct_->gtype_name = g_strdup (gtype_name);
1950 struct_->gtype_init = g_strdup (gtype_init);
1952 ctx->current_node = (GIrNode *)struct_;
1953 ctx->current_module->entries =
1954 g_list_append (ctx->current_module->entries, struct_);
1956 state_switch (ctx, STATE_STRUCT);
1964 start_union (GMarkupParseContext *context,
1965 const gchar *element_name,
1966 const gchar **attribute_names,
1967 const gchar **attribute_values,
1971 if (strcmp (element_name, "union") == 0 &&
1972 ctx->state == STATE_NAMESPACE)
1975 const gchar *deprecated;
1976 const gchar *typename;
1977 const gchar *typeinit;
1979 name = find_attribute ("name", attribute_names, attribute_values);
1980 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1981 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
1982 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
1985 MISSING_ATTRIBUTE (context, error, element_name, "name");
1988 GIrNodeUnion *union_;
1990 union_ = (GIrNodeUnion *) g_ir_node_new (G_IR_NODE_UNION);
1992 ((GIrNode *)union_)->name = g_strdup (name);
1993 union_->gtype_name = g_strdup (typename);
1994 union_->gtype_init = g_strdup (typeinit);
1996 union_->deprecated = TRUE;
1998 union_->deprecated = FALSE;
2000 ctx->current_node = (GIrNode *)union_;
2001 ctx->current_module->entries =
2002 g_list_append (ctx->current_module->entries, union_);
2004 state_switch (ctx, STATE_UNION);
2012 start_discriminator (GMarkupParseContext *context,
2013 const gchar *element_name,
2014 const gchar **attribute_names,
2015 const gchar **attribute_values,
2019 if (strcmp (element_name, "discriminator") == 0 &&
2020 ctx->state == STATE_UNION)
2023 const gchar *offset;
2025 type = find_attribute ("type", attribute_names, attribute_values);
2026 offset = find_attribute ("offset", attribute_names, attribute_values);
2028 MISSING_ATTRIBUTE (context, error, element_name, "type");
2029 else if (offset == NULL)
2030 MISSING_ATTRIBUTE (context, error, element_name, "offset");
2032 ((GIrNodeUnion *)ctx->current_node)->discriminator_type
2033 = parse_type (ctx, type);
2034 ((GIrNodeUnion *)ctx->current_node)->discriminator_offset
2045 parse_include (GMarkupParseContext *context,
2050 ParseContext sub_ctx = { 0 };
2051 GMarkupParseContext *sub_context;
2056 girpath = locate_gir (name, ctx->includes);
2058 if (girpath == NULL)
2062 G_MARKUP_ERROR_INVALID_CONTENT,
2063 "Could not find GIR file '%s.gir'; check XDG_DATA_DIRS or use --includedir",
2068 g_debug ("Parsing include %s", girpath);
2070 if (!g_file_get_contents (girpath, &buffer, &length, error))
2077 sub_ctx.state = STATE_START;
2078 sub_ctx.includes = ctx->includes;
2079 sub_ctx.prefix_aliases = TRUE;
2080 sub_ctx.namespace = name;
2081 sub_ctx.aliases = ctx->aliases;
2082 sub_ctx.type_depth = 0;
2084 context = g_markup_parse_context_new (&firstpass_parser, 0, &sub_ctx, NULL);
2086 if (!g_markup_parse_context_parse (context, buffer, length, error))
2092 if (!g_markup_parse_context_end_parse (context, error))
2098 g_markup_parse_context_free (context);
2102 extern GLogLevelFlags logged_levels;
2105 start_element_handler (GMarkupParseContext *context,
2106 const gchar *element_name,
2107 const gchar **attribute_names,
2108 const gchar **attribute_values,
2112 ParseContext *ctx = user_data;
2113 gint line_number, char_number;
2115 if (logged_levels & G_LOG_LEVEL_DEBUG)
2117 GString *tags = g_string_new ("");
2119 for (i = 0; attribute_names[i]; i++)
2120 g_string_append_printf (tags, "%s=\"%s\" ",
2122 attribute_values[i]);
2126 g_string_insert_c (tags, 0, ' ');
2127 g_string_truncate (tags, tags->len - 1);
2129 g_debug ("<%s%s>", element_name, tags->str);
2130 g_string_free (tags, TRUE);
2133 switch (element_name[0])
2136 if (ctx->state == STATE_NAMESPACE && strcmp (element_name, "alias") == 0)
2138 state_switch (ctx, STATE_ALIAS);
2141 if (start_type (context, element_name,
2142 attribute_names, attribute_values,
2147 if (start_enum (context, element_name,
2148 attribute_names, attribute_values,
2153 if (start_function (context, element_name,
2154 attribute_names, attribute_values,
2157 else if (start_constant (context, element_name,
2158 attribute_names, attribute_values,
2161 else if (start_class (context, element_name,
2162 attribute_names, attribute_values,
2165 else if (strcmp (element_name, "class") == 0 &&
2166 ctx->state == STATE_REQUIRES)
2170 name = find_attribute ("name", attribute_names, attribute_values);
2173 MISSING_ATTRIBUTE (context, error, element_name, "name");
2176 GIrNodeInterface *iface;
2178 iface = (GIrNodeInterface *)ctx->current_node;
2179 iface ->prerequisites = g_list_append (iface->prerequisites, g_strdup (name));
2187 if (start_discriminator (context, element_name,
2188 attribute_names, attribute_values,
2194 if (start_enum (context, element_name,
2195 attribute_names, attribute_values,
2198 else if (start_errordomain (context, element_name,
2199 attribute_names, attribute_values,
2205 if (start_function (context, element_name,
2206 attribute_names, attribute_values,
2209 else if (start_field (context, element_name,
2210 attribute_names, attribute_values,
2216 if (start_glib_boxed (context, element_name,
2217 attribute_names, attribute_values,
2220 else if (start_glib_signal (context, element_name,
2221 attribute_names, attribute_values,
2227 if (strcmp (element_name, "include") == 0 &&
2228 ctx->state == STATE_REPOSITORY)
2232 name = find_attribute ("name", attribute_names, attribute_values);
2236 MISSING_ATTRIBUTE (context, error, element_name, "name");
2240 if (!parse_include (context, ctx, name, error))
2243 ctx->dependencies = g_list_prepend (ctx->dependencies, g_strdup (name));
2246 state_switch (ctx, STATE_INCLUDE);
2249 if (start_interface (context, element_name,
2250 attribute_names, attribute_values,
2253 else if (start_implements (context, element_name,
2254 attribute_names, attribute_values,
2260 if (start_function (context, element_name,
2261 attribute_names, attribute_values,
2264 else if (start_member (context, element_name,
2265 attribute_names, attribute_values,
2271 if (strcmp (element_name, "namespace") == 0 && ctx->state == STATE_REPOSITORY)
2273 const gchar *name, *version, *shared_library;
2275 name = find_attribute ("name", attribute_names, attribute_values);
2276 version = find_attribute ("version", attribute_names, attribute_values);
2277 shared_library = find_attribute ("shared-library", attribute_names, attribute_values);
2280 MISSING_ATTRIBUTE (context, error, element_name, "name");
2281 else if (version == NULL)
2282 MISSING_ATTRIBUTE (context, error, element_name, "version");
2285 ctx->current_module = g_ir_module_new (name, version, shared_library);
2286 ctx->modules = g_list_append (ctx->modules, ctx->current_module);
2287 ctx->current_module->dependencies = ctx->dependencies;
2289 state_switch (ctx, STATE_NAMESPACE);
2296 if (start_property (context, element_name,
2297 attribute_names, attribute_values,
2300 else if (strcmp (element_name, "parameters") == 0 &&
2301 ctx->state == STATE_FUNCTION)
2303 state_switch (ctx, STATE_FUNCTION_PARAMETERS);
2307 else if (start_parameter (context, element_name,
2308 attribute_names, attribute_values,
2315 if (strcmp (element_name, "repository") == 0 && ctx->state == STATE_START)
2317 const gchar *version;
2319 version = find_attribute ("version", attribute_names, attribute_values);
2321 if (version == NULL)
2322 MISSING_ATTRIBUTE (context, error, element_name, "version");
2323 else if (strcmp (version, "1.0") != 0)
2326 G_MARKUP_ERROR_INVALID_CONTENT,
2327 "Unsupported version '%s'",
2330 state_switch (ctx, STATE_REPOSITORY);
2334 else if (start_return_value (context, element_name,
2335 attribute_names, attribute_values,
2338 else if (strcmp (element_name, "requires") == 0 &&
2339 ctx->state == STATE_INTERFACE)
2341 state_switch (ctx, STATE_REQUIRES);
2345 else if (start_struct (context, element_name,
2346 attribute_names, attribute_values,
2352 if (start_union (context, element_name,
2353 attribute_names, attribute_values,
2359 if (start_type (context, element_name,
2360 attribute_names, attribute_values,
2366 if (start_vfunc (context, element_name,
2367 attribute_names, attribute_values,
2370 if (start_type (context, element_name,
2371 attribute_names, attribute_values,
2377 g_markup_parse_context_get_position (context, &line_number, &char_number);
2379 if (error && *error == NULL)
2382 G_MARKUP_ERROR_UNKNOWN_ELEMENT,
2383 "Unexpected start tag '%s' on line %d char %d; current state=%d",
2385 line_number, char_number, ctx->state);
2390 g_markup_parse_context_get_position (context, &line_number, &char_number);
2392 fprintf (stderr, "Error at line %d, character %d: %s\n", line_number, char_number, (*error)->message);
2393 backtrace_stderr ();
2398 require_one_of_end_elements (GMarkupParseContext *context,
2400 const char *actual_name,
2405 int line_number, char_number;
2406 const char *expected;
2407 gboolean matched = FALSE;
2409 va_start (args, error);
2411 while ((expected = va_arg (args, const char*)) != NULL)
2413 if (strcmp (expected, actual_name) == 0)
2425 g_markup_parse_context_get_position (context, &line_number, &char_number);
2428 G_MARKUP_ERROR_INVALID_CONTENT,
2429 "Unexpected end tag '%s' on line %d char %d; current state=%d",
2431 line_number, char_number, ctx->state);
2437 require_end_element (GMarkupParseContext *context,
2439 const char *expected_name,
2440 const char *actual_name,
2443 return require_one_of_end_elements (context, ctx, actual_name, error, expected_name, NULL);
2447 end_element_handler (GMarkupParseContext *context,
2448 const gchar *element_name,
2452 ParseContext *ctx = user_data;
2454 g_debug ("</%s>", element_name);
2460 /* no need to GError here, GMarkup already catches this */
2463 case STATE_REPOSITORY:
2464 state_switch (ctx, STATE_END);
2468 if (require_end_element (context, ctx, "include", element_name, error))
2470 state_switch (ctx, STATE_REPOSITORY);
2474 case STATE_NAMESPACE:
2475 if (require_end_element (context, ctx, "namespace", element_name, error))
2477 ctx->current_module = NULL;
2478 state_switch (ctx, STATE_REPOSITORY);
2483 if (require_end_element (context, ctx, "alias", element_name, error))
2485 state_switch (ctx, STATE_NAMESPACE);
2489 case STATE_FUNCTION_RETURN:
2490 if (strcmp ("type", element_name) == 0)
2492 if (require_end_element (context, ctx, "return-value", element_name, error))
2494 state_switch (ctx, STATE_FUNCTION);
2498 case STATE_FUNCTION_PARAMETERS:
2499 if (require_end_element (context, ctx, "parameters", element_name, error))
2501 state_switch (ctx, STATE_FUNCTION);
2505 case STATE_FUNCTION_PARAMETER:
2506 if (strcmp ("type", element_name) == 0)
2508 if (require_end_element (context, ctx, "parameter", element_name, error))
2510 state_switch (ctx, STATE_FUNCTION_PARAMETERS);
2514 case STATE_FUNCTION:
2516 gboolean current_is_toplevel;
2517 GList *last = g_list_last (ctx->current_module->entries);
2519 current_is_toplevel = ctx->current_node == last->data;
2521 if (current_is_toplevel)
2523 ctx->current_node = NULL;
2524 state_switch (ctx, STATE_NAMESPACE);
2528 ctx->current_node = g_list_last (ctx->current_module->entries)->data;
2529 if (ctx->current_node->type == G_IR_NODE_INTERFACE)
2530 state_switch (ctx, STATE_INTERFACE);
2531 else if (ctx->current_node->type == G_IR_NODE_OBJECT)
2532 state_switch (ctx, STATE_CLASS);
2533 else if (ctx->current_node->type == G_IR_NODE_BOXED)
2534 state_switch (ctx, STATE_BOXED);
2535 else if (ctx->current_node->type == G_IR_NODE_STRUCT)
2536 state_switch (ctx, STATE_STRUCT);
2537 else if (ctx->current_node->type == G_IR_NODE_UNION)
2538 state_switch (ctx, STATE_UNION);
2541 int line_number, char_number;
2542 g_markup_parse_context_get_position (context, &line_number, &char_number);
2545 G_MARKUP_ERROR_INVALID_CONTENT,
2546 "Unexpected end tag '%s' on line %d char %d",
2548 line_number, char_number);
2554 case STATE_CLASS_FIELD:
2555 if (strcmp ("type", element_name) == 0)
2557 if (require_end_element (context, ctx, "field", element_name, error))
2559 state_switch (ctx, STATE_CLASS);
2563 case STATE_CLASS_PROPERTY:
2564 if (strcmp ("type", element_name) == 0)
2566 if (require_end_element (context, ctx, "property", element_name, error))
2568 state_switch (ctx, STATE_CLASS);
2573 if (require_end_element (context, ctx, "class", element_name, error))
2575 ctx->current_node = NULL;
2576 state_switch (ctx, STATE_NAMESPACE);
2580 case STATE_ERRORDOMAIN:
2581 if (require_end_element (context, ctx, "errordomain", element_name, error))
2583 ctx->current_node = NULL;
2584 state_switch (ctx, STATE_NAMESPACE);
2588 case STATE_INTERFACE_PROPERTY:
2589 if (strcmp ("type", element_name) == 0)
2591 if (require_end_element (context, ctx, "property", element_name, error))
2593 state_switch (ctx, STATE_INTERFACE);
2597 case STATE_INTERFACE_FIELD:
2598 if (strcmp ("type", element_name) == 0)
2600 if (require_end_element (context, ctx, "field", element_name, error))
2602 state_switch (ctx, STATE_INTERFACE);
2606 case STATE_INTERFACE:
2607 if (require_end_element (context, ctx, "interface", element_name, error))
2609 ctx->current_node = NULL;
2610 state_switch (ctx, STATE_NAMESPACE);
2615 if (strcmp ("member", element_name) == 0)
2617 else if (require_one_of_end_elements (context, ctx,
2618 element_name, error, "enumeration",
2621 ctx->current_node = NULL;
2622 state_switch (ctx, STATE_NAMESPACE);
2627 if (require_end_element (context, ctx, "glib:boxed", element_name, error))
2629 ctx->current_node = NULL;
2630 state_switch (ctx, STATE_NAMESPACE);
2634 case STATE_BOXED_FIELD:
2635 if (strcmp ("type", element_name) == 0)
2637 if (require_end_element (context, ctx, "field", element_name, error))
2639 state_switch (ctx, STATE_BOXED);
2643 case STATE_STRUCT_FIELD:
2644 if (strcmp ("type", element_name) == 0)
2646 if (require_end_element (context, ctx, "field", element_name, error))
2648 state_switch (ctx, STATE_STRUCT);
2653 if (require_end_element (context, ctx, "record", element_name, error))
2655 ctx->current_node = NULL;
2656 state_switch (ctx, STATE_NAMESPACE);
2660 case STATE_UNION_FIELD:
2661 if (strcmp ("type", element_name) == 0)
2663 if (require_end_element (context, ctx, "field", element_name, error))
2665 state_switch (ctx, STATE_UNION);
2670 if (require_end_element (context, ctx, "union", element_name, error))
2672 ctx->current_node = NULL;
2673 state_switch (ctx, STATE_NAMESPACE);
2676 case STATE_IMPLEMENTS:
2677 if (strcmp ("interface", element_name) == 0)
2679 if (require_end_element (context, ctx, "implements", element_name, error))
2680 state_switch (ctx, STATE_CLASS);
2682 case STATE_REQUIRES:
2683 if (require_end_element (context, ctx, "requires", element_name, error))
2684 state_switch (ctx, STATE_INTERFACE);
2686 case STATE_NAMESPACE_CONSTANT:
2687 case STATE_CLASS_CONSTANT:
2688 case STATE_INTERFACE_CONSTANT:
2689 if (strcmp ("type", element_name) == 0)
2691 if (require_end_element (context, ctx, "constant", element_name, error))
2693 ctx->current_node = NULL;
2696 case STATE_NAMESPACE_CONSTANT:
2697 state_switch (ctx, STATE_NAMESPACE);
2699 case STATE_CLASS_CONSTANT:
2700 state_switch (ctx, STATE_CLASS);
2702 case STATE_INTERFACE_CONSTANT:
2703 state_switch (ctx, STATE_INTERFACE);
2706 g_assert_not_reached ();
2712 if ((strcmp ("type", element_name) == 0) || (strcmp ("array", element_name) == 0) ||
2713 (strcmp ("varargs", element_name) == 0))
2719 g_error ("Unhandled state %d in end_element_handler\n", ctx->state);
2724 text_handler (GMarkupParseContext *context,
2730 /* FIXME warn about non-whitespace text */
2734 cleanup (GMarkupParseContext *context,
2738 ParseContext *ctx = user_data;
2740 int line_number, char_number;
2742 for (m = ctx->modules; m; m = m->next)
2743 g_ir_module_free (m->data);
2744 g_list_free (ctx->modules);
2745 ctx->modules = NULL;
2747 ctx->current_module = NULL;
2750 static GMarkupParser parser =
2752 start_element_handler,
2753 end_element_handler,
2760 post_filter_varargs_functions (GList *list)
2768 GIrNode *node = iter->data;
2772 if (node->type == G_IR_NODE_FUNCTION)
2774 if (((GIrNodeFunction*)node)->is_varargs)
2776 list = g_list_delete_link (list, link);
2784 post_filter (GIrModule *module)
2788 module->entries = post_filter_varargs_functions (module->entries);
2789 iter = module->entries;
2793 GIrNode *node = iter->data;
2797 if (node->type == G_IR_NODE_OBJECT ||
2798 node->type == G_IR_NODE_INTERFACE)
2800 GIrNodeInterface *iface = (GIrNodeInterface*)node;
2801 iface->members = post_filter_varargs_functions (iface->members);
2803 else if (node->type == G_IR_NODE_BOXED)
2805 GIrNodeBoxed *boxed = (GIrNodeBoxed*)node;
2806 boxed->members = post_filter_varargs_functions (boxed->members);
2808 else if (node->type == G_IR_NODE_STRUCT)
2810 GIrNodeStruct *iface = (GIrNodeStruct*)node;
2811 iface->members = post_filter_varargs_functions (iface->members);
2813 else if (node->type == G_IR_NODE_UNION)
2815 GIrNodeUnion *iface = (GIrNodeUnion*)node;
2816 iface->members = post_filter_varargs_functions (iface->members);
2822 g_ir_parse_string (const gchar *namespace,
2823 const gchar *const *includes,
2824 const gchar *buffer,
2828 ParseContext ctx = { 0 };
2829 GMarkupParseContext *context;
2831 ctx.state = STATE_START;
2832 ctx.includes = includes;
2833 ctx.prefix_aliases = FALSE;
2834 ctx.namespace = namespace;
2835 ctx.aliases = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
2837 ctx.dependencies = NULL;
2838 ctx.current_module = NULL;
2840 context = g_markup_parse_context_new (&firstpass_parser, 0, &ctx, NULL);
2842 if (!g_markup_parse_context_parse (context, buffer, length, error))
2845 if (!g_markup_parse_context_end_parse (context, error))
2848 g_markup_parse_context_free (context);
2850 context = g_markup_parse_context_new (&parser, 0, &ctx, NULL);
2851 if (!g_markup_parse_context_parse (context, buffer, length, error))
2854 if (!g_markup_parse_context_end_parse (context, error))
2859 g_hash_table_destroy (ctx.aliases);
2861 g_markup_parse_context_free (context);
2867 g_ir_parse_file (const gchar *filename,
2868 const gchar *const *includes,
2878 if (!g_str_has_suffix (filename, ".gir"))
2882 G_MARKUP_ERROR_INVALID_CONTENT,
2883 "Expected filename to end with '.gir'");
2887 g_debug ("[parsing] filename %s", filename);
2889 slash = g_strrstr (filename, "/");
2891 namespace = g_strdup (filename);
2893 namespace = g_strdup (slash+1);
2894 namespace[strlen(namespace)-4] = '\0';
2896 if (!g_file_get_contents (filename, &buffer, &length, error))
2899 modules = g_ir_parse_string (namespace, includes, buffer, length, error);
2901 for (iter = modules; iter; iter = iter->next)
2903 post_filter ((GIrModule*)iter->data);