dbus/glib .cvsignore, 1.5, 1.6 Makefile.am, 1.9, 1.10 dbus-gidl.c, 1.8, 1.9 dbus-gidl.h, 1.5, 1.6 dbus-glib-tool.c, 1.6, 1.7 dbus-gobject.c, 1.12, 1.13 dbus-gparser.c, 1.7, 1.8

Havoc Pennington hp at freedesktop.org
Sat Jan 29 11:52:21 PST 2005


Update of /cvs/dbus/dbus/glib
In directory gabe:/tmp/cvs-serv20067/glib

Modified Files:
	.cvsignore Makefile.am dbus-gidl.c dbus-gidl.h 
	dbus-glib-tool.c dbus-gobject.c dbus-gparser.c 
Log Message:
2005-01-29  Havoc Pennington  <hp at redhat.com>

	* glib/Makefile.am: rename dbus-glib-tool to dbus-binding-tool;
	though it uses glib, it could be extended for any binding in
	principle

	* glib/dbus-gobject.c (gobject_message_function): change to the
	new way properties work

	* dbus/dbus-protocol.h: add the new interfaces

	* doc/dbus-specification.xml: document the introspection format,
	Introspectable interface, and add an org.freedesktop.Properties
	interface.

	* glib/dbus-gparser.c: add support for a <property> element

	* glib/dbus-gidl.c: add PropertyInfo

	* glib/dbus-gobject.c (handle_introspect): put the outermost
	<node> outside the signal and property descriptions.
	(introspect_properties): export properties as <property> rather
	than as method calls



Index: .cvsignore
===================================================================
RCS file: /cvs/dbus/dbus/glib/.cvsignore,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- .cvsignore	30 Sep 2003 02:32:57 -0000	1.5
+++ .cvsignore	29 Jan 2005 19:52:19 -0000	1.6
@@ -5,7 +5,7 @@
 *.lo
 *.la
 dbus-glib-test
-dbus-glib-tool
+dbus-binding-tool
 *.bb
 *.bbg
 *.da

Index: Makefile.am
===================================================================
RCS file: /cvs/dbus/dbus/glib/Makefile.am,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -d -r1.9 -r1.10
--- Makefile.am	29 Jul 2004 08:00:45 -0000	1.9
+++ Makefile.am	29 Jan 2005 19:52:19 -0000	1.10
@@ -34,12 +34,12 @@
 
 libdbus_gtool_la_LIBADD = libdbus-glib-1.la
 
-bin_PROGRAMS=dbus-glib-tool
+bin_PROGRAMS=dbus-binding-tool
 
-dbus_glib_tool_SOURCES =			\
+dbus_binding_tool_SOURCES =			\
 	dbus-glib-tool.c
 
-dbus_glib_tool_LDADD= -lexpat libdbus-gtool.la
+dbus_binding_tool_LDADD= -lexpat libdbus-gtool.la
 
 if DBUS_BUILD_TESTS
 

Index: dbus-gidl.c
===================================================================
RCS file: /cvs/dbus/dbus/glib/dbus-gidl.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- dbus-gidl.c	10 Aug 2004 03:07:00 -0000	1.8
+++ dbus-gidl.c	29 Jan 2005 19:52:19 -0000	1.9
@@ -2,7 +2,7 @@
 /* dbus-gidl.c data structure describing an interface, to be generated from IDL
  *             or something
  *
- * Copyright (C) 2003  Red Hat, Inc.
+ * Copyright (C) 2003, 2005  Red Hat, Inc.
  *
  * Licensed under the Academic Free License version 2.1
  *
@@ -46,6 +46,7 @@
   /* Since we have BaseInfo now these could be one list */
   GSList *methods;
   GSList *signals;
+  GSList *properties;
 };
 
 struct MethodInfo
@@ -60,6 +61,13 @@
   GSList *args;
 };
 
