mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +00:00
Lots of new stuff again. Moved buffer types to some separate files.
Added some new-fangled features to bgenOutput. Generate doc strings!
This commit is contained in:
parent
5679e56bd1
commit
01f5a81d11
13 changed files with 1327 additions and 455 deletions
|
@ -1,6 +1,11 @@
|
||||||
"Export everything in the various bgen submodules."
|
"Export everything in the various bgen submodules."
|
||||||
|
|
||||||
from bgenType import *
|
from bgenType import *
|
||||||
|
from bgenVariable import *
|
||||||
|
from bgenBuffer import *
|
||||||
|
from bgenStackBuffer import *
|
||||||
|
from bgenHeapBuffer import *
|
||||||
|
from bgenStringBuffer import *
|
||||||
from bgenOutput import *
|
from bgenOutput import *
|
||||||
from bgenGenerator import *
|
from bgenGenerator import *
|
||||||
from bgenModule import *
|
from bgenModule import *
|
||||||
|
|
227
Tools/bgen/bgen/bgenBuffer.py
Normal file
227
Tools/bgen/bgen/bgenBuffer.py
Normal file
|
@ -0,0 +1,227 @@
|
||||||
|
"""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.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
from bgenType import Type, InputOnlyMixIn, OutputOnlyMixIn, InputOnlyType, OutputOnlyType
|
||||||
|
from bgenOutput import *
|
||||||
|
|
||||||
|
|
||||||
|
# Map common types to their format characters
|
||||||
|
type2format = {
|
||||||
|
'long': 'l',
|
||||||
|
'int': 'i',
|
||||||
|
'short': 'h',
|
||||||
|
'char': 'b',
|
||||||
|
'unsigned long': 'l',
|
||||||
|
'unsigned int': 'i',
|
||||||
|
'unsigned short': 'h',
|
||||||
|
'unsigned char': 'b',
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# ----- PART 1: Fixed character buffers -----
|
||||||
|
|
||||||
|
|
||||||
|
class FixedInputOutputBufferType(InputOnlyType):
|
||||||
|
|
||||||
|
"""Fixed buffer -- passed as (inbuffer, outbuffer)."""
|
||||||
|
|
||||||
|
def __init__(self, size, datatype = 'char', sizetype = 'int', sizeformat = None):
|
||||||
|
self.typeName = "Buffer"
|
||||||
|
self.size = str(size)
|
||||||
|
self.datatype = datatype
|
||||||
|
self.sizetype = sizetype
|
||||||
|
self.sizeformat = sizeformat or type2format[sizetype]
|
||||||
|
|
||||||
|
def declare(self, name):
|
||||||
|
self.declareBuffer(name)
|
||||||
|
self.declareSize(name)
|
||||||
|
|
||||||
|
def declareBuffer(self, name):
|
||||||
|
self.declareInputBuffer(name)
|
||||||
|
self.declareOutputBuffer(name)
|
||||||
|
|
||||||
|
def declareInputBuffer(self, name):
|
||||||
|
Output("%s *%s__in__;", self.datatype, name)
|
||||||
|
|
||||||
|
def declareOutputBuffer(self, name):
|
||||||
|
Output("%s %s__out__[%s];", self.datatype, name, self.size)
|
||||||
|
|
||||||
|
def declareSize(self, name):
|
||||||
|
Output("%s %s__len__;", self.sizetype, name)
|
||||||
|
|
||||||
|
def getargsFormat(self):
|
||||||
|
# XXX This only works if the size is int-sized!!!
|
||||||
|
return "s#"
|
||||||
|
|
||||||
|
def getargsArgs(self, name):
|
||||||
|
return "&%s__in__, &%s__len__" % (name, name)
|
||||||
|
|
||||||
|
def getargsCheck(self, name):
|
||||||
|
Output("if (%s__len__ != %s)", name, self.size)
|
||||||
|
OutLbrace()
|
||||||
|
Output('PyErr_SetString(PyExc_TypeError, "buffer length should be %s");',
|
||||||
|
self.size)
|
||||||
|
Output("goto %s__error__;", name)
|
||||||
|
OutRbrace()
|
||||||
|
|
||||||
|
def passOutput(self, name):
|
||||||
|
return "%s__in__, %s__out__" % (name, name)
|
||||||
|
|
||||||
|
def mkvalueFormat(self):
|
||||||
|
return "s#"
|
||||||
|
|
||||||
|
def mkvalueArgs(self, name):
|
||||||
|
return "%s__out__, %s" % (name, self.size)
|
||||||
|
|
||||||
|
def cleanup(self, name):
|
||||||
|
DedentLevel()
|
||||||
|
Output(" %s__error__: ;", name)
|
||||||
|
IndentLevel()
|
||||||
|
|
||||||
|
|
||||||
|
class FixedCombinedInputOutputBufferType(FixedInputOutputBufferType):
|
||||||
|
|
||||||
|
"""Like fixed buffer -- but same parameter is input and output."""
|
||||||
|
|
||||||
|
def passOutput(self, name):
|
||||||
|
return "(%s *)memcpy(%s__out__, %s__in__, %s)" % \
|
||||||
|
(self.datatype, name, name, self.size)
|
||||||
|
|
||||||
|
|
||||||
|
class InputOnlyBufferMixIn(InputOnlyMixIn):
|
||||||
|
|
||||||
|
def declareOutputBuffer(self, name):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class OutputOnlyBufferMixIn(OutputOnlyMixIn):
|
||||||
|
|
||||||
|
def declareInputBuffer(self, name):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class FixedInputBufferType(InputOnlyBufferMixIn, FixedInputOutputBufferType):
|
||||||
|
|
||||||
|
"""Fixed size input buffer -- passed without size information.
|
||||||
|
|
||||||
|
Instantiate with the size as parameter.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def passInput(self, name):
|
||||||
|
return "%s__in__" % name
|
||||||
|
|
||||||
|
|
||||||
|
class FixedOutputBufferType(OutputOnlyBufferMixIn, FixedInputOutputBufferType):
|
||||||
|
|
||||||
|
"""Fixed size output buffer -- passed without size information.
|
||||||
|
|
||||||
|
Instantiate with the size as parameter.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def passOutput(self, name):
|
||||||
|
return "%s__out__" % name
|
||||||
|
|
||||||
|
|
||||||
|
class VarInputBufferType(FixedInputBufferType):
|
||||||
|
|
||||||
|
"""Variable size input buffer -- passed as (buffer, size).
|
||||||
|
|
||||||
|
Instantiate without size parameter.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, datatype = 'char', sizetype = 'int', sizeformat = None):
|
||||||
|
FixedInputBufferType.__init__(self, "0", datatype, sizetype, sizeformat)
|
||||||
|
|
||||||
|
def getargsCheck(self, name):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def passInput(self, name):
|
||||||
|
return "%s__in__, %s__len__" % (name, name)
|
||||||
|
|
||||||
|
|
||||||
|
# ----- PART 2: Structure buffers -----
|
||||||
|
|
||||||
|
|
||||||
|
class StructInputOutputBufferType(FixedInputOutputBufferType):
|
||||||
|
|
||||||
|
"""Structure buffer -- passed as a structure pointer.
|
||||||
|
|
||||||
|
Instantiate with the struct type as parameter.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, type):
|
||||||
|
FixedInputOutputBufferType.__init__(self, "sizeof(%s)" % type)
|
||||||
|
self.typeName = self.type = type
|
||||||
|
|
||||||
|
def declareInputBuffer(self, name):
|
||||||
|
Output("%s *%s__in__;", self.type, name)
|
||||||
|
|
||||||
|
def declareOutputBuffer(self, name):
|
||||||
|
Output("%s %s__out__;", self.type, name)
|
||||||
|
|
||||||
|
def getargsArgs(self, name):
|
||||||
|
return "(char **)&%s__in__, &%s__len__" % (name, name)
|
||||||
|
|
||||||
|
def passInput(self, name):
|
||||||
|
return "%s__in__" % name
|
||||||
|
|
||||||
|
def passOutput(self, name):
|
||||||
|
return "%s__in__, &%s__out__" % (name, name)
|
||||||
|
|
||||||
|
def mkvalueArgs(self, name):
|
||||||
|
return "(char *)&%s__out__, %s" % (name, self.size)
|
||||||
|
|
||||||
|
|
||||||
|
class StructCombinedInputOutputBufferType(StructInputOutputBufferType):
|
||||||
|
|
||||||
|
"""Like structure buffer -- but same parameter is input and output."""
|
||||||
|
|
||||||
|
def passOutput(self, name):
|
||||||
|
return "(%s *)memcpy((char *)%s__out__, (char *)%s__in__, %s)" % \
|
||||||
|
(self.type, name, name, self.size)
|
||||||
|
|
||||||
|
|
||||||
|
class StructInputBufferType(InputOnlyBufferMixIn, StructInputOutputBufferType):
|
||||||
|
|
||||||
|
"""Fixed size input buffer -- passed as a pointer to a structure.
|
||||||
|
|
||||||
|
Instantiate with the struct type as parameter.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
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__in__" % name
|
||||||
|
|
||||||
|
|
||||||
|
class StructOutputBufferType(OutputOnlyBufferMixIn, StructInputOutputBufferType):
|
||||||
|
|
||||||
|
"""Fixed size output buffer -- passed as a pointer to a structure.
|
||||||
|
|
||||||
|
Instantiate with the struct type as parameter.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def passOutput(self, name):
|
||||||
|
return "&%s__out__" % name
|
||||||
|
|
||||||
|
|
||||||
|
class ArrayOutputBufferType(OutputOnlyBufferMixIn, StructInputOutputBufferType):
|
||||||
|
|
||||||
|
"""Fixed size output buffer -- declared as a typedef, passed as an array.
|
||||||
|
|
||||||
|
Instantiate with the struct type as parameter.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def passOutput(self, name):
|
||||||
|
return "%s__out__" % name
|
|
@ -1,5 +1,6 @@
|
||||||
from bgenOutput import *
|
from bgenOutput import *
|
||||||
from bgenType import *
|
from bgenType import *
|
||||||
|
from bgenVariable import *
|
||||||
|
|
||||||
|
|
||||||
Error = "bgenGenerator.Error"
|
Error = "bgenGenerator.Error"
|
||||||
|
@ -14,6 +15,7 @@ INOUT = IN_OUT = "in-out"
|
||||||
class FunctionGenerator:
|
class FunctionGenerator:
|
||||||
|
|
||||||
def __init__(self, returntype, name, *argumentList):
|
def __init__(self, returntype, name, *argumentList):
|
||||||
|
print "<--", name
|
||||||
self.returntype = returntype
|
self.returntype = returntype
|
||||||
self.name = name
|
self.name = name
|
||||||
self.argumentList = []
|
self.argumentList = []
|
||||||
|
@ -51,8 +53,42 @@ class FunctionGenerator:
|
||||||
def reference(self, name = None):
|
def reference(self, name = None):
|
||||||
if name is None:
|
if name is None:
|
||||||
name = self.name
|
name = self.name
|
||||||
Output("{\"%s\", (PyCFunction)%s_%s, 1},",
|
docstring = self.docstring()
|
||||||
name, self.prefix, self.name)
|
Output("{\"%s\", (PyCFunction)%s_%s, 1,", name, self.prefix, self.name)
|
||||||
|
Output(" %s},", stringify(docstring))
|
||||||
|
|
||||||
|
def docstring(self):
|
||||||
|
import string
|
||||||
|
input = []
|
||||||
|
output = []
|
||||||
|
for arg in self.argumentList:
|
||||||
|
if arg.flags == ErrorMode or arg.flags == SelfMode:
|
||||||
|
continue
|
||||||
|
if arg.type == None:
|
||||||
|
str = 'void'
|
||||||
|
else:
|
||||||
|
if hasattr(arg.type, 'typeName'):
|
||||||
|
typeName = arg.type.typeName
|
||||||
|
if typeName is None: # Suppressed type
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
typeName = "?"
|
||||||
|
print "Nameless type", arg.type
|
||||||
|
|
||||||
|
str = typeName + ' ' + arg.name
|
||||||
|
if arg.mode in (InMode, InOutMode):
|
||||||
|
input.append(str)
|
||||||
|
if arg.mode in (InOutMode, OutMode):
|
||||||
|
output.append(str)
|
||||||
|
if not input:
|
||||||
|
instr = "()"
|
||||||
|
else:
|
||||||
|
instr = "(%s)" % string.joinfields(input, ", ")
|
||||||
|
if not output or output == ["void"]:
|
||||||
|
outstr = "None"
|
||||||
|
else:
|
||||||
|
outstr = "(%s)" % string.joinfields(output, ", ")
|
||||||
|
return instr + " -> " + outstr
|
||||||
|
|
||||||
def generate(self):
|
def generate(self):
|
||||||
print "-->", self.name
|
print "-->", self.name
|
||||||
|
@ -143,9 +179,7 @@ class FunctionGenerator:
|
||||||
tmp.reverse()
|
tmp.reverse()
|
||||||
for arg in tmp:
|
for arg in tmp:
|
||||||
if not arg: continue
|
if not arg: continue
|
||||||
if arg.flags == ErrorMode: continue
|
arg.cleanup()
|
||||||
if arg.mode in (OutMode, InOutMode):
|
|
||||||
arg.mkvalueCleanup()
|
|
||||||
Output("return _res;")
|
Output("return _res;")
|
||||||
|
|
||||||
def functiontrailer(self):
|
def functiontrailer(self):
|
||||||
|
@ -174,6 +208,18 @@ class ManualGenerator(FunctionGenerator):
|
||||||
Output("%s", self.body)
|
Output("%s", self.body)
|
||||||
self.functiontrailer()
|
self.functiontrailer()
|
||||||
|
|
||||||
|
_stringify_map = {'\n': '\\n', '\t': '\\t', '\r': '\\r', '\b': '\\b',
|
||||||
|
'\e': '\\e', '\a': '\\a', '\f': '\\f', '"': '\\"'}
|
||||||
|
def stringify(str):
|
||||||
|
if str is None: return "None"
|
||||||
|
res = '"'
|
||||||
|
map = _stringify_map
|
||||||
|
for c in str:
|
||||||
|
if map.has_key(c): res = res + map[c]
|
||||||
|
elif ' ' <= c <= '~': res = res + c
|
||||||
|
else: res = res + '\\%03o' % ord(c)
|
||||||
|
res = res + '"'
|
||||||
|
return res
|
||||||
|
|
||||||
def _test():
|
def _test():
|
||||||
void = None
|
void = None
|
||||||
|
|
108
Tools/bgen/bgen/bgenHeapBuffer.py
Normal file
108
Tools/bgen/bgen/bgenHeapBuffer.py
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
# Buffers allocated on the heap
|
||||||
|
|
||||||
|
from bgenOutput import *
|
||||||
|
from bgenType import OutputOnlyMixIn
|
||||||
|
from bgenBuffer import FixedInputOutputBufferType
|
||||||
|
|
||||||
|
|
||||||
|
class HeapInputOutputBufferType(FixedInputOutputBufferType):
|
||||||
|
|
||||||
|
"""Input-output buffer allocated on the heap -- passed as (inbuffer, outbuffer, size).
|
||||||
|
|
||||||
|
Instantiate without parameters.
|
||||||
|
Call from Python with input buffer.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, datatype = 'char', sizetype = 'int', sizeformat = None):
|
||||||
|
FixedInputOutputBufferType.__init__(self, "0", datatype, sizetype, sizeformat)
|
||||||
|
|
||||||
|
def declareOutputBuffer(self, name):
|
||||||
|
Output("%s *%s__out__;", self.datatype, name)
|
||||||
|
|
||||||
|
def getargsCheck(self, name):
|
||||||
|
Output("if ((%s__out__ = malloc(%s__len__)) == NULL)", name, name)
|
||||||
|
OutLbrace()
|
||||||
|
Output('PyErr_NoMemory();')
|
||||||
|
Output("goto %s__error__;", name)
|
||||||
|
OutRbrace()
|
||||||
|
|
||||||
|
def passOutput(self, name):
|
||||||
|
return "%s__in__, %s__out__, %s__len__" % (name, name, name)
|
||||||
|
|
||||||
|
def mkvalueArgs(self, name):
|
||||||
|
return "%s__out__, %s__len__" % (name, name)
|
||||||
|
|
||||||
|
def cleanup(self, name):
|
||||||
|
Output("free(%s__out__);", name)
|
||||||
|
FixedInputOutputBufferType.cleanup(self, name)
|
||||||
|
|
||||||
|
|
||||||
|
class VarHeapInputOutputBufferType(HeapInputOutputBufferType):
|
||||||
|
|
||||||
|
"""same as base class, but passed as (inbuffer, outbuffer, &size)"""
|
||||||
|
|
||||||
|
def passOutput(self, name):
|
||||||
|
return "%s__in__, %s__out__, &%s__len__" % (name, name, name)
|
||||||
|
|
||||||
|
|
||||||
|
class HeapCombinedInputOutputBufferType(HeapInputOutputBufferType):
|
||||||
|
|
||||||
|
"""same as base class, but passed as (inoutbuffer, size)"""
|
||||||
|
|
||||||
|
def passOutput(self, name):
|
||||||
|
return "(%s *)memcpy(%s__out__, %s__in__, %s__len__)" % \
|
||||||
|
(self.datatype, name, name, name)
|
||||||
|
|
||||||
|
|
||||||
|
class VarHeapCombinedInputOutputBufferType(HeapInputOutputBufferType):
|
||||||
|
|
||||||
|
"""same as base class, but passed as (inoutbuffer, &size)"""
|
||||||
|
|
||||||
|
def passOutput(self, name):
|
||||||
|
return "(%s *)memcpy(%s__out__, %s__in__, &%s__len__)" % \
|
||||||
|
(self.datatype, name, name, name)
|
||||||
|
|
||||||
|
|
||||||
|
class HeapOutputBufferType(OutputOnlyMixIn, HeapInputOutputBufferType):
|
||||||
|
|
||||||
|
"""Output buffer allocated on the heap -- passed as (buffer, size).
|
||||||
|
|
||||||
|
Instantiate without parameters.
|
||||||
|
Call from Python with buffer size.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def declareInputBuffer(self, name):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def getargsFormat(self):
|
||||||
|
return self.sizeformat
|
||||||
|
|
||||||
|
def getargsArgs(self, name):
|
||||||
|
return "&%s__len__" % name
|
||||||
|
|
||||||
|
def passOutput(self, name):
|
||||||
|
return "%s__out__, %s__len__" % (name, name)
|
||||||
|
|
||||||
|
|
||||||
|
class VarHeapOutputBufferType(HeapOutputBufferType):
|
||||||
|
|
||||||
|
"""Output buffer allocated on the heap -- passed as (buffer, &size).
|
||||||
|
|
||||||
|
Instantiate without parameters.
|
||||||
|
Call from Python with buffer size.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def passOutput(self, name):
|
||||||
|
return "%s__out__, &%s__len__" % (name, name)
|
||||||
|
|
||||||
|
|
||||||
|
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__out__, %s__len__, &%s__len__" % (name, name, name)
|
|
@ -5,13 +5,13 @@ class Module(GeneratorGroup):
|
||||||
|
|
||||||
def __init__(self, name, prefix = None,
|
def __init__(self, name, prefix = None,
|
||||||
includestuff = None,
|
includestuff = None,
|
||||||
initstuff = None,
|
finalstuff = None,
|
||||||
preinitstuff = None):
|
initstuff = None):
|
||||||
GeneratorGroup.__init__(self, prefix or name)
|
GeneratorGroup.__init__(self, prefix or name)
|
||||||
self.name = name
|
self.name = name
|
||||||
self.includestuff = includestuff
|
self.includestuff = includestuff
|
||||||
self.initstuff = initstuff
|
self.initstuff = initstuff
|
||||||
self.preinitstuff = preinitstuff
|
self.finalstuff = finalstuff
|
||||||
|
|
||||||
def addobject(self, od):
|
def addobject(self, od):
|
||||||
self.generators.append(od)
|
self.generators.append(od)
|
||||||
|
@ -29,9 +29,9 @@ class Module(GeneratorGroup):
|
||||||
|
|
||||||
GeneratorGroup.generate(self)
|
GeneratorGroup.generate(self)
|
||||||
|
|
||||||
if self.preinitstuff:
|
if self.finalstuff:
|
||||||
Output()
|
Output()
|
||||||
Output("%s", self.preinitstuff)
|
Output("%s", self.finalstuff)
|
||||||
|
|
||||||
Output()
|
Output()
|
||||||
Output("void init%s()", self.name)
|
Output("void init%s()", self.name)
|
||||||
|
@ -56,12 +56,17 @@ class Module(GeneratorGroup):
|
||||||
Output("static PyObject *%s;", self.errorname)
|
Output("static PyObject *%s;", self.errorname)
|
||||||
|
|
||||||
def createModuleVariables(self):
|
def createModuleVariables(self):
|
||||||
Output("""if ((%s = PyString_FromString("%s.Error")) == NULL ||""",
|
Output("""%s = %s;""", self.errorname, self.exceptionInitializer())
|
||||||
self.errorname, self.name)
|
Output("""if (%s == NULL ||""", self.errorname)
|
||||||
Output(""" PyDict_SetItemString(d, "Error", %s) != 0)""",
|
Output(""" PyDict_SetItemString(d, "Error", %s) != 0)""",
|
||||||
self.errorname)
|
self.errorname)
|
||||||
|
IndentLevel()
|
||||||
Output("""Py_FatalError("can't initialize %s.Error");""",
|
Output("""Py_FatalError("can't initialize %s.Error");""",
|
||||||
self.name)
|
self.name)
|
||||||
|
DedentLevel()
|
||||||
|
|
||||||
|
def exceptionInitializer(self):
|
||||||
|
return """PyString_FromString("%s.Error")""" % self.name
|
||||||
|
|
||||||
|
|
||||||
def _test():
|
def _test():
|
||||||
|
|
|
@ -2,15 +2,25 @@ from bgenOutput import *
|
||||||
from bgenGeneratorGroup import GeneratorGroup
|
from bgenGeneratorGroup import GeneratorGroup
|
||||||
|
|
||||||
class ObjectDefinition(GeneratorGroup):
|
class ObjectDefinition(GeneratorGroup):
|
||||||
|
"Spit out code that together defines a new Python object type"
|
||||||
|
|
||||||
def __init__(self, name, prefix, itselftype):
|
def __init__(self, name, prefix, itselftype):
|
||||||
import string
|
"""ObjectDefinition constructor. May be extended, but do not override.
|
||||||
|
|
||||||
|
- name: the object's official name, e.g. 'SndChannel'.
|
||||||
|
- prefix: the prefix used for the object's functions and data, e.g. 'SndCh'.
|
||||||
|
- itselftype: the C type actually contained in the object, e.g. 'SndChannelPtr'.
|
||||||
|
|
||||||
|
XXX For official Python data types, rules for the 'Py' prefix are a problem.
|
||||||
|
"""
|
||||||
|
|
||||||
GeneratorGroup.__init__(self, prefix or name)
|
GeneratorGroup.__init__(self, prefix or name)
|
||||||
self.name = name
|
self.name = name
|
||||||
self.itselftype = itselftype
|
self.itselftype = itselftype
|
||||||
self.objecttype = name + 'Object'
|
self.objecttype = name + 'Object'
|
||||||
self.typename = name + '_Type'
|
self.typename = name + '_Type'
|
||||||
self.argref = "" # set to "*" if arg to <type>_New should be pointer
|
self.argref = "" # set to "*" if arg to <type>_New should be pointer
|
||||||
|
self.static = "static " # set to "" to make <type>_New and <type>_Convert public
|
||||||
|
|
||||||
def add(self, g):
|
def add(self, g):
|
||||||
g.setselftype(self.objecttype, self.itselftype)
|
g.setselftype(self.objecttype, self.itselftype)
|
||||||
|
@ -25,17 +35,18 @@ class ObjectDefinition(GeneratorGroup):
|
||||||
|
|
||||||
OutHeader2("Object type " + self.name)
|
OutHeader2("Object type " + self.name)
|
||||||
|
|
||||||
Output("staticforward PyTypeObject %s;", self.typename)
|
sf = self.static and "staticforward "
|
||||||
|
Output("%sPyTypeObject %s;", sf, self.typename)
|
||||||
Output()
|
Output()
|
||||||
|
|
||||||
Output("#define %s_Check(x) ((x)->ob_type == &%s)",
|
Output("#define %s_Check(x) ((x)->ob_type == &%s)",
|
||||||
self.prefix, self.typename)
|
self.prefix, self.typename)
|
||||||
Output()
|
Output()
|
||||||
|
|
||||||
Output("typedef struct {")
|
Output("typedef struct %s {", self.objecttype)
|
||||||
IndentLevel()
|
IndentLevel()
|
||||||
Output("PyObject_HEAD")
|
Output("PyObject_HEAD")
|
||||||
Output("%s ob_itself;", self.itselftype)
|
self.outputStructMembers()
|
||||||
DedentLevel()
|
DedentLevel()
|
||||||
Output("} %s;", self.objecttype)
|
Output("} %s;", self.objecttype)
|
||||||
Output()
|
Output()
|
||||||
|
@ -56,8 +67,11 @@ class ObjectDefinition(GeneratorGroup):
|
||||||
|
|
||||||
OutHeader2("End object type " + self.name)
|
OutHeader2("End object type " + self.name)
|
||||||
|
|
||||||
|
def outputStructMembers(self):
|
||||||
|
Output("%s ob_itself;", self.itselftype)
|
||||||
|
|
||||||
def outputNew(self):
|
def outputNew(self):
|
||||||
Output("static PyObject *%s_New(itself)", self.prefix)
|
Output("%sPyObject *%s_New(itself)", self.static, self.prefix)
|
||||||
IndentLevel()
|
IndentLevel()
|
||||||
Output("const %s %sitself;", self.itselftype, self.argref)
|
Output("const %s %sitself;", self.itselftype, self.argref)
|
||||||
DedentLevel()
|
DedentLevel()
|
||||||
|
@ -66,28 +80,36 @@ class ObjectDefinition(GeneratorGroup):
|
||||||
self.outputCheckNewArg()
|
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)
|
self.outputInitStructMembers()
|
||||||
Output("return (PyObject *)it;")
|
Output("return (PyObject *)it;")
|
||||||
OutRbrace()
|
OutRbrace()
|
||||||
Output()
|
Output()
|
||||||
|
|
||||||
|
def outputInitStructMembers(self):
|
||||||
|
Output("it->ob_itself = %sitself;", self.argref)
|
||||||
|
|
||||||
def outputCheckNewArg(self):
|
def outputCheckNewArg(self):
|
||||||
pass
|
"Override this method to apply additional checks/conversions"
|
||||||
|
|
||||||
def outputConvert(self):
|
def outputConvert(self):
|
||||||
Output("""\
|
Output("%s%s_Convert(v, p_itself)", self.static, self.prefix)
|
||||||
static int %(prefix)s_Convert(v, p_itself)
|
IndentLevel()
|
||||||
PyObject *v;
|
Output("PyObject *v;")
|
||||||
%(itselftype)s *p_itself;
|
Output("%s *p_itself;", self.itselftype)
|
||||||
{
|
DedentLevel()
|
||||||
if (v == NULL || !%(prefix)s_Check(v)) {
|
OutLbrace()
|
||||||
PyErr_SetString(PyExc_TypeError, "%(name)s required");
|
self.outputCheckConvertArg()
|
||||||
return 0;
|
Output("if (!%s_Check(v))", self.prefix)
|
||||||
}
|
OutLbrace()
|
||||||
*p_itself = ((%(objecttype)s *)v)->ob_itself;
|
Output('PyErr_SetString(PyExc_TypeError, "%s required");', self.name)
|
||||||
return 1;
|
Output("return 0;")
|
||||||
}
|
OutRbrace()
|
||||||
""" % self.__dict__)
|
Output("*p_itself = ((%s *)v)->ob_itself;", self.objecttype)
|
||||||
|
Output("return 1;")
|
||||||
|
OutRbrace()
|
||||||
|
|
||||||
|
def outputCheckConvertArg(self):
|
||||||
|
"Override this method to apply additional conversions"
|
||||||
|
|
||||||
def outputDealloc(self):
|
def outputDealloc(self):
|
||||||
Output("static void %s_dealloc(self)", self.prefix)
|
Output("static void %s_dealloc(self)", self.prefix)
|
||||||
|
@ -95,11 +117,14 @@ static int %(prefix)s_Convert(v, p_itself)
|
||||||
Output("%s *self;", self.objecttype)
|
Output("%s *self;", self.objecttype)
|
||||||
DedentLevel()
|
DedentLevel()
|
||||||
OutLbrace()
|
OutLbrace()
|
||||||
self.outputFreeIt("self->ob_itself")
|
self.outputCleanupStructMembers()
|
||||||
Output("PyMem_DEL(self);")
|
Output("PyMem_DEL(self);")
|
||||||
OutRbrace()
|
OutRbrace()
|
||||||
Output()
|
Output()
|
||||||
|
|
||||||
|
def outputCleanupStructMembers(self):
|
||||||
|
self.outputFreeIt("self->ob_itself")
|
||||||
|
|
||||||
def outputFreeIt(self, name):
|
def outputFreeIt(self, name):
|
||||||
Output("/* Cleanup of %s goes here */", name)
|
Output("/* Cleanup of %s goes here */", name)
|
||||||
|
|
||||||
|
@ -126,7 +151,7 @@ static int %(prefix)s_Convert(v, p_itself)
|
||||||
Output()
|
Output()
|
||||||
|
|
||||||
def outputTypeObject(self):
|
def outputTypeObject(self):
|
||||||
Output("static PyTypeObject %s = {", self.typename)
|
Output("%sPyTypeObject %s = {", self.static, self.typename)
|
||||||
IndentLevel()
|
IndentLevel()
|
||||||
Output("PyObject_HEAD_INIT(&PyType_Type)")
|
Output("PyObject_HEAD_INIT(&PyType_Type)")
|
||||||
Output("0, /*ob_size*/")
|
Output("0, /*ob_size*/")
|
||||||
|
@ -140,3 +165,11 @@ static int %(prefix)s_Convert(v, p_itself)
|
||||||
Output("(setattrfunc) %s_setattr, /*tp_setattr*/", self.prefix)
|
Output("(setattrfunc) %s_setattr, /*tp_setattr*/", self.prefix)
|
||||||
DedentLevel()
|
DedentLevel()
|
||||||
Output("};")
|
Output("};")
|
||||||
|
|
||||||
|
|
||||||
|
class GlobalObjectDefinition(ObjectDefinition):
|
||||||
|
"Same as ObjectDefinition but exports its New and Create methods"
|
||||||
|
|
||||||
|
def __init__(self, name, prefix = None, itselftype = None):
|
||||||
|
ObjectDefinition.__init__(self, name, prefix or name, itselftype or name)
|
||||||
|
self.static = ""
|
||||||
|
|
|
@ -2,20 +2,41 @@
|
||||||
|
|
||||||
This should really be a class, but then everybody would be passing
|
This should really be a class, but then everybody would be passing
|
||||||
the output object to each other. I chose for the simpler approach
|
the output object to each other. I chose for the simpler approach
|
||||||
of a module with a global variable. Use SetOutputFile() to change
|
of a module with a global variable. Use SetOutputFile() or
|
||||||
the output file.
|
SetOutputFileName() to change the output file.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def SetOutputFile(file = None):
|
_NeedClose = 0
|
||||||
"""Call this with an open file object to make that the output file.
|
|
||||||
|
|
||||||
Call it without arguments to reset the output file to sys.stdout.
|
def SetOutputFile(file = None, needclose = 0):
|
||||||
|
"""Call this with an open file object to make it the output file.
|
||||||
|
|
||||||
|
Call it without arguments to close the current file (if necessary)
|
||||||
|
and reset it to sys.stdout.
|
||||||
|
If the second argument is true, the new file will be explicitly closed
|
||||||
|
on a subsequence call.
|
||||||
"""
|
"""
|
||||||
global _File
|
global _File, _NeedClose
|
||||||
|
if _NeedClose:
|
||||||
|
tmp = _File
|
||||||
|
_NeedClose = 0
|
||||||
|
_File = None
|
||||||
|
tmp.close()
|
||||||
if file is None:
|
if file is None:
|
||||||
import sys
|
import sys
|
||||||
file = sys.stdout
|
file = sys.stdout
|
||||||
_File = file
|
_File = file
|
||||||
|
_NeedClose = file and needclose
|
||||||
|
|
||||||
|
def SetOutputFileName(filename = None):
|
||||||
|
"""Call this with a filename to make it the output file.
|
||||||
|
|
||||||
|
Call it without arguments to close the current file (if necessary)
|
||||||
|
and reset it to sys.stdout.
|
||||||
|
"""
|
||||||
|
SetOutputFile()
|
||||||
|
if filename:
|
||||||
|
SetOutputFile(open(filename, 'w'), 1)
|
||||||
|
|
||||||
SetOutputFile() # Initialize _File
|
SetOutputFile() # Initialize _File
|
||||||
|
|
||||||
|
@ -34,7 +55,10 @@ def SetLevel(level):
|
||||||
_Level = level
|
_Level = level
|
||||||
|
|
||||||
def Output(format = "", *args):
|
def Output(format = "", *args):
|
||||||
"""Call this with a format string and arguments for the format.
|
VaOutput(format, args)
|
||||||
|
|
||||||
|
def VaOutput(format, args):
|
||||||
|
"""Call this with a format string and and argument tuple for the format.
|
||||||
|
|
||||||
A newline is always added. Each line in the output is indented
|
A newline is always added. Each line in the output is indented
|
||||||
to the proper indentation level -- even if the result of the
|
to the proper indentation level -- even if the result of the
|
||||||
|
@ -64,15 +88,38 @@ def IndentLevel(by = 1):
|
||||||
_Level = _Level + by
|
_Level = _Level + by
|
||||||
|
|
||||||
def DedentLevel(by = 1):
|
def DedentLevel(by = 1):
|
||||||
"""Decfrement the indentation level by one.
|
"""Decrement the indentation level by one.
|
||||||
|
|
||||||
When called with an argument, subtracts it from the indentation level.
|
When called with an argument, subtracts it from the indentation level.
|
||||||
"""
|
"""
|
||||||
IndentLevel(-by)
|
IndentLevel(-by)
|
||||||
|
|
||||||
def OutLbrace():
|
def OutIndent(format = "", *args):
|
||||||
"""Output a '{' on a line by itself and increase the indentation level."""
|
"""Combine Output() followed by IndentLevel().
|
||||||
Output("{")
|
|
||||||
|
If no text is given, acts like lone IndentLevel().
|
||||||
|
"""
|
||||||
|
if format: VaOutput(format, args)
|
||||||
|
IndentLevel()
|
||||||
|
|
||||||
|
def OutDedent(format = "", *args):
|
||||||
|
"""Combine Output() followed by DedentLevel().
|
||||||
|
|
||||||
|
If no text is given, acts like loneDedentLevel().
|
||||||
|
"""
|
||||||
|
if format: VaOutput(format, args)
|
||||||
|
DedentLevel()
|
||||||
|
|
||||||
|
def OutLbrace(format = "", *args):
|
||||||
|
"""Like Output, but add a '{' and increase the indentation level.
|
||||||
|
|
||||||
|
If no text is given a lone '{' is output.
|
||||||
|
"""
|
||||||
|
if format:
|
||||||
|
format = format + " {"
|
||||||
|
else:
|
||||||
|
format = "{"
|
||||||
|
VaOutput(format, args)
|
||||||
IndentLevel()
|
IndentLevel()
|
||||||
|
|
||||||
def OutRbrace():
|
def OutRbrace():
|
||||||
|
@ -95,22 +142,67 @@ def OutHeader2(text):
|
||||||
"""Output a level 2 header comment (uses '-' dashes)."""
|
"""Output a level 2 header comment (uses '-' dashes)."""
|
||||||
OutHeader(text, "-")
|
OutHeader(text, "-")
|
||||||
|
|
||||||
|
def Out(text):
|
||||||
|
"""Output multiline text that's internally indented.
|
||||||
|
|
||||||
|
Pass this a multiline character string. The whitespace before the
|
||||||
|
first nonblank line of the string will be subtracted from all lines.
|
||||||
|
The lines are then output using Output(), but without interpretation
|
||||||
|
of formatting (if you need formatting you can do it before the call).
|
||||||
|
Recommended use:
|
||||||
|
|
||||||
|
Out('''
|
||||||
|
int main(argc, argv)
|
||||||
|
int argc;
|
||||||
|
char *argv;
|
||||||
|
{
|
||||||
|
printf("Hello, world\\n");
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
''')
|
||||||
|
|
||||||
|
Caveat: the indentation must be consistent -- if you use three tabs
|
||||||
|
in the first line, (up to) three tabs are removed from following lines,
|
||||||
|
but a line beginning with 24 spaces is not trimmed at all. Don't use
|
||||||
|
this as a feature.
|
||||||
|
"""
|
||||||
|
# (Don't you love using triple quotes *inside* triple quotes? :-)
|
||||||
|
|
||||||
|
import string
|
||||||
|
lines = string.splitfields(text, '\n')
|
||||||
|
indent = ""
|
||||||
|
for line in lines:
|
||||||
|
if string.strip(line):
|
||||||
|
for c in line:
|
||||||
|
if c not in string.whitespace:
|
||||||
|
break
|
||||||
|
indent = indent + c
|
||||||
|
break
|
||||||
|
n = len(indent)
|
||||||
|
for line in lines:
|
||||||
|
if line[:n] == indent:
|
||||||
|
line = line[n:]
|
||||||
|
else:
|
||||||
|
for c in indent:
|
||||||
|
if line[:1] <> c: break
|
||||||
|
line = line[1:]
|
||||||
|
VaOutput("%s", line)
|
||||||
|
|
||||||
|
|
||||||
def _test():
|
def _test():
|
||||||
"""Test program. Run when the module is run as a script."""
|
"""Test program. Run when the module is run as a script."""
|
||||||
OutHeader1("test bgenOutput")
|
OutHeader1("test bgenOutput")
|
||||||
Output("""
|
Out("""
|
||||||
#include <Python.h>
|
#include <Python.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
""")
|
|
||||||
Output("main(argc, argv)")
|
main(argc, argv)
|
||||||
|
int argc;
|
||||||
|
char **argv;
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
""")
|
||||||
IndentLevel()
|
IndentLevel()
|
||||||
Output("int argc;")
|
|
||||||
Output("char **argv;")
|
|
||||||
DedentLevel()
|
|
||||||
OutLbrace()
|
|
||||||
Output("int i;")
|
|
||||||
Output()
|
|
||||||
Output("""\
|
Output("""\
|
||||||
/* Here are a few comment lines.
|
/* Here are a few comment lines.
|
||||||
Just to test indenting multiple lines.
|
Just to test indenting multiple lines.
|
||||||
|
|
59
Tools/bgen/bgen/bgenStackBuffer.py
Normal file
59
Tools/bgen/bgen/bgenStackBuffer.py
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
"""Buffers allocated on the stack."""
|
||||||
|
|
||||||
|
|
||||||
|
from bgenBuffer import FixedInputBufferType, FixedOutputBufferType
|
||||||
|
|
||||||
|
|
||||||
|
class StackOutputBufferType(FixedOutputBufferType):
|
||||||
|
|
||||||
|
"""Fixed output buffer allocated on the stack -- passed as (buffer, size).
|
||||||
|
|
||||||
|
Instantiate with the buffer size as parameter.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def passOutput(self, name):
|
||||||
|
return "%s__out__, %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__out__, &%s__len__" % (name, name)
|
||||||
|
|
||||||
|
def mkvalueArgs(self, name):
|
||||||
|
return "%s__out__, %s__len__" % (name, name)
|
||||||
|
|
||||||
|
|
||||||
|
class VarVarStackOutputBufferType(VarStackOutputBufferType):
|
||||||
|
|
||||||
|
"""Output buffer allocated on the stack -- passed as (buffer, size, &size).
|
||||||
|
|
||||||
|
Instantiate with the buffer size as parameter.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def passOutput(self, name):
|
||||||
|
return "%s__out__, %s__len__, &%s__len__" % (name, name, name)
|
||||||
|
|
||||||
|
|
||||||
|
class ReturnVarStackOutputBufferType(VarStackOutputBufferType):
|
||||||
|
|
||||||
|
"""Output buffer allocated on the stack -- passed as (buffer, size) -> size.
|
||||||
|
|
||||||
|
Instantiate with the buffer size as parameter.
|
||||||
|
The function's return value is the size.
|
||||||
|
(XXX Should have a way to suppress returning it separately, too.)
|
||||||
|
"""
|
||||||
|
|
||||||
|
def passOutput(self, name):
|
||||||
|
return "%s__out__, %s__len__" % (name, name)
|
||||||
|
|
||||||
|
def mkvalueArgs(self, name):
|
||||||
|
return "%s__out__, _rv" % name
|
64
Tools/bgen/bgen/bgenStringBuffer.py
Normal file
64
Tools/bgen/bgen/bgenStringBuffer.py
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
"""Buffers used to hold null-terminated strings."""
|
||||||
|
|
||||||
|
|
||||||
|
from bgenBuffer import FixedOutputBufferType
|
||||||
|
from bgenStackBuffer import StackOutputBufferType
|
||||||
|
from bgenHeapBuffer import HeapOutputBufferType
|
||||||
|
|
||||||
|
|
||||||
|
class StringBufferMixIn:
|
||||||
|
|
||||||
|
"""Mix-in class to create various string buffer types.
|
||||||
|
|
||||||
|
Strings are character arrays terminated by a null byte.
|
||||||
|
(For input, this is also covered by stringptr.)
|
||||||
|
For output, there are again three variants:
|
||||||
|
- Fixed: size is a constant given in the documentation; or
|
||||||
|
- 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 declareSize(self, name):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def getargsFormat(self):
|
||||||
|
return "s"
|
||||||
|
|
||||||
|
def getargsArgs(self, name):
|
||||||
|
return "&%s__in__" % name
|
||||||
|
|
||||||
|
def mkvalueFormat(self):
|
||||||
|
return "s"
|
||||||
|
|
||||||
|
def mkvalueArgs(self, name):
|
||||||
|
return "%s__out__" % name
|
||||||
|
|
||||||
|
|
||||||
|
class FixedOutputStringType(StringBufferMixIn, FixedOutputBufferType):
|
||||||
|
|
||||||
|
"""Null-terminated output string -- passed without size.
|
||||||
|
|
||||||
|
Instantiate with buffer size as parameter.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class StackOutputStringType(StringBufferMixIn, StackOutputBufferType):
|
||||||
|
|
||||||
|
"""Null-terminated output string -- passed as (buffer, size).
|
||||||
|
|
||||||
|
Instantiate with buffer size as parameter.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class HeapOutputStringType(StringBufferMixIn, HeapOutputBufferType):
|
||||||
|
|
||||||
|
"""Null-terminated output string -- passed as (buffer, size).
|
||||||
|
|
||||||
|
Instantiate without parameters.
|
||||||
|
Call from Python with buffer size.
|
||||||
|
"""
|
|
@ -1,22 +1,9 @@
|
||||||
"""Type and Variable classes and a modest collection of standard types."""
|
"""Type classes and a modest collection of standard types."""
|
||||||
|
|
||||||
|
|
||||||
from bgenOutput import *
|
from bgenOutput import *
|
||||||
|
|
||||||
|
|
||||||
# Values to represent argument transfer modes
|
|
||||||
InMode = 1 # input-only argument
|
|
||||||
OutMode = 2 # output-only argument
|
|
||||||
InOutMode = 3 # input-output argument
|
|
||||||
ModeMask = 3 # bits to keep for mode
|
|
||||||
|
|
||||||
|
|
||||||
# Special cases for mode/flags argument
|
|
||||||
# XXX This is still a mess!
|
|
||||||
SelfMode = 4+InMode # this is 'self' -- don't declare it
|
|
||||||
ReturnMode = 8+OutMode # this is the function return value
|
|
||||||
ErrorMode = 16+OutMode # this is an error status -- turn it into an exception
|
|
||||||
|
|
||||||
|
|
||||||
class Type:
|
class Type:
|
||||||
|
|
||||||
"""Define the various things you can do with a C type.
|
"""Define the various things you can do with a C type.
|
||||||
|
@ -106,8 +93,8 @@ class Type:
|
||||||
"""
|
"""
|
||||||
return name
|
return name
|
||||||
|
|
||||||
def mkvalueCleanup(self, name):
|
def cleanup(self, name):
|
||||||
"""Clean up if necessary after mkvalue().
|
"""Clean up if necessary.
|
||||||
|
|
||||||
This is normally empty; it may deallocate buffers etc.
|
This is normally empty; it may deallocate buffers etc.
|
||||||
"""
|
"""
|
||||||
|
@ -120,7 +107,7 @@ class InputOnlyMixIn:
|
||||||
|
|
||||||
"Mix-in class to boobytrap passOutput"
|
"Mix-in class to boobytrap passOutput"
|
||||||
|
|
||||||
def passOutput(self):
|
def passOutput(self, name):
|
||||||
raise RuntimeError, "this type can only be used for input parameters"
|
raise RuntimeError, "this type can only be used for input parameters"
|
||||||
|
|
||||||
class InputOnlyType(InputOnlyMixIn, Type):
|
class InputOnlyType(InputOnlyMixIn, Type):
|
||||||
|
@ -131,7 +118,7 @@ class OutputOnlyMixIn:
|
||||||
|
|
||||||
"Mix-in class to boobytrap passInput"
|
"Mix-in class to boobytrap passInput"
|
||||||
|
|
||||||
def passInput(self):
|
def passInput(self, name):
|
||||||
raise RuntimeError, "this type can only be used for output parameters"
|
raise RuntimeError, "this type can only be used for output parameters"
|
||||||
|
|
||||||
class OutputOnlyType(OutputOnlyMixIn, Type):
|
class OutputOnlyType(OutputOnlyMixIn, Type):
|
||||||
|
@ -145,13 +132,14 @@ 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")
|
||||||
|
unsigned_long = Type("unsigned long", "l")
|
||||||
float = Type("float", "f")
|
float = Type("float", "f")
|
||||||
double = Type("double", "d")
|
double = Type("double", "d")
|
||||||
|
|
||||||
|
|
||||||
# The most common use of character pointers is a null-terminated string.
|
# 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 *,
|
# For input, this is easy. For output, and for other uses of char *,
|
||||||
# see the various Buffer types below.
|
# see the module bgenBuffer.
|
||||||
stringptr = InputOnlyType("char*", "s")
|
stringptr = InputOnlyType("char*", "s")
|
||||||
|
|
||||||
|
|
||||||
|
@ -170,6 +158,7 @@ class FakeType(InputOnlyType):
|
||||||
|
|
||||||
def __init__(self, substitute):
|
def __init__(self, substitute):
|
||||||
self.substitute = substitute
|
self.substitute = substitute
|
||||||
|
self.typeName = None # Don't show this argument in __doc__ string
|
||||||
|
|
||||||
def declare(self, name):
|
def declare(self, name):
|
||||||
pass
|
pass
|
||||||
|
@ -184,333 +173,49 @@ class FakeType(InputOnlyType):
|
||||||
return self.substitute
|
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)
|
|
||||||
|
|
||||||
|
|
||||||
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):
|
|
||||||
return "s#"
|
|
||||||
|
|
||||||
def getargsArgs(self, name):
|
|
||||||
return "&%s, &%s__len__" % (name, name)
|
|
||||||
|
|
||||||
def getargsCheck(self, name):
|
|
||||||
Output("if (%s__len__ != %s)", name, self.size)
|
|
||||||
OutLbrace()
|
|
||||||
Output('PyErr_SetString(PyExc_TypeError, "buffer length should be %s");',
|
|
||||||
self.size)
|
|
||||||
Output('return NULL;') # XXX should do a goto
|
|
||||||
OutRbrace()
|
|
||||||
|
|
||||||
def passInput(self, name):
|
|
||||||
return name
|
|
||||||
|
|
||||||
|
|
||||||
class FixedOutputBufferType(OutputOnlyMixIn, FixedBufferType):
|
|
||||||
|
|
||||||
"""Fixed size output buffer -- passed without size information.
|
|
||||||
|
|
||||||
Instantiate with the size as parameter.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def declareBuffer(self, name):
|
|
||||||
Output("char %s[%s];", name, self.size)
|
|
||||||
|
|
||||||
def passOutput(self, name):
|
|
||||||
return name
|
|
||||||
|
|
||||||
def mkvalueFormat(self):
|
|
||||||
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):
|
|
||||||
return "%s, %s__len__" % (name, name)
|
|
||||||
|
|
||||||
|
|
||||||
class VarVarStackOutputBufferType(VarStackOutputBufferType):
|
|
||||||
|
|
||||||
"""Output buffer allocated on the stack -- passed as (buffer, size, &size).
|
|
||||||
|
|
||||||
Instantiate with the buffer size as parameter.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def passOutput(self, name):
|
|
||||||
return "%s, %s__len__, &%s__len__" % (name, name, name)
|
|
||||||
|
|
||||||
|
|
||||||
class HeapOutputBufferType(FixedOutputBufferType):
|
|
||||||
|
|
||||||
"""Output buffer allocated on the heap -- passed as (buffer, size).
|
|
||||||
|
|
||||||
Instantiate without parameters.
|
|
||||||
Call from Python with buffer size.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def declareBuffer(self, name):
|
|
||||||
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):
|
|
||||||
return "%s, %s__len__" % (name, name)
|
|
||||||
|
|
||||||
def mkvalueCleanup(self, name):
|
|
||||||
Output("free(%s);", name)
|
|
||||||
DedentLevel()
|
|
||||||
Output(" %s__error__: ;", name);
|
|
||||||
IndentLevel()
|
|
||||||
|
|
||||||
|
|
||||||
class VarHeapOutputBufferType(HeapOutputBufferType):
|
|
||||||
|
|
||||||
"""Output buffer allocated on the heap -- passed as (buffer, &size).
|
|
||||||
|
|
||||||
Instantiate without parameters.
|
|
||||||
Call from Python with buffer size.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def passOutput(self, name):
|
|
||||||
return "%s, &%s__len__" % (name, name)
|
|
||||||
|
|
||||||
|
|
||||||
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):
|
|
||||||
return "s"
|
|
||||||
|
|
||||||
def mkvalueArgs(self, name):
|
|
||||||
return name
|
|
||||||
|
|
||||||
|
|
||||||
class FixedOutputStringType(StringBufferType, FixedOutputBufferType):
|
|
||||||
|
|
||||||
"""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):
|
class OpaqueType(Type):
|
||||||
|
|
||||||
"""A type represented by an opaque object type, always passed by address.
|
"""A type represented by an opaque object type, always passed by address.
|
||||||
|
|
||||||
Instantiate with the type name, and optional an object type name whose
|
Instantiate with the type name and the names of the new and convert procs.
|
||||||
New/Convert functions will be used.
|
If fewer than three arguments are passed, the second argument is used
|
||||||
|
to derive the new and convert procs by appending _New and _Convert; it
|
||||||
|
defaults to the first argument.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, name, sameAs = None):
|
def __init__(self, name, arg = None, extra = None):
|
||||||
self.typeName = name
|
self.typeName = name
|
||||||
self.sameAs = sameAs or name
|
if extra is None:
|
||||||
|
# Two arguments (name, usetype) or one (name)
|
||||||
|
arg = arg or name
|
||||||
|
self.new = arg + '_New'
|
||||||
|
self.convert = arg + '_Convert'
|
||||||
|
else:
|
||||||
|
# Three arguments (name, new, convert)
|
||||||
|
self.new = arg
|
||||||
|
self.convert = extra
|
||||||
|
|
||||||
def getargsFormat(self):
|
def getargsFormat(self):
|
||||||
return 'O&'
|
return "O&"
|
||||||
|
|
||||||
def getargsArgs(self, name):
|
def getargsArgs(self, name):
|
||||||
return "%s_Convert, &%s" % (self.sameAs, name)
|
return "%s, &%s" % (self.convert, name)
|
||||||
|
|
||||||
def passInput(self, name):
|
def passInput(self, name):
|
||||||
return "&%s" % name
|
return "&%s" % name
|
||||||
|
|
||||||
def mkvalueFormat(self):
|
def mkvalueFormat(self):
|
||||||
return 'O&'
|
return "O&"
|
||||||
|
|
||||||
def mkvalueArgs(self, name):
|
def mkvalueArgs(self, name):
|
||||||
return "%s_New, &%s" % (self.sameAs, name)
|
return "%s, &%s" % (self.new, name)
|
||||||
|
|
||||||
|
|
||||||
class OpaqueByValueType(OpaqueType):
|
class OpaqueByValueType(OpaqueType):
|
||||||
|
|
||||||
"""A type represented by an opaque object type, on input passed BY VALUE.
|
"""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
|
Instantiate with the type name, and optionally an object type name whose
|
||||||
New/Convert functions will be used.
|
New/Convert functions will be used.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@ -518,7 +223,7 @@ class OpaqueByValueType(OpaqueType):
|
||||||
return name
|
return name
|
||||||
|
|
||||||
def mkvalueArgs(self, name):
|
def mkvalueArgs(self, name):
|
||||||
return "%s_New, %s" % (self.sameAs, name)
|
return "%s, %s" % (self.new, name)
|
||||||
|
|
||||||
|
|
||||||
class OpaqueArrayType(OpaqueByValueType):
|
class OpaqueArrayType(OpaqueByValueType):
|
||||||
|
@ -530,80 +235,7 @@ class OpaqueArrayType(OpaqueByValueType):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def getargsArgs(self, name):
|
def getargsArgs(self, name):
|
||||||
return "%s_Convert, &%s" % (self.sameAs, name)
|
return "%s, %s" % (self.convert, name)
|
||||||
|
|
||||||
def passOutput(self, name):
|
def passOutput(self, name):
|
||||||
return name
|
return name
|
||||||
|
|
||||||
|
|
||||||
class Variable:
|
|
||||||
|
|
||||||
"""A Variable holds a type, a name, a transfer mode and flags.
|
|
||||||
|
|
||||||
Most of its methods call the correponding type method with the
|
|
||||||
variable name.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, type, name = None, flags = InMode):
|
|
||||||
"""Call with a type, a name and flags.
|
|
||||||
|
|
||||||
If name is None, it muse be set later.
|
|
||||||
flags defaults to InMode.
|
|
||||||
"""
|
|
||||||
self.type = type
|
|
||||||
self.name = name
|
|
||||||
self.flags = flags
|
|
||||||
self.mode = flags & ModeMask
|
|
||||||
|
|
||||||
def declare(self):
|
|
||||||
"""Declare the variable if necessary.
|
|
||||||
|
|
||||||
If it is "self", it is not declared.
|
|
||||||
"""
|
|
||||||
if self.flags != SelfMode:
|
|
||||||
self.type.declare(self.name)
|
|
||||||
|
|
||||||
def getargsFormat(self):
|
|
||||||
"""Call the type's getargsFormatmethod."""
|
|
||||||
return self.type.getargsFormat()
|
|
||||||
|
|
||||||
def getargsArgs(self):
|
|
||||||
"""Call the type's getargsArgsmethod."""
|
|
||||||
return self.type.getargsArgs(self.name)
|
|
||||||
|
|
||||||
def getargsCheck(self):
|
|
||||||
return self.type.getargsCheck(self.name)
|
|
||||||
|
|
||||||
def passArgument(self):
|
|
||||||
"""Return the string required to pass the variable as argument.
|
|
||||||
|
|
||||||
For "in" arguments, return the variable name.
|
|
||||||
For "out" and "in out" arguments,
|
|
||||||
return its name prefixed with "&".
|
|
||||||
"""
|
|
||||||
if self.mode == InMode:
|
|
||||||
return self.type.passInput(self.name)
|
|
||||||
if self.mode in (OutMode, InOutMode):
|
|
||||||
return self.type.passOutput(self.name)
|
|
||||||
# XXX Shouldn't get here
|
|
||||||
return "/*mode?*/" + self.type.passInput(self.name)
|
|
||||||
|
|
||||||
def errorCheck(self):
|
|
||||||
"""Check for an error if necessary.
|
|
||||||
|
|
||||||
This only generates code if the variable's mode is ErrorMode.
|
|
||||||
"""
|
|
||||||
if self.flags == ErrorMode:
|
|
||||||
self.type.errorCheck(self.name)
|
|
||||||
|
|
||||||
def mkvalueFormat (self):
|
|
||||||
"""Call the type's mkvalueFormatmethod."""
|
|
||||||
return self.type.mkvalueFormat()
|
|
||||||
|
|
||||||
def mkvalueArgs(self):
|
|
||||||
"""Call the type's mkvalueArgs method."""
|
|
||||||
return self.type.mkvalueArgs(self.name)
|
|
||||||
|
|
||||||
def mkvalueCleanup(self):
|
|
||||||
"""Call the type's mkvalueCleanup method."""
|
|
||||||
return self.type.mkvalueCleanup(self.name)
|
|
||||||
|
|
88
Tools/bgen/bgen/bgenVariable.py
Normal file
88
Tools/bgen/bgen/bgenVariable.py
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
"""Variables, arguments and argument transfer modes etc."""
|
||||||
|
|
||||||
|
|
||||||
|
# Values to represent argument transfer modes
|
||||||
|
InMode = 1 # input-only argument
|
||||||
|
OutMode = 2 # output-only argument
|
||||||
|
InOutMode = 3 # input-output argument
|
||||||
|
ModeMask = 3 # bits to keep for mode
|
||||||
|
|
||||||
|
|
||||||
|
# Special cases for mode/flags argument
|
||||||
|
# XXX This is still a mess!
|
||||||
|
SelfMode = 4+InMode # this is 'self' -- don't declare it
|
||||||
|
ReturnMode = 8+OutMode # this is the function return value
|
||||||
|
ErrorMode = 16+OutMode # this is an error status -- turn it into an exception
|
||||||
|
|
||||||
|
|
||||||
|
class Variable:
|
||||||
|
|
||||||
|
"""A Variable holds a type, a name, a transfer mode and flags.
|
||||||
|
|
||||||
|
Most of its methods call the correponding type method with the
|
||||||
|
variable name.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, type, name = None, flags = InMode):
|
||||||
|
"""Call with a type, a name and flags.
|
||||||
|
|
||||||
|
If name is None, it muse be set later.
|
||||||
|
flags defaults to InMode.
|
||||||
|
"""
|
||||||
|
self.type = type
|
||||||
|
self.name = name
|
||||||
|
self.flags = flags
|
||||||
|
self.mode = flags & ModeMask
|
||||||
|
|
||||||
|
def declare(self):
|
||||||
|
"""Declare the variable if necessary.
|
||||||
|
|
||||||
|
If it is "self", it is not declared.
|
||||||
|
"""
|
||||||
|
if self.flags != SelfMode:
|
||||||
|
self.type.declare(self.name)
|
||||||
|
|
||||||
|
def getargsFormat(self):
|
||||||
|
"""Call the type's getargsFormatmethod."""
|
||||||
|
return self.type.getargsFormat()
|
||||||
|
|
||||||
|
def getargsArgs(self):
|
||||||
|
"""Call the type's getargsArgsmethod."""
|
||||||
|
return self.type.getargsArgs(self.name)
|
||||||
|
|
||||||
|
def getargsCheck(self):
|
||||||
|
return self.type.getargsCheck(self.name)
|
||||||
|
|
||||||
|
def passArgument(self):
|
||||||
|
"""Return the string required to pass the variable as argument.
|
||||||
|
|
||||||
|
For "in" arguments, return the variable name.
|
||||||
|
For "out" and "in out" arguments,
|
||||||
|
return its name prefixed with "&".
|
||||||
|
"""
|
||||||
|
if self.mode == InMode:
|
||||||
|
return self.type.passInput(self.name)
|
||||||
|
if self.mode in (OutMode, InOutMode):
|
||||||
|
return self.type.passOutput(self.name)
|
||||||
|
# XXX Shouldn't get here
|
||||||
|
return "/*mode?*/" + self.type.passInput(self.name)
|
||||||
|
|
||||||
|
def errorCheck(self):
|
||||||
|
"""Check for an error if necessary.
|
||||||
|
|
||||||
|
This only generates code if the variable's mode is ErrorMode.
|
||||||
|
"""
|
||||||
|
if self.flags == ErrorMode:
|
||||||
|
self.type.errorCheck(self.name)
|
||||||
|
|
||||||
|
def mkvalueFormat (self):
|
||||||
|
"""Call the type's mkvalueFormat method."""
|
||||||
|
return self.type.mkvalueFormat()
|
||||||
|
|
||||||
|
def mkvalueArgs(self):
|
||||||
|
"""Call the type's mkvalueArgs method."""
|
||||||
|
return self.type.mkvalueArgs(self.name)
|
||||||
|
|
||||||
|
def cleanup(self):
|
||||||
|
"""Call the type's cleanup method."""
|
||||||
|
return self.type.cleanup(self.name)
|
140
Tools/bgen/bgen/macsupport.py
Normal file
140
Tools/bgen/bgen/macsupport.py
Normal file
|
@ -0,0 +1,140 @@
|
||||||
|
"""\
|
||||||
|
Augment the "bgen" package with definitions that are useful on the Apple Macintosh.
|
||||||
|
|
||||||
|
Intended usage is "from macsupport import *" -- this implies all bgen's goodies.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
# Import everything from bgen (for ourselves as well as for re-export)
|
||||||
|
from bgen import *
|
||||||
|
|
||||||
|
|
||||||
|
# Simple types
|
||||||
|
Boolean = Type("Boolean", "b")
|
||||||
|
SignedByte = Type("SignedByte", "b")
|
||||||
|
ScriptCode = Type("ScriptCode", "h")
|
||||||
|
Size = Type("Size", "l")
|
||||||
|
Style = Type("Style", "b")
|
||||||
|
|
||||||
|
# Pascal strings
|
||||||
|
ConstStr255Param = OpaqueArrayType("Str255", "PyMac_BuildStr255", "PyMac_GetStr255")
|
||||||
|
Str255 = OpaqueArrayType("Str255", "PyMac_BuildStr255", "PyMac_GetStr255")
|
||||||
|
|
||||||
|
# File System Specifications
|
||||||
|
FSSpec_ptr = OpaqueType("FSSpec", "PyMac_BuildFSSpec", "PyMac_GetFSSpec")
|
||||||
|
|
||||||
|
# OSType and ResType: 4-byte character strings
|
||||||
|
def OSTypeType(typename):
|
||||||
|
return OpaqueByValueType(typename, "PyMac_BuildOSType", "PyMac_GetOSType")
|
||||||
|
OSType = OSTypeType("OSType")
|
||||||
|
ResType = OSTypeType("ResType")
|
||||||
|
|
||||||
|
# Handles (always resources in our case)
|
||||||
|
Handle = OpaqueByValueType("Handle", "ResObj")
|
||||||
|
MenuHandle = OpaqueByValueType("MenuHandle", "MenuObj")
|
||||||
|
ControlHandle = OpaqueByValueType("ControlHandle", "CtlObj")
|
||||||
|
|
||||||
|
# Windows and Dialogs
|
||||||
|
WindowPtr = OpaqueByValueType("WindowPtr", "WinObj")
|
||||||
|
DialogPtr = OpaqueByValueType("DialogPtr", "DlgObj")
|
||||||
|
|
||||||
|
# NULL pointer passed in as optional storage -- not present in Python version
|
||||||
|
NullStorage = FakeType("(void *)0")
|
||||||
|
|
||||||
|
# Quickdraw data types
|
||||||
|
Rect = Rect_ptr = OpaqueType("Rect", "PyMac_BuildRect", "PyMac_GetRect")
|
||||||
|
Point = OpaqueByValueType("Point", "PyMac_BuildPoint", "PyMac_GetPoint")
|
||||||
|
|
||||||
|
# Event records
|
||||||
|
EventRecord = OpaqueType("EventRecord", "PyMac_BuildEventRecord", "PyMac_GetEventRecord")
|
||||||
|
EventRecord_ptr = EventRecord
|
||||||
|
|
||||||
|
# OSErr is special because it is turned into an exception
|
||||||
|
# (Could do this with less code using a variant of mkvalue("O&")?)
|
||||||
|
class OSErrType(Type):
|
||||||
|
def errorCheck(self, name):
|
||||||
|
Output("if (%s != noErr) return PyMac_Error(%s);", name, name)
|
||||||
|
self.used = 1
|
||||||
|
OSErr = OSErrType("OSErr", 'h')
|
||||||
|
|
||||||
|
|
||||||
|
# Various buffer types
|
||||||
|
|
||||||
|
InBuffer = VarInputBufferType('char', 'long', 'l') # (buf, len)
|
||||||
|
|
||||||
|
InOutBuffer = HeapInputOutputBufferType('char', 'long', 'l') # (inbuf, outbuf, len)
|
||||||
|
VarInOutBuffer = VarHeapInputOutputBufferType('char', 'long', 'l') # (inbuf, outbuf, &len)
|
||||||
|
|
||||||
|
OutBuffer = HeapOutputBufferType('char', 'long', 'l') # (buf, len)
|
||||||
|
VarOutBuffer = VarHeapOutputBufferType('char', 'long', 'l') # (buf, &len)
|
||||||
|
VarVarOutBuffer = VarVarHeapOutputBufferType('char', 'long', 'l') # (buf, len, &len)
|
||||||
|
|
||||||
|
|
||||||
|
# Predefine various pieces of program text to be passed to Module() later:
|
||||||
|
|
||||||
|
# Stuff added immediately after the system include files
|
||||||
|
includestuff = """
|
||||||
|
#define SystemSevenOrLater 1
|
||||||
|
|
||||||
|
#include "macglue.h"
|
||||||
|
#include <Memory.h>
|
||||||
|
#include <Dialogs.h>
|
||||||
|
#include <Menus.h>
|
||||||
|
#include <Controls.h>
|
||||||
|
|
||||||
|
extern PyObject *ResObj_New(Handle);
|
||||||
|
extern int ResObj_Convert(PyObject *, Handle *);
|
||||||
|
|
||||||
|
extern PyObject *WinObj_New(WindowPtr);
|
||||||
|
extern int WinObj_Convert(PyObject *, WindowPtr *);
|
||||||
|
|
||||||
|
extern PyObject *DlgObj_New(DialogPtr);
|
||||||
|
extern int DlgObj_Convert(PyObject *, DialogPtr *);
|
||||||
|
extern PyTypeObject Dialog_Type;
|
||||||
|
#define DlgObj_Check(x) ((x)->ob_type == &Dialog_Type)
|
||||||
|
|
||||||
|
extern PyObject *MenuObj_New(MenuHandle);
|
||||||
|
extern int MenuObj_Convert(PyObject *, MenuHandle *);
|
||||||
|
|
||||||
|
extern PyObject *CtlObj_New(ControlHandle);
|
||||||
|
extern int CtlObj_Convert(PyObject *, ControlHandle *);
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Stuff added just before the module's init function
|
||||||
|
finalstuff = """
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Stuff added inside the module's init function
|
||||||
|
initstuff = """
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
# Generator classes with a twist -- if the function returns OSErr,
|
||||||
|
# its mode is manipulated so that it turns into an exception or disappears
|
||||||
|
# (and its name is changed to _err, for documentation purposes).
|
||||||
|
# This requires that the OSErr type (defined above) has a non-trivial
|
||||||
|
# errorCheck method.
|
||||||
|
class OSErrMixIn:
|
||||||
|
"Mix-in class to treat OSErr return values special"
|
||||||
|
def makereturnvar(self):
|
||||||
|
if self.returntype is OSErr:
|
||||||
|
return Variable(self.returntype, "_err", ErrorMode)
|
||||||
|
else:
|
||||||
|
return Variable(self.returntype, "_rv", OutMode)
|
||||||
|
|
||||||
|
class OSErrFunctionGenerator(OSErrMixIn, FunctionGenerator): pass
|
||||||
|
class OSErrMethodGenerator(OSErrMixIn, MethodGenerator): pass
|
||||||
|
|
||||||
|
|
||||||
|
class MacModule(Module):
|
||||||
|
"Subclass which gets the exception initializer from macglue.c"
|
||||||
|
def exceptionInitializer(self):
|
||||||
|
return "PyMac_GetOSErrException()"
|
||||||
|
|
||||||
|
_SetOutputFileName = SetOutputFileName # Save original
|
||||||
|
def SetOutputFileName(file = None):
|
||||||
|
"Set the output file name and set its creator&type to KAHL&TEXT"
|
||||||
|
_SetOutputFileName(file)
|
||||||
|
if file:
|
||||||
|
import MacOS
|
||||||
|
MacOS.SetCreatorAndType(file, 'KAHL', 'TEXT')
|
373
Tools/bgen/bgen/scantools.py
Normal file
373
Tools/bgen/bgen/scantools.py
Normal file
|
@ -0,0 +1,373 @@
|
||||||
|
"""\
|
||||||
|
Tools for scanning header files in search of function prototypes.
|
||||||
|
|
||||||
|
Often, the function prototypes in header files contain enough information
|
||||||
|
to automatically generate (or reverse-engineer) interface specifications
|
||||||
|
from them. The conventions used are very vendor specific, but once you've
|
||||||
|
figured out what they are they are often a great help, and it sure beats
|
||||||
|
manually entering the interface specifications. (These are needed to generate
|
||||||
|
the glue used to access the functions from Python.)
|
||||||
|
|
||||||
|
In order to make this class useful, almost every component can be overridden.
|
||||||
|
The defaults are (currently) tuned to scanning Apple Macintosh header files,
|
||||||
|
although most Mac specific details are contained in header-specific subclasses.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import regex
|
||||||
|
import regsub
|
||||||
|
import string
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
import fnmatch
|
||||||
|
from types import *
|
||||||
|
try:
|
||||||
|
import MacOS
|
||||||
|
except ImportError:
|
||||||
|
MacOS = None
|
||||||
|
|
||||||
|
# Default preferences
|
||||||
|
CREATOR = 'KAHL' # My favorite text editor on the Mac
|
||||||
|
INCLUDEDIR = "D:Development:THINK C:Mac #includes:Apple #includes:"
|
||||||
|
|
||||||
|
|
||||||
|
Error = "scantools.Error"
|
||||||
|
|
||||||
|
class Scanner:
|
||||||
|
|
||||||
|
def __init__(self, input = None, output = None, defsoutput = None):
|
||||||
|
self.initsilent()
|
||||||
|
self.initblacklists()
|
||||||
|
self.initrepairinstructions()
|
||||||
|
self.initpaths()
|
||||||
|
self.initfiles()
|
||||||
|
self.initpatterns()
|
||||||
|
self.compilepatterns()
|
||||||
|
self.initosspecifics()
|
||||||
|
if output:
|
||||||
|
self.setoutput(output, defsoutput)
|
||||||
|
if input:
|
||||||
|
self.setinput(input)
|
||||||
|
|
||||||
|
def initsilent(self):
|
||||||
|
self.silent = 0
|
||||||
|
|
||||||
|
def error(self, format, *args):
|
||||||
|
if self.silent >= 0:
|
||||||
|
print format%args
|
||||||
|
|
||||||
|
def report(self, format, *args):
|
||||||
|
if not self.silent:
|
||||||
|
print format%args
|
||||||
|
|
||||||
|
def initblacklists(self):
|
||||||
|
self.blacklistnames = self.makeblacklistnames()
|
||||||
|
self.blacklisttypes = ["unknown"] + self.makeblacklisttypes()
|
||||||
|
|
||||||
|
def makeblacklistnames(self):
|
||||||
|
return []
|
||||||
|
|
||||||
|
def makeblacklisttypes(self):
|
||||||
|
return []
|
||||||
|
|
||||||
|
def initrepairinstructions(self):
|
||||||
|
self.repairinstructions = self.makerepairinstructions()
|
||||||
|
|
||||||
|
def makerepairinstructions(self):
|
||||||
|
return []
|
||||||
|
|
||||||
|
def initfiles(self):
|
||||||
|
self.specmine = 0
|
||||||
|
self.defsmine = 0
|
||||||
|
self.scanmine = 0
|
||||||
|
self.specfile = sys.stdout
|
||||||
|
self.defsfile = None
|
||||||
|
self.scanfile = sys.stdin
|
||||||
|
self.lineno = 0
|
||||||
|
self.line = ""
|
||||||
|
|
||||||
|
def initpaths(self):
|
||||||
|
self.includepath = [':', INCLUDEDIR]
|
||||||
|
|
||||||
|
def initpatterns(self):
|
||||||
|
self.head_pat = "^pascal[ \t]+" # XXX Mac specific!
|
||||||
|
self.tail_pat = "[);]"
|
||||||
|
self.whole_pat = "\(<type>[a-zA-Z0-9_]+\)[ \t\n]+" + \
|
||||||
|
"\(<name>[a-zA-Z0-9_]+\)[ \t\n]*(\(<args>[^()]*\))"
|
||||||
|
self.sym_pat = "^[ \t]*\(<name>[a-zA-Z0-9_]+\)[ \t]*=" + \
|
||||||
|
"[ \t]*\(<defn>[-0-9'\"][^\t\n,]*\),?"
|
||||||
|
self.asplit_pat = "^\(<type>.*[^a-zA-Z0-9_]\)\(<name>[a-zA-Z0-9_]+\)$"
|
||||||
|
|
||||||
|
def compilepatterns(self):
|
||||||
|
for name in dir(self):
|
||||||
|
if name[-4:] == "_pat":
|
||||||
|
pat = getattr(self, name)
|
||||||
|
prog = regex.symcomp(pat)
|
||||||
|
setattr(self, name[:-4], prog)
|
||||||
|
|
||||||
|
def initosspecifics(self):
|
||||||
|
if MacOS:
|
||||||
|
self.filetype = 'TEXT'
|
||||||
|
self.filecreator = CREATOR
|
||||||
|
else:
|
||||||
|
self.filetype = self.filecreator = None
|
||||||
|
|
||||||
|
def setfiletype(self, filename):
|
||||||
|
if MacOS and (self.filecreator or self.filetype):
|
||||||
|
creator, type = MacOS.GetCreatorAndType(filename)
|
||||||
|
if self.filecreator: creator = self.filecreator
|
||||||
|
if self.filetype: type = self.filetype
|
||||||
|
MacOS.SetCreatorAndType(filename, creator, type)
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
self.closefiles()
|
||||||
|
|
||||||
|
def closefiles(self):
|
||||||
|
self.closespec()
|
||||||
|
self.closedefs()
|
||||||
|
self.closescan()
|
||||||
|
|
||||||
|
def closespec(self):
|
||||||
|
tmp = self.specmine and self.specfile
|
||||||
|
self.specfile = None
|
||||||
|
if tmp: tmp.close()
|
||||||
|
|
||||||
|
def closedefs(self):
|
||||||
|
tmp = self.defsmine and self.defsfile
|
||||||
|
self.defsfile = None
|
||||||
|
if tmp: tmp.close()
|
||||||
|
|
||||||
|
def closescan(self):
|
||||||
|
tmp = self.scanmine and self.scanfile
|
||||||
|
self.scanfile = None
|
||||||
|
if tmp: tmp.close()
|
||||||
|
|
||||||
|
def setoutput(self, spec, defs = None):
|
||||||
|
self.closespec()
|
||||||
|
self.closedefs()
|
||||||
|
if spec:
|
||||||
|
if type(spec) == StringType:
|
||||||
|
file = self.openoutput(spec)
|
||||||
|
mine = 1
|
||||||
|
else:
|
||||||
|
file = spec
|
||||||
|
mine = 0
|
||||||
|
self.specfile = file
|
||||||
|
self.specmine = mine
|
||||||
|
if defs:
|
||||||
|
if type(defs) == StringType:
|
||||||
|
file = self.openoutput(defs)
|
||||||
|
mine = 1
|
||||||
|
else:
|
||||||
|
file = defs
|
||||||
|
mine = 0
|
||||||
|
self.defsfile = file
|
||||||
|
self.defsmine = mine
|
||||||
|
|
||||||
|
def openoutput(self, filename):
|
||||||
|
file = open(filename, 'w')
|
||||||
|
self.setfiletype(filename)
|
||||||
|
return file
|
||||||
|
|
||||||
|
def setinput(self, scan = sys.stdin):
|
||||||
|
self.closescan()
|
||||||
|
if scan:
|
||||||
|
if type(scan) == StringType:
|
||||||
|
file = self.openinput(scan)
|
||||||
|
mine = 1
|
||||||
|
else:
|
||||||
|
file = scan
|
||||||
|
mine = 0
|
||||||
|
self.scanfile = file
|
||||||
|
self.scanmine = mine
|
||||||
|
self.lineno = 0
|
||||||
|
|
||||||
|
def openinput(self, filename):
|
||||||
|
if not os.path.isabs(filename):
|
||||||
|
for dir in self.includepath:
|
||||||
|
fullname = os.path.join(dir, filename)
|
||||||
|
#self.report("trying full name %s", `fullname`)
|
||||||
|
try:
|
||||||
|
return open(fullname, 'r')
|
||||||
|
except IOError:
|
||||||
|
pass
|
||||||
|
# If not on the path, or absolute, try default open()
|
||||||
|
return open(filename, 'r')
|
||||||
|
|
||||||
|
def getline(self):
|
||||||
|
if not self.scanfile:
|
||||||
|
raise Error, "input file not set"
|
||||||
|
self.line = self.scanfile.readline()
|
||||||
|
if not self.line:
|
||||||
|
raise EOFError
|
||||||
|
self.lineno = self.lineno + 1
|
||||||
|
return self.line
|
||||||
|
|
||||||
|
def scan(self):
|
||||||
|
if not self.scanfile:
|
||||||
|
self.error("No input file has been specified")
|
||||||
|
return
|
||||||
|
inputname = self.scanfile.name
|
||||||
|
self.report("scanfile = %s", `inputname`)
|
||||||
|
if not self.specfile:
|
||||||
|
self.report("(No interface specifications will be written)")
|
||||||
|
else:
|
||||||
|
self.report("specfile = %s", `self.specfile.name`)
|
||||||
|
self.specfile.write("# Generated from %s\n" % `inputname`)
|
||||||
|
if not self.defsfile:
|
||||||
|
self.report("(No symbol definitions will be written)")
|
||||||
|
else:
|
||||||
|
self.report("defsfile = %s", `self.defsfile.name`)
|
||||||
|
self.defsfile.write("# Generated from %s\n" % `inputname`)
|
||||||
|
self.alreadydone = []
|
||||||
|
try:
|
||||||
|
while 1:
|
||||||
|
try: line = self.getline()
|
||||||
|
except EOFError: break
|
||||||
|
if self.defsfile and self.sym.match(line) >= 0:
|
||||||
|
self.dosymdef()
|
||||||
|
continue
|
||||||
|
if self.head.match(line) >= 0:
|
||||||
|
self.dofuncspec()
|
||||||
|
continue
|
||||||
|
except EOFError:
|
||||||
|
self.error("Uncaught EOF error")
|
||||||
|
|
||||||
|
def dosymdef(self):
|
||||||
|
name, defn = self.sym.group('name', 'defn')
|
||||||
|
self.defsfile.write("%s = %s\n" % (name, defn))
|
||||||
|
|
||||||
|
def dofuncspec(self):
|
||||||
|
raw = self.line[len(self.head.group(0)):]
|
||||||
|
while self.tail.search(raw) < 0:
|
||||||
|
line = self.getline()
|
||||||
|
raw = raw + line
|
||||||
|
self.processrawspec(raw)
|
||||||
|
|
||||||
|
def processrawspec(self, raw):
|
||||||
|
if self.whole.search(raw) < 0:
|
||||||
|
self.report("Bad raw spec: %s", `raw`)
|
||||||
|
return
|
||||||
|
type, name, args = self.whole.group('type', 'name', 'args')
|
||||||
|
if name in self.alreadydone:
|
||||||
|
self.report("Name has already been defined: %s", `name`)
|
||||||
|
return
|
||||||
|
self.report("==> %s %s <==", type, name)
|
||||||
|
if self.blacklisted(type, name):
|
||||||
|
self.error("*** %s %s blacklisted", type, name)
|
||||||
|
return
|
||||||
|
arglist = self.extractarglist(args)
|
||||||
|
arglist = self.repairarglist(arglist)
|
||||||
|
if self.unmanageable(type, name, arglist):
|
||||||
|
##for arg in arglist:
|
||||||
|
## self.report(" %s", `arg`)
|
||||||
|
self.error("*** %s %s unmanageable", type, name)
|
||||||
|
return
|
||||||
|
self.alreadydone.append(name)
|
||||||
|
self.generate(type, name, arglist)
|
||||||
|
|
||||||
|
def extractarglist(self, args):
|
||||||
|
args = string.strip(args)
|
||||||
|
if not args or args == "void":
|
||||||
|
return []
|
||||||
|
parts = map(string.strip, string.splitfields(args, ","))
|
||||||
|
arglist = []
|
||||||
|
for part in parts:
|
||||||
|
arg = self.extractarg(part)
|
||||||
|
arglist.append(arg)
|
||||||
|
return arglist
|
||||||
|
|
||||||
|
def extractarg(self, part):
|
||||||
|
mode = "InMode"
|
||||||
|
if self.asplit.match(part) < 0:
|
||||||
|
self.error("Indecipherable argument: %s", `part`)
|
||||||
|
return ("unknown", part, mode)
|
||||||
|
type, name = self.asplit.group('type', 'name')
|
||||||
|
type = regsub.gsub("\*", " ptr ", type)
|
||||||
|
type = string.strip(type)
|
||||||
|
type = regsub.gsub("[ \t]+", "_", type)
|
||||||
|
if type[:6] == "const_":
|
||||||
|
type = type[6:]
|
||||||
|
elif type[-4:] == "_ptr":
|
||||||
|
type = type[:-4]
|
||||||
|
mode = "OutMode"
|
||||||
|
return type, name, mode
|
||||||
|
|
||||||
|
def repairarglist(self, arglist):
|
||||||
|
arglist = arglist[:]
|
||||||
|
i = 0
|
||||||
|
while i < len(arglist):
|
||||||
|
for pattern, replacement in self.repairinstructions:
|
||||||
|
n = len(pattern)
|
||||||
|
if i+n > len(arglist): continue
|
||||||
|
current = arglist[i:i+n]
|
||||||
|
for j in range(n):
|
||||||
|
if not self.matcharg(pattern[j], current[j]):
|
||||||
|
break
|
||||||
|
else: # All items of the pattern match
|
||||||
|
new = self.substituteargs(
|
||||||
|
pattern, replacement, current)
|
||||||
|
if new is not None:
|
||||||
|
arglist[i:i+n] = new
|
||||||
|
i = i+len(new) # No recursive substitutions
|
||||||
|
break
|
||||||
|
else: # No patterns match
|
||||||
|
i = i+1
|
||||||
|
return arglist
|
||||||
|
|
||||||
|
def matcharg(self, patarg, arg):
|
||||||
|
return len(filter(None, map(fnmatch.fnmatch, arg, patarg))) == 3
|
||||||
|
|
||||||
|
def substituteargs(self, pattern, replacement, old):
|
||||||
|
new = []
|
||||||
|
for k in range(len(replacement)):
|
||||||
|
item = replacement[k]
|
||||||
|
newitem = [item[0], item[1], item[2]]
|
||||||
|
for i in range(3):
|
||||||
|
if item[i] == '*':
|
||||||
|
newitem[i] = old[k][i]
|
||||||
|
elif item[i][:1] == '$':
|
||||||
|
index = string.atoi(item[i][1:]) - 1
|
||||||
|
newitem[i] = old[index][i]
|
||||||
|
new.append(tuple(newitem))
|
||||||
|
##self.report("old: %s", `old`)
|
||||||
|
##self.report("new: %s", `new`)
|
||||||
|
return new
|
||||||
|
|
||||||
|
def generate(self, type, name, arglist):
|
||||||
|
classname, listname = self.destination(type, name, arglist)
|
||||||
|
if not self.specfile: return
|
||||||
|
self.specfile.write("\nf = %s(%s, %s,\n" % (classname, type, `name`))
|
||||||
|
for atype, aname, amode in arglist:
|
||||||
|
self.specfile.write(" (%s, %s, %s),\n" %
|
||||||
|
(atype, `aname`, amode))
|
||||||
|
self.specfile.write(")\n")
|
||||||
|
self.specfile.write("%s.append(f)\n" % listname)
|
||||||
|
|
||||||
|
def destination(self, type, name, arglist):
|
||||||
|
return "FunctionGenerator", "functions"
|
||||||
|
|
||||||
|
def blacklisted(self, type, name):
|
||||||
|
if type in self.blacklisttypes:
|
||||||
|
##self.report("return type %s is blacklisted", type)
|
||||||
|
return 1
|
||||||
|
if name in self.blacklistnames:
|
||||||
|
##self.report("function name %s is blacklisted", name)
|
||||||
|
return 1
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def unmanageable(self, type, name, arglist):
|
||||||
|
for atype, aname, amode in arglist:
|
||||||
|
if atype in self.blacklisttypes:
|
||||||
|
self.report("argument type %s is blacklisted", atype)
|
||||||
|
return 1
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def test():
|
||||||
|
input = "D:Development:THINK C:Mac #includes:Apple #includes:AppleEvents.h"
|
||||||
|
output = "@aespecs.py"
|
||||||
|
defsoutput = "@aedefs.py"
|
||||||
|
s = Scanner(input, output, defsoutput)
|
||||||
|
s.scan()
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
test()
|
Loading…
Add table
Add a link
Reference in a new issue