summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Zeuthen <davidz@redhat.com>2009-05-07 19:26:55 -0400
committerDavid Zeuthen <davidz@redhat.com>2009-05-07 19:26:55 -0400
commite4e6527f7ad3c486b23186c1ce53045664b28bb8 (patch)
treef4e2c60e65903892a335eeda252a86ea7adf2a23
parentbc2486b369506c07ec2d62bc16a5c80d35479947 (diff)
First stab at language and parser
-rw-r--r--configure.ac3
-rw-r--r--src/Makefile.am58
-rw-r--r--src/dbus-idl-1.pc.in11
-rw-r--r--src/dbusidl.c1867
-rw-r--r--src/dbusidl.h234
-rw-r--r--src/dbusidlprivate.h319
-rw-r--r--src/idl.h (renamed from src/main.c)25
-rw-r--r--src/idllexer.l156
-rw-r--r--src/idlparser.y788
-rw-r--r--src/org.freedesktop.DBus.Idl.Tests1.didl116
-rw-r--r--src/test.c74
11 files changed, 3635 insertions, 16 deletions
diff --git a/configure.ac b/configure.ac
index 25155a0..a49c081 100644
--- a/configure.ac
+++ b/configure.ac
@@ -8,6 +8,8 @@ AC_PROG_CC
AC_ISC_POSIX
AC_HEADER_STDC
AC_PROG_LIBTOOL
+AC_PROG_LEX
+AC_PROG_YACC
#### gcc warning flags
AC_ARG_ENABLE(ansi, [ --enable-ansi enable -ansi -pedantic gcc flags],enable_ansi=$enableval,enable_ansi=no)
@@ -90,6 +92,7 @@ AC_SUBST(GLIB2_LIBS)
AC_OUTPUT([
Makefile
src/Makefile
+src/dbus-idl-1.pc
])
echo "
diff --git a/src/Makefile.am b/src/Makefile.am
index 70b8886..5291751 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,19 +1,65 @@
NULL =
-noinst_PROGRAMS = dbus-idl
+INCLUDES = -DDBUS_IDL_I_UNDERSTAND_THAT_API_IS_UNSTABLE
-dbus_idl_SOURCES = \
- main.c \
+noinst_PROGRAMS = dbus-idl-test
+
+pkgconfigdir=$(libdir)/pkgconfig
+pkgconfig_DATA = dbus-idl-1.pc
+
+dbus_idl_test_SOURCES = \
+ test.c \
$(NULL)
-dbus_idl_CFLAGS = \
+dbus_idl_test_CFLAGS = \
$(GLIB2_CFLAGS) \
$(NULL)
-dbus_idl_LDADD = \
+dbus_idl_test_LDADD = \
$(GLIB2_LIBS) \
+ libdbus-idl-1.la \
+ $(NULL)
+
+lib_LTLIBRARIES=libdbus-idl-1.la
+
+libdbus_idl_1_la_includedir = \
+ $(includedir)/dbus-idl-1/dbusidl
+ $(NULL)
+
+libdbus_idl_1_la_include_HEADERS = \
+ dbusidl.h \
+ $(NULL)
+
+libdbus_idl_1_la_SOURCES = \
+ idl.h \
+ idllexer.l idlparser.y \
+ dbusidlprivate.h \
+ dbusidl.h dbusidl.c \
+ $(NULL)
+
+libdbus_idl_1_la_CFLAGS = \
+ $(GLIB2_CFLAGS) \
$(NULL)
+libdbus_idl_1_la_LIBADD = \
+ $(GLIB2_LIBS) \
+ $(NULL)
+
+idllexer.c : idllexer.l libdbus_idl_1_la-idlparser.h
+
+idlparser.c : idlparser.y
+
+libdbus_idl_1_la_YFLAGS = -v -d
+
+# ----------------------------------------------------------------------------------------------------
+
+TESTS = dbus-idl-test
+
+EXTRA_DIST = org.freedesktop.DBus.Idl.Tests1.didl
+
+# ----------------------------------------------------------------------------------------------------
+
clean-local:
- rm -f *~
+ rm -f *~ libdbus_idl_1_la-*
+
diff --git a/src/dbus-idl-1.pc.in b/src/dbus-idl-1.pc.in
new file mode 100644
index 0000000..906da07
--- /dev/null
+++ b/src/dbus-idl-1.pc.in
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: dbus-idl-1
+Description: D-Bus Introspection Parser
+Version: @VERSION@
+Libs: -L${libdir} -ldbus-idl-1
+Cflags: -I${includedir}/dbus-idl-1
+Requires: glib-2.0 >= 2.18
diff --git a/src/dbusidl.c b/src/dbusidl.c
new file mode 100644
index 0000000..947d486
--- /dev/null
+++ b/src/dbusidl.c
@@ -0,0 +1,1867 @@
+/* Copyright (C) 2009 David Zeuthen <zeuthen@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <zeuthen@gmail.com>
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include "idl.h"
+#include "dbusidl.h"
+
+/* ---------------------------------------------------------------------------------------------------- */
+/* ---------------------------------------------------------------------------------------------------- */
+/* ---------------------------------------------------------------------------------------------------- */
+
+DIBaseType
+di_base_get_type (DIBase *base)
+{
+ return base->type;
+}
+
+const gchar *
+di_base_get_decl_path (DIBase *base)
+{
+ return base->decl_filename;
+}
+
+guint
+di_base_get_decl_lineno (DIBase *base)
+{
+ return base->decl_lineno;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+/* getters */
+
+const gchar *
+di_type_get_name (DIType *type)
+{
+ return type->fully_qualified_name != NULL ? type->fully_qualified_name : type->name;
+}
+
+const gchar *
+di_type_get_signature (DIType *type)
+{
+ return type->signature;
+}
+
+static gint
+get_typecode_for_primitive_type (const gchar *name)
+{
+ guint n;
+ const gchar *primitive_types[] = {
+ "byte", "y",
+ "boolean", "b",
+ "int16", "n",
+ "uint16", "q",
+ "int32", "i",
+ "uint32", "u",
+ "int64", "x",
+ "uint64", "t",
+ "double", "d",
+ "string", "s",
+ "objpath", "o",
+ "signature", "g",
+ "variant", "v",
+ NULL
+ };
+
+ for (n = 0; primitive_types[n] != NULL; n += 2)
+ {
+ if (g_strcmp0 (name, primitive_types[n]) == 0)
+ return (primitive_types[n+1])[0];
+ }
+
+ return -1;
+}
+
+gint
+di_type_get_typecode (DIType *type)
+{
+ return get_typecode_for_primitive_type (type->name);
+}
+
+GList *
+di_type_get_inner_types (DIType *type)
+{
+ return type->inner_types;
+}
+
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+const gchar *
+di_arg_get_name (DIArg *arg)
+{
+ return arg->name;
+}
+
+DIType *
+di_arg_get_type (DIArg *arg)
+{
+ return arg->type;
+}
+
+DIArgDirection
+di_arg_get_direction (DIArg *arg)
+{
+ return arg->direction;
+}
+
+GList *
+di_arg_get_annotations (DIArg *arg)
+{
+ return arg->annotations;
+}
+
+
+const gchar *
+di_method_get_name (DIMethod *method)
+{
+ return method->name;
+}
+
+GList *
+di_method_get_args (DIMethod *method)
+{
+ return method->args;
+}
+
+GList *
+di_method_get_annotations (DIMethod *method)
+{
+ return method->annotations;
+}
+
+const gchar *
+di_method_get_in_signature (DIMethod *method)
+{
+ return method->in_signature;
+}
+
+const gchar *
+di_method_get_out_signature (DIMethod *method)
+{
+ return method->out_signature;
+}
+
+
+const gchar *
+di_signal_get_name (DISignal *signal)
+{
+ return signal->name;
+}
+
+GList *
+di_signal_get_args (DISignal *signal)
+{
+ return signal->args;
+}
+
+GList *
+di_signal_get_annotations (DISignal *signal)
+{
+ return signal->annotations;
+}
+
+const gchar *
+di_signal_get_signature (DISignal *signal)
+{
+ return signal->signature;
+}
+
+
+const gchar *
+di_property_get_name (DIProperty *property)
+{
+ return property->name;
+}
+
+DIType *
+di_property_get_type (DIProperty *property)
+{
+ return property->type;
+}
+
+GList *
+di_property_get_annotations (DIProperty *property)
+{
+ return property->annotations;
+}
+
+const gchar *
+di_property_get_signature (DIProperty *property)
+{
+ return property->signature;
+}
+
+
+const gchar *
+di_interface_get_name (DIInterface *interface)
+{
+ return interface->name;
+}
+
+GList *
+di_interface_get_methods (DIInterface *interface)
+{
+ return interface->methods;
+}
+
+GList *
+di_interface_get_signals (DIInterface *interface)
+{
+ return interface->signals;
+}
+
+GList *
+di_interface_get_properties (DIInterface *interface)
+{
+ return interface->properties;
+}
+
+GList *
+di_interface_get_annotations (DIInterface *interface)
+{
+ return interface->annotations;
+}
+
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+const gchar *
+di_struct_member_get_name (DIStructMember *struct_member)
+{
+ return struct_member->name;
+}
+
+DIType *
+di_struct_member_get_type (DIStructMember *struct_member)
+{
+ return struct_member->type;
+}
+
+GList *
+di_struct_member_get_annotations (DIStructMember *struct_member)
+{
+ return struct_member->annotations;
+}
+
+
+const gchar *
+di_struct_get_name (DIStruct *struct_)
+{
+ return struct_->name;
+}
+
+GList *
+di_struct_get_members (DIStruct *struct_)
+{
+ return struct_->members;
+}
+
+GList *
+di_struct_get_annotations (DIStruct *struct_)
+{
+ return struct_->annotations;
+}
+
+const gchar *
+di_struct_get_signature (DIStruct *struct_)
+{
+ return struct_->signature;
+}
+
+
+const gchar *
+di_dynamic_struct_get_name (DIDynamicStruct *dynamic_struct)
+{
+ return dynamic_struct->name;
+}
+
+GList *
+di_dynamic_struct_get_members (DIDynamicStruct *dynamic_struct)
+{
+ return dynamic_struct->members;
+}
+
+GList *
+di_dynamic_struct_get_annotations (DIDynamicStruct *dynamic_struct)
+{
+ return dynamic_struct->annotations;
+}
+
+const gchar *
+di_dynamic_struct_get_signature (DIDynamicStruct *dynamic_struct)
+{
+ return "(sa{sv})";
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+const gchar *
+di_enum_member_get_name (DIEnumMember *enum_member)
+{
+ return enum_member->name;
+}
+
+guint
+di_enum_member_get_value (DIEnumMember *enum_member)
+{
+ return enum_member->value;
+}
+
+gboolean
+di_enum_member_get_unset (DIEnumMember *enum_member)
+{
+ return enum_member->unset;
+}
+
+GList *
+di_enum_member_get_annotations (DIEnumMember *enum_member)
+{
+ return enum_member->annotations;
+}
+
+
+const gchar *
+di_enum_get_name (DIEnum *enum_)
+{
+ return enum_->name;
+}
+
+GList *
+di_enum_get_members (DIEnum *enum_)
+{
+ return enum_->members;
+}
+
+GList *
+di_enum_get_annotations (DIEnum *enum_)
+{
+ return enum_->annotations;
+}
+
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+const gchar *
+di_error_member_get_name (DIErrorMember *error_member)
+{
+ return error_member->name;
+}
+
+GList *
+di_error_member_get_annotations (DIErrorMember *error_member)
+{
+ return error_member->annotations;
+}
+
+
+const gchar *
+di_error_domain_get_name (DIErrorDomain *error_domain)
+{
+ return error_domain->name;
+}
+
+GList *
+di_error_domain_get_members (DIErrorDomain *error_domain)
+{
+ return error_domain->members;
+}
+
+GList *
+di_error_domain_get_annotations (DIErrorDomain *error_domain)
+{
+ return error_domain->annotations;
+}
+
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+const gchar *
+di_namespace_get_name (DINamespace *namespace)
+{
+ return namespace->name;
+}
+
+GList *
+di_namespace_get_interfaces (DINamespace *namespace)
+{
+ return namespace->interfaces;
+}
+
+GList *
+di_namespace_get_structs (DINamespace *namespace)
+{
+ return namespace->structs;
+}
+
+GList *
+di_namespace_get_dynamic_structs (DINamespace *namespace)
+{
+ return namespace->dynamic_structs;
+}
+
+GList *
+di_namespace_get_enums (DINamespace *namespace)
+{
+ return namespace->enums;
+}
+
+GList *
+di_namespace_get_error_domains (DINamespace *namespace)
+{
+ return namespace->error_domains;
+}
+
+GList *
+di_namespace_get_annotations (DINamespace *namespace)
+{
+ return namespace->annotations;
+}
+
+
+/* ---------------------------------------------------------------------------------------------------- */
+/* ---------------------------------------------------------------------------------------------------- */
+/* ---------------------------------------------------------------------------------------------------- */
+
+void
+di_annotation_free (DIAnnotation *annotation)
+{
+}
+
+void
+di_type_free (DIType *type)
+{
+}
+
+void
+di_arg_free (DIArg *arg)
+{
+}
+
+void
+di_signal_free (DISignal *signal)
+{
+}
+
+void
+di_method_free (DIMethod *method)
+{
+}
+
+void
+di_property_free (DIProperty *property)
+{
+}
+
+void
+di_interface_free (DIInterface *interface)
+{
+}
+
+void
+di_struct_member_free (DIStructMember *struct_member)
+{
+}
+
+void
+di_struct_free (DIStruct *struct_)
+{
+}
+
+void
+di_dynamic_struct_free (DIDynamicStruct *dynamic_struct)
+{
+}
+
+void
+di_enum_member_free (DIEnumMember *enum_member)
+{
+}
+
+void
+di_enum_free (DIEnum *enum_)
+{
+}
+
+void
+di_error_member_free (DIErrorMember *error_member)
+{
+}
+
+void
+di_error_domain_free (DIErrorDomain *error_domain)
+{
+}
+
+void
+di_namespace_free (DINamespace *namespace)
+{
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+DIAnnotation *di_annotation_new (gchar *decl_filename,
+ guint decl_lineno,
+ gchar *name,
+ gchar *value)
+{
+ DIAnnotation *ret;
+ ret = g_new0 (DIAnnotation, 1);
+ ret->base.type = DI_BASE_TYPE_ANNOTATION;
+ ret->base.decl_filename = decl_filename;
+ ret->base.decl_lineno = decl_lineno;
+ ret->name = name;
+ ret->value = value;
+ return ret;
+}
+
+DIType *
+di_type_new (gchar *decl_filename,
+ guint decl_lineno,
+ gchar *name,
+ GList *inner_types)
+{
+ DIType *ret;
+ ret = g_new0 (DIType, 1);
+ ret->base.type = DI_BASE_TYPE_TYPE;
+ ret->base.decl_filename = decl_filename;
+ ret->base.decl_lineno = decl_lineno;
+ ret->name = name;
+ ret->inner_types = inner_types;
+ return ret;
+}
+
+DIArg *
+di_arg_new (gchar *decl_filename,
+ guint decl_lineno,
+ gchar *name,
+ DIType *type,
+ DIArgDirection direction,
+ GList *annotations)
+{
+ DIArg *ret;
+ ret = g_new0 (DIArg, 1);
+ ret->base.type = DI_BASE_TYPE_ARG;
+ ret->base.decl_filename = decl_filename;
+ ret->base.decl_lineno = decl_lineno;
+ ret->name = name;
+ ret->type = type;
+ ret->direction = direction;
+ ret->annotations = annotations;
+ return ret;
+}
+
+DIMethod *
+di_method_new (gchar *decl_filename,
+ guint decl_lineno,
+ gchar *name,
+ GList *args,
+ GList *annotations)
+{
+ DIMethod *ret;
+ ret = g_new0 (DIMethod, 1);
+ ret->base.type = DI_BASE_TYPE_METHOD;
+ ret->base.decl_filename = decl_filename;
+ ret->base.decl_lineno = decl_lineno;
+ ret->name = name;
+ ret->args = args;
+ ret->annotations = annotations;
+ return ret;
+}
+
+DISignal *
+di_signal_new (gchar *decl_filename,
+ guint decl_lineno,
+ gchar *name,
+ GList *args,
+ GList *annotations)
+{
+ DISignal *ret;
+ ret = g_new0 (DISignal, 1);
+ ret->base.type = DI_BASE_TYPE_SIGNAL;
+ ret->base.decl_filename = decl_filename;
+ ret->base.decl_lineno = decl_lineno;
+ ret->name = name;
+ ret->args = args;
+ ret->annotations = annotations;
+ return ret;
+}
+
+DIProperty *
+di_property_new (gchar *decl_filename,
+ guint decl_lineno,
+ gchar *name,
+ DIType *type,
+ DIPropertyFlags flags,
+ GList *annotations)
+{
+ DIProperty *ret;
+ ret = g_new0 (DIProperty, 1);
+ ret->base.type = DI_BASE_TYPE_PROPERTY;
+ ret->base.decl_filename = decl_filename;
+ ret->base.decl_lineno = decl_lineno;
+ ret->name = name;
+ ret->type = type;
+ ret->flags = flags;
+ ret->annotations = annotations;
+ return ret;
+}
+
+DIInterface *
+di_interface_new (gchar *decl_filename,
+ guint decl_lineno,
+ gchar *name,
+ GList *methods,
+ GList *signals,
+ GList *properties,
+ GList *annotations)
+{
+ DIInterface *ret;
+ ret = g_new0 (DIInterface, 1);
+ ret->base.type = DI_BASE_TYPE_INTERFACE;
+ ret->base.decl_filename = decl_filename;
+ ret->base.decl_lineno = decl_lineno;
+ ret->name = name;
+ ret->methods = methods;
+ ret->signals = signals;
+ ret->properties = properties;
+ ret->annotations = annotations;
+ return ret;
+}
+
+DIStructMember *
+di_struct_member_new (gchar *decl_filename,
+ guint decl_lineno,
+ gchar *name,
+ DIType *type,
+ GList *annotations)
+{
+ DIStructMember *ret;
+ ret = g_new0 (DIStructMember, 1);
+ ret->base.type = DI_BASE_TYPE_STRUCT_MEMBER;
+ ret->base.decl_filename = decl_filename;
+ ret->base.decl_lineno = decl_lineno;
+ ret->name = name;
+ ret->type = type;
+ ret->annotations = annotations;
+ return ret;
+}
+
+DIStruct *
+di_struct_new (gchar *decl_filename,
+ guint decl_lineno,
+ gchar *name,
+ GList *members,
+ GList *annotations)
+{
+ DIStruct *ret;
+ ret = g_new0 (DIStruct, 1);
+ ret->base.type = DI_BASE_TYPE_STRUCT;
+ ret->base.decl_filename = decl_filename;
+ ret->base.decl_lineno = decl_lineno;
+ ret->name = name;
+ ret->members = members;
+ ret->annotations = annotations;
+ return ret;
+}
+
+DIDynamicStruct *
+di_dynamic_struct_new (gchar *decl_filename,
+ guint decl_lineno,
+ gchar *name,
+ GList *members,
+ GList *annotations)
+{
+ DIDynamicStruct *ret;
+ ret = g_new0 (DIDynamicStruct, 1);
+ ret->base.type = DI_BASE_TYPE_DYNAMIC_STRUCT;
+ ret->base.decl_filename = decl_filename;
+ ret->base.decl_lineno = decl_lineno;
+ ret->name = name;
+ ret->members = members;
+ ret->annotations = annotations;
+ return ret;
+}
+
+DIEnumMember *
+di_enum_member_new (gchar *decl_filename,
+ guint decl_lineno,
+ gchar *name,
+ guint32 value,
+ gboolean unset,
+ GList *annotations)
+{
+ DIEnumMember *ret;
+ ret = g_new0 (DIEnumMember, 1);
+ ret->base.type = DI_BASE_TYPE_ENUM_MEMBER;
+ ret->base.decl_filename = decl_filename;
+ ret->base.decl_lineno = decl_lineno;
+ ret->name = name;
+ ret->value = value;
+ ret->unset = unset;
+ ret->annotations = annotations;
+ return ret;
+}
+
+DIEnum *
+di_enum_new (gchar *decl_filename,
+ guint decl_lineno,
+ gchar *name,
+ GList *members,
+ GList *annotations)
+{
+ DIEnum *ret;
+ ret = g_new0 (DIEnum, 1);
+ ret->base.type = DI_BASE_TYPE_ENUM;
+ ret->base.decl_filename = decl_filename;
+ ret->base.decl_lineno = decl_lineno;
+ ret->name = name;
+ ret->members = members;
+ ret->annotations = annotations;
+ return ret;
+}
+
+DIErrorMember *
+di_error_member_new (gchar *decl_filename,
+ guint decl_lineno,
+ gchar *name,
+ GList *annotations)
+{
+ DIErrorMember *ret;
+ ret = g_new0 (DIErrorMember, 1);
+ ret->base.type = DI_BASE_TYPE_ERROR_MEMBER;
+ ret->base.decl_filename = decl_filename;
+ ret->base.decl_lineno = decl_lineno;
+ ret->name = name;
+ ret->annotations = annotations;
+ return ret;
+}
+
+DIErrorDomain *
+di_error_domain_new (gchar *decl_filename,
+ guint decl_lineno,
+ gchar *name,
+ GList *members,
+ GList *annotations)
+{
+ DIErrorDomain *ret;
+ ret = g_new0 (DIErrorDomain, 1);
+ ret->base.type = DI_BASE_TYPE_ERROR_DOMAIN;
+ ret->base.decl_filename = decl_filename;
+ ret->base.decl_lineno = decl_lineno;
+ ret->name = name;
+ ret->members = members;
+ ret->annotations = annotations;
+ return ret;
+}
+
+DINamespace *
+di_namespace_new (gchar *decl_filename,
+ guint decl_lineno,
+ gchar *name,
+ GList *interfaces,
+ GList *structs,
+ GList *dynamic_structs,
+ GList *enums,
+ GList *error_domains,
+ GList *annotations)
+{
+ DINamespace *ret;
+ ret = g_new0 (DINamespace, 1);
+ ret->base.type = DI_BASE_TYPE_NAMESPACE;
+ ret->base.decl_filename = decl_filename;
+ ret->base.decl_lineno = decl_lineno;
+ ret->name = name;
+ ret->interfaces = interfaces;
+ ret->structs = structs;
+ ret->dynamic_structs = dynamic_structs;
+ ret->enums = enums;
+ ret->error_domains = error_domains;
+ ret->annotations = annotations;
+ return ret;
+}
+
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+void
+di_annotation_print (DIAnnotation *annotation, guint indent)
+{
+ g_print ("%*s@%s", indent, "", annotation->name);
+ if (annotation->value != NULL)
+ {
+ g_print (" (\"%s\")", annotation->value);
+ }
+ g_print ("\n");
+}
+
+void
+di_type_print (DIType *type, guint indent)
+{
+ g_print ("%*s%s", indent, "",
+ type->fully_qualified_name != NULL ? type->fully_qualified_name : type->name);
+ if (type->inner_types != NULL)
+ {
+ GList *l;
+ g_print ("<");
+ for (l = type->inner_types; l != NULL; l = l->next)
+ {
+ if (l != type->inner_types)
+ g_print (",");
+ di_type_print (l->data, 0);
+ }
+ g_print (">");
+ }
+}
+
+void
+di_arg_print (DIArg *arg, guint indent)
+{
+ const gchar *direction;
+ GList *l;
+
+ switch (arg->direction)
+ {
+ case DI_ARG_DIRECTION_NONE:
+ direction = "";
+ break;
+ case DI_ARG_DIRECTION_IN:
+ direction = "IN ";
+ break;
+ case DI_ARG_DIRECTION_OUT:
+ direction = "OUT ";
+ break;
+ }
+ for (l = arg->annotations; l != NULL; l = l->next)
+ di_annotation_print ((DIAnnotation *) l->data, indent);
+ g_print ("%*s%s", indent, "", direction);
+ di_type_print (arg->type, 0);
+ g_print (" %s", arg->name);
+}
+
+void
+di_signal_print (DISignal *signal, guint indent)
+{
+ GList *l;
+ guint arg_indent;
+
+ arg_indent = indent + 7 + strlen (signal->name) + 2;
+
+ for (l = signal->annotations; l != NULL; l = l->next)
+ di_annotation_print ((DIAnnotation *) l->data, indent);
+ g_print ("%*s# signature=%s\n", indent, "", signal->signature);
+ g_print ("%*ssignal %s (", indent, "", signal->name);
+ for (l = signal->args; l != NULL; l = l->next)
+ {
+ if (((DIArg *) l->data)->annotations != NULL)
+ di_arg_print (l->data, arg_indent);
+ else
+ di_arg_print (l->data, (l == signal->args ? 0 : arg_indent));
+ if (l->next != NULL)
+ g_print (",\n");
+ }
+ g_print (");\n");
+}
+
+void
+di_method_print (DIMethod *method, guint indent)
+{
+ GList *l;
+ guint arg_indent;
+
+ arg_indent = indent + 7 + strlen (method->name) + 2;
+
+ for (l = method->annotations; l != NULL; l = l->next)
+ di_annotation_print ((DIAnnotation *) l->data, indent);
+ g_print ("%*s# in_signature=%s out_signature=%s\n",
+ indent, "",
+ method->in_signature,
+ method->out_signature);
+ g_print ("%*smethod %s (", indent, "",
+ method->name);
+ for (l = method->args; l != NULL; l = l->next)
+ {
+ if (((DIArg *) l->data)->annotations != NULL)
+ di_arg_print (l->data, arg_indent);
+ else
+ di_arg_print (l->data, (l == method->args ? 0 : arg_indent));
+ if (l->next != NULL)
+ g_print (",\n");
+ }
+ g_print (");\n");
+}
+
+void
+di_property_print (DIProperty *property, guint indent)
+{
+ const gchar *flags_str;
+ GList *l;
+
+ switch (property->flags)
+ {
+ case DI_PROPERTY_FLAGS_READABLE:
+ flags_str = "readonly";
+ break;
+ case DI_PROPERTY_FLAGS_WRITABLE:
+ flags_str = "writeonly";
+ break;
+ case DI_PROPERTY_FLAGS_READABLE | DI_PROPERTY_FLAGS_WRITABLE:
+ flags_str = "readwrite";
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+ for (l = property->annotations; l != NULL; l = l->next)
+ di_annotation_print ((DIAnnotation *) l->data, indent);
+ g_print ("%*s# signature=%s\n", indent, "", property->signature);
+ g_print ("%*s%s property ",
+ indent, "",
+ flags_str);
+ di_type_print (property->type, 0);
+ g_print (" %s;\n", property->name);
+}
+
+void
+di_interface_print (DIInterface *interface, guint indent)
+{
+ GList *l;
+ for (l = interface->annotations; l != NULL; l = l->next)
+ di_annotation_print ((DIAnnotation *) l->data, indent);
+ g_print ("%*sinterface %s {\n", indent, "", interface->name);
+ for (l = interface->methods; l != NULL; l = l->next)
+ di_method_print (l->data, indent + 2);
+ for (l = interface->signals; l != NULL; l = l->next)
+ di_signal_print (l->data, indent + 2);
+ for (l = interface->properties; l != NULL; l = l->next)
+ di_property_print (l->data, indent + 2);
+ g_print ("%*s};\n", indent, "");
+}
+
+void
+di_struct_member_print (DIStructMember *struct_member, guint indent)
+{
+ GList *l;
+
+ for (l = struct_member->annotations; l != NULL; l = l->next)
+ di_annotation_print ((DIAnnotation *) l->data, indent);
+ g_print ("%*s", indent, "");
+ di_type_print (struct_member->type, 0);
+ g_print (" %s;\n", struct_member->name);
+}
+
+void
+di_struct_print (DIStruct *struct_, guint indent)
+{
+ GList *l;
+
+ for (l = struct_->annotations; l != NULL; l = l->next)
+ di_annotation_print ((DIAnnotation *) l->data, indent);
+ g_print ("%*s# signature=%s\n", indent, "", struct_->signature);
+ g_print ("%*sstruct %s {\n", indent, "", struct_->name);
+ for (l = struct_->members; l != NULL; l = l->next)
+ di_struct_member_print (l->data, indent + 2);
+ g_print ("%*s};\n", indent, "");
+}
+
+void
+di_dynamic_struct_print (DIDynamicStruct *dynamic_struct, guint indent)
+{
+ GList *l;
+
+ for (l = dynamic_struct->annotations; l != NULL; l = l->next)
+ di_annotation_print ((DIAnnotation *) l->data, indent);
+ g_print ("%*sdynamic_struct %s {\n", indent, "", dynamic_struct->name);
+ for (l = dynamic_struct->members; l != NULL; l = l->next)
+ di_struct_member_print (l->data, indent + 2);
+ g_print ("%*s};\n", indent, "");
+}
+
+void
+di_enum_member_print (DIEnumMember *enum_member, guint indent)
+{
+ GList *l;
+
+ for (l = enum_member->annotations; l != NULL; l = l->next)
+ di_annotation_print ((DIAnnotation *) l->data, indent);
+ if (enum_member->unset)
+ {
+ g_print ("%*s%s = 0x%08x (unset),\n", indent, "",
+ enum_member->name,
+ enum_member->value);
+ }
+ else
+ {
+ g_print ("%*s%s = 0x%08x,\n", indent, "",
+ enum_member->name,
+ enum_member->value);
+ }
+}
+
+void
+di_enum_print (DIEnum *enum_, guint indent)
+{
+ GList *l;
+
+ for (l = enum_->annotations; l != NULL; l = l->next)
+ di_annotation_print ((DIAnnotation *) l->data, indent);
+ g_print ("%*senum %s {\n", indent, "", enum_->name);
+ for (l = enum_->members; l != NULL; l = l->next)
+ di_enum_member_print (l->data, indent + 2);
+ g_print ("%*s};\n", indent, "");
+}
+
+void
+di_error_member_print (DIErrorMember *error_member, guint indent)
+{
+ GList *l;
+
+ for (l = error_member->annotations; l != NULL; l = l->next)
+ di_annotation_print ((DIAnnotation *) l->data, indent);
+ g_print ("%*s%s,\n", indent, "",
+ error_member->name);
+}
+
+void
+di_error_domain_print (DIErrorDomain *error_domain, guint indent)
+{
+ GList *l;
+
+ for (l = error_domain->annotations; l != NULL; l = l->next)
+ di_annotation_print ((DIAnnotation *) l->data, indent);
+ g_print ("%*serror_domain %s {\n", indent, "", error_domain->name);
+ for (l = error_domain->members; l != NULL; l = l->next)
+ di_error_member_print (l->data, indent + 2);
+ g_print ("%*s};\n", indent, "");
+}
+
+void
+di_namespace_print (DINamespace *namespace, guint indent)
+{
+ GList *l;
+
+ for (l = namespace->annotations; l != NULL; l = l->next)
+ di_annotation_print ((DIAnnotation *) l->data, indent);
+ g_print ("%*snamespace %s {\n", indent, "", namespace->name);
+ for (l = namespace->structs; l != NULL; l = l->next)
+ di_struct_print (l->data, indent + 2);
+ for (l = namespace->dynamic_structs; l != NULL; l = l->next)
+ di_dynamic_struct_print (l->data, indent + 2);
+ for (l = namespace->enums; l != NULL; l = l->next)
+ di_enum_print (l->data, indent + 2);
+ for (l = namespace->error_domains; l != NULL; l = l->next)
+ di_error_domain_print (l->data, indent + 2);
+ for (l = namespace->interfaces; l != NULL; l = l->next)
+ di_interface_print (l->data, indent + 2);
+ g_print ("%*s};\n", indent, "");
+}
+
+
+/* ---------------------------------------------------------------------------------------------------- */
+static void
+ensure_method (DIParser *parser,
+ DIMethod *method)
+{
+ GList *l, *ll;
+ for (l = method->args; l != NULL; l = l->next)
+ {
+ DIArg *i = l->data;
+ for (ll = method->args; ll != l; ll = ll->next)
+ {
+ DIArg *other = ll->data;
+ if (g_strcmp0 (other->name, i->name) == 0)
+ {
+ parser->errors = g_list_append (parser->errors,
+ g_strdup_printf ("%s:%d: Method %s already has an argument named %s",
+ method->base.decl_filename,
+ method->base.decl_lineno,
+ method->name,
+ i->name));
+ }
+ }
+ }
+}
+
+static void
+ensure_signal (DIParser *parser,
+ DISignal *signal)
+{
+ GList *l, *ll;
+ for (l = signal->args; l != NULL; l = l->next)
+ {
+ DIArg *i = l->data;
+ for (ll = signal->args; ll != l; ll = ll->next)
+ {
+ DIArg *other = ll->data;
+ if (g_strcmp0 (other->name, i->name) == 0)
+ {
+ parser->errors = g_list_append (parser->errors,
+ g_strdup_printf ("%s:%d: Signal %s already has an argument named %s",
+ signal->base.decl_filename,
+ signal->base.decl_lineno,
+ signal->name,
+ i->name));
+ }
+ }
+ }
+}
+
+static const gchar *
+di_base_type_to_string (DIBaseType type)
+{
+ const gchar *ret;
+ ret = NULL;
+ switch (type)
+ {
+ case DI_BASE_TYPE_METHOD: ret = "method"; break;
+ case DI_BASE_TYPE_SIGNAL: ret = "signal"; break;
+ case DI_BASE_TYPE_PROPERTY: ret = "property"; break;
+ case DI_BASE_TYPE_INTERFACE: ret = "interface"; break;
+ case DI_BASE_TYPE_STRUCT_MEMBER: ret = "struct_member"; break;
+ case DI_BASE_TYPE_STRUCT: ret = "struct"; break;
+ case DI_BASE_TYPE_DYNAMIC_STRUCT: ret = "dynstruct"; break;
+ case DI_BASE_TYPE_ENUM_MEMBER: ret = "enum_member"; break;
+ case DI_BASE_TYPE_ENUM: ret = "enum"; break;
+ case DI_BASE_TYPE_ERROR_MEMBER: ret = "error_member"; break;
+ case DI_BASE_TYPE_ERROR_DOMAIN: ret = "error_domain"; break;
+ case DI_BASE_TYPE_NAMESPACE: ret = "namespace"; break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+ return ret;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static gboolean
+insert_and_check (DIParser *parser,
+ DIBase *symbol,
+ const gchar *fully_qualified_name)
+{
+ DIBase *base;
+ gboolean ret;
+
+ ret = FALSE;
+
+ base = (DIBase *) g_hash_table_lookup (parser->symbol_table, fully_qualified_name);
+ if (base != NULL)
+ {
+ parser->errors = g_list_append (parser->errors,
+ g_strdup_printf ("%s:%d: error: name %s for %s is already in use",
+ symbol->decl_filename,
+ symbol->decl_lineno,
+ fully_qualified_name,
+ di_base_type_to_string (symbol->type)));
+ parser->errors = g_list_append (parser->errors,
+ g_strdup_printf ("%s:%d: error: name %s previously declared as a %s",
+ base->decl_filename,
+ base->decl_lineno,
+ fully_qualified_name,
+ di_base_type_to_string (base->type)));
+ goto out;
+ }
+
+ g_hash_table_insert (parser->symbol_table,
+ (gpointer) fully_qualified_name,
+ symbol);
+
+ ret = TRUE;
+
+ out:
+ return ret;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+type_compute_fully_qualified_name (DIParser *parser,
+ DIType *type,
+ DINamespace *namespace)
+{
+ type->fully_qualified_name = NULL;
+ if (get_typecode_for_primitive_type (type->name) != -1)
+ {
+ /* do nothing for primitive types */
+ g_assert (type->inner_types == NULL);
+ }
+ else if (g_strcmp0 (type->name, "array") == 0)
+ {
+ /* recurse into arrays */
+ g_assert (g_list_length (type->inner_types) == 1);
+ type_compute_fully_qualified_name (parser,
+ (DIType *) type->inner_types->data,
+ namespace);
+ }
+ else if (g_strcmp0 (type->name, "dict") == 0)
+ {
+ /* recurse into dicts */
+ g_assert (g_list_length (type->inner_types) == 2);
+ type_compute_fully_qualified_name (parser,
+ (DIType *) type->inner_types->data,
+ namespace);
+ type_compute_fully_qualified_name (parser,
+ (DIType *) type->inner_types->next->data,
+ namespace);
+ }
+ else if (strstr (type->name, ".") != NULL)
+ {
+ /* if name is already qualified, use that */
+ g_assert (type->inner_types == NULL);
+ type->fully_qualified_name = g_strdup (type->name);
+ }
+ else
+ {
+ /* otherwise prepend the given namespace */
+ g_assert (type->inner_types == NULL);
+ type->fully_qualified_name = g_strdup_printf ("%s.%s",
+ namespace->name,
+ type->name);
+ }
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+build_symbol_table (DIParser *parser)
+{
+ GList *l, *ll, *lll, *llll;
+
+ parser->symbol_table = g_hash_table_new (g_str_hash, g_str_equal);
+ /* for all namespaces */
+ for (l = parser->namespaces; l != NULL; l = l->next)
+ {
+ DINamespace *namespace = l->data;
+
+ if (!insert_and_check (parser, (DIBase *) namespace, namespace->name))
+ continue;
+
+ /* for all interfaces */
+ for (ll = namespace->interfaces; ll != NULL; ll = ll->next)
+ {
+ DIInterface *interface = ll->data;
+ interface->fully_qualified_name = g_strdup_printf ("%s.%s",
+ namespace->name,
+ interface->name);
+ if (!insert_and_check (parser, (DIBase *) interface, interface->fully_qualified_name))
+ continue;
+
+ /* for all methods */
+ for (lll = interface->methods; lll != NULL; lll = lll->next)
+ {
+ DIMethod *method = lll->data;
+ method->fully_qualified_name = g_strdup_printf ("%s.%s",
+ interface->fully_qualified_name,
+ method->name);
+ insert_and_check (parser, (DIBase *) method, method->fully_qualified_name);
+
+ /* check for collision for arg names */
+ ensure_method (parser, method);
+
+ /* make type names for all args fully qualified */
+ for (llll = method->args; llll != NULL; llll = llll->next)
+ {
+ DIArg *arg = llll->data;
+ type_compute_fully_qualified_name (parser,
+ arg->type,
+ namespace);
+ }
+ }
+
+ /* for all signals */
+ for (lll = interface->signals; lll != NULL; lll = lll->next)
+ {
+ DISignal *signal = lll->data;
+ signal->fully_qualified_name = g_strdup_printf ("%s.%s",
+ interface->fully_qualified_name,
+ signal->name);
+ insert_and_check (parser, (DIBase *) signal, signal->fully_qualified_name);
+ /* check for collision for arg names */
+ ensure_signal (parser, signal);
+
+ /* make type names for all args fully qualified */
+ for (llll = signal->args; llll != NULL; llll = llll->next)
+ {
+ DIArg *arg = llll->data;
+ type_compute_fully_qualified_name (parser,
+ arg->type,
+ namespace);
+ }
+ }
+
+ /* for all properties */
+ for (lll = interface->properties; lll != NULL; lll = lll->next)
+ {
+ DIProperty *property = lll->data;
+ property->fully_qualified_name = g_strdup_printf ("%s.%s",
+ interface->fully_qualified_name,
+ property->name);
+ insert_and_check (parser, (DIBase *) property, property->fully_qualified_name);
+
+ /* make type name fully qualified */
+ type_compute_fully_qualified_name (parser,
+ property->type,
+ namespace);
+ }
+ }
+
+ /* for all structs */
+ for (ll = namespace->structs; ll != NULL; ll = ll->next)
+ {
+ DIStruct *struct_ = ll->data;
+ struct_->fully_qualified_name = g_strdup_printf ("%s.%s",
+ namespace->name,
+ struct_->name);
+ insert_and_check (parser, (DIBase *) struct_, struct_->fully_qualified_name);
+ for (lll = struct_->members; lll != NULL; lll = lll->next)
+ {
+ DIStructMember *struct_member = lll->data;
+
+ /* make type name fully qualified */
+ type_compute_fully_qualified_name (parser,
+ struct_member->type,
+ namespace);
+ }
+ }
+
+ /* for all dynamic structs */
+ for (ll = namespace->dynamic_structs; ll != NULL; ll = ll->next)
+ {
+ DIDynamicStruct *dynamic_struct = ll->data;
+ dynamic_struct->fully_qualified_name = g_strdup_printf ("%s.%s",
+ namespace->name,
+ dynamic_struct->name);
+ insert_and_check (parser, (DIBase *) dynamic_struct, dynamic_struct->fully_qualified_name);
+ for (lll = dynamic_struct->members; lll != NULL; lll = lll->next)
+ {
+ DIStructMember *struct_member = lll->data;
+
+ /* make type name fully qualified */
+ type_compute_fully_qualified_name (parser,
+ struct_member->type,
+ namespace);
+ }
+ }
+
+ /* for all enums */
+ for (ll = namespace->enums; ll != NULL; ll = ll->next)
+ {
+ DIEnum *enum_ = ll->data;
+ enum_->fully_qualified_name = g_strdup_printf ("%s.%s",
+ namespace->name,
+ enum_->name);
+ insert_and_check (parser, (DIBase *) enum_, enum_->fully_qualified_name);
+ for (lll = enum_->members; lll != NULL; lll = lll->next)
+ {
+ DIEnumMember *enum_member = lll->data;
+ enum_member->fully_qualified_name = g_strdup_printf ("%s.%s",
+ enum_->fully_qualified_name,
+ enum_member->name);
+ insert_and_check (parser, (DIBase *) enum_member, enum_member->fully_qualified_name);
+ }
+ }
+
+ /* for all errors */
+ for (ll = namespace->error_domains; ll != NULL; ll = ll->next)
+ {
+ DIErrorDomain *error_domain = ll->data;
+ error_domain->fully_qualified_name = g_strdup_printf ("%s.%s",
+ namespace->name,
+ error_domain->name);
+ insert_and_check (parser, (DIBase *) error_domain, error_domain->fully_qualified_name);
+ for (lll = error_domain->members; lll != NULL; lll = lll->next)
+ {
+ DIErrorMember *error_member = lll->data;
+ error_member->fully_qualified_name = g_strdup_printf ("%s.%s",
+ error_domain->fully_qualified_name,
+ error_member->name);
+ insert_and_check (parser, (DIBase *) error_member, error_member->fully_qualified_name);
+ }
+ }
+ } /* for all namespaces */
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+DIBase *
+di_parser_lookup_symbol (DIParser *parser,
+ const gchar *fully_qualified_name)
+{
+ DIBase *base;
+ base = (DIBase *) g_hash_table_lookup (parser->symbol_table, fully_qualified_name);
+ return base;
+}
+
+static void
+visit_type (DIParser *parser,
+ DIType *type,
+ DIBase *referenced_in,
+ guint recursion_level)
+{
+ GString *s;
+ gint typecode;
+
+ if (recursion_level >= 128)
+ {
+ parser->errors = g_list_append (parser->errors,
+ g_strdup_printf ("%s:%d: error: type recursion level reached",
+ referenced_in->decl_filename,
+ referenced_in->decl_lineno));
+ return;
+ }
+
+ if (type->signature != NULL)
+ return;
+
+ s = g_string_new (NULL);
+
+ typecode = get_typecode_for_primitive_type (type->name);
+ if (typecode != -1)
+ {
+ /* primitive type */
+ g_string_append_c (s, typecode);
+ }
+ else if (g_strcmp0 (type->name, "array") == 0)
+ {
+ /* array */
+ g_assert (g_list_length (type->inner_types) == 1);
+ visit_type (parser,
+ (DIType *) type->inner_types->data,
+ referenced_in,
+ recursion_level + 1);
+ g_string_append_c (s, 'a');
+ g_string_append (s, ((DIType *) type->inner_types->data)->signature);
+ }
+ else if (g_strcmp0 (type->name, "dict") == 0)
+ {
+ /* dict */
+ g_assert (g_list_length (type->inner_types) == 2);
+ visit_type (parser,
+ (DIType *) type->inner_types->data,
+ referenced_in,
+ recursion_level + 1);
+ visit_type (parser,
+ (DIType *) type->inner_types->next->data,
+ referenced_in,
+ recursion_level + 1);
+ g_string_append (s, "a{");
+ g_string_append (s, ((DIType *) type->inner_types->data)->signature);
+ g_string_append (s, ((DIType *) type->inner_types->next->data)->signature);
+ g_string_append_c (s, '}');
+ }
+ else
+ {
+ DIBase *base;
+
+ /* can either reference a struct or an enum */
+ base = di_parser_lookup_symbol (parser, type->fully_qualified_name);
+ if (base == NULL)
+ {
+ parser->errors = g_list_append (parser->errors,
+ g_strdup_printf ("%s:%d: error: cannot resolve type %s",
+ referenced_in->decl_filename,
+ referenced_in->decl_lineno,
+ type->fully_qualified_name));
+ }
+ else if (base->type == DI_BASE_TYPE_STRUCT)
+ {
+ GList *l;
+ DIStruct *struct_;
+ DIStructMember *struct_member;
+
+ g_string_append_c (s, '(');
+ struct_ = (DIStruct *) base;
+ for (l = struct_->members; l != NULL; l = l->next)
+ {
+ struct_member = (DIStructMember *) l->data;
+ visit_type (parser,
+ struct_member->type,
+ base,
+ recursion_level + 1);
+ g_string_append (s, struct_member->type->signature);
+ }
+ g_string_append_c (s, ')');
+ }
+ else if (base->type == DI_BASE_TYPE_DYNAMIC_STRUCT)
+ {
+ GList *l;
+ DIDynamicStruct *dynamic_struct;
+ DIStructMember *struct_member;
+
+ dynamic_struct = (DIDynamicStruct *) base;
+ for (l = dynamic_struct->members; l != NULL; l = l->next)
+ {
+ struct_member = (DIStructMember *) l->data;
+ visit_type (parser,
+ struct_member->type,
+ base,
+ recursion_level + 1);
+ }
+ /* dynamic structs are always marshalled as a (string, dict:string->variant) structure */
+ g_string_append (s, "(sa{sv})");
+ }
+ else if (base->type == DI_BASE_TYPE_ENUM)
+ {
+ /* we use uint32 for enums */
+ g_string_append_c (s, 'u');
+ }
+ else
+ {
+ parser->errors = g_list_append (parser->errors,
+ g_strdup_printf ("%s:%d: error: expected a struct or enum for %s "
+ "but got a %s",
+ referenced_in->decl_filename,
+ referenced_in->decl_lineno,
+ type->fully_qualified_name,
+ di_base_type_to_string (base->type)));
+ }
+ }
+
+ type->signature = g_string_free (s, FALSE);
+#if 0
+ g_debug ("signature %s for %s %s %s",
+ type->signature,
+ type->name,
+ di_base_type_to_string (referenced_in->type),
+ referenced_in->fully_qualified_name);
+#endif
+}
+
+static void
+check_types (DIParser *parser)
+{
+ GHashTableIter iter;
+ const gchar *fqn;
+ DIBase *base;
+ GList *l;
+ GString *s1;
+ GString *s2;
+ DIArg *arg;
+ DIMethod *method;
+ DISignal *signal;
+ DIProperty *property;
+ DIStruct *struct_;
+ DIDynamicStruct *dynamic_struct;
+ DIStructMember *struct_member;
+
+ /* here we ensure that all the user supplied types referenced actually exists. We also
+ * compute the signature field for each of them.
+ */
+
+ g_hash_table_iter_init (&iter, parser->symbol_table);
+ while (g_hash_table_iter_next (&iter, (gpointer) &fqn, (gpointer) &base))
+ {
+ switch (base->type)
+ {
+ case DI_BASE_TYPE_METHOD:
+ s1 = g_string_new (NULL);
+ s2 = g_string_new (NULL);
+ method = (DIMethod *) base;
+ for (l = method->args; l != NULL; l = l->next)
+ {
+ arg = l->data;
+ visit_type (parser, arg->type, base, 0);
+ if (arg->direction == DI_ARG_DIRECTION_IN)
+ g_string_append (s1, arg->type->signature);
+ else
+ g_string_append (s2, arg->type->signature);
+ }
+ method->in_signature = g_string_free (s1, FALSE);
+ method->out_signature = g_string_free (s2, FALSE);
+ break;
+
+ case DI_BASE_TYPE_SIGNAL:
+ s1 = g_string_new (NULL);
+ signal = (DISignal *) base;
+ for (l = signal->args; l != NULL; l = l->next)
+ {
+ arg = l->data;
+ visit_type (parser, arg->type, base, 0);
+ g_string_append (s1, arg->type->signature);
+ }
+ signal->signature = g_string_free (s1, FALSE);
+ break;
+
+ case DI_BASE_TYPE_PROPERTY:
+ property = (DIProperty *) base;
+ visit_type (parser, property->type, base, 0);
+ property->signature = g_strdup (property->type->signature);
+ break;
+
+ case DI_BASE_TYPE_STRUCT:
+ s1 = g_string_new ("(");
+ struct_ = (DIStruct *) base;
+ for (l = struct_->members; l != NULL; l = l->next)
+ {
+ struct_member = (DIStructMember *) l->data;
+ visit_type (parser, struct_member->type, base, 0);
+ g_string_append (s1, struct_member->type->signature);
+ }
+ g_string_append_c (s1, ')');
+ struct_->signature = g_string_free (s1, FALSE);
+ break;
+
+ case DI_BASE_TYPE_DYNAMIC_STRUCT:
+ dynamic_struct = (DIDynamicStruct *) base;
+ for (l = dynamic_struct->members; l != NULL; l = l->next)
+ {
+ struct_member = (DIStructMember *) l->data;
+ visit_type (parser, struct_member->type, base, 0);
+ }
+ break;
+
+ default:
+ /* ignore symbols that don't correspond to signatures */
+ break;
+ }
+ }
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+DIParser *
+di_parser_new (const gchar *path)
+{
+ DIParser *parser;
+ gchar *s;
+
+ parser = g_new0 (DIParser, 1);
+
+ yyin = fopen (path, "rt");
+ if (yyin == NULL)
+ {
+ s = g_strdup_printf ("Error opening file %s: %m", path);
+ parser->errors = g_list_append (parser->errors, s);
+ goto out;
+ }
+
+ parser->path_to_current_file = g_strdup (path);
+
+ /* this covers lexical and syntactical analysis */
+ yyparse (parser);
+ fclose (yyin);
+
+ /* bail if we have errors at this point */
+ if (parser->errors != NULL)
+ goto out;
+
+ /* Now for semantical analysis... */
+
+ /* First build the symbol table - this is basically a mapping from the fully
+ * qualified name into a DIBase pointer. It contain the following objects
+ *
+ * o namespaces
+ * o interfaces
+ * - methods
+ * - signals
+ * - properties
+ * o structs
+ * - struct members
+ * o dynamic structs
+ * - struct members
+ * o enumerations
+ * - enum members
+ * o error domains
+ * - error members
+ *
+ * with user API being di_parser_lookup_symbol(). The user can then safely
+ * cast to the appropriate type by inspecting the type of the returned object.
+ *
+ * While doing this, also compute fully-qualified names and output errors
+ * if there are collisions.
+ */
+ build_symbol_table (parser);
+
+ /* bail if we have errors at this point */
+ if (parser->errors != NULL)
+ goto out;
+
+ /* With the symbol table in place, we can resolve and check types and
+ * also compute the D-Bus signature of all types, structs, methods,
+ * signals and properties.
+ */
+ check_types (parser);
+
+ out:
+ return parser;
+}
+
+GList *
+di_parser_get_namespaces (DIParser *parser)
+{
+ return parser->namespaces;
+}
+
+GList *
+di_parser_get_warnings (DIParser *parser)
+{
+ return parser->warnings;
+}
+
+GList *
+di_parser_get_errors (DIParser *parser)
+{
+ return parser->errors;
+}
+
+void
+di_parser_free (DIParser *parser)
+{
+ /* TODO */
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+DINamespace *
+di_parser_lookup_namespace (DIParser *parser,
+ const gchar *name)
+{
+ GList *l;
+ for (l = parser->namespaces; l != NULL; l = l->next)
+ {
+ DINamespace *i = l->data;
+ if (g_strcmp0 (i->name, name) == 0)
+ return i;
+ }
+ return NULL;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+DIInterface *
+di_namespace_lookup_interface (DINamespace *namespace,
+ const gchar *name)
+{
+ GList *l;
+ for (l = namespace->interfaces; l != NULL; l = l->next)
+ {
+ DIInterface *interface = l->data;
+ if (g_strcmp0 (interface->name, name) == 0)
+ return interface;
+ }
+ return NULL;
+}
+
+DIStruct *
+di_namespace_lookup_struct (DINamespace *namespace,
+ const gchar *name)
+{
+ GList *l;
+ for (l = namespace->structs; l != NULL; l = l->next)
+ {
+ DIStruct *struct_ = l->data;
+ if (g_strcmp0 (struct_->name, name) == 0)
+ return struct_;
+ }
+ return NULL;
+}
+
+DIDynamicStruct *
+di_namespace_lookup_dynamic_struct (DINamespace *namespace,
+ const gchar *name)
+{
+ GList *l;
+ for (l = namespace->dynamic_structs; l != NULL; l = l->next)
+ {
+ DIDynamicStruct *dynamic_struct = l->data;
+ if (g_strcmp0 (dynamic_struct->name, name) == 0)
+ return dynamic_struct;
+ }
+ return NULL;
+}
+
+DIEnum *
+di_namespace_lookup_enum (DINamespace *namespace,
+ const gchar *name)
+{
+ GList *l;
+ for (l = namespace->enums; l != NULL; l = l->next)
+ {
+ DIEnum *enum_ = l->data;
+ if (g_strcmp0 (enum_->name, name) == 0)
+ return enum_;
+ }
+ return NULL;
+}
+
+DIErrorDomain *
+di_namespace_lookup_error_domain (DINamespace *namespace,
+ const gchar *name)
+{
+ GList *l;
+ for (l = namespace->error_domains; l != NULL; l = l->next)
+ {
+ DIErrorDomain *error_domain = l->data;
+ if (g_strcmp0 (error_domain->name, name) == 0)
+ return error_domain;
+ }
+ return NULL;
+}
+
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+DIMethod *
+di_interface_lookup_method (DIInterface *interface,
+ const gchar *name)
+{
+ GList *l;
+ for (l = interface->methods; l != NULL; l = l->next)
+ {
+ DIMethod *method = l->data;
+ if (g_strcmp0 (method->name, name) == 0)
+ return method;
+ }
+ return NULL;
+}
+
+DISignal *
+di_interface_lookup_signal (DIInterface *interface,
+ const gchar *name)
+{
+ GList *l;
+ for (l = interface->signals; l != NULL; l = l->next)
+ {
+ DISignal *signal = l->data;
+ if (g_strcmp0 (signal->name, name) == 0)
+ return signal;
+ }
+ return NULL;
+}
+
+DIProperty *
+di_interface_lookup_property (DIInterface *interface,
+ const gchar *name)
+{
+ GList *l;
+ for (l = interface->properties; l != NULL; l = l->next)
+ {
+ DIProperty *property = l->data;
+ if (g_strcmp0 (property->name, name) == 0)
+ return property;
+ }
+ return NULL;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
diff --git a/src/dbusidl.h b/src/dbusidl.h
new file mode 100644
index 0000000..d1e45b2
--- /dev/null
+++ b/src/dbusidl.h
@@ -0,0 +1,234 @@
+/* Copyright (C) 2009 David Zeuthen <zeuthen@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <zeuthen@gmail.com>
+ */
+
+#include <glib.h>
+
+#ifndef __DBUS_IDL_H
+#define __DBUS_IDL_H
+
+#ifndef DBUS_IDL_I_UNDERSTAND_THAT_API_IS_UNSTABLE
+#error "The dbus-idl API is unstable You need to define DBUS_IDL_I_UNDERSTAND_THAT_API_IS_UNSTABLE to use this API."
+#endif
+
+G_BEGIN_DECLS
+
+typedef enum
+{
+ DI_BASE_TYPE_ANNOTATION,
+ DI_BASE_TYPE_TYPE,
+ DI_BASE_TYPE_ARG,
+ DI_BASE_TYPE_METHOD,
+ DI_BASE_TYPE_SIGNAL,
+ DI_BASE_TYPE_PROPERTY,
+ DI_BASE_TYPE_INTERFACE,
+ DI_BASE_TYPE_STRUCT_MEMBER,
+ DI_BASE_TYPE_STRUCT,
+ DI_BASE_TYPE_DYNAMIC_STRUCT,
+ DI_BASE_TYPE_ENUM_MEMBER,
+ DI_BASE_TYPE_ENUM,
+ DI_BASE_TYPE_ERROR_MEMBER,
+ DI_BASE_TYPE_ERROR_DOMAIN,
+ DI_BASE_TYPE_NAMESPACE,
+} DIBaseType;
+
+typedef enum
+{
+ DI_PROPERTY_FLAGS_NONE = 0,
+ DI_PROPERTY_FLAGS_READABLE = (1<<0),
+ DI_PROPERTY_FLAGS_WRITABLE = (1<<1),
+} DIPropertyFlags;
+
+typedef enum
+{
+ DI_ARG_DIRECTION_NONE,
+ DI_ARG_DIRECTION_IN,
+ DI_ARG_DIRECTION_OUT,
+} DIArgDirection;
+
+/* Parser object */
+typedef struct _DIParser DIParser;
+
+/* The base class for all objects */
+typedef struct _DIBase DIBase;
+
+/* These objects are all based on DIBase */
+typedef struct _DIAnnotation DIAnnotation;
+typedef struct _DIType DIType;
+typedef struct _DIArg DIArg;
+typedef struct _DIMethod DIMethod;
+typedef struct _DISignal DISignal;
+typedef struct _DIProperty DIProperty;
+typedef struct _DIInterface DIInterface;
+typedef struct _DIStructMember DIStructMember;
+typedef struct _DIStruct DIStruct;
+typedef struct _DIDynamicStruct DIDynamicStruct;
+typedef struct _DIEnumMember DIEnumMember;
+typedef struct _DIEnum DIEnum;
+typedef struct _DIErrorMember DIErrorMember;
+typedef struct _DIErrorDomain DIErrorDomain;
+typedef struct _DINamespace DINamespace;
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+DIBaseType di_base_get_type (DIBase *base);
+const gchar *di_base_get_decl_path (DIBase *base);
+guint di_base_get_decl_lineno (DIBase *base);
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+const gchar *di_type_get_name (DIType *type);
+const gchar *di_type_get_signature (DIType *type);
+gint di_type_get_typecode (DIType *type);
+GList *di_type_get_inner_types (DIType *type);
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+const gchar *di_arg_get_name (DIArg *arg);
+DIType *di_arg_get_type (DIArg *arg);
+DIArgDirection di_arg_get_direction (DIArg *arg);
+GList *di_arg_get_annotations (DIArg *arg);
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+const gchar *di_method_get_name (DIMethod *method);
+const gchar *di_method_get_fully_qualified_name (DIMethod *method);
+GList *di_method_get_args (DIMethod *method);
+GList *di_method_get_annotations (DIMethod *method);
+const gchar *di_method_get_in_signature (DIMethod *method);
+const gchar *di_method_get_out_signature (DIMethod *method);
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+const gchar *di_signal_get_name (DISignal *signal);
+const gchar *di_signal_get_fully_qualified_name (DISignal *signal);
+GList *di_signal_get_args (DISignal *signal);
+GList *di_signal_get_annotations (DISignal *signal);
+const gchar *di_signal_get_signature (DISignal *signal);
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+const gchar *di_property_get_name (DIProperty *property);
+const gchar *di_property_get_fully_qualified_name (DIProperty *property);
+DIType *di_property_get_type (DIProperty *property);
+GList *di_property_get_annotations (DIProperty *property);
+const gchar *di_property_get_signature (DIProperty *property);
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+const gchar *di_interface_get_name (DIInterface *interface);
+const gchar *di_interface_get_fully_qualified_name (DIInterface *interface);
+GList *di_interface_get_methods (DIInterface *interface);
+GList *di_interface_get_signals (DIInterface *interface);
+GList *di_interface_get_properties (DIInterface *interface);
+GList *di_interface_get_annotations (DIInterface *interface);
+DIMethod *di_interface_lookup_method (DIInterface *interface,
+ const gchar *name);
+DISignal *di_interface_lookup_signal (DIInterface *interface,
+ const gchar *name);
+DIProperty *di_interface_lookup_property (DIInterface *interface,
+ const gchar *name);
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+const gchar *di_struct_member_get_name (DIStructMember *struct_member);
+DIType *di_struct_member_get_type (DIStructMember *struct_member);
+GList *di_struct_member_get_annotations (DIStructMember *struct_member);
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+const gchar *di_struct_get_name (DIStruct *struct_);
+const gchar *di_struct_get_fully_qualified_name (DIStruct *struct_);
+GList *di_struct_get_members (DIStruct *struct_);
+GList *di_struct_get_annotations (DIStruct *struct_);
+const gchar *di_struct_get_signature (DIStruct *struct_);
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+const gchar *di_dynamic_struct_get_name (DIDynamicStruct *dynamic_struct);
+const gchar *di_dynamic_get_fully_qualified_name (DIDynamicStruct *dynamic_struct);
+GList *di_dynamic_struct_get_members (DIDynamicStruct *dynamic_struct);
+GList *di_dynamic_struct_get_annotations (DIDynamicStruct *dynamic_struct);
+const gchar *di_dynamic_struct_get_signature (DIDynamicStruct *dynamic_struct);
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+const gchar *di_enum_member_get_name (DIEnumMember *enum_member);
+const gchar *di_enum_member_get_fully_qualified_name (DIEnumMember *enum_member);
+guint di_enum_member_get_value (DIEnumMember *enum_member);
+gboolean di_enum_member_get_unset (DIEnumMember *enum_member);
+GList *di_enum_member_get_annotations (DIEnumMember *enum_member);
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+const gchar *di_enum_get_name (DIEnum *enum_);
+const gchar *di_enum_get_fully_qualified_name (DIEnum *enum_);
+GList *di_enum_get_members (DIEnum *enum_);
+GList *di_enum_get_annotations (DIEnum *enum_);
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+const gchar *di_error_member_get_name (DIErrorMember *error_member);
+const gchar *di_error_member_get_fully_qualified_name (DIErrorMember *error_member);
+GList *di_error_member_get_annotations (DIErrorMember *error_member);
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+const gchar *di_error_domain_get_name (DIErrorDomain *error_domain);
+const gchar *di_error_domain_get_fully_qualified_name (DIErrorDomain *error_domain);
+GList *di_error_domain_get_members (DIErrorDomain *error_domain);
+GList *di_error_domain_get_annotations (DIErrorDomain *error_domain);
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+const gchar *di_namespace_get_name (DINamespace *namespace);
+GList *di_namespace_get_interfaces (DINamespace *namespace);
+GList *di_namespace_get_structs (DINamespace *namespace);
+GList *di_namespace_get_dynamic_structs (DINamespace *namespace);
+GList *di_namespace_get_enums (DINamespace *namespace);
+GList *di_namespace_get_error_domains (DINamespace *namespace);
+GList *di_namespace_get_annotations (DINamespace *namespace);
+DIInterface *di_namespace_lookup_interface (DINamespace *namespace,
+ const gchar *name);
+DIStruct *di_namespace_lookup_struct (DINamespace *namespace,
+ const gchar *name);
+DIDynamicStruct *di_namespace_lookup_dynamic_struct (DINamespace *namespace,
+ const gchar *name);
+DIEnum *di_namespace_lookup_enum (DINamespace *namespace,
+ const gchar *name);
+DIErrorDomain *di_namespace_lookup_error_domain (DINamespace *namespace,
+ const gchar *name);
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+DIParser *di_parser_new (const gchar *path);
+GList *di_parser_get_namespaces (DIParser *parser);
+DINamespace *di_parser_lookup_namespace (DIParser *parser,
+ const gchar *name);
+DIBase *di_parser_lookup_symbol (DIParser *parser,
+ const gchar *fully_qualified_name);
+GList *di_parser_get_warnings (DIParser *parser);
+GList *di_parser_get_errors (DIParser *parser);
+void di_parser_free (DIParser *parser);
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+G_END_DECLS
+
+#endif /* __DBUS_IDL_H */
diff --git a/src/dbusidlprivate.h b/src/dbusidlprivate.h
new file mode 100644
index 0000000..4f0b9ec
--- /dev/null
+++ b/src/dbusidlprivate.h
@@ -0,0 +1,319 @@
+/* Copyright (C) 2009 David Zeuthen <zeuthen@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <zeuthen@gmail.com>
+ */
+
+#include "dbusidl.h"
+
+#ifndef __DBUS_IDL_PRIVATE_H
+#define __DBUS_IDL_PRIVATE_H
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+struct _DIBase
+{
+ DIBaseType type;
+ gchar *decl_filename;
+ guint decl_lineno;
+};
+
+struct _DIAnnotation
+{
+ DIBase base;
+ gchar *name;
+ gchar *value;
+};
+
+struct _DIType
+{
+ DIBase base;
+ gchar *name;
+ GList *inner_types;
+
+ gchar *signature;
+
+ /* only set if type is a user supplied type */
+ gchar *fully_qualified_name;
+};
+
+struct _DIArg
+{
+ DIBase base;
+ gchar *name;
+ DIType *type;
+ DIArgDirection direction;
+ GList *annotations;
+};
+
+struct _DIMethod
+{
+ DIBase base;
+ gchar *name;
+ gchar *fully_qualified_name;
+ GList *args;
+ GList *annotations;
+
+ gchar *in_signature;
+ gchar *out_signature;
+};
+
+struct _DISignal
+{
+ DIBase base;
+ gchar *name;
+ gchar *fully_qualified_name;
+ GList *args;
+ GList *annotations;
+
+ gchar *signature;
+};
+
+struct _DIProperty
+{
+ DIBase base;
+ gchar *name;
+ gchar *fully_qualified_name;
+ DIType *type;
+ DIPropertyFlags flags;
+ GList *annotations;
+
+ gchar *signature;
+};
+
+struct _DIInterface
+{
+ DIBase base;
+ gchar *name;
+ gchar *fully_qualified_name;
+ GList *methods;
+ GList *signals;
+ GList *properties;
+ GList *annotations;
+};
+
+struct _DIStructMember
+{
+ DIBase base;
+ gchar *name;
+ DIType *type;
+ GList *annotations;
+};
+
+struct _DIStruct
+{
+ DIBase base;
+ gchar *name;
+ gchar *fully_qualified_name;
+ GList *members;
+ GList *annotations;
+
+ gchar *signature;
+};
+
+struct _DIDynamicStruct
+{
+ DIBase base;
+ gchar *name;
+ gchar *fully_qualified_name;
+ GList *members;
+ GList *annotations;
+};
+
+struct _DIEnumMember
+{
+ DIBase base;
+ gchar *name;
+ gchar *fully_qualified_name;
+ guint32 value;
+ gboolean unset;
+ GList *annotations;
+};
+
+struct _DIEnum
+{
+ DIBase base;
+ gchar *name;
+ gchar *fully_qualified_name;
+ GList *members;
+ GList *annotations;
+};
+
+struct _DIErrorMember
+{
+ DIBase base;
+ gchar *name;
+ gchar *fully_qualified_name;
+ GList *annotations;
+};
+
+struct _DIErrorDomain
+{
+ DIBase base;
+ gchar *name;
+ gchar *fully_qualified_name;
+ GList *members;
+ GList *annotations;
+};
+
+struct _DINamespace
+{
+ DIBase base;
+ gchar *name;
+ GList *interfaces;
+ GList *structs;
+ GList *dynamic_structs;
+ GList *enums;
+ GList *error_domains;
+
+ GList *annotations;
+};
+
+struct _DIParser
+{
+ gchar *path_to_current_file;
+ GList *namespaces;
+ GList *warnings;
+ GList *errors;
+
+ /* hash from fully-qualified name to DIBase* */
+ GHashTable *symbol_table;
+};
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+DIAnnotation *di_annotation_new (gchar *decl_filename,
+ guint decl_lineno,
+ gchar *name,
+ gchar *value);
+DIType *di_type_new (gchar *decl_filename,
+ guint decl_lineno,
+ gchar *name,
+ GList *inner_types);
+DIArg *di_arg_new (gchar *decl_filename,
+ guint decl_lineno,
+ gchar *name,
+ DIType *type,
+ DIArgDirection direction,
+ GList *annotations);
+DIMethod *di_method_new (gchar *decl_filename,
+ guint decl_lineno,
+ gchar *name,
+ GList *args,
+ GList *annotations);
+DISignal *di_signal_new (gchar *decl_filename,
+ guint decl_lineno,
+ gchar *name,
+ GList *args,
+ GList *annotations);
+DIProperty *di_property_new (gchar *decl_filename,
+ guint decl_lineno,
+ gchar *name,
+ DIType *type,
+ DIPropertyFlags flags,
+ GList *annotations);
+DIInterface *di_interface_new (gchar *decl_filename,
+ guint decl_lineno,
+ gchar *name,
+ GList *methods,
+ GList *signals,
+ GList *properties,
+ GList *annotations);
+DIStructMember *di_struct_member_new (gchar *decl_filename,
+ guint decl_lineno,
+ gchar *name,
+ DIType *type,
+ GList *annotations);
+DIStruct *di_struct_new (gchar *decl_filename,
+ guint decl_lineno,
+ gchar *name,
+ GList *members,
+ GList *annotations);
+DIDynamicStruct *di_dynamic_struct_new (gchar *decl_filename,
+ guint decl_lineno,
+ gchar *name,
+ GList *members,
+ GList *annotations);
+DIEnumMember *di_enum_member_new (gchar *decl_filename,
+ guint decl_lineno,
+ gchar *name,
+ guint32 value,
+ gboolean unset,
+ GList *annotations);
+DIEnum *di_enum_new (gchar *decl_filename,
+ guint decl_lineno,
+ gchar *name,
+ GList *members,
+ GList *annotations);
+DIErrorMember *di_error_member_new (gchar *decl_filename,
+ guint decl_lineno,
+ gchar *name,
+ GList *annotations);
+DIErrorDomain *di_error_domain_new (gchar *decl_filename,
+ guint decl_lineno,
+ gchar *name,
+ GList *members,
+ GList *annotations);
+DINamespace *di_namespace_new (gchar *decl_filename,
+ guint decl_lineno,
+ gchar *name,
+ GList *interfaces,
+ GList *structs,
+ GList *dynamic_structs,
+ GList *enums,
+ GList *error_domains,
+ GList *annotations);
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+void di_annotation_free (DIAnnotation *annotation);
+void di_type_free (DIType *type);
+void di_arg_free (DIArg *arg);
+void di_signal_free (DISignal *signal);
+void di_method_free (DIMethod *method);
+void di_property_free (DIProperty *property);
+void di_interface_free (DIInterface *interface);
+void di_struct_member_free (DIStructMember *struct_member);
+void di_struct_free (DIStruct *struct_);
+void di_dynamic_struct_free (DIDynamicStruct *dynamic_struct);
+void di_enum_member_free (DIEnumMember *enum_member);
+void di_enum_free (DIEnum *enum_);
+void di_error_member_free (DIErrorMember *error_member);
+void di_error_domain_free (DIErrorDomain *error_domain);
+void di_namespace_free (DINamespace *namespace);
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+void di_annotation_print (DIAnnotation *annotation, guint indent);
+void di_type_print (DIType *type, guint indent);
+void di_arg_print (DIArg *arg, guint indent);
+void di_signal_print (DISignal *signal, guint indent);
+void di_method_print (DIMethod *method, guint indent);
+void di_property_print (DIProperty *property, guint indent);
+void di_interface_print (DIInterface *interface, guint indent);
+void di_struct_member_print (DIStructMember *struct_member, guint indent);
+void di_struct_print (DIStruct *struct_, guint indent);
+void di_dynamic_struct_print (DIDynamicStruct *struct_, guint indent);
+void di_enum_member_print (DIEnumMember *enum_member, guint indent);
+void di_enum_print (DIEnum *enum_, guint indent);
+void di_error_member_print (DIErrorMember *error_member, guint indent);
+void di_error_domain_print (DIErrorDomain *error_domain, guint indent);
+void di_namespace_print (DINamespace *namespace, guint indent);
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+#endif /* __DBUS_IDL_PRIVATE_H */
diff --git a/src/main.c b/src/idl.h
index 3a1e217..0d7a07e 100644
--- a/src/main.c
+++ b/src/idl.h
@@ -1,5 +1,3 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-
/* Copyright (C) 2009 David Zeuthen <zeuthen@gmail.com>
*
* This library is free software; you can redistribute it and/or
@@ -17,16 +15,23 @@
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
- * Author: David Zeuthen <davidz@redhat.com>
+ * Author: David Zeuthen <zeuthen@gmail.com>
*/
-#include "config.h"
+#ifndef __IDL_H
+#define __IDL_H
+#include <stdio.h>
#include <glib.h>
-int
-main (int argc, char *argv[])
-{
- printf ("Hello World!\n");
- return 0;
-}
+#include "dbusidl.h"
+#include "dbusidlprivate.h"
+
+extern FILE *yyin;
+extern int yyparse (DIParser *parser);
+extern int yydebug;
+extern int yy_flex_debug;
+
+extern DINamespace *yynamespace;
+
+#endif /* __IDL_H */
diff --git a/src/idllexer.l b/src/idllexer.l
new file mode 100644
index 0000000..e54c7a7
--- /dev/null
+++ b/src/idllexer.l
@@ -0,0 +1,156 @@
+/* Copyright (C) 2009 David Zeuthen <zeuthen@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <zeuthen@gmail.com>
+ */
+
+%{
+#define YYDEBUG 1
+
+#include <stdio.h>
+#include <glib.h>
+#include "libdbus_idl_1_la-idlparser.h"
+
+static void parse_comment (void);
+static void parse_eol_comment (void);
+static gchar *unescape_string (const gchar *str);
+%}
+
+%option nounput
+
+stringtext ([^\\\"])|(\\.)
+
+%%
+
+"//" { parse_eol_comment (); yylineno++; }
+"/*" { parse_comment (); }
+"namespace" {return NAMESPACE;}
+"interface" {return INTERFACE;}
+"signal" {return SIGNAL;}
+"property" {return PROPERTY;}
+"struct" {return STRUCT;}
+"dynamic_struct" {return DYNAMIC_STRUCT;}
+"enum" {return ENUM;}
+"error_domain" {return ERROR_DOMAIN;}
+"in" {return IN;}
+"out" {return OUT;}
+"readonly" {return READONLY;}
+"writeonly" {return WRITEONLY;}
+"byte" {return TYPE_BYTE;}
+"int16" {return TYPE_INT16;}
+"uint16" {return TYPE_UINT16;}
+"int32" {return TYPE_INT32;}
+"uint32" {return TYPE_UINT32;}
+"int64" {return TYPE_INT64;}
+"uint64" {return TYPE_UINT64;}
+"double" {return TYPE_DOUBLE;}
+"boolean" {return TYPE_BOOLEAN;}
+"string" {return TYPE_STRING;}
+"objpath" {return TYPE_OBJECT_PATH;}
+"signature" {return TYPE_SIGNATURE;}
+"array" {return TYPE_ARRAY;}
+"dict" {return TYPE_DICT;}
+"variant" {return TYPE_VARIANT;}
+"." {return DOT;}
+"," {return COMMA;}
+";" {return SEMICOLON;}
+[a-zA-Z_][a-zA-Z0-9_]* {yylval.str = g_strdup (yytext); return IDENTIFIER;}
+[0-9][0-9]* {yylval.number = atoi (yytext); return NUMBER;}
+"=" {return EQUAL;}
+"+" {return PLUS;}
+"-" {return MINUS;}
+"*" {return STAR;}
+"/" {return SLASH;}
+"&" {return AMPERSAND;}
+"|" {return PIPE;}
+"%" {return PERCENT;}
+"{" {return OBRACE;}
+"}" {return EBRACE;}
+"(" {return OPAREN;}
+")" {return EPAREN;}
+"<" {return OBRACKET;}
+">" {return EBRACKET;}
+"@" {return ATSIGN;}
+"\""{stringtext}*"\"" {yylval.str = unescape_string (yytext) ; return STRING; }
+[\r\n] { yylineno++; /* ignore end of line */ }
+[ \t]+ { /* ignore whitespace */ }
+. {return UNKNOWN;}
+%%
+
+
+static void
+parse_comment (void)
+{
+ GString *comment;
+ int c1, c2;
+
+ c1 = input();
+ c2 = input();
+
+ comment = g_string_new ("");
+
+ while (c2 != EOF && (c1 != '*' || c2 != '/'))
+ {
+ g_string_append_c (comment, c1);
+
+ if (c1 == '\n')
+ yylineno++;
+
+ c1 = c2;
+ c2 = input();
+ }
+ /* TODO: use comment */
+ g_string_free (comment, TRUE);
+}
+
+
+static void
+parse_eol_comment (void)
+{
+ GString *comment;
+ int c;
+
+ c = input();
+ comment = g_string_new ("");
+
+ while (c != EOF && c != '\r' && c != '\n')
+ {
+ g_string_append_c (comment, c);
+ c = input ();
+ }
+ /* TODO: use comment */
+ g_string_free (comment, TRUE);
+}
+
+static gchar *
+unescape_string (const gchar *str)
+{
+ gchar *ret;
+ gchar *s;
+
+ ret = g_strdup (str + 1);
+ if (strlen (ret) == 0)
+ goto out;
+ ret[strlen (ret) - 1] = '\0';
+
+ s = ret;
+ ret = g_strcompress (ret);
+ g_free (s);
+
+out:
+ return ret;
+}
diff --git a/src/idlparser.y b/src/idlparser.y
new file mode 100644
index 0000000..e141575
--- /dev/null
+++ b/src/idlparser.y
@@ -0,0 +1,788 @@
+/* Copyright (C) 2009 David Zeuthen <zeuthen@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <zeuthen@gmail.com>
+ */
+
+%{
+#define YYDEBUG 1
+
+#include <stdio.h>
+#include <string.h>
+#include "idl.h"
+#include "dbusidl.h"
+
+int yylex (DIParser *parser);
+int yywrap (void);
+void yyerror (DIParser *parser, char const *str);
+
+extern int yylineno;
+
+void
+yyerror (DIParser *parser, const char *str)
+{
+ parser->errors = g_list_append (parser->errors,
+ g_strdup_printf ("%s:%d: %s",
+ parser->path_to_current_file,
+ yylineno,
+ str));
+}
+
+int yywrap (void)
+{
+ return 1;
+}
+
+%}
+
+%parse-param { DIParser* parser }
+%lex-param { DIParser* parser }
+
+%error-verbose
+%union {
+ gchar *str;
+ guint32 number;
+ gint direction;
+ struct _DIType *type;
+ struct _DIArg *arg;
+ struct _DIMethod *method;
+ struct _DISignal *signal;
+ struct _DIInterface *interface;
+ struct _DIProperty *property;
+ gint property_flags;
+ struct _GList *arg_list;
+ struct _DIStruct *struct_;
+ struct _DIDynamicStruct *dynamic_struct;
+ struct _DIStructMember *struct_member;
+ struct _GList *struct_body;
+ struct _DIEnum *enum_;
+ struct _DIEnumMember *enum_member;
+ struct _GList *enum_body;
+ struct _DIErrorDomain *error_domain;
+ struct _DIErrorMember *error_member;
+ struct _GList *error_body;
+ struct
+ {
+ struct _GList *methods;
+ struct _GList *signals;
+ struct _GList *properties;
+ } iface_body;
+ struct
+ {
+ struct _GList *interfaces;
+ struct _GList *structs;
+ struct _GList *dynamic_structs;
+ struct _GList *enums;
+ struct _GList *error_domains;
+ } ns_body;
+ struct _GList *annotation_list;
+ struct _DIAnnotation *annotation;
+}
+
+%type <number> numberexpr
+
+%type <annotation_list> annotation_list
+%type <annotation> annotation
+
+%type <str> dbus_name
+%type <direction> direction
+
+%type <type> type
+%type <type> basic_type
+
+%type <arg> method_arg
+%type <arg> signal_arg
+
+%type <method> method
+%type <signal> signal
+%type <interface> iface_decl
+%type <arg_list> method_arg_list
+%type <arg_list> signal_arg_list
+%type <property> property
+%type <property_flags> property_flags
+
+%type <dynamic_struct> dynamic_struct_decl
+
+%type <struct_> struct_decl
+%type <struct_member> struct_member
+%type <struct_body> struct_body
+
+%type <error_domain> error_domain_decl
+%type <error_member> error_member
+%type <error_body> error_body
+
+%type <enum_> enum_decl
+%type <enum_member> enum_member
+%type <enum_body> enum_body
+
+%type <iface_body> iface_body
+
+%type <ns_body> ns_decls
+
+%left PIPE
+%left AMPERSAND
+%left PLUS MINUS
+%left STAR SLASH PERCENT
+%left UMINUS /*supplies precedence for unary minus */
+
+%%
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+file:
+ | ns_decl
+ ;
+
+ns_decl
+ : annotation_list NAMESPACE dbus_name OBRACE ns_decls EBRACE SEMICOLON
+ {
+ parser->namespaces = g_list_append (parser->namespaces,
+ di_namespace_new (g_strdup (parser->path_to_current_file),
+ yylineno,
+ $3,
+ $5.interfaces,
+ $5.structs,
+ $5.dynamic_structs,
+ $5.enums,
+ $5.error_domains,
+ $1));
+ $5.interfaces = NULL;
+ $5.dynamic_structs = NULL;
+ $5.structs = NULL;
+ $5.enums = NULL;
+ $5.error_domains = NULL;
+ }
+ ;
+
+ns_decls
+ : iface_decl
+ {
+ $$.interfaces = g_list_append (NULL, $1);
+ $$.dynamic_structs = NULL;
+ $$.structs = NULL;
+ $$.enums = NULL;
+ $$.error_domains = NULL;
+ }
+ | ns_decls iface_decl
+ {
+ $$.interfaces = g_list_append ($1.interfaces, $2);
+ }
+ | struct_decl
+ {
+ $$.interfaces = NULL;
+ $$.structs = g_list_append (NULL, $1);
+ $$.dynamic_structs = NULL;
+ $$.enums = NULL;
+ $$.error_domains = NULL;
+ }
+ | ns_decls struct_decl
+ {
+ $$.structs = g_list_append ($1.structs, $2);
+ }
+ | dynamic_struct_decl
+ {
+ $$.interfaces = NULL;
+ $$.structs = NULL;
+ $$.dynamic_structs = g_list_append (NULL, $1);
+ $$.enums = NULL;
+ $$.error_domains = NULL;
+ }
+ | ns_decls dynamic_struct_decl
+ {
+ $$.dynamic_structs = g_list_append ($1.dynamic_structs, $2);
+ }
+ | enum_decl
+ {
+ $$.interfaces = NULL;
+ $$.structs = NULL;
+ $$.dynamic_structs = NULL;
+ $$.enums = g_list_append (NULL, $1);
+ $$.error_domains = NULL;
+ }
+ | ns_decls enum_decl
+ {
+ $$.enums = g_list_append ($1.enums, $2);
+ }
+ | error_domain_decl
+ {
+ $$.interfaces = NULL;
+ $$.structs = NULL;
+ $$.dynamic_structs = NULL;
+ $$.enums = NULL;
+ $$.error_domains = g_list_append (NULL, $1);
+ }
+ | ns_decls error_domain_decl
+ {
+ $$.error_domains = g_list_append ($1.error_domains, $2);
+ }
+ ;
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+dbus_name
+ : IDENTIFIER
+ {
+ $$ = $1;
+ }
+ | IDENTIFIER DOT dbus_name
+ {
+ $$ = g_strdup_printf ("%s.%s", $1, $3);
+ g_free ($1);
+ g_free ($3);
+ }
+ ;
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+error_domain_decl
+ : annotation_list ERROR_DOMAIN IDENTIFIER OBRACE error_body EBRACE SEMICOLON
+ {
+ $$ = di_error_domain_new (g_strdup (parser->path_to_current_file),
+ yylineno,
+ g_strdup ($3),
+ $5,
+ $1);
+ }
+ ;
+
+error_body
+ : error_member
+ {
+ $$ = g_list_append (NULL, $1);
+ }
+ | error_body COMMA error_member
+ {
+ $$ = g_list_append ($1, $3);
+ }
+ ;
+
+error_member
+ : annotation_list IDENTIFIER
+ {
+ $$ = di_error_member_new (g_strdup (parser->path_to_current_file),
+ yylineno,
+ g_strdup ($2),
+ $1);
+ }
+ ;
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+enum_decl
+ : annotation_list ENUM IDENTIFIER OBRACE enum_body EBRACE SEMICOLON
+ {
+ $$ = di_enum_new (g_strdup (parser->path_to_current_file),
+ yylineno,
+ g_strdup ($3),
+ $5,
+ $1);
+ }
+ ;
+
+enum_body
+ : enum_member
+ {
+ $$ = g_list_append (NULL, $1);
+ }
+ | enum_body COMMA enum_member
+ {
+ $$ = g_list_append ($1, $3);
+ }
+ ;
+
+enum_member
+ : annotation_list IDENTIFIER
+ {
+ $$ = di_enum_member_new (g_strdup (parser->path_to_current_file),
+ yylineno,
+ g_strdup ($2),
+ 0,
+ TRUE,
+ $1);
+ }
+ | annotation_list IDENTIFIER EQUAL numberexpr
+ {
+ $$ = di_enum_member_new (g_strdup (parser->path_to_current_file),
+ yylineno,
+ g_strdup ($2),
+ $4,
+ FALSE,
+ $1);
+ }
+ ;
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+numberexpr
+ : OPAREN numberexpr EPAREN
+ {
+ $$ = $2;
+ }
+ | numberexpr STAR numberexpr
+ {
+ $$ = $1 * $3;
+ }
+ | numberexpr SLASH numberexpr
+ {
+ $$ = $1 / $3;
+ }
+ | numberexpr PERCENT numberexpr
+ {
+ $$ = $1 % $3;
+ }
+ | numberexpr PLUS numberexpr
+ {
+ $$ = $1 + $3;
+ }
+ | numberexpr MINUS numberexpr
+ {
+ $$ = $1 - $3;
+ }
+ | numberexpr AMPERSAND numberexpr
+ {
+ $$ = $1 & $3;
+ }
+ | numberexpr PIPE numberexpr
+ {
+ $$ = $1 | $3;
+ }
+ | numberexpr OBRACKET OBRACKET numberexpr
+ {
+ $$ = $1 << $4;
+ }
+ | numberexpr EBRACKET EBRACKET numberexpr
+ {
+ $$ = $1 >> $4;
+ }
+ | MINUS numberexpr %prec UMINUS
+ {
+ $$ = -$2;
+ }
+ | NUMBER
+ {
+ $$ = $1;
+ }
+ ;
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+dynamic_struct_decl
+ : annotation_list DYNAMIC_STRUCT IDENTIFIER OBRACE struct_body EBRACE SEMICOLON
+ {
+ $$ = di_dynamic_struct_new (g_strdup (parser->path_to_current_file),
+ yylineno,
+ g_strdup ($3),
+ $5,
+ $1);
+ }
+ ;
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+struct_decl
+ : annotation_list STRUCT IDENTIFIER OBRACE struct_body EBRACE SEMICOLON
+ {
+ $$ = di_struct_new (g_strdup (parser->path_to_current_file),
+ yylineno,
+ g_strdup ($3),
+ $5,
+ $1);
+ }
+ ;
+
+struct_body
+ : struct_member
+ {
+ $$ = g_list_append (NULL, $1);
+ }
+ | struct_body struct_member
+ {
+ $$ = g_list_append ($1, $2);
+ }
+ ;
+
+struct_member
+ : annotation_list type IDENTIFIER SEMICOLON
+ {
+ $$ = di_struct_member_new (g_strdup (parser->path_to_current_file),
+ yylineno,
+ g_strdup ($3),
+ $2,
+ $1);
+ }
+ ;
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+iface_decl
+ : annotation_list INTERFACE IDENTIFIER OBRACE iface_body EBRACE SEMICOLON
+ {
+ $$ = di_interface_new (g_strdup (parser->path_to_current_file),
+ yylineno,
+ $3,
+ $5.methods,
+ $5.signals,
+ $5.properties,
+ $1);
+ $5.methods = NULL;
+ $5.signals = NULL;
+ $5.properties = NULL;
+ }
+ ;
+
+iface_body
+ : method
+ {
+ $$.methods = g_list_append (NULL, $1);
+ }
+ | iface_body method
+ {
+ $$.methods = g_list_append ($1.methods, $2);
+ }
+ | signal
+ {
+ $$.signals = g_list_append (NULL, $1);
+ }
+ | iface_body signal
+ {
+ $$.signals = g_list_append ($1.signals, $2);
+ }
+ | property
+ {
+ $$.properties = g_list_append (NULL, $1);
+ }
+ | iface_body property
+ {
+ $$.properties = g_list_append ($1.properties, $2);
+ }
+ ;
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+signal
+ : annotation_list SIGNAL IDENTIFIER OPAREN signal_arg_list EPAREN SEMICOLON
+ {
+ $$ = di_signal_new (g_strdup (parser->path_to_current_file),
+ yylineno,
+ g_strdup ($3),
+ $5,
+ $1);
+ }
+ ;
+
+signal_arg_list
+ :
+ {
+ $$ = NULL;
+ }
+ | signal_arg
+ {
+ $$ = g_list_append (NULL, $1);
+ }
+ | signal_arg_list COMMA signal_arg
+ {
+ $$ = g_list_append ($1, $3);
+ }
+ ;
+
+signal_arg
+ : annotation_list type IDENTIFIER
+ {
+ $$ = di_arg_new (g_strdup (parser->path_to_current_file),
+ yylineno,
+ g_strdup ($3),
+ $2,
+ DI_ARG_DIRECTION_NONE,
+ $1);
+ }
+ ;
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+method
+ : annotation_list IDENTIFIER OPAREN method_arg_list EPAREN SEMICOLON
+ {
+ $$ = di_method_new (g_strdup (parser->path_to_current_file),
+ yylineno,
+ g_strdup ($2),
+ $4,
+ $1);
+ }
+ ;
+
+method_arg_list
+ :
+ {
+ $$ = NULL;
+ }
+ | method_arg
+ {
+ $$ = g_list_append (NULL, $1);
+ }
+ | method_arg_list COMMA method_arg
+ {
+ $$ = g_list_append ($1, $3);
+ }
+ ;
+
+method_arg
+ : annotation_list direction type IDENTIFIER
+ {
+ $$ = di_arg_new (g_strdup (parser->path_to_current_file),
+ yylineno,
+ g_strdup ($4),
+ $3,
+ $2,
+ $1);
+ }
+ ;
+
+direction
+ : IN
+ {
+ $$=DI_ARG_DIRECTION_IN;
+ }
+ | OUT
+ {
+ $$=DI_ARG_DIRECTION_OUT;
+ }
+ ;
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+property
+ : annotation_list property_flags PROPERTY type IDENTIFIER SEMICOLON
+ {
+ $$ = di_property_new (g_strdup (parser->path_to_current_file),
+ yylineno,
+ g_strdup ($5),
+ $4,
+ $2,
+ $1);
+ }
+ ;
+
+property_flags
+ :
+ {
+ $$ = DI_PROPERTY_FLAGS_WRITABLE | DI_PROPERTY_FLAGS_READABLE;
+ }
+ | READONLY
+ {
+ $$ = DI_PROPERTY_FLAGS_READABLE;
+ }
+ | WRITEONLY
+ {
+ $$ = DI_PROPERTY_FLAGS_WRITABLE;
+ }
+ ;
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+annotation_list
+ :
+ {
+ $$ = NULL;
+ }
+ | annotation
+ {
+ $$ = g_list_append (NULL, $1);
+ }
+ | annotation_list annotation
+ {
+ $$ = g_list_append ($1, $2);
+ }
+ ;
+
+annotation
+ : ATSIGN dbus_name
+ {
+ $$ = di_annotation_new (g_strdup (parser->path_to_current_file),
+ yylineno,
+ g_strdup ($2),
+ NULL);
+ }
+ | ATSIGN dbus_name OPAREN STRING EPAREN
+ {
+ $$ = di_annotation_new (g_strdup (parser->path_to_current_file),
+ yylineno,
+ g_strdup ($2),
+ g_strdup ($4));
+ }
+ ;
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+type
+ : basic_type
+ {
+ $$ = $1;
+ }
+ | TYPE_ARRAY OBRACKET type EBRACKET
+ {
+ $$ = di_type_new (g_strdup (parser->path_to_current_file),
+ yylineno,
+ g_strdup ("array"),
+ g_list_append (NULL, $3));
+ }
+ | TYPE_DICT OBRACKET type COMMA type EBRACKET
+ {
+ GList *inner_types;
+ inner_types = g_list_append (NULL, $3);
+ inner_types = g_list_append (inner_types, $5);
+ $$ = di_type_new (g_strdup (parser->path_to_current_file),
+ yylineno,
+ g_strdup ("dict"),
+ inner_types);
+ }
+ ;
+
+basic_type
+ : TYPE_BYTE
+ {
+ $$ = di_type_new (g_strdup (parser->path_to_current_file),
+ yylineno,
+ g_strdup ("byte"),
+ NULL);
+ }
+ | TYPE_INT16
+ {
+ $$ = di_type_new (g_strdup (parser->path_to_current_file),
+ yylineno,
+ g_strdup ("int16"),
+ NULL);
+ }
+ | TYPE_UINT16
+ {
+ $$ = di_type_new (g_strdup (parser->path_to_current_file),
+ yylineno,
+ g_strdup ("uint16"),
+ NULL);
+ }
+ | TYPE_INT32
+ {
+ $$ = di_type_new (g_strdup (parser->path_to_current_file),
+ yylineno,
+ g_strdup ("int32"),
+ NULL);
+ }
+ | TYPE_UINT32
+ {
+ $$ = di_type_new (g_strdup (parser->path_to_current_file),
+ yylineno,
+ g_strdup ("uint32"),
+ NULL);
+ }
+ | TYPE_INT64
+ {
+ $$ = di_type_new (g_strdup (parser->path_to_current_file),
+ yylineno,
+ g_strdup ("int64"),
+ NULL);
+ }
+ | TYPE_UINT64
+ {
+ $$ = di_type_new (g_strdup (parser->path_to_current_file),
+ yylineno,
+ g_strdup ("uint64"),
+ NULL);
+ }
+ | TYPE_DOUBLE
+ {
+ $$ = di_type_new (g_strdup (parser->path_to_current_file),
+ yylineno,
+ g_strdup ("double"),
+ NULL);
+ }
+ | TYPE_BOOLEAN
+ {
+ $$ = di_type_new (g_strdup (parser->path_to_current_file),
+ yylineno,
+ g_strdup ("boolean"),
+ NULL);
+ }
+ | TYPE_STRING
+ {
+ $$ = di_type_new (g_strdup (parser->path_to_current_file),
+ yylineno,
+ g_strdup ("string"),
+ NULL);
+ }
+ | TYPE_OBJECT_PATH
+ {
+ $$ = di_type_new (g_strdup (parser->path_to_current_file),
+ yylineno,
+ g_strdup ("objpath"),
+ NULL);
+ }
+ | TYPE_SIGNATURE
+ {
+ $$ = di_type_new (g_strdup (parser->path_to_current_file),
+ yylineno,
+ g_strdup ("signature"),
+ NULL);
+ }
+ | TYPE_VARIANT
+ {
+ $$ = di_type_new (g_strdup (parser->path_to_current_file),
+ yylineno,
+ g_strdup ("variant"),
+ NULL);
+ }
+ | dbus_name
+ {
+ $$ = di_type_new (g_strdup (parser->path_to_current_file),
+ yylineno,
+ g_strdup ($1),
+ NULL);
+ }
+ ;
+
+// keywords
+%token INTERFACE SIGNAL PROPERTY STRUCT DYNAMIC_STRUCT ENUM FLAGS ERROR_DOMAIN NAMESPACE;
+
+%token IN OUT READONLY WRITEONLY;
+
+%token TYPE_BYTE;
+%token TYPE_INT16;
+%token TYPE_UINT16;
+%token TYPE_INT32;
+%token TYPE_UINT32;
+%token TYPE_INT64;
+%token TYPE_UINT64;
+%token TYPE_DOUBLE;
+%token TYPE_BOOLEAN;
+%token TYPE_STRING;
+%token TYPE_OBJECT_PATH;
+%token TYPE_SIGNATURE;
+%token TYPE_VARIANT;
+
+%token TYPE_ARRAY;
+%token TYPE_DICT;
+
+%token <str> IDENTIFIER;
+%token <number> NUMBER;
+%token <str> STRING;
+
+// braces / parens etc
+%token OBRACE EBRACE OPAREN EPAREN OBRACKET EBRACKET SEMICOLON COMMA DOT EQUAL ATSIGN;
+
+// operators
+%token PLUS MINUS STAR AMPERSAND PIPE PERCENT;
+
+// unknown
+%token UNKNOWN;
diff --git a/src/org.freedesktop.DBus.Idl.Tests1.didl b/src/org.freedesktop.DBus.Idl.Tests1.didl
new file mode 100644
index 0000000..e506fd7
--- /dev/null
+++ b/src/org.freedesktop.DBus.Idl.Tests1.didl
@@ -0,0 +1,116 @@
+// -*- idl -*-
+
+@Version("1.5")
+namespace org.freedesktop.DBus.Idl.Tests1
+{
+ struct Struct1
+ {
+ int32 bar;
+ uint64 baz;
+ variant something;
+ array<variant> lots_of_something;
+ dict<string,variant> property_bag;
+ };
+
+ dynamic_struct Struct2
+ {
+ uint64 a;
+ uint64 b;
+ uint64 c;
+ string d;
+ array<string> stuff;
+ };
+
+ enum Enum1
+ {
+ Foo,
+ Bar,
+ Baz,
+ BigFoo = 1000,
+ BigBar,
+ BigBaz,
+ A = 2000 + 0,
+ B = 2100 - 10,
+ C = -32,
+ D = 1408 / 11,
+ E = 2 * 5,
+ F = 1<<5,
+ G = (1<<5) + 10,
+ H = 1<<5 + 10
+ };
+
+ @Flags
+ enum Enum2
+ {
+ None = 0,
+ AllowReplacement = 1<<0,
+ Replace = 1<<1,
+ Activate = 1<<2
+ };
+
+ struct Point
+ {
+ int32 x;
+ int32 y;
+ };
+
+ struct Pair
+ {
+ int32 first;
+ int32 second;
+ };
+
+ interface Frobnicable
+ {
+ VoidMethod ();
+
+ PrimitiveMethod (in byte a1,
+ in boolean a2,
+ in int16 a3,
+ in uint16 a4,
+ in int32 a5,
+ in uint32 a6,
+ in int64 a7,
+ in uint64 a8,
+ in double a9,
+ in string a10,
+ in objpath a11,
+ in signature a12);
+
+ @NoReply
+ ContainerMethod (in array<int32> a1,
+ in array<string> a2,
+ in array<array<int32>> a3,
+ in dict<int32,int32> a4,
+ in dict<string,dict<array<string>,string>> a5);
+
+ @Deprecated
+ StructsMethod (in Struct1 a1,
+ in array<Struct1> a2,
+ in array<array<Struct1>> a3,
+ in dict<string,Struct1> a4,
+ out Struct2 a5,
+ out array<Struct2> a6,
+ out dict<string,Struct2> a7);
+
+ @Since("1.3")
+ EnumMethod (in Enum1 a1, out Enum2 a2);
+
+ @Deprecated("1.2")
+ signal VoidSignal();
+
+ signal ArgSignal (array<Point> points, array<Pair> pairs);
+
+ property int32 RWProperty;
+ readonly property int32 ROProperty;
+ writeonly property int32 WOProperty;
+
+ property dict<string,array<Point>> ComplexProperty;
+ };
+
+ interface SecondaryProtocol
+ {
+ SecretMethod (in int32 foo);
+ };
+
+};
diff --git a/src/test.c b/src/test.c
new file mode 100644
index 0000000..5408cf8
--- /dev/null
+++ b/src/test.c
@@ -0,0 +1,74 @@
+/* Copyright (C) 2009 David Zeuthen <zeuthen@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <zeuthen@gmail.com>
+ */
+
+#include "config.h"
+
+#include <glib.h>
+
+#include "dbusidl.h"
+
+static gboolean
+pof (const gchar *path)
+{
+ DIParser *parser;
+ gboolean ret;
+ GList *l;
+
+ ret = FALSE;
+
+ parser = di_parser_new (path);
+
+ for (l = di_parser_get_errors (parser); l != NULL; l = l->next)
+ {
+ const gchar *message = l->data;
+ g_printerr ("%s\n", message);
+ }
+
+ for (l = di_parser_get_warnings (parser); l != NULL; l = l->next)
+ {
+ const gchar *message = l->data;
+ g_printerr ("%s\n", message);
+ }
+
+ ret = (di_parser_get_errors (parser) == NULL);
+ if (!ret)
+ goto out;
+
+
+ for (l = di_parser_get_namespaces (parser); l != NULL; l = l->next)
+ {
+ DINamespace *namespace = l->data;
+ di_namespace_print (namespace, 0);
+ }
+
+ out:
+ di_parser_free (parser);
+ return ret;
+}
+
+int
+main (int argc, char *argv[])
+{
+ /* TODO: actually compare di_namespace_print() output and di_parser_get_errors/warnings() with
+ * something
+ */
+ pof ("org.freedesktop.DBus.Idl.Tests1.didl");
+ return 0;
+}