+struct PropertyInfo
+{
+  BaseInfo base;
+  int type;
+  PropertyAccessFlags access;
+};
+
 struct ArgInfo
 {
   BaseInfo base;
@@ -111,6 +119,9 @@
     case INFO_TYPE_METHOD:
       method_info_unref ((MethodInfo*) info);
       break;
+    case INFO_TYPE_PROPERTY:
+      property_info_unref ((PropertyInfo*) info);
+      break;
     case INFO_TYPE_ARG:
       arg_info_unref ((ArgInfo*) info);
       break;
@@ -209,6 +220,20 @@
   *signals_p = NULL;
 }
 
+static void
+free_property_list (GSList **props_p)
+{
+  GSList *tmp;
+  tmp = *props_p;
+  while (tmp != NULL)
+    {
+      property_info_unref (tmp->data);
+      tmp = tmp->next;
+    }
+  g_slist_free (*props_p);
+  *props_p = NULL;
+}
+
 NodeInfo*
 node_info_new (const char *name)
 {
@@ -307,6 +332,7 @@
     {
       free_method_list (&info->methods);
       free_signal_list (&info->signals);
+      free_property_list (&info->properties);
       base_info_free (info);
     }
 }
@@ -329,6 +355,12 @@
   return info->signals;
 }
 
+GSList*
+interface_info_get_properties (InterfaceInfo *info)
+{
+  return info->properties;
+}
+
 void
 interface_info_add_method (InterfaceInfo *info,
                            MethodInfo    *method)
@@ -345,6 +377,14 @@
   info->signals = g_slist_append (info->signals, signal);
 }
 
+void
+interface_info_add_property (InterfaceInfo *info,
+                             PropertyInfo  *property)
+{
+  property_info_ref (property);
+  info->properties = g_slist_append (info->properties, property);
+}
+
 static void
 free_arg_list (GSList **args_p)
 {
@@ -352,6 +392,8 @@
   tmp = *args_p;
   while (tmp != NULL)
     {
+      ArgInfo *ai = tmp->data;
+      g_assert (ai->base.type == INFO_TYPE_ARG);
       arg_info_unref (tmp->data);
       tmp = tmp->next;
     }
@@ -484,10 +526,64 @@
   
   arg_info_ref (arg);
   info->args = g_slist_append (info->args, arg);
-
+  
   /* signal args don't need sorting since only "out" is allowed */
 }
 
