[pypy-commit] pypy cpyext-int: merge default into branch

mattip noreply at buildbot.pypy.org
Sat Nov 9 22:11:46 CET 2013


Author: Matti Picus <matti.picus at gmail.com>
Branch: cpyext-int
Changeset: r67909:2f1482525200
Date: 2013-11-09 23:06 +0200
http://bitbucket.org/pypy/pypy/changeset/2f1482525200/

Log:	merge default into branch

diff --git a/pypy/doc/how-to-release.rst b/pypy/doc/how-to-release.rst
--- a/pypy/doc/how-to-release.rst
+++ b/pypy/doc/how-to-release.rst
@@ -47,3 +47,7 @@
 * post announcement on morepypy.blogspot.com
 * send announcements to pypy-dev, python-list,
   python-announce, python-dev ...
+
+* add a tag on jitviewer that corresponds to pypy release
+* add a tag on codespeed that corresponds to pypy release
+
diff --git a/pypy/module/_cffi_backend/__init__.py b/pypy/module/_cffi_backend/__init__.py
--- a/pypy/module/_cffi_backend/__init__.py
+++ b/pypy/module/_cffi_backend/__init__.py
@@ -7,7 +7,7 @@
     appleveldefs = {
         }
     interpleveldefs = {
-        '__version__': 'space.wrap("0.7")',
+        '__version__': 'space.wrap("0.8")',
 
         'load_library': 'libraryobj.load_library',
 
diff --git a/pypy/module/_cffi_backend/cdataobj.py b/pypy/module/_cffi_backend/cdataobj.py
--- a/pypy/module/_cffi_backend/cdataobj.py
+++ b/pypy/module/_cffi_backend/cdataobj.py
@@ -19,9 +19,9 @@
     _cdata = lltype.nullptr(rffi.CCHARP.TO)
 
     def __init__(self, space, cdata, ctype):
-        from pypy.module._cffi_backend import ctypeprim
+        from pypy.module._cffi_backend import ctypeobj
         assert lltype.typeOf(cdata) == rffi.CCHARP
-        assert isinstance(ctype, ctypeprim.W_CType)
+        assert isinstance(ctype, ctypeobj.W_CType)
         self.space = space
         self._cdata = cdata    # don't forget keepalive_until_here!
         self.ctype = ctype
@@ -211,7 +211,21 @@
                 keepalive_until_here(w_value)
                 return
         #
+        # A fast path for <char[]>[0:N] = "somestring".
+        from pypy.module._cffi_backend import ctypeprim
         space = self.space
+        if (space.isinstance_w(w_value, space.w_str) and
+                isinstance(ctitem, ctypeprim.W_CTypePrimitiveChar)):
+            from rpython.rtyper.annlowlevel import llstr
+            from rpython.rtyper.lltypesystem.rstr import copy_string_to_raw
+            value = space.str_w(w_value)
+            if len(value) != length:
+                raise operationerrfmt(space.w_ValueError,
+                                      "need a string of length %d, got %d",
+                                      length, len(value))
+            copy_string_to_raw(llstr(value), cdata, 0, length)
+            return
+        #
         w_iter = space.iter(w_value)
         for i in range(length):
             try:
@@ -245,19 +259,22 @@
         space = self.space
         if isinstance(w_other, W_CData):
             from pypy.module._cffi_backend import ctypeptr, ctypearray
+            from pypy.module._cffi_backend import ctypevoid
             ct = w_other.ctype
             if isinstance(ct, ctypearray.W_CTypeArray):
                 ct = ct.ctptr
             #
             if (ct is not self.ctype or
                    not isinstance(ct, ctypeptr.W_CTypePointer) or
-                   ct.ctitem.size <= 0):
+                   (ct.ctitem.size <= 0 and not ct.is_void_ptr)):
                 raise operationerrfmt(space.w_TypeError,
                     "cannot subtract cdata '%s' and cdata '%s'",
                     self.ctype.name, ct.name)
             #
+            itemsize = ct.ctitem.size
+            if itemsize <= 0: itemsize = 1
             diff = (rffi.cast(lltype.Signed, self._cdata) -
-                    rffi.cast(lltype.Signed, w_other._cdata)) // ct.ctitem.size
+                    rffi.cast(lltype.Signed, w_other._cdata)) // itemsize
             return space.wrap(diff)
         #
         return self._add_or_sub(w_other, -1)
@@ -441,6 +458,7 @@
     __getitem__ = interp2app(W_CData.getitem),
     __setitem__ = interp2app(W_CData.setitem),
     __add__ = interp2app(W_CData.add),
+    __radd__ = interp2app(W_CData.add),
     __sub__ = interp2app(W_CData.sub),
     __getattr__ = interp2app(W_CData.getattr),
     __setattr__ = interp2app(W_CData.setattr),
diff --git a/pypy/module/_cffi_backend/ctypearray.py b/pypy/module/_cffi_backend/ctypearray.py
--- a/pypy/module/_cffi_backend/ctypearray.py
+++ b/pypy/module/_cffi_backend/ctypearray.py
@@ -34,19 +34,8 @@
         datasize = self.size
         #
         if datasize < 0:
-            if (space.isinstance_w(w_init, space.w_list) or
-                space.isinstance_w(w_init, space.w_tuple)):
-                length = space.int_w(space.len(w_init))
-            elif space.isinstance_w(w_init, space.w_basestring):
-                # from a string, we add the null terminator
-                length = space.int_w(space.len(w_init)) + 1
-            else:
-                length = space.getindex_w(w_init, space.w_OverflowError)
-                if length < 0:
-                    raise OperationError(space.w_ValueError,
-                                         space.wrap("negative array length"))
-                w_init = space.w_None
-            #
+            from pypy.module._cffi_backend import misc
+            w_init, length = misc.get_new_array_length(space, w_init)
             try:
                 datasize = ovfcheck(length * self.ctitem.size)
             except OverflowError:
