Release 0.41.92
[vala-gnome.git] / gobject-introspection / gidlparser.c
blob6a76b2ca7b112a027cf6a6a55e96e48e42698c16
1 /* GObject introspection: A parser for the XML IDL format
3 * Copyright (C) 2005 Matthias Clasen
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.
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.
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.
21 #include <stdlib.h>
22 #include <string.h>
23 #include <stdlib.h>
25 #include <glib.h>
26 #include "gidlmodule.h"
27 #include "gidlnode.h"
28 #include "gmetadata.h"
30 typedef enum
32 STATE_START,
33 STATE_END,
34 STATE_ROOT,
35 STATE_NAMESPACE,
36 STATE_FUNCTION,
37 STATE_PARAMETERS,
38 STATE_OBJECT,
39 STATE_INTERFACE,
40 STATE_IMPLEMENTS,
41 STATE_REQUIRES,
42 STATE_ENUM,
43 STATE_BOXED,
44 STATE_STRUCT,
45 STATE_SIGNAL,
46 STATE_ERRORDOMAIN,
47 STATE_UNION
48 } ParseState;
50 typedef struct _ParseContext ParseContext;
51 struct _ParseContext
53 ParseState state;
54 ParseState prev_state;
56 GList *modules;
58 GIdlModule *current_module;
59 GIdlNode *current_node;
62 #define MISSING_ATTRIBUTE(error,element,attribute) \
63 g_set_error (error, \
64 G_MARKUP_ERROR, \
65 G_MARKUP_ERROR_INVALID_CONTENT, \
66 "The attribute '%s' on the element '%s' must be specified", \
67 attribute, element)
69 static const gchar *
70 find_attribute (const gchar *name,
71 const gchar **attribute_names,
72 const gchar **attribute_values)
74 gint i;
76 for (i = 0; attribute_names[i] != NULL; i++)
77 if (strcmp (attribute_names[i], name) == 0)
78 return attribute_values[i];
80 return 0;
83 static GIdlNodeType *
84 parse_type_internal (gchar *str, gchar **rest)
86 gint i;
88 static struct {
89 const gchar *str;
90 gint tag;
91 gboolean pointer;
92 } basic[] = {
93 { "void", TYPE_TAG_VOID, 0 },
94 { "gpointer", TYPE_TAG_VOID, 1 },
95 { "bool", TYPE_TAG_BOOLEAN, 0 },
96 { "gboolean", TYPE_TAG_BOOLEAN, 0 },
97 #if 0
98 { "char", TYPE_TAG_INT8, 0 },
99 { "gchar", TYPE_TAG_INT8, 0 },
100 { "guchar", TYPE_TAG_UINT8, 0 },
101 #endif
102 { "int8_t", TYPE_TAG_INT8, 0 },
103 { "int8", TYPE_TAG_INT8, 0 },
104 { "gint8", TYPE_TAG_INT8, 0 },
105 { "uint8_t", TYPE_TAG_UINT8, 0 },
106 { "uint8", TYPE_TAG_UINT8, 0 },
107 { "guint8", TYPE_TAG_UINT8, 0 },
108 { "int16_t", TYPE_TAG_INT16, 0 },
109 { "int16", TYPE_TAG_INT16, 0 },
110 { "gint16", TYPE_TAG_INT16, 0 },
111 { "uint16_t", TYPE_TAG_UINT16, 0 },
112 { "uint16", TYPE_TAG_UINT16, 0 },
113 { "guint16", TYPE_TAG_UINT16, 0 },
114 { "int32_t", TYPE_TAG_INT32, 0 },
115 { "int32", TYPE_TAG_INT32, 0 },
116 { "gint32", TYPE_TAG_INT32, 0 },
117 { "uint32_t", TYPE_TAG_UINT32, 0 },
118 { "uint32", TYPE_TAG_UINT32, 0 },
119 { "guint32", TYPE_TAG_UINT32, 0 },
120 { "int64_t", TYPE_TAG_INT64, 0 },
121 { "int64", TYPE_TAG_INT64, 0 },
122 { "gint64", TYPE_TAG_INT64, 0 },
123 { "uint64_t", TYPE_TAG_UINT64, 0 },
124 { "uint64", TYPE_TAG_UINT64, 0 },
125 { "guint64", TYPE_TAG_UINT64, 0 },
126 { "int", TYPE_TAG_INT, 0 },
127 { "gint", TYPE_TAG_INT, 0 },
128 { "uint", TYPE_TAG_UINT, 0 },
129 { "guint", TYPE_TAG_UINT, 0 },
130 { "long", TYPE_TAG_LONG, 0 },
131 { "glong", TYPE_TAG_LONG, 0 },
132 { "ulong", TYPE_TAG_ULONG, 0 },
133 { "gulong", TYPE_TAG_ULONG, 0 },
134 { "ssize_t", TYPE_TAG_SSIZE, 0 },
135 { "gssize", TYPE_TAG_SSIZE, 0 },
136 { "size_t", TYPE_TAG_SIZE, 0 },
137 { "gsize", TYPE_TAG_SIZE, 0 },
138 { "float", TYPE_TAG_FLOAT, 0 },
139 { "gfloat", TYPE_TAG_FLOAT, 0 },
140 { "double", TYPE_TAG_DOUBLE, 0 },
141 { "gdouble", TYPE_TAG_DOUBLE, 0 },
142 { "utf8", TYPE_TAG_UTF8, 1 },
143 { "gchar*", TYPE_TAG_UTF8, 1 },
144 { "filename", TYPE_TAG_FILENAME,1 }
147 gint n_basic = G_N_ELEMENTS (basic);
148 gchar *start, *end;
150 GIdlNodeType *type;
152 type = (GIdlNodeType *)g_idl_node_new (G_IDL_NODE_TYPE);
154 str = g_strstrip (str);
156 type->unparsed = g_strdup (str);
158 *rest = str;
159 for (i = 0; i < n_basic; i++)
161 if (g_str_has_prefix (*rest, basic[i].str))
163 type->is_basic = TRUE;
164 type->tag = basic[i].tag;
165 type->is_pointer = basic[i].pointer;
167 *rest += strlen(basic[i].str);
168 *rest = g_strchug (*rest);
169 if (**rest == '*' && !type->is_pointer)
171 type->is_pointer = TRUE;
172 (*rest)++;
175 break;
179 if (i < n_basic)
180 /* found a basic type */;
181 else if (g_str_has_prefix (*rest, "GList") ||
182 g_str_has_prefix (*rest, "GSList"))
184 if (g_str_has_prefix (*rest, "GList"))
186 type->tag = TYPE_TAG_LIST;
187 type->is_glist = TRUE;
188 type->is_pointer = TRUE;
189 *rest += strlen ("GList");
191 else
193 type->tag = TYPE_TAG_SLIST;
194 type->is_gslist = TRUE;
195 type->is_pointer = TRUE;
196 *rest += strlen ("GSList");
199 *rest = g_strchug (*rest);
201 if (**rest == '<')
203 (*rest)++;
205 type->parameter_type1 = parse_type_internal (*rest, rest);
206 if (type->parameter_type1 == NULL)
207 goto error;
209 *rest = g_strchug (*rest);
211 if ((*rest)[0] != '>')
212 goto error;
213 (*rest)++;
216 else if (g_str_has_prefix (*rest, "GHashTable"))
218 type->tag = TYPE_TAG_HASH;
219 type->is_ghashtable = TRUE;
220 type->is_pointer = TRUE;
221 *rest += strlen ("GHashTable");
223 *rest = g_strchug (*rest);
225 if (**rest == '<')
227 (*rest)++;
229 type->parameter_type1 = parse_type_internal (*rest, rest);
230 if (type->parameter_type1 == NULL)
231 goto error;
233 *rest = g_strchug (*rest);
235 if ((*rest)[0] != ',')
236 goto error;
237 (*rest)++;
239 type->parameter_type2 = parse_type_internal (*rest, rest);
240 if (type->parameter_type2 == NULL)
241 goto error;
243 if ((*rest)[0] != '>')
244 goto error;
245 (*rest)++;
248 else if (g_str_has_prefix (*rest, "GError"))
250 type->tag = TYPE_TAG_ERROR;
251 type->is_error = TRUE;
252 type->is_pointer = TRUE;
253 *rest += strlen ("GError");
255 *rest = g_strchug (*rest);
257 if (**rest == '<')
259 (*rest)++;
261 end = strchr (*rest, '>');
262 str = g_strndup (*rest, end - *rest);
263 type->errors = g_strsplit (str, ",", 0);
264 g_free (str);
266 *rest = end + 1;
269 else
271 type->tag = TYPE_TAG_INTERFACE;
272 type->is_interface = TRUE;
273 start = *rest;
275 /* must be an interface type */
276 while (g_ascii_isalnum (**rest) ||
277 **rest == '.' ||
278 **rest == '-' ||
279 **rest == '_' ||
280 **rest == ':')
281 (*rest)++;
283 type->interface = g_strndup (start, *rest - start);
285 *rest = g_strchug (*rest);
286 if (**rest == '*')
288 type->is_pointer = TRUE;
289 (*rest)++;
293 *rest = g_strchug (*rest);
294 if (g_str_has_prefix (*rest, "["))
296 GIdlNodeType *array;
298 array = (GIdlNodeType *)g_idl_node_new (G_IDL_NODE_TYPE);
300 array->tag = TYPE_TAG_ARRAY;
301 array->is_pointer = TRUE;
302 array->is_array = TRUE;
304 array->parameter_type1 = type;
306 array->zero_terminated = FALSE;
307 array->has_length = FALSE;
308 array->length = 0;
310 if (!g_str_has_prefix (*rest, "[]"))
312 gchar *end, *str, **opts;
314 end = strchr (*rest, ']');
315 str = g_strndup (*rest + 1, (end - *rest) - 1);
316 opts = g_strsplit (str, ",", 0);
318 *rest = end + 1;
320 for (i = 0; opts[i]; i++)
322 gchar **vals;
324 vals = g_strsplit (opts[i], "=", 0);
326 if (strcmp (vals[0], "zero-terminated") == 0)
327 array->zero_terminated = (strcmp (vals[1], "1") == 0);
328 else if (strcmp (vals[0], "length") == 0)
330 array->has_length = TRUE;
331 array->length = atoi (vals[1]);
334 g_strfreev (vals);
337 g_free (str);
338 g_strfreev (opts);
341 type = array;
344 return type;
346 error:
347 g_idl_node_free ((GIdlNode *)type);
349 return NULL;
352 static GIdlNodeType *
353 parse_type (const gchar *type)
355 gchar *str;
356 gchar *rest;
357 GIdlNodeType *node;
359 str = g_strdup (type);
360 node = parse_type_internal (str, &rest);
361 g_free (str);
363 return node;
366 static gboolean
367 start_boxed (GMarkupParseContext *context,
368 const gchar *element_name,
369 const gchar **attribute_names,
370 const gchar **attribute_values,
371 ParseContext *ctx,
372 GError **error)
374 if (strcmp (element_name, "boxed") == 0 &&
375 ctx->state == STATE_NAMESPACE)
377 const gchar *name;
378 const gchar *typename;
379 const gchar *typeinit;
380 const gchar *deprecated;
382 name = find_attribute ("name", attribute_names, attribute_values);
383 typename = find_attribute ("type-name", attribute_names, attribute_values);
384 typeinit = find_attribute ("get-type", attribute_names, attribute_values);
385 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
387 if (name == NULL)
388 MISSING_ATTRIBUTE (error, element_name, "name");
389 else if (typename == NULL)
390 MISSING_ATTRIBUTE (error, element_name, "type-name");
391 else if (typeinit == NULL)
392 MISSING_ATTRIBUTE (error, element_name, "get-type");
393 else
395 GIdlNodeBoxed *boxed;
397 boxed = (GIdlNodeBoxed *) g_idl_node_new (G_IDL_NODE_BOXED);
399 ((GIdlNode *)boxed)->name = g_strdup (name);
400 boxed->gtype_name = g_strdup (typename);
401 boxed->gtype_init = g_strdup (typeinit);
402 if (deprecated && strcmp (deprecated, "1") == 0)
403 boxed->deprecated = TRUE;
404 else
405 boxed->deprecated = FALSE;
407 ctx->current_node = (GIdlNode *)boxed;
408 ctx->current_module->entries =
409 g_list_append (ctx->current_module->entries, boxed);
411 ctx->state = STATE_BOXED;
414 return TRUE;
417 return FALSE;
420 static gboolean
421 start_function (GMarkupParseContext *context,
422 const gchar *element_name,
423 const gchar **attribute_names,
424 const gchar **attribute_values,
425 ParseContext *ctx,
426 GError **error)
428 if ((ctx->state == STATE_NAMESPACE &&
429 (strcmp (element_name, "function") == 0 ||
430 strcmp (element_name, "callback") == 0)) ||
431 ((ctx->state == STATE_OBJECT ||
432 ctx->state == STATE_INTERFACE ||
433 ctx->state == STATE_BOXED ||
434 ctx->state == STATE_STRUCT ||
435 ctx->state == STATE_UNION) &&
436 strcmp (element_name, "method") == 0) ||
437 ((ctx->state == STATE_OBJECT ||
438 ctx->state == STATE_BOXED) &&
439 strcmp (element_name, "constructor") == 0))
441 const gchar *name;
442 const gchar *symbol;
443 const gchar *deprecated;
444 const gchar *type;
446 name = find_attribute ("name", attribute_names, attribute_values);
447 symbol = find_attribute ("symbol", attribute_names, attribute_values);
448 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
449 type = find_attribute ("type", attribute_names, attribute_values);
451 if (name == NULL)
452 MISSING_ATTRIBUTE (error, element_name, "name");
453 else if (strcmp (element_name, "callback") != 0 && symbol == NULL)
454 MISSING_ATTRIBUTE (error, element_name, "symbol");
455 else
457 GIdlNodeFunction *function;
459 function = (GIdlNodeFunction *) g_idl_node_new (G_IDL_NODE_FUNCTION);
461 ((GIdlNode *)function)->name = g_strdup (name);
462 function->symbol = g_strdup (symbol);
463 function->parameters = NULL;
464 if (deprecated && strcmp (deprecated, "1") == 0)
465 function->deprecated = TRUE;
466 else
467 function->deprecated = FALSE;
469 if (strcmp (element_name, "method") == 0 ||
470 strcmp (element_name, "constructor") == 0)
472 function->is_method = TRUE;
474 if (type && strcmp (type, "setter") == 0)
475 function->is_setter = TRUE;
476 else if (type && strcmp (type, "getter") == 0)
477 function->is_getter = TRUE;
479 if (strcmp (element_name, "constructor") == 0)
480 function->is_constructor = TRUE;
481 else
482 function->is_constructor = FALSE;
484 else
486 function->is_method = FALSE;
487 function->is_setter = FALSE;
488 function->is_getter = FALSE;
489 function->is_constructor = FALSE;
490 if (strcmp (element_name, "callback") == 0)
491 ((GIdlNode *)function)->type = G_IDL_NODE_CALLBACK;
494 if (ctx->current_node == NULL)
496 ctx->current_module->entries =
497 g_list_append (ctx->current_module->entries, function);
499 else
500 switch (ctx->current_node->type)
502 case G_IDL_NODE_INTERFACE:
503 case G_IDL_NODE_OBJECT:
505 GIdlNodeInterface *iface;
507 iface = (GIdlNodeInterface *)ctx->current_node;
508 iface->members = g_list_append (iface->members, function);
510 break;
511 case G_IDL_NODE_BOXED:
513 GIdlNodeBoxed *boxed;
515 boxed = (GIdlNodeBoxed *)ctx->current_node;
516 boxed->members = g_list_append (boxed->members, function);
518 break;
519 case G_IDL_NODE_STRUCT:
521 GIdlNodeStruct *struct_;
523 struct_ = (GIdlNodeStruct *)ctx->current_node;
524 struct_->members = g_list_append (struct_->members, function); }
525 break;
526 case G_IDL_NODE_UNION:
528 GIdlNodeUnion *union_;
530 union_ = (GIdlNodeUnion *)ctx->current_node;
531 union_->members = g_list_append (union_->members, function);
533 break;
534 default:
535 g_assert_not_reached ();
538 ctx->current_node = (GIdlNode *)function;
539 ctx->state = STATE_FUNCTION;
541 return TRUE;
545 return FALSE;
548 static gboolean
549 start_parameter (GMarkupParseContext *context,
550 const gchar *element_name,
551 const gchar **attribute_names,
552 const gchar **attribute_values,
553 ParseContext *ctx,
554 GError **error)
556 if (strcmp (element_name, "parameter") == 0 &&
557 ctx->state == STATE_PARAMETERS)
559 const gchar *type;
560 const gchar *name;
561 const gchar *direction;
562 const gchar *retval;
563 const gchar *dipper;
564 const gchar *optional;
565 const gchar *nullok;
566 const gchar *transfer;
568 type = find_attribute ("type", attribute_names, attribute_values);
569 name = find_attribute ("name", attribute_names, attribute_values);
570 direction = find_attribute ("direction", attribute_names, attribute_values);
571 retval = find_attribute ("retval", attribute_names, attribute_values);
572 dipper = find_attribute ("dipper", attribute_names, attribute_values);
573 optional = find_attribute ("optional", attribute_names, attribute_values);
574 nullok = find_attribute ("null-ok", attribute_names, attribute_values);
575 transfer = find_attribute ("transfer", attribute_names, attribute_values);
577 if (type == NULL)
578 MISSING_ATTRIBUTE (error, element_name, "type");
579 else if (name == NULL)
580 MISSING_ATTRIBUTE (error, element_name, "name");
581 else
583 GIdlNodeParam *param;
585 param = (GIdlNodeParam *)g_idl_node_new (G_IDL_NODE_PARAM);
587 if (direction && strcmp (direction, "out") == 0)
589 param->in = FALSE;
590 param->out = TRUE;
592 else if (direction && strcmp (direction, "inout") == 0)
594 param->in = TRUE;
595 param->out = TRUE;
597 else
599 param->in = TRUE;
600 param->out = FALSE;
603 if (retval && strcmp (retval, "1") == 0)
604 param->retval = TRUE;
605 else
606 param->retval = FALSE;
608 if (dipper && strcmp (dipper, "1") == 0)
609 param->dipper = TRUE;
610 else
611 param->dipper = FALSE;
613 if (optional && strcmp (optional, "1") == 0)
614 param->optional = TRUE;
615 else
616 param->optional = FALSE;
618 if (nullok && strcmp (nullok, "1") == 0)
619 param->null_ok = TRUE;
620 else
621 param->null_ok = FALSE;
623 if (transfer && strcmp (transfer, "none") == 0)
625 param->transfer = FALSE;
626 param->shallow_transfer = FALSE;
628 else if (transfer && strcmp (transfer, "shallow") == 0)
630 param->transfer = FALSE;
631 param->shallow_transfer = TRUE;
633 else
635 param->transfer = TRUE;
636 param->shallow_transfer = FALSE;
639 ((GIdlNode *)param)->name = g_strdup (name);
640 param->type = parse_type (type);
642 switch (ctx->current_node->type)
644 case G_IDL_NODE_FUNCTION:
645 case G_IDL_NODE_CALLBACK:
647 GIdlNodeFunction *func;
649 func = (GIdlNodeFunction *)ctx->current_node;
650 func->parameters = g_list_append (func->parameters, param);
652 break;
653 case G_IDL_NODE_SIGNAL:
655 GIdlNodeSignal *signal;
657 signal = (GIdlNodeSignal *)ctx->current_node;
658 signal->parameters = g_list_append (signal->parameters, param);
660 break;
661 case G_IDL_NODE_VFUNC:
663 GIdlNodeVFunc *vfunc;
665 vfunc = (GIdlNodeVFunc *)ctx->current_node;
666 vfunc->parameters = g_list_append (vfunc->parameters, param);
668 break;
669 default:
670 g_assert_not_reached ();
674 return TRUE;
677 return FALSE;
680 static gboolean
681 start_field (GMarkupParseContext *context,
682 const gchar *element_name,
683 const gchar **attribute_names,
684 const gchar **attribute_values,
685 ParseContext *ctx,
686 GError **error)
688 if (strcmp (element_name, "field") == 0 &&
689 (ctx->state == STATE_OBJECT ||
690 ctx->state == STATE_BOXED ||
691 ctx->state == STATE_STRUCT ||
692 ctx->state == STATE_UNION))
694 const gchar *name;
695 const gchar *type;
696 const gchar *readable;
697 const gchar *writable;
698 const gchar *bits;
699 const gchar *branch;
700 const gchar *offset;
702 name = find_attribute ("name", attribute_names, attribute_values);
703 type = find_attribute ("type", attribute_names, attribute_values);
704 readable = find_attribute ("readable", attribute_names, attribute_values);
705 writable = find_attribute ("writable", attribute_names, attribute_values);
706 bits = find_attribute ("bits", attribute_names, attribute_values);
707 branch = find_attribute ("branch", attribute_names, attribute_values);
708 offset = find_attribute ("offset", attribute_names, attribute_values);
710 if (name == NULL)
711 MISSING_ATTRIBUTE (error, element_name, "name");
712 else if (type == NULL)
713 MISSING_ATTRIBUTE (error, element_name, "type");
714 else
716 GIdlNodeField *field;
718 field = (GIdlNodeField *)g_idl_node_new (G_IDL_NODE_FIELD);
719 ((GIdlNode *)field)->name = g_strdup (name);
720 if (readable && strcmp (readable, "1") == 0)
721 field->readable = TRUE;
722 else
723 field->readable = FALSE;
725 if (writable && strcmp (writable, "1") == 0)
726 field->writable = TRUE;
727 else
728 field->writable = FALSE;
730 if (bits)
731 field->bits = atoi (bits);
732 else
733 field->bits = 0;
735 if (offset)
736 field->offset = atoi (offset);
737 else
738 field->offset = 0;
740 field->type = parse_type (type);
742 switch (ctx->current_node->type)
744 case G_IDL_NODE_OBJECT:
746 GIdlNodeInterface *iface;
748 iface = (GIdlNodeInterface *)ctx->current_node;
749 iface->members = g_list_append (iface->members, field);
751 break;
752 case G_IDL_NODE_BOXED:
754 GIdlNodeBoxed *boxed;
756 boxed = (GIdlNodeBoxed *)ctx->current_node;
757 boxed->members = g_list_append (boxed->members, field);
759 break;
760 case G_IDL_NODE_STRUCT:
762 GIdlNodeStruct *struct_;
764 struct_ = (GIdlNodeStruct *)ctx->current_node;
765 struct_->members = g_list_append (struct_->members, field);
767 break;
768 case G_IDL_NODE_UNION:
770 GIdlNodeUnion *union_;
772 union_ = (GIdlNodeUnion *)ctx->current_node;
773 union_->members = g_list_append (union_->members, field);
774 if (branch)
776 GIdlNodeConstant *constant;
778 constant = (GIdlNodeConstant *) g_idl_node_new (G_IDL_NODE_CONSTANT);
779 ((GIdlNode *)constant)->name = g_strdup (name);
780 constant->value = g_strdup (branch);
781 constant->type = union_->discriminator_type;
782 constant->deprecated = FALSE;
784 union_->discriminators = g_list_append (union_->discriminators, constant);
787 break;
788 default:
789 g_assert_not_reached ();
792 return TRUE;
795 return FALSE;
798 static gboolean
799 start_enum (GMarkupParseContext *context,
800 const gchar *element_name,
801 const gchar **attribute_names,
802 const gchar **attribute_values,
803 ParseContext *ctx,
804 GError **error)
806 if ((strcmp (element_name, "enum") == 0 && ctx->state == STATE_NAMESPACE) ||
807 (strcmp (element_name, "flags") == 0 && ctx->state == STATE_NAMESPACE))
809 const gchar *name;
810 const gchar *typename;
811 const gchar *typeinit;
812 const gchar *deprecated;
814 name = find_attribute ("name", attribute_names, attribute_values);
815 typename = find_attribute ("type-name", attribute_names, attribute_values);
816 typeinit = find_attribute ("get-type", attribute_names, attribute_values);
817 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
819 if (name == NULL)
820 MISSING_ATTRIBUTE (error, element_name, "name");
821 else
823 GIdlNodeEnum *enum_;
825 if (strcmp (element_name, "enum") == 0)
826 enum_ = (GIdlNodeEnum *) g_idl_node_new (G_IDL_NODE_ENUM);
827 else
828 enum_ = (GIdlNodeEnum *) g_idl_node_new (G_IDL_NODE_FLAGS);
829 ((GIdlNode *)enum_)->name = g_strdup (name);
830 enum_->gtype_name = g_strdup (typename);
831 enum_->gtype_init = g_strdup (typeinit);
832 if (deprecated && strcmp (deprecated, "1") == 0)
833 enum_->deprecated = TRUE;
834 else
835 enum_->deprecated = FALSE;
837 ctx->current_node = (GIdlNode *) enum_;
838 ctx->current_module->entries =
839 g_list_append (ctx->current_module->entries, enum_);
841 ctx->state = STATE_ENUM;
844 return TRUE;
846 return FALSE;
849 static gboolean
850 start_property (GMarkupParseContext *context,
851 const gchar *element_name,
852 const gchar **attribute_names,
853 const gchar **attribute_values,
854 ParseContext *ctx,
855 GError **error)
857 if (strcmp (element_name, "property") == 0 &&
858 (ctx->state == STATE_OBJECT ||
859 ctx->state == STATE_INTERFACE))
861 const gchar *name;
862 const gchar *type;
863 const gchar *readable;
864 const gchar *writable;
865 const gchar *construct;
866 const gchar *construct_only;
868 name = find_attribute ("name", attribute_names, attribute_values);
869 type = find_attribute ("type", attribute_names, attribute_values);
870 readable = find_attribute ("readable", attribute_names, attribute_values);
871 writable = find_attribute ("writable", attribute_names, attribute_values);
872 construct = find_attribute ("construct", attribute_names, attribute_values);
873 construct_only = find_attribute ("construct-only", attribute_names, attribute_values);
875 if (name == NULL)
876 MISSING_ATTRIBUTE (error, element_name, "name");
877 else if (type == NULL)
878 MISSING_ATTRIBUTE (error, element_name, "type");
879 else
881 GIdlNodeProperty *property;
882 GIdlNodeInterface *iface;
884 property = (GIdlNodeProperty *) g_idl_node_new (G_IDL_NODE_PROPERTY);
886 ((GIdlNode *)property)->name = g_strdup (name);
888 if (readable && strcmp (readable, "1") == 0)
889 property->readable = TRUE;
890 else
891 property->readable = FALSE;
892 if (writable && strcmp (writable, "1") == 0)
893 property->writable = TRUE;
894 else
895 property->writable = FALSE;
896 if (construct && strcmp (construct, "1") == 0)
897 property->construct = TRUE;
898 else
899 property->construct = FALSE;
900 if (construct_only && strcmp (construct_only, "1") == 0)
901 property->construct_only = TRUE;
902 else
903 property->construct_only = FALSE;
905 property->type = parse_type (type);
907 iface = (GIdlNodeInterface *)ctx->current_node;
908 iface->members = g_list_append (iface->members, property);
911 return TRUE;
913 return FALSE;
916 static gint
917 parse_value (const gchar *str)
919 gchar *shift_op;
921 /* FIXME just a quick hack */
922 shift_op = strstr (str, "<<");
924 if (shift_op)
926 gint base, shift;
928 base = strtol (str, NULL, 10);
929 shift = strtol (shift_op + 3, NULL, 10);
931 return base << shift;
933 else
934 return strtol (str, NULL, 10);
936 return 0;
939 static gboolean
940 start_member (GMarkupParseContext *context,
941 const gchar *element_name,
942 const gchar **attribute_names,
943 const gchar **attribute_values,
944 ParseContext *ctx,
945 GError **error)
947 if (strcmp (element_name, "member") == 0 &&
948 ctx->state == STATE_ENUM)
950 const gchar *name;
951 const gchar *value;
952 const gchar *deprecated;
954 name = find_attribute ("name", attribute_names, attribute_values);
955 value = find_attribute ("value", attribute_names, attribute_values);
956 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
958 if (name == NULL)
959 MISSING_ATTRIBUTE (error, element_name, "name");
960 else
962 GIdlNodeEnum *enum_;
963 GIdlNodeValue *value_;
965 value_ = (GIdlNodeValue *) g_idl_node_new (G_IDL_NODE_VALUE);
967 ((GIdlNode *)value_)->name = g_strdup (name);
969 value_->value = parse_value (value);
971 if (deprecated && strcmp (deprecated, "1") == 0)
972 value_->deprecated = TRUE;
973 else
974 value_->deprecated = FALSE;
976 enum_ = (GIdlNodeEnum *)ctx->current_node;
977 enum_->values = g_list_append (enum_->values, value_);
980 return TRUE;
982 return FALSE;
985 static gboolean
986 start_constant (GMarkupParseContext *context,
987 const gchar *element_name,
988 const gchar **attribute_names,
989 const gchar **attribute_values,
990 ParseContext *ctx,
991 GError **error)
993 if (strcmp (element_name, "constant") == 0 &&
994 (ctx->state == STATE_NAMESPACE ||
995 ctx->state == STATE_OBJECT ||
996 ctx->state == STATE_INTERFACE))
998 const gchar *name;
999 const gchar *type;
1000 const gchar *value;
1001 const gchar *deprecated;
1003 name = find_attribute ("name", attribute_names, attribute_values);
1004 type = find_attribute ("type", attribute_names, attribute_values);
1005 value = find_attribute ("value", attribute_names, attribute_values);
1006 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1008 if (name == NULL)
1009 MISSING_ATTRIBUTE (error, element_name, "name");
1010 else if (type == NULL)
1011 MISSING_ATTRIBUTE (error, element_name, "type");
1012 else if (value == NULL)
1013 MISSING_ATTRIBUTE (error, element_name, "value");
1014 else
1016 GIdlNodeConstant *constant;
1018 constant = (GIdlNodeConstant *) g_idl_node_new (G_IDL_NODE_CONSTANT);
1020 ((GIdlNode *)constant)->name = g_strdup (name);
1021 constant->value = g_strdup (value);
1023 constant->type = parse_type (type);
1025 if (deprecated && strcmp (deprecated, "1") == 0)
1026 constant->deprecated = TRUE;
1027 else
1028 constant->deprecated = FALSE;
1030 if (ctx->state == STATE_NAMESPACE)
1032 ctx->current_node = (GIdlNode *) constant;
1033 ctx->current_module->entries =
1034 g_list_append (ctx->current_module->entries, constant);
1036 else
1038 GIdlNodeInterface *iface;
1040 iface = (GIdlNodeInterface *)ctx->current_node;
1041 iface->members = g_list_append (iface->members, constant);
1045 return TRUE;
1047 return FALSE;
1050 static gboolean
1051 start_errordomain (GMarkupParseContext *context,
1052 const gchar *element_name,
1053 const gchar **attribute_names,
1054 const gchar **attribute_values,
1055 ParseContext *ctx,
1056 GError **error)
1058 if (strcmp (element_name, "errordomain") == 0 &&
1059 ctx->state == STATE_NAMESPACE)
1061 const gchar *name;
1062 const gchar *getquark;
1063 const gchar *codes;
1064 const gchar *deprecated;
1066 name = find_attribute ("name", attribute_names, attribute_values);
1067 getquark = find_attribute ("get-quark", attribute_names, attribute_values);
1068 codes = find_attribute ("codes", attribute_names, attribute_values);
1069 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1071 if (name == NULL)
1072 MISSING_ATTRIBUTE (error, element_name, "name");
1073 else if (getquark == NULL)
1074 MISSING_ATTRIBUTE (error, element_name, "getquark");
1075 else if (codes == NULL)
1076 MISSING_ATTRIBUTE (error, element_name, "codes");
1077 else
1079 GIdlNodeErrorDomain *domain;
1081 domain = (GIdlNodeErrorDomain *) g_idl_node_new (G_IDL_NODE_ERROR_DOMAIN);
1083 ((GIdlNode *)domain)->name = g_strdup (name);
1084 domain->getquark = g_strdup (getquark);
1085 domain->codes = g_strdup (codes);
1087 if (deprecated && strcmp (deprecated, "1") == 0)
1088 domain->deprecated = TRUE;
1089 else
1090 domain->deprecated = FALSE;
1092 ctx->current_node = (GIdlNode *) domain;
1093 ctx->current_module->entries =
1094 g_list_append (ctx->current_module->entries, domain);
1096 ctx->state = STATE_ERRORDOMAIN;
1099 return TRUE;
1101 return FALSE;
1104 static gboolean
1105 start_interface (GMarkupParseContext *context,
1106 const gchar *element_name,
1107 const gchar **attribute_names,
1108 const gchar **attribute_values,
1109 ParseContext *ctx,
1110 GError **error)
1112 if (strcmp (element_name, "interface") == 0 &&
1113 ctx->state == STATE_NAMESPACE)
1115 const gchar *name;
1116 const gchar *typename;
1117 const gchar *typeinit;
1118 const gchar *deprecated;
1120 name = find_attribute ("name", attribute_names, attribute_values);
1121 typename = find_attribute ("type-name", attribute_names, attribute_values);
1122 typeinit = find_attribute ("get-type", attribute_names, attribute_values);
1123 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1125 if (name == NULL)
1126 MISSING_ATTRIBUTE (error, element_name, "name");
1127 else if (typename == NULL)
1128 MISSING_ATTRIBUTE (error, element_name, "type-name");
1129 else if (typeinit == NULL)
1130 MISSING_ATTRIBUTE (error, element_name, "get-type");
1131 else
1133 GIdlNodeInterface *iface;
1135 iface = (GIdlNodeInterface *) g_idl_node_new (G_IDL_NODE_INTERFACE);
1136 ((GIdlNode *)iface)->name = g_strdup (name);
1137 iface->gtype_name = g_strdup (typename);
1138 iface->gtype_init = g_strdup (typeinit);
1139 if (deprecated && strcmp (deprecated, "1") == 0)
1140 iface->deprecated = TRUE;
1141 else
1142 iface->deprecated = FALSE;
1144 ctx->current_node = (GIdlNode *) iface;
1145 ctx->current_module->entries =
1146 g_list_append (ctx->current_module->entries, iface);
1148 ctx->state = STATE_INTERFACE;
1152 return TRUE;
1154 return FALSE;
1157 static gboolean
1158 start_object (GMarkupParseContext *context,
1159 const gchar *element_name,
1160 const gchar **attribute_names,
1161 const gchar **attribute_values,
1162 ParseContext *ctx,
1163 GError **error)
1165 if (strcmp (element_name, "object") == 0 &&
1166 ctx->state == STATE_NAMESPACE)
1168 const gchar *name;
1169 const gchar *parent;
1170 const gchar *typename;
1171 const gchar *typeinit;
1172 const gchar *deprecated;
1174 name = find_attribute ("name", attribute_names, attribute_values);
1175 parent = find_attribute ("parent", attribute_names, attribute_values);
1176 typename = find_attribute ("type-name", attribute_names, attribute_values);
1177 typeinit = find_attribute ("get-type", attribute_names, attribute_values);
1178 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1180 if (name == NULL)
1181 MISSING_ATTRIBUTE (error, element_name, "name");
1182 else if (typename == NULL)
1183 MISSING_ATTRIBUTE (error, element_name, "type-name");
1184 else if (typeinit == NULL)
1185 MISSING_ATTRIBUTE (error, element_name, "get-type");
1186 else
1188 GIdlNodeInterface *iface;
1190 iface = (GIdlNodeInterface *) g_idl_node_new (G_IDL_NODE_OBJECT);
1191 ((GIdlNode *)iface)->name = g_strdup (name);
1192 iface->gtype_name = g_strdup (typename);
1193 iface->gtype_init = g_strdup (typeinit);
1194 iface->parent = g_strdup (parent);
1195 if (deprecated && strcmp (deprecated, "1") == 0)
1196 iface->deprecated = TRUE;
1197 else
1198 iface->deprecated = FALSE;
1200 ctx->current_node = (GIdlNode *) iface;
1201 ctx->current_module->entries =
1202 g_list_append (ctx->current_module->entries, iface);
1204 ctx->state = STATE_OBJECT;
1207 return TRUE;
1209 return FALSE;
1212 static gboolean
1213 start_return_type (GMarkupParseContext *context,
1214 const gchar *element_name,
1215 const gchar **attribute_names,
1216 const gchar **attribute_values,
1217 ParseContext *ctx,
1218 GError **error)
1220 if (strcmp (element_name, "return-type") == 0 &&
1221 ctx->state == STATE_FUNCTION)
1223 const gchar *type;
1224 const gchar *nullok;
1225 const gchar *transfer;
1227 type = find_attribute ("type", attribute_names, attribute_values);
1228 nullok = find_attribute ("null-ok", attribute_names, attribute_values);
1229 transfer = find_attribute ("transfer", attribute_names, attribute_values);
1230 if (type == NULL)
1231 MISSING_ATTRIBUTE (error, element_name, "type");
1232 else
1234 GIdlNodeParam *param;
1236 param = (GIdlNodeParam *)g_idl_node_new (G_IDL_NODE_PARAM);
1237 param->in = FALSE;
1238 param->out = FALSE;
1239 param->retval = TRUE;
1240 if (nullok && strcmp (nullok, "1") == 0)
1241 param->null_ok = TRUE;
1242 else
1243 param->null_ok = FALSE;
1244 if (transfer && strcmp (transfer, "none") == 0)
1246 param->transfer = FALSE;
1247 param->shallow_transfer = FALSE;
1249 else if (transfer && strcmp (transfer, "shallow") == 0)
1251 param->transfer = FALSE;
1252 param->shallow_transfer = TRUE;
1254 else
1256 param->transfer = TRUE;
1257 param->shallow_transfer = FALSE;
1260 param->type = parse_type (type);
1262 switch (ctx->current_node->type)
1264 case G_IDL_NODE_FUNCTION:
1265 case G_IDL_NODE_CALLBACK:
1267 GIdlNodeFunction *func = (GIdlNodeFunction *)ctx->current_node;
1268 func->result = param;
1270 break;
1271 case G_IDL_NODE_SIGNAL:
1273 GIdlNodeSignal *signal = (GIdlNodeSignal *)ctx->current_node;
1274 signal->result = param;
1276 break;
1277 case G_IDL_NODE_VFUNC:
1279 GIdlNodeVFunc *vfunc = (GIdlNodeVFunc *)ctx->current_node;
1280 vfunc->result = param;
1282 break;
1283 default:
1284 g_assert_not_reached ();
1288 return TRUE;
1291 return FALSE;
1294 static gboolean
1295 start_signal (GMarkupParseContext *context,
1296 const gchar *element_name,
1297 const gchar **attribute_names,
1298 const gchar **attribute_values,
1299 ParseContext *ctx,
1300 GError **error)
1302 if (strcmp (element_name, "signal") == 0 &&
1303 (ctx->state == STATE_OBJECT ||
1304 ctx->state == STATE_INTERFACE))
1306 const gchar *name;
1307 const gchar *when;
1308 const gchar *no_recurse;
1309 const gchar *detailed;
1310 const gchar *action;
1311 const gchar *no_hooks;
1312 const gchar *has_class_closure;
1314 name = find_attribute ("name", attribute_names, attribute_values);
1315 when = find_attribute ("when", attribute_names, attribute_values);
1316 no_recurse = find_attribute ("no-recurse", attribute_names, attribute_values);
1317 detailed = find_attribute ("detailed", attribute_names, attribute_values);
1318 action = find_attribute ("action", attribute_names, attribute_values);
1319 no_hooks = find_attribute ("no-hooks", attribute_names, attribute_values);
1320 has_class_closure = find_attribute ("has-class-closure", attribute_names, attribute_values);
1322 if (name == NULL)
1323 MISSING_ATTRIBUTE (error, element_name, "name");
1324 else if (when == NULL)
1325 MISSING_ATTRIBUTE (error, element_name, "when");
1326 else
1328 GIdlNodeInterface *iface;
1329 GIdlNodeSignal *signal;
1331 signal = (GIdlNodeSignal *)g_idl_node_new (G_IDL_NODE_SIGNAL);
1333 ((GIdlNode *)signal)->name = g_strdup (name);
1335 signal->run_first = FALSE;
1336 signal->run_last = FALSE;
1337 signal->run_cleanup = FALSE;
1338 if (strcmp (when, "FIRST") == 0)
1339 signal->run_first = TRUE;
1340 else if (strcmp (when, "LAST") == 0)
1341 signal->run_last = TRUE;
1342 else
1343 signal->run_cleanup = TRUE;
1345 if (no_recurse && strcmp (no_recurse, "1") == 0)
1346 signal->no_recurse = TRUE;
1347 else
1348 signal->no_recurse = FALSE;
1349 if (detailed && strcmp (detailed, "1") == 0)
1350 signal->detailed = TRUE;
1351 else
1352 signal->detailed = FALSE;
1353 if (action && strcmp (action, "1") == 0)
1354 signal->action = TRUE;
1355 else
1356 signal->action = FALSE;
1357 if (no_hooks && strcmp (no_hooks, "1") == 0)
1358 signal->no_hooks = TRUE;
1359 else
1360 signal->no_hooks = FALSE;
1361 if (has_class_closure && strcmp (has_class_closure, "1") == 0)
1362 signal->has_class_closure = TRUE;
1363 else
1364 signal->has_class_closure = FALSE;
1366 iface = (GIdlNodeInterface *)ctx->current_node;
1367 iface->members = g_list_append (iface->members, signal);
1369 ctx->current_node = (GIdlNode *)signal;
1370 ctx->state = STATE_FUNCTION;
1373 return TRUE;
1375 return FALSE;
1378 static gboolean
1379 start_vfunc (GMarkupParseContext *context,
1380 const gchar *element_name,
1381 const gchar **attribute_names,
1382 const gchar **attribute_values,
1383 ParseContext *ctx,
1384 GError **error)
1386 if (strcmp (element_name, "vfunc") == 0 &&
1387 (ctx->state == STATE_OBJECT ||
1388 ctx->state == STATE_INTERFACE))
1390 const gchar *name;
1391 const gchar *must_chain_up;
1392 const gchar *override;
1393 const gchar *is_class_closure;
1394 const gchar *offset;
1396 name = find_attribute ("name", attribute_names, attribute_values);
1397 must_chain_up = find_attribute ("must-chain-up", attribute_names, attribute_values);
1398 override = find_attribute ("override", attribute_names, attribute_values);
1399 is_class_closure = find_attribute ("is-class-closure", attribute_names, attribute_values);
1400 offset = find_attribute ("offset", attribute_names, attribute_values);
1402 if (name == NULL)
1403 MISSING_ATTRIBUTE (error, element_name, "name");
1404 else
1406 GIdlNodeInterface *iface;
1407 GIdlNodeVFunc *vfunc;
1409 vfunc = (GIdlNodeVFunc *)g_idl_node_new (G_IDL_NODE_VFUNC);
1411 ((GIdlNode *)vfunc)->name = g_strdup (name);
1413 if (must_chain_up && strcmp (must_chain_up, "1") == 0)
1414 vfunc->must_chain_up = TRUE;
1415 else
1416 vfunc->must_chain_up = FALSE;
1418 if (override && strcmp (override, "always") == 0)
1420 vfunc->must_be_implemented = TRUE;
1421 vfunc->must_not_be_implemented = FALSE;
1423 else if (override && strcmp (override, "never") == 0)
1425 vfunc->must_be_implemented = FALSE;
1426 vfunc->must_not_be_implemented = TRUE;
1428 else
1430 vfunc->must_be_implemented = FALSE;
1431 vfunc->must_not_be_implemented = FALSE;
1434 if (is_class_closure && strcmp (is_class_closure, "1") == 0)
1435 vfunc->is_class_closure = TRUE;
1436 else
1437 vfunc->is_class_closure = FALSE;
1439 if (offset)
1440 vfunc->offset = atoi (offset);
1441 else
1442 vfunc->offset = 0;
1444 iface = (GIdlNodeInterface *)ctx->current_node;
1445 iface->members = g_list_append (iface->members, vfunc);
1447 ctx->current_node = (GIdlNode *)vfunc;
1448 ctx->state = STATE_FUNCTION;
1451 return TRUE;
1453 return FALSE;
1457 static gboolean
1458 start_struct (GMarkupParseContext *context,
1459 const gchar *element_name,
1460 const gchar **attribute_names,
1461 const gchar **attribute_values,
1462 ParseContext *ctx,
1463 GError **error)
1465 if (strcmp (element_name, "struct") == 0 &&
1466 ctx->state == STATE_NAMESPACE)
1468 const gchar *name;
1469 const gchar *deprecated;
1471 name = find_attribute ("name", attribute_names, attribute_values);
1472 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1474 if (name == NULL)
1475 MISSING_ATTRIBUTE (error, element_name, "name");
1476 else
1478 GIdlNodeStruct *struct_;
1480 struct_ = (GIdlNodeStruct *) g_idl_node_new (G_IDL_NODE_STRUCT);
1482 ((GIdlNode *)struct_)->name = g_strdup (name);
1483 if (deprecated && strcmp (deprecated, "1") == 0)
1484 struct_->deprecated = TRUE;
1485 else
1486 struct_->deprecated = FALSE;
1488 ctx->current_node = (GIdlNode *)struct_;
1489 ctx->current_module->entries =
1490 g_list_append (ctx->current_module->entries, struct_);
1492 ctx->state = STATE_STRUCT;
1494 return TRUE;
1496 return FALSE;
1500 static gboolean
1501 start_union (GMarkupParseContext *context,
1502 const gchar *element_name,
1503 const gchar **attribute_names,
1504 const gchar **attribute_values,
1505 ParseContext *ctx,
1506 GError **error)
1508 if (strcmp (element_name, "union") == 0 &&
1509 ctx->state == STATE_NAMESPACE)
1511 const gchar *name;
1512 const gchar *deprecated;
1513 const gchar *typename;
1514 const gchar *typeinit;
1516 name = find_attribute ("name", attribute_names, attribute_values);
1517 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1518 typename = find_attribute ("type-name", attribute_names, attribute_values);
1519 typeinit = find_attribute ("get-type", attribute_names, attribute_values);
1521 if (name == NULL)
1522 MISSING_ATTRIBUTE (error, element_name, "name");
1523 else
1525 GIdlNodeUnion *union_;
1527 union_ = (GIdlNodeUnion *) g_idl_node_new (G_IDL_NODE_UNION);
1529 ((GIdlNode *)union_)->name = g_strdup (name);
1530 union_->gtype_name = g_strdup (typename);
1531 union_->gtype_init = g_strdup (typeinit);
1532 if (deprecated && strcmp (deprecated, "1") == 0)
1533 union_->deprecated = TRUE;
1534 else
1535 union_->deprecated = FALSE;
1537 ctx->current_node = (GIdlNode *)union_;
1538 ctx->current_module->entries =
1539 g_list_append (ctx->current_module->entries, union_);
1541 ctx->state = STATE_UNION;
1543 return TRUE;
1545 return FALSE;
1548 static gboolean
1549 start_discriminator (GMarkupParseContext *context,
1550 const gchar *element_name,
1551 const gchar **attribute_names,
1552 const gchar **attribute_values,
1553 ParseContext *ctx,
1554 GError **error)
1556 if (strcmp (element_name, "discriminator") == 0 &&
1557 ctx->state == STATE_UNION)
1559 const gchar *type;
1560 const gchar *offset;
1562 type = find_attribute ("type", attribute_names, attribute_values);
1563 offset = find_attribute ("offset", attribute_names, attribute_values);
1564 if (type == NULL)
1565 MISSING_ATTRIBUTE (error, element_name, "type");
1566 else if (offset == NULL)
1567 MISSING_ATTRIBUTE (error, element_name, "offset");
1569 ((GIdlNodeUnion *)ctx->current_node)->discriminator_type
1570 = parse_type (type);
1571 ((GIdlNodeUnion *)ctx->current_node)->discriminator_offset
1572 = atoi (offset);
1575 return TRUE;
1578 return FALSE;
1581 static void
1582 start_element_handler (GMarkupParseContext *context,
1583 const gchar *element_name,
1584 const gchar **attribute_names,
1585 const gchar **attribute_values,
1586 gpointer user_data,
1587 GError **error)
1589 ParseContext *ctx = user_data;
1590 gint line_number, char_number;
1592 switch (element_name[0])
1594 case 'a':
1595 if (strcmp (element_name, "api") == 0 && ctx->state == STATE_START)
1597 const gchar *version;
1599 version = find_attribute ("version", attribute_names, attribute_values);
1601 if (version == NULL)
1602 MISSING_ATTRIBUTE (error, element_name, "version");
1603 else if (strcmp (version, "1.0") != 0)
1604 g_set_error (error,
1605 G_MARKUP_ERROR,
1606 G_MARKUP_ERROR_INVALID_CONTENT,
1607 "Unsupported version '%s'",
1608 version);
1609 else
1610 ctx->state = STATE_ROOT;
1612 goto out;
1614 break;
1616 case 'b':
1617 if (start_boxed (context, element_name,
1618 attribute_names, attribute_values,
1619 ctx, error))
1620 goto out;
1621 break;
1623 case 'c':
1624 if (start_function (context, element_name,
1625 attribute_names, attribute_values,
1626 ctx, error))
1627 goto out;
1628 else if (start_constant (context, element_name,
1629 attribute_names, attribute_values,
1630 ctx, error))
1631 goto out;
1632 break;
1634 case 'd':
1635 if (start_discriminator (context, element_name,
1636 attribute_names, attribute_values,
1637 ctx, error))
1638 goto out;
1639 break;
1641 case 'e':
1642 if (start_enum (context, element_name,
1643 attribute_names, attribute_values,
1644 ctx, error))
1645 goto out;
1646 else if (start_errordomain (context, element_name,
1647 attribute_names, attribute_values,
1648 ctx, error))
1649 goto out;
1650 break;
1652 case 'f':
1653 if (start_function (context, element_name,
1654 attribute_names, attribute_values,
1655 ctx, error))
1656 goto out;
1657 else if (start_field (context, element_name,
1658 attribute_names, attribute_values,
1659 ctx, error))
1660 goto out;
1661 else if (start_enum (context, element_name,
1662 attribute_names, attribute_values,
1663 ctx, error))
1664 goto out;
1666 break;
1668 case 'i':
1669 if (start_interface (context, element_name,
1670 attribute_names, attribute_values,
1671 ctx, error))
1672 goto out;
1673 if (strcmp (element_name, "implements") == 0 &&
1674 ctx->state == STATE_OBJECT)
1676 ctx->state = STATE_IMPLEMENTS;
1678 goto out;
1680 else if (strcmp (element_name, "interface") == 0 &&
1681 ctx->state == STATE_IMPLEMENTS)
1683 const gchar *name;
1685 name = find_attribute ("name", attribute_names, attribute_values);
1687 if (name == NULL)
1688 MISSING_ATTRIBUTE (error, element_name, "name");
1689 else
1691 GIdlNodeInterface *iface;
1693 iface = (GIdlNodeInterface *)ctx->current_node;
1694 iface ->interfaces = g_list_append (iface->interfaces, g_strdup (name));
1697 goto out;
1699 else if (strcmp (element_name, "interface") == 0 &&
1700 ctx->state == STATE_REQUIRES)
1702 const gchar *name;
1704 name = find_attribute ("name", attribute_names, attribute_values);
1706 if (name == NULL)
1707 MISSING_ATTRIBUTE (error, element_name, "name");
1708 else
1710 GIdlNodeInterface *iface;
1712 iface = (GIdlNodeInterface *)ctx->current_node;
1713 iface ->prerequisites = g_list_append (iface->prerequisites, g_strdup (name));
1716 goto out;
1718 break;
1720 case 'm':
1721 if (start_function (context, element_name,
1722 attribute_names, attribute_values,
1723 ctx, error))
1724 goto out;
1725 else if (start_member (context, element_name,
1726 attribute_names, attribute_values,
1727 ctx, error))
1728 goto out;
1729 break;
1731 case 'n':
1732 if (strcmp (element_name, "namespace") == 0 && ctx->state == STATE_ROOT)
1734 const gchar *name, *shared_library;
1736 name = find_attribute ("name", attribute_names, attribute_values);
1737 shared_library = find_attribute ("shared-library", attribute_names, attribute_values);
1739 if (name == NULL)
1740 MISSING_ATTRIBUTE (error, element_name, "name");
1741 else
1743 ctx->current_module = g_idl_module_new (name, shared_library);
1744 ctx->modules = g_list_append (ctx->modules, ctx->current_module);
1746 ctx->state = STATE_NAMESPACE;
1749 goto out;
1751 break;
1753 case 'o':
1754 if (start_object (context, element_name,
1755 attribute_names, attribute_values,
1756 ctx, error))
1757 goto out;
1758 else if (strcmp (element_name, "object") == 0 &&
1759 ctx->state == STATE_REQUIRES)
1761 const gchar *name;
1763 name = find_attribute ("name", attribute_names, attribute_values);
1765 if (name == NULL)
1766 MISSING_ATTRIBUTE (error, element_name, "name");
1767 else
1769 GIdlNodeInterface *iface;
1771 iface = (GIdlNodeInterface *)ctx->current_node;
1772 iface ->prerequisites = g_list_append (iface->prerequisites, g_strdup (name));
1775 goto out;
1777 break;
1779 case 'p':
1780 if (start_property (context, element_name,
1781 attribute_names, attribute_values,
1782 ctx, error))
1783 goto out;
1784 else if (strcmp (element_name, "parameters") == 0 &&
1785 ctx->state == STATE_FUNCTION)
1787 ctx->state = STATE_PARAMETERS;
1789 goto out;
1791 else if (start_parameter (context, element_name,
1792 attribute_names, attribute_values,
1793 ctx, error))
1794 goto out;
1796 break;
1798 case 'r':
1799 if (start_return_type (context, element_name,
1800 attribute_names, attribute_values,
1801 ctx, error))
1802 goto out;
1803 else if (strcmp (element_name, "requires") == 0 &&
1804 ctx->state == STATE_INTERFACE)
1806 ctx->state = STATE_REQUIRES;
1808 goto out;
1811 break;
1813 case 's':
1814 if (start_signal (context, element_name,
1815 attribute_names, attribute_values,
1816 ctx, error))
1817 goto out;
1818 else if (start_struct (context, element_name,
1819 attribute_names, attribute_values,
1820 ctx, error))
1821 goto out;
1823 break;
1825 case 'u':
1826 if (start_union (context, element_name,
1827 attribute_names, attribute_values,
1828 ctx, error))
1829 goto out;
1830 break;
1832 case 'v':
1833 if (start_vfunc (context, element_name,
1834 attribute_names, attribute_values,
1835 ctx, error))
1836 goto out;
1837 break;
1840 g_markup_parse_context_get_position (context, &line_number, &char_number);
1842 g_set_error (error,
1843 G_MARKUP_ERROR,
1844 G_MARKUP_ERROR_UNKNOWN_ELEMENT,
1845 "Unexpected start tag '%s' on line %d char %d",
1846 element_name,
1847 line_number, char_number);
1849 out: ;
1853 static void
1854 end_element_handler (GMarkupParseContext *context,
1855 const gchar *element_name,
1856 gpointer user_data,
1857 GError **error)
1859 ParseContext *ctx = user_data;
1861 switch (ctx->state)
1863 case STATE_START:
1864 case STATE_END:
1865 /* no need to GError here, GMarkup already catches this */
1866 break;
1868 case STATE_ROOT:
1869 ctx->state = STATE_END;
1870 break;
1872 case STATE_NAMESPACE:
1873 if (strcmp (element_name, "namespace") == 0)
1875 ctx->current_module = NULL;
1876 ctx->state = STATE_ROOT;
1878 break;
1880 case STATE_FUNCTION:
1881 if (strcmp (element_name, "return-type") == 0)
1882 /* do nothing */ ;
1884 else if (ctx->current_node == g_list_last (ctx->current_module->entries)->data)
1886 ctx->current_node = NULL;
1887 ctx->state = STATE_NAMESPACE;
1889 else
1891 ctx->current_node = g_list_last (ctx->current_module->entries)->data;
1892 if (ctx->current_node->type == G_IDL_NODE_INTERFACE)
1893 ctx->state = STATE_INTERFACE;
1894 else if (ctx->current_node->type == G_IDL_NODE_OBJECT)
1895 ctx->state = STATE_OBJECT;
1896 else if (ctx->current_node->type == G_IDL_NODE_BOXED)
1897 ctx->state = STATE_BOXED;
1898 else if (ctx->current_node->type == G_IDL_NODE_STRUCT)
1899 ctx->state = STATE_STRUCT;
1900 else if (ctx->current_node->type == G_IDL_NODE_UNION)
1901 ctx->state = STATE_UNION;
1903 break;
1905 case STATE_OBJECT:
1906 if (strcmp (element_name, "object") == 0)
1908 ctx->current_node = NULL;
1909 ctx->state = STATE_NAMESPACE;
1911 break;
1913 case STATE_ERRORDOMAIN:
1914 if (strcmp (element_name, "errordomain") == 0)
1916 ctx->current_node = NULL;
1917 ctx->state = STATE_NAMESPACE;
1919 break;
1921 case STATE_INTERFACE:
1922 if (strcmp (element_name, "interface") == 0)
1924 ctx->current_node = NULL;
1925 ctx->state = STATE_NAMESPACE;
1927 break;
1929 case STATE_ENUM:
1930 if (strcmp (element_name, "enum") == 0 ||
1931 strcmp (element_name, "flags") == 0)
1933 ctx->current_node = NULL;
1934 ctx->state = STATE_NAMESPACE;
1936 break;
1938 case STATE_BOXED:
1939 if (strcmp (element_name, "boxed") == 0)
1941 ctx->current_node = NULL;
1942 ctx->state = STATE_NAMESPACE;
1944 break;
1946 case STATE_STRUCT:
1947 if (strcmp (element_name, "struct") == 0)
1949 ctx->current_node = NULL;
1950 ctx->state = STATE_NAMESPACE;
1952 break;
1953 case STATE_UNION:
1954 if (strcmp (element_name, "union") == 0)
1956 ctx->current_node = NULL;
1957 ctx->state = STATE_NAMESPACE;
1959 break;
1961 case STATE_IMPLEMENTS:
1962 if (strcmp (element_name, "implements") == 0)
1963 ctx->state = STATE_OBJECT;
1964 break;
1965 case STATE_REQUIRES:
1966 if (strcmp (element_name, "requires") == 0)
1967 ctx->state = STATE_INTERFACE;
1968 break;
1969 case STATE_PARAMETERS:
1970 if (strcmp (element_name, "parameters") == 0)
1971 ctx->state = STATE_FUNCTION;
1972 break;
1973 default:
1974 g_error ("Unhandled state %d in end_element_handler\n", ctx->state);
1978 static void
1979 text_handler (GMarkupParseContext *context,
1980 const gchar *text,
1981 gsize text_len,
1982 gpointer user_data,
1983 GError **error)
1985 /* FIXME warn about non-whitespace text */
1988 static void
1989 cleanup (GMarkupParseContext *context,
1990 GError *error,
1991 gpointer user_data)
1993 ParseContext *ctx = user_data;
1994 GList *m;
1996 for (m = ctx->modules; m; m = m->next)
1997 g_idl_module_free (m->data);
1998 g_list_free (ctx->modules);
1999 ctx->modules = NULL;
2001 ctx->current_module = NULL;
2004 static GMarkupParser parser =
2006 start_element_handler,
2007 end_element_handler,
2008 text_handler,
2009 NULL,
2010 cleanup
2013 GList *
2014 g_idl_parse_string (const gchar *buffer,
2015 gssize length,
2016 GError **error)
2018 ParseContext ctx = { 0 };
2019 GMarkupParseContext *context;
2021 ctx.state = STATE_START;
2023 context = g_markup_parse_context_new (&parser, 0, &ctx, NULL);
2024 if (!g_markup_parse_context_parse (context, buffer, length, error))
2025 goto out;
2027 if (!g_markup_parse_context_end_parse (context, error))
2028 goto out;
2030 out:
2032 g_markup_parse_context_free (context);
2034 return ctx.modules;
2037 GList *
2038 g_idl_parse_file (const gchar *filename,
2039 GError **error)
2041 gchar *buffer;
2042 gsize length;
2043 GList *modules;
2045 if (!g_file_get_contents (filename, &buffer, &length, error))
2046 return NULL;
2048 modules = g_idl_parse_string (buffer, length, error);
2050 g_free (buffer);
2052 return modules;