+PropertyInfo*
+property_info_new (const char          *name,
+                   int                  type,
+                   PropertyAccessFlags  access)
+{
+  PropertyInfo *info;
+
+  info = g_new0 (PropertyInfo, 1);
+  info->base.refcount = 1;
+  info->base.name = g_strdup (name);
+  info->base.type = INFO_TYPE_PROPERTY;
+
+  info->type = type;
+  info->access = access;
+  
+  return info;
+}
+
+PropertyInfo*
+property_info_ref (PropertyInfo *info)
+{
+  info->base.refcount += 1;
+  
+  return info;
+}
+
+void
+property_info_unref (PropertyInfo *info)
+{
+  info->base.refcount -= 1;
+  if (info->base.refcount == 0)
+    {
+      base_info_free (info);
+    }
+}
+
+const char*
+property_info_get_name (PropertyInfo *info)
+{
+  return info->base.name;
+}
+
+int
+property_info_get_type (PropertyInfo *info)
+{
+  return info->type;
+}
+
+PropertyAccessFlags
+property_info_get_access (PropertyInfo *info)
+{
+  return info->access;
+}
+
 ArgInfo*
 arg_info_new (const char  *name,
               ArgDirection direction,

Index: dbus-gidl.h
===================================================================
RCS file: /cvs/dbus/dbus/glib/dbus-gidl.h,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- dbus-gidl.h	10 Aug 2004 03:07:00 -0000	1.5
+++ dbus-gidl.h	29 Jan 2005 19:52:19 -0000	1.6
@@ -36,21 +36,30 @@
 typedef struct InterfaceInfo InterfaceInfo;
 typedef struct MethodInfo    MethodInfo;
 typedef struct SignalInfo    SignalInfo;
+typedef struct PropertyInfo  PropertyInfo;
 typedef struct ArgInfo       ArgInfo;
 
 typedef enum
 {
+  ARG_INVALID = -1,
   ARG_IN,
   ARG_OUT
 } ArgDirection;
 
 typedef enum
 {
+  PROPERTY_READ  = 1 << 0,
+  PROPERTY_WRITE = 1 << 1
+} PropertyAccessFlags;
+
+typedef enum
+{
   INFO_TYPE_NODE,
   INFO_TYPE_INTERFACE,
   INFO_TYPE_METHOD,
   INFO_TYPE_SIGNAL,
-  INFO_TYPE_ARG
+  INFO_TYPE_ARG,
+  INFO_TYPE_PROPERTY
 
 } InfoType;
 
@@ -64,54 +73,59 @@
 #define        BASE_INFO_TYPE             (base_info_get_gtype ())
 
 
-NodeInfo*      node_info_new              (const char    *name);
-NodeInfo*      node_info_ref              (NodeInfo      *info);
-void           node_info_unref            (NodeInfo      *info);
-const char*    node_info_get_name         (NodeInfo      *info);
-GSList*        node_info_get_interfaces   (NodeInfo      *info);
-GSList*        node_info_get_nodes        (NodeInfo      *info);
-void           node_info_add_interface    (NodeInfo      *info,
-                                           InterfaceInfo *interface);
-void           node_info_add_node         (NodeInfo      *info,
-                                           NodeInfo      *child);
-
-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_methods (InterfaceInfo *info);
-GSList*        interface_info_get_signals (InterfaceInfo *info);
-void           interface_info_add_method  (InterfaceInfo *info,
-                                           MethodInfo    *method);
-void           interface_info_add_signal  (InterfaceInfo *info,
-                                           SignalInfo    *signal);
-
-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_args       (MethodInfo    *info);
-void           method_info_add_arg        (MethodInfo    *info,
-                                           ArgInfo       *arg);
-
-SignalInfo*    signal_info_new            (const char    *name);
-SignalInfo*    signal_info_ref            (SignalInfo    *info);
-void           signal_info_unref          (SignalInfo    *info);
-
-const char*    signal_info_get_name       (SignalInfo    *info);
-GSList*        signal_info_get_args       (SignalInfo    *info);
-void           signal_info_add_arg        (SignalInfo    *info,
-                                           ArgInfo       *arg);
-
-ArgInfo*       arg_info_new               (const char    *name,
-                                           ArgDirection   direction,
-                                           int            type);
-ArgInfo*       arg_info_ref               (ArgInfo       *info);
-void           arg_info_unref             (ArgInfo       *info);
-const char*    arg_info_get_name          (ArgInfo       *info);
-int            arg_info_get_type          (ArgInfo       *info);
-ArgDirection   arg_info_get_direction     (ArgInfo       *info);
+NodeInfo*           node_info_new                 (const char          *name);
+NodeInfo*           node_info_ref                 (NodeInfo            *info);
+void                node_info_unref               (NodeInfo            *info);
+const char*         node_info_get_name            (NodeInfo            *info);
+GSList*             node_info_get_interfaces      (NodeInfo            *info);
+GSList*             node_info_get_nodes           (NodeInfo            *info);
+void                node_info_add_interface       (NodeInfo            *info,
+                                                   InterfaceInfo       *interface);
+void                node_info_add_node            (NodeInfo            *info,
+                                                   NodeInfo            *child);
+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_methods    (InterfaceInfo       *info);
+GSList*             interface_info_get_signals    (InterfaceInfo       *info);
+GSList*             interface_info_get_properties (InterfaceInfo       *info);
+void                interface_info_add_method     (InterfaceInfo       *info,
+                                                   MethodInfo          *method);
+void                interface_info_add_signal     (InterfaceInfo       *info,
+                                                   SignalInfo          *signal);
+void                interface_info_add_property   (InterfaceInfo       *info,
+                                                   PropertyInfo        *property);
+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_args          (MethodInfo          *info);
+void                method_info_add_arg           (MethodInfo          *info,
+                                                   ArgInfo             *arg);
+SignalInfo*         signal_info_new               (const char          *name);
+SignalInfo*         signal_info_ref               (SignalInfo          *info);
+void                signal_info_unref             (SignalInfo          *info);
+const char*         signal_info_get_name          (SignalInfo          *info);
+GSList*             signal_info_get_args          (SignalInfo          *info);
+void                signal_info_add_arg           (SignalInfo          *info,
+                                                   ArgInfo             *arg);
+PropertyInfo*       property_info_new             (const char          *name,
+                                                   int                  type,
+                                                   PropertyAccessFlags  access);
+PropertyInfo*       property_info_ref             (PropertyInfo        *info);
+void                property_info_unref           (PropertyInfo        *info);
+const char*         property_info_get_name        (PropertyInfo        *info);
+int                 property_info_get_type        (PropertyInfo        *info);
+PropertyAccessFlags property_info_get_access      (PropertyInfo        *info);
+ArgInfo*            arg_info_new                  (const char          *name,
+                                                   ArgDirection         direction,
+                                                   int                  type);
+ArgInfo*            arg_info_ref                  (ArgInfo             *info);
+void                arg_info_unref                (ArgInfo             *info);
+const char*         arg_info_get_name             (ArgInfo             *info);
+int                 arg_info_get_type             (ArgInfo             *info);
+ArgDirection        arg_info_get_direction        (ArgInfo             *info);
 
 G_END_DECLS
 

Index: dbus-glib-tool.c
===================================================================
RCS file: /cvs/dbus/dbus/glib/dbus-glib-tool.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- dbus-glib-tool.c	10 Aug 2004 03:07:00 -0000	1.6
+++ dbus-glib-tool.c	29 Jan 2005 19:52:19 -0000	1.7
@@ -57,7 +57,7 @@
                    int     depth)
 {
   GSList *tmp;
-
+  
   tmp = list;
   while (tmp != NULL)
     {
@@ -106,6 +106,7 @@
 
         pretty_print_list (interface_info_get_methods (i), depth + 1);
         pretty_print_list (interface_info_get_signals (i), depth + 1);
+        pretty_print_list (interface_info_get_properties (i), depth + 1);
 
         indent (depth);
         printf ("}\n");
@@ -139,6 +140,22 @@
         printf (")\n");
       }
       break;
+    case INFO_TYPE_PROPERTY:
+      {
+        PropertyInfo *a = (PropertyInfo*) base;
+        int pt = property_info_get_type (a);
+        PropertyAccessFlags acc = property_info_get_access (a);
+
+        printf ("%s%s %s",
+                acc & PROPERTY_READ ? "read" : "",
+                acc & PROPERTY_WRITE ? "write" : "",
+                _dbus_gutils_type_to_string (pt));
+        if (name)
+          printf (" %s\n", name);
+        else
+          printf ("\n");
+      }
+      break;
     case INFO_TYPE_ARG:
       {
         ArgInfo *a = (ArgInfo*) base;
@@ -160,16 +177,16 @@
 static void
 usage (int ecode)
 {
-  fprintf (stderr, "dbus-glib-tool [--version] [--help]\n");
+  fprintf (stderr, "dbus-binding-tool [--version] [--help] [--pretty-print]\n");
   exit (ecode);
 }
 
 static void
 version (void)
 {
-  printf ("D-BUS GLib Tool %s\n"
-          "Copyright (C) 2003, 2004 Red Hat, Inc.\n"
-          "This is free software; see the source for copying conditions.\n"
+  printf ("D-BUS Binding Tool %s\n"
+          "Copyright (C) 2003-2005 Red Hat, Inc.\n"
+          "This is free software; xsee the source for copying conditions.\n"
           "There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n",
           VERSION);
   exit (0);
@@ -313,11 +330,11 @@
   else
     printf ("No test data!\n");
 
-  printf ("%s: running gtool tests\n", "dbus-glib-tool");
+  printf ("%s: running binding tests\n", "dbus-binding-tool");
   if (!_dbus_gtool_test (test_data_dir))
     test_die ("gtool");
 
-  printf ("%s: completed successfully\n", "dbus-glib-tool");
+  printf ("%s: completed successfully\n", "dbus-binding-tool");
 }
 
 #endif /* DBUS_BUILD_TESTS */

Index: dbus-gobject.c
===================================================================
RCS file: /cvs/dbus/dbus/glib/dbus-gobject.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -d -r1.12 -r1.13
--- dbus-gobject.c	16 Jan 2005 15:51:55 -0000	1.12
+++ dbus-gobject.c	29 Jan 2005 19:52:19 -0000	1.13
@@ -198,28 +198,27 @@
 
       s = uscore_to_wincaps (spec->name);
       
-      if (can_set)
+      if (can_set || can_get)
         {
-          g_string_append (xml, "    <method name=\"set_");
+          g_string_append (xml, "    <property name=\"");
           g_string_append (xml, s);
-          g_string_append (xml, "\">\n");
-          
-          g_string_append (xml, "      <arg type=\"");
+          g_string_append (xml, "\" type=\"");
           g_string_append (xml, _dbus_gutils_type_to_string (dbus_type));
-          g_string_append (xml, "\"/>\n");
-        }
+          g_string_append (xml, "\" access=\"\n");
 
-      if (can_get)
-        {
-          g_string_append (xml, "    <method name=\"get_");
-          g_string_append (xml, s);
-          g_string_append (xml, "\">\n");
+          if (can_set && can_get)
+            g_string_append (xml, "readwrite");
+          else if (can_get)
+            g_string_append (xml, "read");
+          else
+            {
+              g_assert (can_set);
+              g_string_append (xml, "write");
+            }
           
-          g_string_append (xml, "      <arg type=\"");
-          g_string_append (xml, _dbus_gutils_type_to_string (dbus_type));
-          g_string_append (xml, "\" direction=\"out\"/>\n");
+          g_string_append (xml, "\">\n");
         }
-
+      
       g_free (s);
     }
 
@@ -290,10 +289,10 @@
   
   xml = g_string_new (NULL);
 
+  g_string_append (xml, "<node>\n");
+  
   introspect_signals (G_OBJECT_TYPE (object), xml);
   introspect_properties (object, xml);
-	  
-  g_string_append (xml, "<node>\n");
 
   /* Append child nodes */
   for (i = 0; children[i]; i++)
@@ -322,23 +321,24 @@
 }
 
 static DBusMessage*
-set_object_property (DBusConnection *connection,
-                     DBusMessage    *message,
-                     GObject        *object,
-                     GParamSpec     *pspec)
+set_object_property (DBusConnection  *connection,
+                     DBusMessage     *message,
+                     DBusMessageIter *iter,
+                     GObject         *object,
+                     GParamSpec      *pspec)
 {
   GValue value = { 0, };
   DBusMessage *ret;
-  DBusMessageIter iter;
-
-  dbus_message_iter_init (message, &iter);
+  DBusMessageIter sub;
 
+  dbus_message_iter_recurse (iter, &sub);
+  
   /* The g_object_set_property() will transform some types, e.g. it
    * will let you use a uchar to set an int property etc. Note that
    * any error in value range or value conversion will just
    * g_warning(). These GObject skels are not for secure applications.
    */
-  if (dbus_gvalue_demarshal (&iter, &value))
+  if (dbus_gvalue_demarshal (&sub, &value))
     {
       g_object_set_property (object,
                              pspec->name,
@@ -405,10 +405,12 @@
   const DBusGObjectInfo *info;
   GParamSpec *pspec;
   GObject *object;
-  const char *member;
   gboolean setter;
   gboolean getter;
   char *s;
+  const char *wincaps_propname;
+  const char *wincaps_propiface;
+  DBusMessageIter iter;
 
   object = G_OBJECT (user_data);
 
@@ -417,8 +419,6 @@
                                    "Introspect"))
     return handle_introspect (connection, message, object);
 
-  member = dbus_message_get_member (message);
-
   /* Try the metainfo, which lets us invoke methods */
 
   g_static_mutex_lock (&info_hash_mutex);
@@ -439,13 +439,39 @@
   /* If no metainfo, we can still do properties and signals
    * via standard GLib introspection
    */
-  setter = (member[0] == 's' && member[1] == 'e' && member[2] == 't' && member[3] == '_');
-  getter = (member[0] == 'g' && member[1] == 'e' && member[2] == 't' && member[3] == '_');
+  getter = FALSE;
+  setter = FALSE;
+  if (dbus_message_is_method_call (message,
+                                   DBUS_INTERFACE_ORG_FREEDESKTOP_PROPERTIES,
+                                   "Get"))
+    getter = TRUE;
+  else if (dbus_message_is_method_call (message,
+                                        DBUS_INTERFACE_ORG_FREEDESKTOP_PROPERTIES,
+                                        "Set"))
+    setter = TRUE;
 
   if (!(setter || getter))
     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
 
-  s = wincaps_to_uscore (&member[4]);
+  dbus_message_iter_init (message, &iter);
+
+  if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRING)
+    {
+      g_warning ("Property get or set does not have an interface string as first arg\n");
+      return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+    }
+  dbus_message_iter_get_basic (&iter, &wincaps_propiface);
+  dbus_message_iter_next (&iter);
+
+  if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRING)
+    {
+      g_warning ("Property get or set does not have a property name string as second arg\n");
+      return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+    }
+  dbus_message_iter_get_basic (&iter, &wincaps_propname);
+  dbus_message_iter_next (&iter);
+  
+  s = wincaps_to_uscore (wincaps_propname);
 
   pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object),
                                         s);
