2005-02-17 Colin Walters <walters@verbum.org>
authorColin Walters <walters@verbum.org>
Thu, 17 Feb 2005 21:11:18 +0000 (21:11 +0000)
committerColin Walters <walters@verbum.org>
Thu, 17 Feb 2005 21:11:18 +0000 (21:11 +0000)
* glib/dbus-gparser.c (struct Parser): Add in_annotation boolean.
(parse_node, parse_interface, parse_method, parse_signal)
(parse_property, parse_annotation): Lose if we're currently in an
annotation.
(parse_annotation): New function.
(parser_start_element, parser_end_element): Handle annotation.
(parse_method, parse_interface): Remove support for c_name attribute,
switch to annotations.

* glib/dbus-gidl.h (interface_info_get_binding_names)
(method_info_get_binding_names)
(interface_info_get_binding_name, method_info_get_binding_name)
(interface_info_set_binding_name, method_info_set_binding_name):
Remove.
(interface_info_get_annotations, method_info_get_annotations)
(interface_info_get_annotation, method_info_get_annotation)
(interface_info_add_annotation, method_info_add_annotation):
Prototype.

* glib/dbus-gidl.c (struct InterfaceInfo): Substitute "annotations"
for "bindings".
(struct MethodInfo): Ditto.
Straightfoward conversion of binding methods into annotation methods
as prototyped.

* glib/dbus-glib-tool.c (pretty_print): Print annotations.

* glib/dbus-binding-tool-glib.h (DBUS_GLIB_ANNOTATION_C_SYMBOL): Define.

* glib/dbus-binding-tool-glib.c (gather_marshallers, generate_glue):
Use new annotation API.

* doc/introspect.dtd: Fix a number of DTD syntax errors.  Add
annotation element.

* doc/dbus-specification.xml: Discuss introspection annotations,
include list of well-known annotations.

* test/glib/test-service-glib.xml: Make validate against new DTD.

ChangeLog
doc/dbus-specification.xml
doc/introspect.dtd
glib/dbus-binding-tool-glib.c
glib/dbus-binding-tool-glib.h
glib/dbus-gidl.c
glib/dbus-gidl.h
glib/dbus-glib-tool.c
glib/dbus-gparser.c
test/glib/test-service-glib.xml

index 30decfa..d418aee 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,47 @@
 2005-02-17  Colin Walters  <walters@verbum.org>
+
+       * glib/dbus-gparser.c (struct Parser): Add in_annotation boolean.
+       (parse_node, parse_interface, parse_method, parse_signal)
+       (parse_property, parse_annotation): Lose if we're currently in an
+       annotation.
+       (parse_annotation): New function.
+       (parser_start_element, parser_end_element): Handle annotation.
+       (parse_method, parse_interface): Remove support for c_name attribute,
+       switch to annotations.
+
+       * glib/dbus-gidl.h (interface_info_get_binding_names)
+       (method_info_get_binding_names)
+       (interface_info_get_binding_name, method_info_get_binding_name)
+       (interface_info_set_binding_name, method_info_set_binding_name):
+       Remove.
+       (interface_info_get_annotations, method_info_get_annotations)
+       (interface_info_get_annotation, method_info_get_annotation)
+       (interface_info_add_annotation, method_info_add_annotation):
+       Prototype.
+
+       * glib/dbus-gidl.c (struct InterfaceInfo): Substitute "annotations"
+       for "bindings".
+       (struct MethodInfo): Ditto.
+       Straightfoward conversion of binding methods into annotation methods
+       as prototyped.
+
+       * glib/dbus-glib-tool.c (pretty_print): Print annotations.
+
+       * glib/dbus-binding-tool-glib.h (DBUS_GLIB_ANNOTATION_C_SYMBOL): Define.
+
+       * glib/dbus-binding-tool-glib.c (gather_marshallers, generate_glue):
+       Use new annotation API.
+
+       * doc/introspect.dtd: Fix a number of DTD syntax errors.  Add
+       annotation element.
        
