Author: mattip <matti.pi...@gmail.com> Branch: win32 Changeset: r874:4b70a2b6ac68 Date: 2012-08-22 22:20 +0300 http://bitbucket.org/cffi/cffi/changeset/4b70a2b6ac68/
Log: merge default into branch diff --git a/c/_cffi_backend.c b/c/_cffi_backend.c --- a/c/_cffi_backend.c +++ b/c/_cffi_backend.c @@ -197,6 +197,8 @@ # else # include "misc_thread.h" # endif +# define save_errno_only save_errno +# define restore_errno_only restore_errno #endif #ifdef HAVE_WCHAR_H @@ -3182,7 +3184,7 @@ else if (ct->ct_flags & (CT_POINTER|CT_ARRAY|CT_FUNCTIONPTR)) { return &ffi_type_pointer; } - else if (ct->ct_flags & CT_VOID) { + else if ((ct->ct_flags & CT_VOID) && is_result_type) { return &ffi_type_void; } @@ -4044,7 +4046,7 @@ static PyObject *b_get_errno(PyObject *self, PyObject *noarg) { int err; - restore_errno(); + restore_errno_only(); err = errno; errno = 0; return PyInt_FromLong(err); @@ -4056,7 +4058,7 @@ if (!PyArg_ParseTuple(args, "i:set_errno", &i)) return NULL; errno = i; - save_errno(); + save_errno_only(); errno = 0; Py_INCREF(Py_None); return Py_None; diff --git a/c/misc_win32.h b/c/misc_win32.h --- a/c/misc_win32.h +++ b/c/misc_win32.h @@ -45,6 +45,18 @@ /* else: cannot report the error */ } +static void save_errno_only(void) +{ + int current_err = errno; + struct cffi_errno_s *p; + + p = _geterrno_object(); + if (p != NULL) { + p->saved_errno = current_err; + } + /* else: cannot report the error */ +} + static void restore_errno(void) { struct cffi_errno_s *p; @@ -57,6 +69,16 @@ /* else: cannot report the error */ } +static void restore_errno_only(void) +{ + struct cffi_errno_s *p; + + p = _geterrno_object(); + if (p != NULL) { + errno = p->saved_errno; + } + /* else: cannot report the error */ +} /************************************************************/ /* Emulate dlopen()&co. from the Windows API */ diff --git a/c/test_c.py b/c/test_c.py --- a/c/test_c.py +++ b/c/test_c.py @@ -773,6 +773,11 @@ BFunc = new_function_type((BInt, BInt), BVoid, False) assert repr(BFunc) == "<ctype 'void(*)(int, int)'>" +def test_function_void_arg(): + BVoid = new_void_type() + BInt = new_primitive_type("int") + py.test.raises(TypeError, new_function_type, (BVoid,), BInt, False) + def test_call_function_0(): BSignedChar = new_primitive_type("signed char") BFunc0 = new_function_type((BSignedChar, BSignedChar), BSignedChar, False) diff --git a/cffi/cparser.py b/cffi/cparser.py --- a/cffi/cparser.py +++ b/cffi/cparser.py @@ -1,6 +1,6 @@ from . import api, model -import pycparser, weakref, re +import pycparser.c_parser, weakref, re _r_comment = re.compile(r"/\*.*?\*/|//.*?$", re.DOTALL | re.MULTILINE) _r_define = re.compile(r"^\s*#\s*define\s+([A-Za-z_][A-Za-z_0-9]*)\s+(.*?)$", @@ -61,9 +61,30 @@ csource, macros = _preprocess(csource) csourcelines.append(csource) csource = '\n'.join(csourcelines) - ast = _get_parser().parse(csource) + try: + ast = _get_parser().parse(csource) + except pycparser.c_parser.ParseError, e: + self.convert_pycparser_error(e, csource) return ast, macros + 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 + msg = str(e) + if msg.startswith(':') and ':' in msg[1:]: + linenum = msg[1:msg.find(':',1)] + if linenum.isdigit(): + linenum = int(linenum, 10) + csourcelines = csource.splitlines() + if 1 <= linenum <= len(csourcelines): + line = csourcelines[linenum-1] + if line: + msg = 'cannot parse "%s"\n%s' % (line, msg) + else: + msg = 'parse error\n%s' % (msg,) + raise api.CDefError(msg) + def parse(self, csource, override=False): prev_override = self._override try: @@ -244,7 +265,11 @@ params[-1].type.type.names == ['__dotdotdot__']) if ellipsis: params.pop() - if (len(params) == 1 and + if not params: + raise api.CDefError( + "%s: a function with only '(...)' as argument" + " is not correct C" % (funcname or 'in expression')) + elif (len(params) == 1 and isinstance(params[0].type, pycparser.c_ast.TypeDecl) and isinstance(params[0].type.type, pycparser.c_ast.IdentifierType) and list(params[0].type.type.names) == ['void']): diff --git a/testing/test_parsing.py b/testing/test_parsing.py --- a/testing/test_parsing.py +++ b/testing/test_parsing.py @@ -1,4 +1,4 @@ -import py, sys +import py, sys, re from cffi import FFI, FFIError, CDefError, VerificationError class FakeBackend(object): @@ -177,3 +177,15 @@ assert C.foo.BType == '<func (), <int>, False>' ffi.cdef("long foo(void);", override=True) assert C.foo.BType == '<func (), <long>, False>' + +def test_cannot_have_only_variadic_part(): + # this checks that we get a sensible error if we try "int foo(...);" + ffi = FFI() + e = py.test.raises(CDefError, ffi.cdef, "int foo(...);") + assert str(e.value) == \ + "foo: a function with only '(...)' as argument is not correct C" + +def test_parse_error(): + ffi = FFI() + e = py.test.raises(CDefError, ffi.cdef, " x y z ") + assert re.match(r'cannot parse " x y z "\n:\d+:', str(e.value)) _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit