diff options
-rw-r--r-- | c/_cffi_backend.c | 4 | ||||
-rw-r--r-- | c/cffi1_module.c | 1 | ||||
-rw-r--r-- | c/commontypes.c | 209 | ||||
-rw-r--r-- | c/parse_c_type.c | 76 | ||||
-rw-r--r-- | cffi/commontypes.py | 224 | ||||
-rw-r--r-- | cffi/cparser.py | 3 | ||||
-rw-r--r-- | testing/cffi0/test_parsing.py | 32 | ||||
-rw-r--r-- | testing/cffi1/test_commontypes.py | 15 | ||||
-rw-r--r-- | testing/cffi1/test_ffi_obj.py | 14 | ||||
-rw-r--r-- | testing/cffi1/test_parse_c_type.py | 7 | ||||
-rw-r--r-- | testing/cffi1/test_verify1.py | 9 |
11 files changed, 334 insertions, 260 deletions
diff --git a/c/_cffi_backend.c b/c/_cffi_backend.c index 1a2e2b8..0a374b1 100644 --- a/c/_cffi_backend.c +++ b/c/_cffi_backend.c @@ -5861,6 +5861,9 @@ static PyObject *b__get_types(PyObject *self, PyObject *noarg) (PyObject *)&CTypeDescr_Type); } +/* forward, in commontypes.c */ +static PyObject *b__get_common_types(PyObject *self, PyObject *arg); + static PyObject *b_gcp(PyObject *self, PyObject *args, PyObject *kwds) { CDataObject *cd; @@ -6187,6 +6190,7 @@ static PyMethodDef FFIBackendMethods[] = { {"getwinerror", (PyCFunction)b_getwinerror, METH_VARARGS | METH_KEYWORDS}, #endif {"_get_types", b__get_types, METH_NOARGS}, + {"_get_common_types", b__get_common_types, METH_O}, {"_testfunc", b__testfunc, METH_VARARGS}, {"_testbuff", b__testbuff, METH_VARARGS}, {"_init_cffi_1_0_external_module", b_init_cffi_1_0_external_module, METH_O}, diff --git a/c/cffi1_module.c b/c/cffi1_module.c index 6cdc2ff..b8668b7 100644 --- a/c/cffi1_module.c +++ b/c/cffi1_module.c @@ -15,6 +15,7 @@ static PyTypeObject Lib_Type; /* forward */ #include "cglob.c" #include "lib_obj.c" #include "cdlopen.c" +#include "commontypes.c" static int init_ffi_lib(PyObject *m) diff --git a/c/commontypes.c b/c/commontypes.c new file mode 100644 index 0000000..86a3e08 --- /dev/null +++ b/c/commontypes.c @@ -0,0 +1,209 @@ +/* This file must be kept in alphabetical order. See test_commontypes.py */ + +#define EQ(key, value) key "\0" value /* string concatenation */ +#ifdef _WIN64 +# define W32_64(X,Y) Y +# else +# define W32_64(X,Y) X +# endif + + +static const char *common_simple_types[] = { + +#ifdef MS_WIN32 /* Windows types */ + EQ("ATOM", "WORD"), + EQ("BOOL", "int"), + EQ("BOOLEAN", "BYTE"), + EQ("BYTE", "unsigned char"), + EQ("CCHAR", "char"), + EQ("CHAR", "char"), + EQ("COLORREF", "DWORD"), + EQ("DWORD", "unsigned long"), + EQ("DWORD32", "unsigned int"), + EQ("DWORD64", "unsigned long long"), + EQ("DWORDLONG", "ULONGLONG"), + EQ("DWORD_PTR", "ULONG_PTR"), + EQ("FLOAT", "float"), + EQ("HACCEL", "HANDLE"), + EQ("HALF_PTR", W32_64("short","int")), + EQ("HBITMAP", "HANDLE"), + EQ("HBRUSH", "HANDLE"), + EQ("HCOLORSPACE", "HANDLE"), + EQ("HCONV", "HANDLE"), + EQ("HCONVLIST", "HANDLE"), + EQ("HCURSOR", "HICON"), + EQ("HDC", "HANDLE"), + EQ("HDDEDATA", "HANDLE"), + EQ("HDESK", "HANDLE"), + EQ("HDROP", "HANDLE"), + EQ("HDWP", "HANDLE"), + EQ("HENHMETAFILE", "HANDLE"), + EQ("HFILE", "int"), + EQ("HFONT", "HANDLE"), + EQ("HGDIOBJ", "HANDLE"), + EQ("HGLOBAL", "HANDLE"), + EQ("HHOOK", "HANDLE"), + EQ("HICON", "HANDLE"), + EQ("HINSTANCE", "HANDLE"), + EQ("HKEY", "HANDLE"), + EQ("HKL", "HANDLE"), + EQ("HLOCAL", "HANDLE"), + EQ("HMENU", "HANDLE"), + EQ("HMETAFILE", "HANDLE"), + EQ("HMODULE", "HINSTANCE"), + EQ("HMONITOR", "HANDLE"), + EQ("HPALETTE", "HANDLE"), + EQ("HPEN", "HANDLE"), + EQ("HRESULT", "LONG"), + EQ("HRGN", "HANDLE"), + EQ("HRSRC", "HANDLE"), + EQ("HSZ", "HANDLE"), + EQ("HWND", "HANDLE"), + EQ("INT", "int"), + EQ("INT16", "short"), + EQ("INT32", "int"), + EQ("INT64", "long long"), + EQ("INT8", "signed char"), + EQ("INT_PTR", W32_64("int","long long")), + EQ("LANGID", "WORD"), + EQ("LCID", "DWORD"), + EQ("LCTYPE", "DWORD"), + EQ("LGRPID", "DWORD"), + EQ("LONG", "long"), + EQ("LONG32", "int"), + EQ("LONG64", "long long"), + EQ("LONGLONG", "long long"), + EQ("LONG_PTR", W32_64("long","long long")), + EQ("LPARAM", "LONG_PTR"), + EQ("LPBOOL", "BOOL *"), + EQ("LPBYTE", "BYTE *"), + EQ("LPCOLORREF", "DWORD *"), + EQ("LPCSTR", "const char *"), + EQ("LPCVOID", "const void *"), + EQ("LPCWSTR", "const WCHAR *"), + EQ("LPDWORD", "DWORD *"), + EQ("LPHANDLE", "HANDLE *"), + EQ("LPINT", "int *"), + EQ("LPLONG", "long *"), + EQ("LPSTR", "CHAR *"), + EQ("LPVOID", "void *"), + EQ("LPWORD", "WORD *"), + EQ("LPWSTR", "WCHAR *"), + EQ("LRESULT", "LONG_PTR"), + EQ("PBOOL", "BOOL *"), + EQ("PBOOLEAN", "BOOLEAN *"), + EQ("PBYTE", "BYTE *"), + EQ("PCHAR", "CHAR *"), + EQ("PCSTR", "const CHAR *"), + EQ("PCWSTR", "const WCHAR *"), + EQ("PDWORD", "DWORD *"), + EQ("PDWORD32", "DWORD32 *"), + EQ("PDWORD64", "DWORD64 *"), + EQ("PDWORDLONG", "DWORDLONG *"), + EQ("PDWORD_PTR", "DWORD_PTR *"), + EQ("PFLOAT", "FLOAT *"), + EQ("PHALF_PTR", "HALF_PTR *"), + EQ("PHANDLE", "HANDLE *"), + EQ("PHKEY", "HKEY *"), + EQ("PINT", "int *"), + EQ("PINT16", "INT16 *"), + EQ("PINT32", "INT32 *"), + EQ("PINT64", "INT64 *"), + EQ("PINT8", "INT8 *"), + EQ("PINT_PTR", "INT_PTR *"), + EQ("PLCID", "PDWORD"), + EQ("PLONG", "LONG *"), + EQ("PLONG32", "LONG32 *"), + EQ("PLONG64", "LONG64 *"), + EQ("PLONGLONG", "LONGLONG *"), + EQ("PLONG_PTR", "LONG_PTR *"), + EQ("PSHORT", "SHORT *"), + EQ("PSIZE_T", "SIZE_T *"), + EQ("PSSIZE_T", "SSIZE_T *"), + EQ("PSTR", "CHAR *"), + EQ("PUCHAR", "UCHAR *"), + EQ("PUHALF_PTR", "UHALF_PTR *"), + EQ("PUINT", "UINT *"), + EQ("PUINT16", "UINT16 *"), + EQ("PUINT32", "UINT32 *"), + EQ("PUINT64", "UINT64 *"), + EQ("PUINT8", "UINT8 *"), + EQ("PUINT_PTR", "UINT_PTR *"), + EQ("PULONG", "ULONG *"), + EQ("PULONG32", "ULONG32 *"), + EQ("PULONG64", "ULONG64 *"), + EQ("PULONGLONG", "ULONGLONG *"), + EQ("PULONG_PTR", "ULONG_PTR *"), + EQ("PUSHORT", "USHORT *"), + EQ("PVOID", "void *"), + EQ("PWCHAR", "WCHAR *"), + EQ("PWORD", "WORD *"), + EQ("PWSTR", "WCHAR *"), + EQ("QWORD", "unsigned long long"), + EQ("SC_HANDLE", "HANDLE"), + EQ("SC_LOCK", "LPVOID"), + EQ("SERVICE_STATUS_HANDLE", "HANDLE"), + EQ("SHORT", "short"), + EQ("SIZE_T", "ULONG_PTR"), + EQ("SSIZE_T", "LONG_PTR"), + EQ("UCHAR", "unsigned char"), + EQ("UHALF_PTR", W32_64("unsigned short","unsigned int")), + EQ("UINT", "unsigned int"), + EQ("UINT16", "unsigned short"), + EQ("UINT32", "unsigned int"), + EQ("UINT64", "unsigned long long"), + EQ("UINT8", "unsigned char"), + EQ("UINT_PTR", W32_64("unsigned int","unsigned long long")), + EQ("ULONG", "unsigned long"), + EQ("ULONG32", "unsigned int"), + EQ("ULONG64", "unsigned long long"), + EQ("ULONGLONG", "unsigned long long"), + EQ("ULONG_PTR", W32_64("unsigned long","unsigned long long")), + EQ("USHORT", "unsigned short"), + EQ("USN", "LONGLONG"), + EQ("VOID", "void"), + EQ("WCHAR", "wchar_t"), + EQ("WINSTA", "HANDLE"), + EQ("WORD", "unsigned short"), + EQ("WPARAM", "UINT_PTR"), +#endif + + EQ("bool", "_Bool"), +}; + + +#undef EQ +#undef W32_64 + +#define num_common_simple_types \ + (sizeof(common_simple_types) / sizeof(common_simple_types[0])) + + +static const char *get_common_type(const char *search, size_t search_len) +{ + const char *entry; + int index = search_sorted(common_simple_types, sizeof(const char *), + num_common_simple_types, search, search_len); + if (index < 0) + return NULL; + + entry = common_simple_types[index]; + return entry + strlen(entry) + 1; +} + +static PyObject *b__get_common_types(PyObject *self, PyObject *arg) +{ + int i, err; + for (i = 0; i < num_common_simple_types; i++) { + const char *s = common_simple_types[i]; + PyObject *o = PyString_FromString(s + strlen(s) + 1); + if (o == NULL) + return NULL; + err = PyDict_SetItemString(arg, s, o); + Py_DECREF(o); + if (err < 0) + return NULL; + } + Py_INCREF(Py_None); + return Py_None; +} diff --git a/c/parse_c_type.c b/c/parse_c_type.c index 80cd3ff..58c85a8 100644 --- a/c/parse_c_type.c +++ b/c/parse_c_type.c @@ -220,6 +220,8 @@ static int write_ds(token_t *tok, _cffi_opcode_t ds) #define MAX_SSIZE_T (((size_t)-1) >> 1) static int parse_complete(token_t *tok); +static const char *get_common_type(const char *search, size_t search_len); +static int parse_common_type_replacement(token_t *tok, const char *replacement); static int parse_sequel(token_t *tok, int outer) { @@ -442,26 +444,34 @@ static int parse_sequel(token_t *tok, int outer) return _CFFI_GETARG(result); } +static int search_sorted(const char *const *base, + size_t item_size, int array_len, + const char *search, size_t search_len) +{ + int left = 0, right = array_len; + const char *baseptr = (const char *)base; + + while (left < right) { + int middle = (left + right) / 2; + const char *src = *(const char *const *)(baseptr + middle * item_size); + int diff = strncmp(src, search, search_len); + if (diff == 0 && src[search_len] == '\0') + return middle; + else if (diff >= 0) + right = middle; + else + left = middle + 1; + } + return -1; +} -#define MAKE_SEARCH_FUNC(FIELD) \ - static \ - int search_in_##FIELD(const struct _cffi_type_context_s *ctx, \ - const char *search, size_t search_len) \ - { \ - int left = 0, right = ctx->num_##FIELD; \ - \ - while (left < right) { \ - int middle = (left + right) / 2; \ - const char *src = ctx->FIELD[middle].name; \ - int diff = strncmp(src, search, search_len); \ - if (diff == 0 && src[search_len] == '\0') \ - return middle; \ - else if (diff >= 0) \ - right = middle; \ - else \ - left = middle + 1; \ - } \ - return -1; \ +#define MAKE_SEARCH_FUNC(FIELD) \ + static \ + int search_in_##FIELD(const struct _cffi_type_context_s *ctx, \ + const char *search, size_t search_len) \ + { \ + return search_sorted(&ctx->FIELD->name, sizeof(*ctx->FIELD), \ + ctx->num_##FIELD, search, search_len); \ } MAKE_SEARCH_FUNC(globals) @@ -715,6 +725,7 @@ static int parse_complete(token_t *tok) break; case TOK_IDENTIFIER: { + const char *replacement; int n = search_in_typenames(tok->info->ctx, tok->p, tok->size); if (n >= 0) { t1 = _CFFI_OP(_CFFI_OP_TYPENAME, n); @@ -725,6 +736,14 @@ static int parse_complete(token_t *tok) t1 = _CFFI_OP(_CFFI_OP_PRIMITIVE, n); break; } + replacement = get_common_type(tok->p, tok->size); + if (replacement != NULL) { + n = parse_common_type_replacement(tok, replacement); + if (n < 0) + return parse_error(tok, "internal error, please report!"); + t1 = _CFFI_OP(_CFFI_OP_NOOP, n); + break; + } return parse_error(tok, "undefined type name"); } case TOK_STRUCT: @@ -770,7 +789,8 @@ static int parse_complete(token_t *tok) static -int parse_c_type(struct _cffi_parse_info_s *info, const char *input) +int parse_c_type_from(struct _cffi_parse_info_s *info, size_t *output_index, + const char *input) { int result; token_t token; @@ -781,12 +801,26 @@ int parse_c_type(struct _cffi_parse_info_s *info, const char *input) token.p = input; token.size = 0; token.output = info->output; - token.output_index = 0; + token.output_index = *output_index; next_token(&token); result = parse_complete(&token); + *output_index = token.output_index; if (token.kind != TOK_END) return parse_error(&token, "unexpected symbol"); return result; } + +static +int parse_c_type(struct _cffi_parse_info_s *info, const char *input) +{ + size_t output_index = 0; + return parse_c_type_from(info, &output_index, input); +} + +static +int parse_common_type_replacement(token_t *tok, const char *replacement) +{ + return parse_c_type_from(tok->info, &tok->output_index, replacement); +} diff --git a/cffi/commontypes.py b/cffi/commontypes.py index 04a5868..60f2532 100644 --- a/cffi/commontypes.py +++ b/cffi/commontypes.py @@ -7,6 +7,13 @@ COMMON_TYPES = { 'bool': '_Bool', } +try: + # fetch "bool" and all simple Windows types + from _cffi_backend import _get_common_types + _get_common_types(COMMON_TYPES) +except ImportError: + pass + for _type in model.PrimitiveType.ALL_PRIMITIVE_TYPES: if _type.endswith('_t'): COMMON_TYPES[_type] = _type @@ -14,212 +21,35 @@ del _type _CACHE = {} -def resolve_common_type(commontype): +def resolve_common_type(parser, commontype): try: return _CACHE[commontype] except KeyError: - result = COMMON_TYPES.get(commontype, commontype) - if not isinstance(result, str): - pass # result is already a BaseType - elif result.endswith(' *'): - if result.startswith('const '): - result = model.ConstPointerType( - resolve_common_type(result[6:-2])) - else: - result = model.PointerType(resolve_common_type(result[:-2])) - elif result in model.PrimitiveType.ALL_PRIMITIVE_TYPES: - result = model.PrimitiveType(result) - elif result == 'set-unicode-needed': + cdecl = COMMON_TYPES.get(commontype, commontype) + if not isinstance(cdecl, str): + result, quals = cdecl, 0 # cdecl is already a BaseType + elif cdecl in model.PrimitiveType.ALL_PRIMITIVE_TYPES: + result, quals = model.PrimitiveType(cdecl), 0 + elif cdecl == 'set-unicode-needed': raise api.FFIError("The Windows type %r is only available after " "you call ffi.set_unicode()" % (commontype,)) else: - if commontype == result: + if commontype == cdecl: raise api.FFIError("Unsupported type: %r. Please file a bug " "if you think it should be." % (commontype,)) - result = resolve_common_type(result) # recursively + result, quals = parser.parse_type_and_quals(cdecl) # recursive + assert isinstance(result, model.BaseTypeByIdentity) - _CACHE[commontype] = result - return result + _CACHE[commontype] = result, quals + return result, quals # ____________________________________________________________ -# Windows common types - - -def win_common_types(maxsize): - result = {} - if maxsize < (1<<32): - result.update({ # Windows 32-bits - 'HALF_PTR': 'short', - 'INT_PTR': 'int', - 'LONG_PTR': 'long', - 'UHALF_PTR': 'unsigned short', - 'UINT_PTR': 'unsigned int', - 'ULONG_PTR': 'unsigned long', - }) - else: - result.update({ # Windows 64-bits - 'HALF_PTR': 'int', - 'INT_PTR': 'long long', - 'LONG_PTR': 'long long', - 'UHALF_PTR': 'unsigned int', - 'UINT_PTR': 'unsigned long long', - 'ULONG_PTR': 'unsigned long long', - }) - result.update({ - "BYTE": "unsigned char", - "BOOL": "int", - "CCHAR": "char", - "CHAR": "char", - "DWORD": "unsigned long", - "DWORD32": "unsigned int", - "DWORD64": "unsigned long long", - "FLOAT": "float", - "INT": "int", - "INT8": "signed char", - "INT16": "short", - "INT32": "int", - "INT64": "long long", - "LONG": "long", - "LONGLONG": "long long", - "LONG32": "int", - "LONG64": "long long", - "WORD": "unsigned short", - "PVOID": model.voidp_type, - "ULONGLONG": "unsigned long long", - "WCHAR": "wchar_t", - "SHORT": "short", - "UCHAR": "unsigned char", - "UINT": "unsigned int", - "UINT8": "unsigned char", - "UINT16": "unsigned short", - "UINT32": "unsigned int", - "UINT64": "unsigned long long", - "ULONG": "unsigned long", - "ULONG32": "unsigned int", - "ULONG64": "unsigned long long", - "USHORT": "unsigned short", - - "SIZE_T": "ULONG_PTR", - "SSIZE_T": "LONG_PTR", - "ATOM": "WORD", - "BOOLEAN": "BYTE", - "COLORREF": "DWORD", +# extra types for Windows (most of them are in commontypes.c) - "HANDLE": "PVOID", - "DWORDLONG": "ULONGLONG", - "DWORD_PTR": "ULONG_PTR", - "HACCEL": "HANDLE", - - "HBITMAP": "HANDLE", - "HBRUSH": "HANDLE", - "HCOLORSPACE": "HANDLE", - "HCONV": "HANDLE", - "HCONVLIST": "HANDLE", - "HDC": "HANDLE", - "HDDEDATA": "HANDLE", - "HDESK": "HANDLE", - "HDROP": "HANDLE", - "HDWP": "HANDLE", - "HENHMETAFILE": "HANDLE", - "HFILE": "int", - "HFONT": "HANDLE", - "HGDIOBJ": "HANDLE", - "HGLOBAL": "HANDLE", - "HHOOK": "HANDLE", - "HICON": "HANDLE", - "HCURSOR": "HICON", - "HINSTANCE": "HANDLE", - "HKEY": "HANDLE", - "HKL": "HANDLE", - "HLOCAL": "HANDLE", - "HMENU": "HANDLE", - "HMETAFILE": "HANDLE", - "HMODULE": "HINSTANCE", - "HMONITOR": "HANDLE", - "HPALETTE": "HANDLE", - "HPEN": "HANDLE", - "HRESULT": "LONG", - "HRGN": "HANDLE", - "HRSRC": "HANDLE", - "HSZ": "HANDLE", - "WINSTA": "HANDLE", - "HWND": "HANDLE", - - "LANGID": "WORD", - "LCID": "DWORD", - "LCTYPE": "DWORD", - "LGRPID": "DWORD", - "LPARAM": "LONG_PTR", - "LPBOOL": "BOOL *", - "LPBYTE": "BYTE *", - "LPCOLORREF": "DWORD *", - "LPCSTR": "const char *", - - "LPCVOID": model.const_voidp_type, - "LPCWSTR": "const WCHAR *", - "LPDWORD": "DWORD *", - "LPHANDLE": "HANDLE *", - "LPINT": "int *", - "LPLONG": "long *", - "LPSTR": "CHAR *", - "LPWSTR": "WCHAR *", - "LPVOID": model.voidp_type, - "LPWORD": "WORD *", - "LRESULT": "LONG_PTR", - "PBOOL": "BOOL *", - "PBOOLEAN": "BOOLEAN *", - "PBYTE": "BYTE *", - "PCHAR": "CHAR *", - "PCSTR": "const CHAR *", - "PCWSTR": "const WCHAR *", - "PDWORD": "DWORD *", - "PDWORDLONG": "DWORDLONG *", - "PDWORD_PTR": "DWORD_PTR *", - "PDWORD32": "DWORD32 *", - "PDWORD64": "DWORD64 *", - "PFLOAT": "FLOAT *", - "PHALF_PTR": "HALF_PTR *", - "PHANDLE": "HANDLE *", - "PHKEY": "HKEY *", - "PINT": "int *", - "PINT_PTR": "INT_PTR *", - "PINT8": "INT8 *", - "PINT16": "INT16 *", - "PINT32": "INT32 *", - "PINT64": "INT64 *", - "PLCID": "PDWORD", - "PLONG": "LONG *", - "PLONGLONG": "LONGLONG *", - "PLONG_PTR": "LONG_PTR *", - "PLONG32": "LONG32 *", - "PLONG64": "LONG64 *", - "PSHORT": "SHORT *", - "PSIZE_T": "SIZE_T *", - "PSSIZE_T": "SSIZE_T *", - "PSTR": "CHAR *", - "PUCHAR": "UCHAR *", - "PUHALF_PTR": "UHALF_PTR *", - "PUINT": "UINT *", - "PUINT_PTR": "UINT_PTR *", - "PUINT8": "UINT8 *", - "PUINT16": "UINT16 *", - "PUINT32": "UINT32 *", - "PUINT64": "UINT64 *", - "PULONG": "ULONG *", - "PULONGLONG": "ULONGLONG *", - "PULONG_PTR": "ULONG_PTR *", - "PULONG32": "ULONG32 *", - "PULONG64": "ULONG64 *", - "PUSHORT": "USHORT *", - "PWCHAR": "WCHAR *", - "PWORD": "WORD *", - "PWSTR": "WCHAR *", - "QWORD": "unsigned long long", - "SC_HANDLE": "HANDLE", - "SC_LOCK": "LPVOID", - "SERVICE_STATUS_HANDLE": "HANDLE", +def win_common_types(): + return { "UNICODE_STRING": model.StructType( "_UNICODE_STRING", ["Length", @@ -232,10 +62,6 @@ def win_common_types(maxsize): "PUNICODE_STRING": "UNICODE_STRING *", "PCUNICODE_STRING": "const UNICODE_STRING *", - "USN": "LONGLONG", - "VOID": model.void_type, - "WPARAM": "UINT_PTR", - "TBYTE": "set-unicode-needed", "TCHAR": "set-unicode-needed", "LPCTSTR": "set-unicode-needed", @@ -244,9 +70,7 @@ def win_common_types(maxsize): "PTSTR": "set-unicode-needed", "PTBYTE": "set-unicode-needed", "PTCHAR": "set-unicode-needed", - }) - return result - + } if sys.platform == 'win32': - COMMON_TYPES.update(win_common_types(sys.maxsize)) + COMMON_TYPES.update(win_common_types()) diff --git a/cffi/cparser.py b/cffi/cparser.py index cd5bea6..9be70c6 100644 --- a/cffi/cparser.py +++ b/cffi/cparser.py @@ -472,7 +472,8 @@ class Parser(object): if ident == '__dotdotdot__': raise api.FFIError(':%d: bad usage of "..."' % typenode.coord.line) - return resolve_common_type(ident), quals + tp0, quals0 = resolve_common_type(self, ident) + return tp0, (quals | quals0) # if isinstance(type, pycparser.c_ast.Struct): # 'struct foobar' diff --git a/testing/cffi0/test_parsing.py b/testing/cffi0/test_parsing.py index 4b10cc4..dea6126 100644 --- a/testing/cffi0/test_parsing.py +++ b/testing/cffi0/test_parsing.py @@ -286,38 +286,16 @@ def test_void_renamed_as_only_arg(): "typedef int (*func_t)(void_t);") assert ffi.typeof("func_t").args == () -def test_win_common_types(): - from cffi.commontypes import COMMON_TYPES, _CACHE - from cffi.commontypes import win_common_types, resolve_common_type - # - def clear_all(extra={}, old_dict=COMMON_TYPES.copy()): - COMMON_TYPES.clear() - COMMON_TYPES.update(old_dict) - COMMON_TYPES.update(extra) - _CACHE.clear() - # - for maxsize in [2**32-1, 2**64-1]: - ct = win_common_types(maxsize) - clear_all(ct) - for key in sorted(ct): - if ct[key] != 'set-unicode-needed': - resolve_common_type(key) - # assert did not crash - # now try to use e.g. WPARAM (-> UINT_PTR -> unsigned 32/64-bit) - for maxsize in [2**32-1, 2**64-1]: - ct = win_common_types(maxsize) - clear_all(ct) - ffi = FFI() - value = int(ffi.cast("WPARAM", -1)) - assert value == maxsize - # - clear_all() - def test_WPARAM_on_windows(): if sys.platform != 'win32': py.test.skip("Only for Windows") ffi = FFI() ffi.cdef("void f(WPARAM);") + # + # WPARAM -> UINT_PTR -> unsigned 32/64-bit integer + ffi = FFI() + value = int(ffi.cast("WPARAM", -42)) + assert value == sys.maxsize * 2 - 40 def test__is_constant_globalvar(): for input, expected_output in [ diff --git a/testing/cffi1/test_commontypes.py b/testing/cffi1/test_commontypes.py new file mode 100644 index 0000000..212da8d --- /dev/null +++ b/testing/cffi1/test_commontypes.py @@ -0,0 +1,15 @@ +import py, os, cffi +import _cffi_backend + + +def test_alphabetical_order(): + f = open(os.path.join(os.path.dirname(cffi.__file__), + '..', 'c', 'commontypes.c')) + lines = [line for line in f.readlines() if line.strip().startswith('EQ(')] + f.close() + assert lines == sorted(lines) + +def test_get_common_types(): + d = {} + _cffi_backend._get_common_types(d) + assert d["bool"] == "_Bool" diff --git a/testing/cffi1/test_ffi_obj.py b/testing/cffi1/test_ffi_obj.py index 8241c75..253206a 100644 --- a/testing/cffi1/test_ffi_obj.py +++ b/testing/cffi1/test_ffi_obj.py @@ -395,3 +395,17 @@ def test_ffi_new_allocator_4(): return ffi.NULL alloc5 = ffi.new_allocator(myalloc5) py.test.raises(MemoryError, alloc5, "int[5]") + +def test_bool_issue228(): + ffi = _cffi1_backend.FFI() + fntype = ffi.typeof("int(*callback)(bool is_valid)") + assert repr(fntype.args[0]) == "<ctype '_Bool'>" + +def test_cast_from_int_type_to_bool(): + ffi = _cffi1_backend.FFI() + for basetype in ['char', 'short', 'int', 'long', 'long long']: + for sign in ['signed', 'unsigned']: + type = '%s %s' % (sign, basetype) + assert int(ffi.cast("_Bool", ffi.cast(type, 42))) == 1 + assert int(ffi.cast("bool", ffi.cast(type, 42))) == 1 + assert int(ffi.cast("_Bool", ffi.cast(type, 0))) == 0 diff --git a/testing/cffi1/test_parse_c_type.py b/testing/cffi1/test_parse_c_type.py index 479e0e8..e90243d 100644 --- a/testing/cffi1/test_parse_c_type.py +++ b/testing/cffi1/test_parse_c_type.py @@ -19,8 +19,11 @@ ffi = cffi.FFI() ffi.cdef(header) lib = ffi.verify( - open(os.path.join(cffi_dir, '..', 'c', 'parse_c_type.c')).read(), - include_dirs=[cffi_dir]) + open(os.path.join(cffi_dir, '..', 'c', 'parse_c_type.c')).read() + """ +static const char *get_common_type(const char *search, size_t search_len) { + return NULL; +} +""", include_dirs=[cffi_dir]) class ParseError(Exception): pass diff --git a/testing/cffi1/test_verify1.py b/testing/cffi1/test_verify1.py index ffc2fc3..4678736 100644 --- a/testing/cffi1/test_verify1.py +++ b/testing/cffi1/test_verify1.py @@ -1494,15 +1494,6 @@ def test_cannot_pass_float(): assert lib.foo(0) == 1 py.test.raises(TypeError, lib.foo, 0.0) -def test_cast_from_int_type_to_bool(): - ffi = FFI() - for basetype in ['char', 'short', 'int', 'long', 'long long']: - for sign in ['signed', 'unsigned']: - type = '%s %s' % (sign, basetype) - assert int(ffi.cast("_Bool", ffi.cast(type, 42))) == 1 - assert int(ffi.cast("bool", ffi.cast(type, 42))) == 1 - assert int(ffi.cast("_Bool", ffi.cast(type, 0))) == 0 - def test_addressof(): ffi = FFI() ffi.cdef(""" |