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,
121 static GMarkupParser firstpass_parser =
123 firstpass_start_element_handler,
124 firstpass_end_element_handler,
131 locate_gir (const char *name, const char *version, const char * const* extra_paths)
133 const gchar *const *datadirs;
134 const gchar *const *dir;
138 datadirs = g_get_system_data_dirs ();
140 girname = g_strdup_printf ("%s-%s.gir", name, version);
142 for (dir = datadirs; *dir; dir++)
144 path = g_build_filename (*dir, "gir", girname, NULL);
145 if (g_file_test (path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))
150 if (extra_paths != NULL)
152 for (dir = extra_paths; *dir; dir++)
154 path = g_build_filename (*dir, girname, NULL);
155 if (g_file_test (path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))
165 #define MISSING_ATTRIBUTE(ctx,error,element,attribute) \
167 int line_number, char_number; \
168 g_markup_parse_context_get_position (context, &line_number, &char_number); \
169 g_set_error (error, \
171 G_MARKUP_ERROR_INVALID_CONTENT, \
172 "Line %d, character %d: The attribute '%s' on the element '%s' must be specified", \
173 line_number, char_number, attribute, element); \
177 backtrace_stderr (void)
179 #if defined(HAVE_BACKTRACE) && defined(HAVE_BACKTRACE_SYMBOLS)
185 size = backtrace (array, 50);
186 strings = (char**) backtrace_symbols (array, size);
188 fprintf (stderr, "--- BACKTRACE (%zd frames) ---\n", size);
190 for (i = 0; i < size; i++)
191 fprintf (stderr, "%s\n", strings[i]);
193 fprintf (stderr, "--- END BACKTRACE ---\n", size);
201 find_attribute (const gchar *name,
202 const gchar **attribute_names,
203 const gchar **attribute_values)
207 for (i = 0; attribute_names[i] != NULL; i++)
208 if (strcmp (attribute_names[i], name) == 0)
209 return attribute_values[i];
215 state_switch (ParseContext *ctx, ParseState newstate)
217 g_debug ("State: %d", newstate);
218 ctx->prev_state = ctx->state;
219 ctx->state = newstate;
222 static GIrNodeType * parse_type_internal (const gchar *str, gchar **next, gboolean in_glib,
223 gboolean in_gobject);
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 { "time_t", GI_TYPE_TAG_TIME_T, 0 },
256 { "GType", GI_TYPE_TAG_GTYPE, 0 },
257 { "utf8", GI_TYPE_TAG_UTF8, 1 },
258 { "filename", GI_TYPE_TAG_FILENAME,1 },
261 static const BasicTypeInfo *
262 parse_basic (const char *str)
265 gint n_basic = G_N_ELEMENTS (basic_types);
267 for (i = 0; i < n_basic; i++)
269 if (g_str_has_prefix (str, basic_types[i].str))
270 return &(basic_types[i]);
276 parse_type_internal (const gchar *str, char **next, gboolean in_glib,
279 const BasicTypeInfo *basic;
281 char *temporary_type = NULL;
283 type = (GIrNodeType *)g_ir_node_new (G_IR_NODE_TYPE);
285 type->unparsed = g_strdup (str);
287 /* See comment below on GLib.List handling */
288 if (in_gobject && strcmp (str, "Type") == 0)
290 temporary_type = g_strdup ("GLib.Type");
291 str = temporary_type;
294 basic = parse_basic (str);
297 type->is_basic = TRUE;
298 type->tag = basic->tag;
299 type->is_pointer = basic->pointer;
301 str += strlen(basic->str);
305 /* If we're inside GLib, handle "List" etc. by prefixing with
306 * "GLib." so the parsing code below doesn't have to get more
309 if (g_str_has_prefix (str, "List<") ||
310 strcmp (str, "List") == 0)
312 temporary_type = g_strdup_printf ("GLib.List%s", str + 4);
313 str = temporary_type;
315 else if (g_str_has_prefix (str, "SList<") ||
316 strcmp (str, "SList") == 0)
318 temporary_type = g_strdup_printf ("GLib.SList%s", str + 5);
319 str = temporary_type;
321 else if (g_str_has_prefix (str, "HashTable<") ||
322 strcmp (str, "HashTable") == 0)
324 temporary_type = g_strdup_printf ("GLib.HashTable%s", str + 9);
325 str = temporary_type;
327 else if (g_str_has_prefix (str, "Error<") ||
328 strcmp (str, "Error") == 0)
330 temporary_type = g_strdup_printf ("GLib.Error%s", str + 5);
331 str = temporary_type;
336 /* found a basic type */;
337 else if (g_str_has_prefix (str, "GLib.List") ||
338 g_str_has_prefix (str, "GLib.SList"))
340 str += strlen ("GLib.");
341 if (g_str_has_prefix (str, "List"))
343 type->tag = GI_TYPE_TAG_GLIST;
344 type->is_glist = TRUE;
345 type->is_pointer = TRUE;
346 str += strlen ("List");
350 type->tag = GI_TYPE_TAG_GSLIST;
351 type->is_gslist = TRUE;
352 type->is_pointer = TRUE;
353 str += strlen ("SList");
356 else if (g_str_has_prefix (str, "GLib.HashTable"))
358 str += strlen ("GLib.");
360 type->tag = GI_TYPE_TAG_GHASH;
361 type->is_ghashtable = TRUE;
362 type->is_pointer = TRUE;
363 str += strlen ("HashTable");
365 else if (g_str_has_prefix (str, "GLib.Error"))
367 str += strlen ("GLib.");
369 type->tag = GI_TYPE_TAG_ERROR;
370 type->is_error = TRUE;
371 type->is_pointer = TRUE;
372 str += strlen ("Error");
379 end = strchr (str, '>');
380 tmp = g_strndup (str, end - str);
381 type->errors = g_strsplit (tmp, ",", 0);
389 type->tag = GI_TYPE_TAG_INTERFACE;
390 type->is_interface = TRUE;
391 const char *start = str;
393 /* must be an interface type */
394 while (g_ascii_isalnum (*str) ||
401 type->interface = g_strndup (start, str - start);
406 g_assert (type->tag >= 0 && type->tag <= GI_TYPE_TAG_ERROR);
407 g_free (temporary_type);
411 g_ir_node_free ((GIrNode *)type);
412 g_free (temporary_type);
417 resolve_aliases (ParseContext *ctx, const gchar *type)
421 GSList *seen_values = NULL;
423 seen_values = g_slist_prepend (seen_values, (char*)type);
424 while (g_hash_table_lookup_extended (ctx->aliases, type, &orig, &value))
426 g_debug ("Resolved: %s => %s", type, (char*)value);
428 if (g_slist_find_custom (seen_values, type,
429 (GCompareFunc)strcmp) != NULL)
431 seen_values = g_slist_prepend (seen_values, (gchar*)type);
433 g_slist_free (seen_values);
438 parse_type (ParseContext *ctx, const gchar *type)
441 const BasicTypeInfo *basic;
442 gboolean in_glib, in_gobject;
444 in_glib = strcmp (ctx->namespace, "GLib") == 0;
445 in_gobject = strcmp (ctx->namespace, "GObject") == 0;
447 /* Do not search aliases for basic types */
448 basic = parse_basic (type);
450 type = resolve_aliases (ctx, type);
452 node = parse_type_internal (type, NULL, in_glib, in_gobject);
454 g_debug ("Parsed type: %s => %d", type, node->tag);
456 g_critical ("Failed to parse type: '%s'", type);
462 start_glib_boxed (GMarkupParseContext *context,
463 const gchar *element_name,
464 const gchar **attribute_names,
465 const gchar **attribute_values,
470 const gchar *typename;
471 const gchar *typeinit;
472 const gchar *deprecated;
475 if (!(strcmp (element_name, "glib:boxed") == 0 &&
476 ctx->state == STATE_NAMESPACE))
479 name = find_attribute ("glib:name", attribute_names, attribute_values);
480 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
481 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
482 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
486 MISSING_ATTRIBUTE (context, error, element_name, "glib:name");
489 else if (typename == NULL)
491 MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
494 else if (typeinit == NULL)
496 MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
500 boxed = (GIrNodeBoxed *) g_ir_node_new (G_IR_NODE_BOXED);
502 ((GIrNode *)boxed)->name = g_strdup (name);
503 boxed->gtype_name = g_strdup (typename);
504 boxed->gtype_init = g_strdup (typeinit);
506 boxed->deprecated = TRUE;
508 boxed->deprecated = FALSE;
510 ctx->current_node = (GIrNode *)boxed;
511 ctx->current_module->entries =
512 g_list_append (ctx->current_module->entries, boxed);
514 state_switch (ctx, STATE_BOXED);
520 start_function (GMarkupParseContext *context,
521 const gchar *element_name,
522 const gchar **attribute_names,
523 const gchar **attribute_values,
529 const gchar *deprecated;
530 GIrNodeFunction *function;
531 gboolean found = FALSE;
535 case STATE_NAMESPACE:
536 found = (strcmp (element_name, "function") == 0 ||
537 strcmp (element_name, "callback") == 0);
543 found = strcmp (element_name, "constructor") == 0;
545 case STATE_INTERFACE:
547 strcmp (element_name, "method") == 0 ||
548 strcmp (element_name, "callback") == 0);
557 name = find_attribute ("name", attribute_names, attribute_values);
558 symbol = find_attribute ("c:identifier", attribute_names, attribute_values);
559 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
563 MISSING_ATTRIBUTE (context, error, element_name, "name");
566 else if (strcmp (element_name, "callback") != 0 && symbol == NULL)
568 MISSING_ATTRIBUTE (context, error, element_name, "c:identifier");
572 function = (GIrNodeFunction *) g_ir_node_new (G_IR_NODE_FUNCTION);
574 ((GIrNode *)function)->name = g_strdup (name);
575 function->symbol = g_strdup (symbol);
576 function->parameters = NULL;
578 function->deprecated = TRUE;
580 function->deprecated = FALSE;
582 if (strcmp (element_name, "method") == 0 ||
583 strcmp (element_name, "constructor") == 0)
585 function->is_method = TRUE;
587 if (strcmp (element_name, "constructor") == 0)
588 function->is_constructor = TRUE;
590 function->is_constructor = FALSE;
594 function->is_method = FALSE;
595 function->is_setter = FALSE;
596 function->is_getter = FALSE;
597 function->is_constructor = FALSE;
598 if (strcmp (element_name, "callback") == 0)
599 ((GIrNode *)function)->type = G_IR_NODE_CALLBACK;
602 if (ctx->current_node == NULL)
604 ctx->current_module->entries =
605 g_list_append (ctx->current_module->entries, function);
608 switch (ctx->current_node->type)
610 case G_IR_NODE_INTERFACE:
611 case G_IR_NODE_OBJECT:
613 GIrNodeInterface *iface;
615 iface = (GIrNodeInterface *)ctx->current_node;
616 iface->members = g_list_append (iface->members, function);
619 case G_IR_NODE_BOXED:
623 boxed = (GIrNodeBoxed *)ctx->current_node;
624 boxed->members = g_list_append (boxed->members, function);
627 case G_IR_NODE_STRUCT:
629 GIrNodeStruct *struct_;
631 struct_ = (GIrNodeStruct *)ctx->current_node;
632 struct_->members = g_list_append (struct_->members, function); }
634 case G_IR_NODE_UNION:
636 GIrNodeUnion *union_;
638 union_ = (GIrNodeUnion *)ctx->current_node;
639 union_->members = g_list_append (union_->members, function);
643 g_assert_not_reached ();
646 ctx->current_node = (GIrNode *)function;
647 state_switch (ctx, STATE_FUNCTION);
653 parse_param_transfer (GIrNodeParam *param, const gchar *transfer)
655 if (transfer && strcmp (transfer, "none") == 0)
657 param->transfer = FALSE;
658 param->shallow_transfer = FALSE;
660 else if (transfer && strcmp (transfer, "container") == 0)
662 param->transfer = FALSE;
663 param->shallow_transfer = TRUE;
669 if (strcmp (transfer, "full") != 0)
670 g_warning ("Unknown transfer %s", transfer);
672 param->transfer = TRUE;
674 else if (param->in && !param->out)
675 param->transfer = FALSE;
677 param->transfer = TRUE;
678 param->shallow_transfer = FALSE;
683 start_parameter (GMarkupParseContext *context,
684 const gchar *element_name,
685 const gchar **attribute_names,
686 const gchar **attribute_values,
691 const gchar *direction;
694 const gchar *optional;
696 const gchar *transfer;
699 if (!(strcmp (element_name, "parameter") == 0 &&
700 ctx->state == STATE_FUNCTION_PARAMETERS))
703 name = find_attribute ("name", attribute_names, attribute_values);
704 direction = find_attribute ("direction", attribute_names, attribute_values);
705 retval = find_attribute ("retval", attribute_names, attribute_values);
706 dipper = find_attribute ("dipper", attribute_names, attribute_values);
707 optional = find_attribute ("optional", attribute_names, attribute_values);
708 nullok = find_attribute ("null-ok", attribute_names, attribute_values);
709 transfer = find_attribute ("transfer", attribute_names, attribute_values);
714 param = (GIrNodeParam *)g_ir_node_new (G_IR_NODE_PARAM);
716 ctx->current_typed = (GIrNode*) param;
717 ctx->current_typed->name = g_strdup (name);
719 state_switch (ctx, STATE_FUNCTION_PARAMETER);
721 if (direction && strcmp (direction, "out") == 0)
726 else if (direction && strcmp (direction, "inout") == 0)
737 if (retval && strcmp (retval, "1") == 0)
738 param->retval = TRUE;
740 param->retval = FALSE;
742 if (dipper && strcmp (dipper, "1") == 0)
743 param->dipper = TRUE;
745 param->dipper = FALSE;
747 if (optional && strcmp (optional, "1") == 0)
748 param->optional = TRUE;
750 param->optional = FALSE;
752 if (nullok && strcmp (nullok, "1") == 0)
753 param->null_ok = TRUE;
755 param->null_ok = FALSE;
757 parse_param_transfer (param, transfer);
759 ((GIrNode *)param)->name = g_strdup (name);
761 switch (ctx->current_node->type)
763 case G_IR_NODE_FUNCTION:
764 case G_IR_NODE_CALLBACK:
766 GIrNodeFunction *func;
768 func = (GIrNodeFunction *)ctx->current_node;
769 func->parameters = g_list_append (func->parameters, param);
772 case G_IR_NODE_SIGNAL:
774 GIrNodeSignal *signal;
776 signal = (GIrNodeSignal *)ctx->current_node;
777 signal->parameters = g_list_append (signal->parameters, param);
780 case G_IR_NODE_VFUNC:
784 vfunc = (GIrNodeVFunc *)ctx->current_node;
785 vfunc->parameters = g_list_append (vfunc->parameters, param);
789 g_assert_not_reached ();
796 start_field (GMarkupParseContext *context,
797 const gchar *element_name,
798 const gchar **attribute_names,
799 const gchar **attribute_values,
804 const gchar *readable;
805 const gchar *writable;
817 case STATE_INTERFACE:
823 if (strcmp (element_name, "field") != 0)
826 name = find_attribute ("name", attribute_names, attribute_values);
827 readable = find_attribute ("readable", attribute_names, attribute_values);
828 writable = find_attribute ("writable", attribute_names, attribute_values);
829 bits = find_attribute ("bits", attribute_names, attribute_values);
830 branch = find_attribute ("branch", attribute_names, attribute_values);
831 offset = find_attribute ("offset", attribute_names, attribute_values);
835 MISSING_ATTRIBUTE (context, error, element_name, "name");
839 field = (GIrNodeField *)g_ir_node_new (G_IR_NODE_FIELD);
840 ctx->current_typed = (GIrNode*) field;
841 ((GIrNode *)field)->name = g_strdup (name);
842 /* Fields are assumed to be read-only.
843 * (see also girwriter.py and generate.c)
845 field->readable = readable == NULL || strcmp (readable, "0") == 0;
846 field->writable = writable != NULL && strcmp (writable, "1") == 0;
849 field->bits = atoi (bits);
854 field->offset = atoi (offset);
858 switch (ctx->current_node->type)
860 case G_IR_NODE_OBJECT:
862 GIrNodeInterface *iface;
864 iface = (GIrNodeInterface *)ctx->current_node;
865 iface->members = g_list_append (iface->members, field);
866 state_switch (ctx, STATE_CLASS_FIELD);
869 case G_IR_NODE_INTERFACE:
871 GIrNodeInterface *iface;
873 iface = (GIrNodeInterface *)ctx->current_node;
874 iface->members = g_list_append (iface->members, field);
875 state_switch (ctx, STATE_INTERFACE_FIELD);
878 case G_IR_NODE_BOXED:
882 boxed = (GIrNodeBoxed *)ctx->current_node;
883 boxed->members = g_list_append (boxed->members, field);
884 state_switch (ctx, STATE_BOXED_FIELD);
887 case G_IR_NODE_STRUCT:
889 GIrNodeStruct *struct_;
891 struct_ = (GIrNodeStruct *)ctx->current_node;
892 struct_->members = g_list_append (struct_->members, field);
893 state_switch (ctx, STATE_STRUCT_FIELD);
896 case G_IR_NODE_UNION:
898 GIrNodeUnion *union_;
900 union_ = (GIrNodeUnion *)ctx->current_node;
901 union_->members = g_list_append (union_->members, field);
904 GIrNodeConstant *constant;
906 constant = (GIrNodeConstant *) g_ir_node_new (G_IR_NODE_CONSTANT);
907 ((GIrNode *)constant)->name = g_strdup (name);
908 constant->value = g_strdup (branch);
909 constant->type = union_->discriminator_type;
910 constant->deprecated = FALSE;
912 union_->discriminators = g_list_append (union_->discriminators, constant);
914 state_switch (ctx, STATE_UNION_FIELD);
918 g_assert_not_reached ();
925 start_alias (GMarkupParseContext *context,
926 const gchar *element_name,
927 const gchar **attribute_names,
928 const gchar **attribute_values,
937 name = find_attribute ("name", attribute_names, attribute_values);
940 MISSING_ATTRIBUTE (context, error, element_name, "name");
944 target = find_attribute ("target", attribute_names, attribute_values);
947 MISSING_ATTRIBUTE (context, error, element_name, "target");
951 value = g_strdup (target);
952 if (ctx->prefix_aliases)
954 key = g_strdup_printf ("%s.%s", ctx->namespace, name);
955 if (!strchr (target, '.'))
957 const BasicTypeInfo *basic = parse_basic (target);
961 /* For non-basic types, re-qualify the interface */
962 value = g_strdup_printf ("%s.%s", ctx->namespace, target);
968 key = g_strdup (name);
970 g_hash_table_insert (ctx->aliases, key, value);
976 start_enum (GMarkupParseContext *context,
977 const gchar *element_name,
978 const gchar **attribute_names,
979 const gchar **attribute_values,
983 if ((strcmp (element_name, "enumeration") == 0 && ctx->state == STATE_NAMESPACE) ||
984 (strcmp (element_name, "bitfield") == 0 && ctx->state == STATE_NAMESPACE))
987 const gchar *typename;
988 const gchar *typeinit;
989 const gchar *deprecated;
991 name = find_attribute ("name", attribute_names, attribute_values);
992 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
993 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
994 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
997 MISSING_ATTRIBUTE (context, error, element_name, "name");
1002 if (strcmp (element_name, "enumeration") == 0)
1003 enum_ = (GIrNodeEnum *) g_ir_node_new (G_IR_NODE_ENUM);
1005 enum_ = (GIrNodeEnum *) g_ir_node_new (G_IR_NODE_FLAGS);
1006 ((GIrNode *)enum_)->name = g_strdup (name);
1007 enum_->gtype_name = g_strdup (typename);
1008 enum_->gtype_init = g_strdup (typeinit);
1010 enum_->deprecated = TRUE;
1012 enum_->deprecated = FALSE;
1014 ctx->current_node = (GIrNode *) enum_;
1015 ctx->current_module->entries =
1016 g_list_append (ctx->current_module->entries, enum_);
1018 state_switch (ctx, STATE_ENUM);
1027 start_property (GMarkupParseContext *context,
1028 const gchar *element_name,
1029 const gchar **attribute_names,
1030 const gchar **attribute_values,
1034 if (strcmp (element_name, "property") == 0 &&
1035 (ctx->state == STATE_CLASS ||
1036 ctx->state == STATE_INTERFACE))
1039 const gchar *readable;
1040 const gchar *writable;
1041 const gchar *construct;
1042 const gchar *construct_only;
1044 name = find_attribute ("name", attribute_names, attribute_values);
1045 readable = find_attribute ("readable", attribute_names, attribute_values);
1046 writable = find_attribute ("writable", attribute_names, attribute_values);
1047 construct = find_attribute ("construct", attribute_names, attribute_values);
1048 construct_only = find_attribute ("construct-only", attribute_names, attribute_values);
1051 MISSING_ATTRIBUTE (context, error, element_name, "name");
1054 GIrNodeProperty *property;
1055 GIrNodeInterface *iface;
1057 property = (GIrNodeProperty *) g_ir_node_new (G_IR_NODE_PROPERTY);
1058 ctx->current_typed = (GIrNode*) property;
1060 ((GIrNode *)property)->name = g_strdup (name);
1062 /* Assume properties are readable */
1063 if (readable == NULL || strcmp (readable, "1") == 0)
1064 property->readable = TRUE;
1066 property->readable = FALSE;
1067 if (writable && strcmp (writable, "1") == 0)
1068 property->writable = TRUE;
1070 property->writable = FALSE;
1071 if (construct && strcmp (construct, "1") == 0)
1072 property->construct = TRUE;
1074 property->construct = FALSE;
1075 if (construct_only && strcmp (construct_only, "1") == 0)
1076 property->construct_only = TRUE;
1078 property->construct_only = FALSE;
1080 iface = (GIrNodeInterface *)ctx->current_node;
1081 iface->members = g_list_append (iface->members, property);
1083 if (ctx->state == STATE_CLASS)
1084 state_switch (ctx, STATE_CLASS_PROPERTY);
1085 else if (ctx->state == STATE_INTERFACE)
1086 state_switch (ctx, STATE_INTERFACE_PROPERTY);
1088 g_assert_not_reached ();
1097 parse_value (const gchar *str)
1101 /* FIXME just a quick hack */
1102 shift_op = strstr (str, "<<");
1108 base = strtol (str, NULL, 10);
1109 shift = strtol (shift_op + 3, NULL, 10);
1111 return base << shift;
1114 return strtol (str, NULL, 10);
1120 start_member (GMarkupParseContext *context,
1121 const gchar *element_name,
1122 const gchar **attribute_names,
1123 const gchar **attribute_values,
1127 if (strcmp (element_name, "member") == 0 &&
1128 ctx->state == STATE_ENUM)
1132 const gchar *deprecated;
1134 name = find_attribute ("name", attribute_names, attribute_values);
1135 value = find_attribute ("value", attribute_names, attribute_values);
1136 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1139 MISSING_ATTRIBUTE (context, error, element_name, "name");
1143 GIrNodeValue *value_;
1145 value_ = (GIrNodeValue *) g_ir_node_new (G_IR_NODE_VALUE);
1147 ((GIrNode *)value_)->name = g_strdup (name);
1149 value_->value = parse_value (value);
1152 value_->deprecated = TRUE;
1154 value_->deprecated = FALSE;
1156 enum_ = (GIrNodeEnum *)ctx->current_node;
1157 enum_->values = g_list_append (enum_->values, value_);
1166 start_constant (GMarkupParseContext *context,
1167 const gchar *element_name,
1168 const gchar **attribute_names,
1169 const gchar **attribute_values,
1173 if (strcmp (element_name, "constant") == 0 &&
1174 (ctx->state == STATE_NAMESPACE ||
1175 ctx->state == STATE_CLASS ||
1176 ctx->state == STATE_INTERFACE))
1180 const gchar *deprecated;
1182 name = find_attribute ("name", attribute_names, attribute_values);
1183 value = find_attribute ("value", attribute_names, attribute_values);
1184 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1187 MISSING_ATTRIBUTE (context, error, element_name, "name");
1188 else if (value == NULL)
1189 MISSING_ATTRIBUTE (context, error, element_name, "value");
1192 GIrNodeConstant *constant;
1194 constant = (GIrNodeConstant *) g_ir_node_new (G_IR_NODE_CONSTANT);
1196 ((GIrNode *)constant)->name = g_strdup (name);
1197 constant->value = g_strdup (value);
1199 ctx->current_typed = (GIrNode*) constant;
1202 constant->deprecated = TRUE;
1204 constant->deprecated = FALSE;
1206 if (ctx->state == STATE_NAMESPACE)
1208 ctx->current_node = (GIrNode *) constant;
1209 ctx->current_module->entries =
1210 g_list_append (ctx->current_module->entries, constant);
1214 GIrNodeInterface *iface;
1216 iface = (GIrNodeInterface *)ctx->current_node;
1217 iface->members = g_list_append (iface->members, constant);
1222 case STATE_NAMESPACE:
1223 state_switch (ctx, STATE_NAMESPACE_CONSTANT);
1226 state_switch (ctx, STATE_CLASS_CONSTANT);
1228 case STATE_INTERFACE:
1229 state_switch (ctx, STATE_INTERFACE_CONSTANT);
1232 g_assert_not_reached ();
1243 start_errordomain (GMarkupParseContext *context,
1244 const gchar *element_name,
1245 const gchar **attribute_names,
1246 const gchar **attribute_values,
1250 if (strcmp (element_name, "errordomain") == 0 &&
1251 ctx->state == STATE_NAMESPACE)
1254 const gchar *getquark;
1256 const gchar *deprecated;
1258 name = find_attribute ("name", attribute_names, attribute_values);
1259 getquark = find_attribute ("get-quark", attribute_names, attribute_values);
1260 codes = find_attribute ("codes", attribute_names, attribute_values);
1261 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1264 MISSING_ATTRIBUTE (context, error, element_name, "name");
1265 else if (getquark == NULL)
1266 MISSING_ATTRIBUTE (context, error, element_name, "getquark");
1267 else if (codes == NULL)
1268 MISSING_ATTRIBUTE (context, error, element_name, "codes");
1271 GIrNodeErrorDomain *domain;
1273 domain = (GIrNodeErrorDomain *) g_ir_node_new (G_IR_NODE_ERROR_DOMAIN);
1275 ((GIrNode *)domain)->name = g_strdup (name);
1276 domain->getquark = g_strdup (getquark);
1277 domain->codes = g_strdup (codes);
1280 domain->deprecated = TRUE;
1282 domain->deprecated = FALSE;
1284 ctx->current_node = (GIrNode *) domain;
1285 ctx->current_module->entries =
1286 g_list_append (ctx->current_module->entries, domain);
1288 state_switch (ctx, STATE_ERRORDOMAIN);
1297 start_interface (GMarkupParseContext *context,
1298 const gchar *element_name,
1299 const gchar **attribute_names,
1300 const gchar **attribute_values,
1304 if (strcmp (element_name, "interface") == 0 &&
1305 ctx->state == STATE_NAMESPACE)
1308 const gchar *typename;
1309 const gchar *typeinit;
1310 const gchar *deprecated;
1312 name = find_attribute ("name", attribute_names, attribute_values);
1313 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
1314 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
1315 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1318 MISSING_ATTRIBUTE (context, error, element_name, "name");
1319 else if (typename == NULL)
1320 MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
1321 else if (typeinit == NULL)
1322 MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
1325 GIrNodeInterface *iface;
1327 iface = (GIrNodeInterface *) g_ir_node_new (G_IR_NODE_INTERFACE);
1328 ((GIrNode *)iface)->name = g_strdup (name);
1329 iface->gtype_name = g_strdup (typename);
1330 iface->gtype_init = g_strdup (typeinit);
1332 iface->deprecated = TRUE;
1334 iface->deprecated = FALSE;
1336 ctx->current_node = (GIrNode *) iface;
1337 ctx->current_module->entries =
1338 g_list_append (ctx->current_module->entries, iface);
1340 state_switch (ctx, STATE_INTERFACE);
1350 start_class (GMarkupParseContext *context,
1351 const gchar *element_name,
1352 const gchar **attribute_names,
1353 const gchar **attribute_values,
1357 if (strcmp (element_name, "class") == 0 &&
1358 ctx->state == STATE_NAMESPACE)
1361 const gchar *parent;
1362 const gchar *typename;
1363 const gchar *typeinit;
1364 const gchar *deprecated;
1366 name = find_attribute ("name", attribute_names, attribute_values);
1367 parent = find_attribute ("parent", attribute_names, attribute_values);
1368 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
1369 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
1370 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1373 MISSING_ATTRIBUTE (context, error, element_name, "name");
1374 else if (typename == NULL)
1375 MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
1376 else if (typeinit == NULL && strcmp (typename, "GObject"))
1377 MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
1380 GIrNodeInterface *iface;
1382 iface = (GIrNodeInterface *) g_ir_node_new (G_IR_NODE_OBJECT);
1383 ((GIrNode *)iface)->name = g_strdup (name);
1384 iface->gtype_name = g_strdup (typename);
1385 iface->gtype_init = g_strdup (typeinit);
1386 iface->parent = g_strdup (parent);
1388 iface->deprecated = TRUE;
1390 iface->deprecated = FALSE;
1392 ctx->current_node = (GIrNode *) iface;
1393 ctx->current_module->entries =
1394 g_list_append (ctx->current_module->entries, iface);
1396 state_switch (ctx, STATE_CLASS);
1405 start_type (GMarkupParseContext *context,
1406 const gchar *element_name,
1407 const gchar **attribute_names,
1408 const gchar **attribute_values,
1415 gboolean is_varargs;
1416 GIrNodeType *typenode;
1418 is_array = strcmp (element_name, "array") == 0;
1419 is_varargs = strcmp (element_name, "varargs") == 0;
1421 if (!(is_array || is_varargs || (strcmp (element_name, "type") == 0)))
1424 if (ctx->state == STATE_TYPE)
1427 ctx->type_stack = g_list_prepend (ctx->type_stack, ctx->type_parameters);
1428 ctx->type_parameters = NULL;
1430 else if (ctx->state == STATE_FUNCTION_PARAMETER ||
1431 ctx->state == STATE_FUNCTION_RETURN ||
1432 ctx->state == STATE_STRUCT_FIELD ||
1433 ctx->state == STATE_UNION_FIELD ||
1434 ctx->state == STATE_CLASS_PROPERTY ||
1435 ctx->state == STATE_CLASS_FIELD ||
1436 ctx->state == STATE_INTERFACE_FIELD ||
1437 ctx->state == STATE_INTERFACE_PROPERTY ||
1438 ctx->state == STATE_BOXED_FIELD ||
1439 ctx->state == STATE_NAMESPACE_CONSTANT ||
1440 ctx->state == STATE_CLASS_CONSTANT ||
1441 ctx->state == STATE_INTERFACE_CONSTANT
1444 state_switch (ctx, STATE_TYPE);
1445 ctx->type_depth = 1;
1448 switch (ctx->current_node->type)
1450 case G_IR_NODE_FUNCTION:
1451 case G_IR_NODE_CALLBACK:
1453 GIrNodeFunction *func = (GIrNodeFunction *)ctx->current_node;
1454 func->is_varargs = TRUE;
1457 case G_IR_NODE_VFUNC:
1459 GIrNodeVFunc *vfunc = (GIrNodeVFunc *)ctx->current_node;
1460 vfunc->is_varargs = TRUE;
1463 /* list others individually rather than with default: so that compiler
1464 * warns if new node types are added without adding them to the switch
1466 case G_IR_NODE_INVALID:
1467 case G_IR_NODE_ENUM:
1468 case G_IR_NODE_FLAGS:
1469 case G_IR_NODE_CONSTANT:
1470 case G_IR_NODE_ERROR_DOMAIN:
1471 case G_IR_NODE_PARAM:
1472 case G_IR_NODE_TYPE:
1473 case G_IR_NODE_PROPERTY:
1474 case G_IR_NODE_SIGNAL:
1475 case G_IR_NODE_VALUE:
1476 case G_IR_NODE_FIELD:
1477 case G_IR_NODE_XREF:
1478 case G_IR_NODE_STRUCT:
1479 case G_IR_NODE_BOXED:
1480 case G_IR_NODE_OBJECT:
1481 case G_IR_NODE_INTERFACE:
1482 case G_IR_NODE_UNION:
1483 g_assert_not_reached ();
1487 ctx->type_stack = NULL;
1488 ctx->type_parameters = NULL;
1491 if (!ctx->current_typed)
1495 G_MARKUP_ERROR_INVALID_CONTENT,
1496 "The element <type> is invalid here");
1508 typenode = (GIrNodeType *)g_ir_node_new (G_IR_NODE_TYPE);
1510 typenode->tag = GI_TYPE_TAG_ARRAY;
1511 typenode->is_pointer = TRUE;
1512 typenode->is_array = TRUE;
1514 zero = find_attribute ("zero-terminated", attribute_names, attribute_values);
1515 len = find_attribute ("length", attribute_names, attribute_values);
1517 typenode->zero_terminated = !(zero && strcmp (zero, "1") != 0);
1518 typenode->has_length = len != NULL;
1519 typenode->length = typenode->has_length ? atoi (len) : -1;
1523 gboolean is_pointer;
1524 name = find_attribute ("name", attribute_names, attribute_values);
1527 MISSING_ATTRIBUTE (context, error, element_name, "name");
1529 ctype = find_attribute ("c:type", attribute_names, attribute_values);
1530 if (ctype != NULL && strchr (ctype, '*'))
1535 typenode = parse_type (ctx, name);
1538 typenode->is_pointer = is_pointer;
1541 ctx->type_parameters = g_list_append (ctx->type_parameters, typenode);
1547 end_type_top (ParseContext *ctx)
1549 GIrNodeType *typenode;
1551 if (!ctx->type_parameters)
1554 typenode = (GIrNodeType*)ctx->type_parameters->data;
1556 /* Default to pointer for unspecified containers */
1557 if (typenode->tag == GI_TYPE_TAG_ARRAY ||
1558 typenode->tag == GI_TYPE_TAG_GLIST ||
1559 typenode->tag == GI_TYPE_TAG_GSLIST)
1561 if (typenode->parameter_type1 == NULL)
1562 typenode->parameter_type1 = parse_type (ctx, "any");
1564 else if (typenode->tag == GI_TYPE_TAG_GHASH)
1566 if (typenode->parameter_type1 == NULL)
1568 typenode->parameter_type1 = parse_type (ctx, "any");
1569 typenode->parameter_type2 = parse_type (ctx, "any");
1573 switch (ctx->current_typed->type)
1575 case G_IR_NODE_PARAM:
1577 GIrNodeParam *param = (GIrNodeParam *)ctx->current_typed;
1578 param->type = typenode;
1581 case G_IR_NODE_FIELD:
1583 GIrNodeField *field = (GIrNodeField *)ctx->current_typed;
1584 field->type = typenode;
1587 case G_IR_NODE_PROPERTY:
1589 GIrNodeProperty *property = (GIrNodeProperty *) ctx->current_typed;
1590 property->type = typenode;
1593 case G_IR_NODE_CONSTANT:
1595 GIrNodeConstant *constant = (GIrNodeConstant *)ctx->current_typed;
1596 constant->type = typenode;
1600 g_printerr("current node is %d\n", ctx->current_node->type);
1601 g_assert_not_reached ();
1603 g_list_free (ctx->type_parameters);
1606 ctx->type_depth = 0;
1607 ctx->type_parameters = NULL;
1608 ctx->current_typed = NULL;
1612 end_type_recurse (ParseContext *ctx)
1614 GIrNodeType *parent;
1615 GIrNodeType *param = NULL;
1617 parent = (GIrNodeType *) ((GList*)ctx->type_stack->data)->data;
1618 if (ctx->type_parameters)
1619 param = (GIrNodeType *) ctx->type_parameters->data;
1621 if (parent->tag == GI_TYPE_TAG_ARRAY ||
1622 parent->tag == GI_TYPE_TAG_GLIST ||
1623 parent->tag == GI_TYPE_TAG_GSLIST)
1625 g_assert (param != NULL);
1627 if (parent->parameter_type1 == NULL)
1628 parent->parameter_type1 = param;
1630 g_assert_not_reached ();
1632 else if (parent->tag == GI_TYPE_TAG_GHASH)
1634 g_assert (param != NULL);
1636 if (parent->parameter_type1 == NULL)
1637 parent->parameter_type1 = param;
1638 else if (parent->parameter_type2 == NULL)
1639 parent->parameter_type2 = param;
1641 g_assert_not_reached ();
1643 g_list_free (ctx->type_parameters);
1644 ctx->type_parameters = (GList *)ctx->type_stack->data;
1645 ctx->type_stack = g_list_delete_link (ctx->type_stack, ctx->type_stack);
1649 end_type (ParseContext *ctx)
1651 if (ctx->type_depth == 1)
1654 state_switch (ctx, ctx->prev_state);
1658 end_type_recurse (ctx);
1664 start_return_value (GMarkupParseContext *context,
1665 const gchar *element_name,
1666 const gchar **attribute_names,
1667 const gchar **attribute_values,
1671 if (strcmp (element_name, "return-value") == 0 &&
1672 ctx->state == STATE_FUNCTION)
1674 GIrNodeParam *param;
1675 const gchar *transfer;
1677 param = (GIrNodeParam *)g_ir_node_new (G_IR_NODE_PARAM);
1680 param->retval = TRUE;
1682 ctx->current_typed = (GIrNode*) param;
1684 state_switch (ctx, STATE_FUNCTION_RETURN);
1686 transfer = find_attribute ("transfer-ownership", attribute_names, attribute_values);
1687 parse_param_transfer (param, transfer);
1689 switch (ctx->current_node->type)
1691 case G_IR_NODE_FUNCTION:
1692 case G_IR_NODE_CALLBACK:
1694 GIrNodeFunction *func = (GIrNodeFunction *)ctx->current_node;
1695 func->result = param;
1698 case G_IR_NODE_SIGNAL:
1700 GIrNodeSignal *signal = (GIrNodeSignal *)ctx->current_node;
1701 signal->result = param;
1704 case G_IR_NODE_VFUNC:
1706 GIrNodeVFunc *vfunc = (GIrNodeVFunc *)ctx->current_node;
1707 vfunc->result = param;
1711 g_assert_not_reached ();
1721 start_implements (GMarkupParseContext *context,
1722 const gchar *element_name,
1723 const gchar **attribute_names,
1724 const gchar **attribute_values,
1728 GIrNodeInterface *iface;
1731 if (strcmp (element_name, "implements") != 0 ||
1732 !(ctx->state == STATE_CLASS))
1735 state_switch (ctx, STATE_IMPLEMENTS);
1737 name = find_attribute ("name", attribute_names, attribute_values);
1740 MISSING_ATTRIBUTE (context, error, element_name, "name");
1744 iface = (GIrNodeInterface *)ctx->current_node;
1745 iface->interfaces = g_list_append (iface->interfaces, g_strdup (name));
1751 start_glib_signal (GMarkupParseContext *context,
1752 const gchar *element_name,
1753 const gchar **attribute_names,
1754 const gchar **attribute_values,
1758 if (strcmp (element_name, "glib:signal") == 0 &&
1759 (ctx->state == STATE_CLASS ||
1760 ctx->state == STATE_INTERFACE))
1764 const gchar *no_recurse;
1765 const gchar *detailed;
1766 const gchar *action;
1767 const gchar *no_hooks;
1768 const gchar *has_class_closure;
1770 name = find_attribute ("name", attribute_names, attribute_values);
1771 when = find_attribute ("when", attribute_names, attribute_values);
1772 no_recurse = find_attribute ("no-recurse", attribute_names, attribute_values);
1773 detailed = find_attribute ("detailed", attribute_names, attribute_values);
1774 action = find_attribute ("action", attribute_names, attribute_values);
1775 no_hooks = find_attribute ("no-hooks", attribute_names, attribute_values);
1776 has_class_closure = find_attribute ("has-class-closure", attribute_names, attribute_values);
1779 MISSING_ATTRIBUTE (context, error, element_name, "name");
1782 GIrNodeInterface *iface;
1783 GIrNodeSignal *signal;
1785 signal = (GIrNodeSignal *)g_ir_node_new (G_IR_NODE_SIGNAL);
1787 ((GIrNode *)signal)->name = g_strdup (name);
1789 signal->run_first = FALSE;
1790 signal->run_last = FALSE;
1791 signal->run_cleanup = FALSE;
1792 if (when == NULL || strcmp (when, "LAST") == 0)
1793 signal->run_last = TRUE;
1794 else if (strcmp (when, "FIRST") == 0)
1795 signal->run_first = TRUE;
1797 signal->run_cleanup = TRUE;
1799 if (no_recurse && strcmp (no_recurse, "1") == 0)
1800 signal->no_recurse = TRUE;
1802 signal->no_recurse = FALSE;
1803 if (detailed && strcmp (detailed, "1") == 0)
1804 signal->detailed = TRUE;
1806 signal->detailed = FALSE;
1807 if (action && strcmp (action, "1") == 0)
1808 signal->action = TRUE;
1810 signal->action = FALSE;
1811 if (no_hooks && strcmp (no_hooks, "1") == 0)
1812 signal->no_hooks = TRUE;
1814 signal->no_hooks = FALSE;
1815 if (has_class_closure && strcmp (has_class_closure, "1") == 0)
1816 signal->has_class_closure = TRUE;
1818 signal->has_class_closure = FALSE;
1820 iface = (GIrNodeInterface *)ctx->current_node;
1821 iface->members = g_list_append (iface->members, signal);
1823 ctx->current_node = (GIrNode *)signal;
1824 state_switch (ctx, STATE_FUNCTION);
1833 start_vfunc (GMarkupParseContext *context,
1834 const gchar *element_name,
1835 const gchar **attribute_names,
1836 const gchar **attribute_values,
1840 if (strcmp (element_name, "vfunc") == 0 &&
1841 (ctx->state == STATE_CLASS ||
1842 ctx->state == STATE_INTERFACE))
1845 const gchar *must_chain_up;
1846 const gchar *override;
1847 const gchar *is_class_closure;
1848 const gchar *offset;
1850 name = find_attribute ("name", attribute_names, attribute_values);
1851 must_chain_up = find_attribute ("must-chain-up", attribute_names, attribute_values);
1852 override = find_attribute ("override", attribute_names, attribute_values);
1853 is_class_closure = find_attribute ("is-class-closure", attribute_names, attribute_values);
1854 offset = find_attribute ("offset", attribute_names, attribute_values);
1857 MISSING_ATTRIBUTE (context, error, element_name, "name");
1860 GIrNodeInterface *iface;
1861 GIrNodeVFunc *vfunc;
1863 vfunc = (GIrNodeVFunc *)g_ir_node_new (G_IR_NODE_VFUNC);
1865 ((GIrNode *)vfunc)->name = g_strdup (name);
1867 if (must_chain_up && strcmp (must_chain_up, "1") == 0)
1868 vfunc->must_chain_up = TRUE;
1870 vfunc->must_chain_up = FALSE;
1872 if (override && strcmp (override, "always") == 0)
1874 vfunc->must_be_implemented = TRUE;
1875 vfunc->must_not_be_implemented = FALSE;
1877 else if (override && strcmp (override, "never") == 0)
1879 vfunc->must_be_implemented = FALSE;
1880 vfunc->must_not_be_implemented = TRUE;
1884 vfunc->must_be_implemented = FALSE;
1885 vfunc->must_not_be_implemented = FALSE;
1888 if (is_class_closure && strcmp (is_class_closure, "1") == 0)
1889 vfunc->is_class_closure = TRUE;
1891 vfunc->is_class_closure = FALSE;
1894 vfunc->offset = atoi (offset);
1898 iface = (GIrNodeInterface *)ctx->current_node;
1899 iface->members = g_list_append (iface->members, vfunc);
1901 ctx->current_node = (GIrNode *)vfunc;
1902 state_switch (ctx, STATE_FUNCTION);
1912 start_struct (GMarkupParseContext *context,
1913 const gchar *element_name,
1914 const gchar **attribute_names,
1915 const gchar **attribute_values,
1919 if (strcmp (element_name, "record") == 0 &&
1920 ctx->state == STATE_NAMESPACE)
1923 const gchar *deprecated;
1924 const gchar *gtype_name;
1925 const gchar *gtype_init;
1926 GIrNodeStruct *struct_;
1928 name = find_attribute ("name", attribute_names, attribute_values);
1929 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1930 gtype_name = find_attribute ("glib:type-name", attribute_names, attribute_values);
1931 gtype_init = find_attribute ("glib:get-type", attribute_names, attribute_values);
1935 MISSING_ATTRIBUTE (context, error, element_name, "name");
1938 if ((gtype_name == NULL && gtype_init != NULL))
1940 MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
1943 if ((gtype_name != NULL && gtype_init == NULL))
1945 MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
1949 struct_ = (GIrNodeStruct *) g_ir_node_new (G_IR_NODE_STRUCT);
1951 ((GIrNode *)struct_)->name = g_strdup (name);
1953 struct_->deprecated = TRUE;
1955 struct_->deprecated = FALSE;
1957 struct_->gtype_name = g_strdup (gtype_name);
1958 struct_->gtype_init = g_strdup (gtype_init);
1960 ctx->current_node = (GIrNode *)struct_;
1961 ctx->current_module->entries =
1962 g_list_append (ctx->current_module->entries, struct_);
1964 state_switch (ctx, STATE_STRUCT);
1972 start_union (GMarkupParseContext *context,
1973 const gchar *element_name,
1974 const gchar **attribute_names,
1975 const gchar **attribute_values,
1979 if (strcmp (element_name, "union") == 0 &&
1980 ctx->state == STATE_NAMESPACE)
1983 const gchar *deprecated;
1984 const gchar *typename;
1985 const gchar *typeinit;
1987 name = find_attribute ("name", attribute_names, attribute_values);
1988 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1989 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
1990 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
1993 MISSING_ATTRIBUTE (context, error, element_name, "name");
1996 GIrNodeUnion *union_;
1998 union_ = (GIrNodeUnion *) g_ir_node_new (G_IR_NODE_UNION);
2000 ((GIrNode *)union_)->name = g_strdup (name);
2001 union_->gtype_name = g_strdup (typename);
2002 union_->gtype_init = g_strdup (typeinit);
2004 union_->deprecated = TRUE;
2006 union_->deprecated = FALSE;
2008 ctx->current_node = (GIrNode *)union_;
2009 ctx->current_module->entries =
2010 g_list_append (ctx->current_module->entries, union_);
2012 state_switch (ctx, STATE_UNION);
2020 start_discriminator (GMarkupParseContext *context,
2021 const gchar *element_name,
2022 const gchar **attribute_names,
2023 const gchar **attribute_values,
2027 if (strcmp (element_name, "discriminator") == 0 &&
2028 ctx->state == STATE_UNION)
2031 const gchar *offset;
2033 type = find_attribute ("type", attribute_names, attribute_values);
2034 offset = find_attribute ("offset", attribute_names, attribute_values);
2036 MISSING_ATTRIBUTE (context, error, element_name, "type");
2037 else if (offset == NULL)
2038 MISSING_ATTRIBUTE (context, error, element_name, "offset");
2040 ((GIrNodeUnion *)ctx->current_node)->discriminator_type
2041 = parse_type (ctx, type);
2042 ((GIrNodeUnion *)ctx->current_node)->discriminator_offset
2053 parse_include (GMarkupParseContext *context,
2056 const char *version,
2059 ParseContext sub_ctx = { 0 };
2064 girpath = locate_gir (name, version, ctx->includes);
2066 if (girpath == NULL)
2070 G_MARKUP_ERROR_INVALID_CONTENT,
2071 "Could not find GIR file '%s.gir'; check XDG_DATA_DIRS or use --includedir",
2076 g_debug ("Parsing include %s", girpath);
2078 if (!g_file_get_contents (girpath, &buffer, &length, error))
2085 sub_ctx.state = STATE_START;
2086 sub_ctx.includes = ctx->includes;
2087 sub_ctx.prefix_aliases = TRUE;
2088 sub_ctx.namespace = name;
2089 sub_ctx.aliases = ctx->aliases;
2090 sub_ctx.type_depth = 0;
2092 context = g_markup_parse_context_new (&firstpass_parser, 0, &sub_ctx, NULL);
2094 if (!g_markup_parse_context_parse (context, buffer, length, error))
2100 if (!g_markup_parse_context_end_parse (context, error))
2106 g_markup_parse_context_free (context);
2110 extern GLogLevelFlags logged_levels;
2113 start_element_handler (GMarkupParseContext *context,
2114 const gchar *element_name,
2115 const gchar **attribute_names,
2116 const gchar **attribute_values,
2120 ParseContext *ctx = user_data;
2121 gint line_number, char_number;
2123 if (logged_levels & G_LOG_LEVEL_DEBUG)
2125 GString *tags = g_string_new ("");
2127 for (i = 0; attribute_names[i]; i++)
2128 g_string_append_printf (tags, "%s=\"%s\" ",
2130 attribute_values[i]);
2134 g_string_insert_c (tags, 0, ' ');
2135 g_string_truncate (tags, tags->len - 1);
2137 g_debug ("<%s%s>", element_name, tags->str);
2138 g_string_free (tags, TRUE);
2141 switch (element_name[0])
2144 if (ctx->state == STATE_NAMESPACE && strcmp (element_name, "alias") == 0)
2146 state_switch (ctx, STATE_ALIAS);
2149 if (start_type (context, element_name,
2150 attribute_names, attribute_values,
2155 if (start_enum (context, element_name,
2156 attribute_names, attribute_values,
2161 if (start_function (context, element_name,
2162 attribute_names, attribute_values,
2165 else if (start_constant (context, element_name,
2166 attribute_names, attribute_values,
2169 else if (start_class (context, element_name,
2170 attribute_names, attribute_values,
2173 else if (strcmp (element_name, "class") == 0 &&
2174 ctx->state == STATE_REQUIRES)
2178 name = find_attribute ("name", attribute_names, attribute_values);
2181 MISSING_ATTRIBUTE (context, error, element_name, "name");
2184 GIrNodeInterface *iface;
2186 iface = (GIrNodeInterface *)ctx->current_node;
2187 iface ->prerequisites = g_list_append (iface->prerequisites, g_strdup (name));
2195 if (start_discriminator (context, element_name,
2196 attribute_names, attribute_values,
2202 if (start_enum (context, element_name,
2203 attribute_names, attribute_values,
2206 else if (start_errordomain (context, element_name,
2207 attribute_names, attribute_values,
2213 if (start_function (context, element_name,
2214 attribute_names, attribute_values,
2217 else if (start_field (context, element_name,
2218 attribute_names, attribute_values,
2224 if (start_glib_boxed (context, element_name,
2225 attribute_names, attribute_values,
2228 else if (start_glib_signal (context, element_name,
2229 attribute_names, attribute_values,
2235 if (strcmp (element_name, "include") == 0 &&
2236 ctx->state == STATE_REPOSITORY)
2239 const gchar *version;
2241 name = find_attribute ("name", attribute_names, attribute_values);
2242 version = find_attribute ("version", attribute_names, attribute_values);
2246 MISSING_ATTRIBUTE (context, error, element_name, "name");
2249 if (version == NULL)
2251 MISSING_ATTRIBUTE (context, error, element_name, "version");
2255 if (!parse_include (context, ctx, name, version, error))
2258 ctx->dependencies = g_list_prepend (ctx->dependencies,
2259 g_strdup_printf ("%s-%s", name, version));
2262 state_switch (ctx, STATE_INCLUDE);
2265 if (start_interface (context, element_name,
2266 attribute_names, attribute_values,
2269 else if (start_implements (context, element_name,
2270 attribute_names, attribute_values,
2276 if (start_function (context, element_name,
2277 attribute_names, attribute_values,
2280 else if (start_member (context, element_name,
2281 attribute_names, attribute_values,
2287 if (strcmp (element_name, "namespace") == 0 && ctx->state == STATE_REPOSITORY)
2289 const gchar *name, *version, *shared_library;
2291 name = find_attribute ("name", attribute_names, attribute_values);
2292 version = find_attribute ("version", attribute_names, attribute_values);
2293 shared_library = find_attribute ("shared-library", attribute_names, attribute_values);
2296 MISSING_ATTRIBUTE (context, error, element_name, "name");
2297 else if (version == NULL)
2298 MISSING_ATTRIBUTE (context, error, element_name, "version");
2301 ctx->current_module = g_ir_module_new (name, version, shared_library);
2302 ctx->modules = g_list_append (ctx->modules, ctx->current_module);
2303 ctx->current_module->dependencies = ctx->dependencies;
2305 state_switch (ctx, STATE_NAMESPACE);
2312 if (start_property (context, element_name,
2313 attribute_names, attribute_values,
2316 else if (strcmp (element_name, "parameters") == 0 &&
2317 ctx->state == STATE_FUNCTION)
2319 state_switch (ctx, STATE_FUNCTION_PARAMETERS);
2323 else if (start_parameter (context, element_name,
2324 attribute_names, attribute_values,
2331 if (strcmp (element_name, "repository") == 0 && ctx->state == STATE_START)
2333 const gchar *version;
2335 version = find_attribute ("version", attribute_names, attribute_values);
2337 if (version == NULL)
2338 MISSING_ATTRIBUTE (context, error, element_name, "version");
2339 else if (strcmp (version, "1.0") != 0)
2342 G_MARKUP_ERROR_INVALID_CONTENT,
2343 "Unsupported version '%s'",
2346 state_switch (ctx, STATE_REPOSITORY);
2350 else if (start_return_value (context, element_name,
2351 attribute_names, attribute_values,
2354 else if (strcmp (element_name, "requires") == 0 &&
2355 ctx->state == STATE_INTERFACE)
2357 state_switch (ctx, STATE_REQUIRES);
2361 else if (start_struct (context, element_name,
2362 attribute_names, attribute_values,
2368 if (start_union (context, element_name,
2369 attribute_names, attribute_values,
2375 if (start_type (context, element_name,
2376 attribute_names, attribute_values,
2382 if (start_vfunc (context, element_name,
2383 attribute_names, attribute_values,
2386 if (start_type (context, element_name,
2387 attribute_names, attribute_values,
2393 g_markup_parse_context_get_position (context, &line_number, &char_number);
2395 if (error && *error == NULL)
2398 G_MARKUP_ERROR_UNKNOWN_ELEMENT,
2399 "Unexpected start tag '%s' on line %d char %d; current state=%d",
2401 line_number, char_number, ctx->state);
2406 g_markup_parse_context_get_position (context, &line_number, &char_number);
2408 fprintf (stderr, "Error at line %d, character %d: %s\n", line_number, char_number, (*error)->message);
2409 backtrace_stderr ();
2414 require_one_of_end_elements (GMarkupParseContext *context,
2416 const char *actual_name,
2421 int line_number, char_number;
2422 const char *expected;
2423 gboolean matched = FALSE;
2425 va_start (args, error);
2427 while ((expected = va_arg (args, const char*)) != NULL)
2429 if (strcmp (expected, actual_name) == 0)
2441 g_markup_parse_context_get_position (context, &line_number, &char_number);
2444 G_MARKUP_ERROR_INVALID_CONTENT,
2445 "Unexpected end tag '%s' on line %d char %d; current state=%d",
2447 line_number, char_number, ctx->state);
2453 require_end_element (GMarkupParseContext *context,
2455 const char *expected_name,
2456 const char *actual_name,
2459 return require_one_of_end_elements (context, ctx, actual_name, error, expected_name, NULL);
2463 end_element_handler (GMarkupParseContext *context,
2464 const gchar *element_name,
2468 ParseContext *ctx = user_data;
2470 g_debug ("</%s>", element_name);
2476 /* no need to GError here, GMarkup already catches this */
2479 case STATE_REPOSITORY:
2480 state_switch (ctx, STATE_END);
2484 if (require_end_element (context, ctx, "include", element_name, error))
2486 state_switch (ctx, STATE_REPOSITORY);
2490 case STATE_NAMESPACE:
2491 if (require_end_element (context, ctx, "namespace", element_name, error))
2493 ctx->current_module = NULL;
2494 state_switch (ctx, STATE_REPOSITORY);
2499 if (require_end_element (context, ctx, "alias", element_name, error))
2501 state_switch (ctx, STATE_NAMESPACE);
2505 case STATE_FUNCTION_RETURN:
2506 if (strcmp ("type", element_name) == 0)
2508 if (require_end_element (context, ctx, "return-value", element_name, error))
2510 state_switch (ctx, STATE_FUNCTION);
2514 case STATE_FUNCTION_PARAMETERS:
2515 if (require_end_element (context, ctx, "parameters", element_name, error))
2517 state_switch (ctx, STATE_FUNCTION);
2521 case STATE_FUNCTION_PARAMETER:
2522 if (strcmp ("type", element_name) == 0)
2524 if (require_end_element (context, ctx, "parameter", element_name, error))
2526 state_switch (ctx, STATE_FUNCTION_PARAMETERS);
2530 case STATE_FUNCTION:
2532 gboolean current_is_toplevel;
2533 GList *last = g_list_last (ctx->current_module->entries);
2535 current_is_toplevel = ctx->current_node == last->data;
2537 if (current_is_toplevel)
2539 ctx->current_node = NULL;
2540 state_switch (ctx, STATE_NAMESPACE);
2544 ctx->current_node = g_list_last (ctx->current_module->entries)->data;
2545 if (ctx->current_node->type == G_IR_NODE_INTERFACE)
2546 state_switch (ctx, STATE_INTERFACE);
2547 else if (ctx->current_node->type == G_IR_NODE_OBJECT)
2548 state_switch (ctx, STATE_CLASS);
2549 else if (ctx->current_node->type == G_IR_NODE_BOXED)
2550 state_switch (ctx, STATE_BOXED);
2551 else if (ctx->current_node->type == G_IR_NODE_STRUCT)
2552 state_switch (ctx, STATE_STRUCT);
2553 else if (ctx->current_node->type == G_IR_NODE_UNION)
2554 state_switch (ctx, STATE_UNION);
2557 int line_number, char_number;
2558 g_markup_parse_context_get_position (context, &line_number, &char_number);
2561 G_MARKUP_ERROR_INVALID_CONTENT,
2562 "Unexpected end tag '%s' on line %d char %d",
2564 line_number, char_number);
2570 case STATE_CLASS_FIELD:
2571 if (strcmp ("type", element_name) == 0)
2573 if (require_end_element (context, ctx, "field", element_name, error))
2575 state_switch (ctx, STATE_CLASS);
2579 case STATE_CLASS_PROPERTY:
2580 if (strcmp ("type", element_name) == 0)
2582 if (require_end_element (context, ctx, "property", element_name, error))
2584 state_switch (ctx, STATE_CLASS);
2589 if (require_end_element (context, ctx, "class", element_name, error))
2591 ctx->current_node = NULL;
2592 state_switch (ctx, STATE_NAMESPACE);
2596 case STATE_ERRORDOMAIN:
2597 if (require_end_element (context, ctx, "errordomain", element_name, error))
2599 ctx->current_node = NULL;
2600 state_switch (ctx, STATE_NAMESPACE);
2604 case STATE_INTERFACE_PROPERTY:
2605 if (strcmp ("type", element_name) == 0)
2607 if (require_end_element (context, ctx, "property", element_name, error))
2609 state_switch (ctx, STATE_INTERFACE);
2613 case STATE_INTERFACE_FIELD:
2614 if (strcmp ("type", element_name) == 0)
2616 if (require_end_element (context, ctx, "field", element_name, error))
2618 state_switch (ctx, STATE_INTERFACE);
2622 case STATE_INTERFACE:
2623 if (require_end_element (context, ctx, "interface", element_name, error))
2625 ctx->current_node = NULL;
2626 state_switch (ctx, STATE_NAMESPACE);
2631 if (strcmp ("member", element_name) == 0)
2633 else if (require_one_of_end_elements (context, ctx,
2634 element_name, error, "enumeration",
2637 ctx->current_node = NULL;
2638 state_switch (ctx, STATE_NAMESPACE);
2643 if (require_end_element (context, ctx, "glib:boxed", element_name, error))
2645 ctx->current_node = NULL;
2646 state_switch (ctx, STATE_NAMESPACE);
2650 case STATE_BOXED_FIELD:
2651 if (strcmp ("type", element_name) == 0)
2653 if (require_end_element (context, ctx, "field", element_name, error))
2655 state_switch (ctx, STATE_BOXED);
2659 case STATE_STRUCT_FIELD:
2660 if (strcmp ("type", element_name) == 0)
2662 if (require_end_element (context, ctx, "field", element_name, error))
2664 state_switch (ctx, STATE_STRUCT);
2669 if (require_end_element (context, ctx, "record", element_name, error))
2671 ctx->current_node = NULL;
2672 state_switch (ctx, STATE_NAMESPACE);
2676 case STATE_UNION_FIELD:
2677 if (strcmp ("type", element_name) == 0)
2679 if (require_end_element (context, ctx, "field", element_name, error))
2681 state_switch (ctx, STATE_UNION);
2686 if (require_end_element (context, ctx, "union", element_name, error))
2688 ctx->current_node = NULL;
2689 state_switch (ctx, STATE_NAMESPACE);
2692 case STATE_IMPLEMENTS:
2693 if (strcmp ("interface", element_name) == 0)
2695 if (require_end_element (context, ctx, "implements", element_name, error))
2696 state_switch (ctx, STATE_CLASS);
2698 case STATE_REQUIRES:
2699 if (require_end_element (context, ctx, "requires", element_name, error))
2700 state_switch (ctx, STATE_INTERFACE);
2702 case STATE_NAMESPACE_CONSTANT:
2703 case STATE_CLASS_CONSTANT:
2704 case STATE_INTERFACE_CONSTANT:
2705 if (strcmp ("type", element_name) == 0)
2707 if (require_end_element (context, ctx, "constant", element_name, error))
2709 ctx->current_node = NULL;
2712 case STATE_NAMESPACE_CONSTANT:
2713 state_switch (ctx, STATE_NAMESPACE);
2715 case STATE_CLASS_CONSTANT:
2716 state_switch (ctx, STATE_CLASS);
2718 case STATE_INTERFACE_CONSTANT:
2719 state_switch (ctx, STATE_INTERFACE);
2722 g_assert_not_reached ();
2728 if ((strcmp ("type", element_name) == 0) || (strcmp ("array", element_name) == 0) ||
2729 (strcmp ("varargs", element_name) == 0))
2735 g_error ("Unhandled state %d in end_element_handler\n", ctx->state);
2740 text_handler (GMarkupParseContext *context,
2746 /* FIXME warn about non-whitespace text */
2750 cleanup (GMarkupParseContext *context,
2754 ParseContext *ctx = user_data;
2757 for (m = ctx->modules; m; m = m->next)
2758 g_ir_module_free (m->data);
2759 g_list_free (ctx->modules);
2760 ctx->modules = NULL;
2762 ctx->current_module = NULL;
2765 static GMarkupParser parser =
2767 start_element_handler,
2768 end_element_handler,
2775 post_filter_varargs_functions (GList *list)
2783 GIrNode *node = iter->data;
2787 if (node->type == G_IR_NODE_FUNCTION)
2789 if (((GIrNodeFunction*)node)->is_varargs)
2791 list = g_list_delete_link (list, link);
2799 post_filter (GIrModule *module)
2803 module->entries = post_filter_varargs_functions (module->entries);
2804 iter = module->entries;
2807 GIrNode *node = iter->data;
2811 if (node->type == G_IR_NODE_OBJECT ||
2812 node->type == G_IR_NODE_INTERFACE)
2814 GIrNodeInterface *iface = (GIrNodeInterface*)node;
2815 iface->members = post_filter_varargs_functions (iface->members);
2817 else if (node->type == G_IR_NODE_BOXED)
2819 GIrNodeBoxed *boxed = (GIrNodeBoxed*)node;
2820 boxed->members = post_filter_varargs_functions (boxed->members);
2822 else if (node->type == G_IR_NODE_STRUCT)
2824 GIrNodeStruct *iface = (GIrNodeStruct*)node;
2825 iface->members = post_filter_varargs_functions (iface->members);
2827 else if (node->type == G_IR_NODE_UNION)
2829 GIrNodeUnion *iface = (GIrNodeUnion*)node;
2830 iface->members = post_filter_varargs_functions (iface->members);
2836 g_ir_parse_string (const gchar *namespace,
2837 const gchar *const *includes,
2838 const gchar *buffer,
2842 ParseContext ctx = { 0 };
2843 GMarkupParseContext *context;
2845 ctx.state = STATE_START;
2846 ctx.includes = includes;
2847 ctx.prefix_aliases = FALSE;
2848 ctx.namespace = namespace;
2849 ctx.aliases = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
2851 ctx.dependencies = NULL;
2852 ctx.current_module = NULL;
2854 context = g_markup_parse_context_new (&firstpass_parser, 0, &ctx, NULL);
2856 if (!g_markup_parse_context_parse (context, buffer, length, error))
2859 if (!g_markup_parse_context_end_parse (context, error))
2862 g_markup_parse_context_free (context);
2864 context = g_markup_parse_context_new (&parser, 0, &ctx, NULL);
2865 if (!g_markup_parse_context_parse (context, buffer, length, error))
2868 if (!g_markup_parse_context_end_parse (context, error))
2873 g_hash_table_destroy (ctx.aliases);
2875 g_markup_parse_context_free (context);
2881 g_ir_parse_file (const gchar *filename,
2882 const gchar *const *includes,
2892 if (!g_str_has_suffix (filename, ".gir"))
2896 G_MARKUP_ERROR_INVALID_CONTENT,
2897 "Expected filename to end with '.gir'");
2901 g_debug ("[parsing] filename %s", filename);
2903 slash = g_strrstr (filename, "/");
2905 namespace = g_strdup (filename);
2907 namespace = g_strdup (slash+1);
2908 namespace[strlen(namespace)-4] = '\0';
2910 if (!g_file_get_contents (filename, &buffer, &length, error))
2913 modules = g_ir_parse_string (namespace, includes, buffer, length, error);
2915 for (iter = modules; iter; iter = iter->next)
2917 post_filter ((GIrModule*)iter->data);