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;
86 start_alias (GMarkupParseContext *context,
87 const gchar *element_name,
88 const gchar **attribute_names,
89 const gchar **attribute_values,
94 firstpass_start_element_handler (GMarkupParseContext *context,
95 const gchar *element_name,
96 const gchar **attribute_names,
97 const gchar **attribute_values,
101 ParseContext *ctx = user_data;
103 if (strcmp (element_name, "alias") == 0)
105 start_alias (context, element_name, attribute_names, attribute_values,
111 firstpass_end_element_handler (GMarkupParseContext *context,
112 const gchar *element_name,
116 ParseContext *ctx = user_data;
120 static GMarkupParser firstpass_parser =
122 firstpass_start_element_handler,
123 firstpass_end_element_handler,
130 locate_gir (const char *name, const char * const* extra_paths)
132 const gchar *const *datadirs;
133 const gchar *const *dir;
137 gboolean firstpass = TRUE;
139 datadirs = g_get_system_data_dirs ();
141 girname = g_strdup_printf ("%s.gir", name);
143 for (dir = datadirs; *dir; dir++)
145 path = g_build_filename (*dir, "gir", girname, NULL);
146 if (g_file_test (path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))
151 for (dir = extra_paths; *dir; dir++)
153 path = g_build_filename (*dir, girname, NULL);
154 if (g_file_test (path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))
163 #define MISSING_ATTRIBUTE(ctx,error,element,attribute) \
165 int line_number, char_number; \
166 g_markup_parse_context_get_position (context, &line_number, &char_number); \
167 g_set_error (error, \
169 G_MARKUP_ERROR_INVALID_CONTENT, \
170 "Line %d, character %d: The attribute '%s' on the element '%s' must be specified", \
171 line_number, char_number, attribute, element); \
175 backtrace_stderr (void)
183 size = backtrace (array, 50);
184 strings = (char**) backtrace_symbols (array, size);
186 fprintf (stderr, "--- BACKTRACE (%zd frames) ---\n", size);
188 for (i = 0; i < size; i++)
189 fprintf (stderr, "%s\n", strings[i]);
191 fprintf (stderr, "--- END BACKTRACE ---\n", size);
199 find_attribute (const gchar *name,
200 const gchar **attribute_names,
201 const gchar **attribute_values)
205 for (i = 0; attribute_names[i] != NULL; i++)
206 if (strcmp (attribute_names[i], name) == 0)
207 return attribute_values[i];
213 state_switch (ParseContext *ctx, ParseState newstate)
215 g_debug ("State: %d", newstate);
216 ctx->prev_state = ctx->state;
217 ctx->state = newstate;
220 static GIrNodeType * parse_type_internal (const gchar *str, gchar **next, gboolean in_glib);
228 static BasicTypeInfo basic_types[] = {
229 { "none", GI_TYPE_TAG_VOID, 0 },
230 { "any", GI_TYPE_TAG_VOID, 1 },
232 { "bool", GI_TYPE_TAG_BOOLEAN, 0 },
233 { "char", GI_TYPE_TAG_INT8, 0 },
234 { "int8", GI_TYPE_TAG_INT8, 0 },
235 { "uint8", GI_TYPE_TAG_UINT8, 0 },
236 { "int16", GI_TYPE_TAG_INT16, 0 },
237 { "uint16", GI_TYPE_TAG_UINT16, 0 },
238 { "int32", GI_TYPE_TAG_INT32, 0 },
239 { "uint32", GI_TYPE_TAG_UINT32, 0 },
240 { "int64", GI_TYPE_TAG_INT64, 0 },
241 { "uint64", GI_TYPE_TAG_UINT64, 0 },
242 { "int", GI_TYPE_TAG_INT, 0 },
243 { "uint", GI_TYPE_TAG_UINT, 0 },
244 { "long", GI_TYPE_TAG_LONG, 0 },
245 { "ulong", GI_TYPE_TAG_ULONG, 0 },
246 { "ssize_t", GI_TYPE_TAG_SSIZE, 0 },
247 { "ssize", GI_TYPE_TAG_SSIZE, 0 },
248 { "size_t", GI_TYPE_TAG_SIZE, 0 },
249 { "size", GI_TYPE_TAG_SIZE, 0 },
250 { "float", GI_TYPE_TAG_FLOAT, 0 },
251 { "double", GI_TYPE_TAG_DOUBLE, 0 },
252 { "utf8", GI_TYPE_TAG_UTF8, 1 },
253 { "filename", GI_TYPE_TAG_FILENAME,1 },
255 /* FIXME: merge - do we still want this? */
256 { "string", GI_TYPE_TAG_UTF8, 1 },
258 /* FIXME: Remove these */
259 { "void", GI_TYPE_TAG_VOID, 0 },
260 { "int8_t", GI_TYPE_TAG_INT8, 0 },
261 { "uint8_t", GI_TYPE_TAG_UINT8, 0 },
262 { "int16_t", GI_TYPE_TAG_INT16, 0 },
263 { "uint16_t", GI_TYPE_TAG_UINT16, 0 },
264 { "int32_t", GI_TYPE_TAG_INT32, 0 },
265 { "uint32_t", GI_TYPE_TAG_UINT32, 0 },
266 { "int64_t", GI_TYPE_TAG_INT64, 0 },
267 { "uint64_t", GI_TYPE_TAG_UINT64, 0 },
268 { "gpointer", GI_TYPE_TAG_VOID, 1 },
269 { "gboolean", GI_TYPE_TAG_BOOLEAN, 0 },
270 { "gchar", GI_TYPE_TAG_INT8, 0 },
271 { "guchar", GI_TYPE_TAG_UINT8, 0 },
272 { "gunichar", GI_TYPE_TAG_UINT32, 0 },
273 { "gint", GI_TYPE_TAG_INT, 0 },
274 { "guint", GI_TYPE_TAG_UINT, 0 },
275 { "gshort", GI_TYPE_TAG_INT16, 0 },
276 { "gushort", GI_TYPE_TAG_UINT16, 0 },
277 { "gint8", GI_TYPE_TAG_INT8, 0 },
278 { "guint8", GI_TYPE_TAG_UINT8, 0 },
279 { "gint16", GI_TYPE_TAG_INT16, 0 },
280 { "guint16", GI_TYPE_TAG_UINT16, 0 },
281 { "gint32", GI_TYPE_TAG_INT32, 0 },
282 { "guint32", GI_TYPE_TAG_UINT32, 0 },
283 { "gint64", GI_TYPE_TAG_INT64, 0 },
284 { "guint64", GI_TYPE_TAG_UINT64, 0 },
285 { "glong", GI_TYPE_TAG_LONG, 0 },
286 { "gulong", GI_TYPE_TAG_ULONG, 0 },
287 { "gssize", GI_TYPE_TAG_SSIZE, 0 },
288 { "gsize", GI_TYPE_TAG_SIZE, 0 },
289 { "gfloat", GI_TYPE_TAG_FLOAT, 0 },
290 { "gdouble", GI_TYPE_TAG_DOUBLE, 0 },
291 { "gchar*", GI_TYPE_TAG_UTF8, 1 }
294 static const BasicTypeInfo *
295 parse_basic (const char *str)
298 gint n_basic = G_N_ELEMENTS (basic_types);
299 gchar *temporary_type = NULL;
303 for (i = 0; i < n_basic; i++)
305 if (g_str_has_prefix (str, basic_types[i].str))
306 return &(basic_types[i]);
312 parse_type_internal (const gchar *str, char **next, gboolean in_glib)
314 const BasicTypeInfo *basic;
316 char *temporary_type = NULL;
318 type = (GIrNodeType *)g_ir_node_new (G_IR_NODE_TYPE);
320 type->unparsed = g_strdup (str);
322 basic = parse_basic (str);
325 type->is_basic = TRUE;
326 type->tag = basic->tag;
327 type->is_pointer = basic->pointer;
329 str += strlen(basic->str);
330 if (*str == '*' && !type->is_pointer)
332 type->is_pointer = TRUE;
338 /* If we're inside GLib, handle "List" by prefixing it with
339 * "GLib." so the parsing code below doesn't have to get more
343 if (g_str_has_prefix (str, "List<") ||
344 strcmp (str, "List") == 0)
346 temporary_type = g_strdup_printf ("GLib.List%s", str + 4);
347 str = temporary_type;
349 else if (g_str_has_prefix (str, "SList<") ||
350 strcmp (str, "SList") == 0)
352 temporary_type = g_strdup_printf ("GLib.SList%s", str + 5);
353 str = temporary_type;
355 else if (g_str_has_prefix (str, "HashTable<") ||
356 strcmp (str, "HashTable") == 0)
358 temporary_type = g_strdup_printf ("GLib.HashTable%s", str + 9);
359 str = temporary_type;
361 else if (g_str_has_prefix (str, "Error<") ||
362 strcmp (str, "Error") == 0)
364 temporary_type = g_strdup_printf ("GLib.Error%s", str + 5);
365 str = temporary_type;
370 /* found a basic type */;
371 else if (g_str_has_prefix (str, "GLib.List") ||
372 g_str_has_prefix (str, "GLib.SList"))
374 str += strlen ("GLib.");
375 if (g_str_has_prefix (str, "List"))
377 type->tag = GI_TYPE_TAG_GLIST;
378 type->is_glist = TRUE;
379 type->is_pointer = TRUE;
380 str += strlen ("List");
384 type->tag = GI_TYPE_TAG_GSLIST;
385 type->is_gslist = TRUE;
386 type->is_pointer = TRUE;
387 str += strlen ("SList");
395 type->parameter_type1 = parse_type_internal (str, &rest, in_glib);
396 if (type->parameter_type1 == NULL)
406 type->parameter_type1 = parse_type_internal ("any", NULL, in_glib);
409 else if (g_str_has_prefix (str, "GLib.HashTable"))
411 str += strlen ("GLib.");
413 type->tag = GI_TYPE_TAG_GHASH;
414 type->is_ghashtable = TRUE;
415 type->is_pointer = TRUE;
416 str += strlen ("HashTable");
423 type->parameter_type1 = parse_type_internal (str, &rest, in_glib);
424 if (type->parameter_type1 == NULL)
432 type->parameter_type2 = parse_type_internal (str, &rest, in_glib);
433 if (type->parameter_type2 == NULL)
443 type->parameter_type1 = parse_type_internal ("any", NULL, in_glib);
444 type->parameter_type2 = parse_type_internal ("any", NULL, in_glib);
447 else if (g_str_has_prefix (str, "GLib.Error"))
449 str += strlen ("GLib.");
451 type->tag = GI_TYPE_TAG_ERROR;
452 type->is_error = TRUE;
453 type->is_pointer = TRUE;
454 str += strlen ("Error");
461 end = strchr (str, '>');
462 tmp = g_strndup (str, end - str);
463 type->errors = g_strsplit (tmp, ",", 0);
471 type->tag = GI_TYPE_TAG_INTERFACE;
472 type->is_interface = TRUE;
473 const char *start = str;
475 /* must be an interface type */
476 while (g_ascii_isalnum (*str) ||
483 type->interface = g_strndup (start, str - start);
487 type->is_pointer = TRUE;
492 if (g_str_has_prefix (str, "["))
497 array = (GIrNodeType *)g_ir_node_new (G_IR_NODE_TYPE);
499 array->tag = GI_TYPE_TAG_ARRAY;
500 array->is_pointer = TRUE;
501 array->is_array = TRUE;
503 array->parameter_type1 = type;
505 array->zero_terminated = FALSE;
506 array->has_length = FALSE;
509 if (!g_str_has_prefix (str, "[]"))
511 gchar *end, *tmp, **opts;
513 end = strchr (str, ']');
514 tmp = g_strndup (str + 1, (end - str) - 1);
515 opts = g_strsplit (tmp, ",", 0);
517 for (i = 0; opts[i]; i++)
521 vals = g_strsplit (opts[i], "=", 0);
523 if (strcmp (vals[0], "zero-terminated") == 0)
524 array->zero_terminated = (strcmp (vals[1], "1") == 0);
525 else if (strcmp (vals[0], "length") == 0)
527 array->has_length = TRUE;
528 array->length = atoi (vals[1]);
545 g_assert (type->tag >= 0 && type->tag <= GI_TYPE_TAG_ERROR);
546 g_free (temporary_type);
550 g_ir_node_free ((GIrNode *)type);
551 g_free (temporary_type);
556 resolve_aliases (ParseContext *ctx, const gchar *type)
560 GSList *seen_values = NULL;
562 seen_values = g_slist_prepend (seen_values, (char*)type);
563 while (g_hash_table_lookup_extended (ctx->aliases, type, &orig, &value))
565 g_debug ("Resolved: %s => %s", type, value);
567 if (g_slist_find_custom (seen_values, type,
568 (GCompareFunc)strcmp) != NULL)
570 seen_values = g_slist_prepend (seen_values, (gchar*)type);
572 g_slist_free (seen_values);
577 parse_type (ParseContext *ctx, const gchar *type)
581 const BasicTypeInfo *basic;
583 gboolean matched_special = FALSE;
585 in_glib = strcmp (ctx->namespace, "GLib") == 0;
587 /* Do not search aliases for basic types */
588 basic = parse_basic (type);
590 type = resolve_aliases (ctx, type);
592 node = parse_type_internal (type, NULL, in_glib);
594 g_debug ("Parsed type: %s => %d", type, node->tag);
596 g_critical ("Failed to parse type: '%s'", type);
602 start_glib_boxed (GMarkupParseContext *context,
603 const gchar *element_name,
604 const gchar **attribute_names,
605 const gchar **attribute_values,
610 const gchar *typename;
611 const gchar *typeinit;
612 const gchar *deprecated;
615 if (!(strcmp (element_name, "glib:boxed") == 0 &&
616 ctx->state == STATE_NAMESPACE))
619 name = find_attribute ("glib:name", attribute_names, attribute_values);
620 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
621 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
622 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
626 MISSING_ATTRIBUTE (context, error, element_name, "glib:name");
629 else if (typename == NULL)
631 MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
634 else if (typeinit == NULL)
636 MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
640 boxed = (GIrNodeBoxed *) g_ir_node_new (G_IR_NODE_BOXED);
642 ((GIrNode *)boxed)->name = g_strdup (name);
643 boxed->gtype_name = g_strdup (typename);
644 boxed->gtype_init = g_strdup (typeinit);
645 if (deprecated && strcmp (deprecated, "1") == 0)
646 boxed->deprecated = TRUE;
648 boxed->deprecated = FALSE;
650 ctx->current_node = (GIrNode *)boxed;
651 ctx->current_module->entries =
652 g_list_append (ctx->current_module->entries, boxed);
654 state_switch (ctx, STATE_BOXED);
660 start_function (GMarkupParseContext *context,
661 const gchar *element_name,
662 const gchar **attribute_names,
663 const gchar **attribute_values,
669 const gchar *deprecated;
670 GIrNodeFunction *function;
671 gboolean found = FALSE;
675 case STATE_NAMESPACE:
676 found = (strcmp (element_name, "function") == 0 ||
677 strcmp (element_name, "callback") == 0);
683 found = strcmp (element_name, "constructor") == 0;
685 case STATE_INTERFACE:
687 strcmp (element_name, "method") == 0 ||
688 strcmp (element_name, "callback") == 0);
697 name = find_attribute ("name", attribute_names, attribute_values);
698 symbol = find_attribute ("c:identifier", attribute_names, attribute_values);
699 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
703 MISSING_ATTRIBUTE (context, error, element_name, "name");
706 else if (strcmp (element_name, "callback") != 0 && symbol == NULL)
708 MISSING_ATTRIBUTE (context, error, element_name, "c:identifier");
712 function = (GIrNodeFunction *) g_ir_node_new (G_IR_NODE_FUNCTION);
714 ((GIrNode *)function)->name = g_strdup (name);
715 function->symbol = g_strdup (symbol);
716 function->parameters = NULL;
717 if (deprecated && strcmp (deprecated, "1") == 0)
718 function->deprecated = TRUE;
720 function->deprecated = FALSE;
722 if (strcmp (element_name, "method") == 0 ||
723 strcmp (element_name, "constructor") == 0)
725 function->is_method = TRUE;
727 if (strcmp (element_name, "constructor") == 0)
728 function->is_constructor = TRUE;
730 function->is_constructor = FALSE;
734 function->is_method = FALSE;
735 function->is_setter = FALSE;
736 function->is_getter = FALSE;
737 function->is_constructor = FALSE;
738 if (strcmp (element_name, "callback") == 0)
739 ((GIrNode *)function)->type = G_IR_NODE_CALLBACK;
742 if (ctx->current_node == NULL)
744 ctx->current_module->entries =
745 g_list_append (ctx->current_module->entries, function);
748 switch (ctx->current_node->type)
750 case G_IR_NODE_INTERFACE:
751 case G_IR_NODE_OBJECT:
753 GIrNodeInterface *iface;
755 iface = (GIrNodeInterface *)ctx->current_node;
756 iface->members = g_list_append (iface->members, function);
759 case G_IR_NODE_BOXED:
763 boxed = (GIrNodeBoxed *)ctx->current_node;
764 boxed->members = g_list_append (boxed->members, function);
767 case G_IR_NODE_STRUCT:
769 GIrNodeStruct *struct_;
771 struct_ = (GIrNodeStruct *)ctx->current_node;
772 struct_->members = g_list_append (struct_->members, function); }
774 case G_IR_NODE_UNION:
776 GIrNodeUnion *union_;
778 union_ = (GIrNodeUnion *)ctx->current_node;
779 union_->members = g_list_append (union_->members, function);
783 g_assert_not_reached ();
786 ctx->current_node = (GIrNode *)function;
787 state_switch (ctx, STATE_FUNCTION);
793 start_parameter (GMarkupParseContext *context,
794 const gchar *element_name,
795 const gchar **attribute_names,
796 const gchar **attribute_values,
801 const gchar *direction;
804 const gchar *optional;
806 const gchar *transfer;
809 if (!(strcmp (element_name, "parameter") == 0 &&
810 ctx->state == STATE_FUNCTION_PARAMETERS))
813 name = find_attribute ("name", attribute_names, attribute_values);
814 direction = find_attribute ("direction", attribute_names, attribute_values);
815 retval = find_attribute ("retval", attribute_names, attribute_values);
816 dipper = find_attribute ("dipper", attribute_names, attribute_values);
817 optional = find_attribute ("optional", attribute_names, attribute_values);
818 nullok = find_attribute ("null-ok", attribute_names, attribute_values);
819 transfer = find_attribute ("transfer", attribute_names, attribute_values);
824 param = (GIrNodeParam *)g_ir_node_new (G_IR_NODE_PARAM);
826 ctx->current_typed = (GIrNode*) param;
827 ctx->current_typed->name = g_strdup (name);
829 state_switch (ctx, STATE_FUNCTION_PARAMETER);
831 if (direction && strcmp (direction, "out") == 0)
836 else if (direction && strcmp (direction, "inout") == 0)
847 if (retval && strcmp (retval, "1") == 0)
848 param->retval = TRUE;
850 param->retval = FALSE;
852 if (dipper && strcmp (dipper, "1") == 0)
853 param->dipper = TRUE;
855 param->dipper = FALSE;
857 if (optional && strcmp (optional, "1") == 0)
858 param->optional = TRUE;
860 param->optional = FALSE;
862 if (nullok && strcmp (nullok, "1") == 0)
863 param->null_ok = TRUE;
865 param->null_ok = FALSE;
867 if (transfer && strcmp (transfer, "none") == 0)
869 param->transfer = FALSE;
870 param->shallow_transfer = FALSE;
872 else if (transfer && strcmp (transfer, "shallow") == 0)
874 param->transfer = FALSE;
875 param->shallow_transfer = TRUE;
881 if (strcmp (transfer, "full") != 0)
882 g_warning ("Unknown transfer %s", transfer);
884 param->transfer = TRUE;
886 else if (param->in && !param->out)
887 param->transfer = FALSE;
889 param->transfer = TRUE;
890 param->shallow_transfer = FALSE;
893 ((GIrNode *)param)->name = g_strdup (name);
895 switch (ctx->current_node->type)
897 case G_IR_NODE_FUNCTION:
898 case G_IR_NODE_CALLBACK:
900 GIrNodeFunction *func;
902 func = (GIrNodeFunction *)ctx->current_node;
903 func->parameters = g_list_append (func->parameters, param);
906 case G_IR_NODE_SIGNAL:
908 GIrNodeSignal *signal;
910 signal = (GIrNodeSignal *)ctx->current_node;
911 signal->parameters = g_list_append (signal->parameters, param);
914 case G_IR_NODE_VFUNC:
918 vfunc = (GIrNodeVFunc *)ctx->current_node;
919 vfunc->parameters = g_list_append (vfunc->parameters, param);
923 g_assert_not_reached ();
930 start_field (GMarkupParseContext *context,
931 const gchar *element_name,
932 const gchar **attribute_names,
933 const gchar **attribute_values,
938 const gchar *readable;
939 const gchar *writable;
951 case STATE_INTERFACE:
957 if (strcmp (element_name, "field") != 0)
960 name = find_attribute ("name", attribute_names, attribute_values);
961 readable = find_attribute ("readable", attribute_names, attribute_values);
962 writable = find_attribute ("writable", attribute_names, attribute_values);
963 bits = find_attribute ("bits", attribute_names, attribute_values);
964 branch = find_attribute ("branch", attribute_names, attribute_values);
965 offset = find_attribute ("offset", attribute_names, attribute_values);
969 MISSING_ATTRIBUTE (context, error, element_name, "name");
973 field = (GIrNodeField *)g_ir_node_new (G_IR_NODE_FIELD);
974 ctx->current_typed = (GIrNode*) field;
975 ((GIrNode *)field)->name = g_strdup (name);
976 if (readable && strcmp (readable, "1") == 0)
977 field->readable = TRUE;
979 field->readable = FALSE;
981 if (writable && strcmp (writable, "1") == 0)
982 field->writable = TRUE;
984 field->writable = FALSE;
987 field->bits = atoi (bits);
992 field->offset = atoi (offset);
996 switch (ctx->current_node->type)
998 case G_IR_NODE_OBJECT:
1000 GIrNodeInterface *iface;
1002 iface = (GIrNodeInterface *)ctx->current_node;
1003 iface->members = g_list_append (iface->members, field);
1004 state_switch (ctx, STATE_CLASS_FIELD);
1007 case G_IR_NODE_INTERFACE:
1009 GIrNodeInterface *iface;
1011 iface = (GIrNodeInterface *)ctx->current_node;
1012 iface->members = g_list_append (iface->members, field);
1013 state_switch (ctx, STATE_INTERFACE_FIELD);
1016 case G_IR_NODE_BOXED:
1018 GIrNodeBoxed *boxed;
1020 boxed = (GIrNodeBoxed *)ctx->current_node;
1021 boxed->members = g_list_append (boxed->members, field);
1022 state_switch (ctx, STATE_BOXED_FIELD);
1025 case G_IR_NODE_STRUCT:
1027 GIrNodeStruct *struct_;
1029 struct_ = (GIrNodeStruct *)ctx->current_node;
1030 struct_->members = g_list_append (struct_->members, field);
1031 state_switch (ctx, STATE_STRUCT_FIELD);
1034 case G_IR_NODE_UNION:
1036 GIrNodeUnion *union_;
1038 union_ = (GIrNodeUnion *)ctx->current_node;
1039 union_->members = g_list_append (union_->members, field);
1042 GIrNodeConstant *constant;
1044 constant = (GIrNodeConstant *) g_ir_node_new (G_IR_NODE_CONSTANT);
1045 ((GIrNode *)constant)->name = g_strdup (name);
1046 constant->value = g_strdup (branch);
1047 constant->type = union_->discriminator_type;
1048 constant->deprecated = FALSE;
1050 union_->discriminators = g_list_append (union_->discriminators, constant);
1052 state_switch (ctx, STATE_UNION_FIELD);
1056 g_assert_not_reached ();
1063 start_alias (GMarkupParseContext *context,
1064 const gchar *element_name,
1065 const gchar **attribute_names,
1066 const gchar **attribute_values,
1071 const gchar *target;
1076 name = find_attribute ("name", attribute_names, attribute_values);
1079 MISSING_ATTRIBUTE (context, error, element_name, "name");
1083 target = find_attribute ("target", attribute_names, attribute_values);
1086 MISSING_ATTRIBUTE (context, error, element_name, "target");
1090 value = g_strdup (target);
1091 if (ctx->prefix_aliases)
1093 key = g_strdup_printf ("%s.%s", ctx->namespace, name);
1094 if (!strchr (target, '.'))
1096 const BasicTypeInfo *basic = parse_basic (target);
1100 /* For non-basic types, re-qualify the interface */
1101 value = g_strdup_printf ("%s.%s", ctx->namespace, target);
1107 key = g_strdup (name);
1110 g_hash_table_insert (ctx->aliases, key, value);
1116 start_enum (GMarkupParseContext *context,
1117 const gchar *element_name,
1118 const gchar **attribute_names,
1119 const gchar **attribute_values,
1123 if ((strcmp (element_name, "enumeration") == 0 && ctx->state == STATE_NAMESPACE) ||
1124 (strcmp (element_name, "bitfield") == 0 && ctx->state == STATE_NAMESPACE))
1127 const gchar *typename;
1128 const gchar *typeinit;
1129 const gchar *deprecated;
1131 name = find_attribute ("name", attribute_names, attribute_values);
1132 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
1133 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
1134 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1137 MISSING_ATTRIBUTE (context, error, element_name, "name");
1142 if (strcmp (element_name, "enumeration") == 0)
1143 enum_ = (GIrNodeEnum *) g_ir_node_new (G_IR_NODE_ENUM);
1145 enum_ = (GIrNodeEnum *) g_ir_node_new (G_IR_NODE_FLAGS);
1146 ((GIrNode *)enum_)->name = g_strdup (name);
1147 enum_->gtype_name = g_strdup (typename);
1148 enum_->gtype_init = g_strdup (typeinit);
1149 if (deprecated && strcmp (deprecated, "1") == 0)
1150 enum_->deprecated = TRUE;
1152 enum_->deprecated = FALSE;
1154 ctx->current_node = (GIrNode *) enum_;
1155 ctx->current_module->entries =
1156 g_list_append (ctx->current_module->entries, enum_);
1158 state_switch (ctx, STATE_ENUM);
1167 start_property (GMarkupParseContext *context,
1168 const gchar *element_name,
1169 const gchar **attribute_names,
1170 const gchar **attribute_values,
1174 if (strcmp (element_name, "property") == 0 &&
1175 (ctx->state == STATE_CLASS ||
1176 ctx->state == STATE_INTERFACE))
1179 const gchar *readable;
1180 const gchar *writable;
1181 const gchar *construct;
1182 const gchar *construct_only;
1184 name = find_attribute ("name", attribute_names, attribute_values);
1185 readable = find_attribute ("readable", attribute_names, attribute_values);
1186 writable = find_attribute ("writable", attribute_names, attribute_values);
1187 construct = find_attribute ("construct", attribute_names, attribute_values);
1188 construct_only = find_attribute ("construct-only", attribute_names, attribute_values);
1191 MISSING_ATTRIBUTE (context, error, element_name, "name");
1194 GIrNodeProperty *property;
1195 GIrNodeInterface *iface;
1197 property = (GIrNodeProperty *) g_ir_node_new (G_IR_NODE_PROPERTY);
1198 ctx->current_typed = (GIrNode*) property;
1200 ((GIrNode *)property)->name = g_strdup (name);
1202 if (readable && strcmp (readable, "1") == 0)
1203 property->readable = TRUE;
1205 property->readable = FALSE;
1206 if (writable && strcmp (writable, "1") == 0)
1207 property->writable = TRUE;
1209 property->writable = FALSE;
1210 if (construct && strcmp (construct, "1") == 0)
1211 property->construct = TRUE;
1213 property->construct = FALSE;
1214 if (construct_only && strcmp (construct_only, "1") == 0)
1215 property->construct_only = TRUE;
1217 property->construct_only = FALSE;
1219 iface = (GIrNodeInterface *)ctx->current_node;
1220 iface->members = g_list_append (iface->members, property);
1222 if (ctx->state == STATE_CLASS)
1223 state_switch (ctx, STATE_CLASS_PROPERTY);
1224 else if (ctx->state == STATE_INTERFACE)
1225 state_switch (ctx, STATE_INTERFACE_PROPERTY);
1227 g_assert_not_reached ();
1236 parse_value (const gchar *str)
1240 /* FIXME just a quick hack */
1241 shift_op = strstr (str, "<<");
1247 base = strtol (str, NULL, 10);
1248 shift = strtol (shift_op + 3, NULL, 10);
1250 return base << shift;
1253 return strtol (str, NULL, 10);
1259 start_member (GMarkupParseContext *context,
1260 const gchar *element_name,
1261 const gchar **attribute_names,
1262 const gchar **attribute_values,
1266 if (strcmp (element_name, "member") == 0 &&
1267 ctx->state == STATE_ENUM)
1271 const gchar *deprecated;
1273 name = find_attribute ("name", attribute_names, attribute_values);
1274 value = find_attribute ("value", attribute_names, attribute_values);
1275 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1278 MISSING_ATTRIBUTE (context, error, element_name, "name");
1282 GIrNodeValue *value_;
1284 value_ = (GIrNodeValue *) g_ir_node_new (G_IR_NODE_VALUE);
1286 ((GIrNode *)value_)->name = g_strdup (name);
1288 value_->value = parse_value (value);
1290 if (deprecated && strcmp (deprecated, "1") == 0)
1291 value_->deprecated = TRUE;
1293 value_->deprecated = FALSE;
1295 enum_ = (GIrNodeEnum *)ctx->current_node;
1296 enum_->values = g_list_append (enum_->values, value_);
1305 start_constant (GMarkupParseContext *context,
1306 const gchar *element_name,
1307 const gchar **attribute_names,
1308 const gchar **attribute_values,
1312 if (strcmp (element_name, "constant") == 0 &&
1313 (ctx->state == STATE_NAMESPACE ||
1314 ctx->state == STATE_CLASS ||
1315 ctx->state == STATE_INTERFACE))
1319 const gchar *deprecated;
1321 name = find_attribute ("name", attribute_names, attribute_values);
1322 value = find_attribute ("value", attribute_names, attribute_values);
1323 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1326 MISSING_ATTRIBUTE (context, error, element_name, "name");
1327 else if (value == NULL)
1328 MISSING_ATTRIBUTE (context, error, element_name, "value");
1331 GIrNodeConstant *constant;
1333 constant = (GIrNodeConstant *) g_ir_node_new (G_IR_NODE_CONSTANT);
1335 ((GIrNode *)constant)->name = g_strdup (name);
1336 constant->value = g_strdup (value);
1338 ctx->current_typed = (GIrNode*) constant;
1340 if (deprecated && strcmp (deprecated, "1") == 0)
1341 constant->deprecated = TRUE;
1343 constant->deprecated = FALSE;
1345 if (ctx->state == STATE_NAMESPACE)
1347 ctx->current_node = (GIrNode *) constant;
1348 ctx->current_module->entries =
1349 g_list_append (ctx->current_module->entries, constant);
1353 GIrNodeInterface *iface;
1355 iface = (GIrNodeInterface *)ctx->current_node;
1356 iface->members = g_list_append (iface->members, constant);
1361 case STATE_NAMESPACE:
1362 state_switch (ctx, STATE_NAMESPACE_CONSTANT);
1365 state_switch (ctx, STATE_CLASS_CONSTANT);
1367 case STATE_INTERFACE:
1368 state_switch (ctx, STATE_INTERFACE_CONSTANT);
1371 g_assert_not_reached ();
1382 start_errordomain (GMarkupParseContext *context,
1383 const gchar *element_name,
1384 const gchar **attribute_names,
1385 const gchar **attribute_values,
1389 if (strcmp (element_name, "errordomain") == 0 &&
1390 ctx->state == STATE_NAMESPACE)
1393 const gchar *getquark;
1395 const gchar *deprecated;
1397 name = find_attribute ("name", attribute_names, attribute_values);
1398 getquark = find_attribute ("get-quark", attribute_names, attribute_values);
1399 codes = find_attribute ("codes", attribute_names, attribute_values);
1400 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1403 MISSING_ATTRIBUTE (context, error, element_name, "name");
1404 else if (getquark == NULL)
1405 MISSING_ATTRIBUTE (context, error, element_name, "getquark");
1406 else if (codes == NULL)
1407 MISSING_ATTRIBUTE (context, error, element_name, "codes");
1410 GIrNodeErrorDomain *domain;
1412 domain = (GIrNodeErrorDomain *) g_ir_node_new (G_IR_NODE_ERROR_DOMAIN);
1414 ((GIrNode *)domain)->name = g_strdup (name);
1415 domain->getquark = g_strdup (getquark);
1416 domain->codes = g_strdup (codes);
1418 if (deprecated && strcmp (deprecated, "1") == 0)
1419 domain->deprecated = TRUE;
1421 domain->deprecated = FALSE;
1423 ctx->current_node = (GIrNode *) domain;
1424 ctx->current_module->entries =
1425 g_list_append (ctx->current_module->entries, domain);
1427 state_switch (ctx, STATE_ERRORDOMAIN);
1436 start_interface (GMarkupParseContext *context,
1437 const gchar *element_name,
1438 const gchar **attribute_names,
1439 const gchar **attribute_values,
1443 if (strcmp (element_name, "interface") == 0 &&
1444 ctx->state == STATE_NAMESPACE)
1447 const gchar *typename;
1448 const gchar *typeinit;
1449 const gchar *deprecated;
1451 name = find_attribute ("name", attribute_names, attribute_values);
1452 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
1453 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
1454 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1457 MISSING_ATTRIBUTE (context, error, element_name, "name");
1458 else if (typename == NULL)
1459 MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
1460 else if (typeinit == NULL)
1461 MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
1464 GIrNodeInterface *iface;
1466 iface = (GIrNodeInterface *) g_ir_node_new (G_IR_NODE_INTERFACE);
1467 ((GIrNode *)iface)->name = g_strdup (name);
1468 iface->gtype_name = g_strdup (typename);
1469 iface->gtype_init = g_strdup (typeinit);
1470 if (deprecated && strcmp (deprecated, "1") == 0)
1471 iface->deprecated = TRUE;
1473 iface->deprecated = FALSE;
1475 ctx->current_node = (GIrNode *) iface;
1476 ctx->current_module->entries =
1477 g_list_append (ctx->current_module->entries, iface);
1479 state_switch (ctx, STATE_INTERFACE);
1489 start_class (GMarkupParseContext *context,
1490 const gchar *element_name,
1491 const gchar **attribute_names,
1492 const gchar **attribute_values,
1496 if (strcmp (element_name, "class") == 0 &&
1497 ctx->state == STATE_NAMESPACE)
1500 const gchar *parent;
1501 const gchar *typename;
1502 const gchar *typeinit;
1503 const gchar *deprecated;
1505 name = find_attribute ("name", attribute_names, attribute_values);
1506 parent = find_attribute ("parent", attribute_names, attribute_values);
1507 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
1508 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
1509 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1512 MISSING_ATTRIBUTE (context, error, element_name, "name");
1513 else if (typename == NULL)
1514 MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
1515 else if (typeinit == NULL && strcmp (typename, "GObject"))
1516 MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
1519 GIrNodeInterface *iface;
1521 iface = (GIrNodeInterface *) g_ir_node_new (G_IR_NODE_OBJECT);
1522 ((GIrNode *)iface)->name = g_strdup (name);
1523 iface->gtype_name = g_strdup (typename);
1524 iface->gtype_init = g_strdup (typeinit);
1525 iface->parent = g_strdup (parent);
1526 if (deprecated && strcmp (deprecated, "1") == 0)
1527 iface->deprecated = TRUE;
1529 iface->deprecated = FALSE;
1531 ctx->current_node = (GIrNode *) iface;
1532 ctx->current_module->entries =
1533 g_list_append (ctx->current_module->entries, iface);
1535 state_switch (ctx, STATE_CLASS);
1544 start_type (GMarkupParseContext *context,
1545 const gchar *element_name,
1546 const gchar **attribute_names,
1547 const gchar **attribute_values,
1553 if (strcmp (element_name, "type") != 0)
1556 if (ctx->state == STATE_TYPE)
1558 else if (ctx->state == STATE_FUNCTION_PARAMETER ||
1559 ctx->state == STATE_FUNCTION_RETURN ||
1560 ctx->state == STATE_STRUCT_FIELD ||
1561 ctx->state == STATE_UNION_FIELD ||
1562 ctx->state == STATE_CLASS_PROPERTY ||
1563 ctx->state == STATE_CLASS_FIELD ||
1564 ctx->state == STATE_INTERFACE_FIELD ||
1565 ctx->state == STATE_INTERFACE_PROPERTY ||
1566 ctx->state == STATE_BOXED_FIELD ||
1567 ctx->state == STATE_NAMESPACE_CONSTANT ||
1568 ctx->state == STATE_CLASS_CONSTANT ||
1569 ctx->state == STATE_INTERFACE_CONSTANT
1572 state_switch (ctx, STATE_TYPE);
1573 ctx->type_depth = 1;
1576 /* FIXME handle recursive types */
1577 if (ctx->type_depth > 1)
1580 if (!ctx->current_typed)
1584 G_MARKUP_ERROR_INVALID_CONTENT,
1585 "The element <type> is invalid here");
1589 name = find_attribute ("name", attribute_names, attribute_values);
1592 MISSING_ATTRIBUTE (context, error, element_name, "name");
1594 switch (ctx->current_typed->type)
1596 case G_IR_NODE_PARAM:
1598 GIrNodeParam *param = (GIrNodeParam *)ctx->current_typed;
1599 param->type = parse_type (ctx, name);
1602 case G_IR_NODE_FIELD:
1604 GIrNodeField *field = (GIrNodeField *)ctx->current_typed;
1605 field->type = parse_type (ctx, name);
1608 case G_IR_NODE_PROPERTY:
1610 GIrNodeProperty *property = (GIrNodeProperty *) ctx->current_typed;
1611 property->type = parse_type (ctx, name);
1614 case G_IR_NODE_CONSTANT:
1616 GIrNodeConstant *constant = (GIrNodeConstant *)ctx->current_typed;
1617 constant->type = parse_type (ctx, name);
1621 g_printerr("current node is %d\n", ctx->current_node->type);
1622 g_assert_not_reached ();
1625 ctx->current_typed = NULL;
1630 start_return_value (GMarkupParseContext *context,
1631 const gchar *element_name,
1632 const gchar **attribute_names,
1633 const gchar **attribute_values,
1637 if (strcmp (element_name, "return-value") == 0 &&
1638 ctx->state == STATE_FUNCTION)
1640 GIrNodeParam *param;
1642 param = (GIrNodeParam *)g_ir_node_new (G_IR_NODE_PARAM);
1645 param->retval = TRUE;
1647 ctx->current_typed = (GIrNode*) param;
1649 state_switch (ctx, STATE_FUNCTION_RETURN);
1651 switch (ctx->current_node->type)
1653 case G_IR_NODE_FUNCTION:
1654 case G_IR_NODE_CALLBACK:
1656 GIrNodeFunction *func = (GIrNodeFunction *)ctx->current_node;
1657 func->result = param;
1660 case G_IR_NODE_SIGNAL:
1662 GIrNodeSignal *signal = (GIrNodeSignal *)ctx->current_node;
1663 signal->result = param;
1666 case G_IR_NODE_VFUNC:
1668 GIrNodeVFunc *vfunc = (GIrNodeVFunc *)ctx->current_node;
1669 vfunc->result = param;
1673 g_assert_not_reached ();
1683 start_implements (GMarkupParseContext *context,
1684 const gchar *element_name,
1685 const gchar **attribute_names,
1686 const gchar **attribute_values,
1690 GIrNodeInterface *iface;
1693 if (strcmp (element_name, "implements") != 0 ||
1694 !(ctx->state == STATE_CLASS))
1697 state_switch (ctx, STATE_IMPLEMENTS);
1699 name = find_attribute ("name", attribute_names, attribute_values);
1702 MISSING_ATTRIBUTE (context, error, element_name, "name");
1706 iface = (GIrNodeInterface *)ctx->current_node;
1707 iface->interfaces = g_list_append (iface->interfaces, g_strdup (name));
1713 start_glib_signal (GMarkupParseContext *context,
1714 const gchar *element_name,
1715 const gchar **attribute_names,
1716 const gchar **attribute_values,
1720 if (strcmp (element_name, "glib:signal") == 0 &&
1721 (ctx->state == STATE_CLASS ||
1722 ctx->state == STATE_INTERFACE))
1726 const gchar *no_recurse;
1727 const gchar *detailed;
1728 const gchar *action;
1729 const gchar *no_hooks;
1730 const gchar *has_class_closure;
1732 name = find_attribute ("name", attribute_names, attribute_values);
1733 when = find_attribute ("when", attribute_names, attribute_values);
1734 no_recurse = find_attribute ("no-recurse", attribute_names, attribute_values);
1735 detailed = find_attribute ("detailed", attribute_names, attribute_values);
1736 action = find_attribute ("action", attribute_names, attribute_values);
1737 no_hooks = find_attribute ("no-hooks", attribute_names, attribute_values);
1738 has_class_closure = find_attribute ("has-class-closure", attribute_names, attribute_values);
1741 MISSING_ATTRIBUTE (context, error, element_name, "name");
1744 GIrNodeInterface *iface;
1745 GIrNodeSignal *signal;
1747 signal = (GIrNodeSignal *)g_ir_node_new (G_IR_NODE_SIGNAL);
1749 ((GIrNode *)signal)->name = g_strdup (name);
1751 signal->run_first = FALSE;
1752 signal->run_last = FALSE;
1753 signal->run_cleanup = FALSE;
1754 if (when == NULL || strcmp (when, "LAST") == 0)
1755 signal->run_last = TRUE;
1756 else if (strcmp (when, "FIRST") == 0)
1757 signal->run_first = TRUE;
1759 signal->run_cleanup = TRUE;
1761 if (no_recurse && strcmp (no_recurse, "1") == 0)
1762 signal->no_recurse = TRUE;
1764 signal->no_recurse = FALSE;
1765 if (detailed && strcmp (detailed, "1") == 0)
1766 signal->detailed = TRUE;
1768 signal->detailed = FALSE;
1769 if (action && strcmp (action, "1") == 0)
1770 signal->action = TRUE;
1772 signal->action = FALSE;
1773 if (no_hooks && strcmp (no_hooks, "1") == 0)
1774 signal->no_hooks = TRUE;
1776 signal->no_hooks = FALSE;
1777 if (has_class_closure && strcmp (has_class_closure, "1") == 0)
1778 signal->has_class_closure = TRUE;
1780 signal->has_class_closure = FALSE;
1782 iface = (GIrNodeInterface *)ctx->current_node;
1783 iface->members = g_list_append (iface->members, signal);
1785 ctx->current_node = (GIrNode *)signal;
1786 state_switch (ctx, STATE_FUNCTION);
1795 start_vfunc (GMarkupParseContext *context,
1796 const gchar *element_name,
1797 const gchar **attribute_names,
1798 const gchar **attribute_values,
1802 if (strcmp (element_name, "vfunc") == 0 &&
1803 (ctx->state == STATE_CLASS ||
1804 ctx->state == STATE_INTERFACE))
1807 const gchar *must_chain_up;
1808 const gchar *override;
1809 const gchar *is_class_closure;
1810 const gchar *offset;
1812 name = find_attribute ("name", attribute_names, attribute_values);
1813 must_chain_up = find_attribute ("must-chain-up", attribute_names, attribute_values);
1814 override = find_attribute ("override", attribute_names, attribute_values);
1815 is_class_closure = find_attribute ("is-class-closure", attribute_names, attribute_values);
1816 offset = find_attribute ("offset", attribute_names, attribute_values);
1819 MISSING_ATTRIBUTE (context, error, element_name, "name");
1822 GIrNodeInterface *iface;
1823 GIrNodeVFunc *vfunc;
1825 vfunc = (GIrNodeVFunc *)g_ir_node_new (G_IR_NODE_VFUNC);
1827 ((GIrNode *)vfunc)->name = g_strdup (name);
1829 if (must_chain_up && strcmp (must_chain_up, "1") == 0)
1830 vfunc->must_chain_up = TRUE;
1832 vfunc->must_chain_up = FALSE;
1834 if (override && strcmp (override, "always") == 0)
1836 vfunc->must_be_implemented = TRUE;
1837 vfunc->must_not_be_implemented = FALSE;
1839 else if (override && strcmp (override, "never") == 0)
1841 vfunc->must_be_implemented = FALSE;
1842 vfunc->must_not_be_implemented = TRUE;
1846 vfunc->must_be_implemented = FALSE;
1847 vfunc->must_not_be_implemented = FALSE;
1850 if (is_class_closure && strcmp (is_class_closure, "1") == 0)
1851 vfunc->is_class_closure = TRUE;
1853 vfunc->is_class_closure = FALSE;
1856 vfunc->offset = atoi (offset);
1860 iface = (GIrNodeInterface *)ctx->current_node;
1861 iface->members = g_list_append (iface->members, vfunc);
1863 ctx->current_node = (GIrNode *)vfunc;
1864 state_switch (ctx, STATE_FUNCTION);
1874 start_struct (GMarkupParseContext *context,
1875 const gchar *element_name,
1876 const gchar **attribute_names,
1877 const gchar **attribute_values,
1881 if (strcmp (element_name, "record") == 0 &&
1882 ctx->state == STATE_NAMESPACE)
1885 const gchar *deprecated;
1887 name = find_attribute ("name", attribute_names, attribute_values);
1888 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1891 MISSING_ATTRIBUTE (context, error, element_name, "name");
1894 GIrNodeStruct *struct_;
1896 struct_ = (GIrNodeStruct *) g_ir_node_new (G_IR_NODE_STRUCT);
1898 ((GIrNode *)struct_)->name = g_strdup (name);
1899 if (deprecated && strcmp (deprecated, "1") == 0)
1900 struct_->deprecated = TRUE;
1902 struct_->deprecated = FALSE;
1904 ctx->current_node = (GIrNode *)struct_;
1905 ctx->current_module->entries =
1906 g_list_append (ctx->current_module->entries, struct_);
1908 state_switch (ctx, STATE_STRUCT);
1917 start_union (GMarkupParseContext *context,
1918 const gchar *element_name,
1919 const gchar **attribute_names,
1920 const gchar **attribute_values,
1924 if (strcmp (element_name, "union") == 0 &&
1925 ctx->state == STATE_NAMESPACE)
1928 const gchar *deprecated;
1929 const gchar *typename;
1930 const gchar *typeinit;
1932 name = find_attribute ("name", attribute_names, attribute_values);
1933 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1934 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
1935 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
1938 MISSING_ATTRIBUTE (context, error, element_name, "name");
1941 GIrNodeUnion *union_;
1943 union_ = (GIrNodeUnion *) g_ir_node_new (G_IR_NODE_UNION);
1945 ((GIrNode *)union_)->name = g_strdup (name);
1946 union_->gtype_name = g_strdup (typename);
1947 union_->gtype_init = g_strdup (typeinit);
1948 if (deprecated && strcmp (deprecated, "1") == 0)
1949 union_->deprecated = TRUE;
1951 union_->deprecated = FALSE;
1953 ctx->current_node = (GIrNode *)union_;
1954 ctx->current_module->entries =
1955 g_list_append (ctx->current_module->entries, union_);
1957 state_switch (ctx, STATE_UNION);
1965 start_discriminator (GMarkupParseContext *context,
1966 const gchar *element_name,
1967 const gchar **attribute_names,
1968 const gchar **attribute_values,
1972 if (strcmp (element_name, "discriminator") == 0 &&
1973 ctx->state == STATE_UNION)
1976 const gchar *offset;
1978 type = find_attribute ("type", attribute_names, attribute_values);
1979 offset = find_attribute ("offset", attribute_names, attribute_values);
1981 MISSING_ATTRIBUTE (context, error, element_name, "type");
1982 else if (offset == NULL)
1983 MISSING_ATTRIBUTE (context, error, element_name, "offset");
1985 ((GIrNodeUnion *)ctx->current_node)->discriminator_type
1986 = parse_type (ctx, type);
1987 ((GIrNodeUnion *)ctx->current_node)->discriminator_offset
1998 parse_include (GMarkupParseContext *context,
2003 ParseContext sub_ctx = { 0 };
2004 GMarkupParseContext *sub_context;
2009 girpath = locate_gir (name, ctx->includes);
2011 if (girpath == NULL)
2015 G_MARKUP_ERROR_INVALID_CONTENT,
2016 "Could not find GIR file '%s'; check XDG_DATA_DIRS or use --includedir",
2021 g_debug ("Parsing include %s", girpath);
2023 if (!g_file_get_contents (girpath, &buffer, &length, error))
2030 sub_ctx.state = STATE_START;
2031 sub_ctx.includes = ctx->includes;
2032 sub_ctx.prefix_aliases = TRUE;
2033 sub_ctx.namespace = name;
2034 sub_ctx.aliases = ctx->aliases;
2035 sub_ctx.type_depth = 0;
2037 context = g_markup_parse_context_new (&firstpass_parser, 0, &sub_ctx, NULL);
2039 if (!g_markup_parse_context_parse (context, buffer, length, error))
2045 if (!g_markup_parse_context_end_parse (context, error))
2051 g_markup_parse_context_free (context);
2055 extern GLogLevelFlags logged_levels;
2058 start_element_handler (GMarkupParseContext *context,
2059 const gchar *element_name,
2060 const gchar **attribute_names,
2061 const gchar **attribute_values,
2065 ParseContext *ctx = user_data;
2066 gint line_number, char_number;
2068 if (logged_levels & G_LOG_LEVEL_DEBUG)
2070 GString *tags = g_string_new ("");
2072 for (i = 0; attribute_names[i]; i++)
2073 g_string_append_printf (tags, "%s=\"%s\" ",
2075 attribute_values[i]);
2079 g_string_insert_c (tags, 0, ' ');
2080 g_string_truncate (tags, tags->len - 1);
2082 g_debug ("<%s%s>", element_name, tags->str);
2083 g_string_free (tags, TRUE);
2086 switch (element_name[0])
2089 if (ctx->state == STATE_NAMESPACE && strcmp (element_name, "alias") == 0)
2091 state_switch (ctx, STATE_ALIAS);
2096 if (start_enum (context, element_name,
2097 attribute_names, attribute_values,
2102 if (start_function (context, element_name,
2103 attribute_names, attribute_values,
2106 else if (start_constant (context, element_name,
2107 attribute_names, attribute_values,
2110 else if (start_class (context, element_name,
2111 attribute_names, attribute_values,
2114 else if (strcmp (element_name, "class") == 0 &&
2115 ctx->state == STATE_REQUIRES)
2119 name = find_attribute ("name", attribute_names, attribute_values);
2122 MISSING_ATTRIBUTE (context, error, element_name, "name");
2125 GIrNodeInterface *iface;
2127 iface = (GIrNodeInterface *)ctx->current_node;
2128 iface ->prerequisites = g_list_append (iface->prerequisites, g_strdup (name));
2136 if (start_discriminator (context, element_name,
2137 attribute_names, attribute_values,
2143 if (start_enum (context, element_name,
2144 attribute_names, attribute_values,
2147 else if (start_errordomain (context, element_name,
2148 attribute_names, attribute_values,
2154 if (start_function (context, element_name,
2155 attribute_names, attribute_values,
2158 else if (start_field (context, element_name,
2159 attribute_names, attribute_values,
2165 if (start_glib_boxed (context, element_name,
2166 attribute_names, attribute_values,
2169 else if (start_glib_signal (context, element_name,
2170 attribute_names, attribute_values,
2176 if (strcmp (element_name, "include") == 0 &&
2177 ctx->state == STATE_REPOSITORY)
2181 name = find_attribute ("name", attribute_names, attribute_values);
2185 MISSING_ATTRIBUTE (context, error, element_name, "name");
2189 if (!parse_include (context, ctx, name, error))
2192 ctx->dependencies = g_list_prepend (ctx->dependencies, g_strdup (name));
2195 state_switch (ctx, STATE_INCLUDE);
2198 if (start_interface (context, element_name,
2199 attribute_names, attribute_values,
2202 else if (start_implements (context, element_name,
2203 attribute_names, attribute_values,
2209 if (start_function (context, element_name,
2210 attribute_names, attribute_values,
2213 else if (start_member (context, element_name,
2214 attribute_names, attribute_values,
2220 if (strcmp (element_name, "namespace") == 0 && ctx->state == STATE_REPOSITORY)
2222 const gchar *name, *shared_library;
2224 name = find_attribute ("name", attribute_names, attribute_values);
2225 shared_library = find_attribute ("shared-library", attribute_names, attribute_values);
2228 MISSING_ATTRIBUTE (context, error, element_name, "name");
2231 ctx->current_module = g_ir_module_new (name, shared_library);
2232 ctx->modules = g_list_append (ctx->modules, ctx->current_module);
2233 ctx->current_module->dependencies = ctx->dependencies;
2235 state_switch (ctx, STATE_NAMESPACE);
2242 if (start_property (context, element_name,
2243 attribute_names, attribute_values,
2246 else if (strcmp (element_name, "parameters") == 0 &&
2247 ctx->state == STATE_FUNCTION)
2249 state_switch (ctx, STATE_FUNCTION_PARAMETERS);
2253 else if (start_parameter (context, element_name,
2254 attribute_names, attribute_values,
2261 if (strcmp (element_name, "repository") == 0 && ctx->state == STATE_START)
2263 const gchar *version;
2265 version = find_attribute ("version", attribute_names, attribute_values);
2267 if (version == NULL)
2268 MISSING_ATTRIBUTE (context, error, element_name, "version");
2269 else if (strcmp (version, "1.0") != 0)
2272 G_MARKUP_ERROR_INVALID_CONTENT,
2273 "Unsupported version '%s'",
2276 state_switch (ctx, STATE_REPOSITORY);
2280 else if (start_return_value (context, element_name,
2281 attribute_names, attribute_values,
2284 else if (strcmp (element_name, "requires") == 0 &&
2285 ctx->state == STATE_INTERFACE)
2287 state_switch (ctx, STATE_REQUIRES);
2291 else if (start_struct (context, element_name,
2292 attribute_names, attribute_values,
2298 if (start_union (context, element_name,
2299 attribute_names, attribute_values,
2305 if (start_type (context, element_name,
2306 attribute_names, attribute_values,
2312 if (start_vfunc (context, element_name,
2313 attribute_names, attribute_values,
2319 g_markup_parse_context_get_position (context, &line_number, &char_number);
2321 if (error && *error == NULL)
2324 G_MARKUP_ERROR_UNKNOWN_ELEMENT,
2325 "Unexpected start tag '%s' on line %d char %d; current state=%d",
2327 line_number, char_number, ctx->state);
2332 g_markup_parse_context_get_position (context, &line_number, &char_number);
2334 fprintf (stderr, "Error at line %d, character %d: %s\n", line_number, char_number, (*error)->message);
2335 backtrace_stderr ();
2340 require_one_of_end_elements (GMarkupParseContext *context,
2342 const char *actual_name,
2347 int line_number, char_number;
2348 const char *expected;
2349 gboolean matched = FALSE;
2351 va_start (args, error);
2353 while ((expected = va_arg (args, const char*)) != NULL)
2355 if (strcmp (expected, actual_name) == 0)
2367 g_markup_parse_context_get_position (context, &line_number, &char_number);
2370 G_MARKUP_ERROR_INVALID_CONTENT,
2371 "Unexpected end tag '%s' on line %d char %d; current state=%d",
2373 line_number, char_number, ctx->state);
2379 require_end_element (GMarkupParseContext *context,
2381 const char *expected_name,
2382 const char *actual_name,
2385 return require_one_of_end_elements (context, ctx, actual_name, error, expected_name, NULL);
2389 end_element_handler (GMarkupParseContext *context,
2390 const gchar *element_name,
2394 ParseContext *ctx = user_data;
2396 g_debug ("</%s>", element_name);
2402 /* no need to GError here, GMarkup already catches this */
2405 case STATE_REPOSITORY:
2406 state_switch (ctx, STATE_END);
2410 if (require_end_element (context, ctx, "include", element_name, error))
2412 state_switch (ctx, STATE_REPOSITORY);
2416 case STATE_NAMESPACE:
2417 if (require_end_element (context, ctx, "namespace", element_name, error))
2419 ctx->current_module = NULL;
2420 state_switch (ctx, STATE_REPOSITORY);
2425 if (require_end_element (context, ctx, "alias", element_name, error))
2427 state_switch (ctx, STATE_NAMESPACE);
2431 case STATE_FUNCTION_RETURN:
2432 if (strcmp ("type", element_name) == 0)
2434 if (require_end_element (context, ctx, "return-value", element_name, error))
2436 state_switch (ctx, STATE_FUNCTION);
2440 case STATE_FUNCTION_PARAMETERS:
2441 if (require_end_element (context, ctx, "parameters", element_name, error))
2443 state_switch (ctx, STATE_FUNCTION);
2447 case STATE_FUNCTION_PARAMETER:
2448 if (strcmp ("type", element_name) == 0)
2450 if (require_end_element (context, ctx, "parameter", element_name, error))
2452 state_switch (ctx, STATE_FUNCTION_PARAMETERS);
2456 case STATE_FUNCTION:
2457 if (ctx->current_node == g_list_last (ctx->current_module->entries)->data)
2459 ctx->current_node = NULL;
2460 state_switch (ctx, STATE_NAMESPACE);
2464 ctx->current_node = g_list_last (ctx->current_module->entries)->data;
2465 if (ctx->current_node->type == G_IR_NODE_INTERFACE)
2466 state_switch (ctx, STATE_INTERFACE);
2467 else if (ctx->current_node->type == G_IR_NODE_OBJECT)
2468 state_switch (ctx, STATE_CLASS);
2469 else if (ctx->current_node->type == G_IR_NODE_BOXED)
2470 state_switch (ctx, STATE_BOXED);
2471 else if (ctx->current_node->type == G_IR_NODE_STRUCT)
2472 state_switch (ctx, STATE_STRUCT);
2473 else if (ctx->current_node->type == G_IR_NODE_UNION)
2474 state_switch (ctx, STATE_UNION);
2477 int line_number, char_number;
2478 g_markup_parse_context_get_position (context, &line_number, &char_number);
2481 G_MARKUP_ERROR_INVALID_CONTENT,
2482 "Unexpected end tag '%s' on line %d char %d",
2484 line_number, char_number);
2489 case STATE_CLASS_FIELD:
2490 if (strcmp ("type", element_name) == 0)
2492 if (require_end_element (context, ctx, "field", element_name, error))
2494 state_switch (ctx, STATE_CLASS);
2498 case STATE_CLASS_PROPERTY:
2499 if (strcmp ("type", element_name) == 0)
2501 if (require_end_element (context, ctx, "property", element_name, error))
2503 state_switch (ctx, STATE_CLASS);
2508 if (require_end_element (context, ctx, "class", element_name, error))
2510 ctx->current_node = NULL;
2511 state_switch (ctx, STATE_NAMESPACE);
2515 case STATE_ERRORDOMAIN:
2516 if (require_end_element (context, ctx, "errordomain", element_name, error))
2518 ctx->current_node = NULL;
2519 state_switch (ctx, STATE_NAMESPACE);
2523 case STATE_INTERFACE_PROPERTY:
2524 if (strcmp ("type", element_name) == 0)
2526 if (require_end_element (context, ctx, "property", element_name, error))
2528 state_switch (ctx, STATE_INTERFACE);
2532 case STATE_INTERFACE_FIELD:
2533 if (strcmp ("type", element_name) == 0)
2535 if (require_end_element (context, ctx, "field", element_name, error))
2537 state_switch (ctx, STATE_INTERFACE);
2541 case STATE_INTERFACE:
2542 if (require_end_element (context, ctx, "interface", element_name, error))
2544 ctx->current_node = NULL;
2545 state_switch (ctx, STATE_NAMESPACE);
2550 if (strcmp ("member", element_name) == 0)
2552 else if (require_one_of_end_elements (context, ctx,
2553 element_name, error, "enumeration",
2556 ctx->current_node = NULL;
2557 state_switch (ctx, STATE_NAMESPACE);
2562 if (require_end_element (context, ctx, "glib:boxed", element_name, error))
2564 ctx->current_node = NULL;
2565 state_switch (ctx, STATE_NAMESPACE);
2569 case STATE_BOXED_FIELD:
2570 if (strcmp ("type", element_name) == 0)
2572 if (require_end_element (context, ctx, "field", element_name, error))
2574 state_switch (ctx, STATE_BOXED);
2578 case STATE_STRUCT_FIELD:
2579 if (strcmp ("type", element_name) == 0)
2581 if (require_end_element (context, ctx, "field", element_name, error))
2583 state_switch (ctx, STATE_STRUCT);
2588 if (require_end_element (context, ctx, "record", element_name, error))
2590 ctx->current_node = NULL;
2591 state_switch (ctx, STATE_NAMESPACE);
2595 case STATE_UNION_FIELD:
2596 if (strcmp ("type", element_name) == 0)
2598 if (require_end_element (context, ctx, "field", element_name, error))
2600 state_switch (ctx, STATE_UNION);
2605 if (require_end_element (context, ctx, "union", element_name, error))
2607 ctx->current_node = NULL;
2608 state_switch (ctx, STATE_NAMESPACE);
2611 case STATE_IMPLEMENTS:
2612 if (strcmp ("interface", element_name) == 0)
2614 if (require_end_element (context, ctx, "implements", element_name, error))
2615 state_switch (ctx, STATE_CLASS);
2617 case STATE_REQUIRES:
2618 if (require_end_element (context, ctx, "requires", element_name, error))
2619 state_switch (ctx, STATE_INTERFACE);
2621 case STATE_NAMESPACE_CONSTANT:
2622 case STATE_CLASS_CONSTANT:
2623 case STATE_INTERFACE_CONSTANT:
2624 if (strcmp ("type", element_name) == 0)
2626 if (require_end_element (context, ctx, "constant", element_name, error))
2628 ctx->current_node = NULL;
2631 case STATE_NAMESPACE_CONSTANT:
2632 state_switch (ctx, STATE_NAMESPACE);
2634 case STATE_CLASS_CONSTANT:
2635 state_switch (ctx, STATE_CLASS);
2637 case STATE_INTERFACE_CONSTANT:
2638 state_switch (ctx, STATE_INTERFACE);
2641 g_assert_not_reached ();
2647 if (strcmp ("type", element_name) == 0)
2649 if (ctx->type_depth == 1)
2650 state_switch (ctx, ctx->prev_state);
2652 ctx->type_depth -= 1;
2656 g_error ("Unhandled state %d in end_element_handler\n", ctx->state);
2661 text_handler (GMarkupParseContext *context,
2667 /* FIXME warn about non-whitespace text */
2671 cleanup (GMarkupParseContext *context,
2675 ParseContext *ctx = user_data;
2677 int line_number, char_number;
2679 for (m = ctx->modules; m; m = m->next)
2680 g_ir_module_free (m->data);
2681 g_list_free (ctx->modules);
2682 ctx->modules = NULL;
2684 ctx->current_module = NULL;
2687 static GMarkupParser parser =
2689 start_element_handler,
2690 end_element_handler,
2697 g_ir_parse_string (const gchar *namespace,
2698 const gchar *const *includes,
2699 const gchar *buffer,
2703 ParseContext ctx = { 0 };
2704 GMarkupParseContext *context;
2706 ctx.state = STATE_START;
2707 ctx.includes = includes;
2708 ctx.prefix_aliases = FALSE;
2709 ctx.namespace = namespace;
2710 ctx.aliases = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
2712 ctx.dependencies = NULL;
2713 ctx.current_module = NULL;
2715 context = g_markup_parse_context_new (&firstpass_parser, 0, &ctx, NULL);
2717 if (!g_markup_parse_context_parse (context, buffer, length, error))
2720 if (!g_markup_parse_context_end_parse (context, error))
2723 g_markup_parse_context_free (context);
2725 context = g_markup_parse_context_new (&parser, 0, &ctx, NULL);
2726 if (!g_markup_parse_context_parse (context, buffer, length, error))
2729 if (!g_markup_parse_context_end_parse (context, error))
2734 g_hash_table_destroy (ctx.aliases);
2736 g_markup_parse_context_free (context);
2742 g_ir_parse_file (const gchar *filename,
2743 const gchar *const *includes,
2752 if (!g_str_has_suffix (filename, ".gir"))
2756 G_MARKUP_ERROR_INVALID_CONTENT,
2757 "Expected filename to end with '.gir'");
2761 g_debug ("[parsing] filename %s", filename);
2763 slash = g_strrstr (filename, "/");
2765 namespace = g_strdup (filename);
2767 namespace = g_strdup (slash+1);
2768 namespace[strlen(namespace)-4] = '\0';
2770 if (!g_file_get_contents (filename, &buffer, &length, error))
2773 modules = g_ir_parse_string (namespace, includes, buffer, length, error);