+       * doc/dbus-specification.xml: Discuss introspection annotations,
+       include list of well-known annotations.
+
+       * test/glib/test-service-glib.xml: Make validate against new DTD.
+
+2005-02-17  Colin Walters  <walters@verbum.org>
+
        This patch is based on initial work from
        Paul Kuliniewicz <kuliniew@purdue.edu>.
 
index 3d6a207..ad21af6 100644 (file)
             &lt;method name="Frobate"&gt;
               &lt;arg name="foo" type="int32" direction="in"/&gt;
               &lt;arg name="bar" type="string" direction="out"/&gt;
+              &lt;annotation name="org.freedesktop.DBus.Deprecated" value="true"/&gt;
             &lt;/method&gt;
             &lt;signal name="Changed"&gt;
               &lt;arg name="new_value" type="boolean"/&gt;
         </listitem>
         <listitem>
           <para>
-            The method, interface, property, and signal elements may have 
-            an attribute deprecated="yes|no". If the attribute is not 
-            present, the default value for an interface is "no", and 
-            the default value for methods, properties, and signals is 
-            the deprecation status of the interface.
-          </para>
-        </listitem>
-        <listitem>
-          <para>
             The "name" attribute on arguments is optional.
           </para>
         </listitem>
       </itemizedlist>
     </para>
-
+    <para>
+        Method, interface, property, and signal elements may have
+        "annotations", which are generic key/value pairs of metadata.
+       They are similar conceptually to Java's annotations and C# attributes.
+        Well-known annotations:
+     </para>
+     <informaltable>
+       <tgroup cols="3">
+        <thead>
+          <row>
+            <entry>Name</entry>
+            <entry>Values (separated by ,)</entry>
+            <entry>Description</entry>
+          </row>
+        </thead>
+        <tbody>
+          <row>
+            <entry>org.freedesktop.DBus.Deprecated</entry>
+            <entry>true,false</entry>
+            <entry>Whether or not the entity is deprecated; defaults to false</entry>
+          </row>
+          <row>
+            <entry>org.freedesktop.DBus.GLib.CSymbol</entry>
+            <entry>(string)</entry>
+            <entry>The C symbol; may be used for methods and interfaces</entry>
+          </row>
+        </tbody>
+       </tgroup>
+     </informaltable>
   </sect1>
-
   <sect1 id="message-bus">
     <title>Message Bus Specification</title>
     <sect2 id="message-bus-overview">
index 5e1c96d..fd6aa47 100644 (file)
@@ -4,32 +4,33 @@
 
 <!-- see D-BUS specification for documentation -->
 
-<!ELEMENT node (interface,node)>
+<!ELEMENT node (interface*,node*)>
 <!ATTLIST node name CDATA #REQUIRED>
 
-<!ELEMENT interface (method,signal,property)>
+<!ELEMENT interface (annotation*,method*,signal*,property*)>
 <!ATTLIST interface name CDATA #REQUIRED>
-<!ATTLIST interface deprecated CDATA "no">
 
+<!ELEMENT method (annotation*,arg*)>
 <!ATTLIST method name CDATA #REQUIRED>
-<!ATTLIST method deprecated #IMPLIED>
 
 <!ELEMENT arg EMPTY>
