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 */
56 STATE_NAMESPACE_CONSTANT,
57 STATE_CLASS_CONSTANT, /* 25 */
58 STATE_INTERFACE_CONSTANT,
62 typedef struct _ParseContext ParseContext;
66 ParseState prev_state;
71 GIrModule *current_module;
72 GIrNode *current_node;
73 GIrNode *current_typed;
76 #define MISSING_ATTRIBUTE(ctx,error,element,attribute) \
78 int line_number, char_number; \
79 g_markup_parse_context_get_position (context, &line_number, &char_number); \
82 G_MARKUP_ERROR_INVALID_CONTENT, \
83 "Line %d, character %d: The attribute '%s' on the element '%s' must be specified", \
84 line_number, char_number, attribute, element); \
88 backtrace_stderr (void)
95 size = backtrace (array, 50);
96 strings = (char**) backtrace_symbols (array, size);
98 fprintf (stderr, "--- BACKTRACE (%zd frames) ---\n", size);
100 for (i = 0; i < size; i++)
101 fprintf (stderr, "%s\n", strings[i]);
103 fprintf (stderr, "--- END BACKTRACE ---\n", size);
110 find_attribute (const gchar *name,
111 const gchar **attribute_names,
112 const gchar **attribute_values)
116 for (i = 0; attribute_names[i] != NULL; i++)
117 if (strcmp (attribute_names[i], name) == 0)
118 return attribute_values[i];
124 state_switch (ParseContext *ctx, ParseState newstate)
126 g_debug ("State: %d", newstate);
127 ctx->prev_state = ctx->state;
128 ctx->state = newstate;
131 static GIrNodeType * parse_type_internal (gchar *str, gchar **rest);
136 char *pointer = g_strdup ("any");
138 GIrNodeType *ret = parse_type_internal (pointer, &pointer_rest);
144 parse_type_internal (gchar *str, gchar **rest)
153 { "none", GI_TYPE_TAG_VOID, 0 },
154 { "any", GI_TYPE_TAG_VOID, 1 },
156 { "bool", GI_TYPE_TAG_BOOLEAN, 0 },
157 { "char", GI_TYPE_TAG_INT8, 0 },
158 { "int8", GI_TYPE_TAG_INT8, 0 },
159 { "uint8", GI_TYPE_TAG_UINT8, 0 },
160 { "int16", GI_TYPE_TAG_INT16, 0 },
161 { "uint16", GI_TYPE_TAG_UINT16, 0 },
162 { "int32", GI_TYPE_TAG_INT32, 0 },
163 { "uint32", GI_TYPE_TAG_UINT32, 0 },
164 { "int64", GI_TYPE_TAG_INT64, 0 },
165 { "uint64", GI_TYPE_TAG_UINT64, 0 },
166 { "int", GI_TYPE_TAG_INT, 0 },
167 { "uint", GI_TYPE_TAG_UINT, 0 },
168 { "long", GI_TYPE_TAG_LONG, 0 },
169 { "ulong", GI_TYPE_TAG_ULONG, 0 },
170 { "ssize_t", GI_TYPE_TAG_SSIZE, 0 },
171 { "ssize", GI_TYPE_TAG_SSIZE, 0 },
172 { "size_t", GI_TYPE_TAG_SIZE, 0 },
173 { "size", GI_TYPE_TAG_SIZE, 0 },
174 { "float", GI_TYPE_TAG_FLOAT, 0 },
175 { "double", GI_TYPE_TAG_DOUBLE, 0 },
176 { "utf8", GI_TYPE_TAG_UTF8, 1 },
177 { "filename", GI_TYPE_TAG_FILENAME,1 },
179 /* FIXME: merge - do we still want this? */
180 { "string", GI_TYPE_TAG_UTF8, 1 }
182 /* FIXME: Remove these */
183 { "void", GI_TYPE_TAG_VOID, 0 },
184 { "int8_t", GI_TYPE_TAG_INT8, 0 },
185 { "uint8_t", GI_TYPE_TAG_UINT8, 0 },
186 { "int16_t", GI_TYPE_TAG_INT16, 0 },
187 { "uint16_t", GI_TYPE_TAG_UINT16, 0 },
188 { "int32_t", GI_TYPE_TAG_INT32, 0 },
189 { "uint32_t", GI_TYPE_TAG_UINT32, 0 },
190 { "int64_t", GI_TYPE_TAG_INT64, 0 },
191 { "uint64_t", GI_TYPE_TAG_UINT64, 0 },
192 { "gpointer", GI_TYPE_TAG_VOID, 1 },
193 { "gboolean", GI_TYPE_TAG_BOOLEAN, 0 },
194 { "gchar", GI_TYPE_TAG_INT8, 0 },
195 { "guchar", GI_TYPE_TAG_UINT8, 0 },
196 { "gunichar", GI_TYPE_TAG_UINT32, 0 },
197 { "gint", GI_TYPE_TAG_INT, 0 },
198 { "guint", GI_TYPE_TAG_UINT, 0 },
199 { "gint8", GI_TYPE_TAG_INT8, 0 },
200 { "guint8", GI_TYPE_TAG_UINT8, 0 },
201 { "gint16", GI_TYPE_TAG_INT16, 0 },
202 { "guint16", GI_TYPE_TAG_UINT16, 0 },
203 { "gint32", GI_TYPE_TAG_INT32, 0 },
204 { "guint32", GI_TYPE_TAG_UINT32, 0 },
205 { "gint64", GI_TYPE_TAG_INT64, 0 },
206 { "guint64", GI_TYPE_TAG_UINT64, 0 },
207 { "glong", GI_TYPE_TAG_LONG, 0 },
208 { "gulong", GI_TYPE_TAG_ULONG, 0 },
209 { "gssize", GI_TYPE_TAG_SSIZE, 0 },
210 { "gsize", GI_TYPE_TAG_SIZE, 0 },
211 { "gfloat", GI_TYPE_TAG_FLOAT, 0 },
212 { "gdouble", GI_TYPE_TAG_DOUBLE, 0 },
213 { "gchar*", GI_TYPE_TAG_UTF8, 1 },
216 gint n_basic = G_N_ELEMENTS (basic);
221 type = (GIrNodeType *)g_ir_node_new (G_IR_NODE_TYPE);
223 str = g_strstrip (str);
225 type->unparsed = g_strdup (str);
228 for (i = 0; i < n_basic; i++)
230 if (g_str_has_prefix (*rest, basic[i].str))
232 type->is_basic = TRUE;
233 type->tag = basic[i].tag;
234 type->is_pointer = basic[i].pointer;
236 *rest += strlen(basic[i].str);
237 *rest = g_strchug (*rest);
238 if (**rest == '*' && !type->is_pointer)
240 type->is_pointer = TRUE;
249 /* found a basic type */;
250 else if (g_str_has_prefix (*rest, "GList") ||
251 g_str_has_prefix (*rest, "GSList"))
253 if (g_str_has_prefix (*rest, "GList"))
255 type->tag = GI_TYPE_TAG_GLIST;
256 type->is_glist = TRUE;
257 type->is_pointer = TRUE;
258 *rest += strlen ("GList");
262 type->tag = GI_TYPE_TAG_GSLIST;
263 type->is_gslist = TRUE;
264 type->is_pointer = TRUE;
265 *rest += strlen ("GSList");
268 *rest = g_strchug (*rest);
274 type->parameter_type1 = parse_type_internal (*rest, rest);
275 if (type->parameter_type1 == NULL)
278 *rest = g_strchug (*rest);
280 if ((*rest)[0] != '>')
286 type->parameter_type1 = create_pointer ();
289 else if (g_str_has_prefix (*rest, "GHashTable"))
291 type->tag = GI_TYPE_TAG_GHASH;
292 type->is_ghashtable = TRUE;
293 type->is_pointer = TRUE;
294 *rest += strlen ("GHashTable");
296 *rest = g_strchug (*rest);
302 type->parameter_type1 = parse_type_internal (*rest, rest);
303 if (type->parameter_type1 == NULL)
306 *rest = g_strchug (*rest);
308 if ((*rest)[0] != ',')
312 type->parameter_type2 = parse_type_internal (*rest, rest);
313 if (type->parameter_type2 == NULL)
316 if ((*rest)[0] != '>')
322 type->parameter_type1 = create_pointer ();
323 type->parameter_type2 = create_pointer ();
327 else if (g_str_has_prefix (*rest, "GError"))
329 type->tag = GI_TYPE_TAG_ERROR;
330 type->is_error = TRUE;
331 type->is_pointer = TRUE;
332 *rest += strlen ("GError");
334 *rest = g_strchug (*rest);
340 end = strchr (*rest, '>');
341 str = g_strndup (*rest, end - *rest);
342 type->errors = g_strsplit (str, ",", 0);
350 type->tag = GI_TYPE_TAG_INTERFACE;
351 type->is_interface = TRUE;
354 /* must be an interface type */
355 while (g_ascii_isalnum (**rest) ||
362 type->interface = g_strndup (start, *rest - start);
364 *rest = g_strchug (*rest);
367 type->is_pointer = TRUE;
372 *rest = g_strchug (*rest);
373 if (g_str_has_prefix (*rest, "["))
377 array = (GIrNodeType *)g_ir_node_new (G_IR_NODE_TYPE);
379 array->tag = GI_TYPE_TAG_ARRAY;
380 array->is_pointer = TRUE;
381 array->is_array = TRUE;
383 array->parameter_type1 = type;
385 array->zero_terminated = FALSE;
386 array->has_length = FALSE;
389 if (!g_str_has_prefix (*rest, "[]"))
391 gchar *end, *str, **opts;
393 end = strchr (*rest, ']');
394 str = g_strndup (*rest + 1, (end - *rest) - 1);
395 opts = g_strsplit (str, ",", 0);
399 for (i = 0; opts[i]; i++)
403 vals = g_strsplit (opts[i], "=", 0);
405 if (strcmp (vals[0], "zero-terminated") == 0)
406 array->zero_terminated = (strcmp (vals[1], "1") == 0);
407 else if (strcmp (vals[0], "length") == 0)
409 array->has_length = TRUE;
410 array->length = atoi (vals[1]);
423 g_assert (type->tag >= 0 && type->tag <= GI_TYPE_TAG_ERROR);
427 g_ir_node_free ((GIrNode *)type);
433 resolve_aliases (ParseContext *ctx, const gchar *type)
438 while (g_hash_table_lookup_extended (ctx->aliases, type, &orig, &value))
440 g_debug ("Resolved: %s => %s", type, value);
447 parse_type (ParseContext *ctx, const gchar *type)
453 type = resolve_aliases (ctx, type);
454 str = g_strdup (type);
455 node = parse_type_internal (str, &rest);
462 start_glib_boxed (GMarkupParseContext *context,
463 const gchar *element_name,
464 const gchar **attribute_names,
465 const gchar **attribute_values,
469 if (strcmp (element_name, "glib:boxed") == 0 &&
470 ctx->state == STATE_NAMESPACE)
473 const gchar *typename;
474 const gchar *typeinit;
475 const gchar *deprecated;
477 name = find_attribute ("glib:name", attribute_names, attribute_values);
478 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
479 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
480 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
483 MISSING_ATTRIBUTE (context, error, element_name, "glib:name");
484 else if (typename == NULL)
485 MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
486 else if (typeinit == NULL)
487 MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
492 boxed = (GIrNodeBoxed *) g_ir_node_new (G_IR_NODE_BOXED);
494 ((GIrNode *)boxed)->name = g_strdup (name);
495 boxed->gtype_name = g_strdup (typename);
496 boxed->gtype_init = g_strdup (typeinit);
497 if (deprecated && strcmp (deprecated, "1") == 0)
498 boxed->deprecated = TRUE;
500 boxed->deprecated = FALSE;
502 ctx->current_node = (GIrNode *)boxed;
503 ctx->current_module->entries =
504 g_list_append (ctx->current_module->entries, boxed);
506 state_switch (ctx, STATE_BOXED);
516 start_function (GMarkupParseContext *context,
517 const gchar *element_name,
518 const gchar **attribute_names,
519 const gchar **attribute_values,
523 if ((ctx->state == STATE_NAMESPACE &&
524 (strcmp (element_name, "function") == 0 ||
525 strcmp (element_name, "callback") == 0)) ||
526 ((ctx->state == STATE_CLASS ||
527 ctx->state == STATE_INTERFACE ||
528 ctx->state == STATE_BOXED ||
529 ctx->state == STATE_UNION) &&
530 (strcmp (element_name, "method") == 0 ||
531 strcmp (element_name, "callback") == 0)) ||
532 ((ctx->state == STATE_CLASS ||
533 ctx->state == STATE_BOXED) &&
534 (strcmp (element_name, "constructor") == 0)) ||
535 (ctx->state == STATE_STRUCT && strcmp (element_name, "callback") == 0))
539 const gchar *deprecated;
542 name = find_attribute ("name", attribute_names, attribute_values);
543 symbol = find_attribute ("c:identifier", attribute_names, attribute_values);
544 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
545 type = find_attribute ("type", attribute_names, attribute_values);
548 MISSING_ATTRIBUTE (context, error, element_name, "name");
549 else if (strcmp (element_name, "callback") != 0 && symbol == NULL)
550 MISSING_ATTRIBUTE (context, error, element_name, "c:identifier");
553 GIrNodeFunction *function;
555 function = (GIrNodeFunction *) g_ir_node_new (G_IR_NODE_FUNCTION);
557 ((GIrNode *)function)->name = g_strdup (name);
558 function->symbol = g_strdup (symbol);
559 function->parameters = NULL;
560 if (deprecated && strcmp (deprecated, "1") == 0)
561 function->deprecated = TRUE;
563 function->deprecated = FALSE;
565 if (strcmp (element_name, "method") == 0 ||
566 strcmp (element_name, "constructor") == 0)
568 function->is_method = TRUE;
570 if (type && strcmp (type, "setter") == 0)
571 function->is_setter = TRUE;
572 else if (type && strcmp (type, "getter") == 0)
573 function->is_getter = TRUE;
575 if (strcmp (element_name, "constructor") == 0)
576 function->is_constructor = TRUE;
578 function->is_constructor = FALSE;
582 function->is_method = FALSE;
583 function->is_setter = FALSE;
584 function->is_getter = FALSE;
585 function->is_constructor = FALSE;
586 if (strcmp (element_name, "callback") == 0)
587 ((GIrNode *)function)->type = G_IR_NODE_CALLBACK;
590 if (ctx->current_node == NULL)
592 ctx->current_module->entries =
593 g_list_append (ctx->current_module->entries, function);
596 switch (ctx->current_node->type)
598 case G_IR_NODE_INTERFACE:
599 case G_IR_NODE_OBJECT:
601 GIrNodeInterface *iface;
603 iface = (GIrNodeInterface *)ctx->current_node;
604 iface->members = g_list_append (iface->members, function);
607 case G_IR_NODE_BOXED:
611 boxed = (GIrNodeBoxed *)ctx->current_node;
612 boxed->members = g_list_append (boxed->members, function);
615 case G_IR_NODE_STRUCT:
617 GIrNodeStruct *struct_;
619 struct_ = (GIrNodeStruct *)ctx->current_node;
620 struct_->members = g_list_append (struct_->members, function); }
622 case G_IR_NODE_UNION:
624 GIrNodeUnion *union_;
626 union_ = (GIrNodeUnion *)ctx->current_node;
627 union_->members = g_list_append (union_->members, function);
631 g_assert_not_reached ();
634 ctx->current_node = (GIrNode *)function;
635 state_switch (ctx, STATE_FUNCTION);
645 start_parameter (GMarkupParseContext *context,
646 const gchar *element_name,
647 const gchar **attribute_names,
648 const gchar **attribute_values,
653 const gchar *direction;
656 const gchar *optional;
658 const gchar *transfer;
661 if (!(strcmp (element_name, "parameter") == 0 &&
662 ctx->state == STATE_FUNCTION_PARAMETERS))
665 name = find_attribute ("name", attribute_names, attribute_values);
666 direction = find_attribute ("direction", attribute_names, attribute_values);
667 retval = find_attribute ("retval", attribute_names, attribute_values);
668 dipper = find_attribute ("dipper", attribute_names, attribute_values);
669 optional = find_attribute ("optional", attribute_names, attribute_values);
670 nullok = find_attribute ("null-ok", attribute_names, attribute_values);
671 transfer = find_attribute ("transfer", attribute_names, attribute_values);
676 param = (GIrNodeParam *)g_ir_node_new (G_IR_NODE_PARAM);
678 ctx->current_typed = (GIrNode*) param;
679 ctx->current_typed->name = g_strdup (name);
681 state_switch (ctx, STATE_FUNCTION_PARAMETER);
683 if (direction && strcmp (direction, "out") == 0)
688 else if (direction && strcmp (direction, "inout") == 0)
699 if (retval && strcmp (retval, "1") == 0)
700 param->retval = TRUE;
702 param->retval = FALSE;
704 if (dipper && strcmp (dipper, "1") == 0)
705 param->dipper = TRUE;
707 param->dipper = FALSE;
709 if (optional && strcmp (optional, "1") == 0)
710 param->optional = TRUE;
712 param->optional = FALSE;
714 if (nullok && strcmp (nullok, "1") == 0)
715 param->null_ok = TRUE;
717 param->null_ok = FALSE;
719 if (transfer && strcmp (transfer, "none") == 0)
721 param->transfer = FALSE;
722 param->shallow_transfer = FALSE;
724 else if (transfer && strcmp (transfer, "shallow") == 0)
726 param->transfer = FALSE;
727 param->shallow_transfer = TRUE;
731 param->transfer = TRUE;
732 param->shallow_transfer = FALSE;
735 ((GIrNode *)param)->name = g_strdup (name);
737 switch (ctx->current_node->type)
739 case G_IR_NODE_FUNCTION:
740 case G_IR_NODE_CALLBACK:
742 GIrNodeFunction *func;
744 func = (GIrNodeFunction *)ctx->current_node;
745 func->parameters = g_list_append (func->parameters, param);
748 case G_IR_NODE_SIGNAL:
750 GIrNodeSignal *signal;
752 signal = (GIrNodeSignal *)ctx->current_node;
753 signal->parameters = g_list_append (signal->parameters, param);
756 case G_IR_NODE_VFUNC:
760 vfunc = (GIrNodeVFunc *)ctx->current_node;
761 vfunc->parameters = g_list_append (vfunc->parameters, param);
765 g_assert_not_reached ();
772 start_field (GMarkupParseContext *context,
773 const gchar *element_name,
774 const gchar **attribute_names,
775 const gchar **attribute_values,
779 if (strcmp (element_name, "field") == 0 &&
780 (ctx->state == STATE_CLASS ||
781 ctx->state == STATE_BOXED ||
782 ctx->state == STATE_STRUCT ||
783 ctx->state == STATE_UNION ||
784 ctx->state == STATE_INTERFACE))
787 const gchar *readable;
788 const gchar *writable;
793 name = find_attribute ("name", attribute_names, attribute_values);
794 readable = find_attribute ("readable", attribute_names, attribute_values);
795 writable = find_attribute ("writable", attribute_names, attribute_values);
796 bits = find_attribute ("bits", attribute_names, attribute_values);
797 branch = find_attribute ("branch", attribute_names, attribute_values);
798 offset = find_attribute ("offset", attribute_names, attribute_values);
801 MISSING_ATTRIBUTE (context, error, element_name, "name");
806 field = (GIrNodeField *)g_ir_node_new (G_IR_NODE_FIELD);
807 ctx->current_typed = (GIrNode*) field;
808 ((GIrNode *)field)->name = g_strdup (name);
809 if (readable && strcmp (readable, "1") == 0)
810 field->readable = TRUE;
812 field->readable = FALSE;
814 if (writable && strcmp (writable, "1") == 0)
815 field->writable = TRUE;
817 field->writable = FALSE;
820 field->bits = atoi (bits);
825 field->offset = atoi (offset);
829 switch (ctx->current_node->type)
831 case G_IR_NODE_OBJECT:
833 GIrNodeInterface *iface;
835 iface = (GIrNodeInterface *)ctx->current_node;
836 iface->members = g_list_append (iface->members, field);
837 state_switch (ctx, STATE_CLASS_FIELD);
840 case G_IR_NODE_INTERFACE:
842 GIrNodeInterface *iface;
844 iface = (GIrNodeInterface *)ctx->current_node;
845 iface->members = g_list_append (iface->members, field);
846 state_switch (ctx, STATE_INTERFACE_FIELD);
849 case G_IR_NODE_BOXED:
853 boxed = (GIrNodeBoxed *)ctx->current_node;
854 boxed->members = g_list_append (boxed->members, field);
855 state_switch (ctx, STATE_BOXED_FIELD);
858 case G_IR_NODE_STRUCT:
860 GIrNodeStruct *struct_;
862 struct_ = (GIrNodeStruct *)ctx->current_node;
863 struct_->members = g_list_append (struct_->members, field);
864 state_switch (ctx, STATE_STRUCT_FIELD);
867 case G_IR_NODE_UNION:
869 GIrNodeUnion *union_;
871 union_ = (GIrNodeUnion *)ctx->current_node;
872 union_->members = g_list_append (union_->members, field);
875 GIrNodeConstant *constant;
877 constant = (GIrNodeConstant *) g_ir_node_new (G_IR_NODE_CONSTANT);
878 ((GIrNode *)constant)->name = g_strdup (name);
879 constant->value = g_strdup (branch);
880 constant->type = union_->discriminator_type;
881 constant->deprecated = FALSE;
883 union_->discriminators = g_list_append (union_->discriminators, constant);
888 g_assert_not_reached ();
898 start_alias (GMarkupParseContext *context,
899 const gchar *element_name,
900 const gchar **attribute_names,
901 const gchar **attribute_values,
909 name = find_attribute ("name", attribute_names, attribute_values);
911 MISSING_ATTRIBUTE (context, error, element_name, "name");
915 target = find_attribute ("target", attribute_names, attribute_values);
917 MISSING_ATTRIBUTE (context, error, element_name, "target");
921 g_hash_table_insert (ctx->aliases, g_strdup (name), g_strdup (target));
926 start_enum (GMarkupParseContext *context,
927 const gchar *element_name,
928 const gchar **attribute_names,
929 const gchar **attribute_values,
933 if ((strcmp (element_name, "enumeration") == 0 && ctx->state == STATE_NAMESPACE) ||
934 (strcmp (element_name, "bitfield") == 0 && ctx->state == STATE_NAMESPACE))
937 const gchar *typename;
938 const gchar *typeinit;
939 const gchar *deprecated;
941 name = find_attribute ("name", attribute_names, attribute_values);
942 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
943 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
944 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
947 MISSING_ATTRIBUTE (context, error, element_name, "name");
952 if (strcmp (element_name, "enumeration") == 0)
953 enum_ = (GIrNodeEnum *) g_ir_node_new (G_IR_NODE_ENUM);
955 enum_ = (GIrNodeEnum *) g_ir_node_new (G_IR_NODE_FLAGS);
956 ((GIrNode *)enum_)->name = g_strdup (name);
957 enum_->gtype_name = g_strdup (typename);
958 enum_->gtype_init = g_strdup (typeinit);
959 if (deprecated && strcmp (deprecated, "1") == 0)
960 enum_->deprecated = TRUE;
962 enum_->deprecated = FALSE;
964 ctx->current_node = (GIrNode *) enum_;
965 ctx->current_module->entries =
966 g_list_append (ctx->current_module->entries, enum_);
968 state_switch (ctx, STATE_ENUM);
977 start_property (GMarkupParseContext *context,
978 const gchar *element_name,
979 const gchar **attribute_names,
980 const gchar **attribute_values,
984 if (strcmp (element_name, "property") == 0 &&
985 (ctx->state == STATE_CLASS ||
986 ctx->state == STATE_INTERFACE))
989 const gchar *readable;
990 const gchar *writable;
991 const gchar *construct;
992 const gchar *construct_only;
994 name = find_attribute ("name", attribute_names, attribute_values);
995 readable = find_attribute ("readable", attribute_names, attribute_values);
996 writable = find_attribute ("writable", attribute_names, attribute_values);
997 construct = find_attribute ("construct", attribute_names, attribute_values);
998 construct_only = find_attribute ("construct-only", attribute_names, attribute_values);
1001 MISSING_ATTRIBUTE (context, error, element_name, "name");
1004 GIrNodeProperty *property;
1005 GIrNodeInterface *iface;
1007 property = (GIrNodeProperty *) g_ir_node_new (G_IR_NODE_PROPERTY);
1008 ctx->current_typed = (GIrNode*) property;
1010 ((GIrNode *)property)->name = g_strdup (name);
1012 if (readable && strcmp (readable, "1") == 0)
1013 property->readable = TRUE;
1015 property->readable = FALSE;
1016 if (writable && strcmp (writable, "1") == 0)
1017 property->writable = TRUE;
1019 property->writable = FALSE;
1020 if (construct && strcmp (construct, "1") == 0)
1021 property->construct = TRUE;
1023 property->construct = FALSE;
1024 if (construct_only && strcmp (construct_only, "1") == 0)
1025 property->construct_only = TRUE;
1027 property->construct_only = FALSE;
1029 iface = (GIrNodeInterface *)ctx->current_node;
1030 iface->members = g_list_append (iface->members, property);
1032 if (ctx->state == STATE_CLASS)
1033 state_switch (ctx, STATE_CLASS_PROPERTY);
1034 else if (ctx->state == STATE_INTERFACE)
1035 state_switch (ctx, STATE_INTERFACE_PROPERTY);
1037 g_assert_not_reached ();
1046 parse_value (const gchar *str)
1050 /* FIXME just a quick hack */
1051 shift_op = strstr (str, "<<");
1057 base = strtol (str, NULL, 10);
1058 shift = strtol (shift_op + 3, NULL, 10);
1060 return base << shift;
1063 return strtol (str, NULL, 10);
1069 start_member (GMarkupParseContext *context,
1070 const gchar *element_name,
1071 const gchar **attribute_names,
1072 const gchar **attribute_values,
1076 if (strcmp (element_name, "member") == 0 &&
1077 ctx->state == STATE_ENUM)
1081 const gchar *deprecated;
1083 name = find_attribute ("name", attribute_names, attribute_values);
1084 value = find_attribute ("value", attribute_names, attribute_values);
1085 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1088 MISSING_ATTRIBUTE (context, error, element_name, "name");
1092 GIrNodeValue *value_;
1094 value_ = (GIrNodeValue *) g_ir_node_new (G_IR_NODE_VALUE);
1096 ((GIrNode *)value_)->name = g_strdup (name);
1098 value_->value = parse_value (value);
1100 if (deprecated && strcmp (deprecated, "1") == 0)
1101 value_->deprecated = TRUE;
1103 value_->deprecated = FALSE;
1105 enum_ = (GIrNodeEnum *)ctx->current_node;
1106 enum_->values = g_list_append (enum_->values, value_);
1115 start_constant (GMarkupParseContext *context,
1116 const gchar *element_name,
1117 const gchar **attribute_names,
1118 const gchar **attribute_values,
1122 if (strcmp (element_name, "constant") == 0 &&
1123 (ctx->state == STATE_NAMESPACE ||
1124 ctx->state == STATE_CLASS ||
1125 ctx->state == STATE_INTERFACE))
1129 const gchar *deprecated;
1131 name = find_attribute ("name", attribute_names, attribute_values);
1132 value = find_attribute ("value", attribute_names, attribute_values);
1133 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1136 MISSING_ATTRIBUTE (context, error, element_name, "name");
1137 else if (value == NULL)
1138 MISSING_ATTRIBUTE (context, error, element_name, "value");
1141 GIrNodeConstant *constant;
1143 constant = (GIrNodeConstant *) g_ir_node_new (G_IR_NODE_CONSTANT);
1145 ((GIrNode *)constant)->name = g_strdup (name);
1146 constant->value = g_strdup (value);
1148 ctx->current_typed = (GIrNode*) constant;
1150 if (deprecated && strcmp (deprecated, "1") == 0)
1151 constant->deprecated = TRUE;
1153 constant->deprecated = FALSE;
1155 if (ctx->state == STATE_NAMESPACE)
1157 ctx->current_node = (GIrNode *) constant;
1158 ctx->current_module->entries =
1159 g_list_append (ctx->current_module->entries, constant);
1163 GIrNodeInterface *iface;
1165 iface = (GIrNodeInterface *)ctx->current_node;
1166 iface->members = g_list_append (iface->members, constant);
1171 case STATE_NAMESPACE:
1172 state_switch (ctx, STATE_NAMESPACE_CONSTANT);
1175 state_switch (ctx, STATE_CLASS_CONSTANT);
1177 case STATE_INTERFACE:
1178 state_switch (ctx, STATE_INTERFACE_CONSTANT);
1181 g_assert_not_reached ();
1192 start_errordomain (GMarkupParseContext *context,
1193 const gchar *element_name,
1194 const gchar **attribute_names,
1195 const gchar **attribute_values,
1199 if (strcmp (element_name, "errordomain") == 0 &&
1200 ctx->state == STATE_NAMESPACE)
1203 const gchar *getquark;
1205 const gchar *deprecated;
1207 name = find_attribute ("name", attribute_names, attribute_values);
1208 getquark = find_attribute ("get-quark", attribute_names, attribute_values);
1209 codes = find_attribute ("codes", attribute_names, attribute_values);
1210 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1213 MISSING_ATTRIBUTE (context, error, element_name, "name");
1214 else if (getquark == NULL)
1215 MISSING_ATTRIBUTE (context, error, element_name, "getquark");
1216 else if (codes == NULL)
1217 MISSING_ATTRIBUTE (context, error, element_name, "codes");
1220 GIrNodeErrorDomain *domain;
1222 domain = (GIrNodeErrorDomain *) g_ir_node_new (G_IR_NODE_ERROR_DOMAIN);
1224 ((GIrNode *)domain)->name = g_strdup (name);
1225 domain->getquark = g_strdup (getquark);
1226 domain->codes = g_strdup (codes);
1228 if (deprecated && strcmp (deprecated, "1") == 0)
1229 domain->deprecated = TRUE;
1231 domain->deprecated = FALSE;
1233 ctx->current_node = (GIrNode *) domain;
1234 ctx->current_module->entries =
1235 g_list_append (ctx->current_module->entries, domain);
1237 state_switch (ctx, STATE_ERRORDOMAIN);
1246 start_interface (GMarkupParseContext *context,
1247 const gchar *element_name,
1248 const gchar **attribute_names,
1249 const gchar **attribute_values,
1253 if (strcmp (element_name, "interface") == 0 &&
1254 ctx->state == STATE_NAMESPACE)
1257 const gchar *typename;
1258 const gchar *typeinit;
1259 const gchar *deprecated;
1261 name = find_attribute ("name", attribute_names, attribute_values);
1262 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
1263 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
1264 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1267 MISSING_ATTRIBUTE (context, error, element_name, "name");
1268 else if (typename == NULL)
1269 MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
1270 else if (typeinit == NULL)
1271 MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
1274 GIrNodeInterface *iface;
1276 iface = (GIrNodeInterface *) g_ir_node_new (G_IR_NODE_INTERFACE);
1277 ((GIrNode *)iface)->name = g_strdup (name);
1278 iface->gtype_name = g_strdup (typename);
1279 iface->gtype_init = g_strdup (typeinit);
1280 if (deprecated && strcmp (deprecated, "1") == 0)
1281 iface->deprecated = TRUE;
1283 iface->deprecated = FALSE;
1285 ctx->current_node = (GIrNode *) iface;
1286 ctx->current_module->entries =
1287 g_list_append (ctx->current_module->entries, iface);
1289 state_switch (ctx, STATE_INTERFACE);
1299 start_class (GMarkupParseContext *context,
1300 const gchar *element_name,
1301 const gchar **attribute_names,
1302 const gchar **attribute_values,
1306 if (strcmp (element_name, "class") == 0 &&
1307 ctx->state == STATE_NAMESPACE)
1310 const gchar *parent;
1311 const gchar *typename;
1312 const gchar *typeinit;
1313 const gchar *deprecated;
1315 name = find_attribute ("name", attribute_names, attribute_values);
1316 parent = find_attribute ("parent", attribute_names, attribute_values);
1317 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
1318 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
1319 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1322 MISSING_ATTRIBUTE (context, error, element_name, "name");
1323 else if (typename == NULL)
1324 MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
1325 else if (typeinit == NULL && strcmp (typename, "GObject"))
1326 MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
1329 GIrNodeInterface *iface;
1331 iface = (GIrNodeInterface *) g_ir_node_new (G_IR_NODE_OBJECT);
1332 ((GIrNode *)iface)->name = g_strdup (name);
1333 iface->gtype_name = g_strdup (typename);
1334 iface->gtype_init = g_strdup (typeinit);
1335 iface->parent = g_strdup (parent);
1336 if (deprecated && strcmp (deprecated, "1") == 0)
1337 iface->deprecated = TRUE;
1339 iface->deprecated = FALSE;
1341 ctx->current_node = (GIrNode *) iface;
1342 ctx->current_module->entries =
1343 g_list_append (ctx->current_module->entries, iface);
1345 state_switch (ctx, STATE_CLASS);
1354 start_type (GMarkupParseContext *context,
1355 const gchar *element_name,
1356 const gchar **attribute_names,
1357 const gchar **attribute_values,
1363 if (strcmp (element_name, "type") != 0 ||
1364 !(ctx->state == STATE_FUNCTION_PARAMETER ||
1365 ctx->state == STATE_FUNCTION_RETURN ||
1366 ctx->state == STATE_STRUCT_FIELD ||
1367 ctx->state == STATE_CLASS_PROPERTY ||
1368 ctx->state == STATE_CLASS_FIELD ||
1369 ctx->state == STATE_INTERFACE_FIELD ||
1370 ctx->state == STATE_INTERFACE_PROPERTY ||
1371 ctx->state == STATE_BOXED_FIELD ||
1372 ctx->state == STATE_NAMESPACE_CONSTANT ||
1373 ctx->state == STATE_CLASS_CONSTANT ||
1374 ctx->state == STATE_INTERFACE_CONSTANT
1378 if (!ctx->current_typed)
1382 G_MARKUP_ERROR_INVALID_CONTENT,
1383 "The element <type> is invalid here");
1387 name = find_attribute ("name", attribute_names, attribute_values);
1390 MISSING_ATTRIBUTE (context, error, element_name, "name");
1392 switch (ctx->current_typed->type)
1394 case G_IR_NODE_PARAM:
1396 GIrNodeParam *param = (GIrNodeParam *)ctx->current_typed;
1397 param->type = parse_type (ctx, name);
1400 case G_IR_NODE_FIELD:
1402 GIrNodeField *field = (GIrNodeField *)ctx->current_typed;
1403 field->type = parse_type (ctx, name);
1406 case G_IR_NODE_PROPERTY:
1408 GIrNodeProperty *property = (GIrNodeProperty *) ctx->current_typed;
1409 property->type = parse_type (ctx, name);
1412 case G_IR_NODE_CONSTANT:
1414 GIrNodeConstant *constant = (GIrNodeConstant *)ctx->current_typed;
1415 constant->type = parse_type (ctx, name);
1419 g_printerr("current node is %d\n", ctx->current_node->type);
1420 g_assert_not_reached ();
1423 ctx->current_typed = NULL;
1428 start_return_value (GMarkupParseContext *context,
1429 const gchar *element_name,
1430 const gchar **attribute_names,
1431 const gchar **attribute_values,
1435 if (strcmp (element_name, "return-value") == 0 &&
1436 ctx->state == STATE_FUNCTION)
1438 GIrNodeParam *param;
1440 param = (GIrNodeParam *)g_ir_node_new (G_IR_NODE_PARAM);
1443 param->retval = TRUE;
1445 ctx->current_typed = (GIrNode*) param;
1447 state_switch (ctx, STATE_FUNCTION_RETURN);
1449 switch (ctx->current_node->type)
1451 case G_IR_NODE_FUNCTION:
1452 case G_IR_NODE_CALLBACK:
1454 GIrNodeFunction *func = (GIrNodeFunction *)ctx->current_node;
1455 func->result = param;
1458 case G_IR_NODE_SIGNAL:
1460 GIrNodeSignal *signal = (GIrNodeSignal *)ctx->current_node;
1461 signal->result = param;
1464 case G_IR_NODE_VFUNC:
1466 GIrNodeVFunc *vfunc = (GIrNodeVFunc *)ctx->current_node;
1467 vfunc->result = param;
1471 g_assert_not_reached ();
1481 start_glib_signal (GMarkupParseContext *context,
1482 const gchar *element_name,
1483 const gchar **attribute_names,
1484 const gchar **attribute_values,
1488 if (strcmp (element_name, "glib:signal") == 0 &&
1489 (ctx->state == STATE_CLASS ||
1490 ctx->state == STATE_INTERFACE))
1494 const gchar *no_recurse;
1495 const gchar *detailed;
1496 const gchar *action;
1497 const gchar *no_hooks;
1498 const gchar *has_class_closure;
1500 name = find_attribute ("name", attribute_names, attribute_values);
1501 when = find_attribute ("when", attribute_names, attribute_values);
1502 no_recurse = find_attribute ("no-recurse", attribute_names, attribute_values);
1503 detailed = find_attribute ("detailed", attribute_names, attribute_values);
1504 action = find_attribute ("action", attribute_names, attribute_values);
1505 no_hooks = find_attribute ("no-hooks", attribute_names, attribute_values);
1506 has_class_closure = find_attribute ("has-class-closure", attribute_names, attribute_values);
1509 MISSING_ATTRIBUTE (context, error, element_name, "name");
1512 GIrNodeInterface *iface;
1513 GIrNodeSignal *signal;
1515 signal = (GIrNodeSignal *)g_ir_node_new (G_IR_NODE_SIGNAL);
1517 ((GIrNode *)signal)->name = g_strdup (name);
1519 signal->run_first = FALSE;
1520 signal->run_last = FALSE;
1521 signal->run_cleanup = FALSE;
1522 if (when == NULL || strcmp (when, "LAST") == 0)
1523 signal->run_last = TRUE;
1524 else if (strcmp (when, "FIRST") == 0)
1525 signal->run_first = TRUE;
1527 signal->run_cleanup = TRUE;
1529 if (no_recurse && strcmp (no_recurse, "1") == 0)
1530 signal->no_recurse = TRUE;
1532 signal->no_recurse = FALSE;
1533 if (detailed && strcmp (detailed, "1") == 0)
1534 signal->detailed = TRUE;
1536 signal->detailed = FALSE;
1537 if (action && strcmp (action, "1") == 0)
1538 signal->action = TRUE;
1540 signal->action = FALSE;
1541 if (no_hooks && strcmp (no_hooks, "1") == 0)
1542 signal->no_hooks = TRUE;
1544 signal->no_hooks = FALSE;
1545 if (has_class_closure && strcmp (has_class_closure, "1") == 0)
1546 signal->has_class_closure = TRUE;
1548 signal->has_class_closure = FALSE;
1550 iface = (GIrNodeInterface *)ctx->current_node;
1551 iface->members = g_list_append (iface->members, signal);
1553 ctx->current_node = (GIrNode *)signal;
1554 state_switch (ctx, STATE_FUNCTION);
1563 start_vfunc (GMarkupParseContext *context,
1564 const gchar *element_name,
1565 const gchar **attribute_names,
1566 const gchar **attribute_values,
1570 if (strcmp (element_name, "vfunc") == 0 &&
1571 (ctx->state == STATE_CLASS ||
1572 ctx->state == STATE_INTERFACE))
1575 const gchar *must_chain_up;
1576 const gchar *override;
1577 const gchar *is_class_closure;
1578 const gchar *offset;
1580 name = find_attribute ("name", attribute_names, attribute_values);
1581 must_chain_up = find_attribute ("must-chain-up", attribute_names, attribute_values);
1582 override = find_attribute ("override", attribute_names, attribute_values);
1583 is_class_closure = find_attribute ("is-class-closure", attribute_names, attribute_values);
1584 offset = find_attribute ("offset", attribute_names, attribute_values);
1587 MISSING_ATTRIBUTE (context, error, element_name, "name");
1590 GIrNodeInterface *iface;
1591 GIrNodeVFunc *vfunc;
1593 vfunc = (GIrNodeVFunc *)g_ir_node_new (G_IR_NODE_VFUNC);
1595 ((GIrNode *)vfunc)->name = g_strdup (name);
1597 if (must_chain_up && strcmp (must_chain_up, "1") == 0)
1598 vfunc->must_chain_up = TRUE;
1600 vfunc->must_chain_up = FALSE;
1602 if (override && strcmp (override, "always") == 0)
1604 vfunc->must_be_implemented = TRUE;
1605 vfunc->must_not_be_implemented = FALSE;
1607 else if (override && strcmp (override, "never") == 0)
1609 vfunc->must_be_implemented = FALSE;
1610 vfunc->must_not_be_implemented = TRUE;
1614 vfunc->must_be_implemented = FALSE;
1615 vfunc->must_not_be_implemented = FALSE;
1618 if (is_class_closure && strcmp (is_class_closure, "1") == 0)
1619 vfunc->is_class_closure = TRUE;
1621 vfunc->is_class_closure = FALSE;
1624 vfunc->offset = atoi (offset);
1628 iface = (GIrNodeInterface *)ctx->current_node;
1629 iface->members = g_list_append (iface->members, vfunc);
1631 ctx->current_node = (GIrNode *)vfunc;
1632 state_switch (ctx, STATE_FUNCTION);
1642 start_struct (GMarkupParseContext *context,
1643 const gchar *element_name,
1644 const gchar **attribute_names,
1645 const gchar **attribute_values,
1649 if (strcmp (element_name, "record") == 0 &&
1650 ctx->state == STATE_NAMESPACE)
1653 const gchar *deprecated;
1655 name = find_attribute ("name", attribute_names, attribute_values);
1656 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1659 MISSING_ATTRIBUTE (context, error, element_name, "name");
1662 GIrNodeStruct *struct_;
1664 struct_ = (GIrNodeStruct *) g_ir_node_new (G_IR_NODE_STRUCT);
1666 ((GIrNode *)struct_)->name = g_strdup (name);
1667 if (deprecated && strcmp (deprecated, "1") == 0)
1668 struct_->deprecated = TRUE;
1670 struct_->deprecated = FALSE;
1672 ctx->current_node = (GIrNode *)struct_;
1673 ctx->current_module->entries =
1674 g_list_append (ctx->current_module->entries, struct_);
1676 state_switch (ctx, STATE_STRUCT);
1685 start_union (GMarkupParseContext *context,
1686 const gchar *element_name,
1687 const gchar **attribute_names,
1688 const gchar **attribute_values,
1692 if (strcmp (element_name, "union") == 0 &&
1693 ctx->state == STATE_NAMESPACE)
1696 const gchar *deprecated;
1697 const gchar *typename;
1698 const gchar *typeinit;
1700 name = find_attribute ("name", attribute_names, attribute_values);
1701 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1702 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
1703 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
1706 MISSING_ATTRIBUTE (context, error, element_name, "name");
1709 GIrNodeUnion *union_;
1711 union_ = (GIrNodeUnion *) g_ir_node_new (G_IR_NODE_UNION);
1713 ((GIrNode *)union_)->name = g_strdup (name);
1714 union_->gtype_name = g_strdup (typename);
1715 union_->gtype_init = g_strdup (typeinit);
1716 if (deprecated && strcmp (deprecated, "1") == 0)
1717 union_->deprecated = TRUE;
1719 union_->deprecated = FALSE;
1721 ctx->current_node = (GIrNode *)union_;
1722 ctx->current_module->entries =
1723 g_list_append (ctx->current_module->entries, union_);
1725 state_switch (ctx, STATE_UNION);
1733 start_discriminator (GMarkupParseContext *context,
1734 const gchar *element_name,
1735 const gchar **attribute_names,
1736 const gchar **attribute_values,
1740 if (strcmp (element_name, "discriminator") == 0 &&
1741 ctx->state == STATE_UNION)
1744 const gchar *offset;
1746 type = find_attribute ("type", attribute_names, attribute_values);
1747 offset = find_attribute ("offset", attribute_names, attribute_values);
1749 MISSING_ATTRIBUTE (context, error, element_name, "type");
1750 else if (offset == NULL)
1751 MISSING_ATTRIBUTE (context, error, element_name, "offset");
1753 ((GIrNodeUnion *)ctx->current_node)->discriminator_type
1754 = parse_type (ctx, type);
1755 ((GIrNodeUnion *)ctx->current_node)->discriminator_offset
1765 extern GLogLevelFlags logged_levels;
1768 start_element_handler (GMarkupParseContext *context,
1769 const gchar *element_name,
1770 const gchar **attribute_names,
1771 const gchar **attribute_values,
1775 ParseContext *ctx = user_data;
1776 gint line_number, char_number;
1778 if (logged_levels & G_LOG_LEVEL_DEBUG)
1780 GString *tags = g_string_new ("");
1782 for (i = 0; attribute_names[i]; i++)
1783 g_string_append_printf (tags, "%s=\"%s\" ",
1785 attribute_values[i]);
1789 g_string_insert_c (tags, 0, ' ');
1790 g_string_truncate (tags, tags->len - 1);
1792 g_debug ("<%s%s>", element_name, tags->str);
1793 g_string_free (tags, TRUE);
1796 switch (element_name[0])
1799 if (ctx->state == STATE_NAMESPACE && strcmp (element_name, "alias") == 0)
1801 state_switch (ctx, STATE_ALIAS);
1806 if (start_enum (context, element_name,
1807 attribute_names, attribute_values,
1812 if (start_function (context, element_name,
1813 attribute_names, attribute_values,
1816 else if (start_constant (context, element_name,
1817 attribute_names, attribute_values,
1820 else if (start_class (context, element_name,
1821 attribute_names, attribute_values,
1824 else if (strcmp (element_name, "class") == 0 &&
1825 ctx->state == STATE_REQUIRES)
1829 name = find_attribute ("name", attribute_names, attribute_values);
1832 MISSING_ATTRIBUTE (context, error, element_name, "name");
1835 GIrNodeInterface *iface;
1837 iface = (GIrNodeInterface *)ctx->current_node;
1838 iface ->prerequisites = g_list_append (iface->prerequisites, g_strdup (name));
1846 if (start_discriminator (context, element_name,
1847 attribute_names, attribute_values,
1853 if (start_enum (context, element_name,
1854 attribute_names, attribute_values,
1857 else if (start_errordomain (context, element_name,
1858 attribute_names, attribute_values,
1864 if (start_function (context, element_name,
1865 attribute_names, attribute_values,
1868 else if (start_field (context, element_name,
1869 attribute_names, attribute_values,
1875 if (start_glib_boxed (context, element_name,
1876 attribute_names, attribute_values,
1879 else if (start_glib_signal (context, element_name,
1880 attribute_names, attribute_values,
1883 else if (start_glib_boxed (context, element_name,
1884 attribute_names, attribute_values,
1890 if (start_interface (context, element_name,
1891 attribute_names, attribute_values,
1894 if (strcmp (element_name, "implements") == 0 &&
1895 ctx->state == STATE_CLASS)
1897 state_switch (ctx, STATE_IMPLEMENTS);
1901 else if (strcmp (element_name, "interface") == 0 &&
1902 ctx->state == STATE_IMPLEMENTS)
1906 name = find_attribute ("name", attribute_names, attribute_values);
1909 MISSING_ATTRIBUTE (context, error, element_name, "name");
1912 GIrNodeInterface *iface;
1914 iface = (GIrNodeInterface *)ctx->current_node;
1915 iface ->interfaces = g_list_append (iface->interfaces, g_strdup (name));
1920 else if (strcmp (element_name, "interface") == 0 &&
1921 ctx->state == STATE_REQUIRES)
1925 name = find_attribute ("name", attribute_names, attribute_values);
1928 MISSING_ATTRIBUTE (context, error, element_name, "name");
1931 GIrNodeInterface *iface;
1933 iface = (GIrNodeInterface *)ctx->current_node;
1934 iface ->prerequisites = g_list_append (iface->prerequisites, g_strdup (name));
1942 if (start_function (context, element_name,
1943 attribute_names, attribute_values,
1946 else if (start_member (context, element_name,
1947 attribute_names, attribute_values,
1953 if (strcmp (element_name, "namespace") == 0 && ctx->state == STATE_REPOSITORY)
1955 const gchar *name, *shared_library;
1957 name = find_attribute ("name", attribute_names, attribute_values);
1958 shared_library = find_attribute ("shared-library", attribute_names, attribute_values);
1961 MISSING_ATTRIBUTE (context, error, element_name, "name");
1964 ctx->current_module = g_ir_module_new (name, shared_library);
1965 ctx->modules = g_list_append (ctx->modules, ctx->current_module);
1967 state_switch (ctx, STATE_NAMESPACE);
1975 if (start_property (context, element_name,
1976 attribute_names, attribute_values,
1979 else if (strcmp (element_name, "parameters") == 0 &&
1980 ctx->state == STATE_FUNCTION)
1982 state_switch (ctx, STATE_FUNCTION_PARAMETERS);
1986 else if (start_parameter (context, element_name,
1987 attribute_names, attribute_values,
1994 if (strcmp (element_name, "repository") == 0 && ctx->state == STATE_START)
1996 const gchar *version;
1998 version = find_attribute ("version", attribute_names, attribute_values);
2000 if (version == NULL)
2001 MISSING_ATTRIBUTE (context, error, element_name, "version");
2002 else if (strcmp (version, "1.0") != 0)
2005 G_MARKUP_ERROR_INVALID_CONTENT,
2006 "Unsupported version '%s'",
2009 state_switch (ctx, STATE_REPOSITORY);
2013 else if (start_return_value (context, element_name,
2014 attribute_names, attribute_values,
2017 else if (strcmp (element_name, "requires") == 0 &&
2018 ctx->state == STATE_INTERFACE)
2020 state_switch (ctx, STATE_REQUIRES);
2024 else if (start_struct (context, element_name,
2025 attribute_names, attribute_values,
2031 if (start_union (context, element_name,
2032 attribute_names, attribute_values,
2038 if (start_type (context, element_name,
2039 attribute_names, attribute_values,
2045 if (start_vfunc (context, element_name,
2046 attribute_names, attribute_values,
2052 g_markup_parse_context_get_position (context, &line_number, &char_number);
2056 G_MARKUP_ERROR_UNKNOWN_ELEMENT,
2057 "Unexpected start tag '%s' on line %d char %d; current state=%d",
2059 line_number, char_number, ctx->state);
2064 g_markup_parse_context_get_position (context, &line_number, &char_number);
2066 fprintf (stderr, "Error at line %d, character %d: %s\n", line_number, char_number, (*error)->message);
2067 backtrace_stderr ();
2072 require_one_of_end_elements (GMarkupParseContext *context,
2074 const char *actual_name,
2079 int line_number, char_number;
2080 const char *expected;
2081 gboolean matched = FALSE;
2083 va_start (args, error);
2085 while ((expected = va_arg (args, const char*)) != NULL)
2087 if (strcmp (expected, actual_name) == 0)
2099 g_markup_parse_context_get_position (context, &line_number, &char_number);
2102 G_MARKUP_ERROR_INVALID_CONTENT,
2103 "Unexpected end tag '%s' on line %d char %d; current state=%d",
2105 line_number, char_number, ctx->state);
2111 require_end_element (GMarkupParseContext *context,
2113 const char *expected_name,
2114 const char *actual_name,
2117 return require_one_of_end_elements (context, ctx, actual_name, error, expected_name, NULL);
2121 end_element_handler (GMarkupParseContext *context,
2122 const gchar *element_name,
2126 ParseContext *ctx = user_data;
2128 g_debug ("</%s>", element_name);
2134 /* no need to GError here, GMarkup already catches this */
2137 case STATE_REPOSITORY:
2138 state_switch (ctx, STATE_END);
2141 case STATE_NAMESPACE:
2142 if (require_end_element (context, ctx, "namespace", element_name, error))
2144 ctx->current_module = NULL;
2145 state_switch (ctx, STATE_REPOSITORY);
2150 if (require_end_element (context, ctx, "alias", element_name, error))
2152 state_switch (ctx, STATE_NAMESPACE);
2156 case STATE_FUNCTION_RETURN:
2157 if (strcmp ("type", element_name) == 0)
2159 if (require_end_element (context, ctx, "return-value", element_name, error))
2161 state_switch (ctx, STATE_FUNCTION);
2165 case STATE_FUNCTION_PARAMETERS:
2166 if (require_end_element (context, ctx, "parameters", element_name, error))
2168 state_switch (ctx, STATE_FUNCTION);
2172 case STATE_FUNCTION_PARAMETER:
2173 if (strcmp ("type", element_name) == 0)
2175 if (require_end_element (context, ctx, "parameter", element_name, error))
2177 state_switch (ctx, STATE_FUNCTION_PARAMETERS);
2181 case STATE_FUNCTION:
2182 if (ctx->current_node == g_list_last (ctx->current_module->entries)->data)
2184 ctx->current_node = NULL;
2185 state_switch (ctx, STATE_NAMESPACE);
2189 ctx->current_node = g_list_last (ctx->current_module->entries)->data;
2190 if (ctx->current_node->type == G_IR_NODE_INTERFACE)
2191 state_switch (ctx, STATE_INTERFACE);
2192 else if (ctx->current_node->type == G_IR_NODE_OBJECT)
2193 state_switch (ctx, STATE_CLASS);
2194 else if (ctx->current_node->type == G_IR_NODE_BOXED)
2195 state_switch (ctx, STATE_BOXED);
2196 else if (ctx->current_node->type == G_IR_NODE_STRUCT)
2197 state_switch (ctx, STATE_STRUCT);
2198 else if (ctx->current_node->type == G_IR_NODE_UNION)
2199 state_switch (ctx, STATE_UNION);
2202 int line_number, char_number;
2203 g_markup_parse_context_get_position (context, &line_number, &char_number);
2206 G_MARKUP_ERROR_INVALID_CONTENT,
2207 "Unexpected end tag '%s' on line %d char %d",
2209 line_number, char_number);
2214 case STATE_CLASS_FIELD:
2215 if (strcmp ("type", element_name) == 0)
2217 if (require_end_element (context, ctx, "field", element_name, error))
2219 state_switch (ctx, STATE_CLASS);
2223 case STATE_CLASS_PROPERTY:
2224 if (strcmp ("type", element_name) == 0)
2226 if (require_end_element (context, ctx, "property", element_name, error))
2228 state_switch (ctx, STATE_CLASS);
2233 if (require_end_element (context, ctx, "class", element_name, error))
2235 ctx->current_node = NULL;
2236 state_switch (ctx, STATE_NAMESPACE);
2240 case STATE_ERRORDOMAIN:
2241 if (require_end_element (context, ctx, "errordomain", element_name, error))
2243 ctx->current_node = NULL;
2244 state_switch (ctx, STATE_NAMESPACE);
2248 case STATE_INTERFACE_PROPERTY:
2249 if (strcmp ("type", element_name) == 0)
2251 if (require_end_element (context, ctx, "property", element_name, error))
2253 state_switch (ctx, STATE_INTERFACE);
2257 case STATE_INTERFACE_FIELD:
2258 if (strcmp ("type", element_name) == 0)
2260 if (require_end_element (context, ctx, "field", element_name, error))
2262 state_switch (ctx, STATE_INTERFACE);
2266 case STATE_INTERFACE:
2267 if (require_end_element (context, ctx, "interface", element_name, error))
2269 ctx->current_node = NULL;
2270 state_switch (ctx, STATE_NAMESPACE);
2275 if (strcmp ("member", element_name) == 0)
2277 else if (require_one_of_end_elements (context, ctx,
2278 element_name, error, "enumeration",
2281 ctx->current_node = NULL;
2282 state_switch (ctx, STATE_NAMESPACE);
2287 if (require_end_element (context, ctx, "glib:boxed", element_name, error))
2289 ctx->current_node = NULL;
2290 state_switch (ctx, STATE_NAMESPACE);
2294 case STATE_BOXED_FIELD:
2295 if (strcmp ("type", element_name) == 0)
2297 if (require_end_element (context, ctx, "field", element_name, error))
2299 state_switch (ctx, STATE_BOXED);
2303 case STATE_STRUCT_FIELD:
2304 if (strcmp ("type", element_name) == 0)
2306 if (require_end_element (context, ctx, "field", element_name, error))
2308 state_switch (ctx, STATE_STRUCT);
2313 if (require_end_element (context, ctx, "record", element_name, error))
2315 ctx->current_node = NULL;
2316 state_switch (ctx, STATE_NAMESPACE);
2320 if (require_end_element (context, ctx, "union", element_name, error))
2322 ctx->current_node = NULL;
2323 state_switch (ctx, STATE_NAMESPACE);
2326 case STATE_IMPLEMENTS:
2327 if (strcmp ("interface", element_name) == 0)
2329 if (require_end_element (context, ctx, "implements", element_name, error))
2330 state_switch (ctx, STATE_CLASS);
2332 case STATE_REQUIRES:
2333 if (require_end_element (context, ctx, "requires", element_name, error))
2334 state_switch (ctx, STATE_INTERFACE);
2336 case STATE_NAMESPACE_CONSTANT:
2337 case STATE_CLASS_CONSTANT:
2338 case STATE_INTERFACE_CONSTANT:
2339 if (strcmp ("type", element_name) == 0)
2341 if (require_end_element (context, ctx, "constant", element_name, error))
2343 ctx->current_node = NULL;
2346 case STATE_NAMESPACE_CONSTANT:
2347 state_switch (ctx, STATE_NAMESPACE);
2349 case STATE_CLASS_CONSTANT:
2350 state_switch (ctx, STATE_CLASS);
2352 case STATE_INTERFACE_CONSTANT:
2353 state_switch (ctx, STATE_INTERFACE);
2356 g_assert_not_reached ();
2362 g_error ("Unhandled state %d in end_element_handler\n", ctx->state);
2367 text_handler (GMarkupParseContext *context,
2373 /* FIXME warn about non-whitespace text */
2377 cleanup (GMarkupParseContext *context,
2381 ParseContext *ctx = user_data;
2383 int line_number, char_number;
2385 for (m = ctx->modules; m; m = m->next)
2386 g_ir_module_free (m->data);
2387 g_list_free (ctx->modules);
2388 ctx->modules = NULL;
2390 ctx->current_module = NULL;
2394 firstpass_start_element_handler (GMarkupParseContext *context,
2395 const gchar *element_name,
2396 const gchar **attribute_names,
2397 const gchar **attribute_values,
2401 ParseContext *ctx = user_data;
2403 if (strcmp (element_name, "alias") == 0)
2405 start_alias (context, element_name, attribute_names, attribute_values,
2411 firstpass_end_element_handler (GMarkupParseContext *context,
2412 const gchar *element_name,
2416 ParseContext *ctx = user_data;
2421 static GMarkupParser firstpass_parser =
2423 firstpass_start_element_handler,
2424 firstpass_end_element_handler,
2431 static GMarkupParser parser =
2433 start_element_handler,
2434 end_element_handler,
2441 g_ir_parse_string (const gchar *buffer,
2445 ParseContext ctx = { 0 };
2446 GMarkupParseContext *context;
2448 ctx.state = STATE_START;
2449 ctx.aliases = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
2451 context = g_markup_parse_context_new (&firstpass_parser, 0, &ctx, NULL);
2453 if (!g_markup_parse_context_parse (context, buffer, length, error))
2456 if (!g_markup_parse_context_end_parse (context, error))
2459 context = g_markup_parse_context_new (&parser, 0, &ctx, NULL);
2460 if (!g_markup_parse_context_parse (context, buffer, length, error))
2463 if (!g_markup_parse_context_end_parse (context, error))
2468 g_hash_table_destroy (ctx.aliases);
2470 g_markup_parse_context_free (context);
2476 g_ir_parse_file (const gchar *filename,
2483 g_debug ("[parsing] filename %s", filename);
2485 if (!g_file_get_contents (filename, &buffer, &length, error))
2488 modules = g_ir_parse_string (buffer, length, error);