@@ -458,11 +484,18 @@
 
       if (setter)
         {
-          ret = set_object_property (connection, message,
+          if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_VARIANT)
+            {
+              g_warning ("Property set does not have a variant value as third arg\n");
+              return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+            }
+          
+          ret = set_object_property (connection, message, &iter,
                                      object, pspec);
+          dbus_message_iter_next (&iter);
         }
       else if (getter)
-        {
+        {     
           ret = get_object_property (connection, message,
                                      object, pspec);
         }
@@ -474,6 +507,9 @@
 
       g_assert (ret != NULL);
 
+      if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INVALID)
+        g_warning ("Property get or set had too many arguments\n");
+      
       dbus_connection_send (connection, ret, NULL);
       dbus_message_unref (ret);
       return DBUS_HANDLER_RESULT_HANDLED;

Index: dbus-gparser.c
===================================================================
RCS file: /cvs/dbus/dbus/glib/dbus-gparser.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- dbus-gparser.c	28 Jan 2005 03:06:56 -0000	1.7
+++ dbus-gparser.c	29 Jan 2005 19:52:19 -0000	1.8
@@ -1,7 +1,7 @@
 /* -*- mode: C; c-file-style: "gnu" -*- */
 /* dbus-gparser.c parse DBus description files
  *
- * Copyright (C) 2003  Red Hat, Inc.
+ * Copyright (C) 2003, 2005  Red Hat, Inc.
  *
  * Licensed under the Academic Free License version 2.1
  * 
@@ -169,6 +169,7 @@
   InterfaceInfo *interface;
   MethodInfo *method;
   SignalInfo *signal;
+  PropertyInfo *property;
   ArgInfo *arg;
 };
 
@@ -238,11 +239,12 @@
   if (parser->interface ||
       parser->method ||
       parser->signal ||
+      parser->property ||
       parser->arg)
     {
       g_set_error (error, G_MARKUP_ERROR,
                    G_MARKUP_ERROR_PARSE,
-                   _("Can't put a <%s> element here"),
+                   _("Can't put <%s> element here"),
                    element_name);
       return FALSE;      
     }
@@ -264,6 +266,25 @@
       return FALSE;
     }
 
+  /* Root element name must be absolute */
+  if (parser->node_stack == NULL && name && *name != '/')
+    {
+      g_set_error (error, G_MARKUP_ERROR,
+                   G_MARKUP_ERROR_PARSE,
+                   _("\"%s\" attribute on <%s> element must be an absolute object path, \"%s\" not OK"),
+                   "name", element_name, name);
+      return FALSE;
+    }
+
+  /* Other element names must not be absolute */
+  if (parser->node_stack != NULL && name && *name == '/')
+    {
+      g_set_error (error, G_MARKUP_ERROR,
+                   G_MARKUP_ERROR_PARSE,
+                   _("\"%s\" attribute on <%s> element must not be an absolute object path, \"%s\" starts with /"),
+                   "name", element_name, name);
+      return FALSE;
+    }
   
   node = node_info_new (name);
 
