1 /* GObject introspection: A parser for the XML GIR format
3 * Copyright (C) 2008 Philip Van Hoof
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
26 #include "girmodule.h"
40 STATE_FUNCTION_RETURN,
41 STATE_FUNCTION_PARAMETERS,
42 STATE_FUNCTION_PARAMETER, /* 10 */
47 STATE_INTERFACE_PROPERTY, /* 15 */
48 STATE_INTERFACE_FIELD,
52 STATE_BOXED_FIELD, /* 20 */
57 STATE_UNION_FIELD, /* 25 */
58 STATE_NAMESPACE_CONSTANT,
60 STATE_INTERFACE_CONSTANT,
65 typedef struct _ParseContext ParseContext;
69 ParseState prev_state;
74 GIrModule *current_module;
75 GIrNode *current_node;
76 GIrNode *current_typed;
80 #define MISSING_ATTRIBUTE(ctx,error,element,attribute) \
82 int line_number, char_number; \
83 g_markup_parse_context_get_position (context, &line_number, &char_number); \
86 G_MARKUP_ERROR_INVALID_CONTENT, \
87 "Line %d, character %d: The attribute '%s' on the element '%s' must be specified", \
88 line_number, char_number, attribute, element); \
92 backtrace_stderr (void)
99 size = backtrace (array, 50);
100 strings = (char**) backtrace_symbols (array, size);
102 fprintf (stderr, "--- BACKTRACE (%zd frames) ---\n", size);
104 for (i = 0; i < size; i++)
105 fprintf (stderr, "%s\n", strings[i]);
107 fprintf (stderr, "--- END BACKTRACE ---\n", size);
114 find_attribute (const gchar *name,
115 const gchar **attribute_names,
116 const gchar **attribute_values)
120 for (i = 0; attribute_names[i] != NULL; i++)
121 if (strcmp (attribute_names[i], name) == 0)
122 return attribute_values[i];
128 state_switch (ParseContext *ctx, ParseState newstate)
130 g_debug ("State: %d", newstate);
131 ctx->prev_state = ctx->state;
132 ctx->state = newstate;
135 static GIrNodeType * parse_type_internal (gchar *str, gchar **rest);
140 char *pointer = g_strdup ("any");
142 GIrNodeType *ret = parse_type_internal (pointer, &pointer_rest);
148 parse_type_internal (gchar *str, gchar **rest)
157 { "none", GI_TYPE_TAG_VOID, 0 },
158 { "any", GI_TYPE_TAG_VOID, 1 },
160 { "bool", GI_TYPE_TAG_BOOLEAN, 0 },
161 { "char", GI_TYPE_TAG_INT8, 0 },
162 { "int8", GI_TYPE_TAG_INT8, 0 },
163 { "uint8", GI_TYPE_TAG_UINT8, 0 },
164 { "int16", GI_TYPE_TAG_INT16, 0 },
165 { "uint16", GI_TYPE_TAG_UINT16, 0 },
166 { "int32", GI_TYPE_TAG_INT32, 0 },
167 { "uint32", GI_TYPE_TAG_UINT32, 0 },
168 { "int64", GI_TYPE_TAG_INT64, 0 },
169 { "uint64", GI_TYPE_TAG_UINT64, 0 },
170 { "int", GI_TYPE_TAG_INT, 0 },
171 { "uint", GI_TYPE_TAG_UINT, 0 },
172 { "long", GI_TYPE_TAG_LONG, 0 },
173 { "ulong", GI_TYPE_TAG_ULONG, 0 },
174 { "ssize_t", GI_TYPE_TAG_SSIZE, 0 },
175 { "ssize", GI_TYPE_TAG_SSIZE, 0 },
176 { "size_t", GI_TYPE_TAG_SIZE, 0 },
177 { "size", GI_TYPE_TAG_SIZE, 0 },
178 { "float", GI_TYPE_TAG_FLOAT, 0 },
179 { "double", GI_TYPE_TAG_DOUBLE, 0 },
180 { "utf8", GI_TYPE_TAG_UTF8, 1 },
181 { "filename", GI_TYPE_TAG_FILENAME,1 },
183 /* FIXME: merge - do we still want this? */
184 { "string", GI_TYPE_TAG_UTF8, 1 },
186 /* FIXME: Remove these */
187 { "void", GI_TYPE_TAG_VOID, 0 },
188 { "int8_t", GI_TYPE_TAG_INT8, 0 },
189 { "uint8_t", GI_TYPE_TAG_UINT8, 0 },
190 { "int16_t", GI_TYPE_TAG_INT16, 0 },
191 { "uint16_t", GI_TYPE_TAG_UINT16, 0 },
192 { "int32_t", GI_TYPE_TAG_INT32, 0 },
193 { "uint32_t", GI_TYPE_TAG_UINT32, 0 },
194 { "int64_t", GI_TYPE_TAG_INT64, 0 },
195 { "uint64_t", GI_TYPE_TAG_UINT64, 0 },
196 { "gpointer", GI_TYPE_TAG_VOID, 1 },
197 { "gboolean", GI_TYPE_TAG_BOOLEAN, 0 },
198 { "gchar", GI_TYPE_TAG_INT8, 0 },
199 { "guchar", GI_TYPE_TAG_UINT8, 0 },
200 { "gunichar", GI_TYPE_TAG_UINT32, 0 },
201 { "gint", GI_TYPE_TAG_INT, 0 },
202 { "guint", GI_TYPE_TAG_UINT, 0 },
203 { "gshort", GI_TYPE_TAG_INT16, 0 },
204 { "gushort", GI_TYPE_TAG_UINT16, 0 },
205 { "gint8", GI_TYPE_TAG_INT8, 0 },
206 { "guint8", GI_TYPE_TAG_UINT8, 0 },
207 { "gint16", GI_TYPE_TAG_INT16, 0 },
208 { "guint16", GI_TYPE_TAG_UINT16, 0 },
209 { "gint32", GI_TYPE_TAG_INT32, 0 },
210 { "guint32", GI_TYPE_TAG_UINT32, 0 },
211 { "gint64", GI_TYPE_TAG_INT64, 0 },
212 { "guint64", GI_TYPE_TAG_UINT64, 0 },
213 { "glong", GI_TYPE_TAG_LONG, 0 },
214 { "gulong", GI_TYPE_TAG_ULONG, 0 },
215 { "gssize", GI_TYPE_TAG_SSIZE, 0 },
216 { "gsize", GI_TYPE_TAG_SIZE, 0 },
217 { "gfloat", GI_TYPE_TAG_FLOAT, 0 },
218 { "gdouble", GI_TYPE_TAG_DOUBLE, 0 },
219 { "gchar*", GI_TYPE_TAG_UTF8, 1 }
222 gint n_basic = G_N_ELEMENTS (basic);
227 type = (GIrNodeType *)g_ir_node_new (G_IR_NODE_TYPE);
229 str = g_strstrip (str);
231 type->unparsed = g_strdup (str);
234 for (i = 0; i < n_basic; i++)
236 if (g_str_has_prefix (*rest, basic[i].str))
238 type->is_basic = TRUE;
239 type->tag = basic[i].tag;
240 type->is_pointer = basic[i].pointer;
242 *rest += strlen(basic[i].str);
243 *rest = g_strchug (*rest);
244 if (**rest == '*' && !type->is_pointer)
246 type->is_pointer = TRUE;
255 /* found a basic type */;
256 else if (g_str_has_prefix (*rest, "GList") ||
257 g_str_has_prefix (*rest, "GSList"))
259 if (g_str_has_prefix (*rest, "GList"))
261 type->tag = GI_TYPE_TAG_GLIST;
262 type->is_glist = TRUE;
263 type->is_pointer = TRUE;
264 *rest += strlen ("GList");
268 type->tag = GI_TYPE_TAG_GSLIST;
269 type->is_gslist = TRUE;
270 type->is_pointer = TRUE;
271 *rest += strlen ("GSList");
274 *rest = g_strchug (*rest);
280 type->parameter_type1 = parse_type_internal (*rest, rest);
281 if (type->parameter_type1 == NULL)
284 *rest = g_strchug (*rest);
286 if ((*rest)[0] != '>')
292 type->parameter_type1 = create_pointer ();
295 else if (g_str_has_prefix (*rest, "GHashTable"))
297 type->tag = GI_TYPE_TAG_GHASH;
298 type->is_ghashtable = TRUE;
299 type->is_pointer = TRUE;
300 *rest += strlen ("GHashTable");
302 *rest = g_strchug (*rest);
308 type->parameter_type1 = parse_type_internal (*rest, rest);
309 if (type->parameter_type1 == NULL)
312 *rest = g_strchug (*rest);
314 if ((*rest)[0] != ',')
318 type->parameter_type2 = parse_type_internal (*rest, rest);
319 if (type->parameter_type2 == NULL)
322 if ((*rest)[0] != '>')
328 type->parameter_type1 = create_pointer ();
329 type->parameter_type2 = create_pointer ();
333 else if (g_str_has_prefix (*rest, "GError"))
335 type->tag = GI_TYPE_TAG_ERROR;
336 type->is_error = TRUE;
337 type->is_pointer = TRUE;
338 *rest += strlen ("GError");
340 *rest = g_strchug (*rest);
346 end = strchr (*rest, '>');
347 str = g_strndup (*rest, end - *rest);
348 type->errors = g_strsplit (str, ",", 0);
356 type->tag = GI_TYPE_TAG_INTERFACE;
357 type->is_interface = TRUE;
360 /* must be an interface type */
361 while (g_ascii_isalnum (**rest) ||
368 type->interface = g_strndup (start, *rest - start);
370 *rest = g_strchug (*rest);
373 type->is_pointer = TRUE;
378 *rest = g_strchug (*rest);
379 if (g_str_has_prefix (*rest, "["))
383 array = (GIrNodeType *)g_ir_node_new (G_IR_NODE_TYPE);
385 array->tag = GI_TYPE_TAG_ARRAY;
386 array->is_pointer = TRUE;
387 array->is_array = TRUE;
389 array->parameter_type1 = type;
391 array->zero_terminated = FALSE;
392 array->has_length = FALSE;
395 if (!g_str_has_prefix (*rest, "[]"))
397 gchar *end, *str, **opts;
399 end = strchr (*rest, ']');
400 str = g_strndup (*rest + 1, (end - *rest) - 1);
401 opts = g_strsplit (str, ",", 0);
405 for (i = 0; opts[i]; i++)
409 vals = g_strsplit (opts[i], "=", 0);
411 if (strcmp (vals[0], "zero-terminated") == 0)
412 array->zero_terminated = (strcmp (vals[1], "1") == 0);
413 else if (strcmp (vals[0], "length") == 0)
415 array->has_length = TRUE;
416 array->length = atoi (vals[1]);
429 g_assert (type->tag >= 0 && type->tag <= GI_TYPE_TAG_ERROR);
433 g_ir_node_free ((GIrNode *)type);
439 resolve_aliases (ParseContext *ctx, const gchar *type)
443 GSList *seen_values = NULL;
445 seen_values = g_slist_prepend (seen_values, (char*)type);
446 while (g_hash_table_lookup_extended (ctx->aliases, type, &orig, &value))
448 g_debug ("Resolved: %s => %s", type, value);
450 if (g_slist_find_custom (seen_values, type,
451 (GCompareFunc)strcmp) != NULL)
453 seen_values = g_slist_prepend (seen_values, (gchar*)type);
455 g_slist_free (seen_values);
460 parse_type (ParseContext *ctx, const gchar *type)
466 type = resolve_aliases (ctx, type);
467 str = g_strdup (type);
468 node = parse_type_internal (str, &rest);
470 g_debug ("Parsed type: %s => %d", type, node->tag);
476 start_glib_boxed (GMarkupParseContext *context,
477 const gchar *element_name,
478 const gchar **attribute_names,
479 const gchar **attribute_values,
484 const gchar *typename;
485 const gchar *typeinit;
486 const gchar *deprecated;
489 if (!(strcmp (element_name, "glib:boxed") == 0 &&
490 ctx->state == STATE_NAMESPACE))
493 name = find_attribute ("glib:name", attribute_names, attribute_values);
494 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
495 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
496 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
500 MISSING_ATTRIBUTE (context, error, element_name, "glib:name");
503 else if (typename == NULL)
505 MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
508 else if (typeinit == NULL)
510 MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
514 boxed = (GIrNodeBoxed *) g_ir_node_new (G_IR_NODE_BOXED);
516 ((GIrNode *)boxed)->name = g_strdup (name);
517 boxed->gtype_name = g_strdup (typename);
518 boxed->gtype_init = g_strdup (typeinit);
519 if (deprecated && strcmp (deprecated, "1") == 0)
520 boxed->deprecated = TRUE;
522 boxed->deprecated = FALSE;
524 ctx->current_node = (GIrNode *)boxed;
525 ctx->current_module->entries =
526 g_list_append (ctx->current_module->entries, boxed);
528 state_switch (ctx, STATE_BOXED);
534 start_function (GMarkupParseContext *context,
535 const gchar *element_name,
536 const gchar **attribute_names,
537 const gchar **attribute_values,
543 const gchar *deprecated;
544 GIrNodeFunction *function;
545 gboolean found = FALSE;
549 case STATE_NAMESPACE:
550 found = (strcmp (element_name, "function") == 0 ||
551 strcmp (element_name, "callback") == 0);
557 found = strcmp (element_name, "constructor") == 0;
559 case STATE_INTERFACE:
561 strcmp (element_name, "method") == 0 ||
562 strcmp (element_name, "callback") == 0);
571 name = find_attribute ("name", attribute_names, attribute_values);
572 symbol = find_attribute ("c:identifier", attribute_names, attribute_values);
573 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
577 MISSING_ATTRIBUTE (context, error, element_name, "name");
580 else if (strcmp (element_name, "callback") != 0 && symbol == NULL)
582 MISSING_ATTRIBUTE (context, error, element_name, "c:identifier");
586 function = (GIrNodeFunction *) g_ir_node_new (G_IR_NODE_FUNCTION);
588 ((GIrNode *)function)->name = g_strdup (name);
589 function->symbol = g_strdup (symbol);
590 function->parameters = NULL;
591 if (deprecated && strcmp (deprecated, "1") == 0)
592 function->deprecated = TRUE;
594 function->deprecated = FALSE;
596 if (strcmp (element_name, "method") == 0 ||
597 strcmp (element_name, "constructor") == 0)
599 function->is_method = TRUE;
601 if (strcmp (element_name, "constructor") == 0)
602 function->is_constructor = TRUE;
604 function->is_constructor = FALSE;
608 function->is_method = FALSE;
609 function->is_setter = FALSE;
610 function->is_getter = FALSE;
611 function->is_constructor = FALSE;
612 if (strcmp (element_name, "callback") == 0)
613 ((GIrNode *)function)->type = G_IR_NODE_CALLBACK;
616 if (ctx->current_node == NULL)
618 ctx->current_module->entries =
619 g_list_append (ctx->current_module->entries, function);
622 switch (ctx->current_node->type)
624 case G_IR_NODE_INTERFACE:
625 case G_IR_NODE_OBJECT:
627 GIrNodeInterface *iface;
629 iface = (GIrNodeInterface *)ctx->current_node;
630 iface->members = g_list_append (iface->members, function);
633 case G_IR_NODE_BOXED:
637 boxed = (GIrNodeBoxed *)ctx->current_node;
638 boxed->members = g_list_append (boxed->members, function);
641 case G_IR_NODE_STRUCT:
643 GIrNodeStruct *struct_;
645 struct_ = (GIrNodeStruct *)ctx->current_node;
646 struct_->members = g_list_append (struct_->members, function); }
648 case G_IR_NODE_UNION:
650 GIrNodeUnion *union_;
652 union_ = (GIrNodeUnion *)ctx->current_node;
653 union_->members = g_list_append (union_->members, function);
657 g_assert_not_reached ();
660 ctx->current_node = (GIrNode *)function;
661 state_switch (ctx, STATE_FUNCTION);
667 start_parameter (GMarkupParseContext *context,
668 const gchar *element_name,
669 const gchar **attribute_names,
670 const gchar **attribute_values,
675 const gchar *direction;
678 const gchar *optional;
680 const gchar *transfer;
683 if (!(strcmp (element_name, "parameter") == 0 &&
684 ctx->state == STATE_FUNCTION_PARAMETERS))
687 name = find_attribute ("name", attribute_names, attribute_values);
688 direction = find_attribute ("direction", attribute_names, attribute_values);
689 retval = find_attribute ("retval", attribute_names, attribute_values);
690 dipper = find_attribute ("dipper", attribute_names, attribute_values);
691 optional = find_attribute ("optional", attribute_names, attribute_values);
692 nullok = find_attribute ("null-ok", attribute_names, attribute_values);
693 transfer = find_attribute ("transfer", attribute_names, attribute_values);
698 param = (GIrNodeParam *)g_ir_node_new (G_IR_NODE_PARAM);
700 ctx->current_typed = (GIrNode*) param;
701 ctx->current_typed->name = g_strdup (name);
703 state_switch (ctx, STATE_FUNCTION_PARAMETER);
705 if (direction && strcmp (direction, "out") == 0)
710 else if (direction && strcmp (direction, "inout") == 0)
721 if (retval && strcmp (retval, "1") == 0)
722 param->retval = TRUE;
724 param->retval = FALSE;
726 if (dipper && strcmp (dipper, "1") == 0)
727 param->dipper = TRUE;
729 param->dipper = FALSE;
731 if (optional && strcmp (optional, "1") == 0)
732 param->optional = TRUE;
734 param->optional = FALSE;
736 if (nullok && strcmp (nullok, "1") == 0)
737 param->null_ok = TRUE;
739 param->null_ok = FALSE;
741 if (transfer && strcmp (transfer, "none") == 0)
743 param->transfer = FALSE;
744 param->shallow_transfer = FALSE;
746 else if (transfer && strcmp (transfer, "shallow") == 0)
748 param->transfer = FALSE;
749 param->shallow_transfer = TRUE;
755 if (strcmp (transfer, "full") != 0)
756 g_warning ("Unknown transfer %s", transfer);
758 param->transfer = TRUE;
760 else if (param->in && !param->out)
761 param->transfer = FALSE;
763 param->transfer = TRUE;
764 param->shallow_transfer = FALSE;
767 ((GIrNode *)param)->name = g_strdup (name);
769 switch (ctx->current_node->type)
771 case G_IR_NODE_FUNCTION:
772 case G_IR_NODE_CALLBACK:
774 GIrNodeFunction *func;
776 func = (GIrNodeFunction *)ctx->current_node;
777 func->parameters = g_list_append (func->parameters, param);
780 case G_IR_NODE_SIGNAL:
782 GIrNodeSignal *signal;
784 signal = (GIrNodeSignal *)ctx->current_node;
785 signal->parameters = g_list_append (signal->parameters, param);
788 case G_IR_NODE_VFUNC:
792 vfunc = (GIrNodeVFunc *)ctx->current_node;
793 vfunc->parameters = g_list_append (vfunc->parameters, param);
797 g_assert_not_reached ();
804 start_field (GMarkupParseContext *context,
805 const gchar *element_name,
806 const gchar **attribute_names,
807 const gchar **attribute_values,
812 const gchar *readable;
813 const gchar *writable;
825 case STATE_INTERFACE:
831 if (strcmp (element_name, "field") != 0)
834 name = find_attribute ("name", attribute_names, attribute_values);
835 readable = find_attribute ("readable", attribute_names, attribute_values);
836 writable = find_attribute ("writable", attribute_names, attribute_values);
837 bits = find_attribute ("bits", attribute_names, attribute_values);
838 branch = find_attribute ("branch", attribute_names, attribute_values);
839 offset = find_attribute ("offset", attribute_names, attribute_values);
843 MISSING_ATTRIBUTE (context, error, element_name, "name");
847 field = (GIrNodeField *)g_ir_node_new (G_IR_NODE_FIELD);
848 ctx->current_typed = (GIrNode*) field;
849 ((GIrNode *)field)->name = g_strdup (name);
850 if (readable && strcmp (readable, "1") == 0)
851 field->readable = TRUE;
853 field->readable = FALSE;
855 if (writable && strcmp (writable, "1") == 0)
856 field->writable = TRUE;
858 field->writable = FALSE;
861 field->bits = atoi (bits);
866 field->offset = atoi (offset);
870 switch (ctx->current_node->type)
872 case G_IR_NODE_OBJECT:
874 GIrNodeInterface *iface;
876 iface = (GIrNodeInterface *)ctx->current_node;
877 iface->members = g_list_append (iface->members, field);
878 state_switch (ctx, STATE_CLASS_FIELD);
881 case G_IR_NODE_INTERFACE:
883 GIrNodeInterface *iface;
885 iface = (GIrNodeInterface *)ctx->current_node;
886 iface->members = g_list_append (iface->members, field);
887 state_switch (ctx, STATE_INTERFACE_FIELD);
890 case G_IR_NODE_BOXED:
894 boxed = (GIrNodeBoxed *)ctx->current_node;
895 boxed->members = g_list_append (boxed->members, field);
896 state_switch (ctx, STATE_BOXED_FIELD);
899 case G_IR_NODE_STRUCT:
901 GIrNodeStruct *struct_;
903 struct_ = (GIrNodeStruct *)ctx->current_node;
904 struct_->members = g_list_append (struct_->members, field);
905 state_switch (ctx, STATE_STRUCT_FIELD);
908 case G_IR_NODE_UNION:
910 GIrNodeUnion *union_;
912 union_ = (GIrNodeUnion *)ctx->current_node;
913 union_->members = g_list_append (union_->members, field);
916 GIrNodeConstant *constant;
918 constant = (GIrNodeConstant *) g_ir_node_new (G_IR_NODE_CONSTANT);
919 ((GIrNode *)constant)->name = g_strdup (name);
920 constant->value = g_strdup (branch);
921 constant->type = union_->discriminator_type;
922 constant->deprecated = FALSE;
924 union_->discriminators = g_list_append (union_->discriminators, constant);
926 state_switch (ctx, STATE_UNION_FIELD);
930 g_assert_not_reached ();
937 start_alias (GMarkupParseContext *context,
938 const gchar *element_name,
939 const gchar **attribute_names,
940 const gchar **attribute_values,
948 name = find_attribute ("name", attribute_names, attribute_values);
951 MISSING_ATTRIBUTE (context, error, element_name, "name");
955 target = find_attribute ("target", attribute_names, attribute_values);
958 MISSING_ATTRIBUTE (context, error, element_name, "target");
962 g_hash_table_insert (ctx->aliases, g_strdup (name), g_strdup (target));
968 start_enum (GMarkupParseContext *context,
969 const gchar *element_name,
970 const gchar **attribute_names,
971 const gchar **attribute_values,
975 if ((strcmp (element_name, "enumeration") == 0 && ctx->state == STATE_NAMESPACE) ||
976 (strcmp (element_name, "bitfield") == 0 && ctx->state == STATE_NAMESPACE))
979 const gchar *typename;
980 const gchar *typeinit;
981 const gchar *deprecated;
983 name = find_attribute ("name", attribute_names, attribute_values);
984 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
985 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
986 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
989 MISSING_ATTRIBUTE (context, error, element_name, "name");
994 if (strcmp (element_name, "enumeration") == 0)
995 enum_ = (GIrNodeEnum *) g_ir_node_new (G_IR_NODE_ENUM);
997 enum_ = (GIrNodeEnum *) g_ir_node_new (G_IR_NODE_FLAGS);
998 ((GIrNode *)enum_)->name = g_strdup (name);
999 enum_->gtype_name = g_strdup (typename);
1000 enum_->gtype_init = g_strdup (typeinit);
1001 if (deprecated && strcmp (deprecated, "1") == 0)
1002 enum_->deprecated = TRUE;
1004 enum_->deprecated = FALSE;
1006 ctx->current_node = (GIrNode *) enum_;
1007 ctx->current_module->entries =
1008 g_list_append (ctx->current_module->entries, enum_);
1010 state_switch (ctx, STATE_ENUM);
1019 start_property (GMarkupParseContext *context,
1020 const gchar *element_name,
1021 const gchar **attribute_names,
1022 const gchar **attribute_values,
1026 if (strcmp (element_name, "property") == 0 &&
1027 (ctx->state == STATE_CLASS ||
1028 ctx->state == STATE_INTERFACE))
1031 const gchar *readable;
1032 const gchar *writable;
1033 const gchar *construct;
1034 const gchar *construct_only;
1036 name = find_attribute ("name", attribute_names, attribute_values);
1037 readable = find_attribute ("readable", attribute_names, attribute_values);
1038 writable = find_attribute ("writable", attribute_names, attribute_values);
1039 construct = find_attribute ("construct", attribute_names, attribute_values);
1040 construct_only = find_attribute ("construct-only", attribute_names, attribute_values);
1043 MISSING_ATTRIBUTE (context, error, element_name, "name");
1046 GIrNodeProperty *property;
1047 GIrNodeInterface *iface;
1049 property = (GIrNodeProperty *) g_ir_node_new (G_IR_NODE_PROPERTY);
1050 ctx->current_typed = (GIrNode*) property;
1052 ((GIrNode *)property)->name = g_strdup (name);
1054 if (readable && strcmp (readable, "1") == 0)
1055 property->readable = TRUE;
1057 property->readable = FALSE;
1058 if (writable && strcmp (writable, "1") == 0)
1059 property->writable = TRUE;
1061 property->writable = FALSE;
1062 if (construct && strcmp (construct, "1") == 0)
1063 property->construct = TRUE;
1065 property->construct = FALSE;
1066 if (construct_only && strcmp (construct_only, "1") == 0)
1067 property->construct_only = TRUE;
1069 property->construct_only = FALSE;
1071 iface = (GIrNodeInterface *)ctx->current_node;
1072 iface->members = g_list_append (iface->members, property);
1074 if (ctx->state == STATE_CLASS)
1075 state_switch (ctx, STATE_CLASS_PROPERTY);
1076 else if (ctx->state == STATE_INTERFACE)
1077 state_switch (ctx, STATE_INTERFACE_PROPERTY);
1079 g_assert_not_reached ();
1088 parse_value (const gchar *str)
1092 /* FIXME just a quick hack */
1093 shift_op = strstr (str, "<<");
1099 base = strtol (str, NULL, 10);
1100 shift = strtol (shift_op + 3, NULL, 10);
1102 return base << shift;
1105 return strtol (str, NULL, 10);
1111 start_member (GMarkupParseContext *context,
1112 const gchar *element_name,
1113 const gchar **attribute_names,
1114 const gchar **attribute_values,
1118 if (strcmp (element_name, "member") == 0 &&
1119 ctx->state == STATE_ENUM)
1123 const gchar *deprecated;
1125 name = find_attribute ("name", attribute_names, attribute_values);
1126 value = find_attribute ("value", attribute_names, attribute_values);
1127 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1130 MISSING_ATTRIBUTE (context, error, element_name, "name");
1134 GIrNodeValue *value_;
1136 value_ = (GIrNodeValue *) g_ir_node_new (G_IR_NODE_VALUE);
1138 ((GIrNode *)value_)->name = g_strdup (name);
1140 value_->value = parse_value (value);
1142 if (deprecated && strcmp (deprecated, "1") == 0)
1143 value_->deprecated = TRUE;
1145 value_->deprecated = FALSE;
1147 enum_ = (GIrNodeEnum *)ctx->current_node;
1148 enum_->values = g_list_append (enum_->values, value_);
1157 start_constant (GMarkupParseContext *context,
1158 const gchar *element_name,
1159 const gchar **attribute_names,
1160 const gchar **attribute_values,
1164 if (strcmp (element_name, "constant") == 0 &&
1165 (ctx->state == STATE_NAMESPACE ||
1166 ctx->state == STATE_CLASS ||
1167 ctx->state == STATE_INTERFACE))
1171 const gchar *deprecated;
1173 name = find_attribute ("name", attribute_names, attribute_values);
1174 value = find_attribute ("value", attribute_names, attribute_values);
1175 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1178 MISSING_ATTRIBUTE (context, error, element_name, "name");
1179 else if (value == NULL)
1180 MISSING_ATTRIBUTE (context, error, element_name, "value");
1183 GIrNodeConstant *constant;
1185 constant = (GIrNodeConstant *) g_ir_node_new (G_IR_NODE_CONSTANT);
1187 ((GIrNode *)constant)->name = g_strdup (name);
1188 constant->value = g_strdup (value);
1190 ctx->current_typed = (GIrNode*) constant;
1192 if (deprecated && strcmp (deprecated, "1") == 0)
1193 constant->deprecated = TRUE;
1195 constant->deprecated = FALSE;
1197 if (ctx->state == STATE_NAMESPACE)
1199 ctx->current_node = (GIrNode *) constant;
1200 ctx->current_module->entries =
1201 g_list_append (ctx->current_module->entries, constant);
1205 GIrNodeInterface *iface;
1207 iface = (GIrNodeInterface *)ctx->current_node;
1208 iface->members = g_list_append (iface->members, constant);
1213 case STATE_NAMESPACE:
1214 state_switch (ctx, STATE_NAMESPACE_CONSTANT);
1217 state_switch (ctx, STATE_CLASS_CONSTANT);
1219 case STATE_INTERFACE:
1220 state_switch (ctx, STATE_INTERFACE_CONSTANT);
1223 g_assert_not_reached ();
1234 start_errordomain (GMarkupParseContext *context,
1235 const gchar *element_name,
1236 const gchar **attribute_names,
1237 const gchar **attribute_values,
1241 if (strcmp (element_name, "errordomain") == 0 &&
1242 ctx->state == STATE_NAMESPACE)
1245 const gchar *getquark;
1247 const gchar *deprecated;
1249 name = find_attribute ("name", attribute_names, attribute_values);
1250 getquark = find_attribute ("get-quark", attribute_names, attribute_values);
1251 codes = find_attribute ("codes", attribute_names, attribute_values);
1252 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1255 MISSING_ATTRIBUTE (context, error, element_name, "name");
1256 else if (getquark == NULL)
1257 MISSING_ATTRIBUTE (context, error, element_name, "getquark");
1258 else if (codes == NULL)
1259 MISSING_ATTRIBUTE (context, error, element_name, "codes");
1262 GIrNodeErrorDomain *domain;
1264 domain = (GIrNodeErrorDomain *) g_ir_node_new (G_IR_NODE_ERROR_DOMAIN);
1266 ((GIrNode *)domain)->name = g_strdup (name);
1267 domain->getquark = g_strdup (getquark);
1268 domain->codes = g_strdup (codes);
1270 if (deprecated && strcmp (deprecated, "1") == 0)
1271 domain->deprecated = TRUE;
1273 domain->deprecated = FALSE;
1275 ctx->current_node = (GIrNode *) domain;
1276 ctx->current_module->entries =
1277 g_list_append (ctx->current_module->entries, domain);
1279 state_switch (ctx, STATE_ERRORDOMAIN);
1288 start_interface (GMarkupParseContext *context,
1289 const gchar *element_name,
1290 const gchar **attribute_names,
1291 const gchar **attribute_values,
1295 if (strcmp (element_name, "interface") == 0 &&
1296 ctx->state == STATE_NAMESPACE)
1299 const gchar *typename;
1300 const gchar *typeinit;
1301 const gchar *deprecated;
1303 name = find_attribute ("name", attribute_names, attribute_values);
1304 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
1305 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
1306 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1309 MISSING_ATTRIBUTE (context, error, element_name, "name");
1310 else if (typename == NULL)
1311 MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
1312 else if (typeinit == NULL)
1313 MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
1316 GIrNodeInterface *iface;
1318 iface = (GIrNodeInterface *) g_ir_node_new (G_IR_NODE_INTERFACE);
1319 ((GIrNode *)iface)->name = g_strdup (name);
1320 iface->gtype_name = g_strdup (typename);
1321 iface->gtype_init = g_strdup (typeinit);
1322 if (deprecated && strcmp (deprecated, "1") == 0)
1323 iface->deprecated = TRUE;
1325 iface->deprecated = FALSE;
1327 ctx->current_node = (GIrNode *) iface;
1328 ctx->current_module->entries =
1329 g_list_append (ctx->current_module->entries, iface);
1331 state_switch (ctx, STATE_INTERFACE);
1341 start_class (GMarkupParseContext *context,
1342 const gchar *element_name,
1343 const gchar **attribute_names,
1344 const gchar **attribute_values,
1348 if (strcmp (element_name, "class") == 0 &&
1349 ctx->state == STATE_NAMESPACE)
1352 const gchar *parent;
1353 const gchar *typename;
1354 const gchar *typeinit;
1355 const gchar *deprecated;
1357 name = find_attribute ("name", attribute_names, attribute_values);
1358 parent = find_attribute ("parent", attribute_names, attribute_values);
1359 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
1360 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
1361 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1364 MISSING_ATTRIBUTE (context, error, element_name, "name");
1365 else if (typename == NULL)
1366 MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
1367 else if (typeinit == NULL && strcmp (typename, "GObject"))
1368 MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
1371 GIrNodeInterface *iface;
1373 iface = (GIrNodeInterface *) g_ir_node_new (G_IR_NODE_OBJECT);
1374 ((GIrNode *)iface)->name = g_strdup (name);
1375 iface->gtype_name = g_strdup (typename);
1376 iface->gtype_init = g_strdup (typeinit);
1377 iface->parent = g_strdup (parent);
1378 if (deprecated && strcmp (deprecated, "1") == 0)
1379 iface->deprecated = TRUE;
1381 iface->deprecated = FALSE;
1383 ctx->current_node = (GIrNode *) iface;
1384 ctx->current_module->entries =
1385 g_list_append (ctx->current_module->entries, iface);
1387 state_switch (ctx, STATE_CLASS);
1396 start_type (GMarkupParseContext *context,
1397 const gchar *element_name,
1398 const gchar **attribute_names,
1399 const gchar **attribute_values,
1405 if (strcmp (element_name, "type") != 0)
1408 if (ctx->state == STATE_TYPE)
1410 else if (ctx->state == STATE_FUNCTION_PARAMETER ||
1411 ctx->state == STATE_FUNCTION_RETURN ||
1412 ctx->state == STATE_STRUCT_FIELD ||
1413 ctx->state == STATE_UNION_FIELD ||
1414 ctx->state == STATE_CLASS_PROPERTY ||
1415 ctx->state == STATE_CLASS_FIELD ||
1416 ctx->state == STATE_INTERFACE_FIELD ||
1417 ctx->state == STATE_INTERFACE_PROPERTY ||
1418 ctx->state == STATE_BOXED_FIELD ||
1419 ctx->state == STATE_NAMESPACE_CONSTANT ||
1420 ctx->state == STATE_CLASS_CONSTANT ||
1421 ctx->state == STATE_INTERFACE_CONSTANT
1424 state_switch (ctx, STATE_TYPE);
1425 ctx->type_depth = 1;
1428 /* FIXME handle recursive types */
1429 if (ctx->type_depth > 1)
1432 if (!ctx->current_typed)
1436 G_MARKUP_ERROR_INVALID_CONTENT,
1437 "The element <type> is invalid here");
1441 name = find_attribute ("name", attribute_names, attribute_values);
1444 MISSING_ATTRIBUTE (context, error, element_name, "name");
1446 switch (ctx->current_typed->type)
1448 case G_IR_NODE_PARAM:
1450 GIrNodeParam *param = (GIrNodeParam *)ctx->current_typed;
1451 param->type = parse_type (ctx, name);
1454 case G_IR_NODE_FIELD:
1456 GIrNodeField *field = (GIrNodeField *)ctx->current_typed;
1457 field->type = parse_type (ctx, name);
1460 case G_IR_NODE_PROPERTY:
1462 GIrNodeProperty *property = (GIrNodeProperty *) ctx->current_typed;
1463 property->type = parse_type (ctx, name);
1466 case G_IR_NODE_CONSTANT:
1468 GIrNodeConstant *constant = (GIrNodeConstant *)ctx->current_typed;
1469 constant->type = parse_type (ctx, name);
1473 g_printerr("current node is %d\n", ctx->current_node->type);
1474 g_assert_not_reached ();
1477 ctx->current_typed = NULL;
1482 start_return_value (GMarkupParseContext *context,
1483 const gchar *element_name,
1484 const gchar **attribute_names,
1485 const gchar **attribute_values,
1489 if (strcmp (element_name, "return-value") == 0 &&
1490 ctx->state == STATE_FUNCTION)
1492 GIrNodeParam *param;
1494 param = (GIrNodeParam *)g_ir_node_new (G_IR_NODE_PARAM);
1497 param->retval = TRUE;
1499 ctx->current_typed = (GIrNode*) param;
1501 state_switch (ctx, STATE_FUNCTION_RETURN);
1503 switch (ctx->current_node->type)
1505 case G_IR_NODE_FUNCTION:
1506 case G_IR_NODE_CALLBACK:
1508 GIrNodeFunction *func = (GIrNodeFunction *)ctx->current_node;
1509 func->result = param;
1512 case G_IR_NODE_SIGNAL:
1514 GIrNodeSignal *signal = (GIrNodeSignal *)ctx->current_node;
1515 signal->result = param;
1518 case G_IR_NODE_VFUNC:
1520 GIrNodeVFunc *vfunc = (GIrNodeVFunc *)ctx->current_node;
1521 vfunc->result = param;
1525 g_assert_not_reached ();
1535 start_implements (GMarkupParseContext *context,
1536 const gchar *element_name,
1537 const gchar **attribute_names,
1538 const gchar **attribute_values,
1542 GIrNodeInterface *iface;
1545 if (strcmp (element_name, "implements") != 0 ||
1546 !(ctx->state == STATE_CLASS))
1549 state_switch (ctx, STATE_IMPLEMENTS);
1551 name = find_attribute ("name", attribute_names, attribute_values);
1554 MISSING_ATTRIBUTE (context, error, element_name, "name");
1558 iface = (GIrNodeInterface *)ctx->current_node;
1559 iface->interfaces = g_list_append (iface->interfaces, g_strdup (name));
1565 start_glib_signal (GMarkupParseContext *context,
1566 const gchar *element_name,
1567 const gchar **attribute_names,
1568 const gchar **attribute_values,
1572 if (strcmp (element_name, "glib:signal") == 0 &&
1573 (ctx->state == STATE_CLASS ||
1574 ctx->state == STATE_INTERFACE))
1578 const gchar *no_recurse;
1579 const gchar *detailed;
1580 const gchar *action;
1581 const gchar *no_hooks;
1582 const gchar *has_class_closure;
1584 name = find_attribute ("name", attribute_names, attribute_values);
1585 when = find_attribute ("when", attribute_names, attribute_values);
1586 no_recurse = find_attribute ("no-recurse", attribute_names, attribute_values);
1587 detailed = find_attribute ("detailed", attribute_names, attribute_values);
1588 action = find_attribute ("action", attribute_names, attribute_values);
1589 no_hooks = find_attribute ("no-hooks", attribute_names, attribute_values);
1590 has_class_closure = find_attribute ("has-class-closure", attribute_names, attribute_values);
1593 MISSING_ATTRIBUTE (context, error, element_name, "name");
1596 GIrNodeInterface *iface;
1597 GIrNodeSignal *signal;
1599 signal = (GIrNodeSignal *)g_ir_node_new (G_IR_NODE_SIGNAL);
1601 ((GIrNode *)signal)->name = g_strdup (name);
1603 signal->run_first = FALSE;
1604 signal->run_last = FALSE;
1605 signal->run_cleanup = FALSE;
1606 if (when == NULL || strcmp (when, "LAST") == 0)
1607 signal->run_last = TRUE;
1608 else if (strcmp (when, "FIRST") == 0)
1609 signal->run_first = TRUE;
1611 signal->run_cleanup = TRUE;
1613 if (no_recurse && strcmp (no_recurse, "1") == 0)
1614 signal->no_recurse = TRUE;
1616 signal->no_recurse = FALSE;
1617 if (detailed && strcmp (detailed, "1") == 0)
1618 signal->detailed = TRUE;
1620 signal->detailed = FALSE;
1621 if (action && strcmp (action, "1") == 0)
1622 signal->action = TRUE;
1624 signal->action = FALSE;
1625 if (no_hooks && strcmp (no_hooks, "1") == 0)
1626 signal->no_hooks = TRUE;
1628 signal->no_hooks = FALSE;
1629 if (has_class_closure && strcmp (has_class_closure, "1") == 0)
1630 signal->has_class_closure = TRUE;
1632 signal->has_class_closure = FALSE;
1634 iface = (GIrNodeInterface *)ctx->current_node;
1635 iface->members = g_list_append (iface->members, signal);
1637 ctx->current_node = (GIrNode *)signal;
1638 state_switch (ctx, STATE_FUNCTION);
1647 start_vfunc (GMarkupParseContext *context,
1648 const gchar *element_name,
1649 const gchar **attribute_names,
1650 const gchar **attribute_values,
1654 if (strcmp (element_name, "vfunc") == 0 &&
1655 (ctx->state == STATE_CLASS ||
1656 ctx->state == STATE_INTERFACE))
1659 const gchar *must_chain_up;
1660 const gchar *override;
1661 const gchar *is_class_closure;
1662 const gchar *offset;
1664 name = find_attribute ("name", attribute_names, attribute_values);
1665 must_chain_up = find_attribute ("must-chain-up", attribute_names, attribute_values);
1666 override = find_attribute ("override", attribute_names, attribute_values);
1667 is_class_closure = find_attribute ("is-class-closure", attribute_names, attribute_values);
1668 offset = find_attribute ("offset", attribute_names, attribute_values);
1671 MISSING_ATTRIBUTE (context, error, element_name, "name");
1674 GIrNodeInterface *iface;
1675 GIrNodeVFunc *vfunc;
1677 vfunc = (GIrNodeVFunc *)g_ir_node_new (G_IR_NODE_VFUNC);
1679 ((GIrNode *)vfunc)->name = g_strdup (name);
1681 if (must_chain_up && strcmp (must_chain_up, "1") == 0)
1682 vfunc->must_chain_up = TRUE;
1684 vfunc->must_chain_up = FALSE;
1686 if (override && strcmp (override, "always") == 0)
1688 vfunc->must_be_implemented = TRUE;
1689 vfunc->must_not_be_implemented = FALSE;
1691 else if (override && strcmp (override, "never") == 0)
1693 vfunc->must_be_implemented = FALSE;
1694 vfunc->must_not_be_implemented = TRUE;
1698 vfunc->must_be_implemented = FALSE;
1699 vfunc->must_not_be_implemented = FALSE;
1702 if (is_class_closure && strcmp (is_class_closure, "1") == 0)
1703 vfunc->is_class_closure = TRUE;
1705 vfunc->is_class_closure = FALSE;
1708 vfunc->offset = atoi (offset);
1712 iface = (GIrNodeInterface *)ctx->current_node;
1713 iface->members = g_list_append (iface->members, vfunc);
1715 ctx->current_node = (GIrNode *)vfunc;
1716 state_switch (ctx, STATE_FUNCTION);
1726 start_struct (GMarkupParseContext *context,
1727 const gchar *element_name,
1728 const gchar **attribute_names,
1729 const gchar **attribute_values,
1733 if (strcmp (element_name, "record") == 0 &&
1734 ctx->state == STATE_NAMESPACE)
1737 const gchar *deprecated;
1739 name = find_attribute ("name", attribute_names, attribute_values);
1740 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1743 MISSING_ATTRIBUTE (context, error, element_name, "name");
1746 GIrNodeStruct *struct_;
1748 struct_ = (GIrNodeStruct *) g_ir_node_new (G_IR_NODE_STRUCT);
1750 ((GIrNode *)struct_)->name = g_strdup (name);
1751 if (deprecated && strcmp (deprecated, "1") == 0)
1752 struct_->deprecated = TRUE;
1754 struct_->deprecated = FALSE;
1756 ctx->current_node = (GIrNode *)struct_;
1757 ctx->current_module->entries =
1758 g_list_append (ctx->current_module->entries, struct_);
1760 state_switch (ctx, STATE_STRUCT);
1769 start_union (GMarkupParseContext *context,
1770 const gchar *element_name,
1771 const gchar **attribute_names,
1772 const gchar **attribute_values,
1776 if (strcmp (element_name, "union") == 0 &&
1777 ctx->state == STATE_NAMESPACE)
1780 const gchar *deprecated;
1781 const gchar *typename;
1782 const gchar *typeinit;
1784 name = find_attribute ("name", attribute_names, attribute_values);
1785 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1786 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
1787 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
1790 MISSING_ATTRIBUTE (context, error, element_name, "name");
1793 GIrNodeUnion *union_;
1795 union_ = (GIrNodeUnion *) g_ir_node_new (G_IR_NODE_UNION);
1797 ((GIrNode *)union_)->name = g_strdup (name);
1798 union_->gtype_name = g_strdup (typename);
1799 union_->gtype_init = g_strdup (typeinit);
1800 if (deprecated && strcmp (deprecated, "1") == 0)
1801 union_->deprecated = TRUE;
1803 union_->deprecated = FALSE;
1805 ctx->current_node = (GIrNode *)union_;
1806 ctx->current_module->entries =
1807 g_list_append (ctx->current_module->entries, union_);
1809 state_switch (ctx, STATE_UNION);
1817 start_discriminator (GMarkupParseContext *context,
1818 const gchar *element_name,
1819 const gchar **attribute_names,
1820 const gchar **attribute_values,
1824 if (strcmp (element_name, "discriminator") == 0 &&
1825 ctx->state == STATE_UNION)
1828 const gchar *offset;
1830 type = find_attribute ("type", attribute_names, attribute_values);
1831 offset = find_attribute ("offset", attribute_names, attribute_values);
1833 MISSING_ATTRIBUTE (context, error, element_name, "type");
1834 else if (offset == NULL)
1835 MISSING_ATTRIBUTE (context, error, element_name, "offset");
1837 ((GIrNodeUnion *)ctx->current_node)->discriminator_type
1838 = parse_type (ctx, type);
1839 ((GIrNodeUnion *)ctx->current_node)->discriminator_offset
1849 extern GLogLevelFlags logged_levels;
1852 start_element_handler (GMarkupParseContext *context,
1853 const gchar *element_name,
1854 const gchar **attribute_names,
1855 const gchar **attribute_values,
1859 ParseContext *ctx = user_data;
1860 gint line_number, char_number;
1862 if (logged_levels & G_LOG_LEVEL_DEBUG)
1864 GString *tags = g_string_new ("");
1866 for (i = 0; attribute_names[i]; i++)
1867 g_string_append_printf (tags, "%s=\"%s\" ",
1869 attribute_values[i]);
1873 g_string_insert_c (tags, 0, ' ');
1874 g_string_truncate (tags, tags->len - 1);
1876 g_debug ("<%s%s>", element_name, tags->str);
1877 g_string_free (tags, TRUE);
1880 switch (element_name[0])
1883 if (ctx->state == STATE_NAMESPACE && strcmp (element_name, "alias") == 0)
1885 state_switch (ctx, STATE_ALIAS);
1890 if (start_enum (context, element_name,
1891 attribute_names, attribute_values,
1896 if (start_function (context, element_name,
1897 attribute_names, attribute_values,
1900 else if (start_constant (context, element_name,
1901 attribute_names, attribute_values,
1904 else if (start_class (context, element_name,
1905 attribute_names, attribute_values,
1908 else if (strcmp (element_name, "class") == 0 &&
1909 ctx->state == STATE_REQUIRES)
1913 name = find_attribute ("name", attribute_names, attribute_values);
1916 MISSING_ATTRIBUTE (context, error, element_name, "name");
1919 GIrNodeInterface *iface;
1921 iface = (GIrNodeInterface *)ctx->current_node;
1922 iface ->prerequisites = g_list_append (iface->prerequisites, g_strdup (name));
1930 if (start_discriminator (context, element_name,
1931 attribute_names, attribute_values,
1937 if (start_enum (context, element_name,
1938 attribute_names, attribute_values,
1941 else if (start_errordomain (context, element_name,
1942 attribute_names, attribute_values,
1948 if (start_function (context, element_name,
1949 attribute_names, attribute_values,
1952 else if (start_field (context, element_name,
1953 attribute_names, attribute_values,
1959 if (start_glib_boxed (context, element_name,
1960 attribute_names, attribute_values,
1963 else if (start_glib_signal (context, element_name,
1964 attribute_names, attribute_values,
1970 if (strcmp (element_name, "include") == 0 &&
1971 ctx->state == STATE_REPOSITORY)
1973 state_switch (ctx, STATE_INCLUDE);
1976 if (start_interface (context, element_name,
1977 attribute_names, attribute_values,
1980 else if (start_implements (context, element_name,
1981 attribute_names, attribute_values,
1987 if (start_function (context, element_name,
1988 attribute_names, attribute_values,
1991 else if (start_member (context, element_name,
1992 attribute_names, attribute_values,
1998 if (strcmp (element_name, "namespace") == 0 && ctx->state == STATE_REPOSITORY)
2000 const gchar *name, *shared_library;
2002 name = find_attribute ("name", attribute_names, attribute_values);
2003 shared_library = find_attribute ("shared-library", attribute_names, attribute_values);
2006 MISSING_ATTRIBUTE (context, error, element_name, "name");
2009 ctx->current_module = g_ir_module_new (name, shared_library);
2010 ctx->modules = g_list_append (ctx->modules, ctx->current_module);
2012 state_switch (ctx, STATE_NAMESPACE);
2020 if (start_property (context, element_name,
2021 attribute_names, attribute_values,
2024 else if (strcmp (element_name, "parameters") == 0 &&
2025 ctx->state == STATE_FUNCTION)
2027 state_switch (ctx, STATE_FUNCTION_PARAMETERS);
2031 else if (start_parameter (context, element_name,
2032 attribute_names, attribute_values,
2039 if (strcmp (element_name, "repository") == 0 && ctx->state == STATE_START)
2041 const gchar *version;
2043 version = find_attribute ("version", attribute_names, attribute_values);
2045 if (version == NULL)
2046 MISSING_ATTRIBUTE (context, error, element_name, "version");
2047 else if (strcmp (version, "1.0") != 0)
2050 G_MARKUP_ERROR_INVALID_CONTENT,
2051 "Unsupported version '%s'",
2054 state_switch (ctx, STATE_REPOSITORY);
2058 else if (start_return_value (context, element_name,
2059 attribute_names, attribute_values,
2062 else if (strcmp (element_name, "requires") == 0 &&
2063 ctx->state == STATE_INTERFACE)
2065 state_switch (ctx, STATE_REQUIRES);
2069 else if (start_struct (context, element_name,
2070 attribute_names, attribute_values,
2076 if (start_union (context, element_name,
2077 attribute_names, attribute_values,
2083 if (start_type (context, element_name,
2084 attribute_names, attribute_values,
2090 if (start_vfunc (context, element_name,
2091 attribute_names, attribute_values,
2097 g_markup_parse_context_get_position (context, &line_number, &char_number);
2099 if (error && *error == NULL)
2102 G_MARKUP_ERROR_UNKNOWN_ELEMENT,
2103 "Unexpected start tag '%s' on line %d char %d; current state=%d",
2105 line_number, char_number, ctx->state);
2110 g_markup_parse_context_get_position (context, &line_number, &char_number);
2112 fprintf (stderr, "Error at line %d, character %d: %s\n", line_number, char_number, (*error)->message);
2113 backtrace_stderr ();
2118 require_one_of_end_elements (GMarkupParseContext *context,
2120 const char *actual_name,
2125 int line_number, char_number;
2126 const char *expected;
2127 gboolean matched = FALSE;
2129 va_start (args, error);
2131 while ((expected = va_arg (args, const char*)) != NULL)
2133 if (strcmp (expected, actual_name) == 0)
2145 g_markup_parse_context_get_position (context, &line_number, &char_number);
2148 G_MARKUP_ERROR_INVALID_CONTENT,
2149 "Unexpected end tag '%s' on line %d char %d; current state=%d",
2151 line_number, char_number, ctx->state);
2157 require_end_element (GMarkupParseContext *context,
2159 const char *expected_name,
2160 const char *actual_name,
2163 return require_one_of_end_elements (context, ctx, actual_name, error, expected_name, NULL);
2167 end_element_handler (GMarkupParseContext *context,
2168 const gchar *element_name,
2172 ParseContext *ctx = user_data;
2174 g_debug ("</%s>", element_name);
2180 /* no need to GError here, GMarkup already catches this */
2183 case STATE_REPOSITORY:
2184 state_switch (ctx, STATE_END);
2188 if (require_end_element (context, ctx, "include", element_name, error))
2190 state_switch (ctx, STATE_REPOSITORY);
2194 case STATE_NAMESPACE:
2195 if (require_end_element (context, ctx, "namespace", element_name, error))
2197 ctx->current_module = NULL;
2198 state_switch (ctx, STATE_REPOSITORY);
2203 if (require_end_element (context, ctx, "alias", element_name, error))
2205 state_switch (ctx, STATE_NAMESPACE);
2209 case STATE_FUNCTION_RETURN:
2210 if (strcmp ("type", element_name) == 0)
2212 if (require_end_element (context, ctx, "return-value", element_name, error))
2214 state_switch (ctx, STATE_FUNCTION);
2218 case STATE_FUNCTION_PARAMETERS:
2219 if (require_end_element (context, ctx, "parameters", element_name, error))
2221 state_switch (ctx, STATE_FUNCTION);
2225 case STATE_FUNCTION_PARAMETER:
2226 if (strcmp ("type", element_name) == 0)
2228 if (require_end_element (context, ctx, "parameter", element_name, error))
2230 state_switch (ctx, STATE_FUNCTION_PARAMETERS);
2234 case STATE_FUNCTION:
2235 if (ctx->current_node == g_list_last (ctx->current_module->entries)->data)
2237 ctx->current_node = NULL;
2238 state_switch (ctx, STATE_NAMESPACE);
2242 ctx->current_node = g_list_last (ctx->current_module->entries)->data;
2243 if (ctx->current_node->type == G_IR_NODE_INTERFACE)
2244 state_switch (ctx, STATE_INTERFACE);
2245 else if (ctx->current_node->type == G_IR_NODE_OBJECT)
2246 state_switch (ctx, STATE_CLASS);
2247 else if (ctx->current_node->type == G_IR_NODE_BOXED)
2248 state_switch (ctx, STATE_BOXED);
2249 else if (ctx->current_node->type == G_IR_NODE_STRUCT)
2250 state_switch (ctx, STATE_STRUCT);
2251 else if (ctx->current_node->type == G_IR_NODE_UNION)
2252 state_switch (ctx, STATE_UNION);
2255 int line_number, char_number;
2256 g_markup_parse_context_get_position (context, &line_number, &char_number);
2259 G_MARKUP_ERROR_INVALID_CONTENT,
2260 "Unexpected end tag '%s' on line %d char %d",
2262 line_number, char_number);
2267 case STATE_CLASS_FIELD:
2268 if (strcmp ("type", element_name) == 0)
2270 if (require_end_element (context, ctx, "field", element_name, error))
2272 state_switch (ctx, STATE_CLASS);
2276 case STATE_CLASS_PROPERTY:
2277 if (strcmp ("type", element_name) == 0)
2279 if (require_end_element (context, ctx, "property", element_name, error))
2281 state_switch (ctx, STATE_CLASS);
2286 if (require_end_element (context, ctx, "class", element_name, error))
2288 ctx->current_node = NULL;
2289 state_switch (ctx, STATE_NAMESPACE);
2293 case STATE_ERRORDOMAIN:
2294 if (require_end_element (context, ctx, "errordomain", element_name, error))
2296 ctx->current_node = NULL;
2297 state_switch (ctx, STATE_NAMESPACE);
2301 case STATE_INTERFACE_PROPERTY:
2302 if (strcmp ("type", element_name) == 0)
2304 if (require_end_element (context, ctx, "property", element_name, error))
2306 state_switch (ctx, STATE_INTERFACE);
2310 case STATE_INTERFACE_FIELD:
2311 if (strcmp ("type", element_name) == 0)
2313 if (require_end_element (context, ctx, "field", element_name, error))
2315 state_switch (ctx, STATE_INTERFACE);
2319 case STATE_INTERFACE:
2320 if (require_end_element (context, ctx, "interface", element_name, error))
2322 ctx->current_node = NULL;
2323 state_switch (ctx, STATE_NAMESPACE);
2328 if (strcmp ("member", element_name) == 0)
2330 else if (require_one_of_end_elements (context, ctx,
2331 element_name, error, "enumeration",
2334 ctx->current_node = NULL;
2335 state_switch (ctx, STATE_NAMESPACE);
2340 if (require_end_element (context, ctx, "glib:boxed", element_name, error))
2342 ctx->current_node = NULL;
2343 state_switch (ctx, STATE_NAMESPACE);
2347 case STATE_BOXED_FIELD:
2348 if (strcmp ("type", element_name) == 0)
2350 if (require_end_element (context, ctx, "field", element_name, error))
2352 state_switch (ctx, STATE_BOXED);
2356 case STATE_STRUCT_FIELD:
2357 if (strcmp ("type", element_name) == 0)
2359 if (require_end_element (context, ctx, "field", element_name, error))
2361 state_switch (ctx, STATE_STRUCT);
2366 if (require_end_element (context, ctx, "record", element_name, error))
2368 ctx->current_node = NULL;
2369 state_switch (ctx, STATE_NAMESPACE);
2373 case STATE_UNION_FIELD:
2374 if (strcmp ("type", element_name) == 0)
2376 if (require_end_element (context, ctx, "field", element_name, error))
2378 state_switch (ctx, STATE_UNION);
2383 if (require_end_element (context, ctx, "union", element_name, error))
2385 ctx->current_node = NULL;
2386 state_switch (ctx, STATE_NAMESPACE);
2389 case STATE_IMPLEMENTS:
2390 if (strcmp ("interface", element_name) == 0)
2392 if (require_end_element (context, ctx, "implements", element_name, error))
2393 state_switch (ctx, STATE_CLASS);
2395 case STATE_REQUIRES:
2396 if (require_end_element (context, ctx, "requires", element_name, error))
2397 state_switch (ctx, STATE_INTERFACE);
2399 case STATE_NAMESPACE_CONSTANT:
2400 case STATE_CLASS_CONSTANT:
2401 case STATE_INTERFACE_CONSTANT:
2402 if (strcmp ("type", element_name) == 0)
2404 if (require_end_element (context, ctx, "constant", element_name, error))
2406 ctx->current_node = NULL;
2409 case STATE_NAMESPACE_CONSTANT:
2410 state_switch (ctx, STATE_NAMESPACE);
2412 case STATE_CLASS_CONSTANT:
2413 state_switch (ctx, STATE_CLASS);
2415 case STATE_INTERFACE_CONSTANT:
2416 state_switch (ctx, STATE_INTERFACE);
2419 g_assert_not_reached ();
2425 if (strcmp ("type", element_name) == 0)
2427 if (ctx->type_depth == 1)
2428 state_switch (ctx, ctx->prev_state);
2430 ctx->type_depth -= 1;
2434 g_error ("Unhandled state %d in end_element_handler\n", ctx->state);
2439 text_handler (GMarkupParseContext *context,
2445 /* FIXME warn about non-whitespace text */
2449 cleanup (GMarkupParseContext *context,
2453 ParseContext *ctx = user_data;
2455 int line_number, char_number;
2457 for (m = ctx->modules; m; m = m->next)
2458 g_ir_module_free (m->data);
2459 g_list_free (ctx->modules);
2460 ctx->modules = NULL;
2462 ctx->current_module = NULL;
2466 firstpass_start_element_handler (GMarkupParseContext *context,
2467 const gchar *element_name,
2468 const gchar **attribute_names,
2469 const gchar **attribute_values,
2473 ParseContext *ctx = user_data;
2475 if (strcmp (element_name, "alias") == 0)
2477 start_alias (context, element_name, attribute_names, attribute_values,
2483 firstpass_end_element_handler (GMarkupParseContext *context,
2484 const gchar *element_name,
2488 ParseContext *ctx = user_data;
2493 static GMarkupParser firstpass_parser =
2495 firstpass_start_element_handler,
2496 firstpass_end_element_handler,
2503 static GMarkupParser parser =
2505 start_element_handler,
2506 end_element_handler,
2513 g_ir_parse_string (const gchar *buffer,
2517 ParseContext ctx = { 0 };
2518 GMarkupParseContext *context;
2520 ctx.state = STATE_START;
2521 ctx.aliases = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
2524 context = g_markup_parse_context_new (&firstpass_parser, 0, &ctx, NULL);
2526 if (!g_markup_parse_context_parse (context, buffer, length, error))
2529 if (!g_markup_parse_context_end_parse (context, error))
2532 context = g_markup_parse_context_new (&parser, 0, &ctx, NULL);
2533 if (!g_markup_parse_context_parse (context, buffer, length, error))
2536 if (!g_markup_parse_context_end_parse (context, error))
2541 g_hash_table_destroy (ctx.aliases);
2543 g_markup_parse_context_free (context);
2549 g_ir_parse_file (const gchar *filename,
2556 g_debug ("[parsing] filename %s", filename);
2558 if (!g_file_get_contents (filename, &buffer, &length, error))
2561 modules = g_ir_parse_string (buffer, length, error);