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"
37 STATE_BITFIELD, /* 5 */
39 STATE_FUNCTION_RETURN,
40 STATE_FUNCTION_PARAMETERS,
41 STATE_FUNCTION_PARAMETER,
46 STATE_INTERFACE_PROPERTY,
47 STATE_INTERFACE_FIELD, /* 15 */
52 STATE_STRUCT, /* 20 */
57 STATE_NAMESPACE_CONSTANT, /* 25 */
59 STATE_INTERFACE_CONSTANT,
63 typedef struct _ParseContext ParseContext;
67 ParseState prev_state;
72 GIrModule *current_module;
73 GIrNode *current_node;
74 GIrNode *current_typed;
77 #define MISSING_ATTRIBUTE(ctx,error,element,attribute) \
79 int line_number, char_number; \
80 g_markup_parse_context_get_position (context, &line_number, &char_number); \
83 G_MARKUP_ERROR_INVALID_CONTENT, \
84 "Line %d, character %d: The attribute '%s' on the element '%s' must be specified", \
85 line_number, char_number, attribute, element); \
89 backtrace_stderr (void)
96 size = backtrace (array, 50);
97 strings = (char**) backtrace_symbols (array, size);
99 fprintf (stderr, "--- BACKTRACE (%zd frames) ---\n", size);
101 for (i = 0; i < size; i++)
102 fprintf (stderr, "%s\n", strings[i]);
104 fprintf (stderr, "--- END BACKTRACE ---\n", size);
111 find_attribute (const gchar *name,
112 const gchar **attribute_names,
113 const gchar **attribute_values)
117 for (i = 0; attribute_names[i] != NULL; i++)
118 if (strcmp (attribute_names[i], name) == 0)
119 return attribute_values[i];
125 state_switch (ParseContext *ctx, ParseState newstate)
127 g_debug ("State: %d", newstate);
128 ctx->prev_state = ctx->state;
129 ctx->state = newstate;
132 static GIrNodeType * parse_type_internal (gchar *str, gchar **rest);
137 char *pointer = g_strdup ("any");
139 GIrNodeType *ret = parse_type_internal (pointer, &pointer_rest);
145 parse_type_internal (gchar *str, gchar **rest)
154 { "none", GI_TYPE_TAG_VOID, 0 },
155 { "any", GI_TYPE_TAG_VOID, 1 },
157 { "bool", GI_TYPE_TAG_BOOLEAN, 0 },
158 { "char", GI_TYPE_TAG_INT8, 0 },
159 { "int8", GI_TYPE_TAG_INT8, 0 },
160 { "uint8", GI_TYPE_TAG_UINT8, 0 },
161 { "int16", GI_TYPE_TAG_INT16, 0 },
162 { "uint16", GI_TYPE_TAG_UINT16, 0 },
163 { "int32", GI_TYPE_TAG_INT32, 0 },
164 { "uint32", GI_TYPE_TAG_UINT32, 0 },
165 { "int64", GI_TYPE_TAG_INT64, 0 },
166 { "uint64", GI_TYPE_TAG_UINT64, 0 },
167 { "int", GI_TYPE_TAG_INT, 0 },
168 { "uint", GI_TYPE_TAG_UINT, 0 },
169 { "long", GI_TYPE_TAG_LONG, 0 },
170 { "ulong", GI_TYPE_TAG_ULONG, 0 },
171 { "ssize_t", GI_TYPE_TAG_SSIZE, 0 },
172 { "ssize", GI_TYPE_TAG_SSIZE, 0 },
173 { "size_t", GI_TYPE_TAG_SIZE, 0 },
174 { "size", GI_TYPE_TAG_SIZE, 0 },
175 { "float", GI_TYPE_TAG_FLOAT, 0 },
176 { "double", GI_TYPE_TAG_DOUBLE, 0 },
177 { "utf8", GI_TYPE_TAG_UTF8, 1 },
178 { "filename", GI_TYPE_TAG_FILENAME,1 },
180 /* FIXME: merge - do we still want this? */
181 { "string", GI_TYPE_TAG_UTF8, 1 },
183 /* FIXME: Remove these */
184 { "void", GI_TYPE_TAG_VOID, 0 },
185 { "int8_t", GI_TYPE_TAG_INT8, 0 },
186 { "uint8_t", GI_TYPE_TAG_UINT8, 0 },
187 { "int16_t", GI_TYPE_TAG_INT16, 0 },
188 { "uint16_t", GI_TYPE_TAG_UINT16, 0 },
189 { "int32_t", GI_TYPE_TAG_INT32, 0 },
190 { "uint32_t", GI_TYPE_TAG_UINT32, 0 },
191 { "int64_t", GI_TYPE_TAG_INT64, 0 },
192 { "uint64_t", GI_TYPE_TAG_UINT64, 0 },
193 { "gpointer", GI_TYPE_TAG_VOID, 1 },
194 { "gboolean", GI_TYPE_TAG_BOOLEAN, 0 },
195 { "gchar", GI_TYPE_TAG_INT8, 0 },
196 { "guchar", GI_TYPE_TAG_UINT8, 0 },
197 { "gunichar", GI_TYPE_TAG_UINT32, 0 },
198 { "gint", GI_TYPE_TAG_INT, 0 },
199 { "guint", GI_TYPE_TAG_UINT, 0 },
200 { "gint8", GI_TYPE_TAG_INT8, 0 },
201 { "guint8", GI_TYPE_TAG_UINT8, 0 },
202 { "gint16", GI_TYPE_TAG_INT16, 0 },
203 { "guint16", GI_TYPE_TAG_UINT16, 0 },
204 { "gint32", GI_TYPE_TAG_INT32, 0 },
205 { "guint32", GI_TYPE_TAG_UINT32, 0 },
206 { "gint64", GI_TYPE_TAG_INT64, 0 },
207 { "guint64", GI_TYPE_TAG_UINT64, 0 },
208 { "glong", GI_TYPE_TAG_LONG, 0 },
209 { "gulong", GI_TYPE_TAG_ULONG, 0 },
210 { "gssize", GI_TYPE_TAG_SSIZE, 0 },
211 { "gsize", GI_TYPE_TAG_SIZE, 0 },
212 { "gfloat", GI_TYPE_TAG_FLOAT, 0 },
213 { "gdouble", GI_TYPE_TAG_DOUBLE, 0 },
214 { "gchar*", GI_TYPE_TAG_UTF8, 1 }
217 gint n_basic = G_N_ELEMENTS (basic);
222 type = (GIrNodeType *)g_ir_node_new (G_IR_NODE_TYPE);
224 str = g_strstrip (str);
226 type->unparsed = g_strdup (str);
229 for (i = 0; i < n_basic; i++)
231 if (g_str_has_prefix (*rest, basic[i].str))
233 type->is_basic = TRUE;
234 type->tag = basic[i].tag;
235 type->is_pointer = basic[i].pointer;
237 *rest += strlen(basic[i].str);
238 *rest = g_strchug (*rest);
239 if (**rest == '*' && !type->is_pointer)
241 type->is_pointer = TRUE;
250 /* found a basic type */;
251 else if (g_str_has_prefix (*rest, "GList") ||
252 g_str_has_prefix (*rest, "GSList"))
254 if (g_str_has_prefix (*rest, "GList"))
256 type->tag = GI_TYPE_TAG_GLIST;
257 type->is_glist = TRUE;
258 type->is_pointer = TRUE;
259 *rest += strlen ("GList");
263 type->tag = GI_TYPE_TAG_GSLIST;
264 type->is_gslist = TRUE;
265 type->is_pointer = TRUE;
266 *rest += strlen ("GSList");
269 *rest = g_strchug (*rest);
275 type->parameter_type1 = parse_type_internal (*rest, rest);
276 if (type->parameter_type1 == NULL)
279 *rest = g_strchug (*rest);
281 if ((*rest)[0] != '>')
287 type->parameter_type1 = create_pointer ();
290 else if (g_str_has_prefix (*rest, "GHashTable"))
292 type->tag = GI_TYPE_TAG_GHASH;
293 type->is_ghashtable = TRUE;
294 type->is_pointer = TRUE;
295 *rest += strlen ("GHashTable");
297 *rest = g_strchug (*rest);
303 type->parameter_type1 = parse_type_internal (*rest, rest);
304 if (type->parameter_type1 == NULL)
307 *rest = g_strchug (*rest);
309 if ((*rest)[0] != ',')
313 type->parameter_type2 = parse_type_internal (*rest, rest);
314 if (type->parameter_type2 == NULL)
317 if ((*rest)[0] != '>')
323 type->parameter_type1 = create_pointer ();
324 type->parameter_type2 = create_pointer ();
328 else if (g_str_has_prefix (*rest, "GError"))
330 type->tag = GI_TYPE_TAG_ERROR;
331 type->is_error = TRUE;
332 type->is_pointer = TRUE;
333 *rest += strlen ("GError");
335 *rest = g_strchug (*rest);
341 end = strchr (*rest, '>');
342 str = g_strndup (*rest, end - *rest);
343 type->errors = g_strsplit (str, ",", 0);
351 type->tag = GI_TYPE_TAG_INTERFACE;
352 type->is_interface = TRUE;
355 /* must be an interface type */
356 while (g_ascii_isalnum (**rest) ||
363 type->interface = g_strndup (start, *rest - start);
365 *rest = g_strchug (*rest);
368 type->is_pointer = TRUE;
373 *rest = g_strchug (*rest);
374 if (g_str_has_prefix (*rest, "["))
378 array = (GIrNodeType *)g_ir_node_new (G_IR_NODE_TYPE);
380 array->tag = GI_TYPE_TAG_ARRAY;
381 array->is_pointer = TRUE;
382 array->is_array = TRUE;
384 array->parameter_type1 = type;
386 array->zero_terminated = FALSE;
387 array->has_length = FALSE;
390 if (!g_str_has_prefix (*rest, "[]"))
392 gchar *end, *str, **opts;
394 end = strchr (*rest, ']');
395 str = g_strndup (*rest + 1, (end - *rest) - 1);
396 opts = g_strsplit (str, ",", 0);
400 for (i = 0; opts[i]; i++)
404 vals = g_strsplit (opts[i], "=", 0);
406 if (strcmp (vals[0], "zero-terminated") == 0)
407 array->zero_terminated = (strcmp (vals[1], "1") == 0);
408 else if (strcmp (vals[0], "length") == 0)
410 array->has_length = TRUE;
411 array->length = atoi (vals[1]);
424 g_assert (type->tag >= 0 && type->tag <= GI_TYPE_TAG_ERROR);
428 g_ir_node_free ((GIrNode *)type);
434 resolve_aliases (ParseContext *ctx, const gchar *type)
438 GSList *seen_values = NULL;
440 seen_values = g_slist_prepend (seen_values, type);
441 while (g_hash_table_lookup_extended (ctx->aliases, type, &orig, &value))
443 g_debug ("Resolved: %s => %s", type, value);
445 if (g_slist_find_custom (seen_values, type, strcmp) != NULL)
447 seen_values = g_slist_prepend (seen_values, type);
453 parse_type (ParseContext *ctx, const gchar *type)
459 type = resolve_aliases (ctx, type);
460 str = g_strdup (type);
461 node = parse_type_internal (str, &rest);
468 start_glib_boxed (GMarkupParseContext *context,
469 const gchar *element_name,
470 const gchar **attribute_names,
471 const gchar **attribute_values,
475 if (strcmp (element_name, "glib:boxed") == 0 &&
476 ctx->state == STATE_NAMESPACE)
479 const gchar *typename;
480 const gchar *typeinit;
481 const gchar *deprecated;
483 name = find_attribute ("glib:name", attribute_names, attribute_values);
484 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
485 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
486 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
489 MISSING_ATTRIBUTE (context, error, element_name, "glib:name");
490 else if (typename == NULL)
491 MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
492 else if (typeinit == NULL)
493 MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
498 boxed = (GIrNodeBoxed *) g_ir_node_new (G_IR_NODE_BOXED);
500 ((GIrNode *)boxed)->name = g_strdup (name);
501 boxed->gtype_name = g_strdup (typename);
502 boxed->gtype_init = g_strdup (typeinit);
503 if (deprecated && strcmp (deprecated, "1") == 0)
504 boxed->deprecated = TRUE;
506 boxed->deprecated = FALSE;
508 ctx->current_node = (GIrNode *)boxed;
509 ctx->current_module->entries =
510 g_list_append (ctx->current_module->entries, boxed);
512 state_switch (ctx, STATE_BOXED);
522 start_function (GMarkupParseContext *context,
523 const gchar *element_name,
524 const gchar **attribute_names,
525 const gchar **attribute_values,
529 if ((ctx->state == STATE_NAMESPACE &&
530 (strcmp (element_name, "function") == 0 ||
531 strcmp (element_name, "callback") == 0)) ||
532 ((ctx->state == STATE_CLASS ||
533 ctx->state == STATE_INTERFACE ||
534 ctx->state == STATE_BOXED ||
535 ctx->state == STATE_UNION) &&
536 (strcmp (element_name, "method") == 0 ||
537 strcmp (element_name, "callback") == 0)) ||
538 ((ctx->state == STATE_CLASS ||
539 ctx->state == STATE_BOXED) &&
540 (strcmp (element_name, "constructor") == 0)) ||
541 (ctx->state == STATE_STRUCT && strcmp (element_name, "callback") == 0))
545 const gchar *deprecated;
548 name = find_attribute ("name", attribute_names, attribute_values);
549 symbol = find_attribute ("c:identifier", attribute_names, attribute_values);
550 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
551 type = find_attribute ("type", attribute_names, attribute_values);
554 MISSING_ATTRIBUTE (context, error, element_name, "name");
555 else if (strcmp (element_name, "callback") != 0 && symbol == NULL)
556 MISSING_ATTRIBUTE (context, error, element_name, "c:identifier");
559 GIrNodeFunction *function;
561 function = (GIrNodeFunction *) g_ir_node_new (G_IR_NODE_FUNCTION);
563 ((GIrNode *)function)->name = g_strdup (name);
564 function->symbol = g_strdup (symbol);
565 function->parameters = NULL;
566 if (deprecated && strcmp (deprecated, "1") == 0)
567 function->deprecated = TRUE;
569 function->deprecated = FALSE;
571 if (strcmp (element_name, "method") == 0 ||
572 strcmp (element_name, "constructor") == 0)
574 function->is_method = TRUE;
576 if (type && strcmp (type, "setter") == 0)
577 function->is_setter = TRUE;
578 else if (type && strcmp (type, "getter") == 0)
579 function->is_getter = TRUE;
581 if (strcmp (element_name, "constructor") == 0)
582 function->is_constructor = TRUE;
584 function->is_constructor = FALSE;
588 function->is_method = FALSE;
589 function->is_setter = FALSE;
590 function->is_getter = FALSE;
591 function->is_constructor = FALSE;
592 if (strcmp (element_name, "callback") == 0)
593 ((GIrNode *)function)->type = G_IR_NODE_CALLBACK;
596 if (ctx->current_node == NULL)
598 ctx->current_module->entries =
599 g_list_append (ctx->current_module->entries, function);
602 switch (ctx->current_node->type)
604 case G_IR_NODE_INTERFACE:
605 case G_IR_NODE_OBJECT:
607 GIrNodeInterface *iface;
609 iface = (GIrNodeInterface *)ctx->current_node;
610 iface->members = g_list_append (iface->members, function);
613 case G_IR_NODE_BOXED:
617 boxed = (GIrNodeBoxed *)ctx->current_node;
618 boxed->members = g_list_append (boxed->members, function);
621 case G_IR_NODE_STRUCT:
623 GIrNodeStruct *struct_;
625 struct_ = (GIrNodeStruct *)ctx->current_node;
626 struct_->members = g_list_append (struct_->members, function); }
628 case G_IR_NODE_UNION:
630 GIrNodeUnion *union_;
632 union_ = (GIrNodeUnion *)ctx->current_node;
633 union_->members = g_list_append (union_->members, function);
637 g_assert_not_reached ();
640 ctx->current_node = (GIrNode *)function;
641 state_switch (ctx, STATE_FUNCTION);
651 start_parameter (GMarkupParseContext *context,
652 const gchar *element_name,
653 const gchar **attribute_names,
654 const gchar **attribute_values,
659 const gchar *direction;
662 const gchar *optional;
664 const gchar *transfer;
667 if (!(strcmp (element_name, "parameter") == 0 &&
668 ctx->state == STATE_FUNCTION_PARAMETERS))
671 name = find_attribute ("name", attribute_names, attribute_values);
672 direction = find_attribute ("direction", attribute_names, attribute_values);
673 retval = find_attribute ("retval", attribute_names, attribute_values);
674 dipper = find_attribute ("dipper", attribute_names, attribute_values);
675 optional = find_attribute ("optional", attribute_names, attribute_values);
676 nullok = find_attribute ("null-ok", attribute_names, attribute_values);
677 transfer = find_attribute ("transfer", attribute_names, attribute_values);
682 param = (GIrNodeParam *)g_ir_node_new (G_IR_NODE_PARAM);
684 ctx->current_typed = (GIrNode*) param;
685 ctx->current_typed->name = g_strdup (name);
687 state_switch (ctx, STATE_FUNCTION_PARAMETER);
689 if (direction && strcmp (direction, "out") == 0)
694 else if (direction && strcmp (direction, "inout") == 0)
705 if (retval && strcmp (retval, "1") == 0)
706 param->retval = TRUE;
708 param->retval = FALSE;
710 if (dipper && strcmp (dipper, "1") == 0)
711 param->dipper = TRUE;
713 param->dipper = FALSE;
715 if (optional && strcmp (optional, "1") == 0)
716 param->optional = TRUE;
718 param->optional = FALSE;
720 if (nullok && strcmp (nullok, "1") == 0)
721 param->null_ok = TRUE;
723 param->null_ok = FALSE;
725 if (transfer && strcmp (transfer, "none") == 0)
727 param->transfer = FALSE;
728 param->shallow_transfer = FALSE;
730 else if (transfer && strcmp (transfer, "shallow") == 0)
732 param->transfer = FALSE;
733 param->shallow_transfer = TRUE;
737 param->transfer = TRUE;
738 param->shallow_transfer = FALSE;
741 ((GIrNode *)param)->name = g_strdup (name);
743 switch (ctx->current_node->type)
745 case G_IR_NODE_FUNCTION:
746 case G_IR_NODE_CALLBACK:
748 GIrNodeFunction *func;
750 func = (GIrNodeFunction *)ctx->current_node;
751 func->parameters = g_list_append (func->parameters, param);
754 case G_IR_NODE_SIGNAL:
756 GIrNodeSignal *signal;
758 signal = (GIrNodeSignal *)ctx->current_node;
759 signal->parameters = g_list_append (signal->parameters, param);
762 case G_IR_NODE_VFUNC:
766 vfunc = (GIrNodeVFunc *)ctx->current_node;
767 vfunc->parameters = g_list_append (vfunc->parameters, param);
771 g_assert_not_reached ();
778 start_field (GMarkupParseContext *context,
779 const gchar *element_name,
780 const gchar **attribute_names,
781 const gchar **attribute_values,
785 if (strcmp (element_name, "field") == 0 &&
786 (ctx->state == STATE_CLASS ||
787 ctx->state == STATE_BOXED ||
788 ctx->state == STATE_STRUCT ||
789 ctx->state == STATE_UNION ||
790 ctx->state == STATE_INTERFACE))
793 const gchar *readable;
794 const gchar *writable;
799 name = find_attribute ("name", attribute_names, attribute_values);
800 readable = find_attribute ("readable", attribute_names, attribute_values);
801 writable = find_attribute ("writable", attribute_names, attribute_values);
802 bits = find_attribute ("bits", attribute_names, attribute_values);
803 branch = find_attribute ("branch", attribute_names, attribute_values);
804 offset = find_attribute ("offset", attribute_names, attribute_values);
807 MISSING_ATTRIBUTE (context, error, element_name, "name");
812 field = (GIrNodeField *)g_ir_node_new (G_IR_NODE_FIELD);
813 ctx->current_typed = (GIrNode*) field;
814 ((GIrNode *)field)->name = g_strdup (name);
815 if (readable && strcmp (readable, "1") == 0)
816 field->readable = TRUE;
818 field->readable = FALSE;
820 if (writable && strcmp (writable, "1") == 0)
821 field->writable = TRUE;
823 field->writable = FALSE;
826 field->bits = atoi (bits);
831 field->offset = atoi (offset);
835 switch (ctx->current_node->type)
837 case G_IR_NODE_OBJECT:
839 GIrNodeInterface *iface;
841 iface = (GIrNodeInterface *)ctx->current_node;
842 iface->members = g_list_append (iface->members, field);
843 state_switch (ctx, STATE_CLASS_FIELD);
846 case G_IR_NODE_INTERFACE:
848 GIrNodeInterface *iface;
850 iface = (GIrNodeInterface *)ctx->current_node;
851 iface->members = g_list_append (iface->members, field);
852 state_switch (ctx, STATE_INTERFACE_FIELD);
855 case G_IR_NODE_BOXED:
859 boxed = (GIrNodeBoxed *)ctx->current_node;
860 boxed->members = g_list_append (boxed->members, field);
861 state_switch (ctx, STATE_BOXED_FIELD);
864 case G_IR_NODE_STRUCT:
866 GIrNodeStruct *struct_;
868 struct_ = (GIrNodeStruct *)ctx->current_node;
869 struct_->members = g_list_append (struct_->members, field);
870 state_switch (ctx, STATE_STRUCT_FIELD);
873 case G_IR_NODE_UNION:
875 GIrNodeUnion *union_;
877 union_ = (GIrNodeUnion *)ctx->current_node;
878 union_->members = g_list_append (union_->members, field);
881 GIrNodeConstant *constant;
883 constant = (GIrNodeConstant *) g_ir_node_new (G_IR_NODE_CONSTANT);
884 ((GIrNode *)constant)->name = g_strdup (name);
885 constant->value = g_strdup (branch);
886 constant->type = union_->discriminator_type;
887 constant->deprecated = FALSE;
889 union_->discriminators = g_list_append (union_->discriminators, constant);
891 state_switch (ctx, STATE_UNION_FIELD);
895 g_assert_not_reached ();
905 start_alias (GMarkupParseContext *context,
906 const gchar *element_name,
907 const gchar **attribute_names,
908 const gchar **attribute_values,
916 name = find_attribute ("name", attribute_names, attribute_values);
918 MISSING_ATTRIBUTE (context, error, element_name, "name");
922 target = find_attribute ("target", attribute_names, attribute_values);
924 MISSING_ATTRIBUTE (context, error, element_name, "target");
928 g_hash_table_insert (ctx->aliases, g_strdup (name), g_strdup (target));
933 start_enum (GMarkupParseContext *context,
934 const gchar *element_name,
935 const gchar **attribute_names,
936 const gchar **attribute_values,
940 if ((strcmp (element_name, "enumeration") == 0 && ctx->state == STATE_NAMESPACE) ||
941 (strcmp (element_name, "bitfield") == 0 && ctx->state == STATE_NAMESPACE))
944 const gchar *typename;
945 const gchar *typeinit;
946 const gchar *deprecated;
948 name = find_attribute ("name", attribute_names, attribute_values);
949 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
950 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
951 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
954 MISSING_ATTRIBUTE (context, error, element_name, "name");
959 if (strcmp (element_name, "enumeration") == 0)
960 enum_ = (GIrNodeEnum *) g_ir_node_new (G_IR_NODE_ENUM);
962 enum_ = (GIrNodeEnum *) g_ir_node_new (G_IR_NODE_FLAGS);
963 ((GIrNode *)enum_)->name = g_strdup (name);
964 enum_->gtype_name = g_strdup (typename);
965 enum_->gtype_init = g_strdup (typeinit);
966 if (deprecated && strcmp (deprecated, "1") == 0)
967 enum_->deprecated = TRUE;
969 enum_->deprecated = FALSE;
971 ctx->current_node = (GIrNode *) enum_;
972 ctx->current_module->entries =
973 g_list_append (ctx->current_module->entries, enum_);
975 state_switch (ctx, STATE_ENUM);
984 start_property (GMarkupParseContext *context,
985 const gchar *element_name,
986 const gchar **attribute_names,
987 const gchar **attribute_values,
991 if (strcmp (element_name, "property") == 0 &&
992 (ctx->state == STATE_CLASS ||
993 ctx->state == STATE_INTERFACE))
996 const gchar *readable;
997 const gchar *writable;
998 const gchar *construct;
999 const gchar *construct_only;
1001 name = find_attribute ("name", attribute_names, attribute_values);
1002 readable = find_attribute ("readable", attribute_names, attribute_values);
1003 writable = find_attribute ("writable", attribute_names, attribute_values);
1004 construct = find_attribute ("construct", attribute_names, attribute_values);
1005 construct_only = find_attribute ("construct-only", attribute_names, attribute_values);
1008 MISSING_ATTRIBUTE (context, error, element_name, "name");
1011 GIrNodeProperty *property;
1012 GIrNodeInterface *iface;
1014 property = (GIrNodeProperty *) g_ir_node_new (G_IR_NODE_PROPERTY);
1015 ctx->current_typed = (GIrNode*) property;
1017 ((GIrNode *)property)->name = g_strdup (name);
1019 if (readable && strcmp (readable, "1") == 0)
1020 property->readable = TRUE;
1022 property->readable = FALSE;
1023 if (writable && strcmp (writable, "1") == 0)
1024 property->writable = TRUE;
1026 property->writable = FALSE;
1027 if (construct && strcmp (construct, "1") == 0)
1028 property->construct = TRUE;
1030 property->construct = FALSE;
1031 if (construct_only && strcmp (construct_only, "1") == 0)
1032 property->construct_only = TRUE;
1034 property->construct_only = FALSE;
1036 iface = (GIrNodeInterface *)ctx->current_node;
1037 iface->members = g_list_append (iface->members, property);
1039 if (ctx->state == STATE_CLASS)
1040 state_switch (ctx, STATE_CLASS_PROPERTY);
1041 else if (ctx->state == STATE_INTERFACE)
1042 state_switch (ctx, STATE_INTERFACE_PROPERTY);
1044 g_assert_not_reached ();
1053 parse_value (const gchar *str)
1057 /* FIXME just a quick hack */
1058 shift_op = strstr (str, "<<");
1064 base = strtol (str, NULL, 10);
1065 shift = strtol (shift_op + 3, NULL, 10);
1067 return base << shift;
1070 return strtol (str, NULL, 10);
1076 start_member (GMarkupParseContext *context,
1077 const gchar *element_name,
1078 const gchar **attribute_names,
1079 const gchar **attribute_values,
1083 if (strcmp (element_name, "member") == 0 &&
1084 ctx->state == STATE_ENUM)
1088 const gchar *deprecated;
1090 name = find_attribute ("name", attribute_names, attribute_values);
1091 value = find_attribute ("value", attribute_names, attribute_values);
1092 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1095 MISSING_ATTRIBUTE (context, error, element_name, "name");
1099 GIrNodeValue *value_;
1101 value_ = (GIrNodeValue *) g_ir_node_new (G_IR_NODE_VALUE);
1103 ((GIrNode *)value_)->name = g_strdup (name);
1105 value_->value = parse_value (value);
1107 if (deprecated && strcmp (deprecated, "1") == 0)
1108 value_->deprecated = TRUE;
1110 value_->deprecated = FALSE;
1112 enum_ = (GIrNodeEnum *)ctx->current_node;
1113 enum_->values = g_list_append (enum_->values, value_);
1122 start_constant (GMarkupParseContext *context,
1123 const gchar *element_name,
1124 const gchar **attribute_names,
1125 const gchar **attribute_values,
1129 if (strcmp (element_name, "constant") == 0 &&
1130 (ctx->state == STATE_NAMESPACE ||
1131 ctx->state == STATE_CLASS ||
1132 ctx->state == STATE_INTERFACE))
1136 const gchar *deprecated;
1138 name = find_attribute ("name", attribute_names, attribute_values);
1139 value = find_attribute ("value", attribute_names, attribute_values);
1140 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1143 MISSING_ATTRIBUTE (context, error, element_name, "name");
1144 else if (value == NULL)
1145 MISSING_ATTRIBUTE (context, error, element_name, "value");
1148 GIrNodeConstant *constant;
1150 constant = (GIrNodeConstant *) g_ir_node_new (G_IR_NODE_CONSTANT);
1152 ((GIrNode *)constant)->name = g_strdup (name);
1153 constant->value = g_strdup (value);
1155 ctx->current_typed = (GIrNode*) constant;
1157 if (deprecated && strcmp (deprecated, "1") == 0)
1158 constant->deprecated = TRUE;
1160 constant->deprecated = FALSE;
1162 if (ctx->state == STATE_NAMESPACE)
1164 ctx->current_node = (GIrNode *) constant;
1165 ctx->current_module->entries =
1166 g_list_append (ctx->current_module->entries, constant);
1170 GIrNodeInterface *iface;
1172 iface = (GIrNodeInterface *)ctx->current_node;
1173 iface->members = g_list_append (iface->members, constant);
1178 case STATE_NAMESPACE:
1179 state_switch (ctx, STATE_NAMESPACE_CONSTANT);
1182 state_switch (ctx, STATE_CLASS_CONSTANT);
1184 case STATE_INTERFACE:
1185 state_switch (ctx, STATE_INTERFACE_CONSTANT);
1188 g_assert_not_reached ();
1199 start_errordomain (GMarkupParseContext *context,
1200 const gchar *element_name,
1201 const gchar **attribute_names,
1202 const gchar **attribute_values,
1206 if (strcmp (element_name, "errordomain") == 0 &&
1207 ctx->state == STATE_NAMESPACE)
1210 const gchar *getquark;
1212 const gchar *deprecated;
1214 name = find_attribute ("name", attribute_names, attribute_values);
1215 getquark = find_attribute ("get-quark", attribute_names, attribute_values);
1216 codes = find_attribute ("codes", attribute_names, attribute_values);
1217 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1220 MISSING_ATTRIBUTE (context, error, element_name, "name");
1221 else if (getquark == NULL)
1222 MISSING_ATTRIBUTE (context, error, element_name, "getquark");
1223 else if (codes == NULL)
1224 MISSING_ATTRIBUTE (context, error, element_name, "codes");
1227 GIrNodeErrorDomain *domain;
1229 domain = (GIrNodeErrorDomain *) g_ir_node_new (G_IR_NODE_ERROR_DOMAIN);
1231 ((GIrNode *)domain)->name = g_strdup (name);
1232 domain->getquark = g_strdup (getquark);
1233 domain->codes = g_strdup (codes);
1235 if (deprecated && strcmp (deprecated, "1") == 0)
1236 domain->deprecated = TRUE;
1238 domain->deprecated = FALSE;
1240 ctx->current_node = (GIrNode *) domain;
1241 ctx->current_module->entries =
1242 g_list_append (ctx->current_module->entries, domain);
1244 state_switch (ctx, STATE_ERRORDOMAIN);
1253 start_interface (GMarkupParseContext *context,
1254 const gchar *element_name,
1255 const gchar **attribute_names,
1256 const gchar **attribute_values,
1260 if (strcmp (element_name, "interface") == 0 &&
1261 ctx->state == STATE_NAMESPACE)
1264 const gchar *typename;
1265 const gchar *typeinit;
1266 const gchar *deprecated;
1268 name = find_attribute ("name", attribute_names, attribute_values);
1269 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
1270 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
1271 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1274 MISSING_ATTRIBUTE (context, error, element_name, "name");
1275 else if (typename == NULL)
1276 MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
1277 else if (typeinit == NULL)
1278 MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
1281 GIrNodeInterface *iface;
1283 iface = (GIrNodeInterface *) g_ir_node_new (G_IR_NODE_INTERFACE);
1284 ((GIrNode *)iface)->name = g_strdup (name);
1285 iface->gtype_name = g_strdup (typename);
1286 iface->gtype_init = g_strdup (typeinit);
1287 if (deprecated && strcmp (deprecated, "1") == 0)
1288 iface->deprecated = TRUE;
1290 iface->deprecated = FALSE;
1292 ctx->current_node = (GIrNode *) iface;
1293 ctx->current_module->entries =
1294 g_list_append (ctx->current_module->entries, iface);
1296 state_switch (ctx, STATE_INTERFACE);
1306 start_class (GMarkupParseContext *context,
1307 const gchar *element_name,
1308 const gchar **attribute_names,
1309 const gchar **attribute_values,
1313 if (strcmp (element_name, "class") == 0 &&
1314 ctx->state == STATE_NAMESPACE)
1317 const gchar *parent;
1318 const gchar *typename;
1319 const gchar *typeinit;
1320 const gchar *deprecated;
1322 name = find_attribute ("name", attribute_names, attribute_values);
1323 parent = find_attribute ("parent", attribute_names, attribute_values);
1324 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
1325 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
1326 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1329 MISSING_ATTRIBUTE (context, error, element_name, "name");
1330 else if (typename == NULL)
1331 MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
1332 else if (typeinit == NULL && strcmp (typename, "GObject"))
1333 MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
1336 GIrNodeInterface *iface;
1338 iface = (GIrNodeInterface *) g_ir_node_new (G_IR_NODE_OBJECT);
1339 ((GIrNode *)iface)->name = g_strdup (name);
1340 iface->gtype_name = g_strdup (typename);
1341 iface->gtype_init = g_strdup (typeinit);
1342 iface->parent = g_strdup (parent);
1343 if (deprecated && strcmp (deprecated, "1") == 0)
1344 iface->deprecated = TRUE;
1346 iface->deprecated = FALSE;
1348 ctx->current_node = (GIrNode *) iface;
1349 ctx->current_module->entries =
1350 g_list_append (ctx->current_module->entries, iface);
1352 state_switch (ctx, STATE_CLASS);
1361 start_type (GMarkupParseContext *context,
1362 const gchar *element_name,
1363 const gchar **attribute_names,
1364 const gchar **attribute_values,
1370 if (strcmp (element_name, "type") != 0 ||
1371 !(ctx->state == STATE_FUNCTION_PARAMETER ||
1372 ctx->state == STATE_FUNCTION_RETURN ||
1373 ctx->state == STATE_STRUCT_FIELD ||
1374 ctx->state == STATE_UNION_FIELD ||
1375 ctx->state == STATE_CLASS_PROPERTY ||
1376 ctx->state == STATE_CLASS_FIELD ||
1377 ctx->state == STATE_INTERFACE_FIELD ||
1378 ctx->state == STATE_INTERFACE_PROPERTY ||
1379 ctx->state == STATE_BOXED_FIELD ||
1380 ctx->state == STATE_NAMESPACE_CONSTANT ||
1381 ctx->state == STATE_CLASS_CONSTANT ||
1382 ctx->state == STATE_INTERFACE_CONSTANT
1386 if (!ctx->current_typed)
1390 G_MARKUP_ERROR_INVALID_CONTENT,
1391 "The element <type> is invalid here");
1395 name = find_attribute ("name", attribute_names, attribute_values);
1398 MISSING_ATTRIBUTE (context, error, element_name, "name");
1400 switch (ctx->current_typed->type)
1402 case G_IR_NODE_PARAM:
1404 GIrNodeParam *param = (GIrNodeParam *)ctx->current_typed;
1405 param->type = parse_type (ctx, name);
1408 case G_IR_NODE_FIELD:
1410 GIrNodeField *field = (GIrNodeField *)ctx->current_typed;
1411 field->type = parse_type (ctx, name);
1414 case G_IR_NODE_PROPERTY:
1416 GIrNodeProperty *property = (GIrNodeProperty *) ctx->current_typed;
1417 property->type = parse_type (ctx, name);
1420 case G_IR_NODE_CONSTANT:
1422 GIrNodeConstant *constant = (GIrNodeConstant *)ctx->current_typed;
1423 constant->type = parse_type (ctx, name);
1427 g_printerr("current node is %d\n", ctx->current_node->type);
1428 g_assert_not_reached ();
1431 ctx->current_typed = NULL;
1436 start_return_value (GMarkupParseContext *context,
1437 const gchar *element_name,
1438 const gchar **attribute_names,
1439 const gchar **attribute_values,
1443 if (strcmp (element_name, "return-value") == 0 &&
1444 ctx->state == STATE_FUNCTION)
1446 GIrNodeParam *param;
1448 param = (GIrNodeParam *)g_ir_node_new (G_IR_NODE_PARAM);
1451 param->retval = TRUE;
1453 ctx->current_typed = (GIrNode*) param;
1455 state_switch (ctx, STATE_FUNCTION_RETURN);
1457 switch (ctx->current_node->type)
1459 case G_IR_NODE_FUNCTION:
1460 case G_IR_NODE_CALLBACK:
1462 GIrNodeFunction *func = (GIrNodeFunction *)ctx->current_node;
1463 func->result = param;
1466 case G_IR_NODE_SIGNAL:
1468 GIrNodeSignal *signal = (GIrNodeSignal *)ctx->current_node;
1469 signal->result = param;
1472 case G_IR_NODE_VFUNC:
1474 GIrNodeVFunc *vfunc = (GIrNodeVFunc *)ctx->current_node;
1475 vfunc->result = param;
1479 g_assert_not_reached ();
1489 start_glib_signal (GMarkupParseContext *context,
1490 const gchar *element_name,
1491 const gchar **attribute_names,
1492 const gchar **attribute_values,
1496 if (strcmp (element_name, "glib:signal") == 0 &&
1497 (ctx->state == STATE_CLASS ||
1498 ctx->state == STATE_INTERFACE))
1502 const gchar *no_recurse;
1503 const gchar *detailed;
1504 const gchar *action;
1505 const gchar *no_hooks;
1506 const gchar *has_class_closure;
1508 name = find_attribute ("name", attribute_names, attribute_values);
1509 when = find_attribute ("when", attribute_names, attribute_values);
1510 no_recurse = find_attribute ("no-recurse", attribute_names, attribute_values);
1511 detailed = find_attribute ("detailed", attribute_names, attribute_values);
1512 action = find_attribute ("action", attribute_names, attribute_values);
1513 no_hooks = find_attribute ("no-hooks", attribute_names, attribute_values);
1514 has_class_closure = find_attribute ("has-class-closure", attribute_names, attribute_values);
1517 MISSING_ATTRIBUTE (context, error, element_name, "name");
1520 GIrNodeInterface *iface;
1521 GIrNodeSignal *signal;
1523 signal = (GIrNodeSignal *)g_ir_node_new (G_IR_NODE_SIGNAL);
1525 ((GIrNode *)signal)->name = g_strdup (name);
1527 signal->run_first = FALSE;
1528 signal->run_last = FALSE;
1529 signal->run_cleanup = FALSE;
1530 if (when == NULL || strcmp (when, "LAST") == 0)
1531 signal->run_last = TRUE;
1532 else if (strcmp (when, "FIRST") == 0)
1533 signal->run_first = TRUE;
1535 signal->run_cleanup = TRUE;
1537 if (no_recurse && strcmp (no_recurse, "1") == 0)
1538 signal->no_recurse = TRUE;
1540 signal->no_recurse = FALSE;
1541 if (detailed && strcmp (detailed, "1") == 0)
1542 signal->detailed = TRUE;
1544 signal->detailed = FALSE;
1545 if (action && strcmp (action, "1") == 0)
1546 signal->action = TRUE;
1548 signal->action = FALSE;
1549 if (no_hooks && strcmp (no_hooks, "1") == 0)
1550 signal->no_hooks = TRUE;
1552 signal->no_hooks = FALSE;
1553 if (has_class_closure && strcmp (has_class_closure, "1") == 0)
1554 signal->has_class_closure = TRUE;
1556 signal->has_class_closure = FALSE;
1558 iface = (GIrNodeInterface *)ctx->current_node;
1559 iface->members = g_list_append (iface->members, signal);
1561 ctx->current_node = (GIrNode *)signal;
1562 state_switch (ctx, STATE_FUNCTION);
1571 start_vfunc (GMarkupParseContext *context,
1572 const gchar *element_name,
1573 const gchar **attribute_names,
1574 const gchar **attribute_values,
1578 if (strcmp (element_name, "vfunc") == 0 &&
1579 (ctx->state == STATE_CLASS ||
1580 ctx->state == STATE_INTERFACE))
1583 const gchar *must_chain_up;
1584 const gchar *override;
1585 const gchar *is_class_closure;
1586 const gchar *offset;
1588 name = find_attribute ("name", attribute_names, attribute_values);
1589 must_chain_up = find_attribute ("must-chain-up", attribute_names, attribute_values);
1590 override = find_attribute ("override", attribute_names, attribute_values);
1591 is_class_closure = find_attribute ("is-class-closure", attribute_names, attribute_values);
1592 offset = find_attribute ("offset", attribute_names, attribute_values);
1595 MISSING_ATTRIBUTE (context, error, element_name, "name");
1598 GIrNodeInterface *iface;
1599 GIrNodeVFunc *vfunc;
1601 vfunc = (GIrNodeVFunc *)g_ir_node_new (G_IR_NODE_VFUNC);
1603 ((GIrNode *)vfunc)->name = g_strdup (name);
1605 if (must_chain_up && strcmp (must_chain_up, "1") == 0)
1606 vfunc->must_chain_up = TRUE;
1608 vfunc->must_chain_up = FALSE;
1610 if (override && strcmp (override, "always") == 0)
1612 vfunc->must_be_implemented = TRUE;
1613 vfunc->must_not_be_implemented = FALSE;
1615 else if (override && strcmp (override, "never") == 0)
1617 vfunc->must_be_implemented = FALSE;
1618 vfunc->must_not_be_implemented = TRUE;
1622 vfunc->must_be_implemented = FALSE;
1623 vfunc->must_not_be_implemented = FALSE;
1626 if (is_class_closure && strcmp (is_class_closure, "1") == 0)
1627 vfunc->is_class_closure = TRUE;
1629 vfunc->is_class_closure = FALSE;
1632 vfunc->offset = atoi (offset);
1636 iface = (GIrNodeInterface *)ctx->current_node;
1637 iface->members = g_list_append (iface->members, vfunc);
1639 ctx->current_node = (GIrNode *)vfunc;
1640 state_switch (ctx, STATE_FUNCTION);
1650 start_struct (GMarkupParseContext *context,
1651 const gchar *element_name,
1652 const gchar **attribute_names,
1653 const gchar **attribute_values,
1657 if (strcmp (element_name, "record") == 0 &&
1658 ctx->state == STATE_NAMESPACE)
1661 const gchar *deprecated;
1663 name = find_attribute ("name", attribute_names, attribute_values);
1664 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1667 MISSING_ATTRIBUTE (context, error, element_name, "name");
1670 GIrNodeStruct *struct_;
1672 struct_ = (GIrNodeStruct *) g_ir_node_new (G_IR_NODE_STRUCT);
1674 ((GIrNode *)struct_)->name = g_strdup (name);
1675 if (deprecated && strcmp (deprecated, "1") == 0)
1676 struct_->deprecated = TRUE;
1678 struct_->deprecated = FALSE;
1680 ctx->current_node = (GIrNode *)struct_;
1681 ctx->current_module->entries =
1682 g_list_append (ctx->current_module->entries, struct_);
1684 state_switch (ctx, STATE_STRUCT);
1693 start_union (GMarkupParseContext *context,
1694 const gchar *element_name,
1695 const gchar **attribute_names,
1696 const gchar **attribute_values,
1700 if (strcmp (element_name, "union") == 0 &&
1701 ctx->state == STATE_NAMESPACE)
1704 const gchar *deprecated;
1705 const gchar *typename;
1706 const gchar *typeinit;
1708 name = find_attribute ("name", attribute_names, attribute_values);
1709 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1710 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
1711 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
1714 MISSING_ATTRIBUTE (context, error, element_name, "name");
1717 GIrNodeUnion *union_;
1719 union_ = (GIrNodeUnion *) g_ir_node_new (G_IR_NODE_UNION);
1721 ((GIrNode *)union_)->name = g_strdup (name);
1722 union_->gtype_name = g_strdup (typename);
1723 union_->gtype_init = g_strdup (typeinit);
1724 if (deprecated && strcmp (deprecated, "1") == 0)
1725 union_->deprecated = TRUE;
1727 union_->deprecated = FALSE;
1729 ctx->current_node = (GIrNode *)union_;
1730 ctx->current_module->entries =
1731 g_list_append (ctx->current_module->entries, union_);
1733 state_switch (ctx, STATE_UNION);
1741 start_discriminator (GMarkupParseContext *context,
1742 const gchar *element_name,
1743 const gchar **attribute_names,
1744 const gchar **attribute_values,
1748 if (strcmp (element_name, "discriminator") == 0 &&
1749 ctx->state == STATE_UNION)
1752 const gchar *offset;
1754 type = find_attribute ("type", attribute_names, attribute_values);
1755 offset = find_attribute ("offset", attribute_names, attribute_values);
1757 MISSING_ATTRIBUTE (context, error, element_name, "type");
1758 else if (offset == NULL)
1759 MISSING_ATTRIBUTE (context, error, element_name, "offset");
1761 ((GIrNodeUnion *)ctx->current_node)->discriminator_type
1762 = parse_type (ctx, type);
1763 ((GIrNodeUnion *)ctx->current_node)->discriminator_offset
1773 extern GLogLevelFlags logged_levels;
1776 start_element_handler (GMarkupParseContext *context,
1777 const gchar *element_name,
1778 const gchar **attribute_names,
1779 const gchar **attribute_values,
1783 ParseContext *ctx = user_data;
1784 gint line_number, char_number;
1786 if (logged_levels & G_LOG_LEVEL_DEBUG)
1788 GString *tags = g_string_new ("");
1790 for (i = 0; attribute_names[i]; i++)
1791 g_string_append_printf (tags, "%s=\"%s\" ",
1793 attribute_values[i]);
1797 g_string_insert_c (tags, 0, ' ');
1798 g_string_truncate (tags, tags->len - 1);
1800 g_debug ("<%s%s>", element_name, tags->str);
1801 g_string_free (tags, TRUE);
1804 switch (element_name[0])
1807 if (ctx->state == STATE_NAMESPACE && strcmp (element_name, "alias") == 0)
1809 state_switch (ctx, STATE_ALIAS);
1814 if (start_enum (context, element_name,
1815 attribute_names, attribute_values,
1820 if (start_function (context, element_name,
1821 attribute_names, attribute_values,
1824 else if (start_constant (context, element_name,
1825 attribute_names, attribute_values,
1828 else if (start_class (context, element_name,
1829 attribute_names, attribute_values,
1832 else if (strcmp (element_name, "class") == 0 &&
1833 ctx->state == STATE_REQUIRES)
1837 name = find_attribute ("name", attribute_names, attribute_values);
1840 MISSING_ATTRIBUTE (context, error, element_name, "name");
1843 GIrNodeInterface *iface;
1845 iface = (GIrNodeInterface *)ctx->current_node;
1846 iface ->prerequisites = g_list_append (iface->prerequisites, g_strdup (name));
1854 if (start_discriminator (context, element_name,
1855 attribute_names, attribute_values,
1861 if (start_enum (context, element_name,
1862 attribute_names, attribute_values,
1865 else if (start_errordomain (context, element_name,
1866 attribute_names, attribute_values,
1872 if (start_function (context, element_name,
1873 attribute_names, attribute_values,
1876 else if (start_field (context, element_name,
1877 attribute_names, attribute_values,
1883 if (start_glib_boxed (context, element_name,
1884 attribute_names, attribute_values,
1887 else if (start_glib_signal (context, element_name,
1888 attribute_names, attribute_values,
1891 else if (start_glib_boxed (context, element_name,
1892 attribute_names, attribute_values,
1898 if (start_interface (context, element_name,
1899 attribute_names, attribute_values,
1902 if (strcmp (element_name, "implements") == 0 &&
1903 ctx->state == STATE_CLASS)
1905 state_switch (ctx, STATE_IMPLEMENTS);
1909 else if (strcmp (element_name, "interface") == 0 &&
1910 ctx->state == STATE_IMPLEMENTS)
1914 name = find_attribute ("name", attribute_names, attribute_values);
1917 MISSING_ATTRIBUTE (context, error, element_name, "name");
1920 GIrNodeInterface *iface;
1922 iface = (GIrNodeInterface *)ctx->current_node;
1923 iface ->interfaces = g_list_append (iface->interfaces, g_strdup (name));
1928 else if (strcmp (element_name, "interface") == 0 &&
1929 ctx->state == STATE_REQUIRES)
1933 name = find_attribute ("name", attribute_names, attribute_values);
1936 MISSING_ATTRIBUTE (context, error, element_name, "name");
1939 GIrNodeInterface *iface;
1941 iface = (GIrNodeInterface *)ctx->current_node;
1942 iface ->prerequisites = g_list_append (iface->prerequisites, g_strdup (name));
1950 if (start_function (context, element_name,
1951 attribute_names, attribute_values,
1954 else if (start_member (context, element_name,
1955 attribute_names, attribute_values,
1961 if (strcmp (element_name, "namespace") == 0 && ctx->state == STATE_REPOSITORY)
1963 const gchar *name, *shared_library;
1965 name = find_attribute ("name", attribute_names, attribute_values);
1966 shared_library = find_attribute ("shared-library", attribute_names, attribute_values);
1969 MISSING_ATTRIBUTE (context, error, element_name, "name");
1972 ctx->current_module = g_ir_module_new (name, shared_library);
1973 ctx->modules = g_list_append (ctx->modules, ctx->current_module);
1975 state_switch (ctx, STATE_NAMESPACE);
1983 if (start_property (context, element_name,
1984 attribute_names, attribute_values,
1987 else if (strcmp (element_name, "parameters") == 0 &&
1988 ctx->state == STATE_FUNCTION)
1990 state_switch (ctx, STATE_FUNCTION_PARAMETERS);
1994 else if (start_parameter (context, element_name,
1995 attribute_names, attribute_values,
2002 if (strcmp (element_name, "repository") == 0 && ctx->state == STATE_START)
2004 const gchar *version;
2006 version = find_attribute ("version", attribute_names, attribute_values);
2008 if (version == NULL)
2009 MISSING_ATTRIBUTE (context, error, element_name, "version");
2010 else if (strcmp (version, "1.0") != 0)
2013 G_MARKUP_ERROR_INVALID_CONTENT,
2014 "Unsupported version '%s'",
2017 state_switch (ctx, STATE_REPOSITORY);
2021 else if (start_return_value (context, element_name,
2022 attribute_names, attribute_values,
2025 else if (strcmp (element_name, "requires") == 0 &&
2026 ctx->state == STATE_INTERFACE)
2028 state_switch (ctx, STATE_REQUIRES);
2032 else if (start_struct (context, element_name,
2033 attribute_names, attribute_values,
2039 if (start_union (context, element_name,
2040 attribute_names, attribute_values,
2046 if (start_type (context, element_name,
2047 attribute_names, attribute_values,
2053 if (start_vfunc (context, element_name,
2054 attribute_names, attribute_values,
2060 g_markup_parse_context_get_position (context, &line_number, &char_number);
2064 G_MARKUP_ERROR_UNKNOWN_ELEMENT,
2065 "Unexpected start tag '%s' on line %d char %d; current state=%d",
2067 line_number, char_number, ctx->state);
2072 g_markup_parse_context_get_position (context, &line_number, &char_number);
2074 fprintf (stderr, "Error at line %d, character %d: %s\n", line_number, char_number, (*error)->message);
2075 backtrace_stderr ();
2080 require_one_of_end_elements (GMarkupParseContext *context,
2082 const char *actual_name,
2087 int line_number, char_number;
2088 const char *expected;
2089 gboolean matched = FALSE;
2091 va_start (args, error);
2093 while ((expected = va_arg (args, const char*)) != NULL)
2095 if (strcmp (expected, actual_name) == 0)
2107 g_markup_parse_context_get_position (context, &line_number, &char_number);
2110 G_MARKUP_ERROR_INVALID_CONTENT,
2111 "Unexpected end tag '%s' on line %d char %d; current state=%d",
2113 line_number, char_number, ctx->state);
2119 require_end_element (GMarkupParseContext *context,
2121 const char *expected_name,
2122 const char *actual_name,
2125 return require_one_of_end_elements (context, ctx, actual_name, error, expected_name, NULL);
2129 end_element_handler (GMarkupParseContext *context,
2130 const gchar *element_name,
2134 ParseContext *ctx = user_data;
2136 g_debug ("</%s>", element_name);
2142 /* no need to GError here, GMarkup already catches this */
2145 case STATE_REPOSITORY:
2146 state_switch (ctx, STATE_END);
2149 case STATE_NAMESPACE:
2150 if (require_end_element (context, ctx, "namespace", element_name, error))
2152 ctx->current_module = NULL;
2153 state_switch (ctx, STATE_REPOSITORY);
2158 if (require_end_element (context, ctx, "alias", element_name, error))
2160 state_switch (ctx, STATE_NAMESPACE);
2164 case STATE_FUNCTION_RETURN:
2165 if (strcmp ("type", element_name) == 0)
2167 if (require_end_element (context, ctx, "return-value", element_name, error))
2169 state_switch (ctx, STATE_FUNCTION);
2173 case STATE_FUNCTION_PARAMETERS:
2174 if (require_end_element (context, ctx, "parameters", element_name, error))
2176 state_switch (ctx, STATE_FUNCTION);
2180 case STATE_FUNCTION_PARAMETER:
2181 if (strcmp ("type", element_name) == 0)
2183 if (require_end_element (context, ctx, "parameter", element_name, error))
2185 state_switch (ctx, STATE_FUNCTION_PARAMETERS);
2189 case STATE_FUNCTION:
2190 if (ctx->current_node == g_list_last (ctx->current_module->entries)->data)
2192 ctx->current_node = NULL;
2193 state_switch (ctx, STATE_NAMESPACE);
2197 ctx->current_node = g_list_last (ctx->current_module->entries)->data;
2198 if (ctx->current_node->type == G_IR_NODE_INTERFACE)
2199 state_switch (ctx, STATE_INTERFACE);
2200 else if (ctx->current_node->type == G_IR_NODE_OBJECT)
2201 state_switch (ctx, STATE_CLASS);
2202 else if (ctx->current_node->type == G_IR_NODE_BOXED)
2203 state_switch (ctx, STATE_BOXED);
2204 else if (ctx->current_node->type == G_IR_NODE_STRUCT)
2205 state_switch (ctx, STATE_STRUCT);
2206 else if (ctx->current_node->type == G_IR_NODE_UNION)
2207 state_switch (ctx, STATE_UNION);
2210 int line_number, char_number;
2211 g_markup_parse_context_get_position (context, &line_number, &char_number);
2214 G_MARKUP_ERROR_INVALID_CONTENT,
2215 "Unexpected end tag '%s' on line %d char %d",
2217 line_number, char_number);
2222 case STATE_CLASS_FIELD:
2223 if (strcmp ("type", element_name) == 0)
2225 if (require_end_element (context, ctx, "field", element_name, error))
2227 state_switch (ctx, STATE_CLASS);
2231 case STATE_CLASS_PROPERTY:
2232 if (strcmp ("type", element_name) == 0)
2234 if (require_end_element (context, ctx, "property", element_name, error))
2236 state_switch (ctx, STATE_CLASS);
2241 if (require_end_element (context, ctx, "class", element_name, error))
2243 ctx->current_node = NULL;
2244 state_switch (ctx, STATE_NAMESPACE);
2248 case STATE_ERRORDOMAIN:
2249 if (require_end_element (context, ctx, "errordomain", element_name, error))
2251 ctx->current_node = NULL;
2252 state_switch (ctx, STATE_NAMESPACE);
2256 case STATE_INTERFACE_PROPERTY:
2257 if (strcmp ("type", element_name) == 0)
2259 if (require_end_element (context, ctx, "property", element_name, error))
2261 state_switch (ctx, STATE_INTERFACE);
2265 case STATE_INTERFACE_FIELD:
2266 if (strcmp ("type", element_name) == 0)
2268 if (require_end_element (context, ctx, "field", element_name, error))
2270 state_switch (ctx, STATE_INTERFACE);
2274 case STATE_INTERFACE:
2275 if (require_end_element (context, ctx, "interface", element_name, error))
2277 ctx->current_node = NULL;
2278 state_switch (ctx, STATE_NAMESPACE);
2283 if (strcmp ("member", element_name) == 0)
2285 else if (require_one_of_end_elements (context, ctx,
2286 element_name, error, "enumeration",
2289 ctx->current_node = NULL;
2290 state_switch (ctx, STATE_NAMESPACE);
2295 if (require_end_element (context, ctx, "glib:boxed", element_name, error))
2297 ctx->current_node = NULL;
2298 state_switch (ctx, STATE_NAMESPACE);
2302 case STATE_BOXED_FIELD:
2303 if (strcmp ("type", element_name) == 0)
2305 if (require_end_element (context, ctx, "field", element_name, error))
2307 state_switch (ctx, STATE_BOXED);
2311 case STATE_STRUCT_FIELD:
2312 if (strcmp ("type", element_name) == 0)
2314 if (require_end_element (context, ctx, "field", element_name, error))
2316 state_switch (ctx, STATE_STRUCT);
2321 if (require_end_element (context, ctx, "record", element_name, error))
2323 ctx->current_node = NULL;
2324 state_switch (ctx, STATE_NAMESPACE);
2328 case STATE_UNION_FIELD:
2329 if (strcmp ("type", element_name) == 0)
2331 if (require_end_element (context, ctx, "field", element_name, error))
2333 state_switch (ctx, STATE_UNION);
2338 if (require_end_element (context, ctx, "union", element_name, error))
2340 ctx->current_node = NULL;
2341 state_switch (ctx, STATE_NAMESPACE);
2344 case STATE_IMPLEMENTS:
2345 if (strcmp ("interface", element_name) == 0)
2347 if (require_end_element (context, ctx, "implements", element_name, error))
2348 state_switch (ctx, STATE_CLASS);
2350 case STATE_REQUIRES:
2351 if (require_end_element (context, ctx, "requires", element_name, error))
2352 state_switch (ctx, STATE_INTERFACE);
2354 case STATE_NAMESPACE_CONSTANT:
2355 case STATE_CLASS_CONSTANT:
2356 case STATE_INTERFACE_CONSTANT:
2357 if (strcmp ("type", element_name) == 0)
2359 if (require_end_element (context, ctx, "constant", element_name, error))
2361 ctx->current_node = NULL;
2364 case STATE_NAMESPACE_CONSTANT:
2365 state_switch (ctx, STATE_NAMESPACE);
2367 case STATE_CLASS_CONSTANT:
2368 state_switch (ctx, STATE_CLASS);
2370 case STATE_INTERFACE_CONSTANT:
2371 state_switch (ctx, STATE_INTERFACE);
2374 g_assert_not_reached ();
2380 g_error ("Unhandled state %d in end_element_handler\n", ctx->state);
2385 text_handler (GMarkupParseContext *context,
2391 /* FIXME warn about non-whitespace text */
2395 cleanup (GMarkupParseContext *context,
2399 ParseContext *ctx = user_data;
2401 int line_number, char_number;
2403 for (m = ctx->modules; m; m = m->next)
2404 g_ir_module_free (m->data);
2405 g_list_free (ctx->modules);
2406 ctx->modules = NULL;
2408 ctx->current_module = NULL;
2412 firstpass_start_element_handler (GMarkupParseContext *context,
2413 const gchar *element_name,
2414 const gchar **attribute_names,
2415 const gchar **attribute_values,
2419 ParseContext *ctx = user_data;
2421 if (strcmp (element_name, "alias") == 0)
2423 start_alias (context, element_name, attribute_names, attribute_values,
2429 firstpass_end_element_handler (GMarkupParseContext *context,
2430 const gchar *element_name,
2434 ParseContext *ctx = user_data;
2439 static GMarkupParser firstpass_parser =
2441 firstpass_start_element_handler,
2442 firstpass_end_element_handler,
2449 static GMarkupParser parser =
2451 start_element_handler,
2452 end_element_handler,
2459 g_ir_parse_string (const gchar *buffer,
2463 ParseContext ctx = { 0 };
2464 GMarkupParseContext *context;
2466 ctx.state = STATE_START;
2467 ctx.aliases = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
2469 context = g_markup_parse_context_new (&firstpass_parser, 0, &ctx, NULL);
2471 if (!g_markup_parse_context_parse (context, buffer, length, error))
2474 if (!g_markup_parse_context_end_parse (context, error))
2477 context = g_markup_parse_context_new (&parser, 0, &ctx, NULL);
2478 if (!g_markup_parse_context_parse (context, buffer, length, error))
2481 if (!g_markup_parse_context_end_parse (context, error))
2486 g_hash_table_destroy (ctx.aliases);
2488 g_markup_parse_context_free (context);
2494 g_ir_parse_file (const gchar *filename,
2501 g_debug ("[parsing] filename %s", filename);
2503 if (!g_file_get_contents (filename, &buffer, &length, error))
2506 modules = g_ir_parse_string (buffer, length, error);