Hi all,

Given the lack of eina_simple_xml (sax-parser) examples and the recent
usage of expat in elev8 I'm sending the attached example so people will see
how to parse xml using super-fast SAX and create an efficient custom memory
structure from it.

It looks complex if you compare to a DOM like parser (that eina_simple_xml
also provides), but this one is very efficient and will provide proper
structures for easy access, you do not have to repeat queries over generic
tree nodes.

I've tested this one with org.bluez and net.connman, both worked all right.

Hope it helps!

-- 
Gustavo Sverzut Barbieri
http://profusion.mobi embedded systems
--------------------------------------
MSN: barbi...@gmail.com
Skype: gsbarbieri
Mobile: +55 (19) 9225-2202
#include <Eina.h>
#include <E_DBus.h>
#include <Ecore.h>

/* memory efficient structures to hold introspection information.
 * maybe Eina_Inlist could be replaced with single array of structures
 * (not to be confused with Eina_Array!!!!)
 */

struct DBus_Method_Argument
{
   EINA_INLIST;
   const char *type;
   const char *name;
   Eina_Bool is_output:1;
};

struct DBus_Method
{
   EINA_INLIST;
   const char *name;
   Eina_Inlist *arguments;
};

struct DBus_Signal_Argument
{
   EINA_INLIST;
   const char *type;
   const char *name;
};

struct DBus_Signal
{
   EINA_INLIST;
   const char *name;
   Eina_Inlist *arguments;
};

struct DBus_Property
{
   EINA_INLIST;
   const char *name;
   const char *type;
   Eina_Bool can_read:1;
   Eina_Bool can_write:1;
};

struct DBus_Interface
{
   EINA_INLIST;
   const char *name;
   Eina_Inlist *methods;
   Eina_Inlist *signals;
   Eina_Inlist *properties;
};

struct DBus_Node
{
   EINA_INLIST;
   const char *name;
   Eina_Inlist *interfaces;
   Eina_Inlist *children;
};

struct DBus_Introspection_Parse_Ctxt
{
   struct DBus_Node *node;
   struct DBus_Interface *interface;
   struct DBus_Method *method;
   struct DBus_Signal *signal;
   Eina_Inlist *nodes;
};

static void print_indent(unsigned indent, FILE *fp)
{
   unsigned i;
   for (i = 0; i < indent; i++)
     putc('\t', fp);
}

static Eina_Bool cb_parse_method_argument_attributes(void *data, const char *key, const char *value)
{
   struct DBus_Method_Argument *ma = data;

   if (strcmp(key, "name") == 0)
     eina_stringshare_replace(&ma->name, value);
   else if (strcmp(key, "type") == 0)
     eina_stringshare_replace(&ma->type, value);
   else if (strcmp(key, "direction") == 0)
     {
        if (strcmp(value, "out") == 0)
          ma->is_output = EINA_TRUE;
        else if (strcmp(value, "in") == 0)
          ma->is_output = EINA_FALSE;
        else
          {
             fprintf(stderr, "Error: unknown method argument direction %s\n",
                     value);
             return EINA_FALSE;
          }
     }
   else
     {
        fprintf(stderr, "Error: unknown method argument attribute %s=%s\n",
                key, value);
        return EINA_FALSE;
     }

   return EINA_TRUE;
}

static Eina_Bool parse_method_argument(struct DBus_Method *m, const char *attrs, unsigned length)
{
   struct DBus_Method_Argument *ma;

   ma = calloc(1, sizeof(struct DBus_Method_Argument));
   if (!ma)
     {
        fprintf(stderr, "Error: could not allocate memory\n");
        return EINA_FALSE;
     }

   if (!eina_simple_xml_attributes_parse
       (attrs, length, cb_parse_method_argument_attributes, ma))
     {
        fprintf(stderr, "Error: could not parse method argument attributes\n");
        eina_stringshare_del(ma->name);
        eina_stringshare_del(ma->type);
        free(ma);
        return EINA_FALSE;
     }

   if (!ma->type)
     {
        fprintf(stderr, "Error: method argument must have a type!\n");
        eina_stringshare_del(ma->name);
        eina_stringshare_del(ma->type);
        free(ma);
        return EINA_FALSE;
     }

   m->arguments = eina_inlist_append(m->arguments, EINA_INLIST_GET(ma));
   return EINA_TRUE;
}

static void free_method_argument(struct DBus_Method_Argument *ma)
{
   eina_stringshare_del(ma->type);
   eina_stringshare_del(ma->name);
   free(ma);
}