@@ -293,12 +314,13 @@
   if (parser->interface ||
       parser->method ||
       parser->signal ||
+      parser->property ||
       parser->arg ||
       (parser->node_stack == NULL))
     {
       g_set_error (error, G_MARKUP_ERROR,
                    G_MARKUP_ERROR_PARSE,
-                   _("Can't put a <%s> element here"),
+                   _("Can't put <%s> element here"),
                    element_name);
       return FALSE;      
     }
@@ -345,11 +367,12 @@
       parser->node_stack == NULL ||
       parser->method ||
       parser->signal ||
+      parser->property ||
       parser->arg)
     {
       g_set_error (error, G_MARKUP_ERROR,
                    G_MARKUP_ERROR_PARSE,
-                   _("Can't put a <%s> element here"),
+                   _("Can't put <%s> element here"),
                    element_name);
       return FALSE;      
     }
@@ -395,12 +418,13 @@
   if (parser->interface == NULL ||
       parser->node_stack == NULL ||
       parser->signal ||
-      parser->signal ||
+      parser->method ||
+      parser->property ||
       parser->arg)
     {
       g_set_error (error, G_MARKUP_ERROR,
                    G_MARKUP_ERROR_PARSE,
-                   _("Can't put a <%s> element here"),
+                   _("Can't put <%s> element here"),
                    element_name);
       return FALSE;      
     }
