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