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