summaryrefslogtreecommitdiff
path: root/codegen/defsgen.py
diff options
context:
space:
mode:
Diffstat (limited to 'codegen/defsgen.py')
-rwxr-xr-xcodegen/defsgen.py737
1 files changed, 737 insertions, 0 deletions
diff --git a/codegen/defsgen.py b/codegen/defsgen.py
new file mode 100755
index 0000000..6c2e63d
--- /dev/null
+++ b/codegen/defsgen.py
@@ -0,0 +1,737 @@
+#!/usr/bin/env python
+# -*- Mode: Python; py-indent-offset: 4 -*-
+#
+# Copyright (C) 2006-2009 John Finlay.
+#
+# Scan the given public .h files of a GTK module (or module using
+# GTK object conventions) and generates a set of scheme defs.
+#
+# defsgen uses the ctypes module to extract information from the installed
+# module library (or libraries) to generate the object, interface, function,
+# method, virtual, enum and flags defs. defsgen uses the gobject library
+# g_type_* functions. defsgen will try to open the "libgobject-2.0.so" library
+# if one is not specified on the command line.
+#
+# Basically the operation of defsgen is:
+#
+# - open and initialize the gobject and module libraries
+# - read each .h file into a buffer which is scrubbed of extraneous data
+# - find all *_get_type() functions prototypes
+# - look in the module libraries for the get_type symbols
+# - if found run the get_type() function to retrieve the GType
+# - find the parent type name and save the object info
+# - find each function prototypes in the file and check if it has a symbol in
+# the module libraries - save the info if found
+# - extract the virtual prototypes from the Class or Iface structs and save
+# - write out the various defs.
+#
+# The command line options are:
+#
+# -l --modulelib Adds the given module library name to the list to be used
+# for finding symbols. Mor ethan one modulefile may be
+# specified. (required)
+# -L --libgobject Specifies the name of the gobject library (optional but
+# must be specified if "libgobject-2.0.so" is not availble)
+# -s --separate Create separate files for objects and function/method defs
+# using the given name as the base name (optional). If this
+# is not specified the combined object and function defs
+# will be output to sys.stdout.
+# -f --defsfile Extract defs from the given file to filter the output defs
+# that is don't output defs that are defined in the
+# defsfile. More than one deffile may be specified.
+# -D --defines Include portions of the defsfile defs that are conditional
+# on the given define, for example GDK_TARGET_X11. Only
+# useful with the --defsfile option
+# -m --modulename The prefix to be stripped from the front of function names
+# for the given module
+# -p --useprefix Use the modulename prefix as a hint to split names into
+# module and name for object and enum defs. Also used for
+# generating type codes.
+# --onlyenums Only produce defs for enums and flags
+# --onlyobjdefs Only produce defs for objects
+# --onlyvirtuals Only produce defs for virtuals
+# --genpropgetsets Experimental option to generate prop-getset annotations.
+# Not supported by codegen.py and friends.
+#
+# Examples:
+#
+# python defsgen.py -m pango -l libpango-1.0.so \
+# /usr/local/include/pango-1.0/pango/*.h >/tmp/pango.defs
+#
+# - Outputs all defs for the pango module.using the library module
+# libpango-1.0.so.
+#
+# python defsgen.py -m gdk -DGDK_TARGET_X11 -l libgdk-x11-2.0.so \
+# -l libgdk_pixbuf-2.0.so -s /tmp/gdk-2.10 \
+# -f /usr/tmp/pygtk/gtk/gdk-base.defs \
+# /usr/local/include/gtk-2.0/gdk/*.h \
+# /usr/local/include/gtk-2.0/gdk-pixbuf/*.h
+#
+# - Outputs the gdk module defs that are not contained in the defs file
+# /usr/tmp/pygtk/gtk/gdk-base.defs. Two output files are created:
+# /tmp/gdk-2.10-types.defs and /tmp/gdk-2.10.defs.
+#
+# Based on the original h2def.py program by
+# Toby D. Reeves <toby@max.rl.plh.af.mil> and
+# modified by James Henstridge <james@daa.com.au> to output stuff in
+# Havoc's new defs format. Info on this format can be seen at:
+# http://www.gnome.org/mailing-lists/archives/gtk-devel-list/2000-January/0085.shtml
+# Updated to be PEP-8 compatible and refactored to use OOP
+# Extensively modified by John Finlay to use ctypes module to extract GType
+# info from the given library and to create virtual defines.
+#
+
+import getopt
+import os
+import re, string
+import sys
+import ctypes
+import defsparser
+
+#------------------ utility defs -----------------
+
+_upperstr_pat1 = re.compile(r'([^A-Z])([A-Z])')
+_upperstr_pat2 = re.compile(r'([A-Z][A-Z])([A-Z][0-9a-z])')
+_upperstr_pat3 = re.compile(r'^([A-Z])([A-Z])')
+
+def to_upper_str(name):
+ """Converts a typename to the equivalent uppercase and underscores
+ name. This is used to form the type conversion macros and enum/flag
+ name variables"""
+ name = _upperstr_pat1.sub(r'\1_\2', name)
+ name = _upperstr_pat2.sub(r'\1_\2', name)
+ name = _upperstr_pat3.sub(r'\1_\2', name, count=1)
+ return name.upper()
+
+def typecode(typename, prefix, use_prefix):
+ """create a typecode (eg. GTK_TYPE_WIDGET) from a typename"""
+ tcode = to_upper_str(typename)
+ if (use_prefix and prefix and tcode.lower() != prefix
+ and tcode.lower().startswith(prefix)):
+ l = len(prefix)
+ tcode = tcode[:l] + '_TYPE' + tcode[l:]
+ else:
+ tcode = tcode.replace('_', '_TYPE_', 1)
+ return tcode
+
+_class_iface_pat = re.compile(r'\w+(Class|Iface)')
+
+def class_iface_sub(mobj):
+ '''Returns matched string if it matches a Class or Iface struct
+ otherwise returns the empty string'''
+ if not _class_iface_pat.match(mobj.group(1)):
+ return ''
+ return mobj.group(0)
+
+clean_patterns = [
+ # strip comments
+ (re.compile(r'/\*.*?\*/', re.DOTALL), ''),
+ # compact continued lines
+ (re.compile(r"\\\n", re.MULTILINE), ''),
+ # remove preprocess directives
+ (re.compile(r"""^[#].*?$""", re.MULTILINE), ''),
+ # strip DECLS macros and Windows DLL API macros
+ (re.compile(r"""G_BEGIN_DECLS|BEGIN_LIBGTOP_DECLS|G_END_DECLS|[A-Z]+_API """,
+ re.MULTILINE), ''),
+ # remove extern "C"
+ (re.compile(r'^\s*(extern)\s+"C"\s+{', re.MULTILINE), ''),
+ # remove singleline typedefs of stucts
+ (re.compile(r'^typedef\s+struct\s*[^{;\n]*;\s*$', re.MULTILINE), ''),
+ # remove all struct definitons but those for object classes and interfaces
+ (re.compile(r'^struct\s+(\w+)\s+{[^}]+}\s*;\s*$', re.MULTILINE),
+ class_iface_sub),
+ # compress multiple whitespace
+ (re.compile(r'\s+', re.MULTILINE), ' '),
+ # clean up line ends
+ (re.compile(r';\s*', re.MULTILINE), '\n'),
+ (re.compile(r'^\s*', re.MULTILINE), ''),
+ # associate *, &, and [] with type instead of variable
+ (re.compile(r' \s* ([*|&]+) \s* ([(\w]+)', re.VERBOSE), r'\1 \2'),
+ (re.compile(r'\s+ (\w+) \[ \s* \]', re.VERBOSE), r'[] \1'),
+ # make return types that are const work.
+ (re.compile(r'\s*\*\s*G_CONST_RETURN\s*\*\s*'), '** '),
+ (re.compile(r'G_CONST_RETURN |const '), 'const-'),
+ # remove typedefs of callback types
+ (re.compile(r'^typedef\s+\w+\s*\*?\s*\(\s*\*\s*\w+\)\s*\([^(]*\)\n',
+ re.MULTILINE), ''),
+ #strip GSEAL macros from the middle of function declarations:
+ (re.compile(r"""GSEAL""", re.VERBOSE), '')
+ ]
+
+def clean_buffer(buf):
+ """Cleans out extraneous data leaving function prototypes, Class and Iface
+ structs."""
+ for pat, subst in clean_patterns:
+ buf = pat.sub(subst, buf)
+ return buf
+
+# ------------------ utility classes -------------------------
+
+class ObjDef(object):
+ def __init__(self, name, type_id, parent_name, parent_type, base_name):
+ self.name = name
+ self.type = type_id
+ self.parent_name = parent_name
+ self.parent_type = parent_type
+ self.base_name = base_name
+ self.props = []
+ return
+ def __cmp__(self, other):
+ try:
+ res = cmp(self.name, other.name)
+ except AttributeError:
+ res = cmp(id(self), id(other))
+ return res
+ def set_properties(self, gobj):
+ if self.base_name == 'GObject':
+ self.props = self._get_gobject_properties(gobj)
+ elif self.base_name == 'GInterface':
+ self.props = self._get_ginterface_properties(gobj)
+
+ def _get_gobject_properties(self, gobj):
+ klass = gobj.g_type_class_ref(self.type)
+ num = ctypes.c_uint()
+ plist = gobj.g_object_class_list_properties(klass, ctypes.byref(num))
+ props = [plist[i][0].name for i in range(num.value)
+ if self.name == gobj.g_type_name(plist[i][0].owner_type)]
+ return props
+ def _get_ginterface_properties(self, gobj):
+ iface = gobj.g_type_default_interface_ref(self.type)
+ num = ctypes.c_uint()
+ plist = gobj.g_object_interface_list_properties(iface,
+ ctypes.byref(num))
+ props = [plist[i][0].name for i in range(num.value)]
+ return props
+
+# ------------------ Find object definitions -----------------
+
+split_prefix_pat = re.compile('([A-Z]+[a-z]*)([A-Za-z0-9]+)')
+
+get_type_pat = re.compile(r'''^\s*(GType|GtkType)\s+
+([a-z]\w+_get_type)\s*(\(void\)|\(\)).*$''', re.VERBOSE | re.MULTILINE)
+
+defkeys = 'GBoxed GInterface GObject gpointer GEnum GFlags'
+
+def find_defs(buf, gobj, modlib, defs):
+ """Find possible gobject, gboxed, interface, gpointer, enum and flags
+ definitions in header files.and find parent type."""
+ # find all *_get_type() functions that may represent a GObject
+ for m in get_type_pat.findall(buf):
+ func_name = m[1]
+ for lib in modlib:
+ if hasattr(lib, func_name):
+ objtype = apply(getattr(lib, func_name))
+ obj_name = gobj.g_type_name(objtype)
+ parent = gobj.g_type_parent(objtype)
+ parent_name = gobj.g_type_name(parent)
+ base_name = gobj.g_type_name(gobj.g_type_fundamental(parent))
+ #if gobj.g_type_is_a(parent, gobj.GObject):
+ # base_name = 'GObject'
+ if base_name in defkeys:
+ obj = ObjDef(obj_name, objtype, parent_name, parent,
+ base_name)
+ obj.set_properties(gobj)
+ defs[obj.base_name].append(obj)
+ break
+ return
+
+# ------------------ Find function definitions -----------------
+
+arg_split_pat = re.compile("\s*,\s*")
+
+proto_pat=re.compile(r"""^
+\s*((?:-|\w|\&|\*)+) # return type
+\s+ # skip whitespace
+([a-z]\w+)\s*[(] # match the function name until the opening (
+\s*(.*?)\s*[)].* # group the function arguments
+$""", re.IGNORECASE|re.VERBOSE|re.MULTILINE)
+
+def find_func_defs(buf, modlib, deffile, defs, verbose):
+ '''Find function prototypes in buf that have symbols in modlib
+ and save in defs.'''
+ funcs = defs['funcs'][deffile] = []
+ for m in proto_pat.findall(buf):
+ ret, func, args = m
+ if not True in [hasattr(lib, func) for lib in modlib]:
+ if verbose:
+ sys.stderr.write('no symbol for function: ' + func
+ + ' from file' + deffile + '\n')
+ else:
+ args = arg_split_pat.split(args)
+ args = [a.replace(' ','-', a.count(' ')-1) for a in args]
+ funcs.append((func, ret, args))
+ return
+
+virtual_pat = re.compile(r'''^
+\s*((?:-|\w|\&|\*)+) # return type
+\s* # skip whitespace
+\(\s*\*\s* # opening (
+([a-z]\w+)\) # match the function name until the closing )
+\s*\(\s*([^)]*)\).* # group the function arguments
+$''', re.VERBOSE|re.MULTILINE)
+
+class_iface_struct_pat = re.compile(
+ r'^struct\s+_(\w+)(?:Class|Iface)\s+{([^}]+)}\s*$', re.MULTILINE)
+
+def find_virt_defs(buf, deffile, defs):
+ '''Find virtual function prototypes in buf and save in defs.'''
+ virts = defs['virts'][deffile] = []
+ # get the Class or Iface structs
+ for m in class_iface_struct_pat.findall(buf):
+ objname, virtuals = m
+ for v in virtual_pat.findall(virtuals):
+ ret, func, args = v
+ if 'reserved' in func or args == 'void':
+ continue
+ args = arg_split_pat.split(args)
+ args = [a.replace(' ','-', a.count(' ')-1) for a in args]
+ virts.append((func, ret, args, objname))
+ return
+
+enum_pat = re.compile(r'^\s*typedef enum\s+{\s*([^}]*)}\s*([^\s]*)$',
+ re.MULTILINE)
+values_splitter = re.compile(r'\s*,\s', re.MULTILINE)
+
+def find_enums(buf, defs):
+ for vals, name in enum_pat.findall(buf):
+ if name != 'GdkCursorType':
+ isflags = '<<' in vals
+ entries = [val.split()[0] for val in values_splitter.split(vals)
+ if val.strip()]
+ if entries:
+ defs['untypedenums'][name] = (isflags, entries)
+ return
+
+# ------------------ write definitions -----------------
+
+type_pat = re.compile(r'(?:const-)?([A-Za-z0-9]+)\*?\s+')
+pointer_pat = re.compile('(.*)\*$')
+func_new_pat = re.compile('(\w+)_new$')
+getset_pat = re.compile(r'^(?:get|set)_(.*)$')
+
+def split_prefix(cname, prefix, use_prefix):
+ # use the module prefix to split the cname
+ pre = prefix.replace('_', '')
+ if use_prefix and cname.lower().startswith(pre):
+ l = len(pre)
+ module = cname[:l]
+ name = cname[l:]
+ else:
+ m = split_prefix_pat.match(cname)
+ if m:
+ module = m.group(1)
+ name = m.group(2)
+ return module, name
+
+class DefsWriter:
+ def __init__(self, defs, fp=None, prefix=None, verbose=False,
+ defsfiles=None, defines={}, genpropgetsets=False,
+ useprefix=False):
+ self.defs = defs
+ self.use_prefix = useprefix
+ self.objnames = reduce(list.__add__,
+ [[o.name for o in defs[base]]
+ for base in defkeys.split()[:3]])
+ self.othernames = reduce(list.__add__,
+ [[o.name for o in defs[base]]
+ for base in defkeys.split()[3:]])
+ self.objifacedefs = dict(reduce(list.__add__,
+ [[(o.name, o) for o in defs[base]]
+ for base in defkeys.split()[1:3]]))
+ self.fp = (fp, sys.stdout)[not fp]
+ self.prefix = prefix
+ self.verbose = verbose
+ self.genpropgetsets = genpropgetsets
+ self._c_names={}
+ for defsfile in defsfiles:
+ filter = defsparser.DefsParser(defsfile, defines)
+ filter.startParsing()
+ self._c_names.update(filter.c_name)
+ for vdef in filter.virtuals:
+ self._c_names[vdef.of_object + '.' + vdef.name] = None
+ return
+
+ def write_func_defs(self, deffiles, onlyvirts=False):
+ filter = self._c_names
+ for deffile in deffiles:
+ self.fp.write('\n;; From %s\n\n' % os.path.basename(deffile))
+ if not onlyvirts:
+ for func, ret, args in self.defs['funcs'][deffile]:
+ if not func in filter:
+ self._write_func(func, ret, args)
+ for virt, ret, args, objname in self.defs['virts'][deffile]:
+ if not objname + '.' + virt in filter:
+ self._write_virt(objname, virt, ret, args)
+ self.fp.write('\n')
+ return
+
+ def write_enum_defs(self, fp=None):
+ fp = (fp, self.fp)[not fp]
+ klassptrs = {'GEnum':ctypes.POINTER(EnumClass),
+ 'GFlags':ctypes.POINTER(FlagsClass)}
+ filter = self._c_names
+ objs = self.defs['GEnum'] + self.defs ['GFlags']
+ #objs.sort()
+ fp.write(';; Enumerations and Flags ...\n\n')
+ for obj in objs:
+ cname = name = obj.name
+ tcode = typecode(cname, self.prefix, self.use_prefix)
+ if cname in filter:
+ continue
+ if cname in self.defs['untypedenums']:
+ if tcode not in self.defs['typedefines']:
+ # no type define so skip and print as untyped enum
+ continue
+ self.defs['untypedenums'].pop(cname, None)
+ parent_name = obj.parent_name
+ klassptr = klassptrs[parent_name]
+ typename = parent_name.lower()[1:]
+ module = None
+ module, name = split_prefix(cname, self.prefix, self.use_prefix)
+ fp.write('(define-' + typename + ' ' + name + '\n')
+ if module:
+ fp.write(' (in-module "' + module + '")\n')
+ fp.write(' (c-name "' + cname + '")\n')
+ fp.write(' (gtype-id "' + tcode + '")\n')
+ fp.write(' (values\n')
+ classref = self.gobj.g_type_class_ref(obj.type)
+ itemclass = ctypes.cast(classref, klassptr).contents
+ for i in range(itemclass.n_values):
+ val = itemclass.values[i]
+ fp.write(' \'("%s" "%s")\n' % (val.value_nick,
+ val.value_name))
+ fp.write(' )\n')
+ fp.write(')\n\n')
+ if self.defs['untypedenums']:
+ self.write_untyped_enum_defs(fp)
+ return
+
+ def write_untyped_enum_defs(self, fp):
+ fp.write(';; Untyped enumerations and flags ...\n\n')
+ filter = self._c_names
+ for cname, (isflags, entries) in self.defs['untypedenums'].items():
+ if filter and cname in filter: continue
+ module, name = split_prefix(cname, self.prefix, self.use_prefix)
+ if isflags:
+ fp.write('(define-flags ' + name + '\n')
+ else:
+ fp.write('(define-enum ' + name + '\n')
+ if module:
+ fp.write(' (in-module "' + module + '")\n')
+ fp.write(' (c-name "' + cname + '")\n')
+ preindex = entries[0].rfind('_')
+ for ent in entries[1:]:
+ while (preindex > 0
+ and ent[:preindex] != entries[0][:preindex]):
+ preindex = ent[:preindex].rfind('_')
+ fp.write(' (values\n')
+ for ent in entries:
+ fp.write(' \'("%s" "%s")\n' %
+ (ent[preindex+1:].lower().replace('_', '-'), ent))
+ fp.write(' )\n')
+ fp.write(')\n\n')
+
+
+ def _write_obj_helper(self, obj, fp):
+ base_name = obj.base_name.lower()[1:]
+ cmodule = None
+ cname = name = obj.name
+ type_id = obj.type
+ parent_name = obj.parent_name
+ cmodule, name = split_prefix(cname, self.prefix, self.use_prefix)
+ fp.write('(define-' + base_name + ' ' + name + '\n')
+ if cmodule:
+ fp.write(' (in-module "' + cmodule + '")\n')
+ if base_name == 'object':
+ fp.write(' (parent "' + parent_name + '")\n')
+ fp.write(' (c-name "' + cname + '")\n')
+ fp.write(' (gtype-id "'
+ + typecode(cname, self.prefix, self.use_prefix) + '")\n')
+ n = ctypes.c_uint()
+ ifaces = self.gobj.g_type_interfaces(type_id, ctypes.byref(n))
+ for i in range(n.value):
+ iface_name = self.gobj.g_type_name(ifaces[i])
+ if iface_name in self.interfaces:
+ fp.write(' (implements "%s")\n' % iface_name)
+ if base_name == 'interface':
+ prereq = self.gobj.g_type_interface_prerequisites(type_id,
+ ctypes.byref(n))
+ for i in range(n.value):
+ fp.write(' (prerequisite "%s")\n'
+ % self.gobj.g_type_name(prereq[i]))
+ # should do something about accessible fields
+ fp.write(')\n\n')
+ return
+
+ def write_obj_defs(self, fp=None):
+ fp = (fp, self.fp)[not fp]
+ fp.write(';; -*- scheme -*-\n')
+ filter = self._c_names
+ for base in defkeys.split()[:4]:
+ base_name = base.lower()[1:]
+ fp.write('; %s definitions ...\n\n' % base_name)
+ for obj in self.defs[base]:
+ if not obj.name in filter:
+ self._write_obj_helper(obj, fp)
+ return
+
+ def _write_func(self, name, ret, args):
+ if len(args) >= 1:
+ # methods must have at least one argument
+ munged_name = name.replace('_', '')
+ m = type_pat.match(args[0])
+ if m:
+ obj = m.group(1)
+ if munged_name.startswith(obj.lower()):
+ if obj not in self.othernames:
+ self._write_method(obj, name, ret, args)
+ return
+ fname = name
+ if self.prefix:
+ fname = re.sub('^'+self.prefix+'_', '', fname)
+
+ # it is either a constructor or normal function
+ self.fp.write('(define-function ' + fname + '\n')
+ self.fp.write(' (c-name "' + name + '")\n')
+
+ # Asume that a constructor function name
+ # ends with '_new' and it returns an object pointer.
+ m = func_new_pat.match(name)
+ r = pointer_pat.match(ret)
+ if m and r:
+ cname = ''
+ # get the type name by using the _get_type function
+ func = m.group(1) + '_get_type'
+ lib = [l for l in self.modlib if hasattr(l, func)]
+ if lib:
+ cname = self.gobj.g_type_name(apply(getattr(lib[0], func)))
+ if cname and self.gobj.g_type_from_name(r.group(1)):
+ self.fp.write(' (is-constructor-of "' + cname + '")\n')
+ self._write_return(ret)
+ self._write_arguments(args)
+ return
+
+ def _write_method(self, obj, name, ret, args):
+ regex = ''.join([c+'_?' for c in obj.lower()])
+ mname, count = re.subn(regex, '', name, 1)
+ if not count and self.prefix:
+ mname = re.sub('^'+self.prefix+'_', '', mname)
+ self.fp.write('(define-method ' + mname + '\n')
+ self.fp.write(' (of-object "' + obj + '")\n')
+ self.fp.write(' (c-name "' + name + '")\n')
+ m = getset_pat.match(mname)
+ if self.genpropgetsets and m and len(args[1:]) <= 1:
+ prop = m.group(1)
+ if obj in self.objifacedefs:
+ oidef = self.objifacedefs[obj]
+ if prop.replace('_', '-') in oidef.props:
+ self.fp.write(' (prop-getset "' + prop + '")\n')
+ self._write_return(ret)
+ self._write_arguments(args[1:])
+ return
+
+ def _write_virt(self, obj, name, ret, args):
+ self.fp.write('(define-virtual ' + name + '\n')
+ self.fp.write(' (of-object "' + obj + '")\n')
+ self._write_return(ret)
+ self._write_arguments(args[1:])
+ return
+
+ def _write_return(self, ret):
+ if ret == 'void':
+ ret = 'none'
+ self.fp.write(' (return-type "' + ret + '")\n')
+ return
+
+ def _write_arguments(self, args):
+ if args and not 'void' in args:
+ varargs = ''
+ self.fp.write(' (parameters\n')
+ for arg in args:
+ if arg == '...':
+ varargs = ' (varargs #t)\n'
+ else:
+ tupleArg = tuple(arg.split())
+ if len(tupleArg) == 2:
+ self.fp.write(' \'("%s" "%s")\n' % tupleArg)
+ self.fp.write(' )\n' + varargs)
+ self.fp.write(')\n\n')
+
+# ---------- ctypes support classes for gobject library functions ----------
+
+GType = ctypes.c_uint
+
+class GTypeClass(ctypes.Structure):
+ _fields_ = [('g_type', GType)]
+
+class GTypeInstance(ctypes.Structure):
+ _fields_ = [('g_class', ctypes.POINTER(GTypeClass))]
+
+class EnumValue(ctypes.Structure):
+ _fields_ = [('value', ctypes.c_int),
+ ('value_name', ctypes.c_char_p),
+ ('value_nick', ctypes.c_char_p)]
+
+class FlagsValue(ctypes.Structure):
+ _fields_ = [('value', ctypes.c_uint),
+ ('value_name', ctypes.c_char_p),
+ ('value_nick', ctypes.c_char_p)]
+
+class EnumClass(ctypes.Structure):
+ _fields_ = [('g_type_class', GTypeClass),
+ ('minimum', ctypes.c_int),
+ ('maximum', ctypes.c_int),
+ ('n_values', ctypes.c_uint),
+ ('values', ctypes.POINTER(EnumValue))]
+
+class FlagsClass(ctypes.Structure):
+ _fields_ = [('g_type_class', GTypeClass),
+ ('mask', ctypes.c_uint),
+ ('n_values', ctypes.c_uint),
+ ('values', ctypes.POINTER(FlagsValue))]
+
+class GTypeInterface(ctypes.Structure):
+ _fields_ = [('g_type', GType),
+ ('g_instance_type', GType)]
+
+class GParamSpec(ctypes.Structure):
+ _fields_ = [('g_type_instance', GTypeInstance),
+ ('name', ctypes.c_char_p),
+ ('flags', ctypes.c_uint),
+ ('value_type', GType),
+ ('owner_type', GType)]
+
+# ------------------ Main function -----------------
+
+def main(args):
+ verbose = False
+ all = True
+ onlyenums = False
+ onlyobjdefs = False
+ onlyvirtuals = False
+ separate = False
+ modulename = None
+ defsfiles = []
+ libgobject = None
+ modulelibs = []
+ defines = {}
+ genpropgetsets = False
+ use_prefix = False
+ opts, args = getopt.getopt(args[1:], 'vs:m:f:D:L:l:p',
+ ['onlyenums', 'onlyobjdefs', 'onlyvirtuals',
+ 'modulename=', 'separate=',
+ 'defsfile=', 'defines=', 'genpropgetsets',
+ 'libgobject-', 'modulelib=', 'useprefix'])
+ for o, v in opts:
+ if o == '-v':
+ verbose = True
+ if o == '--onlyenums':
+ onlyenums = True
+ all = False
+ if o == '--onlyvirtuals':
+ onlyvirtuals = True
+ all = False
+ if o == '--onlyobjdefs':
+ onlyobjdefs = True
+ all = False
+ if o in ('-p', '--useprefix'):
+ use_prefix = True
+ if o == '--genpropgetsets':
+ genpropgetsets = True
+ if o in ('-s', '--separate'):
+ separate = v
+ if o in ('-m', '--modulename'):
+ modulename = v
+ if o in ('-L', '--libgobject'):
+ libgobject = v
+ if o in ('-l', '--modulelib'):
+ modulelibs.append(v)
+ if o in ('-f', '--defsfile'):
+ defsfiles.append(v)
+ if o in ('-D', '--defines'):
+ nameval = v.split('=')
+ try:
+ defines[nameval[0]] = nameval[1]
+ except IndexError:
+ defines[nameval[0]] = None
+
+ if not args[0:1]:
+ print 'Must specify at least one input file name'
+ return -1
+ if not modulelibs:
+ print 'Must specify one or more modulelib names'
+ return -1
+
+ # load the gobject and module libraries and init the gtype system
+ if not libgobject:
+ if verbose:
+ sys.stderr.write('Using "libgobject-2.0.so" as the libobject' \
+ 'library name by default\n')
+ gobj = ctypes.cdll.LoadLibrary('libgobject-2.0.so')
+ else:
+ gobj = ctypes.cdll.LoadLibrary(libgobject)
+
+ modlib = [ctypes.cdll.LoadLibrary(lib) for lib in modulelibs]
+
+ gobj.g_type_init()
+ gobj.g_type_name.restype = ctypes.c_char_p
+ gobj.g_type_from_name.argtypes = [ctypes.c_char_p]
+ gobj.g_type_interfaces.restype = ctypes.POINTER(ctypes.c_int)
+ gobj.g_type_interface_prerequisites.restype = ctypes.POINTER(ctypes.c_int)
+ gobj.g_object_class_list_properties.restype = ctypes.POINTER(ctypes.POINTER(GParamSpec))
+ gobj.g_object_interface_list_properties.restype = ctypes.POINTER(ctypes.POINTER(GParamSpec))
+ gobj.GObject = gobj.g_type_from_name('GObject')
+ gobj.g_object_new(gobj.GObject, None)
+
+ defs = {}
+ for key in defkeys.split():
+ defs[key] = []
+ defs['funcs'] = {}
+ defs['virts'] = {}
+ defs['untypedenums'] = {}
+ defs['typedefines'] = []
+
+ # read in all the object and function definitions
+ args.sort()
+ type_define_pat = re.compile(
+ r'^#define\s+([A-Z]\S+_TYPE_\S+)\s+.*[a-z]\w+_get_type.*$',
+ re.MULTILINE)
+ for filename in args:
+ buf = open(filename).read()
+ defs['typedefines'] += type_define_pat.findall(buf)
+ buf = clean_buffer(buf)
+ find_enums(buf, defs)
+ find_defs(buf, gobj, modlib, defs)
+ find_func_defs(buf, modlib, filename, defs, verbose)
+ find_virt_defs(buf, filename, defs)
+
+ for key in defkeys.split():
+ defs[key].sort()
+
+ methods = types = None
+ if separate:
+ methods = file(separate + '.defs', 'w')
+ types = file(separate + '-types.defs', 'w')
+
+ dw = DefsWriter(defs, methods, prefix=modulename, verbose=verbose,
+ defsfiles=defsfiles, defines=defines,
+ genpropgetsets=genpropgetsets, useprefix=use_prefix)
+ dw.interfaces = [i.name for i in defs['GInterface']]
+ dw.gobj = gobj
+ dw.modlib = modlib
+
+ if onlyobjdefs or all:
+ dw.write_obj_defs(types)
+ if separate:
+ print "Wrote object defs to %s-types.defs" % separate
+ if onlyenums or all:
+ dw.write_enum_defs(types)
+ if separate:
+ print "Wrote enum and flags defs to %s-types.defs" % separate
+ if onlyvirtuals or all:
+ dw.write_func_defs(args, onlyvirtuals)
+ if separate:
+ print "Wrote function and virtual defs to %s.defs" % separate
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv))