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