summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
author <rob.taylor@collabora.co.uk>2006-01-15 21:02:58 +0000
committer <rob.taylor@collabora.co.uk>2006-01-15 21:02:58 +0000
commitb5afd8ff21499d0e5ee47429b6cd235a0df81656 (patch)
tree440416cb318d1f3496fb967da9897b695ca15d04 /tools
parentae8a44f2eb6684a8581a6f892719c6fcd85e5348 (diff)
downloadtelepathy-farstream-b5afd8ff21499d0e5ee47429b6cd235a0df81656.tar.gz
added code autogen tools
20060115210258-25e70-e35df579405fe907cd0326849a31e1c65dcc93c9.gz
Diffstat (limited to 'tools')
-rw-r--r--tools/.git-darcs-dir0
-rw-r--r--tools/Makefile.am3
-rw-r--r--tools/generrors.py41
-rw-r--r--tools/gengobject.py416
4 files changed, 460 insertions, 0 deletions
diff --git a/tools/.git-darcs-dir b/tools/.git-darcs-dir
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tools/.git-darcs-dir
diff --git a/tools/Makefile.am b/tools/Makefile.am
new file mode 100644
index 0000000..9bfdbcc
--- /dev/null
+++ b/tools/Makefile.am
@@ -0,0 +1,3 @@
+EXTRA_DIST = \
+ generrors.py \
+ gengobject.py
diff --git a/tools/generrors.py b/tools/generrors.py
new file mode 100644
index 0000000..51a7ddd
--- /dev/null
+++ b/tools/generrors.py
@@ -0,0 +1,41 @@
+#!/usr/bin/python2.4
+import telepathy.errors
+import inspect
+import gengobject
+
+out = open("telepathy-errors.h", 'w')
+
+gengobject.print_license(out, "telepathy-errors.h", "Header for Telepathy error types")
+
+gengobject.print_header_begin(out, "telepathy_errors")
+out.write("typedef enum\n{\n")
+
+errors = [];
+max_name_length = 0
+for (cname,val) in telepathy.errors.__dict__.items():
+ if inspect.isclass(val):
+ if '_dbus_error_name' in val.__dict__:
+ errors.append(val)
+ if len(val.__name__) > max_name_length:
+ max_name_length = len(val.__name__)
+
+
+for val in errors:
+ line = " "+val.__name__ + ","
+ line = line.ljust(max_name_length + 4)
+ line += "/** "+val.__doc__.strip()
+ while len (line) > 79:
+ cut = line[:80]
+ cutidx = cut.rfind(' ')
+ if cutidx == 80:
+ out.write(cut[:79])
+ else:
+ out.write(cut[:cutidx])
+ out.write('\n')
+ line = ' ' * (max_name_length +4) + ' * ' + line[cutidx:]
+ out.write(line + '\n')
+ out.write(' ' * (max_name_length + 4) + ' */\n')
+
+out.write("} TelepathyErrors; \n\n")
+
+gengobject.print_header_end(out, "telepathy_errors");
diff --git a/tools/gengobject.py b/tools/gengobject.py
new file mode 100644
index 0000000..4f4c011
--- /dev/null
+++ b/tools/gengobject.py
@@ -0,0 +1,416 @@
+#!/usr/bin/python
+
+import sys
+import os.path
+import xml.dom.minidom
+
+def cmdline_error():
+ print "usage: gen-gobject xmlfile classname"
+ sys.exit(1)
+
+def camelcase_to_lower(s):
+ out ="";
+ out += s[0].lower()
+ last_upper=False
+ if s[0].isupper():
+ last_upper=True
+ for i in range(1,len(s)):
+ if s[i].isupper():
+ if last_upper:
+ if (i+1) < len(s) and s[i+1].islower():
+ out += "_" + s[i].lower()
+ else:
+ out += s[i].lower()
+ else:
+ out += "_" + s[i].lower()
+ last_upper=True
+ else:
+ out += s[i]
+ last_upper=False
+ return out
+
+def camelcase_to_upper(s):
+ return camelcase_to_lower(s).upper()
+
+def type_to_gtype(s):
+ if s == 'y': #byte
+ return ("guchar", "G_TYPE_UCHAR","UCHAR", False)
+ if s == 'b': #boolean
+ return ("gboolean", "G_TYPE_BOOLEAN","BOOLEAN", False)
+ if s == 'n': #int16
+ return ("gint", "G_TYPE_INT","INT", False)
+ if s == 'q': #uint16
+ return ("guint", "G_TYPE_UINT","UINT", False)
+ if s == 'i': #int32
+ return ("gint", "G_TYPE_INT","INT", False)
+ if s == 'u': #uint32
+ return ("guint", "G_TYPE_UINT","INT", False)
+ if s == 'x': #int64
+ return ("gint", "G_TYPE_INT64","INT64", False)
+ if s == 't': #uint32
+ return ("guint", "G_TYPE_UINT64","UINT64", False)
+ if s == 'd': #double
+ return ("gdouble", "G_TYPE_DOUBLE","DOUBLE", False)
+ if s == 's': #string
+ return ("gchar *", "G_TYPE_STRING", "STRING", True)
+ if s == 'o': #object path
+ return ("gchar *", "DBUS_TYPE_G_OBJECT_PATH", "STRING", True)
+ if s == 'as': #array of strings
+ return ("gchar **", "G_TYPE_STRV", "BOXED", True)
+ if s == 'v': #variant
+ return ("GValue *", "G_TYPE_VALUE", "BOXED", True)
+ if s[:3] == 'a{s': # dict mapping of strings to any marshalable value
+ return ("GHashTable *", "DBUS_TYPE_G_STRING_HASHTABLE", "BOXED", False)
+ if s == 'ay': #byte array
+ return ("GArray *", "DBUS_TYPE_G_BYTE_ARRAY", "BOXED", True)
+ if s == 'au': #uint array
+ return ("GArray *", "DBUS_TYPE_G_UINT_ARRAY", "BOXED", True)
+ if s == 'ai': #int array
+ return ("GArray *", "DBUS_TYPE_G_INT_ARRAY", "BOXED", True)
+ if s == 'ax': #int64 array
+ return ("GArray *", "DBUS_TYPE_G_INT64_ARRAY", "BOXED", True)
+ if s == 'at': #uint64 array
+ return ("GArray *", "DBUS_TYPE_G_UINT64_ARRAY", "BOXED", True)
+ if s == 'ad': #double array
+ return ("GArray *", "DBUS_TYPE_G_DOUBLE_ARRAY", "BOXED", True)
+ if s == 'ab': #boolean array
+ return ("GArray *", "DBUS_TYPE_G_BOOLEAN_ARRAY", "BOXED", True)
+
+ # we just don't know ..
+ return ("gpointer", "G_TYPE_BOXED", "BOXED", True)
+
+
+def signal_to_marshal_type(signal):
+ """
+ return a list of strings indicating the marshalling type for this signal.
+ """
+
+ mtype=[]
+ for i in signal.getElementsByTagName("arg"):
+ name =i.getAttribute("name")
+ type = i.getAttribute("type")
+ mtype.append(type_to_gtype(type)[2])
+
+ return mtype
+
+def signal_to_marshal_name(signal, prefix):
+ mtype=signal_to_marshal_type(signal)
+ if len(mtype):
+ return prefix+'_marshal_VOID__' + '_'.join(mtype)
+ else:
+ return prefix+'_marshal_VOID__VOID'
+
+def signal_to_gtype_list(signal):
+ gtype=[]
+ for i in signal.getElementsByTagName("arg"):
+ name =i.getAttribute("name")
+ type = i.getAttribute("type")
+ gtype.append(type_to_gtype(type)[1])
+
+ return gtype
+
+
+def print_license(stream, filename, description):
+ stream.write(
+"""/*
+ * %s - %s
+ * Copyright (C) 2005 Collabora Ltd.
+ * Copyright (C) 2005 Nokia Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+""" % (filename, description))
+
+def print_header_begin(stream, prefix):
+ guardname = '__'+prefix.upper()+'_H__'
+ stream.write ("#ifndef "+guardname+"\n")
+ stream.write ("#define "+guardname+"\n\n")
+
+ stream.write ("#include <glib-object.h>\n\n")
+ stream.write ("G_BEGIN_DECLS\n\n")
+
+def print_header_end(stream, prefix):
+ guardname = '__'+prefix.upper()+'_H__'
+ stream.write ("\nG_END_DECLS\n\n")
+ stream.write ("#endif /* #ifndef "+guardname+"*/\n")
+
+def print_simple_class_defn(stream, prefix, classname):
+ stream.write ("typedef struct _%s %s;\n" % (classname,classname))
+ stream.write ("typedef struct _%sClass %sClass;\n\n" % (classname,classname))
+ stream.write ("struct _%sClass {\n" % classname)
+ stream.write (" GObjectClass parent_class;\n")
+ stream.write ("};\n\n")
+
+ stream.write ("struct _%s {\n" % classname)
+ stream.write (" GObject parent;\n")
+ stream.write ("};\n")
+
+ stream.write(
+"""
+GType %(prefix)s_get_type(void);
+
+""" % {'prefix':prefix,'uprefix':prefix.upper()})
+
+ macro_prefix = prefix.upper().split('_',1)
+ gtype = '_TYPE_'.join(macro_prefix)
+
+ stream.write(
+"""/* TYPE MACROS */
+#define %(type)s \\
+ (%(prefix)s_get_type())
+#define %(main)s_%(sub)s(obj) \\
+ (G_TYPE_CHECK_INSTANCE_CAST((obj), %(type)s, %(name)s))
+#define %(main)s_%(sub)s_CLASS(klass) \\
+ (G_TYPE_CHECK_CLASS_CAST((klass), %(type)s, %(name)sClass))
+#define %(main)s_IS_%(sub)s(obj) \\
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj), %(type)s))
+#define %(main)s_IS_%(sub)s_CLASS(klass) \\
+ (G_TYPE_CHECK_CLASS_TYPE((klass), %(type)s))
+#define %(main)s_%(sub)s_GET_CLASS(obj) \\
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), %(type)s, %(name)sClass))
+
+""" % {"main":macro_prefix[0], "sub":macro_prefix[1], "type":gtype, "name":classname, "prefix":prefix})
+
+if __name__ == '__main__':
+ try:
+ classname = sys.argv[2]
+ except IndexError:
+ cmdline_error()
+
+ prefix = camelcase_to_lower(classname)
+ basename = prefix.replace('_','-')
+ outname_header = basename + ".h"
+ outname_body = basename + ".c"
+ outname_signal_marshal = basename + "-signals-marshal.list"
+
+ header=open(outname_header,'w')
+ body=open(outname_body, 'w')
+ signal_marshal=open(outname_signal_marshal, 'w')
+
+ try:
+ dom = xml.dom.minidom.parse(sys.argv[1])
+ except IndexError:
+ cmdline_error()
+
+ signals = dom.getElementsByTagName("signal")
+ signals.sort()
+ methods = dom.getElementsByTagName("method")
+ methods.sort()
+
+ print_license(header, outname_header, "Header for " + classname)
+ print_license(body, outname_body, "Source for " + classname)
+ print_header_begin(header,prefix)
+
+ print_simple_class_defn(header, prefix, classname)
+
+ body.write(
+"""#include <dbus/dbus-glib.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "%s"
+#include "%s-signals-marshal.h"
+
+#include "%s-glue.h"
+
+""" % (outname_header, basename, basename))
+
+ body.write(
+"""G_DEFINE_TYPE(%(classname)s, %(prefix)s, G_TYPE_OBJECT)
+
+""" % {'classname':classname, 'prefix':prefix})
+
+ body.write("/* signal enum */\nenum\n{\n")
+ for signal in signals:
+ dbus_name = signal.getAttributeNode("name").nodeValue
+ body.write(" %s,\n" % camelcase_to_upper(dbus_name) )
+ body.write(" LAST_SIGNAL\n};\n\n")
+ body.write("static guint signals[LAST_SIGNAL] = {0};\n\n")
+
+ gtypename = '_TYPE_'.join(prefix.upper().split('_',1))
+
+ body.write("""/* private structure */
+typedef struct _%(classname)sPrivate %(classname)sPrivate;
+
+struct _%(classname)sPrivate
+{
+ gboolean dispose_has_run;
+};
+
+#define %(uprefix)s_GET_PRIVATE(o) \
+ (G_TYPE_INSTANCE_GET_PRIVATE ((o), %(gtypename)s, %(classname)sPrivate))
+""" % {'classname':classname, 'uprefix':prefix.upper(), 'gtypename':gtypename})
+
+ body.write(
+"""
+static void
+%(prefix)s_init (%(classname)s *obj)
+{
+ %(classname)sPrivate *priv = %(uprefix)s_GET_PRIVATE (obj);
+
+ /* allocate any data required by the object here */
+}
+
+static void %(prefix)s_dispose (GObject *object);
+static void %(prefix)s_finalize (GObject *object);
+
+static void
+%(prefix)s_class_init (%(classname)sClass *%(prefix)s_class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (%(prefix)s_class);
+
+ g_type_class_add_private (%(prefix)s_class, sizeof (%(classname)sPrivate));
+
+ object_class->dispose = %(prefix)s_dispose;
+ object_class->finalize = %(prefix)s_finalize;
+""" % {"prefix":prefix, "classname":classname, 'uprefix':prefix.upper()})
+
+ for signal in signals:
+ mtype = signal_to_marshal_type(signal)
+ if len(mtype):
+ signal_marshal.write("VOID:"+','.join(mtype)+"\n")
+ else:
+ signal_marshal.write("VOID:VOID\n")
+
+ header.write("\n")
+
+ for signal in signals:
+ dbus_name = signal.getAttributeNode("name").nodeValue
+ gtypelist=signal_to_gtype_list(signal)
+
+ body.write(
+"""
+ signals[%s] =
+ g_signal_new ("%s",
+ G_OBJECT_CLASS_TYPE (%s_class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
+ 0,
+ NULL, NULL,
+ %s,
+ G_TYPE_NONE, %s);
+""" % (camelcase_to_upper(dbus_name),
+ camelcase_to_lower(dbus_name).replace('_','-'),
+ prefix,
+ signal_to_marshal_name(signal,prefix), ', '.join([str(len(gtypelist))] + gtypelist)))
+
+ body.write(
+"""
+ dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (%(prefix)s_class), &dbus_glib_%(prefix)s_object_info);
+}
+
+void
+%(prefix)s_dispose (GObject *object)
+{
+ %(classname)s *self = %(uprefix)s (object);
+ %(classname)sPrivate *priv = %(uprefix)s_GET_PRIVATE (self);
+
+ if (priv->dispose_has_run)
+ return;
+
+ priv->dispose_has_run = TRUE;
+
+ /* release any references held by the object here */
+
+ if (G_OBJECT_CLASS (%(prefix)s_parent_class)->dispose)
+ G_OBJECT_CLASS (%(prefix)s_parent_class)->dispose (object);
+}
+
+void
+%(prefix)s_finalize (GObject *object)
+{
+ %(classname)s *self = %(uprefix)s (object);
+ %(classname)sPrivate *priv = %(uprefix)s_GET_PRIVATE (self);
+
+ /* free any data held directly by the object here */
+
+ G_OBJECT_CLASS (%(prefix)s_parent_class)->finalize (object);
+}
+
+
+""" % {'classname':classname,'prefix':prefix, 'uprefix':prefix.upper()})
+
+ for method in methods:
+ dbus_method_name = method.getAttributeNode("name").nodeValue
+ c_method_name = prefix + '_' + camelcase_to_lower(dbus_method_name)
+ c_decl = 'gboolean '+c_method_name+' ('+classname+' *obj'
+ async=False
+ ret_count=0
+
+ for i in method.getElementsByTagName("annotation"):
+ if i.getAttribute("name") == "org.freedesktop.DBus.GLib.Async":
+ async=True
+
+ for i in method.getElementsByTagName("arg"):
+ name =i.getAttribute("name")
+ direction = i.getAttribute("direction")
+ type = i.getAttribute("type")
+
+ if async and direction=="out":
+ continue
+
+ if not name and direction == "out":
+ if ret_count==0:
+ name = "ret"
+ else:
+ name = "ret"+str(ret_count)
+ ret_count += 1
+
+ gtype = type_to_gtype(type)[0]
+ if direction =="out":
+ gtype+='*'
+ else:
+ if type_to_gtype(type)[3]:
+ gtype="const "+gtype
+ c_decl +=", "+gtype+" "+name
+ if async:
+ c_decl += ", DBusGMethodInvocation *context)"
+ else:
+ c_decl += ", GError **error)"
+
+ interface = method.parentNode.getAttribute("name");
+ header.write(c_decl+";\n")
+ body.write(
+"""
+/**
+ * %(c_method_name)s
+ *
+ * Implements DBus method %(method)s
+ * on interface %(interface)s
+ *""" % {'c_method_name':c_method_name, 'method':dbus_method_name, 'interface':interface})
+ if async:
+ body.write(
+"""
+ * @context: The DBUS invocation context to use to return values
+ * or throw an error.
+ */
+""")
+ else:
+ body.write(
+"""
+ * @error: Used to return a pointer to a GError detailing any error
+ * that occured, DBus will throw the error only if this
+ * function returns false.
+ *
+ * Returns: TRUE if successful, FALSE if an error was thrown.
+ */
+""")
+ body.write(c_decl+"\n{\n return TRUE;\n}\n\n")
+
+ header.write('\n')
+
+ print_header_end(header,prefix)
+ header.close()
+ body.close()