[girepository] Remove trailing whitespace
[gnome.gobject-introspection] / girepository / girparser.c
1 /* GObject introspection: A parser for the XML GIR format
2  *
3  * Copyright (C) 2008 Philip Van Hoof
4  *
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.
9  *
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.
14  *
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.
19  */
20
21 #include <stdlib.h>
22 #include <string.h>
23 #include <stdio.h>
24
25 #include <glib.h>
26 #include "girparser.h"
27 #include "girmodule.h"
28 #include "girnode.h"
29 #include "gtypelib.h"
30 #include "config.h"
31
32 #if defined(HAVE_BACKTRACE) && defined(HAVE_BACKTRACE_SYMBOLS)
33 # include <execinfo.h>
34 #endif
35
36 struct _GIrParser
37 {
38   gchar **includes;
39   GList *parsed_modules; /* All previously parsed modules */
40 };
41
42 typedef enum
43 {
44   STATE_START,
45   STATE_END,
46   STATE_REPOSITORY,
47   STATE_INCLUDE,
48   STATE_PACKAGE,
49   STATE_NAMESPACE, /* 5 */
50   STATE_ENUM,
51   STATE_BITFIELD,
52   STATE_FUNCTION,
53   STATE_FUNCTION_RETURN,
54   STATE_FUNCTION_PARAMETERS, /* 10 */
55   STATE_FUNCTION_PARAMETER,
56   STATE_CLASS,
57   STATE_CLASS_FIELD,
58   STATE_CLASS_PROPERTY,
59   STATE_INTERFACE, /* 15 */
60   STATE_INTERFACE_PROPERTY,
61   STATE_INTERFACE_FIELD,
62   STATE_IMPLEMENTS,
63   STATE_PREREQUISITE,
64   STATE_BOXED,   /* 20 */
65   STATE_BOXED_FIELD,
66   STATE_STRUCT,
67   STATE_STRUCT_FIELD,
68   STATE_ERRORDOMAIN,
69   STATE_UNION, /* 25 */
70   STATE_UNION_FIELD,
71   STATE_NAMESPACE_CONSTANT,
72   STATE_CLASS_CONSTANT,
73   STATE_INTERFACE_CONSTANT,
74   STATE_ALIAS,
75   STATE_TYPE,
76   STATE_ATTRIBUTE,
77   STATE_UNKNOWN
78 } ParseState;
79
80 typedef struct _ParseContext ParseContext;
81 struct _ParseContext
82 {
83   GIrParser *parser;
84
85   ParseState state;
86   int unknown_depth;
87   ParseState prev_state;
88
89   GList *modules;
90   GList *include_modules;
91   GList *dependencies;
92   GHashTable *aliases;
93   GHashTable *disguised_structures;
94
95   const char *namespace;
96   const char *c_prefix;
97   GIrModule *current_module;
98   GSList *node_stack;
99   GIrNode *current_typed;
100   gboolean is_varargs;
101   GList *type_stack;
102   GList *type_parameters;
103   int type_depth;
104   gboolean in_embedded_type;
105 };
106 #define CURRENT_NODE(ctx) ((GIrNode *)((ctx)->node_stack->data))
107
108 static void start_element_handler (GMarkupParseContext *context,
109                                    const gchar         *element_name,
110                                    const gchar        **attribute_names,
111                                    const gchar        **attribute_values,
112                                    gpointer             user_data,
113                                    GError             **error);
114 static void end_element_handler   (GMarkupParseContext *context,
115                                    const gchar         *element_name,
116                                    gpointer             user_data,
117                                    GError             **error);
118 static void text_handler          (GMarkupParseContext *context,
119                                    const gchar         *text,
120                                    gsize                text_len,
121                                    gpointer             user_data,
122                                    GError             **error);
123 static void cleanup               (GMarkupParseContext *context,
124                                    GError              *error,
125                                    gpointer             user_data);
126
127 static GMarkupParser markup_parser =
128 {
129   start_element_handler,
130   end_element_handler,
131   text_handler,
132   NULL,
133   cleanup
134 };
135
136 static gboolean
137 start_alias (GMarkupParseContext *context,
138              const gchar         *element_name,
139              const gchar        **attribute_names,
140              const gchar        **attribute_values,
141              ParseContext        *ctx,
142              GError             **error);
143
144 static const gchar *find_attribute (const gchar  *name,
145                                     const gchar **attribute_names,
146                                     const gchar **attribute_values);
147
148
149 GIrParser *
150 g_ir_parser_new (void)
151 {
152   GIrParser *parser = g_slice_new0 (GIrParser);
153
154   return parser;
155 }
156
157 void
158 g_ir_parser_free (GIrParser *parser)
159 {
160   GList *l;
161
162   if (parser->includes)
163     g_strfreev (parser->includes);
164
165   for (l = parser->parsed_modules; l; l = l->next)
166     g_ir_module_free (l->data);
167
168   g_slice_free (GIrParser, parser);
169 }
170
171 void
172 g_ir_parser_set_includes (GIrParser          *parser,
173                           const gchar *const *includes)
174 {
175   if (parser->includes)
176     g_strfreev (parser->includes);
177
178   parser->includes = g_strdupv ((char **)includes);
179 }
180
181 static void
182 firstpass_start_element_handler (GMarkupParseContext *context,
183                                  const gchar         *element_name,
184                                  const gchar        **attribute_names,
185                                  const gchar        **attribute_values,
186                                  gpointer             user_data,
187                                  GError             **error)
188 {
189   ParseContext *ctx = user_data;
190
191   if (strcmp (element_name, "alias") == 0)
192     {
193       start_alias (context, element_name, attribute_names, attribute_values,
194                    ctx, error);
195     }
196   else if (strcmp (element_name, "record") == 0)
197     {
198       const gchar *name;
199       const gchar *disguised;
200
201       name = find_attribute ("name", attribute_names, attribute_values);
202       disguised = find_attribute ("disguised", attribute_names, attribute_values);
203
204       if (disguised && strcmp (disguised, "1") == 0)
205         {
206           char *key;
207
208           key = g_strdup_printf ("%s.%s", ctx->namespace, name);
209           g_hash_table_replace (ctx->disguised_structures, key, GINT_TO_POINTER (1));
210         }
211     }
212 }
213
214 static void
215 firstpass_end_element_handler (GMarkupParseContext *context,
216                                const gchar         *element_name,
217                                gpointer             user_data,
218                                GError             **error)
219 {
220 }
221
222 static GMarkupParser firstpass_parser =
223 {
224   firstpass_start_element_handler,
225   firstpass_end_element_handler,
226   NULL,
227   NULL,
228   NULL,
229 };
230
231 static char *
232 locate_gir (GIrParser  *parser,
233             const char *girname)
234 {
235   const gchar *const *datadirs;
236   const gchar *const *dir;
237   char *path = NULL;
238
239   datadirs = g_get_system_data_dirs ();
240
241   if (parser->includes != NULL)
242     {
243       for (dir = (const gchar *const *)parser->includes; *dir; dir++)
244         {
245           path = g_build_filename (*dir, girname, NULL);
246           if (g_file_test (path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))
247             return path;
248           g_free (path);
249           path = NULL;
250         }
251     }
252   for (dir = datadirs; *dir; dir++)
253     {
254       path = g_build_filename (*dir, GIR_SUFFIX, girname, NULL);
255       if (g_file_test (path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))
256         return path;
257       g_free (path);
258       path = NULL;
259     }
260
261   path = g_build_filename (GIR_DIR, girname, NULL);
262   if (g_file_test (path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))
263     return path;
264   g_free (path);
265   return NULL;
266 }
267
268 #define MISSING_ATTRIBUTE(ctx,error,element,attribute)                          \
269   do {                                                                          \
270     int line_number, char_number;                                                \
271     g_markup_parse_context_get_position (context, &line_number, &char_number);  \
272     g_set_error (error,                                                         \
273                  G_MARKUP_ERROR,                                                \
274                  G_MARKUP_ERROR_INVALID_CONTENT,                                \
275                  "Line %d, character %d: The attribute '%s' on the element '%s' must be specified",    \
276                  line_number, char_number, attribute, element);         \
277   } while (0)
278
279 static void
280 backtrace_stderr (void)
281 {
282 #if defined(HAVE_BACKTRACE) && defined(HAVE_BACKTRACE_SYMBOLS)
283   void *array[50];
284   int size, i;
285   char **strings;
286
287   size = backtrace (array, 50);
288   strings = (char**) backtrace_symbols (array, size);
289
290   fprintf (stderr, "--- BACKTRACE (%zd frames) ---\n", size);
291
292   for (i = 0; i < size; i++)
293     fprintf (stderr, "%s\n", strings[i]);
294
295   fprintf (stderr, "--- END BACKTRACE ---\n");
296
297   free (strings);
298 #endif
299 }
300
301
302 static const gchar *
303 find_attribute (const gchar  *name,
304                 const gchar **attribute_names,
305                 const gchar **attribute_values)
306 {
307   gint i;
308
309   for (i = 0; attribute_names[i] != NULL; i++)
310     if (strcmp (attribute_names[i], name) == 0)
311       return attribute_values[i];
312
313   return 0;
314 }
315
316 static void
317 state_switch (ParseContext *ctx, ParseState newstate)
318 {
319   g_debug ("State: %d", newstate);
320   ctx->prev_state = ctx->state;
321   ctx->state = newstate;
322 }
323
324 static GIrNode *
325 pop_node (ParseContext *ctx)
326 {
327   g_assert (ctx->node_stack != 0);
328
329   GSList *top = ctx->node_stack;
330   GIrNode *node = top->data;
331
332   g_debug ("popping node %d %s", node->type, node->name);
333   ctx->node_stack = top->next;
334   g_slist_free_1 (top);
335   return node;
336 }
337
338 static void
339 push_node (ParseContext *ctx, GIrNode *node)
340 {
341   g_debug ("pushing node %d %s", node->type, node->name);
342   ctx->node_stack = g_slist_prepend (ctx->node_stack, node);
343 }
344
345 static GIrNodeType * parse_type_internal (const gchar *str, gchar **next, gboolean in_glib,
346                                           gboolean in_gobject);
347
348 typedef struct {
349   const gchar *str;
350   gint tag;
351   gboolean pointer;
352 } BasicTypeInfo;
353
354 static BasicTypeInfo basic_types[] = {
355     { "none",     GI_TYPE_TAG_VOID,    0 },
356     { "any",      GI_TYPE_TAG_VOID,    1 },
357
358     { "bool",     GI_TYPE_TAG_BOOLEAN, 0 },
359     { "char",     GI_TYPE_TAG_INT8,    0 },
360     { "int8",     GI_TYPE_TAG_INT8,    0 },
361     { "uint8",    GI_TYPE_TAG_UINT8,   0 },
362     { "int16",    GI_TYPE_TAG_INT16,   0 },
363     { "uint16",   GI_TYPE_TAG_UINT16,  0 },
364     { "int32",    GI_TYPE_TAG_INT32,   0 },
365     { "uint32",   GI_TYPE_TAG_UINT32,  0 },
366     { "int64",    GI_TYPE_TAG_INT64,   0 },
367     { "uint64",   GI_TYPE_TAG_UINT64,  0 },
368     { "short",    GI_TYPE_TAG_SHORT,   0 },
369     { "ushort",   GI_TYPE_TAG_USHORT,  0 },
370     { "int",      GI_TYPE_TAG_INT,     0 },
371     { "uint",     GI_TYPE_TAG_UINT,    0 },
372     { "long",     GI_TYPE_TAG_LONG,    0 },
373     { "ulong",    GI_TYPE_TAG_ULONG,   0 },
374     { "ssize_t",  GI_TYPE_TAG_SSIZE,   0 },
375     { "ssize",    GI_TYPE_TAG_SSIZE,   0 },
376     { "size_t",   GI_TYPE_TAG_SIZE,    0 },
377     { "size",     GI_TYPE_TAG_SIZE,    0 },
378     { "float",    GI_TYPE_TAG_FLOAT,   0 },
379     { "double",   GI_TYPE_TAG_DOUBLE,  0 },
380     { "time_t",   GI_TYPE_TAG_TIME_T,  0 },
381     { "GType",    GI_TYPE_TAG_GTYPE,   0 },
382     { "utf8",     GI_TYPE_TAG_UTF8,    1 },
383     { "filename", GI_TYPE_TAG_FILENAME,1 },
384 };
385
386 static const BasicTypeInfo *
387 parse_basic (const char *str)
388 {
389   gint i;
390   gint n_basic = G_N_ELEMENTS (basic_types);
391
392   for (i = 0; i < n_basic; i++)
393     {
394       if (g_str_has_prefix (str, basic_types[i].str))
395         return &(basic_types[i]);
396     }
397   return NULL;
398 }
399
400 static GIrNodeType *
401 parse_type_internal (const gchar *str, char **next, gboolean in_glib,
402                      gboolean in_gobject)
403 {
404   const BasicTypeInfo *basic;
405   GIrNodeType *type;
406   char *temporary_type = NULL;
407
408   type = (GIrNodeType *)g_ir_node_new (G_IR_NODE_TYPE);
409
410   type->unparsed = g_strdup (str);
411
412   /* See comment below on GLib.List handling */
413   if (in_gobject && strcmp (str, "Type") == 0)
414     {
415       temporary_type = g_strdup ("GLib.Type");
416       str = temporary_type;
417     }
418
419   basic = parse_basic (str);
420   if (basic != NULL)
421     {
422       type->is_basic = TRUE;
423       type->tag = basic->tag;
424       type->is_pointer = basic->pointer;
425
426       str += strlen(basic->str);
427     }
428   else if (in_glib)
429     {
430       /* If we're inside GLib, handle "List" etc. by prefixing with
431        * "GLib." so the parsing code below doesn't have to get more
432        * special.
433        */
434       if (g_str_has_prefix (str, "List<") ||
435           strcmp (str, "List") == 0)
436         {
437           temporary_type = g_strdup_printf ("GLib.List%s", str + 4);
438           str = temporary_type;
439         }
440       else if (g_str_has_prefix (str, "SList<") ||
441           strcmp (str, "SList") == 0)
442         {
443           temporary_type = g_strdup_printf ("GLib.SList%s", str + 5);
444           str = temporary_type;
445         }
446       else if (g_str_has_prefix (str, "HashTable<") ||
447           strcmp (str, "HashTable") == 0)
448         {
449           temporary_type = g_strdup_printf ("GLib.HashTable%s", str + 9);
450           str = temporary_type;
451         }
452       else if (g_str_has_prefix (str, "Error<") ||
453           strcmp (str, "Error") == 0)
454         {
455           temporary_type = g_strdup_printf ("GLib.Error%s", str + 5);
456           str = temporary_type;
457         }
458     }
459
460   if (basic != NULL)
461     /* found a basic type */;
462   else if (g_str_has_prefix (str, "GLib.List") ||
463            g_str_has_prefix (str, "GLib.SList"))
464     {
465       str += strlen ("GLib.");
466       if (g_str_has_prefix (str, "List"))
467         {
468           type->tag = GI_TYPE_TAG_GLIST;
469           type->is_glist = TRUE;
470           type->is_pointer = TRUE;
471           str += strlen ("List");
472         }
473       else
474         {
475           type->tag = GI_TYPE_TAG_GSLIST;
476           type->is_gslist = TRUE;
477           type->is_pointer = TRUE;
478           str += strlen ("SList");
479         }
480     }
481   else if (g_str_has_prefix (str, "GLib.HashTable"))
482     {
483       str += strlen ("GLib.");
484
485       type->tag = GI_TYPE_TAG_GHASH;
486       type->is_ghashtable = TRUE;
487       type->is_pointer = TRUE;
488       str += strlen ("HashTable");
489     }
490   else if (g_str_has_prefix (str, "GLib.Error"))
491     {
492       str += strlen ("GLib.");
493
494       type->tag = GI_TYPE_TAG_ERROR;
495       type->is_error = TRUE;
496       type->is_pointer = TRUE;
497       str += strlen ("Error");
498
499       if (*str == '<')
500         {
501           (str)++;
502           char *tmp, *end;
503
504           end = strchr (str, '>');
505           tmp = g_strndup (str, end - str);
506           type->errors = g_strsplit (tmp, ",", 0);
507           g_free (tmp);
508
509           str = end;
510         }
511     }
512   else
513     {
514       type->tag = GI_TYPE_TAG_INTERFACE;
515       type->is_interface = TRUE;
516       const char *start = str;
517
518       /* must be an interface type */
519       while (g_ascii_isalnum (*str) ||
520              *str == '.' ||
521              *str == '-' ||
522              *str == '_' ||
523              *str == ':')
524         (str)++;
525
526       type->interface = g_strndup (start, str - start);
527     }
528
529   if (next)
530     *next = (char*)str;
531   g_assert (type->tag >= 0 && type->tag <= GI_TYPE_TAG_ERROR);
532   g_free (temporary_type);
533   return type;
534
535 /* error: */
536   g_ir_node_free ((GIrNode *)type);
537   g_free (temporary_type);
538   return NULL;
539 }
540
541 static const char *
542 resolve_aliases (ParseContext *ctx, const gchar *type)
543 {
544   gpointer orig;
545   gpointer value;
546   GSList *seen_values = NULL;
547   const gchar *lookup;
548   gchar *prefixed;
549
550   if (strchr (type, '.') == NULL)
551     {
552       prefixed = g_strdup_printf ("%s.%s", ctx->namespace, type);
553       lookup = prefixed;
554     }
555   else
556     {
557       lookup = type;
558       prefixed = NULL;
559     }
560
561   seen_values = g_slist_prepend (seen_values, (char*)lookup);
562   while (g_hash_table_lookup_extended (ctx->current_module->aliases, lookup, &orig, &value))
563     {
564       g_debug ("Resolved: %s => %s\n", lookup, (char*)value);
565       lookup = value;
566       if (g_slist_find_custom (seen_values, lookup,
567                                (GCompareFunc)strcmp) != NULL)
568         break;
569       seen_values = g_slist_prepend (seen_values, (gchar*)lookup);
570     }
571   g_slist_free (seen_values);
572
573   if (lookup == prefixed)
574     lookup = type;
575
576   g_free (prefixed);
577
578   return lookup;
579 }
580
581 static gboolean
582 is_disguised_structure (ParseContext *ctx, const gchar *type)
583 {
584   const gchar *lookup;
585   gchar *prefixed;
586   gboolean result;
587
588   if (strchr (type, '.') == NULL)
589     {
590       prefixed = g_strdup_printf ("%s.%s", ctx->namespace, type);
591       lookup = prefixed;
592     }
593   else
594     {
595       lookup = type;
596       prefixed = NULL;
597     }
598
599   result = g_hash_table_lookup (ctx->current_module->disguised_structures,
600                                 lookup) != NULL;
601
602   g_free (prefixed);
603
604   return result;
605 }
606
607 static GIrNodeType *
608 parse_type (ParseContext *ctx, const gchar *type)
609 {
610   GIrNodeType *node;
611   const BasicTypeInfo *basic;
612   gboolean in_glib, in_gobject;
613
614   in_glib = strcmp (ctx->namespace, "GLib") == 0;
615   in_gobject = strcmp (ctx->namespace, "GObject") == 0;
616
617   /* Do not search aliases for basic types */
618   basic = parse_basic (type);
619   if (basic == NULL)
620     type = resolve_aliases (ctx, type);
621
622   node = parse_type_internal (type, NULL, in_glib, in_gobject);
623   if (node)
624     g_debug ("Parsed type: %s => %d", type, node->tag);
625   else
626     g_critical ("Failed to parse type: '%s'", type);
627
628   return node;
629 }
630
631 static gboolean
632 start_glib_boxed (GMarkupParseContext *context,
633                   const gchar         *element_name,
634                   const gchar        **attribute_names,
635                   const gchar        **attribute_values,
636                   ParseContext        *ctx,
637                   GError             **error)
638 {
639   const gchar *name;
640   const gchar *typename;
641   const gchar *typeinit;
642   const gchar *deprecated;
643   GIrNodeBoxed *boxed;
644
645   if (!(strcmp (element_name, "glib:boxed") == 0 &&
646         ctx->state == STATE_NAMESPACE))
647     return FALSE;
648
649   name = find_attribute ("glib:name", attribute_names, attribute_values);
650   typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
651   typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
652   deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
653
654   if (name == NULL)
655     {
656       MISSING_ATTRIBUTE (context, error, element_name, "glib:name");
657       return FALSE;
658     }
659   else if (typename == NULL)
660     {
661       MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
662       return FALSE;
663     }
664   else if (typeinit == NULL)
665     {
666       MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
667       return FALSE;
668     }
669
670   boxed = (GIrNodeBoxed *) g_ir_node_new (G_IR_NODE_BOXED);
671
672   ((GIrNode *)boxed)->name = g_strdup (name);
673   boxed->gtype_name = g_strdup (typename);
674   boxed->gtype_init = g_strdup (typeinit);
675   if (deprecated)
676     boxed->deprecated = TRUE;
677   else
678     boxed->deprecated = FALSE;
679
680   push_node (ctx, (GIrNode *)boxed);
681   ctx->current_module->entries =
682     g_list_append (ctx->current_module->entries, boxed);
683
684   state_switch (ctx, STATE_BOXED);
685
686   return TRUE;
687 }
688
689 static gboolean
690 start_function (GMarkupParseContext *context,
691                 const gchar         *element_name,
692                 const gchar        **attribute_names,
693                 const gchar        **attribute_values,
694                 ParseContext        *ctx,
695                 GError             **error)
696 {
697   const gchar *name;
698   const gchar *symbol;
699   const gchar *deprecated;
700   const gchar *throws;
701   GIrNodeFunction *function;
702   gboolean found = FALSE;
703
704   switch (ctx->state)
705     {
706     case STATE_NAMESPACE:
707       found = (strcmp (element_name, "function") == 0 ||
708                strcmp (element_name, "callback") == 0);
709       break;
710     case STATE_CLASS:
711       found = strcmp (element_name, "function") == 0;
712         /* fallthrough */
713     case STATE_BOXED:
714     case STATE_STRUCT:
715     case STATE_UNION:
716       found = (found || strcmp (element_name, "constructor") == 0);
717       /* fallthrough */
718     case STATE_INTERFACE:
719       found = (found ||
720                strcmp (element_name, "method") == 0 ||
721                strcmp (element_name, "callback") == 0);
722       break;
723     case STATE_STRUCT_FIELD:
724       ctx->in_embedded_type = TRUE;
725       found = (found || strcmp (element_name, "callback") == 0);
726       break;
727     default:
728       break;
729     }
730
731   if (!found)
732     return FALSE;
733
734   name = find_attribute ("name", attribute_names, attribute_values);
735   symbol = find_attribute ("c:identifier", attribute_names, attribute_values);
736   deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
737   throws = find_attribute ("throws", attribute_names, attribute_values);
738
739   if (name == NULL)
740     {
741       MISSING_ATTRIBUTE (context, error, element_name, "name");
742       return FALSE;
743     }
744   else if (strcmp (element_name, "callback") != 0 && symbol == NULL)
745     {
746       MISSING_ATTRIBUTE (context, error, element_name, "c:identifier");
747       return FALSE;
748     }
749
750   function = (GIrNodeFunction *) g_ir_node_new (G_IR_NODE_FUNCTION);
751
752   ((GIrNode *)function)->name = g_strdup (name);
753   function->symbol = g_strdup (symbol);
754   function->parameters = NULL;
755   if (deprecated)
756     function->deprecated = TRUE;
757   else
758     function->deprecated = FALSE;
759
760   if (strcmp (element_name, "method") == 0 ||
761       strcmp (element_name, "constructor") == 0)
762     {
763       function->is_method = TRUE;
764
765       if (strcmp (element_name, "constructor") == 0)
766         function->is_constructor = TRUE;
767       else
768         function->is_constructor = FALSE;
769     }
770   else
771     {
772       function->is_method = FALSE;
773       function->is_setter = FALSE;
774       function->is_getter = FALSE;
775       function->is_constructor = FALSE;
776       if (strcmp (element_name, "callback") == 0)
777         ((GIrNode *)function)->type = G_IR_NODE_CALLBACK;
778     }
779
780   if (throws && strcmp (throws, "1") == 0)
781     function->throws = TRUE;
782   else
783     function->throws = FALSE;
784
785   if (ctx->node_stack == NULL)
786     {
787       ctx->current_module->entries =
788         g_list_append (ctx->current_module->entries, function);
789     }
790   else if (ctx->current_typed)
791     {
792       GIrNodeField *field;
793
794       field = (GIrNodeField *)ctx->current_typed;
795       field->callback = function;
796     }
797   else
798     switch (CURRENT_NODE (ctx)->type)
799       {
800       case G_IR_NODE_INTERFACE:
801       case G_IR_NODE_OBJECT:
802         {
803           GIrNodeInterface *iface;
804
805           iface = (GIrNodeInterface *)CURRENT_NODE (ctx);
806           iface->members = g_list_append (iface->members, function);
807         }
808         break;
809       case G_IR_NODE_BOXED:
810         {
811           GIrNodeBoxed *boxed;
812
813           boxed = (GIrNodeBoxed *)CURRENT_NODE (ctx);
814           boxed->members = g_list_append (boxed->members, function);
815         }
816         break;
817       case G_IR_NODE_STRUCT:
818         {
819           GIrNodeStruct *struct_;
820
821           struct_ = (GIrNodeStruct *)CURRENT_NODE (ctx);
822           struct_->members = g_list_append (struct_->members, function);                }
823         break;
824       case G_IR_NODE_UNION:
825         {
826           GIrNodeUnion *union_;
827
828           union_ = (GIrNodeUnion *)CURRENT_NODE (ctx);
829           union_->members = g_list_append (union_->members, function);
830         }
831         break;
832       default:
833         g_assert_not_reached ();
834       }
835
836   push_node(ctx, (GIrNode *)function);
837   state_switch (ctx, STATE_FUNCTION);
838
839   return TRUE;
840 }
841
842 static void
843 parse_param_transfer (GIrNodeParam *param, const gchar *transfer, const gchar *name)
844 {
845   if (transfer == NULL)
846   {
847     if (!name)
848       g_warning ("required attribute 'transfer-ownership' missing");
849     else
850       g_warning ("required attribute 'transfer-ownership' for function '%s'", name);
851   }
852   else if (strcmp (transfer, "none") == 0)
853     {
854       param->transfer = FALSE;
855       param->shallow_transfer = FALSE;
856     }
857   else if (strcmp (transfer, "container") == 0)
858     {
859       param->transfer = FALSE;
860       param->shallow_transfer = TRUE;
861     }
862   else if (strcmp (transfer, "full") == 0)
863     {
864       param->transfer = TRUE;
865       param->shallow_transfer = FALSE;
866     }
867   else
868     {
869       g_warning ("Unknown transfer-ownership value: %s", transfer);
870     }
871 }
872
873 static gboolean
874 start_parameter (GMarkupParseContext *context,
875                  const gchar         *element_name,
876                  const gchar        **attribute_names,
877                  const gchar        **attribute_values,
878                  ParseContext        *ctx,
879                  GError             **error)
880 {
881   const gchar *name;
882   const gchar *direction;
883   const gchar *retval;
884   const gchar *dipper;
885   const gchar *optional;
886   const gchar *allow_none;
887   const gchar *transfer;
888   const gchar *scope;
889   const gchar *closure;
890   const gchar *destroy;
891   GIrNodeParam *param;
892
893   if (!(strcmp (element_name, "parameter") == 0 &&
894         ctx->state == STATE_FUNCTION_PARAMETERS))
895     return FALSE;
896
897   name = find_attribute ("name", attribute_names, attribute_values);
898   direction = find_attribute ("direction", attribute_names, attribute_values);
899   retval = find_attribute ("retval", attribute_names, attribute_values);
900   dipper = find_attribute ("dipper", attribute_names, attribute_values);
901   optional = find_attribute ("optional", attribute_names, attribute_values);
902   allow_none = find_attribute ("allow-none", attribute_names, attribute_values);
903   transfer = find_attribute ("transfer-ownership", attribute_names, attribute_values);
904   scope = find_attribute ("scope", attribute_names, attribute_values);
905   closure = find_attribute ("closure", attribute_names, attribute_values);
906   destroy = find_attribute ("destroy", attribute_names, attribute_values);
907
908   if (name == NULL)
909     name = "unknown";
910
911   param = (GIrNodeParam *)g_ir_node_new (G_IR_NODE_PARAM);
912
913   ctx->current_typed = (GIrNode*) param;
914   ctx->current_typed->name = g_strdup (name);
915
916   state_switch (ctx, STATE_FUNCTION_PARAMETER);
917
918   if (direction && strcmp (direction, "out") == 0)
919     {
920       param->in = FALSE;
921       param->out = TRUE;
922     }
923   else if (direction && strcmp (direction, "inout") == 0)
924     {
925       param->in = TRUE;
926       param->out = TRUE;
927     }
928   else
929     {
930       param->in = TRUE;
931       param->out = FALSE;
932     }
933
934   if (retval && strcmp (retval, "1") == 0)
935     param->retval = TRUE;
936   else
937     param->retval = FALSE;
938
939   if (dipper && strcmp (dipper, "1") == 0)
940     param->dipper = TRUE;
941   else
942     param->dipper = FALSE;
943
944   if (optional && strcmp (optional, "1") == 0)
945     param->optional = TRUE;
946   else
947     param->optional = FALSE;
948
949   if (allow_none && strcmp (allow_none, "1") == 0)
950     param->allow_none = TRUE;
951   else
952     param->allow_none = FALSE;
953
954   parse_param_transfer (param, transfer, name);
955
956   if (scope && strcmp (scope, "call") == 0)
957     param->scope = GI_SCOPE_TYPE_CALL;
958   else if (scope && strcmp (scope, "async") == 0)
959     param->scope = GI_SCOPE_TYPE_ASYNC;
960   else if (scope && strcmp (scope, "notified") == 0)
961     param->scope = GI_SCOPE_TYPE_NOTIFIED;
962   else
963     param->scope = GI_SCOPE_TYPE_INVALID;
964
965   param->closure = closure ? atoi (closure) : -1;
966   param->destroy = destroy ? atoi (destroy) : -1;
967
968   ((GIrNode *)param)->name = g_strdup (name);
969
970   switch (CURRENT_NODE (ctx)->type)
971     {
972     case G_IR_NODE_FUNCTION:
973     case G_IR_NODE_CALLBACK:
974       {
975         GIrNodeFunction *func;
976
977         func = (GIrNodeFunction *)CURRENT_NODE (ctx);
978         func->parameters = g_list_append (func->parameters, param);
979       }
980       break;
981     case G_IR_NODE_SIGNAL:
982       {
983         GIrNodeSignal *signal;
984
985         signal = (GIrNodeSignal *)CURRENT_NODE (ctx);
986         signal->parameters = g_list_append (signal->parameters, param);
987       }
988       break;
989     case G_IR_NODE_VFUNC:
990       {
991         GIrNodeVFunc *vfunc;
992
993         vfunc = (GIrNodeVFunc *)CURRENT_NODE (ctx);
994         vfunc->parameters = g_list_append (vfunc->parameters, param);
995       }
996       break;
997     default:
998       g_assert_not_reached ();
999     }
1000
1001   return TRUE;
1002 }
1003
1004 static gboolean
1005 start_field (GMarkupParseContext *context,
1006              const gchar         *element_name,
1007              const gchar        **attribute_names,
1008              const gchar        **attribute_values,
1009              ParseContext        *ctx,
1010              GError             **error)
1011 {
1012   const gchar *name;
1013   const gchar *readable;
1014   const gchar *writable;
1015   const gchar *bits;
1016   const gchar *branch;
1017   GIrNodeField *field;
1018
1019   switch (ctx->state)
1020     {
1021     case STATE_CLASS:
1022     case STATE_BOXED:
1023     case STATE_STRUCT:
1024     case STATE_UNION:
1025     case STATE_INTERFACE:
1026       break;
1027     default:
1028       return FALSE;
1029     }
1030
1031   if (strcmp (element_name, "field") != 0)
1032     return FALSE;
1033
1034   name = find_attribute ("name", attribute_names, attribute_values);
1035   readable = find_attribute ("readable", attribute_names, attribute_values);
1036   writable = find_attribute ("writable", attribute_names, attribute_values);
1037   bits = find_attribute ("bits", attribute_names, attribute_values);
1038   branch = find_attribute ("branch", attribute_names, attribute_values);
1039
1040   if (name == NULL)
1041     {
1042       MISSING_ATTRIBUTE (context, error, element_name, "name");
1043       return FALSE;
1044     }
1045
1046   field = (GIrNodeField *)g_ir_node_new (G_IR_NODE_FIELD);
1047   ctx->current_typed = (GIrNode*) field;
1048   ((GIrNode *)field)->name = g_strdup (name);
1049   /* Fields are assumed to be read-only.
1050    * (see also girwriter.py and generate.c)
1051    */
1052   field->readable = readable == NULL || strcmp (readable, "0") == 0;
1053   field->writable = writable != NULL && strcmp (writable, "1") == 0;
1054
1055   if (bits)
1056     field->bits = atoi (bits);
1057   else
1058     field->bits = 0;
1059
1060   switch (CURRENT_NODE (ctx)->type)
1061     {
1062     case G_IR_NODE_OBJECT:
1063       {
1064         GIrNodeInterface *iface;
1065
1066         iface = (GIrNodeInterface *)CURRENT_NODE (ctx);
1067         iface->members = g_list_append (iface->members, field);
1068         state_switch (ctx, STATE_CLASS_FIELD);
1069       }
1070       break;
1071     case G_IR_NODE_INTERFACE:
1072       {
1073         GIrNodeInterface *iface;
1074
1075         iface = (GIrNodeInterface *)CURRENT_NODE (ctx);
1076         iface->members = g_list_append (iface->members, field);
1077         state_switch (ctx, STATE_INTERFACE_FIELD);
1078       }
1079       break;
1080     case G_IR_NODE_BOXED:
1081       {
1082         GIrNodeBoxed *boxed;
1083
1084         boxed = (GIrNodeBoxed *)CURRENT_NODE (ctx);
1085                 boxed->members = g_list_append (boxed->members, field);
1086                 state_switch (ctx, STATE_BOXED_FIELD);
1087       }
1088       break;
1089     case G_IR_NODE_STRUCT:
1090       {
1091         GIrNodeStruct *struct_;
1092
1093         struct_ = (GIrNodeStruct *)CURRENT_NODE (ctx);
1094         struct_->members = g_list_append (struct_->members, field);
1095         state_switch (ctx, STATE_STRUCT_FIELD);
1096       }
1097       break;
1098     case G_IR_NODE_UNION:
1099       {
1100         GIrNodeUnion *union_;
1101
1102         union_ = (GIrNodeUnion *)CURRENT_NODE (ctx);
1103         union_->members = g_list_append (union_->members, field);
1104         if (branch)
1105           {
1106             GIrNodeConstant *constant;
1107
1108             constant = (GIrNodeConstant *) g_ir_node_new (G_IR_NODE_CONSTANT);
1109             ((GIrNode *)constant)->name = g_strdup (name);
1110             constant->value = g_strdup (branch);
1111             constant->type = union_->discriminator_type;
1112             constant->deprecated = FALSE;
1113
1114             union_->discriminators = g_list_append (union_->discriminators, constant);
1115           }
1116         state_switch (ctx, STATE_UNION_FIELD);
1117       }
1118       break;
1119     default:
1120       g_assert_not_reached ();
1121     }
1122
1123   return TRUE;
1124 }
1125
1126 static gboolean
1127 start_alias (GMarkupParseContext *context,
1128              const gchar         *element_name,
1129              const gchar        **attribute_names,
1130              const gchar        **attribute_values,
1131              ParseContext        *ctx,
1132              GError             **error)
1133 {
1134   const gchar *name;
1135   const gchar *target;
1136   char *key;
1137   char *value;
1138
1139   name = find_attribute ("name", attribute_names, attribute_values);
1140   if (name == NULL)
1141     {
1142       MISSING_ATTRIBUTE (context, error, element_name, "name");
1143       return FALSE;
1144     }
1145
1146   target = find_attribute ("target", attribute_names, attribute_values);
1147   if (name == NULL)
1148     {
1149       MISSING_ATTRIBUTE (context, error, element_name, "target");
1150       return FALSE;
1151     }
1152
1153   value = g_strdup (target);
1154   key = g_strdup_printf ("%s.%s", ctx->namespace, name);
1155   if (!strchr (target, '.'))
1156     {
1157       const BasicTypeInfo *basic = parse_basic (target);
1158       if (!basic)
1159         {
1160           g_free (value);
1161           /* For non-basic types, re-qualify the interface */
1162           value = g_strdup_printf ("%s.%s", ctx->namespace, target);
1163         }
1164     }
1165   g_hash_table_replace (ctx->aliases, key, value);
1166
1167   return TRUE;
1168 }
1169
1170 static gboolean
1171 start_enum (GMarkupParseContext *context,
1172              const gchar         *element_name,
1173              const gchar        **attribute_names,
1174              const gchar        **attribute_values,
1175              ParseContext        *ctx,
1176              GError             **error)
1177 {
1178   if ((strcmp (element_name, "enumeration") == 0 && ctx->state == STATE_NAMESPACE) ||
1179       (strcmp (element_name, "bitfield") == 0 && ctx->state == STATE_NAMESPACE))
1180     {
1181       const gchar *name;
1182       const gchar *typename;
1183       const gchar *typeinit;
1184       const gchar *deprecated;
1185
1186       name = find_attribute ("name", attribute_names, attribute_values);
1187       typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
1188       typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
1189       deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1190
1191       if (name == NULL)
1192         MISSING_ATTRIBUTE (context, error, element_name, "name");
1193       else
1194         {
1195           GIrNodeEnum *enum_;
1196
1197           if (strcmp (element_name, "enumeration") == 0)
1198             enum_ = (GIrNodeEnum *) g_ir_node_new (G_IR_NODE_ENUM);
1199           else
1200             enum_ = (GIrNodeEnum *) g_ir_node_new (G_IR_NODE_FLAGS);
1201           ((GIrNode *)enum_)->name = g_strdup (name);
1202           enum_->gtype_name = g_strdup (typename);
1203           enum_->gtype_init = g_strdup (typeinit);
1204           if (deprecated)
1205             enum_->deprecated = TRUE;
1206           else
1207             enum_->deprecated = FALSE;
1208
1209           push_node (ctx, (GIrNode *) enum_);
1210           ctx->current_module->entries =
1211             g_list_append (ctx->current_module->entries, enum_);
1212
1213           state_switch (ctx, STATE_ENUM);
1214         }
1215
1216       return TRUE;
1217     }
1218   return FALSE;
1219 }
1220
1221 static gboolean
1222 start_property (GMarkupParseContext *context,
1223                 const gchar         *element_name,
1224                 const gchar        **attribute_names,
1225                 const gchar        **attribute_values,
1226                 ParseContext        *ctx,
1227                 GError             **error)
1228 {
1229   if (strcmp (element_name, "property") == 0 &&
1230       (ctx->state == STATE_CLASS ||
1231        ctx->state == STATE_INTERFACE))
1232     {
1233       const gchar *name;
1234       const gchar *readable;
1235       const gchar *writable;
1236       const gchar *construct;
1237       const gchar *construct_only;
1238
1239       name = find_attribute ("name", attribute_names, attribute_values);
1240       readable = find_attribute ("readable", attribute_names, attribute_values);
1241       writable = find_attribute ("writable", attribute_names, attribute_values);
1242       construct = find_attribute ("construct", attribute_names, attribute_values);
1243       construct_only = find_attribute ("construct-only", attribute_names, attribute_values);
1244
1245       if (name == NULL)
1246         MISSING_ATTRIBUTE (context, error, element_name, "name");
1247       else
1248         {
1249           GIrNodeProperty *property;
1250           GIrNodeInterface *iface;
1251
1252           property = (GIrNodeProperty *) g_ir_node_new (G_IR_NODE_PROPERTY);
1253           ctx->current_typed = (GIrNode*) property;
1254
1255           ((GIrNode *)property)->name = g_strdup (name);
1256
1257           /* Assume properties are readable */
1258           if (readable == NULL || strcmp (readable, "1") == 0)
1259             property->readable = TRUE;
1260           else
1261             property->readable = FALSE;
1262           if (writable && strcmp (writable, "1") == 0)
1263             property->writable = TRUE;
1264           else
1265             property->writable = FALSE;
1266           if (construct && strcmp (construct, "1") == 0)
1267             property->construct = TRUE;
1268           else
1269             property->construct = FALSE;
1270           if (construct_only && strcmp (construct_only, "1") == 0)
1271             property->construct_only = TRUE;
1272           else
1273             property->construct_only = FALSE;
1274
1275           iface = (GIrNodeInterface *)CURRENT_NODE (ctx);
1276           iface->members = g_list_append (iface->members, property);
1277
1278           if (ctx->state == STATE_CLASS)
1279             state_switch (ctx, STATE_CLASS_PROPERTY);
1280           else if (ctx->state == STATE_INTERFACE)
1281             state_switch (ctx, STATE_INTERFACE_PROPERTY);
1282           else
1283             g_assert_not_reached ();
1284         }
1285
1286       return TRUE;
1287     }
1288   return FALSE;
1289 }
1290
1291 static gint
1292 parse_value (const gchar *str)
1293 {
1294   gchar *shift_op;
1295
1296   /* FIXME just a quick hack */
1297   shift_op = strstr (str, "<<");
1298
1299   if (shift_op)
1300     {
1301       gint base, shift;
1302
1303       base = strtol (str, NULL, 10);
1304       shift = strtol (shift_op + 3, NULL, 10);
1305
1306       return base << shift;
1307     }
1308   else
1309     return strtol (str, NULL, 10);
1310
1311   return 0;
1312 }
1313
1314 static gboolean
1315 start_member (GMarkupParseContext *context,
1316               const gchar         *element_name,
1317               const gchar        **attribute_names,
1318               const gchar        **attribute_values,
1319               ParseContext        *ctx,
1320               GError             **error)
1321 {
1322   if (strcmp (element_name, "member") == 0 &&
1323       ctx->state == STATE_ENUM)
1324     {
1325       const gchar *name;
1326       const gchar *value;
1327       const gchar *deprecated;
1328
1329       name = find_attribute ("name", attribute_names, attribute_values);
1330       value = find_attribute ("value", attribute_names, attribute_values);
1331       deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1332
1333       if (name == NULL)
1334         MISSING_ATTRIBUTE (context, error, element_name, "name");
1335       else
1336         {
1337           GIrNodeEnum *enum_;
1338           GIrNodeValue *value_;
1339
1340           value_ = (GIrNodeValue *) g_ir_node_new (G_IR_NODE_VALUE);
1341
1342           ((GIrNode *)value_)->name = g_strdup (name);
1343
1344           value_->value = parse_value (value);
1345
1346           if (deprecated)
1347             value_->deprecated = TRUE;
1348           else
1349             value_->deprecated = FALSE;
1350
1351           enum_ = (GIrNodeEnum *)CURRENT_NODE (ctx);
1352           enum_->values = g_list_append (enum_->values, value_);
1353         }
1354
1355       return TRUE;
1356     }
1357   return FALSE;
1358 }
1359
1360 static gboolean
1361 start_constant (GMarkupParseContext *context,
1362                 const gchar         *element_name,
1363                 const gchar        **attribute_names,
1364                 const gchar        **attribute_values,
1365                 ParseContext        *ctx,
1366                 GError             **error)
1367 {
1368   if (strcmp (element_name, "constant") == 0 &&
1369       (ctx->state == STATE_NAMESPACE ||
1370        ctx->state == STATE_CLASS ||
1371        ctx->state == STATE_INTERFACE))
1372     {
1373       const gchar *name;
1374       const gchar *value;
1375       const gchar *deprecated;
1376
1377       name = find_attribute ("name", attribute_names, attribute_values);
1378       value = find_attribute ("value", attribute_names, attribute_values);
1379       deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1380
1381       if (name == NULL)
1382         MISSING_ATTRIBUTE (context, error, element_name, "name");
1383       else if (value == NULL)
1384         MISSING_ATTRIBUTE (context, error, element_name, "value");
1385       else
1386         {
1387           GIrNodeConstant *constant;
1388
1389           constant = (GIrNodeConstant *) g_ir_node_new (G_IR_NODE_CONSTANT);
1390
1391           ((GIrNode *)constant)->name = g_strdup (name);
1392           constant->value = g_strdup (value);
1393
1394           ctx->current_typed = (GIrNode*) constant;
1395
1396           if (deprecated)
1397             constant->deprecated = TRUE;
1398           else
1399             constant->deprecated = FALSE;
1400
1401           if (ctx->state == STATE_NAMESPACE)
1402             {
1403               push_node (ctx, (GIrNode *) constant);
1404               ctx->current_module->entries =
1405                 g_list_append (ctx->current_module->entries, constant);
1406             }
1407           else
1408             {
1409               GIrNodeInterface *iface;
1410
1411               iface = (GIrNodeInterface *)CURRENT_NODE (ctx);
1412               iface->members = g_list_append (iface->members, constant);
1413             }
1414
1415           switch (ctx->state)
1416             {
1417             case STATE_NAMESPACE:
1418               state_switch (ctx, STATE_NAMESPACE_CONSTANT);
1419               break;
1420             case STATE_CLASS:
1421               state_switch (ctx, STATE_CLASS_CONSTANT);
1422               break;
1423             case STATE_INTERFACE:
1424               state_switch (ctx, STATE_INTERFACE_CONSTANT);
1425               break;
1426             default:
1427               g_assert_not_reached ();
1428               break;
1429             }
1430         }
1431
1432       return TRUE;
1433     }
1434   return FALSE;
1435 }
1436
1437 static gboolean
1438 start_errordomain (GMarkupParseContext *context,
1439                    const gchar         *element_name,
1440                    const gchar        **attribute_names,
1441                    const gchar        **attribute_values,
1442                    ParseContext        *ctx,
1443                    GError             **error)
1444 {
1445   if (strcmp (element_name, "errordomain") == 0 &&
1446       ctx->state == STATE_NAMESPACE)
1447     {
1448       const gchar *name;
1449       const gchar *getquark;
1450       const gchar *codes;
1451       const gchar *deprecated;
1452
1453       name = find_attribute ("name", attribute_names, attribute_values);
1454       getquark = find_attribute ("get-quark", attribute_names, attribute_values);
1455       codes = find_attribute ("codes", attribute_names, attribute_values);
1456       deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1457
1458       if (name == NULL)
1459         MISSING_ATTRIBUTE (context, error, element_name, "name");
1460       else if (getquark == NULL)
1461         MISSING_ATTRIBUTE (context, error, element_name, "getquark");
1462       else if (codes == NULL)
1463         MISSING_ATTRIBUTE (context, error, element_name, "codes");
1464       else
1465         {
1466           GIrNodeErrorDomain *domain;
1467
1468           domain = (GIrNodeErrorDomain *) g_ir_node_new (G_IR_NODE_ERROR_DOMAIN);
1469
1470           ((GIrNode *)domain)->name = g_strdup (name);
1471           domain->getquark = g_strdup (getquark);
1472           domain->codes = g_strdup (codes);
1473
1474           if (deprecated)
1475             domain->deprecated = TRUE;
1476           else
1477             domain->deprecated = FALSE;
1478
1479           push_node (ctx, (GIrNode *) domain);
1480           ctx->current_module->entries =
1481             g_list_append (ctx->current_module->entries, domain);
1482
1483           state_switch (ctx, STATE_ERRORDOMAIN);
1484         }
1485
1486       return TRUE;
1487     }
1488   return FALSE;
1489 }
1490
1491 static gboolean
1492 start_interface (GMarkupParseContext *context,
1493                  const gchar         *element_name,
1494                  const gchar        **attribute_names,
1495                  const gchar        **attribute_values,
1496                  ParseContext        *ctx,
1497                  GError             **error)
1498 {
1499   if (strcmp (element_name, "interface") == 0 &&
1500       ctx->state == STATE_NAMESPACE)
1501     {
1502       const gchar *name;
1503       const gchar *typename;
1504       const gchar *typeinit;
1505       const gchar *deprecated;
1506       const gchar *glib_type_struct;
1507
1508       name = find_attribute ("name", attribute_names, attribute_values);
1509       typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
1510       typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
1511       glib_type_struct = find_attribute ("glib:type-struct", attribute_names, attribute_values);
1512       deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1513
1514       if (name == NULL)
1515         MISSING_ATTRIBUTE (context, error, element_name, "name");
1516       else if (typename == NULL)
1517         MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
1518       else if (typeinit == NULL)
1519         MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
1520       else
1521         {
1522           GIrNodeInterface *iface;
1523
1524           iface = (GIrNodeInterface *) g_ir_node_new (G_IR_NODE_INTERFACE);
1525           ((GIrNode *)iface)->name = g_strdup (name);
1526           iface->gtype_name = g_strdup (typename);
1527           iface->gtype_init = g_strdup (typeinit);
1528           iface->glib_type_struct = g_strdup (glib_type_struct);
1529           if (deprecated)
1530             iface->deprecated = TRUE;
1531           else
1532             iface->deprecated = FALSE;
1533
1534           push_node (ctx, (GIrNode *) iface);
1535           ctx->current_module->entries =
1536             g_list_append (ctx->current_module->entries, iface);
1537
1538           state_switch (ctx, STATE_INTERFACE);
1539
1540         }
1541
1542       return TRUE;
1543     }
1544   return FALSE;
1545 }
1546
1547 static gboolean
1548 start_class (GMarkupParseContext *context,
1549               const gchar         *element_name,
1550               const gchar        **attribute_names,
1551               const gchar        **attribute_values,
1552               ParseContext        *ctx,
1553               GError             **error)
1554 {
1555   if (strcmp (element_name, "class") == 0 &&
1556       ctx->state == STATE_NAMESPACE)
1557     {
1558       const gchar *name;
1559       const gchar *parent;
1560       const gchar *glib_type_struct;
1561       const gchar *typename;
1562       const gchar *typeinit;
1563       const gchar *deprecated;
1564       const gchar *abstract;
1565
1566       name = find_attribute ("name", attribute_names, attribute_values);
1567       parent = find_attribute ("parent", attribute_names, attribute_values);
1568       glib_type_struct = find_attribute ("glib:type-struct", attribute_names, attribute_values);
1569       typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
1570       typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
1571       deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1572       abstract = find_attribute ("abstract", attribute_names, attribute_values);
1573
1574       if (name == NULL)
1575         MISSING_ATTRIBUTE (context, error, element_name, "name");
1576       else if (typename == NULL)
1577         MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
1578       else if (typeinit == NULL && strcmp (typename, "GObject"))
1579         MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
1580       else
1581         {
1582           GIrNodeInterface *iface;
1583
1584           iface = (GIrNodeInterface *) g_ir_node_new (G_IR_NODE_OBJECT);
1585           ((GIrNode *)iface)->name = g_strdup (name);
1586           iface->gtype_name = g_strdup (typename);
1587           iface->gtype_init = g_strdup (typeinit);
1588           iface->parent = g_strdup (parent);
1589           iface->glib_type_struct = g_strdup (glib_type_struct);
1590           if (deprecated)
1591             iface->deprecated = TRUE;
1592           else
1593             iface->deprecated = FALSE;
1594
1595           iface->abstract = abstract && strcmp (abstract, "1") == 0;
1596
1597           push_node (ctx, (GIrNode *) iface);
1598           ctx->current_module->entries =
1599             g_list_append (ctx->current_module->entries, iface);
1600
1601           state_switch (ctx, STATE_CLASS);
1602         }
1603
1604       return TRUE;
1605     }
1606   return  FALSE;
1607 }
1608
1609 static gboolean
1610 start_type (GMarkupParseContext *context,
1611             const gchar         *element_name,
1612             const gchar        **attribute_names,
1613             const gchar        **attribute_values,
1614             ParseContext       *ctx,
1615             GError             **error)
1616 {
1617   const gchar *name;
1618   const gchar *ctype;
1619   gboolean is_array;
1620   gboolean is_varargs;
1621   GIrNodeType *typenode;
1622
1623   is_array = strcmp (element_name, "array") == 0;
1624   is_varargs = strcmp (element_name, "varargs") == 0;
1625
1626   if (!(is_array || is_varargs || (strcmp (element_name, "type") == 0)))
1627     return FALSE;
1628
1629   if (ctx->state == STATE_TYPE)
1630     {
1631       ctx->type_depth++;
1632       ctx->type_stack = g_list_prepend (ctx->type_stack, ctx->type_parameters);
1633       ctx->type_parameters = NULL;
1634     }
1635   else if (ctx->state == STATE_FUNCTION_PARAMETER ||
1636            ctx->state == STATE_FUNCTION_RETURN ||
1637            ctx->state == STATE_STRUCT_FIELD ||
1638            ctx->state == STATE_UNION_FIELD ||
1639            ctx->state == STATE_CLASS_PROPERTY ||
1640            ctx->state == STATE_CLASS_FIELD ||
1641            ctx->state == STATE_INTERFACE_FIELD ||
1642            ctx->state == STATE_INTERFACE_PROPERTY ||
1643            ctx->state == STATE_BOXED_FIELD ||
1644            ctx->state == STATE_NAMESPACE_CONSTANT ||
1645            ctx->state == STATE_CLASS_CONSTANT ||
1646            ctx->state == STATE_INTERFACE_CONSTANT
1647            )
1648     {
1649       state_switch (ctx, STATE_TYPE);
1650       ctx->type_depth = 1;
1651       if (is_varargs)
1652         {
1653           switch (CURRENT_NODE (ctx)->type)
1654             {
1655             case G_IR_NODE_FUNCTION:
1656             case G_IR_NODE_CALLBACK:
1657               {
1658                 GIrNodeFunction *func = (GIrNodeFunction *)CURRENT_NODE (ctx);
1659                 func->is_varargs = TRUE;
1660               }
1661               break;
1662             case G_IR_NODE_VFUNC:
1663               {
1664                 GIrNodeVFunc *vfunc = (GIrNodeVFunc *)CURRENT_NODE (ctx);
1665                 vfunc->is_varargs = TRUE;
1666               }
1667               break;
1668             /* list others individually rather than with default: so that compiler
1669              * warns if new node types are added without adding them to the switch
1670              */
1671             case G_IR_NODE_INVALID:
1672             case G_IR_NODE_ENUM:
1673             case G_IR_NODE_FLAGS:
1674             case G_IR_NODE_CONSTANT:
1675             case G_IR_NODE_ERROR_DOMAIN:
1676             case G_IR_NODE_PARAM:
1677             case G_IR_NODE_TYPE:
1678             case G_IR_NODE_PROPERTY:
1679             case G_IR_NODE_SIGNAL:
1680             case G_IR_NODE_VALUE:
1681             case G_IR_NODE_FIELD:
1682             case G_IR_NODE_XREF:
1683             case G_IR_NODE_STRUCT:
1684             case G_IR_NODE_BOXED:
1685             case G_IR_NODE_OBJECT:
1686             case G_IR_NODE_INTERFACE:
1687             case G_IR_NODE_UNION:
1688               g_assert_not_reached ();
1689               break;
1690             }
1691         }
1692       ctx->type_stack = NULL;
1693       ctx->type_parameters = NULL;
1694     }
1695
1696   if (!ctx->current_typed)
1697     {
1698       g_set_error (error,
1699                    G_MARKUP_ERROR,
1700                    G_MARKUP_ERROR_INVALID_CONTENT,
1701                    "The element <type> is invalid here");
1702       return FALSE;
1703     }
1704
1705   if (is_varargs)
1706     return TRUE;
1707
1708   if (is_array)
1709     {
1710       const char *zero;
1711       const char *len;
1712       const char *size;
1713
1714       typenode = (GIrNodeType *)g_ir_node_new (G_IR_NODE_TYPE);
1715
1716       typenode->tag = GI_TYPE_TAG_ARRAY;
1717       typenode->is_pointer = TRUE;
1718       typenode->is_array = TRUE;
1719
1720       zero = find_attribute ("zero-terminated", attribute_names, attribute_values);
1721       len = find_attribute ("length", attribute_names, attribute_values);
1722       size = find_attribute ("fixed-size", attribute_names, attribute_values);
1723
1724       typenode->zero_terminated = !(zero && strcmp (zero, "1") != 0);
1725       typenode->has_length = len != NULL;
1726       typenode->length = typenode->has_length ? atoi (len) : -1;
1727
1728       typenode->has_size = size != NULL;
1729       typenode->size = typenode->has_size ? atoi (size) : -1;
1730
1731       if (zero)
1732         typenode->zero_terminated = strcmp(zero, "1") == 0;
1733       else
1734         /* If neither zero-terminated nor length nor fixed-size is given, assume zero-terminated. */
1735         typenode->zero_terminated = !(typenode->has_length || typenode->has_size);
1736     }
1737   else
1738     {
1739       int pointer_depth;
1740       name = find_attribute ("name", attribute_names, attribute_values);
1741
1742       if (name == NULL)
1743         MISSING_ATTRIBUTE (context, error, element_name, "name");
1744
1745       pointer_depth = 0;
1746       ctype = find_attribute ("c:type", attribute_names, attribute_values);
1747       if (ctype != NULL)
1748         {
1749           const char *cp = ctype + strlen(ctype) - 1;
1750           while (cp > ctype && *cp-- == '*')
1751             pointer_depth++;
1752         }
1753
1754       if (ctx->current_typed->type == G_IR_NODE_PARAM &&
1755           ((GIrNodeParam *)ctx->current_typed)->out &&
1756           pointer_depth > 0)
1757         pointer_depth--;
1758
1759       typenode = parse_type (ctx, name);
1760
1761       /* A 'disguised' structure is one where the c:type is a typedef that
1762        * doesn't look like a pointer, but is internally.
1763        */
1764       if (typenode->tag == GI_TYPE_TAG_INTERFACE &&
1765           is_disguised_structure (ctx, typenode->interface))
1766         pointer_depth++;
1767
1768       if (pointer_depth > 0)
1769         typenode->is_pointer = TRUE;
1770     }
1771
1772   ctx->type_parameters = g_list_append (ctx->type_parameters, typenode);
1773
1774   return TRUE;
1775 }
1776
1777 static void
1778 end_type_top (ParseContext *ctx)
1779 {
1780   GIrNodeType *typenode;
1781
1782   if (!ctx->type_parameters)
1783     goto out;
1784
1785   typenode = (GIrNodeType*)ctx->type_parameters->data;
1786
1787   /* Default to pointer for unspecified containers */
1788   if (typenode->tag == GI_TYPE_TAG_ARRAY ||
1789       typenode->tag == GI_TYPE_TAG_GLIST ||
1790       typenode->tag == GI_TYPE_TAG_GSLIST)
1791     {
1792       if (typenode->parameter_type1 == NULL)
1793         typenode->parameter_type1 = parse_type (ctx, "any");
1794     }
1795   else if (typenode->tag == GI_TYPE_TAG_GHASH)
1796     {
1797       if (typenode->parameter_type1 == NULL)
1798         {
1799           typenode->parameter_type1 = parse_type (ctx, "any");
1800           typenode->parameter_type2 = parse_type (ctx, "any");
1801         }
1802     }
1803
1804   switch (ctx->current_typed->type)
1805     {
1806     case G_IR_NODE_PARAM:
1807       {
1808         GIrNodeParam *param = (GIrNodeParam *)ctx->current_typed;
1809         param->type = typenode;
1810       }
1811       break;
1812     case G_IR_NODE_FIELD:
1813       {
1814         GIrNodeField *field = (GIrNodeField *)ctx->current_typed;
1815         field->type = typenode;
1816       }
1817       break;
1818     case G_IR_NODE_PROPERTY:
1819       {
1820         GIrNodeProperty *property = (GIrNodeProperty *) ctx->current_typed;
1821         property->type = typenode;
1822       }
1823       break;
1824     case G_IR_NODE_CONSTANT:
1825       {
1826         GIrNodeConstant *constant = (GIrNodeConstant *)ctx->current_typed;
1827         constant->type = typenode;
1828       }
1829       break;
1830     default:
1831       g_printerr("current node is %d\n", CURRENT_NODE (ctx)->type);
1832       g_assert_not_reached ();
1833     }
1834   g_list_free (ctx->type_parameters);
1835
1836  out:
1837   ctx->type_depth = 0;
1838   ctx->type_parameters = NULL;
1839   ctx->current_typed = NULL;
1840 }
1841
1842 static void
1843 end_type_recurse (ParseContext *ctx)
1844 {
1845   GIrNodeType *parent;
1846   GIrNodeType *param = NULL;
1847
1848   parent = (GIrNodeType *) ((GList*)ctx->type_stack->data)->data;
1849   if (ctx->type_parameters)
1850     param = (GIrNodeType *) ctx->type_parameters->data;
1851
1852   if (parent->tag == GI_TYPE_TAG_ARRAY ||
1853       parent->tag == GI_TYPE_TAG_GLIST ||
1854       parent->tag == GI_TYPE_TAG_GSLIST)
1855     {
1856       g_assert (param != NULL);
1857
1858       if (parent->parameter_type1 == NULL)
1859         parent->parameter_type1 = param;
1860       else
1861         g_assert_not_reached ();
1862     }
1863   else if (parent->tag == GI_TYPE_TAG_GHASH)
1864     {
1865       g_assert (param != NULL);
1866
1867       if (parent->parameter_type1 == NULL)
1868         parent->parameter_type1 = param;
1869       else if (parent->parameter_type2 == NULL)
1870         parent->parameter_type2 = param;
1871       else
1872         g_assert_not_reached ();
1873     }
1874   g_list_free (ctx->type_parameters);
1875   ctx->type_parameters = (GList *)ctx->type_stack->data;
1876   ctx->type_stack = g_list_delete_link (ctx->type_stack, ctx->type_stack);
1877 }
1878
1879 static void
1880 end_type (ParseContext *ctx)
1881 {
1882   if (ctx->type_depth == 1)
1883     {
1884       end_type_top (ctx);
1885       state_switch (ctx, ctx->prev_state);
1886     }
1887   else
1888     {
1889       end_type_recurse (ctx);
1890       ctx->type_depth--;
1891     }
1892 }
1893
1894 static gboolean
1895 start_attribute (GMarkupParseContext *context,
1896                  const gchar         *element_name,
1897                  const gchar        **attribute_names,
1898                  const gchar        **attribute_values,
1899                  ParseContext       *ctx,
1900                  GError             **error)
1901 {
1902   const gchar *name;
1903   const gchar *value;
1904   GIrNode *curnode;
1905
1906   if (strcmp (element_name, "attribute") != 0 || ctx->node_stack == NULL)
1907     return FALSE;
1908
1909   name = find_attribute ("name", attribute_names, attribute_values);
1910   value = find_attribute ("value", attribute_names, attribute_values);
1911
1912   if (name == NULL)
1913     {
1914       MISSING_ATTRIBUTE (context, error, element_name, "name");
1915       return FALSE;
1916     }
1917   if (value == NULL)
1918     {
1919       MISSING_ATTRIBUTE (context, error, element_name, "value");
1920       return FALSE;
1921     }
1922
1923   state_switch (ctx, STATE_ATTRIBUTE);
1924
1925   curnode = CURRENT_NODE (ctx);
1926
1927   g_hash_table_insert (curnode->attributes, g_strdup (name), g_strdup (value));
1928
1929   return TRUE;
1930 }
1931
1932 static gboolean
1933 start_return_value (GMarkupParseContext *context,
1934                     const gchar         *element_name,
1935                     const gchar        **attribute_names,
1936                     const gchar        **attribute_values,
1937                     ParseContext       *ctx,
1938                     GError             **error)
1939 {
1940   if (strcmp (element_name, "return-value") == 0 &&
1941       ctx->state == STATE_FUNCTION)
1942     {
1943       GIrNodeParam *param;
1944       const gchar  *transfer;
1945
1946       param = (GIrNodeParam *)g_ir_node_new (G_IR_NODE_PARAM);
1947       param->in = FALSE;
1948       param->out = FALSE;
1949       param->retval = TRUE;
1950
1951       ctx->current_typed = (GIrNode*) param;
1952
1953       state_switch (ctx, STATE_FUNCTION_RETURN);
1954
1955       transfer = find_attribute ("transfer-ownership", attribute_names, attribute_values);
1956       parse_param_transfer (param, transfer, NULL);
1957
1958       switch (CURRENT_NODE (ctx)->type)
1959         {
1960         case G_IR_NODE_FUNCTION:
1961         case G_IR_NODE_CALLBACK:
1962           {
1963             GIrNodeFunction *func = (GIrNodeFunction *)CURRENT_NODE (ctx);
1964             func->result = param;
1965           }
1966           break;
1967         case G_IR_NODE_SIGNAL:
1968           {
1969             GIrNodeSignal *signal = (GIrNodeSignal *)CURRENT_NODE (ctx);
1970             signal->result = param;
1971           }
1972           break;
1973         case G_IR_NODE_VFUNC:
1974           {
1975             GIrNodeVFunc *vfunc = (GIrNodeVFunc *)CURRENT_NODE (ctx);
1976             vfunc->result = param;
1977           }
1978           break;
1979         default:
1980           g_assert_not_reached ();
1981         }
1982
1983       return TRUE;
1984     }
1985
1986   return FALSE;
1987 }
1988
1989 static gboolean
1990 start_implements (GMarkupParseContext *context,
1991                   const gchar         *element_name,
1992                   const gchar        **attribute_names,
1993                   const gchar        **attribute_values,
1994                   ParseContext       *ctx,
1995                   GError             **error)
1996 {
1997   GIrNodeInterface *iface;
1998   const char *name;
1999
2000   if (strcmp (element_name, "implements") != 0 ||
2001       !(ctx->state == STATE_CLASS))
2002     return FALSE;
2003
2004   state_switch (ctx, STATE_IMPLEMENTS);
2005
2006   name = find_attribute ("name", attribute_names, attribute_values);
2007   if (name == NULL)
2008     {
2009       MISSING_ATTRIBUTE (context, error, element_name, "name");
2010       return FALSE;
2011     }
2012
2013   iface = (GIrNodeInterface *)CURRENT_NODE (ctx);
2014   iface->interfaces = g_list_append (iface->interfaces, g_strdup (name));
2015
2016   return TRUE;
2017 }
2018
2019 static gboolean
2020 start_glib_signal (GMarkupParseContext *context,
2021                    const gchar         *element_name,
2022                    const gchar        **attribute_names,
2023                    const gchar        **attribute_values,
2024                    ParseContext       *ctx,
2025                    GError             **error)
2026 {
2027   if (strcmp (element_name, "glib:signal") == 0 &&
2028       (ctx->state == STATE_CLASS ||
2029        ctx->state == STATE_INTERFACE))
2030     {
2031       const gchar *name;
2032       const gchar *when;
2033       const gchar *no_recurse;
2034       const gchar *detailed;
2035       const gchar *action;
2036       const gchar *no_hooks;
2037       const gchar *has_class_closure;
2038
2039       name = find_attribute ("name", attribute_names, attribute_values);
2040       when = find_attribute ("when", attribute_names, attribute_values);
2041       no_recurse = find_attribute ("no-recurse", attribute_names, attribute_values);
2042       detailed = find_attribute ("detailed", attribute_names, attribute_values);
2043       action = find_attribute ("action", attribute_names, attribute_values);
2044       no_hooks = find_attribute ("no-hooks", attribute_names, attribute_values);
2045       has_class_closure = find_attribute ("has-class-closure", attribute_names, attribute_values);
2046
2047       if (name == NULL)
2048         MISSING_ATTRIBUTE (context, error, element_name, "name");
2049       else
2050         {
2051           GIrNodeInterface *iface;
2052           GIrNodeSignal *signal;
2053
2054           signal = (GIrNodeSignal *)g_ir_node_new (G_IR_NODE_SIGNAL);
2055
2056           ((GIrNode *)signal)->name = g_strdup (name);
2057
2058           signal->run_first = FALSE;
2059           signal->run_last = FALSE;
2060           signal->run_cleanup = FALSE;
2061           if (when == NULL || strcmp (when, "LAST") == 0)
2062             signal->run_last = TRUE;
2063           else if (strcmp (when, "FIRST") == 0)
2064             signal->run_first = TRUE;
2065           else
2066             signal->run_cleanup = TRUE;
2067
2068           if (no_recurse && strcmp (no_recurse, "1") == 0)
2069             signal->no_recurse = TRUE;
2070           else
2071             signal->no_recurse = FALSE;
2072           if (detailed && strcmp (detailed, "1") == 0)
2073             signal->detailed = TRUE;
2074           else
2075             signal->detailed = FALSE;
2076           if (action && strcmp (action, "1") == 0)
2077             signal->action = TRUE;
2078           else
2079             signal->action = FALSE;
2080           if (no_hooks && strcmp (no_hooks, "1") == 0)
2081             signal->no_hooks = TRUE;
2082           else
2083             signal->no_hooks = FALSE;
2084           if (has_class_closure && strcmp (has_class_closure, "1") == 0)
2085             signal->has_class_closure = TRUE;
2086           else
2087             signal->has_class_closure = FALSE;
2088
2089           iface = (GIrNodeInterface *)CURRENT_NODE (ctx);
2090           iface->members = g_list_append (iface->members, signal);
2091
2092           push_node (ctx, (GIrNode *)signal);
2093           state_switch (ctx, STATE_FUNCTION);
2094         }
2095
2096       return TRUE;
2097     }
2098   return FALSE;
2099 }
2100
2101 static gboolean
2102 start_vfunc (GMarkupParseContext *context,
2103              const gchar         *element_name,
2104              const gchar        **attribute_names,
2105              const gchar        **attribute_values,
2106              ParseContext       *ctx,
2107              GError             **error)
2108 {
2109   if (strcmp (element_name, "virtual-method") == 0 &&
2110       (ctx->state == STATE_CLASS ||
2111        ctx->state == STATE_INTERFACE))
2112     {
2113       const gchar *name;
2114       const gchar *must_chain_up;
2115       const gchar *override;
2116       const gchar *is_class_closure;
2117       const gchar *offset;
2118       const gchar *invoker;
2119
2120       name = find_attribute ("name", attribute_names, attribute_values);
2121       must_chain_up = find_attribute ("must-chain-up", attribute_names, attribute_values);
2122       override = find_attribute ("override", attribute_names, attribute_values);
2123       is_class_closure = find_attribute ("is-class-closure", attribute_names, attribute_values);
2124       offset = find_attribute ("offset", attribute_names, attribute_values);
2125       invoker = find_attribute ("invoker", attribute_names, attribute_values);
2126
2127       if (name == NULL)
2128         MISSING_ATTRIBUTE (context, error, element_name, "name");
2129       else
2130         {
2131           GIrNodeInterface *iface;
2132           GIrNodeVFunc *vfunc;
2133
2134           vfunc = (GIrNodeVFunc *)g_ir_node_new (G_IR_NODE_VFUNC);
2135
2136           ((GIrNode *)vfunc)->name = g_strdup (name);
2137
2138           if (must_chain_up && strcmp (must_chain_up, "1") == 0)
2139             vfunc->must_chain_up = TRUE;
2140           else
2141             vfunc->must_chain_up = FALSE;
2142
2143           if (override && strcmp (override, "always") == 0)
2144             {
2145               vfunc->must_be_implemented = TRUE;
2146               vfunc->must_not_be_implemented = FALSE;
2147             }
2148           else if (override && strcmp (override, "never") == 0)
2149             {
2150               vfunc->must_be_implemented = FALSE;
2151               vfunc->must_not_be_implemented = TRUE;
2152             }
2153           else
2154             {
2155               vfunc->must_be_implemented = FALSE;
2156               vfunc->must_not_be_implemented = FALSE;
2157             }
2158
2159           if (is_class_closure && strcmp (is_class_closure, "1") == 0)
2160             vfunc->is_class_closure = TRUE;
2161           else
2162             vfunc->is_class_closure = FALSE;
2163
2164           if (offset)
2165             vfunc->offset = atoi (offset);
2166           else
2167             vfunc->offset = 0;
2168
2169           vfunc->invoker = g_strdup (invoker);
2170
2171           iface = (GIrNodeInterface *)CURRENT_NODE (ctx);
2172           iface->members = g_list_append (iface->members, vfunc);
2173
2174           push_node (ctx, (GIrNode *)vfunc);
2175           state_switch (ctx, STATE_FUNCTION);
2176         }
2177
2178       return TRUE;
2179     }
2180   return FALSE;
2181 }
2182
2183
2184 static gboolean
2185 start_struct (GMarkupParseContext *context,
2186               const gchar         *element_name,
2187               const gchar        **attribute_names,
2188               const gchar        **attribute_values,
2189               ParseContext       *ctx,
2190               GError             **error)
2191 {
2192   if (strcmp (element_name, "record") == 0 &&
2193       (ctx->state == STATE_NAMESPACE ||
2194        ctx->state == STATE_UNION ||
2195        ctx->state == STATE_STRUCT ||
2196        ctx->state == STATE_CLASS))
2197     {
2198       const gchar *name;
2199       const gchar *deprecated;
2200       const gchar *disguised;
2201       const gchar *gtype_name;
2202       const gchar *gtype_init;
2203       const gchar *gtype_struct;
2204       GIrNodeStruct *struct_;
2205
2206       name = find_attribute ("name", attribute_names, attribute_values);
2207       deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
2208       disguised = find_attribute ("disguised", attribute_names, attribute_values);
2209       gtype_name = find_attribute ("glib:type-name", attribute_names, attribute_values);
2210       gtype_init = find_attribute ("glib:get-type", attribute_names, attribute_values);
2211       gtype_struct = find_attribute ("glib:is-gtype-struct-for", attribute_names, attribute_values);
2212
2213       if (name == NULL && ctx->node_stack == NULL)
2214         {
2215           MISSING_ATTRIBUTE (context, error, element_name, "name");
2216           return FALSE;
2217         }
2218       if ((gtype_name == NULL && gtype_init != NULL))
2219         {
2220           MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
2221           return FALSE;
2222         }
2223       if ((gtype_name != NULL && gtype_init == NULL))
2224         {
2225           MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
2226           return FALSE;
2227         }
2228
2229       struct_ = (GIrNodeStruct *) g_ir_node_new (G_IR_NODE_STRUCT);
2230
2231       ((GIrNode *)struct_)->name = g_strdup (name ? name : "");
2232       if (deprecated)
2233         struct_->deprecated = TRUE;
2234       else
2235         struct_->deprecated = FALSE;
2236
2237       if (disguised && strcmp (disguised, "1") == 0)
2238         struct_->disguised = TRUE;
2239
2240       struct_->is_gtype_struct = gtype_struct != NULL;
2241
2242       struct_->gtype_name = g_strdup (gtype_name);
2243       struct_->gtype_init = g_strdup (gtype_init);
2244
2245       if (ctx->node_stack == NULL)
2246         ctx->current_module->entries =
2247           g_list_append (ctx->current_module->entries, struct_);
2248       push_node (ctx, (GIrNode *)struct_);
2249
2250       state_switch (ctx, STATE_STRUCT);
2251       return TRUE;
2252     }
2253   return FALSE;
2254 }
2255
2256
2257 static gboolean
2258 start_union (GMarkupParseContext *context,
2259              const gchar         *element_name,
2260              const gchar        **attribute_names,
2261              const gchar        **attribute_values,
2262              ParseContext       *ctx,
2263              GError             **error)
2264 {
2265   if (strcmp (element_name, "union") == 0 &&
2266       (ctx->state == STATE_NAMESPACE ||
2267        ctx->state == STATE_UNION ||
2268        ctx->state == STATE_STRUCT ||
2269        ctx->state == STATE_CLASS))
2270     {
2271       const gchar *name;
2272       const gchar *deprecated;
2273       const gchar *typename;
2274       const gchar *typeinit;
2275
2276       name = find_attribute ("name", attribute_names, attribute_values);
2277       deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
2278       typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
2279       typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
2280
2281       if (name == NULL && ctx->node_stack == NULL)
2282         MISSING_ATTRIBUTE (context, error, element_name, "name");
2283       else
2284         {
2285           GIrNodeUnion *union_;
2286
2287           union_ = (GIrNodeUnion *) g_ir_node_new (G_IR_NODE_UNION);
2288
2289           ((GIrNode *)union_)->name = g_strdup (name ? name : "");
2290           union_->gtype_name = g_strdup (typename);
2291           union_->gtype_init = g_strdup (typeinit);
2292           if (deprecated)
2293             union_->deprecated = TRUE;
2294           else
2295             union_->deprecated = FALSE;
2296
2297           if (ctx->node_stack == NULL)
2298             ctx->current_module->entries =
2299               g_list_append (ctx->current_module->entries, union_);
2300           push_node (ctx, (GIrNode *)union_);
2301
2302           state_switch (ctx, STATE_UNION);
2303         }
2304       return TRUE;
2305     }
2306   return FALSE;
2307 }
2308
2309 static gboolean
2310 start_discriminator (GMarkupParseContext *context,
2311                      const gchar         *element_name,
2312                      const gchar        **attribute_names,
2313                      const gchar        **attribute_values,
2314                      ParseContext       *ctx,
2315                      GError             **error)
2316 {
2317   if (strcmp (element_name, "discriminator") == 0 &&
2318       ctx->state == STATE_UNION)
2319     {
2320       const gchar *type;
2321       const gchar *offset;
2322
2323       type = find_attribute ("type", attribute_names, attribute_values);
2324       offset = find_attribute ("offset", attribute_names, attribute_values);
2325       if (type == NULL)
2326         MISSING_ATTRIBUTE (context, error, element_name, "type");
2327       else if (offset == NULL)
2328         MISSING_ATTRIBUTE (context, error, element_name, "offset");
2329         {
2330           ((GIrNodeUnion *)CURRENT_NODE (ctx))->discriminator_type
2331             = parse_type (ctx, type);
2332           ((GIrNodeUnion *)CURRENT_NODE (ctx))->discriminator_offset
2333             = atoi (offset);
2334         }
2335
2336       return TRUE;
2337     }
2338
2339   return FALSE;
2340 }
2341
2342 static gboolean
2343 parse_include (GMarkupParseContext *context,
2344                ParseContext        *ctx,
2345                const char          *name,
2346                const char          *version,
2347                GError             **error)
2348 {
2349   gchar *buffer;
2350   gsize length;
2351   gchar *girpath, *girname;
2352   gboolean success = FALSE;
2353   GList *modules;
2354   GList *l;
2355
2356   for (l = ctx->parser->parsed_modules; l; l = l->next)
2357     {
2358       GIrModule *m = l->data;
2359
2360       if (strcmp (m->name, name) == 0)
2361         {
2362           if (strcmp (m->version, version) == 0)
2363             {
2364               ctx->include_modules = g_list_prepend (ctx->include_modules, m);
2365
2366               return TRUE;
2367             }
2368           else
2369             {
2370               g_set_error (error,
2371                            G_MARKUP_ERROR,
2372                            G_MARKUP_ERROR_INVALID_CONTENT,
2373                            "Module '%s' imported with conflicting versions '%s' and '%s'",
2374                            name, m->version, version);
2375               return FALSE;
2376             }
2377         }
2378     }
2379
2380   girname = g_strdup_printf ("%s-%s.gir", name, version);
2381   girpath = locate_gir (ctx->parser, girname);
2382
2383   if (girpath == NULL)
2384     {
2385       g_set_error (error,
2386                    G_MARKUP_ERROR,
2387                    G_MARKUP_ERROR_INVALID_CONTENT,
2388                    "Could not find GIR file '%s'; check XDG_DATA_DIRS or use --includedir",
2389                    girname);
2390       g_free (girname);
2391       return FALSE;
2392     }
2393   g_free (girname);
2394
2395   g_debug ("Parsing include %s", girpath);
2396
2397   if (!g_file_get_contents (girpath, &buffer, &length, error))
2398     {
2399       g_free (girpath);
2400       return FALSE;
2401     }
2402   g_free (girpath);
2403
2404   modules = g_ir_parser_parse_string (ctx->parser, name, buffer, length, error);
2405   success = error != NULL;
2406
2407   ctx->include_modules = g_list_concat (ctx->include_modules,
2408                                         modules);
2409
2410   g_free (buffer);
2411
2412   return success;
2413 }
2414
2415 extern GLogLevelFlags logged_levels;
2416
2417 static void
2418 start_element_handler (GMarkupParseContext *context,
2419                        const gchar         *element_name,
2420                        const gchar        **attribute_names,
2421                        const gchar        **attribute_values,
2422                        gpointer             user_data,
2423                        GError             **error)
2424 {
2425   ParseContext *ctx = user_data;
2426   gint line_number, char_number;
2427
2428   if (logged_levels & G_LOG_LEVEL_DEBUG)
2429     {
2430       GString *tags = g_string_new ("");
2431       int i;
2432       for (i = 0; attribute_names[i]; i++)
2433         g_string_append_printf (tags, "%s=\"%s\" ",
2434                                 attribute_names[i],
2435                                 attribute_values[i]);
2436
2437       if (i)
2438         {
2439           g_string_insert_c (tags, 0, ' ');
2440           g_string_truncate (tags, tags->len - 1);
2441         }
2442       g_debug ("<%s%s>", element_name, tags->str);
2443       g_string_free (tags, TRUE);
2444     }
2445
2446   switch (element_name[0])
2447     {
2448     case 'a':
2449       if (ctx->state == STATE_NAMESPACE && strcmp (element_name, "alias") == 0)
2450         {
2451           state_switch (ctx, STATE_ALIAS);
2452           goto out;
2453         }
2454       if (start_type (context, element_name,
2455                       attribute_names, attribute_values,
2456                       ctx, error))
2457         goto out;
2458       else if (start_attribute (context, element_name,
2459                                 attribute_names, attribute_values,
2460                                 ctx, error))
2461         goto out;
2462       break;
2463     case 'b':
2464       if (start_enum (context, element_name,
2465                       attribute_names, attribute_values,
2466                       ctx, error))
2467         goto out;
2468       break;
2469     case 'c':
2470       if (start_function (context, element_name,
2471                           attribute_names, attribute_values,
2472                           ctx, error))
2473         goto out;
2474       else if (start_constant (context, element_name,
2475                                attribute_names, attribute_values,
2476                                ctx, error))
2477         goto out;
2478       else if (start_class (context, element_name,
2479                             attribute_names, attribute_values,
2480                             ctx, error))
2481         goto out;
2482       break;
2483
2484     case 'd':
2485       if (start_discriminator (context, element_name,
2486                                attribute_names, attribute_values,
2487                                ctx, error))
2488         goto out;
2489       break;
2490
2491     case 'e':
2492       if (start_enum (context, element_name,
2493                       attribute_names, attribute_values,
2494                       ctx, error))
2495         goto out;
2496       else if (start_errordomain (context, element_name,
2497                       attribute_names, attribute_values,
2498                       ctx, error))
2499         goto out;
2500       break;
2501
2502     case 'f':
2503       if (start_function (context, element_name,
2504                           attribute_names, attribute_values,
2505                           ctx, error))
2506         goto out;
2507       else if (start_field (context, element_name,
2508                             attribute_names, attribute_values,
2509                             ctx, error))
2510         goto out;
2511       break;
2512
2513     case 'g':
2514       if (start_glib_boxed (context, element_name,
2515                             attribute_names, attribute_values,
2516                             ctx, error))
2517         goto out;
2518       else if (start_glib_signal (context, element_name,
2519                              attribute_names, attribute_values,
2520                              ctx, error))
2521         goto out;
2522       break;
2523
2524     case 'i':
2525       if (strcmp (element_name, "include") == 0 &&
2526           ctx->state == STATE_REPOSITORY)
2527         {
2528           const gchar *name;
2529           const gchar *version;
2530
2531           name = find_attribute ("name", attribute_names, attribute_values);
2532           version = find_attribute ("version", attribute_names, attribute_values);
2533
2534           if (name == NULL)
2535             {
2536               MISSING_ATTRIBUTE (context, error, element_name, "name");
2537               break;
2538             }
2539           if (version == NULL)
2540             {
2541               MISSING_ATTRIBUTE (context, error, element_name, "version");
2542               break;
2543             }
2544
2545           if (!parse_include (context, ctx, name, version, error))
2546             break;
2547
2548           ctx->dependencies = g_list_prepend (ctx->dependencies,
2549                                               g_strdup_printf ("%s-%s", name, version));
2550
2551
2552           state_switch (ctx, STATE_INCLUDE);
2553           goto out;
2554         }
2555       if (start_interface (context, element_name,
2556                            attribute_names, attribute_values,
2557                            ctx, error))
2558         goto out;
2559       else if (start_implements (context, element_name,
2560                                  attribute_names, attribute_values,
2561                                  ctx, error))
2562         goto out;
2563       break;
2564
2565     case 'm':
2566       if (start_function (context, element_name,
2567                           attribute_names, attribute_values,
2568                           ctx, error))
2569         goto out;
2570       else if (start_member (context, element_name,
2571                           attribute_names, attribute_values,
2572                           ctx, error))
2573         goto out;
2574       break;
2575
2576     case 'n':
2577       if (strcmp (element_name, "namespace") == 0 && ctx->state == STATE_REPOSITORY)
2578         {
2579           const gchar *name, *version, *shared_library, *cprefix;
2580
2581           if (ctx->current_module != NULL)
2582             {
2583               g_set_error (error,
2584                            G_MARKUP_ERROR,
2585                            G_MARKUP_ERROR_INVALID_CONTENT,
2586                            "Only one <namespace/> element is currently allowed per <repository/>");
2587               goto out;
2588             }
2589
2590           name = find_attribute ("name", attribute_names, attribute_values);
2591           version = find_attribute ("version", attribute_names, attribute_values);
2592           shared_library = find_attribute ("shared-library", attribute_names, attribute_values);
2593           cprefix = find_attribute ("c:prefix", attribute_names, attribute_values);
2594
2595           if (name == NULL)
2596             MISSING_ATTRIBUTE (context, error, element_name, "name");
2597           else if (version == NULL)
2598             MISSING_ATTRIBUTE (context, error, element_name, "version");
2599           else
2600             {
2601               GList *l;
2602
2603               if (strcmp (name, ctx->namespace) != 0)
2604                 g_set_error (error,
2605                              G_MARKUP_ERROR,
2606                              G_MARKUP_ERROR_INVALID_CONTENT,
2607                              "<namespace/> name element '%s' doesn't match file name '%s'",
2608                              name, ctx->namespace);
2609
2610               ctx->current_module = g_ir_module_new (name, version, shared_library, cprefix);
2611
2612               ctx->current_module->aliases = ctx->aliases;
2613               ctx->aliases = NULL;
2614               ctx->current_module->disguised_structures = ctx->disguised_structures;
2615               ctx->disguised_structures = NULL;
2616
2617               for (l = ctx->include_modules; l; l = l->next)
2618                 g_ir_module_add_include_module (ctx->current_module, l->data);
2619
2620               g_list_free (ctx->include_modules);
2621               ctx->include_modules = NULL;
2622
2623               ctx->modules = g_list_append (ctx->modules, ctx->current_module);
2624               ctx->current_module->dependencies = ctx->dependencies;
2625
2626               state_switch (ctx, STATE_NAMESPACE);
2627               goto out;
2628             }
2629         }
2630       break;
2631
2632     case 'p':
2633       if (start_property (context, element_name,
2634                           attribute_names, attribute_values,
2635                           ctx, error))
2636         goto out;
2637       else if (strcmp (element_name, "parameters") == 0 &&
2638                ctx->state == STATE_FUNCTION)
2639         {
2640           state_switch (ctx, STATE_FUNCTION_PARAMETERS);
2641
2642           goto out;
2643         }
2644       else if (start_parameter (context, element_name,
2645                                 attribute_names, attribute_values,
2646                                 ctx, error))
2647         goto out;
2648       else if (strcmp (element_name, "prerequisite") == 0 &&
2649                ctx->state == STATE_INTERFACE)
2650         {
2651           const gchar *name;
2652
2653           name = find_attribute ("name", attribute_names, attribute_values);
2654
2655           state_switch (ctx, STATE_PREREQUISITE);
2656
2657           if (name == NULL)
2658             MISSING_ATTRIBUTE (context, error, element_name, "name");
2659           else
2660             {
2661               GIrNodeInterface *iface;
2662
2663               iface = (GIrNodeInterface *)CURRENT_NODE(ctx);
2664               iface->prerequisites = g_list_append (iface->prerequisites, g_strdup (name));
2665             }
2666           goto out;
2667         }
2668       else if (strcmp (element_name, "package") == 0 &&
2669           ctx->state == STATE_REPOSITORY)
2670         {
2671           state_switch (ctx, STATE_PACKAGE);
2672           goto out;
2673         }
2674       break;
2675
2676     case 'r':
2677       if (strcmp (element_name, "repository") == 0 && ctx->state == STATE_START)
2678         {
2679           const gchar *version;
2680
2681           version = find_attribute ("version", attribute_names, attribute_values);
2682
2683           if (version == NULL)
2684             MISSING_ATTRIBUTE (context, error, element_name, "version");
2685           else if (strcmp (version, "1.0") != 0)
2686             g_set_error (error,
2687                          G_MARKUP_ERROR,
2688                          G_MARKUP_ERROR_INVALID_CONTENT,
2689                          "Unsupported version '%s'",
2690                          version);
2691           else
2692             state_switch (ctx, STATE_REPOSITORY);
2693
2694           goto out;
2695         }
2696       else if (start_return_value (context, element_name,
2697                                    attribute_names, attribute_values,
2698                                    ctx, error))
2699         goto out;
2700       else if (start_struct (context, element_name,
2701                              attribute_names, attribute_values,
2702                              ctx, error))
2703         goto out;
2704       break;
2705
2706     case 'u':
2707       if (start_union (context, element_name,
2708                        attribute_names, attribute_values,
2709                        ctx, error))
2710         goto out;
2711       break;
2712
2713     case 't':
2714       if (start_type (context, element_name,
2715                       attribute_names, attribute_values,
2716                       ctx, error))
2717         goto out;
2718       break;
2719
2720     case 'v':
2721       if (start_vfunc (context, element_name,
2722                        attribute_names, attribute_values,
2723                        ctx, error))
2724         goto out;
2725       if (start_type (context, element_name,
2726                       attribute_names, attribute_values,
2727                       ctx, error))
2728         goto out;
2729       break;
2730     }
2731
2732   if (ctx->state != STATE_UNKNOWN)
2733     {
2734       state_switch (ctx, STATE_UNKNOWN);
2735       ctx->unknown_depth = 1;
2736     }
2737   else
2738     {
2739       ctx->unknown_depth += 1;
2740     }
2741
2742  out:
2743   if (*error)
2744     {
2745       g_markup_parse_context_get_position (context, &line_number, &char_number);
2746
2747       fprintf (stderr, "Error at line %d, character %d: %s\n", line_number, char_number, (*error)->message);
2748       backtrace_stderr ();
2749     }
2750 }
2751
2752 static gboolean
2753 require_one_of_end_elements (GMarkupParseContext *context,
2754                              ParseContext        *ctx,
2755                              const char          *actual_name,
2756                              GError             **error,
2757                              ...)
2758 {
2759   va_list args;
2760   int line_number, char_number;
2761   const char *expected;
2762   gboolean matched = FALSE;
2763
2764   va_start (args, error);
2765
2766   while ((expected = va_arg (args, const char*)) != NULL)
2767     {
2768       if (strcmp (expected, actual_name) == 0)
2769         {
2770           matched = TRUE;
2771           break;
2772         }
2773     }
2774
2775   va_end (args);
2776
2777   if (matched)
2778     return TRUE;
2779
2780   g_markup_parse_context_get_position (context, &line_number, &char_number);
2781   g_set_error (error,
2782                G_MARKUP_ERROR,
2783                G_MARKUP_ERROR_INVALID_CONTENT,
2784                "Unexpected end tag '%s' on line %d char %d; current state=%d",
2785                actual_name,
2786                line_number, char_number, ctx->state);
2787   backtrace_stderr();
2788   return FALSE;
2789 }
2790
2791 static gboolean
2792 state_switch_end_struct_or_union (GMarkupParseContext *context,
2793                                   ParseContext *ctx,
2794                                   const gchar *element_name,
2795                                   GError **error)
2796 {
2797   pop_node (ctx);
2798   if (ctx->node_stack == NULL)
2799     {
2800       state_switch (ctx, STATE_NAMESPACE);
2801     }
2802   else
2803     {
2804       if (CURRENT_NODE (ctx)->type == G_IR_NODE_STRUCT)
2805         state_switch (ctx, STATE_STRUCT);
2806       else if (CURRENT_NODE (ctx)->type == G_IR_NODE_UNION)
2807         state_switch (ctx, STATE_UNION);
2808       else if (CURRENT_NODE (ctx)->type == G_IR_NODE_OBJECT)
2809         state_switch (ctx, STATE_CLASS);
2810       else
2811         {
2812           int line_number, char_number;
2813           g_markup_parse_context_get_position (context, &line_number, &char_number);
2814           g_set_error (error,
2815                        G_MARKUP_ERROR,
2816                        G_MARKUP_ERROR_INVALID_CONTENT,
2817                        "Unexpected end tag '%s' on line %d char %d",
2818                        element_name,
2819                        line_number, char_number);
2820           return FALSE;
2821         }
2822     }
2823   return TRUE;
2824 }
2825
2826 static gboolean
2827 require_end_element (GMarkupParseContext *context,
2828                      ParseContext        *ctx,
2829                      const char          *expected_name,
2830                      const char          *actual_name,
2831                      GError             **error)
2832 {
2833   return require_one_of_end_elements (context, ctx, actual_name, error, expected_name, NULL);
2834 }
2835
2836 static void
2837 end_element_handler (GMarkupParseContext *context,
2838                      const gchar         *element_name,
2839                      gpointer             user_data,
2840                      GError             **error)
2841 {
2842   ParseContext *ctx = user_data;
2843
2844   g_debug ("</%s>", element_name);
2845
2846   switch (ctx->state)
2847     {
2848     case STATE_START:
2849     case STATE_END:
2850       /* no need to GError here, GMarkup already catches this */
2851       break;
2852
2853     case STATE_REPOSITORY:
2854       state_switch (ctx, STATE_END);
2855       break;
2856
2857     case STATE_INCLUDE:
2858       if (require_end_element (context, ctx, "include", element_name, error))
2859         {
2860           state_switch (ctx, STATE_REPOSITORY);
2861         }
2862       break;
2863
2864     case STATE_PACKAGE:
2865       if (require_end_element (context, ctx, "package", element_name, error))
2866         {
2867           state_switch (ctx, STATE_REPOSITORY);
2868         }
2869       break;
2870
2871     case STATE_NAMESPACE:
2872       if (require_end_element (context, ctx, "namespace", element_name, error))
2873         {
2874           ctx->current_module = NULL;
2875           state_switch (ctx, STATE_REPOSITORY);
2876         }
2877       break;
2878
2879     case STATE_ALIAS:
2880       if (require_end_element (context, ctx, "alias", element_name, error))
2881         {
2882           state_switch (ctx, STATE_NAMESPACE);
2883         }
2884       break;
2885
2886     case STATE_FUNCTION_RETURN:
2887       if (strcmp ("type", element_name) == 0)
2888         break;
2889       if (require_end_element (context, ctx, "return-value", element_name, error))
2890         {
2891           state_switch (ctx, STATE_FUNCTION);
2892         }
2893       break;
2894
2895     case STATE_FUNCTION_PARAMETERS:
2896       if (require_end_element (context, ctx, "parameters", element_name, error))
2897         {
2898           state_switch (ctx, STATE_FUNCTION);
2899         }
2900       break;
2901
2902     case STATE_FUNCTION_PARAMETER:
2903       if (strcmp ("type", element_name) == 0)
2904         break;
2905       if (require_end_element (context, ctx, "parameter", element_name, error))
2906         {
2907           state_switch (ctx, STATE_FUNCTION_PARAMETERS);
2908         }
2909       break;
2910
2911     case STATE_FUNCTION:
2912       {
2913         pop_node (ctx);
2914         if (ctx->node_stack == NULL)
2915           {
2916             state_switch (ctx, STATE_NAMESPACE);
2917           }
2918         else
2919           {
2920             g_debug("case STATE_FUNCTION %d", CURRENT_NODE (ctx)->type);
2921             if (ctx->in_embedded_type)
2922               {
2923                 ctx->in_embedded_type = FALSE;
2924                 state_switch (ctx, STATE_STRUCT_FIELD);
2925               }
2926             else if (CURRENT_NODE (ctx)->type == G_IR_NODE_INTERFACE)
2927               state_switch (ctx, STATE_INTERFACE);
2928             else if (CURRENT_NODE (ctx)->type == G_IR_NODE_OBJECT)
2929               state_switch (ctx, STATE_CLASS);
2930             else if (CURRENT_NODE (ctx)->type == G_IR_NODE_BOXED)
2931               state_switch (ctx, STATE_BOXED);
2932             else if (CURRENT_NODE (ctx)->type == G_IR_NODE_STRUCT)
2933               state_switch (ctx, STATE_STRUCT);
2934             else if (CURRENT_NODE (ctx)->type == G_IR_NODE_UNION)
2935               state_switch (ctx, STATE_UNION);
2936             else
2937               {
2938                 int line_number, char_number;
2939                 g_markup_parse_context_get_position (context, &line_number, &char_number);
2940                 g_set_error (error,
2941                              G_MARKUP_ERROR,
2942                              G_MARKUP_ERROR_INVALID_CONTENT,
2943                              "Unexpected end tag '%s' on line %d char %d",
2944                              element_name,
2945                              line_number, char_number);
2946               }
2947           }
2948       }
2949       break;
2950
2951     case STATE_CLASS_FIELD:
2952       if (strcmp ("type", element_name) == 0)
2953         break;
2954       if (require_end_element (context, ctx, "field", element_name, error))
2955         {
2956           state_switch (ctx, STATE_CLASS);
2957         }
2958       break;
2959
2960     case STATE_CLASS_PROPERTY:
2961       if (strcmp ("type", element_name) == 0)
2962         break;
2963       if (require_end_element (context, ctx, "property", element_name, error))
2964         {
2965           state_switch (ctx, STATE_CLASS);
2966         }
2967       break;
2968
2969     case STATE_CLASS:
2970       if (require_end_element (context, ctx, "class", element_name, error))
2971         {
2972           pop_node (ctx);
2973           state_switch (ctx, STATE_NAMESPACE);
2974         }
2975       break;
2976
2977     case STATE_ERRORDOMAIN:
2978       if (require_end_element (context, ctx, "errordomain", element_name, error))
2979         {
2980           pop_node (ctx);
2981           state_switch (ctx, STATE_NAMESPACE);
2982         }
2983       break;
2984
2985     case STATE_INTERFACE_PROPERTY:
2986       if (strcmp ("type", element_name) == 0)
2987         break;
2988       if (require_end_element (context, ctx, "property", element_name, error))
2989         {
2990           state_switch (ctx, STATE_INTERFACE);
2991         }
2992       break;
2993
2994     case STATE_INTERFACE_FIELD:
2995       if (strcmp ("type", element_name) == 0)
2996         break;
2997       if (require_end_element (context, ctx, "field", element_name, error))
2998         {
2999           state_switch (ctx, STATE_INTERFACE);
3000         }
3001       break;
3002
3003     case STATE_INTERFACE:
3004       if (require_end_element (context, ctx, "interface", element_name, error))
3005         {
3006           pop_node (ctx);
3007           state_switch (ctx, STATE_NAMESPACE);
3008         }
3009       break;
3010
3011     case STATE_ENUM:
3012       if (strcmp ("member", element_name) == 0)
3013         break;
3014       else if (require_one_of_end_elements (context, ctx,
3015                                             element_name, error, "enumeration",
3016                                             "bitfield", NULL))
3017         {
3018           pop_node (ctx);
3019           state_switch (ctx, STATE_NAMESPACE);
3020         }
3021       break;
3022
3023     case STATE_BOXED:
3024       if (require_end_element (context, ctx, "glib:boxed", element_name, error))
3025         {
3026           pop_node (ctx);
3027           state_switch (ctx, STATE_NAMESPACE);
3028         }
3029       break;
3030
3031     case STATE_BOXED_FIELD:
3032       if (strcmp ("type", element_name) == 0)
3033         break;
3034       if (require_end_element (context, ctx, "field", element_name, error))
3035         {
3036           state_switch (ctx, STATE_BOXED);
3037         }
3038       break;
3039
3040     case STATE_STRUCT_FIELD:
3041       if (strcmp ("type", element_name) == 0)
3042         break;
3043       if (require_end_element (context, ctx, "field", element_name, error))
3044         {
3045           state_switch (ctx, STATE_STRUCT);
3046         }
3047       break;
3048
3049     case STATE_STRUCT:
3050       if (require_end_element (context, ctx, "record", element_name, error))
3051         {
3052           state_switch_end_struct_or_union (context, ctx, element_name, error);
3053         }
3054       break;
3055
3056     case STATE_UNION_FIELD:
3057       if (strcmp ("type", element_name) == 0)
3058         break;
3059       if (require_end_element (context, ctx, "field", element_name, error))
3060         {
3061           state_switch (ctx, STATE_UNION);
3062         }
3063       break;
3064
3065     case STATE_UNION:
3066       if (require_end_element (context, ctx, "union", element_name, error))
3067         {
3068           state_switch_end_struct_or_union (context, ctx, element_name, error);
3069         }
3070       break;
3071     case STATE_IMPLEMENTS:
3072       if (strcmp ("interface", element_name) == 0)
3073         break;
3074       if (require_end_element (context, ctx, "implements", element_name, error))
3075         state_switch (ctx, STATE_CLASS);
3076       break;
3077     case STATE_PREREQUISITE:
3078       if (require_end_element (context, ctx, "prerequisite", element_name, error))
3079         state_switch (ctx, STATE_INTERFACE);
3080       break;
3081     case STATE_NAMESPACE_CONSTANT:
3082     case STATE_CLASS_CONSTANT:
3083     case STATE_INTERFACE_CONSTANT:
3084       if (strcmp ("type", element_name) == 0)
3085         break;
3086       if (require_end_element (context, ctx, "constant", element_name, error))
3087         {
3088           switch (ctx->state)
3089             {
3090             case STATE_NAMESPACE_CONSTANT:
3091                   pop_node (ctx);
3092               state_switch (ctx, STATE_NAMESPACE);
3093               break;
3094             case STATE_CLASS_CONSTANT:
3095               state_switch (ctx, STATE_CLASS);
3096               break;
3097             case STATE_INTERFACE_CONSTANT:
3098               state_switch (ctx, STATE_INTERFACE);
3099               break;
3100             default:
3101               g_assert_not_reached ();
3102               break;
3103             }
3104         }
3105       break;
3106     case STATE_TYPE:
3107       if ((strcmp ("type", element_name) == 0) || (strcmp ("array", element_name) == 0) ||
3108           (strcmp ("varargs", element_name) == 0))
3109         {
3110           end_type (ctx);
3111           break;
3112         }
3113     case STATE_ATTRIBUTE:
3114       if (strcmp ("attribute", element_name) == 0)
3115         {
3116           state_switch (ctx, ctx->prev_state);
3117         }
3118       break;
3119
3120     case STATE_UNKNOWN:
3121       ctx->unknown_depth -= 1;
3122       if (ctx->unknown_depth == 0)
3123         state_switch (ctx, ctx->prev_state);
3124       break;
3125     default:
3126       g_error ("Unhandled state %d in end_element_handler\n", ctx->state);
3127     }
3128 }
3129
3130 static void
3131 text_handler (GMarkupParseContext *context,
3132               const gchar         *text,
3133               gsize                text_len,
3134               gpointer             user_data,
3135               GError             **error)
3136 {
3137   /* FIXME warn about non-whitespace text */
3138 }
3139
3140 static void
3141 cleanup (GMarkupParseContext *context,
3142          GError              *error,
3143          gpointer             user_data)
3144 {
3145   ParseContext *ctx = user_data;
3146   GList *m;
3147
3148   for (m = ctx->modules; m; m = m->next)
3149     g_ir_module_free (m->data);
3150   g_list_free (ctx->modules);
3151   ctx->modules = NULL;
3152
3153   ctx->current_module = NULL;
3154 }
3155
3156 static GList *
3157 post_filter_toplevel_varargs_functions (GList *list,
3158                                         GList **varargs_callbacks_out)
3159 {
3160   GList *iter;
3161   GList *varargs_callbacks = *varargs_callbacks_out;
3162
3163   iter = list;
3164   while (iter)
3165     {
3166       GList *link = iter;
3167       GIrNode *node = iter->data;
3168
3169       iter = iter->next;
3170
3171       if (node->type == G_IR_NODE_FUNCTION)
3172         {
3173           if (((GIrNodeFunction*)node)->is_varargs)
3174             {
3175               list = g_list_delete_link (list, link);
3176             }
3177         }
3178       if (node->type == G_IR_NODE_CALLBACK)
3179         {
3180           if (((GIrNodeFunction*)node)->is_varargs)
3181             {
3182               varargs_callbacks = g_list_append (varargs_callbacks,
3183                                                  node);
3184               list = g_list_delete_link (list, link);
3185             }
3186         }
3187     }
3188
3189   *varargs_callbacks_out = varargs_callbacks;
3190
3191   return list;
3192 }
3193
3194 static GList *
3195 post_filter_varargs_functions (GList *list, GList ** varargs_callbacks_out)
3196 {
3197   GList *iter;
3198   GList *varargs_callbacks;
3199
3200   list = post_filter_toplevel_varargs_functions (list, varargs_callbacks_out);
3201
3202   varargs_callbacks = *varargs_callbacks_out;
3203
3204   iter = list;
3205   while (iter)
3206     {
3207       GList *link = iter;
3208       GIrNode *node = iter->data;
3209
3210       iter = iter->next;
3211
3212       if (node->type == G_IR_NODE_FUNCTION)
3213         {
3214           GList *param;
3215           gboolean function_done = FALSE;
3216
3217           for (param = ((GIrNodeFunction *)node)->parameters;
3218                param;
3219                param = param->next)
3220             {
3221               GIrNodeParam *node = (GIrNodeParam *)param->data;
3222
3223               if (function_done)
3224                 break;
3225
3226               if (node->type->is_interface)
3227                 {
3228                   GList *callback;
3229                   for (callback = varargs_callbacks;
3230                        callback;
3231                        callback = callback->next)
3232                     {
3233                       if (!strcmp (node->type->interface,
3234                                    ((GIrNode *)varargs_callbacks->data)->name))
3235                         {
3236                           list = g_list_delete_link (list, link);
3237                           function_done = TRUE;
3238                           break;
3239                         }
3240                     }
3241                 }
3242             }
3243         }
3244     }
3245
3246   *varargs_callbacks_out = varargs_callbacks;
3247
3248   return list;
3249 }
3250
3251 static void
3252 post_filter (GIrModule *module)
3253 {
3254   GList *iter;
3255   GList *varargs_callbacks = NULL;
3256
3257   module->entries = post_filter_varargs_functions (module->entries,
3258                                                    &varargs_callbacks);
3259   iter = module->entries;
3260   while (iter)
3261     {
3262       GIrNode *node = iter->data;
3263
3264       iter = iter->next;
3265
3266       if (node->type == G_IR_NODE_OBJECT ||
3267           node->type == G_IR_NODE_INTERFACE)
3268         {
3269           GIrNodeInterface *iface = (GIrNodeInterface*)node;
3270           iface->members = post_filter_varargs_functions (iface->members,
3271                                                           &varargs_callbacks);
3272         }
3273       else if (node->type == G_IR_NODE_BOXED)
3274         {
3275           GIrNodeBoxed *boxed = (GIrNodeBoxed*)node;
3276           boxed->members = post_filter_varargs_functions (boxed->members,
3277                                                           &varargs_callbacks);
3278         }
3279       else if (node->type == G_IR_NODE_STRUCT)
3280         {
3281           GIrNodeStruct *iface = (GIrNodeStruct*)node;
3282           iface->members = post_filter_varargs_functions (iface->members,
3283                                                           &varargs_callbacks);
3284         }
3285       else if (node->type == G_IR_NODE_UNION)
3286         {
3287           GIrNodeUnion *iface = (GIrNodeUnion*)node;
3288           iface->members = post_filter_varargs_functions (iface->members,
3289                                                           &varargs_callbacks);
3290         }
3291     }
3292   g_list_free (varargs_callbacks);
3293 }
3294
3295 /**
3296  * g_ir_parser_parse_string:
3297  * @parser: a #GIrParser
3298  * @namespace: the namespace of the string
3299  * @buffer: the data containing the XML
3300  * @length: length of the data
3301  * @error: return location for a #GError, or %NULL
3302  *
3303  * Parse a string that holds a complete GIR XML file, and return a list of a
3304  * a #GirModule for each &lt;namespace/&gt; element within the file.
3305  *
3306  * Returns: a newly allocated list of #GIrModule. The modules themselves
3307  *  are owned by the #GIrParser and will be freed along with the parser.
3308  */
3309 GList *
3310 g_ir_parser_parse_string (GIrParser           *parser,
3311                           const gchar         *namespace,
3312                           const gchar         *buffer,
3313                           gssize               length,
3314                           GError             **error)
3315 {
3316   ParseContext ctx = { 0 };
3317   GMarkupParseContext *context;
3318
3319   ctx.parser = parser;
3320   ctx.state = STATE_START;
3321   ctx.namespace = namespace;
3322   ctx.include_modules = NULL;
3323   ctx.aliases = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
3324   ctx.disguised_structures = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
3325   ctx.type_depth = 0;
3326   ctx.dependencies = NULL;
3327   ctx.current_module = NULL;
3328
3329   context = g_markup_parse_context_new (&firstpass_parser, 0, &ctx, NULL);
3330
3331   if (!g_markup_parse_context_parse (context, buffer, length, error))
3332     goto out;
3333
3334   if (!g_markup_parse_context_end_parse (context, error))
3335     goto out;
3336
3337   g_markup_parse_context_free (context);
3338
3339   context = g_markup_parse_context_new (&markup_parser, 0, &ctx, NULL);
3340   if (!g_markup_parse_context_parse (context, buffer, length, error))
3341     goto out;
3342
3343   if (!g_markup_parse_context_end_parse (context, error))
3344     goto out;
3345
3346   parser->parsed_modules = g_list_concat (g_list_copy (ctx.modules),
3347                                           parser->parsed_modules);
3348
3349  out:
3350
3351   if (ctx.modules == NULL)
3352     {
3353       /* An error occurred before we created a module, so we haven't
3354        * transferred ownership of these hash tables to the module.
3355        */
3356       if (ctx.aliases != NULL)
3357         g_hash_table_destroy (ctx.aliases);
3358       if (ctx.disguised_structures != NULL)
3359         g_hash_table_destroy (ctx.disguised_structures);
3360       g_list_free (ctx.include_modules);
3361     }
3362
3363   g_markup_parse_context_free (context);
3364
3365   return ctx.modules;
3366 }
3367
3368 /**
3369  * g_ir_parser_parse_file:
3370  * @parser: a #GIrParser
3371  * @filename: filename to parse
3372  * @error: return location for a #GError, or %NULL
3373  *
3374  * Parse GIR XML file, and return a list of a a #GirModule for each
3375  * &lt;namespace/&gt; element within the file.
3376  *
3377  * Returns: a newly allocated list of #GIrModule. The modules themselves
3378  *  are owned by the #GIrParser and will be freed along with the parser.
3379  */
3380 GList *
3381 g_ir_parser_parse_file (GIrParser   *parser,
3382                         const gchar *filename,
3383                         GError     **error)
3384 {
3385   gchar *buffer;
3386   gsize length;
3387   GList *modules;
3388   GList *iter;
3389   const char *slash;
3390   char *dash;
3391   char *namespace;
3392
3393   if (!g_str_has_suffix (filename, ".gir"))
3394     {
3395       g_set_error (error,
3396                    G_MARKUP_ERROR,
3397                    G_MARKUP_ERROR_INVALID_CONTENT,
3398                    "Expected filename to end with '.gir'");
3399       return NULL;
3400     }
3401
3402   g_debug ("[parsing] filename %s", filename);
3403
3404   slash = g_strrstr (filename, "/");
3405   if (!slash)
3406     namespace = g_strdup (filename);
3407   else
3408     namespace = g_strdup (slash+1);
3409   namespace[strlen(namespace)-4] = '\0';
3410
3411   /* Remove version */
3412   dash = strstr (namespace, "-");
3413   if (dash != NULL)
3414     *dash = '\0';
3415
3416   if (!g_file_get_contents (filename, &buffer, &length, error))
3417     return NULL;
3418
3419   modules = g_ir_parser_parse_string (parser, namespace, buffer, length, error);
3420
3421   for (iter = modules; iter; iter = iter->next)
3422     {
3423       post_filter ((GIrModule*)iter->data);
3424     }
3425
3426   g_free (namespace);
3427
3428   g_free (buffer);
3429
3430   return modules;
3431 }
3432
3433