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 "girparser.h"
27 #include "girmodule.h"
32 #if defined(HAVE_BACKTRACE) && defined(HAVE_BACKTRACE_SYMBOLS)
33 # include <execinfo.h>
39 GList *parsed_modules; /* All previously parsed modules */
49 STATE_NAMESPACE, /* 5 */
53 STATE_FUNCTION_RETURN,
54 STATE_FUNCTION_PARAMETERS, /* 10 */
55 STATE_FUNCTION_PARAMETER,
59 STATE_INTERFACE, /* 15 */
60 STATE_INTERFACE_PROPERTY,
61 STATE_INTERFACE_FIELD,
71 STATE_NAMESPACE_CONSTANT,
73 STATE_INTERFACE_CONSTANT,
80 typedef struct _ParseContext ParseContext;
87 ParseState prev_state;
90 GList *include_modules;
93 GHashTable *disguised_structures;
95 const char *namespace;
97 GIrModule *current_module;
99 GIrNode *current_typed;
102 GList *type_parameters;
104 gboolean in_embedded_type;
106 #define CURRENT_NODE(ctx) ((GIrNode *)((ctx)->node_stack->data))
108 static void start_element_handler (GMarkupParseContext *context,
109 const gchar *element_name,
110 const gchar **attribute_names,
111 const gchar **attribute_values,
114 static void end_element_handler (GMarkupParseContext *context,
115 const gchar *element_name,
118 static void text_handler (GMarkupParseContext *context,
123 static void cleanup (GMarkupParseContext *context,
127 static GMarkupParser markup_parser =
129 start_element_handler,
137 start_alias (GMarkupParseContext *context,
138 const gchar *element_name,
139 const gchar **attribute_names,
140 const gchar **attribute_values,
144 static const gchar *find_attribute (const gchar *name,
145 const gchar **attribute_names,
146 const gchar **attribute_values);
150 g_ir_parser_new (void)
152 GIrParser *parser = g_slice_new0 (GIrParser);
158 g_ir_parser_free (GIrParser *parser)
162 if (parser->includes)
163 g_strfreev (parser->includes);
165 for (l = parser->parsed_modules; l; l = l->next)
166 g_ir_module_free (l->data);
168 g_slice_free (GIrParser, parser);
172 g_ir_parser_set_includes (GIrParser *parser,
173 const gchar *const *includes)
175 if (parser->includes)
176 g_strfreev (parser->includes);
178 parser->includes = g_strdupv ((char **)includes);
182 firstpass_start_element_handler (GMarkupParseContext *context,
183 const gchar *element_name,
184 const gchar **attribute_names,
185 const gchar **attribute_values,
189 ParseContext *ctx = user_data;
191 if (strcmp (element_name, "alias") == 0)
193 start_alias (context, element_name, attribute_names, attribute_values,
196 else if (strcmp (element_name, "record") == 0)
199 const gchar *disguised;
201 name = find_attribute ("name", attribute_names, attribute_values);
202 disguised = find_attribute ("disguised", attribute_names, attribute_values);
204 if (disguised && strcmp (disguised, "1") == 0)
208 key = g_strdup_printf ("%s.%s", ctx->namespace, name);
209 g_hash_table_replace (ctx->disguised_structures, key, GINT_TO_POINTER (1));
215 firstpass_end_element_handler (GMarkupParseContext *context,
216 const gchar *element_name,
222 static GMarkupParser firstpass_parser =
224 firstpass_start_element_handler,
225 firstpass_end_element_handler,
232 locate_gir (GIrParser *parser,
235 const gchar *const *datadirs;
236 const gchar *const *dir;
239 datadirs = g_get_system_data_dirs ();
241 if (parser->includes != NULL)
243 for (dir = (const gchar *const *)parser->includes; *dir; dir++)
245 path = g_build_filename (*dir, girname, NULL);
246 if (g_file_test (path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))
252 for (dir = datadirs; *dir; dir++)
254 path = g_build_filename (*dir, GIR_SUFFIX, girname, NULL);
255 if (g_file_test (path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))
261 path = g_build_filename (GIR_DIR, girname, NULL);
262 if (g_file_test (path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))
268 #define MISSING_ATTRIBUTE(ctx,error,element,attribute) \
270 int line_number, char_number; \
271 g_markup_parse_context_get_position (context, &line_number, &char_number); \
272 g_set_error (error, \
274 G_MARKUP_ERROR_INVALID_CONTENT, \
275 "Line %d, character %d: The attribute '%s' on the element '%s' must be specified", \
276 line_number, char_number, attribute, element); \
280 backtrace_stderr (void)
282 #if defined(HAVE_BACKTRACE) && defined(HAVE_BACKTRACE_SYMBOLS)
287 size = backtrace (array, 50);
288 strings = (char**) backtrace_symbols (array, size);
290 fprintf (stderr, "--- BACKTRACE (%zd frames) ---\n", size);
292 for (i = 0; i < size; i++)
293 fprintf (stderr, "%s\n", strings[i]);
295 fprintf (stderr, "--- END BACKTRACE ---\n");
303 find_attribute (const gchar *name,
304 const gchar **attribute_names,
305 const gchar **attribute_values)
309 for (i = 0; attribute_names[i] != NULL; i++)
310 if (strcmp (attribute_names[i], name) == 0)
311 return attribute_values[i];
317 state_switch (ParseContext *ctx, ParseState newstate)
319 g_debug ("State: %d", newstate);
320 ctx->prev_state = ctx->state;
321 ctx->state = newstate;
325 pop_node (ParseContext *ctx)
327 g_assert (ctx->node_stack != 0);
329 GSList *top = ctx->node_stack;
330 GIrNode *node = top->data;
332 g_debug ("popping node %d %s", node->type, node->name);
333 ctx->node_stack = top->next;
334 g_slist_free_1 (top);
339 push_node (ParseContext *ctx, GIrNode *node)
341 g_debug ("pushing node %d %s", node->type, node->name);
342 ctx->node_stack = g_slist_prepend (ctx->node_stack, node);
345 static GIrNodeType * parse_type_internal (const gchar *str, gchar **next, gboolean in_glib,
346 gboolean in_gobject);
354 static BasicTypeInfo basic_types[] = {
355 { "none", GI_TYPE_TAG_VOID, 0 },
356 { "any", GI_TYPE_TAG_VOID, 1 },
358 { "bool", GI_TYPE_TAG_BOOLEAN, 0 },
359 { "char", GI_TYPE_TAG_INT8, 0 },
360 { "int8", GI_TYPE_TAG_INT8, 0 },
361 { "uint8", GI_TYPE_TAG_UINT8, 0 },
362 { "int16", GI_TYPE_TAG_INT16, 0 },
363 { "uint16", GI_TYPE_TAG_UINT16, 0 },
364 { "int32", GI_TYPE_TAG_INT32, 0 },
365 { "uint32", GI_TYPE_TAG_UINT32, 0 },
366 { "int64", GI_TYPE_TAG_INT64, 0 },
367 { "uint64", GI_TYPE_TAG_UINT64, 0 },
368 { "short", GI_TYPE_TAG_SHORT, 0 },
369 { "ushort", GI_TYPE_TAG_USHORT, 0 },
370 { "int", GI_TYPE_TAG_INT, 0 },
371 { "uint", GI_TYPE_TAG_UINT, 0 },
372 { "long", GI_TYPE_TAG_LONG, 0 },
373 { "ulong", GI_TYPE_TAG_ULONG, 0 },
374 { "ssize_t", GI_TYPE_TAG_SSIZE, 0 },
375 { "ssize", GI_TYPE_TAG_SSIZE, 0 },
376 { "size_t", GI_TYPE_TAG_SIZE, 0 },
377 { "size", GI_TYPE_TAG_SIZE, 0 },
378 { "float", GI_TYPE_TAG_FLOAT, 0 },
379 { "double", GI_TYPE_TAG_DOUBLE, 0 },
380 { "time_t", GI_TYPE_TAG_TIME_T, 0 },
381 { "GType", GI_TYPE_TAG_GTYPE, 0 },
382 { "utf8", GI_TYPE_TAG_UTF8, 1 },
383 { "filename", GI_TYPE_TAG_FILENAME,1 },
386 static const BasicTypeInfo *
387 parse_basic (const char *str)
390 gint n_basic = G_N_ELEMENTS (basic_types);
392 for (i = 0; i < n_basic; i++)
394 if (g_str_has_prefix (str, basic_types[i].str))
395 return &(basic_types[i]);
401 parse_type_internal (const gchar *str, char **next, gboolean in_glib,
404 const BasicTypeInfo *basic;
406 char *temporary_type = NULL;
408 type = (GIrNodeType *)g_ir_node_new (G_IR_NODE_TYPE);
410 type->unparsed = g_strdup (str);
412 /* See comment below on GLib.List handling */
413 if (in_gobject && strcmp (str, "Type") == 0)
415 temporary_type = g_strdup ("GLib.Type");
416 str = temporary_type;
419 basic = parse_basic (str);
422 type->is_basic = TRUE;
423 type->tag = basic->tag;
424 type->is_pointer = basic->pointer;
426 str += strlen(basic->str);
430 /* If we're inside GLib, handle "List" etc. by prefixing with
431 * "GLib." so the parsing code below doesn't have to get more
434 if (g_str_has_prefix (str, "List<") ||
435 strcmp (str, "List") == 0)
437 temporary_type = g_strdup_printf ("GLib.List%s", str + 4);
438 str = temporary_type;
440 else if (g_str_has_prefix (str, "SList<") ||
441 strcmp (str, "SList") == 0)
443 temporary_type = g_strdup_printf ("GLib.SList%s", str + 5);
444 str = temporary_type;
446 else if (g_str_has_prefix (str, "HashTable<") ||
447 strcmp (str, "HashTable") == 0)
449 temporary_type = g_strdup_printf ("GLib.HashTable%s", str + 9);
450 str = temporary_type;
452 else if (g_str_has_prefix (str, "Error<") ||
453 strcmp (str, "Error") == 0)
455 temporary_type = g_strdup_printf ("GLib.Error%s", str + 5);
456 str = temporary_type;
461 /* found a basic type */;
462 else if (g_str_has_prefix (str, "GLib.List") ||
463 g_str_has_prefix (str, "GLib.SList"))
465 str += strlen ("GLib.");
466 if (g_str_has_prefix (str, "List"))
468 type->tag = GI_TYPE_TAG_GLIST;
469 type->is_glist = TRUE;
470 type->is_pointer = TRUE;
471 str += strlen ("List");
475 type->tag = GI_TYPE_TAG_GSLIST;
476 type->is_gslist = TRUE;
477 type->is_pointer = TRUE;
478 str += strlen ("SList");
481 else if (g_str_has_prefix (str, "GLib.HashTable"))
483 str += strlen ("GLib.");
485 type->tag = GI_TYPE_TAG_GHASH;
486 type->is_ghashtable = TRUE;
487 type->is_pointer = TRUE;
488 str += strlen ("HashTable");
490 else if (g_str_has_prefix (str, "GLib.Error"))
492 str += strlen ("GLib.");
494 type->tag = GI_TYPE_TAG_ERROR;
495 type->is_error = TRUE;
496 type->is_pointer = TRUE;
497 str += strlen ("Error");
504 end = strchr (str, '>');
505 tmp = g_strndup (str, end - str);
506 type->errors = g_strsplit (tmp, ",", 0);
514 type->tag = GI_TYPE_TAG_INTERFACE;
515 type->is_interface = TRUE;
516 const char *start = str;
518 /* must be an interface type */
519 while (g_ascii_isalnum (*str) ||
526 type->interface = g_strndup (start, str - start);
529 The alias code can return pointers for typedefs.
530 since the type reader code does not catch this,
531 it has to be set here.
533 if (strchr(start, '*'))
535 g_debug("Adding type as interface (pointer) %s ", type->interface);
536 type->is_pointer = TRUE;
542 g_assert (type->tag >= 0 && type->tag <= GI_TYPE_TAG_ERROR);
543 g_free (temporary_type);
547 g_ir_node_free ((GIrNode *)type);
548 g_free (temporary_type);
553 resolve_aliases (ParseContext *ctx, const gchar *type, gboolean *is_pointer)
557 GSList *seen_values = NULL;
559 gchar *prefixed, *lookup_copy;
563 if (strchr (type, '.') == NULL)
565 prefixed = g_strdup_printf ("%s.%s", ctx->namespace, type);
574 Since target could be a name + '*'
575 we need to duplicate the lookup value always
578 star_pos = strchr(lookup, '*');
582 lookup_copy = g_strndup(lookup, star_pos ? (gsize) (star_pos - lookup) : strlen(lookup));
584 seen_values = g_slist_prepend (seen_values, (char*)lookup);
585 while (g_hash_table_lookup_extended (ctx->current_module->aliases, lookup_copy, &orig, &value))
587 g_debug ("Resolved: %s => %s\n", lookup, (char*)value);
589 /* prevent looping forever.. */
590 if (g_slist_find_custom (seen_values, lookup,
591 (GCompareFunc)strcmp) != NULL)
593 seen_values = g_slist_prepend (seen_values, (gchar*)lookup);
596 star_pos = strchr(lookup, '*');
599 lookup_copy = g_strndup(lookup, star_pos ? (gsize) (star_pos - lookup) : strlen(lookup));
603 g_slist_free (seen_values);
605 if (lookup == prefixed)
614 is_disguised_structure (ParseContext *ctx, const gchar *type)
620 if (strchr (type, '.') == NULL)
622 prefixed = g_strdup_printf ("%s.%s", ctx->namespace, type);
631 result = g_hash_table_lookup (ctx->current_module->disguised_structures,
640 parse_type (ParseContext *ctx, const gchar *type)
643 const BasicTypeInfo *basic;
644 gboolean in_glib, in_gobject;
645 gboolean is_pointer = FALSE;
647 in_glib = strcmp (ctx->namespace, "GLib") == 0;
648 in_gobject = strcmp (ctx->namespace, "GObject") == 0;
650 /* Do not search aliases for basic types */
651 basic = parse_basic (type);
653 type = resolve_aliases (ctx, type, &is_pointer);
655 node = parse_type_internal (type, NULL, in_glib, in_gobject);
658 g_debug ("Parsed type: %s => %d", type, node->tag);
659 /* Overlay is_pointer if it get's set */
660 node->is_pointer = node->is_pointer || is_pointer;
663 g_critical ("Failed to parse type: '%s'", type);
669 start_glib_boxed (GMarkupParseContext *context,
670 const gchar *element_name,
671 const gchar **attribute_names,
672 const gchar **attribute_values,
677 const gchar *typename;
678 const gchar *typeinit;
679 const gchar *deprecated;
682 if (!(strcmp (element_name, "glib:boxed") == 0 &&
683 ctx->state == STATE_NAMESPACE))
686 name = find_attribute ("glib:name", attribute_names, attribute_values);
687 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
688 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
689 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
693 MISSING_ATTRIBUTE (context, error, element_name, "glib:name");
696 else if (typename == NULL)
698 MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
701 else if (typeinit == NULL)
703 MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
707 boxed = (GIrNodeBoxed *) g_ir_node_new (G_IR_NODE_BOXED);
709 ((GIrNode *)boxed)->name = g_strdup (name);
710 boxed->gtype_name = g_strdup (typename);
711 boxed->gtype_init = g_strdup (typeinit);
713 boxed->deprecated = TRUE;
715 boxed->deprecated = FALSE;
717 push_node (ctx, (GIrNode *)boxed);
718 ctx->current_module->entries =
719 g_list_append (ctx->current_module->entries, boxed);
721 state_switch (ctx, STATE_BOXED);
727 start_function (GMarkupParseContext *context,
728 const gchar *element_name,
729 const gchar **attribute_names,
730 const gchar **attribute_values,
736 const gchar *deprecated;
738 GIrNodeFunction *function;
739 gboolean found = FALSE;
743 case STATE_NAMESPACE:
744 found = (strcmp (element_name, "function") == 0 ||
745 strcmp (element_name, "callback") == 0);
748 found = strcmp (element_name, "function") == 0;
753 found = (found || strcmp (element_name, "constructor") == 0);
755 case STATE_INTERFACE:
757 strcmp (element_name, "method") == 0 ||
758 strcmp (element_name, "callback") == 0);
760 case STATE_STRUCT_FIELD:
761 ctx->in_embedded_type = TRUE;
762 found = (found || strcmp (element_name, "callback") == 0);
771 name = find_attribute ("name", attribute_names, attribute_values);
772 symbol = find_attribute ("c:identifier", attribute_names, attribute_values);
773 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
774 throws = find_attribute ("throws", attribute_names, attribute_values);
778 MISSING_ATTRIBUTE (context, error, element_name, "name");
781 else if (strcmp (element_name, "callback") != 0 && symbol == NULL)
783 MISSING_ATTRIBUTE (context, error, element_name, "c:identifier");
787 function = (GIrNodeFunction *) g_ir_node_new (G_IR_NODE_FUNCTION);
789 ((GIrNode *)function)->name = g_strdup (name);
790 function->symbol = g_strdup (symbol);
791 function->parameters = NULL;
793 function->deprecated = TRUE;
795 function->deprecated = FALSE;
797 if (strcmp (element_name, "method") == 0 ||
798 strcmp (element_name, "constructor") == 0)
800 function->is_method = TRUE;
802 if (strcmp (element_name, "constructor") == 0)
803 function->is_constructor = TRUE;
805 function->is_constructor = FALSE;
809 function->is_method = FALSE;
810 function->is_setter = FALSE;
811 function->is_getter = FALSE;
812 function->is_constructor = FALSE;
813 if (strcmp (element_name, "callback") == 0)
814 ((GIrNode *)function)->type = G_IR_NODE_CALLBACK;
817 if (throws && strcmp (throws, "1") == 0)
818 function->throws = TRUE;
820 function->throws = FALSE;
822 if (ctx->node_stack == NULL)
824 ctx->current_module->entries =
825 g_list_append (ctx->current_module->entries, function);
827 else if (ctx->current_typed)
831 field = (GIrNodeField *)ctx->current_typed;
832 field->callback = function;
835 switch (CURRENT_NODE (ctx)->type)
837 case G_IR_NODE_INTERFACE:
838 case G_IR_NODE_OBJECT:
840 GIrNodeInterface *iface;
842 iface = (GIrNodeInterface *)CURRENT_NODE (ctx);
843 iface->members = g_list_append (iface->members, function);
846 case G_IR_NODE_BOXED:
850 boxed = (GIrNodeBoxed *)CURRENT_NODE (ctx);
851 boxed->members = g_list_append (boxed->members, function);
854 case G_IR_NODE_STRUCT:
856 GIrNodeStruct *struct_;
858 struct_ = (GIrNodeStruct *)CURRENT_NODE (ctx);
859 struct_->members = g_list_append (struct_->members, function); }
861 case G_IR_NODE_UNION:
863 GIrNodeUnion *union_;
865 union_ = (GIrNodeUnion *)CURRENT_NODE (ctx);
866 union_->members = g_list_append (union_->members, function);
870 g_assert_not_reached ();
873 push_node(ctx, (GIrNode *)function);
874 state_switch (ctx, STATE_FUNCTION);
880 parse_param_transfer (GIrNodeParam *param, const gchar *transfer, const gchar *name)
882 if (transfer == NULL)
885 g_warning ("required attribute 'transfer-ownership' missing");
887 g_warning ("required attribute 'transfer-ownership' for function '%s'", name);
889 else if (strcmp (transfer, "none") == 0)
891 param->transfer = FALSE;
892 param->shallow_transfer = FALSE;
894 else if (strcmp (transfer, "container") == 0)
896 param->transfer = FALSE;
897 param->shallow_transfer = TRUE;
899 else if (strcmp (transfer, "full") == 0)
901 param->transfer = TRUE;
902 param->shallow_transfer = FALSE;
906 g_warning ("Unknown transfer-ownership value: %s", transfer);
911 start_parameter (GMarkupParseContext *context,
912 const gchar *element_name,
913 const gchar **attribute_names,
914 const gchar **attribute_values,
919 const gchar *direction;
922 const gchar *optional;
923 const gchar *allow_none;
924 const gchar *transfer;
926 const gchar *closure;
927 const gchar *destroy;
930 if (!(strcmp (element_name, "parameter") == 0 &&
931 ctx->state == STATE_FUNCTION_PARAMETERS))
934 name = find_attribute ("name", attribute_names, attribute_values);
935 direction = find_attribute ("direction", attribute_names, attribute_values);
936 retval = find_attribute ("retval", attribute_names, attribute_values);
937 dipper = find_attribute ("dipper", attribute_names, attribute_values);
938 optional = find_attribute ("optional", attribute_names, attribute_values);
939 allow_none = find_attribute ("allow-none", attribute_names, attribute_values);
940 transfer = find_attribute ("transfer-ownership", attribute_names, attribute_values);
941 scope = find_attribute ("scope", attribute_names, attribute_values);
942 closure = find_attribute ("closure", attribute_names, attribute_values);
943 destroy = find_attribute ("destroy", attribute_names, attribute_values);
948 param = (GIrNodeParam *)g_ir_node_new (G_IR_NODE_PARAM);
950 ctx->current_typed = (GIrNode*) param;
951 ctx->current_typed->name = g_strdup (name);
953 state_switch (ctx, STATE_FUNCTION_PARAMETER);
955 if (direction && strcmp (direction, "out") == 0)
960 else if (direction && strcmp (direction, "inout") == 0)
971 if (retval && strcmp (retval, "1") == 0)
972 param->retval = TRUE;
974 param->retval = FALSE;
976 if (dipper && strcmp (dipper, "1") == 0)
977 param->dipper = TRUE;
979 param->dipper = FALSE;
981 if (optional && strcmp (optional, "1") == 0)
982 param->optional = TRUE;
984 param->optional = FALSE;
986 if (allow_none && strcmp (allow_none, "1") == 0)
987 param->allow_none = TRUE;
989 param->allow_none = FALSE;
991 parse_param_transfer (param, transfer, name);
993 if (scope && strcmp (scope, "call") == 0)
994 param->scope = GI_SCOPE_TYPE_CALL;
995 else if (scope && strcmp (scope, "async") == 0)
996 param->scope = GI_SCOPE_TYPE_ASYNC;
997 else if (scope && strcmp (scope, "notified") == 0)
998 param->scope = GI_SCOPE_TYPE_NOTIFIED;
1000 param->scope = GI_SCOPE_TYPE_INVALID;
1002 param->closure = closure ? atoi (closure) : -1;
1003 param->destroy = destroy ? atoi (destroy) : -1;
1005 ((GIrNode *)param)->name = g_strdup (name);
1007 switch (CURRENT_NODE (ctx)->type)
1009 case G_IR_NODE_FUNCTION:
1010 case G_IR_NODE_CALLBACK:
1012 GIrNodeFunction *func;
1014 func = (GIrNodeFunction *)CURRENT_NODE (ctx);
1015 func->parameters = g_list_append (func->parameters, param);
1018 case G_IR_NODE_SIGNAL:
1020 GIrNodeSignal *signal;
1022 signal = (GIrNodeSignal *)CURRENT_NODE (ctx);
1023 signal->parameters = g_list_append (signal->parameters, param);
1026 case G_IR_NODE_VFUNC:
1028 GIrNodeVFunc *vfunc;
1030 vfunc = (GIrNodeVFunc *)CURRENT_NODE (ctx);
1031 vfunc->parameters = g_list_append (vfunc->parameters, param);
1035 g_assert_not_reached ();
1042 start_field (GMarkupParseContext *context,
1043 const gchar *element_name,
1044 const gchar **attribute_names,
1045 const gchar **attribute_values,
1050 const gchar *readable;
1051 const gchar *writable;
1053 const gchar *branch;
1054 GIrNodeField *field;
1062 case STATE_INTERFACE:
1068 if (strcmp (element_name, "field") != 0)
1071 name = find_attribute ("name", attribute_names, attribute_values);
1072 readable = find_attribute ("readable", attribute_names, attribute_values);
1073 writable = find_attribute ("writable", attribute_names, attribute_values);
1074 bits = find_attribute ("bits", attribute_names, attribute_values);
1075 branch = find_attribute ("branch", attribute_names, attribute_values);
1079 MISSING_ATTRIBUTE (context, error, element_name, "name");
1083 field = (GIrNodeField *)g_ir_node_new (G_IR_NODE_FIELD);
1084 ctx->current_typed = (GIrNode*) field;
1085 ((GIrNode *)field)->name = g_strdup (name);
1086 /* Fields are assumed to be read-only.
1087 * (see also girwriter.py and generate.c)
1089 field->readable = readable == NULL || strcmp (readable, "0") == 0;
1090 field->writable = writable != NULL && strcmp (writable, "1") == 0;
1093 field->bits = atoi (bits);
1097 switch (CURRENT_NODE (ctx)->type)
1099 case G_IR_NODE_OBJECT:
1101 GIrNodeInterface *iface;
1103 iface = (GIrNodeInterface *)CURRENT_NODE (ctx);
1104 iface->members = g_list_append (iface->members, field);
1105 state_switch (ctx, STATE_CLASS_FIELD);
1108 case G_IR_NODE_INTERFACE:
1110 GIrNodeInterface *iface;
1112 iface = (GIrNodeInterface *)CURRENT_NODE (ctx);
1113 iface->members = g_list_append (iface->members, field);
1114 state_switch (ctx, STATE_INTERFACE_FIELD);
1117 case G_IR_NODE_BOXED:
1119 GIrNodeBoxed *boxed;
1121 boxed = (GIrNodeBoxed *)CURRENT_NODE (ctx);
1122 boxed->members = g_list_append (boxed->members, field);
1123 state_switch (ctx, STATE_BOXED_FIELD);
1126 case G_IR_NODE_STRUCT:
1128 GIrNodeStruct *struct_;
1130 struct_ = (GIrNodeStruct *)CURRENT_NODE (ctx);
1131 struct_->members = g_list_append (struct_->members, field);
1132 state_switch (ctx, STATE_STRUCT_FIELD);
1135 case G_IR_NODE_UNION:
1137 GIrNodeUnion *union_;
1139 union_ = (GIrNodeUnion *)CURRENT_NODE (ctx);
1140 union_->members = g_list_append (union_->members, field);
1143 GIrNodeConstant *constant;
1145 constant = (GIrNodeConstant *) g_ir_node_new (G_IR_NODE_CONSTANT);
1146 ((GIrNode *)constant)->name = g_strdup (name);
1147 constant->value = g_strdup (branch);
1148 constant->type = union_->discriminator_type;
1149 constant->deprecated = FALSE;
1151 union_->discriminators = g_list_append (union_->discriminators, constant);
1153 state_switch (ctx, STATE_UNION_FIELD);
1157 g_assert_not_reached ();
1164 start_alias (GMarkupParseContext *context,
1165 const gchar *element_name,
1166 const gchar **attribute_names,
1167 const gchar **attribute_values,
1172 const gchar *target;
1176 name = find_attribute ("name", attribute_names, attribute_values);
1179 MISSING_ATTRIBUTE (context, error, element_name, "name");
1183 target = find_attribute ("target", attribute_names, attribute_values);
1186 MISSING_ATTRIBUTE (context, error, element_name, "target");
1190 value = g_strdup (target);
1191 key = g_strdup_printf ("%s.%s", ctx->namespace, name);
1192 if (!strchr (target, '.'))
1194 const BasicTypeInfo *basic = parse_basic (target);
1198 /* For non-basic types, re-qualify the interface */
1199 value = g_strdup_printf ("%s.%s", ctx->namespace, target);
1202 g_hash_table_replace (ctx->aliases, key, value);
1208 start_enum (GMarkupParseContext *context,
1209 const gchar *element_name,
1210 const gchar **attribute_names,
1211 const gchar **attribute_values,
1215 if ((strcmp (element_name, "enumeration") == 0 && ctx->state == STATE_NAMESPACE) ||
1216 (strcmp (element_name, "bitfield") == 0 && ctx->state == STATE_NAMESPACE))
1219 const gchar *typename;
1220 const gchar *typeinit;
1221 const gchar *deprecated;
1223 name = find_attribute ("name", attribute_names, attribute_values);
1224 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
1225 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
1226 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1229 MISSING_ATTRIBUTE (context, error, element_name, "name");
1234 if (strcmp (element_name, "enumeration") == 0)
1235 enum_ = (GIrNodeEnum *) g_ir_node_new (G_IR_NODE_ENUM);
1237 enum_ = (GIrNodeEnum *) g_ir_node_new (G_IR_NODE_FLAGS);
1238 ((GIrNode *)enum_)->name = g_strdup (name);
1239 enum_->gtype_name = g_strdup (typename);
1240 enum_->gtype_init = g_strdup (typeinit);
1242 enum_->deprecated = TRUE;
1244 enum_->deprecated = FALSE;
1246 push_node (ctx, (GIrNode *) enum_);
1247 ctx->current_module->entries =
1248 g_list_append (ctx->current_module->entries, enum_);
1250 state_switch (ctx, STATE_ENUM);
1259 start_property (GMarkupParseContext *context,
1260 const gchar *element_name,
1261 const gchar **attribute_names,
1262 const gchar **attribute_values,
1266 if (strcmp (element_name, "property") == 0 &&
1267 (ctx->state == STATE_CLASS ||
1268 ctx->state == STATE_INTERFACE))
1271 const gchar *readable;
1272 const gchar *writable;
1273 const gchar *construct;
1274 const gchar *construct_only;
1276 name = find_attribute ("name", attribute_names, attribute_values);
1277 readable = find_attribute ("readable", attribute_names, attribute_values);
1278 writable = find_attribute ("writable", attribute_names, attribute_values);
1279 construct = find_attribute ("construct", attribute_names, attribute_values);
1280 construct_only = find_attribute ("construct-only", attribute_names, attribute_values);
1283 MISSING_ATTRIBUTE (context, error, element_name, "name");
1286 GIrNodeProperty *property;
1287 GIrNodeInterface *iface;
1289 property = (GIrNodeProperty *) g_ir_node_new (G_IR_NODE_PROPERTY);
1290 ctx->current_typed = (GIrNode*) property;
1292 ((GIrNode *)property)->name = g_strdup (name);
1294 /* Assume properties are readable */
1295 if (readable == NULL || strcmp (readable, "1") == 0)
1296 property->readable = TRUE;
1298 property->readable = FALSE;
1299 if (writable && strcmp (writable, "1") == 0)
1300 property->writable = TRUE;
1302 property->writable = FALSE;
1303 if (construct && strcmp (construct, "1") == 0)
1304 property->construct = TRUE;
1306 property->construct = FALSE;
1307 if (construct_only && strcmp (construct_only, "1") == 0)
1308 property->construct_only = TRUE;
1310 property->construct_only = FALSE;
1312 iface = (GIrNodeInterface *)CURRENT_NODE (ctx);
1313 iface->members = g_list_append (iface->members, property);
1315 if (ctx->state == STATE_CLASS)
1316 state_switch (ctx, STATE_CLASS_PROPERTY);
1317 else if (ctx->state == STATE_INTERFACE)
1318 state_switch (ctx, STATE_INTERFACE_PROPERTY);
1320 g_assert_not_reached ();
1329 parse_value (const gchar *str)
1333 /* FIXME just a quick hack */
1334 shift_op = strstr (str, "<<");
1340 base = strtol (str, NULL, 10);
1341 shift = strtol (shift_op + 3, NULL, 10);
1343 return base << shift;
1346 return strtol (str, NULL, 10);
1352 start_member (GMarkupParseContext *context,
1353 const gchar *element_name,
1354 const gchar **attribute_names,
1355 const gchar **attribute_values,
1359 if (strcmp (element_name, "member") == 0 &&
1360 ctx->state == STATE_ENUM)
1364 const gchar *deprecated;
1366 name = find_attribute ("name", attribute_names, attribute_values);
1367 value = find_attribute ("value", attribute_names, attribute_values);
1368 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1371 MISSING_ATTRIBUTE (context, error, element_name, "name");
1375 GIrNodeValue *value_;
1377 value_ = (GIrNodeValue *) g_ir_node_new (G_IR_NODE_VALUE);
1379 ((GIrNode *)value_)->name = g_strdup (name);
1381 value_->value = parse_value (value);
1384 value_->deprecated = TRUE;
1386 value_->deprecated = FALSE;
1388 enum_ = (GIrNodeEnum *)CURRENT_NODE (ctx);
1389 enum_->values = g_list_append (enum_->values, value_);
1398 start_constant (GMarkupParseContext *context,
1399 const gchar *element_name,
1400 const gchar **attribute_names,
1401 const gchar **attribute_values,
1405 if (strcmp (element_name, "constant") == 0 &&
1406 (ctx->state == STATE_NAMESPACE ||
1407 ctx->state == STATE_CLASS ||
1408 ctx->state == STATE_INTERFACE))
1412 const gchar *deprecated;
1414 name = find_attribute ("name", attribute_names, attribute_values);
1415 value = find_attribute ("value", attribute_names, attribute_values);
1416 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1419 MISSING_ATTRIBUTE (context, error, element_name, "name");
1420 else if (value == NULL)
1421 MISSING_ATTRIBUTE (context, error, element_name, "value");
1424 GIrNodeConstant *constant;
1426 constant = (GIrNodeConstant *) g_ir_node_new (G_IR_NODE_CONSTANT);
1428 ((GIrNode *)constant)->name = g_strdup (name);
1429 constant->value = g_strdup (value);
1431 ctx->current_typed = (GIrNode*) constant;
1434 constant->deprecated = TRUE;
1436 constant->deprecated = FALSE;
1438 if (ctx->state == STATE_NAMESPACE)
1440 push_node (ctx, (GIrNode *) constant);
1441 ctx->current_module->entries =
1442 g_list_append (ctx->current_module->entries, constant);
1446 GIrNodeInterface *iface;
1448 iface = (GIrNodeInterface *)CURRENT_NODE (ctx);
1449 iface->members = g_list_append (iface->members, constant);
1454 case STATE_NAMESPACE:
1455 state_switch (ctx, STATE_NAMESPACE_CONSTANT);
1458 state_switch (ctx, STATE_CLASS_CONSTANT);
1460 case STATE_INTERFACE:
1461 state_switch (ctx, STATE_INTERFACE_CONSTANT);
1464 g_assert_not_reached ();
1475 start_errordomain (GMarkupParseContext *context,
1476 const gchar *element_name,
1477 const gchar **attribute_names,
1478 const gchar **attribute_values,
1482 if (strcmp (element_name, "errordomain") == 0 &&
1483 ctx->state == STATE_NAMESPACE)
1486 const gchar *getquark;
1488 const gchar *deprecated;
1490 name = find_attribute ("name", attribute_names, attribute_values);
1491 getquark = find_attribute ("get-quark", attribute_names, attribute_values);
1492 codes = find_attribute ("codes", attribute_names, attribute_values);
1493 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1496 MISSING_ATTRIBUTE (context, error, element_name, "name");
1497 else if (getquark == NULL)
1498 MISSING_ATTRIBUTE (context, error, element_name, "getquark");
1499 else if (codes == NULL)
1500 MISSING_ATTRIBUTE (context, error, element_name, "codes");
1503 GIrNodeErrorDomain *domain;
1505 domain = (GIrNodeErrorDomain *) g_ir_node_new (G_IR_NODE_ERROR_DOMAIN);
1507 ((GIrNode *)domain)->name = g_strdup (name);
1508 domain->getquark = g_strdup (getquark);
1509 domain->codes = g_strdup (codes);
1512 domain->deprecated = TRUE;
1514 domain->deprecated = FALSE;
1516 push_node (ctx, (GIrNode *) domain);
1517 ctx->current_module->entries =
1518 g_list_append (ctx->current_module->entries, domain);
1520 state_switch (ctx, STATE_ERRORDOMAIN);
1529 start_interface (GMarkupParseContext *context,
1530 const gchar *element_name,
1531 const gchar **attribute_names,
1532 const gchar **attribute_values,
1536 if (strcmp (element_name, "interface") == 0 &&
1537 ctx->state == STATE_NAMESPACE)
1540 const gchar *typename;
1541 const gchar *typeinit;
1542 const gchar *deprecated;
1543 const gchar *glib_type_struct;
1545 name = find_attribute ("name", attribute_names, attribute_values);
1546 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
1547 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
1548 glib_type_struct = find_attribute ("glib:type-struct", attribute_names, attribute_values);
1549 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1552 MISSING_ATTRIBUTE (context, error, element_name, "name");
1553 else if (typename == NULL)
1554 MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
1555 else if (typeinit == NULL)
1556 MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
1559 GIrNodeInterface *iface;
1561 iface = (GIrNodeInterface *) g_ir_node_new (G_IR_NODE_INTERFACE);
1562 ((GIrNode *)iface)->name = g_strdup (name);
1563 iface->gtype_name = g_strdup (typename);
1564 iface->gtype_init = g_strdup (typeinit);
1565 iface->glib_type_struct = g_strdup (glib_type_struct);
1567 iface->deprecated = TRUE;
1569 iface->deprecated = FALSE;
1571 push_node (ctx, (GIrNode *) iface);
1572 ctx->current_module->entries =
1573 g_list_append (ctx->current_module->entries, iface);
1575 state_switch (ctx, STATE_INTERFACE);
1585 start_class (GMarkupParseContext *context,
1586 const gchar *element_name,
1587 const gchar **attribute_names,
1588 const gchar **attribute_values,
1592 if (strcmp (element_name, "class") == 0 &&
1593 ctx->state == STATE_NAMESPACE)
1596 const gchar *parent;
1597 const gchar *glib_type_struct;
1598 const gchar *typename;
1599 const gchar *typeinit;
1600 const gchar *deprecated;
1601 const gchar *abstract;
1603 name = find_attribute ("name", attribute_names, attribute_values);
1604 parent = find_attribute ("parent", attribute_names, attribute_values);
1605 glib_type_struct = find_attribute ("glib:type-struct", attribute_names, attribute_values);
1606 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
1607 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
1608 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1609 abstract = find_attribute ("abstract", attribute_names, attribute_values);
1612 MISSING_ATTRIBUTE (context, error, element_name, "name");
1613 else if (typename == NULL)
1614 MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
1615 else if (typeinit == NULL && strcmp (typename, "GObject"))
1616 MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
1619 GIrNodeInterface *iface;
1621 iface = (GIrNodeInterface *) g_ir_node_new (G_IR_NODE_OBJECT);
1622 ((GIrNode *)iface)->name = g_strdup (name);
1623 iface->gtype_name = g_strdup (typename);
1624 iface->gtype_init = g_strdup (typeinit);
1625 iface->parent = g_strdup (parent);
1626 iface->glib_type_struct = g_strdup (glib_type_struct);
1628 iface->deprecated = TRUE;
1630 iface->deprecated = FALSE;
1632 iface->abstract = abstract && strcmp (abstract, "1") == 0;
1634 push_node (ctx, (GIrNode *) iface);
1635 ctx->current_module->entries =
1636 g_list_append (ctx->current_module->entries, iface);
1638 state_switch (ctx, STATE_CLASS);
1647 start_type (GMarkupParseContext *context,
1648 const gchar *element_name,
1649 const gchar **attribute_names,
1650 const gchar **attribute_values,
1657 gboolean is_varargs;
1658 GIrNodeType *typenode;
1660 is_array = strcmp (element_name, "array") == 0;
1661 is_varargs = strcmp (element_name, "varargs") == 0;
1663 if (!(is_array || is_varargs || (strcmp (element_name, "type") == 0)))
1666 if (ctx->state == STATE_TYPE)
1669 ctx->type_stack = g_list_prepend (ctx->type_stack, ctx->type_parameters);
1670 ctx->type_parameters = NULL;
1672 else if (ctx->state == STATE_FUNCTION_PARAMETER ||
1673 ctx->state == STATE_FUNCTION_RETURN ||
1674 ctx->state == STATE_STRUCT_FIELD ||
1675 ctx->state == STATE_UNION_FIELD ||
1676 ctx->state == STATE_CLASS_PROPERTY ||
1677 ctx->state == STATE_CLASS_FIELD ||
1678 ctx->state == STATE_INTERFACE_FIELD ||
1679 ctx->state == STATE_INTERFACE_PROPERTY ||
1680 ctx->state == STATE_BOXED_FIELD ||
1681 ctx->state == STATE_NAMESPACE_CONSTANT ||
1682 ctx->state == STATE_CLASS_CONSTANT ||
1683 ctx->state == STATE_INTERFACE_CONSTANT
1686 state_switch (ctx, STATE_TYPE);
1687 ctx->type_depth = 1;
1690 switch (CURRENT_NODE (ctx)->type)
1692 case G_IR_NODE_FUNCTION:
1693 case G_IR_NODE_CALLBACK:
1695 GIrNodeFunction *func = (GIrNodeFunction *)CURRENT_NODE (ctx);
1696 func->is_varargs = TRUE;
1699 case G_IR_NODE_VFUNC:
1701 GIrNodeVFunc *vfunc = (GIrNodeVFunc *)CURRENT_NODE (ctx);
1702 vfunc->is_varargs = TRUE;
1705 /* list others individually rather than with default: so that compiler
1706 * warns if new node types are added without adding them to the switch
1708 case G_IR_NODE_INVALID:
1709 case G_IR_NODE_ENUM:
1710 case G_IR_NODE_FLAGS:
1711 case G_IR_NODE_CONSTANT:
1712 case G_IR_NODE_ERROR_DOMAIN:
1713 case G_IR_NODE_PARAM:
1714 case G_IR_NODE_TYPE:
1715 case G_IR_NODE_PROPERTY:
1716 case G_IR_NODE_SIGNAL:
1717 case G_IR_NODE_VALUE:
1718 case G_IR_NODE_FIELD:
1719 case G_IR_NODE_XREF:
1720 case G_IR_NODE_STRUCT:
1721 case G_IR_NODE_BOXED:
1722 case G_IR_NODE_OBJECT:
1723 case G_IR_NODE_INTERFACE:
1724 case G_IR_NODE_UNION:
1725 g_assert_not_reached ();
1729 ctx->type_stack = NULL;
1730 ctx->type_parameters = NULL;
1733 if (!ctx->current_typed)
1737 G_MARKUP_ERROR_INVALID_CONTENT,
1738 "The element <type> is invalid here");
1751 typenode = (GIrNodeType *)g_ir_node_new (G_IR_NODE_TYPE);
1753 typenode->tag = GI_TYPE_TAG_ARRAY;
1754 typenode->is_pointer = TRUE;
1755 typenode->is_array = TRUE;
1757 zero = find_attribute ("zero-terminated", attribute_names, attribute_values);
1758 len = find_attribute ("length", attribute_names, attribute_values);
1759 size = find_attribute ("fixed-size", attribute_names, attribute_values);
1761 typenode->zero_terminated = !(zero && strcmp (zero, "1") != 0);
1762 typenode->has_length = len != NULL;
1763 typenode->length = typenode->has_length ? atoi (len) : -1;
1765 typenode->has_size = size != NULL;
1766 typenode->size = typenode->has_size ? atoi (size) : -1;
1769 typenode->zero_terminated = strcmp(zero, "1") == 0;
1771 /* If neither zero-terminated nor length nor fixed-size is given, assume zero-terminated. */
1772 typenode->zero_terminated = !(typenode->has_length || typenode->has_size);
1777 name = find_attribute ("name", attribute_names, attribute_values);
1780 MISSING_ATTRIBUTE (context, error, element_name, "name");
1783 ctype = find_attribute ("c:type", attribute_names, attribute_values);
1786 const char *cp = ctype + strlen(ctype) - 1;
1787 while (cp > ctype && *cp-- == '*')
1791 if (ctx->current_typed->type == G_IR_NODE_PARAM &&
1792 ((GIrNodeParam *)ctx->current_typed)->out &&
1796 typenode = parse_type (ctx, name);
1798 /* A 'disguised' structure is one where the c:type is a typedef that
1799 * doesn't look like a pointer, but is internally.
1801 if (typenode->tag == GI_TYPE_TAG_INTERFACE &&
1802 is_disguised_structure (ctx, typenode->interface))
1805 if (pointer_depth > 0)
1806 typenode->is_pointer = TRUE;
1809 ctx->type_parameters = g_list_append (ctx->type_parameters, typenode);
1815 end_type_top (ParseContext *ctx)
1817 GIrNodeType *typenode;
1819 if (!ctx->type_parameters)
1822 typenode = (GIrNodeType*)ctx->type_parameters->data;
1824 /* Default to pointer for unspecified containers */
1825 if (typenode->tag == GI_TYPE_TAG_ARRAY ||
1826 typenode->tag == GI_TYPE_TAG_GLIST ||
1827 typenode->tag == GI_TYPE_TAG_GSLIST)
1829 if (typenode->parameter_type1 == NULL)
1830 typenode->parameter_type1 = parse_type (ctx, "any");
1832 else if (typenode->tag == GI_TYPE_TAG_GHASH)
1834 if (typenode->parameter_type1 == NULL)
1836 typenode->parameter_type1 = parse_type (ctx, "any");
1837 typenode->parameter_type2 = parse_type (ctx, "any");
1841 switch (ctx->current_typed->type)
1843 case G_IR_NODE_PARAM:
1845 GIrNodeParam *param = (GIrNodeParam *)ctx->current_typed;
1846 param->type = typenode;
1849 case G_IR_NODE_FIELD:
1851 GIrNodeField *field = (GIrNodeField *)ctx->current_typed;
1852 field->type = typenode;
1855 case G_IR_NODE_PROPERTY:
1857 GIrNodeProperty *property = (GIrNodeProperty *) ctx->current_typed;
1858 property->type = typenode;
1861 case G_IR_NODE_CONSTANT:
1863 GIrNodeConstant *constant = (GIrNodeConstant *)ctx->current_typed;
1864 constant->type = typenode;
1868 g_printerr("current node is %d\n", CURRENT_NODE (ctx)->type);
1869 g_assert_not_reached ();
1871 g_list_free (ctx->type_parameters);
1874 ctx->type_depth = 0;
1875 ctx->type_parameters = NULL;
1876 ctx->current_typed = NULL;
1880 end_type_recurse (ParseContext *ctx)
1882 GIrNodeType *parent;
1883 GIrNodeType *param = NULL;
1885 parent = (GIrNodeType *) ((GList*)ctx->type_stack->data)->data;
1886 if (ctx->type_parameters)
1887 param = (GIrNodeType *) ctx->type_parameters->data;
1889 if (parent->tag == GI_TYPE_TAG_ARRAY ||
1890 parent->tag == GI_TYPE_TAG_GLIST ||
1891 parent->tag == GI_TYPE_TAG_GSLIST)
1893 g_assert (param != NULL);
1895 if (parent->parameter_type1 == NULL)
1896 parent->parameter_type1 = param;
1898 g_assert_not_reached ();
1900 else if (parent->tag == GI_TYPE_TAG_GHASH)
1902 g_assert (param != NULL);
1904 if (parent->parameter_type1 == NULL)
1905 parent->parameter_type1 = param;
1906 else if (parent->parameter_type2 == NULL)
1907 parent->parameter_type2 = param;
1909 g_assert_not_reached ();
1911 g_list_free (ctx->type_parameters);
1912 ctx->type_parameters = (GList *)ctx->type_stack->data;
1913 ctx->type_stack = g_list_delete_link (ctx->type_stack, ctx->type_stack);
1917 end_type (ParseContext *ctx)
1919 if (ctx->type_depth == 1)
1922 state_switch (ctx, ctx->prev_state);
1926 end_type_recurse (ctx);
1932 start_attribute (GMarkupParseContext *context,
1933 const gchar *element_name,
1934 const gchar **attribute_names,
1935 const gchar **attribute_values,
1943 if (strcmp (element_name, "attribute") != 0 || ctx->node_stack == NULL)
1946 name = find_attribute ("name", attribute_names, attribute_values);
1947 value = find_attribute ("value", attribute_names, attribute_values);
1951 MISSING_ATTRIBUTE (context, error, element_name, "name");
1956 MISSING_ATTRIBUTE (context, error, element_name, "value");
1960 state_switch (ctx, STATE_ATTRIBUTE);
1962 curnode = CURRENT_NODE (ctx);
1964 g_hash_table_insert (curnode->attributes, g_strdup (name), g_strdup (value));
1970 start_return_value (GMarkupParseContext *context,
1971 const gchar *element_name,
1972 const gchar **attribute_names,
1973 const gchar **attribute_values,
1977 if (strcmp (element_name, "return-value") == 0 &&
1978 ctx->state == STATE_FUNCTION)
1980 GIrNodeParam *param;
1981 const gchar *transfer;
1983 param = (GIrNodeParam *)g_ir_node_new (G_IR_NODE_PARAM);
1986 param->retval = TRUE;
1988 ctx->current_typed = (GIrNode*) param;
1990 state_switch (ctx, STATE_FUNCTION_RETURN);
1992 transfer = find_attribute ("transfer-ownership", attribute_names, attribute_values);
1993 parse_param_transfer (param, transfer, NULL);
1995 switch (CURRENT_NODE (ctx)->type)
1997 case G_IR_NODE_FUNCTION:
1998 case G_IR_NODE_CALLBACK:
2000 GIrNodeFunction *func = (GIrNodeFunction *)CURRENT_NODE (ctx);
2001 func->result = param;
2004 case G_IR_NODE_SIGNAL:
2006 GIrNodeSignal *signal = (GIrNodeSignal *)CURRENT_NODE (ctx);
2007 signal->result = param;
2010 case G_IR_NODE_VFUNC:
2012 GIrNodeVFunc *vfunc = (GIrNodeVFunc *)CURRENT_NODE (ctx);
2013 vfunc->result = param;
2017 g_assert_not_reached ();
2027 start_implements (GMarkupParseContext *context,
2028 const gchar *element_name,
2029 const gchar **attribute_names,
2030 const gchar **attribute_values,
2034 GIrNodeInterface *iface;
2037 if (strcmp (element_name, "implements") != 0 ||
2038 !(ctx->state == STATE_CLASS))
2041 state_switch (ctx, STATE_IMPLEMENTS);
2043 name = find_attribute ("name", attribute_names, attribute_values);
2046 MISSING_ATTRIBUTE (context, error, element_name, "name");
2050 iface = (GIrNodeInterface *)CURRENT_NODE (ctx);
2051 iface->interfaces = g_list_append (iface->interfaces, g_strdup (name));
2057 start_glib_signal (GMarkupParseContext *context,
2058 const gchar *element_name,
2059 const gchar **attribute_names,
2060 const gchar **attribute_values,
2064 if (strcmp (element_name, "glib:signal") == 0 &&
2065 (ctx->state == STATE_CLASS ||
2066 ctx->state == STATE_INTERFACE))
2070 const gchar *no_recurse;
2071 const gchar *detailed;
2072 const gchar *action;
2073 const gchar *no_hooks;
2074 const gchar *has_class_closure;
2076 name = find_attribute ("name", attribute_names, attribute_values);
2077 when = find_attribute ("when", attribute_names, attribute_values);
2078 no_recurse = find_attribute ("no-recurse", attribute_names, attribute_values);
2079 detailed = find_attribute ("detailed", attribute_names, attribute_values);
2080 action = find_attribute ("action", attribute_names, attribute_values);
2081 no_hooks = find_attribute ("no-hooks", attribute_names, attribute_values);
2082 has_class_closure = find_attribute ("has-class-closure", attribute_names, attribute_values);
2085 MISSING_ATTRIBUTE (context, error, element_name, "name");
2088 GIrNodeInterface *iface;
2089 GIrNodeSignal *signal;
2091 signal = (GIrNodeSignal *)g_ir_node_new (G_IR_NODE_SIGNAL);
2093 ((GIrNode *)signal)->name = g_strdup (name);
2095 signal->run_first = FALSE;
2096 signal->run_last = FALSE;
2097 signal->run_cleanup = FALSE;
2098 if (when == NULL || strcmp (when, "LAST") == 0)
2099 signal->run_last = TRUE;
2100 else if (strcmp (when, "FIRST") == 0)
2101 signal->run_first = TRUE;
2103 signal->run_cleanup = TRUE;
2105 if (no_recurse && strcmp (no_recurse, "1") == 0)
2106 signal->no_recurse = TRUE;
2108 signal->no_recurse = FALSE;
2109 if (detailed && strcmp (detailed, "1") == 0)
2110 signal->detailed = TRUE;
2112 signal->detailed = FALSE;
2113 if (action && strcmp (action, "1") == 0)
2114 signal->action = TRUE;
2116 signal->action = FALSE;
2117 if (no_hooks && strcmp (no_hooks, "1") == 0)
2118 signal->no_hooks = TRUE;
2120 signal->no_hooks = FALSE;
2121 if (has_class_closure && strcmp (has_class_closure, "1") == 0)
2122 signal->has_class_closure = TRUE;
2124 signal->has_class_closure = FALSE;
2126 iface = (GIrNodeInterface *)CURRENT_NODE (ctx);
2127 iface->members = g_list_append (iface->members, signal);
2129 push_node (ctx, (GIrNode *)signal);
2130 state_switch (ctx, STATE_FUNCTION);
2139 start_vfunc (GMarkupParseContext *context,
2140 const gchar *element_name,
2141 const gchar **attribute_names,
2142 const gchar **attribute_values,
2146 if (strcmp (element_name, "virtual-method") == 0 &&
2147 (ctx->state == STATE_CLASS ||
2148 ctx->state == STATE_INTERFACE))
2151 const gchar *must_chain_up;
2152 const gchar *override;
2153 const gchar *is_class_closure;
2154 const gchar *offset;
2155 const gchar *invoker;
2157 name = find_attribute ("name", attribute_names, attribute_values);
2158 must_chain_up = find_attribute ("must-chain-up", attribute_names, attribute_values);
2159 override = find_attribute ("override", attribute_names, attribute_values);
2160 is_class_closure = find_attribute ("is-class-closure", attribute_names, attribute_values);
2161 offset = find_attribute ("offset", attribute_names, attribute_values);
2162 invoker = find_attribute ("invoker", attribute_names, attribute_values);
2165 MISSING_ATTRIBUTE (context, error, element_name, "name");
2168 GIrNodeInterface *iface;
2169 GIrNodeVFunc *vfunc;
2171 vfunc = (GIrNodeVFunc *)g_ir_node_new (G_IR_NODE_VFUNC);
2173 ((GIrNode *)vfunc)->name = g_strdup (name);
2175 if (must_chain_up && strcmp (must_chain_up, "1") == 0)
2176 vfunc->must_chain_up = TRUE;
2178 vfunc->must_chain_up = FALSE;
2180 if (override && strcmp (override, "always") == 0)
2182 vfunc->must_be_implemented = TRUE;
2183 vfunc->must_not_be_implemented = FALSE;
2185 else if (override && strcmp (override, "never") == 0)
2187 vfunc->must_be_implemented = FALSE;
2188 vfunc->must_not_be_implemented = TRUE;
2192 vfunc->must_be_implemented = FALSE;
2193 vfunc->must_not_be_implemented = FALSE;
2196 if (is_class_closure && strcmp (is_class_closure, "1") == 0)
2197 vfunc->is_class_closure = TRUE;
2199 vfunc->is_class_closure = FALSE;
2202 vfunc->offset = atoi (offset);
2206 vfunc->invoker = g_strdup (invoker);
2208 iface = (GIrNodeInterface *)CURRENT_NODE (ctx);
2209 iface->members = g_list_append (iface->members, vfunc);
2211 push_node (ctx, (GIrNode *)vfunc);
2212 state_switch (ctx, STATE_FUNCTION);
2222 start_struct (GMarkupParseContext *context,
2223 const gchar *element_name,
2224 const gchar **attribute_names,
2225 const gchar **attribute_values,
2229 if (strcmp (element_name, "record") == 0 &&
2230 (ctx->state == STATE_NAMESPACE ||
2231 ctx->state == STATE_UNION ||
2232 ctx->state == STATE_STRUCT ||
2233 ctx->state == STATE_CLASS))
2236 const gchar *deprecated;
2237 const gchar *disguised;
2238 const gchar *gtype_name;
2239 const gchar *gtype_init;
2240 const gchar *gtype_struct;
2241 const gchar *foreign;
2242 GIrNodeStruct *struct_;
2244 name = find_attribute ("name", attribute_names, attribute_values);
2245 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
2246 disguised = find_attribute ("disguised", attribute_names, attribute_values);
2247 gtype_name = find_attribute ("glib:type-name", attribute_names, attribute_values);
2248 gtype_init = find_attribute ("glib:get-type", attribute_names, attribute_values);
2249 gtype_struct = find_attribute ("glib:is-gtype-struct-for", attribute_names, attribute_values);
2250 foreign = find_attribute ("foreign", attribute_names, attribute_values);
2252 if (name == NULL && ctx->node_stack == NULL)
2254 MISSING_ATTRIBUTE (context, error, element_name, "name");
2257 if ((gtype_name == NULL && gtype_init != NULL))
2259 MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
2262 if ((gtype_name != NULL && gtype_init == NULL))
2264 MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
2268 struct_ = (GIrNodeStruct *) g_ir_node_new (G_IR_NODE_STRUCT);
2270 ((GIrNode *)struct_)->name = g_strdup (name ? name : "");
2272 struct_->deprecated = TRUE;
2274 struct_->deprecated = FALSE;
2276 if (disguised && strcmp (disguised, "1") == 0)
2277 struct_->disguised = TRUE;
2279 struct_->is_gtype_struct = gtype_struct != NULL;
2281 struct_->gtype_name = g_strdup (gtype_name);
2282 struct_->gtype_init = g_strdup (gtype_init);
2284 struct_->foreign = (g_strcmp0 (foreign, "1") == 0);
2286 if (ctx->node_stack == NULL)
2287 ctx->current_module->entries =
2288 g_list_append (ctx->current_module->entries, struct_);
2289 push_node (ctx, (GIrNode *)struct_);
2291 state_switch (ctx, STATE_STRUCT);
2299 start_union (GMarkupParseContext *context,
2300 const gchar *element_name,
2301 const gchar **attribute_names,
2302 const gchar **attribute_values,
2306 if (strcmp (element_name, "union") == 0 &&
2307 (ctx->state == STATE_NAMESPACE ||
2308 ctx->state == STATE_UNION ||
2309 ctx->state == STATE_STRUCT ||
2310 ctx->state == STATE_CLASS))
2313 const gchar *deprecated;
2314 const gchar *typename;
2315 const gchar *typeinit;
2317 name = find_attribute ("name", attribute_names, attribute_values);
2318 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
2319 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
2320 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
2322 if (name == NULL && ctx->node_stack == NULL)
2323 MISSING_ATTRIBUTE (context, error, element_name, "name");
2326 GIrNodeUnion *union_;
2328 union_ = (GIrNodeUnion *) g_ir_node_new (G_IR_NODE_UNION);
2330 ((GIrNode *)union_)->name = g_strdup (name ? name : "");
2331 union_->gtype_name = g_strdup (typename);
2332 union_->gtype_init = g_strdup (typeinit);
2334 union_->deprecated = TRUE;
2336 union_->deprecated = FALSE;
2338 if (ctx->node_stack == NULL)
2339 ctx->current_module->entries =
2340 g_list_append (ctx->current_module->entries, union_);
2341 push_node (ctx, (GIrNode *)union_);
2343 state_switch (ctx, STATE_UNION);
2351 start_discriminator (GMarkupParseContext *context,
2352 const gchar *element_name,
2353 const gchar **attribute_names,
2354 const gchar **attribute_values,
2358 if (strcmp (element_name, "discriminator") == 0 &&
2359 ctx->state == STATE_UNION)
2362 const gchar *offset;
2364 type = find_attribute ("type", attribute_names, attribute_values);
2365 offset = find_attribute ("offset", attribute_names, attribute_values);
2367 MISSING_ATTRIBUTE (context, error, element_name, "type");
2368 else if (offset == NULL)
2369 MISSING_ATTRIBUTE (context, error, element_name, "offset");
2371 ((GIrNodeUnion *)CURRENT_NODE (ctx))->discriminator_type
2372 = parse_type (ctx, type);
2373 ((GIrNodeUnion *)CURRENT_NODE (ctx))->discriminator_offset
2384 parse_include (GMarkupParseContext *context,
2387 const char *version,
2392 gchar *girpath, *girname;
2393 gboolean success = FALSE;
2397 for (l = ctx->parser->parsed_modules; l; l = l->next)
2399 GIrModule *m = l->data;
2401 if (strcmp (m->name, name) == 0)
2403 if (strcmp (m->version, version) == 0)
2405 ctx->include_modules = g_list_prepend (ctx->include_modules, m);
2413 G_MARKUP_ERROR_INVALID_CONTENT,
2414 "Module '%s' imported with conflicting versions '%s' and '%s'",
2415 name, m->version, version);
2421 girname = g_strdup_printf ("%s-%s.gir", name, version);
2422 girpath = locate_gir (ctx->parser, girname);
2424 if (girpath == NULL)
2428 G_MARKUP_ERROR_INVALID_CONTENT,
2429 "Could not find GIR file '%s'; check XDG_DATA_DIRS or use --includedir",
2436 g_debug ("Parsing include %s", girpath);
2438 if (!g_file_get_contents (girpath, &buffer, &length, error))
2445 modules = g_ir_parser_parse_string (ctx->parser, name, buffer, length, error);
2446 success = error != NULL;
2448 ctx->include_modules = g_list_concat (ctx->include_modules,
2456 extern GLogLevelFlags logged_levels;
2459 start_element_handler (GMarkupParseContext *context,
2460 const gchar *element_name,
2461 const gchar **attribute_names,
2462 const gchar **attribute_values,
2466 ParseContext *ctx = user_data;
2467 gint line_number, char_number;
2469 if (logged_levels & G_LOG_LEVEL_DEBUG)
2471 GString *tags = g_string_new ("");
2473 for (i = 0; attribute_names[i]; i++)
2474 g_string_append_printf (tags, "%s=\"%s\" ",
2476 attribute_values[i]);
2480 g_string_insert_c (tags, 0, ' ');
2481 g_string_truncate (tags, tags->len - 1);
2483 g_debug ("<%s%s>", element_name, tags->str);
2484 g_string_free (tags, TRUE);
2487 switch (element_name[0])
2490 if (ctx->state == STATE_NAMESPACE && strcmp (element_name, "alias") == 0)
2492 state_switch (ctx, STATE_ALIAS);
2495 if (start_type (context, element_name,
2496 attribute_names, attribute_values,
2499 else if (start_attribute (context, element_name,
2500 attribute_names, attribute_values,
2505 if (start_enum (context, element_name,
2506 attribute_names, attribute_values,
2511 if (start_function (context, element_name,
2512 attribute_names, attribute_values,
2515 else if (start_constant (context, element_name,
2516 attribute_names, attribute_values,
2519 else if (start_class (context, element_name,
2520 attribute_names, attribute_values,
2526 if (start_discriminator (context, element_name,
2527 attribute_names, attribute_values,
2533 if (start_enum (context, element_name,
2534 attribute_names, attribute_values,
2537 else if (start_errordomain (context, element_name,
2538 attribute_names, attribute_values,
2544 if (start_function (context, element_name,
2545 attribute_names, attribute_values,
2548 else if (start_field (context, element_name,
2549 attribute_names, attribute_values,
2555 if (start_glib_boxed (context, element_name,
2556 attribute_names, attribute_values,
2559 else if (start_glib_signal (context, element_name,
2560 attribute_names, attribute_values,
2566 if (strcmp (element_name, "include") == 0 &&
2567 ctx->state == STATE_REPOSITORY)
2570 const gchar *version;
2572 name = find_attribute ("name", attribute_names, attribute_values);
2573 version = find_attribute ("version", attribute_names, attribute_values);
2577 MISSING_ATTRIBUTE (context, error, element_name, "name");
2580 if (version == NULL)
2582 MISSING_ATTRIBUTE (context, error, element_name, "version");
2586 if (!parse_include (context, ctx, name, version, error))
2589 ctx->dependencies = g_list_prepend (ctx->dependencies,
2590 g_strdup_printf ("%s-%s", name, version));
2593 state_switch (ctx, STATE_INCLUDE);
2596 if (start_interface (context, element_name,
2597 attribute_names, attribute_values,
2600 else if (start_implements (context, element_name,
2601 attribute_names, attribute_values,
2607 if (start_function (context, element_name,
2608 attribute_names, attribute_values,
2611 else if (start_member (context, element_name,
2612 attribute_names, attribute_values,
2618 if (strcmp (element_name, "namespace") == 0 && ctx->state == STATE_REPOSITORY)
2620 const gchar *name, *version, *shared_library, *cprefix;
2622 if (ctx->current_module != NULL)
2626 G_MARKUP_ERROR_INVALID_CONTENT,
2627 "Only one <namespace/> element is currently allowed per <repository/>");
2631 name = find_attribute ("name", attribute_names, attribute_values);
2632 version = find_attribute ("version", attribute_names, attribute_values);
2633 shared_library = find_attribute ("shared-library", attribute_names, attribute_values);
2634 cprefix = find_attribute ("c:prefix", attribute_names, attribute_values);
2637 MISSING_ATTRIBUTE (context, error, element_name, "name");
2638 else if (version == NULL)
2639 MISSING_ATTRIBUTE (context, error, element_name, "version");
2644 if (strcmp (name, ctx->namespace) != 0)
2647 G_MARKUP_ERROR_INVALID_CONTENT,
2648 "<namespace/> name element '%s' doesn't match file name '%s'",
2649 name, ctx->namespace);
2651 ctx->current_module = g_ir_module_new (name, version, shared_library, cprefix);
2653 ctx->current_module->aliases = ctx->aliases;
2654 ctx->aliases = NULL;
2655 ctx->current_module->disguised_structures = ctx->disguised_structures;
2656 ctx->disguised_structures = NULL;
2658 for (l = ctx->include_modules; l; l = l->next)
2659 g_ir_module_add_include_module (ctx->current_module, l->data);
2661 g_list_free (ctx->include_modules);
2662 ctx->include_modules = NULL;
2664 ctx->modules = g_list_append (ctx->modules, ctx->current_module);
2665 ctx->current_module->dependencies = ctx->dependencies;
2667 state_switch (ctx, STATE_NAMESPACE);
2674 if (start_property (context, element_name,
2675 attribute_names, attribute_values,
2678 else if (strcmp (element_name, "parameters") == 0 &&
2679 ctx->state == STATE_FUNCTION)
2681 state_switch (ctx, STATE_FUNCTION_PARAMETERS);
2685 else if (start_parameter (context, element_name,
2686 attribute_names, attribute_values,
2689 else if (strcmp (element_name, "prerequisite") == 0 &&
2690 ctx->state == STATE_INTERFACE)
2694 name = find_attribute ("name", attribute_names, attribute_values);
2696 state_switch (ctx, STATE_PREREQUISITE);
2699 MISSING_ATTRIBUTE (context, error, element_name, "name");
2702 GIrNodeInterface *iface;
2704 iface = (GIrNodeInterface *)CURRENT_NODE(ctx);
2705 iface->prerequisites = g_list_append (iface->prerequisites, g_strdup (name));
2709 else if (strcmp (element_name, "package") == 0 &&
2710 ctx->state == STATE_REPOSITORY)
2712 state_switch (ctx, STATE_PACKAGE);
2718 if (strcmp (element_name, "repository") == 0 && ctx->state == STATE_START)
2720 const gchar *version;
2722 version = find_attribute ("version", attribute_names, attribute_values);
2724 if (version == NULL)
2725 MISSING_ATTRIBUTE (context, error, element_name, "version");
2726 else if (strcmp (version, "1.0") != 0)
2729 G_MARKUP_ERROR_INVALID_CONTENT,
2730 "Unsupported version '%s'",
2733 state_switch (ctx, STATE_REPOSITORY);
2737 else if (start_return_value (context, element_name,
2738 attribute_names, attribute_values,
2741 else if (start_struct (context, element_name,
2742 attribute_names, attribute_values,
2748 if (start_union (context, element_name,
2749 attribute_names, attribute_values,
2755 if (start_type (context, element_name,
2756 attribute_names, attribute_values,
2762 if (start_vfunc (context, element_name,
2763 attribute_names, attribute_values,
2766 if (start_type (context, element_name,
2767 attribute_names, attribute_values,
2773 if (ctx->state != STATE_UNKNOWN)
2775 state_switch (ctx, STATE_UNKNOWN);
2776 ctx->unknown_depth = 1;
2780 ctx->unknown_depth += 1;
2786 g_markup_parse_context_get_position (context, &line_number, &char_number);
2788 fprintf (stderr, "Error at line %d, character %d: %s\n", line_number, char_number, (*error)->message);
2789 backtrace_stderr ();
2794 require_one_of_end_elements (GMarkupParseContext *context,
2796 const char *actual_name,
2801 int line_number, char_number;
2802 const char *expected;
2803 gboolean matched = FALSE;
2805 va_start (args, error);
2807 while ((expected = va_arg (args, const char*)) != NULL)
2809 if (strcmp (expected, actual_name) == 0)
2821 g_markup_parse_context_get_position (context, &line_number, &char_number);
2824 G_MARKUP_ERROR_INVALID_CONTENT,
2825 "Unexpected end tag '%s' on line %d char %d; current state=%d",
2827 line_number, char_number, ctx->state);
2833 state_switch_end_struct_or_union (GMarkupParseContext *context,
2835 const gchar *element_name,
2839 if (ctx->node_stack == NULL)
2841 state_switch (ctx, STATE_NAMESPACE);
2845 if (CURRENT_NODE (ctx)->type == G_IR_NODE_STRUCT)
2846 state_switch (ctx, STATE_STRUCT);
2847 else if (CURRENT_NODE (ctx)->type == G_IR_NODE_UNION)
2848 state_switch (ctx, STATE_UNION);
2849 else if (CURRENT_NODE (ctx)->type == G_IR_NODE_OBJECT)
2850 state_switch (ctx, STATE_CLASS);
2853 int line_number, char_number;
2854 g_markup_parse_context_get_position (context, &line_number, &char_number);
2857 G_MARKUP_ERROR_INVALID_CONTENT,
2858 "Unexpected end tag '%s' on line %d char %d",
2860 line_number, char_number);
2868 require_end_element (GMarkupParseContext *context,
2870 const char *expected_name,
2871 const char *actual_name,
2874 return require_one_of_end_elements (context, ctx, actual_name, error, expected_name, NULL);
2878 end_element_handler (GMarkupParseContext *context,
2879 const gchar *element_name,
2883 ParseContext *ctx = user_data;
2885 g_debug ("</%s>", element_name);
2891 /* no need to GError here, GMarkup already catches this */
2894 case STATE_REPOSITORY:
2895 state_switch (ctx, STATE_END);
2899 if (require_end_element (context, ctx, "include", element_name, error))
2901 state_switch (ctx, STATE_REPOSITORY);
2906 if (require_end_element (context, ctx, "package", element_name, error))
2908 state_switch (ctx, STATE_REPOSITORY);
2912 case STATE_NAMESPACE:
2913 if (require_end_element (context, ctx, "namespace", element_name, error))
2915 ctx->current_module = NULL;
2916 state_switch (ctx, STATE_REPOSITORY);
2921 if (require_end_element (context, ctx, "alias", element_name, error))
2923 state_switch (ctx, STATE_NAMESPACE);
2927 case STATE_FUNCTION_RETURN:
2928 if (strcmp ("type", element_name) == 0)
2930 if (require_end_element (context, ctx, "return-value", element_name, error))
2932 state_switch (ctx, STATE_FUNCTION);
2936 case STATE_FUNCTION_PARAMETERS:
2937 if (require_end_element (context, ctx, "parameters", element_name, error))
2939 state_switch (ctx, STATE_FUNCTION);
2943 case STATE_FUNCTION_PARAMETER:
2944 if (strcmp ("type", element_name) == 0)
2946 if (require_end_element (context, ctx, "parameter", element_name, error))
2948 state_switch (ctx, STATE_FUNCTION_PARAMETERS);
2952 case STATE_FUNCTION:
2955 if (ctx->node_stack == NULL)
2957 state_switch (ctx, STATE_NAMESPACE);
2961 g_debug("case STATE_FUNCTION %d", CURRENT_NODE (ctx)->type);
2962 if (ctx->in_embedded_type)
2964 ctx->in_embedded_type = FALSE;
2965 state_switch (ctx, STATE_STRUCT_FIELD);
2967 else if (CURRENT_NODE (ctx)->type == G_IR_NODE_INTERFACE)
2968 state_switch (ctx, STATE_INTERFACE);
2969 else if (CURRENT_NODE (ctx)->type == G_IR_NODE_OBJECT)
2970 state_switch (ctx, STATE_CLASS);
2971 else if (CURRENT_NODE (ctx)->type == G_IR_NODE_BOXED)
2972 state_switch (ctx, STATE_BOXED);
2973 else if (CURRENT_NODE (ctx)->type == G_IR_NODE_STRUCT)
2974 state_switch (ctx, STATE_STRUCT);
2975 else if (CURRENT_NODE (ctx)->type == G_IR_NODE_UNION)
2976 state_switch (ctx, STATE_UNION);
2979 int line_number, char_number;
2980 g_markup_parse_context_get_position (context, &line_number, &char_number);
2983 G_MARKUP_ERROR_INVALID_CONTENT,
2984 "Unexpected end tag '%s' on line %d char %d",
2986 line_number, char_number);
2992 case STATE_CLASS_FIELD:
2993 if (strcmp ("type", element_name) == 0)
2995 if (require_end_element (context, ctx, "field", element_name, error))
2997 state_switch (ctx, STATE_CLASS);
3001 case STATE_CLASS_PROPERTY:
3002 if (strcmp ("type", element_name) == 0)
3004 if (require_end_element (context, ctx, "property", element_name, error))
3006 state_switch (ctx, STATE_CLASS);
3011 if (require_end_element (context, ctx, "class", element_name, error))
3014 state_switch (ctx, STATE_NAMESPACE);
3018 case STATE_ERRORDOMAIN:
3019 if (require_end_element (context, ctx, "errordomain", element_name, error))
3022 state_switch (ctx, STATE_NAMESPACE);
3026 case STATE_INTERFACE_PROPERTY:
3027 if (strcmp ("type", element_name) == 0)
3029 if (require_end_element (context, ctx, "property", element_name, error))
3031 state_switch (ctx, STATE_INTERFACE);
3035 case STATE_INTERFACE_FIELD:
3036 if (strcmp ("type", element_name) == 0)
3038 if (require_end_element (context, ctx, "field", element_name, error))
3040 state_switch (ctx, STATE_INTERFACE);
3044 case STATE_INTERFACE:
3045 if (require_end_element (context, ctx, "interface", element_name, error))
3048 state_switch (ctx, STATE_NAMESPACE);
3053 if (strcmp ("member", element_name) == 0)
3055 else if (require_one_of_end_elements (context, ctx,
3056 element_name, error, "enumeration",
3060 state_switch (ctx, STATE_NAMESPACE);
3065 if (require_end_element (context, ctx, "glib:boxed", element_name, error))
3068 state_switch (ctx, STATE_NAMESPACE);
3072 case STATE_BOXED_FIELD:
3073 if (strcmp ("type", element_name) == 0)
3075 if (require_end_element (context, ctx, "field", element_name, error))
3077 state_switch (ctx, STATE_BOXED);
3081 case STATE_STRUCT_FIELD:
3082 if (strcmp ("type", element_name) == 0)
3084 if (require_end_element (context, ctx, "field", element_name, error))
3086 state_switch (ctx, STATE_STRUCT);
3091 if (require_end_element (context, ctx, "record", element_name, error))
3093 state_switch_end_struct_or_union (context, ctx, element_name, error);
3097 case STATE_UNION_FIELD:
3098 if (strcmp ("type", element_name) == 0)
3100 if (require_end_element (context, ctx, "field", element_name, error))
3102 state_switch (ctx, STATE_UNION);
3107 if (require_end_element (context, ctx, "union", element_name, error))
3109 state_switch_end_struct_or_union (context, ctx, element_name, error);
3112 case STATE_IMPLEMENTS:
3113 if (strcmp ("interface", element_name) == 0)
3115 if (require_end_element (context, ctx, "implements", element_name, error))
3116 state_switch (ctx, STATE_CLASS);
3118 case STATE_PREREQUISITE:
3119 if (require_end_element (context, ctx, "prerequisite", element_name, error))
3120 state_switch (ctx, STATE_INTERFACE);
3122 case STATE_NAMESPACE_CONSTANT:
3123 case STATE_CLASS_CONSTANT:
3124 case STATE_INTERFACE_CONSTANT:
3125 if (strcmp ("type", element_name) == 0)
3127 if (require_end_element (context, ctx, "constant", element_name, error))
3131 case STATE_NAMESPACE_CONSTANT:
3133 state_switch (ctx, STATE_NAMESPACE);
3135 case STATE_CLASS_CONSTANT:
3136 state_switch (ctx, STATE_CLASS);
3138 case STATE_INTERFACE_CONSTANT:
3139 state_switch (ctx, STATE_INTERFACE);
3142 g_assert_not_reached ();
3148 if ((strcmp ("type", element_name) == 0) || (strcmp ("array", element_name) == 0) ||
3149 (strcmp ("varargs", element_name) == 0))
3154 case STATE_ATTRIBUTE:
3155 if (strcmp ("attribute", element_name) == 0)
3157 state_switch (ctx, ctx->prev_state);
3162 ctx->unknown_depth -= 1;
3163 if (ctx->unknown_depth == 0)
3164 state_switch (ctx, ctx->prev_state);
3167 g_error ("Unhandled state %d in end_element_handler\n", ctx->state);
3172 text_handler (GMarkupParseContext *context,
3178 /* FIXME warn about non-whitespace text */
3182 cleanup (GMarkupParseContext *context,
3186 ParseContext *ctx = user_data;
3189 for (m = ctx->modules; m; m = m->next)
3190 g_ir_module_free (m->data);
3191 g_list_free (ctx->modules);
3192 ctx->modules = NULL;
3194 ctx->current_module = NULL;
3198 post_filter_toplevel_varargs_functions (GList *list,
3199 GList **varargs_callbacks_out)
3202 GList *varargs_callbacks = *varargs_callbacks_out;
3208 GIrNode *node = iter->data;
3212 if (node->type == G_IR_NODE_FUNCTION)
3214 if (((GIrNodeFunction*)node)->is_varargs)
3216 list = g_list_delete_link (list, link);
3219 if (node->type == G_IR_NODE_CALLBACK)
3221 if (((GIrNodeFunction*)node)->is_varargs)
3223 varargs_callbacks = g_list_append (varargs_callbacks,
3225 list = g_list_delete_link (list, link);
3230 *varargs_callbacks_out = varargs_callbacks;
3238 quick look up of node in the list..
3239 return null, or a pointer to the list item..
3242 node_find_in_list(GList *list, const char *name)
3249 if (!strcmp (name, ((GIrNode *)link->data)->name))
3258 post_filter_varargs_functions (GList *list, GList ** varargs_callbacks_out)
3261 GList *varargs_callbacks;
3263 list = post_filter_toplevel_varargs_functions (list, varargs_callbacks_out);
3265 varargs_callbacks = *varargs_callbacks_out;
3271 GIrNode *node = iter->data;
3275 if (node->type == G_IR_NODE_FUNCTION)
3278 gboolean function_done = FALSE;
3280 for (param = ((GIrNodeFunction *)node)->parameters;
3282 param = param->next)
3284 GIrNodeParam *node = (GIrNodeParam *)param->data;
3289 if (node->type->is_interface)
3292 GList *callback = node_find_in_list(
3294 node->type->interface);
3297 list = g_list_delete_link (list, link);
3298 function_done = TRUE;
3305 if (node->type == G_IR_NODE_FIELD)
3308 this is a field, if the member is a blacklisted callback,
3309 then we need to flag it as to be generated as a void*
3311 GIrNodeField *fnode = (GIrNodeField *)node;
3312 GIrNodeType * tnode;
3318 tnode = (GIrNodeType *)fnode->type;
3319 /* field is not an interface. */
3320 if (!tnode->is_interface)
3323 match = node_find_in_list(
3324 varargs_callbacks, tnode->interface);
3330 we now have a field which is pointing to an blacklisted callback.
3331 so need modify the type so it points to void* and
3332 is not read/or writable.
3334 fnode->readable = FALSE;
3335 fnode->writable = FALSE;
3337 tnode->tag = GI_TYPE_TAG_VOID;
3338 tnode->is_interface = FALSE;
3339 tnode->is_pointer = TRUE;
3340 tnode->is_basic = TRUE;
3346 *varargs_callbacks_out = varargs_callbacks;
3352 post_filter (GIrModule *module)
3355 GList *varargs_callbacks = NULL;
3357 module->entries = post_filter_varargs_functions (module->entries,
3358 &varargs_callbacks);
3359 iter = module->entries;
3362 GIrNode *node = iter->data;
3366 if (node->type == G_IR_NODE_OBJECT ||
3367 node->type == G_IR_NODE_INTERFACE)
3369 GIrNodeInterface *iface = (GIrNodeInterface*)node;
3370 iface->members = post_filter_varargs_functions (iface->members,
3371 &varargs_callbacks);
3373 else if (node->type == G_IR_NODE_BOXED)
3375 GIrNodeBoxed *boxed = (GIrNodeBoxed*)node;
3376 boxed->members = post_filter_varargs_functions (boxed->members,
3377 &varargs_callbacks);
3379 else if (node->type == G_IR_NODE_STRUCT)
3381 GIrNodeStruct *iface = (GIrNodeStruct*)node;
3382 iface->members = post_filter_varargs_functions (iface->members,
3383 &varargs_callbacks);
3385 else if (node->type == G_IR_NODE_UNION)
3387 GIrNodeUnion *iface = (GIrNodeUnion*)node;
3388 iface->members = post_filter_varargs_functions (iface->members,
3389 &varargs_callbacks);
3392 g_list_free (varargs_callbacks);
3396 * g_ir_parser_parse_string:
3397 * @parser: a #GIrParser
3398 * @namespace: the namespace of the string
3399 * @buffer: the data containing the XML
3400 * @length: length of the data
3401 * @error: return location for a #GError, or %NULL
3403 * Parse a string that holds a complete GIR XML file, and return a list of a
3404 * a #GirModule for each <namespace/> element within the file.
3406 * Returns: a newly allocated list of #GIrModule. The modules themselves
3407 * are owned by the #GIrParser and will be freed along with the parser.
3410 g_ir_parser_parse_string (GIrParser *parser,
3411 const gchar *namespace,
3412 const gchar *buffer,
3416 ParseContext ctx = { 0 };
3417 GMarkupParseContext *context;
3419 ctx.parser = parser;
3420 ctx.state = STATE_START;
3421 ctx.namespace = namespace;
3422 ctx.include_modules = NULL;
3423 ctx.aliases = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
3424 ctx.disguised_structures = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
3426 ctx.dependencies = NULL;
3427 ctx.current_module = NULL;
3429 context = g_markup_parse_context_new (&firstpass_parser, 0, &ctx, NULL);
3431 if (!g_markup_parse_context_parse (context, buffer, length, error))
3434 if (!g_markup_parse_context_end_parse (context, error))
3437 g_markup_parse_context_free (context);
3439 context = g_markup_parse_context_new (&markup_parser, 0, &ctx, NULL);
3440 if (!g_markup_parse_context_parse (context, buffer, length, error))
3443 if (!g_markup_parse_context_end_parse (context, error))
3446 parser->parsed_modules = g_list_concat (g_list_copy (ctx.modules),
3447 parser->parsed_modules);
3451 if (ctx.modules == NULL)
3453 /* An error occurred before we created a module, so we haven't
3454 * transferred ownership of these hash tables to the module.
3456 if (ctx.aliases != NULL)
3457 g_hash_table_destroy (ctx.aliases);
3458 if (ctx.disguised_structures != NULL)
3459 g_hash_table_destroy (ctx.disguised_structures);
3460 g_list_free (ctx.include_modules);
3463 g_markup_parse_context_free (context);
3469 * g_ir_parser_parse_file:
3470 * @parser: a #GIrParser
3471 * @filename: filename to parse
3472 * @error: return location for a #GError, or %NULL
3474 * Parse GIR XML file, and return a list of a a #GirModule for each
3475 * <namespace/> element within the file.
3477 * Returns: a newly allocated list of #GIrModule. The modules themselves
3478 * are owned by the #GIrParser and will be freed along with the parser.
3481 g_ir_parser_parse_file (GIrParser *parser,
3482 const gchar *filename,
3493 if (!g_str_has_suffix (filename, ".gir"))
3497 G_MARKUP_ERROR_INVALID_CONTENT,
3498 "Expected filename to end with '.gir'");
3502 g_debug ("[parsing] filename %s", filename);
3504 slash = g_strrstr (filename, "/");
3506 namespace = g_strdup (filename);
3508 namespace = g_strdup (slash+1);
3509 namespace[strlen(namespace)-4] = '\0';
3511 /* Remove version */
3512 dash = strstr (namespace, "-");
3516 if (!g_file_get_contents (filename, &buffer, &length, error))
3519 modules = g_ir_parser_parse_string (parser, namespace, buffer, length, error);
3521 for (iter = modules; iter; iter = iter->next)
3523 post_filter ((GIrModule*)iter->data);