static void print_method_argument(const struct DBus_Method_Argument *ma, unsigned indent, FILE *fp)
{
   print_indent(indent, fp);
   fprintf(fp, "Argument: type: %s, direction: %s, name: %s\n",
           ma->type, ma->is_output ? "out" : "in", ma->name ? ma->name : "");
}

static Eina_Bool cb_parse_method_attributes(void *data, const char *key, const char *value)
{
   struct DBus_Method *m = data;
   if (strcmp(key, "name") != 0) return EINA_FALSE;

   eina_stringshare_replace(&m->name, value);
   return EINA_TRUE;
}

static struct DBus_Method *parse_method(const char *attrs, unsigned length)
{
   struct DBus_Method *m = calloc(1, sizeof(struct DBus_Method));
   if (!m)
     {
        fprintf(stderr, "Error: could not allocate memory\n");
        return NULL;
     }

   if (!eina_simple_xml_attributes_parse
       (attrs, length, cb_parse_method_attributes, m))
     {
        fprintf(stderr, "Error: could not parse method attributes\n");
        free(m);
        return NULL;
     }

   if (!m->name)
     {
        fprintf(stderr, "Error: method must have a name!\n");
        free(m);
        return NULL;
     }

   return m;
}

static void free_method(struct DBus_Method *m)
{
   while (m->arguments)
     {
        struct DBus_Method_Argument *tmp = EINA_INLIST_CONTAINER_GET
          (m->arguments, struct DBus_Method_Argument);
        m->arguments = m->arguments->next;
        free_method_argument(tmp);
     }

   eina_stringshare_del(m->name);
   free(m);
}

static void print_method(const struct DBus_Method *m, unsigned indent, FILE *fp)
{
   print_indent(indent, fp);
   fprintf(fp, "Method: name: %s\n", m->name);

   if (m->arguments)
     {
        const struct DBus_Method_Argument *ma;

        print_indent(indent + 1, fp);
        fprintf(fp, "Arguments:\n");
        EINA_INLIST_FOREACH(m->arguments, ma)
          print_method_argument(ma, indent + 2, fp);
     }
}

static Eina_Bool cb_parse_signal_argument_attributes(void *data, const char *key, const char *value)
{
   struct DBus_Signal_Argument *sa = data;

   if (strcmp(key, "name") == 0)
     eina_stringshare_replace(&sa->name, value);
   else if (strcmp(key, "type") == 0)
     eina_stringshare_replace(&sa->type, value);
   else
     {
        fprintf(stderr, "Error: unknown signal argument attribute %s=%s\n",
                key, value);
        return EINA_FALSE;
     }

   return EINA_TRUE;
}

static Eina_Bool parse_signal_argument(struct DBus_Signal *s, const char *attrs, unsigned length)
{
   struct DBus_Signal_Argument *sa;

   sa = calloc(1, sizeof(struct DBus_Signal_Argument));
   if (!sa)
     {
        fprintf(stderr, "Error: could not allocate memory\n");
        return EINA_FALSE;
     }

   if (!eina_simple_xml_attributes_parse
       (attrs, length, cb_parse_signal_argument_attributes, sa))
     {
        fprintf(stderr, "Error: could not parse signal argument attributes\n");
        eina_stringshare_del(sa->name);
        eina_stringshare_del(sa->type);
        free(sa);
        return EINA_FALSE;
     }

   if (!sa->type)
     {
        fprintf(stderr, "Error: signal argument must have a type!\n");
        eina_stringshare_del(sa->name);
        eina_stringshare_del(sa->type);
        free(sa);
        return EINA_FALSE;
     }

   s->arguments = eina_inlist_append(s->arguments, EINA_INLIST_GET(sa));
   return EINA_TRUE;
}

static void free_signal_argument(struct DBus_Signal_Argument *sa)
{
   eina_stringshare_del(sa->type);
   eina_stringshare_del(sa->name);
   free(sa);
}

static void print_signal_argument(const struct DBus_Signal_Argument *sa, unsigned indent, FILE *fp)
{
   print_indent(indent, fp);
   fprintf(fp, "Argument: type: %s, name: %s\n",
           sa->type, sa->name ? sa->name : "");
}

static Eina_Bool cb_parse_signal_attributes(void *data, const char *key, const char *value)
{
   struct DBus_Signal *s = data;
   if (strcmp(key, "name") != 0) return EINA_FALSE;

   eina_stringshare_replace(&s->name, value);
   return EINA_TRUE;
}

