diff options
author | Edward Hervey <bilboed@bilboed.com> | 2006-06-09 10:50:21 +0000 |
---|---|---|
committer | Edward Hervey <bilboed@bilboed.com> | 2006-06-09 10:50:21 +0000 |
commit | bc17f73dcbde88042a175213dfeb98e45afafef3 (patch) | |
tree | a8e4e4d8a816b788b3db37771cd1350370518d91 /codegen | |
parent | 6189051361a16f28279ab7d2c8c8ebab71a41a17 (diff) |
codegen/: Updated codegenerator to current pygtk one.
Original commit message from CVS:
* codegen/Makefile.am:
* codegen/argtypes.py:
* codegen/codegen.py:
* codegen/definitions.py:
* codegen/defsconvert.py:
* codegen/defsparser.py:
* codegen/docextract.py:
* codegen/docextract_to_xml.py:
* codegen/docgen.py:
* codegen/h2def.py:
* codegen/mergedefs.py:
* codegen/missingdefs.py:
* codegen/mkskel.py:
* codegen/override.py:
* codegen/reversewrapper.py:
Updated codegenerator to current pygtk one.
* gst/gst.defs:
* gst/gst.override:
* gst/gstpad.override:
Update defs for new constructor definition.
* testsuite/test_bin.py:
With new constructors, pygobject will try to convert the argument to the
proper GType (here a string).
Diffstat (limited to 'codegen')
-rw-r--r-- | codegen/Makefile.am | 3 | ||||
-rw-r--r-- | codegen/argtypes.py | 510 | ||||
-rw-r--r-- | codegen/codegen.py | 1112 | ||||
-rw-r--r-- | codegen/definitions.py | 468 | ||||
-rw-r--r-- | codegen/defsconvert.py | 135 | ||||
-rw-r--r-- | codegen/defsparser.py | 63 | ||||
-rw-r--r-- | codegen/docextract.py | 162 | ||||
-rwxr-xr-x | codegen/docextract_to_xml.py | 78 | ||||
-rw-r--r-- | codegen/docgen.py | 69 | ||||
-rwxr-xr-x | codegen/h2def.py | 505 | ||||
-rwxr-xr-x | codegen/mergedefs.py | 7 | ||||
-rwxr-xr-x | codegen/missingdefs.py | 17 | ||||
-rwxr-xr-x | codegen/mkskel.py | 34 | ||||
-rw-r--r-- | codegen/override.py | 172 | ||||
-rw-r--r-- | codegen/reversewrapper.py | 206 |
15 files changed, 1914 insertions, 1627 deletions
diff --git a/codegen/Makefile.am b/codegen/Makefile.am index 45d232f..dd3eea0 100644 --- a/codegen/Makefile.am +++ b/codegen/Makefile.am @@ -3,15 +3,12 @@ EXTRA_DIST = \ code-coverage.py \ codegen.py \ definitions.py \ - defsconvert.py \ defsparser.py \ docextract.py \ - docextract_to_xml.py \ docgen.py \ h2def.py \ __init__.py \ mergedefs.py \ - missingdefs.py \ mkskel.py \ override.py \ reversewrapper.py \ diff --git a/codegen/argtypes.py b/codegen/argtypes.py index 6fd445c..300400f 100644 --- a/codegen/argtypes.py +++ b/codegen/argtypes.py @@ -1,31 +1,29 @@ # -*- Mode: Python; py-indent-offset: 4 -*- -import sys import string -import traceback import keyword import struct class VarList: """Nicely format a C variable list""" def __init__(self): - self.vars = {} + self.vars = {} def add(self, ctype, name): - if self.vars.has_key(ctype): - self.vars[ctype] = self.vars[ctype] + (name,) - else: - self.vars[ctype] = (name,) + if self.vars.has_key(ctype): + self.vars[ctype] = self.vars[ctype] + (name,) + else: + self.vars[ctype] = (name,) def __str__(self): - ret = [] - for type in self.vars.keys(): - ret.append(' ') - ret.append(type) - ret.append(' ') - ret.append(string.join(self.vars[type], ', ')) - ret.append(';\n') - if ret: + ret = [] + for type in self.vars.keys(): + ret.append(' ') + ret.append(type) + ret.append(' ') + ret.append(string.join(self.vars[type], ', ')) + ret.append(';\n') + if ret: ret.append('\n') return string.join(ret, '') - return '' + return '' class WrapperInfo: """A class that holds information about variable defs, code @@ -66,16 +64,16 @@ class WrapperInfo: self.kwlist.append('"%s"' % kw) class ArgType: - def write_param(self, ptype, pname, pdflt, pnull, info): - """Add code to the WrapperInfo instance to handle - parameter.""" - raise RuntimeError, "write_param not implemented for %s" % \ + def write_param(self, ptype, pname, pdflt, pnull, keeprefcount, info): + """Add code to the WrapperInfo instance to handle + parameter.""" + raise RuntimeError, "write_param not implemented for %s" % \ self.__class__.__name__ def write_return(self, ptype, ownsreturn, info): - """Adds a variable named ret of the return type to - info.varlist, and add any required code to info.codeafter to - convert the return value to a python object.""" - raise RuntimeError, "write_return not implemented for %s" % \ + """Adds a variable named ret of the return type to + info.varlist, and add any required code to info.codeafter to + convert the return value to a python object.""" + raise RuntimeError, "write_return not implemented for %s" % \ self.__class__.__name__ class NoneArg(ArgType): @@ -85,20 +83,20 @@ class NoneArg(ArgType): class StringArg(ArgType): def write_param(self, ptype, pname, pdflt, pnull, keeprefcount, info): - if pdflt: + if pdflt: if pdflt != 'NULL': pdflt = '"' + pdflt + '"' - info.varlist.add('char', '*' + pname + ' = ' + pdflt) - else: - info.varlist.add('char', '*' + pname) - info.arglist.append(pname) - if pnull: + info.varlist.add('char', '*' + pname + ' = ' + pdflt) + else: + info.varlist.add('char', '*' + pname) + info.arglist.append(pname) + if pnull: info.add_parselist('z', ['&' + pname], [pname]) - else: + else: info.add_parselist('s', ['&' + pname], [pname]) def write_return(self, ptype, ownsreturn, info): if ownsreturn: - # have to free result ... - info.varlist.add('gchar', '*ret') + # have to free result ... + info.varlist.add('gchar', '*ret') info.codeafter.append(' if (ret) {\n' + ' PyObject *py_ret = PyString_FromString(ret);\n' + ' g_free(ret);\n' + @@ -106,8 +104,8 @@ class StringArg(ArgType): ' }\n' + ' Py_INCREF(Py_None);\n' + ' return Py_None;') - else: - info.varlist.add('const gchar', '*ret') + else: + info.varlist.add('const gchar', '*ret') info.codeafter.append(' if (ret)\n' + ' return PyString_FromString(ret);\n'+ ' Py_INCREF(Py_None);\n' + @@ -116,29 +114,29 @@ class StringArg(ArgType): class UCharArg(ArgType): # allows strings with embedded NULLs. def write_param(self, ptype, pname, pdflt, pnull, keeprefcount, info): - if pdflt: - info.varlist.add('guchar', '*' + pname + ' = "' + pdflt + '"') - else: - info.varlist.add('guchar', '*' + pname) + if pdflt: + info.varlist.add('guchar', '*' + pname + ' = "' + pdflt + '"') + else: + info.varlist.add('guchar', '*' + pname) info.varlist.add('int', pname + '_len') - info.arglist.append(pname) - if pnull: + info.arglist.append(pname) + if pnull: info.add_parselist('z#', ['&' + pname, '&' + pname + '_len'], [pname]) - else: + else: info.add_parselist('s#', ['&' + pname, '&' + pname + '_len'], [pname]) class CharArg(ArgType): def write_param(self, ptype, pname, pdflt, pnull, keeprefcount, info): - if pdflt: - info.varlist.add('char', pname + " = '" + pdflt + "'") - else: - info.varlist.add('char', pname) - info.arglist.append(pname) + if pdflt: + info.varlist.add('char', pname + " = '" + pdflt + "'") + else: + info.varlist.add('char', pname) + info.arglist.append(pname) info.add_parselist('c', ['&' + pname], [pname]) def write_return(self, ptype, ownsreturn, info): - info.varlist.add('gchar', 'ret') + info.varlist.add('gchar', 'ret') info.codeafter.append(' return PyString_FromStringAndSize(&ret, 1);') class GUniCharArg(ArgType): ret_tmpl = ('#if !defined(Py_UNICODE_SIZE) || Py_UNICODE_SIZE == 2\n' @@ -150,25 +148,25 @@ class GUniCharArg(ArgType): ' py_ret = (Py_UNICODE)ret;\n' ' return PyUnicode_FromUnicode(&py_ret, 1);\n') def write_param(self, ptype, pname, pdflt, pnull, keeprefcount, info): - if pdflt: - info.varlist.add('gunichar', pname + " = '" + pdflt + "'") - else: - info.varlist.add('gunichar', pname) - info.arglist.append(pname) + if pdflt: + info.varlist.add('gunichar', pname + " = '" + pdflt + "'") + else: + info.varlist.add('gunichar', pname) + info.arglist.append(pname) info.add_parselist('O&', ['pyg_pyobj_to_unichar_conv', '&' + pname], [pname]) def write_return(self, ptype, ownsreturn, info): info.varlist.add('gunichar', 'ret') info.varlist.add('Py_UNICODE', 'py_ret') info.codeafter.append(self.ret_tmpl) - + class IntArg(ArgType): def write_param(self, ptype, pname, pdflt, pnull, keeprefcount, info): - if pdflt: - info.varlist.add('int', pname + ' = ' + pdflt) - else: - info.varlist.add('int', pname) - info.arglist.append(pname) + if pdflt: + info.varlist.add('int', pname + ' = ' + pdflt) + else: + info.varlist.add('int', pname) + info.arglist.append(pname) info.add_parselist('i', ['&' + pname], [pname]) def write_return(self, ptype, ownsreturn, info): info.varlist.add('int', 'ret') @@ -212,13 +210,13 @@ class SizeArg(ArgType): llp64 = True else: llp64 = False - + def write_param(self, ptype, pname, pdflt, pnull, keeprefcount, info): - if pdflt: - info.varlist.add(ptype, pname + ' = ' + pdflt) - else: - info.varlist.add(ptype, pname) - info.arglist.append(pname) + if pdflt: + info.varlist.add(ptype, pname + ' = ' + pdflt) + else: + info.varlist.add(ptype, pname) + info.arglist.append(pname) if self.llp64: info.add_parselist('k', ['&' + pname], [pname]) else: @@ -236,13 +234,13 @@ class SSizeArg(ArgType): llp64 = True else: llp64 = False - + def write_param(self, ptype, pname, pdflt, pnull, keeprefcount, info): - if pdflt: - info.varlist.add(ptype, pname + ' = ' + pdflt) - else: - info.varlist.add(ptype, pname) - info.arglist.append(pname) + if pdflt: + info.varlist.add(ptype, pname + ' = ' + pdflt) + else: + info.varlist.add(ptype, pname) + info.arglist.append(pname) if self.llp64: info.add_parselist('l', ['&' + pname], [pname]) else: @@ -256,11 +254,11 @@ class SSizeArg(ArgType): class LongArg(ArgType): def write_param(self, ptype, pname, pdflt, pnull, keeprefcount, info): - if pdflt: - info.varlist.add(ptype, pname + ' = ' + pdflt) - else: - info.varlist.add(ptype, pname) - info.arglist.append(pname) + if pdflt: + info.varlist.add(ptype, pname + ' = ' + pdflt) + else: + info.varlist.add(ptype, pname) + info.arglist.append(pname) info.add_parselist('l', ['&' + pname], [pname]) def write_return(self, ptype, ownsreturn, info): info.varlist.add(ptype, 'ret') @@ -273,66 +271,80 @@ class BoolArg(IntArg): class TimeTArg(ArgType): def write_param(self, ptype, pname, pdflt, pnull, keeprefcount, info): - if pdflt: - info.varlist.add('time_t', pname + ' = ' + pdflt) - else: - info.varlist.add('time_t', pname) - info.arglist.append(pname) + if pdflt: + info.varlist.add('time_t', pname + ' = ' + pdflt) + else: + info.varlist.add('time_t', pname) + info.arglist.append(pname) info.add_parselist('i', ['&' + pname], [pname]) def write_return(self, ptype, ownsreturn, info): info.varlist.add('time_t', 'ret') info.codeafter.append(' return PyInt_FromLong(ret);') class ULongArg(ArgType): - dflt = ' if (py_%(name)s)\n' \ - ' %(name)s = PyLong_AsUnsignedLong(py_%(name)s);\n' - before = ' %(name)s = PyLong_AsUnsignedLong(py_%(name)s);\n' def write_param(self, ptype, pname, pdflt, pnull, keeprefcount, info): if pdflt: - info.varlist.add('gulong', pname + ' = ' + pdflt) - info.codebefore.append(self.dflt % {'name':pname}) + info.varlist.add('unsigned long', pname + ' = ' + pdflt) else: - info.varlist.add('gulong', pname) - info.codebefore.append(self.before % {'name':pname}) - info.varlist.add('PyObject', "*py_" + pname + ' = NULL') + info.varlist.add('unsigned long', pname) info.arglist.append(pname) - info.add_parselist('O!', ['&PyLong_Type', '&py_' + pname], [pname]) + info.add_parselist('k', ['&' + pname], [pname]) def write_return(self, ptype, ownsreturn, info): - info.varlist.add('gulong', 'ret') - info.codeafter.append(' return PyLong_FromUnsignedLong(ret);') + info.varlist.add(ptype, 'ret') + info.codeafter.append(' return PyLong_FromUnsignedLong(ret);\n') + +class UInt32Arg(ULongArg): + def write_param(self, ptype, pname, pdflt, pnull, keeprefcount, info): + ULongArg.write_param(self, ptype, pname, pdflt, pnull, keeprefcount, info) + ## if sizeof(unsigned long) > sizeof(unsigned int), we need to + ## check the value is within guint32 range + if struct.calcsize('L') > struct.calcsize('I'): + info.codebefore.append(( + ' if (%(pname)s > G_MAXUINT32) {\n' + ' PyErr_SetString(PyExc_ValueError,\n' + ' "Value out of range in conversion of"\n' + ' " %(pname)s parameter to unsigned 32 bit integer");\n' + ' return NULL;\n' + ' }\n') % vars()) class Int64Arg(ArgType): def write_param(self, ptype, pname, pdflt, pnull, keeprefcount, info): - if pdflt: - info.varlist.add('gint64', pname + ' = ' + pdflt) - else: - info.varlist.add('gint64', pname) - info.arglist.append(pname) + if pdflt: + info.varlist.add('gint64', pname + ' = ' + pdflt) + else: + info.varlist.add('gint64', pname) + info.arglist.append(pname) info.add_parselist('L', ['&' + pname], [pname]) def write_return(self, ptype, ownsreturn, info): info.varlist.add('gint64', 'ret') info.codeafter.append(' return PyLong_FromLongLong(ret);') class UInt64Arg(ArgType): + dflt = ' if (py_%(name)s)\n' \ + ' %(name)s = PyLong_AsUnsignedLongLong(py_%(name)s);\n' + before = ' %(name)s = PyLong_AsUnsignedLongLong(py_%(name)s);\n' def write_param(self, ptype, pname, pdflt, pnull, keeprefcount, info): - if pdflt: - info.varlist.add('guint64', pname + ' = ' + pdflt) - else: - info.varlist.add('guint64', pname) - info.arglist.append(pname) - info.add_parselist('K', ['&' + pname], [pname]) + if pdflt: + info.varlist.add('guint64', pname + ' = ' + pdflt) + info.codebefore.append(self.dflt % {'name':pname}) + else: + info.varlist.add('guint64', pname) + info.codebefore.append(self.before % {'name':pname}) + info.varlist.add('PyObject', "*py_" + pname + ' = NULL') + info.arglist.append(pname) + info.add_parselist('O!', ['&PyLong_Type', '&py_' + pname], [pname]) def write_return(self, ptype, ownsreturn, info): info.varlist.add('guint64', 'ret') info.codeafter.append(' return PyLong_FromUnsignedLongLong(ret);') - + class DoubleArg(ArgType): def write_param(self, ptype, pname, pdflt, pnull, keeprefcount, info): - if pdflt: - info.varlist.add('double', pname + ' = ' + pdflt) - else: - info.varlist.add('double', pname) - info.arglist.append(pname) + if pdflt: + info.varlist.add('double', pname + ' = ' + pdflt) + else: + info.varlist.add('double', pname) + info.arglist.append(pname) info.add_parselist('d', ['&' + pname], [pname]) def write_return(self, ptype, ownsreturn, info): info.varlist.add('double', 'ret') @@ -345,7 +357,7 @@ class FileArg(ArgType): ' %s = PyFile_AsFile(py_%(name)s);\n' ' else if (py_%(name)s) {\n' ' PyErr_SetString(PyExc_TypeError, "%(name)s should be a file object or None");\n' - ' return NULL;\n' + ' return NULL;\n' ' }') null = (' if (py_%(name)s && PyFile_Check(py_%(name)s)\n' ' %(name)s = PyFile_AsFile(py_%(name)s);\n' @@ -356,29 +368,29 @@ class FileArg(ArgType): dflt = (' if (py_%(name)s)\n' ' %(name)s = PyFile_AsFile(py_%(name)s);\n') def write_param(self, ptype, pname, pdflt, pnull, keeprefcount, info): - if pnull: - if pdflt: - info.varlist.add('FILE', '*' + pname + ' = ' + pdflt) - info.varlist.add('PyObject', '*py_' + pname + ' = NULL') - info.codebefore.append(self.nulldflt % {'name':pname}) - else: - info.varlist.add('FILE', '*' + pname + ' = NULL') - info.varlist.add('PyObject', '*py_' + pname) - info.codebefore.append(self.null & {'name':pname}) + if pnull: + if pdflt: + info.varlist.add('FILE', '*' + pname + ' = ' + pdflt) + info.varlist.add('PyObject', '*py_' + pname + ' = NULL') + info.codebefore.append(self.nulldflt % {'name':pname}) + else: + info.varlist.add('FILE', '*' + pname + ' = NULL') + info.varlist.add('PyObject', '*py_' + pname) + info.codebefore.append(self.null & {'name':pname}) info.arglist.appned(pname) info.add_parselist('O', ['&py_' + pname], [pname]) - else: - if pdflt: - info.varlist.add('FILE', '*' + pname + ' = ' + pdflt) - info.varlist.add('PyObject', '*py_' + pname + ' = NULL') - info.codebefore.append(self.dflt % {'name':pname}) - info.arglist.append(pname) - else: - info.varlist.add('PyObject', '*' + pname) - info.arglist.append('PyFile_AsFile(' + pname + ')') + else: + if pdflt: + info.varlist.add('FILE', '*' + pname + ' = ' + pdflt) + info.varlist.add('PyObject', '*py_' + pname + ' = NULL') + info.codebefore.append(self.dflt % {'name':pname}) + info.arglist.append(pname) + else: + info.varlist.add('PyObject', '*' + pname) + info.arglist.append('PyFile_AsFile(' + pname + ')') info.add_parselist('O!', ['&PyFile_Type', '&' + pname], [pname]) def write_return(self, ptype, ownsreturn, info): - info.varlist.add('FILE', '*ret') + info.varlist.add('FILE', '*ret') info.codeafter.append(' if (ret)\n' + ' return PyFile_FromFile(ret, "", "", fclose);\n' + ' Py_INCREF(Py_None);\n' + @@ -388,17 +400,17 @@ class EnumArg(ArgType): enum = (' if (pyg_enum_get_value(%(typecode)s, py_%(name)s, (gint *)&%(name)s))\n' ' return NULL;\n') def __init__(self, enumname, typecode): - self.enumname = enumname - self.typecode = typecode + self.enumname = enumname + self.typecode = typecode def write_param(self, ptype, pname, pdflt, pnull, keeprefcount, info): - if pdflt: - info.varlist.add(self.enumname, pname + ' = ' + pdflt) - else: - info.varlist.add(self.enumname, pname) - info.varlist.add('PyObject', '*py_' + pname + ' = NULL') - info.codebefore.append(self.enum % { 'typecode': self.typecode, + if pdflt: + info.varlist.add(self.enumname, pname + ' = ' + pdflt) + else: + info.varlist.add(self.enumname, pname) + info.varlist.add('PyObject', '*py_' + pname + ' = NULL') + info.codebefore.append(self.enum % { 'typecode': self.typecode, 'name': pname}) - info.arglist.append(pname) + info.arglist.append(pname) info.add_parselist('O', ['&py_' + pname], [pname]); def write_return(self, ptype, ownsreturn, info): info.varlist.add('gint', 'ret') @@ -408,20 +420,20 @@ class FlagsArg(ArgType): flag = (' if (%(default)spyg_flags_get_value(%(typecode)s, py_%(name)s, (gint *)&%(name)s))\n' ' return NULL;\n') def __init__(self, flagname, typecode): - self.flagname = flagname - self.typecode = typecode + self.flagname = flagname + self.typecode = typecode def write_param(self, ptype, pname, pdflt, pnull, keeprefcount, info): - if pdflt: - info.varlist.add(self.flagname, pname + ' = ' + pdflt) + if pdflt: + info.varlist.add(self.flagname, pname + ' = ' + pdflt) default = "py_%s && " % (pname,) - else: - info.varlist.add(self.flagname, pname) + else: + info.varlist.add(self.flagname, pname) default = "" - info.varlist.add('PyObject', '*py_' + pname + ' = NULL') + info.varlist.add('PyObject', '*py_' + pname + ' = NULL') info.codebefore.append(self.flag % {'default':default, 'typecode':self.typecode, 'name':pname}) - info.arglist.append(pname) + info.arglist.append(pname) info.add_parselist('O', ['&py_' + pname], [pname]) def write_return(self, ptype, ownsreturn, info): info.varlist.add('guint', 'ret') @@ -447,42 +459,57 @@ class ObjectArg(ArgType): dflt = ' if (py_%(name)s)\n' \ ' %(name)s = %(cast)s(py_%(name)s->obj);\n' def __init__(self, objname, parent, typecode): - self.objname = objname - self.cast = string.replace(typecode, '_TYPE_', '_', 1) + self.objname = objname + self.cast = string.replace(typecode, '_TYPE_', '_', 1) self.parent = parent def write_param(self, ptype, pname, pdflt, pnull, keeprefcount, info): - if pnull: - if pdflt: - info.varlist.add(self.objname, '*' + pname + ' = ' + pdflt) - info.varlist.add('PyGObject', '*py_' + pname + ' = NULL') - info.codebefore.append(self.nulldflt % {'name':pname, + if pnull: + if pdflt: + info.varlist.add(self.objname, '*' + pname + ' = ' + pdflt) + info.varlist.add('PyGObject', '*py_' + pname + ' = NULL') + info.codebefore.append(self.nulldflt % {'name':pname, 'cast':self.cast, - 'type':self.objname}) - else: - info.varlist.add(self.objname, '*' + pname + ' = NULL') - info.varlist.add('PyGObject', '*py_' + pname) - info.codebefore.append(self.null % {'name':pname, + 'type':self.objname}) + else: + info.varlist.add(self.objname, '*' + pname + ' = NULL') + info.varlist.add('PyGObject', '*py_' + pname) + info.codebefore.append(self.null % {'name':pname, 'cast':self.cast, - 'type':self.objname}) - info.arglist.append(pname) + 'type':self.objname}) + if ptype.endswith('*'): + typename = ptype[:-1] + try: + const, typename = typename.split('const-') + except ValueError: + const = '' + if typename != ptype: + info.arglist.append('(%s *) %s' % (ptype[:-1], pname)) + else: + info.arglist.append(pname) + info.add_parselist('O', ['&py_' + pname], [pname]) - else: - if pdflt: - info.varlist.add(self.objname, '*' + pname + ' = ' + pdflt) - info.varlist.add('PyGObject', '*py_' + pname + ' = NULL') - info.codebefore.append(self.dflt % {'name':pname, - 'cast':self.cast}) - info.arglist.append(pname) + else: + if pdflt: + info.varlist.add(self.objname, '*' + pname + ' = ' + pdflt) + info.varlist.add('PyGObject', '*py_' + pname + ' = NULL') + info.codebefore.append(self.dflt % {'name':pname, + 'cast':self.cast}) + info.arglist.append(pname) info.add_parselist('O!', ['&Py%s_Type' % self.objname, '&py_' + pname], [pname]) - else: - info.varlist.add('PyGObject', '*' + pname) - info.arglist.append('%s(%s->obj)' % (self.cast, pname)) + else: + info.varlist.add('PyGObject', '*' + pname) + info.arglist.append('%s(%s->obj)' % (self.cast, pname)) info.add_parselist('O!', ['&Py%s_Type' % self.objname, '&' + pname], [pname]) def write_return(self, ptype, ownsreturn, info): - if ptype[-1] == '*': ptype = ptype[:-1] - info.varlist.add(ptype, '*ret') + if ptype.endswith('*'): + typename = ptype[:-1] + try: + const, typename = typename.split('const-') + except ValueError: + const = '' + info.varlist.add(typename, '*ret') if ownsreturn: info.varlist.add('PyObject', '*py_ret') # < GLib 2.8: using our custom _new and _unref functions @@ -532,7 +559,17 @@ class MiniObjectArg(ArgType): info.codebefore.append(self.null % {'name':pname, 'cast':self.cast, 'type':self.objname}) - info.arglist.append(pname) + if ptype.endswith('*'): + typename = ptype[:-1] + try: + const, typename = typename.split('const-') + except ValueError: + const = '' + if typename != ptype: + info.arglist.append('(%s *) %s' % (ptype[:-1], pname)) + else: + info.arglist.append(pname) + info.add_parselist('O', ['&py_' + pname], [pname]) else: if pdflt: @@ -551,8 +588,13 @@ class MiniObjectArg(ArgType): if keeprefcount: info.codebefore.append(' gst_mini_object_ref(GST_MINI_OBJECT(%s->obj));\n' % pname) def write_return(self, ptype, ownsreturn, info): - if ptype[-1] == '*': ptype = ptype[:-1] - info.varlist.add(ptype, '*ret') + if ptype.endswith('*'): + typename = ptype[:-1] + try: + const, typename = typename.split('const-') + except ValueError: + const = '' + info.varlist.add(typename, '*ret') if ownsreturn: info.varlist.add('PyObject', '*py_ret') info.codeafter.append(' py_ret = pygstminiobject_new((GstMiniObject *)ret);\n' @@ -578,19 +620,19 @@ class BoxedArg(ArgType): ' return NULL;\n' ' }\n') def __init__(self, ptype, typecode): - self.typename = ptype - self.typecode = typecode + self.typename = ptype + self.typecode = typecode def write_param(self, ptype, pname, pdflt, pnull, keeprefcount, info): - if pnull: + if pnull: info.varlist.add(self.typename, '*' + pname + ' = NULL') - info.varlist.add('PyObject', '*py_' + pname + ' = Py_None') - info.codebefore.append(self.null % {'name': pname, + info.varlist.add('PyObject', '*py_' + pname + ' = Py_None') + info.codebefore.append(self.null % {'name': pname, 'typename': self.typename, 'typecode': self.typecode}) - else: + else: info.varlist.add(self.typename, '*' + pname + ' = NULL') - info.varlist.add('PyObject', '*py_' + pname) - info.codebefore.append(self.check % {'name': pname, + info.varlist.add('PyObject', '*py_' + pname) + info.codebefore.append(self.check % {'name': pname, 'typename': self.typename, 'typecode': self.typecode}) if ptype[-1] == '*': @@ -627,23 +669,23 @@ class CustomBoxedArg(ArgType): ' return NULL;\n' ' }\n') def __init__(self, ptype, pytype, getter, new): - self.pytype = pytype - self.getter = getter + self.pytype = pytype + self.getter = getter self.checker = 'Py' + ptype + '_Check' - self.new = new + self.new = new def write_param(self, ptype, pname, pdflt, pnull, keeprefcount, info): - if pnull: + if pnull: info.varlist.add(ptype[:-1], '*' + pname + ' = NULL') - info.varlist.add('PyObject', '*py_' + pname + ' = Py_None') - info.codebefore.append(self.null % {'name': pname, + info.varlist.add('PyObject', '*py_' + pname + ' = Py_None') + info.codebefore.append(self.null % {'name': pname, 'get': self.getter, 'check': self.checker, 'type': ptype[:-1]}) - info.arglist.append(pname) + info.arglist.append(pname) info.add_parselist('O', ['&py_' + pname], [pname]) - else: - info.varlist.add('PyObject', '*' + pname) - info.arglist.append(self.getter + '(' + pname + ')') + else: + info.varlist.add('PyObject', '*' + pname) + info.arglist.append(self.getter + '(' + pname + ')') info.add_parselist('O!', ['&' + self.pytype, '&' + pname], [pname]) def write_return(self, ptype, ownsreturn, info): info.varlist.add(ptype[:-1], '*ret') @@ -667,19 +709,19 @@ class PointerArg(ArgType): ' return NULL;\n' ' }\n') def __init__(self, ptype, typecode): - self.typename = ptype - self.typecode = typecode + self.typename = ptype + self.typecode = typecode def write_param(self, ptype, pname, pdflt, pnull, keeprefcount, info): - if pnull: + if pnull: info.varlist.add(self.typename, '*' + pname + ' = NULL') - info.varlist.add('PyObject', '*py_' + pname + ' = Py_None') - info.codebefore.append(self.null % {'name': pname, + info.varlist.add('PyObject', '*py_' + pname + ' = Py_None') + info.codebefore.append(self.null % {'name': pname, 'typename': self.typename, 'typecode': self.typecode}) - else: + else: info.varlist.add(self.typename, '*' + pname + ' = NULL') - info.varlist.add('PyObject', '*py_' + pname) - info.codebefore.append(self.check % {'name': pname, + info.varlist.add('PyObject', '*py_' + pname) + info.codebefore.append(self.check % {'name': pname, 'typename': self.typename, 'typecode': self.typecode}) info.arglist.append(pname) @@ -716,16 +758,21 @@ class AtomArg(IntArg): info.add_parselist('O', ['&py_' + pname], [pname]) def write_return(self, ptype, ownsreturn, info): info.varlist.add('GdkAtom', 'ret') - info.codeafter.append(' return PyString_FromString(gdk_atom_name(ret));') + info.varlist.add('PyObject *', 'py_ret') + info.varlist.add('gchar *', 'name') + info.codeafter.append(' name = gdk_atom_name(ret);\n' + ' py_ret = PyString_FromString(name);\n' + ' g_free(name);\n' + ' return py_ret;') class GTypeArg(ArgType): gtype = (' if ((%(name)s = pyg_type_from_object(py_%(name)s)) == 0)\n' ' return NULL;\n') def write_param(self, ptype, pname, pdflt, pnull, keeprefcount, info): info.varlist.add('GType', pname) - info.varlist.add('PyObject', '*py_' + pname + ' = NULL') - info.codebefore.append(self.gtype % {'name': pname}) - info.arglist.append(pname) + info.varlist.add('PyObject', '*py_' + pname + ' = NULL') + info.codebefore.append(self.gtype % {'name': pname}) + info.arglist.append(pname) info.add_parselist('O', ['&py_' + pname], [pname]) def write_return(self, ptype, ownsreturn, info): info.varlist.add('GType', 'ret') @@ -759,17 +806,17 @@ class GtkTreePathArg(ArgType): def __init__(self): pass def write_param(self, ptype, pname, pdflt, pnull, keeprefcount, info): - if pnull: + if pnull: info.varlist.add('GtkTreePath', '*' + pname + ' = NULL') - info.varlist.add('PyObject', '*py_' + pname + ' = Py_None') - info.codebefore.append(self.null % {'name': pname}) - info.arglist.append(pname) + info.varlist.add('PyObject', '*py_' + pname + ' = Py_None') + info.codebefore.append(self.null % {'name': pname}) + info.arglist.append(pname) info.add_parselist('O', ['&py_' + pname], [pname]) - else: + else: info.varlist.add('GtkTreePath', '*' + pname) - info.varlist.add('PyObject', '*py_' + pname) + info.varlist.add('PyObject', '*py_' + pname) info.codebefore.append(self.normal % {'name': pname}) - info.arglist.append(pname) + info.arglist.append(pname) info.add_parselist('O', ['&py_' + pname], [pname]) info.codeafter.append(self.freepath % {'name': pname}) def write_return(self, ptype, ownsreturn, info): @@ -789,7 +836,7 @@ class GtkTreePathArg(ArgType): ' }\n' ' Py_INCREF(Py_None);\n' ' return Py_None;') - + class GdkRectanglePtrArg(ArgType): normal = (' if (!pygdk_rectangle_from_pyobject(py_%(name)s, &%(name)s))\n' ' return NULL;\n') @@ -816,8 +863,8 @@ class GdkRectanglePtrArg(ArgType): class GdkRectangleArg(ArgType): def write_return(self, ptype, ownsreturn, info): - info.varlist.add('GdkRectangle', 'ret') - info.codeafter.append(' return pyg_boxed_new(GDK_TYPE_RECTANGLE, &ret, TRUE, TRUE);') + info.varlist.add('GdkRectangle', 'ret') + info.codeafter.append(' return pyg_boxed_new(GDK_TYPE_RECTANGLE, &ret, TRUE, TRUE);') class PyObjectArg(ArgType): def write_param(self, ptype, pname, pdflt, pnull, keeprefcount, info): @@ -839,17 +886,17 @@ class PyObjectArg(ArgType): class ArgMatcher: def __init__(self): - self.argtypes = {} - self.reverse_argtypes = {} - self.reverse_rettypes = {} + self.argtypes = {} + self.reverse_argtypes = {} + self.reverse_rettypes = {} def register(self, ptype, handler): - self.argtypes[ptype] = handler + self.argtypes[ptype] = handler def register_reverse(self, ptype, handler): - self.reverse_argtypes[ptype] = handler + self.reverse_argtypes[ptype] = handler def register_reverse_ret(self, ptype, handler): - self.reverse_rettypes[ptype] = handler - + self.reverse_rettypes[ptype] = handler + def register_enum(self, ptype, typecode): if typecode is None: typecode = "G_TYPE_NONE" @@ -857,11 +904,12 @@ class ArgMatcher: def register_flag(self, ptype, typecode): if typecode is None: typecode = "G_TYPE_NONE" - self.register(ptype, FlagsArg(ptype, typecode)) + self.register(ptype, FlagsArg(ptype, typecode)) def register_object(self, ptype, parent, typecode): oa = ObjectArg(ptype, parent, typecode) self.register(ptype, oa) # in case I forget the * in the .defs - self.register(ptype+'*', oa) + self.register(ptype+'*', oa) + self.register('const-'+ptype+'*', oa) if ptype == 'GdkPixmap': # hack to handle GdkBitmap synonym. self.register('GdkBitmap', oa) @@ -874,16 +922,16 @@ class ArgMatcher: if self.argtypes.has_key(ptype): return arg = BoxedArg(ptype, typecode) self.register(ptype, arg) - self.register(ptype+'*', arg) + self.register(ptype+'*', arg) self.register('const-'+ptype+'*', arg) def register_custom_boxed(self, ptype, pytype, getter, new): arg = CustomBoxedArg(ptype, pytype, getter, new) - self.register(ptype+'*', arg) + self.register(ptype+'*', arg) self.register('const-'+ptype+'*', arg) def register_pointer(self, ptype, typecode): arg = PointerArg(ptype, typecode) self.register(ptype, arg) - self.register(ptype+'*', arg) + self.register(ptype+'*', arg) self.register('const-'+ptype+'*', arg) def get(self, ptype): @@ -994,13 +1042,7 @@ matcher.register('gboolean', arg) arg = TimeTArg() matcher.register('time_t', arg) -# If the system maxint is smaller than unsigned int, we need to use -# Long objects with PyLong_AsUnsignedLong -if sys.maxint >= (1L << 32): - matcher.register('guint32', arg) -else: - arg = ULongArg() - matcher.register('guint32', arg) +matcher.register('guint32', UInt32Arg()) arg = ULongArg() matcher.register('gulong', arg) diff --git a/codegen/codegen.py b/codegen/codegen.py index 7cc5bb4..dd8ac80 100644 --- a/codegen/codegen.py +++ b/codegen/codegen.py @@ -1,7 +1,13 @@ -import sys, os, string -import getopt, traceback, keyword -import defsparser, argtypes, override +import getopt +import keyword +import os +import string +import sys + +import argtypes import definitions +import defsparser +import override import reversewrapper class Coverage(object): @@ -9,18 +15,24 @@ class Coverage(object): self.name = name self.wrapped = 0 self.not_wrapped = 0 + def declare_wrapped(self): self.wrapped += 1 + def declare_not_wrapped(self): self.not_wrapped += 1 + def printstats(self): - total = (self.wrapped + self.not_wrapped) + total = self.wrapped + self.not_wrapped + fd = sys.stderr if total: - print >> sys.stderr, "***INFO*** The coverage of %s is %.2f%% (%i/%i)" %\ - (self.name, float(self.wrapped*100)/total, self.wrapped, total) + fd.write("***INFO*** The coverage of %s is %.2f%% (%i/%i)\n" % + (self.name, + float(self.wrapped*100)/total, + self.wrapped, + total)) else: - print >> sys.stderr, "***INFO*** There are no declared %s." %\ - (self.name, ) + fd.write("***INFO*** There are no declared %s." % self.name) functions_coverage = Coverage("global functions") methods_coverage = Coverage("methods") @@ -44,7 +56,7 @@ def exc_info(): def fixname(name): if keyword.iskeyword(name): - return name + '_' + return name + '_' return name class FileOutput: @@ -78,121 +90,140 @@ class FileOutput: self.setline(self.lineno + 1, self.filename) class Wrapper: - type_tmpl = \ - 'PyTypeObject Py%(typename)s_Type = {\n' \ - ' PyObject_HEAD_INIT(NULL)\n' \ - ' 0, /* ob_size */\n' \ - ' "%(classname)s", /* tp_name */\n' \ - ' sizeof(%(tp_basicsize)s), /* tp_basicsize */\n' \ - ' 0, /* tp_itemsize */\n' \ - ' /* methods */\n' \ - ' (destructor)%(tp_dealloc)s, /* tp_dealloc */\n' \ - ' (printfunc)0, /* tp_print */\n' \ - ' (getattrfunc)%(tp_getattr)s, /* tp_getattr */\n' \ - ' (setattrfunc)%(tp_setattr)s, /* tp_setattr */\n' \ - ' (cmpfunc)%(tp_compare)s, /* tp_compare */\n' \ - ' (reprfunc)%(tp_repr)s, /* tp_repr */\n' \ - ' (PyNumberMethods*)%(tp_as_number)s, /* tp_as_number */\n' \ - ' (PySequenceMethods*)%(tp_as_sequence)s, /* tp_as_sequence */\n' \ - ' (PyMappingMethods*)%(tp_as_mapping)s, /* tp_as_mapping */\n' \ - ' (hashfunc)%(tp_hash)s, /* tp_hash */\n' \ - ' (ternaryfunc)%(tp_call)s, /* tp_call */\n' \ - ' (reprfunc)%(tp_str)s, /* tp_str */\n' \ - ' (getattrofunc)%(tp_getattro)s, /* tp_getattro */\n' \ - ' (setattrofunc)%(tp_setattro)s, /* tp_setattro */\n' \ - ' (PyBufferProcs*)%(tp_as_buffer)s, /* tp_as_buffer */\n' \ - ' %(tp_flags)s, /* tp_flags */\n' \ - ' NULL, /* Documentation string */\n' \ - ' (traverseproc)%(tp_traverse)s, /* tp_traverse */\n' \ - ' (inquiry)%(tp_clear)s, /* tp_clear */\n' \ - ' (richcmpfunc)%(tp_richcompare)s, /* tp_richcompare */\n' \ - ' %(tp_weaklistoffset)s, /* tp_weaklistoffset */\n' \ - ' (getiterfunc)%(tp_iter)s, /* tp_iter */\n' \ - ' (iternextfunc)%(tp_iternext)s, /* tp_iternext */\n' \ - ' %(tp_methods)s, /* tp_methods */\n' \ - ' 0, /* tp_members */\n' \ - ' %(tp_getset)s, /* tp_getset */\n' \ - ' NULL, /* tp_base */\n' \ - ' NULL, /* tp_dict */\n' \ - ' (descrgetfunc)%(tp_descr_get)s, /* tp_descr_get */\n' \ - ' (descrsetfunc)%(tp_descr_set)s, /* tp_descr_set */\n' \ - ' %(tp_dictoffset)s, /* tp_dictoffset */\n' \ - ' (initproc)%(tp_init)s, /* tp_init */\n' \ - ' (allocfunc)%(tp_alloc)s, /* tp_alloc */\n' \ - ' (newfunc)%(tp_new)s, /* tp_new */\n' \ - ' (freefunc)%(tp_free)s, /* tp_free */\n' \ - ' (inquiry)%(tp_is_gc)s /* tp_is_gc */\n' \ + type_tmpl = ( + 'PyTypeObject Py%(typename)s_Type = {\n' + ' PyObject_HEAD_INIT(NULL)\n' + ' 0, /* ob_size */\n' + ' "%(classname)s", /* tp_name */\n' + ' sizeof(%(tp_basicsize)s), /* tp_basicsize */\n' + ' 0, /* tp_itemsize */\n' + ' /* methods */\n' + ' (destructor)%(tp_dealloc)s, /* tp_dealloc */\n' + ' (printfunc)0, /* tp_print */\n' + ' (getattrfunc)%(tp_getattr)s, /* tp_getattr */\n' + ' (setattrfunc)%(tp_setattr)s, /* tp_setattr */\n' + ' (cmpfunc)%(tp_compare)s, /* tp_compare */\n' + ' (reprfunc)%(tp_repr)s, /* tp_repr */\n' + ' (PyNumberMethods*)%(tp_as_number)s, /* tp_as_number */\n' + ' (PySequenceMethods*)%(tp_as_sequence)s, /* tp_as_sequence */\n' + ' (PyMappingMethods*)%(tp_as_mapping)s, /* tp_as_mapping */\n' + ' (hashfunc)%(tp_hash)s, /* tp_hash */\n' + ' (ternaryfunc)%(tp_call)s, /* tp_call */\n' + ' (reprfunc)%(tp_str)s, /* tp_str */\n' + ' (getattrofunc)%(tp_getattro)s, /* tp_getattro */\n' + ' (setattrofunc)%(tp_setattro)s, /* tp_setattro */\n' + ' (PyBufferProcs*)%(tp_as_buffer)s, /* tp_as_buffer */\n' + ' %(tp_flags)s, /* tp_flags */\n' + ' %(tp_doc)s, /* Documentation string */\n' + ' (traverseproc)%(tp_traverse)s, /* tp_traverse */\n' + ' (inquiry)%(tp_clear)s, /* tp_clear */\n' + ' (richcmpfunc)%(tp_richcompare)s, /* tp_richcompare */\n' + ' %(tp_weaklistoffset)s, /* tp_weaklistoffset */\n' + ' (getiterfunc)%(tp_iter)s, /* tp_iter */\n' + ' (iternextfunc)%(tp_iternext)s, /* tp_iternext */\n' + ' (struct PyMethodDef*)%(tp_methods)s, /* tp_methods */\n' + ' (struct PyMemberDef*)0, /* tp_members */\n' + ' (struct PyGetSetDef*)%(tp_getset)s, /* tp_getset */\n' + ' NULL, /* tp_base */\n' + ' NULL, /* tp_dict */\n' + ' (descrgetfunc)%(tp_descr_get)s, /* tp_descr_get */\n' + ' (descrsetfunc)%(tp_descr_set)s, /* tp_descr_set */\n' + ' %(tp_dictoffset)s, /* tp_dictoffset */\n' + ' (initproc)%(tp_init)s, /* tp_init */\n' + ' (allocfunc)%(tp_alloc)s, /* tp_alloc */\n' + ' (newfunc)%(tp_new)s, /* tp_new */\n' + ' (freefunc)%(tp_free)s, /* tp_free */\n' + ' (inquiry)%(tp_is_gc)s /* tp_is_gc */\n' '};\n\n' - - slots_list = ['tp_getattr', 'tp_setattr', 'tp_getattro', 'tp_setattro', - 'tp_compare', 'tp_repr', - 'tp_as_number', 'tp_as_sequence', 'tp_as_mapping', 'tp_hash', - 'tp_call', 'tp_str', 'tp_as_buffer', 'tp_richcompare', 'tp_iter', - 'tp_iternext', 'tp_descr_get', 'tp_descr_set', 'tp_init', - 'tp_alloc', 'tp_new', 'tp_free', 'tp_is_gc', - 'tp_traverse', 'tp_clear', 'tp_dealloc', 'tp_flags'] - - getter_tmpl = \ - 'static PyObject *\n' \ - '%(funcname)s(PyObject *self, void *closure)\n' \ - '{\n' \ - '%(varlist)s' \ - ' ret = %(field)s;\n' \ - '%(codeafter)s\n' \ + ) + + slots_list = [ + 'tp_getattr', 'tp_setattr', 'tp_getattro', 'tp_setattro', + 'tp_compare', 'tp_repr', + 'tp_as_number', 'tp_as_sequence', 'tp_as_mapping', 'tp_hash', + 'tp_call', 'tp_str', 'tp_as_buffer', 'tp_richcompare', 'tp_iter', + 'tp_iternext', 'tp_descr_get', 'tp_descr_set', 'tp_init', + 'tp_alloc', 'tp_new', 'tp_free', 'tp_is_gc', + 'tp_traverse', 'tp_clear', 'tp_dealloc', 'tp_flags', 'tp_doc' + ] + + getter_tmpl = ( + 'static PyObject *\n' + '%(funcname)s(PyObject *self, void *closure)\n' + '{\n' + '%(varlist)s' + ' ret = %(field)s;\n' + '%(codeafter)s\n' '}\n\n' - - parse_tmpl = \ - ' if (!PyArg_ParseTupleAndKeywords(args, kwargs, "%(typecodes)s:%(name)s"%(parselist)s))\n' \ - ' return %(errorreturn)s;\n' + ) - deprecated_tmpl = \ - ' if (PyErr_Warn(PyExc_DeprecationWarning, "%(deprecationmsg)s") < 0)\n' \ + parse_tmpl = ( + ' if (!PyArg_ParseTupleAndKeywords(args, kwargs,' + '"%(typecodes)s:%(name)s"%(parselist)s))\n' ' return %(errorreturn)s;\n' + ) - methdef_tmpl = ' { "%(name)s", (PyCFunction)%(cname)s, %(flags)s },\n' - - noconstructor = \ - 'static int\n' \ - 'pygobject_no_constructor(PyObject *self, PyObject *args, PyObject *kwargs)\n' \ - '{\n' \ - ' gchar buf[512];\n' \ - '\n' \ - ' g_snprintf(buf, sizeof(buf), "%s is an abstract widget", self->ob_type->tp_name);\n' \ - ' PyErr_SetString(PyExc_NotImplementedError, buf);\n' \ - ' return -1;\n' \ + deprecated_tmpl = ( + ' if (PyErr_Warn(PyExc_DeprecationWarning, ' + '"%(deprecationmsg)s") < 0)\n' + ' return %(errorreturn)s;\n' + ) + + methdef_tmpl = ( + ' { "%(name)s", (PyCFunction)%(cname)s, %(flags)s,\n' + ' %(docstring)s },\n' + ) + + noconstructor = ( + 'static int\n' + 'pygobject_no_constructor(PyObject *self, PyObject *args, ' + 'PyObject *kwargs)\n' + '{\n' + ' gchar buf[512];\n' + '\n' + ' g_snprintf(buf, sizeof(buf), "%s is an abstract widget", ' + 'self->ob_type->tp_name);\n' + ' PyErr_SetString(PyExc_NotImplementedError, buf);\n' + ' return -1;\n' '}\n\n' - - function_tmpl = \ - 'static PyObject *\n' \ - '_wrap_%(cname)s(PyObject *self%(extraparams)s)\n' \ - '{\n' \ - '%(varlist)s' \ - '%(parseargs)s' \ - '%(codebefore)s' \ - ' %(setreturn)s%(cname)s(%(arglist)s);\n' \ - '%(codeafter)s\n' \ + ) + + function_tmpl = ( + 'static PyObject *\n' + '_wrap_%(cname)s(PyObject *self%(extraparams)s)\n' + '{\n' + '%(varlist)s' + '%(parseargs)s' + '%(codebefore)s' + ' %(begin_allow_threads)s\n' + ' %(setreturn)s%(cname)s(%(arglist)s);\n' + ' %(end_allow_threads)s\n' + '%(codeafter)s\n' '}\n\n' - - virtual_accessor_tmpl = \ - 'static PyObject *\n' \ - '_wrap_%(cname)s(PyObject *cls%(extraparams)s)\n' \ - '{\n' \ - ' gpointer klass;\n' \ - '%(varlist)s' \ - '%(parseargs)s' \ - '%(codebefore)s' \ - ' klass = g_type_class_ref(pyg_type_from_object(cls));\n' \ - ' if (%(class_cast_macro)s(klass)->%(virtual)s)\n' \ - ' %(setreturn)s%(class_cast_macro)s(klass)->%(virtual)s(%(arglist)s);\n' \ - ' else {\n' \ - ' PyErr_SetString(PyExc_NotImplementedError, ' \ - '"virtual method %(name)s not implemented");\n' \ - ' g_type_class_unref(klass);\n' \ - ' return NULL;\n' \ - ' }\n' \ - ' g_type_class_unref(klass);\n' \ - '%(codeafter)s\n' \ + ) + + virtual_accessor_tmpl = ( + 'static PyObject *\n' + '_wrap_%(cname)s(PyObject *cls%(extraparams)s)\n' + '{\n' + ' gpointer klass;\n' + '%(varlist)s' + '%(parseargs)s' + '%(codebefore)s' + ' klass = g_type_class_ref(pyg_type_from_object(cls));\n' + ' if (%(class_cast_macro)s(klass)->%(virtual)s)\n' + ' %(setreturn)s%(class_cast_macro)s(klass)->' + '%(virtual)s(%(arglist)s);\n' + ' else {\n' + ' PyErr_SetString(PyExc_NotImplementedError, ' + '"virtual method %(name)s not implemented");\n' + ' g_type_class_unref(klass);\n' + ' return NULL;\n' + ' }\n' + ' g_type_class_unref(klass);\n' + '%(codeafter)s\n' '}\n\n' + ) # template for method calls constructor_tmpl = None @@ -217,12 +248,20 @@ class Wrapper: return { 'name': '%s.__init__' % self.objinfo.c_name, 'errorreturn': '-1' } def get_initial_method_substdict(self, method): - return { 'name': '%s.%s' % (self.objinfo.c_name, method.name) } + substdict = { 'name': '%s.%s' % (self.objinfo.c_name, method.name) } + if method.unblock_threads: + substdict['begin_allow_threads'] = 'pyg_begin_allow_threads;' + substdict['end_allow_threads'] = 'pyg_end_allow_threads;' + else: + substdict['begin_allow_threads'] = '' + substdict['end_allow_threads'] = '' + return substdict def write_class(self): if self.overrides.is_type_ignored(self.objinfo.c_name): return - self.fp.write('\n/* ----------- ' + self.objinfo.c_name + ' ----------- */\n\n') + self.fp.write('\n/* ----------- %s ----------- */\n\n' % + self.objinfo.c_name) substdict = self.get_initial_class_substdict() if not substdict.has_key('tp_flags'): substdict['tp_flags'] = 'Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE' @@ -232,17 +271,19 @@ class Wrapper: self.objinfo.name) else: substdict['classname'] = self.objinfo.name + substdict['tp_doc'] = self.objinfo.docstring # Maybe this could be done in a nicer way, but I'll leave it as it is # for now: -- Johan - if not self.overrides.slot_is_overriden('%s.tp_init' % self.objinfo.c_name): + if not self.overrides.slot_is_overriden('%s.tp_init' % + self.objinfo.c_name): substdict['tp_init'] = self.write_constructor() substdict['tp_methods'] = self.write_methods() substdict['tp_getset'] = self.write_getsets() # handle slots ... for slot in self.slots_list: - + slotname = '%s.%s' % (self.objinfo.c_name, slot) slotfunc = '_wrap_%s_%s' % (self.get_lower_name(), slot) if slot[:6] == 'tp_as_': @@ -254,7 +295,7 @@ class Wrapper: else: if not substdict.has_key(slot): substdict[slot] = '0' - + self.fp.write(self.type_tmpl % substdict) self.write_virtuals() @@ -265,7 +306,7 @@ class Wrapper: '''This function is the guts of all functions that generate wrappers for functions, methods and constructors.''' if not substdict: substdict = {} - + info = argtypes.WrapperInfo() substdict.setdefault('errorreturn', 'NULL') @@ -302,6 +343,13 @@ class Wrapper: # if name isn't set, set it to function_obj.name substdict.setdefault('name', function_obj.name) + if function_obj.unblock_threads: + substdict['begin_allow_threads'] = 'pyg_begin_allow_threads;' + substdict['end_allow_threads'] = 'pyg_end_allow_threads;' + else: + substdict['begin_allow_threads'] = '' + substdict['end_allow_threads'] = '' + if self.objinfo: substdict['typename'] = self.objinfo.c_name substdict.setdefault('cname', function_obj.c_name) @@ -309,11 +357,14 @@ class Wrapper: substdict['typecodes'] = info.parsestr substdict['parselist'] = info.get_parselist() substdict['arglist'] = info.get_arglist() - substdict['codebefore'] = deprecated + \ + substdict['codebefore'] = deprecated + ( string.replace(info.get_codebefore(), 'return NULL', 'return ' + substdict['errorreturn']) - substdict['codeafter'] = string.replace(info.get_codeafter(), - 'return NULL', 'return ' + substdict['errorreturn']) + ) + substdict['codeafter'] = ( + string.replace(info.get_codeafter(), + 'return NULL', + 'return ' + substdict['errorreturn'])) if info.parsestr or kwargs_needed: substdict['parseargs'] = self.parse_tmpl % substdict @@ -326,41 +377,55 @@ class Wrapper: substdict['parseargs'] = '' substdict['extraparams'] = '' flags = 'METH_NOARGS' + return template % substdict, flags def write_constructor(self): initfunc = '0' constructor = self.parser.find_constructor(self.objinfo,self.overrides) - if constructor: - funcname = constructor.c_name - try: - if self.overrides.is_overriden(funcname): - data = self.overrides.override(funcname) - self.write_function(funcname, data) - else: - # ok, a hack to determine if we should use new-style constructores :P - if getattr(self, 'write_property_based_constructor', None) is not None: - if (len(constructor.params) == 0 or - isinstance(constructor.params[0], definitions.Property)): - # write_property_based_constructor is only - # implemented in GObjectWrapper - return self.write_property_based_constructor(constructor) - else: - print >> sys.stderr, "Warning: generating old-style constructor for",\ - constructor.c_name - # write constructor from template ... - code = self.write_function_wrapper(constructor, - self.constructor_tmpl, - handle_return=0, is_method=0, kwargs_needed=1, - substdict=self.get_initial_constructor_substdict(constructor))[0] - self.fp.write(code) - initfunc = '_wrap_' + funcname - except: - sys.stderr.write('Could not write constructor for %s: %s\n' - % (self.objinfo.c_name, exc_info())) - initfunc = self.write_noconstructor() - else: - initfunc = self.write_default_constructor() + if not constructor: + return self.write_default_constructor() + + funcname = constructor.c_name + try: + if self.overrides.is_overriden(funcname): + data = self.overrides.override(funcname) + self.write_function(funcname, data) + self.objinfo.has_new_constructor_api = ( + self.objinfo.typecode in + self.overrides.newstyle_constructors) + else: + # ok, a hack to determine if we should use + # new-style constructores :P + property_based = getattr(self, + 'write_property_based_constructor', + None) + if property_based: + if (len(constructor.params) == 0 or + isinstance(constructor.params[0], + definitions.Property)): + # write_property_based_constructor is only + # implemented in GObjectWrapper + return self.write_property_based_constructor( + constructor) + else: + sys.stderr.write( + "Warning: generating old-style constructor for:" + + constructor.c_name + '\n') + + # write constructor from template ... + code = self.write_function_wrapper(constructor, + self.constructor_tmpl, + handle_return=0, is_method=0, kwargs_needed=1, + substdict=self.get_initial_constructor_substdict( + constructor))[0] + self.fp.write(code) + initfunc = '_wrap_' + funcname + except: + sys.stderr.write('Could not write constructor for %s: %s\n' + % (self.objinfo.c_name, exc_info())) + + initfunc = self.write_noconstructor() return initfunc def write_noconstructor(self): @@ -376,11 +441,18 @@ class Wrapper: def get_methflags(self, funcname): if self.overrides.wants_kwargs(funcname): - return 'METH_VARARGS|METH_KEYWORDS' + flags = 'METH_VARARGS|METH_KEYWORDS' elif self.overrides.wants_noargs(funcname): - return 'METH_NOARGS' + flags = 'METH_NOARGS' + elif self.overrides.wants_onearg(funcname): + flags = 'METH_O' else: - return 'METH_VARARGS' + flags = 'METH_VARARGS' + if self.overrides.is_staticmethod(funcname): + flags += '|METH_STATIC' + elif self.overrides.is_classmethod(funcname): + flags += '|METH_CLASS' + return flags def write_function(self, funcname, data): lineno, filename = self.overrides.getstartline(funcname) @@ -393,7 +465,8 @@ class Wrapper: substdict = self.get_initial_method_substdict(meth) substdict['virtual'] = substdict['name'].split('.')[1] substdict['cname'] = cname - substdict['class_cast_macro'] = parent.typecode.replace('_TYPE_', '_', 1) + "_CLASS" + substdict['class_cast_macro'] = parent.typecode.replace( + '_TYPE_', '_', 1) + "_CLASS" substdict['typecode'] = self.objinfo.typecode substdict['cast'] = string.replace(parent.typecode, '_TYPE_', '_', 1) return substdict @@ -410,7 +483,7 @@ class Wrapper: if self.overrides.is_overriden(method_name): if not self.overrides.is_already_included(method_name): data = self.overrides.override(method_name) - self.write_function(method_name, data) + self.write_function(method_name, data) methflags = self.get_methflags(method_name) else: @@ -422,7 +495,8 @@ class Wrapper: methods.append(self.methdef_tmpl % { 'name': fixname(meth.name), 'cname': '_wrap_' + method_name, - 'flags': methflags}) + 'flags': methflags, + 'docstring': meth.docstring }) methods_coverage.declare_wrapped() except: methods_coverage.declare_not_wrapped() @@ -437,13 +511,14 @@ class Wrapper: try: data = self.overrides.define(klass, method_name) - self.write_function(method_name, data) + self.write_function(method_name, data) methflags = self.get_methflags(method_name) methods.append(self.methdef_tmpl % { 'name': method_name, 'cname': '_wrap_' + c_name, - 'flags': methflags}) + 'flags': methflags, + 'docstring': meth.docstring }) methods_coverage.declare_wrapped() except: methods_coverage.declare_not_wrapped() @@ -453,12 +528,12 @@ class Wrapper: # Add GObject virtual method accessors, for chaining to parent # virtuals from subclasses methods += self.write_virtual_accessors() - + if methods: methoddefs = '_Py%s_methods' % self.objinfo.c_name # write the PyMethodDef structure - methods.append(' { NULL, NULL, 0 }\n') - self.fp.write('static PyMethodDef %s[] = {\n' % methoddefs) + methods.append(' { NULL, NULL, 0, NULL }\n') + self.fp.write('static const PyMethodDef %s[] = {\n' % methoddefs) self.fp.write(string.join(methods, '')) self.fp.write('};\n\n') else: @@ -485,25 +560,32 @@ class Wrapper: pname='self', pdflt=None, pnull=None)) try: # write method from template ... - code, methflags = self.write_function_wrapper(meth, - self.virtual_accessor_tmpl, handle_return=True, is_method=False, - substdict=self._get_class_virtual_substdict(meth, method_name, self.objinfo)) + code, methflags = self.write_function_wrapper( + meth, self.virtual_accessor_tmpl, + handle_return=True, is_method=False, + substdict=self._get_class_virtual_substdict( + meth, method_name, self.objinfo)) self.fp.write(code) finally: del meth.params[0] methods.append(self.methdef_tmpl % { 'name': "do_" + fixname(meth.name), 'cname': '_wrap_' + method_name, - 'flags': methflags + '|METH_CLASS'}) + 'flags': methflags + '|METH_CLASS', + 'docstring': 'NULL'}) vaccessors_coverage.declare_wrapped() except: vaccessors_coverage.declare_not_wrapped() - sys.stderr.write('Could not write virtual accessor method %s.%s: %s\n' - % (klass, meth.name, exc_info())) + sys.stderr.write( + 'Could not write virtual accessor method %s.%s: %s\n' + % (klass, meth.name, exc_info())) return methods def write_virtuals(self): - '''Write _wrap_FooBar__proxy_do_zbr() reverse wrapers for GObject virtuals''' + ''' + Write _wrap_FooBar__proxy_do_zbr() reverse wrapers for + GObject virtuals + ''' klass = self.objinfo.c_name virtuals = [] for meth in self.parser.find_virtuals(self.objinfo): @@ -525,14 +607,17 @@ class Wrapper: wrapper, "self", method_name="do_" + meth.name, c_type=(klass + ' *'))) for param in meth.params: - handler, props = argtypes.matcher.get_reverse(param.ptype) - wrapper.add_parameter(handler(wrapper, param.pname, **props)) + handler, props = argtypes.matcher.get_reverse( + param.ptype) + props["direction"] = param.pdir + wrapper.add_parameter(handler(wrapper, + param.pname, **props)) buf = reversewrapper.MemoryCodeSink() wrapper.generate(buf) self.fp.write(buf.flush()) virtuals.append((fixname(meth.name), '_wrap_' + method_name)) vproxies_coverage.declare_wrapped() - except KeyError: + except (KeyError, ValueError): vproxies_coverage.declare_not_wrapped() virtuals.append((fixname(meth.name), None)) sys.stderr.write('Could not write virtual proxy %s.%s: %s\n' @@ -543,22 +628,28 @@ class Wrapper: # GtkPlug and GtkSocket on win32). if self.overrides.is_ignored(self.objinfo.typecode): return - class_cast_macro = self.objinfo.typecode.replace('_TYPE_', '_', 1) + "_CLASS" + class_cast_macro = self.objinfo.typecode.replace( + '_TYPE_', '_', 1) + "_CLASS" cast_macro = self.objinfo.typecode.replace('_TYPE_', '_', 1) funcname = "__%s_class_init" % klass self.objinfo.class_init_func = funcname - have_implemented_virtuals = not not [True for name, cname in virtuals - if cname is not None] - self.fp.write(('\nstatic int\n' - '%(funcname)s(gpointer gclass, PyTypeObject *pyclass)\n' - '{\n') % vars()) + have_implemented_virtuals = not not [True + for name, cname in virtuals + if cname is not None] + self.fp.write( + ('\nstatic int\n' + '%(funcname)s(gpointer gclass, PyTypeObject *pyclass)\n' + '{\n') % vars()) if have_implemented_virtuals: self.fp.write(' PyObject *o;\n') self.fp.write( - ' %(klass)sClass *klass = %(class_cast_macro)s(gclass);\n' + ' %(klass)sClass *klass = ' + '%(class_cast_macro)s(gclass);\n' + ' PyObject *gsignals = ' + 'PyDict_GetItemString(pyclass->tp_dict, "__gsignals__");\n' % vars()) - + for name, cname in virtuals: do_name = 'do_' + name if cname is None: @@ -566,26 +657,35 @@ class Wrapper: 'is currently not supported */\n' % vars()) else: self.fp.write(''' - if ((o = PyDict_GetItemString(pyclass->tp_dict, "%(do_name)s")) - && !PyObject_TypeCheck(o, &PyCFunction_Type)) - klass->%(name)s = %(cname)s;\n''' % vars()) + o = PyObject_GetAttrString((PyObject *) pyclass, "%(do_name)s"); + if (o == NULL) + PyErr_Clear(); + else { + if (!PyObject_TypeCheck(o, &PyCFunction_Type) + && !(gsignals && PyDict_GetItemString(gsignals, "%(name)s"))) + klass->%(name)s = %(cname)s; + Py_DECREF(o); + } +''' % vars()) self.fp.write(' return 0;\n}\n') - + def write_getsets(self): lower_name = self.get_lower_name() getsets_name = lower_name + '_getsets' getterprefix = '_wrap_' + lower_name + '__get_' setterprefix = '_wrap_' + lower_name + '__set_' - # no overrides for the whole function. If no fields, don't write a func + # no overrides for the whole function. If no fields, + # don't write a func if not self.objinfo.fields: return '0' getsets = [] - for ftype, fname in self.objinfo.fields: + for ftype, cfname in self.objinfo.fields: + fname = cfname.replace('.', '_') gettername = '0' settername = '0' attrname = self.objinfo.c_name + '.' + fname - if self.overrides.attr_is_overriden(attrname): + if self.overrides.attr_is_overriden(attrname): code = self.overrides.attr_override(attrname) self.write_function(attrname, code) if string.find(code, getterprefix + fname) >= 0: @@ -602,30 +702,31 @@ class Wrapper: self.fp.write(self.getter_tmpl % { 'funcname': funcname, 'varlist': info.varlist, - 'field': self.get_field_accessor(fname), + 'field': self.get_field_accessor(cfname), 'codeafter': info.get_codeafter() }) gettername = funcname except: - sys.stderr.write("Could not write getter for %s.%s: %s\n" - % (self.objinfo.c_name, fname, exc_info())) + sys.stderr.write( + "Could not write getter for %s.%s: %s\n" + % (self.objinfo.c_name, fname, exc_info())) if gettername != '0' or settername != '0': getsets.append(' { "%s", (getter)%s, (setter)%s },\n' % (fixname(fname), gettername, settername)) if not getsets: return '0' - self.fp.write('static PyGetSetDef %s[] = {\n' % getsets_name) + self.fp.write('static const PyGetSetDef %s[] = {\n' % getsets_name) for getset in getsets: self.fp.write(getset) self.fp.write(' { NULL, (getter)0, (setter)0 },\n') self.fp.write('};\n\n') - + return getsets_name def write_functions(self, prefix): self.fp.write('\n/* ----------- functions ----------- */\n\n') functions = [] - + # First, get methods from the defs files for func in self.parser.find_functions(): funcname = func.c_name @@ -645,7 +746,8 @@ class Wrapper: functions.append(self.methdef_tmpl % { 'name': func.name, 'cname': '_wrap_' + funcname, - 'flags': methflags }) + 'flags': methflags, + 'docstring': func.docstring }) functions_coverage.declare_wrapped() except: functions_coverage.declare_not_wrapped() @@ -656,56 +758,60 @@ class Wrapper: for funcname in self.overrides.get_functions(): try: data = self.overrides.function(funcname) - self.write_function(funcname) + self.write_function(funcname, data) methflags = self.get_methflags(funcname) functions.append(self.methdef_tmpl % { 'name': funcname, 'cname': '_wrap_' + funcname, - 'flags': methflags }) + 'flags': methflags, + 'docstring': 'NULL'}) functions_coverage.declare_wrapped() except: functions_coverage.declare_not_wrapped() sys.stderr.write('Could not write function %s: %s\n' % (funcname, exc_info())) - + # write the PyMethodDef structure - functions.append(' { NULL, NULL, 0 }\n') - - self.fp.write('PyMethodDef ' + prefix + '_functions[] = {\n') + functions.append(' { NULL, NULL, 0, NULL }\n') + + self.fp.write('const PyMethodDef ' + prefix + '_functions[] = {\n') self.fp.write(string.join(functions, '')) self.fp.write('};\n\n') class GObjectWrapper(Wrapper): - constructor_tmpl = \ - 'static int\n' \ - '_wrap_%(cname)s(PyGObject *self%(extraparams)s)\n' \ - '{\n' \ - '%(varlist)s' \ - '%(parseargs)s' \ - '%(codebefore)s' \ - ' self->obj = (GObject *)%(cname)s(%(arglist)s);\n' \ - '%(codeafter)s\n' \ - ' if (!self->obj) {\n' \ - ' PyErr_SetString(PyExc_RuntimeError, "could not create %(typename)s object");\n' \ - ' return -1;\n' \ - ' }\n' \ - '%(aftercreate)s' \ - ' pygobject_register_wrapper((PyObject *)self);\n' \ - ' return 0;\n' \ + constructor_tmpl = ( + 'static int\n' + '_wrap_%(cname)s(PyGObject *self%(extraparams)s)\n' + '{\n' + '%(varlist)s' + '%(parseargs)s' + '%(codebefore)s' + ' self->obj = (GObject *)%(cname)s(%(arglist)s);\n' + '%(codeafter)s\n' + ' if (!self->obj) {\n' + ' PyErr_SetString(PyExc_RuntimeError, ' + '"could not create %(typename)s object");\n' + ' return -1;\n' + ' }\n' + '%(aftercreate)s' + ' pygobject_register_wrapper((PyObject *)self);\n' + ' return 0;\n' '}\n\n' - method_tmpl = \ - 'static PyObject *\n' \ - '_wrap_%(cname)s(PyGObject *self%(extraparams)s)\n' \ - '{\n' \ - '%(varlist)s' \ - '%(parseargs)s' \ - '%(codebefore)s' \ - ' pyg_begin_allow_threads;\n' \ - ' %(setreturn)s%(cname)s(%(cast)s(self->obj)%(arglist)s);\n' \ - ' pyg_end_allow_threads;\n' \ - '%(codeafter)s\n' \ + ) + + method_tmpl = ( + 'static PyObject *\n' + '_wrap_%(cname)s(PyGObject *self%(extraparams)s)\n' + '{\n' + '%(varlist)s' + '%(parseargs)s' + '%(codebefore)s' + ' %(begin_allow_threads)s\n' + ' %(setreturn)s%(cname)s(%(cast)s(self->obj)%(arglist)s);\n' + ' %(end_allow_threads)s\n' + '%(codeafter)s\n' '}\n\n' - + ) def __init__(self, parser, objinfo, overrides, fp=FileOutput(sys.stdout)): Wrapper.__init__(self, parser, objinfo, overrides, fp) if self.objinfo: @@ -716,13 +822,14 @@ class GObjectWrapper(Wrapper): return { 'tp_basicsize' : 'PyGObject', 'tp_weaklistoffset' : 'offsetof(PyGObject, weakreflist)', 'tp_dictoffset' : 'offsetof(PyGObject, inst_dict)' } - + def get_field_accessor(self, fieldname): castmacro = string.replace(self.objinfo.typecode, '_TYPE_', '_', 1) return '%s(pygobject_get(self))->%s' % (castmacro, fieldname) def get_initial_constructor_substdict(self, constructor): - substdict = Wrapper.get_initial_constructor_substdict(self, constructor) + substdict = Wrapper.get_initial_constructor_substdict(self, + constructor) if not constructor.caller_owns_return: substdict['aftercreate'] = " g_object_ref(self->obj);\n" else: @@ -731,47 +838,73 @@ class GObjectWrapper(Wrapper): def get_initial_method_substdict(self, method): substdict = Wrapper.get_initial_method_substdict(self, method) - substdict['cast'] = string.replace(self.objinfo.typecode, '_TYPE_', '_', 1) + substdict['cast'] = string.replace(self.objinfo.typecode, + '_TYPE_', '_', 1) return substdict - + def write_default_constructor(self): + try: + parent = self.parser.find_object(self.objinfo.parent) + except ValueError: + parent = None + if parent is not None: + ## just like the constructor is inheritted, we should + # inherit the new API compatibility flag + self.objinfo.has_new_constructor_api = ( + parent.has_new_constructor_api) + elif self.objinfo.parent == 'GObject': + self.objinfo.has_new_constructor_api = True return '0' def write_property_based_constructor(self, constructor): + self.objinfo.has_new_constructor_api = True out = self.fp print >> out, "static int" - print >> out, '_wrap_%s(PyGObject *self, PyObject *args,'\ + print >> out, '_wrap_%s(PyGObject *self, PyObject *args,' \ ' PyObject *kwargs)\n{' % constructor.c_name - print >> out, " GType obj_type = pyg_type_from_object((PyObject *) self);" + if constructor.params: + s = " GType obj_type = pyg_type_from_object((PyObject *) self);" + print >> out, s def py_str_list_to_c(arg): if arg: - return "{" + ", ".join(map(lambda s: '"' + s + '"', arg)) + ", NULL }" + return "{" + ", ".join( + map(lambda s: '"' + s + '"', arg)) + ", NULL }" else: return "{ NULL }" - classname = '%s.%s' % (self.overrides.modulename, self.objinfo.name) + classname = '%s.%s' % (self.overrides.modulename, + self.objinfo.name) if constructor.params: - mandatory_arguments = [param for param in constructor.params if not param.optional] - optional_arguments = [param for param in constructor.params if param.optional] - arg_names = py_str_list_to_c([param.argname for param in - mandatory_arguments + optional_arguments]) - prop_names = py_str_list_to_c([param.pname for param in - mandatory_arguments + optional_arguments]) - - print >> out, " GParameter params[%i];" % len(constructor.params) - print >> out, " PyObject *parsed_args[%i] = {NULL, };" % len(constructor.params) + mandatory_arguments = [param for param in constructor.params + if not param.optional] + optional_arguments = [param for param in constructor.params + if param.optional] + arg_names = py_str_list_to_c( + [param.argname + for param in mandatory_arguments + optional_arguments]) + + prop_names = py_str_list_to_c( + [param.pname + for param in mandatory_arguments + optional_arguments]) + + print >> out, " GParameter params[%i];" % \ + len(constructor.params) + print >> out, " PyObject *parsed_args[%i] = {NULL, };" % \ + len(constructor.params) print >> out, " char *arg_names[] = %s;" % arg_names print >> out, " char *prop_names[] = %s;" % prop_names print >> out, " guint nparams, i;" print >> out if constructor.deprecated is not None: - print >> out, ' if (PyErr_Warn(PyExc_DeprecationWarning, "%s") < 0)' %\ - constructor.deprecated + out.write( + ' if (PyErr_Warn(PyExc_DeprecationWarning, ' + '"%s") < 0)\n' % + constructor.deprecated) print >> out, ' return -1;' print >> out - print >> out, " if (!PyArg_ParseTupleAndKeywords(args, kwargs, ", + out.write(" if (!PyArg_ParseTupleAndKeywords(args, kwargs, ") template = '"' if mandatory_arguments: template += "O"*len(mandatory_arguments) @@ -781,78 +914,90 @@ class GObjectWrapper(Wrapper): print >> out, template, ", arg_names", for i in range(len(constructor.params)): print >> out, ", &parsed_args[%i]" % i, - print >> out, "))" - print >> out, " return -1;" - print >> out - print >> out, " memset(params, 0, sizeof(GParameter)*%i);" % len(constructor.params) - print >> out, " if (!pyg_parse_constructor_args(obj_type, arg_names, prop_names," - print >> out, " params, &nparams, parsed_args))" - print >> out, " return -1;" - print >> out, " self->obj = g_object_newv(obj_type, nparams, params);" - print >> out, " for (i = 0; i < nparams; ++i)" - print >> out, " g_value_unset(¶ms[i].value);" + + out.write( + "))\n" + " return -1;\n" + "\n" + " memset(params, 0, sizeof(GParameter)*%i);\n" + " if (!pyg_parse_constructor_args(obj_type, arg_names,\n" + " prop_names, params, \n" + " &nparams, parsed_args))\n" + " return -1;\n" + " pygobject_constructv(self, nparams, params);\n" + " for (i = 0; i < nparams; ++i)\n" + " g_value_unset(¶ms[i].value);\n" + % len(constructor.params)) else: - print >> out, " static char* kwlist[] = { NULL };"; - print >> out - if constructor.deprecated is not None: - print >> out, ' if (PyErr_Warn(PyExc_DeprecationWarning, "%s") < 0)' %\ - constructor.deprecated - print >> out, ' return -1;' - print >> out - print >> out, ' if (!PyArg_ParseTupleAndKeywords(args, kwargs, ":%s.__init__", kwlist))' % classname - print >> out, " return -1;" - print >> out - print >> out, " self->obj = g_object_newv(obj_type, 0, NULL);" + out.write( + " static char* kwlist[] = { NULL };\n" + "\n") - print >> out, \ - ' if (!self->obj) {\n' \ - ' PyErr_SetString(PyExc_RuntimeError, "could not create %(typename)s object");\n' \ - ' return -1;\n' \ - ' }\n' + if constructor.deprecated is not None: + out.write( + ' if (PyErr_Warn(PyExc_DeprecationWarning, "%s") < 0)\n' + ' return -1;\n' + '\n' % constructor.deprecated) + + out.write( + ' if (!PyArg_ParseTupleAndKeywords(args, kwargs,\n' + ' ":%s.__init__",\n' + ' kwlist))\n' + ' return -1;\n' + '\n' + ' pygobject_constructv(self, 0, NULL);\n' % classname) + out.write( + ' if (!self->obj) {\n' + ' PyErr_SetString(\n' + ' PyExc_RuntimeError, \n' + ' "could not create %s object");\n' + ' return -1;\n' + ' }\n' % classname) if not constructor.caller_owns_return: print >> out, " g_object_ref(self->obj);\n" - print >> out, \ - ' pygobject_register_wrapper((PyObject *)self);\n' \ - ' return 0;\n' \ - '}\n\n' % { 'typename': classname } + out.write( + ' return 0;\n' + '}\n\n') + return "_wrap_%s" % constructor.c_name ## TODO : Add GstMiniObjectWrapper(Wrapper) class GstMiniObjectWrapper(Wrapper): - constructor_tmpl = \ - 'static int\n' \ - '_wrap_%(cname)s(PyGstMiniObject *self%(extraparams)s)\n' \ - '{\n' \ - '%(varlist)s' \ - '%(parseargs)s' \ - '%(codebefore)s' \ - ' self->obj = (GstMiniObject *)%(cname)s(%(arglist)s);\n' \ - '%(codeafter)s\n' \ - ' if (!self->obj) {\n' \ - ' PyErr_SetString(PyExc_RuntimeError, "could not create %(typename)s miniobject");\n' \ - ' return -1;\n' \ - ' }\n' \ - '%(aftercreate)s' \ - ' pygstminiobject_register_wrapper((PyObject *)self);\n' \ - ' return 0;\n' \ + constructor_tmpl = ( + 'static int\n' + '_wrap_%(cname)s(PyGstMiniObject *self%(extraparams)s)\n' + '{\n' + '%(varlist)s' + '%(parseargs)s' + '%(codebefore)s' + ' self->obj = (GstMiniObject *)%(cname)s(%(arglist)s);\n' + '%(codeafter)s\n' + ' if (!self->obj) {\n' + ' PyErr_SetString(PyExc_RuntimeError, ' + '"could not create %(typename)s miniobject");\n' + ' return -1;\n' + ' }\n' + '%(aftercreate)s' + ' pygstminiobject_register_wrapper((PyObject *)self);\n' + ' return 0;\n' '}\n\n' - method_tmpl = \ - 'static PyObject *\n' \ - '_wrap_%(cname)s(PyGstMiniObject *self%(extraparams)s)\n' \ - '{\n' \ - '%(varlist)s' \ - '%(parseargs)s' \ - '%(codebefore)s' \ - ' pyg_begin_allow_threads;\n' \ - ' %(setreturn)s%(cname)s(%(cast)s(self->obj)%(arglist)s);\n' \ - ' pyg_end_allow_threads;\n' \ - '%(codeafter)s\n' \ + ) + method_tmpl = ( + 'static PyObject *\n' + '_wrap_%(cname)s(PyGstMiniObject *self%(extraparams)s)\n' + '{\n' + '%(varlist)s' + '%(parseargs)s' + '%(codebefore)s' + ' %(begin_allow_threads)s\n' + ' %(setreturn)s%(cname)s(%(cast)s(self->obj)%(arglist)s);\n' + ' %(end_allow_threads)s\n' + '%(codeafter)s\n' '}\n\n' - - + ) def __init__(self, parser, objinfo, overrides, fp=FileOutput(sys.stdout)): Wrapper.__init__(self, parser, objinfo, overrides, fp) if self.objinfo: @@ -869,7 +1014,8 @@ class GstMiniObjectWrapper(Wrapper): return '%s(pygstminiobject_get(self))->%s' % (castmacro, fieldname) def get_initial_constructor_substdict(self, constructor): - substdict = Wrapper.get_initial_constructor_substdict(self, constructor) + substdict = Wrapper.get_initial_constructor_substdict(self, + constructor) if not constructor.caller_owns_return: substdict['aftercreate'] = " gst_mini_object_ref(self->obj);\n" else: @@ -878,11 +1024,34 @@ class GstMiniObjectWrapper(Wrapper): def get_initial_method_substdict(self, method): substdict = Wrapper.get_initial_method_substdict(self, method) - substdict['cast'] = string.replace(self.objinfo.typecode, '_TYPE_', '_', 1) + substdict['cast'] = string.replace(self.objinfo.typecode, + '_TYPE_', '_', 1) return substdict + class GInterfaceWrapper(GObjectWrapper): + virtual_accessor_tmpl = ( + 'static PyObject *\n' + '_wrap_%(cname)s(PyObject *cls%(extraparams)s)\n' + '{\n' + ' %(vtable)s *iface;\n' + '%(varlist)s' + '%(parseargs)s' + '%(codebefore)s' + ' iface = g_type_interface_peek(' + 'g_type_class_peek(pyg_type_from_object(cls)), %(typecode)s);\n' + ' if (iface->%(virtual)s)\n' + ' %(setreturn)siface->%(virtual)s(%(arglist)s);\n' + ' else {\n' + ' PyErr_SetString(PyExc_NotImplementedError, ' + '"interface method %(name)s not implemented");\n' + ' return NULL;\n' + ' }\n' + '%(codeafter)s\n' + '}\n\n' + ) + def get_initial_class_substdict(self): return { 'tp_basicsize' : 'PyObject', 'tp_weaklistoffset' : '0', @@ -895,9 +1064,13 @@ class GInterfaceWrapper(GObjectWrapper): # interfaces have no fields ... return '0' - def write_virtual_accessors(self): - ## we don't want the 'chaining' functions for interfaces - return [] + def _get_class_virtual_substdict(self, meth, cname, parent): + substdict = self.get_initial_method_substdict(meth) + substdict['virtual'] = substdict['name'].split('.')[1] + substdict['cname'] = cname + substdict['typecode'] = self.objinfo.typecode + substdict['vtable'] = self.objinfo.vtable + return substdict def write_virtuals(self): ## Now write reverse method wrappers, which let python code @@ -924,71 +1097,108 @@ class GInterfaceWrapper(GObjectWrapper): wrapper, "self", method_name="do_" + meth.name, c_type=(klass + ' *'))) for param in meth.params: - handler, props = argtypes.matcher.get_reverse(param.ptype) - wrapper.add_parameter(handler(wrapper, param.pname, **props)) + handler, props = argtypes.matcher.get_reverse( + param.ptype) + props["direction"] = param.pdir + wrapper.add_parameter( + handler(wrapper, param.pname, **props)) buf = reversewrapper.MemoryCodeSink() wrapper.generate(buf) self.fp.write(buf.flush()) proxies.append((fixname(meth.name), '_wrap_' + method_name)) iproxies_coverage.declare_wrapped() - except KeyError: + except (KeyError, ValueError): iproxies_coverage.declare_not_wrapped() proxies.append((fixname(meth.name), None)) sys.stderr.write('Could not write interface proxy %s.%s: %s\n' % (klass, meth.name, exc_info())) - if proxies: - ## Write an interface init function for this object - funcname = "__%s__interface_init" % klass - vtable = self.objinfo.vtable - self.fp.write(('\nstatic void\n' - '%(funcname)s(%(vtable)s *iface)\n' - '{\n') % vars()) - for name, cname in proxies: - do_name = 'do_' + name - if cname is not None: - self.fp.write(' iface->%s = %s;\n' % (name, cname)) - self.fp.write('}\n\n') - interface_info = "__%s__iinfo" % klass - self.fp.write(''' + + if not proxies: + return + + # Make sure we have at least one proxy function + if not [cname for name,cname in proxies if not cname is None]: + return + + ## Write an interface init function for this object + funcname = "__%s__interface_init" % klass + vtable = self.objinfo.vtable + self.fp.write( + '\nstatic void\n' + '%(funcname)s(%(vtable)s *iface, PyTypeObject *pytype)\n' + '{\n' + ' %(vtable)s *parent_iface = ' + 'g_type_interface_peek_parent(iface);\n' + ' PyObject *py_method;\n' + '\n' + % vars()) + + for name, cname in proxies: + do_name = 'do_' + name + if cname is None: + continue + + self.fp.write(( + ' py_method = pytype? PyObject_GetAttrString(' + '(PyObject *) pytype, "%(do_name)s") : NULL;\n' + ' if (py_method && !PyObject_TypeCheck(py_method, ' + '&PyCFunction_Type)) {\n' + ' iface->%(name)s = %(cname)s;\n' + ' } else {\n' + ' PyErr_Clear();\n' + ' if (parent_iface) {\n' + ' iface->%(name)s = parent_iface->%(name)s;\n' + ' }\n' + ' Py_XDECREF(py_method);\n' + ' }\n' + ) % vars()) + self.fp.write('}\n\n') + interface_info = "__%s__iinfo" % klass + self.fp.write(''' static const GInterfaceInfo %s = { (GInterfaceInitFunc) %s, NULL, NULL }; ''' % (interface_info, funcname)) - self.objinfo.interface_info = interface_info - + self.objinfo.interface_info = interface_info class GBoxedWrapper(Wrapper): - constructor_tmpl = \ - 'static int\n' \ - '_wrap_%(cname)s(PyGBoxed *self%(extraparams)s)\n' \ + constructor_tmpl = ( + 'static int\n' + '_wrap_%(cname)s(PyGBoxed *self%(extraparams)s)\n' '{\n' \ - '%(varlist)s' \ - '%(parseargs)s' \ - '%(codebefore)s' \ - ' self->gtype = %(typecode)s;\n' \ - ' self->free_on_dealloc = FALSE;\n' \ - ' self->boxed = %(cname)s(%(arglist)s);\n' \ - '%(codeafter)s\n' \ - ' if (!self->boxed) {\n' \ - ' PyErr_SetString(PyExc_RuntimeError, "could not create %(typename)s object");\n' \ - ' return -1;\n' \ - ' }\n' \ - ' self->free_on_dealloc = TRUE;\n' \ - ' return 0;\n' \ + '%(varlist)s' + '%(parseargs)s' + '%(codebefore)s' + ' self->gtype = %(typecode)s;\n' + ' self->free_on_dealloc = FALSE;\n' + ' self->boxed = %(cname)s(%(arglist)s);\n' + '%(codeafter)s\n' + ' if (!self->boxed) {\n' + ' PyErr_SetString(PyExc_RuntimeError, ' + '"could not create %(typename)s object");\n' + ' return -1;\n' + ' }\n' + ' self->free_on_dealloc = TRUE;\n' + ' return 0;\n' '}\n\n' - - method_tmpl = \ - 'static PyObject *\n' \ - '_wrap_%(cname)s(PyObject *self%(extraparams)s)\n' \ - '{\n' \ - '%(varlist)s' \ - '%(parseargs)s' \ - '%(codebefore)s' \ - ' %(setreturn)s%(cname)s(pyg_boxed_get(self, %(typename)s)%(arglist)s);\n' \ - '%(codeafter)s\n' \ + ) + + method_tmpl = ( + 'static PyObject *\n' + '_wrap_%(cname)s(PyObject *self%(extraparams)s)\n' + '{\n' + '%(varlist)s' + '%(parseargs)s' + '%(codebefore)s' + ' %(begin_allow_threads)s\n' + ' %(setreturn)s%(cname)s(pyg_boxed_get(self, ' + '%(typename)s)%(arglist)s);\n' + ' %(end_allow_threads)s\n' + '%(codeafter)s\n' '}\n\n' + ) def get_initial_class_substdict(self): return { 'tp_basicsize' : 'PyGBoxed', @@ -999,38 +1209,43 @@ class GBoxedWrapper(Wrapper): return 'pyg_boxed_get(self, %s)->%s' % (self.objinfo.c_name, fieldname) def get_initial_constructor_substdict(self, constructor): - substdict = Wrapper.get_initial_constructor_substdict(self, constructor) + substdict = Wrapper.get_initial_constructor_substdict( + self, constructor) substdict['typecode'] = self.objinfo.typecode return substdict class GPointerWrapper(GBoxedWrapper): - constructor_tmpl = \ - 'static int\n' \ - '_wrap_%(cname)s(PyGPointer *self%(extraparams)s)\n' \ - '{\n' \ - '%(varlist)s' \ - '%(parseargs)s' \ - '%(codebefore)s' \ - ' self->gtype = %(typecode)s;\n' \ - ' self->pointer = %(cname)s(%(arglist)s);\n' \ - '%(codeafter)s\n' \ - ' if (!self->pointer) {\n' \ - ' PyErr_SetString(PyExc_RuntimeError, "could not create %(typename)s object");\n' \ - ' return -1;\n' \ - ' }\n' \ - ' return 0;\n' \ + constructor_tmpl = ( + 'static int\n' + '_wrap_%(cname)s(PyGPointer *self%(extraparams)s)\n' + '{\n' + '%(varlist)s' + '%(parseargs)s' + '%(codebefore)s' + ' self->gtype = %(typecode)s;\n' + ' self->pointer = %(cname)s(%(arglist)s);\n' + '%(codeafter)s\n' + ' if (!self->pointer) {\n' + ' PyErr_SetString(PyExc_RuntimeError, ' + '"could not create %(typename)s object");\n' + ' return -1;\n' + ' }\n' + ' return 0;\n' '}\n\n' - - method_tmpl = \ - 'static PyObject *\n' \ - '_wrap_%(cname)s(PyObject *self%(extraparams)s)\n' \ - '{\n' \ - '%(varlist)s' \ - '%(parseargs)s' \ - '%(codebefore)s' \ - ' %(setreturn)s%(cname)s(pyg_pointer_get(self, %(typename)s)%(arglist)s);\n' \ - '%(codeafter)s\n' \ + ) + + method_tmpl = ( + 'static PyObject *\n' + '_wrap_%(cname)s(PyObject *self%(extraparams)s)\n' + '{\n' + '%(varlist)s' + '%(parseargs)s' + '%(codebefore)s' + ' %(setreturn)s%(cname)s(pyg_pointer_get(self, ' + '%(typename)s)%(arglist)s);\n' + '%(codeafter)s\n' '}\n\n' + ) def get_initial_class_substdict(self): return { 'tp_basicsize' : 'PyGPointer', @@ -1038,10 +1253,12 @@ class GPointerWrapper(GBoxedWrapper): 'tp_dictoffset' : '0' } def get_field_accessor(self, fieldname): - return 'pyg_pointer_get(self, %s)->%s' % (self.objinfo.c_name, fieldname) + return 'pyg_pointer_get(self, %s)->%s' % (self.objinfo.c_name, + fieldname) def get_initial_constructor_substdict(self, constructor): - substdict = Wrapper.get_initial_constructor_substdict(self, constructor) + substdict = Wrapper.get_initial_constructor_substdict( + self, constructor) substdict['typecode'] = self.objinfo.typecode return substdict @@ -1052,14 +1269,19 @@ def write_headers(data, fp): fp.write(data) fp.resetline() fp.write('\n\n') - + +def write_body(data, fp): + fp.write(data) + fp.resetline() + fp.write('\n\n') + def write_imports(overrides, fp): fp.write('/* ---------- types from other modules ---------- */\n') for module, pyname, cname in overrides.get_imports(): fp.write('static PyTypeObject *_%s;\n' % cname) fp.write('#define %s (*_%s)\n' % (cname, cname)) fp.write('\n\n') - + def write_type_declarations(parser, fp): fp.write('/* ---------- forward type declarations ---------- */\n') for obj in parser.boxes: @@ -1072,10 +1294,39 @@ def write_type_declarations(parser, fp): fp.write('PyTypeObject Py' + interface.c_name + '_Type;\n') fp.write('\n') + +def sort_parent_children(objects): + objects = list(objects) + modified = True + while modified: + modified = False + parent_index = None + child_index = None + for i, obj in enumerate(objects): + if obj.parent == 'GObject': + continue + if obj.parent not in [info.c_name for info in objects[:i]]: + for j, info in enumerate(objects[i+1:]): + if info.c_name == obj.parent: + parent_index = i + 1 + j + child_index = i + break + else: + continue + break + if child_index is not None and parent_index is not None: + if child_index != parent_index: + objects.insert(child_index, objects.pop(parent_index)) + modified = True + return objects + def write_classes(parser, overrides, fp): + ## Sort the objects, so that we generate code for the parent types + ## before their children. + objects = sort_parent_children(parser.objects) for klass, items in ((GBoxedWrapper, parser.boxes), (GPointerWrapper, parser.pointers), - (GObjectWrapper, parser.objects), + (GObjectWrapper, objects), (GstMiniObjectWrapper, parser.miniobjects), (GInterfaceWrapper, parser.interfaces)): for item in items: @@ -1087,26 +1338,33 @@ def write_enums(parser, overrides, prefix, fp=sys.stdout): if not parser.enums: return fp.write('\n/* ----------- enums and flags ----------- */\n\n') - fp.write('void\n' + prefix + '_add_constants(PyObject *module, const gchar *strip_prefix)\n{\n') + fp.write( + 'void\n' + prefix + + '_add_constants(PyObject *module, const gchar *strip_prefix)\n{\n') + for enum in parser.enums: if overrides.is_type_ignored(enum.c_name): continue if enum.typecode is None: for nick, value in enum.values: - fp.write(' PyModule_AddIntConstant(module, pyg_constant_strip_prefix("%s", strip_prefix), %s);\n' - % (value, value)) + fp.write( + ' PyModule_AddIntConstant(module, ' + 'pyg_constant_strip_prefix("%s", strip_prefix), %s);\n' + % (value, value)) else: if enum.deftype == 'enum': - fp.write(' pyg_enum_add(module, "%s", strip_prefix, %s);\n' % (enum.name, enum.typecode)) + fp.write(' pyg_enum_add(module, "%s", strip_prefix, %s);\n' + % (enum.name, enum.typecode)) else: - fp.write(' pyg_flags_add(module, "%s", strip_prefix, %s);\n' % (enum.name, enum.typecode)) - + fp.write(' pyg_flags_add(module, "%s", strip_prefix, %s);\n' + % (enum.name, enum.typecode)) + fp.write('\n') fp.write(' if (PyErr_Occurred())\n') - fp.write(' PyErr_Print();\n') + fp.write(' PyErr_Print();\n') fp.write('}\n\n') -def write_extension_init(overrides, prefix, fp): +def write_extension_init(overrides, prefix, fp): fp.write('/* initialise stuff extension classes */\n') fp.write('void\n' + prefix + '_register_classes(PyObject *d)\n{\n') imports = overrides.get_imports()[:] @@ -1116,10 +1374,15 @@ def write_extension_init(overrides, prefix, fp): bymod.setdefault(module, []).append((pyname, cname)) fp.write(' PyObject *module;\n\n') for module in bymod: - fp.write(' if ((module = PyImport_ImportModule("%s")) != NULL) {\n' % module) - fp.write(' PyObject *moddict = PyModule_GetDict(module);\n\n') + fp.write( + ' if ((module = PyImport_ImportModule("%s")) != NULL) {\n' + % module) + fp.write( + ' PyObject *moddict = PyModule_GetDict(module);\n\n') for pyname, cname in bymod[module]: - fp.write(' _%s = (PyTypeObject *)PyDict_GetItemString(moddict, "%s");\n' % (cname, pyname)) + fp.write( + ' _%s = (PyTypeObject *)PyDict_GetItemString(' + 'moddict, "%s");\n' % (cname, pyname)) fp.write(' if (_%s == NULL) {\n' % cname) fp.write(' PyErr_SetString(PyExc_ImportError,\n') fp.write(' "cannot import name %s from %s");\n' @@ -1138,10 +1401,13 @@ def write_extension_init(overrides, prefix, fp): def write_registers(parser, overrides, fp): for boxed in parser.boxes: fp.write(' pyg_register_boxed(d, "' + boxed.name + - '", ' + boxed.typecode + ', &Py' + boxed.c_name + '_Type);\n') + '", ' + boxed.typecode + + ', &Py' + boxed.c_name + + '_Type);\n') for pointer in parser.pointers: fp.write(' pyg_register_pointer(d, "' + pointer.name + - '", ' + pointer.typecode + ', &Py' + pointer.c_name + '_Type);\n') + '", ' + pointer.typecode + + ', &Py' + pointer.c_name + '_Type);\n') for interface in parser.interfaces: fp.write(' pyg_register_interface(d, "' + interface.name + '", '+ interface.typecode + ', &Py' + interface.c_name + @@ -1178,6 +1444,14 @@ def write_registers(parser, overrides, fp): fp.write(' pygobject_register_class(d, "' + obj.c_name + '", ' + obj.typecode + ', &Py' + obj.c_name + '_Type, NULL);\n') + if obj.has_new_constructor_api: + fp.write(' pyg_set_object_has_new_constructor(%s);\n' % + obj.typecode) + else: + print >> sys.stderr, ( + "Warning: Constructor for %s needs to be updated to new API\n" + " See http://live.gnome.org/PyGTK_2fWhatsNew28" + "#update-constructors") % obj.c_name if obj.class_init_func is not None: fp.write(' pyg_register_class_init(%s, %s);\n' % (obj.typecode, obj.class_init_func)) @@ -1205,6 +1479,7 @@ def write_source(parser, overrides, prefix, fp=FileOutput(sys.stdout)): write_headers(overrides.get_headers(), fp) write_imports(overrides, fp) write_type_declarations(parser, fp) + write_body(overrides.get_body(), fp) write_classes(parser, overrides, fp) wrapper = Wrapper(parser, None, overrides, fp) @@ -1226,13 +1501,14 @@ def register_types(parser): for obj in parser.interfaces: argtypes.matcher.register_object(obj.c_name, None, obj.typecode) for enum in parser.enums: - if enum.deftype == 'flags': - argtypes.matcher.register_flag(enum.c_name, enum.typecode) - else: - argtypes.matcher.register_enum(enum.c_name, enum.typecode) + if enum.deftype == 'flags': + argtypes.matcher.register_flag(enum.c_name, enum.typecode) + else: + argtypes.matcher.register_enum(enum.c_name, enum.typecode) usage = 'usage: codegen.py [-o overridesfile] [-p prefix] defsfile' def main(argv): + o = override.Overrides() prefix = 'pygtk' outfilename = None errorfilename = None @@ -1254,7 +1530,7 @@ def main(argv): elif opt in ('-p', '--prefix'): prefix = arg elif opt in ('-r', '--register'): - # Warning: user has to make sure all -D options appear before -r + # Warning: user has to make sure all -D options appear before -r p = defsparser.DefsParser(arg, defines) p.startParsing() register_types(p) @@ -1266,12 +1542,12 @@ def main(argv): elif opt in ('-t', '--load-types'): globals = {} execfile(arg, globals) - elif opt == '-D': - nameval = arg.split('=') - try: - defines[nameval[0]] = nameval[1] - except IndexError: - defines[nameval[0]] = None + elif opt == '-D': + nameval = arg.split('=') + try: + defines[nameval[0]] = nameval[1] + except IndexError: + defines[nameval[0]] = None if len(args) < 1: print >> sys.stderr, usage return 1 @@ -1280,9 +1556,9 @@ def main(argv): p = defsparser.DefsParser(args[0], defines) if not outfilename: outfilename = os.path.splitext(args[0])[0] + '.c' - + p.startParsing() - + register_types(p) write_source(p, o, prefix, FileOutput(sys.stdout, outfilename)) diff --git a/codegen/definitions.py b/codegen/definitions.py index c5c06c2..911c8dd 100644 --- a/codegen/definitions.py +++ b/codegen/definitions.py @@ -1,17 +1,25 @@ # -*- Mode: Python; py-indent-offset: 4 -*- +import copy import sys -from copy import * def get_valid_scheme_definitions(defs): return [x for x in defs if isinstance(x, tuple) and len(x) >= 2] +def unescape(s): + s = s.replace('\r\n', '\\r\\n').replace('\t', '\\t') + return s.replace('\r', '\\r').replace('\n', '\\n') + +def make_docstring(lines): + return "(char *) " + '\n'.join(['"%s"' % unescape(s) for s in lines]) + # New Parameter class, wich emulates a tuple for compatibility reasons class Parameter(object): - def __init__(self, ptype, pname, pdflt, pnull, prop=None, keeprefcount=False): + def __init__(self, ptype, pname, pdflt, pnull, pdir=None, keeprefcount = False): self.ptype = ptype self.pname = pname self.pdflt = pdflt self.pnull = pnull + self.pdir = pdir self.keeprefcount = keeprefcount def __len__(self): return 4 @@ -39,16 +47,17 @@ class Property(object): class Definition: + docstring = "NULL" def __init__(self, *args): - """Create a new defs object of this type. The arguments are the - components of the definition""" - raise RuntimeError, "this is an abstract class" + """Create a new defs object of this type. The arguments are the + components of the definition""" + raise RuntimeError, "this is an abstract class" def merge(self, old): - """Merge in customisations from older version of definition""" - raise RuntimeError, "this is an abstract class" + """Merge in customisations from older version of definition""" + raise RuntimeError, "this is an abstract class" def write_defs(self, fp=sys.stdout): - """write out this definition in defs file format""" - raise RuntimeError, "this is an abstract class" + """write out this definition in defs file format""" + raise RuntimeError, "this is an abstract class" def guess_return_value_ownership(self): "return 1 if caller owns return value" @@ -62,46 +71,49 @@ class Definition: class ObjectDef(Definition): def __init__(self, name, *args): - self.name = name - self.module = None - self.parent = None - self.c_name = None + self.name = name + self.module = None + self.parent = None + self.c_name = None self.typecode = None - self.fields = [] + self.fields = [] self.implements = [] self.class_init_func = None - for arg in get_valid_scheme_definitions(args): - if arg[0] == 'in-module': - self.module = arg[1] - elif arg[0] == 'parent': + self.has_new_constructor_api = False + for arg in get_valid_scheme_definitions(args): + if arg[0] == 'in-module': + self.module = arg[1] + elif arg[0] == 'docstring': + self.docstring = make_docstring(arg[1:]) + elif arg[0] == 'parent': self.parent = arg[1] - elif arg[0] == 'c-name': - self.c_name = arg[1] - elif arg[0] == 'gtype-id': - self.typecode = arg[1] - elif arg[0] == 'fields': + elif arg[0] == 'c-name': + self.c_name = arg[1] + elif arg[0] == 'gtype-id': + self.typecode = arg[1] + elif arg[0] == 'fields': for parg in arg[1:]: self.fields.append((parg[0], parg[1])) elif arg[0] == 'implements': self.implements.append(arg[1]) def merge(self, old): - # currently the .h parser doesn't try to work out what fields of - # an object structure should be public, so we just copy the list - # from the old version ... - self.fields = old.fields + # currently the .h parser doesn't try to work out what fields of + # an object structure should be public, so we just copy the list + # from the old version ... + self.fields = old.fields self.implements = old.implements def write_defs(self, fp=sys.stdout): - fp.write('(define-object ' + self.name + '\n') - if self.module: - fp.write(' (in-module "' + self.module + '")\n') - if self.parent != (None, None): - fp.write(' (parent "' + self.parent + '")\n') + fp.write('(define-object ' + self.name + '\n') + if self.module: + fp.write(' (in-module "' + self.module + '")\n') + if self.parent != (None, None): + fp.write(' (parent "' + self.parent + '")\n') for interface in self.implements: fp.write(' (implements "' + interface + '")\n') - if self.c_name: - fp.write(' (c-name "' + self.c_name + '")\n') - if self.typecode: - fp.write(' (gtype-id "' + self.typecode + '")\n') + if self.c_name: + fp.write(' (c-name "' + self.c_name + '")\n') + if self.typecode: + fp.write(' (gtype-id "' + self.typecode + '")\n') if self.fields: fp.write(' (fields\n') for (ftype, fname) in self.fields: @@ -162,108 +174,110 @@ class MiniObjectDef(Definition): class InterfaceDef(Definition): def __init__(self, name, *args): - self.name = name - self.module = None - self.c_name = None + self.name = name + self.module = None + self.c_name = None self.typecode = None self.vtable = None - self.fields = [] + self.fields = [] self.interface_info = None - for arg in get_valid_scheme_definitions(args): - if arg[0] == 'in-module': - self.module = arg[1] - elif arg[0] == 'c-name': - self.c_name = arg[1] - elif arg[0] == 'gtype-id': - self.typecode = arg[1] - elif arg[0] == 'vtable': - self.vtable = arg[1] + for arg in get_valid_scheme_definitions(args): + if arg[0] == 'in-module': + self.module = arg[1] + elif arg[0] == 'docstring': + self.docstring = make_docstring(arg[1:]) + elif arg[0] == 'c-name': + self.c_name = arg[1] + elif arg[0] == 'gtype-id': + self.typecode = arg[1] + elif arg[0] == 'vtable': + self.vtable = arg[1] if self.vtable is None: self.vtable = self.c_name + "Iface" def write_defs(self, fp=sys.stdout): - fp.write('(define-interface ' + self.name + '\n') - if self.module: - fp.write(' (in-module "' + self.module + '")\n') - if self.c_name: - fp.write(' (c-name "' + self.c_name + '")\n') - if self.typecode: - fp.write(' (gtype-id "' + self.typecode + '")\n') - fp.write(')\n\n') + fp.write('(define-interface ' + self.name + '\n') + if self.module: + fp.write(' (in-module "' + self.module + '")\n') + if self.c_name: + fp.write(' (c-name "' + self.c_name + '")\n') + if self.typecode: + fp.write(' (gtype-id "' + self.typecode + '")\n') + fp.write(')\n\n') class EnumDef(Definition): def __init__(self, name, *args): - self.deftype = 'enum' - self.name = name - self.in_module = None - self.c_name = None + self.deftype = 'enum' + self.name = name + self.in_module = None + self.c_name = None self.typecode = None - self.values = [] - for arg in get_valid_scheme_definitions(args): - if arg[0] == 'in-module': - self.in_module = arg[1] - elif arg[0] == 'c-name': - self.c_name = arg[1] - elif arg[0] == 'gtype-id': - self.typecode = arg[1] - elif arg[0] == 'values': + self.values = [] + for arg in get_valid_scheme_definitions(args): + if arg[0] == 'in-module': + self.in_module = arg[1] + elif arg[0] == 'c-name': + self.c_name = arg[1] + elif arg[0] == 'gtype-id': + self.typecode = arg[1] + elif arg[0] == 'values': for varg in arg[1:]: self.values.append((varg[0], varg[1])) def merge(self, old): - pass + pass def write_defs(self, fp=sys.stdout): - fp.write('(define-' + self.deftype + ' ' + self.name + '\n') - if self.in_module: - fp.write(' (in-module "' + self.in_module + '")\n') - fp.write(' (c-name "' + self.c_name + '")\n') - fp.write(' (gtype-id "' + self.typecode + '")\n') + fp.write('(define-' + self.deftype + ' ' + self.name + '\n') + if self.in_module: + fp.write(' (in-module "' + self.in_module + '")\n') + fp.write(' (c-name "' + self.c_name + '")\n') + fp.write(' (gtype-id "' + self.typecode + '")\n') if self.values: fp.write(' (values\n') for name, val in self.values: fp.write(' \'("' + name + '" "' + val + '")\n') fp.write(' )\n') - fp.write(')\n\n') + fp.write(')\n\n') class FlagsDef(EnumDef): def __init__(self, *args): - apply(EnumDef.__init__, (self,) + args) - self.deftype = 'flags' + apply(EnumDef.__init__, (self,) + args) + self.deftype = 'flags' class BoxedDef(Definition): def __init__(self, name, *args): - self.name = name - self.module = None - self.c_name = None + self.name = name + self.module = None + self.c_name = None self.typecode = None self.copy = None self.release = None - self.fields = [] - for arg in get_valid_scheme_definitions(args): - if arg[0] == 'in-module': - self.module = arg[1] - elif arg[0] == 'c-name': - self.c_name = arg[1] - elif arg[0] == 'gtype-id': - self.typecode = arg[1] + self.fields = [] + for arg in get_valid_scheme_definitions(args): + if arg[0] == 'in-module': + self.module = arg[1] + elif arg[0] == 'c-name': + self.c_name = arg[1] + elif arg[0] == 'gtype-id': + self.typecode = arg[1] elif arg[0] == 'copy-func': self.copy = arg[1] elif arg[0] == 'release-func': self.release = arg[1] - elif arg[0] == 'fields': + elif arg[0] == 'fields': for parg in arg[1:]: self.fields.append((parg[0], parg[1])) def merge(self, old): - # currently the .h parser doesn't try to work out what fields of - # an object structure should be public, so we just copy the list - # from the old version ... - self.fields = old.fields + # currently the .h parser doesn't try to work out what fields of + # an object structure should be public, so we just copy the list + # from the old version ... + self.fields = old.fields def write_defs(self, fp=sys.stdout): - fp.write('(define-boxed ' + self.name + '\n') - if self.module: - fp.write(' (in-module "' + self.module + '")\n') - if self.c_name: - fp.write(' (c-name "' + self.c_name + '")\n') - if self.typecode: - fp.write(' (gtype-id "' + self.typecode + '")\n') + fp.write('(define-boxed ' + self.name + '\n') + if self.module: + fp.write(' (in-module "' + self.module + '")\n') + if self.c_name: + fp.write(' (c-name "' + self.c_name + '")\n') + if self.typecode: + fp.write(' (gtype-id "' + self.typecode + '")\n') if self.copy: fp.write(' (copy-func "' + self.copy + '")\n') if self.release: @@ -273,74 +287,80 @@ class BoxedDef(Definition): for (ftype, fname) in self.fields: fp.write(' \'("' + ftype + '" "' + fname + '")\n') fp.write(' )\n') - fp.write(')\n\n') + fp.write(')\n\n') class PointerDef(Definition): def __init__(self, name, *args): - self.name = name - self.module = None - self.c_name = None + self.name = name + self.module = None + self.c_name = None self.typecode = None - self.fields = [] - for arg in get_valid_scheme_definitions(args): - if arg[0] == 'in-module': - self.module = arg[1] - elif arg[0] == 'c-name': - self.c_name = arg[1] - elif arg[0] == 'gtype-id': - self.typecode = arg[1] - elif arg[0] == 'fields': + self.fields = [] + for arg in get_valid_scheme_definitions(args): + if arg[0] == 'in-module': + self.module = arg[1] + elif arg[0] == 'c-name': + self.c_name = arg[1] + elif arg[0] == 'gtype-id': + self.typecode = arg[1] + elif arg[0] == 'fields': for parg in arg[1:]: self.fields.append((parg[0], parg[1])) def merge(self, old): - # currently the .h parser doesn't try to work out what fields of - # an object structure should be public, so we just copy the list - # from the old version ... - self.fields = old.fields + # currently the .h parser doesn't try to work out what fields of + # an object structure should be public, so we just copy the list + # from the old version ... + self.fields = old.fields def write_defs(self, fp=sys.stdout): - fp.write('(define-pointer ' + self.name + '\n') - if self.module: - fp.write(' (in-module "' + self.module + '")\n') - if self.c_name: - fp.write(' (c-name "' + self.c_name + '")\n') - if self.typecode: - fp.write(' (gtype-id "' + self.typecode + '")\n') + fp.write('(define-pointer ' + self.name + '\n') + if self.module: + fp.write(' (in-module "' + self.module + '")\n') + if self.c_name: + fp.write(' (c-name "' + self.c_name + '")\n') + if self.typecode: + fp.write(' (gtype-id "' + self.typecode + '")\n') if self.fields: fp.write(' (fields\n') for (ftype, fname) in self.fields: fp.write(' \'("' + ftype + '" "' + fname + '")\n') fp.write(' )\n') - fp.write(')\n\n') + fp.write(')\n\n') class MethodDefBase(Definition): def __init__(self, name, *args): dump = 0 - self.name = name - self.ret = None + self.name = name + self.ret = None self.caller_owns_return = None - self.c_name = None + self.unblock_threads = None + self.c_name = None self.typecode = None - self.of_object = None - self.params = [] # of form (type, name, default, nullok) + self.of_object = None + self.params = [] # of form (type, name, default, nullok) self.varargs = 0 self.deprecated = None - for arg in get_valid_scheme_definitions(args): - if arg[0] == 'of-object': + for arg in get_valid_scheme_definitions(args): + if arg[0] == 'of-object': self.of_object = arg[1] - elif arg[0] == 'c-name': - self.c_name = arg[1] - elif arg[0] == 'gtype-id': - self.typecode = arg[1] - elif arg[0] == 'return-type': - self.ret = arg[1] + elif arg[0] == 'docstring': + self.docstring = make_docstring(arg[1:]) + elif arg[0] == 'c-name': + self.c_name = arg[1] + elif arg[0] == 'gtype-id': + self.typecode = arg[1] + elif arg[0] == 'return-type': + self.ret = arg[1] elif arg[0] == 'caller-owns-return': self.caller_owns_return = arg[1] in ('t', '#t') - elif arg[0] == 'parameters': + elif arg[0] == 'unblock-threads': + self.unblock_threads = arg[1] in ('t', '#t') + elif arg[0] == 'parameters': for parg in arg[1:]: ptype = parg[0] pname = parg[1] pdflt = None pnull = 0 + pdir = None keeprefcount = False for farg in parg[2:]: assert isinstance(farg, tuple) @@ -348,16 +368,18 @@ class MethodDefBase(Definition): pdflt = farg[1] elif farg[0] == 'null-ok': pnull = 1 + elif farg[0] == 'direction': + pdir = farg[1] elif farg[0] == 'keep-refcount': keeprefcount = True - self.params.append(Parameter(ptype, pname, pdflt, pnull, + self.params.append(Parameter(ptype, pname, pdflt, pnull, pdir, keeprefcount=keeprefcount)) elif arg[0] == 'varargs': self.varargs = arg[1] in ('t', '#t') elif arg[0] == 'deprecated': self.deprecated = arg[1] else: - sys.stderr.write("Warning: %s argument unsupported.\n" + sys.stderr.write("Warning: %s argument unsupported.\n" % (arg[0])) dump = 1 if dump: @@ -365,33 +387,35 @@ class MethodDefBase(Definition): if self.caller_owns_return is None and self.ret is not None: self.guess_return_value_ownership() - + def merge(self, old, parmerge): self.caller_owns_return = old.caller_owns_return self.varargs = old.varargs - # here we merge extra parameter flags accross to the new object. + # here we merge extra parameter flags accross to the new object. if not parmerge: - self.params = deepcopy(old.params) + self.params = copy.deepcopy(old.params) return - for i in range(len(self.params)): - ptype, pname, pdflt, pnull = self.params[i] - for p2 in old.params: - if p2[1] == pname: - self.params[i] = (ptype, pname, p2[2], p2[3]) - break + for i in range(len(self.params)): + ptype, pname, pdflt, pnull = self.params[i] + for p2 in old.params: + if p2[1] == pname: + self.params[i] = (ptype, pname, p2[2], p2[3]) + break def _write_defs(self, fp=sys.stdout): - if self.of_object != (None, None): - fp.write(' (of-object "' + self.of_object + '")\n') - if self.c_name: - fp.write(' (c-name "' + self.c_name + '")\n') - if self.typecode: - fp.write(' (gtype-id "' + self.typecode + '")\n') + if self.of_object != (None, None): + fp.write(' (of-object "' + self.of_object + '")\n') + if self.c_name: + fp.write(' (c-name "' + self.c_name + '")\n') + if self.typecode: + fp.write(' (gtype-id "' + self.typecode + '")\n') if self.caller_owns_return: - fp.write(' (caller-owns-return #t)\n') - if self.ret: - fp.write(' (return-type "' + self.ret + '")\n') - if self.deprecated: - fp.write(' (deprecated "' + self.deprecated + '")\n') + fp.write(' (caller-owns-return #t)\n') + if self.unblock_threads: + fp.write(' (unblock_threads #t)\n') + if self.ret: + fp.write(' (return-type "' + self.ret + '")\n') + if self.deprecated: + fp.write(' (deprecated "' + self.deprecated + '")\n') if self.params: fp.write(' (parameters\n') for ptype, pname, pdflt, pnull in self.params: @@ -400,9 +424,10 @@ class MethodDefBase(Definition): if pnull: fp.write(' (null-ok)') fp.write(')\n') fp.write(' )\n') - if self.varargs: - fp.write(' (varargs #t)\n') - fp.write(')\n\n') + if self.varargs: + fp.write(' (varargs #t)\n') + fp.write(')\n\n') + class MethodDef(MethodDefBase): def __init__(self, name, *args): @@ -411,43 +436,48 @@ class MethodDef(MethodDefBase): if self.__dict__[item] == None: self.write_defs(sys.stderr) raise RuntimeError, "definition missing required %s" % (item,) - + def write_defs(self, fp=sys.stdout): - fp.write('(define-method ' + self.name + '\n') + fp.write('(define-method ' + self.name + '\n') self._write_defs(fp) class VirtualDef(MethodDefBase): def write_defs(self, fp=sys.stdout): - fp.write('(define-virtual ' + self.name + '\n') + fp.write('(define-virtual ' + self.name + '\n') self._write_defs(fp) class FunctionDef(Definition): def __init__(self, name, *args): dump = 0 - self.name = name - self.in_module = None - self.is_constructor_of = None - self.ret = None + self.name = name + self.in_module = None + self.is_constructor_of = None + self.ret = None self.caller_owns_return = None - self.c_name = None + self.unblock_threads = None + self.c_name = None self.typecode = None - self.params = [] # of form (type, name, default, nullok) + self.params = [] # of form (type, name, default, nullok) self.varargs = 0 self.deprecated = None - for arg in get_valid_scheme_definitions(args): - if arg[0] == 'in-module': - self.in_module = arg[1] - elif arg[0] == 'is-constructor-of': - self.is_constructor_of = arg[1] - elif arg[0] == 'c-name': - self.c_name = arg[1] - elif arg[0] == 'gtype-id': - self.typecode = arg[1] - elif arg[0] == 'return-type': - self.ret = arg[1] + for arg in get_valid_scheme_definitions(args): + if arg[0] == 'in-module': + self.in_module = arg[1] + elif arg[0] == 'docstring': + self.docstring = make_docstring(arg[1:]) + elif arg[0] == 'is-constructor-of': + self.is_constructor_of = arg[1] + elif arg[0] == 'c-name': + self.c_name = arg[1] + elif arg[0] == 'gtype-id': + self.typecode = arg[1] + elif arg[0] == 'return-type': + self.ret = arg[1] elif arg[0] == 'caller-owns-return': self.caller_owns_return = arg[1] in ('t', '#t') - elif arg[0] == 'parameters': + elif arg[0] == 'unblock-threads': + self.unblock_threads = arg[1] in ('t', '#t') + elif arg[0] == 'parameters': for parg in arg[1:]: ptype = parg[0] pname = parg[1] @@ -501,17 +531,17 @@ class FunctionDef(Definition): self.caller_owns_return = old.caller_owns_return self.varargs = old.varargs if not parmerge: - self.params = deepcopy(old.params) + self.params = copy.deepcopy(old.params) return - # here we merge extra parameter flags accross to the new object. + # here we merge extra parameter flags accross to the new object. def merge_param(param): - for old_param in old.params: - if old_param.pname == param.pname: + for old_param in old.params: + if old_param.pname == param.pname: if isinstance(old_param, Property): # h2def never scans Property's, therefore if # we have one it was manually written, so we # keep it. - return deepcopy(old_param) + return copy.deepcopy(old_param) else: param.merge(old_param) return param @@ -522,35 +552,37 @@ class FunctionDef(Definition): except RuntimeError: # parameter names changed and we can't find a match; it's # safer to keep the old parameter list untouched. - self.params = deepcopy(old.params) - - if not self.is_constructor_of: + self.params = copy.deepcopy(old.params) + + if not self.is_constructor_of: try: self.is_constructor_of = old.is_constructor_of except AttributeError: pass - if isinstance(old, MethodDef): - self.name = old.name - # transmogrify from function into method ... - self.write_defs = self._method_write_defs - self.of_object = old.of_object - del self.params[0] + if isinstance(old, MethodDef): + self.name = old.name + # transmogrify from function into method ... + self.write_defs = self._method_write_defs + self.of_object = old.of_object + del self.params[0] def write_defs(self, fp=sys.stdout): - fp.write('(define-function ' + self.name + '\n') - if self.in_module: - fp.write(' (in-module "' + self.in_module + '")\n') - if self.is_constructor_of: - fp.write(' (is-constructor-of "' + self.is_constructor_of +'")\n') - if self.c_name: - fp.write(' (c-name "' + self.c_name + '")\n') - if self.typecode: - fp.write(' (gtype-id "' + self.typecode + '")\n') + fp.write('(define-function ' + self.name + '\n') + if self.in_module: + fp.write(' (in-module "' + self.in_module + '")\n') + if self.is_constructor_of: + fp.write(' (is-constructor-of "' + self.is_constructor_of +'")\n') + if self.c_name: + fp.write(' (c-name "' + self.c_name + '")\n') + if self.typecode: + fp.write(' (gtype-id "' + self.typecode + '")\n') if self.caller_owns_return: - fp.write(' (caller-owns-return #t)\n') - if self.ret: - fp.write(' (return-type "' + self.ret + '")\n') - if self.deprecated: - fp.write(' (deprecated "' + self.deprecated + '")\n') + fp.write(' (caller-owns-return #t)\n') + if self.unblock_threads: + fp.write(' (unblock-threads #t)\n') + if self.ret: + fp.write(' (return-type "' + self.ret + '")\n') + if self.deprecated: + fp.write(' (deprecated "' + self.deprecated + '")\n') if self.params: if isinstance(self.params[0], Parameter): fp.write(' (parameters\n') @@ -569,7 +601,7 @@ class FunctionDef(Definition): fp.write(' )\n') else: assert False, "strange parameter list %r" % self.params[0] - if self.varargs: - fp.write(' (varargs #t)\n') + if self.varargs: + fp.write(' (varargs #t)\n') - fp.write(')\n\n') + fp.write(')\n\n') diff --git a/codegen/defsconvert.py b/codegen/defsconvert.py deleted file mode 100644 index c25dcfb..0000000 --- a/codegen/defsconvert.py +++ /dev/null @@ -1,135 +0,0 @@ -import sys -import string, re - -# ------------------ Create typecodes from typenames --------- - -_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 upercase 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 string.upper(name) - -def typecode(typename): - """create a typecode (eg. GTK_TYPE_WIDGET) from a typename""" - return string.replace(to_upper_str(typename), '_', '_TYPE_', 1) - - -STATE_START = 0 -STATE_OBJECT = 1 -STATE_INTERFACE = 2 -STATE_BOXED = 3 -STATE_ENUM = 4 -STATE_FLAGS = 5 -STATE_METHOD = 6 -STATE_FUNCTION = 7 -STATE_MINIOBJECT = 8 - -def convert(infp=sys.stdin, outfp=sys.stdout): - state = STATE_START - seen_params = 0 - - line = infp.readline() - while line: - if line[:8] == '(object ': - state = STATE_OBJECT - seen_params = 0 - outfp.write('(define-object ' + line[8:]) - elif line[:13] == '(mini-object ': - state = STATE_MINI_OBJECT - seen_params = 0 - outfp.write('(define mini-object ' + line[13:]) - elif line[:11] == '(interface ': - state = STATE_INTERFACE - seen_params = 0 - outfp.write('(define-interface ' + line[11:]) - elif line[:7] == '(boxed ': - state = STATE_BOXED - seen_params = 0 - outfp.write('(define-boxed ' + line[7:]) - elif line[:6] == '(enum ': - state = STATE_ENUM - seen_params = 0 - outfp.write('(define-enum ' + line[6:]) - elif line[:7] == '(flags ': - state = STATE_FLAGS - seen_params = 0 - outfp.write('(define-flags ' + line[7:]) - elif line[:8] == '(method ': - state = STATE_METHOD - seen_params = 0 - outfp.write('(define-method ' + line[8:]) - elif line[:10] == '(function ': - state = STATE_FUNCTION - seen_params = 0 - outfp.write('(define-function ' + line[10:]) - elif line[:13] == ' (in-module ': - outfp.write(re.sub(r'^(\s+\(in-module\s+)(\w+)(.*)$', - r'\1"\2"\3', line)) - elif line[:10] == ' (parent ': - outfp.write(re.sub(r'^(\s+\(parent\s+)(\w+)(\s+\((\w+)\))?(.*)$', - r'\1"\4\2"\5', line)) - elif line[:14] == ' (implements ': - outfp.write(re.sub(r'^(\s+\(implements\s+)([^\s]+)(\s*\))$', - r'\1"\2"\3', line)) - elif line[:13] == ' (of-object ': - outfp.write(re.sub(r'^(\s+\(of-object\s+)(\w+)(\s+\((\w+)\))?(.*)$', - r'\1"\4\2"\5', line)) - elif line[:10] == ' (c-name ': - outfp.write(re.sub(r'^(\s+\(c-name\s+)([^\s]+)(\s*\))$', - r'\1"\2"\3', line)) - if state in (STATE_OBJECT, STATE_INTERFACE, STATE_BOXED, - STATE_ENUM, STATE_FLAGS): - c_name = re.match(r'^\s+\(c-name\s+([^\s]+)\s*\)$', - line).group(1) - outfp.write(' (gtype-id "%s")\n' % typecode(c_name)) - elif line[:15] == ' (return-type ': - outfp.write(re.sub(r'^(\s+\(return-type\s+)([^\s]+)(\s*\))$', - r'\1"\2"\3', line)) - elif line[:13] == ' (copy-func ': - outfp.write(re.sub(r'^(\s+\(copy-func\s+)(\w+)(.*)$', - r'\1"\2"\3', line)) - elif line[:16] == ' (release-func ': - outfp.write(re.sub(r'^(\s+\(release-func\s+)(\w+)(.*)$', - r'\1"\2"\3', line)) - elif line[:9] == ' (field ': - if not seen_params: - outfp.write(' (fields\n') - seen_params = 1 - outfp.write(re.sub(r'^\s+\(field\s+\(type-and-name\s+([^\s]+)\s+([^\s]+)\s*\)\s*\)$', - ' \'("\\1" "\\2")', line)) - elif line[:9] == ' (value ': - if not seen_params: - outfp.write(' (values\n') - seen_params = 1 - outfp.write(re.sub(r'^\s+\(value\s+\(name\s+([^\s]+)\)\s+\(c-name\s+([^\s]+)\s*\)\s*\)$', - ' \'("\\1" "\\2")', line)) - elif line[:13] == ' (parameter ': - if not seen_params: - outfp.write(' (parameters\n') - seen_params = 1 - outfp.write(re.sub(r'^\s+\(parameter\s+\(type-and-name\s+([^\s]+)\s+([^\s]+)\s*\)(\s*.*)\)$', - ' \'("\\1" "\\2"\\3)', line)) - elif line[:11] == ' (varargs ': - if seen_params: - outfp.write(' )\n') - seen_params = 0 - outfp.write(' (varargs #t)\n') - elif line[0] == ')': - if seen_params: - outfp.write(' )\n') - seen_params = 0 - state = STATE_START - outfp.write(line) - else: - outfp.write(line) - line = infp.readline() - -if __name__ == '__main__': - convert() diff --git a/codegen/defsparser.py b/codegen/defsparser.py index 9f58f1a..e24a969 100644 --- a/codegen/defsparser.py +++ b/codegen/defsparser.py @@ -1,7 +1,9 @@ # -*- Mode: Python; py-indent-offset: 4 -*- import os, sys import scmexpr -from definitions import * +from definitions import BoxedDef, EnumDef, FlagsDef, FunctionDef, \ + InterfaceDef, MethodDef, ObjectDef, MiniObjectDef, PointerDef, \ + VirtualDef class IncludeParser(scmexpr.Parser): """A simple parser that follows include statements automatically""" @@ -21,14 +23,14 @@ class DefsParser(IncludeParser): self.objects = [] self.miniobjects = [] self.interfaces = [] - self.enums = [] # enums and flags + self.enums = [] # enums and flags self.boxes = [] # boxed types self.pointers = [] # pointer types - self.functions = [] # functions and methods - self.virtuals = [] # virtual methods - self.c_name = {} # hash of c names of functions - self.methods = {} # hash of methods of particular objects - self.defines = defines # -Dfoo=bar options, as dictionary + self.functions = [] # functions and methods + self.virtuals = [] # virtual methods + self.c_name = {} # hash of c names of functions + self.methods = {} # hash of methods of particular objects + self.defines = defines # -Dfoo=bar options, as dictionary def define_object(self, *args): odef = apply(ObjectDef, args) @@ -60,16 +62,16 @@ class DefsParser(IncludeParser): self.pointers.append(pdef) self.c_name[pdef.c_name] = pdef def define_function(self, *args): - fdef = apply(FunctionDef, args) - self.functions.append(fdef) - self.c_name[fdef.c_name] = fdef + fdef = apply(FunctionDef, args) + self.functions.append(fdef) + self.c_name[fdef.c_name] = fdef def define_method(self, *args): - mdef = apply(MethodDef, args) - self.functions.append(mdef) - self.c_name[mdef.c_name] = mdef + mdef = apply(MethodDef, args) + self.functions.append(mdef) + self.c_name[mdef.c_name] = mdef def define_virtual(self, *args): - vdef = apply(VirtualDef, args) - self.virtuals.append(vdef) + vdef = apply(VirtualDef, args) + self.virtuals.append(vdef) def merge(self, old, parmerge): for obj in self.objects: if old.c_name.has_key(obj.c_name): @@ -79,12 +81,12 @@ class DefsParser(IncludeParser): f.merge(old.c_name[f.c_name], parmerge) def printMissing(self, old): - for obj in self.objects: - if not old.c_name.has_key(obj.c_name): + for obj in self.objects: + if not old.c_name.has_key(obj.c_name): obj.write_defs() - for f in self.functions: - if not old.c_name.has_key(f.c_name): - f.write_defs() + for f in self.functions: + if not old.c_name.has_key(f.c_name): + f.write_defs() def write_defs(self, fp=sys.stdout): for obj in self.objects: @@ -92,14 +94,14 @@ class DefsParser(IncludeParser): # TODO: Add miniobject for obj in self.miniobjects: obj.write_defs(fp) - for enum in self.enums: - enum.write_defs(fp) + for enum in self.enums: + enum.write_defs(fp) for boxed in self.boxes: boxed.write_defs(fp) for pointer in self.pointers: pointer.write_defs(fp) - for func in self.functions: - func.write_defs(fp) + for func in self.functions: + func.write_defs(fp) def find_object(self, c_name): for obj in self.objects: @@ -131,12 +133,11 @@ class DefsParser(IncludeParser): not func.is_constructor_of, self.functions) def ifdef(self, *args): - if args[0] in self.defines: - for arg in args[1:]: - self.handle(arg) + if args[0] in self.defines: + for arg in args[1:]: + self.handle(arg) def ifndef(self, *args): - if args[0] not in self.defines: - for arg in args[1:]: - self.handle(arg) - + if args[0] not in self.defines: + for arg in args[1:]: + self.handle(arg) diff --git a/codegen/docextract.py b/codegen/docextract.py index 1de4567..e6c6505 100644 --- a/codegen/docextract.py +++ b/codegen/docextract.py @@ -8,18 +8,18 @@ __all__ = ['extract'] class FunctionDoc: def __init__(self): - self.name = None - self.params = [] - self.description = '' - self.ret = '' + self.name = None + self.params = [] + self.description = '' + self.ret = '' def set_name(self, name): - self.name = name + self.name = name def add_param(self, name, description): - if name == '...': - name = 'Varargs' - self.params.append((name, description)) + if name == '...': + name = 'Varargs' + self.params.append((name, description)) def append_to_last_param(self, extra): - self.params[-1] = (self.params[-1][0], self.params[-1][1] + extra) + self.params[-1] = (self.params[-1][0], self.params[-1][1] + extra) def append_to_named_param(self, name, extra): for i in range(len(self.params)): if self.params[i][0] == name: @@ -28,9 +28,9 @@ class FunctionDoc: # fall through to adding extra parameter ... self.add_param(name, extra) def append_description(self, extra): - self.description = self.description + extra + self.description = self.description + extra def append_return(self, extra): - self.ret = self.ret + extra + self.ret = self.ret + extra def get_param_description(self, name): for param, description in self.params: @@ -44,97 +44,97 @@ comment_end_pat = re.compile(r'^\s*\*+/') comment_line_lead = re.compile(r'^\s*\*\s*') funcname_pat = re.compile(r'^(\w+)\s*:?') return_pat = re.compile(r'^(returns:|return\s+value:|returns\s*)(.*\n?)$', - re.IGNORECASE) + re.IGNORECASE) param_pat = re.compile(r'^@(\S+)\s*:(.*\n?)$') def parse_file(fp, doc_dict): line = fp.readline() in_comment_block = 0 while line: - if not in_comment_block: - if comment_start_pat.match(line): - in_comment_block = 1 - cur_doc = FunctionDoc() - in_description = 0 - in_return = 0 - line = fp.readline() - continue - - # we are inside a comment block ... - if comment_end_pat.match(line): - if not cur_doc.name: - sys.stderr.write("no function name found in doc comment\n") - else: - doc_dict[cur_doc.name] = cur_doc - in_comment_block = 0 - line = fp.readline() - continue - - # inside a comment block, and not the end of the block ... - line = comment_line_lead.sub('', line) - if not line: line = '\n' - - if not cur_doc.name: - match = funcname_pat.match(line) - if match: - cur_doc.set_name(match.group(1)) - elif in_return: - match = return_pat.match(line) - if match: - # assume the last return statement was really part of the - # description - cur_doc.description = cur_doc.description + return_start + \ - cur_doc.ret - return_start = match.group(1) - cur_doc.ret = match.group(2) - else: - cur_doc.append_return(line) - elif in_description: - if line[:12] == 'Description:': - line = line[12:] - match = return_pat.match(line) - if match: - in_return = 1 - return_start = match.group(1) - cur_doc.append_return(match.group(2)) - else: - cur_doc.append_description(line) - elif line == '\n': - # end of parameters - in_description = 1 - else: - match = param_pat.match(line) - if match: - param = match.group(1) - desc = match.group(2) + if not in_comment_block: + if comment_start_pat.match(line): + in_comment_block = 1 + cur_doc = FunctionDoc() + in_description = 0 + in_return = 0 + line = fp.readline() + continue + + # we are inside a comment block ... + if comment_end_pat.match(line): + if not cur_doc.name: + sys.stderr.write("no function name found in doc comment\n") + else: + doc_dict[cur_doc.name] = cur_doc + in_comment_block = 0 + line = fp.readline() + continue + + # inside a comment block, and not the end of the block ... + line = comment_line_lead.sub('', line) + if not line: line = '\n' + + if not cur_doc.name: + match = funcname_pat.match(line) + if match: + cur_doc.set_name(match.group(1)) + elif in_return: + match = return_pat.match(line) + if match: + # assume the last return statement was really part of the + # description + return_start = match.group(1) + cur_doc.ret = match.group(2) + cur_doc.description = cur_doc.description + return_start + \ + cur_doc.ret + else: + cur_doc.append_return(line) + elif in_description: + if line[:12] == 'Description:': + line = line[12:] + match = return_pat.match(line) + if match: + in_return = 1 + return_start = match.group(1) + cur_doc.append_return(match.group(2)) + else: + cur_doc.append_description(line) + elif line == '\n': + # end of parameters + in_description = 1 + else: + match = param_pat.match(line) + if match: + param = match.group(1) + desc = match.group(2) if param == 'returns': cur_doc.ret = desc else: cur_doc.add_param(param, desc) - else: - # must be continuation - try: + else: + # must be continuation + try: if param == 'returns': cur_doc.append_return(line) else: cur_doc.append_to_last_param(line) - except: - sys.stderr.write('something weird while reading param\n') - line = fp.readline() + except: + sys.stderr.write('something weird while reading param\n') + line = fp.readline() def parse_dir(dir, doc_dict): for file in os.listdir(dir): - if file in ('.', '..'): continue - path = os.path.join(dir, file) - if os.path.isdir(path): - parse_dir(path, doc_dict) - if len(file) > 2 and file[-2:] == '.c': - parse_file(open(path, 'r'), doc_dict) + if file in ('.', '..'): continue + path = os.path.join(dir, file) + if os.path.isdir(path): + parse_dir(path, doc_dict) + if len(file) > 2 and file[-2:] == '.c': + parse_file(open(path, 'r'), doc_dict) def extract(dirs, doc_dict=None): if not doc_dict: doc_dict = {} for dir in dirs: - parse_dir(dir, doc_dict) + parse_dir(dir, doc_dict) return doc_dict tmpl_section_pat = re.compile(r'^<!-- ##### (\w+) (\w+) ##### -->$') diff --git a/codegen/docextract_to_xml.py b/codegen/docextract_to_xml.py deleted file mode 100755 index 38d6722..0000000 --- a/codegen/docextract_to_xml.py +++ /dev/null @@ -1,78 +0,0 @@ -#!/usr/bin/env python -# -*- Mode: Python; py-indent-offset: 4 -*- -# -# This litte script outputs the C doc comments to an XML format. -# So far it's only used by gtkmm (The C++ bindings). Murray Cumming. -# Usage example: -# # ./docextract_to_xml.py -s /gnome/head/cvs/gtk+/gtk/ -s /gnome/head/cvs/gtk+/docs/reference/gtk/tmpl/ > gtk_docs.xml - -import sys, os, string, re, getopt - -import docextract -import string - -def escape_text(unescaped_text): - escaped_text = unescaped_text - escaped_text = string.replace(escaped_text, '<', '<') - escaped_text = string.replace(escaped_text, '>', '>') - escaped_text = string.replace(escaped_text, '&', '&') - escaped_text = string.replace(escaped_text, '\'', ''') - escaped_text = string.replace(escaped_text, '\"', '"') - - #Apparently this is an undefined symbol: - escaped_text = string.replace(escaped_text, '—', ' mdash ') - - return escaped_text - -if __name__ == '__main__': - try: - opts, args = getopt.getopt(sys.argv[1:], "d:s:o:", - ["source-dir="]) - except getopt.error, e: - sys.stderr.write('docgen.py: %s\n' % e) - sys.stderr.write( - 'usage: docgen.py [-s /src/dir]\n') - sys.exit(1) - source_dirs = [] - for opt, arg in opts: - if opt in ('-s', '--source-dir'): - source_dirs.append(arg) - if len(args) != 0: - sys.stderr.write( - 'usage: docgen.py [-s /src/dir]\n') - sys.exit(1) - - docs = docextract.extract(source_dirs); - docextract.extract_tmpl(source_dirs, docs); #Try the tmpl sgml files too. - - # print d.docs - - if docs: - - print "<root>" - - for name, value in docs.items(): - print "<function name=\"" + escape_text(name) + "\">" - - print "<description>" - #The value is a docextract.FunctionDoc - print escape_text(value.description) - print "</description>" - - # Loop through the parameters: - print "<parameters>" - for name, description in value.params: - print "<parameter name=\"" + escape_text(name) + "\">" - print "<parameter_description>" + escape_text(description) + "</parameter_description>" - print "</parameter>" - - print "</parameters>" - - # Show the return-type: - print "<return>" + escape_text(value.ret) + "</return>" - - print "</function>\n" - - print "</root>" - - diff --git a/codegen/docgen.py b/codegen/docgen.py index 5c7cde7..6905a14 100644 --- a/codegen/docgen.py +++ b/codegen/docgen.py @@ -32,13 +32,12 @@ def build_object_tree(parser): root = Node(None) nodes = { None: root } for obj_def in objects: + print obj_def.name parent_node = nodes[obj_def.parent] node = Node(obj_def.c_name, obj_def.implements) parent_node.add_child(node) nodes[node.name] = node - # TODO: Add mini-object - if parser.interfaces: interfaces = Node('gobject.GInterface') root.add_child(interfaces) @@ -70,7 +69,7 @@ def build_object_tree(parser): class DocWriter: def __init__(self): - # parse the defs file + # parse the defs file self.parser = defsparser.DefsParser(()) self.overrides = override.Overrides() self.classmap = {} @@ -116,12 +115,12 @@ class DocWriter: self.write_full_hierarchy(hierarchy, fp) fp.close() - obj_defs = self.parser.objects + self.parser.interfaces + \ + obj_defs = self.parser.objects + self.parser.interfaces + \ self.parser.boxes + self.parser.pointers - obj_defs.sort(self.__compare) - for obj_def in obj_defs: + obj_defs.sort(self.__compare) + for obj_def in obj_defs: filename = self.create_filename(obj_def.c_name, output_prefix) - fp = open(filename, 'w') + fp = open(filename, 'w') if isinstance(obj_def, definitions.ObjectDef): self.output_object_docs(obj_def, fp) elif isinstance(obj_def, definitions.InterfaceDef): @@ -130,24 +129,24 @@ class DocWriter: self.output_boxed_docs(obj_def, fp) elif isinstance(obj_def, definitions.PointerDef): self.output_boxed_docs(obj_def, fp) - fp.close() + fp.close() files.append((os.path.basename(filename), obj_def)) if files: filename = self.create_toc_filename(output_prefix) - fp = open(filename, 'w') + fp = open(filename, 'w') self.output_toc(files, fp) fp.close() - + def output_object_docs(self, obj_def, fp=sys.stdout): - self.write_class_header(obj_def.c_name, fp) + self.write_class_header(obj_def.c_name, fp) self.write_heading('Synopsis', fp) self.write_synopsis(obj_def, fp) self.close_section(fp) - # construct the inheritence hierarchy ... - ancestry = [ (obj_def.c_name, obj_def.implements) ] + # construct the inheritence hierarchy ... + ancestry = [ (obj_def.c_name, obj_def.implements) ] try: parent = obj_def.parent while parent != None: @@ -185,7 +184,7 @@ class DocWriter: self.write_class_footer(obj_def.c_name, fp) def output_interface_docs(self, int_def, fp=sys.stdout): - self.write_class_header(int_def.c_name, fp) + self.write_class_header(int_def.c_name, fp) self.write_heading('Synopsis', fp) self.write_synopsis(int_def, fp) @@ -203,7 +202,7 @@ class DocWriter: self.write_class_footer(int_def.c_name, fp) def output_boxed_docs(self, box_def, fp=sys.stdout): - self.write_class_header(box_def.c_name, fp) + self.write_class_header(box_def.c_name, fp) self.write_heading('Synopsis', fp) self.write_synopsis(box_def, fp) @@ -235,8 +234,8 @@ class DocWriter: # override the following to create a more complex output format def create_filename(self, obj_name, output_prefix): - '''Create output filename for this particular object''' - return output_prefix + '-' + string.lower(obj_name) + '.txt' + '''Create output filename for this particular object''' + return output_prefix + '-' + string.lower(obj_name) + '.txt' def create_toc_filename(self, output_prefix): return self.create_filename(self, 'docs', output_prefix) @@ -269,8 +268,8 @@ class DocWriter: ')' def write_class_header(self, obj_name, fp): - fp.write('Class %s\n' % obj_name) - fp.write('======%s\n\n' % ('=' * len(obj_name))) + fp.write('Class %s\n' % obj_name) + fp.write('======%s\n\n' % ('=' * len(obj_name))) def write_class_footer(self, obj_name, fp): pass def write_heading(self, text, fp): @@ -352,9 +351,9 @@ class DocbookDocWriter(DocWriter): def __init__(self, use_xml=0): DocWriter.__init__(self) self.use_xml = use_xml - + def create_filename(self, obj_name, output_prefix): - '''Create output filename for this particular object''' + '''Create output filename for this particular object''' stem = output_prefix + '-' + string.lower(obj_name) if self.use_xml: return stem + '.xml' @@ -429,7 +428,7 @@ class DocbookDocWriter(DocWriter): '</classname></link>' # fall through through return '<literal>' + match.group(1) + '</literal>' - + def reformat_text(self, text, singleline=0): # replace special strings ... text = self.__function_pat.sub(self.__format_function, text) @@ -439,7 +438,7 @@ class DocbookDocWriter(DocWriter): # don't bother with <para> expansion for single line text. if singleline: return text - + lines = string.split(string.strip(text), '\n') for index in range(len(lines)): if string.strip(lines[index]) == '': @@ -538,7 +537,7 @@ class DocbookDocWriter(DocWriter): sgml.append(' <methodparam></methodparam>') sgml.append(' </methodsynopsis>') return string.join(sgml, '') - + def write_class_header(self, obj_name, fp): if self.use_xml: fp.write('<?xml version="1.0" standalone="no"?>\n') @@ -680,7 +679,7 @@ class DocbookDocWriter(DocWriter): # fp.write('&' + string.translate(obj_def.c_name, # self.__transtable) + ';\n') #fp.write('</reference>\n') - + fp.write('<reference id="class-reference" xmlns:xi="http://www.w3.org/2001/XInclude">\n') fp.write(' <title>Class Reference</title>\n') for filename, obj_def in files: @@ -726,25 +725,25 @@ if __name__ == '__main__': "output-prefix="]) except getopt.error, e: sys.stderr.write('docgen.py: %s\n' % e) - sys.stderr.write( - 'usage: docgen.py -d file.defs [-s /src/dir] [-o output-prefix]\n') + sys.stderr.write( + 'usage: docgen.py -d file.defs [-s /src/dir] [-o output-prefix]\n') sys.exit(1) defs_file = None overrides_file = None source_dirs = [] output_prefix = 'docs' for opt, arg in opts: - if opt in ('-d', '--defs-file'): - defs_file = arg + if opt in ('-d', '--defs-file'): + defs_file = arg if opt in ('--override',): overrides_file = arg - elif opt in ('-s', '--source-dir'): - source_dirs.append(arg) - elif opt in ('-o', '--output-prefix'): - output_prefix = arg + elif opt in ('-s', '--source-dir'): + source_dirs.append(arg) + elif opt in ('-o', '--output-prefix'): + output_prefix = arg if len(args) != 0 or not defs_file: - sys.stderr.write( - 'usage: docgen.py -d file.defs [-s /src/dir] [-o output-prefix]\n') + sys.stderr.write( + 'usage: docgen.py -d file.defs [-s /src/dir] [-o output-prefix]\n') sys.exit(1) d = DocbookDocWriter() diff --git a/codegen/h2def.py b/codegen/h2def.py index 517ed5c..d4b2135 100755 --- a/codegen/h2def.py +++ b/codegen/h2def.py @@ -4,13 +4,19 @@ # For each prototype, generate a scheme style definition. # GPL'ed # Toby D. Reeves <toby@max.rl.plh.af.mil> - +# # 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 +import getopt +import os +import re +import string +import sys -import string, sys, re, types +import defsparser # ------------------ Create typecodes from typenames --------- @@ -114,7 +120,8 @@ def find_obj_defs(buf, objdefs=[]): objdefs.append(t) pos = m.end() - # now find all structures that look like they might represent a class inherited from GTypeInterface: + # now find all structures that look like they might represent + # a class inherited from GTypeInterface: pat = re.compile("struct _(" + obj_name_pat + ")Class\s*{\s*" + "GTypeInterface\s+", re.MULTILINE) pos = 0 @@ -129,7 +136,8 @@ def find_obj_defs(buf, objdefs=[]): objdefs.append(t) pos = m.end() - # now find all structures that look like they might represent an Iface inherited from GTypeInterface: + # now find all structures that look like they might represent + # an Iface inherited from GTypeInterface: pat = re.compile("struct _(" + obj_name_pat + ")Iface\s*{\s*" + "GTypeInterface\s+", re.MULTILINE) pos = 0 @@ -159,35 +167,6 @@ def sort_obj_defs(objdefs): pos = pos + 1 return objdefs -def write_obj_defs(objdefs, output): - if type(output)==types.StringType: - fp=open(output,'w') - elif type(output)==types.FileType: - fp=output - else: - fp=sys.stdout - - fp.write(';; -*- scheme -*-\n') - fp.write('; object definitions ...\n') - - for klass, parent in objdefs: - m = split_prefix_pat.match(klass) - cmodule = None - cname = klass - if m: - cmodule = m.group(1) - cname = m.group(2) - - fp.write('(define-object ' + cname + '\n') - if cmodule: - fp.write(' (in-module "' + cmodule + '")\n') - if parent: - fp.write(' (parent "' + parent + '")\n') - fp.write(' (c-name "' + klass + '")\n') - fp.write(' (gtype-id "' + typecode(klass) + '")\n') - # should do something about accessible fields - fp.write(')\n\n') - # ------------------ Find enum definitions ----------------- def find_enum_defs(buf, enums=[]): @@ -196,7 +175,7 @@ def find_enum_defs(buf, enums=[]): buf = strip_comments(buf) buf = re.sub('\n', ' ', buf) - + enum_pat = re.compile(r'enum\s*{([^}]*)}\s*([A-Z][A-Za-z]*)(\s|;)') splitter = re.compile(r'\s*,\s', re.MULTILINE) pos = 0 @@ -213,47 +192,8 @@ def find_enum_defs(buf, enums=[]): entries.append(string.split(val)[0]) if name != 'GdkCursorType': enums.append((name, isflags, entries)) - - pos = m.end() -def write_enum_defs(enums, output=None): - if type(output)==types.StringType: - fp=open(output,'w') - elif type(output)==types.FileType: - fp=output - else: - fp=sys.stdout - - fp.write(';; Enumerations and flags ...\n\n') - trans = string.maketrans(string.uppercase + '_', string.lowercase + '-') - for cname, isflags, entries in enums: - name = cname - module = None - m = split_prefix_pat.match(cname) - if m: - module = m.group(1) - name = m.group(2) - 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') - fp.write(' (gtype-id "' + typecode(cname) + '")\n') - prefix = entries[0] - for ent in entries: - # shorten prefix til we get a match ... - # and handle GDK_FONT_FONT, GDK_FONT_FONTSET case - while ent[:len(prefix)] != prefix or len(prefix) >= len(ent): - prefix = prefix[:-1] - prefix_len = len(prefix) - fp.write(' (values\n') - for ent in entries: - fp.write(' \'("%s" "%s")\n' % - (string.translate(ent[prefix_len:], trans), ent)) - fp.write(' )\n') - fp.write(')\n\n') + pos = m.end() # ------------------ Find function definitions ----------------- @@ -267,40 +207,41 @@ def clean_func(buf): buf = strip_comments(buf) # compact continued lines - pat = re.compile(r"""\\\n""", re.MULTILINE) - buf=pat.sub('',buf) + pat = re.compile(r"""\\\n""", re.MULTILINE) + buf = pat.sub('', buf) # Preprocess directives - pat = re.compile(r"""^[#].*?$""", re.MULTILINE) - buf=pat.sub('',buf) + pat = re.compile(r"""^[#].*?$""", re.MULTILINE) + buf = pat.sub('', buf) #typedefs, stucts, and enums - pat = re.compile(r"""^(typedef|struct|enum)(\s|.|\n)*?;\s*""", re.MULTILINE) - buf=pat.sub('',buf) + pat = re.compile(r"""^(typedef|struct|enum)(\s|.|\n)*?;\s*""", + re.MULTILINE) + buf = pat.sub('', buf) #strip DECLS macros - pat = re.compile(r"""G_BEGIN_DECLS|BEGIN_LIBGTOP_DECLS""", re.MULTILINE) - buf=pat.sub('',buf) + pat = re.compile(r"""G_BEGIN_DECLS|BEGIN_LIBGTOP_DECLS""", re.MULTILINE) + buf = pat.sub('', buf) #extern "C" - pat = re.compile(r"""^\s*(extern)\s+\"C\"\s+{""", re.MULTILINE) - buf=pat.sub('',buf) + pat = re.compile(r"""^\s*(extern)\s+\"C\"\s+{""", re.MULTILINE) + buf = pat.sub('', buf) #multiple whitespace - pat = re.compile(r"""\s+""", re.MULTILINE) - buf=pat.sub(' ',buf) + pat = re.compile(r"""\s+""", re.MULTILINE) + buf = pat.sub(' ', buf) #clean up line ends - pat = re.compile(r""";\s*""", re.MULTILINE) - buf=pat.sub('\n',buf) + pat = re.compile(r""";\s*""", re.MULTILINE) + buf = pat.sub('\n', buf) buf = buf.lstrip() #associate *, &, and [] with type instead of variable - #pat=re.compile(r'\s+([*|&]+)\s*(\w+)') - pat=re.compile(r' \s* ([*|&]+) \s* (\w+)',re.VERBOSE) - buf=pat.sub(r'\1 \2', buf) - pat=re.compile(r'\s+ (\w+) \[ \s* \]',re.VERBOSE) - buf=pat.sub(r'[] \1', buf) + #pat = re.compile(r'\s+([*|&]+)\s*(\w+)') + pat = re.compile(r' \s* ([*|&]+) \s* (\w+)', re.VERBOSE) + buf = pat.sub(r'\1 \2', buf) + pat = re.compile(r'\s+ (\w+) \[ \s* \]', re.VERBOSE) + buf = pat.sub(r'[] \1', buf) # make return types that are const work. buf = string.replace(buf, 'G_CONST_RETURN ', 'const-') @@ -312,165 +253,244 @@ proto_pat=re.compile(r""" (?P<ret>(-|\w|\&|\*)+\s*) # return type \s+ # skip whitespace (?P<func>\w+)\s*[(] # match the function name until the opening ( -\s*(?P<args>.*?)[)] # group the function arguments +\s*(?P<args>.*?)\s*[)] # group the function arguments """, re.IGNORECASE|re.VERBOSE) #""" arg_split_pat = re.compile("\s*,\s*") -def define_func(buf,fp, prefix): - buf=clean_func(buf) - buf=string.split(buf,'\n') - for p in buf: - if len(p)==0: continue - m=proto_pat.match(p) - if m==None: - if verbose: - sys.stderr.write('No match:|%s|\n'%p) - continue - func = m.group('func') - if func[0] == '_': - continue - ret = m.group('ret') - args=m.group('args') - args=arg_split_pat.split(args) - for i in range(len(args)): - spaces = string.count(args[i], ' ') - if spaces > 1: - args[i] = string.replace(args[i], ' ', '-', spaces - 1) - - write_func(fp, func, ret, args, prefix) - get_type_pat = re.compile(r'(const-)?([A-Za-z0-9]+)\*?\s+') pointer_pat = re.compile('.*\*$') func_new_pat = re.compile('(\w+)_new$') -def write_func(fp, name, ret, args, prefix): - if len(args) >= 1: - # methods must have at least one argument - munged_name = string.replace(name, '_', '') - m = get_type_pat.match(args[0]) - if m: - obj = m.group(2) - if munged_name[:len(obj)] == string.lower(obj): - regex = string.join(map(lambda x: x+'_?',string.lower(obj)),'') - mname = re.sub(regex, '', name, 1) - if prefix: - l = len(prefix) + 1 - if mname[:l] == prefix and mname[l+1] == '_': - mname = mname[l+1:] - fp.write('(define-method ' + mname + '\n') - fp.write(' (of-object "' + obj + '")\n') - fp.write(' (c-name "' + name + '")\n') - if ret != 'void': - fp.write(' (return-type "' + ret + '")\n') - else: - fp.write(' (return-type "none")\n') - is_varargs = 0 - has_args = len(args) > 1 - for arg in args[1:]: - if arg == '...': - is_varargs = 1 - elif arg in ('void', 'void '): - has_args = 0 - if has_args: - fp.write(' (parameters\n') - for arg in args[1:]: - if arg != '...': - tupleArg = tuple(string.split(arg)) - if len(tupleArg) == 2: - fp.write(' \'("%s" "%s")\n' % tupleArg) - fp.write(' )\n') - if is_varargs: - fp.write(' (varargs #t)\n') - fp.write(')\n\n') - return - if prefix: - l = len(prefix) - if name[:l] == prefix and name[l] == '_': - fname = name[l+1:] +class DefsWriter: + def __init__(self, fp=None, prefix=None, verbose=False, + defsfilter=None): + if not fp: + fp = sys.stdout + + self.fp = fp + self.prefix = prefix + self.verbose = verbose + + self._enums = {} + self._objects = {} + self._functions = {} + if defsfilter: + filter = defsparser.DefsParser(defsfilter) + filter.startParsing() + for func in filter.functions + filter.methods.values(): + self._functions[func.c_name] = func + for obj in filter.objects + filter.boxes + filter.interfaces: + self._objects[obj.c_name] = func + for obj in filter.enums: + self._enums[obj.c_name] = func + + def write_def(self, deffile): + buf = open(deffile).read() + + self.fp.write('\n;; From %s\n\n' % os.path.basename(deffile)) + self._define_func(buf) + self.fp.write('\n') + + def write_enum_defs(self, enums, fp=None): + if not fp: + fp = self.fp + + fp.write(';; Enumerations and flags ...\n\n') + trans = string.maketrans(string.uppercase + '_', + string.lowercase + '-') + filter = self._enums + for cname, isflags, entries in enums: + if filter: + if cname in filter: + continue + name = cname + module = None + m = split_prefix_pat.match(cname) + if m: + module = m.group(1) + name = m.group(2) + 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') + fp.write(' (gtype-id "' + typecode(cname) + '")\n') + prefix = entries[0] + for ent in entries: + # shorten prefix til we get a match ... + # and handle GDK_FONT_FONT, GDK_FONT_FONTSET case + while ent[:len(prefix)] != prefix or len(prefix) >= len(ent): + prefix = prefix[:-1] + prefix_len = len(prefix) + fp.write(' (values\n') + for ent in entries: + fp.write(' \'("%s" "%s")\n' % + (string.translate(ent[prefix_len:], trans), ent)) + fp.write(' )\n') + fp.write(')\n\n') + + def write_obj_defs(self, objdefs, fp=None): + if not fp: + fp = self.fp + + fp.write(';; -*- scheme -*-\n') + fp.write('; object definitions ...\n') + + filter = self._objects + for klass, parent in objdefs: + if filter: + if klass in filter: + continue + m = split_prefix_pat.match(klass) + cmodule = None + cname = klass + if m: + cmodule = m.group(1) + cname = m.group(2) + fp.write('(define-object ' + cname + '\n') + if cmodule: + fp.write(' (in-module "' + cmodule + '")\n') + if parent: + fp.write(' (parent "' + parent + '")\n') + fp.write(' (c-name "' + klass + '")\n') + fp.write(' (gtype-id "' + typecode(klass) + '")\n') + # should do something about accessible fields + fp.write(')\n\n') + + def _define_func(self, buf): + buf = clean_func(buf) + buf = string.split(buf,'\n') + filter = self._functions + for p in buf: + if not p: + continue + m = proto_pat.match(p) + if m == None: + if self.verbose: + sys.stderr.write('No match:|%s|\n' % p) + continue + func = m.group('func') + if func[0] == '_': + continue + if filter: + if func in filter: + continue + ret = m.group('ret') + args = m.group('args') + args = arg_split_pat.split(args) + for i in range(len(args)): + spaces = string.count(args[i], ' ') + if spaces > 1: + args[i] = string.replace(args[i], ' ', '-', spaces - 1) + + self._write_func(func, ret, args) + + def _write_func(self, name, ret, args): + if len(args) >= 1: + # methods must have at least one argument + munged_name = name.replace('_', '') + m = get_type_pat.match(args[0]) + if m: + obj = m.group(2) + if munged_name[:len(obj)] == obj.lower(): + self._write_method(obj, name, ret, args) + return + + if self.prefix: + l = len(self.prefix) + if name[:l] == self.prefix and name[l] == '_': + fname = name[l+1:] + else: + fname = name else: fname = name - else: - fname = name - # it is either a constructor or normal function - fp.write('(define-function ' + fname + '\n') - fp.write(' (c-name "' + name + '")\n') - - # Hmmm... Let's asume that a constructor function name - # ends with '_new' and it returns a pointer. - m = func_new_pat.match(name) - if pointer_pat.match(ret) and m: - cname = '' - for s in m.group(1).split ('_'): - cname += s.title() - if cname != '': - fp.write(' (is-constructor-of "' + cname + '")\n') - - if ret != 'void': - fp.write(' (return-type "' + ret + '")\n') - else: - fp.write(' (return-type "none")\n') - is_varargs = 0 - has_args = len(args) > 0 - for arg in args: - if arg == '...': - is_varargs = 1 - elif arg in ('void', 'void '): - has_args = 0 - if has_args: - fp.write(' (parameters\n') - for arg in args: - if arg != '...': - tupleArg = tuple(string.split(arg)) - if len(tupleArg) == 2: - fp.write(' \'("%s" "%s")\n' % tupleArg) - fp.write(' )\n') - if is_varargs: - fp.write(' (varargs #t)\n') - fp.write(')\n\n') - -def write_def(input,output=None, prefix=None): - fp = open(input) - buf = fp.read() - fp.close() - - if type(output) == types.StringType: - fp = open(output,'w') - elif type(output) == types.FileType: - fp = output - else: - fp = sys.stdout - fp.write('\n;; From %s\n\n' % input) - buf = define_func(buf, fp, prefix) - fp.write('\n') + # it is either a constructor or normal function + self.fp.write('(define-function ' + fname + '\n') + self.fp.write(' (c-name "' + name + '")\n') + + # Hmmm... Let's asume that a constructor function name + # ends with '_new' and it returns a pointer. + m = func_new_pat.match(name) + if pointer_pat.match(ret) and m: + cname = '' + for s in m.group(1).split ('_'): + cname += s.title() + if cname != '': + self.fp.write(' (is-constructor-of "' + cname + '")\n') + + self._write_return(ret) + self._write_arguments(args) + + def _write_method(self, obj, name, ret, args): + regex = string.join(map(lambda x: x+'_?', string.lower(obj)),'') + mname = re.sub(regex, '', name, 1) + if self.prefix: + l = len(self.prefix) + 1 + if mname[:l] == self.prefix and mname[l+1] == '_': + mname = mname[l+1:] + self.fp.write('(define-method ' + mname + '\n') + self.fp.write(' (of-object "' + obj + '")\n') + self.fp.write(' (c-name "' + name + '")\n') + self._write_return(ret) + self._write_arguments(args[1:]) + + def _write_return(self, ret): + if ret != 'void': + self.fp.write(' (return-type "' + ret + '")\n') + else: + self.fp.write(' (return-type "none")\n') + + def _write_arguments(self, args): + is_varargs = 0 + has_args = len(args) > 0 + for arg in args: + if arg == '...': + is_varargs = 1 + elif arg in ('void', 'void '): + has_args = 0 + if has_args: + self.fp.write(' (parameters\n') + for arg in args: + if arg != '...': + tupleArg = tuple(string.split(arg)) + if len(tupleArg) == 2: + self.fp.write(' \'("%s" "%s")\n' % tupleArg) + self.fp.write(' )\n') + if is_varargs: + self.fp.write(' (varargs #t)\n') + self.fp.write(')\n\n') # ------------------ Main function ----------------- -verbose=0 def main(args): - import getopt - global verbose - - onlyenums = 0 - onlyobjdefs = 0 - separate = 0 + verbose = False + onlyenums = False + onlyobjdefs = False + separate = False modulename = None - opts, args = getopt.getopt(args[1:], 'vs:m:', + defsfilter = None + opts, args = getopt.getopt(args[1:], 'vs:m:f:', ['onlyenums', 'onlyobjdefs', - 'modulename=', 'separate=']) + 'modulename=', 'separate=', + 'defsfilter=']) for o, v in opts: if o == '-v': - verbose = 1 + verbose = True if o == '--onlyenums': - onlyenums = 1 + onlyenums = True if o == '--onlyobjdefs': - onlyobjdefs = 1 + onlyobjdefs = True if o in ('-s', '--separate'): separate = v if o in ('-m', '--modulename'): modulename = v - + if o in ('-f', '--defsfilter'): + defsfilter = v + if not args[0:1]: print 'Must specify at least one input file name' return -1 @@ -485,29 +505,32 @@ def main(args): objdefs = sort_obj_defs(objdefs) if separate: - types = file(separate + '-types.defs', 'w') methods = file(separate + '.defs', 'w') - - write_obj_defs(objdefs,types) - write_enum_defs(enums,types) - types.close() + types = file(separate + '-types.defs', 'w') + + dw = DefsWriter(methods, prefix=modulename, verbose=verbose, + defsfilter=defsfilter) + dw.write_obj_defs(objdefs, types) + dw.write_enum_defs(enums, types) print "Wrote %s-types.defs" % separate - + for filename in args: - write_def(filename,methods,prefix=modulename) - methods.close() + dw.write_def(filename) print "Wrote %s.defs" % separate else: + dw = DefsWriter(prefix=modulename, verbose=verbose, + defsfilter=defsfilter) + if onlyenums: - write_enum_defs(enums,None) + dw.write_enum_defs(enums) elif onlyobjdefs: - write_obj_defs(objdefs,None) + dw.write_obj_defs(objdefs) else: - write_obj_defs(objdefs,None) - write_enum_defs(enums,None) + dw.write_obj_defs(objdefs) + dw.write_enum_defs(enums) for filename in args: - write_def(filename,None,prefix=modulename) - + dw.write_def(filename) + if __name__ == '__main__': sys.exit(main(sys.argv)) diff --git a/codegen/mergedefs.py b/codegen/mergedefs.py index 3e92f9c..773e499 100755 --- a/codegen/mergedefs.py +++ b/codegen/mergedefs.py @@ -1,11 +1,12 @@ #!/usr/bin/env python # -*- Mode: Python; py-indent-offset: 4 -*- -import sys +import optparse + import defsparser -from optparse import OptionParser -parser = OptionParser(usage="usage: %prog [options] generated-defs old-defs") +parser = optparse.OptionParser( + usage="usage: %prog [options] generated-defs old-defs") parser.add_option("-p", "--merge-parameters", help="Merge changes in function/methods parameter lists", action="store_true", dest="parmerge", default=False) diff --git a/codegen/missingdefs.py b/codegen/missingdefs.py deleted file mode 100755 index f0017e7..0000000 --- a/codegen/missingdefs.py +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env python -# -*- Mode: Python; py-indent-offset: 4 -*- - -import sys -import defsparser - -if len(sys.argv) < 3: - sys.stderr.write("Usage: missingdefs.py generated-defs old-defs\n") - sys.exit(1) - -newp = defsparser.DefsParser(sys.argv[1]) -oldp = defsparser.DefsParser(sys.argv[2]) - -newp.startParsing() -oldp.startParsing() - -newp.printMissing(oldp) diff --git a/codegen/mkskel.py b/codegen/mkskel.py index 2a1e1c3..61f520b 100755 --- a/codegen/mkskel.py +++ b/codegen/mkskel.py @@ -52,11 +52,11 @@ override_template = \ def open_with_backup(file): if os.path.exists(file): - try: - os.rename(file, file+'~') - except OSError: - # fail silently if we can't make a backup - pass + try: + os.rename(file, file+'~') + except OSError: + # fail silently if we can't make a backup + pass return open(file, 'w') def write_skels(fileprefix, prefix, module): @@ -69,21 +69,21 @@ def write_skels(fileprefix, prefix, module): if __name__ == '__main__': opts, args = getopt.getopt(sys.argv[1:], 'f:p:m:h', - ['file-prefix=', 'prefix=', 'module=', 'help']) + ['file-prefix=', 'prefix=', 'module=', 'help']) fileprefix = None prefix = None module = None for opt, arg in opts: - if opt in ('-f', '--file-prefix'): - fileprefix = arg - elif opt in ('-p', '--prefix'): - prefix = arg - elif opt in ('-m', '--module'): - module = arg - elif opt in ('-h', '--help'): - print 'usage: mkskel.py -f fileprefix -p prefix -m module' - sys.exit(0) + if opt in ('-f', '--file-prefix'): + fileprefix = arg + elif opt in ('-p', '--prefix'): + prefix = arg + elif opt in ('-m', '--module'): + module = arg + elif opt in ('-h', '--help'): + print 'usage: mkskel.py -f fileprefix -p prefix -m module' + sys.exit(0) if not fileprefix or not prefix or not module: - print 'usage: mkskel.py -f fileprefix -p prefix -m module' - sys.exit(1) + print 'usage: mkskel.py -f fileprefix -p prefix -m module' + sys.exit(1) write_skels(fileprefix, prefix, module) diff --git a/codegen/override.py b/codegen/override.py index 5b59632..4940876 100644 --- a/codegen/override.py +++ b/codegen/override.py @@ -18,27 +18,32 @@ def class2cname(klass, method): else: c_name += c return c_name[1:] + '_' + method - + import_pat = re.compile(r'\s*import\s+(\S+)\.([^\s.]+)\s+as\s+(\S+)') class Overrides: def __init__(self, filename=None, path=[]): self.modulename = None - self.ignores = {} - self.glob_ignores = [] + self.ignores = {} + self.glob_ignores = [] self.type_ignores = {} - self.overrides = {} + self.overrides = {} self.overridden = {} - self.kwargs = {} + self.kwargs = {} self.noargs = {} + self.onearg = {} + self.staticmethod = {} + self.classmethod = {} self.startlines = {} self.override_attrs = {} self.override_slots = {} self.headers = '' + self.body = '' self.init = '' self.imports = [] self.defines = {} self.functions = {} + self.newstyle_constructors = {} self.path = path if filename: self.handle_file(filename) @@ -61,8 +66,8 @@ class Overrides: if dirname != oldpath: os.chdir(dirname) - - # read all the components of the file ... + + # read all the components of the file ... bufs = [] startline = 1 lines = [] @@ -80,36 +85,36 @@ class Overrides: linenum = linenum + 1 if lines: bufs.append((string.join(lines, ''), startline)) - if not bufs: return + if not bufs: return - for buf, startline in bufs: - self.__parse_override(buf, startline, filename) + for buf, startline in bufs: + self.__parse_override(buf, startline, filename) os.chdir(oldpath) - + def __parse_override(self, buffer, startline, filename): - pos = string.find(buffer, '\n') - if pos >= 0: - line = buffer[:pos] - rest = buffer[pos+1:] - else: - line = buffer ; rest = '' - words = string.split(line) + pos = string.find(buffer, '\n') + if pos >= 0: + line = buffer[:pos] + rest = buffer[pos+1:] + else: + line = buffer ; rest = '' + words = string.split(line) command = words[0] - if (command == 'ignore' or + if (command == 'ignore' or command == 'ignore-' + sys.platform): "ignore/ignore-platform [functions..]" - for func in words[1:]: + for func in words[1:]: self.ignores[func] = 1 - for func in string.split(rest): + for func in string.split(rest): self.ignores[func] = 1 - elif (command == 'ignore-glob' or + elif (command == 'ignore-glob' or command == 'ignore-glob-' + sys.platform): - "ignore-glob/ignore-glob-platform [globs..]" - for func in words[1:]: + "ignore-glob/ignore-glob-platform [globs..]" + for func in words[1:]: + self.glob_ignores.append(func) + for func in string.split(rest): self.glob_ignores.append(func) - for func in string.split(rest): - self.glob_ignores.append(func) elif (command == 'ignore-type' or command == 'ignore-type-' + sys.platform): "ignore-type/ignore-type-platform [typenames..]" @@ -117,14 +122,23 @@ class Overrides: self.type_ignores[typename] = 1 for typename in string.split(rest): self.type_ignores[typename] = 1 - elif command == 'override': - "override function/method [kwargs,noargs]" - func = words[1] - if 'kwargs' in words[1:]: - self.kwargs[func] = 1 + elif command == 'override': + "override function/method [kwargs|noargs|onearg] [staticmethod|classmethod]" + func = words[1] + if 'kwargs' in words[1:]: + self.kwargs[func] = 1 elif 'noargs' in words[1:]: - self.noargs[func] = 1 - self.overrides[func] = rest + self.noargs[func] = 1 + elif 'onearg' in words[1:]: + self.onearg[func] = True + + if 'staticmethod' in words[1:]: + self.staticmethod[func] = True + elif 'classmethod' in words[1:]: + self.classmethod[func] = True + if func in self.overrides: + raise RuntimeError("Function %s is being overridden more than once" % (func,)) + self.overrides[func] = rest self.startlines[func] = (startline + 1, filename) elif command == 'override-attr': "override-slot Class.attr" @@ -140,6 +154,10 @@ class Overrides: "headers" self.headers = '%s\n#line %d "%s"\n%s' % \ (self.headers, startline + 1, filename, rest) + elif command == 'body': + "body" + self.body = '%s\n#line %d "%s"\n%s' % \ + (self.body, startline + 1, filename, rest) elif command == 'init': "init" self.init = '%s\n#line %d "%s"\n%s' % \ @@ -149,9 +167,9 @@ class Overrides: self.modulename = words[1] elif command == 'include': "include filename" - for filename in words[1:]: + for filename in words[1:]: self.handle_file(filename) - for filename in string.split(rest): + for filename in string.split(rest): self.handle_file(filename) elif command == 'import': "import module1 [\n module2, \n module3 ...]" @@ -160,9 +178,9 @@ class Overrides: if match: self.imports.append(match.groups()) elif command == 'define': - "define funcname [kwargs,noargs]" - "define Class.method [kwargs,noargs]" - func = words[1] + "define funcname [kwargs|noargs|onearg] [classmethod|staticmethod]" + "define Class.method [kwargs|noargs|onearg] [classmethod|staticmethod]" + func = words[1] klass = None if func.find('.') != -1: klass, func = func.split('.', 1) @@ -173,30 +191,42 @@ class Overrides: else: self.functions[func] = rest - if 'kwargs' in words[1:]: - self.kwargs[func] = 1 + if 'kwargs' in words[1:]: + self.kwargs[func] = 1 elif 'noargs' in words[1:]: - self.noargs[func] = 1 + self.noargs[func] = 1 + elif 'onearg' in words[1:]: + self.onearg[func] = 1 + + if 'staticmethod' in words[1:]: + self.staticmethod[func] = True + elif 'classmethod' in words[1:]: + self.classmethod[func] = True self.startlines[func] = (startline + 1, filename) - + + elif command == 'new-constructor': + "new-constructor GType" + gtype, = words[1:] + self.newstyle_constructors[gtype] = True + def is_ignored(self, name): - if self.ignores.has_key(name): - return 1 - for glob in self.glob_ignores: - if fnmatch.fnmatchcase(name, glob): - return 1 - return 0 - + if self.ignores.has_key(name): + return 1 + for glob in self.glob_ignores: + if fnmatch.fnmatchcase(name, glob): + return 1 + return 0 + def is_type_ignored(self, name): return name in self.type_ignores - + def is_overriden(self, name): - return self.overrides.has_key(name) - + return self.overrides.has_key(name) + def is_already_included(self, name): return self.overridden.has_key(name) - + def override(self, name): self.overridden[name] = 1 return self.overrides[name] @@ -207,39 +237,51 @@ class Overrides: def function(self, name): return self.functions[name] - + def getstartline(self, name): return self.startlines[name] def wants_kwargs(self, name): - return self.kwargs.has_key(name) - + return self.kwargs.has_key(name) + def wants_noargs(self, name): - return self.noargs.has_key(name) - + return self.noargs.has_key(name) + + def wants_onearg(self, name): + return self.onearg.has_key(name) + + def is_staticmethod(self, name): + return self.staticmethod.has_key(name) + + def is_classmethod(self, name): + return self.classmethod.has_key(name) + def attr_is_overriden(self, attr): return self.override_attrs.has_key(attr) - + def attr_override(self, attr): return self.override_attrs[attr] - + def slot_is_overriden(self, slot): return self.override_slots.has_key(slot) - + def slot_override(self, slot): return self.override_slots[slot] - + def get_headers(self): return self.headers - + + def get_body(self): + return self.body + def get_init(self): return self.init - + def get_imports(self): return self.imports def get_defines_for(self, klass): return self.defines.get(klass, {}) - + def get_functions(self): return self.functions diff --git a/codegen/reversewrapper.py b/codegen/reversewrapper.py index 3f0fb4f..f528828 100644 --- a/codegen/reversewrapper.py +++ b/codegen/reversewrapper.py @@ -2,6 +2,9 @@ ### Code to generate "Reverse Wrappers", i.e. C->Python wrappers ### (C) 2004 Gustavo Carneiro <gjc@gnome.org> import argtypes +import os + +DEBUG_MODE = ('PYGTK_CODEGEN_DEBUG' in os.environ) def join_ctype_name(ctype, name): '''Joins a C type and a variable name into a single string''' @@ -24,10 +27,10 @@ class CodeSink(object): if l[-1]: l.append('') return '\n'.join(l) - + def writeln(self, line=''): raise NotImplementedError - + def indent(self, level=4): '''Add a certain ammount of indentation to all lines written from now on and until unindent() is called''' @@ -75,18 +78,20 @@ class ReverseWrapper(object): assert isinstance(cname, str) self.cname = cname - ## function object we will call, or object whose method we will call + ## function object we will call, or object whose method we will call self.called_pyobj = None ## name of method of self.called_pyobj we will call - self.method_name = None + self.method_name = None self.is_static = is_static self.parameters = [] self.declarations = MemoryCodeSink() + self.post_return_code = MemoryCodeSink() self.body = MemoryCodeSink() self.cleanup_actions = [] self.pyargv_items = [] self.pyargv_optional_items = [] + self.pyret_parse_items = [] # list of (format_spec, parameter) def set_call_target(self, called_pyobj, method_name=None): assert called_pyobj is not None @@ -111,10 +116,18 @@ class ReverseWrapper(object): else: self.pyargv_items.append(variable) + def add_pyret_parse_item(self, format_specifier, parameter, prepend=False): + if prepend: + self.pyret_parse_items.insert(0, (format_specifier, parameter)) + else: + self.pyret_parse_items.append((format_specifier, parameter)) + def write_code(self, code, - cleanup=None, - failure_expression=None, - failure_cleanup=None): + cleanup=None, + failure_expression=None, + failure_cleanup=None, + failure_exception=None, + code_sink=None): '''Add a chunk of code with cleanup and error handling This method is to be used by TypeHandlers when generating code @@ -127,23 +140,39 @@ class ReverseWrapper(object): if anything failed (default None) failure_cleanup -- code to cleanup any dynamic resources created by @code in case of failure (default None) + failure_exception -- code to raise an exception in case of + failure (which will be immediately + printed and cleared), (default None) + code_sink -- "code sink" to use; by default, + ReverseWrapper.body is used, which writes the + main body of the wrapper, before calling the + python method. Alternatively, + ReverseWrapper.after_pyret_parse can be used, to + write code after the PyArg_ParseTuple that + parses the python method return value. ''' + if code_sink is None: + code_sink = self.body if code is not None: - self.body.writeln(code) + code_sink.writeln(code) if failure_expression is not None: - self.body.writeln("if (%s) {" % failure_expression) - self.body.indent() - self.body.writeln("if (PyErr_Occurred())") - self.body.indent() - self.body.writeln("PyErr_Print();") - self.body.unindent() + code_sink.writeln("if (%s) {" % (failure_expression,)) + code_sink.indent() + if failure_exception is None: + code_sink.writeln("if (PyErr_Occurred())") + code_sink.indent() + code_sink.writeln("PyErr_Print();") + code_sink.unindent() + else: + code_sink.writeln(failure_exception) + code_sink.writeln("PyErr_Print();") if failure_cleanup is not None: - self.body.writeln(failure_cleanup) + code_sink.writeln(failure_cleanup) for cleanup_action in self.cleanup_actions: - self.body.writeln(cleanup_action) + code_sink.writeln(cleanup_action) self.return_type.write_error_return() - self.body.unindent() - self.body.writeln("}") + code_sink.unindent() + code_sink.writeln("}") if cleanup is not None: self.cleanup_actions.insert(0, cleanup) @@ -151,6 +180,11 @@ class ReverseWrapper(object): '''Generate the code into a CodeSink object''' assert isinstance(sink, CodeSink) + if DEBUG_MODE: + self.declarations.writeln("/* begin declarations */") + self.body.writeln("/* begin main body */") + self.post_return_code.writeln("/* begin post-return code */") + self.add_declaration("PyGILState_STATE __py_state;") self.write_code(code="__py_state = pyg_gil_state_ensure();", cleanup="pyg_gil_state_release(__py_state);") @@ -201,7 +235,7 @@ class ReverseWrapper(object): argc = None self.body.writeln() - + if py_args != "NULL": self.write_code("py_args = PyTuple_New(%s);" % argc, cleanup="Py_DECREF(py_args);") @@ -227,7 +261,7 @@ class ReverseWrapper(object): self.body.writeln() - # call it + ## Call the python method if self.method_name is None: self.write_code("py_retval = PyObject_Call(%s, %s);" % (self.called_pyobj, py_args), @@ -243,14 +277,44 @@ class ReverseWrapper(object): % (py_args,), cleanup="Py_DECREF(py_retval);", failure_expression="!py_retval") - + + ## -- Handle the return value -- + + ## we need to check if the return_type object is prepared to cooperate with multiple return values + len_before = len(self.pyret_parse_items) self.return_type.write_conversion() + len_after = len(self.pyret_parse_items) + assert (self.return_type.get_c_type() == 'void' + or not (len_before == len_after and len_after > 0)),\ + ("Bug in reverse wrappers: return type handler %s" + " is not prepared to cooperate multiple return values") % (type(self.return_type),) sink.indent() + + if len(self.pyret_parse_items) == 1: + ## if retval is one item only, pack it in a tuple so we + ## can use PyArg_ParseTuple as usual.. + self.write_code('py_retval = Py_BuildValue("(N)", py_retval);') + if len(self.pyret_parse_items) > 0: + ## Parse return values using PyArg_ParseTuple + self.write_code(code=None, failure_expression=( + '!PyArg_ParseTuple(py_retval, "%s", %s)' % ( + "".join([format for format, param in self.pyret_parse_items]), + ", ".join([param for format, param in self.pyret_parse_items])))) + + if DEBUG_MODE: + self.declarations.writeln("/* end declarations */") self.declarations.flush_to(sink) sink.writeln() + if DEBUG_MODE: + self.body.writeln("/* end main body */") self.body.flush_to(sink) sink.writeln() + if DEBUG_MODE: + self.post_return_code.writeln("/* end post-return code */") + self.post_return_code.flush_to(sink) + sink.writeln() + for cleanup_action in self.cleanup_actions: sink.writeln(cleanup_action) if self.return_type.get_c_type() != 'void': @@ -325,7 +389,7 @@ class StringParam(Parameter): for ctype in ('char*', 'gchar*', 'const-char*', 'char-const*', 'const-gchar*', 'gchar-const*', 'string', 'static_string'): argtypes.matcher.register_reverse(ctype, StringParam) - +del ctype class StringReturn(ReturnType): @@ -339,15 +403,12 @@ class StringReturn(ReturnType): self.wrapper.write_code("return NULL;") def write_conversion(self): - self.wrapper.write_code( - code=None, - failure_expression="!PyString_Check(py_retval)", - failure_cleanup='PyErr_SetString(PyExc_TypeError, "retval should be a string");') - self.wrapper.write_code("retval = g_strdup(PyString_AsString(py_retval));") + self.wrapper.add_pyret_parse_item("s", "&retval", prepend=True) + self.wrapper.write_code("retval = g_strdup(retval);", code_sink=self.wrapper.post_return_code) for ctype in ('char*', 'gchar*'): - argtypes.matcher.register_reverse(ctype, StringReturn) - + argtypes.matcher.register_reverse_ret(ctype, StringReturn) +del ctype class VoidReturn(ReturnType): @@ -401,6 +462,10 @@ class GObjectReturn(ReturnType): self.wrapper.write_code("return NULL;") def write_conversion(self): + self.wrapper.write_code( + code=None, + failure_expression="!PyObject_TypeCheck(py_retval, &PyGObject_Type)", + failure_exception='PyErr_SetString(PyExc_TypeError, "retval should be a GObject");') self.wrapper.write_code("retval = (%s) pygobject_get(py_retval);" % self.get_c_type()) self.wrapper.write_code("g_object_ref((GObject *) retval);") @@ -429,17 +494,35 @@ class IntReturn(ReturnType): def write_error_return(self): self.wrapper.write_code("return -G_MAXINT;") def write_conversion(self): - self.wrapper.write_code( - code=None, - failure_expression="!PyInt_Check(py_retval)", - failure_cleanup='PyErr_SetString(PyExc_TypeError, "retval should be an int");') - self.wrapper.write_code("retval = PyInt_AsLong(py_retval);") + self.wrapper.add_pyret_parse_item("i", "&retval", prepend=True) for argtype in ('int', 'gint', 'guint', 'short', 'gshort', 'gushort', 'long', 'glong', 'gsize', 'gssize', 'guint8', 'gint8', 'guint16', 'gint16', 'gint32', 'GTime'): argtypes.matcher.register_reverse(argtype, IntParam) argtypes.matcher.register_reverse_ret(argtype, IntReturn) +del argtype + +class IntPtrParam(Parameter): + def __init__(self, wrapper, name, **props): + if "direction" not in props: + raise ValueError("cannot use int* parameter without direction") + if props["direction"] not in ("out", "inout"): + raise ValueError("cannot use int* parameter with direction '%s'" % (props["direction"],)) + Parameter.__init__(self, wrapper, name, **props) + def get_c_type(self): + return self.props.get('c_type', 'int*') + def convert_c2py(self): + if self.props["direction"] == "inout": + self.wrapper.add_declaration("PyObject *py_%s;" % self.name) + self.wrapper.write_code(code=("py_%s = PyInt_FromLong(*%s);" % + (self.name, self.name)), + cleanup=("Py_DECREF(py_%s);" % self.name)) + self.wrapper.add_pyargv_item("py_%s" % self.name) + self.wrapper.add_pyret_parse_item("i", self.name) +for argtype in ('int*', 'gint*'): + argtypes.matcher.register_reverse(argtype, IntPtrParam) +del argtype class GEnumReturn(IntReturn): @@ -500,10 +583,13 @@ class BooleanReturn(ReturnType): return "gboolean" def write_decl(self): self.wrapper.add_declaration("gboolean retval;") + self.wrapper.add_declaration("PyObject *py_main_retval;") def write_error_return(self): self.wrapper.write_code("return FALSE;") def write_conversion(self): - self.wrapper.write_code("retval = PyObject_IsTrue(py_retval)? TRUE : FALSE;") + self.wrapper.add_pyret_parse_item("O", "&py_main_retval", prepend=True) + self.wrapper.write_code("retval = PyObject_IsTrue(py_main_retval)? TRUE : FALSE;", + code_sink=self.wrapper.post_return_code) argtypes.matcher.register_reverse_ret("gboolean", BooleanReturn) class BooleanParam(Parameter): @@ -528,6 +614,21 @@ class DoubleParam(Parameter): cleanup=("Py_DECREF(py_%s);" % self.name)) self.wrapper.add_pyargv_item("py_%s" % self.name) +class DoublePtrParam(Parameter): + def __init__(self, wrapper, name, **props): + if "direction" not in props: + raise ValueError("cannot use double* parameter without direction") + if props["direction"] not in ("out", ): # inout not yet implemented + raise ValueError("cannot use double* parameter with direction '%s'" % (props["direction"],)) + Parameter.__init__(self, wrapper, name, **props) + def get_c_type(self): + return self.props.get('c_type', 'double*') + def convert_c2py(self): + self.wrapper.add_pyret_parse_item("d", self.name) +for argtype in ('double*', 'gdouble*'): + argtypes.matcher.register_reverse(argtype, DoublePtrParam) +del argtype + class DoubleReturn(ReturnType): def get_c_type(self): return self.props.get('c_type', 'gdouble') @@ -594,13 +695,13 @@ class GdkRectanglePtrParam(Parameter): def convert_c2py(self): self.wrapper.add_declaration("PyObject *py_%s;" % self.name) self.wrapper.write_code( - code=('py_%(name)s = Py_BuildValue("(ffff)", %(name)s->x, %(name)s->y,\n' - ' %(name)s->width, %(name)s->height);' - % dict(name=self.name)), + code=('py_%s = pyg_boxed_new(GDK_TYPE_RECTANGLE, %s, TRUE, TRUE);' % + (self.name, self.name)), cleanup=("Py_DECREF(py_%s);" % self.name)) self.wrapper.add_pyargv_item("py_%s" % self.name) argtypes.matcher.register_reverse("GdkRectangle*", GdkRectanglePtrParam) +argtypes.matcher.register_reverse('GtkAllocation*', GdkRectanglePtrParam) class PyGObjectMethodParam(Parameter): @@ -649,19 +750,22 @@ class CallbackInUserDataParam(Parameter): def _test(): import sys - wrapper = ReverseWrapper("this_is_the_c_function_name", is_static=True) - wrapper.set_return_type(StringReturn(wrapper)) - wrapper.add_parameter(PyGObjectMethodParam(wrapper, "self", method_name="do_xxx")) - wrapper.add_parameter(StringParam(wrapper, "param2", optional=True)) - wrapper.add_parameter(GObjectParam(wrapper, "param3")) - wrapper.generate(FileCodeSink(sys.stderr)) - - wrapper = ReverseWrapper("this_a_callback_wrapper") - wrapper.set_return_type(VoidReturn(wrapper)) - wrapper.add_parameter(StringParam(wrapper, "param1", optional=False)) - wrapper.add_parameter(GObjectParam(wrapper, "param2")) - wrapper.add_parameter(CallbackInUserDataParam(wrapper, "data", free_it=True)) - wrapper.generate(FileCodeSink(sys.stderr)) + if 1: + wrapper = ReverseWrapper("this_is_the_c_function_name", is_static=True) + wrapper.set_return_type(StringReturn(wrapper)) + wrapper.add_parameter(PyGObjectMethodParam(wrapper, "self", method_name="do_xxx")) + wrapper.add_parameter(StringParam(wrapper, "param2", optional=True)) + wrapper.add_parameter(GObjectParam(wrapper, "param3")) + #wrapper.add_parameter(InoutIntParam(wrapper, "param4")) + wrapper.generate(FileCodeSink(sys.stderr)) + + if 0: + wrapper = ReverseWrapper("this_a_callback_wrapper") + wrapper.set_return_type(VoidReturn(wrapper)) + wrapper.add_parameter(StringParam(wrapper, "param1", optional=False)) + wrapper.add_parameter(GObjectParam(wrapper, "param2")) + wrapper.add_parameter(CallbackInUserDataParam(wrapper, "data", free_it=True)) + wrapper.generate(FileCodeSink(sys.stderr)) if __name__ == '__main__': _test() |