@@ -463,10 +487,122 @@
     return DBUS_TYPE_INVALID;
 }
 
+/* FIXME we have to allow type signatures, not just basic types
+ */
 static int
-type_from_string (const char *str)
+type_from_string (const char *str,
+                  const char *element_name,
+                  GError    **error)
 {
-  return basic_type_from_string (str);
+  int t;
+  
+  t = basic_type_from_string (str);
+
+  if (t == DBUS_TYPE_INVALID)
+    {
+      g_set_error (error, G_MARKUP_ERROR,
+                   G_MARKUP_ERROR_PARSE,
+                   _("Type \"%s\" not understood on <%s> element "),
+                   str, element_name);
+    }
+
+  return t;
+}
+
+static gboolean
+parse_property (Parser      *parser,
+                const char  *element_name,
+                const char **attribute_names,
+                const char **attribute_values,
+                GError     **error)
+{
+  const char *name;
+  const char *access;
+  const char *type;
+  PropertyInfo *property;
+  NodeInfo *top;
+  PropertyAccessFlags access_flags;
+  int t;
+  
+  if (parser->interface == NULL ||
+      parser->node_stack == NULL ||
+      parser->signal ||
+      parser->method ||
+      parser->property ||
+      parser->arg)
+    {
+      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,
+                          "access", &access,
+                          "type", &type,
+                          NULL))
+    return FALSE;
+
+  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 (access == NULL)
+    {
+      g_set_error (error, G_MARKUP_ERROR,
+                   G_MARKUP_ERROR_PARSE,
+                   _("\"%s\" attribute required on <%s> element "),
+                   "access", element_name);
+      return FALSE;
+    }
+
+  if (type == NULL)
+    {
+      g_set_error (error, G_MARKUP_ERROR,
+                   G_MARKUP_ERROR_PARSE,
+                   _("\"%s\" attribute required on <%s> element "),
+                   "type", element_name);
+      return FALSE;
+    }
+
+  t = type_from_string (type, element_name, error);
+  if (t == DBUS_TYPE_INVALID)
+    return FALSE;
+
+  access_flags = 0;
+  if (strcmp (access, "readwrite") == 0)
+    access_flags = PROPERTY_READ | PROPERTY_WRITE;
+  else if (strcmp (access, "read") == 0)
+    access_flags = PROPERTY_READ;
+  else if (strcmp (access, "write") == 0)
+    access_flags = PROPERTY_WRITE;
+  else
+    {
+      g_set_error (error, G_MARKUP_ERROR,
+                   G_MARKUP_ERROR_PARSE,
+                   _("access=\"%s\" must have value readwrite, read, or write on %s\n"),
+                   access, element_name);
+      return FALSE;
+    }
+  
+  top = parser->node_stack->data;
+  
+  property = property_info_new (name, t, access_flags);
+  interface_info_add_property (parser->interface, property);
+  property_info_unref (property);
+
+  parser->property = property;
+  
+  return TRUE;
 }
 
 static gboolean