diff --git a/pypy/module/_cffi_backend/ctypeptr.py b/pypy/module/_cffi_backend/ctypeptr.py
--- a/pypy/module/_cffi_backend/ctypeptr.py
+++ b/pypy/module/_cffi_backend/ctypeptr.py
@@ -2,27 +2,25 @@
 Pointers.
 """
 
-from pypy.interpreter.error import OperationError, operationerrfmt, wrap_oserror
-
 from rpython.rlib import rposix
 from rpython.rlib.objectmodel import keepalive_until_here
 from rpython.rlib.rarithmetic import ovfcheck
+from rpython.rtyper.annlowlevel import llstr, llunicode
 from rpython.rtyper.lltypesystem import lltype, rffi
+from rpython.rtyper.lltypesystem.rstr import copy_string_to_raw, copy_unicode_to_raw
 
+from pypy.interpreter.error import OperationError, operationerrfmt, wrap_oserror
 from pypy.module._cffi_backend import cdataobj, misc, ctypeprim, ctypevoid
 from pypy.module._cffi_backend.ctypeobj import W_CType
 
 
 class W_CTypePtrOrArray(W_CType):
-    _attrs_            = ['ctitem', 'can_cast_anything', 'is_struct_ptr',
-                          'length']
-    _immutable_fields_ = ['ctitem', 'can_cast_anything', 'is_struct_ptr',
-                          'length']
+    _attrs_            = ['ctitem', 'can_cast_anything', 'length']
+    _immutable_fields_ = ['ctitem', 'can_cast_anything', 'length']
     length = -1
 
     def __init__(self, space, size, extra, extra_position, ctitem,
                  could_cast_anything=True):
-        from pypy.module._cffi_backend.ctypestruct import W_CTypeStructOrUnion
         name, name_position = ctitem.insert_name(extra, extra_position)
         W_CType.__init__(self, space, size, name, name_position)
         # this is the "underlying type":
@@ -31,7 +29,6 @@
         #  - for functions, it is the return type
         self.ctitem = ctitem
         self.can_cast_anything = could_cast_anything and ctitem.cast_anything
-        self.is_struct_ptr = isinstance(ctitem, W_CTypeStructOrUnion)
 
     def is_char_ptr_or_array(self):
         return isinstance(self.ctitem, ctypeprim.W_CTypePrimitiveChar)
@@ -90,8 +87,7 @@
                                       "initializer string is too long for '%s'"
                                       " (got %d characters)",
                                       self.name, n)
-            for i in range(n):
-                cdata[i] = s[i]
+            copy_string_to_raw(llstr(s), cdata, 0, n)
             if n != self.length:
                 cdata[n] = '\x00'
         elif isinstance(self.ctitem, ctypeprim.W_CTypePrimitiveUniChar):
@@ -105,8 +101,7 @@
                                       " (got %d characters)",
                                       self.name, n)
             unichardata = rffi.cast(rffi.CWCHARP, cdata)
-            for i in range(n):
-                unichardata[i] = s[i]
+            copy_unicode_to_raw(llunicode(s), unichardata, 0, n)
             if n != self.length:
                 unichardata[n] = u'\x00'
         else:
@@ -157,7 +152,6 @@
         return cdataobj.W_CData(self.space, ptrdata, self)
 
     def convert_from_object(self, cdata, w_ob):
-        space = self.space
         if not isinstance(w_ob, cdataobj.W_CData):
             raise self._convert_error("cdata pointer", w_ob)
         other = w_ob.ctype
@@ -197,6 +191,7 @@
         W_CTypePtrBase.__init__(self, space, size, extra, 2, ctitem)
 
     def newp(self, w_init):
+        from pypy.module._cffi_backend.ctypestruct import W_CTypeStructOrUnion
         space = self.space
         ctitem = self.ctitem
         datasize = ctitem.size
@@ -204,10 +199,15 @@
             raise operationerrfmt(space.w_TypeError,
                 "cannot instantiate ctype '%s' of unknown size",
                                   self.name)
-        if self.is_struct_ptr:
+        if isinstance(ctitem, W_CTypeStructOrUnion):
             # 'newp' on a struct-or-union pointer: in this case, we return
             # a W_CDataPtrToStruct object which has a strong reference
             # to a W_CDataNewOwning that really contains the structure.
+            #
+            if ctitem.with_var_array and not space.is_w(w_init, space.w_None):
+                datasize = ctitem.convert_struct_from_object(
+                    lltype.nullptr(rffi.CCHARP.TO), w_init, datasize)
+            #
             cdatastruct = cdataobj.W_CDataNewOwning(space, datasize, ctitem)
             cdata = cdataobj.W_CDataPtrToStructOrUnion(space,
                                                        cdatastruct._cdata,
@@ -238,11 +238,15 @@
     def add(self, cdata, i):
         space = self.space
         ctitem = self.ctitem
+        itemsize = ctitem.size
         if ctitem.size < 0:
-            raise operationerrfmt(space.w_TypeError,
+            if self.is_void_ptr:
+                itemsize = 1
+            else:
+                raise operationerrfmt(space.w_TypeError,
                                   "ctype '%s' points to items of unknown size",
                                   self.name)
-        p = rffi.ptradd(cdata, i * self.ctitem.size)
+        p = rffi.ptradd(cdata, i * itemsize)
         return cdataobj.W_CData(space, p, self)
 
     def cast(self, w_ob):
@@ -298,7 +302,6 @@
 
     def convert_argument_from_object(self, cdata, w_ob):
         from pypy.module._cffi_backend.ctypefunc import set_mustfree_flag
-        space = self.space
         result = (not isinstance(w_ob, cdataobj.W_CData) and
                   self._prepare_pointer_call_argument(w_ob, cdata))
         if result == 0:
@@ -320,7 +323,8 @@
         space = self.space
         ctype2 = cdata.ctype
         if (isinstance(ctype2, W_CTypeStructOrUnion) or
-            (isinstance(ctype2, W_CTypePtrOrArray) and ctype2.is_struct_ptr)):
+               (isinstance(ctype2, W_CTypePtrOrArray) and
+                isinstance(ctype2.ctitem, W_CTypeStructOrUnion))):
             ptrdata = rffi.ptradd(cdata._cdata, offset)
             return cdataobj.W_CData(space, ptrdata, self)
         else:
diff --git a/pypy/module/_cffi_backend/ctypestruct.py b/pypy/module/_cffi_backend/ctypestruct.py
--- a/pypy/module/_cffi_backend/ctypestruct.py
+++ b/pypy/module/_cffi_backend/ctypestruct.py
@@ -9,7 +9,8 @@
 from rpython.rlib import jit
 from rpython.rlib.objectmodel import keepalive_until_here
 from rpython.rlib.rarithmetic import r_uint, r_ulonglong, r_longlong, intmask
-from rpython.rtyper.lltypesystem import rffi
+from rpython.rlib.rarithmetic import ovfcheck
+from rpython.rtyper.lltypesystem import lltype, rffi
 
 from pypy.module._cffi_backend import cdataobj, ctypeprim, misc
 from pypy.module._cffi_backend.ctypeobj import W_CType
@@ -17,12 +18,13 @@
 
 class W_CTypeStructOrUnion(W_CType):
     _immutable_fields_ = ['alignment?', 'fields_list?', 'fields_dict?',
-                          'custom_field_pos?']
+                          'custom_field_pos?', 'with_var_array?']
     # fields added by complete_struct_or_union():
     alignment = -1
     fields_list = None
     fields_dict = None
     custom_field_pos = False
+    with_var_array = False
 
     def __init__(self, space, name):
         W_CType.__init__(self, space, -1, name, len(name))
@@ -90,12 +92,13 @@
         pass
 
     def convert_from_object(self, cdata, w_ob):
-        space = self.space
-        if self._copy_from_same(cdata, w_ob):
-            return
+        if not self._copy_from_same(cdata, w_ob):
+            self.convert_struct_from_object(cdata, w_ob, optvarsize=-1)
 
+    def convert_struct_from_object(self, cdata, w_ob, optvarsize):
         self._check_only_one_argument_for_union(w_ob)
 
+        space = self.space
         if (space.isinstance_w(w_ob, space.w_list) or
             space.isinstance_w(w_ob, space.w_tuple)):
             lst_w = space.listview(w_ob)
@@ -104,7 +107,9 @@
                         "too many initializers for '%s' (got %d)",
                                       self.name, len(lst_w))
             for i in range(len(lst_w)):
-                self.fields_list[i].write(cdata, lst_w[i])
+                optvarsize = self.fields_list[i].write_v(cdata, lst_w[i],
+                                                         optvarsize)
+            return optvarsize
 
         elif space.isinstance_w(w_ob, space.w_dict):
             lst_w = space.fixedview(w_ob)
@@ -116,11 +121,16 @@
                 except KeyError:
                     space.raise_key_error(w_key)
                     assert 0
-                cf.write(cdata, space.getitem(w_ob, w_key))
+                optvarsize = cf.write_v(cdata, space.getitem(w_ob, w_key),
+                                        optvarsize)
+            return optvarsize
 
         else:
-            raise self._convert_error("list or tuple or dict or struct-cdata",
-                                      w_ob)
+            if optvarsize == -1:
+                msg = "list or tuple or dict or struct-cdata"
+            else:
+                msg = "list or tuple or dict"
+            raise self._convert_error(msg, w_ob)
 
     @jit.elidable
     def _getcfield_const(self, attr):
@@ -192,6 +202,37 @@
         else:
             self.ctype.convert_from_object(cdata, w_ob)
 
+    def write_v(self, cdata, w_ob, optvarsize):
+        # a special case for var-sized C99 arrays
+        from pypy.module._cffi_backend import ctypearray
+        ct = self.ctype
+        if isinstance(ct, ctypearray.W_CTypeArray) and ct.length < 0:
+            space = ct.space
+            w_ob, varsizelength = misc.get_new_array_length(space, w_ob)
+            if optvarsize != -1:
+                # in this mode, the only purpose of this function is to compute
+                # the real size of the structure from a var-sized C99 array
+                assert cdata == lltype.nullptr(rffi.CCHARP.TO)
+                itemsize = ct.ctitem.size
+                try:
+                    varsize = ovfcheck(itemsize * varsizelength)
+                    size = ovfcheck(self.offset + varsize)
+                except OverflowError:
+                    raise OperationError(space.w_OverflowError,
+                        space.wrap("array size would overflow a ssize_t"))
+                assert size >= 0
+                return max(size, optvarsize)
+            # if 'value' was only an integer, get_new_array_length() returns
+            # w_ob = space.w_None.  Detect if this was the case,
+            # and if so, stop here, leaving the content uninitialized
+            # (it should be zero-initialized from somewhere else).
+            if space.is_w(w_ob, space.w_None):
+                return optvarsize
+        #
+        if optvarsize == -1:
+            self.write(cdata, w_ob)
+        return optvarsize
+
     def convert_bitfield_to_object(self, cdata):
         ctype = self.ctype
         space = ctype.space
diff --git a/pypy/module/_cffi_backend/misc.py b/pypy/module/_cffi_backend/misc.py
--- a/pypy/module/_cffi_backend/misc.py
+++ b/pypy/module/_cffi_backend/misc.py
@@ -278,6 +278,22 @@
 
 # ____________________________________________________________
 
+def get_new_array_length(space, w_value):
+    if (space.isinstance_w(w_value, space.w_list) or
+        space.isinstance_w(w_value, space.w_tuple)):
+        return (w_value, space.int_w(space.len(w_value)))
+    elif space.isinstance_w(w_value, space.w_basestring):
+        # from a string, we add the null terminator
+        return (w_value, space.int_w(space.len(w_value)) + 1)
+    else:
+        explicitlength = space.getindex_w(w_value, space.w_OverflowError)
+        if explicitlength < 0:
+            raise OperationError(space.w_ValueError,
+                                 space.wrap("negative array length"))
+        return (space.w_None, explicitlength)
+
+# ____________________________________________________________
+
 @specialize.arg(0)
 def _raw_memcopy_tp(TPP, source, dest):
     # in its own function: LONGLONG may make the whole function jit-opaque
diff --git a/pypy/module/_cffi_backend/newtype.py b/pypy/module/_cffi_backend/newtype.py
--- a/pypy/module/_cffi_backend/newtype.py
+++ b/pypy/module/_cffi_backend/newtype.py
@@ -158,8 +158,10 @@
     fields_list = []
     fields_dict = {}
     custom_field_pos = False
+    with_var_array = False
 
-    for w_field in fields_w:
+    for i in range(len(fields_w)):
+        w_field = fields_w[i]
         field_w = space.fixedview(w_field)
         if not (2 <= len(field_w) <= 4):
             raise OperationError(space.w_TypeError,
@@ -176,7 +178,11 @@
                                   "duplicate field name '%s'", fname)
         #
         if ftype.size < 0:
-            raise operationerrfmt(space.w_TypeError,
+            if (isinstance(ftype, ctypearray.W_CTypeArray) and fbitsize < 0
+                    and (i == len(fields_w) - 1 or foffset != -1)):
+                with_var_array = True
+            else:
+                raise operationerrfmt(space.w_TypeError,
                     "field '%s.%s' has ctype '%s' of unknown size",
                                   w_ctype.name, fname, ftype.name)
         #
@@ -235,7 +241,8 @@
                 fields_list.append(fld)
                 fields_dict[fname] = fld
 
-            boffset += ftype.size * 8
+            if ftype.size >= 0:
+                boffset += ftype.size * 8
             prev_bitfield_size = 0
 
         else:
@@ -359,6 +366,7 @@
     w_ctype.fields_list = fields_list
     w_ctype.fields_dict = fields_dict
     w_ctype.custom_field_pos = custom_field_pos
+    w_ctype.with_var_array = with_var_array
 
 # ____________________________________________________________
 
diff --git a/pypy/module/_cffi_backend/test/_backend_test_c.py b/pypy/module/_cffi_backend/test/_backend_test_c.py
--- a/pypy/module/_cffi_backend/test/_backend_test_c.py
+++ b/pypy/module/_cffi_backend/test/_backend_test_c.py
@@ -542,6 +542,7 @@
     assert repr(a) == "<cdata 'int[3][5]' owning %d bytes>" % (
         3*5*size_of_int(),)
     assert repr(a + 0).startswith("<cdata 'int(*)[5]' 0x")
+    assert 0 + a == a + 0 != 1 + a == a + 1
     assert repr(a[0]).startswith("<cdata 'int[5]' 0x")
     assert repr((a + 0)[0]).startswith("<cdata 'int[5]' 0x")
     assert repr(a[0] + 0).startswith("<cdata 'int *' 0x")
@@ -1631,9 +1632,6 @@
 def test_void_errors():
     py.test.raises(ValueError, alignof, new_void_type())
     py.test.raises(TypeError, newp, new_pointer_type(new_void_type()), None)
-    x = cast(new_pointer_type(new_void_type()), 42)
-    py.test.raises(TypeError, "x + 1")
-    py.test.raises(TypeError, "x - 1")
 
 def test_too_many_items():
     BChar = new_primitive_type("char")
@@ -2952,6 +2950,166 @@
     _test_bitfield_details(flag=4)
 
 
+def test_struct_array_no_length():
+    BInt = new_primitive_type("int")
+    BIntP = new_pointer_type(BInt)
+    BArray = new_array_type(BIntP, None)
+    BStruct = new_struct_type("foo")
+    py.test.raises(TypeError, complete_struct_or_union,
+                   BStruct, [('x', BArray),
+                             ('y', BInt)])
+    #
+    BStruct = new_struct_type("foo")
+    complete_struct_or_union(BStruct, [('x', BInt),
+                                       ('y', BArray)])
+    assert sizeof(BStruct) == size_of_int()
+    d = BStruct.fields
+    assert len(d) == 2
+    assert d[0][0] == 'x'
+    assert d[0][1].type is BInt
+    assert d[0][1].offset == 0
+    assert d[0][1].bitshift == -1
+    assert d[0][1].bitsize == -1
+    assert d[1][0] == 'y'
+    assert d[1][1].type is BArray
+    assert d[1][1].offset == size_of_int()
+    assert d[1][1].bitshift == -1
+    assert d[1][1].bitsize == -1
+    #
+    p = newp(new_pointer_type(BStruct))
+    p.x = 42
+    assert p.x == 42
+    assert typeof(p.y) is BIntP
+    assert p.y == cast(BIntP, p) + 1
+    #
+    p = newp(new_pointer_type(BStruct), [100])
+    assert p.x == 100
+    #
+    # Tests for
+    #    ffi.new("struct_with_var_array *", [field.., [the_array_items..]])
+    #    ffi.new("struct_with_var_array *", [field.., array_size])
+    plist = []
+    for i in range(20):
+        if i % 2 == 0:
+            p = newp(new_pointer_type(BStruct), [100, [200, i, 400]])
+        else:
+            p = newp(new_pointer_type(BStruct), [100, 3])
+            p.y[1] = i
+            p.y[0] = 200
+            assert p.y[2] == 0
+            p.y[2] = 400
+        plist.append(p)
+    for i in range(20):
+        p = plist[i]
+        assert p.x == 100
+        assert p.y[0] == 200
+        assert p.y[1] == i
+        assert p.y[2] == 400
+        assert list(p.y[0:3]) == [200, i, 400]
+    #
+    # the following assignment works, as it normally would, for any array field
+    p.y = [500, 600]
+    assert list(p.y[0:3]) == [500, 600, 400]
+    #
+    # error cases
+    py.test.raises(TypeError, "p.y = cast(BIntP, 0)")
+    py.test.raises(TypeError, "p.y = 15")
+    py.test.raises(TypeError, "p.y = None")
+    #
+    # accepting this may be specified by the C99 standard,
+    # or a GCC strangeness...
+    BStruct2 = new_struct_type("bar")
+    complete_struct_or_union(BStruct2, [('f', BStruct),
+                                        ('n', BInt)])
+    p = newp(new_pointer_type(BStruct2), {'n': 42})
+    assert p.n == 42
+    #
+    # more error cases
+    py.test.raises(TypeError, newp, new_pointer_type(BStruct), [100, None])
+    BArray4 = new_array_type(BIntP, 4)
+    BStruct4 = new_struct_type("test4")
+    complete_struct_or_union(BStruct4, [('a', BArray4)])   # not varsized
+    py.test.raises(TypeError, newp, new_pointer_type(BStruct4), [None])
+    py.test.raises(TypeError, newp, new_pointer_type(BStruct4), [4])
+    p = newp(new_pointer_type(BStruct4), [[10, 20, 30]])
+    assert p.a[0] == 10
+    assert p.a[1] == 20
+    assert p.a[2] == 30
+    assert p.a[3] == 0
+
+def test_struct_array_no_length_explicit_position():
+    BInt = new_primitive_type("int")
+    BIntP = new_pointer_type(BInt)
+    BArray = new_array_type(BIntP, None)
+    BStruct = new_struct_type("foo")
+    complete_struct_or_union(BStruct, [('x', BArray, -1, 0), # actually 3 items
+                                       ('y', BInt, -1, 12)])
+    p = newp(new_pointer_type(BStruct), [[10, 20], 30])
+    assert p.x[0] == 10
+    assert p.x[1] == 20
+    assert p.x[2] == 0
+    assert p.y == 30
+    p = newp(new_pointer_type(BStruct), {'x': [40], 'y': 50})
+    assert p.x[0] == 40
+    assert p.x[1] == 0
+    assert p.x[2] == 0
+    assert p.y == 50
+    p = newp(new_pointer_type(BStruct), {'y': 60})
+    assert p.x[0] == 0
+    assert p.x[1] == 0
+    assert p.x[2] == 0
+    assert p.y == 60
+    #
+    # This "should" work too, allocating a larger structure
+    # (a bit strange in this case, but useful in general)
+    plist = []
+    for i in range(20):
+        p = newp(new_pointer_type(BStruct), [[10, 20, 30, 40, 50, 60, 70]])
+        plist.append(p)
+    for i in range(20):
+        p = plist[i]
+        assert p.x[0] == 10
+        assert p.x[1] == 20
+        assert p.x[2] == 30
+        assert p.x[3] == 40 == p.y
+        assert p.x[4] == 50
+        assert p.x[5] == 60
+        assert p.x[6] == 70
+
+def test_ass_slice():
+    BChar = new_primitive_type("char")
+    BArray = new_array_type(new_pointer_type(BChar), None)
+    p = newp(BArray, b"foobar")
+    p[2:5] = [b"*", b"Z", b"T"]
+    p[1:3] = b"XY"
+    assert list(p) == [b"f", b"X", b"Y", b"Z", b"T", b"r", b"\x00"]
+    py.test.raises(TypeError, "p[1:5] = u+'XYZT'")
+    py.test.raises(TypeError, "p[1:5] = [1, 2, 3, 4]")
+    #
+    BUniChar = new_primitive_type("wchar_t")
+    BArray = new_array_type(new_pointer_type(BUniChar), None)
+    p = newp(BArray, u+"foobar")
+    p[2:5] = [u+"*", u+"Z", u+"T"]
+    p[1:3] = u+"XY"
+    assert list(p) == [u+"f", u+"X", u+"Y", u+"Z", u+"T", u+"r", u+"\x00"]
+    py.test.raises(TypeError, "p[1:5] = b'XYZT'")
+    py.test.raises(TypeError, "p[1:5] = [1, 2, 3, 4]")
+
+def test_void_p_arithmetic():
+    BVoid = new_void_type()
+    BInt = new_primitive_type("intptr_t")
+    p = cast(new_pointer_type(BVoid), 100000)
+    assert int(cast(BInt, p)) == 100000
+    assert int(cast(BInt, p + 42)) == 100042
+    assert int(cast(BInt, p - (-42))) == 100042
+    assert (p + 42) - p == 42
+    q = cast(new_pointer_type(new_primitive_type("char")), 100000)
+    py.test.raises(TypeError, "p - q")
+    py.test.raises(TypeError, "q - p")
+    py.test.raises(TypeError, "p + cast(new_primitive_type('int'), 42)")
+    py.test.raises(TypeError, "p - cast(new_primitive_type('int'), 42)")
+
+
 def test_version():
     # this test is here mostly for PyPy
-    assert __version__ == "0.7"
+    assert __version__ == "0.8"
diff --git a/pypy/module/array/interp_array.py b/pypy/module/array/interp_array.py
--- a/pypy/module/array/interp_array.py
+++ b/pypy/module/array/interp_array.py
@@ -410,7 +410,6 @@
     def descr_getslice(self, space, w_i, w_j):
         return space.getitem(self, space.newslice(w_i, w_j, space.w_None))
 
-
     def descr_setitem(self, space, w_idx, w_item):
         "x.__setitem__(i, y) <==> x[i]=y"
         if space.isinstance_w(w_idx, space.w_slice):
@@ -869,9 +868,6 @@
                     self.buffer[i] = w_item.buffer[j]
                     j += 1
 
-        # We can't look into this function until ptradd works with things (in the
-        # JIT) other than rffi.CCHARP
-        @jit.dont_look_inside
         def delitem(self, space, i, j):
             if i < 0:
                 i += self.len
@@ -907,16 +903,23 @@
                 lltype.free(oldbuffer, flavor='raw')
 
         # Add and mul methods
-
         def descr_add(self, space, w_other):
             if not isinstance(w_other, W_Array):
                 return space.w_NotImplemented
             a = mytype.w_class(space)
             a.setlen(self.len + w_other.len, overallocate=False)
-            for i in range(self.len):
-                a.buffer[i] = self.buffer[i]
-            for i in range(w_other.len):
-                a.buffer[i + self.len] = w_other.buffer[i]
+            if self.len:
+                rffi.c_memcpy(
+                    rffi.cast(rffi.VOIDP, a.buffer),
+                    rffi.cast(rffi.VOIDP, self.buffer),
+                    self.len * mytype.bytes
+                )
+            if w_other.len:
+                rffi.c_memcpy(
+                    rffi.cast(rffi.VOIDP, rffi.ptradd(a.buffer, self.len)),
+                    rffi.cast(rffi.VOIDP, w_other.buffer),
+                    w_other.len * mytype.bytes
+                )
             return a
 
         def descr_inplace_add(self, space, w_other):
@@ -925,8 +928,12 @@
             oldlen = self.len
             otherlen = w_other.len
             self.setlen(oldlen + otherlen)
-            for i in range(otherlen):
-                self.buffer[oldlen + i] = w_other.buffer[i]
+            if otherlen:
+                rffi.c_memcpy(
+                    rffi.cast(rffi.VOIDP, rffi.ptradd(self.buffer, oldlen)),
+                    rffi.cast(rffi.VOIDP, w_other.buffer),
+                    otherlen * mytype.bytes
+                )
             return self
 
         def descr_mul(self, space, w_repeat):
diff --git a/pypy/module/micronumpy/interp_numarray.py b/pypy/module/micronumpy/interp_numarray.py
--- a/pypy/module/micronumpy/interp_numarray.py
+++ b/pypy/module/micronumpy/interp_numarray.py
@@ -519,10 +519,13 @@
         # by converting nonnative byte order.
         if self.is_scalar():
             return space.wrap(0)
-        s = self.get_dtype().name
-        if not self.get_dtype().is_native():
-            s = s[1:]
-        dtype = interp_dtype.get_dtype_cache(space).dtypes_by_name[s]
+        if not self.get_dtype().is_flexible_type():
+            s = self.get_dtype().name
+            if not self.get_dtype().is_native():
+                s = s[1:]
+            dtype = interp_dtype.get_dtype_cache(space).dtypes_by_name[s]
+        else:
+            dtype = self.get_dtype()
         contig = self.implementation.astype(space, dtype)
         return contig.argsort(space, w_axis)
 
diff --git a/pypy/module/micronumpy/test/test_sorting.py b/pypy/module/micronumpy/test/test_sorting.py
--- a/pypy/module/micronumpy/test/test_sorting.py
+++ b/pypy/module/micronumpy/test/test_sorting.py
@@ -12,8 +12,7 @@
             exp = sorted(range(len(exp)), key=exp.__getitem__)
             c = a.copy()
             res = a.argsort()
-            assert (res == exp).all(), \
-                'a,res,dtype %r,%r,%r' % (a,res,dtype)
+            assert (res == exp).all(), '%r\n%r\n%r' % (a,res,exp)
             assert (a == c).all() # not modified
 
             a = arange(100, dtype=dtype)
@@ -60,11 +59,10 @@
         for dtype in ['int', 'float', 'int16', 'float32', 'uint64',
                       'i2', complex]:
             a = array([6, 4, -1, 3, 8, 3, 256+20, 100, 101], dtype=dtype)
-            b = sorted(list(a))
-            c = a.copy()
-            a.sort()
-            assert (a == b).all(), \
-                'a,orig,dtype %r,%r,%r' % (a,c,dtype)
+            exp = sorted(list(a))
+            res = a.copy()
+            res.sort()
+            assert (res == exp).all(), '%r\n%r\n%r' % (a,res,exp)
 
             a = arange(100, dtype=dtype)
             c = a.copy()
@@ -85,7 +83,6 @@
             #assert (a == b).all(), \
             #    'a,orig,dtype %r,%r,%r' % (a,c,dtype)
 
-
 # tests from numpy/tests/test_multiarray.py
     def test_sort_corner_cases(self):
         # test ordering for floats and complex containing nans. It is only
@@ -307,7 +304,6 @@
         assert (r == array([('a', 1), ('c', 3), ('b', 255), ('d', 258)],
                                  dtype=mydtype)).all()
 
-
 # tests from numpy/tests/test_regression.py
     def test_sort_bigendian(self):
         skip('not implemented yet')
@@ -325,3 +321,13 @@
         y = fromstring("\x00\x01\x00\x02", dtype="S2")
         x.sort(kind='q')
         assert (x == y).all()
+
+    def test_string_mergesort(self):
+        import numpypy as np
+        import sys
+        x = np.array(['a'] * 32)
+        if '__pypy__' in sys.builtin_module_names:
+            exc = raises(NotImplementedError, "x.argsort(kind='m')")
+            assert 'non-numeric types' in exc.value.message
+        else:
+            assert (x.argsort(kind='m') == np.arange(32)).all()
diff --git a/pypy/module/mmap/interp_mmap.py b/pypy/module/mmap/interp_mmap.py
--- a/pypy/module/mmap/interp_mmap.py
+++ b/pypy/module/mmap/interp_mmap.py
@@ -163,6 +163,8 @@
         if step == 0:  # index only
             return space.wrap(self.mmap.getitem(start))
         elif step == 1:
+            if stop - start < 0:
+                return space.wrap("")
             return space.wrap(self.mmap.getslice(start, stop - start))
         else:
             res = "".join([self.mmap.getitem(i)
diff --git a/pypy/module/mmap/test/test_mmap.py b/pypy/module/mmap/test/test_mmap.py
--- a/pypy/module/mmap/test/test_mmap.py
+++ b/pypy/module/mmap/test/test_mmap.py
@@ -525,6 +525,8 @@
         m = mmap(f.fileno(), 6)
         assert m[-3:7] == "bar"
 
+        assert m[1:0:1] == ""
+
         f.close()
 
     def test_sequence_type(self):
diff --git a/pypy/module/posix/__init__.py b/pypy/module/posix/__init__.py
--- a/pypy/module/posix/__init__.py
+++ b/pypy/module/posix/__init__.py
@@ -131,6 +131,11 @@
     if hasattr(os, 'fpathconf'):
         interpleveldefs['fpathconf'] = 'interp_posix.fpathconf'
         interpleveldefs['pathconf_names'] = 'space.wrap(os.pathconf_names)'
+    if hasattr(os, 'pathconf'):
+        interpleveldefs['pathconf'] = 'interp_posix.pathconf'
+    if hasattr(os, 'confstr'):
+        interpleveldefs['confstr'] = 'interp_posix.confstr'
+        interpleveldefs['confstr_names'] = 'space.wrap(os.confstr_names)'
     if hasattr(os, 'ttyname'):
         interpleveldefs['ttyname'] = 'interp_posix.ttyname'
     if hasattr(os, 'getloadavg'):
@@ -155,7 +160,9 @@
     for name in ['setsid', 'getuid', 'geteuid', 'getgid', 'getegid', 'setuid',
                  'seteuid', 'setgid', 'setegid', 'getgroups', 'getpgrp',
                  'setpgrp', 'getppid', 'getpgid', 'setpgid', 'setreuid',
-                 'setregid', 'getsid', 'setsid', 'fstatvfs', 'statvfs']:
+                 'setregid', 'getsid', 'setsid', 'fstatvfs', 'statvfs',
+                 'setgroups', 'initgroups', 'tcgetpgrp', 'tcsetpgrp',
+                 'getresuid', 'getresgid', 'setresuid', 'setresgid']:
         if hasattr(os, name):
             interpleveldefs[name] = 'interp_posix.%s' % (name,)
     # not visible via os, inconsistency in nt:
diff --git a/pypy/module/posix/interp_posix.py b/pypy/module/posix/interp_posix.py
--- a/pypy/module/posix/interp_posix.py
+++ b/pypy/module/posix/interp_posix.py
@@ -987,7 +987,39 @@
 
     Return list of supplemental group IDs for the process.
     """