static struct DBus_Signal *parse_signal(const char *attrs, unsigned length)
{
   struct DBus_Signal *s = calloc(1, sizeof(struct DBus_Signal));
   if (!s)
     {
        fprintf(stderr, "Error: could not allocate memory\n");
        return NULL;
     }

   if (!eina_simple_xml_attributes_parse
       (attrs, length, cb_parse_signal_attributes, s))
     {
        fprintf(stderr, "Error: could not parse signal attributes\n");
        free(s);
        return NULL;
     }

   if (!s->name)
     {
        fprintf(stderr, "Error: signal must have a name!\n");
        free(s);
        return NULL;
     }

   return s;
}

static void free_signal(struct DBus_Signal *s)
{
   while (s->arguments)
     {
        struct DBus_Signal_Argument *tmp = EINA_INLIST_CONTAINER_GET
          (s->arguments, struct DBus_Signal_Argument);
        s->arguments = s->arguments->next;
        free_signal_argument(tmp);
     }

   eina_stringshare_del(s->name);
   free(s);
}

static void print_signal(const struct DBus_Signal *s, unsigned indent, FILE *fp)
{
   print_indent(indent, fp);
   fprintf(fp, "Signal: name: %s\n", s->name);

   if (s->arguments)
     {
        const struct DBus_Signal_Argument *sa;

        print_indent(indent + 1, fp);
        fprintf(fp, "Arguments:\n");
        EINA_INLIST_FOREACH(s->arguments, sa)
          print_signal_argument(sa, indent + 2, fp);
     }
}

static Eina_Bool cb_parse_property_attributes(void *data, const char *key, const char *value)
{
   struct DBus_Property *p = data;
   if (strcmp(key, "name") == 0)
     eina_stringshare_replace(&p->name, value);
   else if (strcmp(key, "type") == 0)
     eina_stringshare_replace(&p->type, value);
   else if (strcmp(key, "access") == 0)
     {
        if (strcmp(value, "read") == 0)
          {
             p->can_read = EINA_TRUE;
             p->can_write = EINA_FALSE;
          }
        else if (strcmp(value, "write") == 0)
          {
             p->can_read = EINA_FALSE;
             p->can_write = EINA_TRUE;
          }
        else if (strcmp(value, "readwrite") == 0)
          {
             p->can_read = EINA_TRUE;
             p->can_write = EINA_TRUE;
          }
        else
          {
             fprintf(stderr, "Error: unknown access value '%s'\n", value);
             return EINA_FALSE;
          }
     }
   else
     {
        fprintf(stderr, "Error: unknown property attribute %s=%s\n",
                key, value);
        return EINA_FALSE;
     }

   return EINA_TRUE;
}

static struct DBus_Property *parse_property(const char *attrs, unsigned length)
{
   struct DBus_Property *p = calloc(1, sizeof(struct DBus_Property));
   if (!p)
     {
        fprintf(stderr, "Error: could not allocate memory\n");
        return NULL;
     }

   p->can_read = EINA_TRUE;
   p->can_write = EINA_TRUE;
   if (!eina_simple_xml_attributes_parse
       (attrs, length, cb_parse_property_attributes, p))
     {
        fprintf(stderr, "Error: could not parse property attributes\n");
        free(p);
        return NULL;
     }

   if (!p->name)
     {
        fprintf(stderr, "Error: property must have a name!\n");
        free(p);
        return NULL;
     }

   return p;
}

static void free_property(struct DBus_Property *p)
{
   eina_stringshare_del(p->name);
   eina_stringshare_del(p->type);
   free(p);
}

static void print_property(const struct DBus_Property *p, unsigned indent, FILE *fp)
{
   print_indent(indent, fp);
   fprintf(fp, "Property: name: %s, type: %s, read: %hhu, write: %hhu\n",
           p->name, p->type, p->can_read, p->can_write);
}

static Eina_Bool cb_parse_interface_attributes(void *data, const char *key, const char *value)
{
   struct DBus_Interface *i = data;
   if (strcmp(key, "name") != 0) return EINA_FALSE;

   eina_stringshare_replace(&i->name, value);
   return EINA_TRUE;
}

static struct DBus_Interface *parse_interface(const char *attrs, unsigned length)
{
   struct DBus_Interface *i = calloc(1, sizeof(struct DBus_Interface));
   if (!i)
     {
        fprintf(stderr, "Error: could not allocate memory\n");
        return NULL;
     }