@@ -485,11 +621,12 @@
   
   if (!(parser->method || parser->signal) ||
       parser->node_stack == NULL ||
+      parser->property ||
       parser->arg)
     {
       g_set_error (error, G_MARKUP_ERROR,
                    G_MARKUP_ERROR_PARSE,
-                   _("Can't put a <%s> element here"),
+                   _("Can't put <%s> element here"),
                    element_name);
       return FALSE;      
     }
@@ -525,20 +662,31 @@
         g_assert_not_reached ();
     }
 
+  dir = ARG_INVALID;
+  
   if (strcmp (direction, "in") == 0)
     dir = ARG_IN;
   else if (strcmp (direction, "out") == 0)
     dir = ARG_OUT;
-  else
+  
+  if (dir == ARG_INVALID ||
+      (parser->signal && dir == ARG_IN))
     {
-      g_set_error (error, G_MARKUP_ERROR,
-                   G_MARKUP_ERROR_PARSE,
-                   _("\"%s\" attribute on <%s> has value \"in\" or \"out\""),
-                   "direction", element_name);
+      if (parser->signal)
+        g_set_error (error, G_MARKUP_ERROR,
+                     G_MARKUP_ERROR_PARSE,
+                     _("Signals must have direction=\"out\" (just omit the direction attribute)"));
+      else
+        g_set_error (error, G_MARKUP_ERROR,
+                     G_MARKUP_ERROR_PARSE,
+                     _("\"%s\" attribute on <%s> has value \"in\" or \"out\""),
+                     "direction", element_name);
       return FALSE;
     }
 
-  t = type_from_string (type);
+  t = type_from_string (type, element_name, error);
+  if (t == DBUS_TYPE_INVALID)
+    return FALSE;
   
   arg = arg_info_new (name, dir, t);
   if (parser->method)
@@ -588,6 +736,12 @@
                          attribute_values, error))
         return FALSE;
     }
+  else if (ELEMENT_IS ("property"))
+    {
+      if (!parse_property (parser, element_name, attribute_names,
+                           attribute_values, error))
+        return FALSE;
+    }
   else if (ELEMENT_IS ("arg"))
     {
       if (!parse_arg (parser, element_name, attribute_names,
@@ -624,6 +778,10 @@
     {
       parser->signal = NULL;
     }
+  else if (ELEMENT_IS ("property"))
+    {
+      parser->property = NULL;
+    }
   else if (ELEMENT_IS ("arg"))
     {
       parser->arg = NULL;
@@ -655,6 +813,8 @@
 {
   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
+  /* FIXME check that it's all whitespace */
+  
   return TRUE;
 }
 



More information about the dbus-commit mailing list