-    return space.newlist([space.wrap(e) for e in os.getgroups()])
+    try:
+        list = os.getgroups()
+    except OSError, e:
+        raise wrap_oserror(space, e)
+    return space.newlist([space.wrap(e) for e in list])
+
+def setgroups(space, w_list):
+    """ setgroups(list)
+
+    Set the groups of the current process to list.
+    """
+    list = []
+    for w_gid in space.unpackiterable(w_list):
+        gid = space.int_w(w_gid)
+        check_uid_range(space, gid)
+        list.append(gid)
+    try:
+        os.setgroups(list[:])
+    except OSError, e:
+        raise wrap_oserror(space, e)
+
+ at unwrap_spec(username=str, gid=c_gid_t)
+def initgroups(space, username, gid):
+    """ initgroups(username, gid) -> None
+    
+    Call the system initgroups() to initialize the group access list with all of
+    the groups of which the specified username is a member, plus the specified
+    group id.
+    """
+    try:
+        os.initgroups(username, gid)
+    except OSError, e:
+        raise wrap_oserror(space, e)
 
 def getpgrp(space):
     """ getpgrp() -> pgrp
@@ -1089,6 +1121,77 @@
         raise wrap_oserror(space, e)
     return space.w_None
 
+ at unwrap_spec(fd=c_int)
+def tcgetpgrp(space, fd):
+    """ tcgetpgrp(fd) -> pgid
+
+    Return the process group associated with the terminal given by a fd.
+    """
+    try:
+        pgid = os.tcgetpgrp(fd)
+    except OSError, e:
+        raise wrap_oserror(space, e)
+    return space.wrap(pgid)
+
+ at unwrap_spec(fd=c_int, pgid=c_gid_t)
+def tcsetpgrp(space, fd, pgid):
+    """ tcsetpgrp(fd, pgid)
+
+    Set the process group associated with the terminal given by a fd.
+    """
+    try:
+        os.tcsetpgrp(fd, pgid)
+    except OSError, e:
+        raise wrap_oserror(space, e)
+
+def getresuid(space):
+    """ getresuid() -> (ruid, euid, suid)
+
+    Get tuple of the current process's real, effective, and saved user ids.
+    """
+    try:
+        (ruid, euid, suid) = os.getresuid()
+    except OSError, e:
+        raise wrap_oserror(space, e)
+    return space.newtuple([space.wrap(ruid),
+                           space.wrap(euid),
+                           space.wrap(suid)])
+
+def getresgid(space):
+    """ getresgid() -> (rgid, egid, sgid)
+
+    Get tuple of the current process's real, effective, and saved group ids.
+    """
+    try:
+        (rgid, egid, sgid) = os.getresgid()
+    except OSError, e:
+        raise wrap_oserror(space, e)
+    return space.newtuple([space.wrap(rgid),
+                           space.wrap(egid),
+                           space.wrap(sgid)])
+
+ at unwrap_spec(ruid=c_uid_t, euid=c_uid_t, suid=c_uid_t)
+def setresuid(space, ruid, euid, suid):
+    """ setresuid(ruid, euid, suid)
+
+    Set the current process's real, effective, and saved user ids.
+    """
+    try:
+        os.setresuid(ruid, euid, suid)
+    except OSError, e:
+        raise wrap_oserror(space, e)
+
+ at unwrap_spec(rgid=c_gid_t, egid=c_gid_t, sgid=c_gid_t)
+def setresgid(space, rgid, egid, sgid):
+    """ setresgid(rgid, egid, sgid)
+    
+    Set the current process's real, effective, and saved group ids.
+    """
+    try:
+        os.setresgid(rgid, egid, sgid)
+    except OSError, e:
+        raise wrap_oserror(space, e)
+
 def declare_new_w_star(name):
     if name in RegisterOs.w_star_returning_int:
         @unwrap_spec(status=c_int)
@@ -1130,15 +1233,37 @@
 
 def sysconf(space, w_name):
     num = confname_w(space, w_name, os.sysconf_names)
-    return space.wrap(os.sysconf(num))
+    try:
+        res = os.sysconf(num)
+    except OSError, e:
+        raise wrap_oserror(space, e)
+    return space.wrap(res)
 
 @unwrap_spec(fd=c_int)
 def fpathconf(space, fd, w_name):
     num = confname_w(space, w_name, os.pathconf_names)
     try:
-        return space.wrap(os.fpathconf(fd, num))
+        res = os.fpathconf(fd, num)
     except OSError, e:
         raise wrap_oserror(space, e)
+    return space.wrap(res)
+
+ at unwrap_spec(path='str0')
+def pathconf(space, path, w_name):
+    num = confname_w(space, w_name, os.pathconf_names)
+    try:
+        res = os.pathconf(path, num)
+    except OSError, e:
+        raise wrap_oserror(space, e)
+    return space.wrap(res)
+
+def confstr(space, w_name):
+    num = confname_w(space, w_name, os.confstr_names)
+    try:
+        res = os.confstr(num)
+    except OSError, e:
+        raise wrap_oserror(space, e)
+    return space.wrap(res)
 
 @unwrap_spec(path='str0', uid=c_uid_t, gid=c_gid_t)
 def chown(space, path, uid, gid):
diff --git a/pypy/module/posix/test/test_posix2.py b/pypy/module/posix/test/test_posix2.py
--- a/pypy/module/posix/test/test_posix2.py
+++ b/pypy/module/posix/test/test_posix2.py
@@ -78,6 +78,11 @@
             cls.w_sysconf_name = space.wrap(sysconf_name)
             cls.w_sysconf_value = space.wrap(os.sysconf_names[sysconf_name])
             cls.w_sysconf_result = space.wrap(os.sysconf(sysconf_name))
+        if hasattr(os, 'confstr'):
+            confstr_name = os.confstr_names.keys()[0]
+            cls.w_confstr_name = space.wrap(confstr_name)
+            cls.w_confstr_value = space.wrap(os.confstr_names[confstr_name])
+            cls.w_confstr_result = space.wrap(os.confstr(confstr_name))
         cls.w_SIGABRT = space.wrap(signal.SIGABRT)
         cls.w_python = space.wrap(sys.executable)
         if hasattr(os, 'major'):
@@ -616,6 +621,30 @@
             os = self.posix
             assert os.getgroups() == self.getgroups
 
+    if hasattr(os, 'setgroups'):
+        def test_os_setgroups(self):
+            os = self.posix
+            raises(TypeError, os.setgroups, [2, 5, "hello"])
+            try:
+                os.setgroups(os.getgroups())
+            except OSError:
+                pass
+
+    if hasattr(os, 'initgroups'):
+        def test_os_initgroups(self):
+            os = self.posix
+            raises(OSError, os.initgroups, "crW2hTQC", 100)
+
+    if hasattr(os, 'tcgetpgrp'):
+        def test_os_tcgetpgrp(self):
+            os = self.posix
+            raises(OSError, os.tcgetpgrp, 9999)
+
+    if hasattr(os, 'tcsetpgrp'):
+        def test_os_tcsetpgrp(self):
+            os = self.posix
+            raises(OSError, os.tcsetpgrp, 9999, 1)
+
     if hasattr(os, 'getpgid'):
         def test_os_getpgid(self):
             os = self.posix
@@ -634,6 +663,30 @@
             assert os.getsid(0) == self.getsid0
             raises(OSError, os.getsid, -100000)
 
+    if hasattr(os, 'getresuid'):
+        def test_os_getresuid(self):
+            os = self.posix
+            res = os.getresuid()
+            assert len(res) == 3
+
+    if hasattr(os, 'getresgid'):
+        def test_os_getresgid(self):
+            os = self.posix
+            res = os.getresgid()
+            assert len(res) == 3
+
+    if hasattr(os, 'setresuid'):
+        def test_os_setresuid(self):
+            os = self.posix
+            a, b, c = os.getresuid()
+            os.setresuid(a, b, c)
+
+    if hasattr(os, 'setresgid'):
+        def test_os_setresgid(self):
+            os = self.posix
+            a, b, c = os.getresgid()
+            os.setresgid(a, b, c)
+
     if hasattr(os, 'sysconf'):
         def test_os_sysconf(self):
             os = self.posix
@@ -652,6 +705,25 @@
             raises(OSError, os.fpathconf, -1, "PC_PIPE_BUF")
             raises(ValueError, os.fpathconf, 1, "##")
 
+    if hasattr(os, 'pathconf'):
+        def test_os_pathconf(self):
+            os = self.posix
+            assert os.pathconf("/tmp", "PC_NAME_MAX") >= 31
+            # Linux: the following gets 'No such file or directory'
+            raises(OSError, os.pathconf, "", "PC_PIPE_BUF")
+            raises(ValueError, os.pathconf, "/tmp", "##")
+
+    if hasattr(os, 'confstr'):
+        def test_os_confstr(self):
+            os = self.posix
+            assert os.confstr(self.confstr_value) == self.confstr_result
+            assert os.confstr(self.confstr_name) == self.confstr_result
+            assert os.confstr_names[self.confstr_name] == self.confstr_value
+
+        def test_os_confstr_error(self):
+            os = self.posix
+            raises(ValueError, os.confstr, "!@#$%!#$!@#")
+
     if hasattr(os, 'wait'):
         def test_os_wait(self):
             os = self.posix
diff --git a/pypy/module/pypyjit/test_pypy_c/test_ffi.py b/pypy/module/pypyjit/test_pypy_c/test_ffi.py
--- a/pypy/module/pypyjit/test_pypy_c/test_ffi.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_ffi.py
@@ -228,7 +228,7 @@
             except ImportError:
                 sys.stderr.write('SKIP: cannot import cffi\n')
                 return 0
-                
+
             ffi = cffi.FFI()
 
             ffi.cdef("""
