[pypy-commit] pypy step-one-xrange: merge default

hakanardo noreply at buildbot.pypy.org
Fri May 11 14:44:50 CEST 2012


Author: Hakan Ardo <hakan at debian.org>
Branch: step-one-xrange
Changeset: r55038:a40f78826fc8
Date: 2012-05-11 14:35 +0200
http://bitbucket.org/pypy/pypy/changeset/a40f78826fc8/

Log:	merge default

diff --git a/lib-python/conftest.py b/lib-python/conftest.py
--- a/lib-python/conftest.py
+++ b/lib-python/conftest.py
@@ -18,6 +18,7 @@
 
 from pypy.tool.pytest import appsupport 
 from pypy.tool.pytest.confpath import pypydir, testdir, testresultdir
+from pypy.config.parse import parse_info
 
 pytest_plugins = "resultlog",
 rsyncdirs = ['.', '../pypy/']
@@ -599,8 +600,9 @@
 
             # check modules
             info = py.process.cmdexec("%s --info" % execpath)
+            info = parse_info(info)
             for mod in regrtest.usemodules:
-                if "objspace.usemodules.%s: False" % mod in info:
+                if info.get('objspace.usemodules.%s' % mod) is not True:
                     py.test.skip("%s module not included in %s" % (mod,
                                                                    execpath))
                     
diff --git a/pypy/bin/rpython b/pypy/bin/rpython
old mode 100755
new mode 100644
diff --git a/pypy/config/parse.py b/pypy/config/parse.py
new file mode 100644
--- /dev/null
+++ b/pypy/config/parse.py
@@ -0,0 +1,55 @@
+
+
+def parse_info(text):
+    """See test_parse.py."""
+    text = text.lstrip()
+    result = {}
+    if (text+':').index(':') > (text+'=').index('='):
+        # found a '=' before a ':' means that we have the new format
+        current = {0: ''}
+        indentation_prefix = None
+        for line in text.splitlines():
+            line = line.rstrip()
+            if not line:
+                continue
+            realline = line.lstrip()
+            indent = len(line) - len(realline)
+            #
+            # 'indentation_prefix' is set when the previous line was a [group]
+            if indentation_prefix is not None:
+                assert indent > max(current)     # missing indent?
+                current[indent] = indentation_prefix
+                indentation_prefix = None
+                #
+            else:
+                # in case of dedent, must kill the extra items from 'current'
+                for n in current.keys():
+                    if n > indent:
+                        del current[n]
+            #
+            prefix = current[indent]      # KeyError if bad dedent
+            #
+            if realline.startswith('[') and realline.endswith(']'):
+                indentation_prefix = prefix + realline[1:-1] + '.'
+            else:
+                # build the whole dotted key and evaluate the value
+                i = realline.index(' = ')
+                key = prefix + realline[:i]
+                value = realline[i+3:]
+                value = eval(value, {})
+                result[key] = value
+        #
+    else:
+        # old format
+        for line in text.splitlines():
+            i = line.index(':')
+            key = line[:i].strip()
+            value = line[i+1:].strip()
+            try:
+                value = int(value)
+            except ValueError:
+                if value in ('True', 'False', 'None'):
+                    value = eval(value, {})
+            result[key] = value
+        #
+    return result
diff --git a/pypy/config/test/test_parse.py b/pypy/config/test/test_parse.py
new file mode 100644
--- /dev/null
+++ b/pypy/config/test/test_parse.py
@@ -0,0 +1,38 @@
+from pypy.config.parse import parse_info
+
+
+def test_parse_new_format():
+    assert (parse_info("[foo]\n"
+                       "    bar = True\n")
+            == {'foo.bar': True})
+    
+    assert (parse_info("[objspace]\n"
+                       "    x = 'hello'\n"
+                       "[translation]\n"
+                       "    bar = 42\n"
+                       "    [egg]\n"
+                       "        something = None\n"
+                       "    foo = True\n")
+            == {
+        'translation.foo': True,
+        'translation.bar': 42,
+        'translation.egg.something': None,
+        'objspace.x': 'hello',
+        })
+
+    assert parse_info("simple = 43\n") == {'simple': 43}
+
+
+def test_parse_old_format():
+    assert (parse_info("                          objspace.allworkingmodules: True\n"
+                       "                    objspace.disable_call_speedhacks: False\n"
+                       "                                 objspace.extmodules: None\n"
+                       "                                       objspace.name: std\n"
+                       "                        objspace.std.prebuiltintfrom: -5\n")
+            == {
+        'objspace.allworkingmodules': True,
+        'objspace.disable_call_speedhacks': False,
+        'objspace.extmodules': None,
+        'objspace.name': 'std',
+        'objspace.std.prebuiltintfrom': -5,
+        })
diff --git a/pypy/interpreter/astcompiler/assemble.py b/pypy/interpreter/astcompiler/assemble.py
--- a/pypy/interpreter/astcompiler/assemble.py
+++ b/pypy/interpreter/astcompiler/assemble.py
@@ -562,7 +562,7 @@
 
     ops.WITH_CLEANUP : -1,
     ops.POP_BLOCK : 0,
-    ops.END_FINALLY : -3,
+    ops.END_FINALLY : -1,
     ops.SETUP_WITH : 1,
     ops.SETUP_FINALLY : 0,
     ops.SETUP_EXCEPT : 0,
diff --git a/pypy/interpreter/astcompiler/codegen.py b/pypy/interpreter/astcompiler/codegen.py
--- a/pypy/interpreter/astcompiler/codegen.py
+++ b/pypy/interpreter/astcompiler/codegen.py
@@ -564,7 +564,8 @@
             self.visit_sequence(handler.body)
             self.emit_jump(ops.JUMP_FORWARD, end)
             self.use_next_block(next_except)
-        self.emit_op(ops.END_FINALLY)
+        self.emit_op(ops.END_FINALLY)   # this END_FINALLY will always re-raise
+        self.is_dead_code()
         self.use_next_block(otherwise)
         self.visit_sequence(te.orelse)
         self.use_next_block(end)
diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -801,6 +801,18 @@
         return obj
     interp_w._annspecialcase_ = 'specialize:arg(1)'
 
+    def _check_constant_interp_w_or_w_None(self, RequiredClass, w_obj):
+        """
+        This method should NOT be called unless you are really sure about
+        it. It is used inside the implementation of end_finally() in
+        pyopcode.py, and it's there so that it can be overridden by the
+        FlowObjSpace.
+        """
+        if self.is_w(w_obj, self.w_None):
+            return True
+        obj = self.interpclass_w(w_obj)
+        return isinstance(obj, RequiredClass)
+
     def unpackiterable(self, w_iterable, expected_length=-1):
         """Unpack an iterable object into a real (interpreter-level) list.
         Raise an OperationError(w_ValueError) if the length is wrong."""
diff --git a/pypy/interpreter/pyopcode.py b/pypy/interpreter/pyopcode.py
--- a/pypy/interpreter/pyopcode.py
+++ b/pypy/interpreter/pyopcode.py
@@ -600,16 +600,28 @@
         block.cleanup(self)  # the block knows how to clean up the value stack
 
     def end_finally(self):
-        # unlike CPython, when we reach this opcode the value stack has
-        # always been set up as follows (topmost first):
-        #   [exception type  or None]
-        #   [exception value or None]
-        #   [wrapped stack unroller ]
-        self.popvalue()   # ignore the exception type
-        self.popvalue()   # ignore the exception value
-        w_unroller = self.popvalue()
-        unroller = self.space.interpclass_w(w_unroller)
-        return unroller
+        # unlike CPython, there are two statically distinct cases: the
+        # END_FINALLY might be closing an 'except' block or a 'finally'
+        # block.  In the first case, the stack contains three items:
+        #   [exception type we are now handling]
+        #   [exception value we are now handling]
+        #   [wrapped SApplicationException]
+        # In the case of a finally: block, the stack contains only one
+        # item (unlike CPython which can have 1, 2 or 3 items):
+        #   [wrapped subclass of SuspendedUnroller]
+        w_top = self.popvalue()
+        # the following logic is a mess for the flow objspace,
+        # so we hide it specially in the space :-/
+        if self.space._check_constant_interp_w_or_w_None(SuspendedUnroller, w_top):
+            # case of a finally: block
+            unroller = self.space.interpclass_w(w_top)
+            return unroller
+        else:
+            # case of an except: block.  We popped the exception type
+            self.popvalue()        #     Now we pop the exception value
+            unroller = self.space.interpclass_w(self.popvalue())
+            assert unroller is not None
+            return unroller
 
     def BUILD_CLASS(self, oparg, next_instr):
         w_methodsdict = self.popvalue()
@@ -939,17 +951,13 @@
             # Implementation since 2.7a0: 62191 (introduce SETUP_WITH)
             or self.pycode.magic >= 0xa0df2d1):
             # implementation since 2.6a1: 62161 (WITH_CLEANUP optimization)
-            self.popvalue()
-            self.popvalue()
             w_unroller = self.popvalue()
             w_exitfunc = self.popvalue()
             self.pushvalue(w_unroller)
-            self.pushvalue(self.space.w_None)
-            self.pushvalue(self.space.w_None)
         elif self.pycode.magic >= 0xa0df28c:
             # Implementation since 2.5a0: 62092 (changed WITH_CLEANUP opcode)
             w_exitfunc = self.popvalue()
-            w_unroller = self.peekvalue(2)
+            w_unroller = self.peekvalue(0)
         else:
             raise NotImplementedError("WITH_CLEANUP for CPython <= 2.4")
 
@@ -966,7 +974,7 @@
                 w_traceback)
             if self.space.is_true(w_suppress):
                 # __exit__() returned True -> Swallow the exception.
