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