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