parent
ccee0ebdca
commit
c5980502e2
|
@ -10,6 +10,19 @@ moopython_plugins = \
|
|||
$(moopython)/plugins/pyconsole.py \
|
||||
$(moopython)/plugins/pystuff.py
|
||||
|
||||
moopython_codegen = \
|
||||
$(moopython)/codegen/__init__.py \
|
||||
$(moopython)/codegen/argtypes.py \
|
||||
$(moopython)/codegen/codegen.py \
|
||||
$(moopython)/codegen/definitions.py \
|
||||
$(moopython)/codegen/defsparser.py \
|
||||
$(moopython)/codegen/docgen.py \
|
||||
$(moopython)/codegen/mergedefs.py \
|
||||
$(moopython)/codegen/mkskel.py \
|
||||
$(moopython)/codegen/override.py \
|
||||
$(moopython)/codegen/reversewrapper.py \
|
||||
$(moopython)/codegen/scmexpr.py
|
||||
|
||||
moopython_sources = \
|
||||
$(moopython)/moo-pygtk.c \
|
||||
$(moopython)/moo-pygtk.h \
|
||||
|
@ -38,6 +51,7 @@ mooedit_defs_files = \
|
|||
|
||||
moopython_extra_dist = \
|
||||
$(moopython_plugins) \
|
||||
$(moopython_codegen) \
|
||||
$(moopython)/moo-mod.py \
|
||||
$(moopython)/moo-pygtk.c \
|
||||
$(moopython)/mooapp-mod.py \
|
||||
|
@ -91,7 +105,8 @@ endif MOO_BUILD_APP
|
|||
|
||||
$(moopython)/mooutils-pygtk.c: $(moopython)/mooutils-pygtk.defs $(moopython)/mooutils-pygtk.override $(mooutils_override_files)
|
||||
mkdir -p $(moopython)
|
||||
pygtk-codegen-2.0 --prefix _moo_utils \
|
||||
$(PYTHON) $(moopython_srcdir)/codegen/codegen.py \
|
||||
--prefix _moo_utils \
|
||||
--register $(PYGTK_DEFS_DIR)/gtk-types.defs \
|
||||
--register $(PYGTK_DEFS_DIR)/gdk-types.defs \
|
||||
--override $(moopython_srcdir)/mooutils-pygtk.override \
|
||||
|
@ -100,7 +115,8 @@ $(moopython)/mooutils-pygtk.c: $(moopython)/mooutils-pygtk.defs $(moopython)/moo
|
|||
|
||||
$(moopython)/mooterm-pygtk.c: $(moopython)/mooterm-pygtk.defs $(moopython)/mooterm-pygtk.override
|
||||
mkdir -p $(moopython)
|
||||
pygtk-codegen-2.0 --prefix _moo_term \
|
||||
$(PYTHON) $(moopython_srcdir)/codegen/codegen.py \
|
||||
--prefix _moo_term \
|
||||
--register $(PYGTK_DEFS_DIR)/gtk-types.defs \
|
||||
--register $(PYGTK_DEFS_DIR)/gdk-types.defs \
|
||||
--register $(moopython_srcdir)/mooutils-pygtk.defs \
|
||||
|
@ -110,7 +126,8 @@ $(moopython)/mooterm-pygtk.c: $(moopython)/mooterm-pygtk.defs $(moopython)/moote
|
|||
|
||||
$(moopython)/mooedit-pygtk.c: $(moopython)/mooedit-pygtk.defs $(moopython)/mooedit-pygtk.override $(mooedit_defs_files)
|
||||
mkdir -p $(moopython)
|
||||
pygtk-codegen-2.0 --prefix _moo_edit \
|
||||
$(PYTHON) $(moopython_srcdir)/codegen/codegen.py \
|
||||
--prefix _moo_edit \
|
||||
--register $(PYGTK_DEFS_DIR)/gtk-types.defs \
|
||||
--register $(PYGTK_DEFS_DIR)/gdk-types.defs \
|
||||
--register $(moopython_srcdir)/mooutils-pygtk.defs \
|
||||
|
@ -120,7 +137,8 @@ $(moopython)/mooedit-pygtk.c: $(moopython)/mooedit-pygtk.defs $(moopython)/mooed
|
|||
|
||||
$(moopython)/mooapp-pygtk.c: $(moopython)/mooapp-pygtk.defs $(moopython)/mooapp-pygtk.override
|
||||
mkdir -p $(moopython)
|
||||
pygtk-codegen-2.0 --prefix _moo_app \
|
||||
$(PYTHON) $(moopython_srcdir)/codegen/codegen.py \
|
||||
--prefix _moo_app \
|
||||
--register $(PYGTK_DEFS_DIR)/gtk-types.defs \
|
||||
--register $(PYGTK_DEFS_DIR)/gdk-types.defs \
|
||||
--register $(moopython_srcdir)/mooedit-pygtk.defs \
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
# -*- Mode: Python; py-indent-offset: 4 -*-
|
||||
|
||||
__all__ = [
|
||||
'argtypes',
|
||||
'codegen',
|
||||
'definitions',
|
||||
'defsparser',
|
||||
'docextract',
|
||||
'docgen',
|
||||
'h2def',
|
||||
'mergedefs',
|
||||
'mkskel',
|
||||
'override',
|
||||
'scmexpr'
|
||||
]
|
|
@ -0,0 +1,950 @@
|
|||
# -*- 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 = {}
|
||||
def add(self, 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.append('\n')
|
||||
return string.join(ret, '')
|
||||
return ''
|
||||
|
||||
class WrapperInfo:
|
||||
"""A class that holds information about variable defs, code
|
||||
snippets, etcd for use in writing out the function/method
|
||||
wrapper."""
|
||||
def __init__(self):
|
||||
self.varlist = VarList()
|
||||
self.parsestr = ''
|
||||
self.parselist = ['', 'kwlist']
|
||||
self.codebefore = []
|
||||
self.codeafter = []
|
||||
self.arglist = []
|
||||
self.kwlist = []
|
||||
def get_parselist(self):
|
||||
return string.join(self.parselist, ', ')
|
||||
def get_codebefore(self):
|
||||
return string.join(self.codebefore, '')
|
||||
def get_codeafter(self):
|
||||
return string.join(self.codeafter, '')
|
||||
def get_arglist(self):
|
||||
return string.join(self.arglist, ', ')
|
||||
def get_varlist(self):
|
||||
return str(self.varlist)
|
||||
def get_kwlist(self):
|
||||
ret = ' static char *kwlist[] = { %s };\n' % \
|
||||
string.join(self.kwlist + [ 'NULL' ], ', ')
|
||||
if not self.get_varlist():
|
||||
ret = ret + '\n'
|
||||
return ret
|
||||
|
||||
def add_parselist(self, codes, parseargs, keywords):
|
||||
self.parsestr = self.parsestr + codes
|
||||
for arg in parseargs:
|
||||
self.parselist.append(arg)
|
||||
for kw in keywords:
|
||||
if keyword.iskeyword(kw):
|
||||
kw = kw + '_'
|
||||
self.kwlist.append('(char*)"%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" % \
|
||||
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" % \
|
||||
self.__class__.__name__
|
||||
|
||||
class NoneArg(ArgType):
|
||||
def write_return(self, ptype, ownsreturn, info):
|
||||
info.codeafter.append(' Py_INCREF(Py_None);\n' +
|
||||
' return Py_None;')
|
||||
|
||||
class StringArg(ArgType):
|
||||
def write_param(self, ptype, pname, pdflt, pnull, info):
|
||||
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.add_parselist('z', ['&' + pname], [pname])
|
||||
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')
|
||||
info.codeafter.append(' if (ret) {\n' +
|
||||
' PyObject *py_ret = PyString_FromString(ret);\n' +
|
||||
' g_free(ret);\n' +
|
||||
' return py_ret;\n' +
|
||||
' }\n' +
|
||||
' Py_INCREF(Py_None);\n' +
|
||||
' return Py_None;')
|
||||
else:
|
||||
info.varlist.add('const gchar', '*ret')
|
||||
info.codeafter.append(' if (ret)\n' +
|
||||
' return PyString_FromString(ret);\n'+
|
||||
' Py_INCREF(Py_None);\n' +
|
||||
' return Py_None;')
|
||||
|
||||
class UCharArg(ArgType):
|
||||
# allows strings with embedded NULLs.
|
||||
def write_param(self, ptype, pname, pdflt, pnull, info):
|
||||
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.add_parselist('z#', ['&' + pname, '&' + pname + '_len'],
|
||||
[pname])
|
||||
else:
|
||||
info.add_parselist('s#', ['&' + pname, '&' + pname + '_len'],
|
||||
[pname])
|
||||
|
||||
class CharArg(ArgType):
|
||||
def write_param(self, ptype, pname, pdflt, pnull, info):
|
||||
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.codeafter.append(' return PyString_FromStringAndSize(&ret, 1);')
|
||||
class GUniCharArg(ArgType):
|
||||
ret_tmpl = ('#if !defined(Py_UNICODE_SIZE) || Py_UNICODE_SIZE == 2\n'
|
||||
' if (ret > 0xffff) {\n'
|
||||
' PyErr_SetString(PyExc_RuntimeError, "returned character can not be represented in 16-bit unicode");\n'
|
||||
' return NULL;\n'
|
||||
' }\n'
|
||||
'#endif\n'
|
||||
' py_ret = (Py_UNICODE)ret;\n'
|
||||
' return PyUnicode_FromUnicode(&py_ret, 1);\n')
|
||||
def write_param(self, ptype, pname, pdflt, pnull, info):
|
||||
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, info):
|
||||
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')
|
||||
info.codeafter.append(' return PyInt_FromLong(ret);')
|
||||
|
||||
class UIntArg(ArgType):
|
||||
def write_param(self, ptype, pname, pdflt, pnull, info):
|
||||
if pdflt:
|
||||
info.varlist.add(ptype, pname + ' = ' + pdflt)
|
||||
else:
|
||||
info.varlist.add(ptype, pname)
|
||||
info.arglist.append(pname)
|
||||
info.add_parselist('I', ['&' + pname], [pname])
|
||||
def write_return(self, ptype, ownsreturn, info):
|
||||
info.varlist.add(ptype, 'ret')
|
||||
info.codeafter.append(' return PyLong_FromUnsignedLong(ret);\n')
|
||||
|
||||
class SizeArg(ArgType):
|
||||
|
||||
if struct.calcsize('P') <= struct.calcsize('l'):
|
||||
llp64 = True
|
||||
else:
|
||||
llp64 = False
|
||||
|
||||
def write_param(self, ptype, pname, pdflt, pnull, info):
|
||||
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:
|
||||
info.add_parselist('K', ['&' + pname], [pname])
|
||||
def write_return(self, ptype, ownsreturn, info):
|
||||
info.varlist.add(ptype, 'ret')
|
||||
if self.llp64:
|
||||
info.codeafter.append(' return PyLong_FromUnsignedLongLong(ret);\n')
|
||||
else:
|
||||
info.codeafter.append(' return PyLong_FromUnsignedLong(ret);\n')
|
||||
|
||||
class SSizeArg(ArgType):
|
||||
|
||||
if struct.calcsize('P') <= struct.calcsize('l'):
|
||||
llp64 = True
|
||||
else:
|
||||
llp64 = False
|
||||
|
||||
def write_param(self, ptype, pname, pdflt, pnull, info):
|
||||
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:
|
||||
info.add_parselist('L', ['&' + pname], [pname])
|
||||
def write_return(self, ptype, ownsreturn, info):
|
||||
info.varlist.add(ptype, 'ret')
|
||||
if self.llp64:
|
||||
info.codeafter.append(' return PyLong_FromLongLong(ret);\n')
|
||||
else:
|
||||
info.codeafter.append(' return PyLong_FromLong(ret);\n')
|
||||
|
||||
class LongArg(ArgType):
|
||||
def write_param(self, ptype, pname, pdflt, pnull, info):
|
||||
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')
|
||||
info.codeafter.append(' return PyInt_FromLong(ret);\n')
|
||||
|
||||
class BoolArg(IntArg):
|
||||
def write_return(self, ptype, ownsreturn, info):
|
||||
info.varlist.add('int', 'ret')
|
||||
info.codeafter.append(' return PyBool_FromLong(ret);\n')
|
||||
|
||||
class TimeTArg(ArgType):
|
||||
def write_param(self, ptype, pname, pdflt, pnull, info):
|
||||
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, info):
|
||||
if pdflt:
|
||||
info.varlist.add('gulong', pname + ' = ' + pdflt)
|
||||
info.codebefore.append(self.dflt % {'name':pname})
|
||||
else:
|
||||
info.varlist.add('gulong', 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('gulong', 'ret')
|
||||
info.codeafter.append(' return PyLong_FromUnsignedLong(ret);')
|
||||
|
||||
class Int64Arg(ArgType):
|
||||
def write_param(self, ptype, pname, pdflt, pnull, info):
|
||||
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, info):
|
||||
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, info):
|
||||
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')
|
||||
info.codeafter.append(' return PyFloat_FromDouble(ret);')
|
||||
|
||||
class FileArg(ArgType):
|
||||
nulldflt = (' if (py_%(name)s == Py_None)\n'
|
||||
' %(name)s = NULL;\n'
|
||||
' else if (py_%(name)s && PyFile_Check(py_%(name)s)\n'
|
||||
' %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'
|
||||
' }')
|
||||
null = (' if (py_%(name)s && PyFile_Check(py_%(name)s)\n'
|
||||
' %(name)s = PyFile_AsFile(py_%(name)s);\n'
|
||||
' else if (py_%(name)s != Py_None) {\n'
|
||||
' PyErr_SetString(PyExc_TypeError, "%(name)s should be a file object or None");\n'
|
||||
' return NULL;\n'
|
||||
' }\n')
|
||||
dflt = (' if (py_%(name)s)\n'
|
||||
' %(name)s = PyFile_AsFile(py_%(name)s);\n')
|
||||
def write_param(self, ptype, pname, pdflt, pnull, 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})
|
||||
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 + ')')
|
||||
info.add_parselist('O!', ['&PyFile_Type', '&' + pname], [pname])
|
||||
def write_return(self, ptype, ownsreturn, info):
|
||||
info.varlist.add('FILE', '*ret')
|
||||
info.codeafter.append(' if (ret)\n' +
|
||||
' return PyFile_FromFile(ret, "", "", fclose);\n' +
|
||||
' Py_INCREF(Py_None);\n' +
|
||||
' return Py_None;')
|
||||
|
||||
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
|
||||
def write_param(self, ptype, pname, pdflt, pnull, 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,
|
||||
'name': pname})
|
||||
info.arglist.append(pname)
|
||||
info.add_parselist('O', ['&py_' + pname], [pname]);
|
||||
def write_return(self, ptype, ownsreturn, info):
|
||||
info.varlist.add('gint', 'ret')
|
||||
info.codeafter.append(' return pyg_enum_from_gtype(%s, ret);' % self.typecode)
|
||||
|
||||
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
|
||||
def write_param(self, ptype, pname, pdflt, pnull, info):
|
||||
if pdflt:
|
||||
info.varlist.add(self.flagname, pname + ' = ' + pdflt)
|
||||
default = "py_%s && " % (pname,)
|
||||
else:
|
||||
info.varlist.add(self.flagname, pname)
|
||||
default = ""
|
||||
info.varlist.add('PyObject', '*py_' + pname + ' = NULL')
|
||||
info.codebefore.append(self.flag % {'default':default,
|
||||
'typecode':self.typecode,
|
||||
'name':pname})
|
||||
info.arglist.append(pname)
|
||||
info.add_parselist('O', ['&py_' + pname], [pname])
|
||||
def write_return(self, ptype, ownsreturn, info):
|
||||
info.varlist.add('guint', 'ret')
|
||||
info.codeafter.append(' return pyg_flags_from_gtype(%s, ret);' % self.typecode)
|
||||
|
||||
class ObjectArg(ArgType):
|
||||
# should change these checks to more typesafe versions that check
|
||||
# a little further down in the class heirachy.
|
||||
nulldflt = (' if ((PyObject *)py_%(name)s == Py_None)\n'
|
||||
' %(name)s = NULL;\n'
|
||||
' else if (py_%(name)s && pygobject_check(py_%(name)s, &Py%(type)s_Type))\n'
|
||||
' %(name)s = %(cast)s(py_%(name)s->obj);\n'
|
||||
' else if (py_%(name)s) {\n'
|
||||
' PyErr_SetString(PyExc_TypeError, "%(name)s should be a %(type)s or None");\n'
|
||||
' return NULL;\n'
|
||||
' }\n')
|
||||
null = (' if (py_%(name)s && pygobject_check(py_%(name)s, &Py%(type)s_Type))\n'
|
||||
' %(name)s = %(cast)s(py_%(name)s->obj);\n'
|
||||
' else if ((PyObject *)py_%(name)s != Py_None) {\n'
|
||||
' PyErr_SetString(PyExc_TypeError, "%(name)s should be a %(type)s or None");\n'
|
||||
' return NULL;\n'
|
||||
' }\n')
|
||||
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.parent = parent
|
||||
def write_param(self, ptype, pname, pdflt, pnull, 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,
|
||||
'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,
|
||||
'cast':self.cast,
|
||||
'type':self.objname})
|
||||
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)
|
||||
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))
|
||||
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 ownsreturn:
|
||||
info.varlist.add('PyObject', '*py_ret')
|
||||
info.codeafter.append(' py_ret = pygobject_new((GObject *)ret);\n'
|
||||
' if (ret != NULL)\n'
|
||||
' g_object_unref(ret);\n'
|
||||
' return py_ret;')
|
||||
else:
|
||||
info.codeafter.append(' /* pygobject_new handles NULL checking */\n' +
|
||||
' return pygobject_new((GObject *)ret);')
|
||||
|
||||
class BoxedArg(ArgType):
|
||||
# haven't done support for default args. Is it needed?
|
||||
check = (' if (pyg_boxed_check(py_%(name)s, %(typecode)s))\n'
|
||||
' %(name)s = pyg_boxed_get(py_%(name)s, %(typename)s);\n'
|
||||
' else {\n'
|
||||
' PyErr_SetString(PyExc_TypeError, "%(name)s should be a %(typename)s");\n'
|
||||
' return NULL;\n'
|
||||
' }\n')
|
||||
null = (' if (pyg_boxed_check(py_%(name)s, %(typecode)s))\n'
|
||||
' %(name)s = pyg_boxed_get(py_%(name)s, %(typename)s);\n'
|
||||
' else if (py_%(name)s != Py_None) {\n'
|
||||
' PyErr_SetString(PyExc_TypeError, "%(name)s should be a %(typename)s or None");\n'
|
||||
' return NULL;\n'
|
||||
' }\n')
|
||||
def __init__(self, ptype, typecode):
|
||||
self.typename = ptype
|
||||
self.typecode = typecode
|
||||
def write_param(self, ptype, pname, pdflt, pnull, info):
|
||||
if pnull:
|
||||
info.varlist.add(self.typename, '*' + pname + ' = NULL')
|
||||
info.varlist.add('PyObject', '*py_' + pname + ' = Py_None')
|
||||
info.codebefore.append(self.null % {'name': pname,
|
||||
'typename': self.typename,
|
||||
'typecode': self.typecode})
|
||||
else:
|
||||
info.varlist.add(self.typename, '*' + pname + ' = NULL')
|
||||
info.varlist.add('PyObject', '*py_' + pname)
|
||||
info.codebefore.append(self.check % {'name': pname,
|
||||
'typename': self.typename,
|
||||
'typecode': self.typecode})
|
||||
if ptype[-1] == '*':
|
||||
typename = ptype[:-1]
|
||||
if typename[:6] == 'const-': typename = typename[6:]
|
||||
if typename != self.typename:
|
||||
info.arglist.append('(%s *)%s' % (ptype[:-1], pname))
|
||||
else:
|
||||
info.arglist.append(pname)
|
||||
else:
|
||||
info.arglist.append(pname)
|
||||
info.add_parselist('O', ['&py_' + pname], [pname])
|
||||
ret_tmpl = ' /* pyg_boxed_new handles NULL checking */\n' \
|
||||
' return pyg_boxed_new(%(typecode)s, %(ret)s, %(copy)s, TRUE);'
|
||||
def write_return(self, ptype, ownsreturn, info):
|
||||
if ptype[-1] == '*':
|
||||
info.varlist.add(self.typename, '*ret')
|
||||
ret = 'ret'
|
||||
else:
|
||||
info.varlist.add(self.typename, 'ret')
|
||||
ret = '&ret'
|
||||
ownsreturn = 0 # of course it can't own a ref to a local var ...
|
||||
info.codeafter.append(self.ret_tmpl %
|
||||
{ 'typecode': self.typecode,
|
||||
'ret': ret,
|
||||
'copy': ownsreturn and 'FALSE' or 'TRUE'})
|
||||
|
||||
class CustomBoxedArg(ArgType):
|
||||
# haven't done support for default args. Is it needed?
|
||||
null = (' if (%(check)s(py_%(name)s))\n'
|
||||
' %(name)s = %(get)s(py_%(name)s);\n'
|
||||
' else if (py_%(name)s != Py_None) {\n'
|
||||
' PyErr_SetString(PyExc_TypeError, "%(name)s should be a %(type)s or None");\n'
|
||||
' return NULL;\n'
|
||||
' }\n')
|
||||
def __init__(self, ptype, pytype, getter, new):
|
||||
self.pytype = pytype
|
||||
self.getter = getter
|
||||
self.checker = 'Py' + ptype + '_Check'
|
||||
self.new = new
|
||||
def write_param(self, ptype, pname, pdflt, pnull, info):
|
||||
if pnull:
|
||||
info.varlist.add(ptype[:-1], '*' + pname + ' = NULL')
|
||||
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.add_parselist('O', ['&py_' + pname], [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')
|
||||
info.codeafter.append(' if (ret)\n' +
|
||||
' return ' + self.new + '(ret);\n' +
|
||||
' Py_INCREF(Py_None);\n' +
|
||||
' return Py_None;')
|
||||
|
||||
class PointerArg(ArgType):
|
||||
# haven't done support for default args. Is it needed?
|
||||
check = (' if (pyg_pointer_check(py_%(name)s, %(typecode)s))\n'
|
||||
' %(name)s = pyg_pointer_get(py_%(name)s, %(typename)s);\n'
|
||||
' else {\n'
|
||||
' PyErr_SetString(PyExc_TypeError, "%(name)s should be a %(typename)s");\n'
|
||||
' return NULL;\n'
|
||||
' }\n')
|
||||
null = (' if (pyg_pointer_check(py_%(name)s, %(typecode)s))\n'
|
||||
' %(name)s = pyg_pointer_get(py_%(name)s, %(typename)s);\n'
|
||||
' else if (py_%(name)s != Py_None) {\n'
|
||||
' PyErr_SetString(PyExc_TypeError, "%(name)s should be a %(typename)s or None");\n'
|
||||
' return NULL;\n'
|
||||
' }\n')
|
||||
def __init__(self, ptype, typecode):
|
||||
self.typename = ptype
|
||||
self.typecode = typecode
|
||||
def write_param(self, ptype, pname, pdflt, pnull, info):
|
||||
if pnull:
|
||||
info.varlist.add(self.typename, '*' + pname + ' = NULL')
|
||||
info.varlist.add('PyObject', '*py_' + pname + ' = Py_None')
|
||||
info.codebefore.append(self.null % {'name': pname,
|
||||
'typename': self.typename,
|
||||
'typecode': self.typecode})
|
||||
else:
|
||||
info.varlist.add(self.typename, '*' + pname + ' = NULL')
|
||||
info.varlist.add('PyObject', '*py_' + pname)
|
||||
info.codebefore.append(self.check % {'name': pname,
|
||||
'typename': self.typename,
|
||||
'typecode': self.typecode})
|
||||
info.arglist.append(pname)
|
||||
info.add_parselist('O', ['&py_' + pname], [pname])
|
||||
def write_return(self, ptype, ownsreturn, info):
|
||||
if ptype[-1] == '*':
|
||||
info.varlist.add(self.typename, '*ret')
|
||||
info.codeafter.append(' /* pyg_pointer_new handles NULL checking */\n' +
|
||||
' return pyg_pointer_new(' + self.typecode + ', ret);')
|
||||
else:
|
||||
info.varlist.add(self.typename, 'ret')
|
||||
info.codeafter.append(' /* pyg_pointer_new handles NULL checking */\n' +
|
||||
' return pyg_pointer_new(' + self.typecode + ', &ret);')
|
||||
|
||||
class AtomArg(IntArg):
|
||||
dflt = ' if (py_%(name)s) {\n' \
|
||||
' %(name)s = pygdk_atom_from_pyobject(py_%(name)s);\n' \
|
||||
' if (PyErr_Occurred())\n' \
|
||||
' return NULL;\n' \
|
||||
' }\n'
|
||||
atom = (' %(name)s = pygdk_atom_from_pyobject(py_%(name)s);\n'
|
||||
' if (PyErr_Occurred())\n'
|
||||
' return NULL;\n')
|
||||
def write_param(self, ptype, pname, pdflt, pnull, info):
|
||||
if pdflt:
|
||||
info.varlist.add('GdkAtom', pname + ' = ' + pdflt)
|
||||
info.varlist.add('PyObject', '*py_' + pname + ' = NULL')
|
||||
info.codebefore.append(self.dflt % {'name': pname})
|
||||
else:
|
||||
info.varlist.add('GdkAtom', pname)
|
||||
info.varlist.add('PyObject', '*py_' + pname + ' = NULL')
|
||||
info.codebefore.append(self.atom % {'name': pname})
|
||||
info.arglist.append(pname)
|
||||
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));')
|
||||
|
||||
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, 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.add_parselist('O', ['&py_' + pname], [pname])
|
||||
def write_return(self, ptype, ownsreturn, info):
|
||||
info.varlist.add('GType', 'ret')
|
||||
info.codeafter.append(' return pyg_type_wrapper_new(ret);')
|
||||
|
||||
# simple GError handler.
|
||||
class GErrorArg(ArgType):
|
||||
handleerror = (' if (pyg_error_check(&%(name)s))\n'
|
||||
' return NULL;\n')
|
||||
def write_param(self, ptype, pname, pdflt, pnull, info):
|
||||
info.varlist.add('GError', '*' + pname + ' = NULL')
|
||||
info.arglist.append('&' + pname)
|
||||
info.codeafter.append(self.handleerror % { 'name': pname })
|
||||
|
||||
class GtkTreePathArg(ArgType):
|
||||
# haven't done support for default args. Is it needed?
|
||||
normal = (' %(name)s = pygtk_tree_path_from_pyobject(py_%(name)s);\n'
|
||||
' if (!%(name)s) {\n'
|
||||
' PyErr_SetString(PyExc_TypeError, "could not convert %(name)s to a GtkTreePath");\n'
|
||||
' return NULL;\n'
|
||||
' }\n')
|
||||
null = (' if (py_%(name)s != Py_None) {\n'
|
||||
' %(name)s = pygtk_tree_path_from_pyobject(py_%(name)s);\n'
|
||||
' if (!%(name)s) {\n'
|
||||
' PyErr_SetString(PyExc_TypeError, "could not convert %(name)s to a GtkTreePath");\n'
|
||||
' return NULL;\n'
|
||||
' }\n'
|
||||
' }\n')
|
||||
freepath = (' if (%(name)s)\n'
|
||||
' gtk_tree_path_free(%(name)s);\n')
|
||||
def __init__(self):
|
||||
pass
|
||||
def write_param(self, ptype, pname, pdflt, pnull, info):
|
||||
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.add_parselist('O', ['&py_' + pname], [pname])
|
||||
else:
|
||||
info.varlist.add('GtkTreePath', '*' + pname)
|
||||
info.varlist.add('PyObject', '*py_' + pname)
|
||||
info.codebefore.append(self.normal % {'name': 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):
|
||||
info.varlist.add('GtkTreePath', '*ret')
|
||||
if ownsreturn:
|
||||
info.codeafter.append(' if (ret) {\n'
|
||||
' PyObject *py_ret = pygtk_tree_path_to_pyobject(ret);\n'
|
||||
' gtk_tree_path_free(ret);\n'
|
||||
' return py_ret;\n'
|
||||
' }\n'
|
||||
' Py_INCREF(Py_None);\n'
|
||||
' return Py_None;')
|
||||
else:
|
||||
info.codeafter.append(' if (ret) {\n'
|
||||
' PyObject *py_ret = pygtk_tree_path_to_pyobject(ret);\n'
|
||||
' return py_ret;\n'
|
||||
' }\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')
|
||||
null = (' if (py_%(name)s == Py_None)\n'
|
||||
' %(name)s = NULL;\n'
|
||||
' else if (pygdk_rectangle_from_pyobject(py_%(name)s, &%(name)s_rect))\n'
|
||||
' %(name)s = &%(name)s_rect;\n'
|
||||
' else\n'
|
||||
' return NULL;\n')
|
||||
def write_param(self, ptype, pname, pdflt, pnull, info):
|
||||
if pnull:
|
||||
info.varlist.add('GdkRectangle', pname + '_rect = { 0, 0, 0, 0 }')
|
||||
info.varlist.add('GdkRectangle', '*' + pname)
|
||||
info.varlist.add('PyObject', '*py_' + pname + ' = Py_None')
|
||||
info.add_parselist('O', ['&py_' + pname], [pname])
|
||||
info.arglist.append(pname)
|
||||
info.codebefore.append(self.null % {'name': pname})
|
||||
else:
|
||||
info.varlist.add('GdkRectangle', pname + ' = { 0, 0, 0, 0 }')
|
||||
info.varlist.add('PyObject', '*py_' + pname)
|
||||
info.add_parselist('O', ['&py_' + pname], [pname])
|
||||
info.arglist.append('&' + pname)
|
||||
info.codebefore.append(self.normal % {'name': pname})
|
||||
|
||||
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);')
|
||||
|
||||
class PyObjectArg(ArgType):
|
||||
def write_param(self, ptype, pname, pdflt, pnull, info):
|
||||
info.varlist.add('PyObject', '*' + pname)
|
||||
info.add_parselist('O', ['&' + pname], [pname])
|
||||
info.arglist.append(pname)
|
||||
def write_return(self, ptype, ownsreturn, info):
|
||||
info.varlist.add("PyObject", "*ret")
|
||||
if ownsreturn:
|
||||
info.codeafter.append(' if (ret) {\n'
|
||||
' return ret;\n'
|
||||
' }\n'
|
||||
' Py_INCREF(Py_None);\n'
|
||||
' return Py_None;')
|
||||
else:
|
||||
info.codeafter.append(' if (!ret) ret = Py_None;\n'
|
||||
' Py_INCREF(ret);\n'
|
||||
' return ret;')
|
||||
|
||||
class ArgMatcher:
|
||||
def __init__(self):
|
||||
self.argtypes = {}
|
||||
self.reverse_argtypes = {}
|
||||
self.reverse_rettypes = {}
|
||||
|
||||
def register(self, ptype, handler):
|
||||
self.argtypes[ptype] = handler
|
||||
def register_reverse(self, ptype, handler):
|
||||
self.reverse_argtypes[ptype] = handler
|
||||
def register_reverse_ret(self, ptype, handler):
|
||||
self.reverse_rettypes[ptype] = handler
|
||||
|
||||
def register_enum(self, ptype, typecode):
|
||||
if typecode is None:
|
||||
typecode = "G_TYPE_NONE"
|
||||
self.register(ptype, EnumArg(ptype, typecode))
|
||||
def register_flag(self, ptype, typecode):
|
||||
if typecode is None:
|
||||
typecode = "G_TYPE_NONE"
|
||||
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)
|
||||
if ptype == 'GdkPixmap':
|
||||
# hack to handle GdkBitmap synonym.
|
||||
self.register('GdkBitmap', oa)
|
||||
self.register('GdkBitmap*', oa)
|
||||
def register_boxed(self, ptype, typecode):
|
||||
if self.argtypes.has_key(ptype): return
|
||||
arg = BoxedArg(ptype, typecode)
|
||||
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('const-'+ptype+'*', arg)
|
||||
def register_pointer(self, ptype, typecode):
|
||||
arg = PointerArg(ptype, typecode)
|
||||
self.register(ptype, arg)
|
||||
self.register(ptype+'*', arg)
|
||||
self.register('const-'+ptype+'*', arg)
|
||||
|
||||
def get(self, ptype):
|
||||
try:
|
||||
return self.argtypes[ptype]
|
||||
except KeyError:
|
||||
if ptype[:8] == 'GdkEvent' and ptype[-1] == '*':
|
||||
return self.argtypes['GdkEvent*']
|
||||
raise
|
||||
def _get_reverse_common(self, ptype, registry):
|
||||
props = dict(c_type=ptype)
|
||||
try:
|
||||
return registry[ptype], props
|
||||
except KeyError:
|
||||
try:
|
||||
handler = self.argtypes[ptype]
|
||||
except KeyError:
|
||||
if ptype.startswith('GdkEvent') and ptype.endswith('*'):
|
||||
handler = self.argtypes['GdkEvent*']
|
||||
else:
|
||||
raise
|
||||
if isinstance(handler, ObjectArg):
|
||||
return registry['GObject*'], props
|
||||
elif isinstance(handler, EnumArg):
|
||||
props['typecode'] = handler.typecode
|
||||
props['enumname'] = handler.enumname
|
||||
return registry['GEnum'], props
|
||||
elif isinstance(handler, FlagsArg):
|
||||
props['typecode'] = handler.typecode
|
||||
props['flagname'] = handler.flagname
|
||||
return registry['GFlags'], props
|
||||
elif isinstance(handler, BoxedArg):
|
||||
props['typecode'] = handler.typecode
|
||||
props['typename'] = handler.typename
|
||||
return registry['GBoxed'], props
|
||||
else:
|
||||
raise
|
||||
def get_reverse(self, ptype):
|
||||
return self._get_reverse_common(ptype, self.reverse_argtypes)
|
||||
def get_reverse_ret(self, ptype):
|
||||
return self._get_reverse_common(ptype, self.reverse_rettypes)
|
||||
|
||||
def object_is_a(self, otype, parent):
|
||||
if otype == None: return 0
|
||||
if otype == parent: return 1
|
||||
if not self.argtypes.has_key(otype): return 0
|
||||
return self.object_is_a(self.get(otype).parent, parent)
|
||||
|
||||
matcher = ArgMatcher()
|
||||
|
||||
arg = NoneArg()
|
||||
matcher.register(None, arg)
|
||||
matcher.register('none', arg)
|
||||
|
||||
arg = StringArg()
|
||||
matcher.register('char*', arg)
|
||||
matcher.register('gchar*', arg)
|
||||
matcher.register('const-char*', arg)
|
||||
matcher.register('char-const*', arg)
|
||||
matcher.register('const-gchar*', arg)
|
||||
matcher.register('gchar-const*', arg)
|
||||
matcher.register('string', arg)
|
||||
matcher.register('static_string', arg)
|
||||
|
||||
arg = UCharArg()
|
||||
matcher.register('unsigned-char*', arg)
|
||||
matcher.register('const-guchar*', arg)
|
||||
matcher.register('guchar*', arg)
|
||||
|
||||
arg = CharArg()
|
||||
matcher.register('char', arg)
|
||||
matcher.register('gchar', arg)
|
||||
matcher.register('guchar', arg)
|
||||
|
||||
arg = GUniCharArg()
|
||||
matcher.register('gunichar', arg)
|
||||
|
||||
arg = IntArg()
|
||||
matcher.register('int', arg)
|
||||
matcher.register('gint', arg)
|
||||
matcher.register('short', arg)
|
||||
matcher.register('gshort', arg)
|
||||
matcher.register('gushort', arg)
|
||||
matcher.register('gsize', SizeArg())
|
||||
matcher.register('gssize', SSizeArg())
|
||||
matcher.register('guint8', arg)
|
||||
matcher.register('gint8', arg)
|
||||
matcher.register('guint16', arg)
|
||||
matcher.register('gint16', arg)
|
||||
matcher.register('gint32', arg)
|
||||
matcher.register('GTime', arg)
|
||||
|
||||
arg = LongArg()
|
||||
matcher.register('long', arg)
|
||||
matcher.register('glong', arg)
|
||||
|
||||
arg = UIntArg()
|
||||
matcher.register('guint', arg)
|
||||
|
||||
arg = BoolArg()
|
||||
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)
|
||||
|
||||
arg = ULongArg()
|
||||
matcher.register('gulong', arg)
|
||||
|
||||
arg = Int64Arg()
|
||||
matcher.register('gint64', arg)
|
||||
matcher.register('long-long', arg)
|
||||
|
||||
arg = UInt64Arg()
|
||||
matcher.register('guint64', arg)
|
||||
matcher.register('unsigned-long-long', arg)
|
||||
|
||||
arg = DoubleArg()
|
||||
matcher.register('double', arg)
|
||||
matcher.register('gdouble', arg)
|
||||
matcher.register('float', arg)
|
||||
matcher.register('gfloat', arg)
|
||||
|
||||
arg = FileArg()
|
||||
matcher.register('FILE*', arg)
|
||||
|
||||
# enums, flags, objects
|
||||
|
||||
matcher.register('GdkAtom', AtomArg())
|
||||
|
||||
matcher.register('GType', GTypeArg())
|
||||
matcher.register('GtkType', GTypeArg())
|
||||
|
||||
matcher.register('GError**', GErrorArg())
|
||||
matcher.register('GtkTreePath*', GtkTreePathArg())
|
||||
matcher.register('GdkRectangle*', GdkRectanglePtrArg())
|
||||
matcher.register('GtkAllocation*', GdkRectanglePtrArg())
|
||||
matcher.register('GdkRectangle', GdkRectangleArg())
|
||||
matcher.register('PyObject*', PyObjectArg())
|
||||
|
||||
matcher.register('GdkNativeWindow', ULongArg())
|
||||
|
||||
matcher.register_object('GObject', None, 'G_TYPE_OBJECT')
|
||||
|
||||
del arg
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,532 @@
|
|||
# -*- Mode: Python; py-indent-offset: 4 -*-
|
||||
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):
|
||||
self.ptype = ptype
|
||||
self.pname = pname
|
||||
self.pdflt = pdflt
|
||||
self.pnull = pnull
|
||||
|
||||
def __len__(self): return 4
|
||||
def __getitem__(self, i):
|
||||
return (self.ptype, self.pname, self.pdflt, self.pnull)[i]
|
||||
|
||||
def merge(self, old):
|
||||
if old.pdflt is not None:
|
||||
self.pdflt = old.pdflt
|
||||
if old.pnull is not None:
|
||||
self.pnull = old.pnull
|
||||
|
||||
# Parameter for property based constructors
|
||||
class Property(object):
|
||||
def __init__(self, pname, optional, argname):
|
||||
self.pname = pname
|
||||
self.optional = optional
|
||||
self.argname = argname
|
||||
|
||||
def merge(self, old):
|
||||
if old.optional is not None:
|
||||
self.optional = old.optional
|
||||
if old.argname is not None:
|
||||
self.argname = old.argname
|
||||
|
||||
|
||||
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"
|
||||
def merge(self, old):
|
||||
"""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"
|
||||
|
||||
def guess_return_value_ownership(self):
|
||||
"return 1 if caller owns return value"
|
||||
if getattr(self, 'is_constructor_of', False):
|
||||
self.caller_owns_return = True
|
||||
elif self.ret in ('char*', 'gchar*', 'string'):
|
||||
self.caller_owns_return = True
|
||||
else:
|
||||
self.caller_owns_return = False
|
||||
|
||||
|
||||
class ObjectDef(Definition):
|
||||
def __init__(self, name, *args):
|
||||
self.name = name
|
||||
self.module = None
|
||||
self.parent = None
|
||||
self.c_name = None
|
||||
self.typecode = None
|
||||
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] == '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':
|
||||
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
|
||||
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')
|
||||
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.fields:
|
||||
fp.write(' (fields\n')
|
||||
for (ftype, fname) in self.fields:
|
||||
fp.write(' \'("' + ftype + '" "' + fname + '")\n')
|
||||
fp.write(' )\n')
|
||||
fp.write(')\n\n')
|
||||
|
||||
class InterfaceDef(Definition):
|
||||
def __init__(self, name, *args):
|
||||
self.name = name
|
||||
self.module = None
|
||||
self.c_name = None
|
||||
self.typecode = None
|
||||
self.vtable = None
|
||||
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] == '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')
|
||||
|
||||
class EnumDef(Definition):
|
||||
def __init__(self, name, *args):
|
||||
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':
|
||||
for varg in arg[1:]:
|
||||
self.values.append((varg[0], varg[1]))
|
||||
def merge(self, old):
|
||||
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')
|
||||
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')
|
||||
|
||||
class FlagsDef(EnumDef):
|
||||
def __init__(self, *args):
|
||||
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.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]
|
||||
elif arg[0] == 'copy-func':
|
||||
self.copy = arg[1]
|
||||
elif arg[0] == 'release-func':
|
||||
self.release = 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
|
||||
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')
|
||||
if self.copy:
|
||||
fp.write(' (copy-func "' + self.copy + '")\n')
|
||||
if self.release:
|
||||
fp.write(' (release-func "' + self.release + '")\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')
|
||||
|
||||
class PointerDef(Definition):
|
||||
def __init__(self, name, *args):
|
||||
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':
|
||||
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
|
||||
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')
|
||||
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')
|
||||
|
||||
class MethodDefBase(Definition):
|
||||
def __init__(self, name, *args):
|
||||
dump = 0
|
||||
self.name = name
|
||||
self.ret = None
|
||||
self.caller_owns_return = None
|
||||
self.c_name = None
|
||||
self.typecode = None
|
||||
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':
|
||||
self.of_object = 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':
|
||||
for parg in arg[1:]:
|
||||
ptype = parg[0]
|
||||
pname = parg[1]
|
||||
pdflt = None
|
||||
pnull = 0
|
||||
for farg in parg[2:]:
|
||||
assert isinstance(farg, tuple)
|
||||
if farg[0] == 'default':
|
||||
pdflt = farg[1]
|
||||
elif farg[0] == 'null-ok':
|
||||
pnull = 1
|
||||
self.params.append(Parameter(ptype, pname, pdflt, pnull))
|
||||
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"
|
||||
% (arg[0]))
|
||||
dump = 1
|
||||
if dump:
|
||||
self.write_defs(sys.stderr)
|
||||
|
||||
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.
|
||||
if not parmerge:
|
||||
self.params = 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
|
||||
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.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')
|
||||
if self.params:
|
||||
fp.write(' (parameters\n')
|
||||
for ptype, pname, pdflt, pnull in self.params:
|
||||
fp.write(' \'("' + ptype + '" "' + pname +'"')
|
||||
if pdflt: fp.write(' (default "' + pdflt + '")')
|
||||
if pnull: fp.write(' (null-ok)')
|
||||
fp.write(')\n')
|
||||
fp.write(' )\n')
|
||||
if self.varargs:
|
||||
fp.write(' (varargs #t)\n')
|
||||
fp.write(')\n\n')
|
||||
|
||||
|
||||
class MethodDef(MethodDefBase):
|
||||
def __init__(self, name, *args):
|
||||
MethodDefBase.__init__(self, name, *args)
|
||||
for item in ('c_name', 'of_object'):
|
||||
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')
|
||||
self._write_defs(fp)
|
||||
|
||||
class VirtualDef(MethodDefBase):
|
||||
def write_defs(self, fp=sys.stdout):
|
||||
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.caller_owns_return = None
|
||||
self.c_name = None
|
||||
self.typecode = 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] == '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':
|
||||
for parg in arg[1:]:
|
||||
ptype = parg[0]
|
||||
pname = parg[1]
|
||||
pdflt = None
|
||||
pnull = 0
|
||||
for farg in parg[2:]:
|
||||
if farg[0] == 'default':
|
||||
pdflt = farg[1]
|
||||
elif farg[0] == 'null-ok':
|
||||
pnull = 1
|
||||
self.params.append(Parameter(ptype, pname, pdflt, pnull))
|
||||
elif arg[0] == 'properties':
|
||||
if self.is_constructor_of is None:
|
||||
print >> sys.stderr, "Warning: (properties ...) "\
|
||||
"is only valid for constructors"
|
||||
for prop in arg[1:]:
|
||||
pname = prop[0]
|
||||
optional = False
|
||||
argname = pname
|
||||
for farg in prop[1:]:
|
||||
if farg[0] == 'optional':
|
||||
optional = True
|
||||
elif farg[0] == 'argname':
|
||||
argname = farg[1]
|
||||
self.params.append(Property(pname, optional, argname))
|
||||
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"
|
||||
% (arg[0],))
|
||||
dump = 1
|
||||
if dump:
|
||||
self.write_defs(sys.stderr)
|
||||
|
||||
if self.caller_owns_return is None and self.ret is not None:
|
||||
self.guess_return_value_ownership()
|
||||
for item in ('c_name',):
|
||||
if self.__dict__[item] == None:
|
||||
self.write_defs(sys.stderr)
|
||||
raise RuntimeError, "definition missing required %s" % (item,)
|
||||
|
||||
_method_write_defs = MethodDef.__dict__['write_defs']
|
||||
|
||||
def merge(self, old, parmerge):
|
||||
self.caller_owns_return = old.caller_owns_return
|
||||
self.varargs = old.varargs
|
||||
if not parmerge:
|
||||
self.params = deepcopy(old.params)
|
||||
return
|
||||
# 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:
|
||||
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)
|
||||
else:
|
||||
param.merge(old_param)
|
||||
return param
|
||||
raise RuntimeError, "could not find %s in old_parameters %r" % (
|
||||
param.pname, [p.pname for p in old.params])
|
||||
try:
|
||||
self.params = map(merge_param, self.params)
|
||||
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:
|
||||
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]
|
||||
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')
|
||||
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')
|
||||
if self.params:
|
||||
if isinstance(self.params[0], Parameter):
|
||||
fp.write(' (parameters\n')
|
||||
for ptype, pname, pdflt, pnull in self.params:
|
||||
fp.write(' \'("' + ptype + '" "' + pname +'"')
|
||||
if pdflt: fp.write(' (default "' + pdflt + '")')
|
||||
if pnull: fp.write(' (null-ok)')
|
||||
fp.write(')\n')
|
||||
fp.write(' )\n')
|
||||
elif isinstance(self.params[0], Property):
|
||||
fp.write(' (properties\n')
|
||||
for prop in self.params:
|
||||
fp.write(' \'("' + prop.pname +'"')
|
||||
if prop.optional: fp.write(' (optional)')
|
||||
fp.write(')\n')
|
||||
fp.write(' )\n')
|
||||
else:
|
||||
assert False, "strange parameter list %r" % self.params[0]
|
||||
if self.varargs:
|
||||
fp.write(' (varargs #t)\n')
|
||||
|
||||
fp.write(')\n\n')
|
|
@ -0,0 +1,133 @@
|
|||
# -*- Mode: Python; py-indent-offset: 4 -*-
|
||||
import os, sys
|
||||
import scmexpr
|
||||
from definitions import *
|
||||
|
||||
class IncludeParser(scmexpr.Parser):
|
||||
"""A simple parser that follows include statements automatically"""
|
||||
def include(self, filename):
|
||||
if not os.path.isabs(filename):
|
||||
filename = os.path.join(os.path.dirname(self.filename), filename)
|
||||
|
||||
# set self.filename to the include name, to handle recursive includes
|
||||
oldfile = self.filename
|
||||
self.filename = filename
|
||||
self.startParsing()
|
||||
self.filename = oldfile
|
||||
|
||||
class DefsParser(IncludeParser):
|
||||
def __init__(self, arg, defines={}):
|
||||
IncludeParser.__init__(self, arg)
|
||||
self.objects = []
|
||||
self.interfaces = []
|
||||
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
|
||||
|
||||
def define_object(self, *args):
|
||||
odef = apply(ObjectDef, args)
|
||||
self.objects.append(odef)
|
||||
self.c_name[odef.c_name] = odef
|
||||
def define_interface(self, *args):
|
||||
idef = apply(InterfaceDef, args)
|
||||
self.interfaces.append(idef)
|
||||
self.c_name[idef.c_name] = idef
|
||||
def define_enum(self, *args):
|
||||
edef = apply(EnumDef, args)
|
||||
self.enums.append(edef)
|
||||
self.c_name[edef.c_name] = edef
|
||||
def define_flags(self, *args):
|
||||
fdef = apply(FlagsDef, args)
|
||||
self.enums.append(fdef)
|
||||
self.c_name[fdef.c_name] = fdef
|
||||
def define_boxed(self, *args):
|
||||
bdef = apply(BoxedDef, args)
|
||||
self.boxes.append(bdef)
|
||||
self.c_name[bdef.c_name] = bdef
|
||||
def define_pointer(self, *args):
|
||||
pdef = apply(PointerDef, args)
|
||||
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
|
||||
def define_method(self, *args):
|
||||
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)
|
||||
def merge(self, old, parmerge):
|
||||
for obj in self.objects:
|
||||
if old.c_name.has_key(obj.c_name):
|
||||
obj.merge(old.c_name[obj.c_name])
|
||||
for f in self.functions:
|
||||
if old.c_name.has_key(f.c_name):
|
||||
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):
|
||||
obj.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:
|
||||
obj.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)
|
||||
|
||||
def find_object(self, c_name):
|
||||
for obj in self.objects:
|
||||
if obj.c_name == c_name:
|
||||
return obj
|
||||
else:
|
||||
raise ValueError, 'object not found'
|
||||
|
||||
def find_constructor(self, obj, overrides):
|
||||
for func in self.functions:
|
||||
if isinstance(func, FunctionDef) and \
|
||||
func.is_constructor_of == obj.c_name and \
|
||||
not overrides.is_ignored(func.c_name):
|
||||
return func
|
||||
|
||||
def find_methods(self, obj):
|
||||
objname = obj.c_name
|
||||
return filter(lambda func, on=objname: isinstance(func, MethodDef) and
|
||||
func.of_object == on, self.functions)
|
||||
|
||||
def find_virtuals(self, obj):
|
||||
objname = obj.c_name
|
||||
retval = filter(lambda func, on=objname: isinstance(func, VirtualDef) and
|
||||
func.of_object == on, self.virtuals)
|
||||
return retval
|
||||
|
||||
def find_functions(self):
|
||||
return filter(lambda func: isinstance(func, FunctionDef) and
|
||||
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)
|
||||
|
||||
def ifndef(self, *args):
|
||||
if args[0] not in self.defines:
|
||||
for arg in args[1:]:
|
||||
self.handle(arg)
|
||||
|
|
@ -0,0 +1,751 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- Mode: Python; py-indent-offset: 4 -*-
|
||||
import sys, os, string, re, getopt
|
||||
|
||||
import defsparser
|
||||
import definitions
|
||||
import override
|
||||
import docextract
|
||||
|
||||
class Node:
|
||||
def __init__(self, name, interfaces=[]):
|
||||
self.name = name
|
||||
self.interfaces = interfaces
|
||||
self.subclasses = []
|
||||
def add_child(self, node):
|
||||
self.subclasses.append(node)
|
||||
|
||||
def build_object_tree(parser):
|
||||
# reorder objects so that parent classes come first ...
|
||||
objects = parser.objects[:]
|
||||
pos = 0
|
||||
while pos < len(objects):
|
||||
parent = objects[pos].parent
|
||||
for i in range(pos+1, len(objects)):
|
||||
if objects[i].c_name == parent:
|
||||
objects.insert(i+1, objects[pos])
|
||||
del objects[pos]
|
||||
break
|
||||
else:
|
||||
pos = pos + 1
|
||||
|
||||
root = Node(None)
|
||||
nodes = { None: root }
|
||||
for obj_def in objects:
|
||||
parent_node = nodes[obj_def.parent]
|
||||
node = Node(obj_def.c_name, obj_def.implements)
|
||||
parent_node.add_child(node)
|
||||
nodes[node.name] = node
|
||||
|
||||
if parser.interfaces:
|
||||
interfaces = Node('gobject.GInterface')
|
||||
root.add_child(interfaces)
|
||||
nodes[interfaces.name] = interfaces
|
||||
for obj_def in parser.interfaces:
|
||||
node = Node(obj_def.c_name)
|
||||
interfaces.add_child(node)
|
||||
nodes[node.name] = node
|
||||
|
||||
if parser.boxes:
|
||||
boxed = Node('gobject.GBoxed')
|
||||
root.add_child(boxed)
|
||||
nodes[boxed.name] = boxed
|
||||
for obj_def in parser.boxes:
|
||||
node = Node(obj_def.c_name)
|
||||
boxed.add_child(node)
|
||||
nodes[node.name] = node
|
||||
|
||||
if parser.pointers:
|
||||
pointers = Node('gobject.GPointer')
|
||||
root.add_child(pointers)
|
||||
nodes[pointers.name] = pointers
|
||||
for obj_def in parser.pointers:
|
||||
node = Node(obj_def.c_name)
|
||||
pointers.add_child(node)
|
||||
nodes[node.name] = node
|
||||
|
||||
return root
|
||||
|
||||
class DocWriter:
|
||||
def __init__(self):
|
||||
# parse the defs file
|
||||
self.parser = defsparser.DefsParser(())
|
||||
self.overrides = override.Overrides()
|
||||
self.classmap = {}
|
||||
self.docs = {}
|
||||
|
||||
def add_sourcedirs(self, source_dirs):
|
||||
self.docs = docextract.extract(source_dirs, self.docs)
|
||||
def add_tmpldirs(self, tmpl_dirs):
|
||||
self.docs = docextract.extract_tmpl(tmpl_dirs, self.docs)
|
||||
|
||||
def add_docs(self, defs_file, overrides_file, module_name):
|
||||
'''parse information about a given defs file'''
|
||||
self.parser.filename = defs_file
|
||||
self.parser.startParsing(defs_file)
|
||||
if overrides_file:
|
||||
self.overrides.handle_file(overrides_file)
|
||||
|
||||
for obj in self.parser.objects:
|
||||
if not self.classmap.has_key(obj.c_name):
|
||||
self.classmap[obj.c_name] = '%s.%s' % (module_name, obj.name)
|
||||
for obj in self.parser.interfaces:
|
||||
if not self.classmap.has_key(obj.c_name):
|
||||
self.classmap[obj.c_name] = '%s.%s' % (module_name, obj.name)
|
||||
for obj in self.parser.boxes:
|
||||
if not self.classmap.has_key(obj.c_name):
|
||||
self.classmap[obj.c_name] = '%s.%s' % (module_name, obj.name)
|
||||
for obj in self.parser.pointers:
|
||||
if not self.classmap.has_key(obj.c_name):
|
||||
self.classmap[obj.c_name] = '%s.%s' % (module_name, obj.name)
|
||||
|
||||
def pyname(self, name):
|
||||
return self.classmap.get(name, name)
|
||||
|
||||
def __compare(self, obja, objb):
|
||||
return cmp(self.pyname(obja.c_name), self.pyname(objb.c_name))
|
||||
def output_docs(self, output_prefix):
|
||||
files = []
|
||||
|
||||
# class hierarchy
|
||||
hierarchy = build_object_tree(self.parser)
|
||||
filename = self.create_filename('hierarchy', output_prefix)
|
||||
fp = open(filename, 'w')
|
||||
self.write_full_hierarchy(hierarchy, fp)
|
||||
fp.close()
|
||||
|
||||
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:
|
||||
filename = self.create_filename(obj_def.c_name, output_prefix)
|
||||
fp = open(filename, 'w')
|
||||
if isinstance(obj_def, definitions.ObjectDef):
|
||||
self.output_object_docs(obj_def, fp)
|
||||
elif isinstance(obj_def, definitions.InterfaceDef):
|
||||
self.output_interface_docs(obj_def, fp)
|
||||
elif isinstance(obj_def, definitions.BoxedDef):
|
||||
self.output_boxed_docs(obj_def, fp)
|
||||
elif isinstance(obj_def, definitions.PointerDef):
|
||||
self.output_boxed_docs(obj_def, fp)
|
||||
fp.close()
|
||||
files.append((os.path.basename(filename), obj_def))
|
||||
|
||||
if files:
|
||||
filename = self.create_toc_filename(output_prefix)
|
||||
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_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) ]
|
||||
try:
|
||||
parent = obj_def.parent
|
||||
while parent != None:
|
||||
if parent == 'GObject':
|
||||
ancestry.append(('GObject', []))
|
||||
parent = None
|
||||
else:
|
||||
parent_def = self.parser.find_object(parent)
|
||||
ancestry.append((parent_def.c_name, parent_def.implements))
|
||||
parent = parent_def.parent
|
||||
except ValueError:
|
||||
pass
|
||||
ancestry.reverse()
|
||||
self.write_heading('Ancestry', fp)
|
||||
self.write_hierarchy(obj_def.c_name, ancestry, fp)
|
||||
self.close_section(fp)
|
||||
|
||||
constructor = self.parser.find_constructor(obj_def, self.overrides)
|
||||
if constructor:
|
||||
self.write_heading('Constructor', fp)
|
||||
self.write_constructor(constructor,
|
||||
self.docs.get(constructor.c_name, None),
|
||||
fp)
|
||||
self.close_section(fp)
|
||||
|
||||
methods = self.parser.find_methods(obj_def)
|
||||
methods = filter(lambda meth, self=self:
|
||||
not self.overrides.is_ignored(meth.c_name), methods)
|
||||
if methods:
|
||||
self.write_heading('Methods', fp)
|
||||
for method in methods:
|
||||
self.write_method(method, self.docs.get(method.c_name, None), fp)
|
||||
self.close_section(fp)
|
||||
|
||||
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_heading('Synopsis', fp)
|
||||
self.write_synopsis(int_def, fp)
|
||||
self.close_section(fp)
|
||||
|
||||
methods = self.parser.find_methods(int_def)
|
||||
methods = filter(lambda meth, self=self:
|
||||
not self.overrides.is_ignored(meth.c_name), methods)
|
||||
if methods:
|
||||
self.write_heading('Methods', fp)
|
||||
for method in methods:
|
||||
self.write_method(method, self.docs.get(method.c_name, None), fp)
|
||||
self.close_section(fp)
|
||||
|
||||
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_heading('Synopsis', fp)
|
||||
self.write_synopsis(box_def, fp)
|
||||
self.close_section(fp)
|
||||
|
||||
constructor = self.parser.find_constructor(box_def, self.overrides)
|
||||
if constructor:
|
||||
self.write_heading('Constructor', fp)
|
||||
self.write_constructor(constructor,
|
||||
self.docs.get(constructor.c_name, None),
|
||||
fp)
|
||||
self.close_section(fp)
|
||||
|
||||
methods = self.parser.find_methods(box_def)
|
||||
methods = filter(lambda meth, self=self:
|
||||
not self.overrides.is_ignored(meth.c_name), methods)
|
||||
if methods:
|
||||
self.write_heading('Methods', fp)
|
||||
for method in methods:
|
||||
self.write_method(method, self.docs.get(method.c_name, None), fp)
|
||||
self.close_section(fp)
|
||||
|
||||
self.write_class_footer(box_def.c_name, fp)
|
||||
|
||||
def output_toc(self, files, fp=sys.stdout):
|
||||
fp.write('TOC\n\n')
|
||||
for filename, obj_def in files:
|
||||
fp.write(obj_def.c_name + ' - ' + filename + '\n')
|
||||
|
||||
# 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'
|
||||
def create_toc_filename(self, output_prefix):
|
||||
return self.create_filename(self, 'docs', output_prefix)
|
||||
|
||||
def write_full_hierarchy(self, hierarchy, fp):
|
||||
def handle_node(node, fp, indent=''):
|
||||
for child in node.subclasses:
|
||||
fp.write(indent + node.name)
|
||||
if node.interfaces:
|
||||
fp.write(' (implements ')
|
||||
fp.write(string.join(node.interfaces, ', '))
|
||||
fp.write(')\n')
|
||||
else:
|
||||
fp.write('\n')
|
||||
handle_node(child, fp, indent + ' ')
|
||||
handle_node(hierarchy, fp)
|
||||
|
||||
# these need to handle default args ...
|
||||
def create_constructor_prototype(self, func_def):
|
||||
return func_def.is_constructor_of + '(' + \
|
||||
string.join(map(lambda x: x[1], func_def.params), ', ') + \
|
||||
')'
|
||||
def create_function_prototype(self, func_def):
|
||||
return func_def.name + '(' + \
|
||||
string.join(map(lambda x: x[1], func_def.params), ', ') + \
|
||||
')'
|
||||
def create_method_prototype(self, meth_def):
|
||||
return meth_def.of_object + '.' + \
|
||||
meth_def.name + '(' + \
|
||||
string.join(map(lambda x: x[1], meth_def.params), ', ') + \
|
||||
')'
|
||||
|
||||
def write_class_header(self, obj_name, fp):
|
||||
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):
|
||||
fp.write('\n' + text + '\n' + ('-' * len(text)) + '\n')
|
||||
def close_section(self, fp):
|
||||
pass
|
||||
def write_synopsis(self, obj_def, fp):
|
||||
fp.write('class %s' % obj_def.c_name)
|
||||
if isinstance(obj_def, definitions.ObjectDef):
|
||||
bases = []
|
||||
if obj_def.parent: bases.append(obj_def.parent)
|
||||
bases = bases = obj_def.implements
|
||||
if bases:
|
||||
fp.write('(%s)' % string.join(bases, ', '))
|
||||
fp.write(':\n')
|
||||
|
||||
constructor = self.parser.find_constructor(obj_def, self.overrides)
|
||||
if constructor:
|
||||
prototype = self.create_constructor_prototype(constructor)
|
||||
fp.write(' def %s\n' % prototype)
|
||||
methods = self.parser.find_methods(obj_def)
|
||||
methods = filter(lambda meth, self=self:
|
||||
not self.overrides.is_ignored(meth.c_name), methods)
|
||||
for meth in methods:
|
||||
prototype = self.create_method_prototype(meth)
|
||||
fp.write(' def %s\n' % prototype)
|
||||
|
||||
def write_hierarchy(self, obj_name, ancestry, fp):
|
||||
indent = ''
|
||||
for name, interfaces in ancestry:
|
||||
fp.write(indent + '+-- ' + name)
|
||||
if interfaces:
|
||||
fp.write(' (implements ')
|
||||
fp.write(string.join(interfaces, ', '))
|
||||
fp.write(')\n')
|
||||
else:
|
||||
fp.write('\n')
|
||||
indent = indent + ' '
|
||||
fp.write('\n')
|
||||
def write_constructor(self, func_def, func_doc, fp):
|
||||
prototype = self.create_constructor_prototype(func_def)
|
||||
fp.write(prototype + '\n\n')
|
||||
for type, name, dflt, null in func_def.params:
|
||||
if func_doc:
|
||||
descr = func_doc.get_param_description(name)
|
||||
else:
|
||||
descr = 'a ' + type
|
||||
fp.write(' ' + name + ': ' + descr + '\n')
|
||||
if func_def.ret and func_def.ret != 'none':
|
||||
if func_doc and func_doc.ret:
|
||||
descr = func_doc.ret
|
||||
else:
|
||||
descr = 'a ' + func_def.ret
|
||||
fp.write(' Returns: ' + descr + '\n')
|
||||
if func_doc and func_doc.description:
|
||||
fp.write(func_doc.description)
|
||||
fp.write('\n\n\n')
|
||||
def write_method(self, meth_def, func_doc, fp):
|
||||
prototype = self.create_method_prototype(meth_def)
|
||||
fp.write(prototype + '\n\n')
|
||||
for type, name, dflt, null in meth_def.params:
|
||||
if func_doc:
|
||||
descr = func_doc.get_param_description(name)
|
||||
else:
|
||||
descr = 'a ' + type
|
||||
fp.write(' ' + name + ': ' + descr + '\n')
|
||||
if meth_def.ret and meth_def.ret != 'none':
|
||||
if func_doc and func_doc.ret:
|
||||
descr = func_doc.ret
|
||||
else:
|
||||
descr = 'a ' + meth_def.ret
|
||||
fp.write(' Returns: ' + descr + '\n')
|
||||
if func_doc and func_doc.description:
|
||||
fp.write('\n')
|
||||
fp.write(func_doc.description)
|
||||
fp.write('\n\n')
|
||||
|
||||
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'''
|
||||
stem = output_prefix + '-' + string.lower(obj_name)
|
||||
if self.use_xml:
|
||||
return stem + '.xml'
|
||||
else:
|
||||
return stem + '.sgml'
|
||||
def create_toc_filename(self, output_prefix):
|
||||
if self.use_xml:
|
||||
return self.create_filename('classes', output_prefix)
|
||||
else:
|
||||
return self.create_filename('docs', output_prefix)
|
||||
|
||||
# make string -> reference translation func
|
||||
__transtable = [ '-' ] * 256
|
||||
for digit in '0123456789':
|
||||
__transtable[ord(digit)] = digit
|
||||
for letter in 'abcdefghijklmnopqrstuvwxyz':
|
||||
__transtable[ord(letter)] = letter
|
||||
__transtable[ord(string.upper(letter))] = letter
|
||||
__transtable = string.join(__transtable, '')
|
||||
|
||||
def make_class_ref(self, obj_name):
|
||||
return 'class-' + string.translate(obj_name, self.__transtable)
|
||||
def make_method_ref(self, meth_def):
|
||||
return 'method-' + string.translate(meth_def.of_object,
|
||||
self.__transtable) + \
|
||||
'--' + string.translate(meth_def.name, self.__transtable)
|
||||
|
||||
__function_pat = re.compile(r'(\w+)\s*\(\)')
|
||||
def __format_function(self, match):
|
||||
info = self.parser.c_name.get(match.group(1), None)
|
||||
if info:
|
||||
if isinstance(info, defsparser.FunctionDef):
|
||||
if info.is_constructor_of is not None:
|
||||
# should have a link here
|
||||
return '<function>%s()</function>' % \
|
||||
self.pyname(info.is_constructor_of)
|
||||
else:
|
||||
return '<function>' + info.name + '()</function>'
|
||||
if isinstance(info, defsparser.MethodDef):
|
||||
return '<link linkend="' + self.make_method_ref(info) + \
|
||||
'"><function>' + self.pyname(info.of_object) + '.' + \
|
||||
info.name + '()</function></link>'
|
||||
# fall through through
|
||||
return '<function>' + match.group(1) + '()</function>'
|
||||
__parameter_pat = re.compile(r'\@(\w+)')
|
||||
def __format_param(self, match):
|
||||
return '<parameter>' + match.group(1) + '</parameter>'
|
||||
__constant_pat = re.compile(r'\%(-?\w+)')
|
||||
def __format_const(self, match):
|
||||
return '<literal>' + match.group(1) + '</literal>'
|
||||
__symbol_pat = re.compile(r'#([\w-]+)')
|
||||
def __format_symbol(self, match):
|
||||
info = self.parser.c_name.get(match.group(1), None)
|
||||
if info:
|
||||
if isinstance(info, defsparser.FunctionDef):
|
||||
if info.is_constructor_of is not None:
|
||||
# should have a link here
|
||||
return '<methodname>' + self.pyname(info.is_constructor_of) + \
|
||||
'</methodname>'
|
||||
else:
|
||||
return '<function>' + info.name + '</function>'
|
||||
if isinstance(info, defsparser.MethodDef):
|
||||
return '<link linkend="' + self.make_method_ref(info) + \
|
||||
'"><methodname>' + self.pyname(info.of_object) + '.' + \
|
||||
info.name + '</methodname></link>'
|
||||
if isinstance(info, defsparser.ObjectDef) or \
|
||||
isinstance(info, defsparser.InterfaceDef) or \
|
||||
isinstance(info, defsparser.BoxedDef) or \
|
||||
isinstance(info, defsparser.PointerDef):
|
||||
return '<link linkend="' + self.make_class_ref(info.c_name) + \
|
||||
'"><classname>' + self.pyname(info.c_name) + \
|
||||
'</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)
|
||||
text = self.__parameter_pat.sub(self.__format_param, text)
|
||||
text = self.__constant_pat.sub(self.__format_const, text)
|
||||
text = self.__symbol_pat.sub(self.__format_symbol, text)
|
||||
|
||||
# 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]) == '':
|
||||
lines[index] = '</para>\n<para>'
|
||||
continue
|
||||
lines.insert(0, '<para>')
|
||||
lines.append('</para>')
|
||||
return string.join(lines, '\n')
|
||||
|
||||
# write out hierarchy
|
||||
def write_full_hierarchy(self, hierarchy, fp):
|
||||
def handle_node(node, fp, indent=''):
|
||||
if node.name:
|
||||
fp.write('%s<link linkend="%s">%s</link>' %
|
||||
(indent, self.make_class_ref(node.name),
|
||||
self.pyname(node.name)))
|
||||
if node.interfaces:
|
||||
fp.write(' (implements ')
|
||||
for i in range(len(node.interfaces)):
|
||||
fp.write('<link linkend="%s">%s</link>' %
|
||||
(self.make_class_ref(node.interfaces[i]),
|
||||
self.pyname(node.interfaces[i])))
|
||||
if i != len(node.interfaces) - 1:
|
||||
fp.write(', ')
|
||||
fp.write(')\n')
|
||||
else:
|
||||
fp.write('\n')
|
||||
|
||||
indent = indent + ' '
|
||||
node.subclasses.sort(lambda a,b:
|
||||
cmp(self.pyname(a.name), self.pyname(b.name)))
|
||||
for child in node.subclasses:
|
||||
handle_node(child, fp, indent)
|
||||
if self.use_xml:
|
||||
fp.write('<?xml version="1.0" standalone="no"?>\n')
|
||||
fp.write('<!DOCTYPE synopsis PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"\n')
|
||||
fp.write(' "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd">\n')
|
||||
fp.write('<synopsis>')
|
||||
handle_node(hierarchy, fp)
|
||||
fp.write('</synopsis>\n')
|
||||
|
||||
# these need to handle default args ...
|
||||
def create_constructor_prototype(self, func_def):
|
||||
sgml = [ '<constructorsynopsis language="python">\n']
|
||||
sgml.append(' <methodname>__init__</methodname>\n')
|
||||
for type, name, dflt, null in func_def.params:
|
||||
sgml.append(' <methodparam><parameter>')
|
||||
sgml.append(name)
|
||||
sgml.append('</parameter>')
|
||||
if dflt:
|
||||
sgml.append('<initializer>')
|
||||
sgml.append(dflt)
|
||||
sgml.append('</initializer>')
|
||||
sgml.append('</methodparam>\n')
|
||||
if not func_def.params:
|
||||
sgml.append(' <methodparam></methodparam>')
|
||||
sgml.append(' </constructorsynopsis>')
|
||||
return string.join(sgml, '')
|
||||
def create_function_prototype(self, func_def):
|
||||
sgml = [ '<funcsynopsis language="python">\n <funcprototype>\n']
|
||||
sgml.append(' <funcdef><function>')
|
||||
sgml.append(func_def.name)
|
||||
sgml.append('</function></funcdef>\n')
|
||||
for type, name, dflt, null in func_def.params:
|
||||
sgml.append(' <paramdef><parameter>')
|
||||
sgml.append(name)
|
||||
sgml.append('</parameter>')
|
||||
if dflt:
|
||||
sgml.append('<initializer>')
|
||||
sgml.append(dflt)
|
||||
sgml.append('</initializer>')
|
||||
sgml.append('</paramdef>\n')
|
||||
if not func_def.params:
|
||||
sgml.append(' <paramdef></paramdef')
|
||||
sgml.append(' </funcprototype>\n </funcsynopsis>')
|
||||
return string.join(sgml, '')
|
||||
def create_method_prototype(self, meth_def, addlink=0):
|
||||
sgml = [ '<methodsynopsis language="python">\n']
|
||||
sgml.append(' <methodname>')
|
||||
if addlink:
|
||||
sgml.append('<link linkend="%s">' % self.make_method_ref(meth_def))
|
||||
sgml.append(self.pyname(meth_def.name))
|
||||
if addlink:
|
||||
sgml.append('</link>')
|
||||
sgml.append('</methodname>\n')
|
||||
for type, name, dflt, null in meth_def.params:
|
||||
sgml.append(' <methodparam><parameter>')
|
||||
sgml.append(name)
|
||||
sgml.append('</parameter>')
|
||||
if dflt:
|
||||
sgml.append('<initializer>')
|
||||
sgml.append(dflt)
|
||||
sgml.append('</initializer>')
|
||||
sgml.append('</methodparam>\n')
|
||||
if not meth_def.params:
|
||||
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')
|
||||
fp.write('<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"\n')
|
||||
fp.write(' "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd">\n')
|
||||
fp.write('<refentry id="' + self.make_class_ref(obj_name) + '">\n')
|
||||
fp.write(' <refmeta>\n')
|
||||
fp.write(' <refentrytitle>%s</refentrytitle>\n'
|
||||
% self.pyname(obj_name))
|
||||
fp.write(' <manvolnum>3</manvolnum>\n')
|
||||
fp.write(' <refmiscinfo>PyGTK Docs</refmiscinfo>\n')
|
||||
fp.write(' </refmeta>\n\n')
|
||||
fp.write(' <refnamediv>\n')
|
||||
fp.write(' <refname>%s</refname><refpurpose></refpurpose>\n'
|
||||
% self.pyname(obj_name))
|
||||
fp.write(' </refnamediv>\n\n')
|
||||
def write_class_footer(self, obj_name, fp):
|
||||
fp.write('</refentry>\n')
|
||||
def write_heading(self, text, fp):
|
||||
fp.write(' <refsect1>\n')
|
||||
fp.write(' <title>' + text + '</title>\n\n')
|
||||
def close_section(self, fp):
|
||||
fp.write(' </refsect1>\n')
|
||||
|
||||
def write_synopsis(self, obj_def, fp):
|
||||
fp.write('<classsynopsis language="python">\n')
|
||||
fp.write(' <ooclass><classname>%s</classname></ooclass>\n'
|
||||
% self.pyname(obj_def.c_name))
|
||||
if isinstance(obj_def, definitions.ObjectDef):
|
||||
if obj_def.parent:
|
||||
fp.write(' <ooclass><classname><link linkend="%s">%s'
|
||||
'</link></classname></ooclass>\n'
|
||||
% (self.make_class_ref(obj_def.parent),
|
||||
self.pyname(obj_def.parent)))
|
||||
for base in obj_def.implements:
|
||||
fp.write(' <ooclass><classname><link linkend="%s">%s'
|
||||
'</link></classname></ooclass>\n'
|
||||
% (self.make_class_ref(base), self.pyname(base)))
|
||||
elif isinstance(obj_def, definitions.InterfaceDef):
|
||||
fp.write(' <ooclass><classname>gobject.GInterface'
|
||||
'</classname></ooclass>\n')
|
||||
elif isinstance(obj_def, definitions.BoxedDef):
|
||||
fp.write(' <ooclass><classname>gobject.GBoxed'
|
||||
'</classname></ooclass>\n')
|
||||
elif isinstance(obj_def, definitions.PointerDef):
|
||||
fp.write(' <ooclass><classname>gobject.GPointer'
|
||||
'</classname></ooclass>\n')
|
||||
|
||||
constructor = self.parser.find_constructor(obj_def, self.overrides)
|
||||
if constructor:
|
||||
fp.write('%s\n' % self.create_constructor_prototype(constructor))
|
||||
methods = self.parser.find_methods(obj_def)
|
||||
methods = filter(lambda meth, self=self:
|
||||
not self.overrides.is_ignored(meth.c_name), methods)
|
||||
for meth in methods:
|
||||
fp.write('%s\n' % self.create_method_prototype(meth, addlink=1))
|
||||
fp.write('</classsynopsis>\n\n')
|
||||
|
||||
def write_hierarchy(self, obj_name, ancestry, fp):
|
||||
fp.write('<synopsis>')
|
||||
indent = ''
|
||||
for name, interfaces in ancestry:
|
||||
fp.write(indent + '+-- <link linkend="' +
|
||||
self.make_class_ref(name) + '">'+ self.pyname(name) + '</link>')
|
||||
if interfaces:
|
||||
fp.write(' (implements ')
|
||||
for i in range(len(interfaces)):
|
||||
fp.write('<link linkend="%s">%s</link>' %
|
||||
(self.make_class_ref(interfaces[i]),
|
||||
self.pyname(interfaces[i])))
|
||||
if i != len(interfaces) - 1:
|
||||
fp.write(', ')
|
||||
fp.write(')\n')
|
||||
else:
|
||||
fp.write('\n')
|
||||
indent = indent + ' '
|
||||
fp.write('</synopsis>\n\n')
|
||||
|
||||
def write_params(self, params, ret, func_doc, fp):
|
||||
if not params and (not ret or ret == 'none'):
|
||||
return
|
||||
fp.write(' <variablelist>\n')
|
||||
for type, name, dflt, null in params:
|
||||
if func_doc:
|
||||
descr = string.strip(func_doc.get_param_description(name))
|
||||
else:
|
||||
descr = 'a ' + type
|
||||
fp.write(' <varlistentry>\n')
|
||||
fp.write(' <term><parameter>%s</parameter> :</term>\n' % name)
|
||||
fp.write(' <listitem><simpara>%s</simpara></listitem>\n' %
|
||||
self.reformat_text(descr, singleline=1))
|
||||
fp.write(' </varlistentry>\n')
|
||||
if ret and ret != 'none':
|
||||
if func_doc and func_doc.ret:
|
||||
descr = string.strip(func_doc.ret)
|
||||
else:
|
||||
descr = 'a ' + ret
|
||||
fp.write(' <varlistentry>\n')
|
||||
fp.write(' <term><emphasis>Returns</emphasis> :</term>\n')
|
||||
fp.write(' <listitem><simpara>%s</simpara></listitem>\n' %
|
||||
self.reformat_text(descr, singleline=1))
|
||||
fp.write(' </varlistentry>\n')
|
||||
fp.write(' </variablelist>\n')
|
||||
|
||||
def write_constructor(self, func_def, func_doc, fp):
|
||||
prototype = self.create_constructor_prototype(func_def)
|
||||
fp.write('<programlisting>%s</programlisting>\n' % prototype)
|
||||
self.write_params(func_def.params, func_def.ret, func_doc, fp)
|
||||
|
||||
if func_doc and func_doc.description:
|
||||
fp.write(self.reformat_text(func_doc.description))
|
||||
fp.write('\n\n\n')
|
||||
|
||||
def write_method(self, meth_def, func_doc, fp):
|
||||
fp.write(' <refsect2 id="' + self.make_method_ref(meth_def) + '">\n')
|
||||
fp.write(' <title>' + self.pyname(meth_def.of_object) + '.' +
|
||||
meth_def.name + '</title>\n\n')
|
||||
prototype = self.create_method_prototype(meth_def)
|
||||
fp.write('<programlisting>%s</programlisting>\n' % prototype)
|
||||
self.write_params(meth_def.params, meth_def.ret, func_doc, fp)
|
||||
if func_doc and func_doc.description:
|
||||
fp.write(self.reformat_text(func_doc.description))
|
||||
fp.write(' </refsect2>\n\n\n')
|
||||
|
||||
def output_toc(self, files, fp=sys.stdout):
|
||||
if self.use_xml:
|
||||
fp.write('<?xml version="1.0" standalone="no"?>\n')
|
||||
fp.write('<!DOCTYPE reference PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"\n')
|
||||
fp.write(' "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd">\n')
|
||||
#for filename, obj_def in files:
|
||||
# fp.write(' <!ENTITY ' + string.translate(obj_def.c_name,
|
||||
# self.__transtable) +
|
||||
# ' SYSTEM "' + filename + '" >\n')
|
||||
#fp.write(']>\n\n')
|
||||
|
||||
#fp.write('<reference id="class-reference">\n')
|
||||
#fp.write(' <title>Class Documentation</title>\n')
|
||||
#for filename, obj_def in files:
|
||||
# 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:
|
||||
fp.write(' <xi:include href="%s"/>\n' % filename)
|
||||
fp.write('</reference>\n')
|
||||
else:
|
||||
fp.write('<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook V4.1.2//EN" [\n')
|
||||
for filename, obj_def in files:
|
||||
fp.write(' <!ENTITY ' + string.translate(obj_def.c_name,
|
||||
self.__transtable) +
|
||||
' SYSTEM "' + filename + '" >\n')
|
||||
fp.write(']>\n\n')
|
||||
|
||||
fp.write('<book id="index">\n\n')
|
||||
fp.write(' <bookinfo>\n')
|
||||
fp.write(' <title>PyGTK Docs</title>\n')
|
||||
fp.write(' <authorgroup>\n')
|
||||
fp.write(' <author>\n')
|
||||
fp.write(' <firstname>James</firstname>\n')
|
||||
fp.write(' <surname>Henstridge</surname>\n')
|
||||
fp.write(' </author>\n')
|
||||
fp.write(' </authorgroup>\n')
|
||||
fp.write(' </bookinfo>\n\n')
|
||||
|
||||
fp.write(' <chapter id="class-hierarchy">\n')
|
||||
fp.write(' <title>Class Hierarchy</title>\n')
|
||||
fp.write(' <para>Not done yet</para>\n')
|
||||
fp.write(' </chapter>\n\n')
|
||||
|
||||
fp.write(' <reference id="class-reference">\n')
|
||||
fp.write(' <title>Class Documentation</title>\n')
|
||||
for filename, obj_def in files:
|
||||
fp.write('&' + string.translate(obj_def.c_name,
|
||||
self.__transtable) + ';\n')
|
||||
|
||||
fp.write(' </reference>\n')
|
||||
fp.write('</book>\n')
|
||||
|
||||
if __name__ == '__main__':
|
||||
try:
|
||||
opts, args = getopt.getopt(sys.argv[1:], "d:s:o:",
|
||||
["defs-file=", "override=", "source-dir=",
|
||||
"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.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 ('--override',):
|
||||
overrides_file = 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.exit(1)
|
||||
|
||||
d = DocbookDocWriter()
|
||||
d.add_sourcedirs(source_dirs)
|
||||
d.add_docs(defs_file, overrides_file, 'gtk')
|
||||
d.output_docs(output_prefix)
|
|
@ -0,0 +1,25 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- Mode: Python; py-indent-offset: 4 -*-
|
||||
|
||||
import sys
|
||||
import defsparser
|
||||
from optparse import OptionParser
|
||||
|
||||
parser = 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)
|
||||
(options, args) = parser.parse_args()
|
||||
|
||||
if len(args) != 2:
|
||||
parser.error("wrong number of arguments")
|
||||
|
||||
newp = defsparser.DefsParser(args[0])
|
||||
oldp = defsparser.DefsParser(args[1])
|
||||
|
||||
newp.startParsing()
|
||||
oldp.startParsing()
|
||||
|
||||
newp.merge(oldp, options.parmerge)
|
||||
|
||||
newp.write_defs()
|
|
@ -0,0 +1,89 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- Mode: Python; py-indent-offset: 4 -*-
|
||||
|
||||
import sys, os, getopt
|
||||
|
||||
module_init_template = \
|
||||
'/* -*- Mode: C; c-basic-offset: 4 -*- */\n' + \
|
||||
'#ifdef HAVE_CONFIG_H\n' + \
|
||||
'# include "config.h"\n' + \
|
||||
'#endif\n' + \
|
||||
'#include <Python.h>\n' + \
|
||||
'#include <pygtk.h>\n' + \
|
||||
'\n' + \
|
||||
'/* include any extra headers needed here */\n' + \
|
||||
'\n' + \
|
||||
'void %(prefix)s_register_classes(PyObject *d);\n' + \
|
||||
'extern PyMethodDef %(prefix)s_functions[];\n' + \
|
||||
'\n' + \
|
||||
'DL_EXPORT(void)\n' + \
|
||||
'init%(module)s(void)\n' + \
|
||||
'{\n' + \
|
||||
' PyObject *m, *d;\n' + \
|
||||
'\n' + \
|
||||
' /* perform any initialisation required by the library here */\n' + \
|
||||
'\n' + \
|
||||
' m = Py_InitModule("%(module)s", %(prefix)s_functions);\n' + \
|
||||
' d = PyModule_GetDict(m);\n' + \
|
||||
'\n' + \
|
||||
' init_pygtk();\n' + \
|
||||
'\n' + \
|
||||
' %(prefix)s_register_classes(d);\n' + \
|
||||
'\n' + \
|
||||
' /* add anything else to the module dictionary (such as constants) */\n' +\
|
||||
'\n' + \
|
||||
' if (PyErr_Occurred())\n' + \
|
||||
' Py_FatalError("could not initialise module %(module)s");\n' + \
|
||||
'}\n'
|
||||
|
||||
override_template = \
|
||||
'/* -*- Mode: C; c-basic-offset: 4 -*- */\n' + \
|
||||
'%%%%\n' + \
|
||||
'headers\n' + \
|
||||
'/* include any required headers here */\n' + \
|
||||
'%%%%\n' + \
|
||||
'init\n' + \
|
||||
' /* include any code here that needs to be executed before the\n' + \
|
||||
' * extension classes get initialised */\n' + \
|
||||
'%%%%\n' + \
|
||||
'\n' + \
|
||||
'/* you should add appropriate ignore, ignore-glob and\n' + \
|
||||
' * override sections here */\n'
|
||||
|
||||
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
|
||||
return open(file, 'w')
|
||||
|
||||
def write_skels(fileprefix, prefix, module):
|
||||
fp = open_with_backup(fileprefix+'module.c')
|
||||
fp.write(module_init_template % { 'prefix': prefix, 'module': module })
|
||||
fp.close()
|
||||
fp = open_with_backup(fileprefix+'.override')
|
||||
fp.write(override_template % { 'prefix': prefix, 'module': module })
|
||||
fp.close()
|
||||
|
||||
if __name__ == '__main__':
|
||||
opts, args = getopt.getopt(sys.argv[1:], 'f:p:m:h',
|
||||
['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 not fileprefix or not prefix or not module:
|
||||
print 'usage: mkskel.py -f fileprefix -p prefix -m module'
|
||||
sys.exit(1)
|
||||
write_skels(fileprefix, prefix, module)
|
|
@ -0,0 +1,223 @@
|
|||
# -*- Mode: Python; py-indent-offset: 4 -*-
|
||||
|
||||
# this file contains code for loading up an override file. The override file
|
||||
# provides implementations of functions where the code generator could not
|
||||
# do its job correctly.
|
||||
|
||||
import fnmatch
|
||||
import os
|
||||
import re
|
||||
import string
|
||||
import sys
|
||||
|
||||
def class2cname(klass, method):
|
||||
c_name = ''
|
||||
for c in klass:
|
||||
if c.isupper():
|
||||
c_name += '_' + c.lower()
|
||||
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):
|
||||
self.modulename = None
|
||||
self.ignores = {}
|
||||
self.glob_ignores = []
|
||||
self.overrides = {}
|
||||
self.overridden = {}
|
||||
self.kwargs = {}
|
||||
self.noargs = {}
|
||||
self.startlines = {}
|
||||
self.override_attrs = {}
|
||||
self.override_slots = {}
|
||||
self.headers = ''
|
||||
self.init = ''
|
||||
self.imports = []
|
||||
self.defines = {}
|
||||
self.functions = {}
|
||||
if filename:
|
||||
self.handle_file(filename)
|
||||
|
||||
def handle_file(self, filename):
|
||||
oldpath = os.getcwd()
|
||||
|
||||
fp = open(filename, 'r')
|
||||
dirname = os.path.dirname(os.path.abspath(filename))
|
||||
|
||||
if dirname != oldpath:
|
||||
os.chdir(dirname)
|
||||
|
||||
# read all the components of the file ...
|
||||
bufs = []
|
||||
startline = 1
|
||||
lines = []
|
||||
line = fp.readline()
|
||||
linenum = 1
|
||||
while line:
|
||||
if line == '%%\n' or line == '%%':
|
||||
if lines:
|
||||
bufs.append((string.join(lines, ''), startline))
|
||||
startline = linenum + 1
|
||||
lines = []
|
||||
else:
|
||||
lines.append(line)
|
||||
line = fp.readline()
|
||||
linenum = linenum + 1
|
||||
if lines:
|
||||
bufs.append((string.join(lines, ''), startline))
|
||||
if not bufs: return
|
||||
|
||||
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)
|
||||
command = words[0]
|
||||
if (command == 'ignore' or
|
||||
command == 'ignore-' + sys.platform):
|
||||
"ignore/ignore-platform [functions..]"
|
||||
for func in words[1:]:
|
||||
self.ignores[func] = 1
|
||||
for func in string.split(rest):
|
||||
self.ignores[func] = 1
|
||||
elif (command == 'ignore-glob' or
|
||||
command == 'ignore-glob-' + sys.platform):
|
||||
"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)
|
||||
elif command == 'override':
|
||||
"override function/method [kwargs,noargs]"
|
||||
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.startlines[func] = (startline + 1, filename)
|
||||
elif command == 'override-attr':
|
||||
"override-slot Class.attr"
|
||||
attr = words[1]
|
||||
self.override_attrs[attr] = rest
|
||||
self.startlines[attr] = (startline + 1, filename)
|
||||
elif command == 'override-slot':
|
||||
"override-slot Class.slot"
|
||||
slot = words[1]
|
||||
self.override_slots[slot] = rest
|
||||
self.startlines[slot] = (startline + 1, filename)
|
||||
elif command == 'headers':
|
||||
"headers"
|
||||
self.headers = '%s\n#line %d "%s"\n%s' % \
|
||||
(self.headers, startline + 1, filename, rest)
|
||||
elif command == 'init':
|
||||
"init"
|
||||
self.init = '%s\n#line %d "%s"\n%s' % \
|
||||
(self.init, startline + 1, filename, rest)
|
||||
elif command == 'modulename':
|
||||
"modulename name"
|
||||
self.modulename = words[1]
|
||||
elif command == 'include':
|
||||
"include filename"
|
||||
for filename in words[1:]:
|
||||
self.handle_file(filename)
|
||||
for filename in string.split(rest):
|
||||
self.handle_file(filename)
|
||||
elif command == 'import':
|
||||
"import module1 [\n module2, \n module3 ...]"
|
||||
for line in string.split(buffer, '\n'):
|
||||
match = import_pat.match(line)
|
||||
if match:
|
||||
self.imports.append(match.groups())
|
||||
elif command == 'define':
|
||||
"define funcname [kwargs,noargs]"
|
||||
"define Class.method [kwargs,noargs]"
|
||||
func = words[1]
|
||||
klass = None
|
||||
if func.find('.') != -1:
|
||||
klass, func = func.split('.', 1)
|
||||
|
||||
if not self.defines.has_key(klass):
|
||||
self.defines[klass] = {}
|
||||
self.defines[klass][func] = rest
|
||||
else:
|
||||
self.functions[func] = rest
|
||||
|
||||
if 'kwargs' in words[1:]:
|
||||
self.kwargs[func] = 1
|
||||
elif 'noargs' in words[1:]:
|
||||
self.noargs[func] = 1
|
||||
|
||||
self.startlines[func] = (startline + 1, filename)
|
||||
|
||||
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
|
||||
|
||||
def is_overriden(self, 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]
|
||||
|
||||
def define(self, klass, name):
|
||||
self.overridden[class2cname(klass, name)] = 1
|
||||
return self.defines[klass][name]
|
||||
|
||||
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)
|
||||
|
||||
def wants_noargs(self, name):
|
||||
return self.noargs.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_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
|
|
@ -0,0 +1,667 @@
|
|||
### -*- python -*-
|
||||
### Code to generate "Reverse Wrappers", i.e. C->Python wrappers
|
||||
### (C) 2004 Gustavo Carneiro <gjc@gnome.org>
|
||||
import argtypes
|
||||
|
||||
def join_ctype_name(ctype, name):
|
||||
'''Joins a C type and a variable name into a single string'''
|
||||
if ctype[-1] != '*':
|
||||
return " ".join((ctype, name))
|
||||
else:
|
||||
return "".join((ctype, name))
|
||||
|
||||
|
||||
class CodeSink(object):
|
||||
def __init__(self):
|
||||
self.indent_level = 0 # current indent level
|
||||
self.indent_stack = [] # previous indent levels
|
||||
|
||||
def _format_code(self, code):
|
||||
assert isinstance(code, str)
|
||||
l = []
|
||||
for line in code.split('\n'):
|
||||
l.append(' '*self.indent_level + line)
|
||||
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'''
|
||||
self.indent_stack.append(self.indent_level)
|
||||
self.indent_level += level
|
||||
|
||||
def unindent(self):
|
||||
'''Revert indentation level to the value before last indent() call'''
|
||||
self.indent_level = self.indent_stack.pop()
|
||||
|
||||
|
||||
class FileCodeSink(CodeSink):
|
||||
def __init__(self, fp):
|
||||
CodeSink.__init__(self)
|
||||
assert isinstance(fp, file)
|
||||
self.fp = fp
|
||||
|
||||
def writeln(self, line=''):
|
||||
self.fp.write(self._format_code(line))
|
||||
|
||||
class MemoryCodeSink(CodeSink):
|
||||
def __init__(self):
|
||||
CodeSink.__init__(self)
|
||||
self.lines = []
|
||||
|
||||
def writeln(self, line=''):
|
||||
self.lines.append(self._format_code(line))
|
||||
|
||||
def flush_to(self, sink):
|
||||
assert isinstance(sink, CodeSink)
|
||||
for line in self.lines:
|
||||
sink.writeln(line.rstrip())
|
||||
self.lines = []
|
||||
|
||||
def flush(self):
|
||||
l = []
|
||||
for line in self.lines:
|
||||
l.append(self._format_code(line))
|
||||
self.lines = []
|
||||
return "".join(l)
|
||||
|
||||
class ReverseWrapper(object):
|
||||
'''Object that generates a C->Python wrapper'''
|
||||
def __init__(self, cname, is_static=True):
|
||||
assert isinstance(cname, str)
|
||||
|
||||
self.cname = cname
|
||||
## 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.is_static = is_static
|
||||
|
||||
self.parameters = []
|
||||
self.declarations = MemoryCodeSink()
|
||||
self.body = MemoryCodeSink()
|
||||
self.cleanup_actions = []
|
||||
self.pyargv_items = []
|
||||
self.pyargv_optional_items = []
|
||||
|
||||
def set_call_target(self, called_pyobj, method_name=None):
|
||||
assert called_pyobj is not None
|
||||
assert self.called_pyobj is None
|
||||
self.called_pyobj = called_pyobj
|
||||
self.method_name = method_name
|
||||
|
||||
def set_return_type(self, return_type):
|
||||
assert isinstance(return_type, ReturnType)
|
||||
self.return_type = return_type
|
||||
|
||||
def add_parameter(self, param):
|
||||
assert isinstance(param, Parameter)
|
||||
self.parameters.append(param)
|
||||
|
||||
def add_declaration(self, decl_code):
|
||||
self.declarations.writeln(decl_code)
|
||||
|
||||
def add_pyargv_item(self, variable, optional=False):
|
||||
if optional:
|
||||
self.pyargv_optional_items.append(variable)
|
||||
else:
|
||||
self.pyargv_items.append(variable)
|
||||
|
||||
def write_code(self, code,
|
||||
cleanup=None,
|
||||
failure_expression=None,
|
||||
failure_cleanup=None):
|
||||
'''Add a chunk of code with cleanup and error handling
|
||||
|
||||
This method is to be used by TypeHandlers when generating code
|
||||
|
||||
Keywork arguments:
|
||||
code -- code to add
|
||||
cleanup -- code to cleanup any dynamic resources created by @code
|
||||
(except in case of failure) (default None)
|
||||
failure_expression -- C boolean expression to indicate
|
||||
if anything failed (default None)
|
||||
failure_cleanup -- code to cleanup any dynamic resources
|
||||
created by @code in case of failure (default None)
|
||||
'''
|
||||
if code is not None:
|
||||
self.body.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()
|
||||
if failure_cleanup is not None:
|
||||
self.body.writeln(failure_cleanup)
|
||||
for cleanup_action in self.cleanup_actions:
|
||||
self.body.writeln(cleanup_action)
|
||||
self.return_type.write_error_return()
|
||||
self.body.unindent()
|
||||
self.body.writeln("}")
|
||||
if cleanup is not None:
|
||||
self.cleanup_actions.insert(0, cleanup)
|
||||
|
||||
def generate(self, sink):
|
||||
'''Generate the code into a CodeSink object'''
|
||||
assert isinstance(sink, CodeSink)
|
||||
|
||||
self.add_declaration("PyGILState_STATE __py_state;")
|
||||
self.write_code(code="__py_state = pyg_gil_state_ensure();",
|
||||
cleanup="pyg_gil_state_release(__py_state);")
|
||||
|
||||
for param in self.parameters:
|
||||
param.convert_c2py()
|
||||
|
||||
assert self.called_pyobj is not None,\
|
||||
"Parameters failed to provide a target function or method."
|
||||
|
||||
if self.is_static:
|
||||
sink.writeln('static %s' % self.return_type.get_c_type())
|
||||
else:
|
||||
sink.writeln(self.return_type.get_c_type())
|
||||
c_proto_params = map(Parameter.format_for_c_proto, self.parameters)
|
||||
sink.writeln("%s(%s)\n{" % (self.cname, ", ".join(c_proto_params)))
|
||||
|
||||
self.return_type.write_decl()
|
||||
self.add_declaration("PyObject *py_retval;")
|
||||
|
||||
## Handle number of arguments
|
||||
if self.pyargv_items:
|
||||
self.add_declaration("PyObject *py_args;")
|
||||
py_args = "py_args"
|
||||
if self.pyargv_optional_items:
|
||||
self.add_declaration("int argc = %i;" % len(self.pyargv_items))
|
||||
argc = "argc"
|
||||
for arg in self.pyargv_optional_items:
|
||||
self.body.writeln("if (%s)" % arg)
|
||||
self.body.indent()
|
||||
self.body.writeln("++argc;")
|
||||
self.body.unindent()
|
||||
else:
|
||||
argc = str(len(self.pyargv_items))
|
||||
else:
|
||||
if self.pyargv_optional_items:
|
||||
self.add_declaration("PyObject *py_args;")
|
||||
py_args = "py_args"
|
||||
self.add_declaration("int argc = 0;")
|
||||
argc = "argc"
|
||||
for arg in self.pyargv_optional_items:
|
||||
self.body.writeln("if (%s)" % arg)
|
||||
self.body.indent()
|
||||
self.body.writeln("++argc;")
|
||||
self.body.unindent()
|
||||
else:
|
||||
py_args = "NULL"
|
||||
argc = None
|
||||
|
||||
self.body.writeln()
|
||||
|
||||
if py_args != "NULL":
|
||||
self.write_code("py_args = PyTuple_New(%s);" % argc,
|
||||
cleanup="Py_DECREF(py_args);")
|
||||
pos = 0
|
||||
for arg in self.pyargv_items:
|
||||
try: # try to remove the Py_DECREF cleanup action, if we can
|
||||
self.cleanup_actions.remove("Py_DECREF(%s);" % arg)
|
||||
except ValueError: # otherwise we have to Py_INCREF..
|
||||
self.body.writeln("Py_INCREF(%s);" % arg)
|
||||
self.body.writeln("PyTuple_SET_ITEM(%s, %i, %s);" % (py_args, pos, arg))
|
||||
pos += 1
|
||||
for arg in self.pyargv_optional_items:
|
||||
self.body.writeln("if (%s) {" % arg)
|
||||
self.body.indent()
|
||||
try: # try to remove the Py_DECREF cleanup action, if we can
|
||||
self.cleanup_actions.remove("Py_XDECREF(%s);" % arg)
|
||||
except ValueError: # otherwise we have to Py_INCREF..
|
||||
self.body.writeln("Py_INCREF(%s);" % arg)
|
||||
self.body.writeln("PyTuple_SET_ITEM(%s, %i, %s);" % (py_args, pos, arg))
|
||||
self.body.unindent()
|
||||
self.body.writeln("}")
|
||||
pos += 1
|
||||
|
||||
self.body.writeln()
|
||||
|
||||
# call it
|
||||
if self.method_name is None:
|
||||
self.write_code("py_retval = PyObject_Call(%s, %s);"
|
||||
% (self.called_pyobj, py_args),
|
||||
cleanup="Py_DECREF(py_retval);",
|
||||
failure_expression="!py_retval")
|
||||
else:
|
||||
self.add_declaration("PyObject *py_method;")
|
||||
self.write_code("py_method = PyObject_GetAttrString(%s, \"%s\");"
|
||||
% (self.called_pyobj, self.method_name),
|
||||
cleanup="Py_DECREF(py_method);",
|
||||
failure_expression="!py_method")
|
||||
self.write_code("py_retval = PyObject_CallObject(py_method, %s);"
|
||||
% (py_args,),
|
||||
cleanup="Py_DECREF(py_retval);",
|
||||
failure_expression="!py_retval")
|
||||
|
||||
self.return_type.write_conversion()
|
||||
|
||||
sink.indent()
|
||||
self.declarations.flush_to(sink)
|
||||
sink.writeln()
|
||||
self.body.flush_to(sink)
|
||||
sink.writeln()
|
||||
for cleanup_action in self.cleanup_actions:
|
||||
sink.writeln(cleanup_action)
|
||||
if self.return_type.get_c_type() != 'void':
|
||||
sink.writeln()
|
||||
sink.writeln("return retval;")
|
||||
sink.unindent()
|
||||
sink.writeln("}")
|
||||
|
||||
class TypeHandler(object):
|
||||
def __init__(self, wrapper, **props):
|
||||
assert isinstance(wrapper, ReverseWrapper)
|
||||
self.wrapper = wrapper
|
||||
self.props = props
|
||||
|
||||
class ReturnType(TypeHandler):
|
||||
|
||||
def get_c_type(self):
|
||||
raise NotImplementedError
|
||||
|
||||
def write_decl(self):
|
||||
raise NotImplementedError
|
||||
|
||||
def write_error_return(self):
|
||||
'''Write "return <value>" code in case of error'''
|
||||
raise NotImplementedError
|
||||
|
||||
def write_conversion(self):
|
||||
'''Writes code to convert Python return value in 'py_retval'
|
||||
into C 'retval'. Returns a string with C boolean expression
|
||||
that determines if anything went wrong. '''
|
||||
raise NotImplementedError
|
||||
|
||||
class Parameter(TypeHandler):
|
||||
|
||||
def __init__(self, wrapper, name, **props):
|
||||
TypeHandler.__init__(self, wrapper, **props)
|
||||
self.name = name
|
||||
|
||||
def get_c_type(self):
|
||||
raise NotImplementedError
|
||||
|
||||
def convert_c2py(self):
|
||||
'''Write some code before calling the Python method.'''
|
||||
pass
|
||||
|
||||
def format_for_c_proto(self):
|
||||
return join_ctype_name(self.get_c_type(), self.name)
|
||||
|
||||
|
||||
###---
|
||||
class StringParam(Parameter):
|
||||
|
||||
def get_c_type(self):
|
||||
return self.props.get('c_type', 'char *').replace('const-', 'const ')
|
||||
|
||||
def convert_c2py(self):
|
||||
if self.props.get('optional', False):
|
||||
self.wrapper.add_declaration("PyObject *py_%s = NULL;" % self.name)
|
||||
self.wrapper.write_code(code=("if (%s)\n"
|
||||
" py_%s = PyString_FromString(%s);\n"
|
||||
% (self.name, self.name, self.name)),
|
||||
cleanup=("Py_XDECREF(py_%s);" % self.name))
|
||||
self.wrapper.add_pyargv_item("py_%s" % self.name, optional=True)
|
||||
else:
|
||||
self.wrapper.add_declaration("PyObject *py_%s;" % self.name)
|
||||
self.wrapper.write_code(code=("py_%s = PyString_FromString(%s);" %
|
||||
(self.name, self.name)),
|
||||
cleanup=("Py_DECREF(py_%s);" % self.name),
|
||||
failure_expression=("!py_%s" % self.name))
|
||||
self.wrapper.add_pyargv_item("py_%s" % self.name)
|
||||
|
||||
for ctype in ('char*', 'gchar*', 'const-char*', 'char-const*', 'const-gchar*',
|
||||
'gchar-const*', 'string', 'static_string'):
|
||||
argtypes.matcher.register_reverse(ctype, StringParam)
|
||||
|
||||
|
||||
class StringReturn(ReturnType):
|
||||
|
||||
def get_c_type(self):
|
||||
return "char *"
|
||||
|
||||
def write_decl(self):
|
||||
self.wrapper.add_declaration("char *retval;")
|
||||
|
||||
def write_error_return(self):
|
||||
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));")
|
||||
|
||||
for ctype in ('char*', 'gchar*'):
|
||||
argtypes.matcher.register_reverse(ctype, StringReturn)
|
||||
|
||||
|
||||
|
||||
class VoidReturn(ReturnType):
|
||||
|
||||
def get_c_type(self):
|
||||
return "void"
|
||||
|
||||
def write_decl(self):
|
||||
pass
|
||||
|
||||
def write_error_return(self):
|
||||
self.wrapper.write_code("return;")
|
||||
|
||||
def write_conversion(self):
|
||||
self.wrapper.write_code(
|
||||
code=None,
|
||||
failure_expression="py_retval != Py_None",
|
||||
failure_cleanup='PyErr_SetString(PyExc_TypeError, "retval should be None");')
|
||||
|
||||
argtypes.matcher.register_reverse_ret('void', VoidReturn)
|
||||
argtypes.matcher.register_reverse_ret('none', VoidReturn)
|
||||
|
||||
class GObjectParam(Parameter):
|
||||
|
||||
def get_c_type(self):
|
||||
return self.props.get('c_type', 'GObject *')
|
||||
|
||||
def convert_c2py(self):
|
||||
self.wrapper.add_declaration("PyObject *py_%s = NULL;" % self.name)
|
||||
self.wrapper.write_code(code=("if (%s)\n"
|
||||
" py_%s = pygobject_new((GObject *) %s);\n"
|
||||
"else {\n"
|
||||
" Py_INCREF(Py_None);\n"
|
||||
" py_%s = Py_None;\n"
|
||||
"}"
|
||||
% (self.name, self.name, self.name, self.name)),
|
||||
cleanup=("Py_DECREF(py_%s);" % self.name))
|
||||
self.wrapper.add_pyargv_item("py_%s" % self.name)
|
||||
|
||||
argtypes.matcher.register_reverse('GObject*', GObjectParam)
|
||||
|
||||
class GObjectReturn(ReturnType):
|
||||
|
||||
def get_c_type(self):
|
||||
return self.props.get('c_type', 'GObject *')
|
||||
|
||||
def write_decl(self):
|
||||
self.wrapper.add_declaration("%s retval;" % self.get_c_type())
|
||||
|
||||
def write_error_return(self):
|
||||
self.wrapper.write_code("return NULL;")
|
||||
|
||||
def write_conversion(self):
|
||||
self.wrapper.write_code("retval = (%s) pygobject_get(py_retval);"
|
||||
% self.get_c_type())
|
||||
self.wrapper.write_code("g_object_ref((GObject *) retval);")
|
||||
|
||||
argtypes.matcher.register_reverse_ret('GObject*', GObjectReturn)
|
||||
|
||||
|
||||
|
||||
class IntParam(Parameter):
|
||||
|
||||
def get_c_type(self):
|
||||
return self.props.get('c_type', 'int')
|
||||
|
||||
def convert_c2py(self):
|
||||
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)
|
||||
|
||||
class IntReturn(ReturnType):
|
||||
def get_c_type(self):
|
||||
return self.props.get('c_type', 'int')
|
||||
def write_decl(self):
|
||||
self.wrapper.add_declaration("%s retval;" % self.get_c_type())
|
||||
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);")
|
||||
|
||||
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)
|
||||
|
||||
|
||||
class GEnumReturn(IntReturn):
|
||||
def write_conversion(self):
|
||||
self.wrapper.write_code(
|
||||
code=None,
|
||||
failure_expression=("pyg_enum_get_value(%s, py_retval, (gint *)&retval)" %
|
||||
self.props['typecode']))
|
||||
|
||||
argtypes.matcher.register_reverse_ret("GEnum", GEnumReturn)
|
||||
|
||||
class GEnumParam(IntParam):
|
||||
def convert_c2py(self):
|
||||
self.wrapper.add_declaration("PyObject *py_%s;" % self.name)
|
||||
self.wrapper.write_code(code=("py_%s = pyg_enum_from_gtype(%s, %s);" %
|
||||
(self.name, self.props['typecode'], self.name)),
|
||||
cleanup=("Py_DECREF(py_%s);" % self.name),
|
||||
failure_expression=("!py_%s" % self.name))
|
||||
self.wrapper.add_pyargv_item("py_%s" % self.name)
|
||||
|
||||
argtypes.matcher.register_reverse("GEnum", GEnumParam)
|
||||
|
||||
class GFlagsReturn(IntReturn):
|
||||
def write_conversion(self):
|
||||
self.wrapper.write_code(
|
||||
code=None,
|
||||
failure_expression=("pyg_flags_get_value(%s, py_retval, (gint *)&retval)" %
|
||||
self.props['typecode']))
|
||||
|
||||
argtypes.matcher.register_reverse_ret("GFlags", GFlagsReturn)
|
||||
|
||||
class GFlagsParam(IntParam):
|
||||
def convert_c2py(self):
|
||||
self.wrapper.add_declaration("PyObject *py_%s;" % self.name)
|
||||
self.wrapper.write_code(code=("py_%s = pyg_flags_from_gtype(%s, %s);" %
|
||||
(self.name, self.props['typecode'], self.name)),
|
||||
cleanup=("Py_DECREF(py_%s);" % self.name),
|
||||
failure_expression=("!py_%s" % self.name))
|
||||
self.wrapper.add_pyargv_item("py_%s" % self.name)
|
||||
|
||||
argtypes.matcher.register_reverse("GFlags", GFlagsParam)
|
||||
|
||||
|
||||
class GtkTreePathParam(IntParam):
|
||||
def convert_c2py(self):
|
||||
self.wrapper.add_declaration("PyObject *py_%s;" % self.name)
|
||||
self.wrapper.write_code(code=("py_%s = pygtk_tree_path_to_pyobject(%s);" %
|
||||
(self.name, self.name)),
|
||||
cleanup=("Py_DECREF(py_%s);" % self.name),
|
||||
failure_expression=("!py_%s" % self.name))
|
||||
self.wrapper.add_pyargv_item("py_%s" % self.name)
|
||||
|
||||
argtypes.matcher.register_reverse("GtkTreePath*", GtkTreePathParam)
|
||||
|
||||
|
||||
class BooleanReturn(ReturnType):
|
||||
def get_c_type(self):
|
||||
return "gboolean"
|
||||
def write_decl(self):
|
||||
self.wrapper.add_declaration("gboolean 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;")
|
||||
argtypes.matcher.register_reverse_ret("gboolean", BooleanReturn)
|
||||
|
||||
class BooleanParam(Parameter):
|
||||
def get_c_type(self):
|
||||
return "gboolean"
|
||||
def convert_c2py(self):
|
||||
self.wrapper.add_declaration("PyObject *py_%s;" % self.name)
|
||||
self.wrapper.write_code("py_%s = %s? Py_True : Py_False;"
|
||||
% (self.name, self.name))
|
||||
self.wrapper.add_pyargv_item("py_%s" % self.name)
|
||||
|
||||
argtypes.matcher.register_reverse("gboolean", BooleanParam)
|
||||
|
||||
|
||||
class DoubleParam(Parameter):
|
||||
def get_c_type(self):
|
||||
return self.props.get('c_type', 'gdouble')
|
||||
def convert_c2py(self):
|
||||
self.wrapper.add_declaration("PyObject *py_%s;" % self.name)
|
||||
self.wrapper.write_code(code=("py_%s = PyFloat_FromDouble(%s);" %
|
||||
(self.name, self.name)),
|
||||
cleanup=("Py_DECREF(py_%s);" % self.name))
|
||||
self.wrapper.add_pyargv_item("py_%s" % self.name)
|
||||
|
||||
class DoubleReturn(ReturnType):
|
||||
def get_c_type(self):
|
||||
return self.props.get('c_type', 'gdouble')
|
||||
def write_decl(self):
|
||||
self.wrapper.add_declaration("%s retval;" % self.get_c_type())
|
||||
def write_error_return(self):
|
||||
self.wrapper.write_code("return -G_MAXFLOAT;")
|
||||
def write_conversion(self):
|
||||
self.wrapper.write_code(
|
||||
code=None,
|
||||
failure_expression="!PyFloat_AsDouble(py_retval)",
|
||||
failure_cleanup='PyErr_SetString(PyExc_TypeError, "retval should be a float");')
|
||||
self.wrapper.write_code("retval = PyFloat_AsDouble(py_retval);")
|
||||
|
||||
for argtype in ('float', 'double', 'gfloat', 'gdouble'):
|
||||
argtypes.matcher.register_reverse(argtype, DoubleParam)
|
||||
argtypes.matcher.register_reverse_ret(argtype, DoubleReturn)
|
||||
|
||||
|
||||
class GBoxedParam(Parameter):
|
||||
def get_c_type(self):
|
||||
return self.props.get('c_type').replace('const-', 'const ')
|
||||
def convert_c2py(self):
|
||||
self.wrapper.add_declaration("PyObject *py_%s;" % self.name)
|
||||
ctype = self.get_c_type()
|
||||
if ctype.startswith('const '):
|
||||
ctype_no_const = ctype[len('const '):]
|
||||
self.wrapper.write_code(
|
||||
code=('py_%s = pyg_boxed_new(%s, (%s) %s, TRUE, TRUE);' %
|
||||
(self.name, self.props['typecode'],
|
||||
ctype_no_const, self.name)),
|
||||
cleanup=("Py_DECREF(py_%s);" % self.name))
|
||||
else:
|
||||
self.wrapper.write_code(
|
||||
code=('py_%s = pyg_boxed_new(%s, %s, FALSE, FALSE);' %
|
||||
(self.name, self.props['typecode'], self.name)),
|
||||
cleanup=("Py_DECREF(py_%s);" % self.name))
|
||||
self.wrapper.add_pyargv_item("py_%s" % self.name)
|
||||
|
||||
argtypes.matcher.register_reverse("GBoxed", GBoxedParam)
|
||||
|
||||
class GBoxedReturn(ReturnType):
|
||||
def get_c_type(self):
|
||||
return self.props.get('c_type')
|
||||
def write_decl(self):
|
||||
self.wrapper.add_declaration("%s retval;" % self.get_c_type())
|
||||
def write_error_return(self):
|
||||
self.wrapper.write_code("return retval;")
|
||||
def write_conversion(self):
|
||||
self.wrapper.write_code(
|
||||
failure_expression=("!pyg_boxed_check(py_retval, %s)" %
|
||||
(self.props['typecode'],)),
|
||||
failure_cleanup=('PyErr_SetString(PyExc_TypeError, "retval should be a %s");'
|
||||
% (self.props['typename'],)))
|
||||
self.wrapper.write_code('retval = pyg_boxed_get(py_retval, %s);' %
|
||||
self.props['typename'])
|
||||
|
||||
argtypes.matcher.register_reverse_ret("GBoxed", GBoxedReturn)
|
||||
|
||||
|
||||
class GdkRectanglePtrParam(Parameter):
|
||||
def get_c_type(self):
|
||||
return self.props.get('c_type').replace('const-', 'const ')
|
||||
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)),
|
||||
cleanup=("Py_DECREF(py_%s);" % self.name))
|
||||
self.wrapper.add_pyargv_item("py_%s" % self.name)
|
||||
|
||||
argtypes.matcher.register_reverse("GdkRectangle*", GdkRectanglePtrParam)
|
||||
|
||||
|
||||
class PyGObjectMethodParam(Parameter):
|
||||
def __init__(self, wrapper, name, method_name, **props):
|
||||
Parameter.__init__(self, wrapper, name, **props)
|
||||
self.method_name = method_name
|
||||
|
||||
def get_c_type(self):
|
||||
return self.props.get('c_type', 'GObject *')
|
||||
|
||||
def convert_c2py(self):
|
||||
self.wrapper.add_declaration("PyObject *py_%s;" % self.name)
|
||||
self.wrapper.write_code(code=("py_%s = pygobject_new((GObject *) %s);" %
|
||||
(self.name, self.name)),
|
||||
cleanup=("Py_DECREF(py_%s);" % self.name),
|
||||
failure_expression=("!py_%s" % self.name))
|
||||
self.wrapper.set_call_target("py_%s" % self.name, self.method_name)
|
||||
|
||||
class CallbackInUserDataParam(Parameter):
|
||||
def __init__(self, wrapper, name, free_it, **props):
|
||||
Parameter.__init__(self, wrapper, name, **props)
|
||||
self.free_it = free_it
|
||||
|
||||
def get_c_type(self):
|
||||
return "gpointer"
|
||||
|
||||
def convert_c2py(self):
|
||||
self.wrapper.add_declaration("PyObject **_user_data;")
|
||||
cleanup = self.free_it and ("g_free(%s);" % self.name) or None
|
||||
self.wrapper.write_code(code=("_real_user_data = (PyObject **) %s;"
|
||||
% self.name),
|
||||
cleanup=cleanup)
|
||||
|
||||
self.wrapper.add_declaration("PyObject *py_func;")
|
||||
cleanup = self.free_it and "Py_DECREF(py_func);" or None
|
||||
self.wrapper.write_code(code="py_func = _user_data[0];",
|
||||
cleanup=cleanup)
|
||||
self.wrapper.set_call_target("py_func")
|
||||
|
||||
self.wrapper.add_declaration("PyObject *py_user_data;")
|
||||
cleanup = self.free_it and "Py_XDECREF(py_user_data);" or None
|
||||
self.wrapper.write_code(code="py_user_data = _user_data[1];",
|
||||
cleanup=cleanup)
|
||||
self.wrapper.add_pyargv_item("py_user_data", optional=True)
|
||||
|
||||
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 __name__ == '__main__':
|
||||
_test()
|
|
@ -0,0 +1,144 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- Mode: Python; py-indent-offset: 4 -*-
|
||||
from __future__ import generators
|
||||
|
||||
import string
|
||||
import types
|
||||
from cStringIO import StringIO
|
||||
|
||||
class error(Exception):
|
||||
def __init__(self, filename, lineno, msg):
|
||||
Exception.__init__(self, msg)
|
||||
self.filename = filename
|
||||
self.lineno = lineno
|
||||
self.msg = msg
|
||||
def __str__(self):
|
||||
return '%s:%d: error: %s' % (self.filename, self.lineno, self.msg)
|
||||
|
||||
trans = [' '] * 256
|
||||
for i in range(256):
|
||||
if chr(i) in string.letters + string.digits + '_':
|
||||
trans[i] = chr(i)
|
||||
else:
|
||||
trans[i] = '_'
|
||||
trans = string.join(trans, '')
|
||||
|
||||
def parse(filename):
|
||||
if isinstance(filename, str):
|
||||
fp = open(filename, 'r')
|
||||
else: # if not string, assume it is some kind of iterator
|
||||
fp = filename
|
||||
filename = getattr(fp, 'name', '<unknown>')
|
||||
whitespace = ' \t\n\r\x0b\x0c'
|
||||
nonsymbol = whitespace + '();\'"'
|
||||
stack = []
|
||||
openlines = []
|
||||
lineno = 0
|
||||
for line in fp:
|
||||
pos = 0
|
||||
lineno += 1
|
||||
while pos < len(line):
|
||||
if line[pos] in whitespace: # ignore whitespace
|
||||
pass
|
||||
elif line[pos] == ';': # comment
|
||||
break
|
||||
elif line[pos:pos+2] == "'(":
|
||||
pass # the open parenthesis will be handled next iteration
|
||||
elif line[pos] == '(':
|
||||
stack.append(())
|
||||
openlines.append(lineno)
|
||||
elif line[pos] == ')':
|
||||
if len(stack) == 0:
|
||||
raise error(filename, lineno, 'close parenthesis found when none open')
|
||||
closed = stack[-1]
|
||||
del stack[-1]
|
||||
del openlines[-1]
|
||||
if stack:
|
||||
stack[-1] += (closed,)
|
||||
else:
|
||||
yield closed
|
||||
elif line[pos] == '"': # quoted string
|
||||
if not stack:
|
||||
raise error(filename, lineno,
|
||||
'string found outside of s-expression')
|
||||
endpos = pos + 1
|
||||
chars = []
|
||||
while endpos < len(line):
|
||||
if endpos+1 < len(line) and line[endpos] == '\\':
|
||||
endpos += 1
|
||||
if line[endpos] == 'n':
|
||||
chars.append('\n')
|
||||
elif line[endpos] == 'r':
|
||||
chars.append('\r')
|
||||
elif line[endpos] == 't':
|
||||
chars.append('\t')
|
||||
else:
|
||||
chars.append('\\')
|
||||
chars.append(line[endpos])
|
||||
elif line[endpos] == '"':
|
||||
break
|
||||
else:
|
||||
chars.append(line[endpos])
|
||||
endpos += 1
|
||||
if endpos >= len(line):
|
||||
raise error(filename, lineno, "unclosed quoted string")
|
||||
pos = endpos
|
||||
stack[-1] += (''.join(chars),)
|
||||
else: # symbol/number
|
||||
if not stack:
|
||||
raise error(filename, lineno,
|
||||
'identifier found outside of s-expression')
|
||||
endpos = pos
|
||||
while endpos < len(line) and line[endpos] not in nonsymbol:
|
||||
endpos += 1
|
||||
symbol = line[pos:endpos]
|
||||
pos = max(pos, endpos-1)
|
||||
try: symbol = int(symbol)
|
||||
except ValueError:
|
||||
try: symbol = float(symbol)
|
||||
except ValueError: pass
|
||||
stack[-1] += (symbol,)
|
||||
pos += 1
|
||||
if len(stack) != 0:
|
||||
msg = '%d unclosed parentheses found at end of ' \
|
||||
'file (opened on line(s) %s)' % (len(stack),
|
||||
', '.join(map(str, openlines)))
|
||||
raise error(filename, lineno, msg)
|
||||
|
||||
class Parser:
|
||||
def __init__(self, filename):
|
||||
"""Argument is either a string, a parse tree, or file object"""
|
||||
self.filename = filename
|
||||
def startParsing(self, filename=None):
|
||||
statements = parse(filename or self.filename)
|
||||
for statement in statements:
|
||||
self.handle(statement)
|
||||
def handle(self, tup):
|
||||
cmd = string.translate(tup[0], trans)
|
||||
if hasattr(self, cmd):
|
||||
getattr(self, cmd)(*tup[1:])
|
||||
else:
|
||||
self.unknown(tup)
|
||||
def unknown(self, tup):
|
||||
pass
|
||||
|
||||
_testString = """; a scheme file
|
||||
(define-func gdk_font_load ; a comment at end of line
|
||||
GdkFont
|
||||
((string name)))
|
||||
|
||||
(define-boxed GdkEvent
|
||||
gdk_event_copy
|
||||
gdk_event_free
|
||||
"sizeof(GdkEvent)")
|
||||
"""
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
if sys.argv[1:]:
|
||||
fp = open(sys.argv[1])
|
||||
else:
|
||||
fp = StringIO(_testString)
|
||||
statements = parse(fp)
|
||||
for s in statements:
|
||||
print `s`
|
Loading…
Reference in New Issue