From 7b4ac5de11d90e9f7048f057d70d3da5104388b6 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Mon, 1 Sep 2003 18:02:06 +0000 Subject: 2003-09-01 Havoc Pennington * glib/Makefile.am: rearrange a bunch of files and get "make check" framework set up --- glib/dbus-gparser.c | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 glib/dbus-gparser.c (limited to 'glib/dbus-gparser.c') diff --git a/glib/dbus-gparser.c b/glib/dbus-gparser.c new file mode 100644 index 00000000..6fea4abc --- /dev/null +++ b/glib/dbus-gparser.c @@ -0,0 +1,121 @@ +/* -*- mode: C; c-file-style: "gnu" -*- */ +/* dbus-gparser.c parse DBus description files + * + * Copyright (C) 2003 Red Hat, Inc. + * + * Licensed under the Academic Free License version 1.2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +#include "dbus-gparser.h" +#include "dbus-gidl.h" + +struct Parser +{ + int refcount; + +}; + +Parser* +parser_new (void) +{ + Parser *parser; + + parser = g_new0 (Parser, 1); + + parser->refcount = 1; + + return parser; +} + +void +parser_ref (Parser *parser) +{ + parser->refcount += 1; +} + +void +parser_unref (Parser *parser) +{ + parser->refcount -= 1; + if (parser->refcount == 0) + { + + + g_free (parser); + } +} + +gboolean +parser_check_doctype (Parser *parser, + const char *doctype, + GError **error) +{ + g_return_val_if_fail (error == NULL || *error == NULL); + + if (strcmp (doctype, "dbus_description") != 0) + { + g_set_error (error, + G_MARKUP_ERROR_PARSE, + "D-BUS description file has the wrong document type %s, use dbus_description", + doctype); + return FALSE; + } + else + return TRUE; +} + +gboolean +parser_start_element (Parser *parser, + const char *element_name, + const char **attribute_names, + const char **attribute_values, + GError **error) +{ + g_return_val_if_fail (error == NULL || *error == NULL); + + return TRUE; +} + +gboolean +parser_end_element (Parser *parser, + const char *element_name, + GError **error) +{ + g_return_val_if_fail (error == NULL || *error == NULL); + + return TRUE; +} + +gboolean +parser_content (Parser *parser, + const char *content, + int len, + GError **error) +{ + g_return_val_if_fail (error == NULL || *error == NULL); + + return TRUE; +} + +gboolean +parser_finished (Parser *parser, + GError **error) +{ + g_return_val_if_fail (error == NULL || *error == NULL); + + return TRUE; +} -- cgit From d021cfae6695f0f44102edf758abfc42e2f3c093 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Wed, 3 Sep 2003 02:08:25 +0000 Subject: 2003-09-01 Havoc Pennington * glib/dbus-gparser.c: implement * glib/dbus-gobject.c: start implementing skeletons support * configure.in: when disabling checks/assert, also define G_DISABLE_ASSERT and G_DISABLE_CHECKS --- glib/dbus-gparser.c | 549 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 543 insertions(+), 6 deletions(-) (limited to 'glib/dbus-gparser.c') diff --git a/glib/dbus-gparser.c b/glib/dbus-gparser.c index 6fea4abc..c2b54d31 100644 --- a/glib/dbus-gparser.c +++ b/glib/dbus-gparser.c @@ -22,11 +22,152 @@ */ #include "dbus-gparser.h" #include "dbus-gidl.h" +#include + +#include +#define _(x) gettext ((x)) +#define N_(x) x + +#define ELEMENT_IS(name) (strcmp (element_name, (name)) == 0) + +typedef struct +{ + const char *name; + const char **retloc; +} LocateAttr; + +static gboolean +locate_attributes (const char *element_name, + const char **attribute_names, + const char **attribute_values, + GError **error, + const char *first_attribute_name, + const char **first_attribute_retloc, + ...) +{ + va_list args; + const char *name; + const char **retloc; + int n_attrs; +#define MAX_ATTRS 24 + LocateAttr attrs[MAX_ATTRS]; + gboolean retval; + int i; + + g_return_val_if_fail (first_attribute_name != NULL, FALSE); + g_return_val_if_fail (first_attribute_retloc != NULL, FALSE); + + retval = TRUE; + + n_attrs = 1; + attrs[0].name = first_attribute_name; + attrs[0].retloc = first_attribute_retloc; + *first_attribute_retloc = NULL; + + va_start (args, first_attribute_retloc); + + name = va_arg (args, const char*); + retloc = va_arg (args, const char**); + + while (name != NULL) + { + g_return_val_if_fail (retloc != NULL, FALSE); + + g_assert (n_attrs < MAX_ATTRS); + + attrs[n_attrs].name = name; + attrs[n_attrs].retloc = retloc; + n_attrs += 1; + *retloc = NULL; + + name = va_arg (args, const char*); + retloc = va_arg (args, const char**); + } + + va_end (args); + + if (!retval) + return retval; + + i = 0; + while (attribute_names[i]) + { + int j; + gboolean found; + + found = FALSE; + j = 0; + while (j < n_attrs) + { + if (strcmp (attrs[j].name, attribute_names[i]) == 0) + { + retloc = attrs[j].retloc; + + if (*retloc != NULL) + { + g_set_error (error, + G_MARKUP_ERROR, + G_MARKUP_ERROR_PARSE, + _("Attribute \"%s\" repeated twice on the same <%s> element"), + attrs[j].name, element_name); + retval = FALSE; + goto out; + } + + *retloc = attribute_values[i]; + found = TRUE; + } + + ++j; + } + + if (!found) + { + g_set_error (error, + G_MARKUP_ERROR, + G_MARKUP_ERROR_PARSE, + _("Attribute \"%s\" is invalid on <%s> element in this context"), + attribute_names[i], element_name); + retval = FALSE; + goto out; + } + + ++i; + } + + out: + return retval; +} + +static gboolean +check_no_attributes (const char *element_name, + const char **attribute_names, + const char **attribute_values, + GError **error) +{ + if (attribute_names[0] != NULL) + { + g_set_error (error, + G_MARKUP_ERROR, + G_MARKUP_ERROR_PARSE, + _("Attribute \"%s\" is invalid on <%s> element in this context"), + attribute_names[0], element_name); + return FALSE; + } + + return TRUE; +} struct Parser { int refcount; + NodeInfo *result; /* Filled in when we pop the last node */ + GSList *node_stack; + InterfaceInfo *interface; + MethodInfo *method; + SignalInfo *signal; + ArgInfo *arg; }; Parser* @@ -53,7 +194,8 @@ parser_unref (Parser *parser) parser->refcount -= 1; if (parser->refcount == 0) { - + if (parser->result) + node_info_unref (parser->result); g_free (parser); } @@ -64,11 +206,12 @@ parser_check_doctype (Parser *parser, const char *doctype, GError **error) { - g_return_val_if_fail (error == NULL || *error == NULL); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); if (strcmp (doctype, "dbus_description") != 0) { g_set_error (error, + G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, "D-BUS description file has the wrong document type %s, use dbus_description", doctype); @@ -78,6 +221,324 @@ parser_check_doctype (Parser *parser, return TRUE; } +static gboolean +parse_node (Parser *parser, + const char *element_name, + const char **attribute_names, + const char **attribute_values, + GError **error) +{ + const char *name; + NodeInfo *node; + + if (parser->interface || + parser->method || + parser->signal || + parser->arg) + { + g_set_error (error, G_MARKUP_ERROR, + G_MARKUP_ERROR_PARSE, + _("Can't put a <%s> element here"), + element_name); + return FALSE; + } + + name = NULL; + if (!locate_attributes (element_name, attribute_names, + attribute_values, error, + "name", &name, + NULL)) + return FALSE; + + /* Only the root node can have no name */ + if (parser->node_stack != NULL && name == NULL) + { + g_set_error (error, G_MARKUP_ERROR, + G_MARKUP_ERROR_PARSE, + _("\"%s\" attribute required on <%s> element "), + "name", element_name); + return FALSE; + } + + node = node_info_new (name); + parser->node_stack = g_slist_prepend (parser->node_stack, + node); + + return TRUE; +} + +static gboolean +parse_interface (Parser *parser, + const char *element_name, + const char **attribute_names, + const char **attribute_values, + GError **error) +{ + const char *name; + InterfaceInfo *iface; + NodeInfo *top; + + if (parser->interface || + parser->method || + parser->signal || + parser->arg || + (parser->node_stack == NULL)) + { + g_set_error (error, G_MARKUP_ERROR, + G_MARKUP_ERROR_PARSE, + _("Can't put a <%s> element here"), + element_name); + return FALSE; + } + + name = NULL; + if (!locate_attributes (element_name, attribute_names, + attribute_values, error, + "name", &name, + 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; + } + + top = parser->node_stack->data; + + iface = interface_info_new (name); + node_info_add_interface (top, iface); + interface_info_unref (iface); + + parser->interface = iface; + + return TRUE; +} + +static gboolean +parse_method (Parser *parser, + const char *element_name, + const char **attribute_names, + const char **attribute_values, + GError **error) +{ + const char *name; + MethodInfo *method; + NodeInfo *top; + + if (parser->interface == NULL || + parser->node_stack == NULL || + parser->method || + parser->signal || + parser->arg) + { + g_set_error (error, G_MARKUP_ERROR, + G_MARKUP_ERROR_PARSE, + _("Can't put a <%s> element here"), + element_name); + return FALSE; + } + + name = NULL; + if (!locate_attributes (element_name, attribute_names, + attribute_values, error, + "name", &name, + 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; + } + + top = parser->node_stack->data; + + method = method_info_new (name); + interface_info_add_method (parser->interface, method); + method_info_unref (method); + + parser->method = method; + + return TRUE; +} + +static gboolean +parse_signal (Parser *parser, + const char *element_name, + const char **attribute_names, + const char **attribute_values, + GError **error) +{ + const char *name; + SignalInfo *signal; + NodeInfo *top; + + if (parser->interface == NULL || + parser->node_stack == NULL || + parser->signal || + parser->signal || + parser->arg) + { + g_set_error (error, G_MARKUP_ERROR, + G_MARKUP_ERROR_PARSE, + _("Can't put a <%s> element here"), + element_name); + return FALSE; + } + + name = NULL; + if (!locate_attributes (element_name, attribute_names, + attribute_values, error, + "name", &name, + 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; + } + + top = parser->node_stack->data; + + signal = signal_info_new (name); + interface_info_add_signal (parser->interface, signal); + signal_info_unref (signal); + + parser->signal = signal; + + return TRUE; +} + +static int +basic_type_from_string (const char *str) +{ + if (strcmp (str, "string") == 0) + return DBUS_TYPE_STRING; + else if (strcmp (str, "int32") == 0) + return DBUS_TYPE_INT32; + else if (strcmp (str, "uint32") == 0) + return DBUS_TYPE_UINT32; + else if (strcmp (str, "int64") == 0) + return DBUS_TYPE_INT64; + else if (strcmp (str, "uint64") == 0) + return DBUS_TYPE_UINT64; + else if (strcmp (str, "double") == 0) + return DBUS_TYPE_DOUBLE; + else if (strcmp (str, "byte") == 0) + return DBUS_TYPE_BYTE; + else if (strcmp (str, "boolean") == 0) + return DBUS_TYPE_BOOLEAN; + else if (strcmp (str, "byte") == 0) + return DBUS_TYPE_BYTE; + else if (strcmp (str, "object") == 0) + return DBUS_TYPE_OBJECT_PATH; + else + return DBUS_TYPE_INVALID; +} + +static int +type_from_string (const char *str) +{ + return basic_type_from_string (str); +} + +static gboolean +parse_arg (Parser *parser, + const char *element_name, + const char **attribute_names, + const char **attribute_values, + GError **error) +{ + const char *name; + const char *type; + const char *direction; + ArgDirection dir; + int t; + ArgInfo *arg; + + if (!(parser->method || parser->signal) || + parser->node_stack == NULL || + parser->arg) + { + g_set_error (error, G_MARKUP_ERROR, + G_MARKUP_ERROR_PARSE, + _("Can't put a <%s> element here"), + element_name); + return FALSE; + } + + name = NULL; + if (!locate_attributes (element_name, attribute_names, + attribute_values, error, + "name", &name, + "type", &type, + "direction", &direction, + NULL)) + return FALSE; + + /* name can be null for args */ + + 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; + } + + if (direction == NULL) + { + /* methods default to in, signal to out */ + if (parser->method) + direction = "in"; + else if (parser->signal) + direction = "out"; + else + g_assert_not_reached (); + } + + if (strcmp (direction, "in") == 0) + dir = ARG_IN; + else if (strcmp (direction, "out") == 0) + dir = ARG_OUT; + 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); + + arg = arg_info_new (name, dir, t); + if (parser->method) + method_info_add_arg (parser->method, arg); + else if (parser->signal) + signal_info_add_arg (parser->signal, arg); + else + g_assert_not_reached (); + + arg_info_unref (arg); + + parser->arg = arg; + + return TRUE; +} + gboolean parser_start_element (Parser *parser, const char *element_name, @@ -85,8 +546,46 @@ parser_start_element (Parser *parser, const char **attribute_values, GError **error) { - g_return_val_if_fail (error == NULL || *error == NULL); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + if (ELEMENT_IS ("node")) + { + if (!parse_node (parser, element_name, attribute_names, + attribute_values, error)) + return FALSE; + } + else if (ELEMENT_IS ("interface")) + { + if (!parse_interface (parser, element_name, attribute_names, + attribute_values, error)) + return FALSE; + } + else if (ELEMENT_IS ("method")) + { + if (!parse_method (parser, element_name, attribute_names, + attribute_values, error)) + return FALSE; + } + else if (ELEMENT_IS ("signal")) + { + if (!parse_signal (parser, element_name, attribute_names, + attribute_values, error)) + return FALSE; + } + else if (ELEMENT_IS ("arg")) + { + if (!parse_arg (parser, element_name, attribute_names, + attribute_values, error)) + return FALSE; + } + else + { + g_set_error (error, G_MARKUP_ERROR, + G_MARKUP_ERROR_PARSE, + _("Element <%s> not recognized"), + element_name); + } + return TRUE; } @@ -95,8 +594,40 @@ parser_end_element (Parser *parser, const char *element_name, GError **error) { - g_return_val_if_fail (error == NULL || *error == NULL); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + if (ELEMENT_IS ("interface")) + { + parser->interface = NULL; + } + else if (ELEMENT_IS ("method")) + { + parser->method = NULL; + } + else if (ELEMENT_IS ("signal")) + { + parser->signal = NULL; + } + else if (ELEMENT_IS ("arg")) + { + parser->arg = NULL; + } + else if (ELEMENT_IS ("node")) + { + NodeInfo *top; + g_assert (parser->node_stack != NULL); + top = parser->node_stack->data; + + parser->node_stack = g_slist_remove (parser->node_stack, + top); + + if (parser->node_stack == NULL) + parser->result = top; /* We are done, store the result */ + } + else + g_assert_not_reached (); /* should have had an error on start_element */ + return TRUE; } @@ -106,7 +637,7 @@ parser_content (Parser *parser, int len, GError **error) { - g_return_val_if_fail (error == NULL || *error == NULL); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); return TRUE; } @@ -115,7 +646,13 @@ gboolean parser_finished (Parser *parser, GError **error) { - g_return_val_if_fail (error == NULL || *error == NULL); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); return TRUE; } + +NodeInfo* +parser_get_nodes (Parser *parser) +{ + return parser->result; +} -- cgit From 85ab0327d82e4945ad16630e583d8cc68df25a90 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Sun, 7 Sep 2003 23:04:54 +0000 Subject: 2003-09-07 Havoc Pennington * Make Doxygen contented. --- glib/dbus-gparser.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'glib/dbus-gparser.c') diff --git a/glib/dbus-gparser.c b/glib/dbus-gparser.c index c2b54d31..f7264b5e 100644 --- a/glib/dbus-gparser.c +++ b/glib/dbus-gparser.c @@ -28,6 +28,8 @@ #define _(x) gettext ((x)) #define N_(x) x +#ifndef DOXYGEN_SHOULD_SKIP_THIS + #define ELEMENT_IS(name) (strcmp (element_name, (name)) == 0) typedef struct @@ -656,3 +658,5 @@ parser_get_nodes (Parser *parser) { return parser->result; } + +#endif /* DOXYGEN_SHOULD_SKIP_THIS */ -- cgit From 583994cb3b7f5562fb7b8c37b4cb0d5af78e4ce2 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Wed, 17 Sep 2003 03:52:07 +0000 Subject: 2003-09-15 Havoc Pennington * dbus/dbus-pending-call.c: add the get/set object data boilerplate as for DBusConnection, etc. Use generic object data for the notify callback. * glib/dbus-gparser.c (parse_node): parse child nodes * tools/dbus-viewer.c: more hacking on the dbus-viewer * glib/dbus-gutils.c (_dbus_gutils_split_path): add a file to contain functions shared between the convenience lib and the installed lib * glib/Makefile.am (libdbus_glib_1_la_LDFLAGS): add -export-symbols-regex to the GLib library * dbus/dbus-object-tree.c (_dbus_object_tree_dispatch_and_unlock): fix the locking in here, and add a default handler for Introspect() that just returns sub-nodes. 2003-09-14 Havoc Pennington * glib/dbus-gthread.c (dbus_g_thread_init): rename to make g_foo rather than gfoo consistent * glib/dbus-gproxy.h: delete for now, move contents to dbus-glib.h, because the include files don't work right since we aren't in the dbus/ subdir. * glib/dbus-gproxy.c (dbus_gproxy_send): finish implementing (dbus_gproxy_end_call): finish (dbus_gproxy_begin_call): finish * glib/dbus-gmain.c (dbus_set_g_error): new * glib/dbus-gobject.c (handle_introspect): include information about child nodes in the introspection * dbus/dbus-connection.c (dbus_connection_list_registered): new function to help in implementation of introspection * dbus/dbus-object-tree.c (_dbus_object_tree_list_registered_and_unlock): new function 2003-09-12 Havoc Pennington * glib/dbus-gidl.h: add common base class for all the foo_info types * tools/dbus-viewer.c: add GTK-based introspection UI thingy similar to kdcop * test/Makefile.am: try test srcdir -ef . in addition to test srcdir = ., one of them should work (yeah lame) * glib/Makefile.am: build the "idl" parser stuff as a convenience library * glib/dbus-gparser.h: make description_load routines return NodeInfo* not Parser* * Makefile.am (SUBDIRS): build test dir after all library dirs * configure.in: add GTK+ detection --- glib/dbus-gparser.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'glib/dbus-gparser.c') diff --git a/glib/dbus-gparser.c b/glib/dbus-gparser.c index f7264b5e..16d17f3d 100644 --- a/glib/dbus-gparser.c +++ b/glib/dbus-gparser.c @@ -262,7 +262,15 @@ parse_node (Parser *parser, return FALSE; } + node = node_info_new (name); + + if (parser->node_stack != NULL) + { + node_info_add_node (parser->node_stack->data, + node); + } + parser->node_stack = g_slist_prepend (parser->node_stack, node); -- cgit