@@ -301,5 +301,30 @@
             f(1)
         #
         libm_name = get_libm_name(sys.platform)
-        log = self.run(main, [libm_name])
+        self.run(main, [libm_name])
         # assert did not crash
+
+    def test_cffi_init_struct_with_list(self):
+        def main(n):
+            import sys
+            try:
+                import cffi
+            except ImportError:
+                sys.stderr.write('SKIP: cannot import cffi\n')
+                return 0
+
+            ffi = cffi.FFI()
+            ffi.cdef("""
+            struct s {
+                int x;
+                int y;
+                int z;
+            };
+            """)
+
+            for i in xrange(n):
+                ffi.new("struct s *", [i, i, i])
+
+        log = self.run(main, [300])
+        loop, = log.loops_by_filename(self.filepath)
+        assert False, "XXX: fill this in"
diff --git a/pypy/objspace/std/typeobject.py b/pypy/objspace/std/typeobject.py
--- a/pypy/objspace/std/typeobject.py
+++ b/pypy/objspace/std/typeobject.py
@@ -568,8 +568,6 @@
 def _create_new_type(space, w_typetype, w_name, w_bases, w_dict):
     # this is in its own function because we want the special case 'type(x)'
     # above to be seen by the jit.
-    from pypy.objspace.std.typeobject import W_TypeObject
-
     if w_bases is None or w_dict is None:
         raise OperationError(space.w_TypeError, space.wrap("type() takes 1 or 3 arguments"))
 
