mirror of https://github.com/python/cpython
remove old mac scripts including bgen
This commit is contained in:
parent
21491717bd
commit
f6325444e9
|
@ -1,56 +0,0 @@
|
|||
# bgenall - Generate all bgen-generated modules
|
||||
#
|
||||
import sys
|
||||
import os
|
||||
import string
|
||||
|
||||
def bgenone(dirname, shortname):
|
||||
os.chdir(dirname)
|
||||
print('%s:'%shortname)
|
||||
# Sigh, we don't want to lose CVS history, so two
|
||||
# modules have funny names:
|
||||
if shortname == 'carbonevt':
|
||||
modulename = 'CarbonEvtscan'
|
||||
elif shortname == 'ibcarbon':
|
||||
modulename = 'IBCarbonscan'
|
||||
else:
|
||||
modulename = shortname + 'scan'
|
||||
try:
|
||||
m = __import__(modulename)
|
||||
except:
|
||||
print("Error:", shortname, sys.exc_info()[1])
|
||||
return 0
|
||||
try:
|
||||
m.main()
|
||||
except:
|
||||
print("Error:", shortname, sys.exc_info()[1])
|
||||
return 0
|
||||
return 1
|
||||
|
||||
def main():
|
||||
success = []
|
||||
failure = []
|
||||
sys.path.insert(0, os.curdir)
|
||||
if len(sys.argv) > 1:
|
||||
srcdir = sys.argv[1]
|
||||
else:
|
||||
srcdir = os.path.join(os.path.join(sys.prefix, 'Mac'), 'Modules')
|
||||
srcdir = os.path.abspath(srcdir)
|
||||
contents = os.listdir(srcdir)
|
||||
for name in contents:
|
||||
moduledir = os.path.join(srcdir, name)
|
||||
scanmodule = os.path.join(moduledir, name +'scan.py')
|
||||
if os.path.exists(scanmodule):
|
||||
if bgenone(moduledir, name):
|
||||
success.append(name)
|
||||
else:
|
||||
failure.append(name)
|
||||
print('Done:', string.join(success, ' '))
|
||||
if failure:
|
||||
print('Failed:', string.join(failure, ' '))
|
||||
return 0
|
||||
return 1
|
||||
|
||||
if __name__ == '__main__':
|
||||
rv = main()
|
||||
sys.exit(not rv)
|
|
@ -1,45 +0,0 @@
|
|||
# Scan the tree passed as argv[0] for .rsrc files, skipping .rsrc.df.rsrc
|
||||
# files, and open these. The effect of this is to create the .rsrc.df.rsrc
|
||||
# cache files if needed.
|
||||
# These are needed on OSX: the .rsrc files are in reality AppleSingle-encoded
|
||||
# files. We decode the resources into a datafork-based resource file.
|
||||
|
||||
import macresource
|
||||
import os
|
||||
import sys
|
||||
import getopt
|
||||
|
||||
class NoArgsError(Exception):
|
||||
pass
|
||||
|
||||
def handler(arg1, dirname, fnames):
|
||||
verbose, force = arg1
|
||||
for fn in fnames:
|
||||
if fn[-5:] == '.rsrc' and fn[-13:] != '.rsrc.df.rsrc':
|
||||
if force:
|
||||
try:
|
||||
os.unlink(os.path.join(dirname, fn + '.df.rsrc'))
|
||||
except IOError:
|
||||
pass
|
||||
macresource.open_pathname(os.path.join(dirname, fn), verbose=verbose)
|
||||
|
||||
def main():
|
||||
try:
|
||||
opts, args = getopt.getopt(sys.argv[1:], 'vf')
|
||||
if not args:
|
||||
raise NoArgsError
|
||||
except (getopt.GetoptError, NoArgsError):
|
||||
sys.stderr.write('Usage: cachersrc.py dirname ...\n')
|
||||
sys.exit(1)
|
||||
verbose = 0
|
||||
force = 0
|
||||
for o, v in opts:
|
||||
if o == '-v':
|
||||
verbose = 1
|
||||
if o == '-f':
|
||||
force = 1
|
||||
for dir in sys.argv[1:]:
|
||||
os.walk(dir, handler, (verbose, force))
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
File diff suppressed because it is too large
Load Diff
|
@ -1,52 +0,0 @@
|
|||
# Generate all the standard scripting suite packages.
|
||||
# Note that this module needs *serious* hand-crafting because of all the
|
||||
# absolute paths. It is, however, a great leap forward compared to the time
|
||||
# when this information was only stored in Jack's brain:-)
|
||||
|
||||
import sys
|
||||
import os
|
||||
import gensuitemodule
|
||||
|
||||
verbose=sys.stdout
|
||||
|
||||
DSTDIR="/Users/jack/src/python/Lib/plat-mac/lib-scriptpackages"
|
||||
OS9DISK="/Volumes/Moes"
|
||||
|
||||
APPLESCRIPT=OS9DISK + "/Systeemmap/Extensies/AppleScript"
|
||||
SYSTEMEVENTS="/System/Library/CoreServices/System Events.app"
|
||||
|
||||
CODEWARRIOR=OS9DISK + "/Applications (Mac OS 9)/Metrowerks CodeWarrior 7.0/Metrowerks CodeWarrior/CodeWarrior IDE 4.2.6"
|
||||
EXPLORER="/Applications/Internet Explorer.app"
|
||||
FINDER="/System/Library/CoreServices/Finder.app"
|
||||
NETSCAPE=OS9DISK + "/Applications (Mac OS 9)/Netscape Communicator\xe2\x84\xa2 Folder/Netscape Communicator\xe2\x84\xa2"
|
||||
TERMINAL="/Applications/Utilities/Terminal.app"
|
||||
|
||||
gensuitemodule.processfile_fromresource(APPLESCRIPT,
|
||||
output=os.path.join(DSTDIR, 'StdSuites'),
|
||||
basepkgname='_builtinSuites',
|
||||
edit_modnames=[], verbose=verbose)
|
||||
gensuitemodule.processfile(SYSTEMEVENTS,
|
||||
output=os.path.join(DSTDIR, 'SystemEvents'),
|
||||
basepkgname='StdSuites',
|
||||
edit_modnames=[('Disk_2d_Folder_2d_File_Suite', 'Disk_Folder_File_Suite')],
|
||||
verbose=verbose)
|
||||
gensuitemodule.processfile(CODEWARRIOR,
|
||||
output=os.path.join(DSTDIR, 'CodeWarrior'),
|
||||
basepkgname='StdSuites',
|
||||
edit_modnames=[], verbose=verbose)
|
||||
gensuitemodule.processfile(EXPLORER,
|
||||
output=os.path.join(DSTDIR, 'Explorer'),
|
||||
basepkgname='StdSuites',
|
||||
edit_modnames=[], verbose=verbose)
|
||||
gensuitemodule.processfile(FINDER,
|
||||
output=os.path.join(DSTDIR, 'Finder'),
|
||||
basepkgname='StdSuites',
|
||||
edit_modnames=[], verbose=verbose)
|
||||
gensuitemodule.processfile(NETSCAPE,
|
||||
output=os.path.join(DSTDIR, 'Netscape'),
|
||||
basepkgname='StdSuites',
|
||||
edit_modnames=[('WorldWideWeb_suite_2c__as_d', 'WorldWideWeb_suite')], verbose=verbose)
|
||||
gensuitemodule.processfile(TERMINAL,
|
||||
output=os.path.join(DSTDIR, 'Terminal'),
|
||||
basepkgname='StdSuites',
|
||||
edit_modnames=[], verbose=verbose)
|
|
@ -1,7 +0,0 @@
|
|||
/* These are defined in MSL errno.h, but unfortunately not documented */
|
||||
#define EFPOS 35 /* File positioning error */
|
||||
#define ESIGPARM 36 /* Signal argument error */
|
||||
#define ENOMEM 37 /* Cannot allocate memory */
|
||||
#define EACCES 38 /* Permission denied */
|
||||
#define ENOENT 39 /* No such file or directory */
|
||||
#define ENOSYS 40 /* Function not implemented */
|
|
@ -1,13 +0,0 @@
|
|||
/* Errors from InternetConfig.h */
|
||||
icPrefNotFoundErr = -666, /* Internet preference not found */
|
||||
icPermErr = -667, /* cannot set preference */
|
||||
icPrefDataErr = -668, /* problem with preference data */
|
||||
icInternalErr = -669, /* Internet Config internal error */
|
||||
icTruncatedErr = -670, /* more data was present than was returned */
|
||||
icNoMoreWritersErr = -671, /* you cannot begin a write session because someone else is already doing it */
|
||||
icNothingToOverrideErr = -672, /* no component for the override component to capture */
|
||||
icNoURLErr = -673, /* no URL found */
|
||||
icConfigNotFoundErr = -674, /* no internet configuration was found */
|
||||
icConfigInappropriateErr = -675, /* incorrect manufacturer code */
|
||||
icProfileNotFoundErr = -676, /* profile not found */
|
||||
icTooManyProfilesErr = -677 /* too many profiles in database */
|
|
@ -1,157 +0,0 @@
|
|||
"""Parse sys/errno.h and Errors.h and create Estr resource"""
|
||||
|
||||
import re
|
||||
import string
|
||||
from Carbon import Res
|
||||
import os
|
||||
|
||||
READ = 1
|
||||
WRITE = 2
|
||||
smAllScripts = -3
|
||||
|
||||
ERRNO_PROG="#define[ \t]+" \
|
||||
"([A-Z0-9a-z_]+)" \
|
||||
"[ \t]+" \
|
||||
"([0-9]+)" \
|
||||
"[ \t]*/\*[ \t]*" \
|
||||
"(.*)" \
|
||||
"[ \t]*\*/"
|
||||
|
||||
ERRORS_PROG="[ \t]*" \
|
||||
"([A-Z0-9a-z_]+)" \
|
||||
"[ \t]*=[ \t]*" \
|
||||
"([-0-9]+)" \
|
||||
"[, \t]*/\*[ \t]*" \
|
||||
"(.*)" \
|
||||
"[ \t]*\*/"
|
||||
|
||||
ERRORS_PROG_2="[ \t]*" \
|
||||
"([A-Z0-9a-z_]+)" \
|
||||
"[ \t]*=[ \t]*" \
|
||||
"([-0-9]+)" \
|
||||
"[, \t]*"
|
||||
|
||||
def Pstring(str):
|
||||
if len(str) > 255:
|
||||
raise ValueError('String too large')
|
||||
return chr(len(str))+str
|
||||
|
||||
def writeestr(dst, edict):
|
||||
"""Create Estr resource file given a dictionary of errors."""
|
||||
|
||||
os.unlink(dst.as_pathname())
|
||||
Res.FSpCreateResFile(dst, 'RSED', 'rsrc', smAllScripts)
|
||||
output = Res.FSpOpenResFile(dst, WRITE)
|
||||
Res.UseResFile(output)
|
||||
for num in edict.keys():
|
||||
res = Res.Resource(Pstring(edict[num][0]))
|
||||
res.AddResource('Estr', num, '')
|
||||
res.WriteResource()
|
||||
Res.CloseResFile(output)
|
||||
|
||||
def writepython(fp, dict):
|
||||
k = dict.keys()
|
||||
k.sort()
|
||||
for i in k:
|
||||
fp.write("%s\t=\t%d\t#%s\n"%(dict[i][1], i, dict[i][0]))
|
||||
|
||||
|
||||
def parse_errno_h(fp, dict):
|
||||
errno_prog = re.compile(ERRNO_PROG)
|
||||
for line in fp.readlines():
|
||||
m = errno_prog.match(line)
|
||||
if m:
|
||||
number = string.atoi(m.group(2))
|
||||
name = m.group(1)
|
||||
desc = string.strip(m.group(3))
|
||||
|
||||
if not dict.has_key(number):
|
||||
dict[number] = desc, name
|
||||
else:
|
||||
print('DUPLICATE', number)
|
||||
print('\t', dict[number])
|
||||
print('\t', (desc, name))
|
||||
|
||||
def parse_errors_h(fp, dict):
|
||||
errno_prog = re.compile(ERRORS_PROG)
|
||||
errno_prog_2 = re.compile(ERRORS_PROG_2)
|
||||
for line in fp.readlines():
|
||||
match = 0
|
||||
m = errno_prog.match(line)
|
||||
m2 = errno_prog_2.match(line)
|
||||
if m:
|
||||
number = string.atoi(m.group(2))
|
||||
name = m.group(1)
|
||||
desc = string.strip(m.group(3))
|
||||
match=1
|
||||
elif m2:
|
||||
number = string.atoi(m2.group(2))
|
||||
name = m2.group(1)
|
||||
desc = name
|
||||
match=1
|
||||
if match:
|
||||
if number > 0: continue
|
||||
|
||||
if not dict.has_key(number):
|
||||
dict[number] = desc, name
|
||||
else:
|
||||
print('DUPLICATE', number)
|
||||
print('\t', dict[number])
|
||||
print('\t', (desc, name))
|
||||
if len(desc) > len(dict[number][0]):
|
||||
print('Pick second one')
|
||||
dict[number] = desc, name
|
||||
|
||||
def main():
|
||||
dict = {}
|
||||
pathname = EasyDialogs.AskFileForOpen(message="Where is GUSI sys/errno.h?")
|
||||
if pathname:
|
||||
fp = open(pathname)
|
||||
parse_errno_h(fp, dict)
|
||||
fp.close()
|
||||
|
||||
pathname = EasyDialogs.AskFileForOpen(message="Select cerrno (MSL) or cancel")
|
||||
if pathname:
|
||||
fp = open(pathname)
|
||||
parse_errno_h(fp, dict)
|
||||
fp.close()
|
||||
|
||||
pathname = EasyDialogs.AskFileForOpen(message="Where is MacErrors.h?")
|
||||
if pathname:
|
||||
fp = open(pathname)
|
||||
parse_errors_h(fp, dict)
|
||||
fp.close()
|
||||
|
||||
pathname = EasyDialogs.AskFileForOpen(message="Where is mkestrres-MacErrors.h?")
|
||||
if pathname:
|
||||
fp = open(pathname)
|
||||
parse_errors_h(fp, dict)
|
||||
fp.close()
|
||||
|
||||
if not dict:
|
||||
return
|
||||
|
||||
pathname = EasyDialogs.AskFileForSave(message="Resource output file?", savedFileName="errors.rsrc")
|
||||
if pathname:
|
||||
writeestr(fss, dict)
|
||||
|
||||
pathname = EasyDialogs.AskFileForSave(message="Python output file?", savedFileName="macerrors.py")
|
||||
if pathname:
|
||||
fp = open(pathname, "w")
|
||||
writepython(fp, dict)
|
||||
fp.close()
|
||||
fss.SetCreatorType('Pyth', 'TEXT')
|
||||
|
||||
pathname = EasyDialogs.AskFileForSave(message="Text output file?", savedFileName="errors.txt")
|
||||
if pathname:
|
||||
fp = open(pathname, "w")
|
||||
|
||||
k = dict.keys()
|
||||
k.sort()
|
||||
for i in k:
|
||||
fp.write("%d\t%s\t%s\n"%(i, dict[i][1], dict[i][0]))
|
||||
fp.close()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
|
@ -1,7 +0,0 @@
|
|||
BGEN -- Automatic Generation of Extension Modules
|
||||
=================================================
|
||||
|
||||
This directory contains BGEN -- a package that helps in generating
|
||||
complete source code for Python extension module. For examples of its
|
||||
use, see the Mac Python source distribution (available separately
|
||||
from the Python ftp archives). Note that BGEN is not Mac specific!
|
|
@ -1,12 +0,0 @@
|
|||
"Export everything in the various bgen submodules."
|
||||
|
||||
from bgenType import *
|
||||
from bgenVariable import *
|
||||
from bgenBuffer import *
|
||||
from bgenStackBuffer import *
|
||||
from bgenHeapBuffer import *
|
||||
from bgenStringBuffer import *
|
||||
from bgenOutput import *
|
||||
from bgenGenerator import *
|
||||
from bgenModule import *
|
||||
from bgenObjectDefinition import *
|
|
@ -1,301 +0,0 @@
|
|||
"""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]
|
||||
self.label_needed = 0
|
||||
|
||||
def getArgDeclarations(self, name, reference=False, constmode=False, outmode=False):
|
||||
if reference:
|
||||
raise RuntimeError("Cannot pass buffer types by reference")
|
||||
return (self.getBufferDeclarations(name, constmode, outmode) +
|
||||
self.getSizeDeclarations(name, outmode))
|
||||
|
||||
def getBufferDeclarations(self, name, constmode=False, outmode=False):
|
||||
return self.getInputBufferDeclarations(name, constmode) + \
|
||||
self.getOutputBufferDeclarations(name, constmode, outmode)
|
||||
|
||||
def getInputBufferDeclarations(self, name, constmode=False):
|
||||
if constmode:
|
||||
const = "const "
|
||||
else:
|
||||
const = ""
|
||||
return ["%s%s *%s__in__" % (const, self.datatype, name)]
|
||||
|
||||
def getOutputBufferDeclarations(self, name, constmode=False, outmode=False):
|
||||
if constmode:
|
||||
raise RuntimeError("Cannot use const output buffer")
|
||||
if outmode:
|
||||
out = "*"
|
||||
else:
|
||||
out = ""
|
||||
return ["%s%s %s__out__[%s]" % (self.datatype, out, name, self.size)]
|
||||
|
||||
def getSizeDeclarations(self, name, outmode=False):
|
||||
if outmode:
|
||||
out = "*"
|
||||
else:
|
||||
out = ""
|
||||
return ["%s%s %s__len__" %(self.sizetype, out, name)]
|
||||
|
||||
def getAuxDeclarations(self, name):
|
||||
return ["int %s__in_len__" %(name)]
|
||||
|
||||
def getargsFormat(self):
|
||||
return "s#"
|
||||
|
||||
def getargsArgs(self, name):
|
||||
return "&%s__in__, &%s__in_len__" % (name, name)
|
||||
|
||||
def getargsCheck(self, name):
|
||||
Output("if (%s__in_len__ != %s)", name, self.size)
|
||||
OutLbrace()
|
||||
Output('PyErr_SetString(PyExc_TypeError, "buffer length should be %s");',
|
||||
self.size)
|
||||
Output("goto %s__error__;", name)
|
||||
self.label_needed = 1
|
||||
OutRbrace()
|
||||
self.transferSize(name)
|
||||
|
||||
def transferSize(self, name):
|
||||
Output("%s__len__ = %s__in_len__;", name, name)
|
||||
|
||||
def passOutput(self, name):
|
||||
return "%s__in__, %s__out__" % (name, name)
|
||||
|
||||
def mkvalueFormat(self):
|
||||
return "s#"
|
||||
|
||||
def mkvalueArgs(self, name):
|
||||
return "%s__out__, (int)%s" % (name, self.size)
|
||||
|
||||
def cleanup(self, name):
|
||||
if self.label_needed:
|
||||
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 getOutputBufferDeclarations(self, name, constmode=False, outmode=False):
|
||||
return []
|
||||
|
||||
|
||||
class OutputOnlyBufferMixIn(OutputOnlyMixIn):
|
||||
|
||||
def getInputBufferDeclarations(self, name, constmode=False):
|
||||
return []
|
||||
|
||||
class OptionalInputBufferMixIn:
|
||||
|
||||
"""Add to input buffers if the buffer may be omitted: pass None in Python
|
||||
and the C code will get a NULL pointer and zero size"""
|
||||
|
||||
def getargsFormat(self):
|
||||
return "z#"
|
||||
|
||||
|
||||
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 OptionalFixedInputBufferType(OptionalInputBufferMixIn, FixedInputBufferType):
|
||||
pass
|
||||
|
||||
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):
|
||||
Output("%s__len__ = %s__in_len__;", name, name)
|
||||
|
||||
def passInput(self, name):
|
||||
return "%s__in__, %s__len__" % (name, name)
|
||||
|
||||
class ReverseInputBufferMixin:
|
||||
""" Mixin for input buffers that are passed as (size, buffer) """
|
||||
|
||||
def passInput(self, name):
|
||||
return "%s__len__, %s__in__" % (name, name)
|
||||
|
||||
class OptionalVarInputBufferType(OptionalInputBufferMixIn, VarInputBufferType):
|
||||
pass
|
||||
|
||||
# ----- 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 getInputBufferDeclarations(self, name, constmode=False):
|
||||
if constmode:
|
||||
const = "const "
|
||||
else:
|
||||
const = ""
|
||||
return ["%s%s *%s__in__" % (const, self.type, name)]
|
||||
|
||||
def getSizeDeclarations(self, name, outmode=False):
|
||||
return []
|
||||
|
||||
def getAuxDeclarations(self, name):
|
||||
return ["int %s__in_len__" % (name)]
|
||||
|
||||
def getOutputBufferDeclarations(self, name, constmode=False, outmode=False):
|
||||
if constmode:
|
||||
raise RuntimeError("Cannot use const output buffer")
|
||||
if outmode:
|
||||
out = "*"
|
||||
else:
|
||||
out = ""
|
||||
return ["%s%s %s__out__" % (self.type, out, name)]
|
||||
|
||||
def getargsArgs(self, name):
|
||||
return "(char **)&%s__in__, &%s__in_len__" % (name, name)
|
||||
|
||||
def transferSize(self, name):
|
||||
pass
|
||||
|
||||
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__, (int)%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 getSizeDeclarations(self, name, outmode=False):
|
||||
return []
|
||||
|
||||
def getAuxDeclarations(self, name):
|
||||
return []
|
||||
|
||||
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 getSizeDeclarations(self, name, outmode=False):
|
||||
return []
|
||||
|
||||
def getAuxDeclarations(self, name):
|
||||
return []
|
||||
|
||||
def passOutput(self, name):
|
||||
return "%s__out__" % name
|
|
@ -1,302 +0,0 @@
|
|||
from bgenOutput import *
|
||||
from bgenType import *
|
||||
from bgenVariable import *
|
||||
|
||||
|
||||
Error = "bgenGenerator.Error"
|
||||
|
||||
DEBUG=0
|
||||
|
||||
# Strings to specify argument transfer modes in generator calls
|
||||
IN = "in"
|
||||
OUT = "out"
|
||||
INOUT = IN_OUT = "in-out"
|
||||
|
||||
|
||||
class BaseFunctionGenerator:
|
||||
|
||||
def __init__(self, name, condition=None, callname=None, modifiers=None):
|
||||
if DEBUG: print("<--", name)
|
||||
self.name = name
|
||||
if callname:
|
||||
self.callname = callname
|
||||
else:
|
||||
self.callname = name
|
||||
self.prefix = name
|
||||
self.objecttype = "PyObject" # Type of _self argument to function
|
||||
self.condition = condition
|
||||
self.modifiers = modifiers
|
||||
|
||||
def setprefix(self, prefix):
|
||||
self.prefix = prefix
|
||||
|
||||
def checkgenerate(self):
|
||||
return True
|
||||
|
||||
def generate(self):
|
||||
if not self.checkgenerate():
|
||||
return
|
||||
if DEBUG: print("-->", self.name)
|
||||
if self.condition:
|
||||
Output()
|
||||
Output(self.condition)
|
||||
self.functionheader()
|
||||
self.functionbody()
|
||||
self.functiontrailer()
|
||||
if self.condition:
|
||||
Output("#endif")
|
||||
|
||||
def functionheader(self):
|
||||
Output()
|
||||
Output("static PyObject *%s_%s(%s *_self, PyObject *_args)",
|
||||
self.prefix, self.name, self.objecttype)
|
||||
OutLbrace()
|
||||
Output("PyObject *_res = NULL;")
|
||||
|
||||
def functionbody(self):
|
||||
Output("/* XXX To be provided */")
|
||||
|
||||
def functiontrailer(self):
|
||||
OutRbrace()
|
||||
|
||||
def reference(self, name = None):
|
||||
if not self.checkgenerate():
|
||||
return
|
||||
if name is None:
|
||||
name = self.name
|
||||
docstring = self.docstring()
|
||||
if self.condition:
|
||||
Output()
|
||||
Output(self.condition)
|
||||
Output("{\"%s\", (PyCFunction)%s_%s, METH_VARARGS,", name, self.prefix, self.name)
|
||||
Output(" PyDoc_STR(%s)},", stringify(docstring))
|
||||
if self.condition:
|
||||
Output("#endif")
|
||||
|
||||
def docstring(self):
|
||||
return None
|
||||
|
||||
def __cmp__(self, other):
|
||||
if not hasattr(other, 'name'):
|
||||
return cmp(id(self), id(other))
|
||||
return cmp(self.name, other.name)
|
||||
|
||||
_stringify_map = {'\n': '\\n', '\t': '\\t', '\r': '\\r', '\b': '\\b',
|
||||
'\e': '\\e', '\a': '\\a', '\f': '\\f', '"': '\\"'}
|
||||
def stringify(str):
|
||||
if str is None: return "NULL"
|
||||
res = '"'
|
||||
map = _stringify_map
|
||||
for c in str:
|
||||
if c in map: res = res + map[c]
|
||||
elif ' ' <= c <= '~': res = res + c
|
||||
else: res = res + '\\%03o' % ord(c)
|
||||
res = res + '"'
|
||||
return res
|
||||
|
||||
|
||||
class ManualGenerator(BaseFunctionGenerator):
|
||||
|
||||
def __init__(self, name, body, condition=None):
|
||||
BaseFunctionGenerator.__init__(self, name, condition=condition)
|
||||
self.body = body
|
||||
|
||||
def functionbody(self):
|
||||
Output("%s", self.body)
|
||||
|
||||
def setselftype(self, selftype, itselftype):
|
||||
self.objecttype = selftype
|
||||
self.itselftype = itselftype
|
||||
|
||||
|
||||
class FunctionGenerator(BaseFunctionGenerator):
|
||||
|
||||
def __init__(self, returntype, name, *argumentList, **conditionlist):
|
||||
BaseFunctionGenerator.__init__(self, name, **conditionlist)
|
||||
self.returntype = returntype
|
||||
self.argumentList = []
|
||||
self.setreturnvar()
|
||||
self.parseArgumentList(argumentList)
|
||||
self.prefix = "XXX" # Will be changed by setprefix() call
|
||||
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 setselftype(self, selftype, itselftype):
|
||||
self.objecttype = selftype
|
||||
self.itselftype = itselftype
|
||||
|
||||
def parseArgumentList(self, argumentList):
|
||||
iarg = 0
|
||||
for type, name, mode in argumentList:
|
||||
iarg = iarg + 1
|
||||
if name is None: name = "_arg%d" % iarg
|
||||
arg = Variable(type, name, mode)
|
||||
self.argumentList.append(arg)
|
||||
|
||||
def docstring(self):
|
||||
input = []
|
||||
output = []
|
||||
for arg in self.argumentList:
|
||||
if arg.flags == ErrorMode or arg.flags == SelfMode:
|
||||
continue
|
||||
if arg.type is 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)" % ", ".join(input)
|
||||
if not output or output == ["void"]:
|
||||
outstr = "None"
|
||||
else:
|
||||
outstr = "(%s)" % ", ".join(output)
|
||||
return instr + " -> " + outstr
|
||||
|
||||
def functionbody(self):
|
||||
self.declarations()
|
||||
self.precheck()
|
||||
self.getargs()
|
||||
self.callit()
|
||||
self.checkit()
|
||||
self.returnvalue()
|
||||
|
||||
def declarations(self):
|
||||
for arg in self.argumentList:
|
||||
arg.declare()
|
||||
|
||||
def getargs(self):
|
||||
sep = ",\n" + ' '*len("if (!PyArg_ParseTuple(")
|
||||
fmt, lst = self.getargsFormatArgs(sep)
|
||||
Output("if (!PyArg_ParseTuple(_args, \"%s\"%s))", fmt, lst)
|
||||
IndentLevel()
|
||||
Output("return NULL;")
|
||||
DedentLevel()
|
||||
for arg in self.argumentList:
|
||||
if arg.flags == SelfMode:
|
||||
continue
|
||||
if arg.mode in (InMode, InOutMode):
|
||||
arg.getargsCheck()
|
||||
|
||||
def getargsFormatArgs(self, sep):
|
||||
fmt = ""
|
||||
lst = ""
|
||||
for arg in self.argumentList:
|
||||
if arg.flags == SelfMode:
|
||||
continue
|
||||
if arg.mode in (InMode, InOutMode):
|
||||
arg.getargsPreCheck()
|
||||
fmt = fmt + arg.getargsFormat()
|
||||
args = arg.getargsArgs()
|
||||
if args:
|
||||
lst = lst + sep + args
|
||||
return fmt, lst
|
||||
|
||||
def precheck(self):
|
||||
pass
|
||||
|
||||
def beginallowthreads(self):
|
||||
pass
|
||||
|
||||
def endallowthreads(self):
|
||||
pass
|
||||
|
||||
def callit(self):
|
||||
args = ""
|
||||
s = "%s%s(" % (self.getrvforcallit(), self.callname)
|
||||
sep = ",\n" + ' '*len(s)
|
||||
for arg in self.argumentList:
|
||||
if arg is self.rv:
|
||||
continue
|
||||
s = arg.passArgument()
|
||||
if args: s = sep + s
|
||||
args = args + s
|
||||
self.beginallowthreads()
|
||||
Output("%s%s(%s);",
|
||||
self.getrvforcallit(), self.callname, args)
|
||||
self.endallowthreads()
|
||||
|
||||
def getrvforcallit(self):
|
||||
if self.rv:
|
||||
return "%s = " % self.rv.name
|
||||
else:
|
||||
return ""
|
||||
|
||||
def checkit(self):
|
||||
for arg in self.argumentList:
|
||||
arg.errorCheck()
|
||||
|
||||
def returnvalue(self):
|
||||
sep = ",\n" + ' '*len("return Py_BuildValue(")
|
||||
fmt, lst = self.mkvalueFormatArgs(sep)
|
||||
if fmt == "":
|
||||
Output("Py_INCREF(Py_None);")
|
||||
Output("_res = Py_None;");
|
||||
else:
|
||||
Output("_res = Py_BuildValue(\"%s\"%s);", fmt, lst)
|
||||
tmp = self.argumentList[:]
|
||||
tmp.reverse()
|
||||
for arg in tmp:
|
||||
if not arg: continue
|
||||
arg.cleanup()
|
||||
Output("return _res;")
|
||||
|
||||
def mkvalueFormatArgs(self, sep):
|
||||
fmt = ""
|
||||
lst = ""
|
||||
for arg in self.argumentList:
|
||||
if not arg: continue
|
||||
if arg.flags == ErrorMode: continue
|
||||
if arg.mode in (OutMode, InOutMode):
|
||||
arg.mkvaluePreCheck()
|
||||
fmt = fmt + arg.mkvalueFormat()
|
||||
lst = lst + sep + arg.mkvalueArgs()
|
||||
return fmt, lst
|
||||
|
||||
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)
|
||||
|
||||
def _test():
|
||||
void = None
|
||||
eggs = FunctionGenerator(void, "eggs",
|
||||
(stringptr, 'cmd', InMode),
|
||||
(int, 'x', InMode),
|
||||
(double, 'y', InOutMode),
|
||||
(int, 'status', ErrorMode),
|
||||
)
|
||||
eggs.setprefix("spam")
|
||||
print("/* START */")
|
||||
eggs.generate()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
_test()
|
|
@ -1,40 +0,0 @@
|
|||
from bgenOutput import *
|
||||
|
||||
class GeneratorGroup:
|
||||
|
||||
def __init__(self, prefix):
|
||||
self.prefix = prefix
|
||||
self.generators = []
|
||||
|
||||
def add(self, g, dupcheck=0):
|
||||
if dupcheck:
|
||||
if g in self.generators:
|
||||
print('DUP', g.name)
|
||||
return
|
||||
g.setprefix(self.prefix)
|
||||
self.generators.append(g)
|
||||
|
||||
def generate(self):
|
||||
for g in self.generators:
|
||||
g.generate()
|
||||
Output()
|
||||
Output("static PyMethodDef %s_methods[] = {", self.prefix)
|
||||
IndentLevel()
|
||||
for g in self.generators:
|
||||
g.reference()
|
||||
Output("{NULL, NULL, 0}")
|
||||
DedentLevel()
|
||||
Output("};")
|
||||
|
||||
|
||||
def _test():
|
||||
void = None
|
||||
from bgenGenerator import FunctionGenerator
|
||||
group = GeneratorGroup("spam")
|
||||
eggs = FunctionGenerator(void, "eggs")
|
||||
group.add(eggs)
|
||||
print("/* START */")
|
||||
group.generate()
|
||||
|
||||
if __name__ == "__main__":
|
||||
_test()
|
|
@ -1,145 +0,0 @@
|
|||
# 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 getOutputBufferDeclarations(self, name, constmode=False, outmode=False):
|
||||
if constmode:
|
||||
raise RuntimeError("Cannot use const output buffer")
|
||||
if outmode:
|
||||
out = "*"
|
||||
else:
|
||||
out = ""
|
||||
return ["%s%s *%s__out__" % (self.datatype, out, name)]
|
||||
|
||||
def getargsCheck(self, name):
|
||||
Output("if ((%s__out__ = malloc(%s__in_len__)) == NULL)", name, name)
|
||||
OutLbrace()
|
||||
Output('PyErr_NoMemory();')
|
||||
Output("goto %s__error__;", name)
|
||||
self.label_needed = 1
|
||||
OutRbrace()
|
||||
Output("%s__len__ = %s__in_len__;", name, name)
|
||||
|
||||
def passOutput(self, name):
|
||||
return "%s__in__, %s__out__, (%s)%s__len__" % \
|
||||
(name, name, self.sizetype, name)
|
||||
|
||||
def mkvalueArgs(self, name):
|
||||
return "%s__out__, (int)%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 getInputBufferDeclarations(self, name, constmode=False):
|
||||
return []
|
||||
|
||||
def getargsFormat(self):
|
||||
return "i"
|
||||
|
||||
def getargsArgs(self, name):
|
||||
return "&%s__in_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)
|
||||
|
||||
class MallocHeapOutputBufferType(HeapOutputBufferType):
|
||||
"""Output buffer allocated by the called function -- passed as (&buffer, &size).
|
||||
|
||||
Instantiate without parameters.
|
||||
Call from Python without parameters.
|
||||
"""
|
||||
|
||||
def getargsCheck(self, name):
|
||||
Output("%s__out__ = NULL;", name)
|
||||
|
||||
def getAuxDeclarations(self, name):
|
||||
return []
|
||||
|
||||
def passOutput(self, name):
|
||||
return "&%s__out__, &%s__len__" % (name, name)
|
||||
|
||||
def getargsFormat(self):
|
||||
return ""
|
||||
|
||||
def getargsArgs(self, name):
|
||||
return None
|
||||
|
||||
def mkvalueFormat(self):
|
||||
return "z#"
|
||||
|
||||
def cleanup(self, name):
|
||||
Output("if( %s__out__ ) free(%s__out__);", name, name)
|
|
@ -1,94 +0,0 @@
|
|||
from bgenOutput import *
|
||||
from bgenGeneratorGroup import GeneratorGroup
|
||||
|
||||
class Module(GeneratorGroup):
|
||||
|
||||
def __init__(self, name, prefix = None,
|
||||
includestuff = None,
|
||||
finalstuff = None,
|
||||
initstuff = None,
|
||||
variablestuff = None,
|
||||
longname = None):
|
||||
GeneratorGroup.__init__(self, prefix or name)
|
||||
self.name = name
|
||||
if longname:
|
||||
self.longname = longname
|
||||
else:
|
||||
self.longname = name
|
||||
self.includestuff = includestuff
|
||||
self.initstuff = initstuff
|
||||
self.finalstuff = finalstuff
|
||||
self.variablestuff = variablestuff
|
||||
self.typeobjects = []
|
||||
|
||||
def addobject(self, od):
|
||||
self.generators.append(od)
|
||||
self.typeobjects.append(od)
|
||||
od.setmodulename(self.longname)
|
||||
|
||||
def generate(self):
|
||||
OutHeader1("Module " + self.name)
|
||||
Output("#include \"Python.h\"")
|
||||
Output()
|
||||
|
||||
if self.includestuff:
|
||||
Output()
|
||||
Output("%s", self.includestuff)
|
||||
|
||||
self.declareModuleVariables()
|
||||
|
||||
GeneratorGroup.generate(self)
|
||||
|
||||
if self.finalstuff:
|
||||
Output()
|
||||
Output("%s", self.finalstuff)
|
||||
|
||||
Output()
|
||||
Output("void init%s(void)", self.name)
|
||||
OutLbrace()
|
||||
Output("PyObject *m;")
|
||||
Output("PyObject *d;")
|
||||
Output()
|
||||
|
||||
if self.initstuff:
|
||||
Output("%s", self.initstuff)
|
||||
Output()
|
||||
|
||||
Output("m = Py_InitModule(\"%s\", %s_methods);",
|
||||
self.name, self.prefix)
|
||||
Output("d = PyModule_GetDict(m);")
|
||||
self.createModuleVariables()
|
||||
OutRbrace()
|
||||
OutHeader1("End module " + self.name)
|
||||
|
||||
def declareModuleVariables(self):
|
||||
self.errorname = self.prefix + "_Error"
|
||||
Output("static PyObject *%s;", self.errorname)
|
||||
|
||||
def createModuleVariables(self):
|
||||
Output("""%s = %s;""", self.errorname, self.exceptionInitializer())
|
||||
Output("""if (%s == NULL ||""", self.errorname)
|
||||
Output(""" PyDict_SetItemString(d, "Error", %s) != 0)""",
|
||||
self.errorname)
|
||||
IndentLevel()
|
||||
Output("""return;""")
|
||||
DedentLevel()
|
||||
for tp in self.typeobjects:
|
||||
tp.outputTypeObjectInitializer()
|
||||
if self.variablestuff:
|
||||
Output("%s", self.variablestuff)
|
||||
Output()
|
||||
|
||||
def exceptionInitializer(self):
|
||||
return """PyErr_NewException("%s.Error", NULL, NULL)""" % self.name
|
||||
|
||||
|
||||
def _test():
|
||||
from bgenGenerator import FunctionGenerator
|
||||
m = Module("spam", "", "#include <stdio.h>")
|
||||
g = FunctionGenerator(None, "bacon")
|
||||
m.add(g)
|
||||
m.generate()
|
||||
|
||||
if __name__ == "__main__":
|
||||
_test()
|
|
@ -1,512 +0,0 @@
|
|||
from bgenOutput import *
|
||||
from bgenGeneratorGroup import GeneratorGroup
|
||||
|
||||
class ObjectDefinition(GeneratorGroup):
|
||||
"Spit out code that together defines a new Python object type"
|
||||
basechain = "NULL"
|
||||
tp_flags = "Py_TPFLAGS_DEFAULT"
|
||||
basetype = None
|
||||
argref = "" # set to "*" if arg to <type>_New should be pointer
|
||||
argconst = "" # set to "const " if arg to <type>_New should be const
|
||||
|
||||
def __init__(self, name, prefix, itselftype):
|
||||
"""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)
|
||||
self.name = name
|
||||
self.itselftype = itselftype
|
||||
self.objecttype = name + 'Object'
|
||||
self.typename = name + '_Type'
|
||||
self.static = "static " # set to "" to make <type>_New and <type>_Convert public
|
||||
self.modulename = None
|
||||
if hasattr(self, "assertions"):
|
||||
self.assertions()
|
||||
|
||||
def add(self, g, dupcheck=0):
|
||||
g.setselftype(self.objecttype, self.itselftype)
|
||||
GeneratorGroup.add(self, g, dupcheck)
|
||||
|
||||
def reference(self):
|
||||
# In case we are referenced from a module
|
||||
pass
|
||||
|
||||
def setmodulename(self, name):
|
||||
self.modulename = name
|
||||
|
||||
def generate(self):
|
||||
# XXX This should use long strings and %(varname)s substitution!
|
||||
|
||||
OutHeader2("Object type " + self.name)
|
||||
|
||||
self.outputCheck()
|
||||
|
||||
Output("typedef struct %s {", self.objecttype)
|
||||
IndentLevel()
|
||||
Output("PyObject_HEAD")
|
||||
self.outputStructMembers()
|
||||
DedentLevel()
|
||||
Output("} %s;", self.objecttype)
|
||||
|
||||
self.outputNew()
|
||||
|
||||
self.outputConvert()
|
||||
|
||||
self.outputDealloc()
|
||||
|
||||
GeneratorGroup.generate(self)
|
||||
|
||||
Output()
|
||||
self.outputMethodChain()
|
||||
|
||||
self.outputGetattr()
|
||||
|
||||
self.outputSetattr()
|
||||
|
||||
self.outputCompare()
|
||||
|
||||
self.outputRepr()
|
||||
|
||||
self.outputHash()
|
||||
|
||||
self.outputPEP253Hooks()
|
||||
|
||||
self.outputTypeObject()
|
||||
|
||||
OutHeader2("End object type " + self.name)
|
||||
|
||||
def outputCheck(self):
|
||||
sf = self.static and "static "
|
||||
Output("%sPyTypeObject %s;", sf, self.typename)
|
||||
Output()
|
||||
Output("#define %s_Check(x) ((x)->ob_type == &%s || PyObject_TypeCheck((x), &%s))",
|
||||
self.prefix, self.typename, self.typename)
|
||||
Output()
|
||||
|
||||
def outputMethodChain(self):
|
||||
Output("%sPyMethodChain %s_chain = { %s_methods, %s };",
|
||||
self.static, self.prefix, self.prefix, self.basechain)
|
||||
|
||||
def outputStructMembers(self):
|
||||
Output("%s ob_itself;", self.itselftype)
|
||||
|
||||
def outputNew(self):
|
||||
Output()
|
||||
Output("%sPyObject *%s_New(%s%s %sitself)", self.static, self.prefix,
|
||||
self.argconst, self.itselftype, self.argref)
|
||||
OutLbrace()
|
||||
Output("%s *it;", self.objecttype)
|
||||
self.outputCheckNewArg()
|
||||
Output("it = PyObject_NEW(%s, &%s);", self.objecttype, self.typename)
|
||||
Output("if (it == NULL) return NULL;")
|
||||
if self.basetype:
|
||||
Output("/* XXXX Should we tp_init or tp_new our basetype? */")
|
||||
self.outputInitStructMembers()
|
||||
Output("return (PyObject *)it;")
|
||||
OutRbrace()
|
||||
|
||||
def outputInitStructMembers(self):
|
||||
Output("it->ob_itself = %sitself;", self.argref)
|
||||
|
||||
def outputCheckNewArg(self):
|
||||
"Override this method to apply additional checks/conversions"
|
||||
|
||||
def outputConvert(self):
|
||||
Output()
|
||||
Output("%sint %s_Convert(PyObject *v, %s *p_itself)", self.static, self.prefix,
|
||||
self.itselftype)
|
||||
OutLbrace()
|
||||
self.outputCheckConvertArg()
|
||||
Output("if (!%s_Check(v))", self.prefix)
|
||||
OutLbrace()
|
||||
Output('PyErr_SetString(PyExc_TypeError, "%s required");', self.name)
|
||||
Output("return 0;")
|
||||
OutRbrace()
|
||||
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):
|
||||
Output()
|
||||
Output("static void %s_dealloc(%s *self)", self.prefix, self.objecttype)
|
||||
OutLbrace()
|
||||
self.outputCleanupStructMembers()
|
||||
if self.basetype:
|
||||
Output("%s.tp_dealloc((PyObject *)self);", self.basetype)
|
||||
elif hasattr(self, 'output_tp_free'):
|
||||
# This is a new-style object with tp_free slot
|
||||
Output("self->ob_type->tp_free((PyObject *)self);")
|
||||
else:
|
||||
Output("PyObject_Free((PyObject *)self);")
|
||||
OutRbrace()
|
||||
|
||||
def outputCleanupStructMembers(self):
|
||||
self.outputFreeIt("self->ob_itself")
|
||||
|
||||
def outputFreeIt(self, name):
|
||||
Output("/* Cleanup of %s goes here */", name)
|
||||
|
||||
def outputGetattr(self):
|
||||
Output()
|
||||
Output("static PyObject *%s_getattr(%s *self, char *name)", self.prefix, self.objecttype)
|
||||
OutLbrace()
|
||||
self.outputGetattrBody()
|
||||
OutRbrace()
|
||||
|
||||
def outputGetattrBody(self):
|
||||
self.outputGetattrHook()
|
||||
Output("return Py_FindMethodInChain(&%s_chain, (PyObject *)self, name);",
|
||||
self.prefix)
|
||||
|
||||
def outputGetattrHook(self):
|
||||
pass
|
||||
|
||||
def outputSetattr(self):
|
||||
Output()
|
||||
Output("#define %s_setattr NULL", self.prefix)
|
||||
|
||||
def outputCompare(self):
|
||||
Output()
|
||||
Output("#define %s_compare NULL", self.prefix)
|
||||
|
||||
def outputRepr(self):
|
||||
Output()
|
||||
Output("#define %s_repr NULL", self.prefix)
|
||||
|
||||
def outputHash(self):
|
||||
Output()
|
||||
Output("#define %s_hash NULL", self.prefix)
|
||||
|
||||
def outputTypeObject(self):
|
||||
sf = self.static and "static "
|
||||
Output()
|
||||
Output("%sPyTypeObject %s = {", sf, self.typename)
|
||||
IndentLevel()
|
||||
Output("PyObject_HEAD_INIT(NULL)")
|
||||
Output("0, /*ob_size*/")
|
||||
if self.modulename:
|
||||
Output("\"%s.%s\", /*tp_name*/", self.modulename, self.name)
|
||||
else:
|
||||
Output("\"%s\", /*tp_name*/", self.name)
|
||||
Output("sizeof(%s), /*tp_basicsize*/", self.objecttype)
|
||||
Output("0, /*tp_itemsize*/")
|
||||
Output("/* methods */")
|
||||
Output("(destructor) %s_dealloc, /*tp_dealloc*/", self.prefix)
|
||||
Output("0, /*tp_print*/")
|
||||
Output("(getattrfunc) %s_getattr, /*tp_getattr*/", self.prefix)
|
||||
Output("(setattrfunc) %s_setattr, /*tp_setattr*/", self.prefix)
|
||||
Output("(cmpfunc) %s_compare, /*tp_compare*/", self.prefix)
|
||||
Output("(reprfunc) %s_repr, /*tp_repr*/", self.prefix)
|
||||
Output("(PyNumberMethods *)0, /* tp_as_number */")
|
||||
Output("(PySequenceMethods *)0, /* tp_as_sequence */")
|
||||
Output("(PyMappingMethods *)0, /* tp_as_mapping */")
|
||||
Output("(hashfunc) %s_hash, /*tp_hash*/", self.prefix)
|
||||
DedentLevel()
|
||||
Output("};")
|
||||
|
||||
def outputTypeObjectInitializer(self):
|
||||
Output("""%s.ob_type = &PyType_Type;""", self.typename)
|
||||
if self.basetype:
|
||||
Output("%s.tp_base = &%s;", self.typename, self.basetype)
|
||||
Output("if (PyType_Ready(&%s) < 0) return;", self.typename)
|
||||
Output("""Py_INCREF(&%s);""", self.typename)
|
||||
Output("PyModule_AddObject(m, \"%s\", (PyObject *)&%s);", self.name, self.typename);
|
||||
self.outputTypeObjectInitializerCompat()
|
||||
|
||||
def outputTypeObjectInitializerCompat(self):
|
||||
Output("/* Backward-compatible name */")
|
||||
Output("""Py_INCREF(&%s);""", self.typename);
|
||||
Output("PyModule_AddObject(m, \"%sType\", (PyObject *)&%s);", self.name, self.typename);
|
||||
|
||||
def outputPEP253Hooks(self):
|
||||
pass
|
||||
|
||||
class PEP252Mixin:
|
||||
getsetlist = []
|
||||
|
||||
def assertions(self):
|
||||
# Check that various things aren't overridden. If they are it could
|
||||
# signify a bgen-client that has been partially converted to PEP252.
|
||||
assert self.outputGetattr.__func__ == PEP252Mixin.outputGetattr.__func__
|
||||
assert self.outputSetattr.__func__ == PEP252Mixin.outputSetattr.__func__
|
||||
assert self.outputGetattrBody == None
|
||||
assert self.outputGetattrHook == None
|
||||
assert self.basechain == "NULL"
|
||||
|
||||
def outputGetattr(self):
|
||||
pass
|
||||
|
||||
outputGetattrBody = None
|
||||
|
||||
outputGetattrHook = None
|
||||
|
||||
def outputSetattr(self):
|
||||
pass
|
||||
|
||||
def outputMethodChain(self):
|
||||
# This is a good place to output the getters and setters
|
||||
self.outputGetSetList()
|
||||
|
||||
def outputHook(self, name):
|
||||
methodname = "outputHook_" + name
|
||||
if hasattr(self, methodname):
|
||||
func = getattr(self, methodname)
|
||||
func()
|
||||
else:
|
||||
Output("0, /*%s*/", name)
|
||||
|
||||
def outputTypeObject(self):
|
||||
sf = self.static and "static "
|
||||
Output()
|
||||
Output("%sPyTypeObject %s = {", sf, self.typename)
|
||||
IndentLevel()
|
||||
Output("PyObject_HEAD_INIT(NULL)")
|
||||
Output("0, /*ob_size*/")
|
||||
if self.modulename:
|
||||
Output("\"%s.%s\", /*tp_name*/", self.modulename, self.name)
|
||||
else:
|
||||
Output("\"%s\", /*tp_name*/", self.name)
|
||||
Output("sizeof(%s), /*tp_basicsize*/", self.objecttype)
|
||||
Output("0, /*tp_itemsize*/")
|
||||
|
||||
Output("/* methods */")
|
||||
Output("(destructor) %s_dealloc, /*tp_dealloc*/", self.prefix)
|
||||
Output("0, /*tp_print*/")
|
||||
Output("(getattrfunc)0, /*tp_getattr*/")
|
||||
Output("(setattrfunc)0, /*tp_setattr*/")
|
||||
Output("(cmpfunc) %s_compare, /*tp_compare*/", self.prefix)
|
||||
Output("(reprfunc) %s_repr, /*tp_repr*/", self.prefix)
|
||||
|
||||
Output("(PyNumberMethods *)0, /* tp_as_number */")
|
||||
Output("(PySequenceMethods *)0, /* tp_as_sequence */")
|
||||
Output("(PyMappingMethods *)0, /* tp_as_mapping */")
|
||||
|
||||
Output("(hashfunc) %s_hash, /*tp_hash*/", self.prefix)
|
||||
self.outputHook("tp_call")
|
||||
Output("0, /*tp_str*/")
|
||||
Output("PyObject_GenericGetAttr, /*tp_getattro*/")
|
||||
Output("PyObject_GenericSetAttr, /*tp_setattro */")
|
||||
|
||||
self.outputHook("tp_as_buffer")
|
||||
Output("%s, /* tp_flags */", self.tp_flags)
|
||||
self.outputHook("tp_doc")
|
||||
self.outputHook("tp_traverse")
|
||||
self.outputHook("tp_clear")
|
||||
self.outputHook("tp_richcompare")
|
||||
self.outputHook("tp_weaklistoffset")
|
||||
self.outputHook("tp_iter")
|
||||
self.outputHook("tp_iternext")
|
||||
Output("%s_methods, /* tp_methods */", self.prefix)
|
||||
self.outputHook("tp_members")
|
||||
Output("%s_getsetlist, /*tp_getset*/", self.prefix)
|
||||
self.outputHook("tp_base")
|
||||
self.outputHook("tp_dict")
|
||||
self.outputHook("tp_descr_get")
|
||||
self.outputHook("tp_descr_set")
|
||||
self.outputHook("tp_dictoffset")
|
||||
self.outputHook("tp_init")
|
||||
self.outputHook("tp_alloc")
|
||||
self.outputHook("tp_new")
|
||||
self.outputHook("tp_free")
|
||||
DedentLevel()
|
||||
Output("};")
|
||||
|
||||
def outputGetSetList(self):
|
||||
if self.getsetlist:
|
||||
for name, get, set, doc in self.getsetlist:
|
||||
if get:
|
||||
self.outputGetter(name, get)
|
||||
else:
|
||||
Output("#define %s_get_%s NULL", self.prefix, name)
|
||||
Output()
|
||||
if set:
|
||||
self.outputSetter(name, set)
|
||||
else:
|
||||
Output("#define %s_set_%s NULL", self.prefix, name)
|
||||
Output()
|
||||
|
||||
Output("static PyGetSetDef %s_getsetlist[] = {", self.prefix)
|
||||
IndentLevel()
|
||||
for name, get, set, doc in self.getsetlist:
|
||||
if doc:
|
||||
doc = '"' + doc + '"'
|
||||
else:
|
||||
doc = "NULL"
|
||||
Output("{\"%s\", (getter)%s_get_%s, (setter)%s_set_%s, %s},",
|
||||
name, self.prefix, name, self.prefix, name, doc)
|
||||
Output("{NULL, NULL, NULL, NULL},")
|
||||
DedentLevel()
|
||||
Output("};")
|
||||
else:
|
||||
Output("#define %s_getsetlist NULL", self.prefix)
|
||||
Output()
|
||||
|
||||
def outputGetter(self, name, code):
|
||||
Output("static PyObject *%s_get_%s(%s *self, void *closure)",
|
||||
self.prefix, name, self.objecttype)
|
||||
OutLbrace()
|
||||
Output(code)
|
||||
OutRbrace()
|
||||
Output()
|
||||
|
||||
def outputSetter(self, name, code):
|
||||
Output("static int %s_set_%s(%s *self, PyObject *v, void *closure)",
|
||||
self.prefix, name, self.objecttype)
|
||||
OutLbrace()
|
||||
Output(code)
|
||||
Output("return 0;")
|
||||
OutRbrace()
|
||||
Output()
|
||||
|
||||
class PEP253Mixin(PEP252Mixin):
|
||||
tp_flags = "Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE"
|
||||
|
||||
def outputHook_tp_init(self):
|
||||
Output("%s_tp_init, /* tp_init */", self.prefix)
|
||||
|
||||
def outputHook_tp_alloc(self):
|
||||
Output("%s_tp_alloc, /* tp_alloc */", self.prefix)
|
||||
|
||||
def outputHook_tp_new(self):
|
||||
Output("%s_tp_new, /* tp_new */", self.prefix)
|
||||
|
||||
def outputHook_tp_free(self):
|
||||
Output("%s_tp_free, /* tp_free */", self.prefix)
|
||||
|
||||
def output_tp_initBody_basecall(self):
|
||||
"""If a type shares its init call with its base type set output_tp_initBody
|
||||
to output_tp_initBody_basecall"""
|
||||
if self.basetype:
|
||||
Output("if (%s.tp_init)", self.basetype)
|
||||
OutLbrace()
|
||||
Output("if ( (*%s.tp_init)(_self, _args, _kwds) < 0) return -1;", self.basetype)
|
||||
OutRbrace()
|
||||
|
||||
output_tp_initBody = None
|
||||
|
||||
def output_tp_init(self):
|
||||
if self.output_tp_initBody:
|
||||
Output("static int %s_tp_init(PyObject *_self, PyObject *_args, PyObject *_kwds)", self.prefix)
|
||||
OutLbrace()
|
||||
self.output_tp_initBody()
|
||||
OutRbrace()
|
||||
else:
|
||||
Output("#define %s_tp_init 0", self.prefix)
|
||||
Output()
|
||||
|
||||
output_tp_allocBody = None
|
||||
|
||||
def output_tp_alloc(self):
|
||||
if self.output_tp_allocBody:
|
||||
Output("static PyObject *%s_tp_alloc(PyTypeObject *type, int nitems)",
|
||||
self.prefix)
|
||||
OutLbrace()
|
||||
self.output_tp_allocBody()
|
||||
OutRbrace()
|
||||
else:
|
||||
Output("#define %s_tp_alloc PyType_GenericAlloc", self.prefix)
|
||||
Output()
|
||||
|
||||
def output_tp_newBody(self):
|
||||
Output("PyObject *_self;");
|
||||
Output("%s itself;", self.itselftype);
|
||||
Output("char *kw[] = {\"itself\", 0};")
|
||||
Output()
|
||||
Output("if (!PyArg_ParseTupleAndKeywords(_args, _kwds, \"O&\", kw, %s_Convert, &itself)) return NULL;",
|
||||
self.prefix);
|
||||
if self.basetype:
|
||||
Output("if (%s.tp_new)", self.basetype)
|
||||
OutLbrace()
|
||||
Output("if ( (*%s.tp_new)(type, _args, _kwds) == NULL) return NULL;", self.basetype)
|
||||
Dedent()
|
||||
Output("} else {")
|
||||
Indent()
|
||||
Output("if ((_self = type->tp_alloc(type, 0)) == NULL) return NULL;")
|
||||
OutRbrace()
|
||||
else:
|
||||
Output("if ((_self = type->tp_alloc(type, 0)) == NULL) return NULL;")
|
||||
Output("((%s *)_self)->ob_itself = itself;", self.objecttype)
|
||||
Output("return _self;")
|
||||
|
||||
def output_tp_new(self):
|
||||
if self.output_tp_newBody:
|
||||
Output("static PyObject *%s_tp_new(PyTypeObject *type, PyObject *_args, PyObject *_kwds)", self.prefix)
|
||||
OutLbrace()
|
||||
self.output_tp_newBody()
|
||||
OutRbrace()
|
||||
else:
|
||||
Output("#define %s_tp_new PyType_GenericNew", self.prefix)
|
||||
Output()
|
||||
|
||||
output_tp_freeBody = None
|
||||
|
||||
def output_tp_free(self):
|
||||
if self.output_tp_freeBody:
|
||||
Output("static void %s_tp_free(PyObject *self)", self.prefix)
|
||||
OutLbrace()
|
||||
self.output_tp_freeBody()
|
||||
OutRbrace()
|
||||
else:
|
||||
Output("#define %s_tp_free PyObject_Del", self.prefix)
|
||||
Output()
|
||||
|
||||
def outputPEP253Hooks(self):
|
||||
self.output_tp_init()
|
||||
self.output_tp_alloc()
|
||||
self.output_tp_new()
|
||||
self.output_tp_free()
|
||||
|
||||
class GlobalObjectDefinition(ObjectDefinition):
|
||||
"""Like ObjectDefinition but exports some parts.
|
||||
|
||||
XXX Should also somehow generate a .h file for them.
|
||||
"""
|
||||
|
||||
def __init__(self, name, prefix = None, itselftype = None):
|
||||
ObjectDefinition.__init__(self, name, prefix or name, itselftype or name)
|
||||
self.static = ""
|
||||
|
||||
class ObjectIdentityMixin:
|
||||
"""A mixin class for objects that makes the identity of ob_itself
|
||||
govern comparisons and dictionary lookups. Useful if the C object can
|
||||
be returned by library calls and it is difficult (or impossible) to find
|
||||
the corresponding Python objects. With this you can create Python object
|
||||
wrappers on the fly"""
|
||||
|
||||
def outputCompare(self):
|
||||
Output()
|
||||
Output("static int %s_compare(%s *self, %s *other)", self.prefix, self.objecttype,
|
||||
self.objecttype)
|
||||
OutLbrace()
|
||||
Output("unsigned long v, w;")
|
||||
Output()
|
||||
Output("if (!%s_Check((PyObject *)other))", self.prefix)
|
||||
OutLbrace()
|
||||
Output("v=(unsigned long)self;")
|
||||
Output("w=(unsigned long)other;")
|
||||
OutRbrace()
|
||||
Output("else")
|
||||
OutLbrace()
|
||||
Output("v=(unsigned long)self->ob_itself;")
|
||||
Output("w=(unsigned long)other->ob_itself;")
|
||||
OutRbrace()
|
||||
Output("if( v < w ) return -1;")
|
||||
Output("if( v > w ) return 1;")
|
||||
Output("return 0;")
|
||||
OutRbrace()
|
||||
|
||||
def outputHash(self):
|
||||
Output()
|
||||
Output("static long %s_hash(%s *self)", self.prefix, self.objecttype)
|
||||
OutLbrace()
|
||||
Output("return (long)self->ob_itself;")
|
||||
OutRbrace()
|
|
@ -1,219 +0,0 @@
|
|||
"""Output primitives for the binding generator classes.
|
||||
|
||||
This should really be a class, but then everybody would be passing
|
||||
the output object to each other. I chose for the simpler approach
|
||||
of a module with a global variable. Use SetOutputFile() or
|
||||
SetOutputFileName() to change the output file.
|
||||
"""
|
||||
|
||||
_NeedClose = 0
|
||||
|
||||
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, _NeedClose
|
||||
if _NeedClose:
|
||||
tmp = _File
|
||||
_NeedClose = 0
|
||||
_File = None
|
||||
tmp.close()
|
||||
if file is None:
|
||||
import sys
|
||||
file = sys.stdout
|
||||
_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
|
||||
|
||||
_Level = 0 # Indentation level
|
||||
|
||||
def GetLevel():
|
||||
"""Return the current indentation level."""
|
||||
return _Level
|
||||
|
||||
def SetLevel(level):
|
||||
"""Set the current indentation level.
|
||||
|
||||
This does no type or range checking -- use at own risk.
|
||||
"""
|
||||
global _Level
|
||||
_Level = level
|
||||
|
||||
def Output(format = "", *args):
|
||||
VaOutput(format, args)
|
||||
|
||||
def VaOutput(format, args):
|
||||
"""Call this with a format string and argument tuple for the format.
|
||||
|
||||
A newline is always added. Each line in the output is indented
|
||||
to the proper indentation level -- even if the result of the
|
||||
format expansion contains embedded newlines. Exception: lines
|
||||
beginning with '#' are not indented -- these are assumed to be
|
||||
C preprprocessor lines.
|
||||
"""
|
||||
text = format % args
|
||||
if _Level > 0:
|
||||
indent = '\t' * _Level
|
||||
lines = text.split('\n')
|
||||
for i in range(len(lines)):
|
||||
if lines[i] and lines[i][0] != '#':
|
||||
lines[i] = indent + lines[i]
|
||||
text = '\n'.join(lines)
|
||||
_File.write(text + '\n')
|
||||
|
||||
def IndentLevel(by = 1):
|
||||
"""Increment the indentation level by one.
|
||||
|
||||
When called with an argument, adds it to the indentation level.
|
||||
"""
|
||||
global _Level
|
||||
if _Level+by < 0:
|
||||
raise Error("indentation underflow (internal error)")
|
||||
_Level = _Level + by
|
||||
|
||||
def DedentLevel(by = 1):
|
||||
"""Decrement the indentation level by one.
|
||||
|
||||
When called with an argument, subtracts it from the indentation level.
|
||||
"""
|
||||
IndentLevel(-by)
|
||||
|
||||
def OutIndent(format = "", *args):
|
||||
"""Combine Output() followed by IndentLevel().
|
||||
|
||||
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()
|
||||
|
||||
def OutRbrace():
|
||||
"""Decrease the indentation level and output a '}' on a line by itself."""
|
||||
DedentLevel()
|
||||
Output("}")
|
||||
|
||||
def OutHeader(text, dash):
|
||||
"""Output a header comment using a given dash character."""
|
||||
n = 64 - len(text)
|
||||
Output()
|
||||
Output("/* %s %s %s */", dash * (n/2), text, dash * (n - n/2))
|
||||
Output()
|
||||
|
||||
def OutHeader1(text):
|
||||
"""Output a level 1 header comment (uses '=' dashes)."""
|
||||
OutHeader(text, "=")
|
||||
|
||||
def OutHeader2(text):
|
||||
"""Output a level 2 header comment (uses '-' dashes)."""
|
||||
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? :-)
|
||||
|
||||
lines = text.split('\n')
|
||||
indent = ""
|
||||
for line in lines:
|
||||
if line.strip():
|
||||
for c in line:
|
||||
if not c.isspace():
|
||||
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():
|
||||
"""Test program. Run when the module is run as a script."""
|
||||
OutHeader1("test bgenOutput")
|
||||
Out("""
|
||||
#include <Python.h>
|
||||
#include <stdio.h>
|
||||
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
int i;
|
||||
""")
|
||||
IndentLevel()
|
||||
Output("""\
|
||||
/* Here are a few comment lines.
|
||||
Just to test indenting multiple lines.
|
||||
|
||||
End of the comment lines. */
|
||||
""")
|
||||
Output("for (i = 0; i < argc; i++)")
|
||||
OutLbrace()
|
||||
Output('printf("argv[%%d] = %%s\\n", i, argv[i]);')
|
||||
OutRbrace()
|
||||
Output("exit(0)")
|
||||
OutRbrace()
|
||||
OutHeader2("end test")
|
||||
|
||||
if __name__ == '__main__':
|
||||
_test()
|
|
@ -1,62 +0,0 @@
|
|||
"""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 getSizeDeclarations(self, name):
|
||||
return []
|
||||
|
||||
def getAuxDeclarations(self, name):
|
||||
return ["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__, (int)%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__, (int)_rv" % name
|
|
@ -1,67 +0,0 @@
|
|||
"""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 getSizeDeclarations(self, name):
|
||||
return []
|
||||
|
||||
def getAuxDeclarations(self, name):
|
||||
return []
|
||||
|
||||
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,328 +0,0 @@
|
|||
"""Type classes and a modest collection of standard types."""
|
||||
|
||||
|
||||
from bgenOutput import *
|
||||
|
||||
|
||||
class Type:
|
||||
|
||||
"""Define the various things you can do with a C type.
|
||||
|
||||
Most methods are intended to be extended or overridden.
|
||||
"""
|
||||
|
||||
def __init__(self, typeName, fmt):
|
||||
"""Call with the C name and getargs format for the type.
|
||||
|
||||
Example: int = Type("int", "i")
|
||||
"""
|
||||
self.typeName = typeName
|
||||
self.fmt = fmt
|
||||
|
||||
def declare(self, name, reference=False):
|
||||
"""Declare a variable of the type with a given name.
|
||||
|
||||
Example: int.declare('spam') prints "int spam;"
|
||||
"""
|
||||
for decl in self.getArgDeclarations(name, reference):
|
||||
Output("%s;", decl)
|
||||
for decl in self.getAuxDeclarations(name):
|
||||
Output("%s;", decl)
|
||||
|
||||
def getArgDeclarations(self, name, reference=False, constmode=False, outmode=False):
|
||||
"""Return the main part of the declarations for this type: the items
|
||||
that will be passed as arguments in the C/C++ function call."""
|
||||
if reference:
|
||||
ref = "&"
|
||||
else:
|
||||
ref = ""
|
||||
if constmode:
|
||||
const = "const "
|
||||
else:
|
||||
const = ""
|
||||
if outmode:
|
||||
out = "*"
|
||||
else:
|
||||
out = ""
|
||||
return ["%s%s%s%s %s" % (const, self.typeName, ref, out, name)]
|
||||
|
||||
def getAuxDeclarations(self, name):
|
||||
"""Return any auxiliary declarations needed for implementing this
|
||||
type, such as helper variables used to hold sizes, etc. These declarations
|
||||
are not part of the C/C++ function call interface."""
|
||||
return []
|
||||
|
||||
def getargs(self):
|
||||
return self.getargsFormat(), self.getargsArgs()
|
||||
|
||||
def getargsFormat(self):
|
||||
"""Return the format for this type for use with PyArg_Parse().
|
||||
|
||||
Example: int.getargsFormat() returns the string "i".
|
||||
(getargs is a very old name for PyArg_Parse, hence the name of this method).
|
||||
"""
|
||||
return self.fmt
|
||||
|
||||
def getargsArgs(self, name):
|
||||
"""Return an argument for use with PyArg_Parse().
|
||||
|
||||
Example: int.getargsArgs("spam") returns the string "&spam".
|
||||
"""
|
||||
return "&" + name
|
||||
|
||||
def getargsPreCheck(self, name):
|
||||
"""Perform any actions needed before calling getargs().
|
||||
|
||||
This could include declaring temporary variables and such.
|
||||
"""
|
||||
|
||||
def getargsCheck(self, name):
|
||||
"""Perform any needed post-[new]getargs() checks.
|
||||
|
||||
This is type-dependent; the default does not check for errors.
|
||||
An example would be a check for a maximum string length, or it
|
||||
could do post-getargs() copying or conversion."""
|
||||
|
||||
def passInput(self, name):
|
||||
"""Return an argument for passing a variable into a call.
|
||||
|
||||
Example: int.passInput("spam") returns the string "spam".
|
||||
"""
|
||||
return name
|
||||
|
||||
def passOutput(self, name):
|
||||
"""Return an argument for returning a variable out of a call.
|
||||
|
||||
Example: int.passOutput("spam") returns the string "&spam".
|
||||
"""
|
||||
return "&" + name
|
||||
|
||||
def passReference(self, name):
|
||||
"""Return an argument for C++ pass-by-reference.
|
||||
Default is to call passInput().
|
||||
"""
|
||||
return self.passInput(name)
|
||||
|
||||
def errorCheck(self, name):
|
||||
"""Check for an error returned in the variable.
|
||||
|
||||
This is type-dependent; the default does not check for errors.
|
||||
An example would be a check for a NULL pointer.
|
||||
If an error is found, the generated routine should
|
||||
raise an exception and return NULL.
|
||||
|
||||
XXX There should be a way to add error clean-up code.
|
||||
"""
|
||||
Output("/* XXX no err check for %s %s */", self.typeName, name)
|
||||
|
||||
def mkvalue(self):
|
||||
return self.mkvalueFormat(), self.mkvalueArgs()
|
||||
|
||||
def mkvalueFormat(self):
|
||||
"""Return the format for this type for use with Py_BuildValue().
|
||||
|
||||
This is normally the same as getargsFormat() but it is
|
||||
a separate function to allow future divergence.
|
||||
(mkvalue is a very old name for Py_BuildValue, hence the name of this
|
||||
method).
|
||||
"""
|
||||
return self.getargsFormat()
|
||||
|
||||
def mkvalueArgs(self, name):
|
||||
"""Return an argument for use with Py_BuildValue().
|
||||
|
||||
Example: int.mkvalueArgs("spam") returns the string "spam".
|
||||
"""
|
||||
return name
|
||||
|
||||
def mkvaluePreCheck(self, name):
|
||||
"""Perform any actions needed before calling mkvalue().
|
||||
|
||||
This could include declaring temporary variables and such.
|
||||
"""
|
||||
|
||||
def cleanup(self, name):
|
||||
"""Clean up if necessary.
|
||||
|
||||
This is normally empty; it may deallocate buffers etc.
|
||||
"""
|
||||
pass
|
||||
|
||||
class ByAddressType(Type):
|
||||
"Simple type that is also passed by address for input"
|
||||
|
||||
def passInput(self, name):
|
||||
return "&%s" % name
|
||||
|
||||
|
||||
|
||||
# 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, name):
|
||||
raise RuntimeError("Type '%s' can only be used for input parameters" % self.typeName)
|
||||
|
||||
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, name):
|
||||
raise RuntimeError("Type '%s' can only be used for output parameters" % self.typeName)
|
||||
|
||||
class OutputOnlyType(OutputOnlyMixIn, Type):
|
||||
|
||||
"Same as Type, but only usable for output parameters -- passInput is boobytrapped"
|
||||
|
||||
|
||||
# A modest collection of standard C types.
|
||||
void = None
|
||||
char = Type("char", "c")
|
||||
short = Type("short", "h")
|
||||
unsigned_short = Type("unsigned short", "H")
|
||||
int = Type("int", "i")
|
||||
long = Type("long", "l")
|
||||
unsigned_long = Type("unsigned long", "l")
|
||||
float = Type("float", "f")
|
||||
double = Type("double", "d")
|
||||
|
||||
|
||||
# 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 module bgenBuffer.
|
||||
stringptr = InputOnlyType("char*", "s")
|
||||
unicodestringptr = InputOnlyType("wchar_t *", "u")
|
||||
|
||||
|
||||
# Some Python related types.
|
||||
objectptr = Type("PyObject*", "O")
|
||||
stringobjectptr = Type("PyStringObject*", "S")
|
||||
# Etc.
|
||||
|
||||
|
||||
class FakeType(InputOnlyType):
|
||||
|
||||
"""A type that is not represented in the Python version of the interface.
|
||||
|
||||
Instantiate with a value to pass in the call.
|
||||
"""
|
||||
|
||||
def __init__(self, substitute):
|
||||
self.substitute = substitute
|
||||
self.typeName = None # Don't show this argument in __doc__ string
|
||||
|
||||
def getArgDeclarations(self, name, reference=False, constmode=False, outmode=False):
|
||||
return []
|
||||
|
||||
def getAuxDeclarations(self, name, reference=False):
|
||||
return []
|
||||
|
||||
def getargsFormat(self):
|
||||
return ""
|
||||
|
||||
def getargsArgs(self, name):
|
||||
return None
|
||||
|
||||
def passInput(self, name):
|
||||
return self.substitute
|
||||
|
||||
|
||||
class OpaqueType(Type):
|
||||
|
||||
"""A type represented by an opaque object type, always passed by address.
|
||||
|
||||
Instantiate with the type name and the names of the new and convert procs.
|
||||
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, arg = None, extra = None):
|
||||
self.typeName = 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):
|
||||
return "O&"
|
||||
|
||||
def getargsArgs(self, name):
|
||||
return "%s, &%s" % (self.convert, name)
|
||||
|
||||
def passInput(self, name):
|
||||
return "&%s" % name
|
||||
|
||||
def mkvalueFormat(self):
|
||||
return "O&"
|
||||
|
||||
def mkvalueArgs(self, name):
|
||||
return "%s, &%s" % (self.new, name)
|
||||
|
||||
|
||||
class OpaqueByValueType(OpaqueType):
|
||||
|
||||
"""A type represented by an opaque object type, on input passed BY VALUE.
|
||||
|
||||
Instantiate with the type name, and optionally an object type name whose
|
||||
New/Convert functions will be used.
|
||||
"""
|
||||
|
||||
def passInput(self, name):
|
||||
return name
|
||||
|
||||
def mkvalueArgs(self, name):
|
||||
return "%s, %s" % (self.new, name)
|
||||
|
||||
class OpaqueByRefType(OpaqueType):
|
||||
"""An opaque object type, passed by reference.
|
||||
|
||||
Instantiate with the type name, and optionally an object type name whose
|
||||
New/Convert functions will be used.
|
||||
"""
|
||||
|
||||
def passInput(self, name):
|
||||
return name
|
||||
|
||||
# def passOutput(self, name):
|
||||
# return name
|
||||
|
||||
def mkvalueFormat(self):
|
||||
return "O"
|
||||
|
||||
def mkvalueArgs(self, name):
|
||||
return "%s(%s)" % (self.new, name)
|
||||
|
||||
class OpaqueByValueStructType(OpaqueByValueType):
|
||||
"""Similar to OpaqueByValueType, but we also pass this to mkvalue by
|
||||
address, in stead of by value.
|
||||
"""
|
||||
|
||||
def mkvalueArgs(self, name):
|
||||
return "%s, &%s" % (self.new, 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, %s" % (self.convert, name)
|
||||
|
||||
def passOutput(self, name):
|
||||
return name
|
|
@ -1,112 +0,0 @@
|
|||
"""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
|
||||
RefMode = 32
|
||||
ConstMode = 64
|
||||
|
||||
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 == ReturnMode+RefMode:
|
||||
self.type.declare(self.name, reference=True)
|
||||
elif self.flags != SelfMode:
|
||||
self.type.declare(self.name)
|
||||
|
||||
def getArgDeclarations(self, fullmodes=False):
|
||||
refmode = (self.flags & RefMode)
|
||||
constmode = False
|
||||
outmode = False
|
||||
if fullmodes:
|
||||
constmode = (self.flags & ConstMode)
|
||||
outmode = (self.flags & OutMode)
|
||||
return self.type.getArgDeclarations(self.name,
|
||||
reference=refmode, constmode=constmode, outmode=outmode)
|
||||
|
||||
def getAuxDeclarations(self):
|
||||
return self.type.getAuxDeclarations(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 getargsPreCheck(self):
|
||||
return self.type.getargsPreCheck(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 & RefMode:
|
||||
return self.type.passReference(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 mkvaluePreCheck(self):
|
||||
return self.type.mkvaluePreCheck(self.name)
|
||||
|
||||
def cleanup(self):
|
||||
"""Call the type's cleanup method."""
|
||||
return self.type.cleanup(self.name)
|
|
@ -1,197 +0,0 @@
|
|||
"""\
|
||||
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")
|
||||
Size = Type("Size", "l")
|
||||
Style = Type("Style", "b")
|
||||
StyleParameter = Type("StyleParameter", "h")
|
||||
CharParameter = Type("CharParameter", "h")
|
||||
TextEncoding = Type("TextEncoding", "l")
|
||||
ByteCount = Type("ByteCount", "l")
|
||||
Duration = Type("Duration", "l")
|
||||
ByteOffset = Type("ByteOffset", "l")
|
||||
OptionBits = Type("OptionBits", "l")
|
||||
ItemCount = Type("ItemCount", "l")
|
||||
PBVersion = Type("PBVersion", "l")
|
||||
ScriptCode = Type("ScriptCode", "h")
|
||||
LangCode = Type("LangCode", "h")
|
||||
RegionCode = Type("RegionCode", "h")
|
||||
|
||||
UInt8 = Type("UInt8", "b")
|
||||
SInt8 = Type("SInt8", "b")
|
||||
UInt16 = Type("UInt16", "H")
|
||||
SInt16 = Type("SInt16", "h")
|
||||
UInt32 = Type("UInt32", "l")
|
||||
SInt32 = Type("SInt32", "l")
|
||||
Float32 = Type("Float32", "f")
|
||||
|
||||
wide = OpaqueByValueType("wide", "PyMac_Buildwide", "PyMac_Getwide")
|
||||
wide_ptr = OpaqueType("wide", "PyMac_Buildwide", "PyMac_Getwide")
|
||||
|
||||
# Pascal strings
|
||||
ConstStr255Param = OpaqueArrayType("Str255", "PyMac_BuildStr255", "PyMac_GetStr255")
|
||||
Str255 = OpaqueArrayType("Str255", "PyMac_BuildStr255", "PyMac_GetStr255")
|
||||
StringPtr = OpaqueByValueType("StringPtr", "PyMac_BuildStr255", "PyMac_GetStr255")
|
||||
ConstStringPtr = StringPtr
|
||||
|
||||
# File System Specifications
|
||||
FSSpec_ptr = OpaqueType("FSSpec", "PyMac_BuildFSSpec", "PyMac_GetFSSpec")
|
||||
FSSpec = OpaqueByValueStructType("FSSpec", "PyMac_BuildFSSpec", "PyMac_GetFSSpec")
|
||||
FSRef_ptr = OpaqueType("FSRef", "PyMac_BuildFSRef", "PyMac_GetFSRef")
|
||||
FSRef = OpaqueByValueStructType("FSRef", "PyMac_BuildFSRef", "PyMac_GetFSRef")
|
||||
|
||||
# OSType and ResType: 4-byte character strings
|
||||
def OSTypeType(typename):
|
||||
return OpaqueByValueType(typename, "PyMac_BuildOSType", "PyMac_GetOSType")
|
||||
OSType = OSTypeType("OSType")
|
||||
ResType = OSTypeType("ResType")
|
||||
FourCharCode = OSTypeType("FourCharCode")
|
||||
|
||||
# Version numbers
|
||||
NumVersion = OpaqueByValueType("NumVersion", "PyMac_BuildNumVersion", "BUG")
|
||||
|
||||
# Handles (always resources in our case)
|
||||
Handle = OpaqueByValueType("Handle", "ResObj")
|
||||
MenuHandle = OpaqueByValueType("MenuHandle", "MenuObj")
|
||||
MenuRef = MenuHandle
|
||||
ControlHandle = OpaqueByValueType("ControlHandle", "CtlObj")
|
||||
ControlRef = ControlHandle
|
||||
|
||||
# Windows and Dialogs
|
||||
WindowPtr = OpaqueByValueType("WindowPtr", "WinObj")
|
||||
WindowRef = WindowPtr
|
||||
DialogPtr = OpaqueByValueType("DialogPtr", "DlgObj")
|
||||
DialogRef = DialogPtr
|
||||
ExistingWindowPtr = OpaqueByValueType("WindowPtr", "WinObj_WhichWindow", "BUG")
|
||||
ExistingDialogPtr = OpaqueByValueType("DialogPtr", "DlgObj_WhichDialog", "BUG")
|
||||
|
||||
# NULL pointer passed in as optional storage -- not present in Python version
|
||||
NullStorage = FakeType("(void *)0")
|
||||
|
||||
# More standard datatypes
|
||||
Fixed = OpaqueByValueType("Fixed", "PyMac_BuildFixed", "PyMac_GetFixed")
|
||||
|
||||
# Quickdraw data types
|
||||
Rect = Rect_ptr = OpaqueType("Rect", "PyMac_BuildRect", "PyMac_GetRect")
|
||||
Point = OpaqueByValueType("Point", "PyMac_BuildPoint", "PyMac_GetPoint")
|
||||
Point_ptr = OpaqueType("Point", "PyMac_BuildPoint", "PyMac_GetPoint")
|
||||
|
||||
# Event records
|
||||
EventRecord = OpaqueType("EventRecord", "PyMac_BuildEventRecord", "PyMac_GetEventRecord")
|
||||
EventRecord_ptr = EventRecord
|
||||
|
||||
# CoreFoundation datatypes
|
||||
CFTypeRef = OpaqueByValueType("CFTypeRef", "CFTypeRefObj")
|
||||
CFStringRef = OpaqueByValueType("CFStringRef", "CFStringRefObj")
|
||||
CFMutableStringRef = OpaqueByValueType("CFMutableStringRef", "CFMutableStringRefObj")
|
||||
CFArrayRef = OpaqueByValueType("CFArrayRef", "CFArrayRefObj")
|
||||
CFMutableArrayRef = OpaqueByValueType("CFMutableArrayRef", "CFMutableArrayRefObj")
|
||||
CFDictionaryRef = OpaqueByValueType("CFDictionaryRef", "CFDictionaryRefObj")
|
||||
CFMutableDictionaryRef = OpaqueByValueType("CFMutableDictionaryRef", "CFMutableDictionaryRefObj")
|
||||
CFURLRef = OpaqueByValueType("CFURLRef", "CFURLRefObj")
|
||||
OptionalCFURLRef = OpaqueByValueType("CFURLRef", "OptionalCFURLRefObj")
|
||||
|
||||
# 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')
|
||||
OSStatus = OSErrType("OSStatus", 'l')
|
||||
|
||||
|
||||
# Various buffer types
|
||||
|
||||
InBuffer = VarInputBufferType('char', 'long', 'l') # (buf, len)
|
||||
UcharInBuffer = VarInputBufferType('unsigned char', 'long', 'l') # (buf, len)
|
||||
OptionalInBuffer = OptionalVarInputBufferType('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)
|
||||
|
||||
# Unicode arguments sometimes have reversed len, buffer (don't understand why Apple did this...)
|
||||
class VarUnicodeInputBufferType(VarInputBufferType):
|
||||
|
||||
def getargsFormat(self):
|
||||
return "u#"
|
||||
|
||||
class VarUnicodeReverseInputBufferType(ReverseInputBufferMixin, VarUnicodeInputBufferType):
|
||||
pass
|
||||
|
||||
UnicodeInBuffer = VarUnicodeInputBufferType('UniChar', 'UniCharCount', 'l')
|
||||
UnicodeReverseInBuffer = VarUnicodeReverseInputBufferType('UniChar', 'UniCharCount', 'l')
|
||||
UniChar_ptr = InputOnlyType("UniCharPtr", "u")
|
||||
|
||||
|
||||
# Predefine various pieces of program text to be passed to Module() later:
|
||||
|
||||
# Stuff added immediately after the system include files
|
||||
includestuff = """
|
||||
#include "pymactoolbox.h"
|
||||
|
||||
/* Macro to test whether a weak-loaded CFM function exists */
|
||||
#define PyMac_PRECHECK(rtn) do { if ( &rtn == NULL ) {\\
|
||||
PyErr_SetString(PyExc_NotImplementedError, \\
|
||||
"Not available in this shared library/OS version"); \\
|
||||
return NULL; \\
|
||||
}} while(0)
|
||||
|
||||
"""
|
||||
|
||||
# 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/OSStatus return values special"
|
||||
def makereturnvar(self):
|
||||
if self.returntype.__class__ == OSErrType:
|
||||
return Variable(self.returntype, "_err", ErrorMode)
|
||||
else:
|
||||
return Variable(self.returntype, "_rv", OutMode)
|
||||
|
||||
class OSErrFunctionGenerator(OSErrMixIn, FunctionGenerator): pass
|
||||
class OSErrMethodGenerator(OSErrMixIn, MethodGenerator): pass
|
||||
|
||||
class WeakLinkMixIn:
|
||||
"Mix-in to test the function actually exists (!= NULL) before calling"
|
||||
|
||||
def precheck(self):
|
||||
Output('#ifndef %s', self.name)
|
||||
Output('PyMac_PRECHECK(%s);', self.name)
|
||||
Output('#endif')
|
||||
|
||||
class WeakLinkFunctionGenerator(WeakLinkMixIn, FunctionGenerator): pass
|
||||
class WeakLinkMethodGenerator(WeakLinkMixIn, MethodGenerator): pass
|
||||
class OSErrWeakLinkFunctionGenerator(OSErrMixIn, WeakLinkMixIn, FunctionGenerator): pass
|
||||
class OSErrWeakLinkMethodGenerator(OSErrMixIn, WeakLinkMixIn, MethodGenerator): pass
|
||||
|
||||
class MacModule(Module):
|
||||
"Subclass which gets the exception initializer from macglue.c"
|
||||
def exceptionInitializer(self):
|
||||
return "PyMac_GetOSErrException()"
|
|
@ -1,846 +0,0 @@
|
|||
"""\
|
||||
|
||||
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 re
|
||||
import sys
|
||||
import os
|
||||
import fnmatch
|
||||
from types import *
|
||||
try:
|
||||
import MacOS
|
||||
except ImportError:
|
||||
MacOS = None
|
||||
|
||||
try:
|
||||
from bgenlocations import CREATOR, INCLUDEDIR
|
||||
except ImportError:
|
||||
CREATOR = None
|
||||
INCLUDEDIR = os.curdir
|
||||
|
||||
Error = "scantools.Error"
|
||||
|
||||
BEGINHTMLREPORT="""<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<html>
|
||||
<head>
|
||||
<style type="text/css">
|
||||
.unmatched { }
|
||||
.commentstripping { color: grey; text-decoration: line-through }
|
||||
.comment { text-decoration: line-through }
|
||||
.notcomment { color: black }
|
||||
.incomplete { color: maroon }
|
||||
.constant { color: green }
|
||||
.pyconstant { background-color: yellow }
|
||||
.blconstant { background-color: yellow; color: red }
|
||||
.declaration { color: blue }
|
||||
.pydeclaration { background-color: yellow }
|
||||
.type { font-style: italic }
|
||||
.name { font-weight: bold }
|
||||
.value { font-style: italic }
|
||||
.arglist { text-decoration: underline }
|
||||
.blacklisted { background-color: yellow; color: red }
|
||||
</style>
|
||||
<title>Bgen scan report</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Bgen scan report</h1>
|
||||
<h2>Legend</h2>
|
||||
<p>This scan report is intended to help you debug the regular expressions
|
||||
used by the bgen scanner. It consists of the original ".h" header file(s)
|
||||
marked up to show you what the regular expressions in the bgen parser matched
|
||||
for each line. NOTE: comments in the original source files may or may not be
|
||||
shown.</p>
|
||||
<p>The typographic conventions of this file are as follows:</p>
|
||||
<dl>
|
||||
<dt>comment stripping</dt>
|
||||
<dd><pre><span class="commentstripping"><span class="notcomment">comment stripping is </span><span class="comment">/* marked up */</span><span class="notcomment"> and the line is repeated if needed</span></span></pre>
|
||||
<p>If anything here does not appear to happen correctly look at
|
||||
<tt>comment1_pat</tt> and <tt>comment2_pat</tt>.</p>
|
||||
</dd>
|
||||
<dt>constant definitions</dt>
|
||||
<dd><pre><span class="constant">#define <span class="name">name</span> <span class="value">value</span></pre>
|
||||
<p>Highlights name and value of the constant. Governed by <tt>sym_pat</tt>.</p>
|
||||
</dd>
|
||||
<dt>function declaration</dt>
|
||||
<dd><pre><span class="declaration"><span class="type">char *</span><span class="name">rindex</span><span class="arglist">(<span class="type">const char *</span><span class="name">s</span>, <span class="type">int </span><span class="name">c</span>)</span>;</span></pre>
|
||||
<p>Highlights type, name and argument list. <tt>type_pat</tt>,
|
||||
<tt>name_pat</tt> and <tt>args_pat</tt> are combined into <tt>whole_pat</tt>, which
|
||||
is what is used here.</p></dd>
|
||||
</dd>
|
||||
<dt>incomplete match for function declaration</dt>
|
||||
<dd><pre><span class="incomplete"><span class="type">char *</span>foo;</span></pre>
|
||||
<p>The beginning of this looked promising, but it did not match a function declaration.
|
||||
In other words, it matched <tt>head_pat</tt> but not <tt>whole_pat</tt>. If the next
|
||||
declaration has also been gobbled up you need to look at <tt>end_pat</tt>.</p>
|
||||
</dd>
|
||||
<dt>unrecognized input</dt>
|
||||
<dd><pre><span class="unmatched">#include "type.h"</span></pre>
|
||||
<p>If there are function declarations the scanner has missed (i.e. things
|
||||
are in this class but you want them to be declarations) you need to adapt
|
||||
<tt>head_pat</tt>.
|
||||
</dd>
|
||||
</dl>
|
||||
<h2>Output</h2>
|
||||
<pre>
|
||||
<span class="unmatched">
|
||||
"""
|
||||
ENDHTMLREPORT="""</span>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
|
||||
class Scanner:
|
||||
|
||||
# Set to 1 in subclass to debug your scanner patterns.
|
||||
debug = 0
|
||||
|
||||
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()
|
||||
self.initusedtypes()
|
||||
if output:
|
||||
self.setoutput(output, defsoutput)
|
||||
if input:
|
||||
self.setinput(input)
|
||||
|
||||
def initusedtypes(self):
|
||||
self.usedtypes = {}
|
||||
|
||||
def typeused(self, type, mode):
|
||||
if type not in self.usedtypes:
|
||||
self.usedtypes[type] = {}
|
||||
self.usedtypes[type][mode] = None
|
||||
|
||||
def reportusedtypes(self):
|
||||
types = sorted(self.usedtypes.keys())
|
||||
for type in types:
|
||||
modes = sorted(self.usedtypes[type].keys())
|
||||
self.report("%s %s", type, " ".join(modes))
|
||||
|
||||
def gentypetest(self, file):
|
||||
fp = open(file, "w")
|
||||
fp.write("types=[\n")
|
||||
types = sorted(self.usedtypes.keys())
|
||||
for type in types:
|
||||
fp.write("\t'%s',\n"%type)
|
||||
fp.write("]\n")
|
||||
fp.write("""missing=0
|
||||
for t in types:
|
||||
try:
|
||||
tt = eval(t)
|
||||
except NameError:
|
||||
print "** Missing type:", t
|
||||
missing = 1
|
||||
if missing: raise "Missing Types"
|
||||
""")
|
||||
fp.close()
|
||||
|
||||
def initsilent(self):
|
||||
self.silent = 1
|
||||
|
||||
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 writeinitialdefs(self):
|
||||
pass
|
||||
|
||||
def initblacklists(self):
|
||||
self.blacklistnames = self.makeblacklistnames()
|
||||
self.blacklisttypes = ["unknown", "-"] + self.makeblacklisttypes()
|
||||
self.greydictnames = self.greylist2dict(self.makegreylist())
|
||||
|
||||
def greylist2dict(self, list):
|
||||
rv = {}
|
||||
for define, namelist in list:
|
||||
for name in namelist:
|
||||
rv[name] = define
|
||||
return rv
|
||||
|
||||
def makeblacklistnames(self):
|
||||
return []
|
||||
|
||||
def makeblacklisttypes(self):
|
||||
return []
|
||||
|
||||
def makegreylist(self):
|
||||
return []
|
||||
|
||||
def initrepairinstructions(self):
|
||||
self.repairinstructions = self.makerepairinstructions()
|
||||
self.inherentpointertypes = self.makeinherentpointertypes()
|
||||
|
||||
def makerepairinstructions(self):
|
||||
"""Parse the repair file into repair instructions.
|
||||
|
||||
The file format is simple:
|
||||
1) use \ to split a long logical line in multiple physical lines
|
||||
2) everything after the first # on a line is ignored (as comment)
|
||||
3) empty lines are ignored
|
||||
4) remaining lines must have exactly 3 colon-separated fields:
|
||||
functionpattern : argumentspattern : argumentsreplacement
|
||||
5) all patterns use shell style pattern matching
|
||||
6) an empty functionpattern means the same as *
|
||||
7) the other two fields are each comma-separated lists of triples
|
||||
8) a triple is a space-separated list of 1-3 words
|
||||
9) a triple with less than 3 words is padded at the end with "*" words
|
||||
10) when used as a pattern, a triple matches the type, name, and mode
|
||||
of an argument, respectively
|
||||
11) when used as a replacement, the words of a triple specify
|
||||
replacements for the corresponding words of the argument,
|
||||
with "*" as a word by itself meaning leave the original word
|
||||
(no other uses of "*" is allowed)
|
||||
12) the replacement need not have the same number of triples
|
||||
as the pattern
|
||||
"""
|
||||
f = self.openrepairfile()
|
||||
if not f: return []
|
||||
print("Reading repair file", repr(f.name), "...")
|
||||
list = []
|
||||
lineno = 0
|
||||
while 1:
|
||||
line = f.readline()
|
||||
if not line: break
|
||||
lineno = lineno + 1
|
||||
startlineno = lineno
|
||||
while line[-2:] == '\\\n':
|
||||
line = line[:-2] + ' ' + f.readline()
|
||||
lineno = lineno + 1
|
||||
i = line.find('#')
|
||||
if i >= 0: line = line[:i]
|
||||
words = [s.strip() for s in line.split(':')]
|
||||
if words == ['']: continue
|
||||
if len(words) != 3:
|
||||
print("Line", startlineno, end=' ')
|
||||
print(": bad line (not 3 colon-separated fields)")
|
||||
print(repr(line))
|
||||
continue
|
||||
[fpat, pat, rep] = words
|
||||
if not fpat: fpat = "*"
|
||||
if not pat:
|
||||
print("Line", startlineno, end=' ')
|
||||
print("Empty pattern")
|
||||
print(repr(line))
|
||||
continue
|
||||
patparts = [s.strip() for s in pat.split(',')]
|
||||
repparts = [s.strip() for s in rep.split(',')]
|
||||
patterns = []
|
||||
for p in patparts:
|
||||
if not p:
|
||||
print("Line", startlineno, end=' ')
|
||||
print("Empty pattern part")
|
||||
print(repr(line))
|
||||
continue
|
||||
pattern = p.split()
|
||||
if len(pattern) > 3:
|
||||
print("Line", startlineno, end=' ')
|
||||
print("Pattern part has > 3 words")
|
||||
print(repr(line))
|
||||
pattern = pattern[:3]
|
||||
else:
|
||||
while len(pattern) < 3:
|
||||
pattern.append("*")
|
||||
patterns.append(pattern)
|
||||
replacements = []
|
||||
for p in repparts:
|
||||
if not p:
|
||||
print("Line", startlineno, end=' ')
|
||||
print("Empty replacement part")
|
||||
print(repr(line))
|
||||
continue
|
||||
replacement = p.split()
|
||||
if len(replacement) > 3:
|
||||
print("Line", startlineno, end=' ')
|
||||
print("Pattern part has > 3 words")
|
||||
print(repr(line))
|
||||
replacement = replacement[:3]
|
||||
else:
|
||||
while len(replacement) < 3:
|
||||
replacement.append("*")
|
||||
replacements.append(replacement)
|
||||
list.append((fpat, patterns, replacements))
|
||||
return list
|
||||
|
||||
def makeinherentpointertypes(self):
|
||||
return []
|
||||
|
||||
def openrepairfile(self, filename = "REPAIR"):
|
||||
try:
|
||||
return open(filename, "rU")
|
||||
except IOError as msg:
|
||||
print(repr(filename), ":", msg)
|
||||
print("Cannot open repair file -- assume no repair needed")
|
||||
return None
|
||||
|
||||
def initfiles(self):
|
||||
self.specmine = 0
|
||||
self.defsmine = 0
|
||||
self.scanmine = 0
|
||||
self.htmlmine = 0
|
||||
self.specfile = sys.stdout
|
||||
self.defsfile = None
|
||||
self.scanfile = sys.stdin
|
||||
self.htmlfile = None
|
||||
self.lineno = 0
|
||||
self.line = ""
|
||||
|
||||
def initpaths(self):
|
||||
self.includepath = [os.curdir, INCLUDEDIR]
|
||||
|
||||
def initpatterns(self):
|
||||
self.head_pat = r"^EXTERN_API[^_]"
|
||||
self.tail_pat = r"[;={}]"
|
||||
self.type_pat = r"EXTERN_API" + \
|
||||
r"[ \t\n]*\([ \t\n]*" + \
|
||||
r"(?P<type>[a-zA-Z0-9_* \t]*[a-zA-Z0-9_*])" + \
|
||||
r"[ \t\n]*\)[ \t\n]*"
|
||||
self.name_pat = r"(?P<name>[a-zA-Z0-9_]+)[ \t\n]*"
|
||||
self.args_pat = r"\((?P<args>([^\(;=\)]+|\([^\(;=\)]*\))*)\)"
|
||||
self.whole_pat = self.type_pat + self.name_pat + self.args_pat
|
||||
self.sym_pat = r"^[ \t]*(?P<name>[a-zA-Z0-9_]+)[ \t]*=" + \
|
||||
r"[ \t]*(?P<defn>[-0-9_a-zA-Z'\"\(][^\t\n,;}]*),?"
|
||||
self.asplit_pat = r"^(?P<type>.*[^a-zA-Z0-9_])(?P<name>[a-zA-Z0-9_]+)(?P<array>\[\])?$"
|
||||
self.comment1_pat = r"(?P<rest>.*)//.*"
|
||||
# note that the next pattern only removes comments that are wholly within one line
|
||||
self.comment2_pat = r"(?P<rest1>.*)/\*.*\*/(?P<rest2>.*)"
|
||||
|
||||
def compilepatterns(self):
|
||||
for name in dir(self):
|
||||
if name[-4:] == "_pat":
|
||||
pat = getattr(self, name)
|
||||
prog = re.compile(pat)
|
||||
setattr(self, name[:-4], prog)
|
||||
|
||||
def initosspecifics(self):
|
||||
if MacOS and CREATOR:
|
||||
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()
|
||||
self.closehtml()
|
||||
|
||||
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 closehtml(self):
|
||||
if self.htmlfile: self.htmlfile.write(ENDHTMLREPORT)
|
||||
tmp = self.htmlmine and self.htmlfile
|
||||
self.htmlfile = 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 sethtmloutput(self, htmlfile):
|
||||
self.closehtml()
|
||||
if htmlfile:
|
||||
if type(htmlfile) == StringType:
|
||||
file = self.openoutput(htmlfile)
|
||||
mine = 1
|
||||
else:
|
||||
file = htmlfile
|
||||
mine = 0
|
||||
self.htmlfile = file
|
||||
self.htmlmine = mine
|
||||
self.htmlfile.write(BEGINHTMLREPORT)
|
||||
|
||||
def openoutput(self, filename):
|
||||
try:
|
||||
file = open(filename, 'w')
|
||||
except IOError as arg:
|
||||
raise IOError(filename, arg)
|
||||
self.setfiletype(filename)
|
||||
return file
|
||||
|
||||
def setinput(self, scan = sys.stdin):
|
||||
if not type(scan) in (TupleType, ListType):
|
||||
scan = [scan]
|
||||
self.allscaninputs = scan
|
||||
self._nextinput()
|
||||
|
||||
def _nextinput(self):
|
||||
if not self.allscaninputs:
|
||||
return 0
|
||||
scan = self.allscaninputs[0]
|
||||
self.allscaninputs = self.allscaninputs[1:]
|
||||
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
|
||||
return 1
|
||||
|
||||
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 %r", fullname)
|
||||
try:
|
||||
return open(fullname, 'rU')
|
||||
except IOError:
|
||||
pass
|
||||
# If not on the path, or absolute, try default open()
|
||||
try:
|
||||
return open(filename, 'rU')
|
||||
except IOError as arg:
|
||||
raise IOError(arg, filename)
|
||||
|
||||
def getline(self):
|
||||
if not self.scanfile:
|
||||
raise Error("input file not set")
|
||||
self.line = self.scanfile.readline()
|
||||
if not self.line:
|
||||
if self._nextinput():
|
||||
return self.getline()
|
||||
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 = %r", inputname)
|
||||
if not self.specfile:
|
||||
self.report("(No interface specifications will be written)")
|
||||
else:
|
||||
self.report("specfile = %r", self.specfile.name)
|
||||
self.specfile.write("# Generated from %r\n\n" % (inputname,))
|
||||
if not self.defsfile:
|
||||
self.report("(No symbol definitions will be written)")
|
||||
else:
|
||||
self.report("defsfile = %r", (self.defsfile.name,))
|
||||
self.defsfile.write("# Generated from %r\n\n" % (os.path.split(inputname)[1],))
|
||||
self.writeinitialdefs()
|
||||
self.alreadydone = []
|
||||
try:
|
||||
while 1:
|
||||
try: line = self.getline()
|
||||
except EOFError: break
|
||||
if self.debug:
|
||||
self.report("LINE: %r" % (line,))
|
||||
match = self.comment1.match(line)
|
||||
if match:
|
||||
self.htmlreport(line, klass='commentstripping', ranges=[(
|
||||
match.start('rest'), match.end('rest'), 'notcomment')])
|
||||
line = match.group('rest')
|
||||
if self.debug:
|
||||
self.report("\tafter comment1: %r" % (line,))
|
||||
match = self.comment2.match(line)
|
||||
while match:
|
||||
if match:
|
||||
self.htmlreport(line, klass='commentstripping', ranges=[
|
||||
(match.start('rest1'), match.end('rest1'), 'notcomment'),
|
||||
(match.start('rest2'), match.end('rest2'), 'notcomment')])
|
||||
line = match.group('rest1')+match.group('rest2')
|
||||
if self.debug:
|
||||
self.report("\tafter comment2: %r" % (line,))
|
||||
match = self.comment2.match(line)
|
||||
if self.defsfile:
|
||||
match = self.sym.match(line)
|
||||
if match:
|
||||
if self.debug:
|
||||
self.report("\tmatches sym.")
|
||||
self.dosymdef(match, line)
|
||||
continue
|
||||
match = self.head.match(line)
|
||||
if match:
|
||||
if self.debug:
|
||||
self.report("\tmatches head.")
|
||||
self.dofuncspec()
|
||||
continue
|
||||
self.htmlreport(line, klass='unmatched')
|
||||
except EOFError:
|
||||
self.error("Uncaught EOF error")
|
||||
self.reportusedtypes()
|
||||
|
||||
def dosymdef(self, match, line):
|
||||
name, defn = match.group('name', 'defn')
|
||||
self.htmlreport(line, klass='constant', ranges=[
|
||||
(match.start('name'), match.end('name'), 'name'),
|
||||
(match.start('defn'), match.end('defn'), 'value')])
|
||||
defn = escape8bit(defn)
|
||||
if self.debug:
|
||||
self.report("\tsym: name=%r, defn=%r" % (name, defn))
|
||||
if not name in self.blacklistnames:
|
||||
oline = "%s = %s\n" % (name, defn)
|
||||
self.defsfile.write(oline)
|
||||
self.htmlreport(oline, klass="pyconstant")
|
||||
else:
|
||||
self.defsfile.write("# %s = %s\n" % (name, defn))
|
||||
self.htmlreport("** no output: name is blacklisted", klass="blconstant")
|
||||
# XXXX No way to handle greylisted names
|
||||
|
||||
def dofuncspec(self):
|
||||
raw = self.line
|
||||
while not self.tail.search(raw):
|
||||
line = self.getline()
|
||||
if self.debug:
|
||||
self.report("* CONTINUATION LINE: %r" % (line,))
|
||||
match = self.comment1.match(line)
|
||||
if match:
|
||||
line = match.group('rest')
|
||||
if self.debug:
|
||||
self.report("\tafter comment1: %r" % (line,))
|
||||
match = self.comment2.match(line)
|
||||
while match:
|
||||
line = match.group('rest1')+match.group('rest2')
|
||||
if self.debug:
|
||||
self.report("\tafter comment1: %r" % (line,))
|
||||
match = self.comment2.match(line)
|
||||
raw = raw + line
|
||||
if self.debug:
|
||||
self.report("* WHOLE LINE: %r" % (raw,))
|
||||
self.processrawspec(raw)
|
||||
return raw
|
||||
|
||||
def processrawspec(self, raw):
|
||||
match = self.whole.search(raw)
|
||||
if not match:
|
||||
self.report("Bad raw spec: %r", raw)
|
||||
if self.debug:
|
||||
match = self.type.search(raw)
|
||||
if not match:
|
||||
self.report("(Type already doesn't match)")
|
||||
self.htmlreport(raw, klass='incomplete', ranges=[(
|
||||
match.start('type'), match.end('type'), 'type')])
|
||||
else:
|
||||
self.report("(but type matched)")
|
||||
self.htmlreport(raw, klass='incomplete')
|
||||
return
|
||||
type, name, args = match.group('type', 'name', 'args')
|
||||
ranges=[
|
||||
(match.start('type'), match.end('type'), 'type'),
|
||||
(match.start('name'), match.end('name'), 'name'),
|
||||
(match.start('args'), match.end('args'), 'arglist')]
|
||||
self.htmlreport(raw, klass='declaration', ranges=ranges)
|
||||
modifiers = self.getmodifiers(match)
|
||||
type = self.pythonizename(type)
|
||||
name = self.pythonizename(name)
|
||||
if self.checkduplicate(name):
|
||||
self.htmlreport("*** no output generated: duplicate name", klass="blacklisted")
|
||||
return
|
||||
self.report("==> %s %s <==", type, name)
|
||||
if self.blacklisted(type, name):
|
||||
self.htmlreport("*** no output generated: function name or return type blacklisted", klass="blacklisted")
|
||||
self.report("*** %s %s blacklisted", type, name)
|
||||
return
|
||||
returnlist = [(type, name, 'ReturnMode')]
|
||||
returnlist = self.repairarglist(name, returnlist)
|
||||
[(type, name, returnmode)] = returnlist
|
||||
arglist = self.extractarglist(args)
|
||||
arglist = self.repairarglist(name, arglist)
|
||||
if self.unmanageable(type, name, arglist):
|
||||
self.htmlreport("*** no output generated: some argument blacklisted", klass="blacklisted")
|
||||
##for arg in arglist:
|
||||
## self.report(" %r", arg)
|
||||
self.report("*** %s %s unmanageable", type, name)
|
||||
return
|
||||
if modifiers:
|
||||
self.generate(type, name, arglist, modifiers)
|
||||
else:
|
||||
self.generate(type, name, arglist)
|
||||
|
||||
def getmodifiers(self, match):
|
||||
return []
|
||||
|
||||
def checkduplicate(self, name):
|
||||
if name in self.alreadydone:
|
||||
self.report("Name has already been defined: %r", name)
|
||||
return True
|
||||
self.alreadydone.append(name)
|
||||
return False
|
||||
|
||||
def pythonizename(self, name):
|
||||
name = re.sub("\*", " ptr", name)
|
||||
name = name.strip()
|
||||
name = re.sub("[ \t]+", "_", name)
|
||||
return name
|
||||
|
||||
def extractarglist(self, args):
|
||||
args = args.strip()
|
||||
if not args or args == "void":
|
||||
return []
|
||||
parts = [s.strip() for s in args.split(",")]
|
||||
arglist = []
|
||||
for part in parts:
|
||||
arg = self.extractarg(part)
|
||||
arglist.append(arg)
|
||||
return arglist
|
||||
|
||||
def extractarg(self, part):
|
||||
mode = "InMode"
|
||||
part = part.strip()
|
||||
match = self.asplit.match(part)
|
||||
if not match:
|
||||
self.error("Indecipherable argument: %r", part)
|
||||
return ("unknown", part, mode)
|
||||
type, name, array = match.group('type', 'name', 'array')
|
||||
if array:
|
||||
# array matches an optional [] after the argument name
|
||||
type = type + " ptr "
|
||||
type = self.pythonizename(type)
|
||||
return self.modifyarg(type, name, mode)
|
||||
|
||||
def modifyarg(self, type, name, mode):
|
||||
if type[:6] == "const_":
|
||||
type = type[6:]
|
||||
elif type[-4:] == "_ptr":
|
||||
type = type[:-4]
|
||||
mode = "OutMode"
|
||||
elif type in self.inherentpointertypes:
|
||||
mode = "OutMode"
|
||||
if type[-4:] == "_far":
|
||||
type = type[:-4]
|
||||
return type, name, mode
|
||||
|
||||
def repairarglist(self, functionname, arglist):
|
||||
arglist = arglist[:]
|
||||
i = 0
|
||||
while i < len(arglist):
|
||||
for item in self.repairinstructions:
|
||||
if len(item) == 2:
|
||||
pattern, replacement = item
|
||||
functionpat = "*"
|
||||
else:
|
||||
functionpat, pattern, replacement = item
|
||||
if not fnmatch.fnmatchcase(functionname, functionpat):
|
||||
continue
|
||||
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(f for f in map(fnmatch.fnmatchcase, arg, patarg) if f) == 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 = int(item[i][1:]) - 1
|
||||
newitem[i] = old[index][i]
|
||||
new.append(tuple(newitem))
|
||||
##self.report("old: %r", old)
|
||||
##self.report("new: %r", new)
|
||||
return new
|
||||
|
||||
def generate(self, tp, name, arglist, modifiers=[]):
|
||||
|
||||
self.typeused(tp, 'return')
|
||||
if modifiers:
|
||||
classname, listname = self.destination(tp, name, arglist, modifiers)
|
||||
else:
|
||||
classname, listname = self.destination(tp, name, arglist)
|
||||
if not classname or not listname:
|
||||
self.htmlreport("*** no output generated: self.destination() returned None", klass="blacklisted")
|
||||
return
|
||||
if not self.specfile:
|
||||
self.htmlreport("*** no output generated: no output file specified", klass="blacklisted")
|
||||
return
|
||||
self.specfile.write("f = %s(%s, %r,\n" % (classname, tp, name))
|
||||
for atype, aname, amode in arglist:
|
||||
self.typeused(atype, amode)
|
||||
self.specfile.write(" (%s, %r, %s),\n" %
|
||||
(atype, aname, amode))
|
||||
if name in self.greydictnames:
|
||||
self.specfile.write(" condition=%r,\n"%(self.greydictnames[name],))
|
||||
self.generatemodifiers(classname, name, modifiers)
|
||||
self.specfile.write(")\n")
|
||||
self.specfile.write("%s.append(f)\n\n" % listname)
|
||||
if self.htmlfile:
|
||||
oline = "Adding to %s:\n%s(returntype=%s, name=%r" % (listname, classname, tp, name)
|
||||
for atype, aname, amode in arglist:
|
||||
oline += ",\n (%s, %r, %s)" % (atype, aname, amode)
|
||||
oline += ")\n"
|
||||
self.htmlreport(oline, klass="pydeclaration")
|
||||
|
||||
def destination(self, type, name, arglist):
|
||||
return "FunctionGenerator", "functions"
|
||||
|
||||
def generatemodifiers(self, classname, name, modifiers):
|
||||
pass
|
||||
|
||||
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 htmlreport(self, line, klass=None, ranges=None):
|
||||
if not self.htmlfile: return
|
||||
if ranges is None:
|
||||
ranges = []
|
||||
if klass:
|
||||
ranges.insert(0, (0, len(line), klass))
|
||||
oline = ''
|
||||
i = 0
|
||||
for c in line:
|
||||
for b, e, name in ranges:
|
||||
if b == i:
|
||||
oline += '<span class="%s">' % name
|
||||
if e == i:
|
||||
oline += '</span>'
|
||||
i += 1
|
||||
|
||||
if c == '<': oline += '<'
|
||||
elif c == '>': oline += '>'
|
||||
else: oline += c
|
||||
for b, e, name in ranges:
|
||||
if b >= i:
|
||||
oline += '<span class="%s">' % name
|
||||
if e >= i:
|
||||
oline += '</span>'
|
||||
if not line or line[-1] != '\n':
|
||||
oline += '\n'
|
||||
self.htmlfile.write(oline)
|
||||
|
||||
class Scanner_PreUH3(Scanner):
|
||||
"""Scanner for Universal Headers before release 3"""
|
||||
def initpatterns(self):
|
||||
Scanner.initpatterns(self)
|
||||
self.head_pat = "^extern pascal[ \t]+" # XXX Mac specific!
|
||||
self.type_pat = "pascal[ \t\n]+(?P<type>[a-zA-Z0-9_ \t]*[a-zA-Z0-9_])[ \t\n]+"
|
||||
self.whole_pat = self.type_pat + self.name_pat + self.args_pat
|
||||
self.sym_pat = "^[ \t]*(?P<name>[a-zA-Z0-9_]+)[ \t]*=" + \
|
||||
"[ \t]*(?P<defn>[-0-9'\"][^\t\n,;}]*),?"
|
||||
|
||||
class Scanner_OSX(Scanner):
|
||||
"""Scanner for modern (post UH3.3) Universal Headers """
|
||||
def initpatterns(self):
|
||||
Scanner.initpatterns(self)
|
||||
self.head_pat = "^EXTERN_API(_C)?"
|
||||
self.type_pat = "EXTERN_API(_C)?" + \
|
||||
"[ \t\n]*\([ \t\n]*" + \
|
||||
"(?P<type>[a-zA-Z0-9_* \t]*[a-zA-Z0-9_*])" + \
|
||||
"[ \t\n]*\)[ \t\n]*"
|
||||
self.whole_pat = self.type_pat + self.name_pat + self.args_pat
|
||||
self.sym_pat = "^[ \t]*(?P<name>[a-zA-Z0-9_]+)[ \t]*=" + \
|
||||
"[ \t]*(?P<defn>[-0-9_a-zA-Z'\"\(][^\t\n,;}]*),?"
|
||||
|
||||
_8bit = re.compile(r"[\200-\377]")
|
||||
|
||||
def escape8bit(s):
|
||||
if _8bit.search(s) is not None:
|
||||
out = []
|
||||
for c in s:
|
||||
o = ord(c)
|
||||
if o >= 128:
|
||||
out.append("\\" + hex(o)[1:])
|
||||
else:
|
||||
out.append(c)
|
||||
s = "".join(out)
|
||||
return s
|
||||
|
||||
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…
Reference in New Issue