-<!ATTLIST arg name CDATA #REQUIRED>
+<!ATTLIST arg name CDATA #IMPLIED>
 <!ATTLIST arg type CDATA #REQUIRED>
 <!-- Method arguments SHOULD include "direction",
      while signal and error arguments SHOULD not (since there's no point).
      The DTD format can't express that subtlety. -->
-<!ATTLIST arg direction "in|out" #IMPLIED>
+<!ATTLIST arg direction (in|out) "in">
 
-<!ELEMENT signal (arg)>
+<!ELEMENT signal (arg,annotation)>
 <!ATTLIST signal name CDATA #REQUIRED>
-<!ATTLIST signal deprecated #IMPLIED>
 
-<!ELEMENT property>  <!-- AKA "attribute" -->
+<!ELEMENT property (annotation)>  <!-- AKA "attribute" -->
 <!ATTLIST property name CDATA #REQUIRED>
 <!ATTLIST property type CDATA #REQUIRED>
-<!ATTLIST property access "read|write|readwrite" #REQUIRED>
-<!ATTLIST property deprecated #IMPLIED>
+<!ATTLIST property access (read|write|readwrite) #REQUIRED>
+
+<!ELEMENT annotation EMPTY>  <!-- Generic metadata -->
+<!ATTLIST annotation name CDATA #REQUIRED>
+<!ATTLIST annotation value CDATA #REQUIRED>
 
 
index 98c1334..4ead51a 100644 (file)
@@ -201,7 +201,7 @@ gather_marshallers (BaseInfo *base, DBusBindingToolCData *data, GError **error)
       const char *interface_c_name;
 
       interface = (InterfaceInfo *) base;
-      interface_c_name = interface_info_get_binding_name (interface, "C");
+      interface_c_name = interface_info_get_annotation (interface, DBUS_GLIB_ANNOTATION_C_SYMBOL);
       if (interface_c_name == NULL)
         {
           return TRUE;
@@ -217,7 +217,7 @@ gather_marshallers (BaseInfo *base, DBusBindingToolCData *data, GError **error)
           char *marshaller_name;
 
           method = (MethodInfo *) tmp->data;
-          if (method_info_get_binding_name (method, "C") == NULL)
+          if (method_info_get_annotation (method, DBUS_GLIB_ANNOTATION_C_SYMBOL) == NULL)
             {
               continue;
             }
@@ -306,7 +306,7 @@ generate_glue (BaseInfo *base, DBusBindingToolCData *data, GError **error)
       channel = data->channel;
 
       interface = (InterfaceInfo *) base;
-      interface_c_name = interface_info_get_binding_name (interface, "C");
+      interface_c_name = interface_info_get_annotation (interface, DBUS_GLIB_ANNOTATION_C_SYMBOL);
       if (interface_c_name == NULL)
         {
           return TRUE;
@@ -319,7 +319,7 @@ generate_glue (BaseInfo *base, DBusBindingToolCData *data, GError **error)
 
       /* Table of marshalled methods. */
 
-      if (!write_printf_to_iochannel ("static const DBusGMethodInfo dbus_glib_%s_methods[] = {\n", channel, error, interface_info_get_binding_name (interface, "C")))
+      if (!write_printf_to_iochannel ("static const DBusGMethodInfo dbus_glib_%s_methods[] = {\n", channel, error, interface_info_get_annotation (interface, DBUS_GLIB_ANNOTATION_C_SYMBOL)))
        goto io_lose;
       for (tmp = methods; tmp != NULL; tmp = g_slist_next (tmp))
         {
@@ -329,7 +329,7 @@ generate_glue (BaseInfo *base, DBusBindingToolCData *data, GError **error)
          GSList *args;
 
           method = (MethodInfo *) tmp->data;
-         method_c_name = method_info_get_binding_name (method, "C");
+         method_c_name = method_info_get_annotation (method, DBUS_GLIB_ANNOTATION_C_SYMBOL);
           if (method_c_name == NULL)
             {
               continue;
index d4589bc..6667438 100644 (file)
@@ -25,6 +25,8 @@
 
 G_BEGIN_DECLS
 
+#define DBUS_GLIB_ANNOTATION_C_SYMBOL "org.freedesktop.DBus.GLib.CSymbol"
+
 gboolean dbus_binding_tool_output_glib_client (BaseInfo *info, GIOChannel *channel, GError **error);
 gboolean dbus_binding_tool_output_glib_server (BaseInfo *info, GIOChannel *channel, GError **error);
 
index 554e18c..fb9573e 100644 (file)
@@ -43,7 +43,7 @@ struct NodeInfo
 struct InterfaceInfo
 {
   BaseInfo base;
-  GHashTable *bindings;
+  GHashTable *annotations;
   /* Since we have BaseInfo now these could be one list */
   GSList *methods;
   GSList *signals;
@@ -53,7 +53,7 @@ struct InterfaceInfo
 struct MethodInfo
 {
   BaseInfo base;
-  GHashTable *bindings;
+  GHashTable *annotations;
   GSList *args;
 };
 
@@ -345,9 +345,9 @@ interface_info_new (const char *name)
   info->base.refcount = 1;
   info->base.name = g_strdup (name);
   info->base.type = INFO_TYPE_INTERFACE;
-  info->bindings = g_hash_table_new_full (g_str_hash, g_str_equal,
-                                         (GDestroyNotify) g_free,
-                                         (GDestroyNotify) g_free);
+  info->annotations = g_hash_table_new_full (g_str_hash, g_str_equal,
+                                            (GDestroyNotify) g_free,
+                                            (GDestroyNotify) g_free);
   
   return info;
 }
@@ -366,7 +366,7 @@ interface_info_unref (InterfaceInfo *info)
   info->base.refcount -= 1;
   if (info->base.refcount == 0)
     {
-      g_hash_table_destroy (info->bindings);
+      g_hash_table_destroy (info->annotations);
       free_method_list (&info->methods);
       free_signal_list (&info->signals);
       free_property_list (&info->properties);
@@ -381,16 +381,16 @@ interface_info_get_name (InterfaceInfo *info)
 }
 
 GSList *
-interface_info_get_binding_names (InterfaceInfo *info)
+interface_info_get_annotations (InterfaceInfo *info)
 {
-  return get_hash_keys (info->bindings);
+  return get_hash_keys (info->annotations);
 }
 
 const char*
-interface_info_get_binding_name (InterfaceInfo *info,
-                                const char    *binding_type)
+interface_info_get_annotation (InterfaceInfo *info,
+                              const char    *name)
 {
-  return g_hash_table_lookup (info->bindings, binding_type);
+  return g_hash_table_lookup (info->annotations, name);
 }
 
 GSList*
@@ -412,13 +412,13 @@ interface_info_get_properties (InterfaceInfo *info)
 }
 
 void
-interface_info_set_binding_name (InterfaceInfo *info,
-                                const char    *binding_type,
-                                const char    *bound_name)
+interface_info_add_annotation (InterfaceInfo *info,
+                              const char    *name,
+                              const char    *value)
 {
-  g_hash_table_insert (info->bindings,
-                      g_strdup (binding_type),
-                      g_strdup (bound_name));
+  g_hash_table_insert (info->annotations,
+                      g_strdup (name),
+                      g_strdup (value));
 }
 
 void
@@ -470,7 +470,7 @@ method_info_new (const char *name)
   info->base.refcount = 1;
   info->base.name = g_strdup (name);
   info->base.type = INFO_TYPE_METHOD;
-  info->bindings = g_hash_table_new_full (g_str_hash, g_str_equal,
+  info->annotations = g_hash_table_new_full (g_str_hash, g_str_equal,
                                          (GDestroyNotify) g_free,
                                          (GDestroyNotify) g_free);
   
@@ -491,7 +491,7 @@ method_info_unref (MethodInfo *info)
   info->base.refcount -= 1;
   if (info->base.refcount == 0)
     {
-      g_hash_table_destroy (info->bindings);
+      g_hash_table_destroy (info->annotations);
       free_arg_list (&info->args);
       base_info_free (info);
     }
@@ -504,16 +504,16 @@ method_info_get_name (MethodInfo *info)
 }
 
 GSList *
-method_info_get_binding_names (MethodInfo *info)
+method_info_get_annotations (MethodInfo *info)
 {
-  return get_hash_keys (info->bindings);
+  return get_hash_keys (info->annotations);
 }
 
 const char*
-method_info_get_binding_name (MethodInfo *info,
-                             const char *binding_type)
+method_info_get_annotation (MethodInfo *info,
+                           const char *name)
 {
-  return g_hash_table_lookup (info->bindings, binding_type);
+  return g_hash_table_lookup (info->annotations, name);
 }
 
 GSList*
@@ -544,13 +544,13 @@ args_sort_by_direction (const void *a,
 }                  
 
 void
-method_info_set_binding_name (MethodInfo  *info,
-                             const char  *binding_type,
-                             const char  *bound_name)
+method_info_add_annotation (MethodInfo  *info,
+                           const char  *name,
+                           const char  *value)
 {
-  g_hash_table_insert (info->bindings,
-                      g_strdup (binding_type),
-                      g_strdup (bound_name));
+  g_hash_table_insert (info->annotations,
+                      g_strdup (name),
+                      g_strdup (value));
 }
 
 void
index 917432e..539c731 100644 (file)
@@ -90,15 +90,15 @@ InterfaceInfo*      interface_info_new            (const char          *name);
 InterfaceInfo*      interface_info_ref            (InterfaceInfo       *info);
 void                interface_info_unref          (InterfaceInfo       *info);
 const char*         interface_info_get_name       (InterfaceInfo       *info);
-GSList*             interface_info_get_binding_names(InterfaceInfo     *info);
-const char*         interface_info_get_binding_name(InterfaceInfo*info,
-                                                   const char         *binding_type);
+GSList*             interface_info_get_annotations(InterfaceInfo       *info);
+const char*         interface_info_get_annotation (InterfaceInfo*info,
+                                                  const char         *annotation);
 GSList*             interface_info_get_methods    (InterfaceInfo       *info);
 GSList*             interface_info_get_signals    (InterfaceInfo       *info);
 GSList*             interface_info_get_properties (InterfaceInfo       *info);
-void                interface_info_set_binding_name(InterfaceInfo      *info,
-                                                   const char         *name,
-                                                   const char         *value);
+void                interface_info_add_annotation (InterfaceInfo      *info,
+                                                  const char         *name,
+                                                  const char         *value);
 void                interface_info_add_method     (InterfaceInfo       *info,
                                                    MethodInfo          *method);
 void                interface_info_add_signal     (InterfaceInfo       *info,
@@ -109,12 +109,12 @@ MethodInfo*         method_info_new               (const char          *name);
 MethodInfo*         method_info_ref               (MethodInfo          *info);
 void                method_info_unref             (MethodInfo          *info);
 const char*         method_info_get_name          (MethodInfo          *info);
-GSList*             method_info_get_binding_names (MethodInfo          *info);
-const char*         method_info_get_binding_name  (MethodInfo          *info,
-                                                  const char          *binding_type);
-void                method_info_set_binding_name  (MethodInfo          *info,
-                                                  const char          *binding_type,
-                                                  const char          *bound_name);
+GSList*             method_info_get_annotations   (MethodInfo          *info);
+const char*         method_info_get_annotation    (MethodInfo          *info,
+                                                  const char          *annotation);
+void                method_info_add_annotation    (MethodInfo          *info,
+                                                  const char          *name,
+                                                  const char          *value);
 GSList*             method_info_get_args          (MethodInfo          *info);
 void                method_info_add_arg           (MethodInfo          *info,
                                                    ArgInfo             *arg);
index 022055e..1359ba5 100644 (file)
@@ -107,22 +107,22 @@ pretty_print (BaseInfo *base,
     case INFO_TYPE_INTERFACE:
       {
         InterfaceInfo *i = (InterfaceInfo*) base;
-       GSList *binding_types, *elt;
+       GSList *annotations, *elt;
 
         g_assert (name != NULL);
 
         printf (_("interface \"%s\" {\n"), name);
 
-       binding_types = interface_info_get_binding_names (i);
-       for (elt = binding_types; elt; elt = elt->next)
+       annotations = interface_info_get_annotations (i);
+       for (elt = annotations; elt; elt = elt->next)
          {
-           const char *binding_type = elt->data;
-           const char *binding_name = interface_info_get_binding_name (i, binding_type);
+           const char *name = elt->data;
+           const char *value = interface_info_get_annotation (i, name);
 
            printf (_(" (binding \"%s\": \"%s\") "),
-                   binding_type, binding_name);
+                   name, value);
          }
-       g_slist_free (binding_types);
+       g_slist_free (annotations);
 
         pretty_print_list (interface_info_get_methods (i), depth + 1);
         pretty_print_list (interface_info_get_signals (i), depth + 1);
@@ -135,21 +135,21 @@ pretty_print (BaseInfo *base,
     case INFO_TYPE_METHOD:
       {
         MethodInfo *m = (MethodInfo*) base;
-       GSList *binding_types, *elt;
+       GSList *annotations, *elt;
 
         g_assert (name != NULL);
 
-       binding_types = method_info_get_binding_names (m);
+       annotations = method_info_get_annotations (m);
         printf (_("method \"%s\""), name);
-       for (elt = binding_types; elt; elt = elt->next)
+       for (elt = annotations; elt; elt = elt->next)
          {
-           const char *binding_type = elt->data;
-           const char *binding_name = method_info_get_binding_name (m, binding_type);
+           const char *name = elt->data;
+           const char *value = method_info_get_annotation (m, name);
 
-           printf (_(" (binding \"%s\": \"%s\") "),
-                   binding_type, binding_name);
+           printf (_(" (annotation \"%s\": \"%s\") "),
+                   name, value);
          }
-       g_slist_free (binding_types);
+       g_slist_free (annotations);
 
         pretty_print_list (method_info_get_args (m), depth + 1);
 
index 05136aa..3adfe32 100644 (file)
@@ -171,6 +171,7 @@ struct Parser
   SignalInfo *signal;
   PropertyInfo *property;
   ArgInfo *arg;
+  gboolean in_annotation;
 };
 
 Parser*
@@ -240,7 +241,8 @@ parse_node (Parser      *parser,
       parser->method ||
       parser->signal ||
       parser->property ||
-      parser->arg)
+      parser->arg ||
+      parser->in_annotation)
     {
       g_set_error (error, G_MARKUP_ERROR,
                    G_MARKUP_ERROR_PARSE,
@@ -308,7 +310,6 @@ parse_interface (Parser      *parser,
                  GError     **error)
 {
   const char *name;
-  const char *c_name;
   InterfaceInfo *iface;
   NodeInfo *top;
   
@@ -317,6 +318,7 @@ parse_interface (Parser      *parser,
       parser->signal ||
       parser->property ||
       parser->arg ||
+      parser->in_annotation ||
       (parser->node_stack == NULL))
     {
       g_set_error (error, G_MARKUP_ERROR,
@@ -330,7 +332,6 @@ parse_interface (Parser      *parser,
   if (!locate_attributes (element_name, attribute_names,
                           attribute_values, error,
                           "name", &name,
-                          "c_name", &c_name,
                           NULL))
     return FALSE;
 
@@ -346,8 +347,6 @@ parse_interface (Parser      *parser,
   top = parser->node_stack->data;
   
   iface = interface_info_new (name);
-  if (c_name)
-    interface_info_set_binding_name (iface, "C", c_name);
   node_info_add_interface (top, iface);
   interface_info_unref (iface);
 
@@ -364,7 +363,6 @@ parse_method (Parser      *parser,
               GError     **error)
 {
   const char *name;
-  const char *c_name;
   MethodInfo *method;
   NodeInfo *top;
   
@@ -373,6 +371,7 @@ parse_method (Parser      *parser,
       parser->method ||
       parser->signal ||
       parser->property ||
+      parser->in_annotation ||
       parser->arg)
     {
       g_set_error (error, G_MARKUP_ERROR,
@@ -386,7 +385,6 @@ parse_method (Parser      *parser,
   if (!locate_attributes (element_name, attribute_names,
                           attribute_values, error,
                           "name", &name,
-                          "c_name", &c_name,
                           NULL))
     return FALSE;
 
@@ -402,8 +400,6 @@ parse_method (Parser      *parser,
   top = parser->node_stack->data;
   
   method = method_info_new (name);
-  if (c_name)
-    method_info_set_binding_name (method, "C", c_name);
   interface_info_add_method (parser->interface, method);
   method_info_unref (method);
 
@@ -428,6 +424,7 @@ parse_signal (Parser      *parser,
       parser->signal ||
       parser->method ||
       parser->property ||
+      parser->in_annotation ||
       parser->arg)
     {
       g_set_error (error, G_MARKUP_ERROR,
@@ -539,6 +536,7 @@ parse_property (Parser      *parser,
       parser->signal ||
       parser->method ||
       parser->property ||
+      parser->in_annotation ||
       parser->arg)
     {
       g_set_error (error, G_MARKUP_ERROR,
@@ -633,6 +631,7 @@ parse_arg (Parser      *parser,
   if (!(parser->method || parser->signal) ||
       parser->node_stack == NULL ||
       parser->property ||
+      parser->in_annotation ||
       parser->arg)
     {
       g_set_error (error, G_MARKUP_ERROR,
@@ -724,6 +723,67 @@ parse_arg (Parser      *parser,
   return TRUE;
 }
 
+static gboolean
+parse_annotation (Parser      *parser,
+                 const char  *element_name,
+                 const char **attribute_names,
+                 const char **attribute_values,
+                 GError     **error)
+{
+  const char *name;
+  const char *value;
+  
+  if (!(parser->method || parser->interface || parser->arg) || 
+      parser->node_stack == NULL ||
+      parser->signal ||
+      parser->in_annotation)
+    {
+      g_set_error (error, G_MARKUP_ERROR,
+                   G_MARKUP_ERROR_PARSE,
+                   _("Can't put <%s> element here"),
+                   element_name);
+      return FALSE;      
+    }
+
+  name = NULL;
+  if (!locate_attributes (element_name, attribute_names,
+                          attribute_values, error,
+                          "name", &name,
+                          "value", &value,
+                          NULL))
+    return FALSE;
+
+  /* name can be null for args */
+  
+  if (name == NULL)
+    {
+      g_set_error (error, G_MARKUP_ERROR,
+                   G_MARKUP_ERROR_PARSE,
+                   _("\"%s\" attribute required on <%s> element "),
+                   "name", element_name);
+      return FALSE;
+    }
+  if (value == NULL)
+    {
+      g_set_error (error, G_MARKUP_ERROR,
+                   G_MARKUP_ERROR_PARSE,
+                   _("\"%s\" attribute required on <%s> element "),
+                   "value", element_name);
+      return FALSE;
+    }
+
+  if (parser->method)
+    method_info_add_annotation (parser->method, name, value);
+  else if (parser->interface)
+    interface_info_add_annotation (parser->interface, name, value);
+  else
+    g_assert_not_reached ();
+
+  parser->in_annotation = TRUE;
+
+  return TRUE;
+}
+
 gboolean
 parser_start_element (Parser      *parser,
                       const char  *element_name,
@@ -769,6 +829,12 @@ parser_start_element (Parser      *parser,
                       attribute_values, error))
         return FALSE;
     }
+  else if (ELEMENT_IS ("annotation"))
+    {
+      if (!parse_annotation (parser, element_name, attribute_names,
+                            attribute_values, error))
+        return FALSE;
+    }
   else
     {
       g_set_error (error, G_MARKUP_ERROR,
@@ -807,6 +873,10 @@ parser_end_element (Parser      *parser,
     {
       parser->arg = NULL;
     }
+  else if (ELEMENT_IS ("annotation"))
+    {
+      parser->in_annotation = FALSE;
+    }
   else if (ELEMENT_IS ("node"))
     {
       NodeInfo *top;
index 223bf67..298e2dd 100644 (file)
@@ -2,25 +2,31 @@
 
 <node name="/org/freedesktop/DBus/Tests/MyTestObject">
 
-  <interface name="org.freedesktop.DBus.Tests.MyObject" c_name="my_object">
+  <interface name="org.freedesktop.DBus.Tests.MyObject">
+    <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="my_object"/>
 
-    <method name="DoNothing" c_name="my_object_do_nothing">
+    <method name="DoNothing">
+      <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="my_object_do_nothing"/>
     </method>
 
-    <method name="Increment" c_name="my_object_increment">
+    <method name="Increment">
+      <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="my_object_increment"/>
       <arg type="uint32" name="x" />
       <arg type="uint32" direction="out" />
     </method>
 
-    <method name="ThrowError" c_name="my_object_throw_error">
+    <method name="ThrowError">
+      <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="my_object_throw_error"/>
     </method>
 
-    <method name="Uppercase" c_name="my_object_uppercase">
+    <method name="Uppercase">
+      <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="my_object_uppercase"/>
       <arg type="string" direction="in" />
       <arg type="string" direction="out" />
     </method>
 
-    <method name="ManyArgs" c_name="my_object_many_args">
+    <method name="ManyArgs">
+      <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="my_object_many_args"/>
       <arg type="uint32" name="x" direction="in" />
       <arg type="string" name="str" direction="in" />
       <arg type="double" name="trouble" direction="in" />