@@ -611,7 +609,6 @@
     return w_type
 
 def _precheck_for_new(space, w_type):
-    from pypy.objspace.std.typeobject import W_TypeObject
     if not isinstance(w_type, W_TypeObject):
         raise operationerrfmt(space.w_TypeError, "X is not a type object (%T)",
                               w_type)
@@ -620,7 +617,6 @@
 # ____________________________________________________________
 
 def _check(space, w_type, w_msg=None):
-    from pypy.objspace.std.typeobject import W_TypeObject
     if not isinstance(w_type, W_TypeObject):
         if w_msg is None:
             w_msg = space.wrap("descriptor is for 'type'")
@@ -653,7 +649,6 @@
     return space.newtuple(w_type.bases_w)
 
 def mro_subclasses(space, w_type, temp):
-    from pypy.objspace.std.typeobject import W_TypeObject, compute_mro
     temp.append((w_type, w_type.mro_w))
     compute_mro(w_type)
     for w_sc in w_type.get_subclasses():
@@ -662,9 +657,6 @@
 
 def descr_set__bases__(space, w_type, w_value):
     # this assumes all app-level type objects are W_TypeObject
-    from pypy.objspace.std.typeobject import (W_TypeObject, get_parent_layout,
-        check_and_find_best_base, is_mro_purely_of_types)
-
     w_type = _check(space, w_type)
     if not w_type.is_heaptype():
         raise operationerrfmt(space.w_TypeError,
@@ -728,7 +720,6 @@
     assert w_type.w_same_layout_as is get_parent_layout(w_type)  # invariant
 
 def descr__base(space, w_type):
-    from pypy.objspace.std.typeobject import find_best_base
     w_type = _check(space, w_type)
     return find_best_base(space, w_type.bases_w)
 
diff --git a/rpython/jit/backend/x86/callbuilder.py b/rpython/jit/backend/x86/callbuilder.py
--- a/rpython/jit/backend/x86/callbuilder.py
+++ b/rpython/jit/backend/x86/callbuilder.py
@@ -304,8 +304,12 @@
         except IndexError:
             return None
         if hint in self.DONT_MOVE_GPR:
-            self.ARGUMENTS_GPR[i] = hint
-            res = hint
+            for j in range(i):
+                if hint is self.ARGUMENTS_GPR[j]:
+                    break
+            else:
+                self.ARGUMENTS_GPR[i] = hint
+                res = hint
         return res
 
     def _unused_xmm(self):
diff --git a/rpython/jit/backend/x86/test/test_callbuilder.py b/rpython/jit/backend/x86/test/test_callbuilder.py
new file mode 100644
--- /dev/null
+++ b/rpython/jit/backend/x86/test/test_callbuilder.py
@@ -0,0 +1,33 @@
+from rpython.jit.backend.x86 import callbuilder
+from rpython.jit.backend.x86.regloc import esi, edi, ebx, ecx, ImmedLoc
+
+
+class FakeAssembler:
+    mc = None
+    class _regalloc:
+        class rm:
+            free_regs = [ebx]
+
+    def __init__(self):
+        self._log = []
+
+    def _is_asmgcc(self):
+        return False
+
+    def regalloc_mov(self, src, dst):
+        self._log.append(('mov', src, dst))
+
+
+def test_base_case():
+    asm = FakeAssembler()
+    cb = callbuilder.CallBuilder64(asm, ImmedLoc(12345), [ebx, ebx])
+    cb.prepare_arguments()
+    assert asm._log == [('mov', ebx, edi),
+                        ('mov', ebx, esi)]
+
+def test_bug_call_release_gil():
+    asm = FakeAssembler()
+    cb = callbuilder.CallBuilder64(asm, ImmedLoc(12345), [ebx, ebx])
+    cb.select_call_release_gil_mode()
+    cb.prepare_arguments()
+    assert asm._log == [('mov', ebx, ecx)]
diff --git a/rpython/jit/codewriter/jtransform.py b/rpython/jit/codewriter/jtransform.py
--- a/rpython/jit/codewriter/jtransform.py
+++ b/rpython/jit/codewriter/jtransform.py
@@ -1162,10 +1162,19 @@
                                   v_result)
 
     def rewrite_op_direct_ptradd(self, op):
