Commit d67e69fa authored by Matti Picus's avatar Matti Picus
Browse files

merge default into branch

--HG--
branch : win32
......@@ -197,6 +197,8 @@ static void init_errno(void) { }
# 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 @@ static ffi_type *fb_fill_type(struct funcbuilder_s *fb, CTypeDescrObject *ct,
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_buffer(PyObject *self, PyObject *args)
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 @@ static PyObject *b_set_errno(PyObject *self, PyObject *args)
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;
......
......@@ -45,6 +45,18 @@ static void save_errno(void)
/* 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 @@ static void restore_errno(void)
/* 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 */
......
......@@ -773,6 +773,11 @@ def test_function_void_result():
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)
......
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 @@ class Parser(object):
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 @@ class Parser(object):
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']):
......
import py, sys
import py, sys, re
from cffi import FFI, FFIError, CDefError, VerificationError
class FakeBackend(object):
......@@ -177,3 +177,15 @@ def test_override():
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))
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment