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 { "gshort", GI_TYPE_TAG_INT16, 0 },
201 { "gushort", GI_TYPE_TAG_UINT16, 0 },
202 { "gint8", GI_TYPE_TAG_INT8, 0 },
203 { "guint8", GI_TYPE_TAG_UINT8, 0 },
204 { "gint16", GI_TYPE_TAG_INT16, 0 },
205 { "guint16", GI_TYPE_TAG_UINT16, 0 },
206 { "gint32", GI_TYPE_TAG_INT32, 0 },
207 { "guint32", GI_TYPE_TAG_UINT32, 0 },
208 { "gint64", GI_TYPE_TAG_INT64, 0 },
209 { "guint64", GI_TYPE_TAG_UINT64, 0 },
210 { "glong", GI_TYPE_TAG_LONG, 0 },
211 { "gulong", GI_TYPE_TAG_ULONG, 0 },
212 { "gssize", GI_TYPE_TAG_SSIZE, 0 },
213 { "gsize", GI_TYPE_TAG_SIZE, 0 },
214 { "gfloat", GI_TYPE_TAG_FLOAT, 0 },
215 { "gdouble", GI_TYPE_TAG_DOUBLE, 0 },
216 { "gchar*", GI_TYPE_TAG_UTF8, 1 }
219 gint n_basic = G_N_ELEMENTS (basic);
224 type = (GIrNodeType *)g_ir_node_new (G_IR_NODE_TYPE);
226 str = g_strstrip (str);
228 type->unparsed = g_strdup (str);
231 for (i = 0; i < n_basic; i++)
233 if (g_str_has_prefix (*rest, basic[i].str))
235 type->is_basic = TRUE;
236 type->tag = basic[i].tag;
237 type->is_pointer = basic[i].pointer;
239 *rest += strlen(basic[i].str);
240 *rest = g_strchug (*rest);
241 if (**rest == '*' && !type->is_pointer)
243 type->is_pointer = TRUE;
252 /* found a basic type */;
253 else if (g_str_has_prefix (*rest, "GList") ||
254 g_str_has_prefix (*rest, "GSList"))
256 if (g_str_has_prefix (*rest, "GList"))
258 type->tag = GI_TYPE_TAG_GLIST;
259 type->is_glist = TRUE;
260 type->is_pointer = TRUE;
261 *rest += strlen ("GList");
265 type->tag = GI_TYPE_TAG_GSLIST;
266 type->is_gslist = TRUE;
267 type->is_pointer = TRUE;
268 *rest += strlen ("GSList");
271 *rest = g_strchug (*rest);
277 type->parameter_type1 = parse_type_internal (*rest, rest);
278 if (type->parameter_type1 == NULL)
281 *rest = g_strchug (*rest);
283 if ((*rest)[0] != '>')
289 type->parameter_type1 = create_pointer ();
292 else if (g_str_has_prefix (*rest, "GHashTable"))
294 type->tag = GI_TYPE_TAG_GHASH;
295 type->is_ghashtable = TRUE;
296 type->is_pointer = TRUE;
297 *rest += strlen ("GHashTable");
299 *rest = g_strchug (*rest);
305 type->parameter_type1 = parse_type_internal (*rest, rest);
306 if (type->parameter_type1 == NULL)
309 *rest = g_strchug (*rest);
311 if ((*rest)[0] != ',')
315 type->parameter_type2 = parse_type_internal (*rest, rest);
316 if (type->parameter_type2 == NULL)
319 if ((*rest)[0] != '>')
325 type->parameter_type1 = create_pointer ();
326 type->parameter_type2 = create_pointer ();
330 else if (g_str_has_prefix (*rest, "GError"))
332 type->tag = GI_TYPE_TAG_ERROR;
333 type->is_error = TRUE;
334 type->is_pointer = TRUE;
335 *rest += strlen ("GError");
337 *rest = g_strchug (*rest);
343 end = strchr (*rest, '>');
344 str = g_strndup (*rest, end - *rest);
345 type->errors = g_strsplit (str, ",", 0);
353 type->tag = GI_TYPE_TAG_INTERFACE;
354 type->is_interface = TRUE;
357 /* must be an interface type */
358 while (g_ascii_isalnum (**rest) ||
365 type->interface = g_strndup (start, *rest - start);
367 *rest = g_strchug (*rest);
370 type->is_pointer = TRUE;
375 *rest = g_strchug (*rest);
376 if (g_str_has_prefix (*rest, "["))
380 array = (GIrNodeType *)g_ir_node_new (G_IR_NODE_TYPE);
382 array->tag = GI_TYPE_TAG_ARRAY;
383 array->is_pointer = TRUE;
384 array->is_array = TRUE;
386 array->parameter_type1 = type;
388 array->zero_terminated = FALSE;
389 array->has_length = FALSE;
392 if (!g_str_has_prefix (*rest, "[]"))
394 gchar *end, *str, **opts;
396 end = strchr (*rest, ']');
397 str = g_strndup (*rest + 1, (end - *rest) - 1);
398 opts = g_strsplit (str, ",", 0);
402 for (i = 0; opts[i]; i++)
406 vals = g_strsplit (opts[i], "=", 0);
408 if (strcmp (vals[0], "zero-terminated") == 0)
409 array->zero_terminated = (strcmp (vals[1], "1") == 0);
410 else if (strcmp (vals[0], "length") == 0)
412 array->has_length = TRUE;
413 array->length = atoi (vals[1]);
426 g_assert (type->tag >= 0 && type->tag <= GI_TYPE_TAG_ERROR);
430 g_ir_node_free ((GIrNode *)type);
436 resolve_aliases (ParseContext *ctx, const gchar *type)
440 GSList *seen_values = NULL;
442 seen_values = g_slist_prepend (seen_values, (char*)type);
443 while (g_hash_table_lookup_extended (ctx->aliases, type, &orig, &value))
445 g_debug ("Resolved: %s => %s", type, value);
447 if (g_slist_find_custom (seen_values, type,
448 (GCompareFunc)strcmp) != NULL)
450 seen_values = g_slist_prepend (seen_values, (gchar*)type);
452 g_slist_free (seen_values);
457 parse_type (ParseContext *ctx, const gchar *type)
463 type = resolve_aliases (ctx, type);
464 str = g_strdup (type);
465 node = parse_type_internal (str, &rest);
472 start_glib_boxed (GMarkupParseContext *context,
473 const gchar *element_name,
474 const gchar **attribute_names,
475 const gchar **attribute_values,
479 if (strcmp (element_name, "glib:boxed") == 0 &&
480 ctx->state == STATE_NAMESPACE)
483 const gchar *typename;
484 const gchar *typeinit;
485 const gchar *deprecated;
487 name = find_attribute ("glib:name", attribute_names, attribute_values);
488 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
489 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
490 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
493 MISSING_ATTRIBUTE (context, error, element_name, "glib:name");
494 else if (typename == NULL)
495 MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
496 else if (typeinit == NULL)
497 MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
502 boxed = (GIrNodeBoxed *) g_ir_node_new (G_IR_NODE_BOXED);
504 ((GIrNode *)boxed)->name = g_strdup (name);
505 boxed->gtype_name = g_strdup (typename);
506 boxed->gtype_init = g_strdup (typeinit);
507 if (deprecated && strcmp (deprecated, "1") == 0)
508 boxed->deprecated = TRUE;
510 boxed->deprecated = FALSE;
512 ctx->current_node = (GIrNode *)boxed;
513 ctx->current_module->entries =
514 g_list_append (ctx->current_module->entries, boxed);
516 state_switch (ctx, STATE_BOXED);
526 start_function (GMarkupParseContext *context,
527 const gchar *element_name,
528 const gchar **attribute_names,
529 const gchar **attribute_values,
533 if ((ctx->state == STATE_NAMESPACE &&
534 (strcmp (element_name, "function") == 0 ||
535 strcmp (element_name, "callback") == 0)) ||
536 ((ctx->state == STATE_CLASS ||
537 ctx->state == STATE_INTERFACE ||
538 ctx->state == STATE_BOXED ||
539 ctx->state == STATE_UNION) &&
540 (strcmp (element_name, "method") == 0 ||
541 strcmp (element_name, "callback") == 0)) ||
542 ((ctx->state == STATE_CLASS ||
543 ctx->state == STATE_BOXED) &&
544 (strcmp (element_name, "constructor") == 0)) ||
545 (ctx->state == STATE_STRUCT && strcmp (element_name, "callback") == 0))
549 const gchar *deprecated;
552 name = find_attribute ("name", attribute_names, attribute_values);
553 symbol = find_attribute ("c:identifier", attribute_names, attribute_values);
554 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
555 type = find_attribute ("type", attribute_names, attribute_values);
558 MISSING_ATTRIBUTE (context, error, element_name, "name");
559 else if (strcmp (element_name, "callback") != 0 && symbol == NULL)
560 MISSING_ATTRIBUTE (context, error, element_name, "c:identifier");
563 GIrNodeFunction *function;
565 function = (GIrNodeFunction *) g_ir_node_new (G_IR_NODE_FUNCTION);
567 ((GIrNode *)function)->name = g_strdup (name);
568 function->symbol = g_strdup (symbol);
569 function->parameters = NULL;
570 if (deprecated && strcmp (deprecated, "1") == 0)
571 function->deprecated = TRUE;
573 function->deprecated = FALSE;
575 if (strcmp (element_name, "method") == 0 ||
576 strcmp (element_name, "constructor") == 0)
578 function->is_method = TRUE;
580 if (type && strcmp (type, "setter") == 0)
581 function->is_setter = TRUE;
582 else if (type && strcmp (type, "getter") == 0)
583 function->is_getter = TRUE;
585 if (strcmp (element_name, "constructor") == 0)
586 function->is_constructor = TRUE;
588 function->is_constructor = FALSE;
592 function->is_method = FALSE;
593 function->is_setter = FALSE;
594 function->is_getter = FALSE;
595 function->is_constructor = FALSE;
596 if (strcmp (element_name, "callback") == 0)
597 ((GIrNode *)function)->type = G_IR_NODE_CALLBACK;
600 if (ctx->current_node == NULL)
602 ctx->current_module->entries =
603 g_list_append (ctx->current_module->entries, function);
606 switch (ctx->current_node->type)
608 case G_IR_NODE_INTERFACE:
609 case G_IR_NODE_OBJECT:
611 GIrNodeInterface *iface;
613 iface = (GIrNodeInterface *)ctx->current_node;
614 iface->members = g_list_append (iface->members, function);
617 case G_IR_NODE_BOXED:
621 boxed = (GIrNodeBoxed *)ctx->current_node;
622 boxed->members = g_list_append (boxed->members, function);
625 case G_IR_NODE_STRUCT:
627 GIrNodeStruct *struct_;
629 struct_ = (GIrNodeStruct *)ctx->current_node;
630 struct_->members = g_list_append (struct_->members, function); }
632 case G_IR_NODE_UNION:
634 GIrNodeUnion *union_;
636 union_ = (GIrNodeUnion *)ctx->current_node;
637 union_->members = g_list_append (union_->members, function);
641 g_assert_not_reached ();
644 ctx->current_node = (GIrNode *)function;
645 state_switch (ctx, STATE_FUNCTION);
655 start_parameter (GMarkupParseContext *context,
656 const gchar *element_name,
657 const gchar **attribute_names,
658 const gchar **attribute_values,
663 const gchar *direction;
666 const gchar *optional;
668 const gchar *transfer;
671 if (!(strcmp (element_name, "parameter") == 0 &&
672 ctx->state == STATE_FUNCTION_PARAMETERS))
675 name = find_attribute ("name", attribute_names, attribute_values);
676 direction = find_attribute ("direction", attribute_names, attribute_values);
677 retval = find_attribute ("retval", attribute_names, attribute_values);
678 dipper = find_attribute ("dipper", attribute_names, attribute_values);
679 optional = find_attribute ("optional", attribute_names, attribute_values);
680 nullok = find_attribute ("null-ok", attribute_names, attribute_values);
681 transfer = find_attribute ("transfer", attribute_names, attribute_values);
686 param = (GIrNodeParam *)g_ir_node_new (G_IR_NODE_PARAM);
688 ctx->current_typed = (GIrNode*) param;
689 ctx->current_typed->name = g_strdup (name);
691 state_switch (ctx, STATE_FUNCTION_PARAMETER);
693 if (direction && strcmp (direction, "out") == 0)
698 else if (direction && strcmp (direction, "inout") == 0)
709 if (retval && strcmp (retval, "1") == 0)
710 param->retval = TRUE;
712 param->retval = FALSE;
714 if (dipper && strcmp (dipper, "1") == 0)
715 param->dipper = TRUE;
717 param->dipper = FALSE;
719 if (optional && strcmp (optional, "1") == 0)
720 param->optional = TRUE;
722 param->optional = FALSE;
724 if (nullok && strcmp (nullok, "1") == 0)
725 param->null_ok = TRUE;
727 param->null_ok = FALSE;
729 if (transfer && strcmp (transfer, "none") == 0)
731 param->transfer = FALSE;
732 param->shallow_transfer = FALSE;
734 else if (transfer && strcmp (transfer, "shallow") == 0)
736 param->transfer = FALSE;
737 param->shallow_transfer = TRUE;
741 param->transfer = TRUE;
742 param->shallow_transfer = FALSE;
745 ((GIrNode *)param)->name = g_strdup (name);
747 switch (ctx->current_node->type)
749 case G_IR_NODE_FUNCTION:
750 case G_IR_NODE_CALLBACK:
752 GIrNodeFunction *func;
754 func = (GIrNodeFunction *)ctx->current_node;
755 func->parameters = g_list_append (func->parameters, param);
758 case G_IR_NODE_SIGNAL:
760 GIrNodeSignal *signal;
762 signal = (GIrNodeSignal *)ctx->current_node;
763 signal->parameters = g_list_append (signal->parameters, param);
766 case G_IR_NODE_VFUNC:
770 vfunc = (GIrNodeVFunc *)ctx->current_node;
771 vfunc->parameters = g_list_append (vfunc->parameters, param);
775 g_assert_not_reached ();
782 start_field (GMarkupParseContext *context,
783 const gchar *element_name,
784 const gchar **attribute_names,
785 const gchar **attribute_values,
789 if (strcmp (element_name, "field") == 0 &&
790 (ctx->state == STATE_CLASS ||
791 ctx->state == STATE_BOXED ||
792 ctx->state == STATE_STRUCT ||
793 ctx->state == STATE_UNION ||
794 ctx->state == STATE_INTERFACE))
797 const gchar *readable;
798 const gchar *writable;
803 name = find_attribute ("name", attribute_names, attribute_values);
804 readable = find_attribute ("readable", attribute_names, attribute_values);
805 writable = find_attribute ("writable", attribute_names, attribute_values);
806 bits = find_attribute ("bits", attribute_names, attribute_values);
807 branch = find_attribute ("branch", attribute_names, attribute_values);
808 offset = find_attribute ("offset", attribute_names, attribute_values);
811 MISSING_ATTRIBUTE (context, error, element_name, "name");
816 field = (GIrNodeField *)g_ir_node_new (G_IR_NODE_FIELD);
817 ctx->current_typed = (GIrNode*) field;
818 ((GIrNode *)field)->name = g_strdup (name);
819 if (readable && strcmp (readable, "1") == 0)
820 field->readable = TRUE;
822 field->readable = FALSE;
824 if (writable && strcmp (writable, "1") == 0)
825 field->writable = TRUE;
827 field->writable = FALSE;
830 field->bits = atoi (bits);
835 field->offset = atoi (offset);
839 switch (ctx->current_node->type)
841 case G_IR_NODE_OBJECT:
843 GIrNodeInterface *iface;
845 iface = (GIrNodeInterface *)ctx->current_node;
846 iface->members = g_list_append (iface->members, field);
847 state_switch (ctx, STATE_CLASS_FIELD);
850 case G_IR_NODE_INTERFACE:
852 GIrNodeInterface *iface;
854 iface = (GIrNodeInterface *)ctx->current_node;
855 iface->members = g_list_append (iface->members, field);
856 state_switch (ctx, STATE_INTERFACE_FIELD);
859 case G_IR_NODE_BOXED:
863 boxed = (GIrNodeBoxed *)ctx->current_node;
864 boxed->members = g_list_append (boxed->members, field);
865 state_switch (ctx, STATE_BOXED_FIELD);
868 case G_IR_NODE_STRUCT:
870 GIrNodeStruct *struct_;
872 struct_ = (GIrNodeStruct *)ctx->current_node;
873 struct_->members = g_list_append (struct_->members, field);
874 state_switch (ctx, STATE_STRUCT_FIELD);
877 case G_IR_NODE_UNION:
879 GIrNodeUnion *union_;
881 union_ = (GIrNodeUnion *)ctx->current_node;
882 union_->members = g_list_append (union_->members, field);
885 GIrNodeConstant *constant;
887 constant = (GIrNodeConstant *) g_ir_node_new (G_IR_NODE_CONSTANT);
888 ((GIrNode *)constant)->name = g_strdup (name);
889 constant->value = g_strdup (branch);
890 constant->type = union_->discriminator_type;
891 constant->deprecated = FALSE;
893 union_->discriminators = g_list_append (union_->discriminators, constant);
895 state_switch (ctx, STATE_UNION_FIELD);
899 g_assert_not_reached ();
909 start_alias (GMarkupParseContext *context,
910 const gchar *element_name,
911 const gchar **attribute_names,
912 const gchar **attribute_values,
920 name = find_attribute ("name", attribute_names, attribute_values);
922 MISSING_ATTRIBUTE (context, error, element_name, "name");
926 target = find_attribute ("target", attribute_names, attribute_values);
928 MISSING_ATTRIBUTE (context, error, element_name, "target");
932 g_hash_table_insert (ctx->aliases, g_strdup (name), g_strdup (target));
937 start_enum (GMarkupParseContext *context,
938 const gchar *element_name,
939 const gchar **attribute_names,
940 const gchar **attribute_values,
944 if ((strcmp (element_name, "enumeration") == 0 && ctx->state == STATE_NAMESPACE) ||
945 (strcmp (element_name, "bitfield") == 0 && ctx->state == STATE_NAMESPACE))
948 const gchar *typename;
949 const gchar *typeinit;
950 const gchar *deprecated;
952 name = find_attribute ("name", attribute_names, attribute_values);
953 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
954 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
955 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
958 MISSING_ATTRIBUTE (context, error, element_name, "name");
963 if (strcmp (element_name, "enumeration") == 0)
964 enum_ = (GIrNodeEnum *) g_ir_node_new (G_IR_NODE_ENUM);
966 enum_ = (GIrNodeEnum *) g_ir_node_new (G_IR_NODE_FLAGS);
967 ((GIrNode *)enum_)->name = g_strdup (name);
968 enum_->gtype_name = g_strdup (typename);
969 enum_->gtype_init = g_strdup (typeinit);
970 if (deprecated && strcmp (deprecated, "1") == 0)
971 enum_->deprecated = TRUE;
973 enum_->deprecated = FALSE;
975 ctx->current_node = (GIrNode *) enum_;
976 ctx->current_module->entries =
977 g_list_append (ctx->current_module->entries, enum_);
979 state_switch (ctx, STATE_ENUM);
988 start_property (GMarkupParseContext *context,
989 const gchar *element_name,
990 const gchar **attribute_names,
991 const gchar **attribute_values,
995 if (strcmp (element_name, "property") == 0 &&
996 (ctx->state == STATE_CLASS ||
997 ctx->state == STATE_INTERFACE))
1000 const gchar *readable;
1001 const gchar *writable;
1002 const gchar *construct;
1003 const gchar *construct_only;
1005 name = find_attribute ("name", attribute_names, attribute_values);
1006 readable = find_attribute ("readable", attribute_names, attribute_values);
1007 writable = find_attribute ("writable", attribute_names, attribute_values);
1008 construct = find_attribute ("construct", attribute_names, attribute_values);
1009 construct_only = find_attribute ("construct-only", attribute_names, attribute_values);
1012 MISSING_ATTRIBUTE (context, error, element_name, "name");
1015 GIrNodeProperty *property;
1016 GIrNodeInterface *iface;
1018 property = (GIrNodeProperty *) g_ir_node_new (G_IR_NODE_PROPERTY);
1019 ctx->current_typed = (GIrNode*) property;
1021 ((GIrNode *)property)->name = g_strdup (name);
1023 if (readable && strcmp (readable, "1") == 0)
1024 property->readable = TRUE;
1026 property->readable = FALSE;
1027 if (writable && strcmp (writable, "1") == 0)
1028 property->writable = TRUE;
1030 property->writable = FALSE;
1031 if (construct && strcmp (construct, "1") == 0)
1032 property->construct = TRUE;
1034 property->construct = FALSE;
1035 if (construct_only && strcmp (construct_only, "1") == 0)
1036 property->construct_only = TRUE;
1038 property->construct_only = FALSE;
1040 iface = (GIrNodeInterface *)ctx->current_node;
1041 iface->members = g_list_append (iface->members, property);
1043 if (ctx->state == STATE_CLASS)
1044 state_switch (ctx, STATE_CLASS_PROPERTY);
1045 else if (ctx->state == STATE_INTERFACE)
1046 state_switch (ctx, STATE_INTERFACE_PROPERTY);
1048 g_assert_not_reached ();
1057 parse_value (const gchar *str)
1061 /* FIXME just a quick hack */
1062 shift_op = strstr (str, "<<");
1068 base = strtol (str, NULL, 10);
1069 shift = strtol (shift_op + 3, NULL, 10);
1071 return base << shift;
1074 return strtol (str, NULL, 10);
1080 start_member (GMarkupParseContext *context,
1081 const gchar *element_name,
1082 const gchar **attribute_names,
1083 const gchar **attribute_values,
1087 if (strcmp (element_name, "member") == 0 &&
1088 ctx->state == STATE_ENUM)
1092 const gchar *deprecated;
1094 name = find_attribute ("name", attribute_names, attribute_values);
1095 value = find_attribute ("value", attribute_names, attribute_values);
1096 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1099 MISSING_ATTRIBUTE (context, error, element_name, "name");
1103 GIrNodeValue *value_;
1105 value_ = (GIrNodeValue *) g_ir_node_new (G_IR_NODE_VALUE);
1107 ((GIrNode *)value_)->name = g_strdup (name);
1109 value_->value = parse_value (value);
1111 if (deprecated && strcmp (deprecated, "1") == 0)
1112 value_->deprecated = TRUE;
1114 value_->deprecated = FALSE;
1116 enum_ = (GIrNodeEnum *)ctx->current_node;
1117 enum_->values = g_list_append (enum_->values, value_);
1126 start_constant (GMarkupParseContext *context,
1127 const gchar *element_name,
1128 const gchar **attribute_names,
1129 const gchar **attribute_values,
1133 if (strcmp (element_name, "constant") == 0 &&
1134 (ctx->state == STATE_NAMESPACE ||
1135 ctx->state == STATE_CLASS ||
1136 ctx->state == STATE_INTERFACE))
1140 const gchar *deprecated;
1142 name = find_attribute ("name", attribute_names, attribute_values);
1143 value = find_attribute ("value", attribute_names, attribute_values);
1144 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1147 MISSING_ATTRIBUTE (context, error, element_name, "name");
1148 else if (value == NULL)
1149 MISSING_ATTRIBUTE (context, error, element_name, "value");
1152 GIrNodeConstant *constant;
1154 constant = (GIrNodeConstant *) g_ir_node_new (G_IR_NODE_CONSTANT);
1156 ((GIrNode *)constant)->name = g_strdup (name);
1157 constant->value = g_strdup (value);
1159 ctx->current_typed = (GIrNode*) constant;
1161 if (deprecated && strcmp (deprecated, "1") == 0)
1162 constant->deprecated = TRUE;
1164 constant->deprecated = FALSE;
1166 if (ctx->state == STATE_NAMESPACE)
1168 ctx->current_node = (GIrNode *) constant;
1169 ctx->current_module->entries =
1170 g_list_append (ctx->current_module->entries, constant);
1174 GIrNodeInterface *iface;
1176 iface = (GIrNodeInterface *)ctx->current_node;
1177 iface->members = g_list_append (iface->members, constant);
1182 case STATE_NAMESPACE:
1183 state_switch (ctx, STATE_NAMESPACE_CONSTANT);
1186 state_switch (ctx, STATE_CLASS_CONSTANT);
1188 case STATE_INTERFACE:
1189 state_switch (ctx, STATE_INTERFACE_CONSTANT);
1192 g_assert_not_reached ();
1203 start_errordomain (GMarkupParseContext *context,
1204 const gchar *element_name,
1205 const gchar **attribute_names,
1206 const gchar **attribute_values,
1210 if (strcmp (element_name, "errordomain") == 0 &&
1211 ctx->state == STATE_NAMESPACE)
1214 const gchar *getquark;
1216 const gchar *deprecated;
1218 name = find_attribute ("name", attribute_names, attribute_values);
1219 getquark = find_attribute ("get-quark", attribute_names, attribute_values);
1220 codes = find_attribute ("codes", attribute_names, attribute_values);
1221 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1224 MISSING_ATTRIBUTE (context, error, element_name, "name");
1225 else if (getquark == NULL)
1226 MISSING_ATTRIBUTE (context, error, element_name, "getquark");
1227 else if (codes == NULL)
1228 MISSING_ATTRIBUTE (context, error, element_name, "codes");
1231 GIrNodeErrorDomain *domain;
1233 domain = (GIrNodeErrorDomain *) g_ir_node_new (G_IR_NODE_ERROR_DOMAIN);
1235 ((GIrNode *)domain)->name = g_strdup (name);
1236 domain->getquark = g_strdup (getquark);
1237 domain->codes = g_strdup (codes);
1239 if (deprecated && strcmp (deprecated, "1") == 0)
1240 domain->deprecated = TRUE;
1242 domain->deprecated = FALSE;
1244 ctx->current_node = (GIrNode *) domain;
1245 ctx->current_module->entries =
1246 g_list_append (ctx->current_module->entries, domain);
1248 state_switch (ctx, STATE_ERRORDOMAIN);
1257 start_interface (GMarkupParseContext *context,
1258 const gchar *element_name,
1259 const gchar **attribute_names,
1260 const gchar **attribute_values,
1264 if (strcmp (element_name, "interface") == 0 &&
1265 ctx->state == STATE_NAMESPACE)
1268 const gchar *typename;
1269 const gchar *typeinit;
1270 const gchar *deprecated;
1272 name = find_attribute ("name", attribute_names, attribute_values);
1273 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
1274 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
1275 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1278 MISSING_ATTRIBUTE (context, error, element_name, "name");
1279 else if (typename == NULL)
1280 MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
1281 else if (typeinit == NULL)
1282 MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
1285 GIrNodeInterface *iface;
1287 iface = (GIrNodeInterface *) g_ir_node_new (G_IR_NODE_INTERFACE);
1288 ((GIrNode *)iface)->name = g_strdup (name);
1289 iface->gtype_name = g_strdup (typename);
1290 iface->gtype_init = g_strdup (typeinit);
1291 if (deprecated && strcmp (deprecated, "1") == 0)
1292 iface->deprecated = TRUE;
1294 iface->deprecated = FALSE;
1296 ctx->current_node = (GIrNode *) iface;
1297 ctx->current_module->entries =
1298 g_list_append (ctx->current_module->entries, iface);
1300 state_switch (ctx, STATE_INTERFACE);
1310 start_class (GMarkupParseContext *context,
1311 const gchar *element_name,
1312 const gchar **attribute_names,
1313 const gchar **attribute_values,
1317 if (strcmp (element_name, "class") == 0 &&
1318 ctx->state == STATE_NAMESPACE)
1321 const gchar *parent;
1322 const gchar *typename;
1323 const gchar *typeinit;
1324 const gchar *deprecated;
1326 name = find_attribute ("name", attribute_names, attribute_values);
1327 parent = find_attribute ("parent", attribute_names, attribute_values);
1328 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
1329 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
1330 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1333 MISSING_ATTRIBUTE (context, error, element_name, "name");
1334 else if (typename == NULL)
1335 MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
1336 else if (typeinit == NULL && strcmp (typename, "GObject"))
1337 MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
1340 GIrNodeInterface *iface;
1342 iface = (GIrNodeInterface *) g_ir_node_new (G_IR_NODE_OBJECT);
1343 ((GIrNode *)iface)->name = g_strdup (name);
1344 iface->gtype_name = g_strdup (typename);
1345 iface->gtype_init = g_strdup (typeinit);
1346 iface->parent = g_strdup (parent);
1347 if (deprecated && strcmp (deprecated, "1") == 0)
1348 iface->deprecated = TRUE;
1350 iface->deprecated = FALSE;
1352 ctx->current_node = (GIrNode *) iface;
1353 ctx->current_module->entries =
1354 g_list_append (ctx->current_module->entries, iface);
1356 state_switch (ctx, STATE_CLASS);
1365 start_type (GMarkupParseContext *context,
1366 const gchar *element_name,
1367 const gchar **attribute_names,
1368 const gchar **attribute_values,
1374 if (strcmp (element_name, "type") != 0 ||
1375 !(ctx->state == STATE_FUNCTION_PARAMETER ||
1376 ctx->state == STATE_FUNCTION_RETURN ||
1377 ctx->state == STATE_STRUCT_FIELD ||
1378 ctx->state == STATE_UNION_FIELD ||
1379 ctx->state == STATE_CLASS_PROPERTY ||
1380 ctx->state == STATE_CLASS_FIELD ||
1381 ctx->state == STATE_INTERFACE_FIELD ||
1382 ctx->state == STATE_INTERFACE_PROPERTY ||
1383 ctx->state == STATE_BOXED_FIELD ||
1384 ctx->state == STATE_NAMESPACE_CONSTANT ||
1385 ctx->state == STATE_CLASS_CONSTANT ||
1386 ctx->state == STATE_INTERFACE_CONSTANT
1390 if (!ctx->current_typed)
1394 G_MARKUP_ERROR_INVALID_CONTENT,
1395 "The element <type> is invalid here");
1399 name = find_attribute ("name", attribute_names, attribute_values);
1402 MISSING_ATTRIBUTE (context, error, element_name, "name");
1404 switch (ctx->current_typed->type)
1406 case G_IR_NODE_PARAM:
1408 GIrNodeParam *param = (GIrNodeParam *)ctx->current_typed;
1409 param->type = parse_type (ctx, name);
1412 case G_IR_NODE_FIELD:
1414 GIrNodeField *field = (GIrNodeField *)ctx->current_typed;
1415 field->type = parse_type (ctx, name);
1418 case G_IR_NODE_PROPERTY:
1420 GIrNodeProperty *property = (GIrNodeProperty *) ctx->current_typed;
1421 property->type = parse_type (ctx, name);
1424 case G_IR_NODE_CONSTANT:
1426 GIrNodeConstant *constant = (GIrNodeConstant *)ctx->current_typed;
1427 constant->type = parse_type (ctx, name);
1431 g_printerr("current node is %d\n", ctx->current_node->type);
1432 g_assert_not_reached ();
1435 ctx->current_typed = NULL;
1440 start_return_value (GMarkupParseContext *context,
1441 const gchar *element_name,
1442 const gchar **attribute_names,
1443 const gchar **attribute_values,
1447 if (strcmp (element_name, "return-value") == 0 &&
1448 ctx->state == STATE_FUNCTION)
1450 GIrNodeParam *param;
1452 param = (GIrNodeParam *)g_ir_node_new (G_IR_NODE_PARAM);
1455 param->retval = TRUE;
1457 ctx->current_typed = (GIrNode*) param;
1459 state_switch (ctx, STATE_FUNCTION_RETURN);
1461 switch (ctx->current_node->type)
1463 case G_IR_NODE_FUNCTION:
1464 case G_IR_NODE_CALLBACK:
1466 GIrNodeFunction *func = (GIrNodeFunction *)ctx->current_node;
1467 func->result = param;
1470 case G_IR_NODE_SIGNAL:
1472 GIrNodeSignal *signal = (GIrNodeSignal *)ctx->current_node;
1473 signal->result = param;
1476 case G_IR_NODE_VFUNC:
1478 GIrNodeVFunc *vfunc = (GIrNodeVFunc *)ctx->current_node;
1479 vfunc->result = param;
1483 g_assert_not_reached ();
1493 start_glib_signal (GMarkupParseContext *context,
1494 const gchar *element_name,
1495 const gchar **attribute_names,
1496 const gchar **attribute_values,
1500 if (strcmp (element_name, "glib:signal") == 0 &&
1501 (ctx->state == STATE_CLASS ||
1502 ctx->state == STATE_INTERFACE))
1506 const gchar *no_recurse;
1507 const gchar *detailed;
1508 const gchar *action;
1509 const gchar *no_hooks;
1510 const gchar *has_class_closure;
1512 name = find_attribute ("name", attribute_names, attribute_values);
1513 when = find_attribute ("when", attribute_names, attribute_values);
1514 no_recurse = find_attribute ("no-recurse", attribute_names, attribute_values);
1515 detailed = find_attribute ("detailed", attribute_names, attribute_values);
1516 action = find_attribute ("action", attribute_names, attribute_values);
1517 no_hooks = find_attribute ("no-hooks", attribute_names, attribute_values);
1518 has_class_closure = find_attribute ("has-class-closure", attribute_names, attribute_values);
1521 MISSING_ATTRIBUTE (context, error, element_name, "name");
1524 GIrNodeInterface *iface;
1525 GIrNodeSignal *signal;
1527 signal = (GIrNodeSignal *)g_ir_node_new (G_IR_NODE_SIGNAL);
1529 ((GIrNode *)signal)->name = g_strdup (name);
1531 signal->run_first = FALSE;
1532 signal->run_last = FALSE;
1533 signal->run_cleanup = FALSE;
1534 if (when == NULL || strcmp (when, "LAST") == 0)
1535 signal->run_last = TRUE;
1536 else if (strcmp (when, "FIRST") == 0)
1537 signal->run_first = TRUE;
1539 signal->run_cleanup = TRUE;
1541 if (no_recurse && strcmp (no_recurse, "1") == 0)
1542 signal->no_recurse = TRUE;
1544 signal->no_recurse = FALSE;
1545 if (detailed && strcmp (detailed, "1") == 0)
1546 signal->detailed = TRUE;
1548 signal->detailed = FALSE;
1549 if (action && strcmp (action, "1") == 0)
1550 signal->action = TRUE;
1552 signal->action = FALSE;
1553 if (no_hooks && strcmp (no_hooks, "1") == 0)
1554 signal->no_hooks = TRUE;
1556 signal->no_hooks = FALSE;
1557 if (has_class_closure && strcmp (has_class_closure, "1") == 0)
1558 signal->has_class_closure = TRUE;
1560 signal->has_class_closure = FALSE;
1562 iface = (GIrNodeInterface *)ctx->current_node;
1563 iface->members = g_list_append (iface->members, signal);
1565 ctx->current_node = (GIrNode *)signal;
1566 state_switch (ctx, STATE_FUNCTION);
1575 start_vfunc (GMarkupParseContext *context,
1576 const gchar *element_name,
1577 const gchar **attribute_names,
1578 const gchar **attribute_values,
1582 if (strcmp (element_name, "vfunc") == 0 &&
1583 (ctx->state == STATE_CLASS ||
1584 ctx->state == STATE_INTERFACE))
1587 const gchar *must_chain_up;
1588 const gchar *override;
1589 const gchar *is_class_closure;
1590 const gchar *offset;
1592 name = find_attribute ("name", attribute_names, attribute_values);
1593 must_chain_up = find_attribute ("must-chain-up", attribute_names, attribute_values);
1594 override = find_attribute ("override", attribute_names, attribute_values);
1595 is_class_closure = find_attribute ("is-class-closure", attribute_names, attribute_values);
1596 offset = find_attribute ("offset", attribute_names, attribute_values);
1599 MISSING_ATTRIBUTE (context, error, element_name, "name");
1602 GIrNodeInterface *iface;
1603 GIrNodeVFunc *vfunc;
1605 vfunc = (GIrNodeVFunc *)g_ir_node_new (G_IR_NODE_VFUNC);
1607 ((GIrNode *)vfunc)->name = g_strdup (name);
1609 if (must_chain_up && strcmp (must_chain_up, "1") == 0)
1610 vfunc->must_chain_up = TRUE;
1612 vfunc->must_chain_up = FALSE;
1614 if (override && strcmp (override, "always") == 0)
1616 vfunc->must_be_implemented = TRUE;
1617 vfunc->must_not_be_implemented = FALSE;
1619 else if (override && strcmp (override, "never") == 0)
1621 vfunc->must_be_implemented = FALSE;
1622 vfunc->must_not_be_implemented = TRUE;
1626 vfunc->must_be_implemented = FALSE;
1627 vfunc->must_not_be_implemented = FALSE;
1630 if (is_class_closure && strcmp (is_class_closure, "1") == 0)
1631 vfunc->is_class_closure = TRUE;
1633 vfunc->is_class_closure = FALSE;
1636 vfunc->offset = atoi (offset);
1640 iface = (GIrNodeInterface *)ctx->current_node;
1641 iface->members = g_list_append (iface->members, vfunc);
1643 ctx->current_node = (GIrNode *)vfunc;
1644 state_switch (ctx, STATE_FUNCTION);
1654 start_struct (GMarkupParseContext *context,
1655 const gchar *element_name,
1656 const gchar **attribute_names,
1657 const gchar **attribute_values,
1661 if (strcmp (element_name, "record") == 0 &&
1662 ctx->state == STATE_NAMESPACE)
1665 const gchar *deprecated;
1667 name = find_attribute ("name", attribute_names, attribute_values);
1668 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1671 MISSING_ATTRIBUTE (context, error, element_name, "name");
1674 GIrNodeStruct *struct_;
1676 struct_ = (GIrNodeStruct *) g_ir_node_new (G_IR_NODE_STRUCT);
1678 ((GIrNode *)struct_)->name = g_strdup (name);
1679 if (deprecated && strcmp (deprecated, "1") == 0)
1680 struct_->deprecated = TRUE;
1682 struct_->deprecated = FALSE;
1684 ctx->current_node = (GIrNode *)struct_;
1685 ctx->current_module->entries =
1686 g_list_append (ctx->current_module->entries, struct_);
1688 state_switch (ctx, STATE_STRUCT);
1697 start_union (GMarkupParseContext *context,
1698 const gchar *element_name,
1699 const gchar **attribute_names,
1700 const gchar **attribute_values,
1704 if (strcmp (element_name, "union") == 0 &&
1705 ctx->state == STATE_NAMESPACE)
1708 const gchar *deprecated;
1709 const gchar *typename;
1710 const gchar *typeinit;
1712 name = find_attribute ("name", attribute_names, attribute_values);
1713 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1714 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
1715 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
1718 MISSING_ATTRIBUTE (context, error, element_name, "name");
1721 GIrNodeUnion *union_;
1723 union_ = (GIrNodeUnion *) g_ir_node_new (G_IR_NODE_UNION);
1725 ((GIrNode *)union_)->name = g_strdup (name);
1726 union_->gtype_name = g_strdup (typename);
1727 union_->gtype_init = g_strdup (typeinit);
1728 if (deprecated && strcmp (deprecated, "1") == 0)
1729 union_->deprecated = TRUE;
1731 union_->deprecated = FALSE;
1733 ctx->current_node = (GIrNode *)union_;
1734 ctx->current_module->entries =
1735 g_list_append (ctx->current_module->entries, union_);
1737 state_switch (ctx, STATE_UNION);
1745 start_discriminator (GMarkupParseContext *context,
1746 const gchar *element_name,
1747 const gchar **attribute_names,
1748 const gchar **attribute_values,
1752 if (strcmp (element_name, "discriminator") == 0 &&
1753 ctx->state == STATE_UNION)
1756 const gchar *offset;
1758 type = find_attribute ("type", attribute_names, attribute_values);
1759 offset = find_attribute ("offset", attribute_names, attribute_values);
1761 MISSING_ATTRIBUTE (context, error, element_name, "type");
1762 else if (offset == NULL)
1763 MISSING_ATTRIBUTE (context, error, element_name, "offset");
1765 ((GIrNodeUnion *)ctx->current_node)->discriminator_type
1766 = parse_type (ctx, type);
1767 ((GIrNodeUnion *)ctx->current_node)->discriminator_offset
1777 extern GLogLevelFlags logged_levels;
1780 start_element_handler (GMarkupParseContext *context,
1781 const gchar *element_name,
1782 const gchar **attribute_names,
1783 const gchar **attribute_values,
1787 ParseContext *ctx = user_data;
1788 gint line_number, char_number;
1790 if (logged_levels & G_LOG_LEVEL_DEBUG)
1792 GString *tags = g_string_new ("");
1794 for (i = 0; attribute_names[i]; i++)
1795 g_string_append_printf (tags, "%s=\"%s\" ",
1797 attribute_values[i]);
1801 g_string_insert_c (tags, 0, ' ');
1802 g_string_truncate (tags, tags->len - 1);
1804 g_debug ("<%s%s>", element_name, tags->str);
1805 g_string_free (tags, TRUE);
1808 switch (element_name[0])
1811 if (ctx->state == STATE_NAMESPACE && strcmp (element_name, "alias") == 0)
1813 state_switch (ctx, STATE_ALIAS);
1818 if (start_enum (context, element_name,
1819 attribute_names, attribute_values,
1824 if (start_function (context, element_name,
1825 attribute_names, attribute_values,
1828 else if (start_constant (context, element_name,
1829 attribute_names, attribute_values,
1832 else if (start_class (context, element_name,
1833 attribute_names, attribute_values,
1836 else if (strcmp (element_name, "class") == 0 &&
1837 ctx->state == STATE_REQUIRES)
1841 name = find_attribute ("name", attribute_names, attribute_values);
1844 MISSING_ATTRIBUTE (context, error, element_name, "name");
1847 GIrNodeInterface *iface;
1849 iface = (GIrNodeInterface *)ctx->current_node;
1850 iface ->prerequisites = g_list_append (iface->prerequisites, g_strdup (name));
1858 if (start_discriminator (context, element_name,
1859 attribute_names, attribute_values,
1865 if (start_enum (context, element_name,
1866 attribute_names, attribute_values,
1869 else if (start_errordomain (context, element_name,
1870 attribute_names, attribute_values,
1876 if (start_function (context, element_name,
1877 attribute_names, attribute_values,
1880 else if (start_field (context, element_name,
1881 attribute_names, attribute_values,
1887 if (start_glib_boxed (context, element_name,
1888 attribute_names, attribute_values,
1891 else if (start_glib_signal (context, element_name,
1892 attribute_names, attribute_values,
1895 else if (start_glib_boxed (context, element_name,
1896 attribute_names, attribute_values,
1902 if (start_interface (context, element_name,
1903 attribute_names, attribute_values,
1906 if (strcmp (element_name, "implements") == 0 &&
1907 ctx->state == STATE_CLASS)
1909 state_switch (ctx, STATE_IMPLEMENTS);
1913 else if (strcmp (element_name, "interface") == 0 &&
1914 ctx->state == STATE_IMPLEMENTS)
1918 name = find_attribute ("name", attribute_names, attribute_values);
1921 MISSING_ATTRIBUTE (context, error, element_name, "name");
1924 GIrNodeInterface *iface;
1926 iface = (GIrNodeInterface *)ctx->current_node;
1927 iface ->interfaces = g_list_append (iface->interfaces, g_strdup (name));
1932 else if (strcmp (element_name, "interface") == 0 &&
1933 ctx->state == STATE_REQUIRES)
1937 name = find_attribute ("name", attribute_names, attribute_values);
1940 MISSING_ATTRIBUTE (context, error, element_name, "name");
1943 GIrNodeInterface *iface;
1945 iface = (GIrNodeInterface *)ctx->current_node;
1946 iface ->prerequisites = g_list_append (iface->prerequisites, g_strdup (name));
1954 if (start_function (context, element_name,
1955 attribute_names, attribute_values,
1958 else if (start_member (context, element_name,
1959 attribute_names, attribute_values,
1965 if (strcmp (element_name, "namespace") == 0 && ctx->state == STATE_REPOSITORY)
1967 const gchar *name, *shared_library;
1969 name = find_attribute ("name", attribute_names, attribute_values);
1970 shared_library = find_attribute ("shared-library", attribute_names, attribute_values);
1973 MISSING_ATTRIBUTE (context, error, element_name, "name");
1976 ctx->current_module = g_ir_module_new (name, shared_library);
1977 ctx->modules = g_list_append (ctx->modules, ctx->current_module);
1979 state_switch (ctx, STATE_NAMESPACE);
1987 if (start_property (context, element_name,
1988 attribute_names, attribute_values,
1991 else if (strcmp (element_name, "parameters") == 0 &&
1992 ctx->state == STATE_FUNCTION)
1994 state_switch (ctx, STATE_FUNCTION_PARAMETERS);
1998 else if (start_parameter (context, element_name,
1999 attribute_names, attribute_values,
2006 if (strcmp (element_name, "repository") == 0 && ctx->state == STATE_START)
2008 const gchar *version;
2010 version = find_attribute ("version", attribute_names, attribute_values);
2012 if (version == NULL)
2013 MISSING_ATTRIBUTE (context, error, element_name, "version");
2014 else if (strcmp (version, "1.0") != 0)
2017 G_MARKUP_ERROR_INVALID_CONTENT,
2018 "Unsupported version '%s'",
2021 state_switch (ctx, STATE_REPOSITORY);
2025 else if (start_return_value (context, element_name,
2026 attribute_names, attribute_values,
2029 else if (strcmp (element_name, "requires") == 0 &&
2030 ctx->state == STATE_INTERFACE)
2032 state_switch (ctx, STATE_REQUIRES);
2036 else if (start_struct (context, element_name,
2037 attribute_names, attribute_values,
2043 if (start_union (context, element_name,
2044 attribute_names, attribute_values,
2050 if (start_type (context, element_name,
2051 attribute_names, attribute_values,
2057 if (start_vfunc (context, element_name,
2058 attribute_names, attribute_values,
2064 g_markup_parse_context_get_position (context, &line_number, &char_number);
2068 G_MARKUP_ERROR_UNKNOWN_ELEMENT,
2069 "Unexpected start tag '%s' on line %d char %d; current state=%d",
2071 line_number, char_number, ctx->state);
2076 g_markup_parse_context_get_position (context, &line_number, &char_number);
2078 fprintf (stderr, "Error at line %d, character %d: %s\n", line_number, char_number, (*error)->message);
2079 backtrace_stderr ();
2084 require_one_of_end_elements (GMarkupParseContext *context,
2086 const char *actual_name,
2091 int line_number, char_number;
2092 const char *expected;
2093 gboolean matched = FALSE;
2095 va_start (args, error);
2097 while ((expected = va_arg (args, const char*)) != NULL)
2099 if (strcmp (expected, actual_name) == 0)
2111 g_markup_parse_context_get_position (context, &line_number, &char_number);
2114 G_MARKUP_ERROR_INVALID_CONTENT,
2115 "Unexpected end tag '%s' on line %d char %d; current state=%d",
2117 line_number, char_number, ctx->state);
2123 require_end_element (GMarkupParseContext *context,
2125 const char *expected_name,
2126 const char *actual_name,
2129 return require_one_of_end_elements (context, ctx, actual_name, error, expected_name, NULL);
2133 end_element_handler (GMarkupParseContext *context,
2134 const gchar *element_name,
2138 ParseContext *ctx = user_data;
2140 g_debug ("</%s>", element_name);
2146 /* no need to GError here, GMarkup already catches this */
2149 case STATE_REPOSITORY:
2150 state_switch (ctx, STATE_END);
2153 case STATE_NAMESPACE:
2154 if (require_end_element (context, ctx, "namespace", element_name, error))
2156 ctx->current_module = NULL;
2157 state_switch (ctx, STATE_REPOSITORY);
2162 if (require_end_element (context, ctx, "alias", element_name, error))
2164 state_switch (ctx, STATE_NAMESPACE);
2168 case STATE_FUNCTION_RETURN:
2169 if (strcmp ("type", element_name) == 0)
2171 if (require_end_element (context, ctx, "return-value", element_name, error))
2173 state_switch (ctx, STATE_FUNCTION);
2177 case STATE_FUNCTION_PARAMETERS:
2178 if (require_end_element (context, ctx, "parameters", element_name, error))
2180 state_switch (ctx, STATE_FUNCTION);
2184 case STATE_FUNCTION_PARAMETER:
2185 if (strcmp ("type", element_name) == 0)
2187 if (require_end_element (context, ctx, "parameter", element_name, error))
2189 state_switch (ctx, STATE_FUNCTION_PARAMETERS);
2193 case STATE_FUNCTION:
2194 if (ctx->current_node == g_list_last (ctx->current_module->entries)->data)
2196 ctx->current_node = NULL;
2197 state_switch (ctx, STATE_NAMESPACE);
2201 ctx->current_node = g_list_last (ctx->current_module->entries)->data;
2202 if (ctx->current_node->type == G_IR_NODE_INTERFACE)
2203 state_switch (ctx, STATE_INTERFACE);
2204 else if (ctx->current_node->type == G_IR_NODE_OBJECT)
2205 state_switch (ctx, STATE_CLASS);
2206 else if (ctx->current_node->type == G_IR_NODE_BOXED)
2207 state_switch (ctx, STATE_BOXED);
2208 else if (ctx->current_node->type == G_IR_NODE_STRUCT)
2209 state_switch (ctx, STATE_STRUCT);
2210 else if (ctx->current_node->type == G_IR_NODE_UNION)
2211 state_switch (ctx, STATE_UNION);
2214 int line_number, char_number;
2215 g_markup_parse_context_get_position (context, &line_number, &char_number);
2218 G_MARKUP_ERROR_INVALID_CONTENT,
2219 "Unexpected end tag '%s' on line %d char %d",
2221 line_number, char_number);
2226 case STATE_CLASS_FIELD:
2227 if (strcmp ("type", element_name) == 0)
2229 if (require_end_element (context, ctx, "field", element_name, error))
2231 state_switch (ctx, STATE_CLASS);
2235 case STATE_CLASS_PROPERTY:
2236 if (strcmp ("type", element_name) == 0)
2238 if (require_end_element (context, ctx, "property", element_name, error))
2240 state_switch (ctx, STATE_CLASS);
2245 if (require_end_element (context, ctx, "class", element_name, error))
2247 ctx->current_node = NULL;
2248 state_switch (ctx, STATE_NAMESPACE);
2252 case STATE_ERRORDOMAIN:
2253 if (require_end_element (context, ctx, "errordomain", element_name, error))
2255 ctx->current_node = NULL;
2256 state_switch (ctx, STATE_NAMESPACE);
2260 case STATE_INTERFACE_PROPERTY:
2261 if (strcmp ("type", element_name) == 0)
2263 if (require_end_element (context, ctx, "property", element_name, error))
2265 state_switch (ctx, STATE_INTERFACE);
2269 case STATE_INTERFACE_FIELD:
2270 if (strcmp ("type", element_name) == 0)
2272 if (require_end_element (context, ctx, "field", element_name, error))
2274 state_switch (ctx, STATE_INTERFACE);
2278 case STATE_INTERFACE:
2279 if (require_end_element (context, ctx, "interface", element_name, error))
2281 ctx->current_node = NULL;
2282 state_switch (ctx, STATE_NAMESPACE);
2287 if (strcmp ("member", element_name) == 0)
2289 else if (require_one_of_end_elements (context, ctx,
2290 element_name, error, "enumeration",
2293 ctx->current_node = NULL;
2294 state_switch (ctx, STATE_NAMESPACE);
2299 if (require_end_element (context, ctx, "glib:boxed", element_name, error))
2301 ctx->current_node = NULL;
2302 state_switch (ctx, STATE_NAMESPACE);
2306 case STATE_BOXED_FIELD:
2307 if (strcmp ("type", element_name) == 0)
2309 if (require_end_element (context, ctx, "field", element_name, error))
2311 state_switch (ctx, STATE_BOXED);
2315 case STATE_STRUCT_FIELD:
2316 if (strcmp ("type", element_name) == 0)
2318 if (require_end_element (context, ctx, "field", element_name, error))
2320 state_switch (ctx, STATE_STRUCT);
2325 if (require_end_element (context, ctx, "record", element_name, error))
2327 ctx->current_node = NULL;
2328 state_switch (ctx, STATE_NAMESPACE);
2332 case STATE_UNION_FIELD:
2333 if (strcmp ("type", element_name) == 0)
2335 if (require_end_element (context, ctx, "field", element_name, error))
2337 state_switch (ctx, STATE_UNION);
2342 if (require_end_element (context, ctx, "union", element_name, error))
2344 ctx->current_node = NULL;
2345 state_switch (ctx, STATE_NAMESPACE);
2348 case STATE_IMPLEMENTS:
2349 if (strcmp ("interface", element_name) == 0)
2351 if (require_end_element (context, ctx, "implements", element_name, error))
2352 state_switch (ctx, STATE_CLASS);
2354 case STATE_REQUIRES:
2355 if (require_end_element (context, ctx, "requires", element_name, error))
2356 state_switch (ctx, STATE_INTERFACE);
2358 case STATE_NAMESPACE_CONSTANT:
2359 case STATE_CLASS_CONSTANT:
2360 case STATE_INTERFACE_CONSTANT:
2361 if (strcmp ("type", element_name) == 0)
2363 if (require_end_element (context, ctx, "constant", element_name, error))
2365 ctx->current_node = NULL;
2368 case STATE_NAMESPACE_CONSTANT:
2369 state_switch (ctx, STATE_NAMESPACE);
2371 case STATE_CLASS_CONSTANT:
2372 state_switch (ctx, STATE_CLASS);
2374 case STATE_INTERFACE_CONSTANT:
2375 state_switch (ctx, STATE_INTERFACE);
2378 g_assert_not_reached ();
2384 g_error ("Unhandled state %d in end_element_handler\n", ctx->state);
2389 text_handler (GMarkupParseContext *context,
2395 /* FIXME warn about non-whitespace text */
2399 cleanup (GMarkupParseContext *context,
2403 ParseContext *ctx = user_data;
2405 int line_number, char_number;
2407 for (m = ctx->modules; m; m = m->next)
2408 g_ir_module_free (m->data);
2409 g_list_free (ctx->modules);
2410 ctx->modules = NULL;
2412 ctx->current_module = NULL;
2416 firstpass_start_element_handler (GMarkupParseContext *context,
2417 const gchar *element_name,
2418 const gchar **attribute_names,
2419 const gchar **attribute_values,
2423 ParseContext *ctx = user_data;
2425 if (strcmp (element_name, "alias") == 0)
2427 start_alias (context, element_name, attribute_names, attribute_values,
2433 firstpass_end_element_handler (GMarkupParseContext *context,
2434 const gchar *element_name,
2438 ParseContext *ctx = user_data;
2443 static GMarkupParser firstpass_parser =
2445 firstpass_start_element_handler,
2446 firstpass_end_element_handler,
2453 static GMarkupParser parser =
2455 start_element_handler,
2456 end_element_handler,
2463 g_ir_parse_string (const gchar *buffer,
2467 ParseContext ctx = { 0 };
2468 GMarkupParseContext *context;
2470 ctx.state = STATE_START;
2471 ctx.aliases = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
2473 context = g_markup_parse_context_new (&firstpass_parser, 0, &ctx, NULL);
2475 if (!g_markup_parse_context_parse (context, buffer, length, error))
2478 if (!g_markup_parse_context_end_parse (context, error))
2481 context = g_markup_parse_context_new (&parser, 0, &ctx, NULL);
2482 if (!g_markup_parse_context_parse (context, buffer, length, error))
2485 if (!g_markup_parse_context_end_parse (context, error))
2490 g_hash_table_destroy (ctx.aliases);
2492 g_markup_parse_context_free (context);
2498 g_ir_parse_file (const gchar *filename,
2505 g_debug ("[parsing] filename %s", filename);
2507 if (!g_file_get_contents (filename, &buffer, &length, error))
2510 modules = g_ir_parse_string (buffer, length, error);