-        # xxx otherwise, not implemented:
-        assert op.args[0].concretetype == rffi.CCHARP
+        v_shift = op.args[1]
+        assert v_shift.concretetype == lltype.Signed
+        ops = []
         #
-        return SpaceOperation('int_add', [op.args[0], op.args[1]], op.result)
+        if op.args[0].concretetype != rffi.CCHARP:
+            v_prod = varoftype(lltype.Signed)
+            by = llmemory.sizeof(op.args[0].concretetype.TO.OF)
+            c_by = Constant(by, lltype.Signed)
+            ops.append(SpaceOperation('int_mul', [v_shift, c_by], v_prod))
+            v_shift = v_prod
+        #
+        ops.append(SpaceOperation('int_add', [op.args[0], v_shift], op.result))
+        return ops
 
     # ----------
     # Long longs, for 32-bit only.  Supported operations are left unmodified,
diff --git a/rpython/jit/codewriter/test/test_flatten.py b/rpython/jit/codewriter/test/test_flatten.py
--- a/rpython/jit/codewriter/test/test_flatten.py
+++ b/rpython/jit/codewriter/test/test_flatten.py
@@ -993,6 +993,16 @@
             int_return %i2
         """, transform=True)
 
+    def test_direct_ptradd_2(self):
+        def f(p, n):
+            return lltype.direct_ptradd(p, n + 2)
+        self.encoding_test(f, [lltype.nullptr(rffi.SHORTP.TO), 123], """
+            int_add %i1, $2 -> %i2
+            int_mul %i2, $<ItemOffset <SHORT> 1> -> %i3
+            int_add %i0, %i3 -> %i4
+            int_return %i4
+        """, transform=True)
+
     def test_convert_float_bytes(self):
         from rpython.rlib.longlong2float import float2longlong, longlong2float
         def f(x):
diff --git a/rpython/jit/metainterp/compile.py b/rpython/jit/metainterp/compile.py
--- a/rpython/jit/metainterp/compile.py
+++ b/rpython/jit/metainterp/compile.py
@@ -514,7 +514,8 @@
         #
         if metainterp_sd.warmrunnerdesc is not None:   # for tests
             jitcounter = metainterp_sd.warmrunnerdesc.jitcounter
-            self.status = jitcounter.fetch_next_index() << self.ST_SHIFT
+            index = jitcounter.in_second_half(jitcounter.fetch_next_index())
+            self.status = index << self.ST_SHIFT
 
     def make_a_counter_per_value(self, guard_value_op):
         assert guard_value_op.getopnum() == rop.GUARD_VALUE
@@ -598,7 +599,7 @@
 
             hash = (current_object_addr_as_int(self) * 777767777 +
                     intval * 1442968193)
-            index = jitcounter.get_index(hash)
+            index = jitcounter.in_second_half(jitcounter.get_index(hash))
         #
         increment = jitdriver_sd.warmstate.increment_trace_eagerness
         return jitcounter.tick(index, increment)
diff --git a/rpython/jit/metainterp/counter.py b/rpython/jit/metainterp/counter.py
--- a/rpython/jit/metainterp/counter.py
+++ b/rpython/jit/metainterp/counter.py
@@ -18,11 +18,20 @@
         while (UINT32MAX >> self.shift) != size - 1:
             self.shift += 1
             assert self.shift < 999, "size is not a power of two <= 2**31"
-        self.timetable = lltype.malloc(rffi.CArray(rffi.FLOAT), size,
+        #
+        # The table of timings.  The first half is used for starting the
+        # compilation of new loops.  The second half is used for turning
+        # failing guards into bridges.  The two halves are split to avoid
+        # too much interference.
+        self.timetablesize = size * 2
+        self.timetable = lltype.malloc(rffi.CArray(rffi.FLOAT),
+                                       self.timetablesize,
                                        flavor='raw', zero=True,
                                        track_allocation=False)
+        self._nextindex = r_uint(0)
+        #
+        # The table of JitCell entries, recording already-compiled loops
         self.celltable = [None] * size
-        self._nextindex = r_uint(0)
         #
         if translator is not None:
             class Glob:
@@ -61,6 +70,10 @@
         self._nextindex = (result + 1) & self.get_index(-1)
         return result
 
+    def in_second_half(self, index):
+        assert index < r_uint(self.size)
+        return self.size + index
+
     def tick(self, index, increment):
         counter = float(self.timetable[index]) + increment
         if counter < 1.0:
@@ -112,7 +125,7 @@
         # important in corner cases where we would suddenly compile more
         # than one loop because all counters reach the bound at the same
         # time, but where compiling all but the first one is pointless.
-        size = self.size
+        size = self.timetablesize
         pypy__decay_jit_counters(self.timetable, self.decay_by_mult, size)
 
 
@@ -152,6 +165,10 @@
         "NOT_RPYTHON"
         pass
 
+    def in_second_half(self, index):
+        "NOT_RPYTHON"
+        return index + 12345
+
     def _clear_all(self):
         self.timetable.clear()
         self.celltable.clear()
diff --git a/rpython/jit/metainterp/heapcache.py b/rpython/jit/metainterp/heapcache.py
--- a/rpython/jit/metainterp/heapcache.py
+++ b/rpython/jit/metainterp/heapcache.py
@@ -96,8 +96,13 @@
                 idx += 1
 
     def _escape(self, box):
-        if box in self.new_boxes:
-            self.new_boxes[box] = False
+        try:
+            unescaped = self.new_boxes[box]
+        except KeyError:
+            pass
+        else:
+            if unescaped:
+                self.new_boxes[box] = False
         try:
             deps = self.dependencies.pop(box)
         except KeyError:
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py b/rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py
--- a/rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py
@@ -5125,18 +5125,39 @@
     def test_str_copy_virtual_src_concrete_dst(self):
         ops = """
         [p0]
