update Linux i686

This commit is contained in:
j 2014-09-05 15:43:43 +00:00
commit 89ee84c73e
1390 changed files with 4932 additions and 433509 deletions

View file

@ -4,5 +4,5 @@ __all__ = ['FFI', 'VerificationError', 'VerificationMissing', 'CDefError',
from .api import FFI, CDefError, FFIError
from .ffiplatform import VerificationError, VerificationMissing
__version__ = "0.8.2"
__version_info__ = (0, 8, 2)
__version__ = "0.8.6"
__version_info__ = (0, 8, 6)

View file

@ -55,8 +55,7 @@ class FFI(object):
# _cffi_backend.so compiled.
import _cffi_backend as backend
from . import __version__
assert (backend.__version__ == __version__ or
backend.__version__ == __version__[:3])
assert backend.__version__ == __version__
# (If you insist you can also try to pass the option
# 'backend=backend_ctypes.CTypesBackend()', but don't
# rely on it! It's probably not going to work well.)
@ -443,6 +442,10 @@ def _make_ffi_library(ffi, libname, flags):
for enumname, enumval in zip(tp.enumerators, tp.enumvalues):
if enumname not in library.__dict__:
library.__dict__[enumname] = enumval
for key, val in ffi._parser._int_constants.items():
if key not in library.__dict__:
library.__dict__[key] = val
copied_enums.append(True)
if name in library.__dict__:
return

View file

@ -24,6 +24,7 @@ _r_enum_dotdotdot = re.compile(r"__dotdotdot\d+__$")
_r_partial_array = re.compile(r"\[\s*\.\.\.\s*\]")
_r_words = re.compile(r"\w+|\S")
_parser_cache = None
_r_int_literal = re.compile(r"^0?x?[0-9a-f]+u?l?$", re.IGNORECASE)
def _get_parser():
global _parser_cache
@ -99,6 +100,7 @@ class Parser(object):
self._structnode2type = weakref.WeakKeyDictionary()
self._override = False
self._packed = False
self._int_constants = {}
def _parse(self, csource):
csource, macros = _preprocess(csource)
@ -128,9 +130,10 @@ class Parser(object):
finally:
if lock is not None:
lock.release()
return ast, macros
# csource will be used to find buggy source text
return ast, macros, csource
def convert_pycparser_error(self, e, csource):
def _convert_pycparser_error(self, e, csource):
# xxx look for ":NUM:" at the start of str(e) and try to interpret
# it as a line number
line = None
@ -142,6 +145,12 @@ class Parser(object):
csourcelines = csource.splitlines()
if 1 <= linenum <= len(csourcelines):
line = csourcelines[linenum-1]
return line
def convert_pycparser_error(self, e, csource):
line = self._convert_pycparser_error(e, csource)
msg = str(e)
if line:
msg = 'cannot parse "%s"\n%s' % (line.strip(), msg)
else:
@ -160,14 +169,9 @@ class Parser(object):
self._packed = prev_packed
def _internal_parse(self, csource):
ast, macros = self._parse(csource)
ast, macros, csource = self._parse(csource)
# add the macros
for key, value in macros.items():
value = value.strip()
if value != '...':
raise api.CDefError('only supports the syntax "#define '
'%s ..." for now (literally)' % key)
self._declare('macro ' + key, value)
self._process_macros(macros)
# find the first "__dotdotdot__" and use that as a separator
# between the repeated typedefs and the real csource
iterator = iter(ast.ext)
@ -175,27 +179,61 @@ class Parser(object):
if decl.name == '__dotdotdot__':
break
#
for decl in iterator:
if isinstance(decl, pycparser.c_ast.Decl):
self._parse_decl(decl)
elif isinstance(decl, pycparser.c_ast.Typedef):
if not decl.name:
raise api.CDefError("typedef does not declare any name",
decl)
if (isinstance(decl.type.type, pycparser.c_ast.IdentifierType)
and decl.type.type.names == ['__dotdotdot__']):
realtype = model.unknown_type(decl.name)
elif (isinstance(decl.type, pycparser.c_ast.PtrDecl) and
isinstance(decl.type.type, pycparser.c_ast.TypeDecl) and
isinstance(decl.type.type.type,
pycparser.c_ast.IdentifierType) and
decl.type.type.type.names == ['__dotdotdot__']):
realtype = model.unknown_ptr_type(decl.name)
try:
for decl in iterator:
if isinstance(decl, pycparser.c_ast.Decl):
self._parse_decl(decl)
elif isinstance(decl, pycparser.c_ast.Typedef):
if not decl.name:
raise api.CDefError("typedef does not declare any name",
decl)
if (isinstance(decl.type.type, pycparser.c_ast.IdentifierType)
and decl.type.type.names == ['__dotdotdot__']):
realtype = model.unknown_type(decl.name)
elif (isinstance(decl.type, pycparser.c_ast.PtrDecl) and
isinstance(decl.type.type, pycparser.c_ast.TypeDecl) and
isinstance(decl.type.type.type,
pycparser.c_ast.IdentifierType) and
decl.type.type.type.names == ['__dotdotdot__']):
realtype = model.unknown_ptr_type(decl.name)
else:
realtype = self._get_type(decl.type, name=decl.name)
self._declare('typedef ' + decl.name, realtype)
else:
realtype = self._get_type(decl.type, name=decl.name)
self._declare('typedef ' + decl.name, realtype)
raise api.CDefError("unrecognized construct", decl)
except api.FFIError as e:
msg = self._convert_pycparser_error(e, csource)
if msg:
e.args = (e.args[0] + "\n *** Err: %s" % msg,)
raise
def _add_constants(self, key, val):
if key in self._int_constants:
raise api.FFIError(
"multiple declarations of constant: %s" % (key,))
self._int_constants[key] = val
def _process_macros(self, macros):
for key, value in macros.items():
value = value.strip()
match = _r_int_literal.search(value)
if match is not None:
int_str = match.group(0).lower().rstrip("ul")
# "010" is not valid oct in py3
if (int_str.startswith("0") and
int_str != "0" and
not int_str.startswith("0x")):
int_str = "0o" + int_str[1:]
pyvalue = int(int_str, 0)
self._add_constants(key, pyvalue)
elif value == '...':
self._declare('macro ' + key, value)
else:
raise api.CDefError("unrecognized construct", decl)
raise api.CDefError('only supports the syntax "#define '
'%s ..." (literally) or "#define '
'%s 0x1FF" for now' % (key, key))
def _parse_decl(self, decl):
node = decl.type
@ -227,7 +265,7 @@ class Parser(object):
self._declare('variable ' + decl.name, tp)
def parse_type(self, cdecl):
ast, macros = self._parse('void __dummy(\n%s\n);' % cdecl)
ast, macros = self._parse('void __dummy(\n%s\n);' % cdecl)[:2]
assert not macros
exprnode = ast.ext[-1].type.args.params[0]
if isinstance(exprnode, pycparser.c_ast.ID):
@ -306,7 +344,8 @@ class Parser(object):
if ident == 'void':
return model.void_type
if ident == '__dotdotdot__':
raise api.FFIError('bad usage of "..."')
raise api.FFIError(':%d: bad usage of "..."' %
typenode.coord.line)
return resolve_common_type(ident)
#
if isinstance(type, pycparser.c_ast.Struct):
@ -333,7 +372,8 @@ class Parser(object):
return self._get_struct_union_enum_type('union', typenode, name,
nested=True)
#
raise api.FFIError("bad or unsupported type declaration")
raise api.FFIError(":%d: bad or unsupported type declaration" %
typenode.coord.line)
def _parse_function_type(self, typenode, funcname=None):
params = list(getattr(typenode.args, 'params', []))
@ -499,6 +539,10 @@ class Parser(object):
if (isinstance(exprnode, pycparser.c_ast.UnaryOp) and
exprnode.op == '-'):
return -self._parse_constant(exprnode.expr)
# load previously defined int constant
if (isinstance(exprnode, pycparser.c_ast.ID) and
exprnode.name in self._int_constants):
return self._int_constants[exprnode.name]
#
if partial_length_ok:
if (isinstance(exprnode, pycparser.c_ast.ID) and
@ -506,8 +550,8 @@ class Parser(object):
self._partial_length = True
return '...'
#
raise api.FFIError("unsupported expression: expected a "
"simple numeric constant")
raise api.FFIError(":%d: unsupported expression: expected a "
"simple numeric constant" % exprnode.coord.line)
def _build_enum_type(self, explicit_name, decls):
if decls is not None:
@ -522,6 +566,7 @@ class Parser(object):
if enum.value is not None:
nextenumvalue = self._parse_constant(enum.value)
enumvalues.append(nextenumvalue)
self._add_constants(enum.name, nextenumvalue)
nextenumvalue += 1
enumvalues = tuple(enumvalues)
tp = model.EnumType(explicit_name, enumerators, enumvalues)
@ -535,3 +580,5 @@ class Parser(object):
kind = name.split(' ', 1)[0]
if kind in ('typedef', 'struct', 'union', 'enum'):
self._declare(name, tp)
for k, v in other._int_constants.items():
self._add_constants(k, v)

View file

@ -38,6 +38,7 @@ def _build(tmpdir, ext):
import distutils.errors
#
dist = Distribution({'ext_modules': [ext]})
dist.parse_config_files()
options = dist.get_option_dict('build_ext')
options['force'] = ('ffiplatform', True)
options['build_lib'] = ('ffiplatform', tmpdir)

View file

@ -89,43 +89,54 @@ class VCPythonEngine(object):
# by generate_cpy_function_method().
prnt('static PyMethodDef _cffi_methods[] = {')
self._generate("method")
prnt(' {"_cffi_setup", _cffi_setup, METH_VARARGS},')
prnt(' {NULL, NULL} /* Sentinel */')
prnt(' {"_cffi_setup", _cffi_setup, METH_VARARGS, NULL},')
prnt(' {NULL, NULL, 0, NULL} /* Sentinel */')
prnt('};')
prnt()
#
# standard init.
modname = self.verifier.get_module_name()
if sys.version_info >= (3,):
prnt('static struct PyModuleDef _cffi_module_def = {')
prnt(' PyModuleDef_HEAD_INIT,')
prnt(' "%s",' % modname)
prnt(' NULL,')
prnt(' -1,')
prnt(' _cffi_methods,')
prnt(' NULL, NULL, NULL, NULL')
prnt('};')
prnt()
initname = 'PyInit_%s' % modname
createmod = 'PyModule_Create(&_cffi_module_def)'
errorcase = 'return NULL'
finalreturn = 'return lib'
else:
initname = 'init%s' % modname
createmod = 'Py_InitModule("%s", _cffi_methods)' % modname
errorcase = 'return'
finalreturn = 'return'
constants = self._chained_list_constants[False]
prnt('#if PY_MAJOR_VERSION >= 3')
prnt()
prnt('static struct PyModuleDef _cffi_module_def = {')
prnt(' PyModuleDef_HEAD_INIT,')
prnt(' "%s",' % modname)
prnt(' NULL,')
prnt(' -1,')
prnt(' _cffi_methods,')
prnt(' NULL, NULL, NULL, NULL')
prnt('};')
prnt()
prnt('PyMODINIT_FUNC')
prnt('%s(void)' % initname)
prnt('PyInit_%s(void)' % modname)
prnt('{')
prnt(' PyObject *lib;')
prnt(' lib = %s;' % createmod)
prnt(' if (lib == NULL || %s < 0)' % (
self._chained_list_constants[False],))
prnt(' %s;' % errorcase)
prnt(' _cffi_init();')
prnt(' %s;' % finalreturn)
prnt(' lib = PyModule_Create(&_cffi_module_def);')
prnt(' if (lib == NULL)')
prnt(' return NULL;')
prnt(' if (%s < 0 || _cffi_init() < 0) {' % (constants,))
prnt(' Py_DECREF(lib);')
prnt(' return NULL;')
prnt(' }')
prnt(' return lib;')
prnt('}')
prnt()
prnt('#else')
prnt()
prnt('PyMODINIT_FUNC')
prnt('init%s(void)' % modname)
prnt('{')
prnt(' PyObject *lib;')
prnt(' lib = Py_InitModule("%s", _cffi_methods);' % modname)
prnt(' if (lib == NULL)')
prnt(' return;')
prnt(' if (%s < 0 || _cffi_init() < 0)' % (constants,))
prnt(' return;')
prnt(' return;')
prnt('}')
prnt()
prnt('#endif')
def load_library(self):
# XXX review all usages of 'self' here!
@ -394,7 +405,7 @@ class VCPythonEngine(object):
meth = 'METH_O'
else:
meth = 'METH_VARARGS'
self._prnt(' {"%s", _cffi_f_%s, %s},' % (name, name, meth))
self._prnt(' {"%s", _cffi_f_%s, %s, NULL},' % (name, name, meth))
_loading_cpy_function = _loaded_noop
@ -481,8 +492,8 @@ class VCPythonEngine(object):
if tp.fldnames is None:
return # nothing to do with opaque structs
layoutfuncname = '_cffi_layout_%s_%s' % (prefix, name)
self._prnt(' {"%s", %s, METH_NOARGS},' % (layoutfuncname,
layoutfuncname))
self._prnt(' {"%s", %s, METH_NOARGS, NULL},' % (layoutfuncname,
layoutfuncname))
def _loading_struct_or_union(self, tp, prefix, name, module):
if tp.fldnames is None:
@ -589,13 +600,7 @@ class VCPythonEngine(object):
'variable type'),))
assert delayed
else:
prnt(' if (LONG_MIN <= (%s) && (%s) <= LONG_MAX)' % (name, name))
prnt(' o = PyInt_FromLong((long)(%s));' % (name,))
prnt(' else if ((%s) <= 0)' % (name,))
prnt(' o = PyLong_FromLongLong((long long)(%s));' % (name,))
prnt(' else')
prnt(' o = PyLong_FromUnsignedLongLong('
'(unsigned long long)(%s));' % (name,))
prnt(' o = _cffi_from_c_int_const(%s);' % name)
prnt(' if (o == NULL)')
prnt(' return -1;')
if size_too:
@ -632,13 +637,18 @@ class VCPythonEngine(object):
# ----------
# enums
def _enum_funcname(self, prefix, name):
# "$enum_$1" => "___D_enum____D_1"
name = name.replace('$', '___D_')
return '_cffi_e_%s_%s' % (prefix, name)
def _generate_cpy_enum_decl(self, tp, name, prefix='enum'):
if tp.partial:
for enumerator in tp.enumerators:
self._generate_cpy_const(True, enumerator, delayed=False)
return
#
funcname = '_cffi_e_%s_%s' % (prefix, name)
funcname = self._enum_funcname(prefix, name)
prnt = self._prnt
prnt('static int %s(PyObject *lib)' % funcname)
prnt('{')
@ -760,17 +770,30 @@ cffimod_header = r'''
#include <Python.h>
#include <stddef.h>
#ifdef MS_WIN32
#include <malloc.h> /* for alloca() */
typedef __int8 int8_t;
typedef __int16 int16_t;
typedef __int32 int32_t;
typedef __int64 int64_t;
typedef unsigned __int8 uint8_t;
typedef unsigned __int16 uint16_t;
typedef unsigned __int32 uint32_t;
typedef unsigned __int64 uint64_t;
typedef unsigned char _Bool;
/* this block of #ifs should be kept exactly identical between
c/_cffi_backend.c, cffi/vengine_cpy.py, cffi/vengine_gen.py */
#if defined(_MSC_VER)
# include <malloc.h> /* for alloca() */
# if _MSC_VER < 1600 /* MSVC < 2010 */
typedef __int8 int8_t;
typedef __int16 int16_t;
typedef __int32 int32_t;
typedef __int64 int64_t;
typedef unsigned __int8 uint8_t;
typedef unsigned __int16 uint16_t;
typedef unsigned __int32 uint32_t;
typedef unsigned __int64 uint64_t;
# else
# include <stdint.h>
# endif
# if _MSC_VER < 1800 /* MSVC < 2013 */
typedef unsigned char _Bool;
# endif
#else
# include <stdint.h>
# if (defined (__SVR4) && defined (__sun)) || defined(_AIX)
# include <alloca.h>
# endif
#endif
#if PY_MAJOR_VERSION < 3
@ -795,6 +818,15 @@ typedef unsigned char _Bool;
#define _cffi_to_c_double PyFloat_AsDouble
#define _cffi_to_c_float PyFloat_AsDouble
#define _cffi_from_c_int_const(x) \
(((x) > 0) ? \
((unsigned long long)(x) <= (unsigned long long)LONG_MAX) ? \
PyInt_FromLong((long)(x)) : \
PyLong_FromUnsignedLongLong((unsigned long long)(x)) : \
((long long)(x) >= (long long)LONG_MIN) ? \
PyInt_FromLong((long)(x)) : \
PyLong_FromLongLong((long long)(x)))
#define _cffi_from_c_int(x, type) \
(((type)-1) > 0 ? /* unsigned */ \
(sizeof(type) < sizeof(long) ? PyInt_FromLong(x) : \
@ -804,14 +836,14 @@ typedef unsigned char _Bool;
PyLong_FromLongLong(x)))
#define _cffi_to_c_int(o, type) \
(sizeof(type) == 1 ? (((type)-1) > 0 ? _cffi_to_c_u8(o) \
: _cffi_to_c_i8(o)) : \
sizeof(type) == 2 ? (((type)-1) > 0 ? _cffi_to_c_u16(o) \
: _cffi_to_c_i16(o)) : \
sizeof(type) == 4 ? (((type)-1) > 0 ? _cffi_to_c_u32(o) \
: _cffi_to_c_i32(o)) : \
sizeof(type) == 8 ? (((type)-1) > 0 ? _cffi_to_c_u64(o) \
: _cffi_to_c_i64(o)) : \
(sizeof(type) == 1 ? (((type)-1) > 0 ? (type)_cffi_to_c_u8(o) \
: (type)_cffi_to_c_i8(o)) : \
sizeof(type) == 2 ? (((type)-1) > 0 ? (type)_cffi_to_c_u16(o) \
: (type)_cffi_to_c_i16(o)) : \
sizeof(type) == 4 ? (((type)-1) > 0 ? (type)_cffi_to_c_u32(o) \
: (type)_cffi_to_c_i32(o)) : \
sizeof(type) == 8 ? (((type)-1) > 0 ? (type)_cffi_to_c_u64(o) \
: (type)_cffi_to_c_i64(o)) : \
(Py_FatalError("unsupported size for type " #type), 0))
#define _cffi_to_c_i8 \
@ -885,25 +917,32 @@ static PyObject *_cffi_setup(PyObject *self, PyObject *args)
return PyBool_FromLong(was_alive);
}
static void _cffi_init(void)
static int _cffi_init(void)
{
PyObject *module = PyImport_ImportModule("_cffi_backend");
PyObject *c_api_object;
PyObject *module, *c_api_object = NULL;
module = PyImport_ImportModule("_cffi_backend");
if (module == NULL)
return;
goto failure;
c_api_object = PyObject_GetAttrString(module, "_C_API");
if (c_api_object == NULL)
return;
goto failure;
if (!PyCapsule_CheckExact(c_api_object)) {
Py_DECREF(c_api_object);
PyErr_SetNone(PyExc_ImportError);
return;
goto failure;
}
memcpy(_cffi_exports, PyCapsule_GetPointer(c_api_object, "cffi"),
_CFFI_NUM_EXPORTS * sizeof(void *));
Py_DECREF(module);
Py_DECREF(c_api_object);
return 0;
failure:
Py_XDECREF(module);
Py_XDECREF(c_api_object);
return -1;
}
#define _cffi_type(num) ((CTypeDescrObject *)PyList_GET_ITEM(_cffi_types, num))

View file

@ -249,10 +249,10 @@ class VGenericEngine(object):
prnt(' /* %s */' % str(e)) # cannot verify it, ignore
prnt('}')
self.export_symbols.append(layoutfuncname)
prnt('ssize_t %s(ssize_t i)' % (layoutfuncname,))
prnt('intptr_t %s(intptr_t i)' % (layoutfuncname,))
prnt('{')
prnt(' struct _cffi_aligncheck { char x; %s y; };' % cname)
prnt(' static ssize_t nums[] = {')
prnt(' static intptr_t nums[] = {')
prnt(' sizeof(%s),' % cname)
prnt(' offsetof(struct _cffi_aligncheck, y),')
for fname, ftype, fbitsize in tp.enumfields():
@ -276,7 +276,7 @@ class VGenericEngine(object):
return # nothing to do with opaque structs
layoutfuncname = '_cffi_layout_%s_%s' % (prefix, name)
#
BFunc = self.ffi._typeof_locked("ssize_t(*)(ssize_t)")[0]
BFunc = self.ffi._typeof_locked("intptr_t(*)(intptr_t)")[0]
function = module.load_function(BFunc, layoutfuncname)
layout = []
num = 0
@ -410,13 +410,18 @@ class VGenericEngine(object):
# ----------
# enums
def _enum_funcname(self, prefix, name):
# "$enum_$1" => "___D_enum____D_1"
name = name.replace('$', '___D_')
return '_cffi_e_%s_%s' % (prefix, name)
def _generate_gen_enum_decl(self, tp, name, prefix='enum'):
if tp.partial:
for enumerator in tp.enumerators:
self._generate_gen_const(True, enumerator)
return
#
funcname = '_cffi_e_%s_%s' % (prefix, name)
funcname = self._enum_funcname(prefix, name)
self.export_symbols.append(funcname)
prnt = self._prnt
prnt('int %s(char *out_error)' % funcname)
@ -430,14 +435,14 @@ class VGenericEngine(object):
enumerator, enumerator, enumvalue))
prnt(' char buf[64];')
prnt(' if ((%s) < 0)' % enumerator)
prnt(' snprintf(buf, 63, "%%ld", (long)(%s));' % enumerator)
prnt(' sprintf(buf, "%%ld", (long)(%s));' % enumerator)
prnt(' else')
prnt(' snprintf(buf, 63, "%%lu", (unsigned long)(%s));' %
prnt(' sprintf(buf, "%%lu", (unsigned long)(%s));' %
enumerator)
prnt(' snprintf(out_error, 255,'
prnt(' sprintf(out_error,'
' "%s has the real value %s, not %s",')
prnt(' "%s", buf, "%d");' % (
enumerator, enumvalue))
enumerator[:100], enumvalue))
prnt(' return -1;')
prnt(' }')
prnt(' return 0;')
@ -453,7 +458,7 @@ class VGenericEngine(object):
else:
BType = self.ffi._typeof_locked("char[]")[0]
BFunc = self.ffi._typeof_locked("int(*)(char*)")[0]
funcname = '_cffi_e_%s_%s' % (prefix, name)
funcname = self._enum_funcname(prefix, name)
function = module.load_function(BFunc, funcname)
p = self.ffi.new(BType, 256)
if function(p) < 0:
@ -547,20 +552,29 @@ cffimod_header = r'''
#include <errno.h>
#include <sys/types.h> /* XXX for ssize_t on some platforms */
#ifdef _WIN32
# include <Windows.h>
# define snprintf _snprintf
typedef __int8 int8_t;
typedef __int16 int16_t;
typedef __int32 int32_t;
typedef __int64 int64_t;
typedef unsigned __int8 uint8_t;
typedef unsigned __int16 uint16_t;
typedef unsigned __int32 uint32_t;
typedef unsigned __int64 uint64_t;
typedef SSIZE_T ssize_t;
typedef unsigned char _Bool;
#else
/* this block of #ifs should be kept exactly identical between
c/_cffi_backend.c, cffi/vengine_cpy.py, cffi/vengine_gen.py */
#if defined(_MSC_VER)
# include <malloc.h> /* for alloca() */
# if _MSC_VER < 1600 /* MSVC < 2010 */
typedef __int8 int8_t;
typedef __int16 int16_t;
typedef __int32 int32_t;
typedef __int64 int64_t;
typedef unsigned __int8 uint8_t;
typedef unsigned __int16 uint16_t;
typedef unsigned __int32 uint32_t;
typedef unsigned __int64 uint64_t;
# else
# include <stdint.h>
# endif
# if _MSC_VER < 1800 /* MSVC < 2013 */
typedef unsigned char _Bool;
# endif
#else
# include <stdint.h>
# if (defined (__SVR4) && defined (__sun)) || defined(_AIX)
# include <alloca.h>
# endif
#endif
'''