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