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 if (extra_paths != NULL)
153 for (dir = extra_paths; *dir; dir++)
155 path = g_build_filename (*dir, girname, NULL);
156 if (g_file_test (path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))
166 #define MISSING_ATTRIBUTE(ctx,error,element,attribute) \
168 int line_number, char_number; \
169 g_markup_parse_context_get_position (context, &line_number, &char_number); \
170 g_set_error (error, \
172 G_MARKUP_ERROR_INVALID_CONTENT, \
173 "Line %d, character %d: The attribute '%s' on the element '%s' must be specified", \
174 line_number, char_number, attribute, element); \
178 backtrace_stderr (void)
186 size = backtrace (array, 50);
187 strings = (char**) backtrace_symbols (array, size);
189 fprintf (stderr, "--- BACKTRACE (%zd frames) ---\n", size);
191 for (i = 0; i < size; i++)
192 fprintf (stderr, "%s\n", strings[i]);
194 fprintf (stderr, "--- END BACKTRACE ---\n", size);
202 find_attribute (const gchar *name,
203 const gchar **attribute_names,
204 const gchar **attribute_values)
208 for (i = 0; attribute_names[i] != NULL; i++)
209 if (strcmp (attribute_names[i], name) == 0)
210 return attribute_values[i];
216 state_switch (ParseContext *ctx, ParseState newstate)
218 g_debug ("State: %d", newstate);
219 ctx->prev_state = ctx->state;
220 ctx->state = newstate;
223 static GIrNodeType * parse_type_internal (const gchar *str, gchar **next, gboolean in_glib);
231 static BasicTypeInfo basic_types[] = {
232 { "none", GI_TYPE_TAG_VOID, 0 },
233 { "any", GI_TYPE_TAG_VOID, 1 },
235 { "bool", GI_TYPE_TAG_BOOLEAN, 0 },
236 { "char", GI_TYPE_TAG_INT8, 0 },
237 { "int8", GI_TYPE_TAG_INT8, 0 },
238 { "uint8", GI_TYPE_TAG_UINT8, 0 },
239 { "int16", GI_TYPE_TAG_INT16, 0 },
240 { "uint16", GI_TYPE_TAG_UINT16, 0 },
241 { "int32", GI_TYPE_TAG_INT32, 0 },
242 { "uint32", GI_TYPE_TAG_UINT32, 0 },
243 { "int64", GI_TYPE_TAG_INT64, 0 },
244 { "uint64", GI_TYPE_TAG_UINT64, 0 },
245 { "int", GI_TYPE_TAG_INT, 0 },
246 { "uint", GI_TYPE_TAG_UINT, 0 },
247 { "long", GI_TYPE_TAG_LONG, 0 },
248 { "ulong", GI_TYPE_TAG_ULONG, 0 },
249 { "ssize_t", GI_TYPE_TAG_SSIZE, 0 },
250 { "ssize", GI_TYPE_TAG_SSIZE, 0 },
251 { "size_t", GI_TYPE_TAG_SIZE, 0 },
252 { "size", GI_TYPE_TAG_SIZE, 0 },
253 { "float", GI_TYPE_TAG_FLOAT, 0 },
254 { "double", GI_TYPE_TAG_DOUBLE, 0 },
255 { "utf8", GI_TYPE_TAG_UTF8, 1 },
256 { "filename", GI_TYPE_TAG_FILENAME,1 },
258 /* FIXME: merge - do we still want this? */
259 { "string", GI_TYPE_TAG_UTF8, 1 },
261 /* FIXME: Remove these */
262 { "void", GI_TYPE_TAG_VOID, 0 },
263 { "int8_t", GI_TYPE_TAG_INT8, 0 },
264 { "uint8_t", GI_TYPE_TAG_UINT8, 0 },
265 { "int16_t", GI_TYPE_TAG_INT16, 0 },
266 { "uint16_t", GI_TYPE_TAG_UINT16, 0 },
267 { "int32_t", GI_TYPE_TAG_INT32, 0 },
268 { "uint32_t", GI_TYPE_TAG_UINT32, 0 },
269 { "int64_t", GI_TYPE_TAG_INT64, 0 },
270 { "uint64_t", GI_TYPE_TAG_UINT64, 0 },
271 { "gpointer", GI_TYPE_TAG_VOID, 1 },
272 { "gboolean", GI_TYPE_TAG_BOOLEAN, 0 },
273 { "gchar", GI_TYPE_TAG_INT8, 0 },
274 { "guchar", GI_TYPE_TAG_UINT8, 0 },
275 { "gunichar", GI_TYPE_TAG_UINT32, 0 },
276 { "gint", GI_TYPE_TAG_INT, 0 },
277 { "guint", GI_TYPE_TAG_UINT, 0 },
278 { "gshort", GI_TYPE_TAG_INT16, 0 },
279 { "gushort", GI_TYPE_TAG_UINT16, 0 },
280 { "gint8", GI_TYPE_TAG_INT8, 0 },
281 { "guint8", GI_TYPE_TAG_UINT8, 0 },
282 { "gint16", GI_TYPE_TAG_INT16, 0 },
283 { "guint16", GI_TYPE_TAG_UINT16, 0 },
284 { "gint32", GI_TYPE_TAG_INT32, 0 },
285 { "guint32", GI_TYPE_TAG_UINT32, 0 },
286 { "gint64", GI_TYPE_TAG_INT64, 0 },
287 { "guint64", GI_TYPE_TAG_UINT64, 0 },
288 { "glong", GI_TYPE_TAG_LONG, 0 },
289 { "gulong", GI_TYPE_TAG_ULONG, 0 },
290 { "gssize", GI_TYPE_TAG_SSIZE, 0 },
291 { "gsize", GI_TYPE_TAG_SIZE, 0 },
292 { "gfloat", GI_TYPE_TAG_FLOAT, 0 },
293 { "gdouble", GI_TYPE_TAG_DOUBLE, 0 },
294 { "gchar*", GI_TYPE_TAG_UTF8, 1 }
297 static const BasicTypeInfo *
298 parse_basic (const char *str)
301 gint n_basic = G_N_ELEMENTS (basic_types);
302 gchar *temporary_type = NULL;
306 for (i = 0; i < n_basic; i++)
308 if (g_str_has_prefix (str, basic_types[i].str))
309 return &(basic_types[i]);
315 parse_type_internal (const gchar *str, char **next, gboolean in_glib)
317 const BasicTypeInfo *basic;
319 char *temporary_type = NULL;
321 type = (GIrNodeType *)g_ir_node_new (G_IR_NODE_TYPE);
323 type->unparsed = g_strdup (str);
325 basic = parse_basic (str);
328 type->is_basic = TRUE;
329 type->tag = basic->tag;
330 type->is_pointer = basic->pointer;
332 str += strlen(basic->str);
333 if (*str == '*' && !type->is_pointer)
335 type->is_pointer = TRUE;
341 /* If we're inside GLib, handle "List" by prefixing it with
342 * "GLib." so the parsing code below doesn't have to get more
346 if (g_str_has_prefix (str, "List<") ||
347 strcmp (str, "List") == 0)
349 temporary_type = g_strdup_printf ("GLib.List%s", str + 4);
350 str = temporary_type;
352 else if (g_str_has_prefix (str, "SList<") ||
353 strcmp (str, "SList") == 0)
355 temporary_type = g_strdup_printf ("GLib.SList%s", str + 5);
356 str = temporary_type;
358 else if (g_str_has_prefix (str, "HashTable<") ||
359 strcmp (str, "HashTable") == 0)
361 temporary_type = g_strdup_printf ("GLib.HashTable%s", str + 9);
362 str = temporary_type;
364 else if (g_str_has_prefix (str, "Error<") ||
365 strcmp (str, "Error") == 0)
367 temporary_type = g_strdup_printf ("GLib.Error%s", str + 5);
368 str = temporary_type;
373 /* found a basic type */;
374 else if (g_str_has_prefix (str, "GLib.List") ||
375 g_str_has_prefix (str, "GLib.SList"))
377 str += strlen ("GLib.");
378 if (g_str_has_prefix (str, "List"))
380 type->tag = GI_TYPE_TAG_GLIST;
381 type->is_glist = TRUE;
382 type->is_pointer = TRUE;
383 str += strlen ("List");
387 type->tag = GI_TYPE_TAG_GSLIST;
388 type->is_gslist = TRUE;
389 type->is_pointer = TRUE;
390 str += strlen ("SList");
398 type->parameter_type1 = parse_type_internal (str, &rest, in_glib);
399 if (type->parameter_type1 == NULL)
409 type->parameter_type1 = parse_type_internal ("any", NULL, in_glib);
412 else if (g_str_has_prefix (str, "GLib.HashTable"))
414 str += strlen ("GLib.");
416 type->tag = GI_TYPE_TAG_GHASH;
417 type->is_ghashtable = TRUE;
418 type->is_pointer = TRUE;
419 str += strlen ("HashTable");
426 type->parameter_type1 = parse_type_internal (str, &rest, in_glib);
427 if (type->parameter_type1 == NULL)
435 type->parameter_type2 = parse_type_internal (str, &rest, in_glib);
436 if (type->parameter_type2 == NULL)
446 type->parameter_type1 = parse_type_internal ("any", NULL, in_glib);
447 type->parameter_type2 = parse_type_internal ("any", NULL, in_glib);
450 else if (g_str_has_prefix (str, "GLib.Error"))
452 str += strlen ("GLib.");
454 type->tag = GI_TYPE_TAG_ERROR;
455 type->is_error = TRUE;
456 type->is_pointer = TRUE;
457 str += strlen ("Error");
464 end = strchr (str, '>');
465 tmp = g_strndup (str, end - str);
466 type->errors = g_strsplit (tmp, ",", 0);
474 type->tag = GI_TYPE_TAG_INTERFACE;
475 type->is_interface = TRUE;
476 const char *start = str;
478 /* must be an interface type */
479 while (g_ascii_isalnum (*str) ||
486 type->interface = g_strndup (start, str - start);
490 type->is_pointer = TRUE;
495 if (g_str_has_prefix (str, "["))
500 array = (GIrNodeType *)g_ir_node_new (G_IR_NODE_TYPE);
502 array->tag = GI_TYPE_TAG_ARRAY;
503 array->is_pointer = TRUE;
504 array->is_array = TRUE;
506 array->parameter_type1 = type;
508 array->zero_terminated = FALSE;
509 array->has_length = FALSE;
512 if (!g_str_has_prefix (str, "[]"))
514 gchar *end, *tmp, **opts;
516 end = strchr (str, ']');
517 tmp = g_strndup (str + 1, (end - str) - 1);
518 opts = g_strsplit (tmp, ",", 0);
520 for (i = 0; opts[i]; i++)
524 vals = g_strsplit (opts[i], "=", 0);
526 if (strcmp (vals[0], "zero-terminated") == 0)
527 array->zero_terminated = (strcmp (vals[1], "1") == 0);
528 else if (strcmp (vals[0], "length") == 0)
530 array->has_length = TRUE;
531 array->length = atoi (vals[1]);
548 g_assert (type->tag >= 0 && type->tag <= GI_TYPE_TAG_ERROR);
549 g_free (temporary_type);
553 g_ir_node_free ((GIrNode *)type);
554 g_free (temporary_type);
559 resolve_aliases (ParseContext *ctx, const gchar *type)
563 GSList *seen_values = NULL;
565 seen_values = g_slist_prepend (seen_values, (char*)type);
566 while (g_hash_table_lookup_extended (ctx->aliases, type, &orig, &value))
568 g_debug ("Resolved: %s => %s", type, value);
570 if (g_slist_find_custom (seen_values, type,
571 (GCompareFunc)strcmp) != NULL)
573 seen_values = g_slist_prepend (seen_values, (gchar*)type);
575 g_slist_free (seen_values);
580 parse_type (ParseContext *ctx, const gchar *type)
584 const BasicTypeInfo *basic;
586 gboolean matched_special = FALSE;
588 in_glib = strcmp (ctx->namespace, "GLib") == 0;
590 /* Do not search aliases for basic types */
591 basic = parse_basic (type);
593 type = resolve_aliases (ctx, type);
595 node = parse_type_internal (type, NULL, in_glib);
597 g_debug ("Parsed type: %s => %d", type, node->tag);
599 g_critical ("Failed to parse type: '%s'", type);
605 start_glib_boxed (GMarkupParseContext *context,
606 const gchar *element_name,
607 const gchar **attribute_names,
608 const gchar **attribute_values,
613 const gchar *typename;
614 const gchar *typeinit;
615 const gchar *deprecated;
618 if (!(strcmp (element_name, "glib:boxed") == 0 &&
619 ctx->state == STATE_NAMESPACE))
622 name = find_attribute ("glib:name", attribute_names, attribute_values);
623 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
624 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
625 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
629 MISSING_ATTRIBUTE (context, error, element_name, "glib:name");
632 else if (typename == NULL)
634 MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
637 else if (typeinit == NULL)
639 MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
643 boxed = (GIrNodeBoxed *) g_ir_node_new (G_IR_NODE_BOXED);
645 ((GIrNode *)boxed)->name = g_strdup (name);
646 boxed->gtype_name = g_strdup (typename);
647 boxed->gtype_init = g_strdup (typeinit);
648 if (deprecated && strcmp (deprecated, "1") == 0)
649 boxed->deprecated = TRUE;
651 boxed->deprecated = FALSE;
653 ctx->current_node = (GIrNode *)boxed;
654 ctx->current_module->entries =
655 g_list_append (ctx->current_module->entries, boxed);
657 state_switch (ctx, STATE_BOXED);
663 start_function (GMarkupParseContext *context,
664 const gchar *element_name,
665 const gchar **attribute_names,
666 const gchar **attribute_values,
672 const gchar *deprecated;
673 GIrNodeFunction *function;
674 gboolean found = FALSE;
678 case STATE_NAMESPACE:
679 found = (strcmp (element_name, "function") == 0 ||
680 strcmp (element_name, "callback") == 0);
686 found = strcmp (element_name, "constructor") == 0;
688 case STATE_INTERFACE:
690 strcmp (element_name, "method") == 0 ||
691 strcmp (element_name, "callback") == 0);
700 name = find_attribute ("name", attribute_names, attribute_values);
701 symbol = find_attribute ("c:identifier", attribute_names, attribute_values);
702 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
706 MISSING_ATTRIBUTE (context, error, element_name, "name");
709 else if (strcmp (element_name, "callback") != 0 && symbol == NULL)
711 MISSING_ATTRIBUTE (context, error, element_name, "c:identifier");
715 function = (GIrNodeFunction *) g_ir_node_new (G_IR_NODE_FUNCTION);
717 ((GIrNode *)function)->name = g_strdup (name);
718 function->symbol = g_strdup (symbol);
719 function->parameters = NULL;
720 if (deprecated && strcmp (deprecated, "1") == 0)
721 function->deprecated = TRUE;
723 function->deprecated = FALSE;
725 if (strcmp (element_name, "method") == 0 ||
726 strcmp (element_name, "constructor") == 0)
728 function->is_method = TRUE;
730 if (strcmp (element_name, "constructor") == 0)
731 function->is_constructor = TRUE;
733 function->is_constructor = FALSE;
737 function->is_method = FALSE;
738 function->is_setter = FALSE;
739 function->is_getter = FALSE;
740 function->is_constructor = FALSE;
741 if (strcmp (element_name, "callback") == 0)
742 ((GIrNode *)function)->type = G_IR_NODE_CALLBACK;
745 if (ctx->current_node == NULL)
747 ctx->current_module->entries =
748 g_list_append (ctx->current_module->entries, function);
751 switch (ctx->current_node->type)
753 case G_IR_NODE_INTERFACE:
754 case G_IR_NODE_OBJECT:
756 GIrNodeInterface *iface;
758 iface = (GIrNodeInterface *)ctx->current_node;
759 iface->members = g_list_append (iface->members, function);
762 case G_IR_NODE_BOXED:
766 boxed = (GIrNodeBoxed *)ctx->current_node;
767 boxed->members = g_list_append (boxed->members, function);
770 case G_IR_NODE_STRUCT:
772 GIrNodeStruct *struct_;
774 struct_ = (GIrNodeStruct *)ctx->current_node;
775 struct_->members = g_list_append (struct_->members, function); }
777 case G_IR_NODE_UNION:
779 GIrNodeUnion *union_;
781 union_ = (GIrNodeUnion *)ctx->current_node;
782 union_->members = g_list_append (union_->members, function);
786 g_assert_not_reached ();
789 ctx->current_node = (GIrNode *)function;
790 state_switch (ctx, STATE_FUNCTION);
796 start_parameter (GMarkupParseContext *context,
797 const gchar *element_name,
798 const gchar **attribute_names,
799 const gchar **attribute_values,
804 const gchar *direction;
807 const gchar *optional;
809 const gchar *transfer;
812 if (!(strcmp (element_name, "parameter") == 0 &&
813 ctx->state == STATE_FUNCTION_PARAMETERS))
816 name = find_attribute ("name", attribute_names, attribute_values);
817 direction = find_attribute ("direction", attribute_names, attribute_values);
818 retval = find_attribute ("retval", attribute_names, attribute_values);
819 dipper = find_attribute ("dipper", attribute_names, attribute_values);
820 optional = find_attribute ("optional", attribute_names, attribute_values);
821 nullok = find_attribute ("null-ok", attribute_names, attribute_values);
822 transfer = find_attribute ("transfer", attribute_names, attribute_values);
827 param = (GIrNodeParam *)g_ir_node_new (G_IR_NODE_PARAM);
829 ctx->current_typed = (GIrNode*) param;
830 ctx->current_typed->name = g_strdup (name);
832 state_switch (ctx, STATE_FUNCTION_PARAMETER);
834 if (direction && strcmp (direction, "out") == 0)
839 else if (direction && strcmp (direction, "inout") == 0)
850 if (retval && strcmp (retval, "1") == 0)
851 param->retval = TRUE;
853 param->retval = FALSE;
855 if (dipper && strcmp (dipper, "1") == 0)
856 param->dipper = TRUE;
858 param->dipper = FALSE;
860 if (optional && strcmp (optional, "1") == 0)
861 param->optional = TRUE;
863 param->optional = FALSE;
865 if (nullok && strcmp (nullok, "1") == 0)
866 param->null_ok = TRUE;
868 param->null_ok = FALSE;
870 if (transfer && strcmp (transfer, "none") == 0)
872 param->transfer = FALSE;
873 param->shallow_transfer = FALSE;
875 else if (transfer && strcmp (transfer, "shallow") == 0)
877 param->transfer = FALSE;
878 param->shallow_transfer = TRUE;
884 if (strcmp (transfer, "full") != 0)
885 g_warning ("Unknown transfer %s", transfer);
887 param->transfer = TRUE;
889 else if (param->in && !param->out)
890 param->transfer = FALSE;
892 param->transfer = TRUE;
893 param->shallow_transfer = FALSE;
896 ((GIrNode *)param)->name = g_strdup (name);
898 switch (ctx->current_node->type)
900 case G_IR_NODE_FUNCTION:
901 case G_IR_NODE_CALLBACK:
903 GIrNodeFunction *func;
905 func = (GIrNodeFunction *)ctx->current_node;
906 func->parameters = g_list_append (func->parameters, param);
909 case G_IR_NODE_SIGNAL:
911 GIrNodeSignal *signal;
913 signal = (GIrNodeSignal *)ctx->current_node;
914 signal->parameters = g_list_append (signal->parameters, param);
917 case G_IR_NODE_VFUNC:
921 vfunc = (GIrNodeVFunc *)ctx->current_node;
922 vfunc->parameters = g_list_append (vfunc->parameters, param);
926 g_assert_not_reached ();
933 start_field (GMarkupParseContext *context,
934 const gchar *element_name,
935 const gchar **attribute_names,
936 const gchar **attribute_values,
941 const gchar *readable;
942 const gchar *writable;
954 case STATE_INTERFACE:
960 if (strcmp (element_name, "field") != 0)
963 name = find_attribute ("name", attribute_names, attribute_values);
964 readable = find_attribute ("readable", attribute_names, attribute_values);
965 writable = find_attribute ("writable", attribute_names, attribute_values);
966 bits = find_attribute ("bits", attribute_names, attribute_values);
967 branch = find_attribute ("branch", attribute_names, attribute_values);
968 offset = find_attribute ("offset", attribute_names, attribute_values);
972 MISSING_ATTRIBUTE (context, error, element_name, "name");
976 field = (GIrNodeField *)g_ir_node_new (G_IR_NODE_FIELD);
977 ctx->current_typed = (GIrNode*) field;
978 ((GIrNode *)field)->name = g_strdup (name);
979 if (readable && strcmp (readable, "1") == 0)
980 field->readable = TRUE;
982 field->readable = FALSE;
984 if (writable && strcmp (writable, "1") == 0)
985 field->writable = TRUE;
987 field->writable = FALSE;
990 field->bits = atoi (bits);
995 field->offset = atoi (offset);
999 switch (ctx->current_node->type)
1001 case G_IR_NODE_OBJECT:
1003 GIrNodeInterface *iface;
1005 iface = (GIrNodeInterface *)ctx->current_node;
1006 iface->members = g_list_append (iface->members, field);
1007 state_switch (ctx, STATE_CLASS_FIELD);
1010 case G_IR_NODE_INTERFACE:
1012 GIrNodeInterface *iface;
1014 iface = (GIrNodeInterface *)ctx->current_node;
1015 iface->members = g_list_append (iface->members, field);
1016 state_switch (ctx, STATE_INTERFACE_FIELD);
1019 case G_IR_NODE_BOXED:
1021 GIrNodeBoxed *boxed;
1023 boxed = (GIrNodeBoxed *)ctx->current_node;
1024 boxed->members = g_list_append (boxed->members, field);
1025 state_switch (ctx, STATE_BOXED_FIELD);
1028 case G_IR_NODE_STRUCT:
1030 GIrNodeStruct *struct_;
1032 struct_ = (GIrNodeStruct *)ctx->current_node;
1033 struct_->members = g_list_append (struct_->members, field);
1034 state_switch (ctx, STATE_STRUCT_FIELD);
1037 case G_IR_NODE_UNION:
1039 GIrNodeUnion *union_;
1041 union_ = (GIrNodeUnion *)ctx->current_node;
1042 union_->members = g_list_append (union_->members, field);
1045 GIrNodeConstant *constant;
1047 constant = (GIrNodeConstant *) g_ir_node_new (G_IR_NODE_CONSTANT);
1048 ((GIrNode *)constant)->name = g_strdup (name);
1049 constant->value = g_strdup (branch);
1050 constant->type = union_->discriminator_type;
1051 constant->deprecated = FALSE;
1053 union_->discriminators = g_list_append (union_->discriminators, constant);
1055 state_switch (ctx, STATE_UNION_FIELD);
1059 g_assert_not_reached ();
1066 start_alias (GMarkupParseContext *context,
1067 const gchar *element_name,
1068 const gchar **attribute_names,
1069 const gchar **attribute_values,
1074 const gchar *target;
1079 name = find_attribute ("name", attribute_names, attribute_values);
1082 MISSING_ATTRIBUTE (context, error, element_name, "name");
1086 target = find_attribute ("target", attribute_names, attribute_values);
1089 MISSING_ATTRIBUTE (context, error, element_name, "target");
1093 value = g_strdup (target);
1094 if (ctx->prefix_aliases)
1096 key = g_strdup_printf ("%s.%s", ctx->namespace, name);
1097 if (!strchr (target, '.'))
1099 const BasicTypeInfo *basic = parse_basic (target);
1103 /* For non-basic types, re-qualify the interface */
1104 value = g_strdup_printf ("%s.%s", ctx->namespace, target);
1110 key = g_strdup (name);
1113 g_hash_table_insert (ctx->aliases, key, value);
1119 start_enum (GMarkupParseContext *context,
1120 const gchar *element_name,
1121 const gchar **attribute_names,
1122 const gchar **attribute_values,
1126 if ((strcmp (element_name, "enumeration") == 0 && ctx->state == STATE_NAMESPACE) ||
1127 (strcmp (element_name, "bitfield") == 0 && ctx->state == STATE_NAMESPACE))
1130 const gchar *typename;
1131 const gchar *typeinit;
1132 const gchar *deprecated;
1134 name = find_attribute ("name", attribute_names, attribute_values);
1135 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
1136 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
1137 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1140 MISSING_ATTRIBUTE (context, error, element_name, "name");
1145 if (strcmp (element_name, "enumeration") == 0)
1146 enum_ = (GIrNodeEnum *) g_ir_node_new (G_IR_NODE_ENUM);
1148 enum_ = (GIrNodeEnum *) g_ir_node_new (G_IR_NODE_FLAGS);
1149 ((GIrNode *)enum_)->name = g_strdup (name);
1150 enum_->gtype_name = g_strdup (typename);
1151 enum_->gtype_init = g_strdup (typeinit);
1152 if (deprecated && strcmp (deprecated, "1") == 0)
1153 enum_->deprecated = TRUE;
1155 enum_->deprecated = FALSE;
1157 ctx->current_node = (GIrNode *) enum_;
1158 ctx->current_module->entries =
1159 g_list_append (ctx->current_module->entries, enum_);
1161 state_switch (ctx, STATE_ENUM);
1170 start_property (GMarkupParseContext *context,
1171 const gchar *element_name,
1172 const gchar **attribute_names,
1173 const gchar **attribute_values,
1177 if (strcmp (element_name, "property") == 0 &&
1178 (ctx->state == STATE_CLASS ||
1179 ctx->state == STATE_INTERFACE))
1182 const gchar *readable;
1183 const gchar *writable;
1184 const gchar *construct;
1185 const gchar *construct_only;
1187 name = find_attribute ("name", attribute_names, attribute_values);
1188 readable = find_attribute ("readable", attribute_names, attribute_values);
1189 writable = find_attribute ("writable", attribute_names, attribute_values);
1190 construct = find_attribute ("construct", attribute_names, attribute_values);
1191 construct_only = find_attribute ("construct-only", attribute_names, attribute_values);
1194 MISSING_ATTRIBUTE (context, error, element_name, "name");
1197 GIrNodeProperty *property;
1198 GIrNodeInterface *iface;
1200 property = (GIrNodeProperty *) g_ir_node_new (G_IR_NODE_PROPERTY);
1201 ctx->current_typed = (GIrNode*) property;
1203 ((GIrNode *)property)->name = g_strdup (name);
1205 if (readable && strcmp (readable, "1") == 0)
1206 property->readable = TRUE;
1208 property->readable = FALSE;
1209 if (writable && strcmp (writable, "1") == 0)
1210 property->writable = TRUE;
1212 property->writable = FALSE;
1213 if (construct && strcmp (construct, "1") == 0)
1214 property->construct = TRUE;
1216 property->construct = FALSE;
1217 if (construct_only && strcmp (construct_only, "1") == 0)
1218 property->construct_only = TRUE;
1220 property->construct_only = FALSE;
1222 iface = (GIrNodeInterface *)ctx->current_node;
1223 iface->members = g_list_append (iface->members, property);
1225 if (ctx->state == STATE_CLASS)
1226 state_switch (ctx, STATE_CLASS_PROPERTY);
1227 else if (ctx->state == STATE_INTERFACE)
1228 state_switch (ctx, STATE_INTERFACE_PROPERTY);
1230 g_assert_not_reached ();
1239 parse_value (const gchar *str)
1243 /* FIXME just a quick hack */
1244 shift_op = strstr (str, "<<");
1250 base = strtol (str, NULL, 10);
1251 shift = strtol (shift_op + 3, NULL, 10);
1253 return base << shift;
1256 return strtol (str, NULL, 10);
1262 start_member (GMarkupParseContext *context,
1263 const gchar *element_name,
1264 const gchar **attribute_names,
1265 const gchar **attribute_values,
1269 if (strcmp (element_name, "member") == 0 &&
1270 ctx->state == STATE_ENUM)
1274 const gchar *deprecated;
1276 name = find_attribute ("name", attribute_names, attribute_values);
1277 value = find_attribute ("value", attribute_names, attribute_values);
1278 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1281 MISSING_ATTRIBUTE (context, error, element_name, "name");
1285 GIrNodeValue *value_;
1287 value_ = (GIrNodeValue *) g_ir_node_new (G_IR_NODE_VALUE);
1289 ((GIrNode *)value_)->name = g_strdup (name);
1291 value_->value = parse_value (value);
1293 if (deprecated && strcmp (deprecated, "1") == 0)
1294 value_->deprecated = TRUE;
1296 value_->deprecated = FALSE;
1298 enum_ = (GIrNodeEnum *)ctx->current_node;
1299 enum_->values = g_list_append (enum_->values, value_);
1308 start_constant (GMarkupParseContext *context,
1309 const gchar *element_name,
1310 const gchar **attribute_names,
1311 const gchar **attribute_values,
1315 if (strcmp (element_name, "constant") == 0 &&
1316 (ctx->state == STATE_NAMESPACE ||
1317 ctx->state == STATE_CLASS ||
1318 ctx->state == STATE_INTERFACE))
1322 const gchar *deprecated;
1324 name = find_attribute ("name", attribute_names, attribute_values);
1325 value = find_attribute ("value", attribute_names, attribute_values);
1326 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1329 MISSING_ATTRIBUTE (context, error, element_name, "name");
1330 else if (value == NULL)
1331 MISSING_ATTRIBUTE (context, error, element_name, "value");
1334 GIrNodeConstant *constant;
1336 constant = (GIrNodeConstant *) g_ir_node_new (G_IR_NODE_CONSTANT);
1338 ((GIrNode *)constant)->name = g_strdup (name);
1339 constant->value = g_strdup (value);
1341 ctx->current_typed = (GIrNode*) constant;
1343 if (deprecated && strcmp (deprecated, "1") == 0)
1344 constant->deprecated = TRUE;
1346 constant->deprecated = FALSE;
1348 if (ctx->state == STATE_NAMESPACE)
1350 ctx->current_node = (GIrNode *) constant;
1351 ctx->current_module->entries =
1352 g_list_append (ctx->current_module->entries, constant);
1356 GIrNodeInterface *iface;
1358 iface = (GIrNodeInterface *)ctx->current_node;
1359 iface->members = g_list_append (iface->members, constant);
1364 case STATE_NAMESPACE:
1365 state_switch (ctx, STATE_NAMESPACE_CONSTANT);
1368 state_switch (ctx, STATE_CLASS_CONSTANT);
1370 case STATE_INTERFACE:
1371 state_switch (ctx, STATE_INTERFACE_CONSTANT);
1374 g_assert_not_reached ();
1385 start_errordomain (GMarkupParseContext *context,
1386 const gchar *element_name,
1387 const gchar **attribute_names,
1388 const gchar **attribute_values,
1392 if (strcmp (element_name, "errordomain") == 0 &&
1393 ctx->state == STATE_NAMESPACE)
1396 const gchar *getquark;
1398 const gchar *deprecated;
1400 name = find_attribute ("name", attribute_names, attribute_values);
1401 getquark = find_attribute ("get-quark", attribute_names, attribute_values);
1402 codes = find_attribute ("codes", attribute_names, attribute_values);
1403 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1406 MISSING_ATTRIBUTE (context, error, element_name, "name");
1407 else if (getquark == NULL)
1408 MISSING_ATTRIBUTE (context, error, element_name, "getquark");
1409 else if (codes == NULL)
1410 MISSING_ATTRIBUTE (context, error, element_name, "codes");
1413 GIrNodeErrorDomain *domain;
1415 domain = (GIrNodeErrorDomain *) g_ir_node_new (G_IR_NODE_ERROR_DOMAIN);
1417 ((GIrNode *)domain)->name = g_strdup (name);
1418 domain->getquark = g_strdup (getquark);
1419 domain->codes = g_strdup (codes);
1421 if (deprecated && strcmp (deprecated, "1") == 0)
1422 domain->deprecated = TRUE;
1424 domain->deprecated = FALSE;
1426 ctx->current_node = (GIrNode *) domain;
1427 ctx->current_module->entries =
1428 g_list_append (ctx->current_module->entries, domain);
1430 state_switch (ctx, STATE_ERRORDOMAIN);
1439 start_interface (GMarkupParseContext *context,
1440 const gchar *element_name,
1441 const gchar **attribute_names,
1442 const gchar **attribute_values,
1446 if (strcmp (element_name, "interface") == 0 &&
1447 ctx->state == STATE_NAMESPACE)
1450 const gchar *typename;
1451 const gchar *typeinit;
1452 const gchar *deprecated;
1454 name = find_attribute ("name", attribute_names, attribute_values);
1455 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
1456 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
1457 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1460 MISSING_ATTRIBUTE (context, error, element_name, "name");
1461 else if (typename == NULL)
1462 MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
1463 else if (typeinit == NULL)
1464 MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
1467 GIrNodeInterface *iface;
1469 iface = (GIrNodeInterface *) g_ir_node_new (G_IR_NODE_INTERFACE);
1470 ((GIrNode *)iface)->name = g_strdup (name);
1471 iface->gtype_name = g_strdup (typename);
1472 iface->gtype_init = g_strdup (typeinit);
1473 if (deprecated && strcmp (deprecated, "1") == 0)
1474 iface->deprecated = TRUE;
1476 iface->deprecated = FALSE;
1478 ctx->current_node = (GIrNode *) iface;
1479 ctx->current_module->entries =
1480 g_list_append (ctx->current_module->entries, iface);
1482 state_switch (ctx, STATE_INTERFACE);
1492 start_class (GMarkupParseContext *context,
1493 const gchar *element_name,
1494 const gchar **attribute_names,
1495 const gchar **attribute_values,
1499 if (strcmp (element_name, "class") == 0 &&
1500 ctx->state == STATE_NAMESPACE)
1503 const gchar *parent;
1504 const gchar *typename;
1505 const gchar *typeinit;
1506 const gchar *deprecated;
1508 name = find_attribute ("name", attribute_names, attribute_values);
1509 parent = find_attribute ("parent", attribute_names, attribute_values);
1510 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
1511 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
1512 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1515 MISSING_ATTRIBUTE (context, error, element_name, "name");
1516 else if (typename == NULL)
1517 MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
1518 else if (typeinit == NULL && strcmp (typename, "GObject"))
1519 MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
1522 GIrNodeInterface *iface;
1524 iface = (GIrNodeInterface *) g_ir_node_new (G_IR_NODE_OBJECT);
1525 ((GIrNode *)iface)->name = g_strdup (name);
1526 iface->gtype_name = g_strdup (typename);
1527 iface->gtype_init = g_strdup (typeinit);
1528 iface->parent = g_strdup (parent);
1529 if (deprecated && strcmp (deprecated, "1") == 0)
1530 iface->deprecated = TRUE;
1532 iface->deprecated = FALSE;
1534 ctx->current_node = (GIrNode *) iface;
1535 ctx->current_module->entries =
1536 g_list_append (ctx->current_module->entries, iface);
1538 state_switch (ctx, STATE_CLASS);
1547 start_type (GMarkupParseContext *context,
1548 const gchar *element_name,
1549 const gchar **attribute_names,
1550 const gchar **attribute_values,
1556 if (strcmp (element_name, "type") != 0)
1559 if (ctx->state == STATE_TYPE)
1561 else if (ctx->state == STATE_FUNCTION_PARAMETER ||
1562 ctx->state == STATE_FUNCTION_RETURN ||
1563 ctx->state == STATE_STRUCT_FIELD ||
1564 ctx->state == STATE_UNION_FIELD ||
1565 ctx->state == STATE_CLASS_PROPERTY ||
1566 ctx->state == STATE_CLASS_FIELD ||
1567 ctx->state == STATE_INTERFACE_FIELD ||
1568 ctx->state == STATE_INTERFACE_PROPERTY ||
1569 ctx->state == STATE_BOXED_FIELD ||
1570 ctx->state == STATE_NAMESPACE_CONSTANT ||
1571 ctx->state == STATE_CLASS_CONSTANT ||
1572 ctx->state == STATE_INTERFACE_CONSTANT
1575 state_switch (ctx, STATE_TYPE);
1576 ctx->type_depth = 1;
1579 /* FIXME handle recursive types */
1580 if (ctx->type_depth > 1)
1583 if (!ctx->current_typed)
1587 G_MARKUP_ERROR_INVALID_CONTENT,
1588 "The element <type> is invalid here");
1592 name = find_attribute ("name", attribute_names, attribute_values);
1595 MISSING_ATTRIBUTE (context, error, element_name, "name");
1597 switch (ctx->current_typed->type)
1599 case G_IR_NODE_PARAM:
1601 GIrNodeParam *param = (GIrNodeParam *)ctx->current_typed;
1602 param->type = parse_type (ctx, name);
1605 case G_IR_NODE_FIELD:
1607 GIrNodeField *field = (GIrNodeField *)ctx->current_typed;
1608 field->type = parse_type (ctx, name);
1611 case G_IR_NODE_PROPERTY:
1613 GIrNodeProperty *property = (GIrNodeProperty *) ctx->current_typed;
1614 property->type = parse_type (ctx, name);
1617 case G_IR_NODE_CONSTANT:
1619 GIrNodeConstant *constant = (GIrNodeConstant *)ctx->current_typed;
1620 constant->type = parse_type (ctx, name);
1624 g_printerr("current node is %d\n", ctx->current_node->type);
1625 g_assert_not_reached ();
1628 ctx->current_typed = NULL;
1633 start_return_value (GMarkupParseContext *context,
1634 const gchar *element_name,
1635 const gchar **attribute_names,
1636 const gchar **attribute_values,
1640 if (strcmp (element_name, "return-value") == 0 &&
1641 ctx->state == STATE_FUNCTION)
1643 GIrNodeParam *param;
1645 param = (GIrNodeParam *)g_ir_node_new (G_IR_NODE_PARAM);
1648 param->retval = TRUE;
1650 ctx->current_typed = (GIrNode*) param;
1652 state_switch (ctx, STATE_FUNCTION_RETURN);
1654 switch (ctx->current_node->type)
1656 case G_IR_NODE_FUNCTION:
1657 case G_IR_NODE_CALLBACK:
1659 GIrNodeFunction *func = (GIrNodeFunction *)ctx->current_node;
1660 func->result = param;
1663 case G_IR_NODE_SIGNAL:
1665 GIrNodeSignal *signal = (GIrNodeSignal *)ctx->current_node;
1666 signal->result = param;
1669 case G_IR_NODE_VFUNC:
1671 GIrNodeVFunc *vfunc = (GIrNodeVFunc *)ctx->current_node;
1672 vfunc->result = param;
1676 g_assert_not_reached ();
1686 start_implements (GMarkupParseContext *context,
1687 const gchar *element_name,
1688 const gchar **attribute_names,
1689 const gchar **attribute_values,
1693 GIrNodeInterface *iface;
1696 if (strcmp (element_name, "implements") != 0 ||
1697 !(ctx->state == STATE_CLASS))
1700 state_switch (ctx, STATE_IMPLEMENTS);
1702 name = find_attribute ("name", attribute_names, attribute_values);
1705 MISSING_ATTRIBUTE (context, error, element_name, "name");
1709 iface = (GIrNodeInterface *)ctx->current_node;
1710 iface->interfaces = g_list_append (iface->interfaces, g_strdup (name));
1716 start_glib_signal (GMarkupParseContext *context,
1717 const gchar *element_name,
1718 const gchar **attribute_names,
1719 const gchar **attribute_values,
1723 if (strcmp (element_name, "glib:signal") == 0 &&
1724 (ctx->state == STATE_CLASS ||
1725 ctx->state == STATE_INTERFACE))
1729 const gchar *no_recurse;
1730 const gchar *detailed;
1731 const gchar *action;
1732 const gchar *no_hooks;
1733 const gchar *has_class_closure;
1735 name = find_attribute ("name", attribute_names, attribute_values);
1736 when = find_attribute ("when", attribute_names, attribute_values);
1737 no_recurse = find_attribute ("no-recurse", attribute_names, attribute_values);
1738 detailed = find_attribute ("detailed", attribute_names, attribute_values);
1739 action = find_attribute ("action", attribute_names, attribute_values);
1740 no_hooks = find_attribute ("no-hooks", attribute_names, attribute_values);
1741 has_class_closure = find_attribute ("has-class-closure", attribute_names, attribute_values);
1744 MISSING_ATTRIBUTE (context, error, element_name, "name");
1747 GIrNodeInterface *iface;
1748 GIrNodeSignal *signal;
1750 signal = (GIrNodeSignal *)g_ir_node_new (G_IR_NODE_SIGNAL);
1752 ((GIrNode *)signal)->name = g_strdup (name);
1754 signal->run_first = FALSE;
1755 signal->run_last = FALSE;
1756 signal->run_cleanup = FALSE;
1757 if (when == NULL || strcmp (when, "LAST") == 0)
1758 signal->run_last = TRUE;
1759 else if (strcmp (when, "FIRST") == 0)
1760 signal->run_first = TRUE;
1762 signal->run_cleanup = TRUE;
1764 if (no_recurse && strcmp (no_recurse, "1") == 0)
1765 signal->no_recurse = TRUE;
1767 signal->no_recurse = FALSE;
1768 if (detailed && strcmp (detailed, "1") == 0)
1769 signal->detailed = TRUE;
1771 signal->detailed = FALSE;
1772 if (action && strcmp (action, "1") == 0)
1773 signal->action = TRUE;
1775 signal->action = FALSE;
1776 if (no_hooks && strcmp (no_hooks, "1") == 0)
1777 signal->no_hooks = TRUE;
1779 signal->no_hooks = FALSE;
1780 if (has_class_closure && strcmp (has_class_closure, "1") == 0)
1781 signal->has_class_closure = TRUE;
1783 signal->has_class_closure = FALSE;
1785 iface = (GIrNodeInterface *)ctx->current_node;
1786 iface->members = g_list_append (iface->members, signal);
1788 ctx->current_node = (GIrNode *)signal;
1789 state_switch (ctx, STATE_FUNCTION);
1798 start_vfunc (GMarkupParseContext *context,
1799 const gchar *element_name,
1800 const gchar **attribute_names,
1801 const gchar **attribute_values,
1805 if (strcmp (element_name, "vfunc") == 0 &&
1806 (ctx->state == STATE_CLASS ||
1807 ctx->state == STATE_INTERFACE))
1810 const gchar *must_chain_up;
1811 const gchar *override;
1812 const gchar *is_class_closure;
1813 const gchar *offset;
1815 name = find_attribute ("name", attribute_names, attribute_values);
1816 must_chain_up = find_attribute ("must-chain-up", attribute_names, attribute_values);
1817 override = find_attribute ("override", attribute_names, attribute_values);
1818 is_class_closure = find_attribute ("is-class-closure", attribute_names, attribute_values);
1819 offset = find_attribute ("offset", attribute_names, attribute_values);
1822 MISSING_ATTRIBUTE (context, error, element_name, "name");
1825 GIrNodeInterface *iface;
1826 GIrNodeVFunc *vfunc;
1828 vfunc = (GIrNodeVFunc *)g_ir_node_new (G_IR_NODE_VFUNC);
1830 ((GIrNode *)vfunc)->name = g_strdup (name);
1832 if (must_chain_up && strcmp (must_chain_up, "1") == 0)
1833 vfunc->must_chain_up = TRUE;
1835 vfunc->must_chain_up = FALSE;
1837 if (override && strcmp (override, "always") == 0)
1839 vfunc->must_be_implemented = TRUE;
1840 vfunc->must_not_be_implemented = FALSE;
1842 else if (override && strcmp (override, "never") == 0)
1844 vfunc->must_be_implemented = FALSE;
1845 vfunc->must_not_be_implemented = TRUE;
1849 vfunc->must_be_implemented = FALSE;
1850 vfunc->must_not_be_implemented = FALSE;
1853 if (is_class_closure && strcmp (is_class_closure, "1") == 0)
1854 vfunc->is_class_closure = TRUE;
1856 vfunc->is_class_closure = FALSE;
1859 vfunc->offset = atoi (offset);
1863 iface = (GIrNodeInterface *)ctx->current_node;
1864 iface->members = g_list_append (iface->members, vfunc);
1866 ctx->current_node = (GIrNode *)vfunc;
1867 state_switch (ctx, STATE_FUNCTION);
1877 start_struct (GMarkupParseContext *context,
1878 const gchar *element_name,
1879 const gchar **attribute_names,
1880 const gchar **attribute_values,
1884 if (strcmp (element_name, "record") == 0 &&
1885 ctx->state == STATE_NAMESPACE)
1888 const gchar *deprecated;
1890 name = find_attribute ("name", attribute_names, attribute_values);
1891 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1894 MISSING_ATTRIBUTE (context, error, element_name, "name");
1897 GIrNodeStruct *struct_;
1899 struct_ = (GIrNodeStruct *) g_ir_node_new (G_IR_NODE_STRUCT);
1901 ((GIrNode *)struct_)->name = g_strdup (name);
1902 if (deprecated && strcmp (deprecated, "1") == 0)
1903 struct_->deprecated = TRUE;
1905 struct_->deprecated = FALSE;
1907 ctx->current_node = (GIrNode *)struct_;
1908 ctx->current_module->entries =
1909 g_list_append (ctx->current_module->entries, struct_);
1911 state_switch (ctx, STATE_STRUCT);
1920 start_union (GMarkupParseContext *context,
1921 const gchar *element_name,
1922 const gchar **attribute_names,
1923 const gchar **attribute_values,
1927 if (strcmp (element_name, "union") == 0 &&
1928 ctx->state == STATE_NAMESPACE)
1931 const gchar *deprecated;
1932 const gchar *typename;
1933 const gchar *typeinit;
1935 name = find_attribute ("name", attribute_names, attribute_values);
1936 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1937 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
1938 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
1941 MISSING_ATTRIBUTE (context, error, element_name, "name");
1944 GIrNodeUnion *union_;
1946 union_ = (GIrNodeUnion *) g_ir_node_new (G_IR_NODE_UNION);
1948 ((GIrNode *)union_)->name = g_strdup (name);
1949 union_->gtype_name = g_strdup (typename);
1950 union_->gtype_init = g_strdup (typeinit);
1951 if (deprecated && strcmp (deprecated, "1") == 0)
1952 union_->deprecated = TRUE;
1954 union_->deprecated = FALSE;
1956 ctx->current_node = (GIrNode *)union_;
1957 ctx->current_module->entries =
1958 g_list_append (ctx->current_module->entries, union_);
1960 state_switch (ctx, STATE_UNION);
1968 start_discriminator (GMarkupParseContext *context,
1969 const gchar *element_name,
1970 const gchar **attribute_names,
1971 const gchar **attribute_values,
1975 if (strcmp (element_name, "discriminator") == 0 &&
1976 ctx->state == STATE_UNION)
1979 const gchar *offset;
1981 type = find_attribute ("type", attribute_names, attribute_values);
1982 offset = find_attribute ("offset", attribute_names, attribute_values);
1984 MISSING_ATTRIBUTE (context, error, element_name, "type");
1985 else if (offset == NULL)
1986 MISSING_ATTRIBUTE (context, error, element_name, "offset");
1988 ((GIrNodeUnion *)ctx->current_node)->discriminator_type
1989 = parse_type (ctx, type);
1990 ((GIrNodeUnion *)ctx->current_node)->discriminator_offset
2001 parse_include (GMarkupParseContext *context,
2006 ParseContext sub_ctx = { 0 };
2007 GMarkupParseContext *sub_context;
2012 girpath = locate_gir (name, ctx->includes);
2014 if (girpath == NULL)
2018 G_MARKUP_ERROR_INVALID_CONTENT,
2019 "Could not find GIR file '%s'; check XDG_DATA_DIRS or use --includedir",
2024 g_debug ("Parsing include %s", girpath);
2026 if (!g_file_get_contents (girpath, &buffer, &length, error))
2033 sub_ctx.state = STATE_START;
2034 sub_ctx.includes = ctx->includes;
2035 sub_ctx.prefix_aliases = TRUE;
2036 sub_ctx.namespace = name;
2037 sub_ctx.aliases = ctx->aliases;
2038 sub_ctx.type_depth = 0;
2040 context = g_markup_parse_context_new (&firstpass_parser, 0, &sub_ctx, NULL);
2042 if (!g_markup_parse_context_parse (context, buffer, length, error))
2048 if (!g_markup_parse_context_end_parse (context, error))
2054 g_markup_parse_context_free (context);
2058 extern GLogLevelFlags logged_levels;
2061 start_element_handler (GMarkupParseContext *context,
2062 const gchar *element_name,
2063 const gchar **attribute_names,
2064 const gchar **attribute_values,
2068 ParseContext *ctx = user_data;
2069 gint line_number, char_number;
2071 if (logged_levels & G_LOG_LEVEL_DEBUG)
2073 GString *tags = g_string_new ("");
2075 for (i = 0; attribute_names[i]; i++)
2076 g_string_append_printf (tags, "%s=\"%s\" ",
2078 attribute_values[i]);
2082 g_string_insert_c (tags, 0, ' ');
2083 g_string_truncate (tags, tags->len - 1);
2085 g_debug ("<%s%s>", element_name, tags->str);
2086 g_string_free (tags, TRUE);
2089 switch (element_name[0])
2092 if (ctx->state == STATE_NAMESPACE && strcmp (element_name, "alias") == 0)
2094 state_switch (ctx, STATE_ALIAS);
2099 if (start_enum (context, element_name,
2100 attribute_names, attribute_values,
2105 if (start_function (context, element_name,
2106 attribute_names, attribute_values,
2109 else if (start_constant (context, element_name,
2110 attribute_names, attribute_values,
2113 else if (start_class (context, element_name,
2114 attribute_names, attribute_values,
2117 else if (strcmp (element_name, "class") == 0 &&
2118 ctx->state == STATE_REQUIRES)
2122 name = find_attribute ("name", attribute_names, attribute_values);
2125 MISSING_ATTRIBUTE (context, error, element_name, "name");
2128 GIrNodeInterface *iface;
2130 iface = (GIrNodeInterface *)ctx->current_node;
2131 iface ->prerequisites = g_list_append (iface->prerequisites, g_strdup (name));
2139 if (start_discriminator (context, element_name,
2140 attribute_names, attribute_values,
2146 if (start_enum (context, element_name,
2147 attribute_names, attribute_values,
2150 else if (start_errordomain (context, element_name,
2151 attribute_names, attribute_values,
2157 if (start_function (context, element_name,
2158 attribute_names, attribute_values,
2161 else if (start_field (context, element_name,
2162 attribute_names, attribute_values,
2168 if (start_glib_boxed (context, element_name,
2169 attribute_names, attribute_values,
2172 else if (start_glib_signal (context, element_name,
2173 attribute_names, attribute_values,
2179 if (strcmp (element_name, "include") == 0 &&
2180 ctx->state == STATE_REPOSITORY)
2184 name = find_attribute ("name", attribute_names, attribute_values);
2188 MISSING_ATTRIBUTE (context, error, element_name, "name");
2192 if (!parse_include (context, ctx, name, error))
2195 ctx->dependencies = g_list_prepend (ctx->dependencies, g_strdup (name));
2198 state_switch (ctx, STATE_INCLUDE);
2201 if (start_interface (context, element_name,
2202 attribute_names, attribute_values,
2205 else if (start_implements (context, element_name,
2206 attribute_names, attribute_values,
2212 if (start_function (context, element_name,
2213 attribute_names, attribute_values,
2216 else if (start_member (context, element_name,
2217 attribute_names, attribute_values,
2223 if (strcmp (element_name, "namespace") == 0 && ctx->state == STATE_REPOSITORY)
2225 const gchar *name, *shared_library;
2227 name = find_attribute ("name", attribute_names, attribute_values);
2228 shared_library = find_attribute ("shared-library", attribute_names, attribute_values);
2231 MISSING_ATTRIBUTE (context, error, element_name, "name");
2234 ctx->current_module = g_ir_module_new (name, shared_library);
2235 ctx->modules = g_list_append (ctx->modules, ctx->current_module);
2236 ctx->current_module->dependencies = ctx->dependencies;
2238 state_switch (ctx, STATE_NAMESPACE);
2245 if (start_property (context, element_name,
2246 attribute_names, attribute_values,
2249 else if (strcmp (element_name, "parameters") == 0 &&
2250 ctx->state == STATE_FUNCTION)
2252 state_switch (ctx, STATE_FUNCTION_PARAMETERS);
2256 else if (start_parameter (context, element_name,
2257 attribute_names, attribute_values,
2264 if (strcmp (element_name, "repository") == 0 && ctx->state == STATE_START)
2266 const gchar *version;
2268 version = find_attribute ("version", attribute_names, attribute_values);
2270 if (version == NULL)
2271 MISSING_ATTRIBUTE (context, error, element_name, "version");
2272 else if (strcmp (version, "1.0") != 0)
2275 G_MARKUP_ERROR_INVALID_CONTENT,
2276 "Unsupported version '%s'",
2279 state_switch (ctx, STATE_REPOSITORY);
2283 else if (start_return_value (context, element_name,
2284 attribute_names, attribute_values,
2287 else if (strcmp (element_name, "requires") == 0 &&
2288 ctx->state == STATE_INTERFACE)
2290 state_switch (ctx, STATE_REQUIRES);
2294 else if (start_struct (context, element_name,
2295 attribute_names, attribute_values,
2301 if (start_union (context, element_name,
2302 attribute_names, attribute_values,
2308 if (start_type (context, element_name,
2309 attribute_names, attribute_values,
2315 if (start_vfunc (context, element_name,
2316 attribute_names, attribute_values,
2322 g_markup_parse_context_get_position (context, &line_number, &char_number);
2324 if (error && *error == NULL)
2327 G_MARKUP_ERROR_UNKNOWN_ELEMENT,
2328 "Unexpected start tag '%s' on line %d char %d; current state=%d",
2330 line_number, char_number, ctx->state);
2335 g_markup_parse_context_get_position (context, &line_number, &char_number);
2337 fprintf (stderr, "Error at line %d, character %d: %s\n", line_number, char_number, (*error)->message);
2338 backtrace_stderr ();
2343 require_one_of_end_elements (GMarkupParseContext *context,
2345 const char *actual_name,
2350 int line_number, char_number;
2351 const char *expected;
2352 gboolean matched = FALSE;
2354 va_start (args, error);
2356 while ((expected = va_arg (args, const char*)) != NULL)
2358 if (strcmp (expected, actual_name) == 0)
2370 g_markup_parse_context_get_position (context, &line_number, &char_number);
2373 G_MARKUP_ERROR_INVALID_CONTENT,
2374 "Unexpected end tag '%s' on line %d char %d; current state=%d",
2376 line_number, char_number, ctx->state);
2382 require_end_element (GMarkupParseContext *context,
2384 const char *expected_name,
2385 const char *actual_name,
2388 return require_one_of_end_elements (context, ctx, actual_name, error, expected_name, NULL);
2392 end_element_handler (GMarkupParseContext *context,
2393 const gchar *element_name,
2397 ParseContext *ctx = user_data;
2399 g_debug ("</%s>", element_name);
2405 /* no need to GError here, GMarkup already catches this */
2408 case STATE_REPOSITORY:
2409 state_switch (ctx, STATE_END);
2413 if (require_end_element (context, ctx, "include", element_name, error))
2415 state_switch (ctx, STATE_REPOSITORY);
2419 case STATE_NAMESPACE:
2420 if (require_end_element (context, ctx, "namespace", element_name, error))
2422 ctx->current_module = NULL;
2423 state_switch (ctx, STATE_REPOSITORY);
2428 if (require_end_element (context, ctx, "alias", element_name, error))
2430 state_switch (ctx, STATE_NAMESPACE);
2434 case STATE_FUNCTION_RETURN:
2435 if (strcmp ("type", element_name) == 0)
2437 if (require_end_element (context, ctx, "return-value", element_name, error))
2439 state_switch (ctx, STATE_FUNCTION);
2443 case STATE_FUNCTION_PARAMETERS:
2444 if (require_end_element (context, ctx, "parameters", element_name, error))
2446 state_switch (ctx, STATE_FUNCTION);
2450 case STATE_FUNCTION_PARAMETER:
2451 if (strcmp ("type", element_name) == 0)
2453 if (require_end_element (context, ctx, "parameter", element_name, error))
2455 state_switch (ctx, STATE_FUNCTION_PARAMETERS);
2459 case STATE_FUNCTION:
2460 if (ctx->current_node == g_list_last (ctx->current_module->entries)->data)
2462 ctx->current_node = NULL;
2463 state_switch (ctx, STATE_NAMESPACE);
2467 ctx->current_node = g_list_last (ctx->current_module->entries)->data;
2468 if (ctx->current_node->type == G_IR_NODE_INTERFACE)
2469 state_switch (ctx, STATE_INTERFACE);
2470 else if (ctx->current_node->type == G_IR_NODE_OBJECT)
2471 state_switch (ctx, STATE_CLASS);
2472 else if (ctx->current_node->type == G_IR_NODE_BOXED)
2473 state_switch (ctx, STATE_BOXED);
2474 else if (ctx->current_node->type == G_IR_NODE_STRUCT)
2475 state_switch (ctx, STATE_STRUCT);
2476 else if (ctx->current_node->type == G_IR_NODE_UNION)
2477 state_switch (ctx, STATE_UNION);
2480 int line_number, char_number;
2481 g_markup_parse_context_get_position (context, &line_number, &char_number);
2484 G_MARKUP_ERROR_INVALID_CONTENT,
2485 "Unexpected end tag '%s' on line %d char %d",
2487 line_number, char_number);
2492 case STATE_CLASS_FIELD:
2493 if (strcmp ("type", element_name) == 0)
2495 if (require_end_element (context, ctx, "field", element_name, error))
2497 state_switch (ctx, STATE_CLASS);
2501 case STATE_CLASS_PROPERTY:
2502 if (strcmp ("type", element_name) == 0)
2504 if (require_end_element (context, ctx, "property", element_name, error))
2506 state_switch (ctx, STATE_CLASS);
2511 if (require_end_element (context, ctx, "class", element_name, error))
2513 ctx->current_node = NULL;
2514 state_switch (ctx, STATE_NAMESPACE);
2518 case STATE_ERRORDOMAIN:
2519 if (require_end_element (context, ctx, "errordomain", element_name, error))
2521 ctx->current_node = NULL;
2522 state_switch (ctx, STATE_NAMESPACE);
2526 case STATE_INTERFACE_PROPERTY:
2527 if (strcmp ("type", element_name) == 0)
2529 if (require_end_element (context, ctx, "property", element_name, error))
2531 state_switch (ctx, STATE_INTERFACE);
2535 case STATE_INTERFACE_FIELD:
2536 if (strcmp ("type", element_name) == 0)
2538 if (require_end_element (context, ctx, "field", element_name, error))
2540 state_switch (ctx, STATE_INTERFACE);
2544 case STATE_INTERFACE:
2545 if (require_end_element (context, ctx, "interface", element_name, error))
2547 ctx->current_node = NULL;
2548 state_switch (ctx, STATE_NAMESPACE);
2553 if (strcmp ("member", element_name) == 0)
2555 else if (require_one_of_end_elements (context, ctx,
2556 element_name, error, "enumeration",
2559 ctx->current_node = NULL;
2560 state_switch (ctx, STATE_NAMESPACE);
2565 if (require_end_element (context, ctx, "glib:boxed", element_name, error))
2567 ctx->current_node = NULL;
2568 state_switch (ctx, STATE_NAMESPACE);
2572 case STATE_BOXED_FIELD:
2573 if (strcmp ("type", element_name) == 0)
2575 if (require_end_element (context, ctx, "field", element_name, error))
2577 state_switch (ctx, STATE_BOXED);
2581 case STATE_STRUCT_FIELD:
2582 if (strcmp ("type", element_name) == 0)
2584 if (require_end_element (context, ctx, "field", element_name, error))
2586 state_switch (ctx, STATE_STRUCT);
2591 if (require_end_element (context, ctx, "record", element_name, error))
2593 ctx->current_node = NULL;
2594 state_switch (ctx, STATE_NAMESPACE);
2598 case STATE_UNION_FIELD:
2599 if (strcmp ("type", element_name) == 0)
2601 if (require_end_element (context, ctx, "field", element_name, error))
2603 state_switch (ctx, STATE_UNION);
2608 if (require_end_element (context, ctx, "union", element_name, error))
2610 ctx->current_node = NULL;
2611 state_switch (ctx, STATE_NAMESPACE);
2614 case STATE_IMPLEMENTS:
2615 if (strcmp ("interface", element_name) == 0)
2617 if (require_end_element (context, ctx, "implements", element_name, error))
2618 state_switch (ctx, STATE_CLASS);
2620 case STATE_REQUIRES:
2621 if (require_end_element (context, ctx, "requires", element_name, error))
2622 state_switch (ctx, STATE_INTERFACE);
2624 case STATE_NAMESPACE_CONSTANT:
2625 case STATE_CLASS_CONSTANT:
2626 case STATE_INTERFACE_CONSTANT:
2627 if (strcmp ("type", element_name) == 0)
2629 if (require_end_element (context, ctx, "constant", element_name, error))
2631 ctx->current_node = NULL;
2634 case STATE_NAMESPACE_CONSTANT:
2635 state_switch (ctx, STATE_NAMESPACE);
2637 case STATE_CLASS_CONSTANT:
2638 state_switch (ctx, STATE_CLASS);
2640 case STATE_INTERFACE_CONSTANT:
2641 state_switch (ctx, STATE_INTERFACE);
2644 g_assert_not_reached ();
2650 if (strcmp ("type", element_name) == 0)
2652 if (ctx->type_depth == 1)
2653 state_switch (ctx, ctx->prev_state);
2655 ctx->type_depth -= 1;
2659 g_error ("Unhandled state %d in end_element_handler\n", ctx->state);
2664 text_handler (GMarkupParseContext *context,
2670 /* FIXME warn about non-whitespace text */
2674 cleanup (GMarkupParseContext *context,
2678 ParseContext *ctx = user_data;
2680 int line_number, char_number;
2682 for (m = ctx->modules; m; m = m->next)
2683 g_ir_module_free (m->data);
2684 g_list_free (ctx->modules);
2685 ctx->modules = NULL;
2687 ctx->current_module = NULL;
2690 static GMarkupParser parser =
2692 start_element_handler,
2693 end_element_handler,
2700 g_ir_parse_string (const gchar *namespace,
2701 const gchar *const *includes,
2702 const gchar *buffer,
2706 ParseContext ctx = { 0 };
2707 GMarkupParseContext *context;
2709 ctx.state = STATE_START;
2710 ctx.includes = includes;
2711 ctx.prefix_aliases = FALSE;
2712 ctx.namespace = namespace;
2713 ctx.aliases = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
2715 ctx.dependencies = NULL;
2716 ctx.current_module = NULL;
2718 context = g_markup_parse_context_new (&firstpass_parser, 0, &ctx, NULL);
2720 if (!g_markup_parse_context_parse (context, buffer, length, error))
2723 if (!g_markup_parse_context_end_parse (context, error))
2726 g_markup_parse_context_free (context);
2728 context = g_markup_parse_context_new (&parser, 0, &ctx, NULL);
2729 if (!g_markup_parse_context_parse (context, buffer, length, error))
2732 if (!g_markup_parse_context_end_parse (context, error))
2737 g_hash_table_destroy (ctx.aliases);
2739 g_markup_parse_context_free (context);
2745 g_ir_parse_file (const gchar *filename,
2746 const gchar *const *includes,
2755 if (!g_str_has_suffix (filename, ".gir"))
2759 G_MARKUP_ERROR_INVALID_CONTENT,
2760 "Expected filename to end with '.gir'");
2764 g_debug ("[parsing] filename %s", filename);
2766 slash = g_strrstr (filename, "/");
2768 namespace = g_strdup (filename);
2770 namespace = g_strdup (slash+1);
2771 namespace[strlen(namespace)-4] = '\0';
2773 if (!g_file_get_contents (filename, &buffer, &length, error))
2776 modules = g_ir_parse_string (namespace, includes, buffer, length, error);