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