/scripts/pymod-process.py
Python | 1955 lines | 1888 code | 49 blank | 18 comment | 43 complexity | ee2a9907b38aa32cf855e626144ce620 MD5 | raw file
Possible License(s): AGPL-1.0
- #!/usr/bin/env python
- # dist: public
- import sys, os, re, string, glob
- DEFBUFLEN = 1024
- # lots of precompiled regular expressions
- # include directives
- re_pyinclude = re.compile(r'\s*/\* pyinclude: (.*) \*/')
- # constants
- re_pyconst_dir = re.compile(r'\s*/\* pyconst: (.*), "(.*)" \*/')
- # callbacks
- re_pycb_cbdef = re.compile(r'#define (CB_[A-Z_0-9]*)')
- re_pycb_typedef = re.compile(r'typedef void \(\*([A-Za-z_0-9]*)\)')
- re_pycb_dir = re.compile(r'/\* pycb: (.*?)(\*/)?$')
- # interfaces
- re_pyint_intdef = re.compile(r'#define (I_[A-Z_0-9]*)')
- re_pyint_typedef = re.compile(r'typedef struct (I[a-z_0-9]*)')
- re_pyint_func = re.compile(r'([ ]{4}|\t)[A-Za-z].*?\(\*([A-Za-z_0-9]*)\)')
- re_pyint_dir = re.compile(r'\s*/\* pyint: (.*?)(\*/)?$')
- re_pyint_done = re.compile(r'^}')
- # advisers
- re_pyadv_advdef = re.compile(r'#define (A_[A-Z_0-9]*)')
- re_pyadv_typedef = re.compile(r'typedef struct (A[a-z_0-9]*)')
- re_pyadv_func = re.compile(r'([ ]{4}|\t)[A-Za-z].*?\(\*([A-Za-z_0-9]*)\)')
- re_pyadv_dir = re.compile(r'\s*/\* pyadv: (.*?)(\*/)?$')
- re_pyadv_done = re.compile(r'^}')
- # types
- re_pytype = re.compile(r'\s*/\* pytype: (.*) \*/')
- # utility functions for constant translation
- def const_int(n):
- const_file.write('INT(%s)\n' % n);
- def const_string(n):
- const_file.write('STRING(%s)\n' % n);
- def const_one(n):
- const_file.write('ONE(%s)\n' % n);
- def const_callback(n):
- const_file.write('PYCALLBACK(%s)\n' % n);
- def const_interface(n):
- const_file.write('PYINTERFACE(%s)\n' % n);
-
- def const_adviser(n):
- const_file.write('PYADVISER(%s)\n' % n);
- def tokenize_signature(s):
- out = []
- t = ''
- dash = 0
- for c in s:
- if c in string.letters or c in string.digits or c == '_':
- t += c
- else:
- if t:
- out.append(t)
- t = ''
- if dash and c == '>':
- out.append('->')
- dash = 0
- else:
- dash = 0
- if c in ',()':
- out.append(c)
- elif c == '-':
- dash = 1
- assert not dash
- if t:
- out.append(t)
- return out
- class Arg:
- def __init__(me, tp, flags):
- me.tp = tp
- me.flags = flags
- def __str__(me):
- return str(me.tp) + '[' + ', '.join(map(str, me.flags)) + ']'
- class Func:
- def __init__(me, args, out):
- me.args = args
- me.out = out
- def __str__(me):
- return '(' + ', '.join(map(str, me.args)) + ' -> ' + str(me.out) + ')'
- def is_func(o):
- return getattr(o, '__class__', None) is Func
- def parse_arg(tokens):
- flags = []
- if tokens[0] == '(':
- tokens.pop(0)
- tp = parse_func(tokens)
- assert tokens[0] == ')'
- tokens.pop(0)
- else:
- tp = tokens.pop(0)
- while tokens and tokens[0] not in [',', '->', ')']:
- flags.append(tokens.pop(0))
- return Arg(tp, flags)
- def parse_func(tokens):
- args = []
- while tokens[0] != '->':
- assert tokens[0] != ')'
- args.append(parse_arg(tokens))
- if tokens[0] == ',':
- tokens.pop(0)
- tokens.pop(0)
- out = parse_arg(tokens)
- return Func(args, out)
- def genid(state = [100]):
- state[0] += 1
- return 'py_genid_%d' % state[0]
- class type_gen:
- def format_char(me):
- raise Exception()
- # these two should throw exceptions unless the format char is O&
- def build_converter(me):
- raise Exception()
- def parse_converter(me):
- raise Exception()
- def decl(me):
- raise Exception()
- def buf_decl(me, s):
- return me.decl(s)
- def buf_decl_def(me, s):
- return me.buf_decl(s) + ' = %s' % me.buf_init()
- def parse_decl(me, s):
- return me.buf_decl(s)
- def ptr_decl(me, s):
- return '%s*%s' % (me.decl(''), s)
- def conv_to_buf(me, buf, val):
- return '\t*%s = %s;' % (buf, val)
- def buf_init(me):
- return '0'
- def buf_prefix(me):
- return '&'
- def out_prefix(me):
- return ''
- def ptr_val(me):
- return '*'
- class type_void(type_gen):
- def decl(me, s):
- return 'void ' + s
- def to_obj(me, s):
- return 'PyCObject_FromVoidPtr(ptr, NULL)'
- def from_obj(me, s):
- return '*(int *)PyCObject_AsVoidPtr(%s)' % s
- class type_null(type_gen):
- def format_char(me):
- return ''
- def decl(me, s):
- return 'void *%s = NULL' % s
- class type_zero(type_gen):
- def format_char(me):
- return ''
- def decl(me, s):
- return 'int %s = 0' % s
- class type_one(type_gen):
- def format_char(me):
- return ''
- def decl(me, s):
- return 'int %s = 1' % s
- class type_int(type_gen):
- def format_char(me):
- return 'i'
- def decl(me, s):
- return 'int ' + s
- def to_obj(me, s):
- return 'PyInt_FromLong(%s)' % s
- def from_obj(me, s):
- return 'PyInt_AsLong(%s)' % s
- class type_short(type_int):
- def format_char(me):
- return 'h'
- def decl(me, s):
- return 'short ' + s
- class type_uint(type_int):
- def format_char(me):
- return 'I'
- def decl(me, s):
- return 'unsigned int ' + s
- class type_ushort(type_int):
- def format_char(me):
- return 'H'
- def decl(me, s):
- return 'unsigned short ' + s
- class type_double(type_gen):
- def format_char(me):
- return 'd'
- def decl(me, s):
- return 'double ' + s
- def to_obj(me, s):
- return 'PyFloat_FromDouble(%s)' % s
- def from_obj(me, s):
- return 'PyFloat_AsDouble(%s)' % s
- class type_string(type_gen):
- def format_char(me):
- return 's'
- def decl(me, s):
- return 'const char *' + s
- def parse_decl(me, s):
- return me.decl(s)
- def buf_decl(me, s):
- return 'charbuf %s' % s
- def ptr_decl(me, s):
- return 'char *%s' % s
- def buf_init(me):
- return '{0}'
- def conv_to_buf(me, buf, val):
- return '\tastrncpy(%s, %s, buflen);' % (buf, val)
- def buf_prefix(me):
- return ''
- class type_zstring(type_string):
- def format_char(me):
- return 'z'
- class type_retstring(type_string):
- def format_char(me):
- return 's#'
- class type_player(type_gen):
- def format_char(me):
- return 'O&'
- def decl(me, s):
- return 'Player *' + s
- def build_converter(me):
- return 'cvt_c2p_player'
- def parse_converter(me):
- return 'cvt_p2c_player'
- class type_player_not_none(type_gen):
- def format_char(me):
- return 'O&'
- def decl(me, s):
- return 'Player *' + s
- def build_converter(me):
- return 'cvt_c2p_player_not_none'
- def parse_converter(me):
- return 'cvt_p2c_player_not_none'
- class type_arena(type_gen):
- def format_char(me):
- return 'O&'
- def decl(me, s):
- return 'Arena *' + s
- def build_converter(me):
- return 'cvt_c2p_arena'
- def parse_converter(me):
- return 'cvt_p2c_arena'
- class type_arena_not_none(type_gen):
- def format_char(me):
- return 'O&'
- def decl(me, s):
- return 'Arena *' + s
- def build_converter(me):
- return 'cvt_c2p_arena_not_none'
- def parse_converter(me):
- return 'cvt_p2c_arena_not_none'
- class type_config(type_gen):
- def format_char(me):
- return 'O&'
- def decl(me, s):
- return 'ConfigHandle ' + s
- def build_converter(me):
- return 'cvt_c2p_config'
- def parse_converter(me):
- return 'cvt_p2c_config'
- class type_banner(type_gen):
- def format_char(me):
- return 'O&'
- def decl(me, s):
- return 'Banner *' + s
- def build_converter(me):
- return 'cvt_c2p_banner'
- def parse_converter(me):
- return 'cvt_p2c_banner'
- class type_target(type_gen):
- def format_char(me):
- return 'O&'
- def decl(me, s):
- return 'Target *' + s
- def buf_decl(me, s):
- return 'Target ' + s
- def build_converter(me):
- return 'cvt_c2p_target'
- def parse_converter(me):
- return 'cvt_p2c_target'
- def out_prefix(me):
- return '&'
- def conv_to_buf(me, buf, val):
- raise Exception()
- class type_bufp(type_gen):
- def format_char(me):
- return 's#'
- def decl(me, s):
- raise Exception()
- def buf_decl(me, s):
- return 'const void *%s' % s
- def buf_init(me):
- return 'NULL'
- def conv_to_buf(me, buf, val):
- raise Exception()
- class type_playerlist(type_gen):
- def format_char(me):
- return 'O&'
- def decl(me, s):
- return 'LinkedList *%s = LLAlloc()' % s
- def build_converter(me):
- return 'cvt_c2p_playerlist'
- def parse_converter(me):
- return 'cvt_p2c_playerlist'
- class type_dict(type_gen):
- def format_char(me):
- return 'O&'
- def decl(me, s):
- return 'HashTable *%s = HashAlloc()' %s
- def build_converter(me):
- return 'cvt_c2p_dict'
- def parse_converter(me):
- return 'cvt_p2c_dict'
- def get_type(tp):
- try:
- cname = 'type_' + tp
- cls = globals()[cname]
- return cls()
- except:
- return None
- def create_c_to_py_func(name, func):
- args = func.args
- out = func.out
- informat = []
- outformat = []
- inargs = []
- outargs = []
- decls = []
- extras3 = []
- allargs = []
- av_arena = None
- av_player = None
- if out.tp == 'void':
- retorblank = ''
- rettype = type_void()
- defretval = ''
- elif out.tp == 'retstring':
- assert not out.flags
- typ = get_type(out.tp)
- argname = 'tmp'
- decls.append('\tconst char *tmp;')
- decls.append('\tint buflen;')
- decls.append('\tchar *ret;')
- outformat.append("s#")
- outargs.append('&tmp')
- outargs.append('&buflen')
- retorblank = 'ret'
- rettype = typ
- defretval = 'NULL'
- extras3.append('\tif(buflen != 0)\n\t{')
- extras3.append('\t\tbuflen++;')
- extras3.append('\t\tret = amalloc(sizeof(char) * buflen);')
- extras3.append('\t\tastrncpy(ret, tmp, buflen);\n\t}')
- else:
- assert not out.flags
- typ = get_type(out.tp)
- argname = 'ret'
- decls.append('\t%s;' % typ.decl(argname))
- outformat.append(typ.format_char())
- try:
- outargs.append(typ.build_converter())
- except:
- pass
- outargs.append('&%s' % argname)
- retorblank = 'ret'
- rettype = typ
- defretval = '0'
- idx = 0
- for arg in args:
- idx = idx + 1
- argname = 'arg%d' % idx
- opts = arg.flags
- typ = get_type(arg.tp)
- if arg.tp == 'void':
- continue
- elif arg.tp == 'clos':
- decls.append('\tPyObject *closobj = clos;')
- allargs.append('void *clos')
- elif 'in' in opts or not opts:
- # this is an incoming arg
- argname += '_in'
- informat.append(typ.format_char())
- try:
- inargs.append(typ.build_converter())
- except:
- pass
- inargs.append(argname)
- allargs.append(typ.decl(argname))
- # the arena value can only be an inarg
- if av_arena is None and (arg.tp == 'arena' or arg.tp == 'arena_not_none'):
- av_arena = argname
- elif av_player is None and (arg.tp == 'player' or arg.tp == 'player_not_none'):
- av_player = argname + '->arena'
- elif 'out' in opts:
- # this is an outgoing arg
- argname += '_out'
- vargname = argname + '_v'
- decls.append('\t%s;' % (typ.parse_decl(vargname)))
- outformat.append(typ.format_char())
- try:
- outargs.append(typ.parse_converter())
- except:
- pass
- outargs.append('&%s' % vargname)
- allargs.append(typ.ptr_decl(argname))
- extras3.append(typ.conv_to_buf(argname, vargname))
- elif 'inout' in opts:
- # this is both incoming and outgoing
- argname += '_inout'
- vargname = argname + '_v'
- if arg.tp == 'string':
- decls.append('\t%s;' % (typ.decl(vargname)))
- decls.append('\tint len_%s;' % vargname)
- outformat.append('s#')
- else:
- decls.append('\t%s;' % (typ.buf_decl(vargname)))
- outformat.append(typ.format_char())
- informat.append(typ.format_char())
- try:
- inargs.append(typ.parse_converter())
- except:
- pass
- if isinstance(typ, type_string):
- inargs.append(argname)
- else:
- inargs.append(typ.ptr_val() + argname)
- try:
- outargs.append(typ.build_converter())
- except:
- pass
- outargs.append('&%s' % vargname)
- allargs.append(typ.ptr_decl(argname))
- if arg.tp == 'string':
- outargs.append('&len_%s' % vargname)
- extras3.append('\tif(++len_%s < buflen) buflen = len_%s;' % (vargname, vargname))
- extras3.append(typ.conv_to_buf(argname, vargname))
- elif 'buflen' in opts:
- # this arg is a buffer length
- allargs.append('int %s' % argname)
- new = []
- for e in extras3:
- new.append(e.replace('buflen', argname))
- extras3 = new
- if inargs:
- inargs = ', ' + ', '.join(inargs)
- else:
- inargs = ''
- if outargs:
- outargs = ', ' + ', '.join(outargs)
- else:
- outargs = ''
- if allargs:
- allargs = ', '.join(allargs)
- else:
- allargs = 'void'
- informat = ''.join(informat)
- outformat = ''.join(outformat)
- decls = '\n'.join(decls)
- extras3 = '\n'.join(extras3)
- retdecl = rettype.decl('')
- if isinstance(rettype, type_playerlist):
- retdecl = "LinkedList *"
- if av_arena:
- arenaval = av_arena
- elif av_player:
- arenaval = av_player
- if name:
- print "warning: %s: guessing arena from player argument" % name
- else:
- arenaval = 'ALLARENAS'
- del av_arena
- del av_player
- del args
- del out
- del rettype
- return vars()
- def create_py_to_c_func(func):
- args = func.args
- out = func.out
- informat = []
- outformat = []
- inargs = []
- outargs = []
- decls = []
- extras1 = []
- extras2 = []
- extras3 = []
- extracode = []
- allargs = []
- if out.tp == 'void':
- asgntoret = ''
- else:
- assert not out.flags
- typ = get_type(out.tp)
- argname = 'ret'
- decls.append('\t%s;' % typ.decl(argname))
- outformat.append(typ.format_char())
- try:
- outargs.append(typ.build_converter())
- except:
- pass
- outargs.append(argname)
- asgntoret = '%s = ' % argname
- idx = 0
- for arg in args:
- idx = idx + 1
- argname = 'arg%d' % idx
- opts = arg.flags
- typ = get_type(arg.tp)
- if arg.tp == 'void':
- continue
- elif arg.tp == 'formatted':
- # these are a little weird
- if idx != len(args):
- raise Exception, "formatted arg isn't last!"
- typ = get_type('string')
- argname += '_infmt'
- informat.append(typ.format_char())
- decls.append('\t%s;' % typ.decl(argname))
- inargs.append('&%s' % argname)
- allargs.append('"%s"')
- allargs.append('%s' % argname)
- elif arg.tp == 'clos':
- # hardcoded value. this depends on the existence of exactly
- # one function argument.
- allargs.append('cbfunc')
- elif is_func(arg.tp):
- cbfuncname = genid()
- informat.append('O')
- decls.append('\tPyObject *cbfunc;')
- inargs.append('&cbfunc')
- allargs.append(cbfuncname)
- extras1.append("""
- if (!PyCallable_Check(cbfunc))
- {
- PyErr_SetString(PyExc_TypeError, "func isn't callable");
- return NULL;
- }
- """)
- if 'dynamic' in opts:
- extras1.append('\tPy_INCREF(cbfunc);')
- if 'failval' in opts:
- # provides a way to clean up the extra reference if
- # the return value from the function indicates that
- # the callback won't be called. otherwise, we expect
- # the callback to be called exactly once.
- failval = opts[opts.index('failval')+1]
- extras2.append(
- '\tif (ret == (%s)) { Py_DECREF(cbfunc); }' % failval)
- decref = '\tPy_DECREF(closobj);'
- else:
- decref = ''
- cbdict = create_c_to_py_func(None, arg.tp)
- cbdict['cbfuncname'] = cbfuncname
- cbdict['decref'] = decref
- cbcode = []
- cbcode.append("""
- local %(retdecl)s %(cbfuncname)s(%(allargs)s)
- {
- NEEDS_GIL;
- GI_LOCK();
- PyObject *args, *out;
- %(decls)s
- args = Py_BuildValue("(%(informat)s)"%(inargs)s);
- if (!args)
- {
- log_py_exception(L_ERROR, "python error building args for "
- "interface argument function");
- GI_UNLOCK();
- return %(defretval)s;
- }
- out = PyObject_Call(closobj, args, NULL);
- Py_DECREF(args);
- %(decref)s
- if (!out)
- {
- log_py_exception(L_ERROR, "python error calling "
- "interface argument function");
- GI_UNLOCK();
- return %(defretval)s;
- }
- """)
- if cbdict['outargs']:
- cbcode.append("""
- if (!PyArg_ParseTuple(out, "%(outformat)s"%(outargs)s))
- {
- Py_DECREF(out);
- log_py_exception(L_ERROR, "python error unpacking results of "
- "interface argument function");
- GI_UNLOCK();
- return %(defretval)s;
- }
- """)
- else:
- cbcode.append("""
- if (out != Py_None)
- {
- Py_DECREF(out);
- log_py_exception(L_ERROR, "interface argument function didn't return None as expected");
- GI_UNLOCK();
- return %(defretval)s;
- }
- """)
- cbcode.append("""
- %(extras3)s
- Py_DECREF(out);
- GI_UNLOCK();
- }
- """)
- cbcode = ''.join(cbcode) % cbdict
- extracode.append(cbcode)
- elif 'in' in opts or not opts:
- # this is an incoming arg
- argname += '_in'
- informat.append(typ.format_char())
- decls.append('\t%s;' % (typ.parse_decl(argname)))
- try:
- inargs.append(typ.parse_converter())
- except:
- pass
- if typ.format_char():
- inargs.append('&' + argname)
- allargs.append(typ.out_prefix() + argname)
- elif 'out' in opts:
- # this is an outgoing arg
- argname += '_out'
- if 'buflen' not in opts:
- outformat.append(typ.format_char())
- decls.append('\t%s;' % (typ.buf_decl_def(argname)))
- try:
- outargs.append(typ.build_converter())
- except:
- pass
- outargs.append(typ.out_prefix() + argname)
- allargs.append(typ.buf_prefix() + argname)
- elif 'inout' in opts:
- # this is both incoming and outgoing
- argname += '_inout'
- informat.append(typ.format_char())
- outformat.append(typ.format_char())
- decls.append('\t%s;' % (typ.buf_decl_def(argname)))
- if typ.format_char():
- try:
- inargs.append(typ.parse_converter())
- except:
- pass
- inargs.append('&' + argname)
- try:
- outargs.append(typ.build_converter())
- except:
- pass
- outargs.append(typ.out_prefix() + argname)
- allargs.append(typ.buf_prefix() + argname)
- elif 'buflen' in opts:
- # this arg is a buffer length
- # it must be passed in, so it's sort of like an
- # inarg, but it doesn't get parsed.
- allargs.append('%s' % DEFBUFLEN)
- decls = '\n'.join(decls)
- if inargs:
- inargs = ', ' + ', '.join(inargs)
- else:
- inargs = ''
- if outargs:
- outargs = ', ' + ', '.join(outargs)
- else:
- outargs = ''
- informat = ''.join(informat)
- outformat = ''.join(outformat)
- allargs = ', '.join(allargs)
- extras1 = '\n'.join(extras1)
- extras2 = '\n'.join(extras2)
- extras3 = '\n'.join(extras3)
- extracode = '\n'.join(extracode)
- del args
- del out
- del idx
- return vars()
- # functions for asss<->python callback translation
- pycb_cb_names = []
- def translate_pycb(name, ctype, line):
- pycb_cb_names.append((name, ctype))
- tokens = tokenize_signature(line + '->void')
- func = parse_func(tokens)
- funcname = 'py_cb_%s' % name
- cbvars = create_c_to_py_func(name, func)
- cbvars.update(vars())
- # an optimization: if we have outargs, we need to build the arg
- # tuple every time to get the updated values, but if we don't, we
- # can reuse the tuple.
- outargs = cbvars['outargs']
- buildcode = """
- args = Py_BuildValue("(%(informat)s)"%(inargs)s);
- if (!args)
- {
- log_py_exception(L_ERROR, "python error building args for "
- "callback %(name)s");
- GI_UNLOCK();
- return;
- }
- """
- decref = """
- Py_DECREF(args);
- """
- code = []
- code.append("""
- local %(retdecl)s %(funcname)s(%(allargs)s)
- {
- NEEDS_GIL;
- GI_LOCK();
- PyObject *args, *out;
- LinkedList cbs = LL_INITIALIZER;
- Link *l;
- %(decls)s
- mm->LookupCallback(PYCBPREFIX %(name)s, %(arenaval)s, &cbs);
- if (LLIsEmpty(&cbs))
- {
- GI_UNLOCK();
- return;
- }
- """)
- if not outargs:
- code.append(buildcode)
- code.append("""
- for (l = LLGetHead(&cbs); l; l = l->next)
- {
- """)
- if outargs:
- code.append(buildcode)
- code.append("""
- out = PyObject_Call(l->data, args, NULL);
- """)
- if outargs:
- code.append(decref)
- code.append("""
- if (!out)
- {
- log_py_exception(L_ERROR, "python error calling "
- "callback %(name)s");
- continue;
- }
- """)
- if outargs:
- code.append("""
- if (!PyArg_ParseTuple(out, "%(outformat)s"%(outargs)s))
- {
- Py_DECREF(out);
- log_py_exception(L_ERROR, "python error unpacking results of "
- "callback %(name)s");
- continue;
- }
- """)
- else:
- code.append("""
- if (out != Py_None)
- {
- Py_DECREF(out);
- log_py_exception(L_ERROR, "callback %(name)s didn't return None as expected");
- continue;
- }
- """)
- code.append("""
- Py_DECREF(out);
- %(extras3)s
- }
- """)
- if not outargs:
- code.append(decref)
- code.append("""
- LLEmpty(&cbs);
- GI_UNLOCK();
- }
- """)
- code = ''.join(code) % cbvars
- callback_file.write(code)
- cbvars = create_py_to_c_func(func)
- cbvars['name'] = name
- cbvars['ctype'] = ctype
- code = """
- local PyObject * py_cb_call_%(name)s(Arena *arena, PyObject *args)
- {
- PyObject *out;
- %(decls)s
- if (!PyArg_ParseTuple(args, "%(informat)s"%(inargs)s))
- return NULL;
- %(extras1)s
- DO_CBS(%(name)s, arena, %(ctype)s, (%(allargs)s));
- %(extras2)s
- out = Py_BuildValue("%(outformat)s"%(outargs)s);
- %(extras3)s
- return out;
- }
- """ % cbvars
- callback_file.write(code)
- def finish_pycb():
- callback_file.write("""
- typedef PyObject * (*py_cb_caller)(Arena *arena, PyObject *args);
- local HashTable *py_cb_callers;
- local void init_py_callbacks(void)
- {
- py_cb_callers = HashAlloc();
- """)
- for n, ctype in pycb_cb_names:
- callback_file.write(" { %s typecheck = py_cb_%s; (void)typecheck; }\n" % (ctype, n))
- callback_file.write(" mm->RegCallback(%s, py_cb_%s, ALLARENAS);\n" % (n, n))
- callback_file.write(" HashReplace(py_cb_callers, PYCBPREFIX %s, py_cb_call_%s);\n" % (n, n))
- callback_file.write("""\
- }
- local void deinit_py_callbacks(void)
- {
- """)
- for n, _ in pycb_cb_names:
- callback_file.write(" mm->UnregCallback(%s, py_cb_%s, ALLARENAS);\n" % (n, n))
- callback_file.write("""\
- HashFree(py_cb_callers);
- }
- """)
- # translating interfaces asss<->python
- def init_pyint():
- out = int_file
- out.write("""
- /* pyint declarations */
- local void pyint_generic_dealloc(pyint_generic_interface_object *self)
- {
- mm->ReleaseInterface(self->i);
- PyObject_Del(self);
- }
- """)
- pyint_init_code = []
- def translate_pyint(iid, ifstruct, dirs):
- _, allowed = dirs.pop(0)
- allowed = map(string.strip, allowed.split(','))
- if 'use' in allowed:
- objstructname = 'pyint_obj_%s' % iid
- methods = []
- methoddecls = []
- members = []
- memberdecls = []
- for name, thing in dirs:
- try:
- tokens = tokenize_signature(thing)
- func = parse_func(tokens)
- except:
- print "couldn't parse '%s'" % thing
- continue
- dict = create_py_to_c_func(func)
- mthdname = 'pyint_method_%s_%s' % (iid, name)
- dict.update(vars())
- mthd = """
- %(extracode)s
- local PyObject *
- %(mthdname)s(%(objstructname)s *me, PyObject *args)
- {
- PyObject *out;
- %(decls)s
- if (!PyArg_ParseTuple(args, "%(informat)s"%(inargs)s))
- return NULL;
- %(extras1)s
- %(asgntoret)sme->i->%(name)s(%(allargs)s);
- %(extras2)s
- out = Py_BuildValue("%(outformat)s"%(outargs)s);
- %(extras3)s
- return out;
- }
- """ % dict
- methods.append(mthd)
- decl = """\
- {"%(name)s", (PyCFunction)%(mthdname)s, METH_VARARGS, NULL },
- """ % vars()
- methoddecls.append(decl)
- objstructdecl = """
- typedef struct {
- PyObject_HEAD
- %(ifstruct)s *i;
- } %(objstructname)s;
- """ % vars()
- methoddeclname = 'pyint_%s_methods' % iid
- methoddeclstart = """
- local PyMethodDef %(methoddeclname)s[] = {
- """ % vars()
- methoddeclend = """\
- {NULL}
- };
- """ % vars()
- memberdeclname = 'pyint_%s_members' % iid
- memberdeclstart = """
- local PyMemberDef %(memberdeclname)s[] = {
- """ % vars()
- memberdeclend = """\
- {NULL}
- };
- """ % vars()
- typestructname = 'pyint_%s_type' % iid
- typedecl = """
- #pragma GCC diagnostic push
- #pragma GCC diagnostic ignored "-Wmissing-field-initializers"
- local PyTypeObject %(typestructname)s = {
- PyObject_HEAD_INIT(NULL)
- 0, /*ob_size*/
- "asss.%(ifstruct)s", /*tp_name*/
- sizeof(%(objstructname)s), /*tp_basicsize*/
- 0, /*tp_itemsize*/
- (destructor)pyint_generic_dealloc, /*tp_dealloc*/
- 0, /*tp_print*/
- 0, /*tp_getattr*/
- 0, /*tp_setattr*/
- 0, /*tp_compare*/
- 0, /*tp_repr*/
- 0, /*tp_as_number*/
- 0, /*tp_as_sequence*/
- 0, /*tp_as_mapping*/
- 0, /*tp_hash */
- 0, /*tp_call*/
- 0, /*tp_str*/
- 0, /*tp_getattro*/
- 0, /*tp_setattro*/
- 0, /*tp_as_buffer*/
- Py_TPFLAGS_DEFAULT, /*tp_flags*/
- 0, /*tp_doc */
- 0, /*tp_traverse */
- 0, /*tp_clear */
- 0, /*tp_richcompare*/
- 0, /*tp_weaklistoffset*/
- 0, /*tp_iter*/
- 0, /*tp_iternext*/
- %(methoddeclname)s, /*tp_methods*/
- %(memberdeclname)s, /*tp_members*/
- /* rest are null */
- };
- #pragma GCC diagnostic pop
- """ % vars()
- doinit = """\
- if (PyType_Ready(&%(typestructname)s) < 0) return;
- HashReplace(pyint_ints, %(iid)s, &%(typestructname)s);
- """ % vars()
- pyint_init_code.append(doinit)
- int_file.write('\n/* using interface %(iid)s from python {{{ */\n' % vars())
- int_file.write(objstructdecl)
- for m in methods:
- int_file.write(m)
- int_file.write(methoddeclstart)
- for m in methoddecls:
- int_file.write(m)
- int_file.write(methoddeclend)
- for m in members:
- int_file.write(m)
- int_file.write(memberdeclstart)
- for m in memberdecls:
- int_file.write(m)
- int_file.write(memberdeclend)
- int_file.write(typedecl)
- int_file.write('\n/* }}} */\n')
- if 'impl' in allowed:
- ifacename = 'pyint_int_%s' % iid
- funcs = []
- funcnames = []
- lastout = None
- for name, thing in dirs:
- try:
- tokens = tokenize_signature(thing)
- func = parse_func(tokens)
- except:
- print "bad declaration '%s'" % thing
- continue
- funcname = 'pyint_func_%s_%s' % (iid, name)
- funcdict = create_c_to_py_func('%s::%s' % (iid, name), func)
- funcdict.update(vars())
- code = []
- code.append("""
- local %(retdecl)s %(funcname)s(%(allargs)s)
- {
- NEEDS_GIL;
- GI_LOCK();
- PyObject *args, *out;
- %(decls)s
- args = Py_BuildValue("(%(informat)s)"%(inargs)s);
- if (!args)
- {
- log_py_exception(L_ERROR, "python error building args for "
- "function %(name)s in interface %(iid)s");
- GI_UNLOCK();
- return %(defretval)s;
- }
- out = call_gen_py_interface(PYINTPREFIX %(iid)s, "%(name)s", args, %(arenaval)s);
- if (!out)
- {
- log_py_exception(L_ERROR, "python error calling "
- "function %(name)s in interface %(iid)s");
- GI_UNLOCK();
- return %(defretval)s;
- }
- """)
- if funcdict['outargs']:
- code.append("""
- if (!PyArg_ParseTuple(out, "%(outformat)s"%(outargs)s))
- {
- Py_DECREF(out);
- log_py_exception(L_ERROR, "python error unpacking results of "
- "function %(name)s in interface %(iid)s");
- GI_UNLOCK();
- return %(defretval)s;
- }
- """)
- else:
- code.append("""
- if (out != Py_None)
- {
- Py_DECREF(out);
- log_py_exception(L_ERROR, "interface func %(name)s didn't return None as expected");
- GI_UNLOCK();
- return %(defretval)s;
- }
- """)
- code.append("""
- %(extras3)s
- Py_DECREF(out);
- GI_UNLOCK();
- return %(retorblank)s;
- }
- """)
- code = ''.join(code) % funcdict
- funcs.append(code)
- funcnames.append(funcname)
- funcnames = ',\n\t'.join(funcnames)
- ifstructdecl = """
- local struct %(ifstruct)s %(ifacename)s = {
- INTERFACE_HEAD_INIT(%(iid)s, "pyint-%(iid)s")
- %(funcnames)s
- };
- """ % vars()
- init = "\tHashReplace(pyint_impl_ints, PYINTPREFIX %(iid)s, &%(ifacename)s);\n" % vars()
- pyint_init_code.append(init)
- int_file.write('\n/* implementing interface %(iid)s in python {{{ */\n' % vars())
- for func in funcs:
- int_file.write(func)
- int_file.write(ifstructdecl)
- int_file.write('\n/* }}} */\n')
- def finish_pyint():
- out = int_file
- out.write("""
- local HashTable *pyint_ints;
- local HashTable *pyint_impl_ints;
- local void init_py_interfaces(void)
- {
- pyint_ints = HashAlloc();
- pyint_impl_ints = HashAlloc();
- """)
- for line in pyint_init_code:
- out.write(line)
- out.write("""\
- }
- local void deinit_py_interfaces(void)
- {
- """)
- out.write("""\
- HashFree(pyint_ints);
- HashFree(pyint_impl_ints);
- }
- """)
- # translating advisers asss<->python
- def init_pyadv():
- out = adv_file
- out.write("""
- /* pyadv declarations */
- local void pyadv_generic_dealloc(pyint_generic_adviser_object *self)
- {
- mm->UnregAdviser(self->adv);/*TODO i -> adv*/
- PyObject_Del(self);
- }
- """)
- pyadv_init_code = []
- def translate_pyadv(aid, ifstruct, dirs):
- _, allowed = dirs.pop(0)
- allowed = map(string.strip, allowed.split(','))
- if 'use' in allowed:
- objstructname = 'pyadv_obj_%s' % aid
- methods = []
- methoddecls = []
- members = []
- memberdecls = []
- for name, thing in dirs:
- try:
- tokens = tokenize_signature(thing)
- func = parse_func(tokens)
- except:
- print "couldn't parse '%s'" % thing
- continue
- dict = create_py_to_c_func(func)
- mthdname = 'pyadv_method_%s_%s' % (aid, name)
- dict.update(vars())
- mthd = """
- %(extracode)s
- local PyObject *
- %(mthdname)s(%(objstructname)s *me, PyObject *args)
- {
- PyObject *out;
- %(decls)s
- if (!PyArg_ParseTuple(args, "%(informat)s"%(inargs)s))
- return NULL;
- %(extras1)s
- %(asgntoret)sme->i->%(name)s(%(allargs)s);
- %(extras2)s
- out = Py_BuildValue("%(outformat)s"%(outargs)s);
- %(extras3)s
- return out;
- }
- """ % dict
- methods.append(mthd)
- decl = """\
- {"%(name)s", (PyCFunction)%(mthdname)s, METH_VARARGS, NULL },
- """ % vars()
- methoddecls.append(decl)
- objstructdecl = """
- typedef struct {
- PyObject_HEAD
- %(ifstruct)s *i;
- } %(objstructname)s;
- """ % vars()
- methoddeclname = 'pyadv_%s_methods' % aid
- methoddeclstart = """
- local PyMethodDef %(methoddeclname)s[] = {
- """ % vars()
- methoddeclend = """\
- {NULL}
- };
- """ % vars()
- memberdeclname = 'pyadv_%s_members' % aid
- memberdeclstart = """
- local PyMemberDef %(memberdeclname)s[] = {
- """ % vars()
- memberdeclend = """\
- {NULL}
- };
- """ % vars()
- typestructname = 'pyadv_%s_type' % aid
- typedecl = """
- #pragma GCC diagnostic push
- #pragma GCC diagnostic ignored "-Wmissing-field-initializers"
- local PyTypeObject %(typestructname)s = {
- PyObject_HEAD_INIT(NULL)
- 0, /*ob_size*/
- "asss.%(ifstruct)s", /*tp_name*/
- sizeof(%(objstructname)s), /*tp_basicsize*/
- 0, /*tp_itemsize*/
- (destructor)pyadv_generic_dealloc, /*tp_dealloc*/
- 0, /*tp_print*/
- 0, /*tp_getattr*/
- 0, /*tp_setattr*/
- 0, /*tp_compare*/
- 0, /*tp_repr*/
- 0, /*tp_as_number*/
- 0, /*tp_as_sequence*/
- 0, /*tp_as_mapping*/
- 0, /*tp_hash */
- 0, /*tp_call*/
- 0, /*tp_str*/
- 0, /*tp_getattro*/
- 0, /*tp_setattro*/
- 0, /*tp_as_buffer*/
- Py_TPFLAGS_DEFAULT, /*tp_flags*/
- 0, /*tp_doc */
- 0, /*tp_traverse */
- 0, /*tp_clear */
- 0, /*tp_richcompare*/
- 0, /*tp_weaklistoffset*/
- 0, /*tp_iter*/
- 0, /*tp_iternext*/
- %(methoddeclname)s, /*tp_methods*/
- %(memberdeclname)s, /*tp_members*/
- /* rest are null */
- };
- #pragma GCC diagnostic pop
- """ % vars()
- doinit = """\
- if (PyType_Ready(&%(typestructname)s) < 0) return;
- HashReplace(pyadv_advs, %(aid)s, &%(typestructname)s);
- """ % vars()
- pyadv_init_code.append(doinit)
- adv_file.write('\n/* using adviser %(aid)s from python {{{ */\n' % vars())
- adv_file.write(objstructdecl)
- for m in methods:
- adv_file.write(m)
- adv_file.write(methoddeclstart)
- for m in methoddecls:
- adv_file.write(m)
- adv_file.write(methoddeclend)
- for m in members:
- adv_file.write(m)
- adv_file.write(memberdeclstart)
- for m in memberdecls:
- adv_file.write(m)
- adv_file.write(memberdeclend)
- adv_file.write(typedecl)
- adv_file.write('\n/* }}} */\n')
- if 'impl' in allowed:
- advisname = 'pyadv_adv_%s' % aid
- funcs = []
- funcnames = []
- lastout = None
- for name, thing in dirs:
- try:
- tokens = tokenize_signature(thing)
- func = parse_func(tokens)
- except:
- print "bad declaration '%s'" % thing
- continue
- funcname = 'pyadv_func_%s_%s' % (aid, name)
- funcdict = create_c_to_py_func('%s::%s' % (aid, name), func)
- funcdict.update(vars())
- code = []
- code.append("""
- local %(retdecl)s %(funcname)s(%(allargs)s)
- {
- NEEDS_GIL;
- PyObject *args, *out;
- GI_LOCK();
- %(decls)s
- args = Py_BuildValue("(%(informat)s)"%(inargs)s);
- if (!args)
- {
- log_py_exception(L_ERROR, "python error building args for "
- "function %(name)s in adviser %(aid)s");
- GI_UNLOCK();
- return %(defretval)s;
- }
- out = call_gen_py_adviser(PYADVPREFIX %(aid)s, "%(name)s", args, %(arenaval)s);
- if (!out)
- {
- log_py_exception(L_ERROR, "python error calling "
- "function %(name)s in adviser %(aid)s");
- GI_UNLOCK();
- return %(defretval)s;
- }
- """)
- if funcdict['outargs']:
- code.append("""
- if (!PyArg_ParseTuple(out, "%(outformat)s"%(outargs)s))
- {
- Py_DECREF(out);
- log_py_exception(L_ERROR, "python error unpacking results of "
- "function %(name)s in adviser %(aid)s");
- GI_UNLOCK();
- return %(defretval)s;
- }
- """)
- else:
- code.append("""
- if (out != Py_None)
- {
- Py_DECREF(out);
- log_py_exception(L_ERROR, "adviser func %(name)s didn't return None as expected");
- GI_UNLOCK();
- return %(defretval)s;
- }
- """)
- code.append("""
- %(extras3)s
- Py_DECREF(out);
- GI_UNLOCK();
- return %(retorblank)s;
- }
- """)
- code = ''.join(code) % funcdict
- funcs.append(code)
- funcnames.append(funcname)
- funcnames = ',\n\t'.join(funcnames)
- ifstructdecl = """
- local struct %(ifstruct)s %(advisname)s = {
- ADVISER_HEAD_INIT(%(aid)s)
- %(funcnames)s
- };
- """ % vars()
- init = "\tHashReplace(pyadv_impl_ints, PYADVPREFIX %(aid)s, &%(advisname)s);\n" % vars()
- pyadv_init_code.append(init)
- adv_file.write('\n/* implementing adviser %(aid)s in python {{{ */\n' % vars())
- for func in funcs:
- adv_file.write(func)
- adv_file.write(ifstructdecl)
- adv_file.write('\n/* }}} */\n')
- def finish_pyadv():
- out = adv_file
- out.write("""
- local HashTable *pyadv_advs;
- local HashTable *pyadv_impl_advs;
- local void init_py_advisers(void)
- {
- pyadv_advs = HashAlloc();
- pyadv_impl_advs = HashAlloc();
- """)
- for line in pyadv_init_code:
- out.write(line)
- out.write("""\
- }
- local void deinit_py_advisers(void)
- {
- """)
- out.write("""\
- HashFree(pyadv_advs);
- HashFree(pyadv_impl_advs);
- }
- """)
- def handle_pyconst_directive(tp, pat):
- def clear():
- del extra_patterns[:]
- pat = pat.replace('*', '[A-Z_0-9]*')
- if tp == 'enum':
- # these are always ints, and last until a line with a close-brace
- pat = r'\s*(%s)' % pat
- newre = re.compile(pat)
- extra_patterns.append((newre, const_int))
- extra_patterns.append((re.compile(r'.*}.*;.*'), clear))
- elif tp.startswith('define'):
- # these can be ints or strings, and last until a blank line
- pat = r'#define (%s)' % pat
- newre = re.compile(pat)
- subtp = tp.split()[1].strip()
- func = { 'int': const_int, 'string': const_string, }[subtp]
- extra_patterns.append((newre, func))
- extra_patterns.append((re.compile(r'^$'), clear))
- elif tp == 'config':
- pat = r'#define (%s)' % pat
- extra_patterns.append((re.compile(pat + ' "'), const_string))
- extra_patterns.append((re.compile(pat + ' [0-9]'), const_int))
- extra_patterns.append((re.compile(pat + '$'), const_one))
- extra_patterns.append((re.compile(r'/\* pyconst: config end \*/'), clear))
- def add_converted_type(ctype, name, isstruct):
- class mytype(type_gen):
- def format_char(me):
- return 'O&'
- if isstruct:
- def decl(me, s):
- return '%s *%s' % (ctype, s)
- def ptr_decl(me, s):
- return '%s *%s' % (ctype, s)
- else:
- def decl(me, s):
- return '%s %s' % (ctype, s)
- if isstruct:
- def buf_decl(me, s):
- return '%s %s' % (ctype, s)
- if isstruct:
- def buf_init(me):
- return '{ 0 }';
- else:
- def buf_init(me):
- raise Exception()
- def build_converter(me):
- return 'cvt_c2p_' + name
- def parse_converter(me):
- return 'cvt_p2c_' + name
- if isstruct:
- def out_prefix(me):
- return '&'
- def ptr_val(me):
- return ''
- globals()['type_' + name] = mytype
- def make_opaque_type(ctype, name):
- code = """
- /* dummy value for uniqueness */
- static int pytype_desc_%(name)s;
- ATTR_UNUSED()
- local PyObject * cvt_c2p_%(name)s(void *p)
- {
- if (p == NULL)
- {
- Py_INCREF(Py_None);
- return Py_None;
- }
- else
- return PyCObject_FromVoidPtrAndDesc(p, &pytype_desc_%(name)s, NULL);
- }
- ATTR_UNUSED()
- local int cvt_p2c_%(name)s(PyObject *o, void **pp)
- {
- if (o == Py_None)
- {
- *pp = NULL;
- return TRUE;
- }
- else if (PyCObject_Check(o) &&
- PyCObject_GetDesc(o) == &pytype_desc_%(name)s)
- {
- *pp = PyCObject_AsVoidPtr(o);
- return TRUE;
- }
- else
- {
- PyErr_Format(PyExc_TypeError, "arg isn't a '%%s'", "%(name)s");
- return FALSE;
- }
- }
- """ % vars()
- type_file.write(code)
- add_converted_type(ctype, name, 0)
- def map_struct_type(tp):
- return {
- 'Player': 'player',
- 'Arena': 'arena',
- 'ticks_t': 'int',
- }.get(tp, tp)
- def getter_name(tp):
- return 'pytype_getter_%s' % tp
- def setter_name(tp):
- return 'pytype_setter_%s' % tp
- pytype_made_getsetters = {}
- pytype_objects = []
- def generate_getset_code(tp):
- if pytype_made_getsetters.has_key(tp):
- return []
- pytype_made_getsetters[tp] = 1
- typ = get_type(tp)
- if not typ:
- return []
- ctype = typ.decl('')
- getname = getter_name(tp)
- setname = setter_name(tp)
- getter = """
- local PyObject * %(getname)s(PyObject *obj, void *v)
- {
- int offset = (long)v;
- %(ctype)s *ptr = (%(ctype)s*)(((char*)obj)+offset);
- """ % vars()
- try:
- getter += """\
- return %s(*ptr);
- }
- """ % typ.build_converter()
- except:
- getter += """\
- return %s;
- }
- """ % typ.to_obj('*ptr')
- setter = """
- local int %(setname)s(PyObject *obj, PyObject *newval, void *v)
- {
- int offset = (long)v;
- %(ctype)s *ptr = (%(ctype)s*)(((char*)obj)+offset);
- """ % vars()
- if isinstance(typ,type_void):
- setter = """
- local int %(setname)s(PyObject *obj, PyObject *newval, void *v)
- {
- int offset = (long)v;
- int *ptr = (int*)(((char*)obj)+offset);
- """ % vars()
- try:
- setter += """\
- return %s(newval, ptr) ? 0 : -1;
- }
- """ % typ.parse_converter()
- except:
- setter += """\
- *ptr = %s;
- return 0;
- }
- """ % typ.from_obj('newval')
- return [getter, setter]
- class struct_context:
- def __init__(me, ctype, name):
- me.ctype = ctype
- me.name = name
- me.fields = []
- def finish(me):
- del extra_patterns[:]
- typeobj = 'pytype_%s_typeobj' % me.name
- pytype_objects.append((me.name, typeobj))
- objtype = 'pytype_%s_struct' % me.name
- getsetters = 'pytype_%s_getset' % me.name
- code = []
- code.append("""
- typedef struct %(objtype)s
- {
- PyObject_HEAD
- %(ctype)s data;
- } %(objtype)s;
- """)
- for tp, vname in me.fields:
- code.extend(generate_getset_code(tp))
- code.append("""
- local PyGetSetDef %(getsetters)s[] =
- {
- """)
- for tp, vname in me.fields:
- code.append('\t{ "%s", %s, %s, NULL, (void*)offsetof(%s, data.%s) },\n' % (
- vname,
- getter_name(tp),
- setter_name(tp),
- objtype,
- vname))
- code.append("""
- {NULL}
- };
- #pragma GCC diagnostic push
- #pragma GCC diagnostic ignored "-Wmissing-field-initializers"
- local PyTypeObject %(typeobj)s =
- {
- PyObject_HEAD_INIT(NULL)
- 0, /* ob_size */
- "asss.%(name)s_wrapper", /* tp_name */
- sizeof(%(objtype)s), /* tp_basicsize */
- 0, /* tp_itemsize */
- 0, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- 0, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- 0, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT, /* tp_flags */
- "type object for %(name)s", /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- 0, /* tp_methods */
- 0, /* tp_members */
- %(getsetters)s, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- 0, /* tp_init */
- 0, /* tp_alloc */
- 0, /* tp_new */
- };
- #pragma GCC diagnostic push
- ATTR_UNUSED()
- local PyObject * cvt_c2p_%(name)s(void *p)
- {
- if (p == NULL)
- {
- Py_INCREF(Py_None);
- return Py_None;
- }
- else
- {
- struct %(objtype)s *o = PyObject_New(%(objtype)s, &%(typeobj)s);
- if (o)
- o->data = *(%(ctype)s*)p;
- return (PyObject*)o;
- }
- }
- ATTR_UNUSED()
- local int cvt_p2c_%(name)s(PyObject *o, void **pp)
- {
- if (o->ob_type == &%(typeobj)s)
- {
- *(%(ctype)s*)pp = ((%(objtype)s*)o)->data;
- return TRUE;
- }
- else
- {
- PyErr_Format(PyExc_TypeError, "arg isn't a '%%s'", "%(name)s");
- return FALSE;
- }
- }
- """)
- dict = vars()
- dict['name'] = me.name
- dict['ctype'] = me.ctype
- type_file.write(''.join(code) % dict)
- def handle_line(me, unsigned, tp, vs):
- if unsigned:
- tp = 'u' + tp
- tp = map_struct_type(tp)
- vs = [v.strip(' \t*') for v in vs.split(',')]
- for v in vs:
- me.fields.append((tp, v))
- def start_struct_type(ctype, name):
- ctx = struct_context(ctype, name)
- extra_patterns.append((re.compile(r'\s*(unsigned\s+)?([A-Za-z_0-9]+)\s+([^;]+);'),
- ctx.handle_line))
- extra_patterns.append((re.compile(r'.*}.*;.*'), ctx.finish))
- add_converted_type(ctype, name, 1)
- def handle_pytype(line):
- things = map(string.strip, line.split(','))
- if things[0] == 'opaque':
- make_opaque_type(things[1], things[2])
- elif things[0] == 'struct':
- start_struct_type(things[1], things[2])
- def finish_pytype():
- type_file.write("""
- local int ready_generated_types(void)
- {
- """)
- for n, t in pytype_objects:
- type_file.write("""\
- %(t)s.tp_dealloc = (destructor)PyObject_Del;
- %(t)s.tp_new = PyType_GenericNew;
- if (PyType_Ready(&%(t)s) < 0) return -1;
- """ % {'t': t})
- type_file.write("""
- return 0;
- }
- """)
- type_file.write("""
- local void add_type_objects_to_module(PyObject *m)
- {
- """)
- for n, t in pytype_objects:
- type_file.write('\tPy_INCREF(&%s);\n' % (t))
- type_file.write('\tPyModule_AddObject(m, "%s", (PyObject*)&%s);\n' % (n, t))
- type_file.write("""
- }
- """)
- # output files
- prefix = sys.argv[1]
- const_file = open(os.path.join(prefix, 'py_constants.inc'), 'w')
- callback_file = open(os.path.join(prefix, 'py_callbacks.inc'), 'w')
- int_file = open(os.path.join(prefix, 'py_interfaces.inc'), 'w')
- adv_file = open(os.path.join(prefix, 'py_advisers.inc'), 'w')
- type_file = open(os.path.join(prefix, 'py_types.inc'), 'w')
- include_file = open(os.path.join(prefix, 'py_include.inc'), 'w')
- warning = """
- /* THIS IS AN AUTOMATICALLY GENERATED FILE */
- """
- const_file.write(warning)
- callback_file.write(warning)
- int_file.write(warning)
- type_file.write(warning)
- include_file.write(warning)
- type_file.write("""
- typedef char charbuf[%d];
- """ % DEFBUFLEN)
- lines = []
- for pat in sys.argv[2:]:
- for f in glob.glob(pat):
- lines.extend(map(lambda l: l.rstrip("\r\n"), open(f).readlines()))
- # default constants
- const_string('ASSSVERSION')
- const_string('BUILDDATE')
- const_int('ASSSVERSION_NUM')
- const_int('TRUE')
- const_int('FALSE')
- init_pyint()
- init_pyadv()
- extra_patterns = []
- # now process file
- intdirs = []
- advdirs = []
- lastfunc = ''
- lastadvfunc = ''
- for l in lines:
- # includes
- m = re_pyinclude.match(l)
- if m:
- include_file.write('#include "%s"\n' % m.group(1).strip())
- # constants
- m = re_pyconst_dir.match(l)
- if m:
- handle_pyconst_directive(m.group(1), m.group(2))
- # callbacks
- m = re_pycb_cbdef.match(l)
- if m:
- lastcbdef = m.group(1)
- m = re_pycb_typedef.match(l)
- if m:
- lasttypedef = m.group(1)
- m = re_pycb_dir.match(l)
- if m:
- const_callback(lastcbdef)
- translate_pycb(lastcbdef, lasttypedef, m.group(1))
- # interfaces
- m = re_pyint_intdef.match(l)
- if m:
- lastintdef = m.group(1)
- intdirs = []
- m = re_pyint_typedef.match(l)
- if m:
- lasttypedef = m.group(1)
- m = re_pyint_func.match(l)
- if m:
- lastfunc = m.group(2)
- m = re_pyint_dir.match(l)
- if m:
- intdirs.append((lastfunc, m.group(1)))
- m = re_pyint_done.match(l)
- if m:
- if intdirs:
- const_interface(lastintdef)
- translate_pyint(lastintdef, lasttypedef, intdirs)
- intdirs = []
-
- # advisers
- m = re_pyadv_advdef.match(l)
- if m:
- lastadvdef = m.group(1)
- advdirs = []
- m = re_pyadv_typedef.match(l)
- if m:
- lastadvtypedef = m.group(1)
- m = re_pyadv_func.match(l)
- if m:
- lastadvfunc = m.group(2)
- m = re_pyadv_dir.match(l)
- if m:
- advdirs.append((lastadvfunc, m.group(1)))
- m = re_pyadv_done.match(l)
- if m:
- if advdirs:
- const_adviser(lastadvdef)
- translate_pyadv(lastadvdef, lastadvtypedef, advdirs)
- advdirs = []
-
- # types
- m = re_pytype.match(l)
- if m:
- handle_pytype(m.group(1))
- # generic stuff
- for myre, func in extra_patterns:
- m = myre.match(l)
- if m:
- apply(func, m.groups())
- finish_pycb()
- finish_pyint()
- finish_pyadv()
- finish_pytype()