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 **includes;
74 gboolean prefix_aliases;
77 const char *namespace;
78 GIrModule *current_module;
79 GIrNode *current_node;
80 GIrNode *current_typed;
85 start_alias (GMarkupParseContext *context,
86 const gchar *element_name,
87 const gchar **attribute_names,
88 const gchar **attribute_values,
93 firstpass_start_element_handler (GMarkupParseContext *context,
94 const gchar *element_name,
95 const gchar **attribute_names,
96 const gchar **attribute_values,
100 ParseContext *ctx = user_data;
102 if (strcmp (element_name, "alias") == 0)
104 start_alias (context, element_name, attribute_names, attribute_values,
110 firstpass_end_element_handler (GMarkupParseContext *context,
111 const gchar *element_name,
115 ParseContext *ctx = user_data;
119 static GMarkupParser firstpass_parser =
121 firstpass_start_element_handler,
122 firstpass_end_element_handler,
129 locate_gir (const char *name, const char **extra_paths)
131 const gchar *const *datadirs;
132 const gchar *const *dir;
136 gboolean firstpass = TRUE;
138 datadirs = g_get_system_data_dirs ();
140 girname = g_strdup_printf ("%s.gir", name);
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))
149 if (firstpass && !*dir)
159 #define MISSING_ATTRIBUTE(ctx,error,element,attribute) \
161 int line_number, char_number; \
162 g_markup_parse_context_get_position (context, &line_number, &char_number); \
163 g_set_error (error, \
165 G_MARKUP_ERROR_INVALID_CONTENT, \
166 "Line %d, character %d: The attribute '%s' on the element '%s' must be specified", \
167 line_number, char_number, attribute, element); \
171 backtrace_stderr (void)
179 size = backtrace (array, 50);
180 strings = (char**) backtrace_symbols (array, size);
182 fprintf (stderr, "--- BACKTRACE (%zd frames) ---\n", size);
184 for (i = 0; i < size; i++)
185 fprintf (stderr, "%s\n", strings[i]);
187 fprintf (stderr, "--- END BACKTRACE ---\n", size);
195 find_attribute (const gchar *name,
196 const gchar **attribute_names,
197 const gchar **attribute_values)
201 for (i = 0; attribute_names[i] != NULL; i++)
202 if (strcmp (attribute_names[i], name) == 0)
203 return attribute_values[i];
209 state_switch (ParseContext *ctx, ParseState newstate)
211 g_debug ("State: %d", newstate);
212 ctx->prev_state = ctx->state;
213 ctx->state = newstate;
216 static GIrNodeType * parse_type_internal (gchar *str, gchar **rest);
221 char *pointer = g_strdup ("any");
223 GIrNodeType *ret = parse_type_internal (pointer, &pointer_rest);
229 parse_type_internal (gchar *str, gchar **rest)
238 { "none", GI_TYPE_TAG_VOID, 0 },
239 { "any", GI_TYPE_TAG_VOID, 1 },
241 { "bool", GI_TYPE_TAG_BOOLEAN, 0 },
242 { "char", GI_TYPE_TAG_INT8, 0 },
243 { "int8", GI_TYPE_TAG_INT8, 0 },
244 { "uint8", GI_TYPE_TAG_UINT8, 0 },
245 { "int16", GI_TYPE_TAG_INT16, 0 },
246 { "uint16", GI_TYPE_TAG_UINT16, 0 },
247 { "int32", GI_TYPE_TAG_INT32, 0 },
248 { "uint32", GI_TYPE_TAG_UINT32, 0 },
249 { "int64", GI_TYPE_TAG_INT64, 0 },
250 { "uint64", GI_TYPE_TAG_UINT64, 0 },
251 { "int", GI_TYPE_TAG_INT, 0 },
252 { "uint", GI_TYPE_TAG_UINT, 0 },
253 { "long", GI_TYPE_TAG_LONG, 0 },
254 { "ulong", GI_TYPE_TAG_ULONG, 0 },
255 { "ssize_t", GI_TYPE_TAG_SSIZE, 0 },
256 { "ssize", GI_TYPE_TAG_SSIZE, 0 },
257 { "size_t", GI_TYPE_TAG_SIZE, 0 },
258 { "size", GI_TYPE_TAG_SIZE, 0 },
259 { "float", GI_TYPE_TAG_FLOAT, 0 },
260 { "double", GI_TYPE_TAG_DOUBLE, 0 },
261 { "utf8", GI_TYPE_TAG_UTF8, 1 },
262 { "filename", GI_TYPE_TAG_FILENAME,1 },
264 /* FIXME: merge - do we still want this? */
265 { "string", GI_TYPE_TAG_UTF8, 1 },
267 /* FIXME: Remove these */
268 { "void", GI_TYPE_TAG_VOID, 0 },
269 { "int8_t", GI_TYPE_TAG_INT8, 0 },
270 { "uint8_t", GI_TYPE_TAG_UINT8, 0 },
271 { "int16_t", GI_TYPE_TAG_INT16, 0 },
272 { "uint16_t", GI_TYPE_TAG_UINT16, 0 },
273 { "int32_t", GI_TYPE_TAG_INT32, 0 },
274 { "uint32_t", GI_TYPE_TAG_UINT32, 0 },
275 { "int64_t", GI_TYPE_TAG_INT64, 0 },
276 { "uint64_t", GI_TYPE_TAG_UINT64, 0 },
277 { "gpointer", GI_TYPE_TAG_VOID, 1 },
278 { "gboolean", GI_TYPE_TAG_BOOLEAN, 0 },
279 { "gchar", GI_TYPE_TAG_INT8, 0 },
280 { "guchar", GI_TYPE_TAG_UINT8, 0 },
281 { "gunichar", GI_TYPE_TAG_UINT32, 0 },
282 { "gint", GI_TYPE_TAG_INT, 0 },
283 { "guint", GI_TYPE_TAG_UINT, 0 },
284 { "gshort", GI_TYPE_TAG_INT16, 0 },
285 { "gushort", GI_TYPE_TAG_UINT16, 0 },
286 { "gint8", GI_TYPE_TAG_INT8, 0 },
287 { "guint8", GI_TYPE_TAG_UINT8, 0 },
288 { "gint16", GI_TYPE_TAG_INT16, 0 },
289 { "guint16", GI_TYPE_TAG_UINT16, 0 },
290 { "gint32", GI_TYPE_TAG_INT32, 0 },
291 { "guint32", GI_TYPE_TAG_UINT32, 0 },
292 { "gint64", GI_TYPE_TAG_INT64, 0 },
293 { "guint64", GI_TYPE_TAG_UINT64, 0 },
294 { "glong", GI_TYPE_TAG_LONG, 0 },
295 { "gulong", GI_TYPE_TAG_ULONG, 0 },
296 { "gssize", GI_TYPE_TAG_SSIZE, 0 },
297 { "gsize", GI_TYPE_TAG_SIZE, 0 },
298 { "gfloat", GI_TYPE_TAG_FLOAT, 0 },
299 { "gdouble", GI_TYPE_TAG_DOUBLE, 0 },
300 { "gchar*", GI_TYPE_TAG_UTF8, 1 }
303 gint n_basic = G_N_ELEMENTS (basic);
308 type = (GIrNodeType *)g_ir_node_new (G_IR_NODE_TYPE);
310 str = g_strstrip (str);
312 type->unparsed = g_strdup (str);
315 for (i = 0; i < n_basic; i++)
317 if (g_str_has_prefix (*rest, basic[i].str))
319 type->is_basic = TRUE;
320 type->tag = basic[i].tag;
321 type->is_pointer = basic[i].pointer;
323 *rest += strlen(basic[i].str);
324 *rest = g_strchug (*rest);
325 if (**rest == '*' && !type->is_pointer)
327 type->is_pointer = TRUE;
336 /* found a basic type */;
337 else if (g_str_has_prefix (*rest, "GList") ||
338 g_str_has_prefix (*rest, "GSList"))
340 if (g_str_has_prefix (*rest, "GList"))
342 type->tag = GI_TYPE_TAG_GLIST;
343 type->is_glist = TRUE;
344 type->is_pointer = TRUE;
345 *rest += strlen ("GList");
349 type->tag = GI_TYPE_TAG_GSLIST;
350 type->is_gslist = TRUE;
351 type->is_pointer = TRUE;
352 *rest += strlen ("GSList");
355 *rest = g_strchug (*rest);
361 type->parameter_type1 = parse_type_internal (*rest, rest);
362 if (type->parameter_type1 == NULL)
365 *rest = g_strchug (*rest);
367 if ((*rest)[0] != '>')
373 type->parameter_type1 = create_pointer ();
376 else if (g_str_has_prefix (*rest, "GHashTable"))
378 type->tag = GI_TYPE_TAG_GHASH;
379 type->is_ghashtable = TRUE;
380 type->is_pointer = TRUE;
381 *rest += strlen ("GHashTable");
383 *rest = g_strchug (*rest);
389 type->parameter_type1 = parse_type_internal (*rest, rest);
390 if (type->parameter_type1 == NULL)
393 *rest = g_strchug (*rest);
395 if ((*rest)[0] != ',')
399 type->parameter_type2 = parse_type_internal (*rest, rest);
400 if (type->parameter_type2 == NULL)
403 if ((*rest)[0] != '>')
409 type->parameter_type1 = create_pointer ();
410 type->parameter_type2 = create_pointer ();
414 else if (g_str_has_prefix (*rest, "GError"))
416 type->tag = GI_TYPE_TAG_ERROR;
417 type->is_error = TRUE;
418 type->is_pointer = TRUE;
419 *rest += strlen ("GError");
421 *rest = g_strchug (*rest);
427 end = strchr (*rest, '>');
428 str = g_strndup (*rest, end - *rest);
429 type->errors = g_strsplit (str, ",", 0);
437 type->tag = GI_TYPE_TAG_INTERFACE;
438 type->is_interface = TRUE;
441 /* must be an interface type */
442 while (g_ascii_isalnum (**rest) ||
449 type->interface = g_strndup (start, *rest - start);
451 *rest = g_strchug (*rest);
454 type->is_pointer = TRUE;
459 *rest = g_strchug (*rest);
460 if (g_str_has_prefix (*rest, "["))
464 array = (GIrNodeType *)g_ir_node_new (G_IR_NODE_TYPE);
466 array->tag = GI_TYPE_TAG_ARRAY;
467 array->is_pointer = TRUE;
468 array->is_array = TRUE;
470 array->parameter_type1 = type;
472 array->zero_terminated = FALSE;
473 array->has_length = FALSE;
476 if (!g_str_has_prefix (*rest, "[]"))
478 gchar *end, *str, **opts;
480 end = strchr (*rest, ']');
481 str = g_strndup (*rest + 1, (end - *rest) - 1);
482 opts = g_strsplit (str, ",", 0);
486 for (i = 0; opts[i]; i++)
490 vals = g_strsplit (opts[i], "=", 0);
492 if (strcmp (vals[0], "zero-terminated") == 0)
493 array->zero_terminated = (strcmp (vals[1], "1") == 0);
494 else if (strcmp (vals[0], "length") == 0)
496 array->has_length = TRUE;
497 array->length = atoi (vals[1]);
510 g_assert (type->tag >= 0 && type->tag <= GI_TYPE_TAG_ERROR);
514 g_ir_node_free ((GIrNode *)type);
520 resolve_aliases (ParseContext *ctx, const gchar *type)
524 GSList *seen_values = NULL;
526 seen_values = g_slist_prepend (seen_values, (char*)type);
527 while (g_hash_table_lookup_extended (ctx->aliases, type, &orig, &value))
529 g_debug ("Resolved: %s => %s", type, value);
531 if (g_slist_find_custom (seen_values, type,
532 (GCompareFunc)strcmp) != NULL)
534 seen_values = g_slist_prepend (seen_values, (gchar*)type);
536 g_slist_free (seen_values);
541 parse_type (ParseContext *ctx, const gchar *type)
547 type = resolve_aliases (ctx, type);
548 str = g_strdup (type);
549 node = parse_type_internal (str, &rest);
551 g_debug ("Parsed type: %s => %d", type, node->tag);
557 start_glib_boxed (GMarkupParseContext *context,
558 const gchar *element_name,
559 const gchar **attribute_names,
560 const gchar **attribute_values,
565 const gchar *typename;
566 const gchar *typeinit;
567 const gchar *deprecated;
570 if (!(strcmp (element_name, "glib:boxed") == 0 &&
571 ctx->state == STATE_NAMESPACE))
574 name = find_attribute ("glib:name", attribute_names, attribute_values);
575 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
576 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
577 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
581 MISSING_ATTRIBUTE (context, error, element_name, "glib:name");
584 else if (typename == NULL)
586 MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
589 else if (typeinit == NULL)
591 MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
595 boxed = (GIrNodeBoxed *) g_ir_node_new (G_IR_NODE_BOXED);
597 ((GIrNode *)boxed)->name = g_strdup (name);
598 boxed->gtype_name = g_strdup (typename);
599 boxed->gtype_init = g_strdup (typeinit);
600 if (deprecated && strcmp (deprecated, "1") == 0)
601 boxed->deprecated = TRUE;
603 boxed->deprecated = FALSE;
605 ctx->current_node = (GIrNode *)boxed;
606 ctx->current_module->entries =
607 g_list_append (ctx->current_module->entries, boxed);
609 state_switch (ctx, STATE_BOXED);
615 start_function (GMarkupParseContext *context,
616 const gchar *element_name,
617 const gchar **attribute_names,
618 const gchar **attribute_values,
624 const gchar *deprecated;
625 GIrNodeFunction *function;
626 gboolean found = FALSE;
630 case STATE_NAMESPACE:
631 found = (strcmp (element_name, "function") == 0 ||
632 strcmp (element_name, "callback") == 0);
638 found = strcmp (element_name, "constructor") == 0;
640 case STATE_INTERFACE:
642 strcmp (element_name, "method") == 0 ||
643 strcmp (element_name, "callback") == 0);
652 name = find_attribute ("name", attribute_names, attribute_values);
653 symbol = find_attribute ("c:identifier", attribute_names, attribute_values);
654 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
658 MISSING_ATTRIBUTE (context, error, element_name, "name");
661 else if (strcmp (element_name, "callback") != 0 && symbol == NULL)
663 MISSING_ATTRIBUTE (context, error, element_name, "c:identifier");
667 function = (GIrNodeFunction *) g_ir_node_new (G_IR_NODE_FUNCTION);
669 ((GIrNode *)function)->name = g_strdup (name);
670 function->symbol = g_strdup (symbol);
671 function->parameters = NULL;
672 if (deprecated && strcmp (deprecated, "1") == 0)
673 function->deprecated = TRUE;
675 function->deprecated = FALSE;
677 if (strcmp (element_name, "method") == 0 ||
678 strcmp (element_name, "constructor") == 0)
680 function->is_method = TRUE;
682 if (strcmp (element_name, "constructor") == 0)
683 function->is_constructor = TRUE;
685 function->is_constructor = FALSE;
689 function->is_method = FALSE;
690 function->is_setter = FALSE;
691 function->is_getter = FALSE;
692 function->is_constructor = FALSE;
693 if (strcmp (element_name, "callback") == 0)
694 ((GIrNode *)function)->type = G_IR_NODE_CALLBACK;
697 if (ctx->current_node == NULL)
699 ctx->current_module->entries =
700 g_list_append (ctx->current_module->entries, function);
703 switch (ctx->current_node->type)
705 case G_IR_NODE_INTERFACE:
706 case G_IR_NODE_OBJECT:
708 GIrNodeInterface *iface;
710 iface = (GIrNodeInterface *)ctx->current_node;
711 iface->members = g_list_append (iface->members, function);
714 case G_IR_NODE_BOXED:
718 boxed = (GIrNodeBoxed *)ctx->current_node;
719 boxed->members = g_list_append (boxed->members, function);
722 case G_IR_NODE_STRUCT:
724 GIrNodeStruct *struct_;
726 struct_ = (GIrNodeStruct *)ctx->current_node;
727 struct_->members = g_list_append (struct_->members, function); }
729 case G_IR_NODE_UNION:
731 GIrNodeUnion *union_;
733 union_ = (GIrNodeUnion *)ctx->current_node;
734 union_->members = g_list_append (union_->members, function);
738 g_assert_not_reached ();
741 ctx->current_node = (GIrNode *)function;
742 state_switch (ctx, STATE_FUNCTION);
748 start_parameter (GMarkupParseContext *context,
749 const gchar *element_name,
750 const gchar **attribute_names,
751 const gchar **attribute_values,
756 const gchar *direction;
759 const gchar *optional;
761 const gchar *transfer;
764 if (!(strcmp (element_name, "parameter") == 0 &&
765 ctx->state == STATE_FUNCTION_PARAMETERS))
768 name = find_attribute ("name", attribute_names, attribute_values);
769 direction = find_attribute ("direction", attribute_names, attribute_values);
770 retval = find_attribute ("retval", attribute_names, attribute_values);
771 dipper = find_attribute ("dipper", attribute_names, attribute_values);
772 optional = find_attribute ("optional", attribute_names, attribute_values);
773 nullok = find_attribute ("null-ok", attribute_names, attribute_values);
774 transfer = find_attribute ("transfer", attribute_names, attribute_values);
779 param = (GIrNodeParam *)g_ir_node_new (G_IR_NODE_PARAM);
781 ctx->current_typed = (GIrNode*) param;
782 ctx->current_typed->name = g_strdup (name);
784 state_switch (ctx, STATE_FUNCTION_PARAMETER);
786 if (direction && strcmp (direction, "out") == 0)
791 else if (direction && strcmp (direction, "inout") == 0)
802 if (retval && strcmp (retval, "1") == 0)
803 param->retval = TRUE;
805 param->retval = FALSE;
807 if (dipper && strcmp (dipper, "1") == 0)
808 param->dipper = TRUE;
810 param->dipper = FALSE;
812 if (optional && strcmp (optional, "1") == 0)
813 param->optional = TRUE;
815 param->optional = FALSE;
817 if (nullok && strcmp (nullok, "1") == 0)
818 param->null_ok = TRUE;
820 param->null_ok = FALSE;
822 if (transfer && strcmp (transfer, "none") == 0)
824 param->transfer = FALSE;
825 param->shallow_transfer = FALSE;
827 else if (transfer && strcmp (transfer, "shallow") == 0)
829 param->transfer = FALSE;
830 param->shallow_transfer = TRUE;
836 if (strcmp (transfer, "full") != 0)
837 g_warning ("Unknown transfer %s", transfer);
839 param->transfer = TRUE;
841 else if (param->in && !param->out)
842 param->transfer = FALSE;
844 param->transfer = TRUE;
845 param->shallow_transfer = FALSE;
848 ((GIrNode *)param)->name = g_strdup (name);
850 switch (ctx->current_node->type)
852 case G_IR_NODE_FUNCTION:
853 case G_IR_NODE_CALLBACK:
855 GIrNodeFunction *func;
857 func = (GIrNodeFunction *)ctx->current_node;
858 func->parameters = g_list_append (func->parameters, param);
861 case G_IR_NODE_SIGNAL:
863 GIrNodeSignal *signal;
865 signal = (GIrNodeSignal *)ctx->current_node;
866 signal->parameters = g_list_append (signal->parameters, param);
869 case G_IR_NODE_VFUNC:
873 vfunc = (GIrNodeVFunc *)ctx->current_node;
874 vfunc->parameters = g_list_append (vfunc->parameters, param);
878 g_assert_not_reached ();
885 start_field (GMarkupParseContext *context,
886 const gchar *element_name,
887 const gchar **attribute_names,
888 const gchar **attribute_values,
893 const gchar *readable;
894 const gchar *writable;
906 case STATE_INTERFACE:
912 if (strcmp (element_name, "field") != 0)
915 name = find_attribute ("name", attribute_names, attribute_values);
916 readable = find_attribute ("readable", attribute_names, attribute_values);
917 writable = find_attribute ("writable", attribute_names, attribute_values);
918 bits = find_attribute ("bits", attribute_names, attribute_values);
919 branch = find_attribute ("branch", attribute_names, attribute_values);
920 offset = find_attribute ("offset", attribute_names, attribute_values);
924 MISSING_ATTRIBUTE (context, error, element_name, "name");
928 field = (GIrNodeField *)g_ir_node_new (G_IR_NODE_FIELD);
929 ctx->current_typed = (GIrNode*) field;
930 ((GIrNode *)field)->name = g_strdup (name);
931 if (readable && strcmp (readable, "1") == 0)
932 field->readable = TRUE;
934 field->readable = FALSE;
936 if (writable && strcmp (writable, "1") == 0)
937 field->writable = TRUE;
939 field->writable = FALSE;
942 field->bits = atoi (bits);
947 field->offset = atoi (offset);
951 switch (ctx->current_node->type)
953 case G_IR_NODE_OBJECT:
955 GIrNodeInterface *iface;
957 iface = (GIrNodeInterface *)ctx->current_node;
958 iface->members = g_list_append (iface->members, field);
959 state_switch (ctx, STATE_CLASS_FIELD);
962 case G_IR_NODE_INTERFACE:
964 GIrNodeInterface *iface;
966 iface = (GIrNodeInterface *)ctx->current_node;
967 iface->members = g_list_append (iface->members, field);
968 state_switch (ctx, STATE_INTERFACE_FIELD);
971 case G_IR_NODE_BOXED:
975 boxed = (GIrNodeBoxed *)ctx->current_node;
976 boxed->members = g_list_append (boxed->members, field);
977 state_switch (ctx, STATE_BOXED_FIELD);
980 case G_IR_NODE_STRUCT:
982 GIrNodeStruct *struct_;
984 struct_ = (GIrNodeStruct *)ctx->current_node;
985 struct_->members = g_list_append (struct_->members, field);
986 state_switch (ctx, STATE_STRUCT_FIELD);
989 case G_IR_NODE_UNION:
991 GIrNodeUnion *union_;
993 union_ = (GIrNodeUnion *)ctx->current_node;
994 union_->members = g_list_append (union_->members, field);
997 GIrNodeConstant *constant;
999 constant = (GIrNodeConstant *) g_ir_node_new (G_IR_NODE_CONSTANT);
1000 ((GIrNode *)constant)->name = g_strdup (name);
1001 constant->value = g_strdup (branch);
1002 constant->type = union_->discriminator_type;
1003 constant->deprecated = FALSE;
1005 union_->discriminators = g_list_append (union_->discriminators, constant);
1007 state_switch (ctx, STATE_UNION_FIELD);
1011 g_assert_not_reached ();
1018 start_alias (GMarkupParseContext *context,
1019 const gchar *element_name,
1020 const gchar **attribute_names,
1021 const gchar **attribute_values,
1026 const gchar *target;
1031 name = find_attribute ("name", attribute_names, attribute_values);
1034 MISSING_ATTRIBUTE (context, error, element_name, "name");
1038 target = find_attribute ("target", attribute_names, attribute_values);
1041 MISSING_ATTRIBUTE (context, error, element_name, "target");
1045 if (ctx->prefix_aliases)
1046 key = g_strdup_printf ("%s.%s", ctx->namespace, name);
1048 key = g_strdup (name);
1050 g_hash_table_insert (ctx->aliases, key, g_strdup (target));
1056 start_enum (GMarkupParseContext *context,
1057 const gchar *element_name,
1058 const gchar **attribute_names,
1059 const gchar **attribute_values,
1063 if ((strcmp (element_name, "enumeration") == 0 && ctx->state == STATE_NAMESPACE) ||
1064 (strcmp (element_name, "bitfield") == 0 && ctx->state == STATE_NAMESPACE))
1067 const gchar *typename;
1068 const gchar *typeinit;
1069 const gchar *deprecated;
1071 name = find_attribute ("name", attribute_names, attribute_values);
1072 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
1073 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
1074 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1077 MISSING_ATTRIBUTE (context, error, element_name, "name");
1082 if (strcmp (element_name, "enumeration") == 0)
1083 enum_ = (GIrNodeEnum *) g_ir_node_new (G_IR_NODE_ENUM);
1085 enum_ = (GIrNodeEnum *) g_ir_node_new (G_IR_NODE_FLAGS);
1086 ((GIrNode *)enum_)->name = g_strdup (name);
1087 enum_->gtype_name = g_strdup (typename);
1088 enum_->gtype_init = g_strdup (typeinit);
1089 if (deprecated && strcmp (deprecated, "1") == 0)
1090 enum_->deprecated = TRUE;
1092 enum_->deprecated = FALSE;
1094 ctx->current_node = (GIrNode *) enum_;
1095 ctx->current_module->entries =
1096 g_list_append (ctx->current_module->entries, enum_);
1098 state_switch (ctx, STATE_ENUM);
1107 start_property (GMarkupParseContext *context,
1108 const gchar *element_name,
1109 const gchar **attribute_names,
1110 const gchar **attribute_values,
1114 if (strcmp (element_name, "property") == 0 &&
1115 (ctx->state == STATE_CLASS ||
1116 ctx->state == STATE_INTERFACE))
1119 const gchar *readable;
1120 const gchar *writable;
1121 const gchar *construct;
1122 const gchar *construct_only;
1124 name = find_attribute ("name", attribute_names, attribute_values);
1125 readable = find_attribute ("readable", attribute_names, attribute_values);
1126 writable = find_attribute ("writable", attribute_names, attribute_values);
1127 construct = find_attribute ("construct", attribute_names, attribute_values);
1128 construct_only = find_attribute ("construct-only", attribute_names, attribute_values);
1131 MISSING_ATTRIBUTE (context, error, element_name, "name");
1134 GIrNodeProperty *property;
1135 GIrNodeInterface *iface;
1137 property = (GIrNodeProperty *) g_ir_node_new (G_IR_NODE_PROPERTY);
1138 ctx->current_typed = (GIrNode*) property;
1140 ((GIrNode *)property)->name = g_strdup (name);
1142 if (readable && strcmp (readable, "1") == 0)
1143 property->readable = TRUE;
1145 property->readable = FALSE;
1146 if (writable && strcmp (writable, "1") == 0)
1147 property->writable = TRUE;
1149 property->writable = FALSE;
1150 if (construct && strcmp (construct, "1") == 0)
1151 property->construct = TRUE;
1153 property->construct = FALSE;
1154 if (construct_only && strcmp (construct_only, "1") == 0)
1155 property->construct_only = TRUE;
1157 property->construct_only = FALSE;
1159 iface = (GIrNodeInterface *)ctx->current_node;
1160 iface->members = g_list_append (iface->members, property);
1162 if (ctx->state == STATE_CLASS)
1163 state_switch (ctx, STATE_CLASS_PROPERTY);
1164 else if (ctx->state == STATE_INTERFACE)
1165 state_switch (ctx, STATE_INTERFACE_PROPERTY);
1167 g_assert_not_reached ();
1176 parse_value (const gchar *str)
1180 /* FIXME just a quick hack */
1181 shift_op = strstr (str, "<<");
1187 base = strtol (str, NULL, 10);
1188 shift = strtol (shift_op + 3, NULL, 10);
1190 return base << shift;
1193 return strtol (str, NULL, 10);
1199 start_member (GMarkupParseContext *context,
1200 const gchar *element_name,
1201 const gchar **attribute_names,
1202 const gchar **attribute_values,
1206 if (strcmp (element_name, "member") == 0 &&
1207 ctx->state == STATE_ENUM)
1211 const gchar *deprecated;
1213 name = find_attribute ("name", attribute_names, attribute_values);
1214 value = find_attribute ("value", attribute_names, attribute_values);
1215 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1218 MISSING_ATTRIBUTE (context, error, element_name, "name");
1222 GIrNodeValue *value_;
1224 value_ = (GIrNodeValue *) g_ir_node_new (G_IR_NODE_VALUE);
1226 ((GIrNode *)value_)->name = g_strdup (name);
1228 value_->value = parse_value (value);
1230 if (deprecated && strcmp (deprecated, "1") == 0)
1231 value_->deprecated = TRUE;
1233 value_->deprecated = FALSE;
1235 enum_ = (GIrNodeEnum *)ctx->current_node;
1236 enum_->values = g_list_append (enum_->values, value_);
1245 start_constant (GMarkupParseContext *context,
1246 const gchar *element_name,
1247 const gchar **attribute_names,
1248 const gchar **attribute_values,
1252 if (strcmp (element_name, "constant") == 0 &&
1253 (ctx->state == STATE_NAMESPACE ||
1254 ctx->state == STATE_CLASS ||
1255 ctx->state == STATE_INTERFACE))
1259 const gchar *deprecated;
1261 name = find_attribute ("name", attribute_names, attribute_values);
1262 value = find_attribute ("value", attribute_names, attribute_values);
1263 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1266 MISSING_ATTRIBUTE (context, error, element_name, "name");
1267 else if (value == NULL)
1268 MISSING_ATTRIBUTE (context, error, element_name, "value");
1271 GIrNodeConstant *constant;
1273 constant = (GIrNodeConstant *) g_ir_node_new (G_IR_NODE_CONSTANT);
1275 ((GIrNode *)constant)->name = g_strdup (name);
1276 constant->value = g_strdup (value);
1278 ctx->current_typed = (GIrNode*) constant;
1280 if (deprecated && strcmp (deprecated, "1") == 0)
1281 constant->deprecated = TRUE;
1283 constant->deprecated = FALSE;
1285 if (ctx->state == STATE_NAMESPACE)
1287 ctx->current_node = (GIrNode *) constant;
1288 ctx->current_module->entries =
1289 g_list_append (ctx->current_module->entries, constant);
1293 GIrNodeInterface *iface;
1295 iface = (GIrNodeInterface *)ctx->current_node;
1296 iface->members = g_list_append (iface->members, constant);
1301 case STATE_NAMESPACE:
1302 state_switch (ctx, STATE_NAMESPACE_CONSTANT);
1305 state_switch (ctx, STATE_CLASS_CONSTANT);
1307 case STATE_INTERFACE:
1308 state_switch (ctx, STATE_INTERFACE_CONSTANT);
1311 g_assert_not_reached ();
1322 start_errordomain (GMarkupParseContext *context,
1323 const gchar *element_name,
1324 const gchar **attribute_names,
1325 const gchar **attribute_values,
1329 if (strcmp (element_name, "errordomain") == 0 &&
1330 ctx->state == STATE_NAMESPACE)
1333 const gchar *getquark;
1335 const gchar *deprecated;
1337 name = find_attribute ("name", attribute_names, attribute_values);
1338 getquark = find_attribute ("get-quark", attribute_names, attribute_values);
1339 codes = find_attribute ("codes", attribute_names, attribute_values);
1340 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1343 MISSING_ATTRIBUTE (context, error, element_name, "name");
1344 else if (getquark == NULL)
1345 MISSING_ATTRIBUTE (context, error, element_name, "getquark");
1346 else if (codes == NULL)
1347 MISSING_ATTRIBUTE (context, error, element_name, "codes");
1350 GIrNodeErrorDomain *domain;
1352 domain = (GIrNodeErrorDomain *) g_ir_node_new (G_IR_NODE_ERROR_DOMAIN);
1354 ((GIrNode *)domain)->name = g_strdup (name);
1355 domain->getquark = g_strdup (getquark);
1356 domain->codes = g_strdup (codes);
1358 if (deprecated && strcmp (deprecated, "1") == 0)
1359 domain->deprecated = TRUE;
1361 domain->deprecated = FALSE;
1363 ctx->current_node = (GIrNode *) domain;
1364 ctx->current_module->entries =
1365 g_list_append (ctx->current_module->entries, domain);
1367 state_switch (ctx, STATE_ERRORDOMAIN);
1376 start_interface (GMarkupParseContext *context,
1377 const gchar *element_name,
1378 const gchar **attribute_names,
1379 const gchar **attribute_values,
1383 if (strcmp (element_name, "interface") == 0 &&
1384 ctx->state == STATE_NAMESPACE)
1387 const gchar *typename;
1388 const gchar *typeinit;
1389 const gchar *deprecated;
1391 name = find_attribute ("name", attribute_names, attribute_values);
1392 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
1393 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
1394 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1397 MISSING_ATTRIBUTE (context, error, element_name, "name");
1398 else if (typename == NULL)
1399 MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
1400 else if (typeinit == NULL)
1401 MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
1404 GIrNodeInterface *iface;
1406 iface = (GIrNodeInterface *) g_ir_node_new (G_IR_NODE_INTERFACE);
1407 ((GIrNode *)iface)->name = g_strdup (name);
1408 iface->gtype_name = g_strdup (typename);
1409 iface->gtype_init = g_strdup (typeinit);
1410 if (deprecated && strcmp (deprecated, "1") == 0)
1411 iface->deprecated = TRUE;
1413 iface->deprecated = FALSE;
1415 ctx->current_node = (GIrNode *) iface;
1416 ctx->current_module->entries =
1417 g_list_append (ctx->current_module->entries, iface);
1419 state_switch (ctx, STATE_INTERFACE);
1429 start_class (GMarkupParseContext *context,
1430 const gchar *element_name,
1431 const gchar **attribute_names,
1432 const gchar **attribute_values,
1436 if (strcmp (element_name, "class") == 0 &&
1437 ctx->state == STATE_NAMESPACE)
1440 const gchar *parent;
1441 const gchar *typename;
1442 const gchar *typeinit;
1443 const gchar *deprecated;
1445 name = find_attribute ("name", attribute_names, attribute_values);
1446 parent = find_attribute ("parent", attribute_names, attribute_values);
1447 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
1448 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
1449 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1452 MISSING_ATTRIBUTE (context, error, element_name, "name");
1453 else if (typename == NULL)
1454 MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
1455 else if (typeinit == NULL && strcmp (typename, "GObject"))
1456 MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
1459 GIrNodeInterface *iface;
1461 iface = (GIrNodeInterface *) g_ir_node_new (G_IR_NODE_OBJECT);
1462 ((GIrNode *)iface)->name = g_strdup (name);
1463 iface->gtype_name = g_strdup (typename);
1464 iface->gtype_init = g_strdup (typeinit);
1465 iface->parent = g_strdup (parent);
1466 if (deprecated && strcmp (deprecated, "1") == 0)
1467 iface->deprecated = TRUE;
1469 iface->deprecated = FALSE;
1471 ctx->current_node = (GIrNode *) iface;
1472 ctx->current_module->entries =
1473 g_list_append (ctx->current_module->entries, iface);
1475 state_switch (ctx, STATE_CLASS);
1484 start_type (GMarkupParseContext *context,
1485 const gchar *element_name,
1486 const gchar **attribute_names,
1487 const gchar **attribute_values,
1493 if (strcmp (element_name, "type") != 0)
1496 if (ctx->state == STATE_TYPE)
1498 else if (ctx->state == STATE_FUNCTION_PARAMETER ||
1499 ctx->state == STATE_FUNCTION_RETURN ||
1500 ctx->state == STATE_STRUCT_FIELD ||
1501 ctx->state == STATE_UNION_FIELD ||
1502 ctx->state == STATE_CLASS_PROPERTY ||
1503 ctx->state == STATE_CLASS_FIELD ||
1504 ctx->state == STATE_INTERFACE_FIELD ||
1505 ctx->state == STATE_INTERFACE_PROPERTY ||
1506 ctx->state == STATE_BOXED_FIELD ||
1507 ctx->state == STATE_NAMESPACE_CONSTANT ||
1508 ctx->state == STATE_CLASS_CONSTANT ||
1509 ctx->state == STATE_INTERFACE_CONSTANT
1512 state_switch (ctx, STATE_TYPE);
1513 ctx->type_depth = 1;
1516 /* FIXME handle recursive types */
1517 if (ctx->type_depth > 1)
1520 if (!ctx->current_typed)
1524 G_MARKUP_ERROR_INVALID_CONTENT,
1525 "The element <type> is invalid here");
1529 name = find_attribute ("name", attribute_names, attribute_values);
1532 MISSING_ATTRIBUTE (context, error, element_name, "name");
1534 switch (ctx->current_typed->type)
1536 case G_IR_NODE_PARAM:
1538 GIrNodeParam *param = (GIrNodeParam *)ctx->current_typed;
1539 param->type = parse_type (ctx, name);
1542 case G_IR_NODE_FIELD:
1544 GIrNodeField *field = (GIrNodeField *)ctx->current_typed;
1545 field->type = parse_type (ctx, name);
1548 case G_IR_NODE_PROPERTY:
1550 GIrNodeProperty *property = (GIrNodeProperty *) ctx->current_typed;
1551 property->type = parse_type (ctx, name);
1554 case G_IR_NODE_CONSTANT:
1556 GIrNodeConstant *constant = (GIrNodeConstant *)ctx->current_typed;
1557 constant->type = parse_type (ctx, name);
1561 g_printerr("current node is %d\n", ctx->current_node->type);
1562 g_assert_not_reached ();
1565 ctx->current_typed = NULL;
1570 start_return_value (GMarkupParseContext *context,
1571 const gchar *element_name,
1572 const gchar **attribute_names,
1573 const gchar **attribute_values,
1577 if (strcmp (element_name, "return-value") == 0 &&
1578 ctx->state == STATE_FUNCTION)
1580 GIrNodeParam *param;
1582 param = (GIrNodeParam *)g_ir_node_new (G_IR_NODE_PARAM);
1585 param->retval = TRUE;
1587 ctx->current_typed = (GIrNode*) param;
1589 state_switch (ctx, STATE_FUNCTION_RETURN);
1591 switch (ctx->current_node->type)
1593 case G_IR_NODE_FUNCTION:
1594 case G_IR_NODE_CALLBACK:
1596 GIrNodeFunction *func = (GIrNodeFunction *)ctx->current_node;
1597 func->result = param;
1600 case G_IR_NODE_SIGNAL:
1602 GIrNodeSignal *signal = (GIrNodeSignal *)ctx->current_node;
1603 signal->result = param;
1606 case G_IR_NODE_VFUNC:
1608 GIrNodeVFunc *vfunc = (GIrNodeVFunc *)ctx->current_node;
1609 vfunc->result = param;
1613 g_assert_not_reached ();
1623 start_implements (GMarkupParseContext *context,
1624 const gchar *element_name,
1625 const gchar **attribute_names,
1626 const gchar **attribute_values,
1630 GIrNodeInterface *iface;
1633 if (strcmp (element_name, "implements") != 0 ||
1634 !(ctx->state == STATE_CLASS))
1637 state_switch (ctx, STATE_IMPLEMENTS);
1639 name = find_attribute ("name", attribute_names, attribute_values);
1642 MISSING_ATTRIBUTE (context, error, element_name, "name");
1646 iface = (GIrNodeInterface *)ctx->current_node;
1647 iface->interfaces = g_list_append (iface->interfaces, g_strdup (name));
1653 start_glib_signal (GMarkupParseContext *context,
1654 const gchar *element_name,
1655 const gchar **attribute_names,
1656 const gchar **attribute_values,
1660 if (strcmp (element_name, "glib:signal") == 0 &&
1661 (ctx->state == STATE_CLASS ||
1662 ctx->state == STATE_INTERFACE))
1666 const gchar *no_recurse;
1667 const gchar *detailed;
1668 const gchar *action;
1669 const gchar *no_hooks;
1670 const gchar *has_class_closure;
1672 name = find_attribute ("name", attribute_names, attribute_values);
1673 when = find_attribute ("when", attribute_names, attribute_values);
1674 no_recurse = find_attribute ("no-recurse", attribute_names, attribute_values);
1675 detailed = find_attribute ("detailed", attribute_names, attribute_values);
1676 action = find_attribute ("action", attribute_names, attribute_values);
1677 no_hooks = find_attribute ("no-hooks", attribute_names, attribute_values);
1678 has_class_closure = find_attribute ("has-class-closure", attribute_names, attribute_values);
1681 MISSING_ATTRIBUTE (context, error, element_name, "name");
1684 GIrNodeInterface *iface;
1685 GIrNodeSignal *signal;
1687 signal = (GIrNodeSignal *)g_ir_node_new (G_IR_NODE_SIGNAL);
1689 ((GIrNode *)signal)->name = g_strdup (name);
1691 signal->run_first = FALSE;
1692 signal->run_last = FALSE;
1693 signal->run_cleanup = FALSE;
1694 if (when == NULL || strcmp (when, "LAST") == 0)
1695 signal->run_last = TRUE;
1696 else if (strcmp (when, "FIRST") == 0)
1697 signal->run_first = TRUE;
1699 signal->run_cleanup = TRUE;
1701 if (no_recurse && strcmp (no_recurse, "1") == 0)
1702 signal->no_recurse = TRUE;
1704 signal->no_recurse = FALSE;
1705 if (detailed && strcmp (detailed, "1") == 0)
1706 signal->detailed = TRUE;
1708 signal->detailed = FALSE;
1709 if (action && strcmp (action, "1") == 0)
1710 signal->action = TRUE;
1712 signal->action = FALSE;
1713 if (no_hooks && strcmp (no_hooks, "1") == 0)
1714 signal->no_hooks = TRUE;
1716 signal->no_hooks = FALSE;
1717 if (has_class_closure && strcmp (has_class_closure, "1") == 0)
1718 signal->has_class_closure = TRUE;
1720 signal->has_class_closure = FALSE;
1722 iface = (GIrNodeInterface *)ctx->current_node;
1723 iface->members = g_list_append (iface->members, signal);
1725 ctx->current_node = (GIrNode *)signal;
1726 state_switch (ctx, STATE_FUNCTION);
1735 start_vfunc (GMarkupParseContext *context,
1736 const gchar *element_name,
1737 const gchar **attribute_names,
1738 const gchar **attribute_values,
1742 if (strcmp (element_name, "vfunc") == 0 &&
1743 (ctx->state == STATE_CLASS ||
1744 ctx->state == STATE_INTERFACE))
1747 const gchar *must_chain_up;
1748 const gchar *override;
1749 const gchar *is_class_closure;
1750 const gchar *offset;
1752 name = find_attribute ("name", attribute_names, attribute_values);
1753 must_chain_up = find_attribute ("must-chain-up", attribute_names, attribute_values);
1754 override = find_attribute ("override", attribute_names, attribute_values);
1755 is_class_closure = find_attribute ("is-class-closure", attribute_names, attribute_values);
1756 offset = find_attribute ("offset", attribute_names, attribute_values);
1759 MISSING_ATTRIBUTE (context, error, element_name, "name");
1762 GIrNodeInterface *iface;
1763 GIrNodeVFunc *vfunc;
1765 vfunc = (GIrNodeVFunc *)g_ir_node_new (G_IR_NODE_VFUNC);
1767 ((GIrNode *)vfunc)->name = g_strdup (name);
1769 if (must_chain_up && strcmp (must_chain_up, "1") == 0)
1770 vfunc->must_chain_up = TRUE;
1772 vfunc->must_chain_up = FALSE;
1774 if (override && strcmp (override, "always") == 0)
1776 vfunc->must_be_implemented = TRUE;
1777 vfunc->must_not_be_implemented = FALSE;
1779 else if (override && strcmp (override, "never") == 0)
1781 vfunc->must_be_implemented = FALSE;
1782 vfunc->must_not_be_implemented = TRUE;
1786 vfunc->must_be_implemented = FALSE;
1787 vfunc->must_not_be_implemented = FALSE;
1790 if (is_class_closure && strcmp (is_class_closure, "1") == 0)
1791 vfunc->is_class_closure = TRUE;
1793 vfunc->is_class_closure = FALSE;
1796 vfunc->offset = atoi (offset);
1800 iface = (GIrNodeInterface *)ctx->current_node;
1801 iface->members = g_list_append (iface->members, vfunc);
1803 ctx->current_node = (GIrNode *)vfunc;
1804 state_switch (ctx, STATE_FUNCTION);
1814 start_struct (GMarkupParseContext *context,
1815 const gchar *element_name,
1816 const gchar **attribute_names,
1817 const gchar **attribute_values,
1821 if (strcmp (element_name, "record") == 0 &&
1822 ctx->state == STATE_NAMESPACE)
1825 const gchar *deprecated;
1827 name = find_attribute ("name", attribute_names, attribute_values);
1828 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1831 MISSING_ATTRIBUTE (context, error, element_name, "name");
1834 GIrNodeStruct *struct_;
1836 struct_ = (GIrNodeStruct *) g_ir_node_new (G_IR_NODE_STRUCT);
1838 ((GIrNode *)struct_)->name = g_strdup (name);
1839 if (deprecated && strcmp (deprecated, "1") == 0)
1840 struct_->deprecated = TRUE;
1842 struct_->deprecated = FALSE;
1844 ctx->current_node = (GIrNode *)struct_;
1845 ctx->current_module->entries =
1846 g_list_append (ctx->current_module->entries, struct_);
1848 state_switch (ctx, STATE_STRUCT);
1857 start_union (GMarkupParseContext *context,
1858 const gchar *element_name,
1859 const gchar **attribute_names,
1860 const gchar **attribute_values,
1864 if (strcmp (element_name, "union") == 0 &&
1865 ctx->state == STATE_NAMESPACE)
1868 const gchar *deprecated;
1869 const gchar *typename;
1870 const gchar *typeinit;
1872 name = find_attribute ("name", attribute_names, attribute_values);
1873 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1874 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
1875 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
1878 MISSING_ATTRIBUTE (context, error, element_name, "name");
1881 GIrNodeUnion *union_;
1883 union_ = (GIrNodeUnion *) g_ir_node_new (G_IR_NODE_UNION);
1885 ((GIrNode *)union_)->name = g_strdup (name);
1886 union_->gtype_name = g_strdup (typename);
1887 union_->gtype_init = g_strdup (typeinit);
1888 if (deprecated && strcmp (deprecated, "1") == 0)
1889 union_->deprecated = TRUE;
1891 union_->deprecated = FALSE;
1893 ctx->current_node = (GIrNode *)union_;
1894 ctx->current_module->entries =
1895 g_list_append (ctx->current_module->entries, union_);
1897 state_switch (ctx, STATE_UNION);
1905 start_discriminator (GMarkupParseContext *context,
1906 const gchar *element_name,
1907 const gchar **attribute_names,
1908 const gchar **attribute_values,
1912 if (strcmp (element_name, "discriminator") == 0 &&
1913 ctx->state == STATE_UNION)
1916 const gchar *offset;
1918 type = find_attribute ("type", attribute_names, attribute_values);
1919 offset = find_attribute ("offset", attribute_names, attribute_values);
1921 MISSING_ATTRIBUTE (context, error, element_name, "type");
1922 else if (offset == NULL)
1923 MISSING_ATTRIBUTE (context, error, element_name, "offset");
1925 ((GIrNodeUnion *)ctx->current_node)->discriminator_type
1926 = parse_type (ctx, type);
1927 ((GIrNodeUnion *)ctx->current_node)->discriminator_offset
1938 parse_include (GMarkupParseContext *context,
1943 ParseContext sub_ctx = { 0 };
1944 GMarkupParseContext *sub_context;
1949 girpath = locate_gir (name, ctx->includes);
1951 if (girpath == NULL)
1955 G_MARKUP_ERROR_INVALID_CONTENT,
1956 "Could not find GIR file '%s'; check XDG_DATA_DIRS or use --includedir",
1961 g_debug ("Parsing include %s", girpath);
1963 if (!g_file_get_contents (girpath, &buffer, &length, error))
1970 sub_ctx.state = STATE_START;
1971 sub_ctx.prefix_aliases = TRUE;
1972 sub_ctx.namespace = name;
1973 sub_ctx.aliases = ctx->aliases;
1974 sub_ctx.type_depth = 0;
1976 context = g_markup_parse_context_new (&firstpass_parser, 0, &sub_ctx, NULL);
1978 if (!g_markup_parse_context_parse (context, buffer, length, error))
1984 if (!g_markup_parse_context_end_parse (context, error))
1990 g_markup_parse_context_free (context);
1994 extern GLogLevelFlags logged_levels;
1997 start_element_handler (GMarkupParseContext *context,
1998 const gchar *element_name,
1999 const gchar **attribute_names,
2000 const gchar **attribute_values,
2004 ParseContext *ctx = user_data;
2005 gint line_number, char_number;
2007 if (logged_levels & G_LOG_LEVEL_DEBUG)
2009 GString *tags = g_string_new ("");
2011 for (i = 0; attribute_names[i]; i++)
2012 g_string_append_printf (tags, "%s=\"%s\" ",
2014 attribute_values[i]);
2018 g_string_insert_c (tags, 0, ' ');
2019 g_string_truncate (tags, tags->len - 1);
2021 g_debug ("<%s%s>", element_name, tags->str);
2022 g_string_free (tags, TRUE);
2025 switch (element_name[0])
2028 if (ctx->state == STATE_NAMESPACE && strcmp (element_name, "alias") == 0)
2030 state_switch (ctx, STATE_ALIAS);
2035 if (start_enum (context, element_name,
2036 attribute_names, attribute_values,
2041 if (start_function (context, element_name,
2042 attribute_names, attribute_values,
2045 else if (start_constant (context, element_name,
2046 attribute_names, attribute_values,
2049 else if (start_class (context, element_name,
2050 attribute_names, attribute_values,
2053 else if (strcmp (element_name, "class") == 0 &&
2054 ctx->state == STATE_REQUIRES)
2058 name = find_attribute ("name", attribute_names, attribute_values);
2061 MISSING_ATTRIBUTE (context, error, element_name, "name");
2064 GIrNodeInterface *iface;
2066 iface = (GIrNodeInterface *)ctx->current_node;
2067 iface ->prerequisites = g_list_append (iface->prerequisites, g_strdup (name));
2075 if (start_discriminator (context, element_name,
2076 attribute_names, attribute_values,
2082 if (start_enum (context, element_name,
2083 attribute_names, attribute_values,
2086 else if (start_errordomain (context, element_name,
2087 attribute_names, attribute_values,
2093 if (start_function (context, element_name,
2094 attribute_names, attribute_values,
2097 else if (start_field (context, element_name,
2098 attribute_names, attribute_values,
2104 if (start_glib_boxed (context, element_name,
2105 attribute_names, attribute_values,
2108 else if (start_glib_signal (context, element_name,
2109 attribute_names, attribute_values,
2115 if (strcmp (element_name, "include") == 0 &&
2116 ctx->state == STATE_REPOSITORY)
2120 name = find_attribute ("name", attribute_names, attribute_values);
2124 MISSING_ATTRIBUTE (context, error, element_name, "name");
2128 if (!parse_include (context, ctx, name, error))
2131 state_switch (ctx, STATE_INCLUDE);
2134 if (start_interface (context, element_name,
2135 attribute_names, attribute_values,
2138 else if (start_implements (context, element_name,
2139 attribute_names, attribute_values,
2145 if (start_function (context, element_name,
2146 attribute_names, attribute_values,
2149 else if (start_member (context, element_name,
2150 attribute_names, attribute_values,
2156 if (strcmp (element_name, "namespace") == 0 && ctx->state == STATE_REPOSITORY)
2158 const gchar *name, *shared_library;
2160 name = find_attribute ("name", attribute_names, attribute_values);
2161 shared_library = find_attribute ("shared-library", attribute_names, attribute_values);
2164 MISSING_ATTRIBUTE (context, error, element_name, "name");
2167 ctx->current_module = g_ir_module_new (name, shared_library);
2168 ctx->modules = g_list_append (ctx->modules, ctx->current_module);
2170 state_switch (ctx, STATE_NAMESPACE);
2178 if (start_property (context, element_name,
2179 attribute_names, attribute_values,
2182 else if (strcmp (element_name, "parameters") == 0 &&
2183 ctx->state == STATE_FUNCTION)
2185 state_switch (ctx, STATE_FUNCTION_PARAMETERS);
2189 else if (start_parameter (context, element_name,
2190 attribute_names, attribute_values,
2197 if (strcmp (element_name, "repository") == 0 && ctx->state == STATE_START)
2199 const gchar *version;
2201 version = find_attribute ("version", attribute_names, attribute_values);
2203 if (version == NULL)
2204 MISSING_ATTRIBUTE (context, error, element_name, "version");
2205 else if (strcmp (version, "1.0") != 0)
2208 G_MARKUP_ERROR_INVALID_CONTENT,
2209 "Unsupported version '%s'",
2212 state_switch (ctx, STATE_REPOSITORY);
2216 else if (start_return_value (context, element_name,
2217 attribute_names, attribute_values,
2220 else if (strcmp (element_name, "requires") == 0 &&
2221 ctx->state == STATE_INTERFACE)
2223 state_switch (ctx, STATE_REQUIRES);
2227 else if (start_struct (context, element_name,
2228 attribute_names, attribute_values,
2234 if (start_union (context, element_name,
2235 attribute_names, attribute_values,
2241 if (start_type (context, element_name,
2242 attribute_names, attribute_values,
2248 if (start_vfunc (context, element_name,
2249 attribute_names, attribute_values,
2255 g_markup_parse_context_get_position (context, &line_number, &char_number);
2257 if (error && *error == NULL)
2260 G_MARKUP_ERROR_UNKNOWN_ELEMENT,
2261 "Unexpected start tag '%s' on line %d char %d; current state=%d",
2263 line_number, char_number, ctx->state);
2268 g_markup_parse_context_get_position (context, &line_number, &char_number);
2270 fprintf (stderr, "Error at line %d, character %d: %s\n", line_number, char_number, (*error)->message);
2271 backtrace_stderr ();
2276 require_one_of_end_elements (GMarkupParseContext *context,
2278 const char *actual_name,
2283 int line_number, char_number;
2284 const char *expected;
2285 gboolean matched = FALSE;
2287 va_start (args, error);
2289 while ((expected = va_arg (args, const char*)) != NULL)
2291 if (strcmp (expected, actual_name) == 0)
2303 g_markup_parse_context_get_position (context, &line_number, &char_number);
2306 G_MARKUP_ERROR_INVALID_CONTENT,
2307 "Unexpected end tag '%s' on line %d char %d; current state=%d",
2309 line_number, char_number, ctx->state);
2315 require_end_element (GMarkupParseContext *context,
2317 const char *expected_name,
2318 const char *actual_name,
2321 return require_one_of_end_elements (context, ctx, actual_name, error, expected_name, NULL);
2325 end_element_handler (GMarkupParseContext *context,
2326 const gchar *element_name,
2330 ParseContext *ctx = user_data;
2332 g_debug ("</%s>", element_name);
2338 /* no need to GError here, GMarkup already catches this */
2341 case STATE_REPOSITORY:
2342 state_switch (ctx, STATE_END);
2346 if (require_end_element (context, ctx, "include", element_name, error))
2348 state_switch (ctx, STATE_REPOSITORY);
2352 case STATE_NAMESPACE:
2353 if (require_end_element (context, ctx, "namespace", element_name, error))
2355 ctx->current_module = NULL;
2356 state_switch (ctx, STATE_REPOSITORY);
2361 if (require_end_element (context, ctx, "alias", element_name, error))
2363 state_switch (ctx, STATE_NAMESPACE);
2367 case STATE_FUNCTION_RETURN:
2368 if (strcmp ("type", element_name) == 0)
2370 if (require_end_element (context, ctx, "return-value", element_name, error))
2372 state_switch (ctx, STATE_FUNCTION);
2376 case STATE_FUNCTION_PARAMETERS:
2377 if (require_end_element (context, ctx, "parameters", element_name, error))
2379 state_switch (ctx, STATE_FUNCTION);
2383 case STATE_FUNCTION_PARAMETER:
2384 if (strcmp ("type", element_name) == 0)
2386 if (require_end_element (context, ctx, "parameter", element_name, error))
2388 state_switch (ctx, STATE_FUNCTION_PARAMETERS);
2392 case STATE_FUNCTION:
2393 if (ctx->current_node == g_list_last (ctx->current_module->entries)->data)
2395 ctx->current_node = NULL;
2396 state_switch (ctx, STATE_NAMESPACE);
2400 ctx->current_node = g_list_last (ctx->current_module->entries)->data;
2401 if (ctx->current_node->type == G_IR_NODE_INTERFACE)
2402 state_switch (ctx, STATE_INTERFACE);
2403 else if (ctx->current_node->type == G_IR_NODE_OBJECT)
2404 state_switch (ctx, STATE_CLASS);
2405 else if (ctx->current_node->type == G_IR_NODE_BOXED)
2406 state_switch (ctx, STATE_BOXED);
2407 else if (ctx->current_node->type == G_IR_NODE_STRUCT)
2408 state_switch (ctx, STATE_STRUCT);
2409 else if (ctx->current_node->type == G_IR_NODE_UNION)
2410 state_switch (ctx, STATE_UNION);
2413 int line_number, char_number;
2414 g_markup_parse_context_get_position (context, &line_number, &char_number);
2417 G_MARKUP_ERROR_INVALID_CONTENT,
2418 "Unexpected end tag '%s' on line %d char %d",
2420 line_number, char_number);
2425 case STATE_CLASS_FIELD:
2426 if (strcmp ("type", element_name) == 0)
2428 if (require_end_element (context, ctx, "field", element_name, error))
2430 state_switch (ctx, STATE_CLASS);
2434 case STATE_CLASS_PROPERTY:
2435 if (strcmp ("type", element_name) == 0)
2437 if (require_end_element (context, ctx, "property", element_name, error))
2439 state_switch (ctx, STATE_CLASS);
2444 if (require_end_element (context, ctx, "class", element_name, error))
2446 ctx->current_node = NULL;
2447 state_switch (ctx, STATE_NAMESPACE);
2451 case STATE_ERRORDOMAIN:
2452 if (require_end_element (context, ctx, "errordomain", element_name, error))
2454 ctx->current_node = NULL;
2455 state_switch (ctx, STATE_NAMESPACE);
2459 case STATE_INTERFACE_PROPERTY:
2460 if (strcmp ("type", element_name) == 0)
2462 if (require_end_element (context, ctx, "property", element_name, error))
2464 state_switch (ctx, STATE_INTERFACE);
2468 case STATE_INTERFACE_FIELD:
2469 if (strcmp ("type", element_name) == 0)
2471 if (require_end_element (context, ctx, "field", element_name, error))
2473 state_switch (ctx, STATE_INTERFACE);
2477 case STATE_INTERFACE:
2478 if (require_end_element (context, ctx, "interface", element_name, error))
2480 ctx->current_node = NULL;
2481 state_switch (ctx, STATE_NAMESPACE);
2486 if (strcmp ("member", element_name) == 0)
2488 else if (require_one_of_end_elements (context, ctx,
2489 element_name, error, "enumeration",
2492 ctx->current_node = NULL;
2493 state_switch (ctx, STATE_NAMESPACE);
2498 if (require_end_element (context, ctx, "glib:boxed", element_name, error))
2500 ctx->current_node = NULL;
2501 state_switch (ctx, STATE_NAMESPACE);
2505 case STATE_BOXED_FIELD:
2506 if (strcmp ("type", element_name) == 0)
2508 if (require_end_element (context, ctx, "field", element_name, error))
2510 state_switch (ctx, STATE_BOXED);
2514 case STATE_STRUCT_FIELD:
2515 if (strcmp ("type", element_name) == 0)
2517 if (require_end_element (context, ctx, "field", element_name, error))
2519 state_switch (ctx, STATE_STRUCT);
2524 if (require_end_element (context, ctx, "record", element_name, error))
2526 ctx->current_node = NULL;
2527 state_switch (ctx, STATE_NAMESPACE);
2531 case STATE_UNION_FIELD:
2532 if (strcmp ("type", element_name) == 0)
2534 if (require_end_element (context, ctx, "field", element_name, error))
2536 state_switch (ctx, STATE_UNION);
2541 if (require_end_element (context, ctx, "union", element_name, error))
2543 ctx->current_node = NULL;
2544 state_switch (ctx, STATE_NAMESPACE);
2547 case STATE_IMPLEMENTS:
2548 if (strcmp ("interface", element_name) == 0)
2550 if (require_end_element (context, ctx, "implements", element_name, error))
2551 state_switch (ctx, STATE_CLASS);
2553 case STATE_REQUIRES:
2554 if (require_end_element (context, ctx, "requires", element_name, error))
2555 state_switch (ctx, STATE_INTERFACE);
2557 case STATE_NAMESPACE_CONSTANT:
2558 case STATE_CLASS_CONSTANT:
2559 case STATE_INTERFACE_CONSTANT:
2560 if (strcmp ("type", element_name) == 0)
2562 if (require_end_element (context, ctx, "constant", element_name, error))
2564 ctx->current_node = NULL;
2567 case STATE_NAMESPACE_CONSTANT:
2568 state_switch (ctx, STATE_NAMESPACE);
2570 case STATE_CLASS_CONSTANT:
2571 state_switch (ctx, STATE_CLASS);
2573 case STATE_INTERFACE_CONSTANT:
2574 state_switch (ctx, STATE_INTERFACE);
2577 g_assert_not_reached ();
2583 if (strcmp ("type", element_name) == 0)
2585 if (ctx->type_depth == 1)
2586 state_switch (ctx, ctx->prev_state);
2588 ctx->type_depth -= 1;
2592 g_error ("Unhandled state %d in end_element_handler\n", ctx->state);
2597 text_handler (GMarkupParseContext *context,
2603 /* FIXME warn about non-whitespace text */
2607 cleanup (GMarkupParseContext *context,
2611 ParseContext *ctx = user_data;
2613 int line_number, char_number;
2615 for (m = ctx->modules; m; m = m->next)
2616 g_ir_module_free (m->data);
2617 g_list_free (ctx->modules);
2618 ctx->modules = NULL;
2620 ctx->current_module = NULL;
2623 static GMarkupParser parser =
2625 start_element_handler,
2626 end_element_handler,
2633 g_ir_parse_string (const char *namespace,
2634 const gchar *buffer,
2638 ParseContext ctx = { 0 };
2639 GMarkupParseContext *context;
2641 ctx.state = STATE_START;
2642 ctx.prefix_aliases = FALSE;
2643 ctx.namespace = namespace;
2644 ctx.aliases = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
2647 context = g_markup_parse_context_new (&firstpass_parser, 0, &ctx, NULL);
2649 if (!g_markup_parse_context_parse (context, buffer, length, error))
2652 if (!g_markup_parse_context_end_parse (context, error))
2655 g_markup_parse_context_free (context);
2657 context = g_markup_parse_context_new (&parser, 0, &ctx, NULL);
2658 if (!g_markup_parse_context_parse (context, buffer, length, error))
2661 if (!g_markup_parse_context_end_parse (context, error))
2666 g_hash_table_destroy (ctx.aliases);
2668 g_markup_parse_context_free (context);
2674 g_ir_parse_file (const gchar *filename,
2683 if (!g_str_has_suffix (filename, ".gir"))
2687 G_MARKUP_ERROR_INVALID_CONTENT,
2688 "Expected filename to end with '.gir'");
2692 g_debug ("[parsing] filename %s", filename);
2694 slash = g_strrstr (filename, "/");
2696 namespace = g_strdup (filename);
2698 namespace = g_strdup (slash+1);
2699 namespace[strlen(namespace)-4] = '\0';
2701 if (!g_file_get_contents (filename, &buffer, &length, error))
2704 modules = g_ir_parse_string (namespace, buffer, length, error);