-        p1 = newstr(1)
+        p1 = newstr(2)
         strsetitem(p1, 0, 101)
-        copystrcontent(p1, p0, 0, 0, 1)
+        strsetitem(p1, 1, 102)
+        copystrcontent(p1, p0, 0, 0, 2)
         finish(p0)
         """
         expected = """
         [p0]
         strsetitem(p0, 0, 101)
+        strsetitem(p0, 1, 102)
         finish(p0)
         """
         self.optimize_strunicode_loop(ops, expected)
 
+    def test_str_copy_bug1(self):
+        ops = """
+        [i0]
+        p1 = newstr(1)
+        strsetitem(p1, 0, i0)
+        p2 = newstr(1)
+        escape(p2)
+        copystrcontent(p1, p2, 0, 0, 1)
+        finish()
+        """
+        expected = """
+        [i0]
+        p2 = newstr(1)
+        escape(p2)
+        strsetitem(p2, 0, i0)
+        finish()
+        """
+        self.optimize_strunicode_loop(ops, expected)
+
     def test_call_pure_vstring_const(self):
         py.test.skip("implement me")
         ops = """
diff --git a/rpython/jit/metainterp/optimizeopt/vstring.py b/rpython/jit/metainterp/optimizeopt/vstring.py
--- a/rpython/jit/metainterp/optimizeopt/vstring.py
+++ b/rpython/jit/metainterp/optimizeopt/vstring.py
@@ -154,6 +154,7 @@
         return self._chars[index]     # may return None!
 
     def setitem(self, index, charvalue):
+        assert self.is_virtual()
         assert isinstance(charvalue, optimizer.OptValue)
         assert self._chars[index] is None, (
             "setitem() on an already-initialized location")
@@ -512,29 +513,28 @@
         srcstart = self.getvalue(op.getarg(2))
         dststart = self.getvalue(op.getarg(3))
         length = self.getvalue(op.getarg(4))
+        dst_virtual = (isinstance(dst, VStringPlainValue) and dst.is_virtual())
 
         if length.is_constant() and length.box.getint() == 0:
             return
         elif ((src.is_virtual() or src.is_constant()) and
               srcstart.is_constant() and dststart.is_constant() and
-              length.is_constant()):
+              length.is_constant() and
+              (length.force_box(self).getint() < 20 or (src.is_virtual() and dst_virtual))):
             src_start = srcstart.force_box(self).getint()
             dst_start = dststart.force_box(self).getint()
-            # 'length' must be <= MAX_CONST_LEN here, because 'dst' is a
-            # VStringPlainValue, which is limited to MAX_CONST_LEN.
             actual_length = length.force_box(self).getint()
-            assert actual_length <= MAX_CONST_LEN
             for index in range(actual_length):
                 vresult = self.strgetitem(src, optimizer.ConstantValue(ConstInt(index + src_start)), mode)
-                if isinstance(dst, VStringPlainValue):
+                if dst_virtual:
                     dst.setitem(index + dst_start, vresult)
                 else:
