Description: Fix long double related test failures on non-x86
 long double on PPC has higher precision than double, while the same size.
 On other architectures, it's simply the same as double.
Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/python-cffi/+bug/1157978
Bug-Upstream: https://bitbucket.org/cffi/cffi/issue/68/long-double
Origin: upstream,
 https://bitbucket.org/cffi/cffi/commits/e67cd88ae64b
 https://bitbucket.org/cffi/cffi/commits/c5e85201f3ce
 https://bitbucket.org/cffi/cffi/commits/be070b8687d3
 https://bitbucket.org/cffi/cffi/commits/3c66c29d2e80
 https://bitbucket.org/cffi/cffi/commits/1f49770a97b2
 https://bitbucket.org/cffi/cffi/commits/231fd7f12dbb
Author: Armin Rigo <arigo@tunes.org>

--- a/c/_cffi_backend.c
+++ b/c/_cffi_backend.c
@@ -4642,11 +4642,12 @@
     return ptr->a1 + (int)ptr->a2;
 }
 
-static long double _testfunc19(long double x)
+static long double _testfunc19(long double x, int count)
 {
     int i;
-    for (i=0; i<28; i++)
-        x += x;
+    for (i=0; i<count; i++) {
+        x = 4*x - x*x;
+    }
     return x;
 }
 
@@ -4786,11 +4787,6 @@
 _cffi_to_c_UNSIGNED_FN(unsigned int, 32)
 _cffi_to_c_UNSIGNED_FN(unsigned PY_LONG_LONG, 64)
 
-static char _cffi_to_c_char(PyObject *obj)
-{
-    return (char)_convert_to_char(obj);
-}
-
 static PyObject *_cffi_from_c_pointer(char *ptr, CTypeDescrObject *ct)
 {
     return convert_to_object((char *)&ptr, ct);
@@ -4878,7 +4874,7 @@
     _cffi_to_c_u32,
     _cffi_to_c_i64,
     _cffi_to_c_u64,
-    _cffi_to_c_char,
+    _convert_to_char,
     _cffi_from_c_pointer,
     _cffi_to_c_pointer,
     _cffi_get_struct_layout,
--- a/c/test_c.py
+++ b/c/test_c.py
@@ -2210,6 +2210,7 @@
 
 def test_longdouble():
     py_py = 'PY_DOT_PY' in globals()
+    BInt = new_primitive_type("int")
     BLongDouble = new_primitive_type("long double")
     BLongDoublePtr = new_pointer_type(BLongDouble)
     BLongDoubleArray = new_array_type(BLongDoublePtr, None)
@@ -2227,21 +2228,23 @@
     assert float(x) == 1.23
     assert int(x) == 1
     #
-    BFunc19 = new_function_type((BLongDouble,), BLongDouble)
+    BFunc19 = new_function_type((BLongDouble, BInt), BLongDouble)
     f = cast(BFunc19, _testfunc(19))
-    start = 8
+    start = lstart = 1.5
     for i in range(107):
-        start = f(start)
-    if sizeof(BLongDouble) > sizeof(new_primitive_type("double")):
-        if not py_py:
-            assert repr(start).startswith("<cdata 'long double' 6.15")
-            assert repr(start).endswith("E+902>")
-        #
-        c = newp(BLongDoubleArray, [start])
-        x = c[0]
-        if not py_py:
-            assert repr(x).endswith("E+902>")
-            assert float(x) == float("inf")
+        start = 4 * start - start * start
+        lstart = f(lstart, 1)
+    lother = f(1.5, 107)
+    if not py_py:
+        assert float(lstart) == float(lother)
+        assert repr(lstart) == repr(lother)
+        if sizeof(BLongDouble) > sizeof(new_primitive_type("double")):
+            assert float(lstart) != start
+            assert repr(lstart).startswith("<cdata 'long double' ")
+    #
+    c = newp(BLongDoubleArray, [lstart])
+    x = c[0]
+    assert float(f(lstart, 107)) == float(f(x, 107))
 
 def test_get_array_of_length_zero():
     for length in [0, 5, 10]:
--- a/testing/test_verify.py
+++ b/testing/test_verify.py
@@ -425,13 +425,18 @@
 
 def _check_field_match(typename, real, expect_mismatch):
     ffi = FFI()
-    if expect_mismatch == 'by_size':
+    testing_by_size = (expect_mismatch == 'by_size')
+    if testing_by_size:
         expect_mismatch = ffi.sizeof(typename) != ffi.sizeof(real)
     ffi.cdef("struct foo_s { %s x; ...; };" % typename)
     try:
         ffi.verify("struct foo_s { %s x; };" % real)
     except VerificationError:
         if not expect_mismatch:
+            if testing_by_size and typename != real:
+                print("ignoring mismatch between %s* and %s* even though "
+                      "they have the same size" % (typename, real))
+                return
             raise AssertionError("unexpected mismatch: %s should be accepted "
                                  "as equal to %s" % (typename, real))
     else:
@@ -1217,7 +1222,8 @@
     f0 = lib.square(0.0)
     f2 = lib.square(f)
     f3 = lib.square(f * 2.0)
-    assert repr(f2) != repr(f3)             # two non-null 'long doubles'
+    if repr(f2) == repr(f3):
+        py.test.skip("long double doesn't have enough precision")
     assert float(f0) == float(f2) == float(f3) == 0.0  # too tiny for 'double'
     assert int(ffi.cast("_Bool", f2)) == 1
     assert int(ffi.cast("_Bool", f3)) == 1
--- a/cffi/vengine_cpy.py
+++ b/cffi/vengine_cpy.py
@@ -773,7 +773,7 @@
 #define _cffi_to_c_u64                                                   \
                  ((unsigned long long(*)(PyObject *))_cffi_exports[8])
 #define _cffi_to_c_char                                                  \
-                 ((char(*)(PyObject *))_cffi_exports[9])
+                 ((int(*)(PyObject *))_cffi_exports[9])
 #define _cffi_from_c_pointer                                             \
     ((PyObject *(*)(char *, CTypeDescrObject *))_cffi_exports[10])
 #define _cffi_to_c_pointer                                               \
