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