-                    op = ResOperation(mode.STRSETITEM, [
-                        op.getarg(1),
+                    new_op = ResOperation(mode.STRSETITEM, [
+                        dst.force_box(self),
                         ConstInt(index + dst_start),
                         vresult.force_box(self),
                     ], None)
-                    self.emit_operation(op)
+                    self.emit_operation(new_op)
         else:
             copy_str_content(self,
                 src.force_box(self),
diff --git a/rpython/rlib/rstring.py b/rpython/rlib/rstring.py
--- a/rpython/rlib/rstring.py
+++ b/rpython/rlib/rstring.py
@@ -371,6 +371,7 @@
         self._grow(times)
 
     def append_charpsize(self, s, size):
+        assert size >= 0
         l = []
         for i in xrange(size):
             l.append(s[i])
diff --git a/rpython/rtyper/lltypesystem/rbytearray.py b/rpython/rtyper/lltypesystem/rbytearray.py
--- a/rpython/rtyper/lltypesystem/rbytearray.py
+++ b/rpython/rtyper/lltypesystem/rbytearray.py
@@ -8,10 +8,10 @@
 def mallocbytearray(size):
     return lltype.malloc(BYTEARRAY, size)
 
-_, copy_bytearray_contents = rstr._new_copy_contents_fun(BYTEARRAY, BYTEARRAY,
+_, _, copy_bytearray_contents = rstr._new_copy_contents_fun(BYTEARRAY, BYTEARRAY,
                                                          lltype.Char,
                                                          'bytearray')
-_, copy_bytearray_contents_from_str = rstr._new_copy_contents_fun(rstr.STR,
+_, _, copy_bytearray_contents_from_str = rstr._new_copy_contents_fun(rstr.STR,
                                                                   BYTEARRAY,
                                                                   lltype.Char,
                                                                   'bytearray_from_str')
diff --git a/rpython/rtyper/module/ll_os.py b/rpython/rtyper/module/ll_os.py
--- a/rpython/rtyper/module/ll_os.py
+++ b/rpython/rtyper/module/ll_os.py
@@ -129,10 +129,6 @@
                            ('tms_cutime', rffi.INT),
                            ('tms_cstime', rffi.INT)])
 
-        GID_T = platform.SimpleType('gid_t', rffi.INT)
-        #TODO right now is used only in getgroups, may need to update other
-        #functions like setgid
-
     # For now we require off_t to be the same size as LONGLONG, which is the
     # interface required by callers of functions that thake an argument of type
     # off_t
@@ -655,6 +651,46 @@
         return extdef([int, int], int, "ll_os.ll_fpathconf",
                       llimpl=fpathconf_llimpl)
 
+    @registering_if(os, 'pathconf')
+    def register_os_pathconf(self):
+        c_pathconf = self.llexternal('pathconf',
+                                     [rffi.CCHARP, rffi.INT], rffi.LONG)
+
+        def pathconf_llimpl(path, i):
+            rposix.set_errno(0)
+            res = c_pathconf(path, i)
+            if res == -1:
+                errno = rposix.get_errno()
+                if errno != 0:
+                    raise OSError(errno, "pathconf failed")
+            return res
+        return extdef([str0, int], int, "ll_os.ll_pathconf",
+                      llimpl=pathconf_llimpl)
+
+    @registering_if(os, 'confstr')
+    def register_os_confstr(self):
+        c_confstr = self.llexternal('confstr', [rffi.INT, rffi.CCHARP,
+                                                rffi.SIZE_T], rffi.SIZE_T)
+
+        def confstr_llimpl(i):
+            rposix.set_errno(0)
+            n = c_confstr(i, lltype.nullptr(rffi.CCHARP.TO), 0)
+            n = rffi.cast(lltype.Signed, n)
+            if n > 0:
+                buf = lltype.malloc(rffi.CCHARP.TO, n, flavor='raw')
+                try:
+                    c_confstr(i, buf, n)
+                    return rffi.charp2strn(buf, n)
+                finally:
+                    lltype.free(buf, flavor='raw')
+            else:
+                errno = rposix.get_errno()
+                if errno != 0:
+                    raise OSError(errno, "confstr failed")
+                return None
+        return extdef([int], SomeString(can_be_None=True),
+                      "ll_os.ll_confstr", llimpl=confstr_llimpl)
+
     @registering_if(os, 'getuid')
     def register_os_getuid(self):
         return self.extdef_for_os_function_returning_int('getuid')
@@ -693,7 +729,7 @@
 
     @registering_if(os, 'getgroups')
     def register_os_getgroups(self):
-        GP = rffi.CArrayPtr(self.GID_T)
+        GP = rffi.CArrayPtr(rffi.PID_T)
         c_getgroups = self.llexternal('getgroups', [rffi.INT, GP], rffi.INT)
 
         def getgroups_llimpl():
@@ -702,16 +738,50 @@
                 groups = lltype.malloc(GP.TO, n, flavor='raw')
                 try:
                     n = c_getgroups(n, groups)
-                    result = [groups[i] for i in range(n)]
+                    result = [rffi.cast(lltype.Signed, groups[i])
+                              for i in range(n)]
                 finally:
                     lltype.free(groups, flavor='raw')
                 if n >= 0:
                     return result
             raise OSError(rposix.get_errno(), "os_getgroups failed")
 
-        return extdef([], [self.GID_T], llimpl=getgroups_llimpl,
+        return extdef([], [int], llimpl=getgroups_llimpl,
                       export_name="ll_os.ll_getgroups")
 
+    @registering_if(os, 'setgroups')
+    def register_os_setgroups(self):
+        GP = rffi.CArrayPtr(rffi.PID_T)
+        c_setgroups = self.llexternal('setgroups', [rffi.SIZE_T, GP], rffi.INT)
+
+        def setgroups_llimpl(list):
+            n = len(list)
+            groups = lltype.malloc(GP.TO, n, flavor='raw')
+            try:
+                for i in range(n):
+                    groups[i] = rffi.cast(rffi.PID_T, list[i])
+                n = c_setgroups(rffi.cast(rffi.SIZE_T, n), groups)
+            finally:
+                lltype.free(groups, flavor='raw')
+            if n != 0:
+                raise OSError(rposix.get_errno(), "os_setgroups failed")
+
+        return extdef([[int]], None, llimpl=setgroups_llimpl,
+                      export_name="ll_os.ll_setgroups")
+
+    @registering_if(os, 'initgroups')
+    def register_os_initgroups(self):
+        c_initgroups = self.llexternal('initgroups',
+                                       [rffi.CCHARP, rffi.PID_T], rffi.INT)
+
+        def initgroups_llimpl(user, group):
+            n = c_initgroups(user, rffi.cast(rffi.PID_T, group))
+            if n != 0:
+                raise OSError(rposix.get_errno(), "os_initgroups failed")
+
+        return extdef([str, int], None, llimpl=initgroups_llimpl,
+                      export_name="ll_os.ll_initgroups")
+
     @registering_if(os, 'getpgrp')
     def register_os_getpgrp(self):
         name = 'getpgrp'
@@ -747,6 +817,35 @@
         else:
             return self.extdef_for_os_function_accepting_0int(name)
 
+    @registering_if(os, 'tcgetpgrp')
+    def register_os_tcgetpgrp(self):
+        c_tcgetpgrp = self.llexternal('tcgetpgrp', [rffi.INT], rffi.PID_T)
+
+        def c_tcgetpgrp_llimpl(fd):
+            res = c_tcgetpgrp(rffi.cast(rffi.INT, fd))
+            res = rffi.cast(lltype.Signed, res)
+            if res == -1:
+                raise OSError(rposix.get_errno(), "tcgetpgrp failed")
+            return res
+
+        return extdef([int], int, llimpl=c_tcgetpgrp_llimpl,
+                      export_name='ll_os.ll_os_tcgetpgrp')
+
+    @registering_if(os, 'tcsetpgrp')
+    def register_os_tcsetpgrp(self):
+        c_tcsetpgrp = self.llexternal('tcsetpgrp', [rffi.INT, rffi.PID_T],
+                                      rffi.INT)
+
+        def c_tcsetpgrp_llimpl(fd, pgrp):
+            res = c_tcsetpgrp(rffi.cast(rffi.INT, fd),
+                              rffi.cast(rffi.PID_T, pgrp))
+            res = rffi.cast(lltype.Signed, res)
+            if res == -1:
+                raise OSError(rposix.get_errno(), "tcsetpgrp failed")
+
+        return extdef([int, int], None, llimpl=c_tcsetpgrp_llimpl,
+                      export_name='ll_os.ll_os_tcsetpgrp')
+
     @registering_if(os, 'getppid')
     def register_os_getppid(self):
         return self.extdef_for_os_function_returning_int('getppid')
@@ -775,6 +874,76 @@
     def register_os_setsid(self):
         return self.extdef_for_os_function_returning_int('setsid')
 
+    @registering_if(os, 'getresuid')
+    def register_os_getresuid(self):
+        c_getresuid = self.llexternal('getresuid', [rffi.INTP] * 3, rffi.INT)
+
+        def c_getresuid_llimpl():
+            out = lltype.malloc(rffi.INTP.TO, 3, flavor='raw')
+            try:
+                res = c_getresuid(rffi.ptradd(out, 0),
+                                  rffi.ptradd(out, 1),
+                                  rffi.ptradd(out, 2))
+                res = rffi.cast(lltype.Signed, res)
+                if res == -1:
+                    raise OSError(rposix.get_errno(), "getresuid failed")
+                return (rffi.cast(lltype.Signed, out[0]),
+                        rffi.cast(lltype.Signed, out[1]),
+                        rffi.cast(lltype.Signed, out[2]))
+            finally:
+                lltype.free(out, flavor='raw')
+
+        return extdef([], (int, int, int), llimpl=c_getresuid_llimpl,
+                      export_name='ll_os.ll_os_getresuid')
+
+    @registering_if(os, 'getresgid')
+    def register_os_getresgid(self):
+        c_getresgid = self.llexternal('getresgid', [rffi.INTP] * 3, rffi.INT)
+
+        def c_getresgid_llimpl():
+            out = lltype.malloc(rffi.INTP.TO, 3, flavor='raw')
+            try:
+                res = c_getresgid(rffi.ptradd(out, 0),
+                                  rffi.ptradd(out, 1),
+                                  rffi.ptradd(out, 2))
+                res = rffi.cast(lltype.Signed, res)
+                if res == -1:
+                    raise OSError(rposix.get_errno(), "getresgid failed")
+                return (rffi.cast(lltype.Signed, out[0]),
+                        rffi.cast(lltype.Signed, out[1]),
+                        rffi.cast(lltype.Signed, out[2]))
+            finally:
+                lltype.free(out, flavor='raw')
+
+        return extdef([], (int, int, int), llimpl=c_getresgid_llimpl,
+                      export_name='ll_os.ll_os_getresgid')
+
+    @registering_if(os, 'setresuid')
+    def register_os_setresuid(self):
+        c_setresuid = self.llexternal('setresuid', [rffi.INT] * 3, rffi.INT)
+
+        def c_setresuid_llimpl(ruid, euid, suid):
+            res = c_setresuid(ruid, euid, suid)
+            res = rffi.cast(lltype.Signed, res)
+            if res == -1:
+                raise OSError(rposix.get_errno(), "setresuid failed")
+
+        return extdef([int, int, int], None, llimpl=c_setresuid_llimpl,
+                      export_name='ll_os.ll_os_setresuid')
+
+    @registering_if(os, 'setresgid')
+    def register_os_setresgid(self):
+        c_setresgid = self.llexternal('setresgid', [rffi.INT] * 3, rffi.INT)
+
+        def c_setresgid_llimpl(rgid, egid, sgid):
+            res = c_setresgid(rgid, egid, sgid)
+            res = rffi.cast(lltype.Signed, res)
+            if res == -1:
+                raise OSError(rposix.get_errno(), "setresgid failed")
+
+        return extdef([int, int, int], None, llimpl=c_setresgid_llimpl,
+                      export_name='ll_os.ll_os_setresgid')
+
     @registering_str_unicode(os.open)
     def register_os_open(self, traits):
         os_open = self.llexternal(traits.posix_function_name('open'),
diff --git a/rpython/rtyper/module/test/test_posix.py b/rpython/rtyper/module/test/test_posix.py
--- a/rpython/rtyper/module/test/test_posix.py
+++ b/rpython/rtyper/module/test/test_posix.py
@@ -1,5 +1,6 @@
 import py
 from rpython.rtyper.test.tool import BaseRtypingTest
+from rpython.rtyper.annlowlevel import hlstr
 from rpython.tool.udir import udir
 from rpython.rlib.rarithmetic import is_valid_int
 
@@ -176,6 +177,27 @@
                 return os.sysconf(i)
             assert self.interpret(f, [13]) == f(13)
 
+    if hasattr(os, 'confstr'):
+        def test_os_confstr(self):
+            def f(i):
+                try:
+                    return os.confstr(i)
+                except OSError:
+                    return "oooops!!"
+            some_value = os.confstr_names.values()[-1]
+            res = self.interpret(f, [some_value])
+            assert hlstr(res) == f(some_value)
+            res = self.interpret(f, [94781413])
+            assert hlstr(res) == "oooops!!"
+
+    if hasattr(os, 'pathconf'):
+        def test_os_pathconf(self):
+            def f(i):
+                return os.pathconf("/tmp", i)
+            i = os.pathconf_names["PC_NAME_MAX"]
+            some_value = self.interpret(f, [i])
+            assert some_value >= 31
+
     if hasattr(os, 'chroot'):
         def test_os_chroot(self):
             def f():
@@ -205,3 +227,78 @@
                 return os.getgroups()
             ll_a = self.interpret(f, [])
             assert self.ll_to_list(ll_a) == f()
+
+    if hasattr(os, 'setgroups'):
+        def test_setgroups(self):
+            def f():
+                try:
+                    os.setgroups(os.getgroups())
+                except OSError:
+                    pass
+            self.interpret(f, [])
+
+    if hasattr(os, 'initgroups'):
+        def test_initgroups(self):
+            def f():
+                try:
+                    os.initgroups('sUJJeumz', 4321)
+                except OSError:
+                    return 1
+                return 0
+            res = self.interpret(f, [])
+            assert res == 1
+
+    if hasattr(os, 'tcgetpgrp'):
+        def test_tcgetpgrp(self):
+            def f(fd):
+                try:
+                    return os.tcgetpgrp(fd)
+                except OSError:
+                    return 42
+            res = self.interpret(f, [9999])
+            assert res == 42
+
+    if hasattr(os, 'tcsetpgrp'):
+        def test_tcsetpgrp(self):
+            def f(fd, pgrp):
+                try:
+                    os.tcsetpgrp(fd, pgrp)
+                except OSError:
+                    return 1
+                return 0
+            res = self.interpret(f, [9999, 1])
+            assert res == 1
+
+    if hasattr(os, 'getresuid'):
+        def test_getresuid(self):
+            def f():
+                a, b, c = os.getresuid()
+                return a + b * 37 + c * 1291
+            res = self.interpret(f, [])
+            a, b, c = os.getresuid()
+            assert res == a + b * 37 + c * 1291
+
+    if hasattr(os, 'getresgid'):
+        def test_getresgid(self):
+            def f():
+                a, b, c = os.getresgid()
+                return a + b * 37 + c * 1291
+            res = self.interpret(f, [])
+            a, b, c = os.getresgid()
+            assert res == a + b * 37 + c * 1291
+
+    if hasattr(os, 'setresuid'):
+        def test_setresuid(self):
+            def f():
+                a, b, c = os.getresuid()
+                a = (a + 1) - 1
+                os.setresuid(a, b, c)
+            self.interpret(f, [])
+
+    if hasattr(os, 'setresgid'):
+        def test_setresgid(self):
+            def f():
+                a, b, c = os.getresgid()
+                a = (a + 1) - 1
+                os.setresgid(a, b, c)
+            self.interpret(f, [])


More information about the pypy-commit mailing list