mirror of https://github.com/python/cpython.git
Lots of changes.
Renamed some things. Added support for methods directly to bgenGenerator.py. Completely reworked buffer, string and and structure types.
This commit is contained in:
parent
7cbf4803a9
commit
f8de0685c9
|
@ -11,20 +11,28 @@
|
||||||
INOUT = IN_OUT = "in-out"
|
INOUT = IN_OUT = "in-out"
|
||||||
|
|
||||||
|
|
||||||
class Generator:
|
class FunctionGenerator:
|
||||||
|
|
||||||
# XXX There are some funny things with the argument list.
|
def __init__(self, returntype, name, *argumentList):
|
||||||
# XXX It would be better to get rid of this and require
|
self.returntype = returntype
|
||||||
# XXX each argument to be a type object or a tuple of the form
|
self.name = name
|
||||||
# XXX (inoutmode, typeobject, argumentname)
|
self.argumentList = []
|
||||||
# XXX or possibly even a Variable() instance...
|
self.setreturnvar()
|
||||||
|
self.parseArgumentList(argumentList)
|
||||||
def __init__(self, *argumentList):
|
|
||||||
apply(self.parseArguments, argumentList)
|
|
||||||
self.prefix = "XXX" # Will be changed by setprefix() call
|
self.prefix = "XXX" # Will be changed by setprefix() call
|
||||||
self.objecttype = "PyObject" # Type of _self argument to function
|
self.objecttype = "PyObject" # Type of _self argument to function
|
||||||
self.itselftype = None # Type of _self->ob_itself, if defined
|
self.itselftype = None # Type of _self->ob_itself, if defined
|
||||||
|
|
||||||
|
def setreturnvar(self):
|
||||||
|
if self.returntype:
|
||||||
|
self.rv = self.makereturnvar()
|
||||||
|
self.argumentList.append(self.rv)
|
||||||
|
else:
|
||||||
|
self.rv = None
|
||||||
|
|
||||||
|
def makereturnvar(self):
|
||||||
|
return Variable(self.returntype, "_rv", OutMode)
|
||||||
|
|
||||||
def setprefix(self, prefix):
|
def setprefix(self, prefix):
|
||||||
self.prefix = prefix
|
self.prefix = prefix
|
||||||
|
|
||||||
|
@ -32,32 +40,12 @@ def setselftype(self, selftype, itselftype):
|
||||||
self.objecttype = selftype
|
self.objecttype = selftype
|
||||||
self.itselftype = itselftype
|
self.itselftype = itselftype
|
||||||
|
|
||||||
def parseArguments(self, returnType, name, *argumentList):
|
|
||||||
if returnType:
|
|
||||||
self.rv = Variable(returnType, "_rv", OutMode)
|
|
||||||
else:
|
|
||||||
self.rv = None
|
|
||||||
self.name = name
|
|
||||||
self.argumentList = []
|
|
||||||
if self.rv:
|
|
||||||
self.argumentList.append(rv)
|
|
||||||
self.parseArgumentList(argumentList)
|
|
||||||
|
|
||||||
def parseArgumentList(self, argumentList):
|
def parseArgumentList(self, argumentList):
|
||||||
from types import *
|
|
||||||
iarg = 0
|
iarg = 0
|
||||||
for arg in argumentList:
|
for type, name, mode in argumentList:
|
||||||
# Arguments can either be:
|
|
||||||
# - a type
|
|
||||||
# - a tuple (type, [name, [mode]])
|
|
||||||
# - a variable
|
|
||||||
iarg = iarg + 1
|
iarg = iarg + 1
|
||||||
if hasattr(arg, 'typeName'):
|
if name is None: name = "_arg%d" % iarg
|
||||||
arg = Variable(arg)
|
arg = Variable(type, name, mode)
|
||||||
elif type(arg) == TupleType:
|
|
||||||
arg = apply(Variable, arg)
|
|
||||||
if arg.name is None:
|
|
||||||
arg.name = "_arg%d" % iarg
|
|
||||||
self.argumentList.append(arg)
|
self.argumentList.append(arg)
|
||||||
|
|
||||||
def reference(self, name = None):
|
def reference(self, name = None):
|
||||||
|
@ -67,6 +55,7 @@ def reference(self, name = None):
|
||||||
name, self.prefix, self.name)
|
name, self.prefix, self.name)
|
||||||
|
|
||||||
def generate(self):
|
def generate(self):
|
||||||
|
print "-->", self.name
|
||||||
self.functionheader()
|
self.functionheader()
|
||||||
self.declarations()
|
self.declarations()
|
||||||
self.getargs()
|
self.getargs()
|
||||||
|
@ -84,6 +73,7 @@ def functionheader(self):
|
||||||
Output("PyObject *_args;")
|
Output("PyObject *_args;")
|
||||||
DedentLevel()
|
DedentLevel()
|
||||||
OutLbrace()
|
OutLbrace()
|
||||||
|
Output("PyObject *_res = NULL;")
|
||||||
|
|
||||||
def declarations(self):
|
def declarations(self):
|
||||||
for arg in self.argumentList:
|
for arg in self.argumentList:
|
||||||
|
@ -98,7 +88,9 @@ def getargs(self):
|
||||||
continue
|
continue
|
||||||
if arg.mode in (InMode, InOutMode):
|
if arg.mode in (InMode, InOutMode):
|
||||||
fmt = fmt + arg.getargsFormat()
|
fmt = fmt + arg.getargsFormat()
|
||||||
lst = lst + sep + arg.getargsArgs()
|
args = arg.getargsArgs()
|
||||||
|
if args:
|
||||||
|
lst = lst + sep + args
|
||||||
Output("if (!PyArg_ParseTuple(_args, \"%s\"%s))", fmt, lst)
|
Output("if (!PyArg_ParseTuple(_args, \"%s\"%s))", fmt, lst)
|
||||||
IndentLevel()
|
IndentLevel()
|
||||||
Output("return NULL;")
|
Output("return NULL;")
|
||||||
|
@ -111,7 +103,11 @@ def getargs(self):
|
||||||
|
|
||||||
def callit(self):
|
def callit(self):
|
||||||
args = ""
|
args = ""
|
||||||
sep = ",\n" + ' '*len("%s = %s(" % (self.rv.name, self.name))
|
if self.rv:
|
||||||
|
s = "%s = %s(" % (self.rv.name, self.name)
|
||||||
|
else:
|
||||||
|
s = "%s(" % self.name
|
||||||
|
sep = ",\n" + ' '*len(s)
|
||||||
for arg in self.argumentList:
|
for arg in self.argumentList:
|
||||||
if arg is self.rv:
|
if arg is self.rv:
|
||||||
continue
|
continue
|
||||||
|
@ -140,15 +136,34 @@ def returnvalue(self):
|
||||||
lst = lst + sep + arg.mkvalueArgs()
|
lst = lst + sep + arg.mkvalueArgs()
|
||||||
if fmt == "":
|
if fmt == "":
|
||||||
Output("Py_INCREF(Py_None);")
|
Output("Py_INCREF(Py_None);")
|
||||||
Output("return Py_None;");
|
Output("_res = Py_None;");
|
||||||
else:
|
else:
|
||||||
Output("return Py_BuildValue(\"%s\"%s);", fmt, lst)
|
Output("_res = Py_BuildValue(\"%s\"%s);", fmt, lst)
|
||||||
|
tmp = self.argumentList[:]
|
||||||
|
tmp.reverse()
|
||||||
|
for arg in tmp:
|
||||||
|
if not arg: continue
|
||||||
|
if arg.flags == ErrorMode: continue
|
||||||
|
if arg.mode in (OutMode, InOutMode):
|
||||||
|
arg.mkvalueCleanup()
|
||||||
|
Output("return _res;")
|
||||||
|
|
||||||
def functiontrailer(self):
|
def functiontrailer(self):
|
||||||
OutRbrace()
|
OutRbrace()
|
||||||
|
|
||||||
|
|
||||||
class ManualGenerator(Generator):
|
class MethodGenerator(FunctionGenerator):
|
||||||
|
|
||||||
|
def parseArgumentList(self, args):
|
||||||
|
a0, args = args[0], args[1:]
|
||||||
|
t0, n0, m0 = a0
|
||||||
|
if m0 != InMode:
|
||||||
|
raise ValueError, "method's 'self' must be 'InMode'"
|
||||||
|
self.itself = Variable(t0, "_self->ob_itself", SelfMode)
|
||||||
|
self.argumentList.append(self.itself)
|
||||||
|
FunctionGenerator.parseArgumentList(self, args)
|
||||||
|
|
||||||
|
class ManualGenerator(FunctionGenerator):
|
||||||
|
|
||||||
def __init__(self, name, body):
|
def __init__(self, name, body):
|
||||||
self.name = name
|
self.name = name
|
||||||
|
|
|
@ -13,7 +13,6 @@ def add(self, g):
|
||||||
def generate(self):
|
def generate(self):
|
||||||
for g in self.generators:
|
for g in self.generators:
|
||||||
g.generate()
|
g.generate()
|
||||||
Output()
|
|
||||||
Output("static PyMethodDef %s_methods[] = {", self.prefix)
|
Output("static PyMethodDef %s_methods[] = {", self.prefix)
|
||||||
IndentLevel()
|
IndentLevel()
|
||||||
for g in self.generators:
|
for g in self.generators:
|
||||||
|
@ -21,6 +20,7 @@ def generate(self):
|
||||||
Output("{NULL, NULL, 0}")
|
Output("{NULL, NULL, 0}")
|
||||||
DedentLevel()
|
DedentLevel()
|
||||||
Output("};")
|
Output("};")
|
||||||
|
Output()
|
||||||
|
|
||||||
|
|
||||||
def _test():
|
def _test():
|
||||||
|
|
|
@ -57,18 +57,22 @@ def generate(self):
|
||||||
OutHeader2("End object type " + self.name)
|
OutHeader2("End object type " + self.name)
|
||||||
|
|
||||||
def outputNew(self):
|
def outputNew(self):
|
||||||
Output("static %s *%s_New(itself)", self.objecttype, self.prefix)
|
Output("static PyObject *%s_New(itself)", self.prefix)
|
||||||
IndentLevel()
|
IndentLevel()
|
||||||
Output("const %s %sitself;", self.itselftype, self.argref)
|
Output("const %s %sitself;", self.itselftype, self.argref)
|
||||||
DedentLevel()
|
DedentLevel()
|
||||||
OutLbrace()
|
OutLbrace()
|
||||||
Output("%s *it;", self.objecttype)
|
Output("%s *it;", self.objecttype)
|
||||||
|
self.outputCheckNewArg()
|
||||||
Output("it = PyObject_NEW(%s, &%s);", self.objecttype, self.typename)
|
Output("it = PyObject_NEW(%s, &%s);", self.objecttype, self.typename)
|
||||||
Output("if (it == NULL) return NULL;")
|
Output("if (it == NULL) return NULL;")
|
||||||
Output("it->ob_itself = %sitself;", self.argref)
|
Output("it->ob_itself = %sitself;", self.argref)
|
||||||
Output("return it;")
|
Output("return (PyObject *)it;")
|
||||||
OutRbrace()
|
OutRbrace()
|
||||||
Output()
|
Output()
|
||||||
|
|
||||||
|
def outputCheckNewArg(self):
|
||||||
|
pass
|
||||||
|
|
||||||
def outputConvert(self):
|
def outputConvert(self):
|
||||||
Output("""\
|
Output("""\
|
||||||
|
|
|
@ -106,16 +106,53 @@ def mkvalueArgs(self, name):
|
||||||
"""
|
"""
|
||||||
return name
|
return name
|
||||||
|
|
||||||
|
def mkvalueCleanup(self, name):
|
||||||
|
"""Clean up if necessary after mkvalue().
|
||||||
|
|
||||||
|
This is normally empty; it may deallocate buffers etc.
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
# Sometimes it's useful to define a type that's only usable as input or output parameter
|
||||||
|
|
||||||
|
class InputOnlyMixIn:
|
||||||
|
|
||||||
|
"Mix-in class to boobytrap passOutput"
|
||||||
|
|
||||||
|
def passOutput(self):
|
||||||
|
raise RuntimeError, "this type can only be used for input parameters"
|
||||||
|
|
||||||
|
class InputOnlyType(InputOnlyMixIn, Type):
|
||||||
|
|
||||||
|
"Same as Type, but only usable for input parameters -- passOutput is boobytrapped"
|
||||||
|
|
||||||
|
class OutputOnlyMixIn:
|
||||||
|
|
||||||
|
"Mix-in class to boobytrap passInput"
|
||||||
|
|
||||||
|
def passInput(self):
|
||||||
|
raise RuntimeError, "this type can only be used for output parameters"
|
||||||
|
|
||||||
|
class OutputOnlyType(OutputOnlyMixIn, Type):
|
||||||
|
|
||||||
|
"Same as Type, but only usable for output parameters -- passInput is boobytrapped"
|
||||||
|
|
||||||
|
|
||||||
# A modest collection of standard C types.
|
# A modest collection of standard C types.
|
||||||
void = None
|
void = None
|
||||||
|
char = Type("char", "c")
|
||||||
short = Type("short", "h")
|
short = Type("short", "h")
|
||||||
int = Type("int", "i")
|
int = Type("int", "i")
|
||||||
long = Type("long", "l")
|
long = Type("long", "l")
|
||||||
float = Type("float", "f")
|
float = Type("float", "f")
|
||||||
double = Type("double", "d")
|
double = Type("double", "d")
|
||||||
stringptr = Type("char*", "s")
|
|
||||||
char = Type("char", "c")
|
|
||||||
|
# The most common use of character pointers is a null-terminated string.
|
||||||
|
# For input, this is easy. For output, and for other uses of char *,
|
||||||
|
# see the various Buffer types below.
|
||||||
|
stringptr = InputOnlyType("char*", "s")
|
||||||
|
|
||||||
|
|
||||||
# Some Python related types.
|
# Some Python related types.
|
||||||
|
@ -124,20 +161,69 @@ def mkvalueArgs(self, name):
|
||||||
# Etc.
|
# Etc.
|
||||||
|
|
||||||
|
|
||||||
# Buffers are character arrays that may contain null bytes.
|
class FakeType(InputOnlyType):
|
||||||
# Their length is either Fixed or Sized (i.e. given by a separate argument).
|
|
||||||
|
|
||||||
class SizedInputBuffer:
|
"""A type that is not represented in the Python version of the interface.
|
||||||
|
|
||||||
"Sized input buffer -- buffer size is an input parameter"
|
Instantiate with a value to pass in the call.
|
||||||
|
"""
|
||||||
|
|
||||||
def __init__(self, size = ''):
|
def __init__(self, substitute):
|
||||||
self.size = size
|
self.substitute = substitute
|
||||||
|
|
||||||
def declare(self, name):
|
def declare(self, name):
|
||||||
Output("char *%s;", name)
|
pass
|
||||||
|
|
||||||
|
def getargsFormat(self):
|
||||||
|
return ""
|
||||||
|
|
||||||
|
def getargsArgs(self, name):
|
||||||
|
return None
|
||||||
|
|
||||||
|
def passInput(self, name):
|
||||||
|
return self.substitute
|
||||||
|
|
||||||
|
|
||||||
|
class AbstractBufferType:
|
||||||
|
"""Buffers are character arrays that may contain null bytes.
|
||||||
|
|
||||||
|
There are a number of variants depending on:
|
||||||
|
- how the buffer is allocated (for output buffers), and
|
||||||
|
- whether and how the size is passed into and/or out of the called function.
|
||||||
|
|
||||||
|
The AbstractbufferType only serves as a placeholder for this doc string.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def declare(self, name):
|
||||||
|
self.declareBuffer(name)
|
||||||
|
self.declareSize(name)
|
||||||
|
|
||||||
|
|
||||||
|
class FixedBufferType(AbstractBufferType):
|
||||||
|
|
||||||
|
"""Fixed size buffer -- passed without size information.
|
||||||
|
|
||||||
|
Instantiate with the size as parameter.
|
||||||
|
THIS IS STILL AN ABSTRACT BASE CLASS -- DO NOT INSTANTIATE.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, size):
|
||||||
|
self.size = str(size)
|
||||||
|
|
||||||
|
def declareSize(self, name):
|
||||||
Output("int %s__len__;", name)
|
Output("int %s__len__;", name)
|
||||||
|
|
||||||
|
|
||||||
|
class FixedInputBufferType(InputOnlyMixIn, FixedBufferType):
|
||||||
|
|
||||||
|
"""Fixed size input buffer -- passed without size information.
|
||||||
|
|
||||||
|
Instantiate with the size as parameter.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def declareBuffer(self, name):
|
||||||
|
Output("char *%s;", name)
|
||||||
|
|
||||||
def getargsFormat(self):
|
def getargsFormat(self):
|
||||||
return "s#"
|
return "s#"
|
||||||
|
|
||||||
|
@ -145,126 +231,221 @@ def getargsArgs(self, name):
|
||||||
return "&%s, &%s__len__" % (name, name)
|
return "&%s, &%s__len__" % (name, name)
|
||||||
|
|
||||||
def getargsCheck(self, name):
|
def getargsCheck(self, name):
|
||||||
pass
|
Output("if (%s__len__ != %s)", name, self.size)
|
||||||
|
|
||||||
def passInput(self, name):
|
|
||||||
return "%s, %s__len__" % (name, name)
|
|
||||||
|
|
||||||
|
|
||||||
class FixedInputBuffer(SizedInputBuffer):
|
|
||||||
|
|
||||||
"Fixed input buffer -- buffer size is a constant"
|
|
||||||
|
|
||||||
def getargsCheck(self, name):
|
|
||||||
Output("if (%s__len__ != %s)", name, str(self.size))
|
|
||||||
OutLbrace()
|
OutLbrace()
|
||||||
Output('PyErr_SetString(PyExc_TypeError, "bad string length");')
|
Output('PyErr_SetString(PyExc_TypeError, "buffer length should be %s");',
|
||||||
Output('return NULL;')
|
self.size)
|
||||||
|
Output('return NULL;') # XXX should do a goto
|
||||||
OutRbrace()
|
OutRbrace()
|
||||||
|
|
||||||
def passInput(self, name):
|
def passInput(self, name):
|
||||||
return name
|
return name
|
||||||
|
|
||||||
|
|
||||||
class RecordBuffer(FixedInputBuffer):
|
class FixedOutputBufferType(OutputOnlyMixIn, FixedBufferType):
|
||||||
|
|
||||||
"Like fixed input buffer -- but declared as a record type pointer"
|
"""Fixed size output buffer -- passed without size information.
|
||||||
|
|
||||||
def __init__(self, type):
|
Instantiate with the size as parameter.
|
||||||
self.type = type
|
"""
|
||||||
self.size = "sizeof(%s)" % type
|
|
||||||
|
|
||||||
def declare(self, name):
|
def declareBuffer(self, name):
|
||||||
Output("%s *%s;", self.type, name)
|
Output("char %s[%s];", name, self.size)
|
||||||
Output("int %s__len__;", name)
|
|
||||||
|
|
||||||
|
|
||||||
class SizedOutputBuffer:
|
|
||||||
|
|
||||||
"Sized output buffer -- buffer size is an input-output parameter"
|
|
||||||
|
|
||||||
def __init__(self, maxsize):
|
|
||||||
self.maxsize = maxsize
|
|
||||||
|
|
||||||
def declare(self, name):
|
|
||||||
Output("char %s[%s];", name, str(self.maxsize))
|
|
||||||
Output("int %s__len__ = %s;", name, str(self.maxsize))
|
|
||||||
|
|
||||||
def passOutput(self, name):
|
def passOutput(self, name):
|
||||||
return "%s, &%s__len__" % (name, name)
|
return name
|
||||||
|
|
||||||
def errorCheck(self, name):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def mkvalueFormat(self):
|
def mkvalueFormat(self):
|
||||||
return "s#"
|
return "s#"
|
||||||
|
|
||||||
|
def mkvalueArgs(self):
|
||||||
|
return "%s, %s" % (name, self.size)
|
||||||
|
|
||||||
|
|
||||||
|
class StructBufferType(FixedBufferType):
|
||||||
|
|
||||||
|
"""Structure buffer -- passed as a structure pointer.
|
||||||
|
|
||||||
|
Instantiate with the struct type as parameter.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, type):
|
||||||
|
FixedBufferType.__init__(self, "sizeof(%s)" % type)
|
||||||
|
self.type = type
|
||||||
|
|
||||||
|
|
||||||
|
class StructInputBufferType(StructBufferType, FixedInputBufferType):
|
||||||
|
|
||||||
|
"""Fixed size input buffer -- passed as a pointer to a structure.
|
||||||
|
|
||||||
|
Instantiate with the struct type as parameter.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def declareBuffer(self, name):
|
||||||
|
Output("%s *%s;", self.type, name)
|
||||||
|
|
||||||
|
|
||||||
|
class StructByValueBufferType(StructInputBufferType):
|
||||||
|
|
||||||
|
"""Fixed size input buffer -- passed as a structure BY VALUE.
|
||||||
|
|
||||||
|
Instantiate with the struct type as parameter.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def passInput(self, name):
|
||||||
|
return "*%s" % name
|
||||||
|
|
||||||
|
|
||||||
|
class StructOutputBufferType(StructBufferType, FixedOutputBufferType):
|
||||||
|
|
||||||
|
"""Fixed size output buffer -- passed as a pointer to a structure.
|
||||||
|
|
||||||
|
Instantiate with the struct type as parameter.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def declareBuffer(self, name):
|
||||||
|
Output("%s %s;", self.type, name)
|
||||||
|
|
||||||
|
def passOutput(self, name):
|
||||||
|
return "&%s" % name
|
||||||
|
|
||||||
|
def mkvalueArgs(self, name):
|
||||||
|
return "(char *)&%s" % name
|
||||||
|
|
||||||
|
|
||||||
|
class VarInputBufferType(InputOnlyMixIn, FixedInputBufferType):
|
||||||
|
|
||||||
|
"""Input buffer -- passed as (buffer, size).
|
||||||
|
|
||||||
|
Instantiate without parameters.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def getargsCheck(self, name):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def passInput(self, name):
|
||||||
|
return "%s, %s__len__" % (name, name)
|
||||||
|
|
||||||
|
|
||||||
|
class StackOutputBufferType(OutputOnlyMixIn, FixedOutputBufferType):
|
||||||
|
|
||||||
|
"""Output buffer -- passed as (buffer, size).
|
||||||
|
|
||||||
|
Instantiate with the buffer size as parameter.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def passOutput(self, name):
|
||||||
|
return "%s, %s" % (name, self.size)
|
||||||
|
|
||||||
|
|
||||||
|
class VarStackOutputBufferType(StackOutputBufferType):
|
||||||
|
|
||||||
|
"""Output buffer allocated on the stack -- passed as (buffer, &size).
|
||||||
|
|
||||||
|
Instantiate with the buffer size as parameter.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def declareSize(self, name):
|
||||||
|
Output("int %s__len__ = %s;", name, self.size)
|
||||||
|
|
||||||
|
def passOutput(self, name):
|
||||||
|
return "%s, &%s__len__" % (name, name)
|
||||||
|
|
||||||
def mkvalueArgs(self, name):
|
def mkvalueArgs(self, name):
|
||||||
return "%s, %s__len__" % (name, name)
|
return "%s, %s__len__" % (name, name)
|
||||||
|
|
||||||
|
|
||||||
class VarSizedOutputBuffer(SizedOutputBuffer):
|
class VarVarStackOutputBufferType(VarStackOutputBufferType):
|
||||||
|
|
||||||
"Variable Sized output buffer -- buffer size is an input and an output parameter"
|
"""Output buffer allocated on the stack -- passed as (buffer, size, &size).
|
||||||
|
|
||||||
def getargsFormat(self):
|
Instantiate with the buffer size as parameter.
|
||||||
return "i"
|
"""
|
||||||
|
|
||||||
def getargsArgs(self, name):
|
|
||||||
return "&%s__len__" % name
|
|
||||||
|
|
||||||
def getargsCheck(self, name):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def passOutput(self, name):
|
def passOutput(self, name):
|
||||||
return "%s, %s__len__, &%s__len__" % (name, name, name)
|
return "%s, %s__len__, &%s__len__" % (name, name, name)
|
||||||
|
|
||||||
|
|
||||||
class FixedOutputBuffer:
|
class HeapOutputBufferType(FixedOutputBufferType):
|
||||||
|
|
||||||
"Fixed output buffer -- buffer size is a constant"
|
"""Output buffer allocated on the heap -- passed as (buffer, size).
|
||||||
|
|
||||||
def __init__(self, size):
|
Instantiate without parameters.
|
||||||
self.size = size
|
Call from Python with buffer size.
|
||||||
|
"""
|
||||||
|
|
||||||
def declare(self, name):
|
def __init__(self):
|
||||||
Output("char %s[%s];", name, str(self.size))
|
|
||||||
|
|
||||||
def passOutput(self, name):
|
|
||||||
return name
|
|
||||||
|
|
||||||
def errorCheck(self, name):
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def mkvalueFormat(self):
|
def declareBuffer(self, name):
|
||||||
return "s#"
|
Output("char *%s;", name)
|
||||||
|
|
||||||
|
def getargsFormat(self):
|
||||||
|
return "i"
|
||||||
|
|
||||||
|
def getargsArgs(self, name):
|
||||||
|
return "&%s__len__" % name
|
||||||
|
|
||||||
|
def getargsCheck(self, name):
|
||||||
|
Output("if ((%s = malloc(%s__len__)) == NULL) goto %s__error__;",
|
||||||
|
name, name, name)
|
||||||
|
|
||||||
|
def passOutput(self, name):
|
||||||
|
return "%s, %s__len__" % (name, name)
|
||||||
|
|
||||||
def mkvalueArgs(self, name):
|
def mkvalueArgs(self, name):
|
||||||
return "%s, %s" % (name, str(self.size))
|
return "%s, %s__len__" % (name, name)
|
||||||
|
|
||||||
|
def mkvalueCleanup(self, name):
|
||||||
|
Output("free(%s);", name)
|
||||||
|
DedentLevel()
|
||||||
|
Output(" %s__error__: ;", name);
|
||||||
|
IndentLevel()
|
||||||
|
|
||||||
|
|
||||||
# Strings are character arrays terminated by a null byte.
|
class VarHeapOutputBufferType(HeapOutputBufferType):
|
||||||
# For input, this is covered by stringptr.
|
|
||||||
# For output, there are again two variants: Fixed (size is a constant
|
|
||||||
# given in the documentation) or Sized (size is given by a variable).
|
|
||||||
# (Note that this doesn't cover output parameters in which a string
|
|
||||||
# pointer is returned.)
|
|
||||||
|
|
||||||
class SizedOutputString:
|
"""Output buffer allocated on the heap -- passed as (buffer, &size).
|
||||||
|
|
||||||
"Null-terminated output string -- buffer size is an input parameter"
|
Instantiate without parameters.
|
||||||
|
Call from Python with buffer size.
|
||||||
def __init__(self, bufsize):
|
"""
|
||||||
self.bufsize = bufsize
|
|
||||||
|
|
||||||
def declare(self, name):
|
|
||||||
Output("char %s[%s];", name, str(self.bufsize))
|
|
||||||
|
|
||||||
def passOutput(self, name):
|
def passOutput(self, name):
|
||||||
return "%s, %s" % (name, str(self.bufsize))
|
return "%s, &%s__len__" % (name, name)
|
||||||
|
|
||||||
def errorCheck(self, name):
|
|
||||||
pass
|
class VarVarHeapOutputBufferType(VarHeapOutputBufferType):
|
||||||
|
|
||||||
|
"""Output buffer allocated on the heap -- passed as (buffer, size, &size).
|
||||||
|
|
||||||
|
Instantiate without parameters.
|
||||||
|
Call from Python with buffer size.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def passOutput(self, name):
|
||||||
|
return "%s, %s__len__, &%s__len__" % (name, name, name)
|
||||||
|
|
||||||
|
|
||||||
|
class StringBufferType:
|
||||||
|
|
||||||
|
"""Mix-in class to create various string buffer types.
|
||||||
|
|
||||||
|
Strings are character arrays terminated by a null byte.
|
||||||
|
For input, this is already covered by stringptr.
|
||||||
|
For output, there are again three variants:
|
||||||
|
- Fixed (size is a constant given in the documentation),
|
||||||
|
- Stack (size is passed to the C function but we decide on a size at
|
||||||
|
code generation time so we can still allocate on the heap), or
|
||||||
|
- Heap (size is passed to the C function and we let the Python caller
|
||||||
|
pass a size.
|
||||||
|
(Note that this doesn't cover output parameters in which a string
|
||||||
|
pointer is returned. These are actually easier (no allocation) but far
|
||||||
|
less common. I'll write the classes when there is demand.)
|
||||||
|
"""
|
||||||
|
|
||||||
def mkvalueFormat(self):
|
def mkvalueFormat(self):
|
||||||
return "s"
|
return "s"
|
||||||
|
@ -273,63 +454,88 @@ def mkvalueArgs(self, name):
|
||||||
return name
|
return name
|
||||||
|
|
||||||
|
|
||||||
class FixedOutputString(SizedOutputString):
|
class FixedOutputStringType(StringBufferType, FixedOutputBufferType):
|
||||||
|
|
||||||
"Null-terminated output string -- buffer size is a constant"
|
"""Null-terminated output string -- passed without size.
|
||||||
|
|
||||||
|
Instantiate with buffer size as parameter.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class StackOutputStringType(StringBufferType, StackOutputBufferType):
|
||||||
|
|
||||||
|
"""Null-terminated output string -- passed as (buffer, size).
|
||||||
|
|
||||||
|
Instantiate with buffer size as parameter.
|
||||||
|
"""
|
||||||
|
|
||||||
|
class HeapOutputStringType(StringBufferType, HeapOutputBufferType):
|
||||||
|
|
||||||
|
"""Null-terminated output string -- passed as (buffer, size).
|
||||||
|
|
||||||
|
Instantiate without parameters.
|
||||||
|
Call from Python with buffer size.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class OpaqueType(Type):
|
||||||
|
|
||||||
|
"""A type represented by an opaque object type, always passed by address.
|
||||||
|
|
||||||
|
Instantiate with the type name, and optional an object type name whose
|
||||||
|
New/Convert functions will be used.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, name, sameAs = None):
|
||||||
|
self.typeName = name
|
||||||
|
self.sameAs = sameAs or name
|
||||||
|
|
||||||
|
def getargsFormat(self):
|
||||||
|
return 'O&'
|
||||||
|
|
||||||
|
def getargsArgs(self, name):
|
||||||
|
return "%s_Convert, &%s" % (self.sameAs, name)
|
||||||
|
|
||||||
|
def passInput(self, name):
|
||||||
|
return "&%s" % name
|
||||||
|
|
||||||
|
def mkvalueFormat(self):
|
||||||
|
return 'O&'
|
||||||
|
|
||||||
|
def mkvalueArgs(self, name):
|
||||||
|
return "%s_New, &%s" % (self.sameAs, name)
|
||||||
|
|
||||||
|
|
||||||
|
class OpaqueByValueType(OpaqueType):
|
||||||
|
|
||||||
|
"""A type represented by an opaque object type, on input passed BY VALUE.
|
||||||
|
|
||||||
|
Instantiate with the type name, and optional an object type name whose
|
||||||
|
New/Convert functions will be used.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def passInput(self, name):
|
||||||
|
return name
|
||||||
|
|
||||||
|
def mkvalueArgs(self, name):
|
||||||
|
return "%s_New, %s" % (self.sameAs, name)
|
||||||
|
|
||||||
|
|
||||||
|
class OpaqueArrayType(OpaqueByValueType):
|
||||||
|
|
||||||
|
"""A type represented by an opaque object type, with ARRAY passing semantics.
|
||||||
|
|
||||||
|
Instantiate with the type name, and optional an object type name whose
|
||||||
|
New/Convert functions will be used.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def getargsArgs(self, name):
|
||||||
|
return "%s_Convert, &%s" % (self.sameAs, name)
|
||||||
|
|
||||||
def passOutput(self, name):
|
def passOutput(self, name):
|
||||||
return name
|
return name
|
||||||
|
|
||||||
|
|
||||||
class StructureByValue:
|
|
||||||
|
|
||||||
"Structure passed by value -- mapped to a Python string (for now)"
|
|
||||||
|
|
||||||
def __init__(self, typeName):
|
|
||||||
self.typeName = typeName
|
|
||||||
|
|
||||||
def declare(self, name):
|
|
||||||
n = len(self.typeName)
|
|
||||||
Output("%-*s %s;", n, self.typeName, name)
|
|
||||||
Output("%-*s*%s__str__;", n, "char", name)
|
|
||||||
Output("%-*s %s__len__;", n, "int", name)
|
|
||||||
|
|
||||||
def getargsFormat(self):
|
|
||||||
return "s#"
|
|
||||||
|
|
||||||
def getargsArgs(self, name):
|
|
||||||
return "&%s__str__, &%s__len__" % (name, name)
|
|
||||||
|
|
||||||
def getargsCheck(self, name):
|
|
||||||
Output("if (%s__len__ != sizeof %s)", name, name)
|
|
||||||
IndentLevel()
|
|
||||||
Output('PyErr_SetString(PyExc_TypeError, "bad structure length");')
|
|
||||||
DedentLevel()
|
|
||||||
Output("memcpy(&%s, %s__str__, %s__len__);",
|
|
||||||
name, name, name)
|
|
||||||
|
|
||||||
def passInput(self, name):
|
|
||||||
return "%s" % name
|
|
||||||
|
|
||||||
def passOutput(self, name):
|
|
||||||
return "&%s" % name
|
|
||||||
|
|
||||||
def errorCheck(self, name):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def mkvalueFormat(self):
|
|
||||||
return "s#"
|
|
||||||
|
|
||||||
def mkvalueArgs(self, name):
|
|
||||||
return "(char *)&%s, (int)sizeof %s" % (name, name)
|
|
||||||
|
|
||||||
|
|
||||||
class StructureByAddress(StructureByValue):
|
|
||||||
|
|
||||||
def passInput(self, name):
|
|
||||||
return "&%s" % name
|
|
||||||
|
|
||||||
|
|
||||||
class Variable:
|
class Variable:
|
||||||
|
|
||||||
"""A Variable holds a type, a name, a transfer mode and flags.
|
"""A Variable holds a type, a name, a transfer mode and flags.
|
||||||
|
@ -397,3 +603,7 @@ def mkvalueFormat (self):
|
||||||
def mkvalueArgs(self):
|
def mkvalueArgs(self):
|
||||||
"""Call the type's mkvalueArgs method."""
|
"""Call the type's mkvalueArgs method."""
|
||||||
return self.type.mkvalueArgs(self.name)
|
return self.type.mkvalueArgs(self.name)
|
||||||
|
|
||||||
|
def mkvalueCleanup(self):
|
||||||
|
"""Call the type's mkvalueCleanup method."""
|
||||||
|
return self.type.mkvalueCleanup(self.name)
|
||||||
|
|
Loading…
Reference in New Issue