1 /* GObject introspection: A parser for the XML GIR format
3 * Copyright (C) 2008 Philip Van Hoof
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
26 #include "girmodule.h"
40 STATE_FUNCTION_RETURN,
41 STATE_FUNCTION_PARAMETERS,
42 STATE_FUNCTION_PARAMETER, /* 10 */
47 STATE_INTERFACE_PROPERTY, /* 15 */
48 STATE_INTERFACE_FIELD,
52 STATE_BOXED_FIELD, /* 20 */
57 STATE_UNION_FIELD, /* 25 */
58 STATE_NAMESPACE_CONSTANT,
60 STATE_INTERFACE_CONSTANT,
65 typedef struct _ParseContext ParseContext;
69 ParseState prev_state;
71 const char * const*includes;
74 gboolean prefix_aliases;
78 const char *namespace;
79 GIrModule *current_module;
80 GIrNode *current_node;
81 GIrNode *current_typed;
86 start_alias (GMarkupParseContext *context,
87 const gchar *element_name,
88 const gchar **attribute_names,
89 const gchar **attribute_values,
94 firstpass_start_element_handler (GMarkupParseContext *context,
95 const gchar *element_name,
96 const gchar **attribute_names,
97 const gchar **attribute_values,
101 ParseContext *ctx = user_data;
103 if (strcmp (element_name, "alias") == 0)
105 start_alias (context, element_name, attribute_names, attribute_values,
111 firstpass_end_element_handler (GMarkupParseContext *context,
112 const gchar *element_name,
116 ParseContext *ctx = user_data;
120 static GMarkupParser firstpass_parser =
122 firstpass_start_element_handler,
123 firstpass_end_element_handler,
130 locate_gir (const char *name, const char * const* extra_paths)
132 const gchar *const *datadirs;
133 const gchar *const *dir;
137 gboolean firstpass = TRUE;
139 datadirs = g_get_system_data_dirs ();
141 girname = g_strdup_printf ("%s.gir", name);
143 for (dir = datadirs; *dir; dir++)
145 path = g_build_filename (*dir, "gir", girname, NULL);
146 if (g_file_test (path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))
151 if (extra_paths != NULL)
153 for (dir = extra_paths; *dir; dir++)
155 path = g_build_filename (*dir, girname, NULL);
156 if (g_file_test (path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))
166 #define MISSING_ATTRIBUTE(ctx,error,element,attribute) \
168 int line_number, char_number; \
169 g_markup_parse_context_get_position (context, &line_number, &char_number); \
170 g_set_error (error, \
172 G_MARKUP_ERROR_INVALID_CONTENT, \
173 "Line %d, character %d: The attribute '%s' on the element '%s' must be specified", \
174 line_number, char_number, attribute, element); \
178 backtrace_stderr (void)
186 size = backtrace (array, 50);
187 strings = (char**) backtrace_symbols (array, size);
189 fprintf (stderr, "--- BACKTRACE (%zd frames) ---\n", size);
191 for (i = 0; i < size; i++)
192 fprintf (stderr, "%s\n", strings[i]);
194 fprintf (stderr, "--- END BACKTRACE ---\n", size);
202 find_attribute (const gchar *name,
203 const gchar **attribute_names,
204 const gchar **attribute_values)
208 for (i = 0; attribute_names[i] != NULL; i++)
209 if (strcmp (attribute_names[i], name) == 0)
210 return attribute_values[i];
216 state_switch (ParseContext *ctx, ParseState newstate)
218 g_debug ("State: %d", newstate);
219 ctx->prev_state = ctx->state;
220 ctx->state = newstate;
223 static GIrNodeType * parse_type_internal (const gchar *str, gchar **next, gboolean in_glib);
231 static BasicTypeInfo basic_types[] = {
232 { "none", GI_TYPE_TAG_VOID, 0 },
233 { "any", GI_TYPE_TAG_VOID, 1 },
235 { "bool", GI_TYPE_TAG_BOOLEAN, 0 },
236 { "char", GI_TYPE_TAG_INT8, 0 },
237 { "int8", GI_TYPE_TAG_INT8, 0 },
238 { "uint8", GI_TYPE_TAG_UINT8, 0 },
239 { "int16", GI_TYPE_TAG_INT16, 0 },
240 { "uint16", GI_TYPE_TAG_UINT16, 0 },
241 { "int32", GI_TYPE_TAG_INT32, 0 },
242 { "uint32", GI_TYPE_TAG_UINT32, 0 },
243 { "int64", GI_TYPE_TAG_INT64, 0 },
244 { "uint64", GI_TYPE_TAG_UINT64, 0 },
245 { "int", GI_TYPE_TAG_INT, 0 },
246 { "uint", GI_TYPE_TAG_UINT, 0 },
247 { "long", GI_TYPE_TAG_LONG, 0 },
248 { "ulong", GI_TYPE_TAG_ULONG, 0 },
249 { "ssize_t", GI_TYPE_TAG_SSIZE, 0 },
250 { "ssize", GI_TYPE_TAG_SSIZE, 0 },
251 { "size_t", GI_TYPE_TAG_SIZE, 0 },
252 { "size", GI_TYPE_TAG_SIZE, 0 },
253 { "float", GI_TYPE_TAG_FLOAT, 0 },
254 { "double", GI_TYPE_TAG_DOUBLE, 0 },
255 { "time_t", GI_TYPE_TAG_TIME_T, 0 },
256 { "utf8", GI_TYPE_TAG_UTF8, 1 },
257 { "filename", GI_TYPE_TAG_FILENAME,1 },
259 /* FIXME: merge - do we still want this? */
260 { "string", GI_TYPE_TAG_UTF8, 1 },
262 /* FIXME: Remove these */
263 { "void", GI_TYPE_TAG_VOID, 0 },
264 { "int8_t", GI_TYPE_TAG_INT8, 0 },
265 { "uint8_t", GI_TYPE_TAG_UINT8, 0 },
266 { "int16_t", GI_TYPE_TAG_INT16, 0 },
267 { "uint16_t", GI_TYPE_TAG_UINT16, 0 },
268 { "int32_t", GI_TYPE_TAG_INT32, 0 },
269 { "uint32_t", GI_TYPE_TAG_UINT32, 0 },
270 { "int64_t", GI_TYPE_TAG_INT64, 0 },
271 { "uint64_t", GI_TYPE_TAG_UINT64, 0 },
272 { "gpointer", GI_TYPE_TAG_VOID, 1 },
273 { "gboolean", GI_TYPE_TAG_BOOLEAN, 0 },
274 { "gchar", GI_TYPE_TAG_INT8, 0 },
275 { "guchar", GI_TYPE_TAG_UINT8, 0 },
276 { "gunichar", GI_TYPE_TAG_UINT32, 0 },
277 { "gint", GI_TYPE_TAG_INT, 0 },
278 { "guint", GI_TYPE_TAG_UINT, 0 },
279 { "gshort", GI_TYPE_TAG_INT16, 0 },
280 { "gushort", GI_TYPE_TAG_UINT16, 0 },
281 { "gint8", GI_TYPE_TAG_INT8, 0 },
282 { "guint8", GI_TYPE_TAG_UINT8, 0 },
283 { "gint16", GI_TYPE_TAG_INT16, 0 },
284 { "guint16", GI_TYPE_TAG_UINT16, 0 },
285 { "gint32", GI_TYPE_TAG_INT32, 0 },
286 { "guint32", GI_TYPE_TAG_UINT32, 0 },
287 { "gint64", GI_TYPE_TAG_INT64, 0 },
288 { "guint64", GI_TYPE_TAG_UINT64, 0 },
289 { "glong", GI_TYPE_TAG_LONG, 0 },
290 { "gulong", GI_TYPE_TAG_ULONG, 0 },
291 { "gssize", GI_TYPE_TAG_SSIZE, 0 },
292 { "gsize", GI_TYPE_TAG_SIZE, 0 },
293 { "gfloat", GI_TYPE_TAG_FLOAT, 0 },
294 { "gdouble", GI_TYPE_TAG_DOUBLE, 0 },
295 { "gchar*", GI_TYPE_TAG_UTF8, 1 }
298 static const BasicTypeInfo *
299 parse_basic (const char *str)
302 gint n_basic = G_N_ELEMENTS (basic_types);
303 gchar *temporary_type = NULL;
307 for (i = 0; i < n_basic; i++)
309 if (g_str_has_prefix (str, basic_types[i].str))
310 return &(basic_types[i]);
316 parse_type_internal (const gchar *str, char **next, gboolean in_glib)
318 const BasicTypeInfo *basic;
320 char *temporary_type = NULL;
322 type = (GIrNodeType *)g_ir_node_new (G_IR_NODE_TYPE);
324 type->unparsed = g_strdup (str);
326 basic = parse_basic (str);
329 type->is_basic = TRUE;
330 type->tag = basic->tag;
331 type->is_pointer = basic->pointer;
333 str += strlen(basic->str);
337 /* If we're inside GLib, handle "List" by prefixing it with
338 * "GLib." so the parsing code below doesn't have to get more
342 if (g_str_has_prefix (str, "List<") ||
343 strcmp (str, "List") == 0)
345 temporary_type = g_strdup_printf ("GLib.List%s", str + 4);
346 str = temporary_type;
348 else if (g_str_has_prefix (str, "SList<") ||
349 strcmp (str, "SList") == 0)
351 temporary_type = g_strdup_printf ("GLib.SList%s", str + 5);
352 str = temporary_type;
354 else if (g_str_has_prefix (str, "HashTable<") ||
355 strcmp (str, "HashTable") == 0)
357 temporary_type = g_strdup_printf ("GLib.HashTable%s", str + 9);
358 str = temporary_type;
360 else if (g_str_has_prefix (str, "Error<") ||
361 strcmp (str, "Error") == 0)
363 temporary_type = g_strdup_printf ("GLib.Error%s", str + 5);
364 str = temporary_type;
369 /* found a basic type */;
370 else if (g_str_has_prefix (str, "GLib.List") ||
371 g_str_has_prefix (str, "GLib.SList"))
373 str += strlen ("GLib.");
374 if (g_str_has_prefix (str, "List"))
376 type->tag = GI_TYPE_TAG_GLIST;
377 type->is_glist = TRUE;
378 type->is_pointer = TRUE;
379 str += strlen ("List");
383 type->tag = GI_TYPE_TAG_GSLIST;
384 type->is_gslist = TRUE;
385 type->is_pointer = TRUE;
386 str += strlen ("SList");
394 type->parameter_type1 = parse_type_internal (str, &rest, in_glib);
395 if (type->parameter_type1 == NULL)
405 type->parameter_type1 = parse_type_internal ("any", NULL, in_glib);
408 else if (g_str_has_prefix (str, "GLib.HashTable"))
410 str += strlen ("GLib.");
412 type->tag = GI_TYPE_TAG_GHASH;
413 type->is_ghashtable = TRUE;
414 type->is_pointer = TRUE;
415 str += strlen ("HashTable");
422 type->parameter_type1 = parse_type_internal (str, &rest, in_glib);
423 if (type->parameter_type1 == NULL)
431 type->parameter_type2 = parse_type_internal (str, &rest, in_glib);
432 if (type->parameter_type2 == NULL)
442 type->parameter_type1 = parse_type_internal ("any", NULL, in_glib);
443 type->parameter_type2 = parse_type_internal ("any", NULL, in_glib);
446 else if (g_str_has_prefix (str, "GLib.Error"))
448 str += strlen ("GLib.");
450 type->tag = GI_TYPE_TAG_ERROR;
451 type->is_error = TRUE;
452 type->is_pointer = TRUE;
453 str += strlen ("Error");
460 end = strchr (str, '>');
461 tmp = g_strndup (str, end - str);
462 type->errors = g_strsplit (tmp, ",", 0);
470 type->tag = GI_TYPE_TAG_INTERFACE;
471 type->is_interface = TRUE;
472 const char *start = str;
474 /* must be an interface type */
475 while (g_ascii_isalnum (*str) ||
482 type->interface = g_strndup (start, str - start);
485 if (g_str_has_prefix (str, "["))
490 array = (GIrNodeType *)g_ir_node_new (G_IR_NODE_TYPE);
492 array->tag = GI_TYPE_TAG_ARRAY;
493 array->is_pointer = TRUE;
494 array->is_array = TRUE;
496 array->parameter_type1 = type;
498 array->zero_terminated = FALSE;
499 array->has_length = FALSE;
502 if (!g_str_has_prefix (str, "[]"))
504 gchar *end, *tmp, **opts;
506 end = strchr (str, ']');
507 tmp = g_strndup (str + 1, (end - str) - 1);
508 opts = g_strsplit (tmp, ",", 0);
510 for (i = 0; opts[i]; i++)
514 vals = g_strsplit (opts[i], "=", 0);
516 if (strcmp (vals[0], "zero-terminated") == 0)
517 array->zero_terminated = (strcmp (vals[1], "1") == 0);
518 else if (strcmp (vals[0], "length") == 0)
520 array->has_length = TRUE;
521 array->length = atoi (vals[1]);
538 g_assert (type->tag >= 0 && type->tag <= GI_TYPE_TAG_ERROR);
539 g_free (temporary_type);
543 g_ir_node_free ((GIrNode *)type);
544 g_free (temporary_type);
549 resolve_aliases (ParseContext *ctx, const gchar *type)
553 GSList *seen_values = NULL;
555 seen_values = g_slist_prepend (seen_values, (char*)type);
556 while (g_hash_table_lookup_extended (ctx->aliases, type, &orig, &value))
558 g_debug ("Resolved: %s => %s", type, value);
560 if (g_slist_find_custom (seen_values, type,
561 (GCompareFunc)strcmp) != NULL)
563 seen_values = g_slist_prepend (seen_values, (gchar*)type);
565 g_slist_free (seen_values);
570 parse_type (ParseContext *ctx, const gchar *type)
574 const BasicTypeInfo *basic;
576 gboolean matched_special = FALSE;
578 in_glib = strcmp (ctx->namespace, "GLib") == 0;
580 /* Do not search aliases for basic types */
581 basic = parse_basic (type);
583 type = resolve_aliases (ctx, type);
585 node = parse_type_internal (type, NULL, in_glib);
587 g_debug ("Parsed type: %s => %d", type, node->tag);
589 g_critical ("Failed to parse type: '%s'", type);
595 start_glib_boxed (GMarkupParseContext *context,
596 const gchar *element_name,
597 const gchar **attribute_names,
598 const gchar **attribute_values,
603 const gchar *typename;
604 const gchar *typeinit;
605 const gchar *deprecated;
608 if (!(strcmp (element_name, "glib:boxed") == 0 &&
609 ctx->state == STATE_NAMESPACE))
612 name = find_attribute ("glib:name", attribute_names, attribute_values);
613 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
614 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
615 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
619 MISSING_ATTRIBUTE (context, error, element_name, "glib:name");
622 else if (typename == NULL)
624 MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
627 else if (typeinit == NULL)
629 MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
633 boxed = (GIrNodeBoxed *) g_ir_node_new (G_IR_NODE_BOXED);
635 ((GIrNode *)boxed)->name = g_strdup (name);
636 boxed->gtype_name = g_strdup (typename);
637 boxed->gtype_init = g_strdup (typeinit);
639 boxed->deprecated = TRUE;
641 boxed->deprecated = FALSE;
643 ctx->current_node = (GIrNode *)boxed;
644 ctx->current_module->entries =
645 g_list_append (ctx->current_module->entries, boxed);
647 state_switch (ctx, STATE_BOXED);
653 start_function (GMarkupParseContext *context,
654 const gchar *element_name,
655 const gchar **attribute_names,
656 const gchar **attribute_values,
662 const gchar *deprecated;
663 GIrNodeFunction *function;
664 gboolean found = FALSE;
668 case STATE_NAMESPACE:
669 found = (strcmp (element_name, "function") == 0 ||
670 strcmp (element_name, "callback") == 0);
676 found = strcmp (element_name, "constructor") == 0;
678 case STATE_INTERFACE:
680 strcmp (element_name, "method") == 0 ||
681 strcmp (element_name, "callback") == 0);
690 name = find_attribute ("name", attribute_names, attribute_values);
691 symbol = find_attribute ("c:identifier", attribute_names, attribute_values);
692 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
696 MISSING_ATTRIBUTE (context, error, element_name, "name");
699 else if (strcmp (element_name, "callback") != 0 && symbol == NULL)
701 MISSING_ATTRIBUTE (context, error, element_name, "c:identifier");
705 function = (GIrNodeFunction *) g_ir_node_new (G_IR_NODE_FUNCTION);
707 ((GIrNode *)function)->name = g_strdup (name);
708 function->symbol = g_strdup (symbol);
709 function->parameters = NULL;
711 function->deprecated = TRUE;
713 function->deprecated = FALSE;
715 if (strcmp (element_name, "method") == 0 ||
716 strcmp (element_name, "constructor") == 0)
718 function->is_method = TRUE;
720 if (strcmp (element_name, "constructor") == 0)
721 function->is_constructor = TRUE;
723 function->is_constructor = FALSE;
727 function->is_method = FALSE;
728 function->is_setter = FALSE;
729 function->is_getter = FALSE;
730 function->is_constructor = FALSE;
731 if (strcmp (element_name, "callback") == 0)
732 ((GIrNode *)function)->type = G_IR_NODE_CALLBACK;
735 if (ctx->current_node == NULL)
737 ctx->current_module->entries =
738 g_list_append (ctx->current_module->entries, function);
741 switch (ctx->current_node->type)
743 case G_IR_NODE_INTERFACE:
744 case G_IR_NODE_OBJECT:
746 GIrNodeInterface *iface;
748 iface = (GIrNodeInterface *)ctx->current_node;
749 iface->members = g_list_append (iface->members, function);
752 case G_IR_NODE_BOXED:
756 boxed = (GIrNodeBoxed *)ctx->current_node;
757 boxed->members = g_list_append (boxed->members, function);
760 case G_IR_NODE_STRUCT:
762 GIrNodeStruct *struct_;
764 struct_ = (GIrNodeStruct *)ctx->current_node;
765 struct_->members = g_list_append (struct_->members, function); }
767 case G_IR_NODE_UNION:
769 GIrNodeUnion *union_;
771 union_ = (GIrNodeUnion *)ctx->current_node;
772 union_->members = g_list_append (union_->members, function);
776 g_assert_not_reached ();
779 ctx->current_node = (GIrNode *)function;
780 state_switch (ctx, STATE_FUNCTION);
786 start_parameter (GMarkupParseContext *context,
787 const gchar *element_name,
788 const gchar **attribute_names,
789 const gchar **attribute_values,
794 const gchar *direction;
797 const gchar *optional;
799 const gchar *transfer;
802 if (!(strcmp (element_name, "parameter") == 0 &&
803 ctx->state == STATE_FUNCTION_PARAMETERS))
806 name = find_attribute ("name", attribute_names, attribute_values);
807 direction = find_attribute ("direction", attribute_names, attribute_values);
808 retval = find_attribute ("retval", attribute_names, attribute_values);
809 dipper = find_attribute ("dipper", attribute_names, attribute_values);
810 optional = find_attribute ("optional", attribute_names, attribute_values);
811 nullok = find_attribute ("null-ok", attribute_names, attribute_values);
812 transfer = find_attribute ("transfer", attribute_names, attribute_values);
817 param = (GIrNodeParam *)g_ir_node_new (G_IR_NODE_PARAM);
819 ctx->current_typed = (GIrNode*) param;
820 ctx->current_typed->name = g_strdup (name);
822 state_switch (ctx, STATE_FUNCTION_PARAMETER);
824 if (direction && strcmp (direction, "out") == 0)
829 else if (direction && strcmp (direction, "inout") == 0)
840 if (retval && strcmp (retval, "1") == 0)
841 param->retval = TRUE;
843 param->retval = FALSE;
845 if (dipper && strcmp (dipper, "1") == 0)
846 param->dipper = TRUE;
848 param->dipper = FALSE;
850 if (optional && strcmp (optional, "1") == 0)
851 param->optional = TRUE;
853 param->optional = FALSE;
855 if (nullok && strcmp (nullok, "1") == 0)
856 param->null_ok = TRUE;
858 param->null_ok = FALSE;
860 if (transfer && strcmp (transfer, "none") == 0)
862 param->transfer = FALSE;
863 param->shallow_transfer = FALSE;
865 else if (transfer && strcmp (transfer, "shallow") == 0)
867 param->transfer = FALSE;
868 param->shallow_transfer = TRUE;
874 if (strcmp (transfer, "full") != 0)
875 g_warning ("Unknown transfer %s", transfer);
877 param->transfer = TRUE;
879 else if (param->in && !param->out)
880 param->transfer = FALSE;
882 param->transfer = TRUE;
883 param->shallow_transfer = FALSE;
886 ((GIrNode *)param)->name = g_strdup (name);
888 switch (ctx->current_node->type)
890 case G_IR_NODE_FUNCTION:
891 case G_IR_NODE_CALLBACK:
893 GIrNodeFunction *func;
895 func = (GIrNodeFunction *)ctx->current_node;
896 func->parameters = g_list_append (func->parameters, param);
899 case G_IR_NODE_SIGNAL:
901 GIrNodeSignal *signal;
903 signal = (GIrNodeSignal *)ctx->current_node;
904 signal->parameters = g_list_append (signal->parameters, param);
907 case G_IR_NODE_VFUNC:
911 vfunc = (GIrNodeVFunc *)ctx->current_node;
912 vfunc->parameters = g_list_append (vfunc->parameters, param);
916 g_assert_not_reached ();
923 start_field (GMarkupParseContext *context,
924 const gchar *element_name,
925 const gchar **attribute_names,
926 const gchar **attribute_values,
931 const gchar *readable;
932 const gchar *writable;
944 case STATE_INTERFACE:
950 if (strcmp (element_name, "field") != 0)
953 name = find_attribute ("name", attribute_names, attribute_values);
954 readable = find_attribute ("readable", attribute_names, attribute_values);
955 writable = find_attribute ("writable", attribute_names, attribute_values);
956 bits = find_attribute ("bits", attribute_names, attribute_values);
957 branch = find_attribute ("branch", attribute_names, attribute_values);
958 offset = find_attribute ("offset", attribute_names, attribute_values);
962 MISSING_ATTRIBUTE (context, error, element_name, "name");
966 field = (GIrNodeField *)g_ir_node_new (G_IR_NODE_FIELD);
967 ctx->current_typed = (GIrNode*) field;
968 ((GIrNode *)field)->name = g_strdup (name);
969 if (readable && strcmp (readable, "1") == 0)
970 field->readable = TRUE;
972 field->readable = FALSE;
974 if (writable && strcmp (writable, "1") == 0)
975 field->writable = TRUE;
977 field->writable = FALSE;
980 field->bits = atoi (bits);
985 field->offset = atoi (offset);
989 switch (ctx->current_node->type)
991 case G_IR_NODE_OBJECT:
993 GIrNodeInterface *iface;
995 iface = (GIrNodeInterface *)ctx->current_node;
996 iface->members = g_list_append (iface->members, field);
997 state_switch (ctx, STATE_CLASS_FIELD);
1000 case G_IR_NODE_INTERFACE:
1002 GIrNodeInterface *iface;
1004 iface = (GIrNodeInterface *)ctx->current_node;
1005 iface->members = g_list_append (iface->members, field);
1006 state_switch (ctx, STATE_INTERFACE_FIELD);
1009 case G_IR_NODE_BOXED:
1011 GIrNodeBoxed *boxed;
1013 boxed = (GIrNodeBoxed *)ctx->current_node;
1014 boxed->members = g_list_append (boxed->members, field);
1015 state_switch (ctx, STATE_BOXED_FIELD);
1018 case G_IR_NODE_STRUCT:
1020 GIrNodeStruct *struct_;
1022 struct_ = (GIrNodeStruct *)ctx->current_node;
1023 struct_->members = g_list_append (struct_->members, field);
1024 state_switch (ctx, STATE_STRUCT_FIELD);
1027 case G_IR_NODE_UNION:
1029 GIrNodeUnion *union_;
1031 union_ = (GIrNodeUnion *)ctx->current_node;
1032 union_->members = g_list_append (union_->members, field);
1035 GIrNodeConstant *constant;
1037 constant = (GIrNodeConstant *) g_ir_node_new (G_IR_NODE_CONSTANT);
1038 ((GIrNode *)constant)->name = g_strdup (name);
1039 constant->value = g_strdup (branch);
1040 constant->type = union_->discriminator_type;
1041 constant->deprecated = FALSE;
1043 union_->discriminators = g_list_append (union_->discriminators, constant);
1045 state_switch (ctx, STATE_UNION_FIELD);
1049 g_assert_not_reached ();
1056 start_alias (GMarkupParseContext *context,
1057 const gchar *element_name,
1058 const gchar **attribute_names,
1059 const gchar **attribute_values,
1064 const gchar *target;
1069 name = find_attribute ("name", attribute_names, attribute_values);
1072 MISSING_ATTRIBUTE (context, error, element_name, "name");
1076 target = find_attribute ("target", attribute_names, attribute_values);
1079 MISSING_ATTRIBUTE (context, error, element_name, "target");
1083 value = g_strdup (target);
1084 if (ctx->prefix_aliases)
1086 key = g_strdup_printf ("%s.%s", ctx->namespace, name);
1087 if (!strchr (target, '.'))
1089 const BasicTypeInfo *basic = parse_basic (target);
1093 /* For non-basic types, re-qualify the interface */
1094 value = g_strdup_printf ("%s.%s", ctx->namespace, target);
1100 key = g_strdup (name);
1103 g_hash_table_insert (ctx->aliases, key, value);
1109 start_enum (GMarkupParseContext *context,
1110 const gchar *element_name,
1111 const gchar **attribute_names,
1112 const gchar **attribute_values,
1116 if ((strcmp (element_name, "enumeration") == 0 && ctx->state == STATE_NAMESPACE) ||
1117 (strcmp (element_name, "bitfield") == 0 && ctx->state == STATE_NAMESPACE))
1120 const gchar *typename;
1121 const gchar *typeinit;
1122 const gchar *deprecated;
1124 name = find_attribute ("name", attribute_names, attribute_values);
1125 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
1126 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
1127 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1130 MISSING_ATTRIBUTE (context, error, element_name, "name");
1135 if (strcmp (element_name, "enumeration") == 0)
1136 enum_ = (GIrNodeEnum *) g_ir_node_new (G_IR_NODE_ENUM);
1138 enum_ = (GIrNodeEnum *) g_ir_node_new (G_IR_NODE_FLAGS);
1139 ((GIrNode *)enum_)->name = g_strdup (name);
1140 enum_->gtype_name = g_strdup (typename);
1141 enum_->gtype_init = g_strdup (typeinit);
1143 enum_->deprecated = TRUE;
1145 enum_->deprecated = FALSE;
1147 ctx->current_node = (GIrNode *) enum_;
1148 ctx->current_module->entries =
1149 g_list_append (ctx->current_module->entries, enum_);
1151 state_switch (ctx, STATE_ENUM);
1160 start_property (GMarkupParseContext *context,
1161 const gchar *element_name,
1162 const gchar **attribute_names,
1163 const gchar **attribute_values,
1167 if (strcmp (element_name, "property") == 0 &&
1168 (ctx->state == STATE_CLASS ||
1169 ctx->state == STATE_INTERFACE))
1172 const gchar *readable;
1173 const gchar *writable;
1174 const gchar *construct;
1175 const gchar *construct_only;
1177 name = find_attribute ("name", attribute_names, attribute_values);
1178 readable = find_attribute ("readable", attribute_names, attribute_values);
1179 writable = find_attribute ("writable", attribute_names, attribute_values);
1180 construct = find_attribute ("construct", attribute_names, attribute_values);
1181 construct_only = find_attribute ("construct-only", attribute_names, attribute_values);
1184 MISSING_ATTRIBUTE (context, error, element_name, "name");
1187 GIrNodeProperty *property;
1188 GIrNodeInterface *iface;
1190 property = (GIrNodeProperty *) g_ir_node_new (G_IR_NODE_PROPERTY);
1191 ctx->current_typed = (GIrNode*) property;
1193 ((GIrNode *)property)->name = g_strdup (name);
1195 /* Assume properties are readable */
1196 if (readable == NULL || strcmp (readable, "1") == 0)
1197 property->readable = TRUE;
1199 property->readable = FALSE;
1200 if (writable && strcmp (writable, "1") == 0)
1201 property->writable = TRUE;
1203 property->writable = FALSE;
1204 if (construct && strcmp (construct, "1") == 0)
1205 property->construct = TRUE;
1207 property->construct = FALSE;
1208 if (construct_only && strcmp (construct_only, "1") == 0)
1209 property->construct_only = TRUE;
1211 property->construct_only = FALSE;
1213 iface = (GIrNodeInterface *)ctx->current_node;
1214 iface->members = g_list_append (iface->members, property);
1216 if (ctx->state == STATE_CLASS)
1217 state_switch (ctx, STATE_CLASS_PROPERTY);
1218 else if (ctx->state == STATE_INTERFACE)
1219 state_switch (ctx, STATE_INTERFACE_PROPERTY);
1221 g_assert_not_reached ();
1230 parse_value (const gchar *str)
1234 /* FIXME just a quick hack */
1235 shift_op = strstr (str, "<<");
1241 base = strtol (str, NULL, 10);
1242 shift = strtol (shift_op + 3, NULL, 10);
1244 return base << shift;
1247 return strtol (str, NULL, 10);
1253 start_member (GMarkupParseContext *context,
1254 const gchar *element_name,
1255 const gchar **attribute_names,
1256 const gchar **attribute_values,
1260 if (strcmp (element_name, "member") == 0 &&
1261 ctx->state == STATE_ENUM)
1265 const gchar *deprecated;
1267 name = find_attribute ("name", attribute_names, attribute_values);
1268 value = find_attribute ("value", attribute_names, attribute_values);
1269 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1272 MISSING_ATTRIBUTE (context, error, element_name, "name");
1276 GIrNodeValue *value_;
1278 value_ = (GIrNodeValue *) g_ir_node_new (G_IR_NODE_VALUE);
1280 ((GIrNode *)value_)->name = g_strdup (name);
1282 value_->value = parse_value (value);
1285 value_->deprecated = TRUE;
1287 value_->deprecated = FALSE;
1289 enum_ = (GIrNodeEnum *)ctx->current_node;
1290 enum_->values = g_list_append (enum_->values, value_);
1299 start_constant (GMarkupParseContext *context,
1300 const gchar *element_name,
1301 const gchar **attribute_names,
1302 const gchar **attribute_values,
1306 if (strcmp (element_name, "constant") == 0 &&
1307 (ctx->state == STATE_NAMESPACE ||
1308 ctx->state == STATE_CLASS ||
1309 ctx->state == STATE_INTERFACE))
1313 const gchar *deprecated;
1315 name = find_attribute ("name", attribute_names, attribute_values);
1316 value = find_attribute ("value", attribute_names, attribute_values);
1317 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1320 MISSING_ATTRIBUTE (context, error, element_name, "name");
1321 else if (value == NULL)
1322 MISSING_ATTRIBUTE (context, error, element_name, "value");
1325 GIrNodeConstant *constant;
1327 constant = (GIrNodeConstant *) g_ir_node_new (G_IR_NODE_CONSTANT);
1329 ((GIrNode *)constant)->name = g_strdup (name);
1330 constant->value = g_strdup (value);
1332 ctx->current_typed = (GIrNode*) constant;
1335 constant->deprecated = TRUE;
1337 constant->deprecated = FALSE;
1339 if (ctx->state == STATE_NAMESPACE)
1341 ctx->current_node = (GIrNode *) constant;
1342 ctx->current_module->entries =
1343 g_list_append (ctx->current_module->entries, constant);
1347 GIrNodeInterface *iface;
1349 iface = (GIrNodeInterface *)ctx->current_node;
1350 iface->members = g_list_append (iface->members, constant);
1355 case STATE_NAMESPACE:
1356 state_switch (ctx, STATE_NAMESPACE_CONSTANT);
1359 state_switch (ctx, STATE_CLASS_CONSTANT);
1361 case STATE_INTERFACE:
1362 state_switch (ctx, STATE_INTERFACE_CONSTANT);
1365 g_assert_not_reached ();
1376 start_errordomain (GMarkupParseContext *context,
1377 const gchar *element_name,
1378 const gchar **attribute_names,
1379 const gchar **attribute_values,
1383 if (strcmp (element_name, "errordomain") == 0 &&
1384 ctx->state == STATE_NAMESPACE)
1387 const gchar *getquark;
1389 const gchar *deprecated;
1391 name = find_attribute ("name", attribute_names, attribute_values);
1392 getquark = find_attribute ("get-quark", attribute_names, attribute_values);
1393 codes = find_attribute ("codes", attribute_names, attribute_values);
1394 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1397 MISSING_ATTRIBUTE (context, error, element_name, "name");
1398 else if (getquark == NULL)
1399 MISSING_ATTRIBUTE (context, error, element_name, "getquark");
1400 else if (codes == NULL)
1401 MISSING_ATTRIBUTE (context, error, element_name, "codes");
1404 GIrNodeErrorDomain *domain;
1406 domain = (GIrNodeErrorDomain *) g_ir_node_new (G_IR_NODE_ERROR_DOMAIN);
1408 ((GIrNode *)domain)->name = g_strdup (name);
1409 domain->getquark = g_strdup (getquark);
1410 domain->codes = g_strdup (codes);
1413 domain->deprecated = TRUE;
1415 domain->deprecated = FALSE;
1417 ctx->current_node = (GIrNode *) domain;
1418 ctx->current_module->entries =
1419 g_list_append (ctx->current_module->entries, domain);
1421 state_switch (ctx, STATE_ERRORDOMAIN);
1430 start_interface (GMarkupParseContext *context,
1431 const gchar *element_name,
1432 const gchar **attribute_names,
1433 const gchar **attribute_values,
1437 if (strcmp (element_name, "interface") == 0 &&
1438 ctx->state == STATE_NAMESPACE)
1441 const gchar *typename;
1442 const gchar *typeinit;
1443 const gchar *deprecated;
1445 name = find_attribute ("name", attribute_names, attribute_values);
1446 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
1447 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
1448 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1451 MISSING_ATTRIBUTE (context, error, element_name, "name");
1452 else if (typename == NULL)
1453 MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
1454 else if (typeinit == NULL)
1455 MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
1458 GIrNodeInterface *iface;
1460 iface = (GIrNodeInterface *) g_ir_node_new (G_IR_NODE_INTERFACE);
1461 ((GIrNode *)iface)->name = g_strdup (name);
1462 iface->gtype_name = g_strdup (typename);
1463 iface->gtype_init = g_strdup (typeinit);
1465 iface->deprecated = TRUE;
1467 iface->deprecated = FALSE;
1469 ctx->current_node = (GIrNode *) iface;
1470 ctx->current_module->entries =
1471 g_list_append (ctx->current_module->entries, iface);
1473 state_switch (ctx, STATE_INTERFACE);
1483 start_class (GMarkupParseContext *context,
1484 const gchar *element_name,
1485 const gchar **attribute_names,
1486 const gchar **attribute_values,
1490 if (strcmp (element_name, "class") == 0 &&
1491 ctx->state == STATE_NAMESPACE)
1494 const gchar *parent;
1495 const gchar *typename;
1496 const gchar *typeinit;
1497 const gchar *deprecated;
1499 name = find_attribute ("name", attribute_names, attribute_values);
1500 parent = find_attribute ("parent", attribute_names, attribute_values);
1501 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
1502 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
1503 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1506 MISSING_ATTRIBUTE (context, error, element_name, "name");
1507 else if (typename == NULL)
1508 MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
1509 else if (typeinit == NULL && strcmp (typename, "GObject"))
1510 MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
1513 GIrNodeInterface *iface;
1515 iface = (GIrNodeInterface *) g_ir_node_new (G_IR_NODE_OBJECT);
1516 ((GIrNode *)iface)->name = g_strdup (name);
1517 iface->gtype_name = g_strdup (typename);
1518 iface->gtype_init = g_strdup (typeinit);
1519 iface->parent = g_strdup (parent);
1521 iface->deprecated = TRUE;
1523 iface->deprecated = FALSE;
1525 ctx->current_node = (GIrNode *) iface;
1526 ctx->current_module->entries =
1527 g_list_append (ctx->current_module->entries, iface);
1529 state_switch (ctx, STATE_CLASS);
1538 start_type (GMarkupParseContext *context,
1539 const gchar *element_name,
1540 const gchar **attribute_names,
1541 const gchar **attribute_values,
1547 gboolean is_pointer;
1548 GIrNodeType *typenode;
1550 if (strcmp (element_name, "type") != 0)
1553 if (ctx->state == STATE_TYPE)
1555 else if (ctx->state == STATE_FUNCTION_PARAMETER ||
1556 ctx->state == STATE_FUNCTION_RETURN ||
1557 ctx->state == STATE_STRUCT_FIELD ||
1558 ctx->state == STATE_UNION_FIELD ||
1559 ctx->state == STATE_CLASS_PROPERTY ||
1560 ctx->state == STATE_CLASS_FIELD ||
1561 ctx->state == STATE_INTERFACE_FIELD ||
1562 ctx->state == STATE_INTERFACE_PROPERTY ||
1563 ctx->state == STATE_BOXED_FIELD ||
1564 ctx->state == STATE_NAMESPACE_CONSTANT ||
1565 ctx->state == STATE_CLASS_CONSTANT ||
1566 ctx->state == STATE_INTERFACE_CONSTANT
1569 state_switch (ctx, STATE_TYPE);
1570 ctx->type_depth = 1;
1573 /* FIXME handle recursive types */
1574 if (ctx->type_depth > 1)
1577 if (!ctx->current_typed)
1581 G_MARKUP_ERROR_INVALID_CONTENT,
1582 "The element <type> is invalid here");
1586 name = find_attribute ("name", attribute_names, attribute_values);
1589 MISSING_ATTRIBUTE (context, error, element_name, "name");
1591 ctype = find_attribute ("c:type", attribute_names, attribute_values);
1592 if (ctype != NULL && strchr (ctype, '*'))
1597 typenode = parse_type (ctx, name);
1599 typenode->is_pointer = is_pointer;
1601 switch (ctx->current_typed->type)
1603 case G_IR_NODE_PARAM:
1605 GIrNodeParam *param = (GIrNodeParam *)ctx->current_typed;
1606 param->type = typenode;
1609 case G_IR_NODE_FIELD:
1611 GIrNodeField *field = (GIrNodeField *)ctx->current_typed;
1612 field->type = typenode;
1615 case G_IR_NODE_PROPERTY:
1617 GIrNodeProperty *property = (GIrNodeProperty *) ctx->current_typed;
1618 property->type = typenode;
1621 case G_IR_NODE_CONSTANT:
1623 GIrNodeConstant *constant = (GIrNodeConstant *)ctx->current_typed;
1624 constant->type = typenode;
1628 g_printerr("current node is %d\n", ctx->current_node->type);
1629 g_assert_not_reached ();
1633 ctx->current_typed = NULL;
1638 start_return_value (GMarkupParseContext *context,
1639 const gchar *element_name,
1640 const gchar **attribute_names,
1641 const gchar **attribute_values,
1645 if (strcmp (element_name, "return-value") == 0 &&
1646 ctx->state == STATE_FUNCTION)
1648 GIrNodeParam *param;
1650 param = (GIrNodeParam *)g_ir_node_new (G_IR_NODE_PARAM);
1653 param->retval = TRUE;
1655 ctx->current_typed = (GIrNode*) param;
1657 state_switch (ctx, STATE_FUNCTION_RETURN);
1659 switch (ctx->current_node->type)
1661 case G_IR_NODE_FUNCTION:
1662 case G_IR_NODE_CALLBACK:
1664 GIrNodeFunction *func = (GIrNodeFunction *)ctx->current_node;
1665 func->result = param;
1668 case G_IR_NODE_SIGNAL:
1670 GIrNodeSignal *signal = (GIrNodeSignal *)ctx->current_node;
1671 signal->result = param;
1674 case G_IR_NODE_VFUNC:
1676 GIrNodeVFunc *vfunc = (GIrNodeVFunc *)ctx->current_node;
1677 vfunc->result = param;
1681 g_assert_not_reached ();
1691 start_implements (GMarkupParseContext *context,
1692 const gchar *element_name,
1693 const gchar **attribute_names,
1694 const gchar **attribute_values,
1698 GIrNodeInterface *iface;
1701 if (strcmp (element_name, "implements") != 0 ||
1702 !(ctx->state == STATE_CLASS))
1705 state_switch (ctx, STATE_IMPLEMENTS);
1707 name = find_attribute ("name", attribute_names, attribute_values);
1710 MISSING_ATTRIBUTE (context, error, element_name, "name");
1714 iface = (GIrNodeInterface *)ctx->current_node;
1715 iface->interfaces = g_list_append (iface->interfaces, g_strdup (name));
1721 start_glib_signal (GMarkupParseContext *context,
1722 const gchar *element_name,
1723 const gchar **attribute_names,
1724 const gchar **attribute_values,
1728 if (strcmp (element_name, "glib:signal") == 0 &&
1729 (ctx->state == STATE_CLASS ||
1730 ctx->state == STATE_INTERFACE))
1734 const gchar *no_recurse;
1735 const gchar *detailed;
1736 const gchar *action;
1737 const gchar *no_hooks;
1738 const gchar *has_class_closure;
1740 name = find_attribute ("name", attribute_names, attribute_values);
1741 when = find_attribute ("when", attribute_names, attribute_values);
1742 no_recurse = find_attribute ("no-recurse", attribute_names, attribute_values);
1743 detailed = find_attribute ("detailed", attribute_names, attribute_values);
1744 action = find_attribute ("action", attribute_names, attribute_values);
1745 no_hooks = find_attribute ("no-hooks", attribute_names, attribute_values);
1746 has_class_closure = find_attribute ("has-class-closure", attribute_names, attribute_values);
1749 MISSING_ATTRIBUTE (context, error, element_name, "name");
1752 GIrNodeInterface *iface;
1753 GIrNodeSignal *signal;
1755 signal = (GIrNodeSignal *)g_ir_node_new (G_IR_NODE_SIGNAL);
1757 ((GIrNode *)signal)->name = g_strdup (name);
1759 signal->run_first = FALSE;
1760 signal->run_last = FALSE;
1761 signal->run_cleanup = FALSE;
1762 if (when == NULL || strcmp (when, "LAST") == 0)
1763 signal->run_last = TRUE;
1764 else if (strcmp (when, "FIRST") == 0)
1765 signal->run_first = TRUE;
1767 signal->run_cleanup = TRUE;
1769 if (no_recurse && strcmp (no_recurse, "1") == 0)
1770 signal->no_recurse = TRUE;
1772 signal->no_recurse = FALSE;
1773 if (detailed && strcmp (detailed, "1") == 0)
1774 signal->detailed = TRUE;
1776 signal->detailed = FALSE;
1777 if (action && strcmp (action, "1") == 0)
1778 signal->action = TRUE;
1780 signal->action = FALSE;
1781 if (no_hooks && strcmp (no_hooks, "1") == 0)
1782 signal->no_hooks = TRUE;
1784 signal->no_hooks = FALSE;
1785 if (has_class_closure && strcmp (has_class_closure, "1") == 0)
1786 signal->has_class_closure = TRUE;
1788 signal->has_class_closure = FALSE;
1790 iface = (GIrNodeInterface *)ctx->current_node;
1791 iface->members = g_list_append (iface->members, signal);
1793 ctx->current_node = (GIrNode *)signal;
1794 state_switch (ctx, STATE_FUNCTION);
1803 start_vfunc (GMarkupParseContext *context,
1804 const gchar *element_name,
1805 const gchar **attribute_names,
1806 const gchar **attribute_values,
1810 if (strcmp (element_name, "vfunc") == 0 &&
1811 (ctx->state == STATE_CLASS ||
1812 ctx->state == STATE_INTERFACE))
1815 const gchar *must_chain_up;
1816 const gchar *override;
1817 const gchar *is_class_closure;
1818 const gchar *offset;
1820 name = find_attribute ("name", attribute_names, attribute_values);
1821 must_chain_up = find_attribute ("must-chain-up", attribute_names, attribute_values);
1822 override = find_attribute ("override", attribute_names, attribute_values);
1823 is_class_closure = find_attribute ("is-class-closure", attribute_names, attribute_values);
1824 offset = find_attribute ("offset", attribute_names, attribute_values);
1827 MISSING_ATTRIBUTE (context, error, element_name, "name");
1830 GIrNodeInterface *iface;
1831 GIrNodeVFunc *vfunc;
1833 vfunc = (GIrNodeVFunc *)g_ir_node_new (G_IR_NODE_VFUNC);
1835 ((GIrNode *)vfunc)->name = g_strdup (name);
1837 if (must_chain_up && strcmp (must_chain_up, "1") == 0)
1838 vfunc->must_chain_up = TRUE;
1840 vfunc->must_chain_up = FALSE;
1842 if (override && strcmp (override, "always") == 0)
1844 vfunc->must_be_implemented = TRUE;
1845 vfunc->must_not_be_implemented = FALSE;
1847 else if (override && strcmp (override, "never") == 0)
1849 vfunc->must_be_implemented = FALSE;
1850 vfunc->must_not_be_implemented = TRUE;
1854 vfunc->must_be_implemented = FALSE;
1855 vfunc->must_not_be_implemented = FALSE;
1858 if (is_class_closure && strcmp (is_class_closure, "1") == 0)
1859 vfunc->is_class_closure = TRUE;
1861 vfunc->is_class_closure = FALSE;
1864 vfunc->offset = atoi (offset);
1868 iface = (GIrNodeInterface *)ctx->current_node;
1869 iface->members = g_list_append (iface->members, vfunc);
1871 ctx->current_node = (GIrNode *)vfunc;
1872 state_switch (ctx, STATE_FUNCTION);
1882 start_struct (GMarkupParseContext *context,
1883 const gchar *element_name,
1884 const gchar **attribute_names,
1885 const gchar **attribute_values,
1889 if (strcmp (element_name, "record") == 0 &&
1890 ctx->state == STATE_NAMESPACE)
1893 const gchar *deprecated;
1894 const gchar *gtype_name;
1895 const gchar *gtype_init;
1896 GIrNodeStruct *struct_;
1898 name = find_attribute ("name", attribute_names, attribute_values);
1899 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1900 gtype_name = find_attribute ("glib:type-name", attribute_names, attribute_values);
1901 gtype_init = find_attribute ("glib:get-type", attribute_names, attribute_values);
1905 MISSING_ATTRIBUTE (context, error, element_name, "name");
1908 if ((gtype_name == NULL && gtype_init != NULL))
1910 MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
1913 if ((gtype_name != NULL && gtype_init == NULL))
1915 MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
1919 struct_ = (GIrNodeStruct *) g_ir_node_new (G_IR_NODE_STRUCT);
1921 ((GIrNode *)struct_)->name = g_strdup (name);
1923 struct_->deprecated = TRUE;
1925 struct_->deprecated = FALSE;
1927 struct_->gtype_name = g_strdup (gtype_name);
1928 struct_->gtype_init = g_strdup (gtype_init);
1930 ctx->current_node = (GIrNode *)struct_;
1931 ctx->current_module->entries =
1932 g_list_append (ctx->current_module->entries, struct_);
1934 state_switch (ctx, STATE_STRUCT);
1942 start_union (GMarkupParseContext *context,
1943 const gchar *element_name,
1944 const gchar **attribute_names,
1945 const gchar **attribute_values,
1949 if (strcmp (element_name, "union") == 0 &&
1950 ctx->state == STATE_NAMESPACE)
1953 const gchar *deprecated;
1954 const gchar *typename;
1955 const gchar *typeinit;
1957 name = find_attribute ("name", attribute_names, attribute_values);
1958 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1959 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
1960 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
1963 MISSING_ATTRIBUTE (context, error, element_name, "name");
1966 GIrNodeUnion *union_;
1968 union_ = (GIrNodeUnion *) g_ir_node_new (G_IR_NODE_UNION);
1970 ((GIrNode *)union_)->name = g_strdup (name);
1971 union_->gtype_name = g_strdup (typename);
1972 union_->gtype_init = g_strdup (typeinit);
1974 union_->deprecated = TRUE;
1976 union_->deprecated = FALSE;
1978 ctx->current_node = (GIrNode *)union_;
1979 ctx->current_module->entries =
1980 g_list_append (ctx->current_module->entries, union_);
1982 state_switch (ctx, STATE_UNION);
1990 start_discriminator (GMarkupParseContext *context,
1991 const gchar *element_name,
1992 const gchar **attribute_names,
1993 const gchar **attribute_values,
1997 if (strcmp (element_name, "discriminator") == 0 &&
1998 ctx->state == STATE_UNION)
2001 const gchar *offset;
2003 type = find_attribute ("type", attribute_names, attribute_values);
2004 offset = find_attribute ("offset", attribute_names, attribute_values);
2006 MISSING_ATTRIBUTE (context, error, element_name, "type");
2007 else if (offset == NULL)
2008 MISSING_ATTRIBUTE (context, error, element_name, "offset");
2010 ((GIrNodeUnion *)ctx->current_node)->discriminator_type
2011 = parse_type (ctx, type);
2012 ((GIrNodeUnion *)ctx->current_node)->discriminator_offset
2023 parse_include (GMarkupParseContext *context,
2028 ParseContext sub_ctx = { 0 };
2029 GMarkupParseContext *sub_context;
2034 girpath = locate_gir (name, ctx->includes);
2036 if (girpath == NULL)
2040 G_MARKUP_ERROR_INVALID_CONTENT,
2041 "Could not find GIR file '%s'; check XDG_DATA_DIRS or use --includedir",
2046 g_debug ("Parsing include %s", girpath);
2048 if (!g_file_get_contents (girpath, &buffer, &length, error))
2055 sub_ctx.state = STATE_START;
2056 sub_ctx.includes = ctx->includes;
2057 sub_ctx.prefix_aliases = TRUE;
2058 sub_ctx.namespace = name;
2059 sub_ctx.aliases = ctx->aliases;
2060 sub_ctx.type_depth = 0;
2062 context = g_markup_parse_context_new (&firstpass_parser, 0, &sub_ctx, NULL);
2064 if (!g_markup_parse_context_parse (context, buffer, length, error))
2070 if (!g_markup_parse_context_end_parse (context, error))
2076 g_markup_parse_context_free (context);
2080 extern GLogLevelFlags logged_levels;
2083 start_element_handler (GMarkupParseContext *context,
2084 const gchar *element_name,
2085 const gchar **attribute_names,
2086 const gchar **attribute_values,
2090 ParseContext *ctx = user_data;
2091 gint line_number, char_number;
2093 if (logged_levels & G_LOG_LEVEL_DEBUG)
2095 GString *tags = g_string_new ("");
2097 for (i = 0; attribute_names[i]; i++)
2098 g_string_append_printf (tags, "%s=\"%s\" ",
2100 attribute_values[i]);
2104 g_string_insert_c (tags, 0, ' ');
2105 g_string_truncate (tags, tags->len - 1);
2107 g_debug ("<%s%s>", element_name, tags->str);
2108 g_string_free (tags, TRUE);
2111 switch (element_name[0])
2114 if (ctx->state == STATE_NAMESPACE && strcmp (element_name, "alias") == 0)
2116 state_switch (ctx, STATE_ALIAS);
2121 if (start_enum (context, element_name,
2122 attribute_names, attribute_values,
2127 if (start_function (context, element_name,
2128 attribute_names, attribute_values,
2131 else if (start_constant (context, element_name,
2132 attribute_names, attribute_values,
2135 else if (start_class (context, element_name,
2136 attribute_names, attribute_values,
2139 else if (strcmp (element_name, "class") == 0 &&
2140 ctx->state == STATE_REQUIRES)
2144 name = find_attribute ("name", attribute_names, attribute_values);
2147 MISSING_ATTRIBUTE (context, error, element_name, "name");
2150 GIrNodeInterface *iface;
2152 iface = (GIrNodeInterface *)ctx->current_node;
2153 iface ->prerequisites = g_list_append (iface->prerequisites, g_strdup (name));
2161 if (start_discriminator (context, element_name,
2162 attribute_names, attribute_values,
2168 if (start_enum (context, element_name,
2169 attribute_names, attribute_values,
2172 else if (start_errordomain (context, element_name,
2173 attribute_names, attribute_values,
2179 if (start_function (context, element_name,
2180 attribute_names, attribute_values,
2183 else if (start_field (context, element_name,
2184 attribute_names, attribute_values,
2190 if (start_glib_boxed (context, element_name,
2191 attribute_names, attribute_values,
2194 else if (start_glib_signal (context, element_name,
2195 attribute_names, attribute_values,
2201 if (strcmp (element_name, "include") == 0 &&
2202 ctx->state == STATE_REPOSITORY)
2206 name = find_attribute ("name", attribute_names, attribute_values);
2210 MISSING_ATTRIBUTE (context, error, element_name, "name");
2214 if (!parse_include (context, ctx, name, error))
2217 ctx->dependencies = g_list_prepend (ctx->dependencies, g_strdup (name));
2220 state_switch (ctx, STATE_INCLUDE);
2223 if (start_interface (context, element_name,
2224 attribute_names, attribute_values,
2227 else if (start_implements (context, element_name,
2228 attribute_names, attribute_values,
2234 if (start_function (context, element_name,
2235 attribute_names, attribute_values,
2238 else if (start_member (context, element_name,
2239 attribute_names, attribute_values,
2245 if (strcmp (element_name, "namespace") == 0 && ctx->state == STATE_REPOSITORY)
2247 const gchar *name, *shared_library;
2249 name = find_attribute ("name", attribute_names, attribute_values);
2250 shared_library = find_attribute ("shared-library", attribute_names, attribute_values);
2253 MISSING_ATTRIBUTE (context, error, element_name, "name");
2256 ctx->current_module = g_ir_module_new (name, shared_library);
2257 ctx->modules = g_list_append (ctx->modules, ctx->current_module);
2258 ctx->current_module->dependencies = ctx->dependencies;
2260 state_switch (ctx, STATE_NAMESPACE);
2267 if (start_property (context, element_name,
2268 attribute_names, attribute_values,
2271 else if (strcmp (element_name, "parameters") == 0 &&
2272 ctx->state == STATE_FUNCTION)
2274 state_switch (ctx, STATE_FUNCTION_PARAMETERS);
2278 else if (start_parameter (context, element_name,
2279 attribute_names, attribute_values,
2286 if (strcmp (element_name, "repository") == 0 && ctx->state == STATE_START)
2288 const gchar *version;
2290 version = find_attribute ("version", attribute_names, attribute_values);
2292 if (version == NULL)
2293 MISSING_ATTRIBUTE (context, error, element_name, "version");
2294 else if (strcmp (version, "1.0") != 0)
2297 G_MARKUP_ERROR_INVALID_CONTENT,
2298 "Unsupported version '%s'",
2301 state_switch (ctx, STATE_REPOSITORY);
2305 else if (start_return_value (context, element_name,
2306 attribute_names, attribute_values,
2309 else if (strcmp (element_name, "requires") == 0 &&
2310 ctx->state == STATE_INTERFACE)
2312 state_switch (ctx, STATE_REQUIRES);
2316 else if (start_struct (context, element_name,
2317 attribute_names, attribute_values,
2323 if (start_union (context, element_name,
2324 attribute_names, attribute_values,
2330 if (start_type (context, element_name,
2331 attribute_names, attribute_values,
2337 if (start_vfunc (context, element_name,
2338 attribute_names, attribute_values,
2344 g_markup_parse_context_get_position (context, &line_number, &char_number);
2346 if (error && *error == NULL)
2349 G_MARKUP_ERROR_UNKNOWN_ELEMENT,
2350 "Unexpected start tag '%s' on line %d char %d; current state=%d",
2352 line_number, char_number, ctx->state);
2357 g_markup_parse_context_get_position (context, &line_number, &char_number);
2359 fprintf (stderr, "Error at line %d, character %d: %s\n", line_number, char_number, (*error)->message);
2360 backtrace_stderr ();
2365 require_one_of_end_elements (GMarkupParseContext *context,
2367 const char *actual_name,
2372 int line_number, char_number;
2373 const char *expected;
2374 gboolean matched = FALSE;
2376 va_start (args, error);
2378 while ((expected = va_arg (args, const char*)) != NULL)
2380 if (strcmp (expected, actual_name) == 0)
2392 g_markup_parse_context_get_position (context, &line_number, &char_number);
2395 G_MARKUP_ERROR_INVALID_CONTENT,
2396 "Unexpected end tag '%s' on line %d char %d; current state=%d",
2398 line_number, char_number, ctx->state);
2404 require_end_element (GMarkupParseContext *context,
2406 const char *expected_name,
2407 const char *actual_name,
2410 return require_one_of_end_elements (context, ctx, actual_name, error, expected_name, NULL);
2414 end_element_handler (GMarkupParseContext *context,
2415 const gchar *element_name,
2419 ParseContext *ctx = user_data;
2421 g_debug ("</%s>", element_name);
2427 /* no need to GError here, GMarkup already catches this */
2430 case STATE_REPOSITORY:
2431 state_switch (ctx, STATE_END);
2435 if (require_end_element (context, ctx, "include", element_name, error))
2437 state_switch (ctx, STATE_REPOSITORY);
2441 case STATE_NAMESPACE:
2442 if (require_end_element (context, ctx, "namespace", element_name, error))
2444 ctx->current_module = NULL;
2445 state_switch (ctx, STATE_REPOSITORY);
2450 if (require_end_element (context, ctx, "alias", element_name, error))
2452 state_switch (ctx, STATE_NAMESPACE);
2456 case STATE_FUNCTION_RETURN:
2457 if (strcmp ("type", element_name) == 0)
2459 if (require_end_element (context, ctx, "return-value", element_name, error))
2461 state_switch (ctx, STATE_FUNCTION);
2465 case STATE_FUNCTION_PARAMETERS:
2466 if (require_end_element (context, ctx, "parameters", element_name, error))
2468 state_switch (ctx, STATE_FUNCTION);
2472 case STATE_FUNCTION_PARAMETER:
2473 if (strcmp ("type", element_name) == 0)
2475 if (require_end_element (context, ctx, "parameter", element_name, error))
2477 state_switch (ctx, STATE_FUNCTION_PARAMETERS);
2481 case STATE_FUNCTION:
2482 if (ctx->current_node == g_list_last (ctx->current_module->entries)->data)
2484 ctx->current_node = NULL;
2485 state_switch (ctx, STATE_NAMESPACE);
2489 ctx->current_node = g_list_last (ctx->current_module->entries)->data;
2490 if (ctx->current_node->type == G_IR_NODE_INTERFACE)
2491 state_switch (ctx, STATE_INTERFACE);
2492 else if (ctx->current_node->type == G_IR_NODE_OBJECT)
2493 state_switch (ctx, STATE_CLASS);
2494 else if (ctx->current_node->type == G_IR_NODE_BOXED)
2495 state_switch (ctx, STATE_BOXED);
2496 else if (ctx->current_node->type == G_IR_NODE_STRUCT)
2497 state_switch (ctx, STATE_STRUCT);
2498 else if (ctx->current_node->type == G_IR_NODE_UNION)
2499 state_switch (ctx, STATE_UNION);
2502 int line_number, char_number;
2503 g_markup_parse_context_get_position (context, &line_number, &char_number);
2506 G_MARKUP_ERROR_INVALID_CONTENT,
2507 "Unexpected end tag '%s' on line %d char %d",
2509 line_number, char_number);
2514 case STATE_CLASS_FIELD:
2515 if (strcmp ("type", element_name) == 0)
2517 if (require_end_element (context, ctx, "field", element_name, error))
2519 state_switch (ctx, STATE_CLASS);
2523 case STATE_CLASS_PROPERTY:
2524 if (strcmp ("type", element_name) == 0)
2526 if (require_end_element (context, ctx, "property", element_name, error))
2528 state_switch (ctx, STATE_CLASS);
2533 if (require_end_element (context, ctx, "class", element_name, error))
2535 ctx->current_node = NULL;
2536 state_switch (ctx, STATE_NAMESPACE);
2540 case STATE_ERRORDOMAIN:
2541 if (require_end_element (context, ctx, "errordomain", element_name, error))
2543 ctx->current_node = NULL;
2544 state_switch (ctx, STATE_NAMESPACE);
2548 case STATE_INTERFACE_PROPERTY:
2549 if (strcmp ("type", element_name) == 0)
2551 if (require_end_element (context, ctx, "property", element_name, error))
2553 state_switch (ctx, STATE_INTERFACE);
2557 case STATE_INTERFACE_FIELD:
2558 if (strcmp ("type", element_name) == 0)
2560 if (require_end_element (context, ctx, "field", element_name, error))
2562 state_switch (ctx, STATE_INTERFACE);
2566 case STATE_INTERFACE:
2567 if (require_end_element (context, ctx, "interface", element_name, error))
2569 ctx->current_node = NULL;
2570 state_switch (ctx, STATE_NAMESPACE);
2575 if (strcmp ("member", element_name) == 0)
2577 else if (require_one_of_end_elements (context, ctx,
2578 element_name, error, "enumeration",
2581 ctx->current_node = NULL;
2582 state_switch (ctx, STATE_NAMESPACE);
2587 if (require_end_element (context, ctx, "glib:boxed", element_name, error))
2589 ctx->current_node = NULL;
2590 state_switch (ctx, STATE_NAMESPACE);
2594 case STATE_BOXED_FIELD:
2595 if (strcmp ("type", element_name) == 0)
2597 if (require_end_element (context, ctx, "field", element_name, error))
2599 state_switch (ctx, STATE_BOXED);
2603 case STATE_STRUCT_FIELD:
2604 if (strcmp ("type", element_name) == 0)
2606 if (require_end_element (context, ctx, "field", element_name, error))
2608 state_switch (ctx, STATE_STRUCT);
2613 if (require_end_element (context, ctx, "record", element_name, error))
2615 ctx->current_node = NULL;
2616 state_switch (ctx, STATE_NAMESPACE);
2620 case STATE_UNION_FIELD:
2621 if (strcmp ("type", element_name) == 0)
2623 if (require_end_element (context, ctx, "field", element_name, error))
2625 state_switch (ctx, STATE_UNION);
2630 if (require_end_element (context, ctx, "union", element_name, error))
2632 ctx->current_node = NULL;
2633 state_switch (ctx, STATE_NAMESPACE);
2636 case STATE_IMPLEMENTS:
2637 if (strcmp ("interface", element_name) == 0)
2639 if (require_end_element (context, ctx, "implements", element_name, error))
2640 state_switch (ctx, STATE_CLASS);
2642 case STATE_REQUIRES:
2643 if (require_end_element (context, ctx, "requires", element_name, error))
2644 state_switch (ctx, STATE_INTERFACE);
2646 case STATE_NAMESPACE_CONSTANT:
2647 case STATE_CLASS_CONSTANT:
2648 case STATE_INTERFACE_CONSTANT:
2649 if (strcmp ("type", element_name) == 0)
2651 if (require_end_element (context, ctx, "constant", element_name, error))
2653 ctx->current_node = NULL;
2656 case STATE_NAMESPACE_CONSTANT:
2657 state_switch (ctx, STATE_NAMESPACE);
2659 case STATE_CLASS_CONSTANT:
2660 state_switch (ctx, STATE_CLASS);
2662 case STATE_INTERFACE_CONSTANT:
2663 state_switch (ctx, STATE_INTERFACE);
2666 g_assert_not_reached ();
2672 if (strcmp ("type", element_name) == 0)
2674 if (ctx->type_depth == 1)
2675 state_switch (ctx, ctx->prev_state);
2677 ctx->type_depth -= 1;
2681 g_error ("Unhandled state %d in end_element_handler\n", ctx->state);
2686 text_handler (GMarkupParseContext *context,
2692 /* FIXME warn about non-whitespace text */
2696 cleanup (GMarkupParseContext *context,
2700 ParseContext *ctx = user_data;
2702 int line_number, char_number;
2704 for (m = ctx->modules; m; m = m->next)
2705 g_ir_module_free (m->data);
2706 g_list_free (ctx->modules);
2707 ctx->modules = NULL;
2709 ctx->current_module = NULL;
2712 static GMarkupParser parser =
2714 start_element_handler,
2715 end_element_handler,
2722 g_ir_parse_string (const gchar *namespace,
2723 const gchar *const *includes,
2724 const gchar *buffer,
2728 ParseContext ctx = { 0 };
2729 GMarkupParseContext *context;
2731 ctx.state = STATE_START;
2732 ctx.includes = includes;
2733 ctx.prefix_aliases = FALSE;
2734 ctx.namespace = namespace;
2735 ctx.aliases = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
2737 ctx.dependencies = NULL;
2738 ctx.current_module = NULL;
2740 context = g_markup_parse_context_new (&firstpass_parser, 0, &ctx, NULL);
2742 if (!g_markup_parse_context_parse (context, buffer, length, error))
2745 if (!g_markup_parse_context_end_parse (context, error))
2748 g_markup_parse_context_free (context);
2750 context = g_markup_parse_context_new (&parser, 0, &ctx, NULL);
2751 if (!g_markup_parse_context_parse (context, buffer, length, error))
2754 if (!g_markup_parse_context_end_parse (context, error))
2759 g_hash_table_destroy (ctx.aliases);
2761 g_markup_parse_context_free (context);
2767 g_ir_parse_file (const gchar *filename,
2768 const gchar *const *includes,
2777 if (!g_str_has_suffix (filename, ".gir"))
2781 G_MARKUP_ERROR_INVALID_CONTENT,
2782 "Expected filename to end with '.gir'");
2786 g_debug ("[parsing] filename %s", filename);
2788 slash = g_strrstr (filename, "/");
2790 namespace = g_strdup (filename);
2792 namespace = g_strdup (slash+1);
2793 namespace[strlen(namespace)-4] = '\0';
2795 if (!g_file_get_contents (filename, &buffer, &length, error))
2798 modules = g_ir_parse_string (namespace, includes, buffer, length, error);