   if (!eina_simple_xml_attributes_parse
       (attrs, length, cb_parse_interface_attributes, i))
     {
        fprintf(stderr, "Error: could not parse interface attributes\n");
        free(i);
        return NULL;
     }

   if (!i->name)
     {
        fprintf(stderr, "Error: interface must have a name!\n");
        free(i);
        return NULL;
     }

   return i;
}

static void free_interface(struct DBus_Interface *i)
{
   while (i->methods)
     {
        struct DBus_Method *tmp = EINA_INLIST_CONTAINER_GET
          (i->methods, struct DBus_Method);
        i->methods = i->methods->next;
        free_method(tmp);
     }

   while (i->signals)
     {
        struct DBus_Signal *tmp = EINA_INLIST_CONTAINER_GET
          (i->signals, struct DBus_Signal);
        i->signals = i->signals->next;
        free_signal(tmp);
     }

   while (i->properties)
     {
        struct DBus_Property *tmp = EINA_INLIST_CONTAINER_GET
          (i->properties, struct DBus_Property);
        i->properties = i->properties->next;
        free_property(tmp);
     }

   eina_stringshare_del(i->name);
   free(i);
}

static void print_interface(const struct DBus_Interface *i, unsigned indent, FILE *fp)
{
   print_indent(indent, fp);
   fprintf(fp, "Interface: %s\n", i->name);

   if (i->methods)
     {
        const struct DBus_Method *m;

        print_indent(indent + 1, fp);
        fprintf(fp, "Methods:\n");
        EINA_INLIST_FOREACH(i->methods, m)
          print_method(m, indent + 2, fp);
     }

   if (i->signals)
     {
        const struct DBus_Signal *m;

        print_indent(indent + 1, fp);
        fprintf(fp, "Signals:\n");
        EINA_INLIST_FOREACH(i->signals, m)
          print_signal(m, indent + 2, fp);
     }

   if (i->properties)
     {
        const struct DBus_Property *m;

        print_indent(indent + 1, fp);
        fprintf(fp, "Propertys:\n");
        EINA_INLIST_FOREACH(i->properties, m)
          print_property(m, indent + 2, fp);
     }
}

static Eina_Bool cb_parse_node_attributes(void *data, const char *key, const char *value)
{
   struct DBus_Node *n = data;
   if (strcmp(key, "name") != 0) return EINA_FALSE;

   eina_stringshare_replace(&n->name, value);
   return EINA_TRUE;
}

static struct DBus_Node *parse_node(const char *attrs, unsigned length)
{
   struct DBus_Node *n = calloc(1, sizeof(struct DBus_Node));
   if (!n)
     {
        fprintf(stderr, "Error: could not allocate memory\n");
        return NULL;
     }

   if (!attrs) return n;

   if (!eina_simple_xml_attributes_parse
       (attrs, length, cb_parse_node_attributes, n))
     {
        fprintf(stderr, "Error: could not parse node attributes\n");
        free(n);
        return NULL;
     }

   return n;
}

static void free_node(struct DBus_Node *n)
{
   while (n->children)
     {
        struct DBus_Node *tmp = EINA_INLIST_CONTAINER_GET
          (n->children, struct DBus_Node);
        n->children = n->children->next;
        free_node(tmp);
     }

   while (n->interfaces)
     {
        struct DBus_Interface *tmp = EINA_INLIST_CONTAINER_GET
          (n->interfaces, struct DBus_Interface);
        n->interfaces = n->interfaces->next;
        free_interface(tmp);
     }

   eina_stringshare_del(n->name);
   free(n);
}

static void print_node(const struct DBus_Node *n, unsigned indent, FILE *fp)
{
   print_indent(indent, fp);
   fprintf(fp, "Node: %s\n", n->name ? n->name : "");

   if (n->children)
     {
        const struct DBus_Node *c;

        print_indent(indent + 1, fp);
        fprintf(fp, "Children:\n");
        EINA_INLIST_FOREACH(n->children, c)
          print_node(c, indent + 2, fp);
     }

   if (n->interfaces)
     {
        const struct DBus_Interface *i;

        print_indent(indent + 1, fp);
        fprintf(fp, "Interfaces:\n");

        EINA_INLIST_FOREACH(n->interfaces, i)
          print_interface(i, indent + 2, fp);
     }
}

