1 /* GObject introspection: A parser for the XML GIR format
3 * Copyright (C) 2008 Philip Van Hoof
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
26 #include "girmodule.h"
40 STATE_FUNCTION_RETURN,
41 STATE_FUNCTION_PARAMETERS,
42 STATE_FUNCTION_PARAMETER, /* 10 */
47 STATE_INTERFACE_PROPERTY, /* 15 */
48 STATE_INTERFACE_FIELD,
52 STATE_BOXED_FIELD, /* 20 */
57 STATE_UNION_FIELD, /* 25 */
58 STATE_NAMESPACE_CONSTANT,
60 STATE_INTERFACE_CONSTANT,
65 typedef struct _ParseContext ParseContext;
69 ParseState prev_state;
71 const char * const*includes;
74 gboolean prefix_aliases;
78 const char *namespace;
79 GIrModule *current_module;
80 GIrNode *current_node;
81 GIrNode *current_typed;
84 GList *type_parameters;
89 start_alias (GMarkupParseContext *context,
90 const gchar *element_name,
91 const gchar **attribute_names,
92 const gchar **attribute_values,
97 firstpass_start_element_handler (GMarkupParseContext *context,
98 const gchar *element_name,
99 const gchar **attribute_names,
100 const gchar **attribute_values,
104 ParseContext *ctx = user_data;
106 if (strcmp (element_name, "alias") == 0)
108 start_alias (context, element_name, attribute_names, attribute_values,
114 firstpass_end_element_handler (GMarkupParseContext *context,
115 const gchar *element_name,
119 ParseContext *ctx = user_data;
123 static GMarkupParser firstpass_parser =
125 firstpass_start_element_handler,
126 firstpass_end_element_handler,
133 locate_gir (const char *name, const char * const* extra_paths)
135 const gchar *const *datadirs;
136 const gchar *const *dir;
140 gboolean firstpass = TRUE;
142 datadirs = g_get_system_data_dirs ();
144 girname = g_strdup_printf ("%s.gir", name);
146 for (dir = datadirs; *dir; dir++)
148 path = g_build_filename (*dir, "gir", girname, NULL);
149 if (g_file_test (path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))
154 if (extra_paths != NULL)
156 for (dir = extra_paths; *dir; dir++)
158 path = g_build_filename (*dir, girname, NULL);
159 if (g_file_test (path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))
169 #define MISSING_ATTRIBUTE(ctx,error,element,attribute) \
171 int line_number, char_number; \
172 g_markup_parse_context_get_position (context, &line_number, &char_number); \
173 g_set_error (error, \
175 G_MARKUP_ERROR_INVALID_CONTENT, \
176 "Line %d, character %d: The attribute '%s' on the element '%s' must be specified", \
177 line_number, char_number, attribute, element); \
181 backtrace_stderr (void)
189 size = backtrace (array, 50);
190 strings = (char**) backtrace_symbols (array, size);
192 fprintf (stderr, "--- BACKTRACE (%zd frames) ---\n", size);
194 for (i = 0; i < size; i++)
195 fprintf (stderr, "%s\n", strings[i]);
197 fprintf (stderr, "--- END BACKTRACE ---\n", size);
205 find_attribute (const gchar *name,
206 const gchar **attribute_names,
207 const gchar **attribute_values)
211 for (i = 0; attribute_names[i] != NULL; i++)
212 if (strcmp (attribute_names[i], name) == 0)
213 return attribute_values[i];
219 state_switch (ParseContext *ctx, ParseState newstate)
221 g_debug ("State: %d", newstate);
222 ctx->prev_state = ctx->state;
223 ctx->state = newstate;
226 static GIrNodeType * parse_type_internal (const gchar *str, gchar **next, gboolean in_glib,
227 gboolean in_gobject);
235 static BasicTypeInfo basic_types[] = {
236 { "none", GI_TYPE_TAG_VOID, 0 },
237 { "any", GI_TYPE_TAG_VOID, 1 },
239 { "bool", GI_TYPE_TAG_BOOLEAN, 0 },
240 { "char", GI_TYPE_TAG_INT8, 0 },
241 { "int8", GI_TYPE_TAG_INT8, 0 },
242 { "uint8", GI_TYPE_TAG_UINT8, 0 },
243 { "int16", GI_TYPE_TAG_INT16, 0 },
244 { "uint16", GI_TYPE_TAG_UINT16, 0 },
245 { "int32", GI_TYPE_TAG_INT32, 0 },
246 { "uint32", GI_TYPE_TAG_UINT32, 0 },
247 { "int64", GI_TYPE_TAG_INT64, 0 },
248 { "uint64", GI_TYPE_TAG_UINT64, 0 },
249 { "int", GI_TYPE_TAG_INT, 0 },
250 { "uint", GI_TYPE_TAG_UINT, 0 },
251 { "long", GI_TYPE_TAG_LONG, 0 },
252 { "ulong", GI_TYPE_TAG_ULONG, 0 },
253 { "ssize_t", GI_TYPE_TAG_SSIZE, 0 },
254 { "ssize", GI_TYPE_TAG_SSIZE, 0 },
255 { "size_t", GI_TYPE_TAG_SIZE, 0 },
256 { "size", GI_TYPE_TAG_SIZE, 0 },
257 { "float", GI_TYPE_TAG_FLOAT, 0 },
258 { "double", GI_TYPE_TAG_DOUBLE, 0 },
259 { "time_t", GI_TYPE_TAG_TIME_T, 0 },
260 { "GType", GI_TYPE_TAG_GTYPE, 0 },
261 { "utf8", GI_TYPE_TAG_UTF8, 1 },
262 { "filename", GI_TYPE_TAG_FILENAME,1 },
265 static const BasicTypeInfo *
266 parse_basic (const char *str)
269 gint n_basic = G_N_ELEMENTS (basic_types);
270 gchar *temporary_type = NULL;
274 for (i = 0; i < n_basic; i++)
276 if (g_str_has_prefix (str, basic_types[i].str))
277 return &(basic_types[i]);
283 parse_type_internal (const gchar *str, char **next, gboolean in_glib,
286 const BasicTypeInfo *basic;
288 char *temporary_type = NULL;
290 type = (GIrNodeType *)g_ir_node_new (G_IR_NODE_TYPE);
292 type->unparsed = g_strdup (str);
294 /* See comment below on GLib.List handling */
295 if (in_gobject && strcmp (str, "Type") == 0)
297 temporary_type = g_strdup ("GLib.Type");
298 str = temporary_type;
301 basic = parse_basic (str);
304 type->is_basic = TRUE;
305 type->tag = basic->tag;
306 type->is_pointer = basic->pointer;
308 str += strlen(basic->str);
312 /* If we're inside GLib, handle "List" etc. by prefixing with
313 * "GLib." so the parsing code below doesn't have to get more
316 if (g_str_has_prefix (str, "List<") ||
317 strcmp (str, "List") == 0)
319 temporary_type = g_strdup_printf ("GLib.List%s", str + 4);
320 str = temporary_type;
322 else if (g_str_has_prefix (str, "SList<") ||
323 strcmp (str, "SList") == 0)
325 temporary_type = g_strdup_printf ("GLib.SList%s", str + 5);
326 str = temporary_type;
328 else if (g_str_has_prefix (str, "HashTable<") ||
329 strcmp (str, "HashTable") == 0)
331 temporary_type = g_strdup_printf ("GLib.HashTable%s", str + 9);
332 str = temporary_type;
334 else if (g_str_has_prefix (str, "Error<") ||
335 strcmp (str, "Error") == 0)
337 temporary_type = g_strdup_printf ("GLib.Error%s", str + 5);
338 str = temporary_type;
343 /* found a basic type */;
344 else if (g_str_has_prefix (str, "GLib.List") ||
345 g_str_has_prefix (str, "GLib.SList"))
347 str += strlen ("GLib.");
348 if (g_str_has_prefix (str, "List"))
350 type->tag = GI_TYPE_TAG_GLIST;
351 type->is_glist = TRUE;
352 type->is_pointer = TRUE;
353 str += strlen ("List");
357 type->tag = GI_TYPE_TAG_GSLIST;
358 type->is_gslist = TRUE;
359 type->is_pointer = TRUE;
360 str += strlen ("SList");
363 else if (g_str_has_prefix (str, "GLib.HashTable"))
365 str += strlen ("GLib.");
367 type->tag = GI_TYPE_TAG_GHASH;
368 type->is_ghashtable = TRUE;
369 type->is_pointer = TRUE;
370 str += strlen ("HashTable");
372 else if (g_str_has_prefix (str, "GLib.Error"))
374 str += strlen ("GLib.");
376 type->tag = GI_TYPE_TAG_ERROR;
377 type->is_error = TRUE;
378 type->is_pointer = TRUE;
379 str += strlen ("Error");
386 end = strchr (str, '>');
387 tmp = g_strndup (str, end - str);
388 type->errors = g_strsplit (tmp, ",", 0);
396 type->tag = GI_TYPE_TAG_INTERFACE;
397 type->is_interface = TRUE;
398 const char *start = str;
400 /* must be an interface type */
401 while (g_ascii_isalnum (*str) ||
408 type->interface = g_strndup (start, str - start);
413 g_assert (type->tag >= 0 && type->tag <= GI_TYPE_TAG_ERROR);
414 g_free (temporary_type);
418 g_ir_node_free ((GIrNode *)type);
419 g_free (temporary_type);
424 resolve_aliases (ParseContext *ctx, const gchar *type)
428 GSList *seen_values = NULL;
430 seen_values = g_slist_prepend (seen_values, (char*)type);
431 while (g_hash_table_lookup_extended (ctx->aliases, type, &orig, &value))
433 g_debug ("Resolved: %s => %s", type, value);
435 if (g_slist_find_custom (seen_values, type,
436 (GCompareFunc)strcmp) != NULL)
438 seen_values = g_slist_prepend (seen_values, (gchar*)type);
440 g_slist_free (seen_values);
445 parse_type (ParseContext *ctx, const gchar *type)
449 const BasicTypeInfo *basic;
450 gboolean in_glib, in_gobject;
451 gboolean matched_special = FALSE;
453 in_glib = strcmp (ctx->namespace, "GLib") == 0;
454 in_gobject = strcmp (ctx->namespace, "GObject") == 0;
456 /* Do not search aliases for basic types */
457 basic = parse_basic (type);
459 type = resolve_aliases (ctx, type);
461 node = parse_type_internal (type, NULL, in_glib, in_gobject);
463 g_debug ("Parsed type: %s => %d", type, node->tag);
465 g_critical ("Failed to parse type: '%s'", type);
471 start_glib_boxed (GMarkupParseContext *context,
472 const gchar *element_name,
473 const gchar **attribute_names,
474 const gchar **attribute_values,
479 const gchar *typename;
480 const gchar *typeinit;
481 const gchar *deprecated;
484 if (!(strcmp (element_name, "glib:boxed") == 0 &&
485 ctx->state == STATE_NAMESPACE))
488 name = find_attribute ("glib:name", attribute_names, attribute_values);
489 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
490 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
491 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
495 MISSING_ATTRIBUTE (context, error, element_name, "glib:name");
498 else if (typename == NULL)
500 MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
503 else if (typeinit == NULL)
505 MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
509 boxed = (GIrNodeBoxed *) g_ir_node_new (G_IR_NODE_BOXED);
511 ((GIrNode *)boxed)->name = g_strdup (name);
512 boxed->gtype_name = g_strdup (typename);
513 boxed->gtype_init = g_strdup (typeinit);
515 boxed->deprecated = TRUE;
517 boxed->deprecated = FALSE;
519 ctx->current_node = (GIrNode *)boxed;
520 ctx->current_module->entries =
521 g_list_append (ctx->current_module->entries, boxed);
523 state_switch (ctx, STATE_BOXED);
529 start_function (GMarkupParseContext *context,
530 const gchar *element_name,
531 const gchar **attribute_names,
532 const gchar **attribute_values,
538 const gchar *deprecated;
539 GIrNodeFunction *function;
540 gboolean found = FALSE;
544 case STATE_NAMESPACE:
545 found = (strcmp (element_name, "function") == 0 ||
546 strcmp (element_name, "callback") == 0);
552 found = strcmp (element_name, "constructor") == 0;
554 case STATE_INTERFACE:
556 strcmp (element_name, "method") == 0 ||
557 strcmp (element_name, "callback") == 0);
566 name = find_attribute ("name", attribute_names, attribute_values);
567 symbol = find_attribute ("c:identifier", attribute_names, attribute_values);
568 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
572 MISSING_ATTRIBUTE (context, error, element_name, "name");
575 else if (strcmp (element_name, "callback") != 0 && symbol == NULL)
577 MISSING_ATTRIBUTE (context, error, element_name, "c:identifier");
581 function = (GIrNodeFunction *) g_ir_node_new (G_IR_NODE_FUNCTION);
583 ((GIrNode *)function)->name = g_strdup (name);
584 function->symbol = g_strdup (symbol);
585 function->parameters = NULL;
587 function->deprecated = TRUE;
589 function->deprecated = FALSE;
591 if (strcmp (element_name, "method") == 0 ||
592 strcmp (element_name, "constructor") == 0)
594 function->is_method = TRUE;
596 if (strcmp (element_name, "constructor") == 0)
597 function->is_constructor = TRUE;
599 function->is_constructor = FALSE;
603 function->is_method = FALSE;
604 function->is_setter = FALSE;
605 function->is_getter = FALSE;
606 function->is_constructor = FALSE;
607 if (strcmp (element_name, "callback") == 0)
608 ((GIrNode *)function)->type = G_IR_NODE_CALLBACK;
611 if (ctx->current_node == NULL)
613 ctx->current_module->entries =
614 g_list_append (ctx->current_module->entries, function);
617 switch (ctx->current_node->type)
619 case G_IR_NODE_INTERFACE:
620 case G_IR_NODE_OBJECT:
622 GIrNodeInterface *iface;
624 iface = (GIrNodeInterface *)ctx->current_node;
625 iface->members = g_list_append (iface->members, function);
628 case G_IR_NODE_BOXED:
632 boxed = (GIrNodeBoxed *)ctx->current_node;
633 boxed->members = g_list_append (boxed->members, function);
636 case G_IR_NODE_STRUCT:
638 GIrNodeStruct *struct_;
640 struct_ = (GIrNodeStruct *)ctx->current_node;
641 struct_->members = g_list_append (struct_->members, function); }
643 case G_IR_NODE_UNION:
645 GIrNodeUnion *union_;
647 union_ = (GIrNodeUnion *)ctx->current_node;
648 union_->members = g_list_append (union_->members, function);
652 g_assert_not_reached ();
655 ctx->current_node = (GIrNode *)function;
656 state_switch (ctx, STATE_FUNCTION);
662 start_parameter (GMarkupParseContext *context,
663 const gchar *element_name,
664 const gchar **attribute_names,
665 const gchar **attribute_values,
670 const gchar *direction;
673 const gchar *optional;
675 const gchar *transfer;
678 if (!(strcmp (element_name, "parameter") == 0 &&
679 ctx->state == STATE_FUNCTION_PARAMETERS))
682 name = find_attribute ("name", attribute_names, attribute_values);
683 direction = find_attribute ("direction", attribute_names, attribute_values);
684 retval = find_attribute ("retval", attribute_names, attribute_values);
685 dipper = find_attribute ("dipper", attribute_names, attribute_values);
686 optional = find_attribute ("optional", attribute_names, attribute_values);
687 nullok = find_attribute ("null-ok", attribute_names, attribute_values);
688 transfer = find_attribute ("transfer", attribute_names, attribute_values);
693 param = (GIrNodeParam *)g_ir_node_new (G_IR_NODE_PARAM);
695 ctx->current_typed = (GIrNode*) param;
696 ctx->current_typed->name = g_strdup (name);
698 state_switch (ctx, STATE_FUNCTION_PARAMETER);
700 if (direction && strcmp (direction, "out") == 0)
705 else if (direction && strcmp (direction, "inout") == 0)
716 if (retval && strcmp (retval, "1") == 0)
717 param->retval = TRUE;
719 param->retval = FALSE;
721 if (dipper && strcmp (dipper, "1") == 0)
722 param->dipper = TRUE;
724 param->dipper = FALSE;
726 if (optional && strcmp (optional, "1") == 0)
727 param->optional = TRUE;
729 param->optional = FALSE;
731 if (nullok && strcmp (nullok, "1") == 0)
732 param->null_ok = TRUE;
734 param->null_ok = FALSE;
736 if (transfer && strcmp (transfer, "none") == 0)
738 param->transfer = FALSE;
739 param->shallow_transfer = FALSE;
741 else if (transfer && strcmp (transfer, "shallow") == 0)
743 param->transfer = FALSE;
744 param->shallow_transfer = TRUE;
750 if (strcmp (transfer, "full") != 0)
751 g_warning ("Unknown transfer %s", transfer);
753 param->transfer = TRUE;
755 else if (param->in && !param->out)
756 param->transfer = FALSE;
758 param->transfer = TRUE;
759 param->shallow_transfer = FALSE;
762 ((GIrNode *)param)->name = g_strdup (name);
764 switch (ctx->current_node->type)
766 case G_IR_NODE_FUNCTION:
767 case G_IR_NODE_CALLBACK:
769 GIrNodeFunction *func;
771 func = (GIrNodeFunction *)ctx->current_node;
772 func->parameters = g_list_append (func->parameters, param);
775 case G_IR_NODE_SIGNAL:
777 GIrNodeSignal *signal;
779 signal = (GIrNodeSignal *)ctx->current_node;
780 signal->parameters = g_list_append (signal->parameters, param);
783 case G_IR_NODE_VFUNC:
787 vfunc = (GIrNodeVFunc *)ctx->current_node;
788 vfunc->parameters = g_list_append (vfunc->parameters, param);
792 g_assert_not_reached ();
799 start_field (GMarkupParseContext *context,
800 const gchar *element_name,
801 const gchar **attribute_names,
802 const gchar **attribute_values,
807 const gchar *readable;
808 const gchar *writable;
820 case STATE_INTERFACE:
826 if (strcmp (element_name, "field") != 0)
829 name = find_attribute ("name", attribute_names, attribute_values);
830 readable = find_attribute ("readable", attribute_names, attribute_values);
831 writable = find_attribute ("writable", attribute_names, attribute_values);
832 bits = find_attribute ("bits", attribute_names, attribute_values);
833 branch = find_attribute ("branch", attribute_names, attribute_values);
834 offset = find_attribute ("offset", attribute_names, attribute_values);
838 MISSING_ATTRIBUTE (context, error, element_name, "name");
842 field = (GIrNodeField *)g_ir_node_new (G_IR_NODE_FIELD);
843 ctx->current_typed = (GIrNode*) field;
844 ((GIrNode *)field)->name = g_strdup (name);
845 if (readable && strcmp (readable, "1") == 0)
846 field->readable = TRUE;
848 field->readable = FALSE;
850 if (writable && strcmp (writable, "1") == 0)
851 field->writable = TRUE;
853 field->writable = FALSE;
856 field->bits = atoi (bits);
861 field->offset = atoi (offset);
865 switch (ctx->current_node->type)
867 case G_IR_NODE_OBJECT:
869 GIrNodeInterface *iface;
871 iface = (GIrNodeInterface *)ctx->current_node;
872 iface->members = g_list_append (iface->members, field);
873 state_switch (ctx, STATE_CLASS_FIELD);
876 case G_IR_NODE_INTERFACE:
878 GIrNodeInterface *iface;
880 iface = (GIrNodeInterface *)ctx->current_node;
881 iface->members = g_list_append (iface->members, field);
882 state_switch (ctx, STATE_INTERFACE_FIELD);
885 case G_IR_NODE_BOXED:
889 boxed = (GIrNodeBoxed *)ctx->current_node;
890 boxed->members = g_list_append (boxed->members, field);
891 state_switch (ctx, STATE_BOXED_FIELD);
894 case G_IR_NODE_STRUCT:
896 GIrNodeStruct *struct_;
898 struct_ = (GIrNodeStruct *)ctx->current_node;
899 struct_->members = g_list_append (struct_->members, field);
900 state_switch (ctx, STATE_STRUCT_FIELD);
903 case G_IR_NODE_UNION:
905 GIrNodeUnion *union_;
907 union_ = (GIrNodeUnion *)ctx->current_node;
908 union_->members = g_list_append (union_->members, field);
911 GIrNodeConstant *constant;
913 constant = (GIrNodeConstant *) g_ir_node_new (G_IR_NODE_CONSTANT);
914 ((GIrNode *)constant)->name = g_strdup (name);
915 constant->value = g_strdup (branch);
916 constant->type = union_->discriminator_type;
917 constant->deprecated = FALSE;
919 union_->discriminators = g_list_append (union_->discriminators, constant);
921 state_switch (ctx, STATE_UNION_FIELD);
925 g_assert_not_reached ();
932 start_alias (GMarkupParseContext *context,
933 const gchar *element_name,
934 const gchar **attribute_names,
935 const gchar **attribute_values,
945 name = find_attribute ("name", attribute_names, attribute_values);
948 MISSING_ATTRIBUTE (context, error, element_name, "name");
952 target = find_attribute ("target", attribute_names, attribute_values);
955 MISSING_ATTRIBUTE (context, error, element_name, "target");
959 value = g_strdup (target);
960 if (ctx->prefix_aliases)
962 key = g_strdup_printf ("%s.%s", ctx->namespace, name);
963 if (!strchr (target, '.'))
965 const BasicTypeInfo *basic = parse_basic (target);
969 /* For non-basic types, re-qualify the interface */
970 value = g_strdup_printf ("%s.%s", ctx->namespace, target);
976 key = g_strdup (name);
979 g_hash_table_insert (ctx->aliases, key, value);
985 start_enum (GMarkupParseContext *context,
986 const gchar *element_name,
987 const gchar **attribute_names,
988 const gchar **attribute_values,
992 if ((strcmp (element_name, "enumeration") == 0 && ctx->state == STATE_NAMESPACE) ||
993 (strcmp (element_name, "bitfield") == 0 && ctx->state == STATE_NAMESPACE))
996 const gchar *typename;
997 const gchar *typeinit;
998 const gchar *deprecated;
1000 name = find_attribute ("name", attribute_names, attribute_values);
1001 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
1002 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
1003 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1006 MISSING_ATTRIBUTE (context, error, element_name, "name");
1011 if (strcmp (element_name, "enumeration") == 0)
1012 enum_ = (GIrNodeEnum *) g_ir_node_new (G_IR_NODE_ENUM);
1014 enum_ = (GIrNodeEnum *) g_ir_node_new (G_IR_NODE_FLAGS);
1015 ((GIrNode *)enum_)->name = g_strdup (name);
1016 enum_->gtype_name = g_strdup (typename);
1017 enum_->gtype_init = g_strdup (typeinit);
1019 enum_->deprecated = TRUE;
1021 enum_->deprecated = FALSE;
1023 ctx->current_node = (GIrNode *) enum_;
1024 ctx->current_module->entries =
1025 g_list_append (ctx->current_module->entries, enum_);
1027 state_switch (ctx, STATE_ENUM);
1036 start_property (GMarkupParseContext *context,
1037 const gchar *element_name,
1038 const gchar **attribute_names,
1039 const gchar **attribute_values,
1043 if (strcmp (element_name, "property") == 0 &&
1044 (ctx->state == STATE_CLASS ||
1045 ctx->state == STATE_INTERFACE))
1048 const gchar *readable;
1049 const gchar *writable;
1050 const gchar *construct;
1051 const gchar *construct_only;
1053 name = find_attribute ("name", attribute_names, attribute_values);
1054 readable = find_attribute ("readable", attribute_names, attribute_values);
1055 writable = find_attribute ("writable", attribute_names, attribute_values);
1056 construct = find_attribute ("construct", attribute_names, attribute_values);
1057 construct_only = find_attribute ("construct-only", attribute_names, attribute_values);
1060 MISSING_ATTRIBUTE (context, error, element_name, "name");
1063 GIrNodeProperty *property;
1064 GIrNodeInterface *iface;
1066 property = (GIrNodeProperty *) g_ir_node_new (G_IR_NODE_PROPERTY);
1067 ctx->current_typed = (GIrNode*) property;
1069 ((GIrNode *)property)->name = g_strdup (name);
1071 /* Assume properties are readable */
1072 if (readable == NULL || strcmp (readable, "1") == 0)
1073 property->readable = TRUE;
1075 property->readable = FALSE;
1076 if (writable && strcmp (writable, "1") == 0)
1077 property->writable = TRUE;
1079 property->writable = FALSE;
1080 if (construct && strcmp (construct, "1") == 0)
1081 property->construct = TRUE;
1083 property->construct = FALSE;
1084 if (construct_only && strcmp (construct_only, "1") == 0)
1085 property->construct_only = TRUE;
1087 property->construct_only = FALSE;
1089 iface = (GIrNodeInterface *)ctx->current_node;
1090 iface->members = g_list_append (iface->members, property);
1092 if (ctx->state == STATE_CLASS)
1093 state_switch (ctx, STATE_CLASS_PROPERTY);
1094 else if (ctx->state == STATE_INTERFACE)
1095 state_switch (ctx, STATE_INTERFACE_PROPERTY);
1097 g_assert_not_reached ();
1106 parse_value (const gchar *str)
1110 /* FIXME just a quick hack */
1111 shift_op = strstr (str, "<<");
1117 base = strtol (str, NULL, 10);
1118 shift = strtol (shift_op + 3, NULL, 10);
1120 return base << shift;
1123 return strtol (str, NULL, 10);
1129 start_member (GMarkupParseContext *context,
1130 const gchar *element_name,
1131 const gchar **attribute_names,
1132 const gchar **attribute_values,
1136 if (strcmp (element_name, "member") == 0 &&
1137 ctx->state == STATE_ENUM)
1141 const gchar *deprecated;
1143 name = find_attribute ("name", attribute_names, attribute_values);
1144 value = find_attribute ("value", attribute_names, attribute_values);
1145 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1148 MISSING_ATTRIBUTE (context, error, element_name, "name");
1152 GIrNodeValue *value_;
1154 value_ = (GIrNodeValue *) g_ir_node_new (G_IR_NODE_VALUE);
1156 ((GIrNode *)value_)->name = g_strdup (name);
1158 value_->value = parse_value (value);
1161 value_->deprecated = TRUE;
1163 value_->deprecated = FALSE;
1165 enum_ = (GIrNodeEnum *)ctx->current_node;
1166 enum_->values = g_list_append (enum_->values, value_);
1175 start_constant (GMarkupParseContext *context,
1176 const gchar *element_name,
1177 const gchar **attribute_names,
1178 const gchar **attribute_values,
1182 if (strcmp (element_name, "constant") == 0 &&
1183 (ctx->state == STATE_NAMESPACE ||
1184 ctx->state == STATE_CLASS ||
1185 ctx->state == STATE_INTERFACE))
1189 const gchar *deprecated;
1191 name = find_attribute ("name", attribute_names, attribute_values);
1192 value = find_attribute ("value", attribute_names, attribute_values);
1193 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1196 MISSING_ATTRIBUTE (context, error, element_name, "name");
1197 else if (value == NULL)
1198 MISSING_ATTRIBUTE (context, error, element_name, "value");
1201 GIrNodeConstant *constant;
1203 constant = (GIrNodeConstant *) g_ir_node_new (G_IR_NODE_CONSTANT);
1205 ((GIrNode *)constant)->name = g_strdup (name);
1206 constant->value = g_strdup (value);
1208 ctx->current_typed = (GIrNode*) constant;
1211 constant->deprecated = TRUE;
1213 constant->deprecated = FALSE;
1215 if (ctx->state == STATE_NAMESPACE)
1217 ctx->current_node = (GIrNode *) constant;
1218 ctx->current_module->entries =
1219 g_list_append (ctx->current_module->entries, constant);
1223 GIrNodeInterface *iface;
1225 iface = (GIrNodeInterface *)ctx->current_node;
1226 iface->members = g_list_append (iface->members, constant);
1231 case STATE_NAMESPACE:
1232 state_switch (ctx, STATE_NAMESPACE_CONSTANT);
1235 state_switch (ctx, STATE_CLASS_CONSTANT);
1237 case STATE_INTERFACE:
1238 state_switch (ctx, STATE_INTERFACE_CONSTANT);
1241 g_assert_not_reached ();
1252 start_errordomain (GMarkupParseContext *context,
1253 const gchar *element_name,
1254 const gchar **attribute_names,
1255 const gchar **attribute_values,
1259 if (strcmp (element_name, "errordomain") == 0 &&
1260 ctx->state == STATE_NAMESPACE)
1263 const gchar *getquark;
1265 const gchar *deprecated;
1267 name = find_attribute ("name", attribute_names, attribute_values);
1268 getquark = find_attribute ("get-quark", attribute_names, attribute_values);
1269 codes = find_attribute ("codes", attribute_names, attribute_values);
1270 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1273 MISSING_ATTRIBUTE (context, error, element_name, "name");
1274 else if (getquark == NULL)
1275 MISSING_ATTRIBUTE (context, error, element_name, "getquark");
1276 else if (codes == NULL)
1277 MISSING_ATTRIBUTE (context, error, element_name, "codes");
1280 GIrNodeErrorDomain *domain;
1282 domain = (GIrNodeErrorDomain *) g_ir_node_new (G_IR_NODE_ERROR_DOMAIN);
1284 ((GIrNode *)domain)->name = g_strdup (name);
1285 domain->getquark = g_strdup (getquark);
1286 domain->codes = g_strdup (codes);
1289 domain->deprecated = TRUE;
1291 domain->deprecated = FALSE;
1293 ctx->current_node = (GIrNode *) domain;
1294 ctx->current_module->entries =
1295 g_list_append (ctx->current_module->entries, domain);
1297 state_switch (ctx, STATE_ERRORDOMAIN);
1306 start_interface (GMarkupParseContext *context,
1307 const gchar *element_name,
1308 const gchar **attribute_names,
1309 const gchar **attribute_values,
1313 if (strcmp (element_name, "interface") == 0 &&
1314 ctx->state == STATE_NAMESPACE)
1317 const gchar *typename;
1318 const gchar *typeinit;
1319 const gchar *deprecated;
1321 name = find_attribute ("name", attribute_names, attribute_values);
1322 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
1323 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
1324 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1327 MISSING_ATTRIBUTE (context, error, element_name, "name");
1328 else if (typename == NULL)
1329 MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
1330 else if (typeinit == NULL)
1331 MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
1334 GIrNodeInterface *iface;
1336 iface = (GIrNodeInterface *) g_ir_node_new (G_IR_NODE_INTERFACE);
1337 ((GIrNode *)iface)->name = g_strdup (name);
1338 iface->gtype_name = g_strdup (typename);
1339 iface->gtype_init = g_strdup (typeinit);
1341 iface->deprecated = TRUE;
1343 iface->deprecated = FALSE;
1345 ctx->current_node = (GIrNode *) iface;
1346 ctx->current_module->entries =
1347 g_list_append (ctx->current_module->entries, iface);
1349 state_switch (ctx, STATE_INTERFACE);
1359 start_class (GMarkupParseContext *context,
1360 const gchar *element_name,
1361 const gchar **attribute_names,
1362 const gchar **attribute_values,
1366 if (strcmp (element_name, "class") == 0 &&
1367 ctx->state == STATE_NAMESPACE)
1370 const gchar *parent;
1371 const gchar *typename;
1372 const gchar *typeinit;
1373 const gchar *deprecated;
1375 name = find_attribute ("name", attribute_names, attribute_values);
1376 parent = find_attribute ("parent", attribute_names, attribute_values);
1377 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
1378 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
1379 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1382 MISSING_ATTRIBUTE (context, error, element_name, "name");
1383 else if (typename == NULL)
1384 MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
1385 else if (typeinit == NULL && strcmp (typename, "GObject"))
1386 MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
1389 GIrNodeInterface *iface;
1391 iface = (GIrNodeInterface *) g_ir_node_new (G_IR_NODE_OBJECT);
1392 ((GIrNode *)iface)->name = g_strdup (name);
1393 iface->gtype_name = g_strdup (typename);
1394 iface->gtype_init = g_strdup (typeinit);
1395 iface->parent = g_strdup (parent);
1397 iface->deprecated = TRUE;
1399 iface->deprecated = FALSE;
1401 ctx->current_node = (GIrNode *) iface;
1402 ctx->current_module->entries =
1403 g_list_append (ctx->current_module->entries, iface);
1405 state_switch (ctx, STATE_CLASS);
1414 start_type (GMarkupParseContext *context,
1415 const gchar *element_name,
1416 const gchar **attribute_names,
1417 const gchar **attribute_values,
1424 gboolean is_varargs;
1425 GIrNodeType *typenode;
1427 is_array = strcmp (element_name, "array") == 0;
1428 is_varargs = strcmp (element_name, "varargs") == 0;
1430 if (!(is_array || is_varargs || (strcmp (element_name, "type") == 0)))
1433 if (ctx->state == STATE_TYPE)
1436 ctx->type_stack = g_list_prepend (ctx->type_stack, ctx->type_parameters);
1437 ctx->type_parameters = NULL;
1439 else if (ctx->state == STATE_FUNCTION_PARAMETER ||
1440 ctx->state == STATE_FUNCTION_RETURN ||
1441 ctx->state == STATE_STRUCT_FIELD ||
1442 ctx->state == STATE_UNION_FIELD ||
1443 ctx->state == STATE_CLASS_PROPERTY ||
1444 ctx->state == STATE_CLASS_FIELD ||
1445 ctx->state == STATE_INTERFACE_FIELD ||
1446 ctx->state == STATE_INTERFACE_PROPERTY ||
1447 ctx->state == STATE_BOXED_FIELD ||
1448 ctx->state == STATE_NAMESPACE_CONSTANT ||
1449 ctx->state == STATE_CLASS_CONSTANT ||
1450 ctx->state == STATE_INTERFACE_CONSTANT
1453 state_switch (ctx, STATE_TYPE);
1454 ctx->type_depth = 1;
1457 switch (ctx->current_node->type)
1459 case G_IR_NODE_FUNCTION:
1460 case G_IR_NODE_CALLBACK:
1462 GIrNodeFunction *func = (GIrNodeFunction *)ctx->current_node;
1463 func->is_varargs = TRUE;
1466 case G_IR_NODE_VFUNC:
1468 GIrNodeVFunc *vfunc = (GIrNodeVFunc *)ctx->current_node;
1469 vfunc->is_varargs = TRUE;
1474 ctx->type_stack = NULL;
1475 ctx->type_parameters = NULL;
1478 if (!ctx->current_typed)
1482 G_MARKUP_ERROR_INVALID_CONTENT,
1483 "The element <type> is invalid here");
1496 typenode = (GIrNodeType *)g_ir_node_new (G_IR_NODE_TYPE);
1498 typenode->tag = GI_TYPE_TAG_ARRAY;
1499 typenode->is_pointer = TRUE;
1500 typenode->is_array = TRUE;
1502 zero = find_attribute ("zero-terminated", attribute_names, attribute_values);
1503 len = find_attribute ("length", attribute_names, attribute_values);
1505 typenode->zero_terminated = !(zero && strcmp (zero, "1") != 0);
1506 typenode->has_length = len != NULL;
1507 typenode->length = typenode->has_length ? atoi (len) : -1;
1511 gboolean is_pointer;
1512 name = find_attribute ("name", attribute_names, attribute_values);
1515 MISSING_ATTRIBUTE (context, error, element_name, "name");
1517 ctype = find_attribute ("c:type", attribute_names, attribute_values);
1518 if (ctype != NULL && strchr (ctype, '*'))
1523 typenode = parse_type (ctx, name);
1526 typenode->is_pointer = is_pointer;
1529 ctx->type_parameters = g_list_append (ctx->type_parameters, typenode);
1535 end_type_top (ParseContext *ctx)
1537 GIrNodeType *typenode;
1539 if (!ctx->type_parameters)
1542 typenode = (GIrNodeType*)ctx->type_parameters->data;
1544 /* Default to pointer for unspecified containers */
1545 if (typenode->tag == GI_TYPE_TAG_ARRAY ||
1546 typenode->tag == GI_TYPE_TAG_GLIST ||
1547 typenode->tag == GI_TYPE_TAG_GSLIST)
1549 if (typenode->parameter_type1 == NULL)
1550 typenode->parameter_type1 = parse_type (ctx, "any");
1552 else if (typenode->tag == GI_TYPE_TAG_GHASH)
1554 if (typenode->parameter_type1 == NULL)
1556 typenode->parameter_type1 = parse_type (ctx, "any");
1557 typenode->parameter_type2 = parse_type (ctx, "any");
1561 switch (ctx->current_typed->type)
1563 case G_IR_NODE_PARAM:
1565 GIrNodeParam *param = (GIrNodeParam *)ctx->current_typed;
1566 param->type = typenode;
1569 case G_IR_NODE_FIELD:
1571 GIrNodeField *field = (GIrNodeField *)ctx->current_typed;
1572 field->type = typenode;
1575 case G_IR_NODE_PROPERTY:
1577 GIrNodeProperty *property = (GIrNodeProperty *) ctx->current_typed;
1578 property->type = typenode;
1581 case G_IR_NODE_CONSTANT:
1583 GIrNodeConstant *constant = (GIrNodeConstant *)ctx->current_typed;
1584 constant->type = typenode;
1588 g_printerr("current node is %d\n", ctx->current_node->type);
1589 g_assert_not_reached ();
1591 g_list_free (ctx->type_parameters);
1594 ctx->type_depth = 0;
1595 ctx->type_parameters = NULL;
1596 ctx->current_typed = NULL;
1600 end_type_recurse (ParseContext *ctx)
1603 GIrNodeType *parent;
1605 parent = (GIrNodeType *) ((GList*)ctx->type_stack->data)->data;
1607 if (parent->tag == GI_TYPE_TAG_ARRAY ||
1608 parent->tag == GI_TYPE_TAG_GLIST ||
1609 parent->tag == GI_TYPE_TAG_GSLIST)
1611 if (ctx->type_parameters == NULL)
1612 parent->parameter_type1 = parse_type (ctx, "pointer");
1614 parent->parameter_type1 = (GIrNodeType*)ctx->type_parameters->data;
1616 else if (parent->tag == GI_TYPE_TAG_GHASH)
1618 if (ctx->type_parameters == NULL)
1620 parent->parameter_type1 = parse_type (ctx, "pointer");
1621 parent->parameter_type2 = parse_type (ctx, "pointer");
1625 parent->parameter_type1 = (GIrNodeType*) ctx->type_parameters->data;
1626 parent->parameter_type2 = (GIrNodeType*) ctx->type_parameters->next->data;
1629 g_list_free (ctx->type_parameters);
1630 ctx->type_parameters = (GList *)ctx->type_stack->data;
1631 ctx->type_stack = g_list_delete_link (ctx->type_stack, ctx->type_stack);
1635 end_type (ParseContext *ctx)
1637 if (ctx->type_depth == 1)
1640 state_switch (ctx, ctx->prev_state);
1644 end_type_recurse (ctx);
1650 start_return_value (GMarkupParseContext *context,
1651 const gchar *element_name,
1652 const gchar **attribute_names,
1653 const gchar **attribute_values,
1657 if (strcmp (element_name, "return-value") == 0 &&
1658 ctx->state == STATE_FUNCTION)
1660 GIrNodeParam *param;
1662 param = (GIrNodeParam *)g_ir_node_new (G_IR_NODE_PARAM);
1665 param->retval = TRUE;
1667 ctx->current_typed = (GIrNode*) param;
1669 state_switch (ctx, STATE_FUNCTION_RETURN);
1671 switch (ctx->current_node->type)
1673 case G_IR_NODE_FUNCTION:
1674 case G_IR_NODE_CALLBACK:
1676 GIrNodeFunction *func = (GIrNodeFunction *)ctx->current_node;
1677 func->result = param;
1680 case G_IR_NODE_SIGNAL:
1682 GIrNodeSignal *signal = (GIrNodeSignal *)ctx->current_node;
1683 signal->result = param;
1686 case G_IR_NODE_VFUNC:
1688 GIrNodeVFunc *vfunc = (GIrNodeVFunc *)ctx->current_node;
1689 vfunc->result = param;
1693 g_assert_not_reached ();
1703 start_implements (GMarkupParseContext *context,
1704 const gchar *element_name,
1705 const gchar **attribute_names,
1706 const gchar **attribute_values,
1710 GIrNodeInterface *iface;
1713 if (strcmp (element_name, "implements") != 0 ||
1714 !(ctx->state == STATE_CLASS))
1717 state_switch (ctx, STATE_IMPLEMENTS);
1719 name = find_attribute ("name", attribute_names, attribute_values);
1722 MISSING_ATTRIBUTE (context, error, element_name, "name");
1726 iface = (GIrNodeInterface *)ctx->current_node;
1727 iface->interfaces = g_list_append (iface->interfaces, g_strdup (name));
1733 start_glib_signal (GMarkupParseContext *context,
1734 const gchar *element_name,
1735 const gchar **attribute_names,
1736 const gchar **attribute_values,
1740 if (strcmp (element_name, "glib:signal") == 0 &&
1741 (ctx->state == STATE_CLASS ||
1742 ctx->state == STATE_INTERFACE))
1746 const gchar *no_recurse;
1747 const gchar *detailed;
1748 const gchar *action;
1749 const gchar *no_hooks;
1750 const gchar *has_class_closure;
1752 name = find_attribute ("name", attribute_names, attribute_values);
1753 when = find_attribute ("when", attribute_names, attribute_values);
1754 no_recurse = find_attribute ("no-recurse", attribute_names, attribute_values);
1755 detailed = find_attribute ("detailed", attribute_names, attribute_values);
1756 action = find_attribute ("action", attribute_names, attribute_values);
1757 no_hooks = find_attribute ("no-hooks", attribute_names, attribute_values);
1758 has_class_closure = find_attribute ("has-class-closure", attribute_names, attribute_values);
1761 MISSING_ATTRIBUTE (context, error, element_name, "name");
1764 GIrNodeInterface *iface;
1765 GIrNodeSignal *signal;
1767 signal = (GIrNodeSignal *)g_ir_node_new (G_IR_NODE_SIGNAL);
1769 ((GIrNode *)signal)->name = g_strdup (name);
1771 signal->run_first = FALSE;
1772 signal->run_last = FALSE;
1773 signal->run_cleanup = FALSE;
1774 if (when == NULL || strcmp (when, "LAST") == 0)
1775 signal->run_last = TRUE;
1776 else if (strcmp (when, "FIRST") == 0)
1777 signal->run_first = TRUE;
1779 signal->run_cleanup = TRUE;
1781 if (no_recurse && strcmp (no_recurse, "1") == 0)
1782 signal->no_recurse = TRUE;
1784 signal->no_recurse = FALSE;
1785 if (detailed && strcmp (detailed, "1") == 0)
1786 signal->detailed = TRUE;
1788 signal->detailed = FALSE;
1789 if (action && strcmp (action, "1") == 0)
1790 signal->action = TRUE;
1792 signal->action = FALSE;
1793 if (no_hooks && strcmp (no_hooks, "1") == 0)
1794 signal->no_hooks = TRUE;
1796 signal->no_hooks = FALSE;
1797 if (has_class_closure && strcmp (has_class_closure, "1") == 0)
1798 signal->has_class_closure = TRUE;
1800 signal->has_class_closure = FALSE;
1802 iface = (GIrNodeInterface *)ctx->current_node;
1803 iface->members = g_list_append (iface->members, signal);
1805 ctx->current_node = (GIrNode *)signal;
1806 state_switch (ctx, STATE_FUNCTION);
1815 start_vfunc (GMarkupParseContext *context,
1816 const gchar *element_name,
1817 const gchar **attribute_names,
1818 const gchar **attribute_values,
1822 if (strcmp (element_name, "vfunc") == 0 &&
1823 (ctx->state == STATE_CLASS ||
1824 ctx->state == STATE_INTERFACE))
1827 const gchar *must_chain_up;
1828 const gchar *override;
1829 const gchar *is_class_closure;
1830 const gchar *offset;
1832 name = find_attribute ("name", attribute_names, attribute_values);
1833 must_chain_up = find_attribute ("must-chain-up", attribute_names, attribute_values);
1834 override = find_attribute ("override", attribute_names, attribute_values);
1835 is_class_closure = find_attribute ("is-class-closure", attribute_names, attribute_values);
1836 offset = find_attribute ("offset", attribute_names, attribute_values);
1839 MISSING_ATTRIBUTE (context, error, element_name, "name");
1842 GIrNodeInterface *iface;
1843 GIrNodeVFunc *vfunc;
1845 vfunc = (GIrNodeVFunc *)g_ir_node_new (G_IR_NODE_VFUNC);
1847 ((GIrNode *)vfunc)->name = g_strdup (name);
1849 if (must_chain_up && strcmp (must_chain_up, "1") == 0)
1850 vfunc->must_chain_up = TRUE;
1852 vfunc->must_chain_up = FALSE;
1854 if (override && strcmp (override, "always") == 0)
1856 vfunc->must_be_implemented = TRUE;
1857 vfunc->must_not_be_implemented = FALSE;
1859 else if (override && strcmp (override, "never") == 0)
1861 vfunc->must_be_implemented = FALSE;
1862 vfunc->must_not_be_implemented = TRUE;
1866 vfunc->must_be_implemented = FALSE;
1867 vfunc->must_not_be_implemented = FALSE;
1870 if (is_class_closure && strcmp (is_class_closure, "1") == 0)
1871 vfunc->is_class_closure = TRUE;
1873 vfunc->is_class_closure = FALSE;
1876 vfunc->offset = atoi (offset);
1880 iface = (GIrNodeInterface *)ctx->current_node;
1881 iface->members = g_list_append (iface->members, vfunc);
1883 ctx->current_node = (GIrNode *)vfunc;
1884 state_switch (ctx, STATE_FUNCTION);
1894 start_struct (GMarkupParseContext *context,
1895 const gchar *element_name,
1896 const gchar **attribute_names,
1897 const gchar **attribute_values,
1901 if (strcmp (element_name, "record") == 0 &&
1902 ctx->state == STATE_NAMESPACE)
1905 const gchar *deprecated;
1906 const gchar *gtype_name;
1907 const gchar *gtype_init;
1908 GIrNodeStruct *struct_;
1910 name = find_attribute ("name", attribute_names, attribute_values);
1911 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1912 gtype_name = find_attribute ("glib:type-name", attribute_names, attribute_values);
1913 gtype_init = find_attribute ("glib:get-type", attribute_names, attribute_values);
1917 MISSING_ATTRIBUTE (context, error, element_name, "name");
1920 if ((gtype_name == NULL && gtype_init != NULL))
1922 MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
1925 if ((gtype_name != NULL && gtype_init == NULL))
1927 MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
1931 struct_ = (GIrNodeStruct *) g_ir_node_new (G_IR_NODE_STRUCT);
1933 ((GIrNode *)struct_)->name = g_strdup (name);
1935 struct_->deprecated = TRUE;
1937 struct_->deprecated = FALSE;
1939 struct_->gtype_name = g_strdup (gtype_name);
1940 struct_->gtype_init = g_strdup (gtype_init);
1942 ctx->current_node = (GIrNode *)struct_;
1943 ctx->current_module->entries =
1944 g_list_append (ctx->current_module->entries, struct_);
1946 state_switch (ctx, STATE_STRUCT);
1954 start_union (GMarkupParseContext *context,
1955 const gchar *element_name,
1956 const gchar **attribute_names,
1957 const gchar **attribute_values,
1961 if (strcmp (element_name, "union") == 0 &&
1962 ctx->state == STATE_NAMESPACE)
1965 const gchar *deprecated;
1966 const gchar *typename;
1967 const gchar *typeinit;
1969 name = find_attribute ("name", attribute_names, attribute_values);
1970 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1971 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
1972 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
1975 MISSING_ATTRIBUTE (context, error, element_name, "name");
1978 GIrNodeUnion *union_;
1980 union_ = (GIrNodeUnion *) g_ir_node_new (G_IR_NODE_UNION);
1982 ((GIrNode *)union_)->name = g_strdup (name);
1983 union_->gtype_name = g_strdup (typename);
1984 union_->gtype_init = g_strdup (typeinit);
1986 union_->deprecated = TRUE;
1988 union_->deprecated = FALSE;
1990 ctx->current_node = (GIrNode *)union_;
1991 ctx->current_module->entries =
1992 g_list_append (ctx->current_module->entries, union_);
1994 state_switch (ctx, STATE_UNION);
2002 start_discriminator (GMarkupParseContext *context,
2003 const gchar *element_name,
2004 const gchar **attribute_names,
2005 const gchar **attribute_values,
2009 if (strcmp (element_name, "discriminator") == 0 &&
2010 ctx->state == STATE_UNION)
2013 const gchar *offset;
2015 type = find_attribute ("type", attribute_names, attribute_values);
2016 offset = find_attribute ("offset", attribute_names, attribute_values);
2018 MISSING_ATTRIBUTE (context, error, element_name, "type");
2019 else if (offset == NULL)
2020 MISSING_ATTRIBUTE (context, error, element_name, "offset");
2022 ((GIrNodeUnion *)ctx->current_node)->discriminator_type
2023 = parse_type (ctx, type);
2024 ((GIrNodeUnion *)ctx->current_node)->discriminator_offset
2035 parse_include (GMarkupParseContext *context,
2040 ParseContext sub_ctx = { 0 };
2041 GMarkupParseContext *sub_context;
2046 girpath = locate_gir (name, ctx->includes);
2048 if (girpath == NULL)
2052 G_MARKUP_ERROR_INVALID_CONTENT,
2053 "Could not find GIR file '%s.gir'; check XDG_DATA_DIRS or use --includedir",
2058 g_debug ("Parsing include %s", girpath);
2060 if (!g_file_get_contents (girpath, &buffer, &length, error))
2067 sub_ctx.state = STATE_START;
2068 sub_ctx.includes = ctx->includes;
2069 sub_ctx.prefix_aliases = TRUE;
2070 sub_ctx.namespace = name;
2071 sub_ctx.aliases = ctx->aliases;
2072 sub_ctx.type_depth = 0;
2074 context = g_markup_parse_context_new (&firstpass_parser, 0, &sub_ctx, NULL);
2076 if (!g_markup_parse_context_parse (context, buffer, length, error))
2082 if (!g_markup_parse_context_end_parse (context, error))
2088 g_markup_parse_context_free (context);
2092 extern GLogLevelFlags logged_levels;
2095 start_element_handler (GMarkupParseContext *context,
2096 const gchar *element_name,
2097 const gchar **attribute_names,
2098 const gchar **attribute_values,
2102 ParseContext *ctx = user_data;
2103 gint line_number, char_number;
2105 if (logged_levels & G_LOG_LEVEL_DEBUG)
2107 GString *tags = g_string_new ("");
2109 for (i = 0; attribute_names[i]; i++)
2110 g_string_append_printf (tags, "%s=\"%s\" ",
2112 attribute_values[i]);
2116 g_string_insert_c (tags, 0, ' ');
2117 g_string_truncate (tags, tags->len - 1);
2119 g_debug ("<%s%s>", element_name, tags->str);
2120 g_string_free (tags, TRUE);
2123 switch (element_name[0])
2126 if (ctx->state == STATE_NAMESPACE && strcmp (element_name, "alias") == 0)
2128 state_switch (ctx, STATE_ALIAS);
2131 if (start_type (context, element_name,
2132 attribute_names, attribute_values,
2137 if (start_enum (context, element_name,
2138 attribute_names, attribute_values,
2143 if (start_function (context, element_name,
2144 attribute_names, attribute_values,
2147 else if (start_constant (context, element_name,
2148 attribute_names, attribute_values,
2151 else if (start_class (context, element_name,
2152 attribute_names, attribute_values,
2155 else if (strcmp (element_name, "class") == 0 &&
2156 ctx->state == STATE_REQUIRES)
2160 name = find_attribute ("name", attribute_names, attribute_values);
2163 MISSING_ATTRIBUTE (context, error, element_name, "name");
2166 GIrNodeInterface *iface;
2168 iface = (GIrNodeInterface *)ctx->current_node;
2169 iface ->prerequisites = g_list_append (iface->prerequisites, g_strdup (name));
2177 if (start_discriminator (context, element_name,
2178 attribute_names, attribute_values,
2184 if (start_enum (context, element_name,
2185 attribute_names, attribute_values,
2188 else if (start_errordomain (context, element_name,
2189 attribute_names, attribute_values,
2195 if (start_function (context, element_name,
2196 attribute_names, attribute_values,
2199 else if (start_field (context, element_name,
2200 attribute_names, attribute_values,
2206 if (start_glib_boxed (context, element_name,
2207 attribute_names, attribute_values,
2210 else if (start_glib_signal (context, element_name,
2211 attribute_names, attribute_values,
2217 if (strcmp (element_name, "include") == 0 &&
2218 ctx->state == STATE_REPOSITORY)
2222 name = find_attribute ("name", attribute_names, attribute_values);
2226 MISSING_ATTRIBUTE (context, error, element_name, "name");
2230 if (!parse_include (context, ctx, name, error))
2233 ctx->dependencies = g_list_prepend (ctx->dependencies, g_strdup (name));
2236 state_switch (ctx, STATE_INCLUDE);
2239 if (start_interface (context, element_name,
2240 attribute_names, attribute_values,
2243 else if (start_implements (context, element_name,
2244 attribute_names, attribute_values,
2250 if (start_function (context, element_name,
2251 attribute_names, attribute_values,
2254 else if (start_member (context, element_name,
2255 attribute_names, attribute_values,
2261 if (strcmp (element_name, "namespace") == 0 && ctx->state == STATE_REPOSITORY)
2263 const gchar *name, *version, *shared_library;
2265 name = find_attribute ("name", attribute_names, attribute_values);
2266 version = find_attribute ("version", attribute_names, attribute_values);
2267 shared_library = find_attribute ("shared-library", attribute_names, attribute_values);
2270 MISSING_ATTRIBUTE (context, error, element_name, "name");
2271 else if (version == NULL)
2272 MISSING_ATTRIBUTE (context, error, element_name, "version");
2275 ctx->current_module = g_ir_module_new (name, version, shared_library);
2276 ctx->modules = g_list_append (ctx->modules, ctx->current_module);
2277 ctx->current_module->dependencies = ctx->dependencies;
2279 state_switch (ctx, STATE_NAMESPACE);
2286 if (start_property (context, element_name,
2287 attribute_names, attribute_values,
2290 else if (strcmp (element_name, "parameters") == 0 &&
2291 ctx->state == STATE_FUNCTION)
2293 state_switch (ctx, STATE_FUNCTION_PARAMETERS);
2297 else if (start_parameter (context, element_name,
2298 attribute_names, attribute_values,
2305 if (strcmp (element_name, "repository") == 0 && ctx->state == STATE_START)
2307 const gchar *version;
2309 version = find_attribute ("version", attribute_names, attribute_values);
2311 if (version == NULL)
2312 MISSING_ATTRIBUTE (context, error, element_name, "version");
2313 else if (strcmp (version, "1.0") != 0)
2316 G_MARKUP_ERROR_INVALID_CONTENT,
2317 "Unsupported version '%s'",
2320 state_switch (ctx, STATE_REPOSITORY);
2324 else if (start_return_value (context, element_name,
2325 attribute_names, attribute_values,
2328 else if (strcmp (element_name, "requires") == 0 &&
2329 ctx->state == STATE_INTERFACE)
2331 state_switch (ctx, STATE_REQUIRES);
2335 else if (start_struct (context, element_name,
2336 attribute_names, attribute_values,
2342 if (start_union (context, element_name,
2343 attribute_names, attribute_values,
2349 if (start_type (context, element_name,
2350 attribute_names, attribute_values,
2356 if (start_vfunc (context, element_name,
2357 attribute_names, attribute_values,
2360 if (start_type (context, element_name,
2361 attribute_names, attribute_values,
2367 g_markup_parse_context_get_position (context, &line_number, &char_number);
2369 if (error && *error == NULL)
2372 G_MARKUP_ERROR_UNKNOWN_ELEMENT,
2373 "Unexpected start tag '%s' on line %d char %d; current state=%d",
2375 line_number, char_number, ctx->state);
2380 g_markup_parse_context_get_position (context, &line_number, &char_number);
2382 fprintf (stderr, "Error at line %d, character %d: %s\n", line_number, char_number, (*error)->message);
2383 backtrace_stderr ();
2388 require_one_of_end_elements (GMarkupParseContext *context,
2390 const char *actual_name,
2395 int line_number, char_number;
2396 const char *expected;
2397 gboolean matched = FALSE;
2399 va_start (args, error);
2401 while ((expected = va_arg (args, const char*)) != NULL)
2403 if (strcmp (expected, actual_name) == 0)
2415 g_markup_parse_context_get_position (context, &line_number, &char_number);
2418 G_MARKUP_ERROR_INVALID_CONTENT,
2419 "Unexpected end tag '%s' on line %d char %d; current state=%d",
2421 line_number, char_number, ctx->state);
2427 require_end_element (GMarkupParseContext *context,
2429 const char *expected_name,
2430 const char *actual_name,
2433 return require_one_of_end_elements (context, ctx, actual_name, error, expected_name, NULL);
2437 end_element_handler (GMarkupParseContext *context,
2438 const gchar *element_name,
2442 ParseContext *ctx = user_data;
2444 g_debug ("</%s>", element_name);
2450 /* no need to GError here, GMarkup already catches this */
2453 case STATE_REPOSITORY:
2454 state_switch (ctx, STATE_END);
2458 if (require_end_element (context, ctx, "include", element_name, error))
2460 state_switch (ctx, STATE_REPOSITORY);
2464 case STATE_NAMESPACE:
2465 if (require_end_element (context, ctx, "namespace", element_name, error))
2467 ctx->current_module = NULL;
2468 state_switch (ctx, STATE_REPOSITORY);
2473 if (require_end_element (context, ctx, "alias", element_name, error))
2475 state_switch (ctx, STATE_NAMESPACE);
2479 case STATE_FUNCTION_RETURN:
2480 if (strcmp ("type", element_name) == 0)
2482 if (require_end_element (context, ctx, "return-value", element_name, error))
2484 state_switch (ctx, STATE_FUNCTION);
2488 case STATE_FUNCTION_PARAMETERS:
2489 if (require_end_element (context, ctx, "parameters", element_name, error))
2491 state_switch (ctx, STATE_FUNCTION);
2495 case STATE_FUNCTION_PARAMETER:
2496 if (strcmp ("type", element_name) == 0)
2498 if (require_end_element (context, ctx, "parameter", element_name, error))
2500 state_switch (ctx, STATE_FUNCTION_PARAMETERS);
2504 case STATE_FUNCTION:
2506 gboolean current_is_toplevel;
2507 GList *last = g_list_last (ctx->current_module->entries);
2509 current_is_toplevel = ctx->current_node == last->data;
2511 if (current_is_toplevel)
2513 ctx->current_node = NULL;
2514 state_switch (ctx, STATE_NAMESPACE);
2518 ctx->current_node = g_list_last (ctx->current_module->entries)->data;
2519 if (ctx->current_node->type == G_IR_NODE_INTERFACE)
2520 state_switch (ctx, STATE_INTERFACE);
2521 else if (ctx->current_node->type == G_IR_NODE_OBJECT)
2522 state_switch (ctx, STATE_CLASS);
2523 else if (ctx->current_node->type == G_IR_NODE_BOXED)
2524 state_switch (ctx, STATE_BOXED);
2525 else if (ctx->current_node->type == G_IR_NODE_STRUCT)
2526 state_switch (ctx, STATE_STRUCT);
2527 else if (ctx->current_node->type == G_IR_NODE_UNION)
2528 state_switch (ctx, STATE_UNION);
2531 int line_number, char_number;
2532 g_markup_parse_context_get_position (context, &line_number, &char_number);
2535 G_MARKUP_ERROR_INVALID_CONTENT,
2536 "Unexpected end tag '%s' on line %d char %d",
2538 line_number, char_number);
2544 case STATE_CLASS_FIELD:
2545 if (strcmp ("type", element_name) == 0)
2547 if (require_end_element (context, ctx, "field", element_name, error))
2549 state_switch (ctx, STATE_CLASS);
2553 case STATE_CLASS_PROPERTY:
2554 if (strcmp ("type", element_name) == 0)
2556 if (require_end_element (context, ctx, "property", element_name, error))
2558 state_switch (ctx, STATE_CLASS);
2563 if (require_end_element (context, ctx, "class", element_name, error))
2565 ctx->current_node = NULL;
2566 state_switch (ctx, STATE_NAMESPACE);
2570 case STATE_ERRORDOMAIN:
2571 if (require_end_element (context, ctx, "errordomain", element_name, error))
2573 ctx->current_node = NULL;
2574 state_switch (ctx, STATE_NAMESPACE);
2578 case STATE_INTERFACE_PROPERTY:
2579 if (strcmp ("type", element_name) == 0)
2581 if (require_end_element (context, ctx, "property", element_name, error))
2583 state_switch (ctx, STATE_INTERFACE);
2587 case STATE_INTERFACE_FIELD:
2588 if (strcmp ("type", element_name) == 0)
2590 if (require_end_element (context, ctx, "field", element_name, error))
2592 state_switch (ctx, STATE_INTERFACE);
2596 case STATE_INTERFACE:
2597 if (require_end_element (context, ctx, "interface", element_name, error))
2599 ctx->current_node = NULL;
2600 state_switch (ctx, STATE_NAMESPACE);
2605 if (strcmp ("member", element_name) == 0)
2607 else if (require_one_of_end_elements (context, ctx,
2608 element_name, error, "enumeration",
2611 ctx->current_node = NULL;
2612 state_switch (ctx, STATE_NAMESPACE);
2617 if (require_end_element (context, ctx, "glib:boxed", element_name, error))
2619 ctx->current_node = NULL;
2620 state_switch (ctx, STATE_NAMESPACE);
2624 case STATE_BOXED_FIELD:
2625 if (strcmp ("type", element_name) == 0)
2627 if (require_end_element (context, ctx, "field", element_name, error))
2629 state_switch (ctx, STATE_BOXED);
2633 case STATE_STRUCT_FIELD:
2634 if (strcmp ("type", element_name) == 0)
2636 if (require_end_element (context, ctx, "field", element_name, error))
2638 state_switch (ctx, STATE_STRUCT);
2643 if (require_end_element (context, ctx, "record", element_name, error))
2645 ctx->current_node = NULL;
2646 state_switch (ctx, STATE_NAMESPACE);
2650 case STATE_UNION_FIELD:
2651 if (strcmp ("type", element_name) == 0)
2653 if (require_end_element (context, ctx, "field", element_name, error))
2655 state_switch (ctx, STATE_UNION);
2660 if (require_end_element (context, ctx, "union", element_name, error))
2662 ctx->current_node = NULL;
2663 state_switch (ctx, STATE_NAMESPACE);
2666 case STATE_IMPLEMENTS:
2667 if (strcmp ("interface", element_name) == 0)
2669 if (require_end_element (context, ctx, "implements", element_name, error))
2670 state_switch (ctx, STATE_CLASS);
2672 case STATE_REQUIRES:
2673 if (require_end_element (context, ctx, "requires", element_name, error))
2674 state_switch (ctx, STATE_INTERFACE);
2676 case STATE_NAMESPACE_CONSTANT:
2677 case STATE_CLASS_CONSTANT:
2678 case STATE_INTERFACE_CONSTANT:
2679 if (strcmp ("type", element_name) == 0)
2681 if (require_end_element (context, ctx, "constant", element_name, error))
2683 ctx->current_node = NULL;
2686 case STATE_NAMESPACE_CONSTANT:
2687 state_switch (ctx, STATE_NAMESPACE);
2689 case STATE_CLASS_CONSTANT:
2690 state_switch (ctx, STATE_CLASS);
2692 case STATE_INTERFACE_CONSTANT:
2693 state_switch (ctx, STATE_INTERFACE);
2696 g_assert_not_reached ();
2702 if ((strcmp ("type", element_name) == 0) || (strcmp ("array", element_name) == 0) ||
2703 (strcmp ("varargs", element_name) == 0))
2709 g_error ("Unhandled state %d in end_element_handler\n", ctx->state);
2714 text_handler (GMarkupParseContext *context,
2720 /* FIXME warn about non-whitespace text */
2724 cleanup (GMarkupParseContext *context,
2728 ParseContext *ctx = user_data;
2730 int line_number, char_number;
2732 for (m = ctx->modules; m; m = m->next)
2733 g_ir_module_free (m->data);
2734 g_list_free (ctx->modules);
2735 ctx->modules = NULL;
2737 ctx->current_module = NULL;
2740 static GMarkupParser parser =
2742 start_element_handler,
2743 end_element_handler,
2750 post_filter_varargs_functions (GList *list)
2758 GIrNode *node = iter->data;
2762 if (node->type == G_IR_NODE_FUNCTION)
2764 if (((GIrNodeFunction*)node)->is_varargs)
2766 list = g_list_delete_link (list, link);
2774 post_filter (GIrModule *module)
2778 module->entries = post_filter_varargs_functions (module->entries);
2779 iter = module->entries;
2783 GIrNode *node = iter->data;
2787 if (node->type == G_IR_NODE_OBJECT ||
2788 node->type == G_IR_NODE_INTERFACE)
2790 GIrNodeInterface *iface = (GIrNodeInterface*)node;
2791 iface->members = post_filter_varargs_functions (iface->members);
2793 else if (node->type == G_IR_NODE_BOXED)
2795 GIrNodeBoxed *boxed = (GIrNodeBoxed*)node;
2796 boxed->members = post_filter_varargs_functions (boxed->members);
2798 else if (node->type == G_IR_NODE_STRUCT)
2800 GIrNodeStruct *iface = (GIrNodeStruct*)node;
2801 iface->members = post_filter_varargs_functions (iface->members);
2803 else if (node->type == G_IR_NODE_UNION)
2805 GIrNodeUnion *iface = (GIrNodeUnion*)node;
2806 iface->members = post_filter_varargs_functions (iface->members);
2812 g_ir_parse_string (const gchar *namespace,
2813 const gchar *const *includes,
2814 const gchar *buffer,
2818 ParseContext ctx = { 0 };
2819 GMarkupParseContext *context;
2821 ctx.state = STATE_START;
2822 ctx.includes = includes;
2823 ctx.prefix_aliases = FALSE;
2824 ctx.namespace = namespace;
2825 ctx.aliases = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
2827 ctx.dependencies = NULL;
2828 ctx.current_module = NULL;
2830 context = g_markup_parse_context_new (&firstpass_parser, 0, &ctx, NULL);
2832 if (!g_markup_parse_context_parse (context, buffer, length, error))
2835 if (!g_markup_parse_context_end_parse (context, error))
2838 g_markup_parse_context_free (context);
2840 context = g_markup_parse_context_new (&parser, 0, &ctx, NULL);
2841 if (!g_markup_parse_context_parse (context, buffer, length, error))
2844 if (!g_markup_parse_context_end_parse (context, error))
2849 g_hash_table_destroy (ctx.aliases);
2851 g_markup_parse_context_free (context);
2857 g_ir_parse_file (const gchar *filename,
2858 const gchar *const *includes,
2868 if (!g_str_has_suffix (filename, ".gir"))
2872 G_MARKUP_ERROR_INVALID_CONTENT,
2873 "Expected filename to end with '.gir'");
2877 g_debug ("[parsing] filename %s", filename);
2879 slash = g_strrstr (filename, "/");
2881 namespace = g_strdup (filename);
2883 namespace = g_strdup (slash+1);
2884 namespace[strlen(namespace)-4] = '\0';
2886 if (!g_file_get_contents (filename, &buffer, &length, error))
2889 modules = g_ir_parse_string (namespace, includes, buffer, length, error);
2891 for (iter = modules; iter; iter = iter->next)
2893 post_filter ((GIrModule*)iter->data);