-                self.settopvalue(self.space.w_None, 2)
+                self.settopvalue(self.space.w_None)
         else:
             self.call_contextmanager_exit_function(
                 w_exitfunc,
@@ -1346,25 +1354,12 @@
     _opname = 'SETUP_FINALLY'
     handling_mask = -1     # handles every kind of SuspendedUnroller
 
-    def cleanup(self, frame):
-        # upon normal entry into the finally: part, the standard Python
-        # bytecode pushes a single None for END_FINALLY.  In our case we
-        # always push three values into the stack: the wrapped ctlflowexc,
-        # the exception value and the exception type (which are all None
-        # here).
-        self.cleanupstack(frame)
-        # one None already pushed by the bytecode
-        frame.pushvalue(frame.space.w_None)
-        frame.pushvalue(frame.space.w_None)
-
     def handle(self, frame, unroller):
         # any abnormal reason for unrolling a finally: triggers the end of
         # the block unrolling and the entering the finally: handler.
         # see comments in cleanup().
         self.cleanupstack(frame)
         frame.pushvalue(frame.space.wrap(unroller))
-        frame.pushvalue(frame.space.w_None)
-        frame.pushvalue(frame.space.w_None)
         return r_uint(self.handlerposition)   # jump to the handler
 
 
diff --git a/pypy/jit/metainterp/optimizeopt/test/test_optimizebasic.py b/pypy/jit/metainterp/optimizeopt/test/test_optimizebasic.py
--- a/pypy/jit/metainterp/optimizeopt/test/test_optimizebasic.py
+++ b/pypy/jit/metainterp/optimizeopt/test/test_optimizebasic.py
@@ -5068,6 +5068,7 @@
         self.optimize_strunicode_loop(ops, expected)
 
     def test_call_pure_vstring_const(self):
+        py.test.skip("implement me")
         ops = """
         []
         p0 = newstr(3)
diff --git a/pypy/module/__pypy__/interp_time.py b/pypy/module/__pypy__/interp_time.py
--- a/pypy/module/__pypy__/interp_time.py
+++ b/pypy/module/__pypy__/interp_time.py
@@ -1,5 +1,5 @@
 from __future__ import with_statement
-import sys
+import os
 
 from pypy.interpreter.error import exception_from_errno
 from pypy.interpreter.gateway import unwrap_spec
@@ -7,11 +7,15 @@
 from pypy.rpython.tool import rffi_platform
 from pypy.translator.tool.cbuild import ExternalCompilationInfo
 
+if os.name == 'nt':
+    libraries = []
+else:
+    libraries = ["rt"]
 
 class CConfig:
     _compilation_info_ = ExternalCompilationInfo(
         includes=["time.h"],
-        libraries=["rt"],
+        libraries=libraries,
     )
 
     HAS_CLOCK_GETTIME = rffi_platform.Has('clock_gettime')
@@ -22,11 +26,6 @@
     CLOCK_PROCESS_CPUTIME_ID = rffi_platform.DefinedConstantInteger("CLOCK_PROCESS_CPUTIME_ID")
     CLOCK_THREAD_CPUTIME_ID = rffi_platform.DefinedConstantInteger("CLOCK_THREAD_CPUTIME_ID")
 
-    TIMESPEC = rffi_platform.Struct("struct timespec", [
-        ("tv_sec", rffi.TIME_T),
-        ("tv_nsec", rffi.LONG),
-    ])
-
 cconfig = rffi_platform.configure(CConfig)
 
 HAS_CLOCK_GETTIME = cconfig["HAS_CLOCK_GETTIME"]
@@ -37,29 +36,36 @@
 CLOCK_PROCESS_CPUTIME_ID = cconfig["CLOCK_PROCESS_CPUTIME_ID"]
 CLOCK_THREAD_CPUTIME_ID = cconfig["CLOCK_THREAD_CPUTIME_ID"]
 
-TIMESPEC = cconfig["TIMESPEC"]
+if HAS_CLOCK_GETTIME:
+    #redo it for timespec
+    CConfig.TIMESPEC = rffi_platform.Struct("struct timespec", [
+        ("tv_sec", rffi.TIME_T),
+        ("tv_nsec", rffi.LONG),
+    ])
+    cconfig = rffi_platform.configure(CConfig)
+    TIMESPEC = cconfig['TIMESPEC']
 
-c_clock_gettime = rffi.llexternal("clock_gettime",
-    [lltype.Signed, lltype.Ptr(TIMESPEC)], rffi.INT,
-    compilation_info=CConfig._compilation_info_, threadsafe=False
-)
-c_clock_getres = rffi.llexternal("clock_getres",
-    [lltype.Signed, lltype.Ptr(TIMESPEC)], rffi.INT,
-    compilation_info=CConfig._compilation_info_, threadsafe=False
-)
+    c_clock_gettime = rffi.llexternal("clock_gettime",
+        [lltype.Signed, lltype.Ptr(TIMESPEC)], rffi.INT,
+        compilation_info=CConfig._compilation_info_, threadsafe=False
+    )
+    c_clock_getres = rffi.llexternal("clock_getres",
+        [lltype.Signed, lltype.Ptr(TIMESPEC)], rffi.INT,
+        compilation_info=CConfig._compilation_info_, threadsafe=False
+    )
 
- at unwrap_spec(clk_id="c_int")
-def clock_gettime(space, clk_id):
-    with lltype.scoped_alloc(TIMESPEC) as tp:
-        ret = c_clock_gettime(clk_id, tp)
-        if ret != 0:
-            raise exception_from_errno(space, space.w_IOError)
-        return space.wrap(tp.c_tv_sec + tp.c_tv_nsec * 1e-9)
+    @unwrap_spec(clk_id="c_int")
+    def clock_gettime(space, clk_id):
+        with lltype.scoped_alloc(TIMESPEC) as tp:
+            ret = c_clock_gettime(clk_id, tp)
+            if ret != 0:
+                raise exception_from_errno(space, space.w_IOError)
+            return space.wrap(tp.c_tv_sec + tp.c_tv_nsec * 1e-9)
 
- at unwrap_spec(clk_id="c_int")
-def clock_getres(space, clk_id):
-    with lltype.scoped_alloc(TIMESPEC) as tp:
-        ret = c_clock_getres(clk_id, tp)
-        if ret != 0:
-            raise exception_from_errno(space, space.w_IOError)
-        return space.wrap(tp.c_tv_sec + tp.c_tv_nsec * 1e-9)
+    @unwrap_spec(clk_id="c_int")
+    def clock_getres(space, clk_id):
+        with lltype.scoped_alloc(TIMESPEC) as tp:
+            ret = c_clock_getres(clk_id, tp)
+            if ret != 0:
+                raise exception_from_errno(space, space.w_IOError)
+            return space.wrap(tp.c_tv_sec + tp.c_tv_nsec * 1e-9)
diff --git a/pypy/module/_file/test/test_file.py b/pypy/module/_file/test/test_file.py
--- a/pypy/module/_file/test/test_file.py
+++ b/pypy/module/_file/test/test_file.py
@@ -265,14 +265,6 @@
 
         if option.runappdirect:
             py.test.skip("works with internals of _file impl on py.py")
-        import platform
-        if platform.system() == 'Windows':
-            # XXX This test crashes until someone implements something like
-            # XXX verify_fd from
-            # XXX http://hg.python.org/cpython/file/80ddbd822227/Modules/posixmodule.c#l434
-            # XXX and adds it to fopen
-            assert False
-
         state = [0]
         def read(fd, n=None):
             if fd != 42:
@@ -286,7 +278,7 @@
             return ''
         os.read = read
         stdin = W_File(cls.space)
-        stdin.file_fdopen(42, "r", 1)
+        stdin.file_fdopen(42, 'rb', 1)
         stdin.name = '<stdin>'
         cls.w_stream = stdin
 
diff --git a/pypy/module/_socket/test/test_sock_app.py b/pypy/module/_socket/test/test_sock_app.py
--- a/pypy/module/_socket/test/test_sock_app.py
+++ b/pypy/module/_socket/test/test_sock_app.py
@@ -616,8 +616,9 @@
                 cli.send('foobar' * 70)
         except timeout:
             pass
-        # test sendall() timeout
-        raises(timeout, cli.sendall, 'foobar' * 70)
+        # test sendall() timeout, be sure to send data larger than the
+        # socket buffer
+        raises(timeout, cli.sendall, 'foobar' * 7000)
         # done
         cli.close()
         t.close()
diff --git a/pypy/module/_weakref/interp__weakref.py b/pypy/module/_weakref/interp__weakref.py
--- a/pypy/module/_weakref/interp__weakref.py
+++ b/pypy/module/_weakref/interp__weakref.py
@@ -4,25 +4,50 @@
 from pypy.interpreter.gateway import interp2app, ObjSpace
 from pypy.interpreter.typedef import TypeDef
 from pypy.rlib import jit
+from pypy.rlib.rshrinklist import AbstractShrinkList
+from pypy.rlib.objectmodel import specialize
 import weakref
 
 
+class WRefShrinkList(AbstractShrinkList):
+    def must_keep(self, wref):
+        return wref() is not None
+
+
 class WeakrefLifeline(W_Root):
-    cached_weakref_index = -1
-    cached_proxy_index = -1
+    cached_weakref  = None
+    cached_proxy    = None
+    other_refs_weak = None
 
     def __init__(self, space):
         self.space = space
-        self.refs_weak = []
+
+    def append_wref_to(self, w_ref):
+        if self.other_refs_weak is None:
+            self.other_refs_weak = WRefShrinkList()
+        self.other_refs_weak.append(weakref.ref(w_ref))
+
+    @specialize.arg(1)
+    def traverse(self, callback, arg=None):
+        if self.cached_weakref is not None:
+            arg = callback(self, self.cached_weakref, arg)
+        if self.cached_proxy is not None:
+            arg = callback(self, self.cached_proxy, arg)
+        if self.other_refs_weak is not None:
+            for ref_w_ref in self.other_refs_weak.items():
+                arg = callback(self, ref_w_ref, arg)
+        return arg
+
+    def _clear_wref(self, wref, _):
+        w_ref = wref()
+        if w_ref is not None:
+            w_ref.clear()
 
     def clear_all_weakrefs(self):
         """Clear all weakrefs.  This is called when an app-level object has
         a __del__, just before the app-level __del__ method is called.
         """
-        for ref_w_ref in self.refs_weak:
-            w_ref = ref_w_ref()
-            if w_ref is not None:
-                w_ref.clear()
+        self.traverse(WeakrefLifeline._clear_wref)
         # Note that for no particular reason other than convenience,
         # weakref callbacks are not invoked eagerly here.  They are
         # invoked by self.__del__() anyway.
@@ -30,49 +55,46 @@
     def get_or_make_weakref(self, w_subtype, w_obj):
         space = self.space
         w_weakreftype = space.gettypeobject(W_Weakref.typedef)
-        is_weakreftype = space.is_w(w_weakreftype, w_subtype)
-        if is_weakreftype and self.cached_weakref_index >= 0:
-            w_cached = self.refs_weak[self.cached_weakref_index]()
-            if w_cached is not None:
-                return w_cached
-            else:
-                self.cached_weakref_index = -1
-        w_ref = space.allocate_instance(W_Weakref, w_subtype)
-        index = len(self.refs_weak)
-        W_Weakref.__init__(w_ref, space, w_obj, None)
-        self.refs_weak.append(weakref.ref(w_ref))
-        if is_weakreftype:
-            self.cached_weakref_index = index
+        #
+        if space.is_w(w_weakreftype, w_subtype):
+            if self.cached_weakref is not None:
+                w_cached = self.cached_weakref()
+                if w_cached is not None:
+                    return w_cached
+            w_ref = W_Weakref(space, w_obj, None)
+            self.cached_weakref = weakref.ref(w_ref)
+        else:
+            # subclass: cannot cache
+            w_ref = space.allocate_instance(W_Weakref, w_subtype)
+            W_Weakref.__init__(w_ref, space, w_obj, None)
+            self.append_wref_to(w_ref)
         return w_ref
 
     def get_or_make_proxy(self, w_obj):
         space = self.space
-        if self.cached_proxy_index >= 0:
-            w_cached = self.refs_weak[self.cached_proxy_index]()
+        if self.cached_proxy is not None:
+            w_cached = self.cached_proxy()
             if w_cached is not None:
                 return w_cached
-            else:
-                self.cached_proxy_index = -1
-        index = len(self.refs_weak)
         if space.is_true(space.callable(w_obj)):
             w_proxy = W_CallableProxy(space, w_obj, None)
         else:
             w_proxy = W_Proxy(space, w_obj, None)
-        self.refs_weak.append(weakref.ref(w_proxy))
-        self.cached_proxy_index = index
+        self.cached_proxy = weakref.ref(w_proxy)
         return w_proxy
 
     def get_any_weakref(self, space):
-        if self.cached_weakref_index != -1:
-            w_ref = self.refs_weak[self.cached_weakref_index]()
+        if self.cached_weakref is not None:
+            w_ref = self.cached_weakref()
             if w_ref is not None:
                 return w_ref
-        w_weakreftype = space.gettypeobject(W_Weakref.typedef)
-        for i in range(len(self.refs_weak)):
-            w_ref = self.refs_weak[i]()
-            if (w_ref is not None and
-                space.is_true(space.isinstance(w_ref, w_weakreftype))):
-                return w_ref
+        if self.other_refs_weak is not None:
+            w_weakreftype = space.gettypeobject(W_Weakref.typedef)
+            for wref in self.other_refs_weak.items():
+                w_ref = wref()
+                if (w_ref is not None and
+                    space.is_true(space.isinstance(w_ref, w_weakreftype))):
+                    return w_ref
         return space.w_None
 
 
@@ -80,10 +102,10 @@
 
     def __init__(self, space, oldlifeline=None):
         self.space = space
-        if oldlifeline is None:
-            self.refs_weak = []
-        else:
-            self.refs_weak = oldlifeline.refs_weak
+        if oldlifeline is not None:
+            self.cached_weakref  = oldlifeline.cached_weakref
+            self.cached_proxy    = oldlifeline.cached_proxy
+            self.other_refs_weak = oldlifeline.other_refs_weak
 
     def __del__(self):
         """This runs when the interp-level object goes away, and allows
@@ -91,8 +113,11 @@
         callbacks even if there is no __del__ method on the interp-level
         W_Root subclass implementing the object.
         """
-        for i in range(len(self.refs_weak) - 1, -1, -1):
-            w_ref = self.refs_weak[i]()
+        if self.other_refs_weak is None:
+            return
+        items = self.other_refs_weak.items()
+        for i in range(len(items)-1, -1, -1):
+            w_ref = items[i]()
             if w_ref is not None and w_ref.w_callable is not None:
                 w_ref.enqueue_for_destruction(self.space,
                                               W_WeakrefBase.activate_callback,
@@ -102,7 +127,7 @@
         space = self.space
         w_ref = space.allocate_instance(W_Weakref, w_subtype)
         W_Weakref.__init__(w_ref, space, w_obj, w_callable)
-        self.refs_weak.append(weakref.ref(w_ref))
+        self.append_wref_to(w_ref)
         return w_ref
 
     def make_proxy_with_callback(self, w_obj, w_callable):
@@ -111,7 +136,7 @@
             w_proxy = W_CallableProxy(space, w_obj, w_callable)
         else:
             w_proxy = W_Proxy(space, w_obj, w_callable)
-        self.refs_weak.append(weakref.ref(w_proxy))
+        self.append_wref_to(w_proxy)
         return w_proxy
 
 # ____________________________________________________________
@@ -247,30 +272,33 @@
 )
 
 
+def _weakref_count(lifeline, wref, count):
+    if wref() is not None:
+        count += 1
+    return count
+
 def getweakrefcount(space, w_obj):
     """Return the number of weak references to 'obj'."""
     lifeline = w_obj.getweakref()
     if lifeline is None:
         return space.wrap(0)
     else:
-        result = 0
-        for i in range(len(lifeline.refs_weak)):
-            if lifeline.refs_weak[i]() is not None:
-                result += 1
+        result = lifeline.traverse(_weakref_count, 0)
         return space.wrap(result)
 
+def _get_weakrefs(lifeline, wref, result):
+    w_ref = wref()
+    if w_ref is not None:
+        result.append(w_ref)
+    return result
+
 def getweakrefs(space, w_obj):
     """Return a list of all weak reference objects that point to 'obj'."""
+    result = []
     lifeline = w_obj.getweakref()
-    if lifeline is None:
-        return space.newlist([])
-    else:
-        result = []
-        for i in range(len(lifeline.refs_weak)):
-            w_ref = lifeline.refs_weak[i]()
-            if w_ref is not None:
-                result.append(w_ref)
-        return space.newlist(result)
+    if lifeline is not None:
+        lifeline.traverse(_get_weakrefs, result)
+    return space.newlist(result)
 
 #_________________________________________________________________
 # Proxy
diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py
--- a/pypy/module/cpyext/api.py
+++ b/pypy/module/cpyext/api.py
@@ -26,6 +26,7 @@
 from pypy.module.__builtin__.interp_classobj import W_ClassObject
 from pypy.module.__builtin__.interp_memoryview import W_MemoryView
 from pypy.rlib.entrypoint import entrypoint
+from pypy.rlib.rposix import is_valid_fd, validate_fd
 from pypy.rlib.unroll import unrolling_iterable
 from pypy.rlib.objectmodel import specialize
 from pypy.rlib.exports import export_struct
@@ -79,20 +80,39 @@
 
 # FILE* interface
 FILEP = rffi.COpaquePtr('FILE')
-fopen = rffi.llexternal('fopen', [CONST_STRING, CONST_STRING], FILEP)
-fclose = rffi.llexternal('fclose', [FILEP], rffi.INT)
-fwrite = rffi.llexternal('fwrite',
-                         [rffi.VOIDP, rffi.SIZE_T, rffi.SIZE_T, FILEP],
-                         rffi.SIZE_T)
-fread = rffi.llexternal('fread',
-                        [rffi.VOIDP, rffi.SIZE_T, rffi.SIZE_T, FILEP],
-                        rffi.SIZE_T)
-feof = rffi.llexternal('feof', [FILEP], rffi.INT)
+
 if sys.platform == 'win32':
     fileno = rffi.llexternal('_fileno', [FILEP], rffi.INT)
 else:
     fileno = rffi.llexternal('fileno', [FILEP], rffi.INT)
 
+fopen = rffi.llexternal('fopen', [CONST_STRING, CONST_STRING], FILEP)
+
+_fclose = rffi.llexternal('fclose', [FILEP], rffi.INT)
+def fclose(fp):
+    if not is_valid_fd(fileno(fp)):
+        return -1
+    return _fclose(fp)
+
+_fwrite = rffi.llexternal('fwrite',
+                         [rffi.VOIDP, rffi.SIZE_T, rffi.SIZE_T, FILEP],
+                         rffi.SIZE_T)
+def fwrite(buf, sz, n, fp):
+    validate_fd(fileno(fp))
+    return _fwrite(buf, sz, n, fp)
+
+_fread = rffi.llexternal('fread',
+                        [rffi.VOIDP, rffi.SIZE_T, rffi.SIZE_T, FILEP],
+                        rffi.SIZE_T)
+def fread(buf, sz, n, fp):
+    validate_fd(fileno(fp))
+    return _fread(buf, sz, n, fp)
+
+_feof = rffi.llexternal('feof', [FILEP], rffi.INT)
+def feof(fp):
+    validate_fd(fileno(fp))
+    return _feof(fp)
+
 
 constant_names = """
 Py_TPFLAGS_READY Py_TPFLAGS_READYING Py_TPFLAGS_HAVE_GETCHARBUFFER
diff --git a/pypy/module/math/test/test_math.py b/pypy/module/math/test/test_math.py
--- a/pypy/module/math/test/test_math.py
+++ b/pypy/module/math/test/test_math.py
@@ -271,5 +271,6 @@
         assert math.trunc(foo()) == "truncated"
 
     def test_copysign_nan(self):
+        skip('sign of nan is undefined')
         import math
         assert math.copysign(1.0, float('-nan')) == -1.0
diff --git a/pypy/module/micronumpy/test/test_ufuncs.py b/pypy/module/micronumpy/test/test_ufuncs.py
--- a/pypy/module/micronumpy/test/test_ufuncs.py
+++ b/pypy/module/micronumpy/test/test_ufuncs.py
@@ -233,12 +233,15 @@
         assert a[1] == 0
 
     def test_signbit(self):
-        from _numpypy import signbit, copysign
+        from _numpypy import signbit
 
-        assert (signbit([0, 0.0, 1, 1.0, float('inf'), float('nan')]) ==
-            [False, False, False, False, False, False]).all()
-        assert (signbit([-0, -0.0, -1, -1.0, float('-inf'), -float('nan'), float('-nan')]) ==
-            [False,  True,  True,  True,  True,  True, True]).all()
+        assert (signbit([0, 0.0, 1, 1.0, float('inf')]) ==
+            [False, False, False, False, False]).all()
+        assert (signbit([-0, -0.0, -1, -1.0, float('-inf')]) ==
+            [False,  True,  True,  True,  True]).all()
+        skip('sign of nan is non-determinant')
+        assert (signbit([float('nan'), float('-nan'), -float('nan')]) ==
+            [False, True, True]).all()    
 
     def test_reciporocal(self):
         from _numpypy import array, reciprocal
@@ -267,8 +270,8 @@
         assert ([ninf, -1.0, -1.0, -1.0, 0.0, 1.0, 2.0, 1.0, inf] == ceil(a)).all()
         assert ([ninf, -1.0, -1.0, -1.0, 0.0, 1.0, 1.0, 0.0, inf] == trunc(a)).all()
         assert all([math.isnan(f(float("nan"))) for f in floor, ceil, trunc])
-        assert all([math.copysign(1, f(float("nan"))) == 1 for f in floor, ceil, trunc])
-        assert all([math.copysign(1, f(float("-nan"))) == -1 for f in floor, ceil, trunc])
+        assert all([math.copysign(1, f(abs(float("nan")))) == 1 for f in floor, ceil, trunc])
+        assert all([math.copysign(1, f(-abs(float("nan")))) == -1 for f in floor, ceil, trunc])
 
     def test_copysign(self):
         from _numpypy import array, copysign
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
@@ -548,6 +548,8 @@
         assert len(b) == 6
         assert b[3] == "b"
         assert b[:] == "foobar"
+        m.close()
+        f.close()
 
     def test_offset(self):
         from mmap import mmap, ALLOCATIONGRANULARITY
diff --git a/pypy/module/rctime/test/test_rctime.py b/pypy/module/rctime/test/test_rctime.py
--- a/pypy/module/rctime/test/test_rctime.py
+++ b/pypy/module/rctime/test/test_rctime.py
@@ -213,6 +213,7 @@
 
     def test_strftime(self):
         import time as rctime
+        import os
 
         t = rctime.time()
         tt = rctime.gmtime(t)
@@ -228,6 +229,14 @@
         exp = '2000 01 01 00 00 00 1 001'
         assert rctime.strftime("%Y %m %d %H %M %S %w %j", (0,)*9) == exp
 
+        # Guard against invalid/non-supported format string
+        # so that Python don't crash (Windows crashes when the format string
+        # input to [w]strftime is not kosher.
+        if os.name == 'nt':
+            raises(ValueError, rctime.strftime, '%f')
+        else:
+            assert rctime.strftime('%f') == '%f'
+
     def test_strftime_ext(self):
         import time as rctime
 
diff --git a/pypy/module/signal/interp_signal.py b/pypy/module/signal/interp_signal.py
--- a/pypy/module/signal/interp_signal.py
+++ b/pypy/module/signal/interp_signal.py
@@ -15,7 +15,8 @@
 
 def setup():
     for key, value in cpy_signal.__dict__.items():
-        if key.startswith('SIG') and is_valid_int(value):
+        if (key.startswith('SIG') or key.startswith('CTRL_')) and \
+                is_valid_int(value):
             globals()[key] = value
             yield key
 
@@ -23,6 +24,10 @@
 SIG_DFL = cpy_signal.SIG_DFL
 SIG_IGN = cpy_signal.SIG_IGN
 signal_names = list(setup())
+signal_values = [globals()[key] for key in signal_names]
+signal_values = {}
+for key in signal_names:
+    signal_values[globals()[key]] = None
 
 includes = ['stdlib.h', 'src/signals.h']
 if sys.platform != 'win32':
@@ -242,9 +247,11 @@
     return space.w_None
 
 def check_signum(space, signum):
-    if signum < 1 or signum >= NSIG:
-        raise OperationError(space.w_ValueError,
-                             space.wrap("signal number out of range"))
+    if signum in signal_values:
+        return
+    raise OperationError(space.w_ValueError,
+                         space.wrap("invalid signal value"))
+
 
 @jit.dont_look_inside
 @unwrap_spec(signum=int)
diff --git a/pypy/module/signal/test/test_interp_signal.py b/pypy/module/signal/test/test_interp_signal.py
--- a/pypy/module/signal/test/test_interp_signal.py
+++ b/pypy/module/signal/test/test_interp_signal.py
@@ -6,6 +6,8 @@
 def setup_module(mod):
     if not hasattr(os, 'kill') or not hasattr(os, 'getpid'):
         py.test.skip("requires os.kill() and os.getpid()")
+    if not hasattr(interp_signal, 'SIGUSR1'):
+        py.test.skip("requires SIGUSR1 in signal")
 
 
 def check(expected):
diff --git a/pypy/module/signal/test/test_signal.py b/pypy/module/signal/test/test_signal.py
--- a/pypy/module/signal/test/test_signal.py
+++ b/pypy/module/signal/test/test_signal.py
@@ -8,6 +8,8 @@
     def setup_class(cls):
         if not hasattr(os, 'kill') or not hasattr(os, 'getpid'):
             py.test.skip("requires os.kill() and os.getpid()")
+        if not hasattr(cpy_signal, 'SIGUSR1'):    
+            py.test.skip("requires SIGUSR1 in signal")
         cls.space = gettestobjspace(usemodules=['signal'])
 
     def test_checksignals(self):
@@ -36,8 +38,6 @@
 class AppTestSignal:
 
     def setup_class(cls):
-        if not hasattr(os, 'kill') or not hasattr(os, 'getpid'):
-            py.test.skip("requires os.kill() and os.getpid()")
         space = gettestobjspace(usemodules=['signal'])
         cls.space = space
         cls.w_signal = space.appexec([], "(): import signal; return signal")
@@ -45,64 +45,72 @@
     def test_exported_names(self):
         self.signal.__dict__   # crashes if the interpleveldefs are invalid
 
-    def test_usr1(self):
-        import types, posix
+    def test_basics(self):
+        import types, os
+        if not hasattr(os, 'kill') or not hasattr(os, 'getpid'):
+            skip("requires os.kill() and os.getpid()")
         signal = self.signal   # the signal module to test
+        if hasattr(signal,'SIGUSR1'):
+            signum = signal.SIGUSR1
+        else:
+            signum = signal.CTRL_BREAK_EVENT
 
         received = []
         def myhandler(signum, frame):
             assert isinstance(frame, types.FrameType)
             received.append(signum)
-        signal.signal(signal.SIGUSR1, myhandler)
+        signal.signal(signum, myhandler)
 
-        posix.kill(posix.getpid(), signal.SIGUSR1)
+        print dir(os)
+
+        os.kill(os.getpid(), signum)
         # the signal should be delivered to the handler immediately
-        assert received == [signal.SIGUSR1]
+        assert received == [signum]
         del received[:]
 
-        posix.kill(posix.getpid(), signal.SIGUSR1)
+        os.kill(os.getpid(), signum)
         # the signal should be delivered to the handler immediately
-        assert received == [signal.SIGUSR1]
+        assert received == [signum]
         del received[:]
 
-        signal.signal(signal.SIGUSR1, signal.SIG_IGN)
+        signal.signal(signum, signal.SIG_IGN)
 
-        posix.kill(posix.getpid(), signal.SIGUSR1)
+        os.kill(os.getpid(), signum)
         for i in range(10000):
             # wait a bit - signal should not arrive
             if received:
                 break
         assert received == []
 
-        signal.signal(signal.SIGUSR1, signal.SIG_DFL)
+        signal.signal(signum, signal.SIG_DFL)
 
 
     def test_default_return(self):
         """
         Test that signal.signal returns SIG_DFL if that is the current handler.
         """
-        from signal import signal, SIGUSR1, SIG_DFL, SIG_IGN
+        from signal import signal, SIGINT, SIG_DFL, SIG_IGN
 
         try:
             for handler in SIG_DFL, SIG_IGN, lambda *a: None:
-                signal(SIGUSR1, SIG_DFL)
-                assert signal(SIGUSR1, handler) == SIG_DFL
+                signal(SIGINT, SIG_DFL)
+                assert signal(SIGINT, handler) == SIG_DFL
         finally:
-            signal(SIGUSR1, SIG_DFL)
+            signal(SIGINT, SIG_DFL)
 
 
     def test_ignore_return(self):
         """
         Test that signal.signal returns SIG_IGN if that is the current handler.
         """
-        from signal import signal, SIGUSR1, SIG_DFL, SIG_IGN
+        from signal import signal, SIGINT, SIG_DFL, SIG_IGN
 
         try:
             for handler in SIG_DFL, SIG_IGN, lambda *a: None:
-                signal(SIGUSR1, SIG_IGN)
-                assert signal(SIGUSR1, handler) == SIG_IGN
+                signal(SIGINT, SIG_IGN)
+                assert signal(SIGINT, handler) == SIG_IGN
         finally:
-            signal(SIGUSR1, SIG_DFL)
+            signal(SIGINT, SIG_DFL)
 
 
     def test_obj_return(self):
@@ -110,43 +118,47 @@
         Test that signal.signal returns a Python object if one is the current
         handler.
         """
-        from signal import signal, SIGUSR1, SIG_DFL, SIG_IGN
+        from signal import signal, SIGINT, SIG_DFL, SIG_IGN
         def installed(*a):
             pass
 
         try:
             for handler in SIG_DFL, SIG_IGN, lambda *a: None:
-                signal(SIGUSR1, installed)
-                assert signal(SIGUSR1, handler) is installed
+                signal(SIGINT, installed)
+                assert signal(SIGINT, handler) is installed
         finally:
-            signal(SIGUSR1, SIG_DFL)
+            signal(SIGINT, SIG_DFL)
 
 
     def test_getsignal(self):
         """
         Test that signal.getsignal returns the currently installed handler.
         """
-        from signal import getsignal, signal, SIGUSR1, SIG_DFL, SIG_IGN
+        from signal import getsignal, signal, SIGINT, SIG_DFL, SIG_IGN
 
         def handler(*a):
             pass
 
         try:
-            assert getsignal(SIGUSR1) == SIG_DFL
-            signal(SIGUSR1, SIG_DFL)
-            assert getsignal(SIGUSR1) == SIG_DFL
-            signal(SIGUSR1, SIG_IGN)
-            assert getsignal(SIGUSR1) == SIG_IGN
-            signal(SIGUSR1, handler)
-            assert getsignal(SIGUSR1) is handler
+            assert getsignal(SIGINT) == SIG_DFL
+            signal(SIGINT, SIG_DFL)
+            assert getsignal(SIGINT) == SIG_DFL
+            signal(SIGINT, SIG_IGN)
+            assert getsignal(SIGINT) == SIG_IGN
+            signal(SIGINT, handler)
+            assert getsignal(SIGINT) is handler
         finally:
-            signal(SIGUSR1, SIG_DFL)
+            signal(SIGINT, SIG_DFL)
 
         raises(ValueError, getsignal, 4444)
         raises(ValueError, signal, 4444, lambda *args: None)
+        raises(ValueError, signal, 42, lambda *args: None)
 
     def test_alarm(self):
-        from signal import alarm, signal, SIG_DFL, SIGALRM
+        try:
+            from signal import alarm, signal, SIG_DFL, SIGALRM
+        except:
+            skip('no alarm on this platform')
         import time
         l = []
         def handler(*a):
@@ -163,10 +175,13 @@
             signal(SIGALRM, SIG_DFL)
 
     def test_set_wakeup_fd(self):
-        import signal, posix, fcntl
+        try:
+            import signal, posix, fcntl
+        except ImportError:
+            skip('cannot import posix or fcntl')
         def myhandler(signum, frame):
             pass
-        signal.signal(signal.SIGUSR1, myhandler)
+        signal.signal(signal.SIGINT, myhandler)
         #
         def cannot_read():
             try:
@@ -187,17 +202,19 @@
         old_wakeup = signal.set_wakeup_fd(fd_write)
         try:
             cannot_read()
-            posix.kill(posix.getpid(), signal.SIGUSR1)
+            posix.kill(posix.getpid(), signal.SIGINT)
             res = posix.read(fd_read, 1)
             assert res == '\x00'
             cannot_read()
         finally:
             old_wakeup = signal.set_wakeup_fd(old_wakeup)
         #
-        signal.signal(signal.SIGUSR1, signal.SIG_DFL)
+        signal.signal(signal.SIGINT, signal.SIG_DFL)
 
     def test_siginterrupt(self):
         import signal, os, time
+        if not hasattr(signal, 'siginterrupt'):
+            skip('non siginterrupt in signal')
         signum = signal.SIGUSR1
         def readpipe_is_not_interrupted():
             # from CPython's test_signal.readpipe_interrupted()
diff --git a/pypy/module/thread/__init__.py b/pypy/module/thread/__init__.py
--- a/pypy/module/thread/__init__.py
+++ b/pypy/module/thread/__init__.py
@@ -18,7 +18,7 @@
         'allocate_lock':          'os_lock.allocate_lock',
         'allocate':               'os_lock.allocate_lock',  # obsolete synonym
         'LockType':               'os_lock.Lock',
-        #'_local':                'os_local.Local',   # only if 'rweakref'
+        '_local':                 'os_local.Local',
         'error':                  'space.fromcache(error.Cache).w_error',
     }
 
@@ -34,8 +34,3 @@
         from pypy.module.posix.interp_posix import add_fork_hook
         from pypy.module.thread.os_thread import reinit_threads
         add_fork_hook('child', reinit_threads)
-
-    def setup_after_space_initialization(self):
-        """NOT_RPYTHON"""
-        if self.space.config.translation.rweakref:
-            self.extra_interpdef('_local', 'os_local.Local')
diff --git a/pypy/module/thread/os_local.py b/pypy/module/thread/os_local.py
--- a/pypy/module/thread/os_local.py
+++ b/pypy/module/thread/os_local.py
@@ -1,16 +1,26 @@
-from pypy.rlib.rweakref import RWeakKeyDictionary
+import weakref
+from pypy.rlib import jit
 from pypy.interpreter.baseobjspace import Wrappable, W_Root
 from pypy.interpreter.executioncontext import ExecutionContext
 from pypy.interpreter.typedef import (TypeDef, interp2app, GetSetProperty,
     descr_get_dict)
+from pypy.rlib.rshrinklist import AbstractShrinkList
+
+class WRefShrinkList(AbstractShrinkList):
+    def must_keep(self, wref):
+        return wref() is not None
+
+
+ExecutionContext._thread_local_objs = None
 
 
 class Local(Wrappable):
     """Thread-local data"""
 
+    @jit.dont_look_inside
     def __init__(self, space, initargs):
         self.initargs = initargs
-        self.dicts = RWeakKeyDictionary(ExecutionContext, W_Root)
+        self.dicts = {}   # mapping ExecutionContexts to the wraped dict
         # The app-level __init__() will be called by the general
         # instance-creation logic.  It causes getdict() to be
         # immediately called.  If we don't prepare and set a w_dict
@@ -18,26 +28,42 @@
         # to call __init__() a second time.
         ec = space.getexecutioncontext()
         w_dict = space.newdict(instance=True)
-        self.dicts.set(ec, w_dict)
+        self.dicts[ec] = w_dict
+        self._register_in_ec(ec)
+
+    def _register_in_ec(self, ec):
+        if not ec.space.config.translation.rweakref:
+            return    # without weakrefs, works but 'dicts' is never cleared
+        if ec._thread_local_objs is None:
+            ec._thread_local_objs = WRefShrinkList()
+        ec._thread_local_objs.append(weakref.ref(self))
+
+    @jit.dont_look_inside
+    def create_new_dict(self, ec):
+        # create a new dict for this thread
+        space = ec.space
+        w_dict = space.newdict(instance=True)
+        self.dicts[ec] = w_dict
+        # call __init__
+        try:
+            w_self = space.wrap(self)
+            w_type = space.type(w_self)
+            w_init = space.getattr(w_type, space.wrap("__init__"))
+            space.call_obj_args(w_init, w_self, self.initargs)
+        except:
+            # failed, forget w_dict and propagate the exception
+            del self.dicts[ec]
+            raise
+        # ready
+        self._register_in_ec(ec)
+        return w_dict
 
     def getdict(self, space):
         ec = space.getexecutioncontext()
-        w_dict = self.dicts.get(ec)
-        if w_dict is None:
-            # create a new dict for this thread
-            w_dict = space.newdict(instance=True)
-            self.dicts.set(ec, w_dict)
-            # call __init__
-            try:
-                w_self = space.wrap(self)
-                w_type = space.type(w_self)
-                w_init = space.getattr(w_type, space.wrap("__init__"))
-                space.call_obj_args(w_init, w_self, self.initargs)
-            except:
-                # failed, forget w_dict and propagate the exception
-                self.dicts.set(ec, None)
-                raise
-            # ready
+        try:
+            w_dict = self.dicts[ec]
+        except KeyError:
+            w_dict = self.create_new_dict(ec)
         return w_dict
 
     def descr_local__new__(space, w_subtype, __args__):
@@ -55,3 +81,13 @@
                         __init__ = interp2app(Local.descr_local__init__),
                         __dict__ = GetSetProperty(descr_get_dict, cls=Local),
                         )
+
+def thread_is_stopping(ec):
+    tlobjs = ec._thread_local_objs
+    if tlobjs is None:
+        return
+    ec._thread_local_objs = None
+    for wref in tlobjs.items():
+        local = wref()
+        if local is not None:
+            del local.dicts[ec]
diff --git a/pypy/module/thread/threadlocals.py b/pypy/module/thread/threadlocals.py
--- a/pypy/module/thread/threadlocals.py
+++ b/pypy/module/thread/threadlocals.py
@@ -54,4 +54,8 @@
 
     def leave_thread(self, space):
         "Notification that the current thread is about to stop."
-        self.setvalue(None)
+        from pypy.module.thread.os_local import thread_is_stopping
+        try:
+            thread_is_stopping(self.getvalue())
+        finally:
+            self.setvalue(None)
diff --git a/pypy/objspace/flow/objspace.py b/pypy/objspace/flow/objspace.py
--- a/pypy/objspace/flow/objspace.py
+++ b/pypy/objspace/flow/objspace.py
@@ -204,6 +204,14 @@
             return obj
         return None
 
+    def _check_constant_interp_w_or_w_None(self, RequiredClass, w_obj):
+        """
+        WARNING: this implementation is not complete at all. It's just enough
+        to be used by end_finally() inside pyopcode.py.
+        """
+        return w_obj == self.w_None or (isinstance(w_obj, Constant) and
+                                        isinstance(w_obj.value, RequiredClass))
+
     def getexecutioncontext(self):
         return getattr(self, 'executioncontext', None)
 
diff --git a/pypy/rlib/jit.py b/pypy/rlib/jit.py
--- a/pypy/rlib/jit.py
+++ b/pypy/rlib/jit.py
@@ -413,8 +413,8 @@
     'retrace_limit': 'how many times we can try retracing before giving up',
     'max_retrace_guards': 'number of extra guards a retrace can cause',
     'max_unroll_loops': 'number of extra unrollings a loop can cause',
-    'enable_opts': 'INTERNAL USE ONLY: optimizations to enable, or all = %s' %
-                       ENABLE_ALL_OPTS,
+    'enable_opts': 'INTERNAL USE ONLY (MAY NOT WORK OR LEAD TO CRASHES): '
+                   'optimizations to enable, or all = %s' % ENABLE_ALL_OPTS,
     }
 
 PARAMETERS = {'threshold': 1039, # just above 1024, prime
diff --git a/pypy/rlib/rarithmetic.py b/pypy/rlib/rarithmetic.py
--- a/pypy/rlib/rarithmetic.py
+++ b/pypy/rlib/rarithmetic.py
@@ -71,7 +71,7 @@
 
 # used in tests for ctypes and for genc and friends
 # to handle the win64 special case:
-is_emulated_long = _long_typecode <> 'l'
+is_emulated_long = _long_typecode != 'l'
     
 LONG_BIT = _get_long_bit()
 LONG_MASK = (2**LONG_BIT)-1
diff --git a/pypy/rlib/rmmap.py b/pypy/rlib/rmmap.py
--- a/pypy/rlib/rmmap.py
+++ b/pypy/rlib/rmmap.py
@@ -739,14 +739,35 @@
         # assume -1 and 0 both mean invalid file descriptor
         # to 'anonymously' map memory.
         if fileno != -1 and fileno != 0:
-            fh = rwin32._get_osfhandle(fileno)
-            if fh == INVALID_HANDLE:
-                errno = rposix.get_errno()
-                raise OSError(errno, os.strerror(errno))
+            fh = rwin32.get_osfhandle(fileno)
             # Win9x appears to need us seeked to zero
             # SEEK_SET = 0
             # libc._lseek(fileno, 0, SEEK_SET)
 
+            # check file size
+            try:
+                low, high = _get_file_size(fh)
+            except OSError:
+                pass     # ignore non-seeking files and errors and trust map_size
+            else:
+                if not high and low <= sys.maxint:
+                   size = low
+                else:   
+                    # not so sure if the signed/unsigned strictness is a good idea:
+                    high = rffi.cast(lltype.Unsigned, high)
+                    low = rffi.cast(lltype.Unsigned, low)
+                    size = (high << 32) + low
+                    size = rffi.cast(lltype.Signed, size)
+                if map_size == 0:
+                    if offset > size:
+                        raise RValueError(
+                            "mmap offset is greater than file size")
+                    map_size = int(size - offset)
+                    if map_size != size - offset:
+                        raise RValueError("mmap length is too large")
+                elif offset + map_size > size:
+                    raise RValueError("mmap length is greater than file size")
+
         m = MMap(access, offset)
         m.file_handle = INVALID_HANDLE
         m.map_handle = INVALID_HANDLE
diff --git a/pypy/rlib/rposix.py b/pypy/rlib/rposix.py
--- a/pypy/rlib/rposix.py
+++ b/pypy/rlib/rposix.py
@@ -98,16 +98,16 @@
     _set_errno(rffi.cast(INT, errno))
 
 if os.name == 'nt':
-    _validate_fd = rffi.llexternal(
+    is_valid_fd = rffi.llexternal(
         "_PyVerify_fd", [rffi.INT], rffi.INT,
         compilation_info=errno_eci,
         )
     @jit.dont_look_inside
     def validate_fd(fd):
-        if not _validate_fd(fd):
+        if not is_valid_fd(fd):
             raise OSError(get_errno(), 'Bad file descriptor')
 else:
-    def _validate_fd(fd):
+    def is_valid_fd(fd):
         return 1
 
     def validate_fd(fd):
@@ -117,7 +117,8 @@
     # this behaves like os.closerange() from Python 2.6.
     for fd in xrange(fd_low, fd_high):
         try:
-            os.close(fd)
+            if is_valid_fd(fd):
+                os.close(fd)
         except OSError:
             pass
 
diff --git a/pypy/rlib/rshrinklist.py b/pypy/rlib/rshrinklist.py
new file mode 100644
--- /dev/null
+++ b/pypy/rlib/rshrinklist.py
@@ -0,0 +1,34 @@
+
+class AbstractShrinkList(object):
+    """A mixin base class.  You should subclass it and add a method
+    must_keep().  Behaves like a list with the method append(), and
+    you can read *for reading* the list of items by calling items().
+    The twist is that occasionally append() will throw away the
+    items for which must_keep() returns False.  (It does so without
+    changing the order.)
+    """
+    _mixin_ = True
+
+    def __init__(self):
+        self._list = []
+        self._next_shrink = 16
+
+    def append(self, x):
+        self._do_shrink()
+        self._list.append(x)
+
+    def items(self):
+        return self._list
+
+    def _do_shrink(self):
+        if len(self._list) >= self._next_shrink:
+            rest = 0
+            for x in self._list:
+                if self.must_keep(x):
+                    self._list[rest] = x
+                    rest += 1
+            del self._list[rest:]
+            self._next_shrink = 16 + 2 * rest
+
+    def must_keep(self, x):
+        raise NotImplementedError
diff --git a/pypy/rlib/rwin32.py b/pypy/rlib/rwin32.py
--- a/pypy/rlib/rwin32.py
+++ b/pypy/rlib/rwin32.py
@@ -8,6 +8,7 @@
 from pypy.translator.platform import CompilationError
 from pypy.rpython.lltypesystem import lltype, rffi
 from pypy.rlib.rarithmetic import intmask
+from pypy.rlib.rposix import validate_fd
 from pypy.rlib import jit
 import os, sys, errno
 
@@ -78,6 +79,7 @@
         for name in """FORMAT_MESSAGE_ALLOCATE_BUFFER FORMAT_MESSAGE_FROM_SYSTEM
                        MAX_PATH
                        WAIT_OBJECT_0 WAIT_TIMEOUT INFINITE
+                       ERROR_INVALID_HANDLE
                     """.split():
             locals()[name] = rffi_platform.ConstantInteger(name)
 
@@ -126,6 +128,13 @@
 
     _get_osfhandle = rffi.llexternal('_get_osfhandle', [rffi.INT], HANDLE)
 
+    def get_osfhandle(fd):
+        validate_fd(fd)
+        handle = _get_osfhandle(fd)
+        if handle == INVALID_HANDLE_VALUE:
+            raise WindowsError(ERROR_INVALID_HANDLE, "Invalid file handle")
+        return handle
+
     def build_winerror_to_errno():
         """Build a dictionary mapping windows error numbers to POSIX errno.
         The function returns the dict, and the default value for codes not
diff --git a/pypy/rlib/streamio.py b/pypy/rlib/streamio.py
--- a/pypy/rlib/streamio.py
+++ b/pypy/rlib/streamio.py
@@ -175,24 +175,23 @@
 
 
 if sys.platform == "win32":
-    from pypy.rlib import rwin32
+    from pypy.rlib.rwin32 import BOOL, HANDLE, get_osfhandle, GetLastError
     from pypy.translator.tool.cbuild import ExternalCompilationInfo
     from pypy.rpython.lltypesystem import rffi
-    import errno
 
     _eci = ExternalCompilationInfo()
-    _get_osfhandle = rffi.llexternal('_get_osfhandle', [rffi.INT], rffi.LONG,
-                                     compilation_info=_eci)
     _setmode = rffi.llexternal('_setmode', [rffi.INT, rffi.INT], rffi.INT,
                                compilation_info=_eci)
-    SetEndOfFile = rffi.llexternal('SetEndOfFile', [rffi.LONG], rwin32.BOOL,
+    SetEndOfFile = rffi.llexternal('SetEndOfFile', [HANDLE], BOOL,
                                    compilation_info=_eci)
 
     # HACK: These implementations are specific to MSVCRT and the C backend.
     # When generating on CLI or JVM, these are patched out.
     # See PyPyTarget.target() in targetpypystandalone.py
     def _setfd_binary(fd):
-        _setmode(fd, os.O_BINARY)
+        #Allow this to succeed on invalid fd's
+        if rposix.is_valid_fd(fd):
+            _setmode(fd, os.O_BINARY)
 
     def ftruncate_win32(fd, size):
         curpos = os.lseek(fd, 0, 1)
@@ -200,11 +199,9 @@
             # move to the position to be truncated
             os.lseek(fd, size, 0)
             # Truncate.  Note that this may grow the file!
-            handle = _get_osfhandle(fd)
-            if handle == -1:
-                raise OSError(errno.EBADF, "Invalid file handle")
+            handle = get_osfhandle(fd)
             if not SetEndOfFile(handle):
-                raise WindowsError(rwin32.GetLastError(),
+                raise WindowsError(GetLastError(),
                                    "Could not truncate file")
         finally:
             # we restore the file pointer position in any case
diff --git a/pypy/rlib/test/test_rmmap.py b/pypy/rlib/test/test_rmmap.py
--- a/pypy/rlib/test/test_rmmap.py
+++ b/pypy/rlib/test/test_rmmap.py
@@ -33,8 +33,6 @@
         interpret(f, [])
 
     def test_file_size(self):
-        if os.name == "nt":
-            skip("Only Unix checks file size")
         def func(no):
 
             try:
@@ -433,15 +431,16 @@
     def test_windows_crasher_1(self):
         if sys.platform != "win32":
             skip("Windows-only test")
-
-        m = mmap.mmap(-1, 1000, tagname="foo")
-        # same tagname, but larger size
-        try:
-            m2 = mmap.mmap(-1, 5000, tagname="foo")
-            m2.getitem(4500)
-        except WindowsError:
-            pass
-        m.close()
+        def func():
+            m = mmap.mmap(-1, 1000, tagname="foo")
+            # same tagname, but larger size
+            try:
+                m2 = mmap.mmap(-1, 5000, tagname="foo")
+                m2.getitem(4500)
+            except WindowsError:
+                pass
+            m.close()
+        interpret(func, [])
 
     def test_windows_crasher_2(self):
         if sys.platform != "win32":
diff --git a/pypy/rlib/test/test_rposix.py b/pypy/rlib/test/test_rposix.py
--- a/pypy/rlib/test/test_rposix.py
+++ b/pypy/rlib/test/test_rposix.py
@@ -132,14 +132,12 @@
             except Exception:
                 pass
 
-    def test_validate_fd(self):
+    def test_is_valid_fd(self):
         if os.name != 'nt':
             skip('relevant for windows only')
-        assert rposix._validate_fd(0) == 1
+        assert rposix.is_valid_fd(0) == 1
         fid = open(str(udir.join('validate_test.txt')), 'w')
         fd = fid.fileno()
-        assert rposix._validate_fd(fd) == 1
+        assert rposix.is_valid_fd(fd) == 1
         fid.close()
-        assert rposix._validate_fd(fd) == 0
-
-
+        assert rposix.is_valid_fd(fd) == 0
diff --git a/pypy/rlib/test/test_rshrinklist.py b/pypy/rlib/test/test_rshrinklist.py
new file mode 100644
--- /dev/null
+++ b/pypy/rlib/test/test_rshrinklist.py
@@ -0,0 +1,30 @@
+from pypy.rlib.rshrinklist import AbstractShrinkList
+
+class Item:
+    alive = True
+
+class ItemList(AbstractShrinkList):
+    def must_keep(self, x):
+        return x.alive
+
+def test_simple():
+    l = ItemList()
+    l2 = [Item() for i in range(150)]
+    for x in l2:
+        l.append(x)
+    assert l.items() == l2
+    #
+    for x in l2[::2]:
+        x.alive = False
+    l3 = [Item() for i in range(150 + 16)]
+    for x in l3:
+        l.append(x)
+    assert l.items() == l2[1::2] + l3   # keeps the order
+
+def test_append_dead_items():
+    l = ItemList()
+    for i in range(150):
+        x = Item()
+        l.append(x)
+        x.alive = False
+    assert len(l.items()) <= 16
diff --git a/pypy/rlib/test/test_rweakkeydict.py b/pypy/rlib/test/test_rweakkeydict.py
--- a/pypy/rlib/test/test_rweakkeydict.py
+++ b/pypy/rlib/test/test_rweakkeydict.py
@@ -135,3 +135,32 @@
             d = RWeakKeyDictionary(KX, VY)
         d.set(KX(), VX())
     py.test.raises(Exception, interpret, g, [1])
+
+
+def test_rpython_free_values():
+    import py; py.test.skip("XXX not implemented, messy")
+    class VXDel:
+        def __del__(self):
+            state.freed.append(1)
+    class State:
+        pass
+    state = State()
+    state.freed = []
+    #
+    def add_me():
+        k = KX()
+        v = VXDel()
+        d = RWeakKeyDictionary(KX, VXDel)
+        d.set(k, v)
+        return d
+    def f():
+        del state.freed[:]
+        d = add_me()
+        rgc.collect()
+        # we want the dictionary to be really empty here.  It's hard to
+        # ensure in the current implementation after just one collect(),
+        # but at least two collects should be enough.
+        rgc.collect()
+        return len(state.freed)
+    assert f() == 1
+    assert interpret(f, []) == 1
diff --git a/pypy/rlib/test/test_rwin32.py b/pypy/rlib/test/test_rwin32.py
new file mode 100644
--- /dev/null
+++ b/pypy/rlib/test/test_rwin32.py
@@ -0,0 +1,28 @@
+import os
+if os.name != 'nt':
+    skip('tests for win32 only')
+
+from pypy.rlib import rwin32
+from pypy.tool.udir import udir
+
+
+def test_get_osfhandle():
+    fid = open(str(udir.join('validate_test.txt')), 'w')
+    fd = fid.fileno()
+    rwin32.get_osfhandle(fd)
+    fid.close()
+    raises(OSError, rwin32.get_osfhandle, fd)
+    rwin32.get_osfhandle(0)
+
+def test_get_osfhandle_raising():
+    #try to test what kind of exception get_osfhandle raises w/out fd validation
+    skip('Crashes python')
+    fid = open(str(udir.join('validate_test.txt')), 'w')
+    fd = fid.fileno()
+    fid.close()
+    def validate_fd(fd):
+        return 1
+    _validate_fd = rwin32.validate_fd
+    rwin32.validate_fd = validate_fd
+    raises(WindowsError, rwin32.get_osfhandle, fd)
+    rwin32.validate_fd = _validate_fd
diff --git a/pypy/rpython/llinterp.py b/pypy/rpython/llinterp.py
--- a/pypy/rpython/llinterp.py
+++ b/pypy/rpython/llinterp.py
@@ -152,7 +152,8 @@
             etype = frame.op_direct_call(exdata.fn_type_of_exc_inst, evalue)
             if etype == klass:
                 return cls
-        raise ValueError, "couldn't match exception"
+        raise ValueError("couldn't match exception, maybe it"
+                      " has RPython attributes like OSError?")
 
     def get_transformed_exc_data(self, graph):
         if hasattr(graph, 'exceptiontransformed'):
diff --git a/pypy/rpython/module/ll_os.py b/pypy/rpython/module/ll_os.py
--- a/pypy/rpython/module/ll_os.py
+++ b/pypy/rpython/module/ll_os.py
@@ -397,6 +397,7 @@
         os_dup = self.llexternal(underscore_on_windows+'dup', [rffi.INT], rffi.INT)
 
         def dup_llimpl(fd):
+            rposix.validate_fd(fd)
             newfd = rffi.cast(lltype.Signed, os_dup(rffi.cast(rffi.INT, fd)))
             if newfd == -1:
                 raise OSError(rposix.get_errno(), "dup failed")
@@ -411,6 +412,7 @@
                                   [rffi.INT, rffi.INT], rffi.INT)
 
         def dup2_llimpl(fd, newfd):
+            rposix.validate_fd(fd)
             error = rffi.cast(lltype.Signed, os_dup2(rffi.cast(rffi.INT, fd),
                                              rffi.cast(rffi.INT, newfd)))
             if error == -1:
@@ -891,6 +893,7 @@
         def os_read_llimpl(fd, count):
             if count < 0:
                 raise OSError(errno.EINVAL, None)
+            rposix.validate_fd(fd)
             raw_buf, gc_buf = rffi.alloc_buffer(count)
             try:
                 void_buf = rffi.cast(rffi.VOIDP, raw_buf)
@@ -916,6 +919,7 @@
 
         def os_write_llimpl(fd, data):
             count = len(data)
+            rposix.validate_fd(fd)
             buf = rffi.get_nonmovingbuffer(data)
             try:
                 written = rffi.cast(lltype.Signed, os_write(
@@ -940,6 +944,7 @@
                                    rffi.INT, threadsafe=False)
         
         def close_llimpl(fd):
+            rposix.validate_fd(fd)
             error = rffi.cast(lltype.Signed, os_close(rffi.cast(rffi.INT, fd)))
             if error == -1:
                 raise OSError(rposix.get_errno(), "close failed")
@@ -972,9 +977,10 @@
 
         os_lseek = self.llexternal(funcname,
                                    [rffi.INT, rffi.LONGLONG, rffi.INT],
-                                   rffi.LONGLONG)
+                                   rffi.LONGLONG, macro=True)
 
         def lseek_llimpl(fd, pos, how):
+            rposix.validate_fd(fd)
             how = fix_seek_arg(how)
             res = os_lseek(rffi.cast(rffi.INT,      fd),
                            rffi.cast(rffi.LONGLONG, pos),
@@ -1000,6 +1006,7 @@
                                        [rffi.INT, rffi.LONGLONG], rffi.INT)
 
         def ftruncate_llimpl(fd, length):
+            rposix.validate_fd(fd)
             res = rffi.cast(rffi.LONG,
                             os_ftruncate(rffi.cast(rffi.INT, fd),
                                          rffi.cast(rffi.LONGLONG, length)))
@@ -1018,6 +1025,7 @@
             os_fsync = self.llexternal('_commit', [rffi.INT], rffi.INT)
 
         def fsync_llimpl(fd):
+            rposix.validate_fd(fd)
             res = rffi.cast(rffi.SIGNED, os_fsync(rffi.cast(rffi.INT, fd)))
             if res < 0:
                 raise OSError(rposix.get_errno(), "fsync failed")
@@ -1030,6 +1038,7 @@
         os_fdatasync = self.llexternal('fdatasync', [rffi.INT], rffi.INT)
 
         def fdatasync_llimpl(fd):
+            rposix.validate_fd(fd)
             res = rffi.cast(rffi.SIGNED, os_fdatasync(rffi.cast(rffi.INT, fd)))
             if res < 0:
                 raise OSError(rposix.get_errno(), "fdatasync failed")
@@ -1042,6 +1051,7 @@
         os_fchdir = self.llexternal('fchdir', [rffi.INT], rffi.INT)
 
         def fchdir_llimpl(fd):
+            rposix.validate_fd(fd)
             res = rffi.cast(rffi.SIGNED, os_fchdir(rffi.cast(rffi.INT, fd)))
             if res < 0:
                 raise OSError(rposix.get_errno(), "fchdir failed")
@@ -1357,6 +1367,7 @@
         os_isatty = self.llexternal(underscore_on_windows+'isatty', [rffi.INT], rffi.INT)
 
         def isatty_llimpl(fd):
+            rposix.validate_fd(fd)
             res = rffi.cast(lltype.Signed, os_isatty(rffi.cast(rffi.INT, fd)))
             return res != 0
 
@@ -1534,6 +1545,7 @@
         os_umask = self.llexternal(underscore_on_windows+'umask', [rffi.MODE_T], rffi.MODE_T)
 
         def umask_llimpl(fd):
+            rposix.validate_fd(fd)
             res = os_umask(rffi.cast(rffi.MODE_T, fd))
             return rffi.cast(lltype.Signed, res)
 
diff --git a/pypy/rpython/module/ll_os_stat.py b/pypy/rpython/module/ll_os_stat.py
--- a/pypy/rpython/module/ll_os_stat.py
+++ b/pypy/rpython/module/ll_os_stat.py
@@ -402,8 +402,7 @@
             lltype.free(data, flavor='raw')
 
     def win32_fstat_llimpl(fd):
-        handle = rwin32._get_osfhandle(fd)
-
+        handle = rwin32.get_osfhandle(fd)
         filetype = win32traits.GetFileType(handle)
         if filetype == win32traits.FILE_TYPE_CHAR:
             # console or LPT device
diff --git a/pypy/rpython/module/test/test_ll_os.py b/pypy/rpython/module/test/test_ll_os.py
--- a/pypy/rpython/module/test/test_ll_os.py
+++ b/pypy/rpython/module/test/test_ll_os.py
@@ -85,8 +85,10 @@
         if (len == 0) and "WINGDB_PYTHON" in os.environ:
             # the ctypes call seems not to work in the Wing debugger
             return
-        assert str(buf.value).lower() == pwd
-        # ctypes returns the drive letter in uppercase, os.getcwd does not
+        assert str(buf.value).lower() == pwd.lower()
+        # ctypes returns the drive letter in uppercase, 
+        # os.getcwd does not, 
+        # but there may be uppercase in os.getcwd path
 
     pwd = os.getcwd()
     try:
@@ -188,7 +190,67 @@
         OSError, ll_execve, "/etc/passwd", [], {})
     assert info.value.errno == errno.EACCES
 
+def test_os_write():
+    #Same as test in rpython/test/test_rbuiltin
+    fname = str(udir.join('os_test.txt'))
+    fd = os.open(fname, os.O_WRONLY|os.O_CREAT, 0777)
+    assert fd >= 0
+    f = getllimpl(os.write)
+    f(fd, 'Hello world')
+    os.close(fd)
+    with open(fname) as fid:
+        assert fid.read() == "Hello world"
+    fd = os.open(fname, os.O_WRONLY|os.O_CREAT, 0777)
+    os.close(fd)
+    raises(OSError, f, fd, 'Hello world')
 
+def test_os_close():
+    fname = str(udir.join('os_test.txt'))
+    fd = os.open(fname, os.O_WRONLY|os.O_CREAT, 0777)
+    assert fd >= 0
+    os.write(fd, 'Hello world')
+    f = getllimpl(os.close)
+    f(fd)
+    raises(OSError, f, fd)
+
+def test_os_lseek():
+    fname = str(udir.join('os_test.txt'))
+    fd = os.open(fname, os.O_RDWR|os.O_CREAT, 0777)
+    assert fd >= 0
+    os.write(fd, 'Hello world')
+    f = getllimpl(os.lseek)
+    f(fd,0,0)
+    assert os.read(fd, 11) == 'Hello world'
+    os.close(fd)
+    raises(OSError, f, fd, 0, 0)
+
+def test_os_fsync():
+    fname = str(udir.join('os_test.txt'))
+    fd = os.open(fname, os.O_WRONLY|os.O_CREAT, 0777)
+    assert fd >= 0
+    os.write(fd, 'Hello world')
+    f = getllimpl(os.fsync)
+    f(fd)
+    os.close(fd)
+    fid = open(fname)
+    assert fid.read() == 'Hello world'
+    fid.close()
+    raises(OSError, f, fd)
+
+def test_os_fdatasync():
+    try:
+        f = getllimpl(os.fdatasync)
+    except:
+        skip('No fdatasync in os')
+    fname = str(udir.join('os_test.txt'))
+    fd = os.open(fname, os.O_WRONLY|os.O_CREAT, 0777)
+    assert fd >= 0
+    os.write(fd, 'Hello world')
+    f(fd)
+    fid = open(fname)
+    assert fid.read() == 'Hello world'
+    os.close(fd)
+    raises(OSError, f, fd)
 
 class ExpectTestOs:
     def setup_class(cls):
diff --git a/pypy/rpython/test/test_llinterp.py b/pypy/rpython/test/test_llinterp.py
--- a/pypy/rpython/test/test_llinterp.py
+++ b/pypy/rpython/test/test_llinterp.py
@@ -34,7 +34,7 @@
     #start = time.time()
     res = call(*args, **kwds) 
     #elapsed = time.time() - start 
-    #print "%.2f secs" %(elapsed,)
+    #print "%.2f secs" % (elapsed,)
     return res 
 
 def gengraph(func, argtypes=[], viewbefore='auto', policy=None,
@@ -137,9 +137,9 @@
     info = py.test.raises(LLException, "interp.eval_graph(graph, values)")
     try:
         got = interp.find_exception(info.value)
-    except ValueError:
-        got = None
-    assert got is exc, "wrong exception type"
+    except ValueError as message:
+        got = 'None %r' % message
+    assert got is exc, "wrong exception type, expected %r got %r" % (exc, got)
 
 #__________________________________________________________________
 # tests
diff --git a/pypy/rpython/test/test_rbuiltin.py b/pypy/rpython/test/test_rbuiltin.py
--- a/pypy/rpython/test/test_rbuiltin.py
+++ b/pypy/rpython/test/test_rbuiltin.py
@@ -201,6 +201,9 @@
         os.close(res)
         hello = open(tmpdir).read()
         assert hello == "hello world"
+        fd = os.open(tmpdir, os.O_WRONLY|os.O_CREAT, 777)
+        os.close(fd)
+        raises(OSError, os.write, fd, "hello world")    
 
     def test_os_write_single_char(self):
         tmpdir = str(udir.udir.join("os_write_test_char"))
diff --git a/pypy/translator/c/src/main.h b/pypy/translator/c/src/main.h
--- a/pypy/translator/c/src/main.h
+++ b/pypy/translator/c/src/main.h
@@ -19,10 +19,6 @@
 #define PYPY_MAIN_FUNCTION main
 #endif
 
-#ifdef MS_WINDOWS
-#include "src/winstuff.c"
-#endif
-
 #ifdef __GNUC__
 /* Hack to prevent this function from being inlined.  Helps asmgcc
    because the main() function has often a different prologue/epilogue. */
@@ -50,10 +46,6 @@
     }
 #endif
 
-#ifdef MS_WINDOWS
-    pypy_Windows_startup();
-#endif
-
     errmsg = RPython_StartupCode();
     if (errmsg) goto error;
 
diff --git a/pypy/translator/c/src/winstuff.c b/pypy/translator/c/src/winstuff.c
deleted file mode 100644
--- a/pypy/translator/c/src/winstuff.c
+++ /dev/null
@@ -1,37 +0,0 @@
-
-/************************************************************/
- /*****  Windows-specific stuff.                         *****/
-
-
-/* copied from CPython. */
-
-#if defined _MSC_VER && _MSC_VER >= 1400 && defined(__STDC_SECURE_LIB__)
-/* crt variable checking in VisualStudio .NET 2005 */
-#include <crtdbg.h>
-
-/* Invalid parameter handler.  Sets a ValueError exception */
-static void
-InvalidParameterHandler(
-    const wchar_t * expression,
-    const wchar_t * function,
-    const wchar_t * file,
-    unsigned int line,
-    uintptr_t pReserved)
-{
-    /* Do nothing, allow execution to continue.  Usually this
-     * means that the CRT will set errno to EINVAL
-     */
-}
-#endif
-
-
-void pypy_Windows_startup(void)
-{
-#if defined _MSC_VER && _MSC_VER >= 1400 && defined(__STDC_SECURE_LIB__)
-    /* Set CRT argument error handler */
-    _set_invalid_parameter_handler(InvalidParameterHandler);
-    /* turn off assertions within CRT in debug mode;
-       instead just return EINVAL */
-    _CrtSetReportMode(_CRT_ASSERT, 0);
-#endif
-}
diff --git a/pypy/translator/c/test/test_extfunc.py b/pypy/translator/c/test/test_extfunc.py
--- a/pypy/translator/c/test/test_extfunc.py
+++ b/pypy/translator/c/test/test_extfunc.py
@@ -134,6 +134,13 @@
         res = os.lseek(fd, -r5200000000, 2)
         assert res == r4800000000
         os.close(fd)
+        try:
+            os.lseek(fd, 0, 0)
+        except OSError:
+            pass
+        else:
+            print "DID NOT RAISE"
+            raise AssertionError
         st = os.stat(filename)
         assert st.st_size == r10000000000
     does_stuff()
diff --git a/pypy/translator/goal/app_main.py b/pypy/translator/goal/app_main.py
--- a/pypy/translator/goal/app_main.py
+++ b/pypy/translator/goal/app_main.py
@@ -121,8 +121,18 @@
     else:
         optitems = options.items()
         optitems.sort()
-        for name, value in optitems:
-            print ' %51s: %s' % (name, value)
+        current = []
+        for key, value in optitems:
+            group = key.split('.')
+            name = group.pop()
+            n = 0
+            while n < min(len(current), len(group)) and current[n] == group[n]:
+                n += 1
+            while n < len(group):
+                print '%s[%s]' % ('    ' * n, group[n])
+                n += 1
+            print '%s%s = %r' % ('    ' * n, name, value)
+            current = group
     raise SystemExit
 
 def print_help(*args):
diff --git a/pypy/translator/goal/test2/test_app_main.py b/pypy/translator/goal/test2/test_app_main.py
--- a/pypy/translator/goal/test2/test_app_main.py
+++ b/pypy/translator/goal/test2/test_app_main.py
@@ -787,6 +787,37 @@
         assert data.startswith("15\xe2\x82\xac")
 
 
+class TestAppMain:
+    
+    def test_print_info(self):
+        from pypy.translator.goal import app_main
+        import sys, cStringIO
+        prev_so = sys.stdout
+        prev_ti = getattr(sys, 'pypy_translation_info', 'missing')
+        sys.pypy_translation_info = {
+            'translation.foo': True,
+            'translation.bar': 42,
+            'translation.egg.something': None,
+            'objspace.x': 'hello',
+        }
+        try:
+            sys.stdout = f = cStringIO.StringIO()
+            py.test.raises(SystemExit, app_main.print_info)
+        finally:
+            sys.stdout = prev_so
+            if prev_ti == 'missing':
+                del sys.pypy_translation_info
+            else:
+                sys.pypy_translation_info = prev_ti
+        assert f.getvalue() == ("[objspace]\n"
+                                "    x = 'hello'\n"
+                                "[translation]\n"
+                                "    bar = 42\n"
+                                "    [egg]\n"
+                                "        something = None\n"
+                                "    foo = True\n")
+
+
 class AppTestAppMain:
 
     def setup_class(self):
diff --git a/pypy/translator/goal/win32/gc_patch_windows.py b/pypy/translator/goal/win32/gc_patch_windows.py
deleted file mode 100644
--- a/pypy/translator/goal/win32/gc_patch_windows.py
+++ /dev/null
@@ -1,129 +0,0 @@
-# patches for the Boehm GC for PyPy under Windows
-
-"""
-This file is obsolete now since gc-7.0 / gc-7.1 .
-Please use the instructions in pypy\doc\windows.rst .
-
-How to build a pypy compatible version of the Boehm collector
-for Windows and Visual Studio .net 2003.
-
-First of all, download the official Boehm collector suite
-from http://www.hpl.hp.com/personal/Hans_Boehm/gc/gc_source/gc.tar.gz
-At the time of writing (2005-10-06) this contains version gc6.5 .
-
-Unpack this folder somewhere, for instance to "d:\tmp".
-Change to this folder using
-
-d:
-cd \tmp\gc6.5
-
-Then copy the file NT_THREADS_MAKEFILE to Makefile:
-
-copy NT_THREADS_MAKEFILE Makefile
-
-This file is the general-purpose gc dll makefile. For some internal
-reasons, this file's defaults are bad for PyPy. The early initialisation
-in DllMain() inhibits the changes necessary for PyPy. Use this script to
-do a patch: (assuming that you have d:\pypy\dist\pypy\translator\goal)
-
-python d:\pypy\dist\pypy\translator\goal\win32\gc_patch_windows.py
-
-Now, your makefile is patched a little bit. In particular,
-
-ALL_INTERIOR_POINTERS   is now undefined, which PyPy wants to have
-NO_GETENV               is specified, since we don't want dependencies
-
-and the name of the .lib and .dll files is changed to gc_pypy.???
-
-Now you need to build your gc, either as a debug or as a release
-build. First of all, make sure that you have your environment prepared.
-Please note that you will need to use Microsoft's cmd, as cygwin bash
-doesn't correctly handle the batch file in the next step.
-
-With my setup, I have to do
-
-"e:\Programme\Microsoft Visual Studio .NET 2003\Vc7\bin\vcvars32.bat"
-
-After that, you can either build a release or a debug gc. 
-
-After a successful build, you need to enable gc_pypy.dll for your compiler.
-There are many ways to install this. The following recommendation just
-works without changing your environment variables. I think this is the
-easiest way possible, but this is a matter of taste. What I did is:
-
-nmake CFG="gc - Win32 Release"
-
-After the build, you will find a gc_pypy.dll file in the Release folder.
-Copy this file to c:\windows\system32 or any other folder that is always
-in your PATH variable.
-
-Also, copy Release\gc_pypy.lib to (in my case)
-"e:\Programme\Microsoft Visual Studio .NET 2003\Vc7\lib";
-
-finally, copy d:\tmp\gc6.5\include to
-"e:\Programme\Microsoft Visual Studio .NET 2003\Vc7\include"
-and rename this folder to "gc", so that "gc/gc.h" is valid.
-
-That's all, folks!
-
-In case of a debug build, replace "Release" by "Debug", and also copy
-gc_pypy.pdb to your lib folder. This allows you to use source-level
-debugging. Please note: If you want to both build the default gc.dll
-and gc_pypy.dll, please delete the Debug resp. Release folders in
-between. The generated .sbr files are in the way.
-
-Please use the above recipe and report any bugs to me.
-In case of trouble, I also can provide you with pre-built dlls.
-Note: We also could have solved this by including the gc source
-into the PyPy build. This may or may not become necessary if something
-changes dramatically, again. As long as this is not needed, I prefer
-this simple solution.
-
-Summary transcript of the steps involved: (please adjust paths)
-
-d:
-cd \tmp\gc6.5
-copy NT_THREADS_MAKEFILE Makefile
-python d:\pypy\dist\pypy\translator\goal\win32\gc_patch_windows.py
-"e:\Programme\Microsoft Visual Studio .NET 2003\Vc7\bin\vcvars32.bat"
-nmake CFG="gc - Win32 Release"
-copy Release\gc_pypy.dll c:\windows\system32
-copy Release\gc_pypy.lib "e:\Programme\Microsoft Visual Studio .NET 2003\Vc7\lib"
-mkdir "e:\Programme\Microsoft Visual Studio .NET 2003\Vc7\include\gc"
-copy include "e:\Programme\Microsoft Visual Studio .NET 2003\Vc7\include\gc"
-
-cheers - chris
-"""
-
-REPLACE = {
-    '"ALL_INTERIOR_POINTERS"': '"NO_GETENV"',
-    }
-
-for ending in "lib exp map pdb bsc dll pch".split():
-    REPLACE["gc.%s" % ending] = "gc_pypy.%s" % ending
-
-def change_settings(src):
-    for old, new in REPLACE.items():
-        newsrc = src.replace(old, new)
-        if newsrc == src:
-            raise ValueError, "this makefile does not contain %s" % old
-        src = newsrc
-    return src
-
-def find_file():
-    import os
-    for name in os.listdir("."):
-        if name.lower() == 'makefile':
-            return name
-    else:
-        raise ValueError, 'Makefile not found'
-
-try:
-    name = find_file()
-    source = change_settings(file(name).read())
-    file(name, "w").write(source)
-    print "Updated your Makefile to fit PyPy's needs. Your lib will be named gc_pypy.dll"
-    print "and gc_pypy.lib. Please put them into appropriate places, see __doc__."
-except:
-    print __doc__
-    raise
diff --git a/pypy/translator/platform/__init__.py b/pypy/translator/platform/__init__.py
--- a/pypy/translator/platform/__init__.py
+++ b/pypy/translator/platform/__init__.py
@@ -299,10 +299,11 @@
 
 def set_platform(new_platform, cc):
     global platform
-    log.msg("Setting platform to %r cc=%s" % (new_platform,cc))
     platform = pick_platform(new_platform, cc)
     if not platform:
-        raise ValueError("pick_platform failed")
+        raise ValueError("pick_platform(%r, %s) failed"%(new_platform, cc))
+    log.msg("Set platform with %r cc=%s, using cc=%r" % (new_platform, cc,
+                    getattr(platform, 'cc','Unknown')))
 
     if new_platform == 'host':
         global host
diff --git a/pypy/translator/platform/windows.py b/pypy/translator/platform/windows.py
--- a/pypy/translator/platform/windows.py
+++ b/pypy/translator/platform/windows.py
@@ -83,13 +83,9 @@
 
         if env is not None:
             return env
-
     log.error("Could not find a Microsoft Compiler")
     # Assume that the compiler is already part of the environment
 
-msvc_compiler_environ32 = find_msvc_env(False)
-msvc_compiler_environ64 = find_msvc_env(True)
-
 class MsvcPlatform(Platform):
     name = "msvc"
     so_ext = 'dll'
@@ -108,10 +104,7 @@
     
     def __init__(self, cc=None, x64=False):
         self.x64 = x64
-        if x64:
-            msvc_compiler_environ = msvc_compiler_environ64
-        else:
-            msvc_compiler_environ = msvc_compiler_environ32
+        msvc_compiler_environ = find_msvc_env(x64)
         Platform.__init__(self, 'cl.exe')
         if msvc_compiler_environ:
             self.c_environ = os.environ.copy()


More information about the pypy-commit mailing list