static Eina_Bool cb_parse(void *data, Eina_Simple_XML_Type type, const char *content, unsigned offset, unsigned length)
{
   struct DBus_Introspection_Parse_Ctxt *ctxt = data;

   switch (type)
     {
      case EINA_SIMPLE_XML_OPEN:
      case EINA_SIMPLE_XML_OPEN_EMPTY:
        {
           /* split tag name and attributes */
           const char *attrs = eina_simple_xml_tag_attributes_find
             (content, length);
           unsigned attrslen = 0;
           int sz = length;
           if (attrs)
             {
                attrslen = length - (attrs - content);
                sz = attrs - content;
                while ((sz > 0) && (isspace(content[sz - 1])))
                  sz--;
             }

           if (!ctxt->node)
             {
                if (strncmp("node", content, sz) != 0)
                  {
                     fprintf(stderr, "Error: expected <node>, got %.*s\n",
                             length, content);
                     return EINA_FALSE;
                  }

                ctxt->node = parse_node(attrs, attrslen);
                if (!ctxt->node) return EINA_FALSE;
                ctxt->nodes = eina_inlist_append
                  (ctxt->nodes, EINA_INLIST_GET(ctxt->node));
             }
           else
             {
                if (strncmp("node", content, sz) == 0)
                  {
                     struct DBus_Node *n = parse_node(attrs, attrslen);
                     if (!n) return EINA_FALSE;
                     ctxt->node->children = eina_inlist_append
                       (ctxt->node->children, EINA_INLIST_GET(n));

                     if (type != EINA_SIMPLE_XML_OPEN_EMPTY)
                       ctxt->node = n;
                  }
                else if (strncmp("interface", content, sz) == 0)
                  {
                     if (!ctxt->node)
                       {
                          fprintf(stderr,
                                  "Error: cannot have <%.*s> outside <node>!\n",
                                  length, content);
                          return EINA_FALSE;
                       }

                     ctxt->interface = parse_interface(attrs, attrslen);
                     if (!ctxt->interface) return EINA_FALSE;
                     ctxt->node->interfaces = eina_inlist_append
                       (ctxt->node->interfaces, EINA_INLIST_GET(ctxt->interface));
                  }
                else if (strncmp("method", content, sz) == 0)
                  {
                     struct DBus_Method *m;

                     if (!ctxt->interface)
                       {
                          fprintf(stderr,
                                  "Error: cannot have <%.*s> outside "
                                  "<interface>!\n",
                                  length, content);
                          return EINA_FALSE;
                       }

                     m = parse_method(attrs, attrslen);
                     if (!m) return EINA_FALSE;
                     ctxt->interface->methods = eina_inlist_append
                       (ctxt->interface->methods, EINA_INLIST_GET(m));

                     if (type != EINA_SIMPLE_XML_OPEN_EMPTY)
                       ctxt->method = m;
                  }
                else if (strncmp("signal", content, sz) == 0)
                  {
                     struct DBus_Signal *s;

                     if (!ctxt->interface)
                       {
                          fprintf(stderr,
                                  "Error: cannot have <%.*s> outside "
                                  "<interface>!\n",
                                  length, content);
                          return EINA_FALSE;
                       }

                     s = parse_signal(attrs, attrslen);
                     if (!s) return EINA_FALSE;
                     ctxt->interface->signals = eina_inlist_append
                       (ctxt->interface->signals, EINA_INLIST_GET(s));

                     if (type != EINA_SIMPLE_XML_OPEN_EMPTY)
                       ctxt->signal = s;
                  }
                else if (strncmp("property", content, sz) == 0)
                  {
                     struct DBus_Property *p;

                     if (!ctxt->interface)
                       {
                          fprintf(stderr,
                                  "Error: cannot have <%.*s> outside "
                                  "<interface>!\n",
                                  length, content);
                          return EINA_FALSE;
                       }

                     p = parse_property(attrs, attrslen);
                     if (!p) return EINA_FALSE;
                     ctxt->interface->properties = eina_inlist_append
                       (ctxt->interface->properties, EINA_INLIST_GET(p));
                  }
                else if (strncmp("arg", content, sz) == 0)
                  {
                     if (ctxt->method)
                       {
                          if (!parse_method_argument
                              (ctxt->method, attrs, attrslen))
                            {
                               fprintf(stderr,
                                       "Error: cannot parse method's <%.*s>\n",
                                       length, content);
                               return EINA_FALSE;
                            }
                       }
                     else if (ctxt->signal)
                       {
                          if (!parse_signal_argument
                              (ctxt->signal, attrs, attrslen))
                            {
                               fprintf(stderr,
                                       "Error: cannot parse signal's <%.*s>\n",
                                       length, content);
                               return EINA_FALSE;
                            }
                       }
                     else
                       {
                          fprintf(stderr,
                                  "Error: cannot have <%.*s> outside "
                                  "<method> or <signal>!\n",
                                  length, content);
                          return EINA_FALSE;
                       }
                  }
                else
                  {
                     fprintf(stderr, "Error: unexpected element <%.*s>\n",
                             length, content);
                     return EINA_FALSE;
                  }
             }
        }
        break;
      case EINA_SIMPLE_XML_CLOSE:
         if (strncmp("node", content, length) == 0)
           ctxt->node = NULL;
         else if (strncmp("interface", content, length) == 0)
           ctxt->interface = NULL;
         else if (strncmp("method", content, length) == 0)
           ctxt->method = NULL;
         else if (strncmp("signal", content, length) == 0)
           ctxt->signal = NULL;
         break;
      case EINA_SIMPLE_XML_DATA:
      case EINA_SIMPLE_XML_CDATA:
      case EINA_SIMPLE_XML_PROCESSING:
      case EINA_SIMPLE_XML_DOCTYPE:
      case EINA_SIMPLE_XML_COMMENT:
      case EINA_SIMPLE_XML_IGNORED:
#ifdef VERBOSE
         fprintf(stderr, "Ignored: contents at offset %u-%u: %.*s\n",
                 offset, length, length, content);
#endif
         break;
      case EINA_SIMPLE_XML_ERROR:
         fprintf(stderr, "Error: parser error at offset %u-%u: %.*s\n",
                 offset, length, length, content);
         break;
     }

   return EINA_TRUE;
}

static void cb_introspect(void *data, DBusMessage *msg, DBusError *error)
{
   DBusError e;
   Eina_Inlist **p_nodes = data;
   struct DBus_Introspection_Parse_Ctxt ctxt;
   const char *xml_str;

   if ((error) && (dbus_error_is_set(error)))
     {
        fprintf(stderr, "Error: DBus replied with error %s: %s\n",
                error->name, error->message);
        goto end;
     }

   dbus_error_init(&e);
   if (!dbus_message_get_args(msg, &e, DBUS_TYPE_STRING, &xml_str,
                              DBUS_TYPE_INVALID))
     {
        fprintf(stderr, "Error: could not get arguments %s: %s\n",
                e.name, e.message);
        goto end;
     }

   memset(&ctxt, 0, sizeof(ctxt));
   if (!eina_simple_xml_parse(xml_str, strlen(xml_str), EINA_TRUE, cb_parse,
                              &ctxt))
     {
        fprintf(stderr, "Error: could not parse XML:\n%s\n", xml_str);
        goto end;
     }

   puts("Introspection was successful");
   *p_nodes = ctxt.nodes;

 end:
   ecore_main_loop_quit();
}

int main(int argc, char *argv[])
{
   E_DBus_Connection *conn;
   Eina_Inlist *nodes = NULL;

   if (argc != 4)
     {
        fprintf(stderr,
                "Usage:\n"
                "\t%s <system|session> <name> <path>\n"
                "\n",
                argv[0]);
        return 1;
     }

   eina_init();
   ecore_init();
   e_dbus_init();

   if (strcmp(argv[1], "system") == 0)
     conn = e_dbus_bus_get(DBUS_BUS_SYSTEM);
   else if (strcmp(argv[1], "session") == 0)
     conn = e_dbus_bus_get(DBUS_BUS_SESSION);
   else
     {
        fprintf(stderr, "Error: unknown bus name '%s'\n", argv[1]);
        return 1;
     }

   e_dbus_introspect(conn, argv[2], argv[3], cb_introspect, &nodes);
   ecore_main_loop_begin();

   if (!nodes)
     {
        fprintf(stderr, "Error: no nodes found in introspection\n");
        return 1;
     }
   else
     {
        struct DBus_Node *n;
        EINA_INLIST_FOREACH(nodes, n)
          print_node(n, 0, stdout);

        while (nodes)
          {
             n = EINA_INLIST_CONTAINER_GET(nodes, struct DBus_Node);
             nodes = nodes->next;
             free_node(n);
          }
     }

   return 0;
}
------------------------------------------------------------------------------
RSA(R) Conference 2012
Save $700 by Nov 18
Register now
http://p.sf.net/sfu/rsa-sfdev2dev1
_______________________________________________
enlightenment-devel mailing list
enlightenment-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/enlightenment-devel

Reply via email to